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, | |
139 | .version = MMC_CTLR_VERSION_2, | |
140 | }; | |
141 | ||
142 | static __init void omapl138_hawk_mmc_init(void) | |
143 | { | |
144 | int ret; | |
145 | ||
146 | ret = davinci_cfg_reg_list(hawk_mmcsd0_pins); | |
147 | if (ret) { | |
6c7c23cc | 148 | pr_warn("%s: MMC/SD0 mux setup failed: %d\n", __func__, ret); |
ef782d8d VR |
149 | return; |
150 | } | |
151 | ||
152 | ret = gpio_request_one(DA850_HAWK_MMCSD_CD_PIN, | |
153 | GPIOF_DIR_IN, "MMC CD"); | |
154 | if (ret < 0) { | |
6c7c23cc | 155 | pr_warn("%s: can not open GPIO %d\n", |
ef782d8d VR |
156 | __func__, DA850_HAWK_MMCSD_CD_PIN); |
157 | return; | |
158 | } | |
159 | ||
160 | ret = gpio_request_one(DA850_HAWK_MMCSD_WP_PIN, | |
161 | GPIOF_DIR_IN, "MMC WP"); | |
162 | if (ret < 0) { | |
6c7c23cc | 163 | pr_warn("%s: can not open GPIO %d\n", |
ef782d8d VR |
164 | __func__, DA850_HAWK_MMCSD_WP_PIN); |
165 | goto mmc_setup_wp_fail; | |
166 | } | |
167 | ||
168 | ret = da8xx_register_mmcsd0(&da850_mmc_config); | |
169 | if (ret) { | |
6c7c23cc | 170 | pr_warn("%s: MMC/SD0 registration failed: %d\n", __func__, ret); |
ef782d8d VR |
171 | goto mmc_setup_mmcsd_fail; |
172 | } | |
173 | ||
174 | return; | |
175 | ||
176 | mmc_setup_mmcsd_fail: | |
177 | gpio_free(DA850_HAWK_MMCSD_WP_PIN); | |
178 | mmc_setup_wp_fail: | |
179 | gpio_free(DA850_HAWK_MMCSD_CD_PIN); | |
180 | } | |
181 | ||
f5714abb VR |
182 | static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id); |
183 | static da8xx_ocic_handler_t hawk_usb_ocic_handler; | |
184 | ||
185 | static const short da850_hawk_usb11_pins[] = { | |
186 | DA850_GPIO2_4, DA850_GPIO6_13, | |
187 | -1 | |
188 | }; | |
189 | ||
190 | static int hawk_usb_set_power(unsigned port, int on) | |
191 | { | |
192 | gpio_set_value(DA850_USB1_VBUS_PIN, on); | |
193 | return 0; | |
194 | } | |
195 | ||
196 | static int hawk_usb_get_power(unsigned port) | |
197 | { | |
198 | return gpio_get_value(DA850_USB1_VBUS_PIN); | |
199 | } | |
200 | ||
201 | static int hawk_usb_get_oci(unsigned port) | |
202 | { | |
203 | return !gpio_get_value(DA850_USB1_OC_PIN); | |
204 | } | |
205 | ||
206 | static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler) | |
207 | { | |
208 | int irq = gpio_to_irq(DA850_USB1_OC_PIN); | |
209 | int error = 0; | |
210 | ||
211 | if (handler != NULL) { | |
212 | hawk_usb_ocic_handler = handler; | |
213 | ||
214 | error = request_irq(irq, omapl138_hawk_usb_ocic_irq, | |
215 | IRQF_DISABLED | IRQF_TRIGGER_RISING | | |
216 | IRQF_TRIGGER_FALLING, | |
217 | "OHCI over-current indicator", NULL); | |
218 | if (error) | |
219 | pr_err("%s: could not request IRQ to watch " | |
220 | "over-current indicator changes\n", __func__); | |
221 | } else { | |
222 | free_irq(irq, NULL); | |
223 | } | |
224 | return error; | |
225 | } | |
226 | ||
227 | static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = { | |
228 | .set_power = hawk_usb_set_power, | |
229 | .get_power = hawk_usb_get_power, | |
230 | .get_oci = hawk_usb_get_oci, | |
231 | .ocic_notify = hawk_usb_ocic_notify, | |
232 | /* TPS2087 switch @ 5V */ | |
233 | .potpgt = (3 + 1) / 2, /* 3 ms max */ | |
234 | }; | |
235 | ||
236 | static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id) | |
237 | { | |
238 | hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1); | |
239 | return IRQ_HANDLED; | |
240 | } | |
241 | ||
242 | static __init void omapl138_hawk_usb_init(void) | |
243 | { | |
244 | int ret; | |
245 | u32 cfgchip2; | |
246 | ||
247 | ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); | |
248 | if (ret) { | |
6c7c23cc | 249 | pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret); |
f5714abb VR |
250 | return; |
251 | } | |
252 | ||
253 | /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */ | |
254 | ||
255 | cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); | |
256 | cfgchip2 &= ~CFGCHIP2_REFFREQ; | |
257 | cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; | |
258 | __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); | |
259 | ||
260 | ret = gpio_request_one(DA850_USB1_VBUS_PIN, | |
261 | GPIOF_DIR_OUT, "USB1 VBUS"); | |
262 | if (ret < 0) { | |
263 | pr_err("%s: failed to request GPIO for USB 1.1 port " | |
264 | "power control: %d\n", __func__, ret); | |
265 | return; | |
266 | } | |
267 | ||
268 | ret = gpio_request_one(DA850_USB1_OC_PIN, | |
269 | GPIOF_DIR_IN, "USB1 OC"); | |
270 | if (ret < 0) { | |
271 | pr_err("%s: failed to request GPIO for USB 1.1 port " | |
272 | "over-current indicator: %d\n", __func__, ret); | |
273 | goto usb11_setup_oc_fail; | |
274 | } | |
275 | ||
276 | ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata); | |
277 | if (ret) { | |
6c7c23cc | 278 | pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret); |
f5714abb VR |
279 | goto usb11_setup_fail; |
280 | } | |
281 | ||
282 | return; | |
283 | ||
284 | usb11_setup_fail: | |
285 | gpio_free(DA850_USB1_OC_PIN); | |
286 | usb11_setup_oc_fail: | |
287 | gpio_free(DA850_USB1_VBUS_PIN); | |
288 | } | |
289 | ||
6c18c91b VR |
290 | static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { |
291 | .enabled_uarts = 0x7, | |
292 | }; | |
293 | ||
294 | static __init void omapl138_hawk_init(void) | |
295 | { | |
296 | int ret; | |
297 | ||
298 | davinci_serial_init(&omapl138_hawk_uart_config); | |
299 | ||
bb59b7fd VR |
300 | omapl138_hawk_config_emac(); |
301 | ||
5f72f380 VR |
302 | ret = da850_register_edma(da850_edma_rsv); |
303 | if (ret) | |
6c7c23cc | 304 | pr_warn("%s: EDMA registration failed: %d\n", __func__, ret); |
5f72f380 | 305 | |
ef782d8d VR |
306 | omapl138_hawk_mmc_init(); |
307 | ||
f5714abb VR |
308 | omapl138_hawk_usb_init(); |
309 | ||
6c18c91b VR |
310 | ret = da8xx_register_watchdog(); |
311 | if (ret) | |
6c7c23cc RT |
312 | pr_warn("%s: watchdog registration failed: %d\n", |
313 | __func__, ret); | |
6c18c91b VR |
314 | } |
315 | ||
316 | #ifdef CONFIG_SERIAL_8250_CONSOLE | |
317 | static int __init omapl138_hawk_console_init(void) | |
318 | { | |
319 | if (!machine_is_omapl138_hawkboard()) | |
320 | return 0; | |
321 | ||
322 | return add_preferred_console("ttyS", 2, "115200"); | |
323 | } | |
324 | console_initcall(omapl138_hawk_console_init); | |
325 | #endif | |
326 | ||
327 | static void __init omapl138_hawk_map_io(void) | |
328 | { | |
329 | da850_init(); | |
330 | } | |
331 | ||
332 | MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") | |
e7e56014 | 333 | .atag_offset = 0x100, |
6c18c91b VR |
334 | .map_io = omapl138_hawk_map_io, |
335 | .init_irq = cp_intc_init, | |
6bb27d73 | 336 | .init_time = davinci_timer_init, |
6c18c91b | 337 | .init_machine = omapl138_hawk_init, |
3aa3e840 | 338 | .init_late = davinci_init_late, |
f68deabf | 339 | .dma_zone_size = SZ_128M, |
c6121ddd | 340 | .restart = da8xx_restart, |
6c18c91b | 341 | MACHINE_END |