Add 2.6.34 patches
[openwrt/openwrt.git] / target / linux / xburst / patches-2.6.34 / 006-add-n516-board-support.patch
1 From 49f148f79887cec83c4b051c104072d770a6a9af Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sat, 24 Apr 2010 17:25:01 +0200
4 Subject: [PATCH] Add n516 board support
5
6 ---
7 arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++
8 arch/mips/jz4740/Kconfig | 4 +
9 arch/mips/jz4740/Makefile | 1 +
10 arch/mips/jz4740/board-n516-display.c | 393 ++++++++++++++++++++++++
11 arch/mips/jz4740/board-n516.c | 206 +++++++++++++
12 5 files changed, 643 insertions(+), 0 deletions(-)
13 create mode 100644 arch/mips/include/asm/mach-jz4740/board-n516.h
14 create mode 100644 arch/mips/jz4740/board-n516-display.c
15 create mode 100644 arch/mips/jz4740/board-n516.c
16
17 diff --git a/arch/mips/include/asm/mach-jz4740/board-n516.h b/arch/mips/include/asm/mach-jz4740/board-n516.h
18 new file mode 100644
19 index 0000000..f3f1e0a
20 --- /dev/null
21 +++ b/arch/mips/include/asm/mach-jz4740/board-n516.h
22 @@ -0,0 +1,39 @@
23 +/*
24 + * linux/include/asm-mips/mach-jz4740/board-n516.h
25 + *
26 + * JZ4730-based N516 board definition.
27 + *
28 + * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
29 + *
30 + * This program is free software; you can redistribute it and/or modify
31 + * it under the terms of the GNU General Public License as published by
32 + * the Free Software Foundation; either version 2 of the License, or
33 + * (at your option) any later version.
34 + */
35 +
36 +#ifndef __ASM_JZ4740_N516_H__
37 +#define __ASM_JZ4740_N516_H__
38 +
39 +#include <asm/mach-jz4740/gpio.h>
40 +
41 +/*
42 + * GPIO
43 + */
44 +#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(17)
45 +#define GPIO_SD_CD_N JZ_GPIO_PORTD(7)
46 +#define GPIO_SD_WP JZ_GPIO_PORTD(15)
47 +#define GPIO_USB_DETECT JZ_GPIO_PORTD(19)
48 +#define GPIO_CHARG_STAT_N JZ_GPIO_PORTD(16)
49 +#define GPIO_LED_ENABLE JZ_GPIO_PORTD(28)
50 +#define GPIO_LPC_INT JZ_GPIO_PORTD(14)
51 +#define GPIO_HPHONE_DETECT JZ_GPIO_PORTD(20)
52 +#define GPIO_SPEAKER_ENABLE JZ_GPIO_PORTD(21)
53 +
54 +/* Display */
55 +#define GPIO_DISPLAY_RST_L JZ_GPIO_PORTB(18)
56 +#define GPIO_DISPLAY_RDY JZ_GPIO_PORTB(17)
57 +#define GPIO_DISPLAY_STBY JZ_GPIO_PORTC(22)
58 +#define GPIO_DISPLAY_ERR JZ_GPIO_PORTC(23)
59 +#define GPIO_DISPLAY_OFF JZ_GPIO_PORTD(1)
60 +
61 +#endif /* __ASM_JZ4740_N516_H__ */
62 diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
63 index 3de3b99..b987c27 100644
64 --- a/arch/mips/jz4740/Kconfig
65 +++ b/arch/mips/jz4740/Kconfig
66 @@ -7,6 +7,10 @@ config JZ4740_QI_LB60
67 bool "Qi Hardware Ben NanoNote"
68 select SOC_JZ4740
69
70 +config JZ4740_N516
71 + bool "Hanvon n516 eBook reader"
72 + select SOC_JZ4740
73 +
74 endchoice
75
76 config HAVE_PWM
77 diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
78 index deca88e..9ed5e5b 100644
79 --- a/arch/mips/jz4740/Makefile
80 +++ b/arch/mips/jz4740/Makefile
81 @@ -12,6 +12,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
82 # board specific support
83
84 obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
85 +obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
86
87 # PM support
88
89 diff --git a/arch/mips/jz4740/board-n516-display.c b/arch/mips/jz4740/board-n516-display.c
90 new file mode 100644
91 index 0000000..44d8237
92 --- /dev/null
93 +++ b/arch/mips/jz4740/board-n516-display.c
94 @@ -0,0 +1,393 @@
95 +/*
96 + * board-n516-display.c -- Platform device for N516 display
97 + *
98 + * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
99 + *
100 + * This file is subject to the terms and conditions of the GNU General Public
101 + * License. See the file COPYING in the main directory of this archive for
102 + * more details.
103 + */
104 +
105 +#include <linux/module.h>
106 +#include <linux/kernel.h>
107 +#include <linux/errno.h>
108 +#include <linux/string.h>
109 +#include <linux/delay.h>
110 +#include <linux/interrupt.h>
111 +#include <linux/fb.h>
112 +#include <linux/init.h>
113 +#include <linux/platform_device.h>
114 +#include <linux/irq.h>
115 +#include <linux/gpio.h>
116 +#include <linux/jz4740_fb.h>
117 +
118 +#include <asm/mach-jz4740/platform.h>
119 +#include <asm/mach-jz4740/board-n516.h>
120 +
121 +#include <video/metronomefb.h>
122 +#include <linux/console.h>
123 +
124 +static struct fb_videomode n516_fb_modes[] = {
125 + [0] = {
126 + .name = "Metronome 800x600",
127 + .refresh = 50,
128 + .xres = 400,
129 + .yres = 624,
130 + .hsync_len = 31,
131 + .vsync_len = 23,
132 + .right_margin = 31,
133 + .left_margin = 5,
134 + .upper_margin = 1,
135 + .lower_margin = 2,
136 + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
137 + },
138 +};
139 +
140 +static struct jz4740_fb_platform_data n516_fb_pdata = {
141 + .num_modes = ARRAY_SIZE(n516_fb_modes),
142 + .modes = n516_fb_modes,
143 + .bpp = 16,
144 + .lcd_type = JZ_LCD_TYPE_GENERIC_16_BIT,
145 +};
146 +
147 +struct n516_board_info {
148 + uint8_t *metromem;
149 + size_t wfm_size;
150 + struct fb_info *host_fbinfo; /* the host LCD controller's fbi */
151 + unsigned int fw;
152 + unsigned int fh;
153 +};
154 +
155 +static struct platform_device *n516_device;
156 +static struct n516_board_info n516_board_info;
157 +
158 +static int metronome_gpios[] = {
159 + GPIO_DISPLAY_STBY,
160 + GPIO_DISPLAY_RST_L,
161 + GPIO_DISPLAY_RDY,
162 + GPIO_DISPLAY_ERR,
163 +/* GPIO_DISPLAY_OFF,*/
164 +};
165 +
166 +static const char *metronome_gpio_names[] = {
167 + "Metronome STDBY",
168 + "Metronome RST",
169 + "Metronome RDY",
170 + "Metronome ERR",
171 +/* "Metronone OFF",*/
172 +};
173 +
174 +static int n516_enable_hostfb(bool enable)
175 +{
176 + int ret;
177 + int blank = enable ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
178 +
179 + acquire_console_sem();
180 + ret = fb_blank(n516_board_info.host_fbinfo, blank);
181 + release_console_sem();
182 +
183 + return ret;
184 +}
185 +
186 +static int n516_init_metronome_gpios(struct metronomefb_par *par)
187 +{
188 + int i;
189 + int ret;
190 +
191 + for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i) {
192 + ret = gpio_request(metronome_gpios[i], metronome_gpio_names[i]);
193 + if (ret)
194 + goto err;
195 + }
196 +
197 + gpio_direction_output(GPIO_DISPLAY_OFF, 0);
198 + gpio_direction_output(GPIO_DISPLAY_RST_L, 0);
199 + gpio_direction_output(GPIO_DISPLAY_STBY, 0);
200 + gpio_direction_input(GPIO_DISPLAY_RDY);
201 + gpio_direction_input(GPIO_DISPLAY_ERR);
202 +
203 + return 0;
204 +err:
205 + for (--i; i >= 0; --i)
206 + gpio_free(metronome_gpios[i]);
207 +
208 + return ret;
209 +}
210 +
211 +static int n516_share_video_mem(struct fb_info *info)
212 +{
213 + int ret;
214 +
215 + dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
216 + dev_dbg(&n516_device->dev, "%s, info->var.xres = %u, info->var.yres = %u\n", __func__, info->var.xres, info->var.yres);
217 + /* rough check if this is our desired fb and not something else */
218 + if ((info->var.xres != n516_fb_pdata.modes[0].xres)
219 + || (info->var.yres != n516_fb_pdata.modes[0].yres))
220 + return 0;
221 +
222 + /* we've now been notified that we have our new fb */
223 + n516_board_info.metromem = info->screen_base;
224 + n516_board_info.host_fbinfo = info;
225 +
226 + n516_enable_hostfb(false);
227 + /* try to refcount host drv since we are the consumer after this */
228 + if (!try_module_get(info->fbops->owner))
229 + return -ENODEV;
230 +
231 + /* this _add binds metronomefb to n516. metronomefb refcounts n516 */
232 + ret = platform_device_add(n516_device);
233 +
234 + if (ret) {
235 + platform_device_put(n516_device);
236 + return ret;
237 + }
238 +
239 + /* request our platform independent driver */
240 + request_module("metronomefb");
241 +
242 + return 0;
243 +}
244 +
245 +static int n516_unshare_video_mem(struct fb_info *info)
246 +{
247 + dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
248 +
249 + if (info != n516_board_info.host_fbinfo)
250 + return 0;
251 +
252 + module_put(n516_board_info.host_fbinfo->fbops->owner);
253 + return 0;
254 +}
255 +
256 +static int n516_fb_notifier_callback(struct notifier_block *self,
257 + unsigned long event, void *data)
258 +{
259 + struct fb_event *evdata = data;
260 + struct fb_info *info = evdata->info;
261 +
262 + dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
263 +
264 + if (event == FB_EVENT_FB_REGISTERED)
265 + return n516_share_video_mem(info);
266 + else if (event == FB_EVENT_FB_UNREGISTERED)
267 + return n516_unshare_video_mem(info);
268 +
269 + return 0;
270 +}
271 +
272 +static struct notifier_block n516_fb_notif = {
273 + .notifier_call = n516_fb_notifier_callback,
274 +};
275 +
276 +/* this gets called as part of our init. these steps must be done now so
277 + * that we can use set_pxa_fb_info */
278 +static void __init n516_presetup_fb(void)
279 +{
280 + int padding_size;
281 + int totalsize;
282 +
283 + /* the frame buffer is divided as follows:
284 + command | CRC | padding
285 + 16kb waveform data | CRC | padding
286 + image data | CRC
287 + */
288 +
289 + n516_board_info.fw = 800;
290 + n516_board_info.fh = 624;
291 +
292 + /* waveform must be 16k + 2 for checksum */
293 + n516_board_info.wfm_size = roundup(16*1024 + 2, n516_board_info.fw);
294 +
295 + padding_size = PAGE_SIZE + (4 * n516_board_info.fw);
296 +
297 + /* total is 1 cmd , 1 wfm, padding and image */
298 + totalsize = n516_board_info.fw + n516_board_info.wfm_size;
299 + totalsize += padding_size + (n516_board_info.fw*n516_board_info.fh);
300 +
301 + /* save this off because we're manipulating fw after this and
302 + * we'll need it when we're ready to setup the framebuffer */
303 +
304 + /* the reason we do this adjustment is because we want to acquire
305 + * more framebuffer memory without imposing custom awareness on the
306 + * underlying driver */
307 + n516_fb_pdata.modes[0].yres = DIV_ROUND_UP(totalsize, n516_board_info.fw);
308 +
309 + jz4740_framebuffer_device.dev.platform_data = &n516_fb_pdata;
310 + platform_device_register(&jz4740_framebuffer_device);
311 +}
312 +
313 +/* this gets called by metronomefb as part of its init, in our case, we
314 + * have already completed initial framebuffer init in presetup_fb so we
315 + * can just setup the fb access pointers */
316 +static int n516_setup_fb(struct metronomefb_par *par)
317 +{
318 + /* metromem was set up by the notifier in share_video_mem so now
319 + * we can use its value to calculate the other entries */
320 + par->metromem_cmd = (struct metromem_cmd *) n516_board_info.metromem;
321 + par->metromem_wfm = n516_board_info.metromem + n516_board_info.fw;
322 + par->metromem_img = par->metromem_wfm + n516_board_info.wfm_size;
323 + par->metromem_img_csum = (u16 *) (par->metromem_img + (n516_board_info.fw * n516_board_info.fh));
324 + par->metromem_dma = n516_board_info.host_fbinfo->fix.smem_start;
325 +
326 + return 0;
327 +}
328 +
329 +static int n516_get_panel_type(void)
330 +{
331 + return 5;
332 +}
333 +
334 +static irqreturn_t n516_handle_irq(int irq, void *dev_id)
335 +{
336 + struct metronomefb_par *par = dev_id;
337 +
338 + dev_dbg(&par->pdev->dev, "Metronome IRQ! RDY=%d\n", gpio_get_value(GPIO_DISPLAY_RDY));
339 + wake_up_all(&par->waitq);
340 +
341 + return IRQ_HANDLED;
342 +}
343 +
344 +static void n516_power_ctl(struct metronomefb_par *par, int cmd)
345 +{
346 + switch (cmd) {
347 + case METRONOME_POWER_OFF:
348 + gpio_set_value(GPIO_DISPLAY_OFF, 1);
349 + n516_enable_hostfb(false);
350 + break;
351 + case METRONOME_POWER_ON:
352 + gpio_set_value(GPIO_DISPLAY_OFF, 0);
353 + n516_enable_hostfb(true);
354 + break;
355 + }
356 +}
357 +
358 +static int n516_get_rdy(struct metronomefb_par *par)
359 +{
360 + return gpio_get_value(GPIO_DISPLAY_RDY);
361 +}
362 +
363 +static int n516_get_err(struct metronomefb_par *par)
364 +{
365 + return gpio_get_value(GPIO_DISPLAY_ERR);
366 +}
367 +
368 +static int n516_setup_irq(struct fb_info *info)
369 +{
370 + int ret;
371 +
372 + dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
373 +
374 + ret = request_irq(gpio_to_irq(GPIO_DISPLAY_RDY), n516_handle_irq,
375 + IRQF_TRIGGER_RISING,
376 + "n516", info->par);
377 + if (ret)
378 + dev_err(&n516_device->dev, "request_irq failed: %d\n", ret);
379 +
380 + return ret;
381 +}
382 +
383 +static void n516_set_rst(struct metronomefb_par *par, int state)
384 +{
385 + dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
386 + if (state)
387 + gpio_set_value(GPIO_DISPLAY_RST_L, 1);
388 + else
389 + gpio_set_value(GPIO_DISPLAY_RST_L, 0);
390 +}
391 +
392 +static void n516_set_stdby(struct metronomefb_par *par, int state)
393 +{
394 + dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
395 + if (state)
396 + gpio_set_value(GPIO_DISPLAY_STBY, 1);
397 + else
398 + gpio_set_value(GPIO_DISPLAY_STBY, 0);
399 +}
400 +
401 +static int n516_wait_event(struct metronomefb_par *par)
402 +{
403 + unsigned long timeout = jiffies + HZ / 20;
404 +
405 + dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
406 + __func__, gpio_get_value(GPIO_DISPLAY_RDY));
407 + while (n516_get_rdy(par) && time_before(jiffies, timeout))
408 + schedule();
409 +
410 + dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
411 + __func__, gpio_get_value(GPIO_DISPLAY_RDY));
412 + return wait_event_timeout(par->waitq,
413 + n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
414 +}
415 +
416 +static int n516_wait_event_intr(struct metronomefb_par *par)
417 +{
418 + unsigned long timeout = jiffies + HZ/20;
419 +
420 + dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
421 + __func__, gpio_get_value(GPIO_DISPLAY_RDY));
422 + while (n516_get_rdy(par) && time_before(jiffies, timeout))
423 + schedule();
424 +
425 + dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
426 + __func__, gpio_get_value(GPIO_DISPLAY_RDY));
427 + return wait_event_interruptible_timeout(par->waitq,
428 + n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
429 +}
430 +
431 +static void n516_cleanup(struct metronomefb_par *par)
432 +{
433 + int i;
434 +
435 + free_irq(gpio_to_irq(GPIO_DISPLAY_RDY), par);
436 + for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i)
437 + gpio_free(metronome_gpios[i]);
438 +}
439 +
440 +static struct metronome_board n516_board __initdata = {
441 + .owner = THIS_MODULE,
442 + .power_ctl = n516_power_ctl,
443 + .setup_irq = n516_setup_irq,
444 + .setup_io = n516_init_metronome_gpios,
445 + .setup_fb = n516_setup_fb,
446 + .set_rst = n516_set_rst,
447 + .get_err = n516_get_err,
448 + .get_rdy = n516_get_rdy,
449 + .set_stdby = n516_set_stdby,
450 + .met_wait_event = n516_wait_event,
451 + .met_wait_event_intr = n516_wait_event_intr,
452 + .get_panel_type = n516_get_panel_type,
453 + .cleanup = n516_cleanup,
454 +};
455 +
456 +static int __init n516_init(void)
457 +{
458 + int ret;
459 +
460 + /* Keep the metronome off, until its driver is loaded */
461 + ret = gpio_request(GPIO_DISPLAY_OFF, "Display off");
462 + if (ret)
463 + return ret;
464 +
465 + gpio_direction_output(GPIO_DISPLAY_OFF, 1);
466 +
467 + /* before anything else, we request notification for any fb
468 + * creation events */
469 + fb_register_client(&n516_fb_notif);
470 +
471 + n516_device = platform_device_alloc("metronomefb", -1);
472 + if (!n516_device)
473 + return -ENOMEM;
474 +
475 + /* the n516_board that will be seen by metronomefb is a copy */
476 + platform_device_add_data(n516_device, &n516_board,
477 + sizeof(n516_board));
478 +
479 + n516_presetup_fb();
480 +
481 + return 0;
482 +}
483 +module_init(n516_init);
484 +
485 +MODULE_DESCRIPTION("board driver for n516 display");
486 +MODULE_AUTHOR("Yauhen Kharuzhy");
487 +MODULE_LICENSE("GPL");
488 diff --git a/arch/mips/jz4740/board-n516.c b/arch/mips/jz4740/board-n516.c
489 new file mode 100644
490 index 0000000..efb8747
491 --- /dev/null
492 +++ b/arch/mips/jz4740/board-n516.c
493 @@ -0,0 +1,206 @@
494 +/*
495 + * linux/arch/mips/jz4740/board-516.c
496 + *
497 + * JZ4740 n516 board setup routines.
498 + *
499 + * Copyright (c) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
500 + *
501 + * This program is free software; you can redistribute it and/or modify
502 + * it under the terms of the GNU General Public License as published by
503 + * the Free Software Foundation; either version 2 of the License, or
504 + * (at your option) any later version.
505 + */
506 +
507 +#include <linux/init.h>
508 +#include <linux/sched.h>
509 +#include <linux/ioport.h>
510 +#include <linux/mm.h>
511 +#include <linux/console.h>
512 +#include <linux/delay.h>
513 +#include <linux/i2c.h>
514 +#include <linux/platform_device.h>
515 +#include <linux/mtd/mtd.h>
516 +#include <linux/mmc/jz4740_mmc.h>
517 +#include <linux/mtd/jz4740_nand.h>
518 +#include <linux/leds.h>
519 +
520 +#include <linux/power_supply.h>
521 +#include <linux/power/gpio-charger.h>
522 +
523 +#include <linux/i2c.h>
524 +#include <linux/i2c-gpio.h>
525 +
526 +#include <asm/mach-jz4740/board-n516.h>
527 +#include <asm/mach-jz4740/platform.h>
528 +
529 +#include "clock.h"
530 +
531 +static long n516_panic_blink(long time)
532 +{
533 + gpio_set_value(GPIO_LED_ENABLE, 1);
534 + mdelay(200);
535 + gpio_set_value(GPIO_LED_ENABLE, 0);
536 + mdelay(200);
537 +
538 + return 400;
539 +}
540 +
541 +static void __init board_gpio_setup(void)
542 +{
543 +/* jz_gpio_enable_pullup(JZ_GPIO_PORTD(23));
544 + jz_gpio_enable_pullup(JZ_GPIO_PORTD(24));*/
545 +}
546 +
547 +static struct i2c_gpio_platform_data n516_i2c_pdata = {
548 + .sda_pin = JZ_GPIO_PORTD(23),
549 + .scl_pin = JZ_GPIO_PORTD(24),
550 + .udelay = 2,
551 + .timeout = 3 * HZ,
552 +};
553 +
554 +static struct platform_device n516_i2c_device = {
555 + .name = "i2c-gpio",
556 + .id = -1,
557 + .dev = {
558 + .platform_data = &n516_i2c_pdata,
559 + },
560 +};
561 +
562 +static const struct i2c_board_info n516_i2c_board_info[] = {
563 + {
564 + .type = "LPC524",
565 + .addr = 0x54,
566 + },
567 + {
568 + .type = "lm75a",
569 + .addr = 0x48,
570 + }
571 +};
572 +
573 +static struct jz4740_mmc_platform_data n516_mmc_pdata = {
574 + .gpio_card_detect = GPIO_SD_CD_N,
575 + .card_detect_active_low = 1,
576 + .gpio_read_only = -1,
577 + .gpio_power = GPIO_SD_VCC_EN_N,
578 + .power_active_low = 1,
579 +};
580 +
581 +static struct gpio_led n516_leds[] = {
582 + {
583 + .name = "n516:blue:power",
584 + .gpio = GPIO_LED_ENABLE,
585 + .default_state = LEDS_GPIO_DEFSTATE_ON,
586 + .default_trigger = "nand-disk",
587 + }
588 +};
589 +
590 +static struct gpio_led_platform_data n516_leds_pdata = {
591 + .leds = n516_leds,
592 + .num_leds = ARRAY_SIZE(n516_leds),
593 +};
594 +
595 +static struct platform_device n516_leds_device = {
596 + .name = "leds-gpio",
597 + .id = -1,
598 + .dev = {
599 + .platform_data = &n516_leds_pdata,
600 + },
601 +};
602 +
603 +static struct mtd_partition n516_partitions[] = {
604 + { .name = "NAND BOOT partition",
605 + .offset = 0 * 0x100000,
606 + .size = 4 * 0x100000,
607 + },
608 + { .name = "NAND KERNEL partition",
609 + .offset = 4 * 0x100000,
610 + .size = 4 * 0x100000,
611 + },
612 + { .name = "NAND ROOTFS partition",
613 + .offset = 8 * 0x100000,
614 + .size = 504 * 0x100000,
615 + },
616 +};
617 +
618 +static struct nand_ecclayout n516_ecclayout = {
619 + .eccbytes = 36,
620 + .eccpos = {
621 + 6, 7, 8, 9, 10, 11, 12, 13, 14,
622 + 15, 16, 17, 18, 19, 20, 21, 22, 23,
623 + 24, 25, 26, 27, 28, 29, 30, 31, 32,
624 + 33, 34, 35, 36, 37, 38, 39, 40, 41,
625 + },
626 + .oobfree = {
627 + {
628 + .offset = 2,
629 + .length = 4
630 + },
631 + {
632 + .offset = 42,
633 + .length = 22,
634 + }
635 + }
636 +};
637 +
638 +static struct jz_nand_platform_data n516_nand_pdata = {
639 + .ecc_layout = &n516_ecclayout,
640 + .partitions = n516_partitions,
641 + .num_partitions = ARRAY_SIZE(n516_partitions),
642 + .busy_gpio = 94,
643 +};
644 +
645 +static char *n516_batteries[] = {
646 + "n516_battery",
647 +};
648 +
649 +static struct gpio_charger_platform_data n516_charger_pdata = {
650 + .name = "usb",
651 + .type = POWER_SUPPLY_TYPE_USB,
652 + .gpio = GPIO_USB_DETECT,
653 + .gpio_active_low = 1,
654 + .batteries = n516_batteries,
655 + .num_batteries = ARRAY_SIZE(n516_batteries),
656 +};
657 +
658 +static struct platform_device n516_charger_device = {
659 + .name = "gpio-charger",
660 + .dev = {
661 + .platform_data = &n516_charger_pdata,
662 + },
663 +};
664 +
665 +static struct platform_device *n516_devices[] __initdata = {
666 + &jz4740_nand_device,
667 + &n516_leds_device,
668 + &jz4740_mmc_device,
669 + &jz4740_i2s_device,
670 + &jz4740_codec_device,
671 + &jz4740_rtc_device,
672 + &jz4740_usb_gdt_device,
673 + &n516_i2c_device,
674 + &n516_charger_device,
675 +};
676 +
677 +struct jz4740_clock_board_data jz4740_clock_bdata = {
678 + .ext_rate = 12000000,
679 + .rtc_rate = 32768,
680 +};
681 +
682 +extern int jz_gpiolib_init(void);
683 +
684 +static int n516_setup_platform(void)
685 +{
686 + if (jz_gpiolib_init())
687 + panic("Failed to initalize jz gpio\n");
688 +
689 + jz4740_clock_init();
690 + board_gpio_setup();
691 +
692 + panic_blink = n516_panic_blink;
693 + i2c_register_board_info(0, n516_i2c_board_info, ARRAY_SIZE(n516_i2c_board_info));
694 + jz4740_mmc_device.dev.platform_data = &n516_mmc_pdata;
695 + jz4740_nand_device.dev.platform_data = &n516_nand_pdata;
696 +
697 + return platform_add_devices(n516_devices, ARRAY_SIZE(n516_devices));
698 +}
699 +arch_initcall(n516_setup_platform);
700 --
701 1.5.6.5
702