Root/
Source at commit fbb88c547b69af5f058a6959d0f33a1398287afe created 11 years 10 months ago. By Maarten ter Huurne, ASoC: JZ4740: Convert a320 to use snd_soc_register_card(). | |
---|---|
1 | /* |
2 | * linux/arch/mips/jz4740/board-a320.c |
3 | * |
4 | * JZ4740 A320 board setup routines. |
5 | * |
6 | * Copyright (c) 2006-2007 Ingenic Semiconductor Inc. |
7 | * Copyright (c) 2009 Ignacio Garcia Perez <iggarpe@gmail.com> |
8 | * Copyright (c) 2010-2011 Maarten ter Huurne <maarten@treewalker.org> |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. |
13 | */ |
14 | |
15 | #include <linux/init.h> |
16 | #include <linux/sched.h> |
17 | #include <linux/ioport.h> |
18 | #include <linux/mm.h> |
19 | #include <linux/console.h> |
20 | #include <linux/delay.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/gpio.h> |
23 | #include <linux/i2c.h> |
24 | #include <linux/i2c-gpio.h> |
25 | #include <linux/power_supply.h> |
26 | #include <linux/power/gpio-charger.h> |
27 | #include <linux/power/jz4740-battery.h> |
28 | |
29 | #include <linux/pwm_backlight.h> |
30 | #include <linux/input.h> |
31 | #include <linux/gpio_keys.h> |
32 | |
33 | #include <media/radio-rda5807.h> |
34 | |
35 | #include <asm/cpu.h> |
36 | #include <asm/bootinfo.h> |
37 | #include <asm/mipsregs.h> |
38 | #include <asm/reboot.h> |
39 | |
40 | #include <asm/mach-jz4740/gpio.h> |
41 | #include <asm/mach-jz4740/jz4740_fb.h> |
42 | #include <asm/mach-jz4740/jz4740_mmc.h> |
43 | #include <asm/mach-jz4740/jz4740_nand.h> |
44 | #include <asm/mach-jz4740/platform.h> |
45 | |
46 | #include "clock.h" |
47 | |
48 | /* |
49 | * This is called by the panic reboot delay loop if panic=<n> parameter |
50 | * is passed to the kernel. The A320 does not have any LEDs, so the best |
51 | * we can do is to blink the LCD backlight. |
52 | * |
53 | * TODO(MtH): This should use the backlight driver instead of directly |
54 | * manipulating the GPIO pin. |
55 | */ |
56 | static long a320_panic_blink_callback(int time) |
57 | { |
58 | gpio_direction_output(JZ_GPIO_PORTD(31), (time / 500) & 1); |
59 | return 0; |
60 | } |
61 | |
62 | #ifdef CONFIG_I2C_GPIO |
63 | /* I2C over GPIO pins */ |
64 | static struct i2c_gpio_platform_data a320_i2c_pdata = { |
65 | .sda_pin = JZ_GPIO_PORTD(23), |
66 | .scl_pin = JZ_GPIO_PORTD(24), |
67 | .udelay = 2, |
68 | .timeout = 3 * HZ, |
69 | }; |
70 | |
71 | static struct platform_device a320_i2c_device = { |
72 | .name = "i2c-gpio", |
73 | .id = -1, |
74 | .dev = { |
75 | .platform_data = &a320_i2c_pdata, |
76 | }, |
77 | }; |
78 | #endif |
79 | |
80 | /* NAND */ |
81 | #define A320_NAND_PAGE_SIZE (4096ull) |
82 | #define A320_NAND_ERASE_BLOCK_SIZE (128 * A320_NAND_PAGE_SIZE) |
83 | |
84 | static struct mtd_partition a320_nand_partitions[] = { |
85 | { .name = "SPL", |
86 | .offset = 0 * A320_NAND_ERASE_BLOCK_SIZE, |
87 | .size = 1 * A320_NAND_ERASE_BLOCK_SIZE, |
88 | /* MtH: Read-only until we can trust it. */ |
89 | .mask_flags = MTD_WRITEABLE, |
90 | }, |
91 | { .name = "uC/OS-II loader", |
92 | .offset = 1 * A320_NAND_ERASE_BLOCK_SIZE, |
93 | .size = 2 * A320_NAND_ERASE_BLOCK_SIZE, |
94 | /* MtH: Read-only until we can trust it. */ |
95 | .mask_flags = MTD_WRITEABLE, |
96 | }, |
97 | /* erase block 3 is empty (maybe alternative location for bbt?) */ |
98 | /* erase block 4 contains the bad block table */ |
99 | { .name = "uC/OS-II Z:", |
100 | .offset = 5 * A320_NAND_ERASE_BLOCK_SIZE, |
101 | .size = 127 * A320_NAND_ERASE_BLOCK_SIZE, |
102 | /* MtH: Read-only until we can trust it. */ |
103 | .mask_flags = MTD_WRITEABLE, |
104 | }, |
105 | { .name = "uC/OS-II A:", |
106 | .offset = 132 * A320_NAND_ERASE_BLOCK_SIZE, |
107 | .size = (8192 - 132) * A320_NAND_ERASE_BLOCK_SIZE, |
108 | /* MtH: Read-only until we can trust it. */ |
109 | .mask_flags = MTD_WRITEABLE, |
110 | }, |
111 | }; |
112 | |
113 | static uint8_t a320_nand_bbt_pattern[] = {'b', 'b', 't', '8' }; |
114 | |
115 | static struct nand_bbt_descr a320_nand_bbt_main_descr = { |
116 | .options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT, |
117 | /* TODO(MtH): Maybe useful flags for the future: |
118 | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_VERSION | NAND_BBT_PERCHIP |
119 | */ |
120 | .pages = { 4 * A320_NAND_ERASE_BLOCK_SIZE / A320_NAND_PAGE_SIZE }, |
121 | .maxblocks = 1, |
122 | .pattern = a320_nand_bbt_pattern, |
123 | .len = ARRAY_SIZE(a320_nand_bbt_pattern), |
124 | .offs = 128 - ARRAY_SIZE(a320_nand_bbt_pattern), |
125 | }; |
126 | |
127 | static struct nand_ecclayout a320_nand_ecc_layout = { |
128 | .eccbytes = 72, |
129 | .eccpos = { |
130 | 4, 5, 6, 7, 8, 9, 10, 11, 12, /* sector 0 */ |
131 | 16, 17, 18, 19, 20, 21, 22, 23, 24, /* sector 1 */ |
132 | 28, 29, 30, 31, 32, 33, 34, 35, 36, /* sector 2 */ |
133 | 40, 41, 42, 43, 44, 45, 46, 47, 48, /* sector 3 */ |
134 | 52, 53, 54, 55, 56, 57, 58, 59, 60, /* sector 4 */ |
135 | 64, 65, 66, 67, 68, 69, 70, 71, 72, /* sector 5 */ |
136 | 76, 77, 78, 79, 80, 81, 82, 83, 84, /* sector 6 */ |
137 | 88, 89, 90, 91, 92, 93, 94, 95, 96, /* sector 7 */ |
138 | }, |
139 | .oobfree = { |
140 | { .offset = 100, .length = 22 }, |
141 | } |
142 | }; |
143 | |
144 | static void a320_nand_ident(struct platform_device *pdev, |
145 | struct nand_chip *chip, |
146 | struct mtd_partition **partitions, |
147 | int *num_partitions) |
148 | { |
149 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
150 | chip->bbt_td = &a320_nand_bbt_main_descr; |
151 | /* MtH: I did not find a mirror bbt yet, but it might exist. */ |
152 | chip->bbt_md = NULL; |
153 | } |
154 | |
155 | static struct jz_nand_platform_data a320_nand_pdata = { |
156 | .num_partitions = ARRAY_SIZE(a320_nand_partitions), |
157 | .partitions = a320_nand_partitions, |
158 | .ecc_layout = &a320_nand_ecc_layout, |
159 | .busy_gpio = JZ_GPIO_PORTC(30), |
160 | .banks = { 1, 2, 3, 4 }, |
161 | .ident_callback = a320_nand_ident, |
162 | }; |
163 | |
164 | /* Display */ |
165 | static struct fb_videomode a320_video_modes[] = { |
166 | { |
167 | .name = "320x240", |
168 | .xres = 320, |
169 | .yres = 240, |
170 | // TODO(MtH): Set refresh or pixclock. |
171 | .vmode = FB_VMODE_NONINTERLACED, |
172 | }, |
173 | }; |
174 | |
175 | static struct jz4740_fb_platform_data a320_fb_pdata = { |
176 | .width = 60, |
177 | .height = 45, |
178 | .num_modes = ARRAY_SIZE(a320_video_modes), |
179 | .modes = a320_video_modes, |
180 | .bpp = 16, |
181 | .lcd_type = JZ_LCD_TYPE_SMART_PARALLEL_16_BIT, |
182 | .pixclk_falling_edge = 0, |
183 | .chip_select_active_low = 1, |
184 | .register_select_active_low = 1, |
185 | }; |
186 | |
187 | static int a320_backlight_notify(struct device *dev, int brightness) |
188 | { |
189 | if (!gpio_get_value(JZ_GPIO_PORTB(18))) { |
190 | /* RESET_N pin of the ILI chip is pulled down, |
191 | so force backlight off. */ |
192 | return 0; |
193 | } |
194 | |
195 | return brightness; |
196 | } |
197 | |
198 | static struct platform_pwm_backlight_data a320_backlight_pdata = { |
199 | .pwm_id = 7, |
200 | .max_brightness = 255, |
201 | .dft_brightness = 145, |
202 | .pwm_period_ns = 1000000, |
203 | .notify = a320_backlight_notify, |
204 | }; |
205 | |
206 | static struct platform_device a320_backlight_device = { |
207 | .name = "pwm-backlight", |
208 | .id = -1, |
209 | .dev = { |
210 | .platform_data = &a320_backlight_pdata, |
211 | }, |
212 | }; |
213 | |
214 | static struct jz4740_mmc_platform_data a320_mmc_pdata = { |
215 | .gpio_card_detect = JZ_GPIO_PORTB(29), |
216 | .gpio_read_only = -1, |
217 | .gpio_power = -1, |
218 | // TODO(MtH): I don't know which GPIO pin the SD power is connected to. |
219 | // Booboo left power alone, but I don't know why. |
220 | //.gpio_power = GPIO_SD_VCC_EN_N, |
221 | //.power_active_low = 1, |
222 | }; |
223 | |
224 | /* Battery */ |
225 | static struct jz_battery_platform_data a320_battery_pdata = { |
226 | // TODO(MtH): Sometimes while charging, the GPIO pin quickly flips between |
227 | // 0 and 1. This causes a very high CPU load because the kernel |
228 | // will invoke a hotplug event handler process on every status |
229 | // change. Until it is clear how to avoid or handle that, it |
230 | // is better not to use the charge status. |
231 | //.gpio_charge = JZ_GPIO_PORTB(30), |
232 | .gpio_charge = -1, |
233 | .gpio_charge_active_low = 1, |
234 | .info = { |
235 | .name = "battery", |
236 | .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, |
237 | .voltage_max_design = 4150000, |
238 | .voltage_min_design = 3450000, |
239 | }, |
240 | }; |
241 | |
242 | static char *a320_batteries[] = { |
243 | "battery", |
244 | }; |
245 | |
246 | static struct gpio_charger_platform_data a320_charger_pdata = { |
247 | .name = "usb", |
248 | .type = POWER_SUPPLY_TYPE_USB, |
249 | .gpio = JZ_GPIO_PORTD(28), |
250 | .gpio_active_low = 0, |
251 | .supplied_to = a320_batteries, |
252 | .num_supplicants = ARRAY_SIZE(a320_batteries), |
253 | }; |
254 | |
255 | static struct platform_device a320_charger_device = { |
256 | .name = "gpio-charger", |
257 | .dev = { |
258 | .platform_data = &a320_charger_pdata, |
259 | }, |
260 | }; |
261 | |
262 | /* Note that the microswitch buttons need debounce while the rubber buttons |
263 | * do not need it. |
264 | */ |
265 | static struct gpio_keys_button a320_buttons[] = { |
266 | /* D-pad up */ { |
267 | .gpio = JZ_GPIO_PORTD(6), |
268 | .active_low = 1, |
269 | .code = KEY_UP, |
270 | }, |
271 | /* D-pad down */ { |
272 | .gpio = JZ_GPIO_PORTD(27), |
273 | .active_low = 1, |
274 | .code = KEY_DOWN, |
275 | }, |
276 | /* D-pad left */ { |
277 | .gpio = JZ_GPIO_PORTD(5), |
278 | .active_low = 1, |
279 | .code = KEY_LEFT, |
280 | }, |
281 | /* D-pad right */ { |
282 | .gpio = JZ_GPIO_PORTD(18), |
283 | .active_low = 1, |
284 | .code = KEY_RIGHT, |
285 | }, |
286 | /* A button */ { |
287 | .gpio = JZ_GPIO_PORTD(0), |
288 | .active_low = 1, |
289 | .code = KEY_LEFTCTRL, |
290 | }, |
291 | /* B button */ { |
292 | .gpio = JZ_GPIO_PORTD(1), |
293 | .active_low = 1, |
294 | .code = KEY_LEFTALT, |
295 | }, |
296 | /* X button */ { |
297 | .gpio = JZ_GPIO_PORTD(19), |
298 | .active_low = 1, |
299 | .code = KEY_SPACE, |
300 | }, |
301 | /* Y button */ { |
302 | .gpio = JZ_GPIO_PORTD(2), |
303 | .active_low = 1, |
304 | .code = KEY_LEFTSHIFT, |
305 | }, |
306 | /* Left shoulder button */ { |
307 | .gpio = JZ_GPIO_PORTD(14), |
308 | .active_low = 1, |
309 | .code = KEY_TAB, |
310 | .debounce_interval = 5, |
311 | }, |
312 | /* Right shoulder button */ { |
313 | .gpio = JZ_GPIO_PORTD(15), |
314 | .active_low = 1, |
315 | .code = KEY_BACKSPACE, |
316 | .debounce_interval = 5, |
317 | }, |
318 | /* START button */ { |
319 | .gpio = JZ_GPIO_PORTC(17), |
320 | .active_low = 1, |
321 | .code = KEY_ENTER, |
322 | .debounce_interval = 5, |
323 | }, |
324 | /* SELECT button */ { |
325 | .gpio = JZ_GPIO_PORTD(17), |
326 | .active_low = 1, |
327 | .code = KEY_ESC, |
328 | .debounce_interval = 5, |
329 | }, |
330 | /* POWER slider */ { |
331 | .gpio = JZ_GPIO_PORTD(29), |
332 | .active_low = 1, |
333 | .code = KEY_POWER, |
334 | .wakeup = 1, |
335 | }, |
336 | /* POWER hold */ { |
337 | .gpio = JZ_GPIO_PORTD(22), |
338 | .active_low = 1, |
339 | .code = KEY_PAUSE, |
340 | }, |
341 | }; |
342 | |
343 | static struct gpio_keys_platform_data a320_gpio_keys_pdata = { |
344 | .buttons = a320_buttons, |
345 | .nbuttons = ARRAY_SIZE(a320_buttons), |
346 | .rep = 1, |
347 | }; |
348 | |
349 | static struct platform_device a320_gpio_keys_device = { |
350 | .name = "gpio-keys", |
351 | .id = -1, |
352 | .dev = { |
353 | .platform_data = &a320_gpio_keys_pdata, |
354 | }, |
355 | }; |
356 | |
357 | /* Audio */ |
358 | static struct platform_device a320_audio_device = { |
359 | .name = "a320-audio", |
360 | .id = -1, |
361 | }; |
362 | |
363 | static struct platform_device *jz_platform_devices[] __initdata = { |
364 | #ifdef CONFIG_I2C_JZ47XX |
365 | &jz4740_i2c_device, |
366 | #endif |
367 | #ifdef CONFIG_I2C_GPIO |
368 | &a320_i2c_device, |
369 | #endif |
370 | /* USB host is not usable since the PCB does not route the pins to |
371 | * a place where new wires can be soldered. */ |
372 | /*&jz4740_usb_ohci_device,*/ |
373 | &jz4740_udc_device, |
374 | &jz4740_mmc_device, |
375 | &jz4740_nand_device, |
376 | &jz4740_framebuffer_device, |
377 | &jz4740_pcm_device, |
378 | &jz4740_i2s_device, |
379 | &jz4740_codec_device, |
380 | &jz4740_rtc_device, |
381 | &jz4740_adc_device, |
382 | &jz4740_wdt_device, |
383 | &a320_charger_device, |
384 | &a320_backlight_device, |
385 | &a320_gpio_keys_device, |
386 | &a320_audio_device, |
387 | }; |
388 | |
389 | static void __init board_gpio_setup(void) |
390 | { |
391 | /* We only need to enable/disable pullup here for pins used in generic |
392 | * drivers. Everything else is done by the drivers themselves. */ |
393 | |
394 | /* Disable pullup of the USB detection pin: on the A320 pullup or not |
395 | * seems to make no difference, but on A330 the signal will be unstable |
396 | * when the pullup is enabled. */ |
397 | jz_gpio_disable_pullup(JZ_GPIO_PORTD(28)); |
398 | } |
399 | |
400 | static int __init a320_init_platform_devices(void) |
401 | { |
402 | jz4740_framebuffer_device.dev.platform_data = &a320_fb_pdata; |
403 | jz4740_nand_device.dev.platform_data = &a320_nand_pdata; |
404 | jz4740_adc_device.dev.platform_data = &a320_battery_pdata; |
405 | jz4740_mmc_device.dev.platform_data = &a320_mmc_pdata; |
406 | |
407 | jz4740_serial_device_register(); |
408 | |
409 | return platform_add_devices(jz_platform_devices, |
410 | ARRAY_SIZE(jz_platform_devices)); |
411 | } |
412 | |
413 | struct jz4740_clock_board_data jz4740_clock_bdata = { |
414 | .ext_rate = 12000000, |
415 | .rtc_rate = 32768, |
416 | }; |
417 | |
418 | static struct rda5807_platform_data a320_rda5807_pdata = { |
419 | .input_flags = RDA5807_INPUT_LNA_WC_25 | RDA5807_LNA_PORT_P, |
420 | .output_flags = RDA5807_OUTPUT_AUDIO_ANALOG, |
421 | }; |
422 | |
423 | static struct i2c_board_info a320_i2c_info[] __initdata = { |
424 | { |
425 | .type = "radio-rda5807", |
426 | .addr = RDA5807_I2C_ADDR, |
427 | .platform_data = &a320_rda5807_pdata, |
428 | } |
429 | }; |
430 | |
431 | static int __init a320_board_setup(void) |
432 | { |
433 | printk(KERN_INFO "JZ4740 A320 board setup\n"); |
434 | |
435 | panic_blink = a320_panic_blink_callback; |
436 | |
437 | board_gpio_setup(); |
438 | |
439 | if (a320_init_platform_devices()) |
440 | panic("Failed to initalize platform devices\n"); |
441 | |
442 | i2c_register_board_info(0, a320_i2c_info, ARRAY_SIZE(a320_i2c_info)); |
443 | |
444 | return 0; |
445 | } |
446 | |
447 | arch_initcall(a320_board_setup); |
448 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9