Commit 2a60f5ea authored by Alexandre Belloni's avatar Alexandre Belloni Committed by Felipe Balbi
Browse files

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: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent f584fa8c
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -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 */