]>
Commit | Line | Data |
---|---|---|
7c6337e2 KH |
1 | /* |
2 | * TI DaVinci EVM board support | |
3 | * | |
4 | * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> | |
5 | * | |
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | |
7 | * the terms of the GNU General Public License version 2. This program | |
8 | * is licensed "as is" without any warranty of any kind, whether express | |
9 | * or implied. | |
10 | */ | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/dma-mapping.h> | |
15 | #include <linux/platform_device.h> | |
7bff3c4c DB |
16 | #include <linux/gpio.h> |
17 | #include <linux/leds.h> | |
18 | ||
19 | #include <linux/i2c.h> | |
20 | #include <linux/i2c/pcf857x.h> | |
21 | #include <linux/i2c/at24.h> | |
22 | ||
7c6337e2 KH |
23 | #include <linux/mtd/mtd.h> |
24 | #include <linux/mtd/partitions.h> | |
25 | #include <linux/mtd/physmap.h> | |
fced80c7 | 26 | #include <linux/io.h> |
7c6337e2 KH |
27 | |
28 | #include <asm/setup.h> | |
7c6337e2 | 29 | #include <asm/mach-types.h> |
7c6337e2 KH |
30 | |
31 | #include <asm/mach/arch.h> | |
32 | #include <asm/mach/map.h> | |
33 | #include <asm/mach/flash.h> | |
34 | ||
7bff3c4c | 35 | #include <mach/hardware.h> |
a09e64fb | 36 | #include <mach/common.h> |
7bff3c4c | 37 | #include <mach/i2c.h> |
7c6337e2 KH |
38 | |
39 | /* other misc. init functions */ | |
40 | void __init davinci_psc_init(void); | |
41 | void __init davinci_irq_init(void); | |
42 | void __init davinci_map_common_io(void); | |
3e062b07 | 43 | void __init davinci_init_common_hw(void); |
7c6337e2 | 44 | |
7bff3c4c DB |
45 | #if defined(CONFIG_MTD_PHYSMAP) || \ |
46 | defined(CONFIG_MTD_PHYSMAP_MODULE) | |
7c6337e2 | 47 | |
7bff3c4c | 48 | static struct mtd_partition davinci_evm_norflash_partitions[] = { |
7c6337e2 KH |
49 | /* bootloader (U-Boot, etc) in first 4 sectors */ |
50 | { | |
51 | .name = "bootloader", | |
52 | .offset = 0, | |
53 | .size = 4 * SZ_64K, | |
54 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | |
55 | }, | |
56 | /* bootloader params in the next 1 sectors */ | |
57 | { | |
58 | .name = "params", | |
59 | .offset = MTDPART_OFS_APPEND, | |
60 | .size = SZ_64K, | |
61 | .mask_flags = 0, | |
62 | }, | |
63 | /* kernel */ | |
64 | { | |
65 | .name = "kernel", | |
66 | .offset = MTDPART_OFS_APPEND, | |
67 | .size = SZ_2M, | |
68 | .mask_flags = 0 | |
69 | }, | |
70 | /* file system */ | |
71 | { | |
72 | .name = "filesystem", | |
73 | .offset = MTDPART_OFS_APPEND, | |
74 | .size = MTDPART_SIZ_FULL, | |
75 | .mask_flags = 0 | |
76 | } | |
77 | }; | |
78 | ||
7bff3c4c | 79 | static struct physmap_flash_data davinci_evm_norflash_data = { |
7c6337e2 | 80 | .width = 2, |
7bff3c4c DB |
81 | .parts = davinci_evm_norflash_partitions, |
82 | .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions), | |
7c6337e2 KH |
83 | }; |
84 | ||
85 | /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF | |
86 | * limits addresses to 16M, so using addresses past 16M will wrap */ | |
7bff3c4c DB |
87 | static struct resource davinci_evm_norflash_resource = { |
88 | .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, | |
89 | .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, | |
7c6337e2 KH |
90 | .flags = IORESOURCE_MEM, |
91 | }; | |
92 | ||
7bff3c4c | 93 | static struct platform_device davinci_evm_norflash_device = { |
7c6337e2 KH |
94 | .name = "physmap-flash", |
95 | .id = 0, | |
96 | .dev = { | |
7bff3c4c | 97 | .platform_data = &davinci_evm_norflash_data, |
7c6337e2 KH |
98 | }, |
99 | .num_resources = 1, | |
7bff3c4c DB |
100 | .resource = &davinci_evm_norflash_resource, |
101 | }; | |
102 | ||
103 | #endif | |
104 | ||
105 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ | |
106 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | |
107 | ||
108 | static struct resource ide_resources[] = { | |
109 | { | |
110 | .start = DAVINCI_CFC_ATA_BASE, | |
111 | .end = DAVINCI_CFC_ATA_BASE + 0x7ff, | |
112 | .flags = IORESOURCE_MEM, | |
113 | }, | |
114 | { | |
115 | .start = IRQ_IDE, | |
116 | .end = IRQ_IDE, | |
117 | .flags = IORESOURCE_IRQ, | |
118 | }, | |
119 | }; | |
120 | ||
284901a9 | 121 | static u64 ide_dma_mask = DMA_BIT_MASK(32); |
7bff3c4c DB |
122 | |
123 | static struct platform_device ide_dev = { | |
124 | .name = "palm_bk3710", | |
125 | .id = -1, | |
126 | .resource = ide_resources, | |
127 | .num_resources = ARRAY_SIZE(ide_resources), | |
128 | .dev = { | |
129 | .dma_mask = &ide_dma_mask, | |
284901a9 | 130 | .coherent_dma_mask = DMA_BIT_MASK(32), |
7bff3c4c DB |
131 | }, |
132 | }; | |
133 | ||
134 | #endif | |
135 | ||
136 | /*----------------------------------------------------------------------*/ | |
137 | ||
138 | /* | |
139 | * I2C GPIO expanders | |
140 | */ | |
141 | ||
142 | #define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8)) | |
143 | ||
144 | ||
145 | /* U2 -- LEDs */ | |
146 | ||
147 | static struct gpio_led evm_leds[] = { | |
148 | { .name = "DS8", .active_low = 1, | |
149 | .default_trigger = "heartbeat", }, | |
150 | { .name = "DS7", .active_low = 1, }, | |
151 | { .name = "DS6", .active_low = 1, }, | |
152 | { .name = "DS5", .active_low = 1, }, | |
153 | { .name = "DS4", .active_low = 1, }, | |
154 | { .name = "DS3", .active_low = 1, }, | |
155 | { .name = "DS2", .active_low = 1, | |
156 | .default_trigger = "mmc0", }, | |
157 | { .name = "DS1", .active_low = 1, | |
158 | .default_trigger = "ide-disk", }, | |
159 | }; | |
160 | ||
161 | static const struct gpio_led_platform_data evm_led_data = { | |
162 | .num_leds = ARRAY_SIZE(evm_leds), | |
163 | .leds = evm_leds, | |
164 | }; | |
165 | ||
166 | static struct platform_device *evm_led_dev; | |
167 | ||
168 | static int | |
169 | evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
170 | { | |
171 | struct gpio_led *leds = evm_leds; | |
172 | int status; | |
173 | ||
174 | while (ngpio--) { | |
175 | leds->gpio = gpio++; | |
176 | leds++; | |
177 | } | |
178 | ||
179 | /* what an extremely annoying way to be forced to handle | |
180 | * device unregistration ... | |
181 | */ | |
182 | evm_led_dev = platform_device_alloc("leds-gpio", 0); | |
183 | platform_device_add_data(evm_led_dev, | |
184 | &evm_led_data, sizeof evm_led_data); | |
185 | ||
186 | evm_led_dev->dev.parent = &client->dev; | |
187 | status = platform_device_add(evm_led_dev); | |
188 | if (status < 0) { | |
189 | platform_device_put(evm_led_dev); | |
190 | evm_led_dev = NULL; | |
191 | } | |
192 | return status; | |
193 | } | |
194 | ||
195 | static int | |
196 | evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
197 | { | |
198 | if (evm_led_dev) { | |
199 | platform_device_unregister(evm_led_dev); | |
200 | evm_led_dev = NULL; | |
201 | } | |
202 | return 0; | |
203 | } | |
204 | ||
205 | static struct pcf857x_platform_data pcf_data_u2 = { | |
206 | .gpio_base = PCF_Uxx_BASE(0), | |
207 | .setup = evm_led_setup, | |
208 | .teardown = evm_led_teardown, | |
209 | }; | |
210 | ||
211 | ||
212 | /* U18 - A/V clock generator and user switch */ | |
213 | ||
214 | static int sw_gpio; | |
215 | ||
216 | static ssize_t | |
217 | sw_show(struct device *d, struct device_attribute *a, char *buf) | |
218 | { | |
219 | char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n"; | |
220 | ||
221 | strcpy(buf, s); | |
222 | return strlen(s); | |
223 | } | |
224 | ||
225 | static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL); | |
226 | ||
227 | static int | |
228 | evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
229 | { | |
230 | int status; | |
231 | ||
232 | /* export dip switch option */ | |
233 | sw_gpio = gpio + 7; | |
234 | status = gpio_request(sw_gpio, "user_sw"); | |
235 | if (status == 0) | |
236 | status = gpio_direction_input(sw_gpio); | |
237 | if (status == 0) | |
238 | status = device_create_file(&client->dev, &dev_attr_user_sw); | |
239 | else | |
240 | gpio_free(sw_gpio); | |
241 | if (status != 0) | |
242 | sw_gpio = -EINVAL; | |
243 | ||
244 | /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */ | |
245 | gpio_request(gpio + 3, "pll_fs2"); | |
246 | gpio_direction_output(gpio + 3, 0); | |
247 | ||
248 | gpio_request(gpio + 2, "pll_fs1"); | |
249 | gpio_direction_output(gpio + 2, 0); | |
250 | ||
251 | gpio_request(gpio + 1, "pll_sr"); | |
252 | gpio_direction_output(gpio + 1, 0); | |
253 | ||
254 | return 0; | |
255 | } | |
256 | ||
257 | static int | |
258 | evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
259 | { | |
260 | gpio_free(gpio + 1); | |
261 | gpio_free(gpio + 2); | |
262 | gpio_free(gpio + 3); | |
263 | ||
264 | if (sw_gpio > 0) { | |
265 | device_remove_file(&client->dev, &dev_attr_user_sw); | |
266 | gpio_free(sw_gpio); | |
267 | } | |
268 | return 0; | |
269 | } | |
270 | ||
271 | static struct pcf857x_platform_data pcf_data_u18 = { | |
272 | .gpio_base = PCF_Uxx_BASE(1), | |
273 | .n_latch = (1 << 3) | (1 << 2) | (1 << 1), | |
274 | .setup = evm_u18_setup, | |
275 | .teardown = evm_u18_teardown, | |
7c6337e2 KH |
276 | }; |
277 | ||
7bff3c4c DB |
278 | |
279 | /* U35 - various I/O signals used to manage USB, CF, ATA, etc */ | |
280 | ||
281 | static int | |
282 | evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
283 | { | |
284 | /* p0 = nDRV_VBUS (initial: don't supply it) */ | |
285 | gpio_request(gpio + 0, "nDRV_VBUS"); | |
286 | gpio_direction_output(gpio + 0, 1); | |
287 | ||
288 | /* p1 = VDDIMX_EN */ | |
289 | gpio_request(gpio + 1, "VDDIMX_EN"); | |
290 | gpio_direction_output(gpio + 1, 1); | |
291 | ||
292 | /* p2 = VLYNQ_EN */ | |
293 | gpio_request(gpio + 2, "VLYNQ_EN"); | |
294 | gpio_direction_output(gpio + 2, 1); | |
295 | ||
296 | /* p3 = n3V3_CF_RESET (initial: stay in reset) */ | |
297 | gpio_request(gpio + 3, "nCF_RESET"); | |
298 | gpio_direction_output(gpio + 3, 0); | |
299 | ||
300 | /* (p4 unused) */ | |
301 | ||
302 | /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */ | |
303 | gpio_request(gpio + 5, "WLAN_RESET"); | |
304 | gpio_direction_output(gpio + 5, 1); | |
305 | ||
306 | /* p6 = nATA_SEL (initial: select) */ | |
307 | gpio_request(gpio + 6, "nATA_SEL"); | |
308 | gpio_direction_output(gpio + 6, 0); | |
309 | ||
310 | /* p7 = nCF_SEL (initial: deselect) */ | |
311 | gpio_request(gpio + 7, "nCF_SEL"); | |
312 | gpio_direction_output(gpio + 7, 1); | |
313 | ||
34f32c97 DB |
314 | /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ |
315 | setup_usb(500, 8); | |
316 | ||
7bff3c4c DB |
317 | return 0; |
318 | } | |
319 | ||
320 | static int | |
321 | evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | |
322 | { | |
323 | gpio_free(gpio + 7); | |
324 | gpio_free(gpio + 6); | |
325 | gpio_free(gpio + 5); | |
326 | gpio_free(gpio + 3); | |
327 | gpio_free(gpio + 2); | |
328 | gpio_free(gpio + 1); | |
329 | gpio_free(gpio + 0); | |
330 | return 0; | |
331 | } | |
332 | ||
333 | static struct pcf857x_platform_data pcf_data_u35 = { | |
334 | .gpio_base = PCF_Uxx_BASE(2), | |
335 | .setup = evm_u35_setup, | |
336 | .teardown = evm_u35_teardown, | |
337 | }; | |
338 | ||
339 | /*----------------------------------------------------------------------*/ | |
340 | ||
341 | /* Most of this EEPROM is unused, but U-Boot uses some data: | |
342 | * - 0x7f00, 6 bytes Ethernet Address | |
343 | * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL) | |
344 | * - ... newer boards may have more | |
345 | */ | |
346 | static struct at24_platform_data eeprom_info = { | |
347 | .byte_len = (256*1024) / 8, | |
348 | .page_size = 64, | |
349 | .flags = AT24_FLAG_ADDR16, | |
350 | }; | |
351 | ||
352 | static struct i2c_board_info __initdata i2c_info[] = { | |
353 | { | |
354 | I2C_BOARD_INFO("pcf8574", 0x38), | |
355 | .platform_data = &pcf_data_u2, | |
356 | }, | |
357 | { | |
358 | I2C_BOARD_INFO("pcf8574", 0x39), | |
359 | .platform_data = &pcf_data_u18, | |
360 | }, | |
361 | { | |
362 | I2C_BOARD_INFO("pcf8574", 0x3a), | |
363 | .platform_data = &pcf_data_u35, | |
364 | }, | |
365 | { | |
366 | I2C_BOARD_INFO("24c256", 0x50), | |
367 | .platform_data = &eeprom_info, | |
368 | }, | |
369 | /* ALSO: | |
370 | * - tvl320aic33 audio codec (0x1b) | |
371 | * - msp430 microcontroller (0x23) | |
372 | * - tvp5146 video decoder (0x5d) | |
373 | */ | |
374 | }; | |
375 | ||
376 | /* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz), | |
377 | * which requires 100 usec of idle bus after i2c writes sent to it. | |
378 | */ | |
379 | static struct davinci_i2c_platform_data i2c_pdata = { | |
380 | .bus_freq = 20 /* kHz */, | |
381 | .bus_delay = 100 /* usec */, | |
382 | }; | |
383 | ||
384 | static void __init evm_init_i2c(void) | |
385 | { | |
386 | davinci_init_i2c(&i2c_pdata); | |
387 | i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); | |
388 | } | |
389 | ||
7c6337e2 | 390 | static struct platform_device *davinci_evm_devices[] __initdata = { |
7bff3c4c DB |
391 | #if defined(CONFIG_MTD_PHYSMAP) || \ |
392 | defined(CONFIG_MTD_PHYSMAP_MODULE) | |
393 | &davinci_evm_norflash_device, | |
394 | #endif | |
395 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ | |
396 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | |
397 | &ide_dev, | |
398 | #endif | |
7c6337e2 KH |
399 | }; |
400 | ||
401 | static void __init | |
402 | davinci_evm_map_io(void) | |
403 | { | |
404 | davinci_map_common_io(); | |
405 | } | |
406 | ||
407 | static __init void davinci_evm_init(void) | |
408 | { | |
409 | davinci_psc_init(); | |
410 | ||
7bff3c4c DB |
411 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ |
412 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | |
413 | #if defined(CONFIG_MTD_PHYSMAP) || \ | |
414 | defined(CONFIG_MTD_PHYSMAP_MODULE) | |
7c6337e2 KH |
415 | printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, " |
416 | "but share pins.\n\t Disable IDE for NOR support.\n"); | |
7bff3c4c | 417 | #endif |
7c6337e2 KH |
418 | #endif |
419 | ||
420 | platform_add_devices(davinci_evm_devices, | |
421 | ARRAY_SIZE(davinci_evm_devices)); | |
7bff3c4c | 422 | evm_init_i2c(); |
7c6337e2 KH |
423 | } |
424 | ||
425 | static __init void davinci_evm_irq_init(void) | |
426 | { | |
3e062b07 | 427 | davinci_init_common_hw(); |
7c6337e2 KH |
428 | davinci_irq_init(); |
429 | } | |
430 | ||
431 | MACHINE_START(DAVINCI_EVM, "DaVinci EVM") | |
432 | /* Maintainer: MontaVista Software <source@mvista.com> */ | |
433 | .phys_io = IO_PHYS, | |
ac7643e4 | 434 | .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, |
7c6337e2 KH |
435 | .boot_params = (DAVINCI_DDR_BASE + 0x100), |
436 | .map_io = davinci_evm_map_io, | |
437 | .init_irq = davinci_evm_irq_init, | |
438 | .timer = &davinci_timer, | |
439 | .init_machine = davinci_evm_init, | |
440 | MACHINE_END |