Lines Matching +full:usb +full:- +full:vbus
1 // SPDX-License-Identifier: GPL-2.0+
3 * NOP USB transceiver for all USB transceiver which are either built-in
4 * into USB IP or which are mostly autonomous.
16 #include <linux/dma-mapping.h>
17 #include <linux/usb/gadget.h>
18 #include <linux/usb/otg.h>
19 #include <linux/usb/usb_phy_generic.h>
27 #include "phy-generic.h"
48 struct usb_phy_generic *nop = dev_get_drvdata(x->dev); in nop_set_suspend()
50 if (!IS_ERR(nop->clk)) { in nop_set_suspend()
52 clk_disable_unprepare(nop->clk); in nop_set_suspend()
54 clk_prepare_enable(nop->clk); in nop_set_suspend()
62 if (!nop->gpiod_reset) in nop_reset()
65 gpiod_set_value_cansleep(nop->gpiod_reset, 1); in nop_reset()
67 gpiod_set_value_cansleep(nop->gpiod_reset, 0); in nop_reset()
73 struct regulator *vbus_draw = nop->vbus_draw; in nop_set_vbus_draw()
80 enabled = nop->vbus_draw_enabled; in nop_set_vbus_draw()
87 nop->vbus_draw_enabled = 1; in nop_set_vbus_draw()
94 nop->vbus_draw_enabled = 0; in nop_set_vbus_draw()
97 nop->mA = mA; in nop_set_vbus_draw()
104 struct usb_otg *otg = nop->phy.otg; in nop_gpio_vbus_thread()
105 int vbus, status; in nop_gpio_vbus_thread() local
107 vbus = gpiod_get_value(nop->gpiod_vbus); in nop_gpio_vbus_thread()
108 if ((vbus ^ nop->vbus) == 0) in nop_gpio_vbus_thread()
110 nop->vbus = vbus; in nop_gpio_vbus_thread()
112 if (vbus) { in nop_gpio_vbus_thread()
114 otg->state = OTG_STATE_B_PERIPHERAL; in nop_gpio_vbus_thread()
115 nop->phy.last_event = status; in nop_gpio_vbus_thread()
120 atomic_notifier_call_chain(&nop->phy.notifier, status, in nop_gpio_vbus_thread()
121 otg->gadget); in nop_gpio_vbus_thread()
126 otg->state = OTG_STATE_B_IDLE; in nop_gpio_vbus_thread()
127 nop->phy.last_event = status; in nop_gpio_vbus_thread()
129 atomic_notifier_call_chain(&nop->phy.notifier, status, in nop_gpio_vbus_thread()
130 otg->gadget); in nop_gpio_vbus_thread()
137 struct usb_phy_generic *nop = dev_get_drvdata(phy->dev); in usb_gen_phy_init()
140 if (!IS_ERR(nop->vcc)) { in usb_gen_phy_init()
141 if (regulator_enable(nop->vcc)) in usb_gen_phy_init()
142 dev_err(phy->dev, "Failed to enable power\n"); in usb_gen_phy_init()
145 if (!IS_ERR(nop->clk)) { in usb_gen_phy_init()
146 ret = clk_prepare_enable(nop->clk); in usb_gen_phy_init()
159 struct usb_phy_generic *nop = dev_get_drvdata(phy->dev); in usb_gen_phy_shutdown()
161 gpiod_set_value_cansleep(nop->gpiod_reset, 1); in usb_gen_phy_shutdown()
163 if (!IS_ERR(nop->clk)) in usb_gen_phy_shutdown()
164 clk_disable_unprepare(nop->clk); in usb_gen_phy_shutdown()
166 if (!IS_ERR(nop->vcc)) { in usb_gen_phy_shutdown()
167 if (regulator_disable(nop->vcc)) in usb_gen_phy_shutdown()
168 dev_err(phy->dev, "Failed to disable power\n"); in usb_gen_phy_shutdown()
176 return -ENODEV; in nop_set_peripheral()
179 otg->gadget = NULL; in nop_set_peripheral()
180 return -ENODEV; in nop_set_peripheral()
183 otg->gadget = gadget; in nop_set_peripheral()
184 if (otg->state == OTG_STATE_B_PERIPHERAL) in nop_set_peripheral()
185 atomic_notifier_call_chain(&otg->usb_phy->notifier, in nop_set_peripheral()
186 USB_EVENT_VBUS, otg->gadget); in nop_set_peripheral()
188 otg->state = OTG_STATE_B_IDLE; in nop_set_peripheral()
195 return -ENODEV; in nop_set_host()
198 otg->host = NULL; in nop_set_host()
199 return -ENODEV; in nop_set_host()
202 otg->host = host; in nop_set_host()
214 if (dev->of_node) { in usb_phy_gen_create_phy()
215 struct device_node *node = dev->of_node; in usb_phy_gen_create_phy()
217 if (of_property_read_u32(node, "clock-frequency", &clk_rate)) in usb_phy_gen_create_phy()
222 nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset", in usb_phy_gen_create_phy()
224 err = PTR_ERR_OR_ZERO(nop->gpiod_reset); in usb_phy_gen_create_phy()
226 nop->gpiod_vbus = devm_gpiod_get_optional(dev, in usb_phy_gen_create_phy()
227 "vbus-detect", in usb_phy_gen_create_phy()
229 err = PTR_ERR_OR_ZERO(nop->gpiod_vbus); in usb_phy_gen_create_phy()
234 "Error requesting RESET or VBUS GPIO\n"); in usb_phy_gen_create_phy()
235 if (nop->gpiod_reset) in usb_phy_gen_create_phy()
236 gpiod_direction_output(nop->gpiod_reset, 1); in usb_phy_gen_create_phy()
238 nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), in usb_phy_gen_create_phy()
240 if (!nop->phy.otg) in usb_phy_gen_create_phy()
241 return -ENOMEM; in usb_phy_gen_create_phy()
243 nop->clk = devm_clk_get(dev, "main_clk"); in usb_phy_gen_create_phy()
244 if (IS_ERR(nop->clk)) { in usb_phy_gen_create_phy()
246 PTR_ERR(nop->clk)); in usb_phy_gen_create_phy()
248 return PTR_ERR(nop->clk); in usb_phy_gen_create_phy()
251 if (!IS_ERR(nop->clk) && clk_rate) { in usb_phy_gen_create_phy()
252 err = clk_set_rate(nop->clk, clk_rate); in usb_phy_gen_create_phy()
259 nop->vcc = devm_regulator_get_optional(dev, "vcc"); in usb_phy_gen_create_phy()
260 if (IS_ERR(nop->vcc) && PTR_ERR(nop->vcc) != -ENODEV) in usb_phy_gen_create_phy()
261 return dev_err_probe(dev, PTR_ERR(nop->vcc), in usb_phy_gen_create_phy()
264 nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus"); in usb_phy_gen_create_phy()
265 if (PTR_ERR(nop->vbus_draw) == -ENODEV) in usb_phy_gen_create_phy()
266 nop->vbus_draw = NULL; in usb_phy_gen_create_phy()
267 if (IS_ERR(nop->vbus_draw)) in usb_phy_gen_create_phy()
268 return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), in usb_phy_gen_create_phy()
269 "could not get vbus regulator\n"); in usb_phy_gen_create_phy()
271 nop->dev = dev; in usb_phy_gen_create_phy()
272 nop->phy.dev = nop->dev; in usb_phy_gen_create_phy()
273 nop->phy.label = "nop-xceiv"; in usb_phy_gen_create_phy()
274 nop->phy.set_suspend = nop_set_suspend; in usb_phy_gen_create_phy()
275 nop->phy.type = type; in usb_phy_gen_create_phy()
277 nop->phy.otg->state = OTG_STATE_UNDEFINED; in usb_phy_gen_create_phy()
278 nop->phy.otg->usb_phy = &nop->phy; in usb_phy_gen_create_phy()
279 nop->phy.otg->set_host = nop_set_host; in usb_phy_gen_create_phy()
280 nop->phy.otg->set_peripheral = nop_set_peripheral; in usb_phy_gen_create_phy()
288 struct device *dev = &pdev->dev; in usb_phy_generic_probe()
289 struct device_node *dn = dev->of_node; in usb_phy_generic_probe()
295 return -ENOMEM; in usb_phy_generic_probe()
300 if (nop->gpiod_vbus) { in usb_phy_generic_probe()
301 err = devm_request_threaded_irq(&pdev->dev, in usb_phy_generic_probe()
302 gpiod_to_irq(nop->gpiod_vbus), in usb_phy_generic_probe()
307 dev_err(&pdev->dev, "can't request irq %i, err: %d\n", in usb_phy_generic_probe()
308 gpiod_to_irq(nop->gpiod_vbus), err); in usb_phy_generic_probe()
311 nop->phy.otg->state = gpiod_get_value(nop->gpiod_vbus) ? in usb_phy_generic_probe()
315 nop->phy.init = usb_gen_phy_init; in usb_phy_generic_probe()
316 nop->phy.shutdown = usb_gen_phy_shutdown; in usb_phy_generic_probe()
318 err = usb_add_phy_dev(&nop->phy); in usb_phy_generic_probe()
320 dev_err(&pdev->dev, "can't register transceiver, err: %d\n", in usb_phy_generic_probe()
327 device_set_wakeup_capable(&pdev->dev, in usb_phy_generic_probe()
328 of_property_read_bool(dn, "wakeup-source")); in usb_phy_generic_probe()
337 usb_remove_phy(&nop->phy); in usb_phy_generic_remove()
341 { .compatible = "usb-nop-xceiv" },
370 MODULE_DESCRIPTION("NOP USB Transceiver driver");