[U-Boot] [PATCH v2 1/4] USB: gadget: Add the cadence USB3 gadget driver

Marek Vasut marex at denx.de
Wed Aug 14 15:26:14 UTC 2019


On 8/14/19 2:16 PM, sherry sun wrote:
> From: Sherry Sun <sherry.sun at nxp.com>
> 
> This driver is ported from NXP i.MX U-Boot version imx_v2019.04
> and some changes have also been made to adapt to U-Boot.
> 
> Add the Cadence USB3 IP(CDNS3) driver for the gadget (device mode).
> The CDNS3 gadget driver support DM mode. CONFIG_DM_USB_GADGET should
> be enabled when use this driver. And gadget_is_cdns3 checking is
> added to provide bcdUSB value in device descriptor.

The cadence core isn't xhci compatible ? Sigh ...

[...]

> +++ b/doc/device-tree-bindings/usb/cdns-usb3.txt
> @@ -0,0 +1,39 @@
> +* Cadence USB3 Controller
> +
> +Required properties:
> +- compatible: "Cadence,usb3";

cdns , no ?

[...]

> +static int cdns3_generic_peripheral_clk_init(struct udevice *dev,
> +					     struct cdns3_generic_peripheral
> +					     *priv)
> +{
> +	int ret;
> +
> +	ret = clk_get_bulk(dev, &priv->clks);
> +	if (ret)
> +		return ret;
> +
> +#if CONFIG_IS_ENABLED(CLK)

Why is the ifdef protecting only half of the clock functions ?

> +	ret = clk_enable_bulk(&priv->clks);
> +	if (ret) {
> +		clk_release_bulk(&priv->clks);
> +		return ret;
> +	}
> +#endif
> +
> +	return 0;
> +}


[...]

