diff options
Diffstat (limited to 'arch/arm/mach-omap1/board-h3.c')
-rw-r--r-- | arch/arm/mach-omap1/board-h3.c | 277 |
1 files changed, 264 insertions, 13 deletions
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index d9f386265996..4b8d0ec73cb7 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -21,8 +21,11 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/workqueue.h> | ||
24 | #include <linux/mtd/mtd.h> | 25 | #include <linux/mtd/mtd.h> |
26 | #include <linux/mtd/nand.h> | ||
25 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
28 | #include <linux/input.h> | ||
26 | 29 | ||
27 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
28 | #include <asm/page.h> | 31 | #include <asm/page.h> |
@@ -33,15 +36,59 @@ | |||
33 | #include <asm/mach/map.h> | 36 | #include <asm/mach/map.h> |
34 | 37 | ||
35 | #include <asm/arch/gpio.h> | 38 | #include <asm/arch/gpio.h> |
39 | #include <asm/arch/gpioexpander.h> | ||
36 | #include <asm/arch/irqs.h> | 40 | #include <asm/arch/irqs.h> |
37 | #include <asm/arch/mux.h> | 41 | #include <asm/arch/mux.h> |
38 | #include <asm/arch/tc.h> | 42 | #include <asm/arch/tc.h> |
43 | #include <asm/arch/irda.h> | ||
39 | #include <asm/arch/usb.h> | 44 | #include <asm/arch/usb.h> |
45 | #include <asm/arch/keypad.h> | ||
46 | #include <asm/arch/dma.h> | ||
40 | #include <asm/arch/common.h> | 47 | #include <asm/arch/common.h> |
41 | 48 | ||
42 | extern int omap_gpio_init(void); | 49 | extern int omap_gpio_init(void); |
43 | 50 | ||
44 | static struct mtd_partition h3_partitions[] = { | 51 | static int h3_keymap[] = { |
52 | KEY(0, 0, KEY_LEFT), | ||
53 | KEY(0, 1, KEY_RIGHT), | ||
54 | KEY(0, 2, KEY_3), | ||
55 | KEY(0, 3, KEY_F10), | ||
56 | KEY(0, 4, KEY_F5), | ||
57 | KEY(0, 5, KEY_9), | ||
58 | KEY(1, 0, KEY_DOWN), | ||
59 | KEY(1, 1, KEY_UP), | ||
60 | KEY(1, 2, KEY_2), | ||
61 | KEY(1, 3, KEY_F9), | ||
62 | KEY(1, 4, KEY_F7), | ||
63 | KEY(1, 5, KEY_0), | ||
64 | KEY(2, 0, KEY_ENTER), | ||
65 | KEY(2, 1, KEY_6), | ||
66 | KEY(2, 2, KEY_1), | ||
67 | KEY(2, 3, KEY_F2), | ||
68 | KEY(2, 4, KEY_F6), | ||
69 | KEY(2, 5, KEY_HOME), | ||
70 | KEY(3, 0, KEY_8), | ||
71 | KEY(3, 1, KEY_5), | ||
72 | KEY(3, 2, KEY_F12), | ||
73 | KEY(3, 3, KEY_F3), | ||
74 | KEY(3, 4, KEY_F8), | ||
75 | KEY(3, 5, KEY_END), | ||
76 | KEY(4, 0, KEY_7), | ||
77 | KEY(4, 1, KEY_4), | ||
78 | KEY(4, 2, KEY_F11), | ||
79 | KEY(4, 3, KEY_F1), | ||
80 | KEY(4, 4, KEY_F4), | ||
81 | KEY(4, 5, KEY_ESC), | ||
82 | KEY(5, 0, KEY_F13), | ||
83 | KEY(5, 1, KEY_F14), | ||
84 | KEY(5, 2, KEY_F15), | ||
85 | KEY(5, 3, KEY_F16), | ||
86 | KEY(5, 4, KEY_SLEEP), | ||
87 | 0 | ||
88 | }; | ||
89 | |||
90 | |||
91 | static struct mtd_partition nor_partitions[] = { | ||
45 | /* bootloader (U-Boot, etc) in first sector */ | 92 | /* bootloader (U-Boot, etc) in first sector */ |
46 | { | 93 | { |
47 | .name = "bootloader", | 94 | .name = "bootloader", |
@@ -72,26 +119,80 @@ static struct mtd_partition h3_partitions[] = { | |||
72 | } | 119 | } |
73 | }; | 120 | }; |
74 | 121 | ||
75 | static struct flash_platform_data h3_flash_data = { | 122 | static struct flash_platform_data nor_data = { |
76 | .map_name = "cfi_probe", | 123 | .map_name = "cfi_probe", |
77 | .width = 2, | 124 | .width = 2, |
78 | .parts = h3_partitions, | 125 | .parts = nor_partitions, |
79 | .nr_parts = ARRAY_SIZE(h3_partitions), | 126 | .nr_parts = ARRAY_SIZE(nor_partitions), |
80 | }; | 127 | }; |
81 | 128 | ||
82 | static struct resource h3_flash_resource = { | 129 | static struct resource nor_resource = { |
83 | /* This is on CS3, wherever it's mapped */ | 130 | /* This is on CS3, wherever it's mapped */ |
84 | .flags = IORESOURCE_MEM, | 131 | .flags = IORESOURCE_MEM, |
85 | }; | 132 | }; |
86 | 133 | ||
87 | static struct platform_device flash_device = { | 134 | static struct platform_device nor_device = { |
88 | .name = "omapflash", | 135 | .name = "omapflash", |
89 | .id = 0, | 136 | .id = 0, |
90 | .dev = { | 137 | .dev = { |
91 | .platform_data = &h3_flash_data, | 138 | .platform_data = &nor_data, |
139 | }, | ||
140 | .num_resources = 1, | ||
141 | .resource = &nor_resource, | ||
142 | }; | ||
143 | |||
144 | static struct mtd_partition nand_partitions[] = { | ||
145 | #if 0 | ||
146 | /* REVISIT: enable these partitions if you make NAND BOOT work */ | ||
147 | { | ||
148 | .name = "xloader", | ||
149 | .offset = 0, | ||
150 | .size = 64 * 1024, | ||
151 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
152 | }, | ||
153 | { | ||
154 | .name = "bootloader", | ||
155 | .offset = MTDPART_OFS_APPEND, | ||
156 | .size = 256 * 1024, | ||
157 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
158 | }, | ||
159 | { | ||
160 | .name = "params", | ||
161 | .offset = MTDPART_OFS_APPEND, | ||
162 | .size = 192 * 1024, | ||
163 | }, | ||
164 | { | ||
165 | .name = "kernel", | ||
166 | .offset = MTDPART_OFS_APPEND, | ||
167 | .size = 2 * SZ_1M, | ||
168 | }, | ||
169 | #endif | ||
170 | { | ||
171 | .name = "filesystem", | ||
172 | .size = MTDPART_SIZ_FULL, | ||
173 | .offset = MTDPART_OFS_APPEND, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | /* dip switches control NAND chip access: 8 bit, 16 bit, or neither */ | ||
178 | static struct nand_platform_data nand_data = { | ||
179 | .options = NAND_SAMSUNG_LP_OPTIONS, | ||
180 | .parts = nand_partitions, | ||
181 | .nr_parts = ARRAY_SIZE(nand_partitions), | ||
182 | }; | ||
183 | |||
184 | static struct resource nand_resource = { | ||
185 | .flags = IORESOURCE_MEM, | ||
186 | }; | ||
187 | |||
188 | static struct platform_device nand_device = { | ||
189 | .name = "omapnand", | ||
190 | .id = 0, | ||
191 | .dev = { | ||
192 | .platform_data = &nand_data, | ||
92 | }, | 193 | }, |
93 | .num_resources = 1, | 194 | .num_resources = 1, |
94 | .resource = &h3_flash_resource, | 195 | .resource = &nand_resource, |
95 | }; | 196 | }; |
96 | 197 | ||
97 | static struct resource smc91x_resources[] = { | 198 | static struct resource smc91x_resources[] = { |
@@ -138,10 +239,136 @@ static struct platform_device intlat_device = { | |||
138 | .resource = intlat_resources, | 239 | .resource = intlat_resources, |
139 | }; | 240 | }; |
140 | 241 | ||
242 | static struct resource h3_kp_resources[] = { | ||
243 | [0] = { | ||
244 | .start = INT_KEYBOARD, | ||
245 | .end = INT_KEYBOARD, | ||
246 | .flags = IORESOURCE_IRQ, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | static struct omap_kp_platform_data h3_kp_data = { | ||
251 | .rows = 8, | ||
252 | .cols = 8, | ||
253 | .keymap = h3_keymap, | ||
254 | .rep = 1, | ||
255 | }; | ||
256 | |||
257 | static struct platform_device h3_kp_device = { | ||
258 | .name = "omap-keypad", | ||
259 | .id = -1, | ||
260 | .dev = { | ||
261 | .platform_data = &h3_kp_data, | ||
262 | }, | ||
263 | .num_resources = ARRAY_SIZE(h3_kp_resources), | ||
264 | .resource = h3_kp_resources, | ||
265 | }; | ||
266 | |||
267 | |||
268 | /* Select between the IrDA and aGPS module | ||
269 | */ | ||
270 | static int h3_select_irda(struct device *dev, int state) | ||
271 | { | ||
272 | unsigned char expa; | ||
273 | int err = 0; | ||
274 | |||
275 | if ((err = read_gpio_expa(&expa, 0x26))) { | ||
276 | printk(KERN_ERR "Error reading from I/O EXPANDER \n"); | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | /* 'P6' enable/disable IRDA_TX and IRDA_RX */ | ||
281 | if (state & IR_SEL) { /* IrDA */ | ||
282 | if ((err = write_gpio_expa(expa | 0x40, 0x26))) { | ||
283 | printk(KERN_ERR "Error writing to I/O EXPANDER \n"); | ||
284 | return err; | ||
285 | } | ||
286 | } else { | ||
287 | if ((err = write_gpio_expa(expa & ~0x40, 0x26))) { | ||
288 | printk(KERN_ERR "Error writing to I/O EXPANDER \n"); | ||
289 | return err; | ||
290 | } | ||
291 | } | ||
292 | return err; | ||
293 | } | ||
294 | |||
295 | static void set_trans_mode(void *data) | ||
296 | { | ||
297 | int *mode = data; | ||
298 | unsigned char expa; | ||
299 | int err = 0; | ||
300 | |||
301 | if ((err = read_gpio_expa(&expa, 0x27)) != 0) { | ||
302 | printk(KERN_ERR "Error reading from I/O expander\n"); | ||
303 | } | ||
304 | |||
305 | expa &= ~0x03; | ||
306 | |||
307 | if (*mode & IR_SIRMODE) { | ||
308 | expa |= 0x01; | ||
309 | } else { /* MIR/FIR */ | ||
310 | expa |= 0x03; | ||
311 | } | ||
312 | |||
313 | if ((err = write_gpio_expa(expa, 0x27)) != 0) { | ||
314 | printk(KERN_ERR "Error writing to I/O expander\n"); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static int h3_transceiver_mode(struct device *dev, int mode) | ||
319 | { | ||
320 | struct omap_irda_config *irda_config = dev->platform_data; | ||
321 | |||
322 | cancel_delayed_work(&irda_config->gpio_expa); | ||
323 | PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); | ||
324 | schedule_work(&irda_config->gpio_expa); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static struct omap_irda_config h3_irda_data = { | ||
330 | .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, | ||
331 | .transceiver_mode = h3_transceiver_mode, | ||
332 | .select_irda = h3_select_irda, | ||
333 | .rx_channel = OMAP_DMA_UART3_RX, | ||
334 | .tx_channel = OMAP_DMA_UART3_TX, | ||
335 | .dest_start = UART3_THR, | ||
336 | .src_start = UART3_RHR, | ||
337 | .tx_trigger = 0, | ||
338 | .rx_trigger = 0, | ||
339 | }; | ||
340 | |||
341 | static struct resource h3_irda_resources[] = { | ||
342 | [0] = { | ||
343 | .start = INT_UART3, | ||
344 | .end = INT_UART3, | ||
345 | .flags = IORESOURCE_IRQ, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct platform_device h3_irda_device = { | ||
350 | .name = "omapirda", | ||
351 | .id = 0, | ||
352 | .dev = { | ||
353 | .platform_data = &h3_irda_data, | ||
354 | }, | ||
355 | .num_resources = ARRAY_SIZE(h3_irda_resources), | ||
356 | .resource = h3_irda_resources, | ||
357 | }; | ||
358 | |||
359 | static struct platform_device h3_lcd_device = { | ||
360 | .name = "lcd_h3", | ||
361 | .id = -1, | ||
362 | }; | ||
363 | |||
141 | static struct platform_device *devices[] __initdata = { | 364 | static struct platform_device *devices[] __initdata = { |
142 | &flash_device, | 365 | &nor_device, |
366 | &nand_device, | ||
143 | &smc91x_device, | 367 | &smc91x_device, |
144 | &intlat_device, | 368 | &intlat_device, |
369 | &h3_irda_device, | ||
370 | &h3_kp_device, | ||
371 | &h3_lcd_device, | ||
145 | }; | 372 | }; |
146 | 373 | ||
147 | static struct omap_usb_config h3_usb_config __initdata = { | 374 | static struct omap_usb_config h3_usb_config __initdata = { |
@@ -171,7 +398,6 @@ static struct omap_uart_config h3_uart_config __initdata = { | |||
171 | }; | 398 | }; |
172 | 399 | ||
173 | static struct omap_lcd_config h3_lcd_config __initdata = { | 400 | static struct omap_lcd_config h3_lcd_config __initdata = { |
174 | .panel_name = "h3", | ||
175 | .ctrl_name = "internal", | 401 | .ctrl_name = "internal", |
176 | }; | 402 | }; |
177 | 403 | ||
@@ -182,11 +408,36 @@ static struct omap_board_config_kernel h3_config[] = { | |||
182 | { OMAP_TAG_LCD, &h3_lcd_config }, | 408 | { OMAP_TAG_LCD, &h3_lcd_config }, |
183 | }; | 409 | }; |
184 | 410 | ||
411 | #define H3_NAND_RB_GPIO_PIN 10 | ||
412 | |||
413 | static int nand_dev_ready(struct nand_platform_data *data) | ||
414 | { | ||
415 | return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN); | ||
416 | } | ||
417 | |||
185 | static void __init h3_init(void) | 418 | static void __init h3_init(void) |
186 | { | 419 | { |
187 | h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys(); | 420 | /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped |
188 | h3_flash_resource.end += OMAP_CS3_SIZE - 1; | 421 | * to address 0 by a dip switch), NAND on CS2B. The NAND driver will |
189 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 422 | * notice whether a NAND chip is enabled at probe time. |
423 | * | ||
424 | * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND | ||
425 | * (which on H2 may be 16bit) on CS3. Try detecting that in code here, | ||
426 | * to avoid probing every possible flash configuration... | ||
427 | */ | ||
428 | nor_resource.end = nor_resource.start = omap_cs3_phys(); | ||
429 | nor_resource.end += SZ_32M - 1; | ||
430 | |||
431 | nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS; | ||
432 | nand_resource.end += SZ_4K - 1; | ||
433 | if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN))) | ||
434 | nand_data.dev_ready = nand_dev_ready; | ||
435 | |||
436 | /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */ | ||
437 | /* GPIO10 pullup/down register, Enable pullup on GPIO10 */ | ||
438 | omap_cfg_reg(V2_1710_GPIO10); | ||
439 | |||
440 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
190 | omap_board_config = h3_config; | 441 | omap_board_config = h3_config; |
191 | omap_board_config_size = ARRAY_SIZE(h3_config); | 442 | omap_board_config_size = ARRAY_SIZE(h3_config); |
192 | omap_serial_init(); | 443 | omap_serial_init(); |