pwm: remove pwm-bfin driver
[linux-2.6-microblaze.git] / drivers / usb / host / ehci-tilegx.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2012 Tilera Corporation. All Rights Reserved.
4  */
5
6 /*
7  * Tilera TILE-Gx USB EHCI host controller driver.
8  */
9
10 #include <linux/irq.h>
11 #include <linux/platform_device.h>
12 #include <linux/usb/tilegx.h>
13 #include <linux/usb.h>
14
15 #include <asm/homecache.h>
16
17 #include <gxio/iorpc_usb_host.h>
18 #include <gxio/usb_host.h>
19
20 static void tilegx_start_ehc(void)
21 {
22 }
23
24 static void tilegx_stop_ehc(void)
25 {
26 }
27
28 static int tilegx_ehci_setup(struct usb_hcd *hcd)
29 {
30         int ret = ehci_init(hcd);
31
32         /*
33          * Some drivers do:
34          *
35          *   struct ehci_hcd *ehci = hcd_to_ehci(hcd);
36          *   ehci->need_io_watchdog = 0;
37          *
38          * here, but since this is a new driver we're going to leave the
39          * watchdog enabled.  Later we may try to turn it off and see
40          * whether we run into any problems.
41          */
42
43         return ret;
44 }
45
46 static const struct hc_driver ehci_tilegx_hc_driver = {
47         .description            = hcd_name,
48         .product_desc           = "Tile-Gx EHCI",
49         .hcd_priv_size          = sizeof(struct ehci_hcd),
50
51         /*
52          * Generic hardware linkage.
53          */
54         .irq                    = ehci_irq,
55         .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
56
57         /*
58          * Basic lifecycle operations.
59          */
60         .reset                  = tilegx_ehci_setup,
61         .start                  = ehci_run,
62         .stop                   = ehci_stop,
63         .shutdown               = ehci_shutdown,
64
65         /*
66          * Managing I/O requests and associated device resources.
67          */
68         .urb_enqueue            = ehci_urb_enqueue,
69         .urb_dequeue            = ehci_urb_dequeue,
70         .endpoint_disable       = ehci_endpoint_disable,
71         .endpoint_reset         = ehci_endpoint_reset,
72
73         /*
74          * Scheduling support.
75          */
76         .get_frame_number       = ehci_get_frame,
77
78         /*
79          * Root hub support.
80          */
81         .hub_status_data        = ehci_hub_status_data,
82         .hub_control            = ehci_hub_control,
83         .bus_suspend            = ehci_bus_suspend,
84         .bus_resume             = ehci_bus_resume,
85         .relinquish_port        = ehci_relinquish_port,
86         .port_handed_over       = ehci_port_handed_over,
87
88         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
89 };
90
91 static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev)
92 {
93         struct usb_hcd *hcd;
94         struct ehci_hcd *ehci;
95         struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
96         pte_t pte = { 0 };
97         int my_cpu = smp_processor_id();
98         int ret;
99
100         if (usb_disabled())
101                 return -ENODEV;
102
103         /*
104          * Try to initialize our GXIO context; if we can't, the device
105          * doesn't exist.
106          */
107         if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 1) != 0)
108                 return -ENXIO;
109
110         hcd = usb_create_hcd(&ehci_tilegx_hc_driver, &pdev->dev,
111                              dev_name(&pdev->dev));
112         if (!hcd) {
113           ret = -ENOMEM;
114           goto err_hcd;
115         }
116
117         /*
118          * We don't use rsrc_start to map in our registers, but seems like
119          * we ought to set it to something, so we use the register VA.
120          */
121         hcd->rsrc_start =
122                 (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx);
123         hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx);
124         hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx);
125
126         tilegx_start_ehc();
127
128         ehci = hcd_to_ehci(hcd);
129         ehci->caps = hcd->regs;
130         ehci->regs =
131                 hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
132         /* cache this readonly data; minimize chip reads */
133         ehci->hcs_params = readl(&ehci->caps->hcs_params);
134
135         /* Create our IRQs and register them. */
136         pdata->irq = irq_alloc_hwirq(-1);
137         if (!pdata->irq) {
138                 ret = -ENXIO;
139                 goto err_no_irq;
140         }
141
142         tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU);
143
144         /* Configure interrupts. */
145         ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx,
146                                           cpu_x(my_cpu), cpu_y(my_cpu),
147                                           KERNEL_PL, pdata->irq);
148         if (ret) {
149                 ret = -ENXIO;
150                 goto err_have_irq;
151         }
152
153         /* Register all of our memory. */
154         pte = pte_set_home(pte, PAGE_HOME_HASH);
155         ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0);
156         if (ret) {
157                 ret = -ENXIO;
158                 goto err_have_irq;
159         }
160
161         ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED);
162         if (ret == 0) {
163                 platform_set_drvdata(pdev, hcd);
164                 device_wakeup_enable(hcd->self.controller);
165                 return ret;
166         }
167
168 err_have_irq:
169         irq_free_hwirq(pdata->irq);
170 err_no_irq:
171         tilegx_stop_ehc();
172         usb_put_hcd(hcd);
173 err_hcd:
174         gxio_usb_host_destroy(&pdata->usb_ctx);
175         return ret;
176 }
177
178 static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev)
179 {
180         struct usb_hcd *hcd = platform_get_drvdata(pdev);
181         struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
182
183         usb_remove_hcd(hcd);
184         usb_put_hcd(hcd);
185         tilegx_stop_ehc();
186         gxio_usb_host_destroy(&pdata->usb_ctx);
187         irq_free_hwirq(pdata->irq);
188
189         return 0;
190 }
191
192 static void ehci_hcd_tilegx_drv_shutdown(struct platform_device *pdev)
193 {
194         usb_hcd_platform_shutdown(pdev);
195         ehci_hcd_tilegx_drv_remove(pdev);
196 }
197
198 static struct platform_driver ehci_hcd_tilegx_driver = {
199         .probe          = ehci_hcd_tilegx_drv_probe,
200         .remove         = ehci_hcd_tilegx_drv_remove,
201         .shutdown       = ehci_hcd_tilegx_drv_shutdown,
202         .driver = {
203                 .name   = "tilegx-ehci",
204         }
205 };
206
207 MODULE_ALIAS("platform:tilegx-ehci");