Message ID | 1554883715-41725-3-git-send-email-biju.das@bp.renesas.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Series | Add USB2.0 support | expand |
Hi Biju-san, Thank you for the patch! > From: Biju Das, Sent: Wednesday, April 10, 2019 5:08 PM <snip> > static int rcar_gen2_phy_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > @@ -238,6 +313,8 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) > struct resource *res; > void __iomem *base; > struct clk *clk; > + const struct phy_ops *gen2_phy_ops = &rcar_gen2_phy_ops; > + const u32 (*select_value)[PHYS_PER_CHANNEL] = pci_select_value; > int i = 0; > > if (!dev->of_node) { > @@ -266,6 +343,11 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) > drv->clk = clk; > drv->base = base; > > + if (soc_device_match(soc_r8a77470)) { I'm not sure, but this driver also should not use the soc_device_match() like phy-rcar-gen3-usb2 driver? If we add a special data struct and has phy_ops and select_value members, we can achieve not to use the soc_device_match(). Best regards, Yoshihiro Shimoda
Hi Shimoda-San, Thanks for the feedback. > Subject: RE: [PATCH V4 02/13] phy: renesas: phy-rcar-gen2: Add support for > r8a77470 > > Hi Biju-san, > > Thank you for the patch! > > > From: Biju Das, Sent: Wednesday, April 10, 2019 5:08 PM > <snip> > > static int rcar_gen2_phy_probe(struct platform_device *pdev) { > > struct device *dev = &pdev->dev; > > @@ -238,6 +313,8 @@ static int rcar_gen2_phy_probe(struct > platform_device *pdev) > > struct resource *res; > > void __iomem *base; > > struct clk *clk; > > + const struct phy_ops *gen2_phy_ops = &rcar_gen2_phy_ops; > > + const u32 (*select_value)[PHYS_PER_CHANNEL] = pci_select_value; > > int i = 0; > > > > if (!dev->of_node) { > > @@ -266,6 +343,11 @@ static int rcar_gen2_phy_probe(struct > platform_device *pdev) > > drv->clk = clk; > > drv->base = base; > > > > + if (soc_device_match(soc_r8a77470)) { > > I'm not sure, but this driver also should not use the soc_device_match() like > phy-rcar-gen3-usb2 driver? > If we add a special data struct and has phy_ops and select_value members, > we can achieve not to use the soc_device_match(). There is a difference compared to phy-rcar-gen3-usb2 driver. Here we are using generic compatible string for RZ/G1C. With the new proposal, I need to make following changes. 1) Add r8a77470 compatible in phy_match table, fill the driver_data structure and remove soc_device_match 2) Modify the SoC dtsi to remove generic compatible string. I will send V5 based on new proposal, if you are ok for removing generic compatibility. Please let me know. Regards, Biju
Hi Biju-san, > From: Biju Das, Sent: Wednesday, April 10, 2019 7:08 PM > > Hi Shimoda-San, > > Thanks for the feedback. > > > Subject: RE: [PATCH V4 02/13] phy: renesas: phy-rcar-gen2: Add support for > > r8a77470 > > > > Hi Biju-san, > > > > Thank you for the patch! > > > > > From: Biju Das, Sent: Wednesday, April 10, 2019 5:08 PM > > <snip> > > > static int rcar_gen2_phy_probe(struct platform_device *pdev) { > > > struct device *dev = &pdev->dev; > > > @@ -238,6 +313,8 @@ static int rcar_gen2_phy_probe(struct > > platform_device *pdev) > > > struct resource *res; > > > void __iomem *base; > > > struct clk *clk; > > > + const struct phy_ops *gen2_phy_ops = &rcar_gen2_phy_ops; > > > + const u32 (*select_value)[PHYS_PER_CHANNEL] = pci_select_value; > > > int i = 0; > > > > > > if (!dev->of_node) { > > > @@ -266,6 +343,11 @@ static int rcar_gen2_phy_probe(struct > > platform_device *pdev) > > > drv->clk = clk; > > > drv->base = base; > > > > > > + if (soc_device_match(soc_r8a77470)) { > > > > I'm not sure, but this driver also should not use the soc_device_match() like > > phy-rcar-gen3-usb2 driver? > > If we add a special data struct and has phy_ops and select_value members, > > we can achieve not to use the soc_device_match(). > > There is a difference compared to phy-rcar-gen3-usb2 driver. > Here we are using generic compatible string for RZ/G1C. > > With the new proposal, I need to make following changes. > > 1) Add r8a77470 compatible in phy_match table, fill the driver_data structure and remove soc_device_match I think so. > 2) Modify the SoC dtsi to remove generic compatible string. I don't think so. For example, r8a77990.dtsi has compatible with both "renesas,usbhs-r8a77990" and "renesas,rcar-gen3-usbhs", and then the renesas_usbhs driver has .data for renesas,usbhs-r8a77990, but it is not compatible with .data of "renesas,rcar-gen3-usbhs". Simon-san, what do you think? Best regards, Yoshihiro Shimoda > I will send V5 based on new proposal, if you are ok for removing generic compatibility. > Please let me know. > > Regards, > Biju > > >
diff --git a/drivers/phy/renesas/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c index 72eeb06..5897386 100644 --- a/drivers/phy/renesas/phy-rcar-gen2.c +++ b/drivers/phy/renesas/phy-rcar-gen2.c @@ -4,6 +4,7 @@ * * Copyright (C) 2014 Renesas Solutions Corp. * Copyright (C) 2014 Cogent Embedded, Inc. + * Copyright (C) 2019 Renesas Electronics Corp. */ #include <linux/clk.h> @@ -15,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/atomic.h> +#include <linux/sys_soc.h> #define USBHS_LPSTS 0x02 #define USBHS_UGCTRL 0x80 @@ -35,6 +37,8 @@ #define USBHS_UGCTRL2_USB0SEL 0x00000030 #define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010 #define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030 +#define USBHS_UGCTRL2_USB0SEL_USB20 0x00000010 +#define USBHS_UGCTRL2_USB0SEL_HS_USB20 0x00000020 /* USB General status register (UGSTS) */ #define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */ @@ -180,6 +184,60 @@ static int rcar_gen2_phy_power_off(struct phy *p) return 0; } +static int rz_g1c_phy_power_on(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_phy_driver *drv = phy->channel->drv; + void __iomem *base = drv->base; + unsigned long flags; + u32 value; + + spin_lock_irqsave(&drv->lock, flags); + + /* Power on USBHS PHY */ + value = readl(base + USBHS_UGCTRL); + value &= ~USBHS_UGCTRL_PLLRESET; + writel(value, base + USBHS_UGCTRL); + + /* As per the data sheet wait 340 micro sec for power stable */ + udelay(340); + + if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { + value = readw(base + USBHS_LPSTS); + value |= USBHS_LPSTS_SUSPM; + writew(value, base + USBHS_LPSTS); + } + + spin_unlock_irqrestore(&drv->lock, flags); + + return 0; +} + +static int rz_g1c_phy_power_off(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_phy_driver *drv = phy->channel->drv; + void __iomem *base = drv->base; + unsigned long flags; + u32 value; + + spin_lock_irqsave(&drv->lock, flags); + /* Power off USBHS PHY */ + if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { + value = readw(base + USBHS_LPSTS); + value &= ~USBHS_LPSTS_SUSPM; + writew(value, base + USBHS_LPSTS); + } + + value = readl(base + USBHS_UGCTRL); + value |= USBHS_UGCTRL_PLLRESET; + writel(value, base + USBHS_UGCTRL); + + spin_unlock_irqrestore(&drv->lock, flags); + + return 0; +} + static const struct phy_ops rcar_gen2_phy_ops = { .init = rcar_gen2_phy_init, .exit = rcar_gen2_phy_exit, @@ -188,6 +246,14 @@ static const struct phy_ops rcar_gen2_phy_ops = { .owner = THIS_MODULE, }; +static const struct phy_ops rz_g1c_phy_ops = { + .init = rcar_gen2_phy_init, + .exit = rcar_gen2_phy_exit, + .power_on = rz_g1c_phy_power_on, + .power_off = rz_g1c_phy_power_off, + .owner = THIS_MODULE, +}; + static const struct of_device_id rcar_gen2_phy_match_table[] = { { .compatible = "renesas,usb-phy-r8a7790" }, { .compatible = "renesas,usb-phy-r8a7791" }, @@ -224,11 +290,20 @@ static const u32 select_mask[] = { [2] = USBHS_UGCTRL2_USB2SEL, }; -static const u32 select_value[][PHYS_PER_CHANNEL] = { +static const u32 pci_select_value[][PHYS_PER_CHANNEL] = { [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB }, [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 }, }; +static const u32 usb20_select_value[][PHYS_PER_CHANNEL] = { + { USBHS_UGCTRL2_USB0SEL_USB20, USBHS_UGCTRL2_USB0SEL_HS_USB20 }, +}; + +static struct soc_device_attribute soc_r8a77470[] = { + { .soc_id = "r8a77470" }, + { /* sentinel */ } +}; + static int rcar_gen2_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -238,6 +313,8 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; struct clk *clk; + const struct phy_ops *gen2_phy_ops = &rcar_gen2_phy_ops; + const u32 (*select_value)[PHYS_PER_CHANNEL] = pci_select_value; int i = 0; if (!dev->of_node) { @@ -266,6 +343,11 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) drv->clk = clk; drv->base = base; + if (soc_device_match(soc_r8a77470)) { + select_value = usb20_select_value; + gen2_phy_ops = &rz_g1c_phy_ops; + } + drv->num_channels = of_get_child_count(dev->of_node); drv->channels = devm_kcalloc(dev, drv->num_channels, sizeof(struct rcar_gen2_channel), @@ -297,7 +379,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) phy->select_value = select_value[channel_num][n]; phy->phy = devm_phy_create(dev, NULL, - &rcar_gen2_phy_ops); + gen2_phy_ops); if (IS_ERR(phy->phy)) { dev_err(dev, "Failed to create PHY\n"); return PTR_ERR(phy->phy);