diff options
author | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2019-04-09 15:09:07 +0300 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2019-05-03 09:13:48 +0300 |
commit | 2a60f5eafa74727f083ce7732d5296bf3e0638b6 (patch) | |
tree | b8e2891b9da7e9808ec303839c68e7fec2f7eaae /drivers/usb | |
parent | f584fa8c1fdc289f23f4948bd58f4e2281fb5ad5 (diff) | |
download | linux-2a60f5eafa74727f083ce7732d5296bf3e0638b6.tar.xz |
usb: gadget: udc: lpc32xx: add support for stotg04 phy
The STOTG04 phy is used as a drop-in replacement of the ISP1301 but some
bits doesn't have exactly the same meaning and this can lead to issues.
Detect the phy dynamically and avoid writing to reserved bits.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/udc/lpc32xx_udc.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 12f2d76e50fe..5d6246d23b99 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -115,6 +115,11 @@ struct lpc32xx_ep { bool wedge; }; +enum atx_type { + ISP1301, + STOTG04, +}; + /* * Common UDC structure */ @@ -149,6 +154,7 @@ struct lpc32xx_udc { u8 last_vbus; int pullup; int poweron; + enum atx_type atx; /* Work queues related to I2C support */ struct work_struct pullup_job; @@ -550,6 +556,15 @@ static inline void remove_debug_file(struct lpc32xx_udc *udc) {} /* Primary initialization sequence for the ISP1301 transceiver */ static void isp1301_udc_configure(struct lpc32xx_udc *udc) { + u8 value; + s32 vendor, product; + + vendor = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00); + product = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02); + + if (vendor == 0x0483 && product == 0xa0c4) + udc->atx = STOTG04; + /* LPC32XX only supports DAT_SE0 USB mode */ /* This sequence is important */ @@ -569,8 +584,12 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) */ i2c_smbus_write_byte_data(udc->isp1301_i2c_client, (ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0); + + value = MC2_BI_DI; + if (udc->atx != STOTG04) + value |= MC2_SPD_SUSP_CTRL; i2c_smbus_write_byte_data(udc->isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL)); + ISP1301_I2C_MODE_CONTROL_2, value); /* Driver VBUS_DRV high or low depending on board setup */ if (udc->board->vbus_drv_pol != 0) @@ -610,12 +629,11 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc) i2c_smbus_write_byte_data(udc->isp1301_i2c_client, ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD); - dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n", - i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00)); - dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", - i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02)); + dev_info(udc->dev, "ISP1301 Vendor ID : 0x%04x\n", vendor); + dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", product); dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n", i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14)); + } /* Enables or disables the USB device pullup via the ISP1301 transceiver */ @@ -658,6 +676,10 @@ static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup, /* Powers up or down the ISP1301 transceiver */ static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable) { + /* There is no "global power down" register for stotg04 */ + if (udc->atx == STOTG04) + return; + if (enable != 0) /* Power up ISP1301 - this ISP1301 will automatically wakeup when VBUS is detected */ |