@ -14,6 +14,7 @@
# include <linux/mutex.h>
# include <linux/i2c.h>
# include <linux/usb/phy.h>
# include <linux/usb/isp1301.h>
# define DRV_NAME "isp1301"
@ -24,6 +25,8 @@ struct isp1301 {
struct i2c_client * client ;
} ;
# define phy_to_isp(p) (container_of((p), struct isp1301, phy))
static const struct i2c_device_id isp1301_id [ ] = {
{ " isp1301 " , 0 } ,
{ }
@ -31,6 +34,60 @@ static const struct i2c_device_id isp1301_id[] = {
static struct i2c_client * isp1301_i2c_client ;
static int __isp1301_write ( struct isp1301 * isp , u8 reg , u8 value , u8 clear )
{
return i2c_smbus_write_byte_data ( isp - > client , reg | clear , value ) ;
}
static int isp1301_write ( struct isp1301 * isp , u8 reg , u8 value )
{
return __isp1301_write ( isp , reg , value , 0 ) ;
}
static int isp1301_clear ( struct isp1301 * isp , u8 reg , u8 value )
{
return __isp1301_write ( isp , reg , value , ISP1301_I2C_REG_CLEAR_ADDR ) ;
}
static int isp1301_phy_init ( struct usb_phy * phy )
{
struct isp1301 * isp = phy_to_isp ( phy ) ;
/* Disable transparent UART mode first */
isp1301_clear ( isp , ISP1301_I2C_MODE_CONTROL_1 , MC1_UART_EN ) ;
isp1301_clear ( isp , ISP1301_I2C_MODE_CONTROL_1 , ~ MC1_SPEED_REG ) ;
isp1301_write ( isp , ISP1301_I2C_MODE_CONTROL_1 , MC1_SPEED_REG ) ;
isp1301_clear ( isp , ISP1301_I2C_MODE_CONTROL_2 , ~ 0 ) ;
isp1301_write ( isp , ISP1301_I2C_MODE_CONTROL_2 , ( MC2_BI_DI | MC2_PSW_EN
| MC2_SPD_SUSP_CTRL ) ) ;
isp1301_clear ( isp , ISP1301_I2C_OTG_CONTROL_1 , ~ 0 ) ;
isp1301_write ( isp , ISP1301_I2C_MODE_CONTROL_1 , MC1_DAT_SE0 ) ;
isp1301_write ( isp , ISP1301_I2C_OTG_CONTROL_1 , ( OTG1_DM_PULLDOWN
| OTG1_DP_PULLDOWN ) ) ;
isp1301_clear ( isp , ISP1301_I2C_OTG_CONTROL_1 , ( OTG1_DM_PULLUP
| OTG1_DP_PULLUP ) ) ;
/* mask all interrupts */
isp1301_clear ( isp , ISP1301_I2C_INTERRUPT_LATCH , ~ 0 ) ;
isp1301_clear ( isp , ISP1301_I2C_INTERRUPT_FALLING , ~ 0 ) ;
isp1301_clear ( isp , ISP1301_I2C_INTERRUPT_RISING , ~ 0 ) ;
return 0 ;
}
static int isp1301_phy_set_vbus ( struct usb_phy * phy , int on )
{
struct isp1301 * isp = phy_to_isp ( phy ) ;
if ( on )
isp1301_write ( isp , ISP1301_I2C_OTG_CONTROL_1 , OTG1_VBUS_DRV ) ;
else
isp1301_clear ( isp , ISP1301_I2C_OTG_CONTROL_1 , OTG1_VBUS_DRV ) ;
return 0 ;
}
static int isp1301_probe ( struct i2c_client * client ,
const struct i2c_device_id * i2c_id )
{
@ -46,6 +103,8 @@ static int isp1301_probe(struct i2c_client *client,
phy = & isp - > phy ;
phy - > label = DRV_NAME ;
phy - > init = isp1301_phy_init ;
phy - > set_vbus = isp1301_phy_set_vbus ;
phy - > type = USB_PHY_TYPE_USB2 ;
i2c_set_clientdata ( client , isp ) ;