diff options
Diffstat (limited to 'target/linux/xburst/patches-2.6.37/006-add-n516-board-support.patch')
-rw-r--r-- | target/linux/xburst/patches-2.6.37/006-add-n516-board-support.patch | 663 |
1 files changed, 0 insertions, 663 deletions
diff --git a/target/linux/xburst/patches-2.6.37/006-add-n516-board-support.patch b/target/linux/xburst/patches-2.6.37/006-add-n516-board-support.patch deleted file mode 100644 index c875f13e17..0000000000 --- a/target/linux/xburst/patches-2.6.37/006-add-n516-board-support.patch +++ /dev/null @@ -1,663 +0,0 @@ -From fc2b1daf842a1b98472699fdddc8c12ce344bbd7 Mon Sep 17 00:00:00 2001 -From: Lars-Peter Clausen <lars@metafoo.de> -Date: Sat, 24 Apr 2010 17:25:01 +0200 -Subject: [PATCH 06/23] Add n516 board support - ---- - arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++ - arch/mips/jz4740/Kconfig | 4 + - arch/mips/jz4740/Makefile | 1 + - arch/mips/jz4740/board-n516-display.c | 394 ++++++++++++++++++++++++ - arch/mips/jz4740/board-n516.c | 182 +++++++++++ - 5 files changed, 620 insertions(+), 0 deletions(-) - create mode 100644 arch/mips/include/asm/mach-jz4740/board-n516.h - create mode 100644 arch/mips/jz4740/board-n516-display.c - create mode 100644 arch/mips/jz4740/board-n516.c - ---- /dev/null -+++ b/arch/mips/include/asm/mach-jz4740/board-n516.h -@@ -0,0 +1,39 @@ -+/* -+ * linux/include/asm-mips/mach-jz4740/board-n516.h -+ * -+ * JZ4730-based N516 board definition. -+ * -+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef __ASM_JZ4740_N516_H__ -+#define __ASM_JZ4740_N516_H__ -+ -+#include <asm/mach-jz4740/gpio.h> -+ -+/* -+ * GPIO -+ */ -+#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(17) -+#define GPIO_SD_CD_N JZ_GPIO_PORTD(7) -+#define GPIO_SD_WP JZ_GPIO_PORTD(15) -+#define GPIO_USB_DETECT JZ_GPIO_PORTD(19) -+#define GPIO_CHARG_STAT_N JZ_GPIO_PORTD(16) -+#define GPIO_LED_ENABLE JZ_GPIO_PORTD(28) -+#define GPIO_LPC_INT JZ_GPIO_PORTD(14) -+#define GPIO_HPHONE_DETECT JZ_GPIO_PORTD(20) -+#define GPIO_SPEAKER_ENABLE JZ_GPIO_PORTD(21) -+ -+/* Display */ -+#define GPIO_DISPLAY_RST_L JZ_GPIO_PORTB(18) -+#define GPIO_DISPLAY_RDY JZ_GPIO_PORTB(17) -+#define GPIO_DISPLAY_STBY JZ_GPIO_PORTC(22) -+#define GPIO_DISPLAY_ERR JZ_GPIO_PORTC(23) -+#define GPIO_DISPLAY_OFF_N JZ_GPIO_PORTD(1) -+ -+#endif /* __ASM_JZ4740_N516_H__ */ ---- a/arch/mips/jz4740/Kconfig -+++ b/arch/mips/jz4740/Kconfig -@@ -6,6 +6,10 @@ choice - config JZ4740_QI_LB60 - bool "Qi Hardware Ben NanoNote" - -+config JZ4740_N516 -+ bool "Hanvon n516 eBook reader" -+ select SOC_JZ4740 -+ - endchoice - - config HAVE_PWM ---- a/arch/mips/jz4740/Makefile -+++ b/arch/mips/jz4740/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs. - # board specific support - - obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o -+obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o - - # PM support - ---- /dev/null -+++ b/arch/mips/jz4740/board-n516-display.c -@@ -0,0 +1,394 @@ -+/* -+ * board-n516-display.c -- Platform device for N516 display -+ * -+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com> -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/irq.h> -+#include <linux/gpio.h> -+ -+#include <asm/mach-jz4740/jz4740_fb.h> -+ -+#include <asm/mach-jz4740/platform.h> -+#include <asm/mach-jz4740/board-n516.h> -+ -+#include <video/metronomefb.h> -+#include <linux/console.h> -+ -+static struct fb_videomode n516_fb_modes[] = { -+ [0] = { -+ .name = "Metronome 800x600", -+ .refresh = 50, -+ .xres = 400, -+ .yres = 624, -+ .hsync_len = 31, -+ .vsync_len = 23, -+ .right_margin = 31, -+ .left_margin = 5, -+ .upper_margin = 1, -+ .lower_margin = 2, -+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, -+ }, -+}; -+ -+static struct jz4740_fb_platform_data n516_fb_pdata = { -+ .num_modes = ARRAY_SIZE(n516_fb_modes), -+ .modes = n516_fb_modes, -+ .bpp = 16, -+ .lcd_type = JZ_LCD_TYPE_GENERIC_16_BIT, -+}; -+ -+struct n516_board_info { -+ uint8_t *metromem; -+ size_t wfm_size; -+ struct fb_info *host_fbinfo; /* the host LCD controller's fbi */ -+ unsigned int fw; -+ unsigned int fh; -+}; -+ -+static struct platform_device *n516_device; -+static struct n516_board_info n516_board_info; -+ -+static int metronome_gpios[] = { -+ GPIO_DISPLAY_STBY, -+ GPIO_DISPLAY_RST_L, -+ GPIO_DISPLAY_RDY, -+ GPIO_DISPLAY_ERR, -+/* GPIO_DISPLAY_OFF_N,*/ -+}; -+ -+static const char *metronome_gpio_names[] = { -+ "Metronome STDBY", -+ "Metronome RST", -+ "Metronome RDY", -+ "Metronome ERR", -+/* "Metronone OFF",*/ -+}; -+ -+static int n516_enable_hostfb(bool enable) -+{ -+ int ret; -+ int blank = enable ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; -+ -+ acquire_console_sem(); -+ ret = fb_blank(n516_board_info.host_fbinfo, blank); -+ release_console_sem(); -+ -+ return ret; -+} -+ -+static int n516_init_metronome_gpios(struct metronomefb_par *par) -+{ -+ int i; -+ int ret; -+ -+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i) { -+ ret = gpio_request(metronome_gpios[i], metronome_gpio_names[i]); -+ if (ret) -+ goto err; -+ } -+ -+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 0); -+ gpio_direction_output(GPIO_DISPLAY_RST_L, 0); -+ gpio_direction_output(GPIO_DISPLAY_STBY, 0); -+ gpio_direction_input(GPIO_DISPLAY_RDY); -+ gpio_direction_input(GPIO_DISPLAY_ERR); -+ -+ return 0; -+err: -+ for (--i; i >= 0; --i) -+ gpio_free(metronome_gpios[i]); -+ -+ return ret; -+} -+ -+static int n516_share_video_mem(struct fb_info *info) -+{ -+ int ret; -+ -+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__); -+ dev_dbg(&n516_device->dev, "%s, info->var.xres = %u, info->var.yres = %u\n", __func__, info->var.xres, info->var.yres); -+ /* rough check if this is our desired fb and not something else */ -+ if ((info->var.xres != n516_fb_pdata.modes[0].xres) -+ || (info->var.yres != n516_fb_pdata.modes[0].yres)) -+ return 0; -+ -+ /* we've now been notified that we have our new fb */ -+ n516_board_info.metromem = info->screen_base; -+ n516_board_info.host_fbinfo = info; -+ -+ n516_enable_hostfb(false); -+ /* try to refcount host drv since we are the consumer after this */ -+ if (!try_module_get(info->fbops->owner)) -+ return -ENODEV; -+ -+ /* this _add binds metronomefb to n516. metronomefb refcounts n516 */ -+ ret = platform_device_add(n516_device); -+ -+ if (ret) { -+ platform_device_put(n516_device); -+ return ret; -+ } -+ -+ /* request our platform independent driver */ -+ request_module("metronomefb"); -+ -+ return 0; -+} -+ -+static int n516_unshare_video_mem(struct fb_info *info) -+{ -+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__); -+ -+ if (info != n516_board_info.host_fbinfo) -+ return 0; -+ -+ module_put(n516_board_info.host_fbinfo->fbops->owner); -+ return 0; -+} -+ -+static int n516_fb_notifier_callback(struct notifier_block *self, -+ unsigned long event, void *data) -+{ -+ struct fb_event *evdata = data; -+ struct fb_info *info = evdata->info; -+ -+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__); -+ -+ if (event == FB_EVENT_FB_REGISTERED) -+ return n516_share_video_mem(info); -+ else if (event == FB_EVENT_FB_UNREGISTERED) -+ return n516_unshare_video_mem(info); -+ -+ return 0; -+} -+ -+static struct notifier_block n516_fb_notif = { -+ .notifier_call = n516_fb_notifier_callback, -+}; -+ -+/* this gets called as part of our init. these steps must be done now so -+ * that we can use set_pxa_fb_info */ -+static void __init n516_presetup_fb(void) -+{ -+ int padding_size; -+ int totalsize; -+ -+ /* the frame buffer is divided as follows: -+ command | CRC | padding -+ 16kb waveform data | CRC | padding -+ image data | CRC -+ */ -+ -+ n516_board_info.fw = 800; -+ n516_board_info.fh = 624; -+ -+ /* waveform must be 16k + 2 for checksum */ -+ n516_board_info.wfm_size = roundup(16*1024 + 2, n516_board_info.fw); -+ -+ padding_size = PAGE_SIZE + (4 * n516_board_info.fw); -+ -+ /* total is 1 cmd , 1 wfm, padding and image */ -+ totalsize = n516_board_info.fw + n516_board_info.wfm_size; -+ totalsize += padding_size + (n516_board_info.fw*n516_board_info.fh); -+ -+ /* save this off because we're manipulating fw after this and -+ * we'll need it when we're ready to setup the framebuffer */ -+ -+ /* the reason we do this adjustment is because we want to acquire -+ * more framebuffer memory without imposing custom awareness on the -+ * underlying driver */ -+ n516_fb_pdata.modes[0].yres = DIV_ROUND_UP(totalsize, n516_board_info.fw); -+ -+ jz4740_framebuffer_device.dev.platform_data = &n516_fb_pdata; -+ platform_device_register(&jz4740_framebuffer_device); -+} -+ -+/* this gets called by metronomefb as part of its init, in our case, we -+ * have already completed initial framebuffer init in presetup_fb so we -+ * can just setup the fb access pointers */ -+static int n516_setup_fb(struct metronomefb_par *par) -+{ -+ /* metromem was set up by the notifier in share_video_mem so now -+ * we can use its value to calculate the other entries */ -+ par->metromem_cmd = (struct metromem_cmd *) n516_board_info.metromem; -+ par->metromem_wfm = n516_board_info.metromem + n516_board_info.fw; -+ par->metromem_img = par->metromem_wfm + n516_board_info.wfm_size; -+ par->metromem_img_csum = (u16 *) (par->metromem_img + (n516_board_info.fw * n516_board_info.fh)); -+ par->metromem_dma = n516_board_info.host_fbinfo->fix.smem_start; -+ -+ return 0; -+} -+ -+static int n516_get_panel_type(void) -+{ -+ return 5; -+} -+ -+static irqreturn_t n516_handle_irq(int irq, void *dev_id) -+{ -+ struct metronomefb_par *par = dev_id; -+ -+ dev_dbg(&par->pdev->dev, "Metronome IRQ! RDY=%d\n", gpio_get_value(GPIO_DISPLAY_RDY)); -+ wake_up_all(&par->waitq); -+ -+ return IRQ_HANDLED; -+} -+ -+static void n516_power_ctl(struct metronomefb_par *par, int cmd) -+{ -+ switch (cmd) { -+ case METRONOME_POWER_OFF: -+ gpio_set_value(GPIO_DISPLAY_OFF_N, 1); -+ n516_enable_hostfb(false); -+ break; -+ case METRONOME_POWER_ON: -+ gpio_set_value(GPIO_DISPLAY_OFF_N, 0); -+ n516_enable_hostfb(true); -+ break; -+ } -+} -+ -+static int n516_get_rdy(struct metronomefb_par *par) -+{ -+ return gpio_get_value(GPIO_DISPLAY_RDY); -+} -+ -+static int n516_get_err(struct metronomefb_par *par) -+{ -+ return gpio_get_value(GPIO_DISPLAY_ERR); -+} -+ -+static int n516_setup_irq(struct fb_info *info) -+{ -+ int ret; -+ -+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__); -+ -+ ret = request_irq(gpio_to_irq(GPIO_DISPLAY_RDY), n516_handle_irq, -+ IRQF_TRIGGER_RISING, -+ "n516", info->par); -+ if (ret) -+ dev_err(&n516_device->dev, "request_irq failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static void n516_set_rst(struct metronomefb_par *par, int state) -+{ -+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ if (state) -+ gpio_set_value(GPIO_DISPLAY_RST_L, 1); -+ else -+ gpio_set_value(GPIO_DISPLAY_RST_L, 0); -+} -+ -+static void n516_set_stdby(struct metronomefb_par *par, int state) -+{ -+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ if (state) -+ gpio_set_value(GPIO_DISPLAY_STBY, 1); -+ else -+ gpio_set_value(GPIO_DISPLAY_STBY, 0); -+} -+ -+static int n516_wait_event(struct metronomefb_par *par) -+{ -+ unsigned long timeout = jiffies + HZ / 20; -+ -+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n", -+ __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ while (n516_get_rdy(par) && time_before(jiffies, timeout)) -+ schedule(); -+ -+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n", -+ __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ return wait_event_timeout(par->waitq, -+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO; -+} -+ -+static int n516_wait_event_intr(struct metronomefb_par *par) -+{ -+ unsigned long timeout = jiffies + HZ/20; -+ -+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n", -+ __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ while (n516_get_rdy(par) && time_before(jiffies, timeout)) -+ schedule(); -+ -+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n", -+ __func__, gpio_get_value(GPIO_DISPLAY_RDY)); -+ return wait_event_interruptible_timeout(par->waitq, -+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO; -+} -+ -+static void n516_cleanup(struct metronomefb_par *par) -+{ -+ int i; -+ -+ free_irq(gpio_to_irq(GPIO_DISPLAY_RDY), par); -+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i) -+ gpio_free(metronome_gpios[i]); -+} -+ -+static struct metronome_board n516_board __initdata = { -+ .owner = THIS_MODULE, -+ .power_ctl = n516_power_ctl, -+ .setup_irq = n516_setup_irq, -+ .setup_io = n516_init_metronome_gpios, -+ .setup_fb = n516_setup_fb, -+ .set_rst = n516_set_rst, -+ .get_err = n516_get_err, -+ .get_rdy = n516_get_rdy, -+ .set_stdby = n516_set_stdby, -+ .met_wait_event = n516_wait_event, -+ .met_wait_event_intr = n516_wait_event_intr, -+ .get_panel_type = n516_get_panel_type, -+ .cleanup = n516_cleanup, -+}; -+ -+static int __init n516_init(void) -+{ -+ int ret; -+ -+ /* Keep the metronome off, until its driver is loaded */ -+ ret = gpio_request(GPIO_DISPLAY_OFF_N, "Display off"); -+ if (ret) -+ return ret; -+ -+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 1); -+ -+ /* before anything else, we request notification for any fb -+ * creation events */ -+ fb_register_client(&n516_fb_notif); -+ -+ n516_device = platform_device_alloc("metronomefb", -1); -+ if (!n516_device) -+ return -ENOMEM; -+ -+ /* the n516_board that will be seen by metronomefb is a copy */ -+ platform_device_add_data(n516_device, &n516_board, -+ sizeof(n516_board)); -+ -+ n516_presetup_fb(); -+ -+ return 0; -+} -+module_init(n516_init); -+ -+MODULE_DESCRIPTION("board driver for n516 display"); -+MODULE_AUTHOR("Yauhen Kharuzhy"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/arch/mips/jz4740/board-n516.c -@@ -0,0 +1,182 @@ -+/* -+ * linux/arch/mips/jz4740/board-516.c -+ * -+ * JZ4740 n516 board setup routines. -+ * -+ * Copyright (c) 2009, Yauhen Kharuzhy <jekhor@gmail.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/init.h> -+#include <linux/sched.h> -+#include <linux/ioport.h> -+#include <linux/mm.h> -+#include <linux/console.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/platform_device.h> -+#include <linux/mtd/mtd.h> -+#include <linux/leds.h> -+ -+#include <linux/power_supply.h> -+#include <linux/power/gpio-charger.h> -+ -+#include <linux/i2c.h> -+ -+#include <asm/mach-jz4740/jz4740_mmc.h> -+#include <asm/mach-jz4740/jz4740_nand.h> -+ -+#include <asm/mach-jz4740/board-n516.h> -+#include <asm/mach-jz4740/platform.h> -+ -+#include "clock.h" -+ -+static long n516_panic_blink(int state) -+{ -+ gpio_set_value(GPIO_LED_ENABLE, state ? 1 : 0); -+ return 0; -+} -+ -+static void __init board_gpio_setup(void) -+{ -+/* jz_gpio_enable_pullup(JZ_GPIO_PORTD(23)); -+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(24));*/ -+} -+ -+static const struct i2c_board_info n516_i2c_board_info[] = { -+ { -+ .type = "LPC524", -+ .addr = 0x54, -+ }, -+ { -+ .type = "lm75a", -+ .addr = 0x48, -+ } -+}; -+ -+static struct jz4740_mmc_platform_data n516_mmc_pdata = { -+ .gpio_card_detect = GPIO_SD_CD_N, -+ .card_detect_active_low = 1, -+ .gpio_read_only = -1, -+ .gpio_power = GPIO_SD_VCC_EN_N, -+ .power_active_low = 1, -+}; -+ -+static struct gpio_led n516_leds[] = { -+ { -+ .name = "n516:blue:power", -+ .gpio = GPIO_LED_ENABLE, -+ .default_state = LEDS_GPIO_DEFSTATE_ON, -+ .default_trigger = "nand-disk", -+ } -+}; -+ -+static struct gpio_led_platform_data n516_leds_pdata = { -+ .leds = n516_leds, -+ .num_leds = ARRAY_SIZE(n516_leds), -+}; -+ -+static struct platform_device n516_leds_device = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev = { -+ .platform_data = &n516_leds_pdata, -+ }, -+}; -+ -+static struct mtd_partition n516_partitions[] = { -+ { .name = "NAND BOOT partition", -+ .offset = 0 * 0x100000, -+ .size = 4 * 0x100000, -+ }, -+ { .name = "NAND KERNEL partition", -+ .offset = 4 * 0x100000, -+ .size = 4 * 0x100000, -+ }, -+ { .name = "NAND ROOTFS partition", -+ .offset = 8 * 0x100000, -+ .size = 504 * 0x100000, -+ }, -+}; -+ -+static struct nand_ecclayout n516_ecclayout = { -+ .eccbytes = 36, -+ .eccpos = { -+ 6, 7, 8, 9, 10, 11, 12, 13, 14, -+ 15, 16, 17, 18, 19, 20, 21, 22, 23, -+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -+ 33, 34, 35, 36, 37, 38, 39, 40, 41, -+ }, -+ .oobfree = { -+ { -+ .offset = 2, -+ .length = 4 -+ }, -+ { -+ .offset = 42, -+ .length = 22, -+ } -+ } -+}; -+ -+static struct jz_nand_platform_data n516_nand_pdata = { -+ .ecc_layout = &n516_ecclayout, -+ .partitions = n516_partitions, -+ .num_partitions = ARRAY_SIZE(n516_partitions), -+ .busy_gpio = 94, -+}; -+ -+static char *n516_batteries[] = { -+ "n516_battery", -+}; -+ -+static struct gpio_charger_platform_data n516_charger_pdata = { -+ .name = "usb", -+ .type = POWER_SUPPLY_TYPE_USB, -+ .gpio = GPIO_USB_DETECT, -+ .gpio_active_low = 1, -+ .batteries = n516_batteries, -+ .num_batteries = ARRAY_SIZE(n516_batteries), -+}; -+ -+static struct platform_device n516_charger_device = { -+ .name = "gpio-charger", -+ .dev = { -+ .platform_data = &n516_charger_pdata, -+ }, -+}; -+ -+static struct platform_device *n516_devices[] __initdata = { -+ &jz4740_nand_device, -+ &n516_leds_device, -+ &jz4740_mmc_device, -+ &jz4740_i2s_device, -+ &jz4740_codec_device, -+ &jz4740_rtc_device, -+ &jz4740_udc_device, -+ &jz4740_i2c_device, -+ &n516_charger_device, -+}; -+ -+struct jz4740_clock_board_data jz4740_clock_bdata = { -+ .ext_rate = 12000000, -+ .rtc_rate = 32768, -+}; -+ -+static int n516_setup_platform(void) -+{ -+ jz4740_serial_device_register(); -+ board_gpio_setup(); -+ -+ panic_blink = n516_panic_blink; -+ i2c_register_board_info(0, n516_i2c_board_info, ARRAY_SIZE(n516_i2c_board_info)); -+ jz4740_mmc_device.dev.platform_data = &n516_mmc_pdata; -+ jz4740_nand_device.dev.platform_data = &n516_nand_pdata; -+ -+ return platform_add_devices(n516_devices, ARRAY_SIZE(n516_devices)); -+} -+arch_initcall(n516_setup_platform); |