]> Git Repo - J-linux.git/blob - drivers/mfd/omap-usb-host.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / mfd / omap-usb-host.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
4  *
5  * Copyright (C) 2011-2013 Texas Instruments Incorporated - https://www.ti.com
6  * Author: Keshava Munegowda <[email protected]>
7  * Author: Roger Quadros <[email protected]>
8  */
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <linux/delay.h>
14 #include <linux/clk.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/platform_device.h>
17 #include <linux/platform_data/usb-omap.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/of.h>
20 #include <linux/of_platform.h>
21 #include <linux/err.h>
22
23 #include "omap-usb.h"
24
25 #define USBHS_DRIVER_NAME       "usbhs_omap"
26 #define OMAP_EHCI_DEVICE        "ehci-omap"
27 #define OMAP_OHCI_DEVICE        "ohci-omap3"
28
29 /* OMAP USBHOST Register addresses  */
30
31 /* UHH Register Set */
32 #define OMAP_UHH_REVISION                               (0x00)
33 #define OMAP_UHH_SYSCONFIG                              (0x10)
34 #define OMAP_UHH_SYSCONFIG_MIDLEMODE                    (1 << 12)
35 #define OMAP_UHH_SYSCONFIG_CACTIVITY                    (1 << 8)
36 #define OMAP_UHH_SYSCONFIG_SIDLEMODE                    (1 << 3)
37 #define OMAP_UHH_SYSCONFIG_ENAWAKEUP                    (1 << 2)
38 #define OMAP_UHH_SYSCONFIG_SOFTRESET                    (1 << 1)
39 #define OMAP_UHH_SYSCONFIG_AUTOIDLE                     (1 << 0)
40
41 #define OMAP_UHH_SYSSTATUS                              (0x14)
42 #define OMAP_UHH_HOSTCONFIG                             (0x40)
43 #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS                 (1 << 0)
44 #define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS              (1 << 0)
45 #define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS              (1 << 11)
46 #define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS              (1 << 12)
47 #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN              (1 << 2)
48 #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN              (1 << 3)
49 #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN             (1 << 4)
50 #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN              (1 << 5)
51 #define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS           (1 << 8)
52 #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS           (1 << 9)
53 #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS           (1 << 10)
54 #define OMAP4_UHH_HOSTCONFIG_APP_START_CLK              (1 << 31)
55
56 /* OMAP4-specific defines */
57 #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR              (3 << 2)
58 #define OMAP4_UHH_SYSCONFIG_NOIDLE                      (1 << 2)
59 #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR             (3 << 4)
60 #define OMAP4_UHH_SYSCONFIG_NOSTDBY                     (1 << 4)
61 #define OMAP4_UHH_SYSCONFIG_SOFTRESET                   (1 << 0)
62
63 #define OMAP4_P1_MODE_CLEAR                             (3 << 16)
64 #define OMAP4_P1_MODE_TLL                               (1 << 16)
65 #define OMAP4_P1_MODE_HSIC                              (3 << 16)
66 #define OMAP4_P2_MODE_CLEAR                             (3 << 18)
67 #define OMAP4_P2_MODE_TLL                               (1 << 18)
68 #define OMAP4_P2_MODE_HSIC                              (3 << 18)
69
70 #define OMAP_UHH_DEBUG_CSR                              (0x44)
71
72 /* Values of UHH_REVISION - Note: these are not given in the TRM */
73 #define OMAP_USBHS_REV1         0x00000010      /* OMAP3 */
74 #define OMAP_USBHS_REV2         0x50700100      /* OMAP4 */
75
76 #define is_omap_usbhs_rev1(x)   (x->usbhs_rev == OMAP_USBHS_REV1)
77 #define is_omap_usbhs_rev2(x)   (x->usbhs_rev == OMAP_USBHS_REV2)
78
79 #define is_ehci_phy_mode(x)     (x == OMAP_EHCI_PORT_MODE_PHY)
80 #define is_ehci_tll_mode(x)     (x == OMAP_EHCI_PORT_MODE_TLL)
81 #define is_ehci_hsic_mode(x)    (x == OMAP_EHCI_PORT_MODE_HSIC)
82
83
84 struct usbhs_hcd_omap {
85         int                             nports;
86         struct clk                      **utmi_clk;
87         struct clk                      **hsic60m_clk;
88         struct clk                      **hsic480m_clk;
89
90         struct clk                      *xclk60mhsp1_ck;
91         struct clk                      *xclk60mhsp2_ck;
92         struct clk                      *utmi_p1_gfclk;
93         struct clk                      *utmi_p2_gfclk;
94         struct clk                      *init_60m_fclk;
95         struct clk                      *ehci_logic_fck;
96
97         void __iomem                    *uhh_base;
98
99         struct usbhs_omap_platform_data *pdata;
100
101         u32                             usbhs_rev;
102 };
103 /*-------------------------------------------------------------------------*/
104
105 static const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
106 static u64 usbhs_dmamask = DMA_BIT_MASK(32);
107
108 /*-------------------------------------------------------------------------*/
109
110 static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
111 {
112         writel_relaxed(val, base + reg);
113 }
114
115 static inline u32 usbhs_read(void __iomem *base, u32 reg)
116 {
117         return readl_relaxed(base + reg);
118 }
119
120 /*-------------------------------------------------------------------------*/
121
122 /*
123  * Map 'enum usbhs_omap_port_mode' found in <linux/platform_data/usb-omap.h>
124  * to the device tree binding portN-mode found in
125  * 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt'
126  */
127 static const char * const port_modes[] = {
128         [OMAP_USBHS_PORT_MODE_UNUSED]   = "",
129         [OMAP_EHCI_PORT_MODE_PHY]       = "ehci-phy",
130         [OMAP_EHCI_PORT_MODE_TLL]       = "ehci-tll",
131         [OMAP_EHCI_PORT_MODE_HSIC]      = "ehci-hsic",
132         [OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0]   = "ohci-phy-6pin-datse0",
133         [OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM]     = "ohci-phy-6pin-dpdm",
134         [OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0]   = "ohci-phy-3pin-datse0",
135         [OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM]     = "ohci-phy-4pin-dpdm",
136         [OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0]   = "ohci-tll-6pin-datse0",
137         [OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM]     = "ohci-tll-6pin-dpdm",
138         [OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0]   = "ohci-tll-3pin-datse0",
139         [OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM]     = "ohci-tll-4pin-dpdm",
140         [OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0]   = "ohci-tll-2pin-datse0",
141         [OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM]     = "ohci-tll-2pin-dpdm",
142 };
143
144 static struct platform_device *omap_usbhs_alloc_child(const char *name,
145                         struct resource *res, int num_resources, void *pdata,
146                         size_t pdata_size, struct device *dev)
147 {
148         struct platform_device  *child;
149         int                     ret;
150
151         child = platform_device_alloc(name, 0);
152
153         if (!child) {
154                 dev_err(dev, "platform_device_alloc %s failed\n", name);
155                 goto err_end;
156         }
157
158         ret = platform_device_add_resources(child, res, num_resources);
159         if (ret) {
160                 dev_err(dev, "platform_device_add_resources failed\n");
161                 goto err_alloc;
162         }
163
164         ret = platform_device_add_data(child, pdata, pdata_size);
165         if (ret) {
166                 dev_err(dev, "platform_device_add_data failed\n");
167                 goto err_alloc;
168         }
169
170         child->dev.dma_mask             = &usbhs_dmamask;
171         dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32));
172         child->dev.parent               = dev;
173
174         ret = platform_device_add(child);
175         if (ret) {
176                 dev_err(dev, "platform_device_add failed\n");
177                 goto err_alloc;
178         }
179
180         return child;
181
182 err_alloc:
183         platform_device_put(child);
184
185 err_end:
186         return NULL;
187 }
188
189 static int omap_usbhs_alloc_children(struct platform_device *pdev)
190 {
191         struct device                           *dev = &pdev->dev;
192         struct usbhs_omap_platform_data         *pdata = dev_get_platdata(dev);
193         struct platform_device                  *ehci;
194         struct platform_device                  *ohci;
195         struct resource                         *res;
196         struct resource                         resources[2];
197         int                                     ret;
198
199         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
200         if (!res) {
201                 dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
202                 ret = -ENODEV;
203                 goto err_end;
204         }
205         resources[0] = *res;
206
207         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
208         if (!res) {
209                 dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
210                 ret = -ENODEV;
211                 goto err_end;
212         }
213         resources[1] = *res;
214
215         ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, pdata,
216                 sizeof(*pdata), dev);
217
218         if (!ehci) {
219                 dev_err(dev, "omap_usbhs_alloc_child failed\n");
220                 ret = -ENOMEM;
221                 goto err_end;
222         }
223
224         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
225         if (!res) {
226                 dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
227                 ret = -ENODEV;
228                 goto err_ehci;
229         }
230         resources[0] = *res;
231
232         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
233         if (!res) {
234                 dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
235                 ret = -ENODEV;
236                 goto err_ehci;
237         }
238         resources[1] = *res;
239
240         ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, pdata,
241                 sizeof(*pdata), dev);
242         if (!ohci) {
243                 dev_err(dev, "omap_usbhs_alloc_child failed\n");
244                 ret = -ENOMEM;
245                 goto err_ehci;
246         }
247
248         return 0;
249
250 err_ehci:
251         platform_device_unregister(ehci);
252
253 err_end:
254         return ret;
255 }
256
257 static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
258 {
259         switch (pmode) {
260         case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
261         case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
262         case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
263         case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
264         case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
265         case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
266         case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
267         case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
268         case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
269         case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
270                 return true;
271
272         default:
273                 return false;
274         }
275 }
276
277 static int usbhs_runtime_resume(struct device *dev)
278 {
279         struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
280         struct usbhs_omap_platform_data *pdata = omap->pdata;
281         int i, r;
282
283         dev_dbg(dev, "usbhs_runtime_resume\n");
284
285         omap_tll_enable(pdata);
286
287         if (!IS_ERR(omap->ehci_logic_fck))
288                 clk_prepare_enable(omap->ehci_logic_fck);
289
290         for (i = 0; i < omap->nports; i++) {
291                 switch (pdata->port_mode[i]) {
292                 case OMAP_EHCI_PORT_MODE_HSIC:
293                         if (!IS_ERR(omap->hsic60m_clk[i])) {
294                                 r = clk_prepare_enable(omap->hsic60m_clk[i]);
295                                 if (r) {
296                                         dev_err(dev,
297                                          "Can't enable port %d hsic60m clk:%d\n",
298                                          i, r);
299                                 }
300                         }
301
302                         if (!IS_ERR(omap->hsic480m_clk[i])) {
303                                 r = clk_prepare_enable(omap->hsic480m_clk[i]);
304                                 if (r) {
305                                         dev_err(dev,
306                                          "Can't enable port %d hsic480m clk:%d\n",
307                                          i, r);
308                                 }
309                         }
310                         fallthrough;    /* as HSIC mode needs utmi_clk */
311
312                 case OMAP_EHCI_PORT_MODE_TLL:
313                         if (!IS_ERR(omap->utmi_clk[i])) {
314                                 r = clk_prepare_enable(omap->utmi_clk[i]);
315                                 if (r) {
316                                         dev_err(dev,
317                                          "Can't enable port %d clk : %d\n",
318                                          i, r);
319                                 }
320                         }
321                         break;
322                 default:
323                         break;
324                 }
325         }
326
327         return 0;
328 }
329
330 static int usbhs_runtime_suspend(struct device *dev)
331 {
332         struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
333         struct usbhs_omap_platform_data *pdata = omap->pdata;
334         int i;
335
336         dev_dbg(dev, "usbhs_runtime_suspend\n");
337
338         for (i = 0; i < omap->nports; i++) {
339                 switch (pdata->port_mode[i]) {
340                 case OMAP_EHCI_PORT_MODE_HSIC:
341                         if (!IS_ERR(omap->hsic60m_clk[i]))
342                                 clk_disable_unprepare(omap->hsic60m_clk[i]);
343
344                         if (!IS_ERR(omap->hsic480m_clk[i]))
345                                 clk_disable_unprepare(omap->hsic480m_clk[i]);
346                         fallthrough;    /* as utmi_clks were used in HSIC mode */
347
348                 case OMAP_EHCI_PORT_MODE_TLL:
349                         if (!IS_ERR(omap->utmi_clk[i]))
350                                 clk_disable_unprepare(omap->utmi_clk[i]);
351                         break;
352                 default:
353                         break;
354                 }
355         }
356
357         if (!IS_ERR(omap->ehci_logic_fck))
358                 clk_disable_unprepare(omap->ehci_logic_fck);
359
360         omap_tll_disable(pdata);
361
362         return 0;
363 }
364
365 static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
366                                                 unsigned reg)
367 {
368         struct usbhs_omap_platform_data *pdata = omap->pdata;
369         int i;
370
371         for (i = 0; i < omap->nports; i++) {
372                 switch (pdata->port_mode[i]) {
373                 case OMAP_USBHS_PORT_MODE_UNUSED:
374                         reg &= ~(OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS << i);
375                         break;
376                 case OMAP_EHCI_PORT_MODE_PHY:
377                         if (pdata->single_ulpi_bypass)
378                                 break;
379
380                         if (i == 0)
381                                 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
382                         else
383                                 reg &= ~(OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
384                                                                 << (i-1));
385                         break;
386                 default:
387                         if (pdata->single_ulpi_bypass)
388                                 break;
389
390                         if (i == 0)
391                                 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
392                         else
393                                 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
394                                                                 << (i-1);
395                         break;
396                 }
397         }
398
399         if (pdata->single_ulpi_bypass) {
400                 /* bypass ULPI only if none of the ports use PHY mode */
401                 reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
402
403                 for (i = 0; i < omap->nports; i++) {
404                         if (is_ehci_phy_mode(pdata->port_mode[i])) {
405                                 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
406                                 break;
407                         }
408                 }
409         }
410
411         return reg;
412 }
413
414 static unsigned omap_usbhs_rev2_hostconfig(struct usbhs_hcd_omap *omap,
415                                                 unsigned reg)
416 {
417         struct usbhs_omap_platform_data *pdata = omap->pdata;
418         int i;
419
420         for (i = 0; i < omap->nports; i++) {
421                 /* Clear port mode fields for PHY mode */
422                 reg &= ~(OMAP4_P1_MODE_CLEAR << 2 * i);
423
424                 if (is_ehci_tll_mode(pdata->port_mode[i]) ||
425                                 (is_ohci_port(pdata->port_mode[i])))
426                         reg |= OMAP4_P1_MODE_TLL << 2 * i;
427                 else if (is_ehci_hsic_mode(pdata->port_mode[i]))
428                         reg |= OMAP4_P1_MODE_HSIC << 2 * i;
429         }
430
431         return reg;
432 }
433
434 static void omap_usbhs_init(struct device *dev)
435 {
436         struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
437         unsigned                        reg;
438
439         dev_dbg(dev, "starting TI HSUSB Controller\n");
440
441         pm_runtime_get_sync(dev);
442
443         reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
444         /* setup ULPI bypass and burst configurations */
445         reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
446                         | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
447                         | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
448         reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK;
449         reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
450
451         switch (omap->usbhs_rev) {
452         case OMAP_USBHS_REV1:
453                 reg = omap_usbhs_rev1_hostconfig(omap, reg);
454                 break;
455
456         case OMAP_USBHS_REV2:
457                 reg = omap_usbhs_rev2_hostconfig(omap, reg);
458                 break;
459
460         default:        /* newer revisions */
461                 reg = omap_usbhs_rev2_hostconfig(omap, reg);
462                 break;
463         }
464
465         usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
466         dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
467
468         pm_runtime_put_sync(dev);
469 }
470
471 static int usbhs_omap_get_dt_pdata(struct device *dev,
472                                         struct usbhs_omap_platform_data *pdata)
473 {
474         int ret, i;
475         struct device_node *node = dev->of_node;
476
477         ret = of_property_read_u32(node, "num-ports", &pdata->nports);
478         if (ret)
479                 pdata->nports = 0;
480
481         if (pdata->nports > OMAP3_HS_USB_PORTS) {
482                 dev_warn(dev, "Too many num_ports <%d> in device tree. Max %d\n",
483                                 pdata->nports, OMAP3_HS_USB_PORTS);
484                 return -ENODEV;
485         }
486
487         /* get port modes */
488         for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
489                 char prop[11];
490                 const char *mode;
491
492                 pdata->port_mode[i] = OMAP_USBHS_PORT_MODE_UNUSED;
493
494                 snprintf(prop, sizeof(prop), "port%d-mode", i + 1);
495                 ret = of_property_read_string(node, prop, &mode);
496                 if (ret < 0)
497                         continue;
498
499                 /* get 'enum usbhs_omap_port_mode' from port mode string */
500                 ret = match_string(port_modes, ARRAY_SIZE(port_modes), mode);
501                 if (ret < 0) {
502                         dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
503                                         i, mode);
504                         return -ENODEV;
505                 }
506
507                 dev_dbg(dev, "port%d-mode: %s -> %d\n", i, mode, ret);
508                 pdata->port_mode[i] = ret;
509         }
510
511         /* get flags */
512         pdata->single_ulpi_bypass = of_property_read_bool(node,
513                                                 "single-ulpi-bypass");
514
515         return 0;
516 }
517
518 static const struct of_device_id usbhs_child_match_table[] = {
519         { .compatible = "ti,ehci-omap", },
520         { .compatible = "ti,ohci-omap3", },
521         { }
522 };
523
524 /**
525  * usbhs_omap_probe - initialize TI-based HCDs
526  *
527  * Allocates basic resources for this USB host controller.
528  *
529  * @pdev: Pointer to this device's platform device structure
530  */
531 static int usbhs_omap_probe(struct platform_device *pdev)
532 {
533         struct device                   *dev =  &pdev->dev;
534         struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
535         struct usbhs_hcd_omap           *omap;
536         int                             ret = 0;
537         int                             i;
538         bool                            need_logic_fck;
539
540         if (dev->of_node) {
541                 /* For DT boot we populate platform data from OF node */
542                 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
543                 if (!pdata)
544                         return -ENOMEM;
545
546                 ret = usbhs_omap_get_dt_pdata(dev, pdata);
547                 if (ret)
548                         return ret;
549
550                 dev->platform_data = pdata;
551         }
552
553         if (!pdata) {
554                 dev_err(dev, "Missing platform data\n");
555                 return -ENODEV;
556         }
557
558         if (pdata->nports > OMAP3_HS_USB_PORTS) {
559                 dev_info(dev, "Too many num_ports <%d> in platform_data. Max %d\n",
560                                 pdata->nports, OMAP3_HS_USB_PORTS);
561                 return -ENODEV;
562         }
563
564         omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
565         if (!omap) {
566                 dev_err(dev, "Memory allocation failed\n");
567                 return -ENOMEM;
568         }
569
570         omap->uhh_base = devm_platform_ioremap_resource(pdev, 0);
571         if (IS_ERR(omap->uhh_base))
572                 return PTR_ERR(omap->uhh_base);
573
574         omap->pdata = pdata;
575
576         /* Initialize the TLL subsystem */
577         omap_tll_init(pdata);
578
579         pm_runtime_enable(dev);
580
581         platform_set_drvdata(pdev, omap);
582         pm_runtime_get_sync(dev);
583
584         omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
585
586         /* we need to call runtime suspend before we update omap->nports
587          * to prevent unbalanced clk_disable()
588          */
589         pm_runtime_put_sync(dev);
590
591         /*
592          * If platform data contains nports then use that
593          * else make out number of ports from USBHS revision
594          */
595         if (pdata->nports) {
596                 omap->nports = pdata->nports;
597         } else {
598                 switch (omap->usbhs_rev) {
599                 case OMAP_USBHS_REV1:
600                         omap->nports = 3;
601                         break;
602                 case OMAP_USBHS_REV2:
603                         omap->nports = 2;
604                         break;
605                 default:
606                         omap->nports = OMAP3_HS_USB_PORTS;
607                         dev_dbg(dev,
608                          "USB HOST Rev:0x%x not recognized, assuming %d ports\n",
609                          omap->usbhs_rev, omap->nports);
610                         break;
611                 }
612                 pdata->nports = omap->nports;
613         }
614
615         i = sizeof(struct clk *) * omap->nports;
616         omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL);
617         omap->hsic480m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
618         omap->hsic60m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
619
620         if (!omap->utmi_clk || !omap->hsic480m_clk || !omap->hsic60m_clk) {
621                 dev_err(dev, "Memory allocation failed\n");
622                 ret = -ENOMEM;
623                 goto err_mem;
624         }
625
626         /* Set all clocks as invalid to begin with */
627         omap->ehci_logic_fck = ERR_PTR(-ENODEV);
628         omap->init_60m_fclk = ERR_PTR(-ENODEV);
629         omap->utmi_p1_gfclk = ERR_PTR(-ENODEV);
630         omap->utmi_p2_gfclk = ERR_PTR(-ENODEV);
631         omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV);
632         omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV);
633
634         for (i = 0; i < omap->nports; i++) {
635                 omap->utmi_clk[i] = ERR_PTR(-ENODEV);
636                 omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
637                 omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
638         }
639
640         /* for OMAP3 i.e. USBHS REV1 */
641         if (omap->usbhs_rev == OMAP_USBHS_REV1) {
642                 need_logic_fck = false;
643                 for (i = 0; i < omap->nports; i++) {
644                         if (is_ehci_phy_mode(pdata->port_mode[i]) ||
645                             is_ehci_tll_mode(pdata->port_mode[i]) ||
646                             is_ehci_hsic_mode(pdata->port_mode[i]))
647
648                                 need_logic_fck |= true;
649                 }
650
651                 if (need_logic_fck) {
652                         omap->ehci_logic_fck = devm_clk_get(dev,
653                                                             "usbhost_120m_fck");
654                         if (IS_ERR(omap->ehci_logic_fck)) {
655                                 ret = PTR_ERR(omap->ehci_logic_fck);
656                                 dev_err(dev, "usbhost_120m_fck failed:%d\n",
657                                         ret);
658                                 goto err_mem;
659                         }
660                 }
661                 goto initialize;
662         }
663
664         /* for OMAP4+ i.e. USBHS REV2+ */
665         omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk");
666         if (IS_ERR(omap->utmi_p1_gfclk)) {
667                 ret = PTR_ERR(omap->utmi_p1_gfclk);
668                 dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
669                 goto err_mem;
670         }
671
672         omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk");
673         if (IS_ERR(omap->utmi_p2_gfclk)) {
674                 ret = PTR_ERR(omap->utmi_p2_gfclk);
675                 dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
676                 goto err_mem;
677         }
678
679         omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1");
680         if (IS_ERR(omap->xclk60mhsp1_ck)) {
681                 ret = PTR_ERR(omap->xclk60mhsp1_ck);
682                 dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret);
683                 goto err_mem;
684         }
685
686         omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2");
687         if (IS_ERR(omap->xclk60mhsp2_ck)) {
688                 ret = PTR_ERR(omap->xclk60mhsp2_ck);
689                 dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret);
690                 goto err_mem;
691         }
692
693         omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int");
694         if (IS_ERR(omap->init_60m_fclk)) {
695                 ret = PTR_ERR(omap->init_60m_fclk);
696                 dev_err(dev, "refclk_60m_int failed error:%d\n", ret);
697                 goto err_mem;
698         }
699
700         for (i = 0; i < omap->nports; i++) {
701                 char clkname[40];
702
703                 /* clock names are indexed from 1*/
704                 snprintf(clkname, sizeof(clkname),
705                                 "usb_host_hs_utmi_p%d_clk", i + 1);
706
707                 /* If a clock is not found we won't bail out as not all
708                  * platforms have all clocks and we can function without
709                  * them
710                  */
711                 omap->utmi_clk[i] = devm_clk_get(dev, clkname);
712                 if (IS_ERR(omap->utmi_clk[i])) {
713                         ret = PTR_ERR(omap->utmi_clk[i]);
714                         dev_err(dev, "Failed to get clock : %s : %d\n",
715                                 clkname, ret);
716                         goto err_mem;
717                 }
718
719                 snprintf(clkname, sizeof(clkname),
720                                 "usb_host_hs_hsic480m_p%d_clk", i + 1);
721                 omap->hsic480m_clk[i] = devm_clk_get(dev, clkname);
722                 if (IS_ERR(omap->hsic480m_clk[i])) {
723                         ret = PTR_ERR(omap->hsic480m_clk[i]);
724                         dev_err(dev, "Failed to get clock : %s : %d\n",
725                                 clkname, ret);
726                         goto err_mem;
727                 }
728
729                 snprintf(clkname, sizeof(clkname),
730                                 "usb_host_hs_hsic60m_p%d_clk", i + 1);
731                 omap->hsic60m_clk[i] = devm_clk_get(dev, clkname);
732                 if (IS_ERR(omap->hsic60m_clk[i])) {
733                         ret = PTR_ERR(omap->hsic60m_clk[i]);
734                         dev_err(dev, "Failed to get clock : %s : %d\n",
735                                 clkname, ret);
736                         goto err_mem;
737                 }
738         }
739
740         if (is_ehci_phy_mode(pdata->port_mode[0])) {
741                 ret = clk_set_parent(omap->utmi_p1_gfclk,
742                                         omap->xclk60mhsp1_ck);
743                 if (ret != 0) {
744                         dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n",
745                                 ret);
746                         goto err_mem;
747                 }
748         } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
749                 ret = clk_set_parent(omap->utmi_p1_gfclk,
750                                         omap->init_60m_fclk);
751                 if (ret != 0) {
752                         dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n",
753                                 ret);
754                         goto err_mem;
755                 }
756         }
757
758         if (is_ehci_phy_mode(pdata->port_mode[1])) {
759                 ret = clk_set_parent(omap->utmi_p2_gfclk,
760                                         omap->xclk60mhsp2_ck);
761                 if (ret != 0) {
762                         dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n",
763                                 ret);
764                         goto err_mem;
765                 }
766         } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
767                 ret = clk_set_parent(omap->utmi_p2_gfclk,
768                                                 omap->init_60m_fclk);
769                 if (ret != 0) {
770                         dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n",
771                                 ret);
772                         goto err_mem;
773                 }
774         }
775
776 initialize:
777         omap_usbhs_init(dev);
778
779         if (dev->of_node) {
780                 ret = of_platform_populate(dev->of_node,
781                                 usbhs_child_match_table, NULL, dev);
782
783                 if (ret) {
784                         dev_err(dev, "Failed to create DT children: %d\n", ret);
785                         goto err_mem;
786                 }
787
788         } else {
789                 ret = omap_usbhs_alloc_children(pdev);
790                 if (ret) {
791                         dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
792                                                 ret);
793                         goto err_mem;
794                 }
795         }
796
797         return 0;
798
799 err_mem:
800         pm_runtime_disable(dev);
801
802         return ret;
803 }
804
805 static int usbhs_omap_remove_child(struct device *dev, void *data)
806 {
807         dev_info(dev, "unregistering\n");
808         platform_device_unregister(to_platform_device(dev));
809         return 0;
810 }
811
812 /**
813  * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
814  * @pdev: USB Host Controller being removed
815  *
816  * Reverses the effect of usbhs_omap_probe().
817  */
818 static void usbhs_omap_remove(struct platform_device *pdev)
819 {
820         pm_runtime_disable(&pdev->dev);
821
822         /* remove children */
823         device_for_each_child(&pdev->dev, NULL, usbhs_omap_remove_child);
824 }
825
826 static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
827         .runtime_suspend        = usbhs_runtime_suspend,
828         .runtime_resume         = usbhs_runtime_resume,
829 };
830
831 static const struct of_device_id usbhs_omap_dt_ids[] = {
832         { .compatible = "ti,usbhs-host" },
833         { }
834 };
835
836 MODULE_DEVICE_TABLE(of, usbhs_omap_dt_ids);
837
838
839 static struct platform_driver usbhs_omap_driver = {
840         .driver = {
841                 .name           = usbhs_driver_name,
842                 .pm             = &usbhsomap_dev_pm_ops,
843                 .of_match_table = usbhs_omap_dt_ids,
844         },
845         .probe          = usbhs_omap_probe,
846         .remove         = usbhs_omap_remove,
847 };
848
849 MODULE_AUTHOR("Keshava Munegowda <[email protected]>");
850 MODULE_AUTHOR("Roger Quadros <[email protected]>");
851 MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
852 MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
853
854 static int omap_usbhs_drvinit(void)
855 {
856         return platform_driver_register(&usbhs_omap_driver);
857 }
858
859 /*
860  * init before ehci and ohci drivers;
861  * The usbhs core driver should be initialized much before
862  * the omap ehci and ohci probe functions are called.
863  * This usbhs core driver should be initialized after
864  * usb tll driver
865  */
866 fs_initcall_sync(omap_usbhs_drvinit);
867
868 static void omap_usbhs_drvexit(void)
869 {
870         platform_driver_unregister(&usbhs_omap_driver);
871 }
872 module_exit(omap_usbhs_drvexit);
This page took 0.078618 seconds and 4 git commands to generate.