Lines Matching +full:drv +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas R-Car Gen2 PHY driver
21 #define USBHS_LPSTS 0x02
22 #define USBHS_UGCTRL 0x80
23 #define USBHS_UGCTRL2 0x84
24 #define USBHS_UGSTS 0x88 /* From technical update */
27 #define USBHS_LPSTS_SUSPM 0x4000
30 #define USBHS_UGCTRL_CONNECT 0x00000004
31 #define USBHS_UGCTRL_PLLRESET 0x00000001
34 #define USBHS_UGCTRL2_USB2SEL 0x80000000
35 #define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000
36 #define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000
37 #define USBHS_UGCTRL2_USB0SEL 0x00000030
38 #define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010
39 #define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030
40 #define USBHS_UGCTRL2_USB0SEL_USB20 0x00000010
41 #define USBHS_UGCTRL2_USB0SEL_HS_USB20 0x00000020
44 #define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */
57 struct rcar_gen2_phy_driver *drv; member
80 struct rcar_gen2_channel *channel = phy->channel; in rcar_gen2_phy_init()
81 struct rcar_gen2_phy_driver *drv = channel->drv; in rcar_gen2_phy_init() local
89 * driver. Achieving this with cmpxcgh() should be SMP-safe. in rcar_gen2_phy_init()
91 if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1) in rcar_gen2_phy_init()
92 return -EBUSY; in rcar_gen2_phy_init()
94 clk_prepare_enable(drv->clk); in rcar_gen2_phy_init()
96 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_init()
97 ugctrl2 = readl(drv->base + USBHS_UGCTRL2); in rcar_gen2_phy_init()
98 ugctrl2 &= ~channel->select_mask; in rcar_gen2_phy_init()
99 ugctrl2 |= phy->select_value; in rcar_gen2_phy_init()
100 writel(ugctrl2, drv->base + USBHS_UGCTRL2); in rcar_gen2_phy_init()
101 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_init()
102 return 0; in rcar_gen2_phy_init()
108 struct rcar_gen2_channel *channel = phy->channel; in rcar_gen2_phy_exit()
110 clk_disable_unprepare(channel->drv->clk); in rcar_gen2_phy_exit()
112 channel->selected_phy = -1; in rcar_gen2_phy_exit()
114 return 0; in rcar_gen2_phy_exit()
120 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rcar_gen2_phy_power_on() local
121 void __iomem *base = drv->base; in rcar_gen2_phy_power_on()
124 int err = 0, i; in rcar_gen2_phy_power_on()
127 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) in rcar_gen2_phy_power_on()
128 return 0; in rcar_gen2_phy_power_on()
130 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_power_on()
141 for (i = 0; i < 20; i++) { in rcar_gen2_phy_power_on()
153 err = -ETIMEDOUT; in rcar_gen2_phy_power_on()
156 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_power_on()
164 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rcar_gen2_phy_power_off() local
165 void __iomem *base = drv->base; in rcar_gen2_phy_power_off()
170 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) in rcar_gen2_phy_power_off()
171 return 0; in rcar_gen2_phy_power_off()
173 spin_lock_irqsave(&drv->lock, flags); in rcar_gen2_phy_power_off()
188 spin_unlock_irqrestore(&drv->lock, flags); in rcar_gen2_phy_power_off()
190 return 0; in rcar_gen2_phy_power_off()
196 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rz_g1c_phy_power_on() local
197 void __iomem *base = drv->base; in rz_g1c_phy_power_on()
201 spin_lock_irqsave(&drv->lock, flags); in rz_g1c_phy_power_on()
211 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { in rz_g1c_phy_power_on()
217 spin_unlock_irqrestore(&drv->lock, flags); in rz_g1c_phy_power_on()
219 return 0; in rz_g1c_phy_power_on()
225 struct rcar_gen2_phy_driver *drv = phy->channel->drv; in rz_g1c_phy_power_off() local
226 void __iomem *base = drv->base; in rz_g1c_phy_power_off()
230 spin_lock_irqsave(&drv->lock, flags); in rz_g1c_phy_power_off()
232 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) { in rz_g1c_phy_power_off()
242 spin_unlock_irqrestore(&drv->lock, flags); in rz_g1c_phy_power_off()
244 return 0; in rz_g1c_phy_power_off()
264 [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
286 .compatible = "renesas,usb-phy-r8a77470",
290 .compatible = "renesas,usb-phy-r8a7790",
294 .compatible = "renesas,usb-phy-r8a7791",
298 .compatible = "renesas,usb-phy-r8a7794",
302 .compatible = "renesas,rcar-gen2-usb-phy",
312 struct rcar_gen2_phy_driver *drv; in rcar_gen2_phy_xlate() local
313 struct device_node *np = args->np; in rcar_gen2_phy_xlate()
316 drv = dev_get_drvdata(dev); in rcar_gen2_phy_xlate()
317 if (!drv) in rcar_gen2_phy_xlate()
318 return ERR_PTR(-EINVAL); in rcar_gen2_phy_xlate()
320 for (i = 0; i < drv->num_channels; i++) { in rcar_gen2_phy_xlate()
321 if (np == drv->channels[i].of_node) in rcar_gen2_phy_xlate()
325 if (i >= drv->num_channels || args->args[0] >= 2) in rcar_gen2_phy_xlate()
326 return ERR_PTR(-ENODEV); in rcar_gen2_phy_xlate()
328 return drv->channels[i].phys[args->args[0]].phy; in rcar_gen2_phy_xlate()
332 [0] = USBHS_UGCTRL2_USB0SEL,
338 struct device *dev = &pdev->dev; in rcar_gen2_phy_probe()
339 struct rcar_gen2_phy_driver *drv; in rcar_gen2_phy_probe() local
346 int i = 0; in rcar_gen2_phy_probe()
348 if (!dev->of_node) { in rcar_gen2_phy_probe()
351 return -EINVAL; in rcar_gen2_phy_probe()
360 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); in rcar_gen2_phy_probe()
365 drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); in rcar_gen2_phy_probe()
366 if (!drv) in rcar_gen2_phy_probe()
367 return -ENOMEM; in rcar_gen2_phy_probe()
369 spin_lock_init(&drv->lock); in rcar_gen2_phy_probe()
371 drv->clk = clk; in rcar_gen2_phy_probe()
372 drv->base = base; in rcar_gen2_phy_probe()
376 return -EINVAL; in rcar_gen2_phy_probe()
378 drv->num_channels = of_get_child_count(dev->of_node); in rcar_gen2_phy_probe()
379 drv->channels = devm_kcalloc(dev, drv->num_channels, in rcar_gen2_phy_probe()
382 if (!drv->channels) in rcar_gen2_phy_probe()
383 return -ENOMEM; in rcar_gen2_phy_probe()
385 for_each_child_of_node(dev->of_node, np) { in rcar_gen2_phy_probe()
386 struct rcar_gen2_channel *channel = drv->channels + i; in rcar_gen2_phy_probe()
390 channel->of_node = np; in rcar_gen2_phy_probe()
391 channel->drv = drv; in rcar_gen2_phy_probe()
392 channel->selected_phy = -1; in rcar_gen2_phy_probe()
395 if (error || channel_num >= data->num_channels) { in rcar_gen2_phy_probe()
400 channel->select_mask = select_mask[channel_num]; in rcar_gen2_phy_probe()
402 for (n = 0; n < PHYS_PER_CHANNEL; n++) { in rcar_gen2_phy_probe()
403 struct rcar_gen2_phy *phy = &channel->phys[n]; in rcar_gen2_phy_probe()
405 phy->channel = channel; in rcar_gen2_phy_probe()
406 phy->number = n; in rcar_gen2_phy_probe()
407 phy->select_value = data->select_value[channel_num][n]; in rcar_gen2_phy_probe()
409 phy->phy = devm_phy_create(dev, NULL, in rcar_gen2_phy_probe()
410 data->gen2_phy_ops); in rcar_gen2_phy_probe()
411 if (IS_ERR(phy->phy)) { in rcar_gen2_phy_probe()
414 return PTR_ERR(phy->phy); in rcar_gen2_phy_probe()
416 phy_set_drvdata(phy->phy, phy); in rcar_gen2_phy_probe()
428 dev_set_drvdata(dev, drv); in rcar_gen2_phy_probe()
430 return 0; in rcar_gen2_phy_probe()
444 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");