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

This is a squashed version of the development done in the jz-2.6.38 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
1818    bool "Sungale id800wt picture frame"
1919    select SOC_JZ4740
2020
21config JZ4740_A320
22    bool "Dingoo A320 game and media player"
23    select SYS_SUPPORTS_ZBOOT
24
2125endchoice
2226
2327config HAVE_PWM
arch/mips/jz4740/Makefile
1515obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
1616obj-$(CONFIG_JZ4740_N526) += board-n526.o
1717obj-$(CONFIG_JZ4740_ID800WT) += board-id800wt.o
18obj-$(CONFIG_JZ4740_A320) += board-a320.o
1819
1920# PM support
2021
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 <asm/cpu.h>
34#include <asm/bootinfo.h>
35#include <asm/mipsregs.h>
36#include <asm/reboot.h>
37
38#include <asm/mach-jz4740/gpio.h>
39#include <asm/mach-jz4740/jz4740_fb.h>
40#include <asm/mach-jz4740/jz4740_mmc.h>
41#include <asm/mach-jz4740/jz4740_nand.h>
42#include <asm/mach-jz4740/platform.h>
43
44#include "clock.h"
45
46/*
47 * This is called by the panic reboot delay loop if panic=<n> parameter
48 * is passed to the kernel. The A320 does not have any LEDs, so the best
49 * we can do is to blink the LCD backlight.
50 *
51 * TODO(MtH): This should use the backlight driver instead of directly
52 * manipulating the GPIO pin.
53 */
54static long a320_panic_blink_callback(int time)
55{
56    gpio_direction_output(JZ_GPIO_PORTD(31), (time / 500) & 1);
57    return 0;
58}
59
60#ifdef CONFIG_I2C_GPIO
61/* I2C over GPIO pins */
62static struct i2c_gpio_platform_data a320_i2c_pdata = {
63    .sda_pin = JZ_GPIO_PORTD(23),
64    .scl_pin = JZ_GPIO_PORTD(24),
65    .udelay = 2,
66    .timeout = 3 * HZ,
67};
68
69static struct platform_device a320_i2c_device = {
70    .name = "i2c-gpio",
71    .id = -1,
72    .dev = {
73        .platform_data = &a320_i2c_pdata,
74    },
75};
76#endif
77
78/* NAND */
79#define A320_NAND_PAGE_SIZE (4096ull)
80#define A320_NAND_ERASE_BLOCK_SIZE (128 * A320_NAND_PAGE_SIZE)
81
82static struct mtd_partition a320_nand_partitions[] = {
83    { .name = "SPL",
84      .offset = 0 * A320_NAND_ERASE_BLOCK_SIZE,
85      .size = 1 * A320_NAND_ERASE_BLOCK_SIZE,
86      /* MtH: Read-only until we can trust it. */
87      .mask_flags = MTD_WRITEABLE,
88    },
89    { .name = "uC/OS-II loader",
90      .offset = 1 * A320_NAND_ERASE_BLOCK_SIZE,
91      .size = 2 * A320_NAND_ERASE_BLOCK_SIZE,
92      /* MtH: Read-only until we can trust it. */
93      .mask_flags = MTD_WRITEABLE,
94    },
95    /* erase block 3 is empty (maybe alternative location for bbt?) */
96    /* erase block 4 contains the bad block table */
97    { .name = "uC/OS-II Z:",
98      .offset = 5 * A320_NAND_ERASE_BLOCK_SIZE,
99      .size = 127 * A320_NAND_ERASE_BLOCK_SIZE,
100      /* MtH: Read-only until we can trust it. */
101      .mask_flags = MTD_WRITEABLE,
102    },
103    { .name = "uC/OS-II A:",
104      .offset = 132 * A320_NAND_ERASE_BLOCK_SIZE,
105      .size = (8192 - 132) * A320_NAND_ERASE_BLOCK_SIZE,
106      /* MtH: Read-only until we can trust it. */
107      .mask_flags = MTD_WRITEABLE,
108    },
109};
110
111static uint8_t a320_nand_bbt_pattern[] = {'b', 'b', 't', '8' };
112
113static struct nand_bbt_descr a320_nand_bbt_main_descr = {
114    .options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT,
115    /* TODO(MtH): Maybe useful flags for the future:
116    NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_VERSION | NAND_BBT_PERCHIP
117    */
118    .pages = { 4 * A320_NAND_ERASE_BLOCK_SIZE / A320_NAND_PAGE_SIZE },
119    .maxblocks = 1,
120    .pattern = a320_nand_bbt_pattern,
121    .len = ARRAY_SIZE(a320_nand_bbt_pattern),
122    .offs = 128 - ARRAY_SIZE(a320_nand_bbt_pattern),
123};
124
125static struct nand_ecclayout a320_nand_ecc_layout = {
126    .eccbytes = 72,
127    .eccpos = {
128         4, 5, 6, 7, 8, 9, 10, 11, 12, /* sector 0 */
129        16, 17, 18, 19, 20, 21, 22, 23, 24, /* sector 1 */
130        28, 29, 30, 31, 32, 33, 34, 35, 36, /* sector 2 */
131        40, 41, 42, 43, 44, 45, 46, 47, 48, /* sector 3 */
132        52, 53, 54, 55, 56, 57, 58, 59, 60, /* sector 4 */
133        64, 65, 66, 67, 68, 69, 70, 71, 72, /* sector 5 */
134        76, 77, 78, 79, 80, 81, 82, 83, 84, /* sector 6 */
135        88, 89, 90, 91, 92, 93, 94, 95, 96, /* sector 7 */
136    },
137    .oobfree = {
138        { .offset = 100, .length = 22 },
139    }
140};
141
142static void a320_nand_ident(struct platform_device *pdev,
143                struct nand_chip *chip,
144                struct mtd_partition **partitions,
145                int *num_partitions)
146{
147    chip->options |= NAND_USE_FLASH_BBT;
148    chip->bbt_td = &a320_nand_bbt_main_descr;
149    /* MtH: I did not find a mirror bbt yet, but it might exist. */
150    chip->bbt_md = NULL;
151}
152
153static struct jz_nand_platform_data a320_nand_pdata = {
154    .num_partitions = ARRAY_SIZE(a320_nand_partitions),
155    .partitions = a320_nand_partitions,
156    .ecc_layout = &a320_nand_ecc_layout,
157    .busy_gpio = JZ_GPIO_PORTC(30),
158    .banks = { 1, 2, 3, 4 },
159    .ident_callback = a320_nand_ident,
160};
161
162/* Display */
163static struct fb_videomode a320_video_modes[] = {
164    {
165        .name = "320x240",
166        .xres = 320,
167        .yres = 240,
168        // TODO(MtH): Set refresh or pixclock.
169        .vmode = FB_VMODE_NONINTERLACED,
170    },
171};
172
173static struct jz4740_fb_platform_data a320_fb_pdata = {
174    .width = 60,
175    .height = 45,
176    .num_modes = ARRAY_SIZE(a320_video_modes),
177    .modes = a320_video_modes,
178    .bpp = 16,
179    .lcd_type = JZ_LCD_TYPE_SMART_PARALLEL_16_BIT,
180    .pixclk_falling_edge = 0,
181    .chip_select_active_low = 1,
182    .register_select_active_low = 1,
183};
184
185static int a320_backlight_notify(struct device *dev, int brightness)
186{
187    if (!gpio_get_value(JZ_GPIO_PORTB(18))) {
188        /* RESET_N pin of the ILI chip is pulled down,
189           so force backlight off. */
190        return 0;
191    }
192
193    return brightness;
194}
195
196static struct platform_pwm_backlight_data a320_backlight_pdata = {
197    .pwm_id = 7,
198    .max_brightness = 255,
199    .dft_brightness = 100,
200    .pwm_period_ns = 5000000,
201    .notify = a320_backlight_notify,
202};
203
204static struct platform_device a320_backlight_device = {
205    .name = "pwm-backlight",
206    .id = -1,
207    .dev = {
208        .platform_data = &a320_backlight_pdata,
209    },
210};
211
212static struct jz4740_mmc_platform_data a320_mmc_pdata = {
213    .gpio_card_detect = JZ_GPIO_PORTB(29),
214    .gpio_read_only = -1,
215    .gpio_power = -1,
216    // TODO(MtH): I don't know which GPIO pin the SD power is connected to.
217    // Booboo left power alone, but I don't know why.
218    //.gpio_power = GPIO_SD_VCC_EN_N,
219    //.power_active_low = 1,
220};
221
222/* Battery */
223static struct jz_battery_platform_data a320_battery_pdata = {
224    // TODO(MtH): Sometimes while charging, the GPIO pin quickly flips between
225    // 0 and 1. This causes a very high CPU load because the kernel
226    // will invoke a hotplug event handler process on every status
227    // change. Until it is clear how to avoid or handle that, it
228    // is better not to use the charge status.
229    //.gpio_charge = JZ_GPIO_PORTB(30),
230    .gpio_charge = -1,
231    .gpio_charge_active_low = 1,
232    .info = {
233        .name = "battery",
234        .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
235        .voltage_max_design = 4200000,
236        .voltage_min_design = 3600000,
237    },
238};
239
240static char *a320_batteries[] = {
241    "battery",
242};
243
244static struct gpio_charger_platform_data a320_charger_pdata = {
245    .name = "usb",
246    .type = POWER_SUPPLY_TYPE_USB,
247    .gpio = JZ_GPIO_PORTD(28),
248    .gpio_active_low = 0,
249    .supplied_to = a320_batteries,
250    .num_supplicants = ARRAY_SIZE(a320_batteries),
251};
252
253static struct platform_device a320_charger_device = {
254    .name = "gpio-charger",
255    .dev = {
256        .platform_data = &a320_charger_pdata,
257    },
258};
259
260    /* TODO(CongoZombie): Figure out a way to reimplement power slider functionality
261                          so that existing apps won't break. (Possible that an SDL
262                          remapping would fix this, but it is unclear how many apps
263                          use other interfaces)
264                          Original Dingux used SysRq keys to perform different tasks
265                          (restart, backlight, volume etc.)
266    */
267    /* TODO(CongoZombie): Confirm power slider pin (Booboo's docs seem unsure) */
268
269static struct gpio_keys_button a320_buttons[] = {
270    /* D-pad up */ {
271        .gpio = JZ_GPIO_PORTD(6),
272        .active_low = 1,
273        .code = KEY_UP
274    },
275    /* D-pad down */ {
276        .gpio = JZ_GPIO_PORTD(27),
277        .active_low = 1,
278        .code = KEY_DOWN
279    },
280    /* D-pad left */ {
281        .gpio = JZ_GPIO_PORTD(5),
282        .active_low = 1,
283        .code = KEY_LEFT
284    },
285    /* D-pad right */ {
286        .gpio = JZ_GPIO_PORTD(18),
287        .active_low = 1,
288        .code = KEY_RIGHT
289    },
290    /* A button */ {
291        .gpio = JZ_GPIO_PORTD(0),
292        .active_low = 1,
293        .code = KEY_LEFTCTRL
294    },
295    /* B button */ {
296        .gpio = JZ_GPIO_PORTD(1),
297        .active_low = 1,
298        .code = KEY_LEFTALT
299    },
300    /* X button */ {
301        .gpio = JZ_GPIO_PORTD(19),
302        .active_low = 1,
303        .code = KEY_SPACE
304    },
305    /* Y button */ {
306        .gpio = JZ_GPIO_PORTD(2),
307        .active_low = 1,
308        .code = KEY_LEFTSHIFT
309    },
310    /* Left shoulder button */ {
311        .gpio = JZ_GPIO_PORTD(14),
312        .active_low = 1,
313        .code = KEY_TAB
314    },
315    /* Right shoulder button */ {
316        .gpio = JZ_GPIO_PORTD(15),
317        .active_low = 1,
318        .code = KEY_BACKSPACE
319    },
320    /* START button */ {
321        .gpio = JZ_GPIO_PORTC(17),
322        .active_low = 1,
323        .code = KEY_ENTER
324    },
325    /* SELECT button */ {
326        .gpio = JZ_GPIO_PORTD(17),
327        .active_low = 1,
328        .code = KEY_ESC
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
357static struct platform_device *jz_platform_devices[] __initdata = {
358#ifdef CONFIG_I2C_JZ47XX
359    &jz4740_i2c_device,
360#endif
361#ifdef CONFIG_I2C_GPIO
362    &a320_i2c_device,
363#endif
364    /* USB host is not usable since the PCB does not route the pins to
365     * a place where new wires can be soldered. */
366    /*&jz4740_usb_ohci_device,*/
367    &jz4740_udc_device,
368    &jz4740_mmc_device,
369    &jz4740_nand_device,
370    &jz4740_framebuffer_device,
371    &jz4740_pcm_device,
372    &jz4740_i2s_device,
373    &jz4740_codec_device,
374    &jz4740_rtc_device,
375    &jz4740_adc_device,
376    &jz4740_wdt_device,
377    &a320_charger_device,
378    &a320_backlight_device,
379    &a320_gpio_keys_device,
380};
381
382static void __init board_gpio_setup(void)
383{
384    /* We only need to enable/disable pullup here for pins used in generic
385     * drivers. Everything else is done by the drivers themselves. */
386
387    /* Disable pullup of the USB detection pin: on the A320 pullup or not
388     * seems to make no difference, but on A330 the signal will be unstable
389     * when the pullup is enabled. */
390    jz_gpio_disable_pullup(JZ_GPIO_PORTD(28));
391}
392
393static int __init a320_init_platform_devices(void)
394{
395    jz4740_framebuffer_device.dev.platform_data = &a320_fb_pdata;
396    jz4740_nand_device.dev.platform_data = &a320_nand_pdata;
397    jz4740_adc_device.dev.platform_data = &a320_battery_pdata;
398    jz4740_mmc_device.dev.platform_data = &a320_mmc_pdata;
399
400    jz4740_serial_device_register();
401
402    return platform_add_devices(jz_platform_devices,
403                    ARRAY_SIZE(jz_platform_devices));
404}
405
406struct jz4740_clock_board_data jz4740_clock_bdata = {
407    .ext_rate = 12000000,
408    .rtc_rate = 32768,
409};
410
411static int __init a320_board_setup(void)
412{
413    printk(KERN_INFO "JZ4740 A320 board setup\n");
414
415    panic_blink = a320_panic_blink_callback;
416
417    board_gpio_setup();
418
419    if (a320_init_platform_devices())
420        panic("Failed to initalize platform devices\n");
421
422    return 0;
423}
424
425arch_initcall(a320_board_setup);

Archive Download the corresponding diff file



interactive