> +static void cdns3_set_role(struct cdns3 *cdns, enum cdns3_roles role)
> +{
> +	u32 value;
> +	int timeout_us = 100000;
> +	struct cdns3_generic_peripheral *priv = container_of(cdns,
> +			struct cdns3_generic_peripheral, cdns3);
> +
> +	if (role == CDNS3_ROLE_END)
> +		return;
> +
> +	/* Wait clk value */
> +	value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
> +	writel(value, cdns->none_core_regs + USB3_SSPHY_STATUS);
> +	udelay(1);
> +	value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
> +	while ((value & 0xf0000000) != 0xf0000000 && timeout_us-- > 0) {
> +		value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
> +		udelay(1);
> +	}

Is this like wait_for_bit() ?

> +	if (timeout_us <= 0)
> +		dev_err(cdns->dev, "wait clkvld timeout\n");
> +
> +	/* Set all Reset bits */
> +	setbits_le32(cdns->none_core_regs + USB3_CORE_CTRL1, ALL_SW_RESET);
> +	udelay(1);
> +
> +	if (role == CDNS3_ROLE_HOST) {

Do we need custom controller role definition ? I don't think so, just
use the one in the USB stack.

Also, use clrsetbits_le32()

> +		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
> +		value = (value & ~MODE_STRAP_MASK) | HOST_MODE | OC_DISABLE;
> +		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
> +		clrbits_le32(cdns->none_core_regs + USB3_CORE_CTRL1,
> +			     PHYAHB_SW_RESET);
> +		mdelay(1);
> +		generic_phy_init(&priv->phy);
> +		setbits_le32(cdns->phy_regs + TB_ADDR_TX_RCVDETSC_CTRL,
> +			     RXDET_IN_P3_32KHZ);
> +		udelay(10);
> +		/* Force B Session Valid as 1 */
> +		writel(0x0060, cdns->phy_regs + 0x380a4);
> +		mdelay(1);
> +
> +		setbits_le32(cdns->none_core_regs + USB3_INT_REG, HOST_INT1_EN);
> +
> +		clrbits_le32(cdns->none_core_regs + USB3_CORE_CTRL1,
> +			     ALL_SW_RESET);
> +
> +		dev_dbg(cdns->dev, "wait xhci_power_on_ready\n");
> +
> +		value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
> +		timeout_us = 100000;
> +		while (!(value & HOST_POWER_ON_READY) && timeout_us-- > 0) {
> +			value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
> +			udelay(1);
> +		}
> +
> +		if (timeout_us <= 0)
> +			dev_err(cdns->dev, "wait xhci_power_on_ready timeout\n");
> +
> +		dev_dbg(cdns->dev, "switch to host role successfully\n");
> +	} else { /* gadget mode */

Split this into sensibly long funtions please.

> +		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
> +		value = (value & ~MODE_STRAP_MASK) | DEV_MODE;
> +		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
> +		clrbits_le32(cdns->none_core_regs + USB3_CORE_CTRL1,
> +			     PHYAHB_SW_RESET);
> +
> +		generic_phy_init(&priv->phy);
> +		setbits_le32(cdns->phy_regs + TB_ADDR_TX_RCVDETSC_CTRL,
> +			     RXDET_IN_P3_32KHZ);
> +		udelay(10);
> +		/* Force B Session Valid as 1 */
> +		writel(0x0060, cdns->phy_regs + 0x380a4);
> +		setbits_le32(cdns->none_core_regs + USB3_INT_REG, DEV_INT_EN);
> +
> +		clrbits_le32(cdns->none_core_regs + USB3_CORE_CTRL1,
> +			     ALL_SW_RESET);
> +
> +		dev_dbg(cdns->dev, "wait gadget_power_on_ready\n");
> +
> +		value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
> +		timeout_us = 100000;
> +		while (!(value & DEV_POWER_ON_READY) && timeout_us-- > 0) {
> +			value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
> +			udelay(1);
> +		}

wait_for_bit()

[...]

> +/* macros for field CFGSTS */
> +#define USB_STS__CFGSTS__MASK                                       0x00000001U
> +#define USB_STS__USBSPEED__READ(src)     (((uint32_t)(src) & 0x00000070U) >> 4)

u32, fix globally

[...]

> +static void __cdns3_gadget_start(struct usb_ss_dev *usb_ss)
> +{
> +	u32 usb_conf_reg = 0;
> +
> +	/* configure endpoint 0 hardware */
> +	cdns_ep0_config(usb_ss);
> +
> +	/* enable interrupts for endpoint 0 (in and out) */
> +	cdns_writel(&usb_ss->regs->ep_ien,
> +		      EP_IEN__EOUTEN0__MASK | EP_IEN__EINEN0__MASK);
> +
> +	/* enable interrupt for device */
> +	cdns_writel(&usb_ss->regs->usb_ien,
> +		      USB_IEN__U2RESIEN__MASK
> +		      | USB_ISTS__DIS2I__MASK
> +		      | USB_IEN__CON2IEN__MASK
> +		      | USB_IEN__UHRESIEN__MASK
> +		      | USB_IEN__UWRESIEN__MASK
> +		      | USB_IEN__DISIEN__MASK
> +		      | USB_IEN__CONIEN__MASK
> +		      | USB_IEN__U3EXTIEN__MASK
> +		      | USB_IEN__L2ENTIEN__MASK
> +		      | USB_IEN__L2EXTIEN__MASK);
> +
> +	usb_conf_reg = USB_CONF__CLK2OFFDS__MASK |
> +			USB_CONF__L1DS__MASK;
> +	if (usb_ss->gadget.max_speed == USB_SPEED_HIGH)
> +		usb_conf_reg |= USB_CONF__USB3DIS__MASK;
> +	cdns_writel(&usb_ss->regs->usb_conf, usb_conf_reg);
> +
> +	cdns_writel(&usb_ss->regs->usb_conf,
> +		      USB_CONF__U1DS__MASK
> +		      | USB_CONF__U2DS__MASK
> +			/*
> +			 * TODO:
> +			 * | USB_CONF__L1EN__MASK
> +			 */
> +			);

Fix the TODO ?


More information about the U-Boot mailing list