]>
Commit | Line | Data |
---|---|---|
5b9974b1 MK |
1 | /* |
2 | * platform.c - DesignWare HS OTG Controller platform driver | |
3 | * | |
4 | * Copyright (C) Matthijs Kooijman <matthijs@stdin.nl> | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions, and the following disclaimer, | |
11 | * without modification. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. The names of the above-listed copyright holders may not be used | |
16 | * to endorse or promote products derived from this software without | |
17 | * specific prior written permission. | |
18 | * | |
19 | * ALTERNATIVELY, this software may be distributed under the terms of the | |
20 | * GNU General Public License ("GPL") as published by the Free Software | |
21 | * Foundation; either version 2 of the License, or (at your option) any | |
22 | * later version. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
25 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
26 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
27 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
28 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
31 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
35 | */ | |
36 | ||
37 | #include <linux/kernel.h> | |
38 | #include <linux/module.h> | |
39 | #include <linux/slab.h> | |
40 | #include <linux/device.h> | |
41 | #include <linux/dma-mapping.h> | |
831eae69 | 42 | #include <linux/of_device.h> |
5b9974b1 MK |
43 | #include <linux/platform_device.h> |
44 | ||
c0155b9d KY |
45 | #include <linux/usb/of.h> |
46 | ||
5b9974b1 MK |
47 | #include "core.h" |
48 | #include "hcd.h" | |
49 | ||
50 | static const char dwc2_driver_name[] = "dwc2"; | |
51 | ||
831eae69 SW |
52 | static const struct dwc2_core_params params_bcm2835 = { |
53 | .otg_cap = 0, /* HNP/SRP capable */ | |
54 | .otg_ver = 0, /* 1.3 */ | |
55 | .dma_enable = 1, | |
56 | .dma_desc_enable = 0, | |
57 | .speed = 0, /* High Speed */ | |
58 | .enable_dynamic_fifo = 1, | |
59 | .en_multiple_tx_fifo = 1, | |
60 | .host_rx_fifo_size = 774, /* 774 DWORDs */ | |
61 | .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */ | |
62 | .host_perio_tx_fifo_size = 512, /* 512 DWORDs */ | |
63 | .max_transfer_size = 65535, | |
64 | .max_packet_count = 511, | |
65 | .host_channels = 8, | |
66 | .phy_type = 1, /* UTMI */ | |
67 | .phy_utmi_width = 8, /* 8 bits */ | |
68 | .phy_ulpi_ddr = 0, /* Single */ | |
69 | .phy_ulpi_ext_vbus = 0, | |
70 | .i2c_enable = 0, | |
71 | .ulpi_fs_ls = 0, | |
72 | .host_support_fs_ls_low_power = 0, | |
73 | .host_ls_low_power_phy_clk = 0, /* 48 MHz */ | |
74 | .ts_dline = 0, | |
75 | .reload_ctl = 0, | |
76 | .ahbcfg = 0x10, | |
58b179dc | 77 | .uframe_sched = 0, |
831eae69 SW |
78 | }; |
79 | ||
95083146 KY |
80 | static const struct dwc2_core_params params_rk3066 = { |
81 | .otg_cap = 2, /* non-HNP/non-SRP */ | |
82 | .otg_ver = -1, | |
83 | .dma_enable = -1, | |
84 | .dma_desc_enable = 0, | |
85 | .speed = -1, | |
86 | .enable_dynamic_fifo = 1, | |
87 | .en_multiple_tx_fifo = -1, | |
88 | .host_rx_fifo_size = 520, /* 520 DWORDs */ | |
89 | .host_nperio_tx_fifo_size = 128, /* 128 DWORDs */ | |
90 | .host_perio_tx_fifo_size = 256, /* 256 DWORDs */ | |
91 | .max_transfer_size = 65535, | |
92 | .max_packet_count = -1, | |
93 | .host_channels = -1, | |
94 | .phy_type = -1, | |
95 | .phy_utmi_width = -1, | |
96 | .phy_ulpi_ddr = -1, | |
97 | .phy_ulpi_ext_vbus = -1, | |
98 | .i2c_enable = -1, | |
99 | .ulpi_fs_ls = -1, | |
100 | .host_support_fs_ls_low_power = -1, | |
101 | .host_ls_low_power_phy_clk = -1, | |
102 | .ts_dline = -1, | |
103 | .reload_ctl = -1, | |
104 | .ahbcfg = 0x7, /* INCR16 */ | |
105 | .uframe_sched = -1, | |
106 | }; | |
107 | ||
5b9974b1 MK |
108 | /** |
109 | * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the | |
110 | * DWC_otg driver | |
111 | * | |
112 | * @dev: Platform device | |
113 | * | |
114 | * This routine is called, for example, when the rmmod command is executed. The | |
115 | * device may or may not be electrically present. If it is present, the driver | |
116 | * stops device processing. Any resources used on behalf of this device are | |
117 | * freed. | |
118 | */ | |
119 | static int dwc2_driver_remove(struct platform_device *dev) | |
120 | { | |
121 | struct dwc2_hsotg *hsotg = platform_get_drvdata(dev); | |
122 | ||
123 | dwc2_hcd_remove(hsotg); | |
117777b2 | 124 | s3c_hsotg_remove(hsotg); |
5b9974b1 MK |
125 | |
126 | return 0; | |
127 | } | |
128 | ||
831eae69 SW |
129 | static const struct of_device_id dwc2_of_match_table[] = { |
130 | { .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 }, | |
95083146 | 131 | { .compatible = "rockchip,rk3066-usb", .data = ¶ms_rk3066 }, |
831eae69 | 132 | { .compatible = "snps,dwc2", .data = NULL }, |
117777b2 | 133 | { .compatible = "samsung,s3c6400-hsotg", .data = NULL}, |
831eae69 SW |
134 | {}, |
135 | }; | |
136 | MODULE_DEVICE_TABLE(of, dwc2_of_match_table); | |
137 | ||
5b9974b1 MK |
138 | /** |
139 | * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg | |
140 | * driver | |
141 | * | |
142 | * @dev: Platform device | |
143 | * | |
144 | * This routine creates the driver components required to control the device | |
145 | * (core, HCD, and PCD) and initializes the device. The driver components are | |
146 | * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved | |
147 | * in the device private data. This allows the driver to access the dwc2_hsotg | |
148 | * structure on subsequent calls to driver methods for this device. | |
149 | */ | |
150 | static int dwc2_driver_probe(struct platform_device *dev) | |
151 | { | |
831eae69 SW |
152 | const struct of_device_id *match; |
153 | const struct dwc2_core_params *params; | |
154 | struct dwc2_core_params defparams; | |
5b9974b1 MK |
155 | struct dwc2_hsotg *hsotg; |
156 | struct resource *res; | |
157 | int retval; | |
158 | int irq; | |
5b9974b1 | 159 | |
861e0f5b AH |
160 | if (usb_disabled()) |
161 | return -ENODEV; | |
162 | ||
831eae69 SW |
163 | match = of_match_device(dwc2_of_match_table, &dev->dev); |
164 | if (match && match->data) { | |
165 | params = match->data; | |
166 | } else { | |
167 | /* Default all params to autodetect */ | |
168 | dwc2_set_all_params(&defparams, -1); | |
169 | params = &defparams; | |
8b3e233e DN |
170 | |
171 | /* | |
172 | * Disable descriptor dma mode by default as the HW can support | |
173 | * it, but does not support it for SPLIT transactions. | |
174 | */ | |
175 | defparams.dma_desc_enable = 0; | |
831eae69 | 176 | } |
5b9974b1 MK |
177 | |
178 | hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); | |
179 | if (!hsotg) | |
180 | return -ENOMEM; | |
181 | ||
182 | hsotg->dev = &dev->dev; | |
183 | ||
642f2ecc MK |
184 | /* |
185 | * Use reasonable defaults so platforms don't have to provide these. | |
186 | */ | |
187 | if (!dev->dev.dma_mask) | |
188 | dev->dev.dma_mask = &dev->dev.coherent_dma_mask; | |
4cdbb4ff RK |
189 | retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); |
190 | if (retval) | |
191 | return retval; | |
642f2ecc | 192 | |
5b9974b1 MK |
193 | irq = platform_get_irq(dev, 0); |
194 | if (irq < 0) { | |
195 | dev_err(&dev->dev, "missing IRQ resource\n"); | |
097f2612 | 196 | return irq; |
5b9974b1 MK |
197 | } |
198 | ||
199 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | |
5b9974b1 MK |
200 | hsotg->regs = devm_ioremap_resource(&dev->dev, res); |
201 | if (IS_ERR(hsotg->regs)) | |
202 | return PTR_ERR(hsotg->regs); | |
203 | ||
204 | dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", | |
205 | (unsigned long)res->start, hsotg->regs); | |
206 | ||
c0155b9d KY |
207 | hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node); |
208 | ||
117777b2 DN |
209 | spin_lock_init(&hsotg->lock); |
210 | retval = dwc2_gadget_init(hsotg, irq); | |
211 | if (retval) | |
212 | return retval; | |
831eae69 | 213 | retval = dwc2_hcd_init(hsotg, irq, params); |
5b9974b1 MK |
214 | if (retval) |
215 | return retval; | |
216 | ||
217 | platform_set_drvdata(dev, hsotg); | |
218 | ||
219 | return retval; | |
220 | } | |
221 | ||
117777b2 DN |
222 | static int dwc2_suspend(struct platform_device *dev, pm_message_t state) |
223 | { | |
224 | struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev); | |
225 | int ret = 0; | |
226 | ||
227 | if (dwc2_is_device_mode(dwc2)) | |
228 | ret = s3c_hsotg_suspend(dwc2); | |
229 | return ret; | |
230 | } | |
231 | ||
232 | static int dwc2_resume(struct platform_device *dev) | |
233 | { | |
234 | struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev); | |
235 | int ret = 0; | |
236 | ||
237 | if (dwc2_is_device_mode(dwc2)) | |
238 | ret = s3c_hsotg_resume(dwc2); | |
239 | return ret; | |
240 | } | |
241 | ||
5b9974b1 MK |
242 | static struct platform_driver dwc2_platform_driver = { |
243 | .driver = { | |
1c126bc6 | 244 | .name = dwc2_driver_name, |
5b9974b1 MK |
245 | .of_match_table = dwc2_of_match_table, |
246 | }, | |
247 | .probe = dwc2_driver_probe, | |
248 | .remove = dwc2_driver_remove, | |
117777b2 DN |
249 | .suspend = dwc2_suspend, |
250 | .resume = dwc2_resume, | |
5b9974b1 MK |
251 | }; |
252 | ||
253 | module_platform_driver(dwc2_platform_driver); | |
254 | ||
255 | MODULE_DESCRIPTION("DESIGNWARE HS OTG Platform Glue"); | |
256 | MODULE_AUTHOR("Matthijs Kooijman <matthijs@stdin.nl>"); | |
257 | MODULE_LICENSE("Dual BSD/GPL"); |