Date:2011-03-16 03:38:46 (12 years 8 months ago)
Author:Maarten ter Huurne
Commit:a1d22d5f548f17f720b68bc8f177624db0a2faa3
Message:MIPS: A320: Add Dingoo A320 board support.

This is a squashed version of the development done in the jz-3.4 branch.
Files: arch/mips/jz4740/Kconfig (1 diff)
arch/mips/jz4740/Makefile (1 diff)
arch/mips/jz4740/board-a320.c (1 diff)

Change Details

arch/mips/jz4740/Kconfig
66config JZ4740_QI_LB60
77    bool "Qi Hardware Ben NanoNote"
88
9config JZ4740_A320
10    bool "Dingoo A320 game and media player"
11
912endchoice
1013
1114config HAVE_PWM
arch/mips/jz4740/Makefile
1212# board specific support
1313
1414obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
15obj-$(CONFIG_JZ4740_A320) += board-a320.o
1516
1617# PM support
1718
arch/mips/jz4740/board-a320.c
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 */
56static 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 */
64static 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
71static 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
84static 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
113static uint8_t a320_nand_bbt_pattern[] = {'b', 'b', 't', '8' };
114
115static 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
127static 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
144static 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
155static 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 */
165static 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
175static 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
187static 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
198static 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
206static struct platform_device a320_backlight_device = {
207    .name = "pwm-backlight",
208    .id = -1,
209    .dev = {
210        .platform_data = &a320_backlight_pdata,
211    },
212};
213
214static 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 */
225static 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
242static char *a320_batteries[] = {
243    "battery",
244};
245
246static 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
255static 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 */
265static 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
343static struct gpio_keys_platform_data a320_gpio_keys_pdata = {
344    .buttons = a320_buttons,
345    .nbuttons = ARRAY_SIZE(a320_buttons),
346    .rep = 1,
347};
348
349static 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 */
358static struct platform_device a320_audio_device = {
359    .name = "a320-audio",
360    .id = -1,
361};
362
363static 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
389static 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
400static 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
413struct jz4740_clock_board_data jz4740_clock_bdata = {
414    .ext_rate = 12000000,
415    .rtc_rate = 32768,
416};
417
418static 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
423static 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
431static 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
447arch_initcall(a320_board_setup);

Archive Download the corresponding diff file



interactive