| .. | .. |
|---|
| 9 | 9 | */ |
|---|
| 10 | 10 | |
|---|
| 11 | 11 | #include <linux/clk.h> |
|---|
| 12 | +#include <linux/gpio/consumer.h> |
|---|
| 12 | 13 | #include <linux/io.h> |
|---|
| 13 | 14 | #include <linux/interrupt.h> |
|---|
| 14 | 15 | #include <linux/jiffies.h> |
|---|
| .. | .. |
|---|
| 39 | 40 | struct phy *usb11_phy; |
|---|
| 40 | 41 | struct regulator *vbus_reg; |
|---|
| 41 | 42 | struct notifier_block nb; |
|---|
| 42 | | - unsigned int reg_enabled; |
|---|
| 43 | + struct gpio_desc *oc_gpio; |
|---|
| 43 | 44 | }; |
|---|
| 44 | 45 | |
|---|
| 45 | 46 | #define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv) |
|---|
| .. | .. |
|---|
| 86 | 87 | static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on) |
|---|
| 87 | 88 | { |
|---|
| 88 | 89 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 89 | | - struct device *dev = hcd->self.controller; |
|---|
| 90 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 90 | + struct device *dev = hcd->self.controller; |
|---|
| 91 | 91 | int ret; |
|---|
| 92 | | - |
|---|
| 93 | | - if (hub && hub->set_power) |
|---|
| 94 | | - return hub->set_power(1, on); |
|---|
| 95 | 92 | |
|---|
| 96 | 93 | if (!da8xx_ohci->vbus_reg) |
|---|
| 97 | 94 | return 0; |
|---|
| 98 | 95 | |
|---|
| 99 | | - if (on && !da8xx_ohci->reg_enabled) { |
|---|
| 96 | + if (on) { |
|---|
| 100 | 97 | ret = regulator_enable(da8xx_ohci->vbus_reg); |
|---|
| 101 | 98 | if (ret) { |
|---|
| 102 | 99 | dev_err(dev, "Failed to enable regulator: %d\n", ret); |
|---|
| 103 | 100 | return ret; |
|---|
| 104 | 101 | } |
|---|
| 105 | | - da8xx_ohci->reg_enabled = 1; |
|---|
| 106 | | - |
|---|
| 107 | | - } else if (!on && da8xx_ohci->reg_enabled) { |
|---|
| 102 | + } else { |
|---|
| 108 | 103 | ret = regulator_disable(da8xx_ohci->vbus_reg); |
|---|
| 109 | 104 | if (ret) { |
|---|
| 110 | 105 | dev_err(dev, "Failed to disable regulator: %d\n", ret); |
|---|
| 111 | 106 | return ret; |
|---|
| 112 | 107 | } |
|---|
| 113 | | - da8xx_ohci->reg_enabled = 0; |
|---|
| 114 | 108 | } |
|---|
| 115 | 109 | |
|---|
| 116 | 110 | return 0; |
|---|
| .. | .. |
|---|
| 119 | 113 | static int ohci_da8xx_get_power(struct usb_hcd *hcd) |
|---|
| 120 | 114 | { |
|---|
| 121 | 115 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 122 | | - struct device *dev = hcd->self.controller; |
|---|
| 123 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 124 | | - |
|---|
| 125 | | - if (hub && hub->get_power) |
|---|
| 126 | | - return hub->get_power(1); |
|---|
| 127 | 116 | |
|---|
| 128 | 117 | if (da8xx_ohci->vbus_reg) |
|---|
| 129 | 118 | return regulator_is_enabled(da8xx_ohci->vbus_reg); |
|---|
| .. | .. |
|---|
| 134 | 123 | static int ohci_da8xx_get_oci(struct usb_hcd *hcd) |
|---|
| 135 | 124 | { |
|---|
| 136 | 125 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 137 | | - struct device *dev = hcd->self.controller; |
|---|
| 138 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 139 | 126 | unsigned int flags; |
|---|
| 140 | 127 | int ret; |
|---|
| 141 | 128 | |
|---|
| 142 | | - if (hub && hub->get_oci) |
|---|
| 143 | | - return hub->get_oci(1); |
|---|
| 129 | + if (da8xx_ohci->oc_gpio) |
|---|
| 130 | + return gpiod_get_value_cansleep(da8xx_ohci->oc_gpio); |
|---|
| 144 | 131 | |
|---|
| 145 | 132 | if (!da8xx_ohci->vbus_reg) |
|---|
| 146 | 133 | return 0; |
|---|
| .. | .. |
|---|
| 158 | 145 | static int ohci_da8xx_has_set_power(struct usb_hcd *hcd) |
|---|
| 159 | 146 | { |
|---|
| 160 | 147 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 161 | | - struct device *dev = hcd->self.controller; |
|---|
| 162 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 163 | | - |
|---|
| 164 | | - if (hub && hub->set_power) |
|---|
| 165 | | - return 1; |
|---|
| 166 | 148 | |
|---|
| 167 | 149 | if (da8xx_ohci->vbus_reg) |
|---|
| 168 | 150 | return 1; |
|---|
| .. | .. |
|---|
| 173 | 155 | static int ohci_da8xx_has_oci(struct usb_hcd *hcd) |
|---|
| 174 | 156 | { |
|---|
| 175 | 157 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 176 | | - struct device *dev = hcd->self.controller; |
|---|
| 177 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 178 | 158 | |
|---|
| 179 | | - if (hub && hub->get_oci) |
|---|
| 159 | + if (da8xx_ohci->oc_gpio) |
|---|
| 180 | 160 | return 1; |
|---|
| 181 | 161 | |
|---|
| 182 | 162 | if (da8xx_ohci->vbus_reg) |
|---|
| .. | .. |
|---|
| 196 | 176 | return 0; |
|---|
| 197 | 177 | } |
|---|
| 198 | 178 | |
|---|
| 199 | | -/* |
|---|
| 200 | | - * Handle the port over-current indicator change. |
|---|
| 201 | | - */ |
|---|
| 202 | | -static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, |
|---|
| 203 | | - unsigned port) |
|---|
| 204 | | -{ |
|---|
| 205 | | - ocic_mask |= 1 << port; |
|---|
| 206 | | - |
|---|
| 207 | | - /* Once over-current is detected, the port needs to be powered down */ |
|---|
| 208 | | - if (hub->get_oci(port) > 0) |
|---|
| 209 | | - hub->set_power(port, 0); |
|---|
| 210 | | -} |
|---|
| 211 | | - |
|---|
| 212 | 179 | static int ohci_da8xx_regulator_event(struct notifier_block *nb, |
|---|
| 213 | 180 | unsigned long event, void *data) |
|---|
| 214 | 181 | { |
|---|
| .. | .. |
|---|
| 223 | 190 | return 0; |
|---|
| 224 | 191 | } |
|---|
| 225 | 192 | |
|---|
| 193 | +static irqreturn_t ohci_da8xx_oc_thread(int irq, void *data) |
|---|
| 194 | +{ |
|---|
| 195 | + struct da8xx_ohci_hcd *da8xx_ohci = data; |
|---|
| 196 | + struct device *dev = da8xx_ohci->hcd->self.controller; |
|---|
| 197 | + int ret; |
|---|
| 198 | + |
|---|
| 199 | + if (gpiod_get_value_cansleep(da8xx_ohci->oc_gpio) && |
|---|
| 200 | + da8xx_ohci->vbus_reg) { |
|---|
| 201 | + ret = regulator_disable(da8xx_ohci->vbus_reg); |
|---|
| 202 | + if (ret) |
|---|
| 203 | + dev_err(dev, "Failed to disable regulator: %d\n", ret); |
|---|
| 204 | + } |
|---|
| 205 | + |
|---|
| 206 | + return IRQ_HANDLED; |
|---|
| 207 | +} |
|---|
| 208 | + |
|---|
| 226 | 209 | static int ohci_da8xx_register_notify(struct usb_hcd *hcd) |
|---|
| 227 | 210 | { |
|---|
| 228 | 211 | struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 229 | 212 | struct device *dev = hcd->self.controller; |
|---|
| 230 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 231 | 213 | int ret = 0; |
|---|
| 232 | 214 | |
|---|
| 233 | | - if (hub && hub->ocic_notify) { |
|---|
| 234 | | - ret = hub->ocic_notify(ohci_da8xx_ocic_handler); |
|---|
| 235 | | - } else if (da8xx_ohci->vbus_reg) { |
|---|
| 215 | + if (!da8xx_ohci->oc_gpio && da8xx_ohci->vbus_reg) { |
|---|
| 236 | 216 | da8xx_ohci->nb.notifier_call = ohci_da8xx_regulator_event; |
|---|
| 237 | 217 | ret = devm_regulator_register_notifier(da8xx_ohci->vbus_reg, |
|---|
| 238 | 218 | &da8xx_ohci->nb); |
|---|
| .. | .. |
|---|
| 242 | 222 | dev_err(dev, "Failed to register notifier: %d\n", ret); |
|---|
| 243 | 223 | |
|---|
| 244 | 224 | return ret; |
|---|
| 245 | | -} |
|---|
| 246 | | - |
|---|
| 247 | | -static void ohci_da8xx_unregister_notify(struct usb_hcd *hcd) |
|---|
| 248 | | -{ |
|---|
| 249 | | - struct device *dev = hcd->self.controller; |
|---|
| 250 | | - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); |
|---|
| 251 | | - |
|---|
| 252 | | - if (hub && hub->ocic_notify) |
|---|
| 253 | | - hub->ocic_notify(NULL); |
|---|
| 254 | 225 | } |
|---|
| 255 | 226 | |
|---|
| 256 | 227 | static int ohci_da8xx_reset(struct usb_hcd *hcd) |
|---|
| .. | .. |
|---|
| 402 | 373 | static int ohci_da8xx_probe(struct platform_device *pdev) |
|---|
| 403 | 374 | { |
|---|
| 404 | 375 | struct da8xx_ohci_hcd *da8xx_ohci; |
|---|
| 376 | + struct device *dev = &pdev->dev; |
|---|
| 377 | + int error, hcd_irq, oc_irq; |
|---|
| 405 | 378 | struct usb_hcd *hcd; |
|---|
| 406 | 379 | struct resource *mem; |
|---|
| 407 | | - int error, irq; |
|---|
| 408 | | - hcd = usb_create_hcd(&ohci_da8xx_hc_driver, &pdev->dev, |
|---|
| 409 | | - dev_name(&pdev->dev)); |
|---|
| 380 | + |
|---|
| 381 | + hcd = usb_create_hcd(&ohci_da8xx_hc_driver, dev, dev_name(dev)); |
|---|
| 410 | 382 | if (!hcd) |
|---|
| 411 | 383 | return -ENOMEM; |
|---|
| 412 | 384 | |
|---|
| 413 | 385 | da8xx_ohci = to_da8xx_ohci(hcd); |
|---|
| 414 | 386 | da8xx_ohci->hcd = hcd; |
|---|
| 415 | 387 | |
|---|
| 416 | | - da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 388 | + da8xx_ohci->usb11_clk = devm_clk_get(dev, NULL); |
|---|
| 417 | 389 | if (IS_ERR(da8xx_ohci->usb11_clk)) { |
|---|
| 418 | 390 | error = PTR_ERR(da8xx_ohci->usb11_clk); |
|---|
| 419 | 391 | if (error != -EPROBE_DEFER) |
|---|
| 420 | | - dev_err(&pdev->dev, "Failed to get clock.\n"); |
|---|
| 392 | + dev_err(dev, "Failed to get clock.\n"); |
|---|
| 421 | 393 | goto err; |
|---|
| 422 | 394 | } |
|---|
| 423 | 395 | |
|---|
| 424 | | - da8xx_ohci->usb11_phy = devm_phy_get(&pdev->dev, "usb-phy"); |
|---|
| 396 | + da8xx_ohci->usb11_phy = devm_phy_get(dev, "usb-phy"); |
|---|
| 425 | 397 | if (IS_ERR(da8xx_ohci->usb11_phy)) { |
|---|
| 426 | 398 | error = PTR_ERR(da8xx_ohci->usb11_phy); |
|---|
| 427 | 399 | if (error != -EPROBE_DEFER) |
|---|
| 428 | | - dev_err(&pdev->dev, "Failed to get phy.\n"); |
|---|
| 400 | + dev_err(dev, "Failed to get phy.\n"); |
|---|
| 429 | 401 | goto err; |
|---|
| 430 | 402 | } |
|---|
| 431 | 403 | |
|---|
| 432 | | - da8xx_ohci->vbus_reg = devm_regulator_get_optional(&pdev->dev, "vbus"); |
|---|
| 404 | + da8xx_ohci->vbus_reg = devm_regulator_get_optional(dev, "vbus"); |
|---|
| 433 | 405 | if (IS_ERR(da8xx_ohci->vbus_reg)) { |
|---|
| 434 | 406 | error = PTR_ERR(da8xx_ohci->vbus_reg); |
|---|
| 435 | 407 | if (error == -ENODEV) { |
|---|
| .. | .. |
|---|
| 437 | 409 | } else if (error == -EPROBE_DEFER) { |
|---|
| 438 | 410 | goto err; |
|---|
| 439 | 411 | } else { |
|---|
| 440 | | - dev_err(&pdev->dev, "Failed to get regulator\n"); |
|---|
| 412 | + dev_err(dev, "Failed to get regulator\n"); |
|---|
| 441 | 413 | goto err; |
|---|
| 442 | 414 | } |
|---|
| 443 | 415 | } |
|---|
| 444 | 416 | |
|---|
| 417 | + da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN); |
|---|
| 418 | + if (IS_ERR(da8xx_ohci->oc_gpio)) { |
|---|
| 419 | + error = PTR_ERR(da8xx_ohci->oc_gpio); |
|---|
| 420 | + goto err; |
|---|
| 421 | + } |
|---|
| 422 | + |
|---|
| 423 | + if (da8xx_ohci->oc_gpio) { |
|---|
| 424 | + oc_irq = gpiod_to_irq(da8xx_ohci->oc_gpio); |
|---|
| 425 | + if (oc_irq < 0) { |
|---|
| 426 | + error = oc_irq; |
|---|
| 427 | + goto err; |
|---|
| 428 | + } |
|---|
| 429 | + |
|---|
| 430 | + error = devm_request_threaded_irq(dev, oc_irq, NULL, |
|---|
| 431 | + ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING | |
|---|
| 432 | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
|---|
| 433 | + "OHCI over-current indicator", da8xx_ohci); |
|---|
| 434 | + if (error) |
|---|
| 435 | + goto err; |
|---|
| 436 | + } |
|---|
| 437 | + |
|---|
| 445 | 438 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 446 | | - hcd->regs = devm_ioremap_resource(&pdev->dev, mem); |
|---|
| 439 | + hcd->regs = devm_ioremap_resource(dev, mem); |
|---|
| 447 | 440 | if (IS_ERR(hcd->regs)) { |
|---|
| 448 | 441 | error = PTR_ERR(hcd->regs); |
|---|
| 449 | 442 | goto err; |
|---|
| .. | .. |
|---|
| 451 | 444 | hcd->rsrc_start = mem->start; |
|---|
| 452 | 445 | hcd->rsrc_len = resource_size(mem); |
|---|
| 453 | 446 | |
|---|
| 454 | | - irq = platform_get_irq(pdev, 0); |
|---|
| 455 | | - if (irq < 0) { |
|---|
| 447 | + hcd_irq = platform_get_irq(pdev, 0); |
|---|
| 448 | + if (hcd_irq < 0) { |
|---|
| 456 | 449 | error = -ENODEV; |
|---|
| 457 | 450 | goto err; |
|---|
| 458 | 451 | } |
|---|
| 459 | 452 | |
|---|
| 460 | | - error = usb_add_hcd(hcd, irq, 0); |
|---|
| 453 | + error = usb_add_hcd(hcd, hcd_irq, 0); |
|---|
| 461 | 454 | if (error) |
|---|
| 462 | 455 | goto err; |
|---|
| 463 | 456 | |
|---|
| .. | .. |
|---|
| 480 | 473 | { |
|---|
| 481 | 474 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
|---|
| 482 | 475 | |
|---|
| 483 | | - ohci_da8xx_unregister_notify(hcd); |
|---|
| 484 | 476 | usb_remove_hcd(hcd); |
|---|
| 485 | 477 | usb_put_hcd(hcd); |
|---|
| 486 | 478 | |
|---|