Commit | Line | Data |
---|---|---|
6c18c91b VR |
1 | /* |
2 | * Hawkboard.org based on TI's OMAP-L138 Platform | |
3 | * | |
4 | * Initial code: Syed Mohammed Khasim | |
5 | * | |
6 | * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com | |
7 | * | |
8 | * This file is licensed under the terms of the GNU General Public License | |
9 | * version 2. This program is licensed "as is" without any warranty of | |
10 | * any kind, whether express or implied. | |
11 | */ | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/console.h> | |
981f18e6 | 15 | #include <linux/interrupt.h> |
6c18c91b | 16 | #include <linux/gpio.h> |
c69f43fb | 17 | #include <linux/gpio/machine.h> |
b856671e | 18 | #include <linux/platform_data/gpio-davinci.h> |
40a17abc | 19 | #include <linux/regulator/machine.h> |
6c18c91b VR |
20 | |
21 | #include <asm/mach-types.h> | |
22 | #include <asm/mach/arch.h> | |
23 | ||
b856671e | 24 | #include <mach/common.h> |
3acf731c | 25 | #include "cp_intc.h" |
6c18c91b | 26 | #include <mach/da8xx.h> |
bb59b7fd VR |
27 | #include <mach/mux.h> |
28 | ||
f6f97588 | 29 | #define HAWKBOARD_PHY_ID "davinci_mdio-0:07" |
bb59b7fd | 30 | |
f5714abb VR |
31 | #define DA850_USB1_VBUS_PIN GPIO_TO_PIN(2, 4) |
32 | #define DA850_USB1_OC_PIN GPIO_TO_PIN(6, 13) | |
33 | ||
bb59b7fd VR |
34 | static short omapl138_hawk_mii_pins[] __initdata = { |
35 | DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, | |
36 | DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, | |
37 | DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, | |
38 | DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, | |
39 | DA850_MDIO_D, | |
40 | -1 | |
41 | }; | |
42 | ||
43 | static __init void omapl138_hawk_config_emac(void) | |
44 | { | |
45 | void __iomem *cfgchip3 = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); | |
46 | int ret; | |
47 | u32 val; | |
48 | struct davinci_soc_info *soc_info = &davinci_soc_info; | |
49 | ||
50 | val = __raw_readl(cfgchip3); | |
51 | val &= ~BIT(8); | |
52 | ret = davinci_cfg_reg_list(omapl138_hawk_mii_pins); | |
53 | if (ret) { | |
6c7c23cc | 54 | pr_warn("%s: CPGMAC/MII mux setup failed: %d\n", __func__, ret); |
bb59b7fd VR |
55 | return; |
56 | } | |
57 | ||
58 | /* configure the CFGCHIP3 register for MII */ | |
59 | __raw_writel(val, cfgchip3); | |
60 | pr_info("EMAC: MII PHY configured\n"); | |
61 | ||
62 | soc_info->emac_pdata->phy_id = HAWKBOARD_PHY_ID; | |
63 | ||
64 | ret = da8xx_register_emac(); | |
65 | if (ret) | |
6c7c23cc | 66 | pr_warn("%s: EMAC registration failed: %d\n", __func__, ret); |
bb59b7fd VR |
67 | } |
68 | ||
5f72f380 VR |
69 | /* |
70 | * The following EDMA channels/slots are not being used by drivers (for | |
71 | * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard, | |
72 | * hence they are being reserved for codecs on the DSP side. | |
73 | */ | |
74 | static const s16 da850_dma0_rsv_chans[][2] = { | |
75 | /* (offset, number) */ | |
76 | { 8, 6}, | |
77 | {24, 4}, | |
78 | {30, 2}, | |
79 | {-1, -1} | |
80 | }; | |
81 | ||
82 | static const s16 da850_dma0_rsv_slots[][2] = { | |
83 | /* (offset, number) */ | |
84 | { 8, 6}, | |
85 | {24, 4}, | |
86 | {30, 50}, | |
87 | {-1, -1} | |
88 | }; | |
89 | ||
90 | static const s16 da850_dma1_rsv_chans[][2] = { | |
91 | /* (offset, number) */ | |
92 | { 0, 28}, | |
93 | {30, 2}, | |
94 | {-1, -1} | |
95 | }; | |
96 | ||
97 | static const s16 da850_dma1_rsv_slots[][2] = { | |
98 | /* (offset, number) */ | |
99 | { 0, 28}, | |
100 | {30, 90}, | |
101 | {-1, -1} | |
102 | }; | |
103 | ||
104 | static struct edma_rsv_info da850_edma_cc0_rsv = { | |
105 | .rsv_chans = da850_dma0_rsv_chans, | |
106 | .rsv_slots = da850_dma0_rsv_slots, | |
107 | }; | |
108 | ||
109 | static struct edma_rsv_info da850_edma_cc1_rsv = { | |
110 | .rsv_chans = da850_dma1_rsv_chans, | |
111 | .rsv_slots = da850_dma1_rsv_slots, | |
112 | }; | |
113 | ||
114 | static struct edma_rsv_info *da850_edma_rsv[2] = { | |
115 | &da850_edma_cc0_rsv, | |
116 | &da850_edma_cc1_rsv, | |
117 | }; | |
6c18c91b | 118 | |
ef782d8d VR |
119 | static const short hawk_mmcsd0_pins[] = { |
120 | DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2, | |
121 | DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD, | |
122 | DA850_GPIO3_12, DA850_GPIO3_13, | |
123 | -1 | |
124 | }; | |
125 | ||
d45622c0 SN |
126 | #define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12) |
127 | #define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13) | |
128 | ||
c69f43fb AH |
129 | static struct gpiod_lookup_table mmc_gpios_table = { |
130 | .dev_id = "da830-mmc.0", | |
131 | .table = { | |
d45622c0 SN |
132 | GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_CD_PIN, "cd", |
133 | GPIO_ACTIVE_LOW), | |
134 | GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_WP_PIN, "wp", | |
135 | GPIO_ACTIVE_LOW), | |
c69f43fb AH |
136 | }, |
137 | }; | |
ef782d8d VR |
138 | |
139 | static struct davinci_mmc_config da850_mmc_config = { | |
ef782d8d VR |
140 | .wires = 4, |
141 | .max_freq = 50000000, | |
142 | .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, | |
ef782d8d VR |
143 | }; |
144 | ||
145 | static __init void omapl138_hawk_mmc_init(void) | |
146 | { | |
147 | int ret; | |
148 | ||
149 | ret = davinci_cfg_reg_list(hawk_mmcsd0_pins); | |
150 | if (ret) { | |
6c7c23cc | 151 | pr_warn("%s: MMC/SD0 mux setup failed: %d\n", __func__, ret); |
ef782d8d VR |
152 | return; |
153 | } | |
154 | ||
c69f43fb | 155 | gpiod_add_lookup_table(&mmc_gpios_table); |
ef782d8d VR |
156 | |
157 | ret = da8xx_register_mmcsd0(&da850_mmc_config); | |
158 | if (ret) { | |
6c7c23cc | 159 | pr_warn("%s: MMC/SD0 registration failed: %d\n", __func__, ret); |
ef782d8d VR |
160 | goto mmc_setup_mmcsd_fail; |
161 | } | |
162 | ||
163 | return; | |
164 | ||
165 | mmc_setup_mmcsd_fail: | |
c69f43fb | 166 | gpiod_remove_lookup_table(&mmc_gpios_table); |
ef782d8d VR |
167 | } |
168 | ||
f5714abb VR |
169 | static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id); |
170 | static da8xx_ocic_handler_t hawk_usb_ocic_handler; | |
171 | ||
172 | static const short da850_hawk_usb11_pins[] = { | |
173 | DA850_GPIO2_4, DA850_GPIO6_13, | |
174 | -1 | |
175 | }; | |
176 | ||
177 | static int hawk_usb_set_power(unsigned port, int on) | |
178 | { | |
179 | gpio_set_value(DA850_USB1_VBUS_PIN, on); | |
180 | return 0; | |
181 | } | |
182 | ||
183 | static int hawk_usb_get_power(unsigned port) | |
184 | { | |
185 | return gpio_get_value(DA850_USB1_VBUS_PIN); | |
186 | } | |
187 | ||
188 | static int hawk_usb_get_oci(unsigned port) | |
189 | { | |
190 | return !gpio_get_value(DA850_USB1_OC_PIN); | |
191 | } | |
192 | ||
193 | static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler) | |
194 | { | |
195 | int irq = gpio_to_irq(DA850_USB1_OC_PIN); | |
196 | int error = 0; | |
197 | ||
198 | if (handler != NULL) { | |
199 | hawk_usb_ocic_handler = handler; | |
200 | ||
201 | error = request_irq(irq, omapl138_hawk_usb_ocic_irq, | |
1091a654 | 202 | IRQF_TRIGGER_RISING | |
f5714abb VR |
203 | IRQF_TRIGGER_FALLING, |
204 | "OHCI over-current indicator", NULL); | |
205 | if (error) | |
206 | pr_err("%s: could not request IRQ to watch " | |
207 | "over-current indicator changes\n", __func__); | |
208 | } else { | |
209 | free_irq(irq, NULL); | |
210 | } | |
211 | return error; | |
212 | } | |
213 | ||
214 | static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = { | |
215 | .set_power = hawk_usb_set_power, | |
216 | .get_power = hawk_usb_get_power, | |
217 | .get_oci = hawk_usb_get_oci, | |
218 | .ocic_notify = hawk_usb_ocic_notify, | |
219 | /* TPS2087 switch @ 5V */ | |
220 | .potpgt = (3 + 1) / 2, /* 3 ms max */ | |
221 | }; | |
222 | ||
223 | static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id) | |
224 | { | |
225 | hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1); | |
226 | return IRQ_HANDLED; | |
227 | } | |
228 | ||
229 | static __init void omapl138_hawk_usb_init(void) | |
230 | { | |
231 | int ret; | |
f5714abb VR |
232 | |
233 | ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); | |
234 | if (ret) { | |
6c7c23cc | 235 | pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret); |
f5714abb VR |
236 | return; |
237 | } | |
238 | ||
0004b02a DL |
239 | ret = da8xx_register_usb20_phy_clk(false); |
240 | if (ret) | |
241 | pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n", | |
242 | __func__, ret); | |
f5714abb | 243 | |
0004b02a DL |
244 | ret = da8xx_register_usb11_phy_clk(false); |
245 | if (ret) | |
246 | pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n", | |
247 | __func__, ret); | |
f5714abb | 248 | |
9b504750 DL |
249 | ret = da8xx_register_usb_phy(); |
250 | if (ret) | |
251 | pr_warn("%s: USB PHY registration failed: %d\n", | |
252 | __func__, ret); | |
253 | ||
f5714abb VR |
254 | ret = gpio_request_one(DA850_USB1_VBUS_PIN, |
255 | GPIOF_DIR_OUT, "USB1 VBUS"); | |
256 | if (ret < 0) { | |
257 | pr_err("%s: failed to request GPIO for USB 1.1 port " | |
258 | "power control: %d\n", __func__, ret); | |
259 | return; | |
260 | } | |
261 | ||
262 | ret = gpio_request_one(DA850_USB1_OC_PIN, | |
263 | GPIOF_DIR_IN, "USB1 OC"); | |
264 | if (ret < 0) { | |
265 | pr_err("%s: failed to request GPIO for USB 1.1 port " | |
266 | "over-current indicator: %d\n", __func__, ret); | |
267 | goto usb11_setup_oc_fail; | |
268 | } | |
269 | ||
270 | ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata); | |
271 | if (ret) { | |
6c7c23cc | 272 | pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret); |
f5714abb VR |
273 | goto usb11_setup_fail; |
274 | } | |
275 | ||
276 | return; | |
277 | ||
278 | usb11_setup_fail: | |
279 | gpio_free(DA850_USB1_OC_PIN); | |
280 | usb11_setup_oc_fail: | |
281 | gpio_free(DA850_USB1_VBUS_PIN); | |
282 | } | |
283 | ||
6c18c91b VR |
284 | static __init void omapl138_hawk_init(void) |
285 | { | |
286 | int ret; | |
287 | ||
b856671e PA |
288 | ret = da850_register_gpio(); |
289 | if (ret) | |
290 | pr_warn("%s: GPIO init failed: %d\n", __func__, ret); | |
291 | ||
fcf7157b | 292 | davinci_serial_init(da8xx_serial_device); |
6c18c91b | 293 | |
bb59b7fd VR |
294 | omapl138_hawk_config_emac(); |
295 | ||
5f72f380 VR |
296 | ret = da850_register_edma(da850_edma_rsv); |
297 | if (ret) | |
6c7c23cc | 298 | pr_warn("%s: EDMA registration failed: %d\n", __func__, ret); |
5f72f380 | 299 | |
ef782d8d VR |
300 | omapl138_hawk_mmc_init(); |
301 | ||
f5714abb VR |
302 | omapl138_hawk_usb_init(); |
303 | ||
6c18c91b VR |
304 | ret = da8xx_register_watchdog(); |
305 | if (ret) | |
6c7c23cc RT |
306 | pr_warn("%s: watchdog registration failed: %d\n", |
307 | __func__, ret); | |
54288134 RT |
308 | |
309 | ret = da8xx_register_rproc(); | |
310 | if (ret) | |
311 | pr_warn("%s: dsp/rproc registration failed: %d\n", | |
312 | __func__, ret); | |
40a17abc AH |
313 | |
314 | regulator_has_full_constraints(); | |
6c18c91b VR |
315 | } |
316 | ||
317 | #ifdef CONFIG_SERIAL_8250_CONSOLE | |
318 | static int __init omapl138_hawk_console_init(void) | |
319 | { | |
320 | if (!machine_is_omapl138_hawkboard()) | |
321 | return 0; | |
322 | ||
323 | return add_preferred_console("ttyS", 2, "115200"); | |
324 | } | |
325 | console_initcall(omapl138_hawk_console_init); | |
326 | #endif | |
327 | ||
328 | static void __init omapl138_hawk_map_io(void) | |
329 | { | |
330 | da850_init(); | |
331 | } | |
332 | ||
333 | MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") | |
e7e56014 | 334 | .atag_offset = 0x100, |
6c18c91b VR |
335 | .map_io = omapl138_hawk_map_io, |
336 | .init_irq = cp_intc_init, | |
96c08173 | 337 | .init_time = da850_init_time, |
6c18c91b | 338 | .init_machine = omapl138_hawk_init, |
3aa3e840 | 339 | .init_late = davinci_init_late, |
f68deabf | 340 | .dma_zone_size = SZ_128M, |
54288134 | 341 | .reserve = da8xx_rproc_reserve_cma, |
6c18c91b | 342 | MACHINE_END |