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>
This commit is contained in:
Alexandre Belloni 2019-04-09 14:09:07 +02:00 committed by Felipe Balbi
parent f584fa8c1f
commit 2a60f5eafa
1 changed files with 27 additions and 5 deletions

View File

@ -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 */