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