Merge tag 'mfd-3.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd...
[deliverable/linux.git] / arch / mips / jz4740 / board-qi_lb60.c
CommitLineData
e6b78c4f
LPC
1/*
2 * linux/arch/mips/jz4740/board-qi_lb60.c
3 *
4 * QI_LB60 board support
5 *
6 * Copyright (c) 2009 Qi Hardware inc.,
7 * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
fe749aab 8 * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>
e6b78c4f
LPC
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 or later
12 * as published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/gpio.h>
18
19#include <linux/input.h>
20#include <linux/gpio_keys.h>
21#include <linux/input/matrix_keypad.h>
22#include <linux/spi/spi.h>
23#include <linux/spi/spi_gpio.h>
24#include <linux/power_supply.h>
25#include <linux/power/jz4740-battery.h>
0b4cf181 26#include <linux/power/gpio-charger.h>
e6b78c4f
LPC
27
28#include <asm/mach-jz4740/jz4740_fb.h>
29#include <asm/mach-jz4740/jz4740_mmc.h>
30#include <asm/mach-jz4740/jz4740_nand.h>
31
32#include <linux/regulator/fixed.h>
33#include <linux/regulator/machine.h>
34
35#include <linux/leds_pwm.h>
36
37#include <asm/mach-jz4740/platform.h>
38
39#include "clock.h"
40
41static bool is_avt2;
42
43/* GPIOs */
44#define QI_LB60_GPIO_SD_CD JZ_GPIO_PORTD(0)
45#define QI_LB60_GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(2)
46
47#define QI_LB60_GPIO_KEYOUT(x) (JZ_GPIO_PORTC(10) + (x))
48#define QI_LB60_GPIO_KEYIN(x) (JZ_GPIO_PORTD(18) + (x))
49#define QI_LB60_GPIO_KEYIN8 JZ_GPIO_PORTD(26)
50
51/* NAND */
52static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
c8fb4022 53 .eccbytes = 36,
e6b78c4f 54 .eccpos = {
70342287 55 6, 7, 8, 9, 10, 11, 12, 13,
e6b78c4f
LPC
56 14, 15, 16, 17, 18, 19, 20, 21,
57 22, 23, 24, 25, 26, 27, 28, 29,
58 30, 31, 32, 33, 34, 35, 36, 37,
59 38, 39, 40, 41
c8fb4022 60 },
e6b78c4f
LPC
61 .oobfree = {
62 { .offset = 2, .length = 4 },
63 { .offset = 42, .length = 22 }
64 },
65};
66
67/* Early prototypes of the QI LB60 had only 1GB of NAND.
25985edc 68 * In order to support these devices as well the partition and ecc layout is
b595076a 69 * initialized depending on the NAND size */
e6b78c4f
LPC
70static struct mtd_partition qi_lb60_partitions_1gb[] = {
71 {
72 .name = "NAND BOOT partition",
73 .offset = 0 * 0x100000,
74 .size = 4 * 0x100000,
75 },
76 {
77 .name = "NAND KERNEL partition",
78 .offset = 4 * 0x100000,
79 .size = 4 * 0x100000,
80 },
81 {
82 .name = "NAND ROOTFS partition",
83 .offset = 8 * 0x100000,
84 .size = (504 + 512) * 0x100000,
85 },
86};
87
88static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
c8fb4022 89 .eccbytes = 72,
e6b78c4f
LPC
90 .eccpos = {
91 12, 13, 14, 15, 16, 17, 18, 19,
92 20, 21, 22, 23, 24, 25, 26, 27,
93 28, 29, 30, 31, 32, 33, 34, 35,
94 36, 37, 38, 39, 40, 41, 42, 43,
95 44, 45, 46, 47, 48, 49, 50, 51,
96 52, 53, 54, 55, 56, 57, 58, 59,
97 60, 61, 62, 63, 64, 65, 66, 67,
98 68, 69, 70, 71, 72, 73, 74, 75,
99 76, 77, 78, 79, 80, 81, 82, 83
c8fb4022 100 },
e6b78c4f
LPC
101 .oobfree = {
102 { .offset = 2, .length = 10 },
103 { .offset = 84, .length = 44 },
104 },
105};
106
107static struct mtd_partition qi_lb60_partitions_2gb[] = {
108 {
109 .name = "NAND BOOT partition",
110 .offset = 0 * 0x100000,
111 .size = 4 * 0x100000,
112 },
113 {
114 .name = "NAND KERNEL partition",
115 .offset = 4 * 0x100000,
116 .size = 4 * 0x100000,
117 },
118 {
119 .name = "NAND ROOTFS partition",
120 .offset = 8 * 0x100000,
121 .size = (504 + 512 + 1024) * 0x100000,
122 },
123};
124
125static void qi_lb60_nand_ident(struct platform_device *pdev,
126 struct nand_chip *chip, struct mtd_partition **partitions,
127 int *num_partitions)
128{
129 if (chip->page_shift == 12) {
130 chip->ecc.layout = &qi_lb60_ecclayout_2gb;
131 *partitions = qi_lb60_partitions_2gb;
132 *num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb);
133 } else {
134 chip->ecc.layout = &qi_lb60_ecclayout_1gb;
135 *partitions = qi_lb60_partitions_1gb;
136 *num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb);
137 }
138}
139
140static struct jz_nand_platform_data qi_lb60_nand_pdata = {
141 .ident_callback = qi_lb60_nand_ident,
142 .busy_gpio = 94,
56635d79 143 .banks = { 1 },
e6b78c4f
LPC
144};
145
146/* Keyboard*/
147
148#define KEY_QI_QI KEY_F13
149#define KEY_QI_UPRED KEY_RIGHTALT
150#define KEY_QI_VOLUP KEY_VOLUMEUP
151#define KEY_QI_VOLDOWN KEY_VOLUMEDOWN
152#define KEY_QI_FN KEY_LEFTCTRL
153
154static const uint32_t qi_lb60_keymap[] = {
155 KEY(0, 0, KEY_F1), /* S2 */
156 KEY(0, 1, KEY_F2), /* S3 */
157 KEY(0, 2, KEY_F3), /* S4 */
158 KEY(0, 3, KEY_F4), /* S5 */
159 KEY(0, 4, KEY_F5), /* S6 */
160 KEY(0, 5, KEY_F6), /* S7 */
161 KEY(0, 6, KEY_F7), /* S8 */
162
163 KEY(1, 0, KEY_Q), /* S10 */
164 KEY(1, 1, KEY_W), /* S11 */
165 KEY(1, 2, KEY_E), /* S12 */
166 KEY(1, 3, KEY_R), /* S13 */
167 KEY(1, 4, KEY_T), /* S14 */
168 KEY(1, 5, KEY_Y), /* S15 */
169 KEY(1, 6, KEY_U), /* S16 */
170 KEY(1, 7, KEY_I), /* S17 */
171 KEY(2, 0, KEY_A), /* S18 */
172 KEY(2, 1, KEY_S), /* S19 */
173 KEY(2, 2, KEY_D), /* S20 */
174 KEY(2, 3, KEY_F), /* S21 */
175 KEY(2, 4, KEY_G), /* S22 */
176 KEY(2, 5, KEY_H), /* S23 */
177 KEY(2, 6, KEY_J), /* S24 */
178 KEY(2, 7, KEY_K), /* S25 */
179 KEY(3, 0, KEY_ESC), /* S26 */
180 KEY(3, 1, KEY_Z), /* S27 */
181 KEY(3, 2, KEY_X), /* S28 */
182 KEY(3, 3, KEY_C), /* S29 */
183 KEY(3, 4, KEY_V), /* S30 */
184 KEY(3, 5, KEY_B), /* S31 */
185 KEY(3, 6, KEY_N), /* S32 */
186 KEY(3, 7, KEY_M), /* S33 */
187 KEY(4, 0, KEY_TAB), /* S34 */
188 KEY(4, 1, KEY_CAPSLOCK), /* S35 */
189 KEY(4, 2, KEY_BACKSLASH), /* S36 */
190 KEY(4, 3, KEY_APOSTROPHE), /* S37 */
191 KEY(4, 4, KEY_COMMA), /* S38 */
192 KEY(4, 5, KEY_DOT), /* S39 */
193 KEY(4, 6, KEY_SLASH), /* S40 */
194 KEY(4, 7, KEY_UP), /* S41 */
195 KEY(5, 0, KEY_O), /* S42 */
196 KEY(5, 1, KEY_L), /* S43 */
197 KEY(5, 2, KEY_EQUAL), /* S44 */
198 KEY(5, 3, KEY_QI_UPRED), /* S45 */
199 KEY(5, 4, KEY_SPACE), /* S46 */
200 KEY(5, 5, KEY_QI_QI), /* S47 */
201 KEY(5, 6, KEY_RIGHTCTRL), /* S48 */
202 KEY(5, 7, KEY_LEFT), /* S49 */
203 KEY(6, 0, KEY_F8), /* S50 */
204 KEY(6, 1, KEY_P), /* S51 */
205 KEY(6, 2, KEY_BACKSPACE),/* S52 */
206 KEY(6, 3, KEY_ENTER), /* S53 */
207 KEY(6, 4, KEY_QI_VOLUP), /* S54 */
208 KEY(6, 5, KEY_QI_VOLDOWN), /* S55 */
209 KEY(6, 6, KEY_DOWN), /* S56 */
210 KEY(6, 7, KEY_RIGHT), /* S57 */
211
212 KEY(7, 0, KEY_LEFTSHIFT), /* S58 */
70342287 213 KEY(7, 1, KEY_LEFTALT), /* S59 */
e6b78c4f
LPC
214 KEY(7, 2, KEY_QI_FN), /* S60 */
215};
216
217static const struct matrix_keymap_data qi_lb60_keymap_data = {
218 .keymap = qi_lb60_keymap,
219 .keymap_size = ARRAY_SIZE(qi_lb60_keymap),
220};
221
222static const unsigned int qi_lb60_keypad_cols[] = {
223 QI_LB60_GPIO_KEYOUT(0),
224 QI_LB60_GPIO_KEYOUT(1),
225 QI_LB60_GPIO_KEYOUT(2),
226 QI_LB60_GPIO_KEYOUT(3),
227 QI_LB60_GPIO_KEYOUT(4),
228 QI_LB60_GPIO_KEYOUT(5),
229 QI_LB60_GPIO_KEYOUT(6),
230 QI_LB60_GPIO_KEYOUT(7),
231};
232
233static const unsigned int qi_lb60_keypad_rows[] = {
234 QI_LB60_GPIO_KEYIN(0),
235 QI_LB60_GPIO_KEYIN(1),
236 QI_LB60_GPIO_KEYIN(2),
237 QI_LB60_GPIO_KEYIN(3),
238 QI_LB60_GPIO_KEYIN(4),
239 QI_LB60_GPIO_KEYIN(5),
fe749aab 240 QI_LB60_GPIO_KEYIN(6),
e6b78c4f
LPC
241 QI_LB60_GPIO_KEYIN8,
242};
243
244static struct matrix_keypad_platform_data qi_lb60_pdata = {
245 .keymap_data = &qi_lb60_keymap_data,
246 .col_gpios = qi_lb60_keypad_cols,
247 .row_gpios = qi_lb60_keypad_rows,
248 .num_col_gpios = ARRAY_SIZE(qi_lb60_keypad_cols),
249 .num_row_gpios = ARRAY_SIZE(qi_lb60_keypad_rows),
250 .col_scan_delay_us = 10,
251 .debounce_ms = 10,
252 .wakeup = 1,
253 .active_low = 1,
254};
255
256static struct platform_device qi_lb60_keypad = {
257 .name = "matrix-keypad",
258 .id = -1,
259 .dev = {
260 .platform_data = &qi_lb60_pdata,
261 },
262};
263
264/* Display */
265static struct fb_videomode qi_lb60_video_modes[] = {
266 {
267 .name = "320x240",
268 .xres = 320,
269 .yres = 240,
270 .refresh = 30,
271 .left_margin = 140,
272 .right_margin = 273,
273 .upper_margin = 20,
274 .lower_margin = 2,
275 .hsync_len = 1,
276 .vsync_len = 1,
277 .sync = 0,
278 .vmode = FB_VMODE_NONINTERLACED,
279 },
280};
281
282static struct jz4740_fb_platform_data qi_lb60_fb_pdata = {
283 .width = 60,
284 .height = 45,
285 .num_modes = ARRAY_SIZE(qi_lb60_video_modes),
286 .modes = qi_lb60_video_modes,
287 .bpp = 24,
288 .lcd_type = JZ_LCD_TYPE_8BIT_SERIAL,
289 .pixclk_falling_edge = 1,
290};
291
292struct spi_gpio_platform_data spigpio_platform_data = {
293 .sck = JZ_GPIO_PORTC(23),
294 .mosi = JZ_GPIO_PORTC(22),
295 .miso = -1,
296 .num_chipselect = 1,
297};
298
299static struct platform_device spigpio_device = {
300 .name = "spi_gpio",
301 .id = 1,
302 .dev = {
303 .platform_data = &spigpio_platform_data,
304 },
305};
306
307static struct spi_board_info qi_lb60_spi_board_info[] = {
308 {
309 .modalias = "ili8960",
310 .controller_data = (void *)JZ_GPIO_PORTC(21),
311 .chip_select = 0,
312 .bus_num = 1,
313 .max_speed_hz = 30 * 1000,
314 .mode = SPI_3WIRE,
315 },
316};
317
318/* Battery */
319static struct jz_battery_platform_data qi_lb60_battery_pdata = {
70342287 320 .gpio_charge = JZ_GPIO_PORTC(27),
e6b78c4f
LPC
321 .gpio_charge_active_low = 1,
322 .info = {
323 .name = "battery",
324 .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
325 .voltage_max_design = 4200000,
326 .voltage_min_design = 3600000,
327 },
328};
329
330/* GPIO Key: power */
331static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = {
332 [0] = {
333 .code = KEY_POWER,
334 .gpio = JZ_GPIO_PORTD(29),
335 .active_low = 1,
336 .desc = "Power",
337 .wakeup = 1,
338 },
339};
340
341static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = {
342 .nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons),
343 .buttons = qi_lb60_gpio_keys_buttons,
344};
345
346static struct platform_device qi_lb60_gpio_keys = {
70342287 347 .name = "gpio-keys",
e6b78c4f
LPC
348 .id = -1,
349 .dev = {
350 .platform_data = &qi_lb60_gpio_keys_data,
351 }
352};
353
354static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = {
355 .gpio_card_detect = QI_LB60_GPIO_SD_CD,
356 .gpio_read_only = -1,
357 .gpio_power = QI_LB60_GPIO_SD_VCC_EN_N,
358 .power_active_low = 1,
359};
360
361/* OHCI */
362static struct regulator_consumer_supply avt2_usb_regulator_consumer =
363 REGULATOR_SUPPLY("vbus", "jz4740-ohci");
364
365static struct regulator_init_data avt2_usb_regulator_init_data = {
366 .num_consumer_supplies = 1,
367 .consumer_supplies = &avt2_usb_regulator_consumer,
368 .constraints = {
369 .name = "USB power",
370 .min_uV = 5000000,
371 .max_uV = 5000000,
372 .valid_modes_mask = REGULATOR_MODE_NORMAL,
373 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
374 },
375};
376
377static struct fixed_voltage_config avt2_usb_regulator_data = {
378 .supply_name = "USB power",
379 .microvolts = 5000000,
380 .gpio = JZ_GPIO_PORTB(17),
381 .init_data = &avt2_usb_regulator_init_data,
382};
383
384static struct platform_device avt2_usb_regulator_device = {
385 .name = "reg-fixed-voltage",
386 .id = -1,
387 .dev = {
388 .platform_data = &avt2_usb_regulator_data,
389 }
390};
391
392/* beeper */
393static struct platform_device qi_lb60_pwm_beeper = {
394 .name = "pwm-beeper",
395 .id = -1,
396 .dev = {
397 .platform_data = (void *)4,
398 },
399};
400
0b4cf181
LPC
401/* charger */
402static char *qi_lb60_batteries[] = {
403 "battery",
404};
405
406static struct gpio_charger_platform_data qi_lb60_charger_pdata = {
407 .name = "usb",
408 .type = POWER_SUPPLY_TYPE_USB,
409 .gpio = JZ_GPIO_PORTD(28),
410 .gpio_active_low = 1,
411 .supplied_to = qi_lb60_batteries,
412 .num_supplicants = ARRAY_SIZE(qi_lb60_batteries),
413};
414
415static struct platform_device qi_lb60_charger_device = {
416 .name = "gpio-charger",
417 .dev = {
418 .platform_data = &qi_lb60_charger_pdata,
419 },
420};
421
b33005f3
AL
422/* audio */
423static struct platform_device qi_lb60_audio_device = {
424 .name = "qi-lb60-audio",
425 .id = -1,
426};
0b4cf181 427
e6b78c4f
LPC
428static struct platform_device *jz_platform_devices[] __initdata = {
429 &jz4740_udc_device,
430 &jz4740_mmc_device,
431 &jz4740_nand_device,
432 &qi_lb60_keypad,
433 &spigpio_device,
434 &jz4740_framebuffer_device,
435 &jz4740_pcm_device,
436 &jz4740_i2s_device,
437 &jz4740_codec_device,
438 &jz4740_rtc_device,
439 &jz4740_adc_device,
f6b8a570 440 &jz4740_pwm_device,
cdcb90ad 441 &jz4740_dma_device,
e6b78c4f
LPC
442 &qi_lb60_gpio_keys,
443 &qi_lb60_pwm_beeper,
0b4cf181 444 &qi_lb60_charger_device,
b33005f3 445 &qi_lb60_audio_device,
e6b78c4f
LPC
446};
447
448static void __init board_gpio_setup(void)
449{
450 /* We only need to enable/disable pullup here for pins used in generic
25985edc 451 * drivers. Everything else is done by the drivers themselves. */
e6b78c4f
LPC
452 jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
453 jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
454}
455
456static int __init qi_lb60_init_platform_devices(void)
457{
458 jz4740_framebuffer_device.dev.platform_data = &qi_lb60_fb_pdata;
459 jz4740_nand_device.dev.platform_data = &qi_lb60_nand_pdata;
460 jz4740_adc_device.dev.platform_data = &qi_lb60_battery_pdata;
461 jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
462
463 jz4740_serial_device_register();
464
465 spi_register_board_info(qi_lb60_spi_board_info,
466 ARRAY_SIZE(qi_lb60_spi_board_info));
467
468 if (is_avt2) {
469 platform_device_register(&avt2_usb_regulator_device);
470 platform_device_register(&jz4740_usb_ohci_device);
471 }
472
473 return platform_add_devices(jz_platform_devices,
474 ARRAY_SIZE(jz_platform_devices));
475
476}
477
478struct jz4740_clock_board_data jz4740_clock_bdata = {
479 .ext_rate = 12000000,
480 .rtc_rate = 32768,
481};
482
483static __init int board_avt2(char *str)
484{
485 qi_lb60_mmc_pdata.card_detect_active_low = 1;
486 is_avt2 = true;
487
488 return 1;
489}
490__setup("avt2", board_avt2);
491
492static int __init qi_lb60_board_setup(void)
493{
494 printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n",
495 is_avt2 ? "AVT2" : "LB60");
496
497 board_gpio_setup();
498
499 if (qi_lb60_init_platform_devices())
ab75dc02 500 panic("Failed to initialize platform devices");
e6b78c4f
LPC
501
502 return 0;
503}
504arch_initcall(qi_lb60_board_setup);
This page took 0.216835 seconds and 5 git commands to generate.