[U-Boot] [PATCH v4 09/34] phy: Add Allwinner A64 USB PHY driver
Marek Vasut
marex at denx.de
Tue Feb 6 14:47:41 UTC 2018
On 02/06/2018 03:25 PM, Jagan Teki wrote:
> USB PHY implementation for Allwinner SOC's can be handling
> in to single driver with different phy configs.
>
> This driver handle all Allwinner USB PHY's start from 4I to
> 50I(except 9I). Currently added A64 compatibility more will
> add in next coming patches.
>
> Current implementation is unable to get pinctrl, clock and reset
> details from DT since the dm code on these will add it future.
>
> Driver named as phy-sun4i-usb.c since the same PHY logic
> work for all Allwinner SOC's start from 4I to A64 except 9I
> with different phy configurations.
>
> Signed-off-by: Jagan Teki <jagan at amarulasolutions.com>
[...]
> +#define MAX_PHYS 4
There should be one PHY per controller , so why do you need this ?
> +enum sun4i_usb_phy_type {
> + sun50i_a64_phy,
> +};
> +
> +struct sun4i_usb_phy_cfg {
> + int num_phys;
> + enum sun4i_usb_phy_type type;
> + u32 disc_thresh;
> + u8 phyctl_offset;
> + bool enable_pmu_unk1;
> + bool phy0_dual_route;
> +};
> +
> +struct sun4i_usb_phy_info {
> + const char *gpio_vbus;
> + const char *gpio_vbus_det;
> + const char *gpio_id_det;
> + int rst_mask;
> +} phy_info[] = {
> + {
> + .gpio_vbus = CONFIG_USB0_VBUS_PIN,
> + .gpio_vbus_det = CONFIG_USB0_VBUS_DET,
> + .gpio_id_det = CONFIG_USB0_ID_DET,
> + .rst_mask = (CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK),
> + },
> + {
> + .gpio_vbus = CONFIG_USB1_VBUS_PIN,
> + .gpio_vbus_det = NULL,
> + .gpio_id_det = NULL,
> + .rst_mask = (CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK),
> + },
> + {
> + .gpio_vbus = CONFIG_USB2_VBUS_PIN,
> + .gpio_vbus_det = NULL,
> + .gpio_id_det = NULL,
> + .rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK),
> + },
> + {
> + .gpio_vbus = CONFIG_USB3_VBUS_PIN,
> + .gpio_vbus_det = NULL,
> + .gpio_id_det = NULL,
> + .rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK),
> + },
> +};
> +
> +struct sun4i_usb_phy_plat {
> + void __iomem *pmu;
> + int power_on_count;
> + int gpio_vbus;
> + int gpio_vbus_det;
> + int gpio_id_det;
> + int rst_mask;
> + int id;
> +};
> +
> +struct sun4i_usb_phy_data {
> + void __iomem *base;
> + struct sunxi_ccm_reg *ccm;
> + const struct sun4i_usb_phy_cfg *cfg;
> + struct sun4i_usb_phy_plat *usb_phy;
> +};
> +
> +static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY;
Get rid of any static variables in this driver. And the delay should
come from DT .
> +static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len)
> +{
> + struct sun4i_usb_phy_data *phy_data = dev_get_priv(phy->dev);
> + struct sun4i_usb_phy_plat *usb_phy = &phy_data->usb_phy[phy->id];
> + u32 temp, usbc_bit = BIT(usb_phy->id * 2);
> + void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
> + int i;
> +
> + if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
You should probably match on some type of the block here, not register
offset, to identify the SoC .
> + /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
> + writel(0, phyctl);
> + }
> +
> + for (i = 0; i < len; i++) {
> + temp = readl(phyctl);
> +
> + /* clear the address portion */
> + temp &= ~(0xff << 8);
> +
> + /* set the address */
> + temp |= ((addr + i) << 8);
> + writel(temp, phyctl);
clrsetbits(), fix globally
> + /* set the data bit and clear usbc bit*/
> + temp = readb(phyctl);
> + if (data & 0x1)
> + temp |= PHYCTL_DATA;
> + else
> + temp &= ~PHYCTL_DATA;
> + temp &= ~usbc_bit;
> + writeb(temp, phyctl);
> +
> + /* pulse usbc_bit */
> + temp = readb(phyctl);
> + temp |= usbc_bit;
> + writeb(temp, phyctl);
> +
> + temp = readb(phyctl);
> + temp &= ~usbc_bit;
> + writeb(temp, phyctl);
> +
> + data >>= 1;
> + }
> +}
[...]
--
Best regards,
Marek Vasut
More information about the U-Boot
mailing list