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