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