Lines Matching +full:usb +full:- +full:phy +full:- +full:r8a7790
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas R-Car Gen2 PHY driver
15 #include <linux/phy/phy.h>
28 /* USB General control register (UGCTRL) */
32 /* USB General control register 2 (UGCTRL2) */
42 /* USB General status register (UGSTS) */
48 struct phy *phy; member
76 static int rcar_gen2_phy_init(struct phy *p) in rcar_gen2_phy_init()
78 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rcar_gen2_phy_init() local
79 struct rcar_gen2_channel *channel = phy->channel; in rcar_gen2_phy_init()
80 struct rcar_gen2_phy_driver *drv = channel->drv; in rcar_gen2_phy_init()
85 * Try to acquire exclusive access to PHY. The first driver calling in rcar_gen2_phy_init()
87 * PHY on this channel will fail until phy_exit() is called by the first in rcar_gen2_phy_init()
88 * driver. Achieving this with cmpxcgh() should be SMP-safe. in rcar_gen2_phy_init()
90 if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1) in rcar_gen2_phy_init()
91 return -EBUSY; in rcar_gen2_phy_init()
93 clk_prepare_enable(drv->clk); in rcar_gen2_phy_init()
95 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_init()
96 ugctrl2 = readl(drv->base + USBHS_UGCTRL2); in rcar_gen2_phy_init()
97 ugctrl2 &= ~channel->select_mask; in rcar_gen2_phy_init()
98 ugctrl2 |= phy->select_value; in rcar_gen2_phy_init()
99 writel(ugctrl2, drv->base + USBHS_UGCTRL2); in rcar_gen2_phy_init()
100 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_init()
104 static int rcar_gen2_phy_exit(struct phy *p) in rcar_gen2_phy_exit()
106 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rcar_gen2_phy_exit() local
107 struct rcar_gen2_channel *channel = phy->channel; in rcar_gen2_phy_exit()
109 clk_disable_unprepare(channel->drv->clk); in rcar_gen2_phy_exit()
111 channel->selected_phy = -1; in rcar_gen2_phy_exit()
116 static int rcar_gen2_phy_power_on(struct phy *p) in rcar_gen2_phy_power_on()
118 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rcar_gen2_phy_power_on() local
119 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rcar_gen2_phy_power_on()
120 void __iomem *base = drv->base; in rcar_gen2_phy_power_on()
126 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) in rcar_gen2_phy_power_on()
129 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_power_on()
131 /* Power on USBHS PHY */ in rcar_gen2_phy_power_on()
152 err = -ETIMEDOUT; in rcar_gen2_phy_power_on()
155 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_power_on()
160 static int rcar_gen2_phy_power_off(struct phy *p) in rcar_gen2_phy_power_off()
162 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rcar_gen2_phy_power_off() local
163 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rcar_gen2_phy_power_off()
164 void __iomem *base = drv->base; in rcar_gen2_phy_power_off()
169 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) in rcar_gen2_phy_power_off()
172 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_power_off()
174 /* Power off USBHS PHY */ in rcar_gen2_phy_power_off()
187 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_power_off()
192 static int rz_g1c_phy_power_on(struct phy *p) in rz_g1c_phy_power_on()
194 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rz_g1c_phy_power_on() local
195 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rz_g1c_phy_power_on()
196 void __iomem *base = drv->base; in rz_g1c_phy_power_on()
200 spin_lock_irqsave(&drv->lock, flags); in rz_g1c_phy_power_on()
202 /* Power on USBHS PHY */ in rz_g1c_phy_power_on()
210 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { in rz_g1c_phy_power_on()
216 spin_unlock_irqrestore(&drv->lock, flags); in rz_g1c_phy_power_on()
221 static int rz_g1c_phy_power_off(struct phy *p) in rz_g1c_phy_power_off()
223 struct rcar_gen2_phy *phy = phy_get_drvdata(p); in rz_g1c_phy_power_off() local
224 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rz_g1c_phy_power_off()
225 void __iomem *base = drv->base; in rz_g1c_phy_power_off()
229 spin_lock_irqsave(&drv->lock, flags); in rz_g1c_phy_power_off()
230 /* Power off USBHS PHY */ in rz_g1c_phy_power_off()
231 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { in rz_g1c_phy_power_off()
241 spin_unlock_irqrestore(&drv->lock, flags); in rz_g1c_phy_power_off()
285 .compatible = "renesas,usb-phy-r8a77470",
289 .compatible = "renesas,usb-phy-r8a7790",
293 .compatible = "renesas,usb-phy-r8a7791",
297 .compatible = "renesas,usb-phy-r8a7794",
301 .compatible = "renesas,rcar-gen2-usb-phy",
308 static struct phy *rcar_gen2_phy_xlate(struct device *dev, in rcar_gen2_phy_xlate()
312 struct device_node *np = args->np; in rcar_gen2_phy_xlate()
317 return ERR_PTR(-EINVAL); in rcar_gen2_phy_xlate()
319 for (i = 0; i < drv->num_channels; i++) { in rcar_gen2_phy_xlate()
320 if (np == drv->channels[i].of_node) in rcar_gen2_phy_xlate()
324 if (i >= drv->num_channels || args->args[0] >= 2) in rcar_gen2_phy_xlate()
325 return ERR_PTR(-ENODEV); in rcar_gen2_phy_xlate()
327 return drv->channels[i].phys[args->args[0]].phy; in rcar_gen2_phy_xlate()
337 struct device *dev = &pdev->dev; in rcar_gen2_phy_probe()
346 if (!dev->of_node) { in rcar_gen2_phy_probe()
349 return -EINVAL; in rcar_gen2_phy_probe()
364 return -ENOMEM; in rcar_gen2_phy_probe()
366 spin_lock_init(&drv->lock); in rcar_gen2_phy_probe()
368 drv->clk = clk; in rcar_gen2_phy_probe()
369 drv->base = base; in rcar_gen2_phy_probe()
373 return -EINVAL; in rcar_gen2_phy_probe()
375 drv->num_channels = of_get_child_count(dev->of_node); in rcar_gen2_phy_probe()
376 drv->channels = devm_kcalloc(dev, drv->num_channels, in rcar_gen2_phy_probe()
379 if (!drv->channels) in rcar_gen2_phy_probe()
380 return -ENOMEM; in rcar_gen2_phy_probe()
382 for_each_child_of_node(dev->of_node, np) { in rcar_gen2_phy_probe()
383 struct rcar_gen2_channel *channel = drv->channels + i; in rcar_gen2_phy_probe()
387 channel->of_node = np; in rcar_gen2_phy_probe()
388 channel->drv = drv; in rcar_gen2_phy_probe()
389 channel->selected_phy = -1; in rcar_gen2_phy_probe()
392 if (error || channel_num >= data->num_channels) { in rcar_gen2_phy_probe()
397 channel->select_mask = select_mask[channel_num]; in rcar_gen2_phy_probe()
400 struct rcar_gen2_phy *phy = &channel->phys[n]; in rcar_gen2_phy_probe() local
402 phy->channel = channel; in rcar_gen2_phy_probe()
403 phy->number = n; in rcar_gen2_phy_probe()
404 phy->select_value = data->select_value[channel_num][n]; in rcar_gen2_phy_probe()
406 phy->phy = devm_phy_create(dev, NULL, in rcar_gen2_phy_probe()
407 data->gen2_phy_ops); in rcar_gen2_phy_probe()
408 if (IS_ERR(phy->phy)) { in rcar_gen2_phy_probe()
409 dev_err(dev, "Failed to create PHY\n"); in rcar_gen2_phy_probe()
411 return PTR_ERR(phy->phy); in rcar_gen2_phy_probe()
413 phy_set_drvdata(phy->phy, phy); in rcar_gen2_phy_probe()
421 dev_err(dev, "Failed to register PHY provider\n"); in rcar_gen2_phy_probe()
441 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");