Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'usb-ci-v4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next

Peter writes:

- Improve the over-current handling for imx
- Add the HSIC support for imx

* tag 'usb-ci-v4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb:
usb: chipidea: imx: allow to configure oc polarity on i.MX25
usb: chipidea: imx: Warn if oc polarity isn't specified
usb: chipidea: imx: support configuring for active low oc signal
doc: usb: ci-hdrc-usb2: Add pinctrl properties for HSIC pin groups
usb: chipidea: host: override ehci->hub_control
usb: chipidea: imx: add HSIC support
usb: chipidea: add flag for imx hsic implementation

+457 -36
+33 -3
Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
··· 80 80 controller. It's expected that a mux state of 0 indicates device mode and a 81 81 mux state of 1 indicates host mode. 82 82 - mux-control-names: Shall be "usb_switch" if mux-controls is specified. 83 - - pinctrl-names: Names for optional pin modes in "default", "host", "device" 83 + - pinctrl-names: Names for optional pin modes in "default", "host", "device". 84 + In case of HSIC-mode, "idle" and "active" pin modes are mandatory. In this 85 + case, the "idle" state needs to pull down the data and strobe pin 86 + and the "active" state needs to pull up the strobe pin. 84 87 - pinctrl-n: alternate pin modes 85 88 86 89 i.mx specific properties 87 90 - fsl,usbmisc: phandler of non-core register device, with one 88 91 argument that indicate usb controller index 89 92 - disable-over-current: disable over current detect 90 - - over-current-active-high: over current signal polarity is high active, 91 - typically over current signal polarity is low active. 93 + - over-current-active-low: over current signal polarity is active low. 94 + - over-current-active-high: over current signal polarity is active high. 95 + It's recommended to specify the over current polarity. 92 96 - external-vbus-divider: enables off-chip resistor divider for Vbus 93 97 94 98 Example: ··· 114 110 phy-clkgate-delay-us = <400>; 115 111 mux-controls = <&usb_switch>; 116 112 mux-control-names = "usb_switch"; 113 + }; 114 + 115 + Example for HSIC: 116 + 117 + usb@2184400 { 118 + compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; 119 + reg = <0x02184400 0x200>; 120 + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; 121 + clocks = <&clks IMX6QDL_CLK_USBOH3>; 122 + fsl,usbphy = <&usbphynop1>; 123 + fsl,usbmisc = <&usbmisc 2>; 124 + phy_type = "hsic"; 125 + dr_mode = "host"; 126 + ahb-burst-config = <0x0>; 127 + tx-burst-size-dword = <0x10>; 128 + rx-burst-size-dword = <0x10>; 129 + pinctrl-names = "idle", "active"; 130 + pinctrl-0 = <&pinctrl_usbh2_idle>; 131 + pinctrl-1 = <&pinctrl_usbh2_active>; 132 + #address-cells = <1>; 133 + #size-cells = <0>; 134 + 135 + usbnet: smsc@1 { 136 + compatible = "usb424,9730"; 137 + reg = <1>; 138 + }; 117 139 };
+140 -22
drivers/usb/chipidea/ci_hdrc_imx.c
··· 14 14 #include <linux/usb/chipidea.h> 15 15 #include <linux/usb/of.h> 16 16 #include <linux/clk.h> 17 + #include <linux/pinctrl/consumer.h> 17 18 18 19 #include "ci.h" 19 20 #include "ci_hdrc_imx.h" ··· 86 85 bool supports_runtime_pm; 87 86 bool override_phy_control; 88 87 bool in_lpm; 88 + struct pinctrl *pinctrl; 89 + struct pinctrl_state *pinctrl_hsic_active; 90 + struct regulator *hsic_pad_regulator; 89 91 /* SoC before i.mx6 (except imx23/imx28) needs three clks */ 90 92 bool need_three_clks; 91 93 struct clk *clk_ipg; ··· 136 132 137 133 data->dev = &misc_pdev->dev; 138 134 139 - if (of_find_property(np, "disable-over-current", NULL)) 135 + /* 136 + * Check the various over current related properties. If over current 137 + * detection is disabled we're not interested in the polarity. 138 + */ 139 + if (of_find_property(np, "disable-over-current", NULL)) { 140 140 data->disable_oc = 1; 141 - 142 - if (of_find_property(np, "over-current-active-high", NULL)) 143 - data->oc_polarity = 1; 141 + } else if (of_find_property(np, "over-current-active-high", NULL)) { 142 + data->oc_pol_active_low = 0; 143 + data->oc_pol_configured = 1; 144 + } else if (of_find_property(np, "over-current-active-low", NULL)) { 145 + data->oc_pol_active_low = 1; 146 + data->oc_pol_configured = 1; 147 + } else { 148 + dev_warn(dev, "No over current polarity defined\n"); 149 + } 144 150 145 151 if (of_find_property(np, "external-vbus-divider", NULL)) 146 152 data->evdo = 1; ··· 259 245 } 260 246 } 261 247 248 + static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) 249 + { 250 + struct device *dev = ci->dev->parent; 251 + struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 252 + int ret = 0; 253 + 254 + switch (event) { 255 + case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: 256 + ret = pinctrl_select_state(data->pinctrl, 257 + data->pinctrl_hsic_active); 258 + if (ret) 259 + dev_err(dev, "hsic_active select failed, err=%d\n", 260 + ret); 261 + break; 262 + case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: 263 + ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data); 264 + if (ret) 265 + dev_err(dev, 266 + "hsic_set_connect failed, err=%d\n", ret); 267 + break; 268 + default: 269 + break; 270 + } 271 + 272 + return ret; 273 + } 274 + 262 275 static int ci_hdrc_imx_probe(struct platform_device *pdev) 263 276 { 264 277 struct ci_hdrc_imx_data *data; 265 278 struct ci_hdrc_platform_data pdata = { 266 279 .name = dev_name(&pdev->dev), 267 280 .capoffset = DEF_CAPOFFSET, 281 + .notify_event = ci_hdrc_imx_notify_event, 268 282 }; 269 283 int ret; 270 284 const struct of_device_id *of_id; 271 285 const struct ci_hdrc_imx_platform_flag *imx_platform_flag; 272 286 struct device_node *np = pdev->dev.of_node; 287 + struct device *dev = &pdev->dev; 288 + struct pinctrl_state *pinctrl_hsic_idle; 273 289 274 - of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); 290 + of_id = of_match_device(ci_hdrc_imx_dt_ids, dev); 275 291 if (!of_id) 276 292 return -ENODEV; 277 293 ··· 312 268 return -ENOMEM; 313 269 314 270 platform_set_drvdata(pdev, data); 315 - data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); 271 + data->usbmisc_data = usbmisc_get_init_data(dev); 316 272 if (IS_ERR(data->usbmisc_data)) 317 273 return PTR_ERR(data->usbmisc_data); 318 274 319 - ret = imx_get_clks(&pdev->dev); 320 - if (ret) 321 - return ret; 275 + if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) { 276 + pdata.flags |= CI_HDRC_IMX_IS_HSIC; 277 + data->usbmisc_data->hsic = 1; 278 + data->pinctrl = devm_pinctrl_get(dev); 279 + if (IS_ERR(data->pinctrl)) { 280 + dev_err(dev, "pinctrl get failed, err=%ld\n", 281 + PTR_ERR(data->pinctrl)); 282 + return PTR_ERR(data->pinctrl); 283 + } 322 284 323 - ret = imx_prepare_enable_clks(&pdev->dev); 324 - if (ret) 325 - return ret; 285 + pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); 286 + if (IS_ERR(pinctrl_hsic_idle)) { 287 + dev_err(dev, 288 + "pinctrl_hsic_idle lookup failed, err=%ld\n", 289 + PTR_ERR(pinctrl_hsic_idle)); 290 + return PTR_ERR(pinctrl_hsic_idle); 291 + } 326 292 327 - data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); 293 + ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); 294 + if (ret) { 295 + dev_err(dev, "hsic_idle select failed, err=%d\n", ret); 296 + return ret; 297 + } 298 + 299 + data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, 300 + "active"); 301 + if (IS_ERR(data->pinctrl_hsic_active)) { 302 + dev_err(dev, 303 + "pinctrl_hsic_active lookup failed, err=%ld\n", 304 + PTR_ERR(data->pinctrl_hsic_active)); 305 + return PTR_ERR(data->pinctrl_hsic_active); 306 + } 307 + 308 + data->hsic_pad_regulator = devm_regulator_get(dev, "hsic"); 309 + if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) { 310 + return -EPROBE_DEFER; 311 + } else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { 312 + /* no pad regualator is needed */ 313 + data->hsic_pad_regulator = NULL; 314 + } else if (IS_ERR(data->hsic_pad_regulator)) { 315 + dev_err(dev, "Get HSIC pad regulator error: %ld\n", 316 + PTR_ERR(data->hsic_pad_regulator)); 317 + return PTR_ERR(data->hsic_pad_regulator); 318 + } 319 + 320 + if (data->hsic_pad_regulator) { 321 + ret = regulator_enable(data->hsic_pad_regulator); 322 + if (ret) { 323 + dev_err(dev, 324 + "Failed to enable HSIC pad regulator\n"); 325 + return ret; 326 + } 327 + } 328 + } 329 + ret = imx_get_clks(dev); 330 + if (ret) 331 + goto disable_hsic_regulator; 332 + 333 + ret = imx_prepare_enable_clks(dev); 334 + if (ret) 335 + goto disable_hsic_regulator; 336 + 337 + data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); 328 338 if (IS_ERR(data->phy)) { 329 339 ret = PTR_ERR(data->phy); 330 340 /* Return -EINVAL if no usbphy is available */ ··· 403 305 404 306 ret = imx_usbmisc_init(data->usbmisc_data); 405 307 if (ret) { 406 - dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); 308 + dev_err(dev, "usbmisc init failed, ret=%d\n", ret); 407 309 goto err_clk; 408 310 } 409 311 410 - data->ci_pdev = ci_hdrc_add_device(&pdev->dev, 312 + data->ci_pdev = ci_hdrc_add_device(dev, 411 313 pdev->resource, pdev->num_resources, 412 314 &pdata); 413 315 if (IS_ERR(data->ci_pdev)) { 414 316 ret = PTR_ERR(data->ci_pdev); 415 317 if (ret != -EPROBE_DEFER) 416 - dev_err(&pdev->dev, 417 - "ci_hdrc_add_device failed, err=%d\n", ret); 318 + dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", 319 + ret); 418 320 goto err_clk; 419 321 } 420 322 421 323 ret = imx_usbmisc_init_post(data->usbmisc_data); 422 324 if (ret) { 423 - dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); 325 + dev_err(dev, "usbmisc post failed, ret=%d\n", ret); 424 326 goto disable_device; 425 327 } 426 328 427 329 if (data->supports_runtime_pm) { 428 - pm_runtime_set_active(&pdev->dev); 429 - pm_runtime_enable(&pdev->dev); 330 + pm_runtime_set_active(dev); 331 + pm_runtime_enable(dev); 430 332 } 431 333 432 - device_set_wakeup_capable(&pdev->dev, true); 334 + device_set_wakeup_capable(dev, true); 433 335 434 336 return 0; 435 337 436 338 disable_device: 437 339 ci_hdrc_remove_device(data->ci_pdev); 438 340 err_clk: 439 - imx_disable_unprepare_clks(&pdev->dev); 341 + imx_disable_unprepare_clks(dev); 342 + disable_hsic_regulator: 343 + if (data->hsic_pad_regulator) 344 + ret = regulator_disable(data->hsic_pad_regulator); 440 345 return ret; 441 346 } 442 347 ··· 456 355 if (data->override_phy_control) 457 356 usb_phy_shutdown(data->phy); 458 357 imx_disable_unprepare_clks(&pdev->dev); 358 + if (data->hsic_pad_regulator) 359 + regulator_disable(data->hsic_pad_regulator); 459 360 460 361 return 0; 461 362 } ··· 470 367 static int __maybe_unused imx_controller_suspend(struct device *dev) 471 368 { 472 369 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 370 + int ret = 0; 473 371 474 372 dev_dbg(dev, "at %s\n", __func__); 373 + 374 + ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false); 375 + if (ret) { 376 + dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 377 + return ret; 378 + } 475 379 476 380 imx_disable_unprepare_clks(dev); 477 381 data->in_lpm = true; ··· 510 400 goto clk_disable; 511 401 } 512 402 403 + ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true); 404 + if (ret) { 405 + dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); 406 + goto hsic_set_clk_fail; 407 + } 408 + 513 409 return 0; 514 410 411 + hsic_set_clk_fail: 412 + imx_usbmisc_set_wakeup(data->usbmisc_data, true); 515 413 clk_disable: 516 414 imx_disable_unprepare_clks(dev); 517 415 return ret;
+13 -4
drivers/usb/chipidea/ci_hdrc_imx.h
··· 11 11 int index; 12 12 13 13 unsigned int disable_oc:1; /* over current detect disabled */ 14 - unsigned int oc_polarity:1; /* over current polarity if oc enabled */ 14 + 15 + /* true if over-current polarity is active low */ 16 + unsigned int oc_pol_active_low:1; 17 + 18 + /* true if dt specifies polarity */ 19 + unsigned int oc_pol_configured:1; 20 + 15 21 unsigned int evdo:1; /* set external vbus divider option */ 16 22 unsigned int ulpi:1; /* connected to an ULPI phy */ 23 + unsigned int hsic:1; /* HSIC controlller */ 17 24 }; 18 25 19 - int imx_usbmisc_init(struct imx_usbmisc_data *); 20 - int imx_usbmisc_init_post(struct imx_usbmisc_data *); 21 - int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool); 26 + int imx_usbmisc_init(struct imx_usbmisc_data *data); 27 + int imx_usbmisc_init_post(struct imx_usbmisc_data *data); 28 + int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled); 29 + int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data); 30 + int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on); 22 31 23 32 #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
+92
drivers/usb/chipidea/host.c
··· 170 170 otg->host = &hcd->self; 171 171 hcd->self.otg_port = 1; 172 172 } 173 + 174 + if (ci->platdata->notify_event && 175 + (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC)) 176 + ci->platdata->notify_event 177 + (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT); 173 178 } 174 179 175 180 return ret; ··· 220 215 host_stop(ci); 221 216 } 222 217 218 + /* The below code is based on tegra ehci driver */ 219 + static int ci_ehci_hub_control( 220 + struct usb_hcd *hcd, 221 + u16 typeReq, 222 + u16 wValue, 223 + u16 wIndex, 224 + char *buf, 225 + u16 wLength 226 + ) 227 + { 228 + struct ehci_hcd *ehci = hcd_to_ehci(hcd); 229 + u32 __iomem *status_reg; 230 + u32 temp; 231 + unsigned long flags; 232 + int retval = 0; 233 + struct device *dev = hcd->self.controller; 234 + struct ci_hdrc *ci = dev_get_drvdata(dev); 235 + 236 + status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; 237 + 238 + spin_lock_irqsave(&ehci->lock, flags); 239 + 240 + if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { 241 + temp = ehci_readl(ehci, status_reg); 242 + if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { 243 + retval = -EPIPE; 244 + goto done; 245 + } 246 + 247 + temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); 248 + temp |= PORT_WKDISC_E | PORT_WKOC_E; 249 + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 250 + 251 + /* 252 + * If a transaction is in progress, there may be a delay in 253 + * suspending the port. Poll until the port is suspended. 254 + */ 255 + if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 256 + PORT_SUSPEND, 5000)) 257 + ehci_err(ehci, "timeout waiting for SUSPEND\n"); 258 + 259 + if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) { 260 + if (ci->platdata->notify_event) 261 + ci->platdata->notify_event(ci, 262 + CI_HDRC_IMX_HSIC_SUSPEND_EVENT); 263 + 264 + temp = ehci_readl(ehci, status_reg); 265 + temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E); 266 + ehci_writel(ehci, temp, status_reg); 267 + } 268 + 269 + set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); 270 + goto done; 271 + } 272 + 273 + /* 274 + * After resume has finished, it needs do some post resume 275 + * operation for some SoCs. 276 + */ 277 + else if (typeReq == ClearPortFeature && 278 + wValue == USB_PORT_FEAT_C_SUSPEND) { 279 + /* Make sure the resume has finished, it should be finished */ 280 + if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000)) 281 + ehci_err(ehci, "timeout waiting for resume\n"); 282 + } 283 + 284 + spin_unlock_irqrestore(&ehci->lock, flags); 285 + 286 + /* Handle the hub control events here */ 287 + return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 288 + done: 289 + spin_unlock_irqrestore(&ehci->lock, flags); 290 + return retval; 291 + } 223 292 static int ci_ehci_bus_suspend(struct usb_hcd *hcd) 224 293 { 225 294 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 295 + struct device *dev = hcd->self.controller; 296 + struct ci_hdrc *ci = dev_get_drvdata(dev); 226 297 int port; 227 298 u32 tmp; 228 299 ··· 330 249 * It needs a short delay between set RS bit and PHCD. 331 250 */ 332 251 usleep_range(150, 200); 252 + /* 253 + * Need to clear WKCN and WKOC for imx HSIC, 254 + * otherwise, there will be wakeup event. 255 + */ 256 + if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) { 257 + tmp = ehci_readl(ehci, reg); 258 + tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E); 259 + ehci_writel(ehci, tmp, reg); 260 + } 261 + 333 262 break; 334 263 } 335 264 } ··· 372 281 ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides); 373 282 orig_bus_suspend = ci_ehci_hc_driver.bus_suspend; 374 283 ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend; 284 + ci_ehci_hc_driver.hub_control = ci_ehci_hub_control; 375 285 }
+176 -7
drivers/usb/chipidea/usbmisc_imx.c
··· 64 64 #define MX6_BM_OVER_CUR_DIS BIT(7) 65 65 #define MX6_BM_OVER_CUR_POLARITY BIT(8) 66 66 #define MX6_BM_WAKEUP_ENABLE BIT(10) 67 + #define MX6_BM_UTMI_ON_CLOCK BIT(13) 67 68 #define MX6_BM_ID_WAKEUP BIT(16) 68 69 #define MX6_BM_VBUS_WAKEUP BIT(17) 69 70 #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29) 70 71 #define MX6_BM_WAKEUP_INTR BIT(31) 72 + 73 + #define MX6_USB_HSIC_CTRL_OFFSET 0x10 74 + /* Send resume signal without 480Mhz PHY clock */ 75 + #define MX6SX_BM_HSIC_AUTO_RESUME BIT(23) 76 + /* set before portsc.suspendM = 1 */ 77 + #define MX6_BM_HSIC_DEV_CONN BIT(21) 78 + /* HSIC enable */ 79 + #define MX6_BM_HSIC_EN BIT(12) 80 + /* Force HSIC module 480M clock on, even when in Host is in suspend mode */ 81 + #define MX6_BM_HSIC_CLK_ON BIT(11) 82 + 71 83 #define MX6_USB_OTG1_PHY_CTRL 0x18 72 84 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */ 73 85 #define MX6_USB_OTG2_PHY_CTRL 0x1c ··· 106 94 int (*post)(struct imx_usbmisc_data *data); 107 95 /* It's called when we need to enable/disable usb wakeup */ 108 96 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); 97 + /* It's called before setting portsc.suspendM */ 98 + int (*hsic_set_connect)(struct imx_usbmisc_data *data); 99 + /* It's called during suspend/resume */ 100 + int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); 109 101 }; 110 102 111 103 struct imx_usbmisc { ··· 136 120 val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT); 137 121 val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; 138 122 val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT); 123 + 124 + /* 125 + * If the polarity is not configured assume active high for 126 + * historical reasons. 127 + */ 128 + if (data->oc_pol_configured && data->oc_pol_active_low) 129 + val &= ~MX25_OTG_OCPOL_BIT; 130 + 139 131 writel(val, usbmisc->base); 140 132 break; 141 133 case 1: ··· 152 128 val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; 153 129 val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | 154 130 MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT); 131 + 132 + /* 133 + * If the polarity is not configured assume active high for 134 + * historical reasons. 135 + */ 136 + if (data->oc_pol_configured && data->oc_pol_active_low) 137 + val &= ~MX25_H1_OCPOL_BIT; 155 138 156 139 writel(val, usbmisc->base); 157 140 ··· 371 340 reg = readl(usbmisc->base + data->index * 4); 372 341 if (data->disable_oc) { 373 342 reg |= MX6_BM_OVER_CUR_DIS; 374 - } else if (data->oc_polarity == 1) { 375 - /* High active */ 376 - reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); 377 343 } else { 378 - reg &= ~(MX6_BM_OVER_CUR_DIS); 344 + reg &= ~MX6_BM_OVER_CUR_DIS; 345 + 346 + /* 347 + * If the polarity is not configured keep it as setup by the 348 + * bootloader. 349 + */ 350 + if (data->oc_pol_configured && data->oc_pol_active_low) 351 + reg |= MX6_BM_OVER_CUR_POLARITY; 352 + else if (data->oc_pol_configured) 353 + reg &= ~MX6_BM_OVER_CUR_POLARITY; 379 354 } 380 355 writel(reg, usbmisc->base + data->index * 4); 381 356 ··· 390 353 writel(reg | MX6_BM_NON_BURST_SETTING, 391 354 usbmisc->base + data->index * 4); 392 355 356 + /* For HSIC controller */ 357 + if (data->hsic) { 358 + reg = readl(usbmisc->base + data->index * 4); 359 + writel(reg | MX6_BM_UTMI_ON_CLOCK, 360 + usbmisc->base + data->index * 4); 361 + reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET 362 + + (data->index - 2) * 4); 363 + reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 364 + writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET 365 + + (data->index - 2) * 4); 366 + } 367 + 393 368 spin_unlock_irqrestore(&usbmisc->lock, flags); 394 369 395 370 usbmisc_imx6q_set_wakeup(data, false); 396 371 397 372 return 0; 398 373 } 374 + 375 + static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data) 376 + { 377 + int offset, ret = 0; 378 + 379 + if (data->index == 2 || data->index == 3) { 380 + offset = (data->index - 2) * 4; 381 + } else if (data->index == 0) { 382 + /* 383 + * For SoCs like i.MX7D and later, each USB controller has 384 + * its own non-core register region. For SoCs before i.MX7D, 385 + * the first two USB controllers are non-HSIC controllers. 386 + */ 387 + offset = 0; 388 + } else { 389 + dev_err(data->dev, "index is error for usbmisc\n"); 390 + ret = -EINVAL; 391 + } 392 + 393 + return ret ? ret : offset; 394 + } 395 + 396 + static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data) 397 + { 398 + unsigned long flags; 399 + u32 val; 400 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 401 + int offset; 402 + 403 + spin_lock_irqsave(&usbmisc->lock, flags); 404 + offset = usbmisc_imx6_hsic_get_reg_offset(data); 405 + if (offset < 0) { 406 + spin_unlock_irqrestore(&usbmisc->lock, flags); 407 + return offset; 408 + } 409 + 410 + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 411 + if (!(val & MX6_BM_HSIC_DEV_CONN)) 412 + writel(val | MX6_BM_HSIC_DEV_CONN, 413 + usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 414 + 415 + spin_unlock_irqrestore(&usbmisc->lock, flags); 416 + 417 + return 0; 418 + } 419 + 420 + static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on) 421 + { 422 + unsigned long flags; 423 + u32 val; 424 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 425 + int offset; 426 + 427 + spin_lock_irqsave(&usbmisc->lock, flags); 428 + offset = usbmisc_imx6_hsic_get_reg_offset(data); 429 + if (offset < 0) { 430 + spin_unlock_irqrestore(&usbmisc->lock, flags); 431 + return offset; 432 + } 433 + 434 + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 435 + val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 436 + if (on) 437 + val |= MX6_BM_HSIC_CLK_ON; 438 + else 439 + val &= ~MX6_BM_HSIC_CLK_ON; 440 + 441 + writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); 442 + spin_unlock_irqrestore(&usbmisc->lock, flags); 443 + 444 + return 0; 445 + } 446 + 399 447 400 448 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) 401 449 { ··· 505 383 writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN, 506 384 usbmisc->base + data->index * 4); 507 385 spin_unlock_irqrestore(&usbmisc->lock, flags); 386 + } 387 + 388 + /* For HSIC controller */ 389 + if (data->hsic) { 390 + val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 391 + val |= MX6SX_BM_HSIC_AUTO_RESUME; 392 + writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 508 393 } 509 394 510 395 return 0; ··· 573 444 reg = readl(usbmisc->base); 574 445 if (data->disable_oc) { 575 446 reg |= MX6_BM_OVER_CUR_DIS; 576 - } else if (data->oc_polarity == 1) { 577 - /* High active */ 578 - reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); 447 + } else { 448 + reg &= ~MX6_BM_OVER_CUR_DIS; 449 + 450 + /* 451 + * If the polarity is not configured keep it as setup by the 452 + * bootloader. 453 + */ 454 + if (data->oc_pol_configured && data->oc_pol_active_low) 455 + reg |= MX6_BM_OVER_CUR_POLARITY; 456 + else if (data->oc_pol_configured) 457 + reg &= ~MX6_BM_OVER_CUR_POLARITY; 579 458 } 580 459 writel(reg, usbmisc->base); 581 460 ··· 591 454 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 592 455 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, 593 456 usbmisc->base + MX7D_USBNC_USB_CTRL2); 457 + 594 458 spin_unlock_irqrestore(&usbmisc->lock, flags); 595 459 596 460 usbmisc_imx7d_set_wakeup(data, false); ··· 619 481 static const struct usbmisc_ops imx6q_usbmisc_ops = { 620 482 .set_wakeup = usbmisc_imx6q_set_wakeup, 621 483 .init = usbmisc_imx6q_init, 484 + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 485 + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 622 486 }; 623 487 624 488 static const struct usbmisc_ops vf610_usbmisc_ops = { ··· 630 490 static const struct usbmisc_ops imx6sx_usbmisc_ops = { 631 491 .set_wakeup = usbmisc_imx6q_set_wakeup, 632 492 .init = usbmisc_imx6sx_init, 493 + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 494 + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 633 495 }; 634 496 635 497 static const struct usbmisc_ops imx7d_usbmisc_ops = { ··· 688 546 } 689 547 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); 690 548 549 + int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data) 550 + { 551 + struct imx_usbmisc *usbmisc; 552 + 553 + if (!data) 554 + return 0; 555 + 556 + usbmisc = dev_get_drvdata(data->dev); 557 + if (!usbmisc->ops->hsic_set_connect || !data->hsic) 558 + return 0; 559 + return usbmisc->ops->hsic_set_connect(data); 560 + } 561 + EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect); 562 + 563 + int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on) 564 + { 565 + struct imx_usbmisc *usbmisc; 566 + 567 + if (!data) 568 + return 0; 569 + 570 + usbmisc = dev_get_drvdata(data->dev); 571 + if (!usbmisc->ops->hsic_set_clk || !data->hsic) 572 + return 0; 573 + return usbmisc->ops->hsic_set_clk(data, on); 574 + } 575 + EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); 691 576 static const struct of_device_id usbmisc_imx_dt_ids[] = { 692 577 { 693 578 .compatible = "fsl,imx25-usbmisc",
+3
include/linux/usb/chipidea.h
··· 60 60 #define CI_HDRC_OVERRIDE_RX_BURST BIT(11) 61 61 #define CI_HDRC_OVERRIDE_PHY_CONTROL BIT(12) /* Glue layer manages phy */ 62 62 #define CI_HDRC_REQUIRES_ALIGNED_DMA BIT(13) 63 + #define CI_HDRC_IMX_IS_HSIC BIT(14) 63 64 enum usb_dr_mode dr_mode; 64 65 #define CI_HDRC_CONTROLLER_RESET_EVENT 0 65 66 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 67 + #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 68 + #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 66 69 int (*notify_event) (struct ci_hdrc *ci, unsigned event); 67 70 struct regulator *reg_vbus; 68 71 struct usb_otg_caps ci_otg_caps;