diff options
Diffstat (limited to 'arch/arm/mach-davinci/board-dm644x-evm.c')
-rw-r--r-- | arch/arm/mach-davinci/board-dm644x-evm.c | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c new file mode 100644 index 000000000000..c039674fe99e --- /dev/null +++ b/arch/arm/mach-davinci/board-dm644x-evm.c | |||
@@ -0,0 +1,696 @@ | |||
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> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/leds.h> | ||
18 | #include <linux/memory.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | |||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/i2c/pcf857x.h> | ||
23 | #include <linux/i2c/at24.h> | ||
24 | |||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mtd/nand.h> | ||
27 | #include <linux/mtd/partitions.h> | ||
28 | #include <linux/mtd/physmap.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/phy.h> | ||
31 | #include <linux/clk.h> | ||
32 | |||
33 | #include <asm/setup.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | |||
36 | #include <asm/mach/arch.h> | ||
37 | #include <asm/mach/map.h> | ||
38 | #include <asm/mach/flash.h> | ||
39 | |||
40 | #include <mach/dm644x.h> | ||
41 | #include <mach/common.h> | ||
42 | #include <mach/i2c.h> | ||
43 | #include <mach/serial.h> | ||
44 | #include <mach/mux.h> | ||
45 | #include <mach/psc.h> | ||
46 | #include <mach/nand.h> | ||
47 | |||
48 | #define DM644X_EVM_PHY_MASK (0x2) | ||
49 | #define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | ||
50 | |||
51 | #define DAVINCI_CFC_ATA_BASE 0x01C66000 | ||
52 | |||
53 | #define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 | ||
54 | #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 | ||
55 | #define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 | ||
56 | #define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE 0x06000000 | ||
57 | #define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE 0x08000000 | ||
58 | |||
59 | #define LXT971_PHY_ID (0x001378e2) | ||
60 | #define LXT971_PHY_MASK (0xfffffff0) | ||
61 | |||
62 | static struct mtd_partition davinci_evm_norflash_partitions[] = { | ||
63 | /* bootloader (UBL, U-Boot, etc) in first 5 sectors */ | ||
64 | { | ||
65 | .name = "bootloader", | ||
66 | .offset = 0, | ||
67 | .size = 5 * SZ_64K, | ||
68 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
69 | }, | ||
70 | /* bootloader params in the next 1 sectors */ | ||
71 | { | ||
72 | .name = "params", | ||
73 | .offset = MTDPART_OFS_APPEND, | ||
74 | .size = SZ_64K, | ||
75 | .mask_flags = 0, | ||
76 | }, | ||
77 | /* kernel */ | ||
78 | { | ||
79 | .name = "kernel", | ||
80 | .offset = MTDPART_OFS_APPEND, | ||
81 | .size = SZ_2M, | ||
82 | .mask_flags = 0 | ||
83 | }, | ||
84 | /* file system */ | ||
85 | { | ||
86 | .name = "filesystem", | ||
87 | .offset = MTDPART_OFS_APPEND, | ||
88 | .size = MTDPART_SIZ_FULL, | ||
89 | .mask_flags = 0 | ||
90 | } | ||
91 | }; | ||
92 | |||
93 | static struct physmap_flash_data davinci_evm_norflash_data = { | ||
94 | .width = 2, | ||
95 | .parts = davinci_evm_norflash_partitions, | ||
96 | .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions), | ||
97 | }; | ||
98 | |||
99 | /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF | ||
100 | * limits addresses to 16M, so using addresses past 16M will wrap */ | ||
101 | static struct resource davinci_evm_norflash_resource = { | ||
102 | .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, | ||
103 | .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, | ||
104 | .flags = IORESOURCE_MEM, | ||
105 | }; | ||
106 | |||
107 | static struct platform_device davinci_evm_norflash_device = { | ||
108 | .name = "physmap-flash", | ||
109 | .id = 0, | ||
110 | .dev = { | ||
111 | .platform_data = &davinci_evm_norflash_data, | ||
112 | }, | ||
113 | .num_resources = 1, | ||
114 | .resource = &davinci_evm_norflash_resource, | ||
115 | }; | ||
116 | |||
117 | /* DM644x EVM includes a 64 MByte small-page NAND flash (16K blocks). | ||
118 | * It may used instead of the (default) NOR chip to boot, using TI's | ||
119 | * tools to install the secondary boot loader (UBL) and U-Boot. | ||
120 | */ | ||
121 | struct mtd_partition davinci_evm_nandflash_partition[] = { | ||
122 | /* Bootloader layout depends on whose u-boot is installed, but we | ||
123 | * can hide all the details. | ||
124 | * - block 0 for u-boot environment ... in mainline u-boot | ||
125 | * - block 1 for UBL (plus up to four backup copies in blocks 2..5) | ||
126 | * - blocks 6...? for u-boot | ||
127 | * - blocks 16..23 for u-boot environment ... in TI's u-boot | ||
128 | */ | ||
129 | { | ||
130 | .name = "bootloader", | ||
131 | .offset = 0, | ||
132 | .size = SZ_256K + SZ_128K, | ||
133 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
134 | }, | ||
135 | /* Kernel */ | ||
136 | { | ||
137 | .name = "kernel", | ||
138 | .offset = MTDPART_OFS_APPEND, | ||
139 | .size = SZ_4M, | ||
140 | .mask_flags = 0, | ||
141 | }, | ||
142 | /* File system (older GIT kernels started this on the 5MB mark) */ | ||
143 | { | ||
144 | .name = "filesystem", | ||
145 | .offset = MTDPART_OFS_APPEND, | ||
146 | .size = MTDPART_SIZ_FULL, | ||
147 | .mask_flags = 0, | ||
148 | } | ||
149 | /* A few blocks at end hold a flash BBT ... created by TI's CCS | ||
150 | * using flashwriter_nand.out, but ignored by TI's versions of | ||
151 | * Linux and u-boot. We boot faster by using them. | ||
152 | */ | ||
153 | }; | ||
154 | |||
155 | static struct davinci_nand_pdata davinci_evm_nandflash_data = { | ||
156 | .parts = davinci_evm_nandflash_partition, | ||
157 | .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition), | ||
158 | .ecc_mode = NAND_ECC_HW, | ||
159 | .options = NAND_USE_FLASH_BBT, | ||
160 | }; | ||
161 | |||
162 | static struct resource davinci_evm_nandflash_resource[] = { | ||
163 | { | ||
164 | .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, | ||
165 | .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, | ||
166 | .flags = IORESOURCE_MEM, | ||
167 | }, { | ||
168 | .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, | ||
169 | .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, | ||
170 | .flags = IORESOURCE_MEM, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | static struct platform_device davinci_evm_nandflash_device = { | ||
175 | .name = "davinci_nand", | ||
176 | .id = 0, | ||
177 | .dev = { | ||
178 | .platform_data = &davinci_evm_nandflash_data, | ||
179 | }, | ||
180 | .num_resources = ARRAY_SIZE(davinci_evm_nandflash_resource), | ||
181 | .resource = davinci_evm_nandflash_resource, | ||
182 | }; | ||
183 | |||
184 | static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32); | ||
185 | |||
186 | static struct platform_device davinci_fb_device = { | ||
187 | .name = "davincifb", | ||
188 | .id = -1, | ||
189 | .dev = { | ||
190 | .dma_mask = &davinci_fb_dma_mask, | ||
191 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
192 | }, | ||
193 | .num_resources = 0, | ||
194 | }; | ||
195 | |||
196 | static struct platform_device rtc_dev = { | ||
197 | .name = "rtc_davinci_evm", | ||
198 | .id = -1, | ||
199 | }; | ||
200 | |||
201 | static struct resource ide_resources[] = { | ||
202 | { | ||
203 | .start = DAVINCI_CFC_ATA_BASE, | ||
204 | .end = DAVINCI_CFC_ATA_BASE + 0x7ff, | ||
205 | .flags = IORESOURCE_MEM, | ||
206 | }, | ||
207 | { | ||
208 | .start = IRQ_IDE, | ||
209 | .end = IRQ_IDE, | ||
210 | .flags = IORESOURCE_IRQ, | ||
211 | }, | ||
212 | }; | ||
213 | |||
214 | static u64 ide_dma_mask = DMA_32BIT_MASK; | ||
215 | |||
216 | static struct platform_device ide_dev = { | ||
217 | .name = "palm_bk3710", | ||
218 | .id = -1, | ||
219 | .resource = ide_resources, | ||
220 | .num_resources = ARRAY_SIZE(ide_resources), | ||
221 | .dev = { | ||
222 | .dma_mask = &ide_dma_mask, | ||
223 | .coherent_dma_mask = DMA_32BIT_MASK, | ||
224 | }, | ||
225 | }; | ||
226 | |||
227 | /*----------------------------------------------------------------------*/ | ||
228 | |||
229 | /* | ||
230 | * I2C GPIO expanders | ||
231 | */ | ||
232 | |||
233 | #define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8)) | ||
234 | |||
235 | |||
236 | /* U2 -- LEDs */ | ||
237 | |||
238 | static struct gpio_led evm_leds[] = { | ||
239 | { .name = "DS8", .active_low = 1, | ||
240 | .default_trigger = "heartbeat", }, | ||
241 | { .name = "DS7", .active_low = 1, }, | ||
242 | { .name = "DS6", .active_low = 1, }, | ||
243 | { .name = "DS5", .active_low = 1, }, | ||
244 | { .name = "DS4", .active_low = 1, }, | ||
245 | { .name = "DS3", .active_low = 1, }, | ||
246 | { .name = "DS2", .active_low = 1, | ||
247 | .default_trigger = "mmc0", }, | ||
248 | { .name = "DS1", .active_low = 1, | ||
249 | .default_trigger = "ide-disk", }, | ||
250 | }; | ||
251 | |||
252 | static const struct gpio_led_platform_data evm_led_data = { | ||
253 | .num_leds = ARRAY_SIZE(evm_leds), | ||
254 | .leds = evm_leds, | ||
255 | }; | ||
256 | |||
257 | static struct platform_device *evm_led_dev; | ||
258 | |||
259 | static int | ||
260 | evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
261 | { | ||
262 | struct gpio_led *leds = evm_leds; | ||
263 | int status; | ||
264 | |||
265 | while (ngpio--) { | ||
266 | leds->gpio = gpio++; | ||
267 | leds++; | ||
268 | } | ||
269 | |||
270 | /* what an extremely annoying way to be forced to handle | ||
271 | * device unregistration ... | ||
272 | */ | ||
273 | evm_led_dev = platform_device_alloc("leds-gpio", 0); | ||
274 | platform_device_add_data(evm_led_dev, | ||
275 | &evm_led_data, sizeof evm_led_data); | ||
276 | |||
277 | evm_led_dev->dev.parent = &client->dev; | ||
278 | status = platform_device_add(evm_led_dev); | ||
279 | if (status < 0) { | ||
280 | platform_device_put(evm_led_dev); | ||
281 | evm_led_dev = NULL; | ||
282 | } | ||
283 | return status; | ||
284 | } | ||
285 | |||
286 | static int | ||
287 | evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
288 | { | ||
289 | if (evm_led_dev) { | ||
290 | platform_device_unregister(evm_led_dev); | ||
291 | evm_led_dev = NULL; | ||
292 | } | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static struct pcf857x_platform_data pcf_data_u2 = { | ||
297 | .gpio_base = PCF_Uxx_BASE(0), | ||
298 | .setup = evm_led_setup, | ||
299 | .teardown = evm_led_teardown, | ||
300 | }; | ||
301 | |||
302 | |||
303 | /* U18 - A/V clock generator and user switch */ | ||
304 | |||
305 | static int sw_gpio; | ||
306 | |||
307 | static ssize_t | ||
308 | sw_show(struct device *d, struct device_attribute *a, char *buf) | ||
309 | { | ||
310 | char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n"; | ||
311 | |||
312 | strcpy(buf, s); | ||
313 | return strlen(s); | ||
314 | } | ||
315 | |||
316 | static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL); | ||
317 | |||
318 | static int | ||
319 | evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
320 | { | ||
321 | int status; | ||
322 | |||
323 | /* export dip switch option */ | ||
324 | sw_gpio = gpio + 7; | ||
325 | status = gpio_request(sw_gpio, "user_sw"); | ||
326 | if (status == 0) | ||
327 | status = gpio_direction_input(sw_gpio); | ||
328 | if (status == 0) | ||
329 | status = device_create_file(&client->dev, &dev_attr_user_sw); | ||
330 | else | ||
331 | gpio_free(sw_gpio); | ||
332 | if (status != 0) | ||
333 | sw_gpio = -EINVAL; | ||
334 | |||
335 | /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */ | ||
336 | gpio_request(gpio + 3, "pll_fs2"); | ||
337 | gpio_direction_output(gpio + 3, 0); | ||
338 | |||
339 | gpio_request(gpio + 2, "pll_fs1"); | ||
340 | gpio_direction_output(gpio + 2, 0); | ||
341 | |||
342 | gpio_request(gpio + 1, "pll_sr"); | ||
343 | gpio_direction_output(gpio + 1, 0); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int | ||
349 | evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
350 | { | ||
351 | gpio_free(gpio + 1); | ||
352 | gpio_free(gpio + 2); | ||
353 | gpio_free(gpio + 3); | ||
354 | |||
355 | if (sw_gpio > 0) { | ||
356 | device_remove_file(&client->dev, &dev_attr_user_sw); | ||
357 | gpio_free(sw_gpio); | ||
358 | } | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static struct pcf857x_platform_data pcf_data_u18 = { | ||
363 | .gpio_base = PCF_Uxx_BASE(1), | ||
364 | .n_latch = (1 << 3) | (1 << 2) | (1 << 1), | ||
365 | .setup = evm_u18_setup, | ||
366 | .teardown = evm_u18_teardown, | ||
367 | }; | ||
368 | |||
369 | |||
370 | /* U35 - various I/O signals used to manage USB, CF, ATA, etc */ | ||
371 | |||
372 | static int | ||
373 | evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
374 | { | ||
375 | /* p0 = nDRV_VBUS (initial: don't supply it) */ | ||
376 | gpio_request(gpio + 0, "nDRV_VBUS"); | ||
377 | gpio_direction_output(gpio + 0, 1); | ||
378 | |||
379 | /* p1 = VDDIMX_EN */ | ||
380 | gpio_request(gpio + 1, "VDDIMX_EN"); | ||
381 | gpio_direction_output(gpio + 1, 1); | ||
382 | |||
383 | /* p2 = VLYNQ_EN */ | ||
384 | gpio_request(gpio + 2, "VLYNQ_EN"); | ||
385 | gpio_direction_output(gpio + 2, 1); | ||
386 | |||
387 | /* p3 = n3V3_CF_RESET (initial: stay in reset) */ | ||
388 | gpio_request(gpio + 3, "nCF_RESET"); | ||
389 | gpio_direction_output(gpio + 3, 0); | ||
390 | |||
391 | /* (p4 unused) */ | ||
392 | |||
393 | /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */ | ||
394 | gpio_request(gpio + 5, "WLAN_RESET"); | ||
395 | gpio_direction_output(gpio + 5, 1); | ||
396 | |||
397 | /* p6 = nATA_SEL (initial: select) */ | ||
398 | gpio_request(gpio + 6, "nATA_SEL"); | ||
399 | gpio_direction_output(gpio + 6, 0); | ||
400 | |||
401 | /* p7 = nCF_SEL (initial: deselect) */ | ||
402 | gpio_request(gpio + 7, "nCF_SEL"); | ||
403 | gpio_direction_output(gpio + 7, 1); | ||
404 | |||
405 | /* irlml6401 switches over 1A, in under 8 msec; | ||
406 | * now it can be managed by nDRV_VBUS ... | ||
407 | */ | ||
408 | setup_usb(500, 8); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int | ||
414 | evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) | ||
415 | { | ||
416 | gpio_free(gpio + 7); | ||
417 | gpio_free(gpio + 6); | ||
418 | gpio_free(gpio + 5); | ||
419 | gpio_free(gpio + 3); | ||
420 | gpio_free(gpio + 2); | ||
421 | gpio_free(gpio + 1); | ||
422 | gpio_free(gpio + 0); | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static struct pcf857x_platform_data pcf_data_u35 = { | ||
427 | .gpio_base = PCF_Uxx_BASE(2), | ||
428 | .setup = evm_u35_setup, | ||
429 | .teardown = evm_u35_teardown, | ||
430 | }; | ||
431 | |||
432 | /*----------------------------------------------------------------------*/ | ||
433 | |||
434 | /* Most of this EEPROM is unused, but U-Boot uses some data: | ||
435 | * - 0x7f00, 6 bytes Ethernet Address | ||
436 | * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL) | ||
437 | * - ... newer boards may have more | ||
438 | */ | ||
439 | static struct memory_accessor *at24_mem_acc; | ||
440 | |||
441 | static void at24_setup(struct memory_accessor *mem_acc, void *context) | ||
442 | { | ||
443 | DECLARE_MAC_BUF(mac_str); | ||
444 | char mac_addr[6]; | ||
445 | |||
446 | at24_mem_acc = mem_acc; | ||
447 | |||
448 | /* Read MAC addr from EEPROM */ | ||
449 | if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, 6) == 6) { | ||
450 | printk(KERN_INFO "Read MAC addr from EEPROM: %s\n", | ||
451 | print_mac(mac_str, mac_addr)); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static struct at24_platform_data eeprom_info = { | ||
456 | .byte_len = (256*1024) / 8, | ||
457 | .page_size = 64, | ||
458 | .flags = AT24_FLAG_ADDR16, | ||
459 | .setup = at24_setup, | ||
460 | }; | ||
461 | |||
462 | int dm6446evm_eeprom_read(void *buf, off_t off, size_t count) | ||
463 | { | ||
464 | if (at24_mem_acc) | ||
465 | return at24_mem_acc->read(at24_mem_acc, buf, off, count); | ||
466 | return -ENODEV; | ||
467 | } | ||
468 | EXPORT_SYMBOL(dm6446evm_eeprom_read); | ||
469 | |||
470 | int dm6446evm_eeprom_write(void *buf, off_t off, size_t count) | ||
471 | { | ||
472 | if (at24_mem_acc) | ||
473 | return at24_mem_acc->write(at24_mem_acc, buf, off, count); | ||
474 | return -ENODEV; | ||
475 | } | ||
476 | EXPORT_SYMBOL(dm6446evm_eeprom_write); | ||
477 | |||
478 | /* | ||
479 | * MSP430 supports RTC, card detection, input from IR remote, and | ||
480 | * a bit more. It triggers interrupts on GPIO(7) from pressing | ||
481 | * buttons on the IR remote, and for card detect switches. | ||
482 | */ | ||
483 | static struct i2c_client *dm6446evm_msp; | ||
484 | |||
485 | static int dm6446evm_msp_probe(struct i2c_client *client, | ||
486 | const struct i2c_device_id *id) | ||
487 | { | ||
488 | dm6446evm_msp = client; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int dm6446evm_msp_remove(struct i2c_client *client) | ||
493 | { | ||
494 | dm6446evm_msp = NULL; | ||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static const struct i2c_device_id dm6446evm_msp_ids[] = { | ||
499 | { "dm6446evm_msp", 0, }, | ||
500 | { /* end of list */ }, | ||
501 | }; | ||
502 | |||
503 | static struct i2c_driver dm6446evm_msp_driver = { | ||
504 | .driver.name = "dm6446evm_msp", | ||
505 | .id_table = dm6446evm_msp_ids, | ||
506 | .probe = dm6446evm_msp_probe, | ||
507 | .remove = dm6446evm_msp_remove, | ||
508 | }; | ||
509 | |||
510 | static int dm6444evm_msp430_get_pins(void) | ||
511 | { | ||
512 | static const char txbuf[2] = { 2, 4, }; | ||
513 | char buf[4]; | ||
514 | struct i2c_msg msg[2] = { | ||
515 | { | ||
516 | .addr = dm6446evm_msp->addr, | ||
517 | .flags = 0, | ||
518 | .len = 2, | ||
519 | .buf = (void __force *)txbuf, | ||
520 | }, | ||
521 | { | ||
522 | .addr = dm6446evm_msp->addr, | ||
523 | .flags = I2C_M_RD, | ||
524 | .len = 4, | ||
525 | .buf = buf, | ||
526 | }, | ||
527 | }; | ||
528 | int status; | ||
529 | |||
530 | if (!dm6446evm_msp) | ||
531 | return -ENXIO; | ||
532 | |||
533 | /* Command 4 == get input state, returns port 2 and port3 data | ||
534 | * S Addr W [A] len=2 [A] cmd=4 [A] | ||
535 | * RS Addr R [A] [len=4] A [cmd=4] A [port2] A [port3] N P | ||
536 | */ | ||
537 | status = i2c_transfer(dm6446evm_msp->adapter, msg, 2); | ||
538 | if (status < 0) | ||
539 | return status; | ||
540 | |||
541 | dev_dbg(&dm6446evm_msp->dev, | ||
542 | "PINS: %02x %02x %02x %02x\n", | ||
543 | buf[0], buf[1], buf[2], buf[3]); | ||
544 | |||
545 | return (buf[3] << 8) | buf[2]; | ||
546 | } | ||
547 | |||
548 | static struct i2c_board_info __initdata i2c_info[] = { | ||
549 | { | ||
550 | I2C_BOARD_INFO("dm6446evm_msp", 0x23), | ||
551 | }, | ||
552 | { | ||
553 | I2C_BOARD_INFO("pcf8574", 0x38), | ||
554 | .platform_data = &pcf_data_u2, | ||
555 | }, | ||
556 | { | ||
557 | I2C_BOARD_INFO("pcf8574", 0x39), | ||
558 | .platform_data = &pcf_data_u18, | ||
559 | }, | ||
560 | { | ||
561 | I2C_BOARD_INFO("pcf8574", 0x3a), | ||
562 | .platform_data = &pcf_data_u35, | ||
563 | }, | ||
564 | { | ||
565 | I2C_BOARD_INFO("24c256", 0x50), | ||
566 | .platform_data = &eeprom_info, | ||
567 | }, | ||
568 | /* ALSO: | ||
569 | * - tvl320aic33 audio codec (0x1b) | ||
570 | * - tvp5146 video decoder (0x5d) | ||
571 | */ | ||
572 | }; | ||
573 | |||
574 | /* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz), | ||
575 | * which requires 100 usec of idle bus after i2c writes sent to it. | ||
576 | */ | ||
577 | static struct davinci_i2c_platform_data i2c_pdata = { | ||
578 | .bus_freq = 20 /* kHz */, | ||
579 | .bus_delay = 100 /* usec */, | ||
580 | }; | ||
581 | |||
582 | static void __init evm_init_i2c(void) | ||
583 | { | ||
584 | davinci_init_i2c(&i2c_pdata); | ||
585 | i2c_add_driver(&dm6446evm_msp_driver); | ||
586 | i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); | ||
587 | } | ||
588 | |||
589 | static struct platform_device *davinci_evm_devices[] __initdata = { | ||
590 | &davinci_fb_device, | ||
591 | &rtc_dev, | ||
592 | }; | ||
593 | |||
594 | static struct davinci_uart_config uart_config __initdata = { | ||
595 | .enabled_uarts = (1 << 0), | ||
596 | }; | ||
597 | |||
598 | static void __init | ||
599 | davinci_evm_map_io(void) | ||
600 | { | ||
601 | davinci_map_common_io(); | ||
602 | dm644x_init(); | ||
603 | } | ||
604 | |||
605 | static int davinci_phy_fixup(struct phy_device *phydev) | ||
606 | { | ||
607 | unsigned int control; | ||
608 | /* CRITICAL: Fix for increasing PHY signal drive strength for | ||
609 | * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY | ||
610 | * signal strength was low causing TX to fail randomly. The | ||
611 | * fix is to Set bit 11 (Increased MII drive strength) of PHY | ||
612 | * register 26 (Digital Config register) on this phy. */ | ||
613 | control = phy_read(phydev, 26); | ||
614 | phy_write(phydev, 26, (control | 0x800)); | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ | ||
619 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | ||
620 | #define HAS_ATA 1 | ||
621 | #else | ||
622 | #define HAS_ATA 0 | ||
623 | #endif | ||
624 | |||
625 | #if defined(CONFIG_MTD_PHYSMAP) || \ | ||
626 | defined(CONFIG_MTD_PHYSMAP_MODULE) | ||
627 | #define HAS_NOR 1 | ||
628 | #else | ||
629 | #define HAS_NOR 0 | ||
630 | #endif | ||
631 | |||
632 | #if defined(CONFIG_MTD_NAND_DAVINCI) || \ | ||
633 | defined(CONFIG_MTD_NAND_DAVINCI_MODULE) | ||
634 | #define HAS_NAND 1 | ||
635 | #else | ||
636 | #define HAS_NAND 0 | ||
637 | #endif | ||
638 | |||
639 | static __init void davinci_evm_init(void) | ||
640 | { | ||
641 | struct clk *aemif_clk; | ||
642 | |||
643 | aemif_clk = clk_get(NULL, "aemif"); | ||
644 | clk_enable(aemif_clk); | ||
645 | |||
646 | if (HAS_ATA) { | ||
647 | if (HAS_NAND || HAS_NOR) | ||
648 | pr_warning("WARNING: both IDE and Flash are " | ||
649 | "enabled, but they share AEMIF pins.\n" | ||
650 | "\tDisable IDE for NAND/NOR support.\n"); | ||
651 | davinci_cfg_reg(DM644X_HPIEN_DISABLE); | ||
652 | davinci_cfg_reg(DM644X_ATAEN); | ||
653 | davinci_cfg_reg(DM644X_HDIREN); | ||
654 | platform_device_register(&ide_dev); | ||
655 | } else if (HAS_NAND || HAS_NOR) { | ||
656 | davinci_cfg_reg(DM644X_HPIEN_DISABLE); | ||
657 | davinci_cfg_reg(DM644X_ATAEN_DISABLE); | ||
658 | |||
659 | /* only one device will be jumpered and detected */ | ||
660 | if (HAS_NAND) { | ||
661 | platform_device_register(&davinci_evm_nandflash_device); | ||
662 | evm_leds[7].default_trigger = "nand-disk"; | ||
663 | if (HAS_NOR) | ||
664 | pr_warning("WARNING: both NAND and NOR flash " | ||
665 | "are enabled; disable one of them.\n"); | ||
666 | } else if (HAS_NOR) | ||
667 | platform_device_register(&davinci_evm_norflash_device); | ||
668 | } | ||
669 | |||
670 | platform_add_devices(davinci_evm_devices, | ||
671 | ARRAY_SIZE(davinci_evm_devices)); | ||
672 | evm_init_i2c(); | ||
673 | |||
674 | davinci_serial_init(&uart_config); | ||
675 | |||
676 | /* Register the fixup for PHY on DaVinci */ | ||
677 | phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, | ||
678 | davinci_phy_fixup); | ||
679 | |||
680 | } | ||
681 | |||
682 | static __init void davinci_evm_irq_init(void) | ||
683 | { | ||
684 | davinci_irq_init(); | ||
685 | } | ||
686 | |||
687 | MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM") | ||
688 | /* Maintainer: MontaVista Software <source@mvista.com> */ | ||
689 | .phys_io = IO_PHYS, | ||
690 | .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, | ||
691 | .boot_params = (DAVINCI_DDR_BASE + 0x100), | ||
692 | .map_io = davinci_evm_map_io, | ||
693 | .init_irq = davinci_evm_irq_init, | ||
694 | .timer = &davinci_timer, | ||
695 | .init_machine = davinci_evm_init, | ||
696 | MACHINE_END | ||