summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch')
-rw-r--r--recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch793
1 files changed, 793 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch b/recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch
new file mode 100644
index 0000000000..fd803dd405
--- /dev/null
+++ b/recipes/linux/linux-2.6.29/micro2440/0007-MINI2440-Add-machine-support.patch
@@ -0,0 +1,793 @@
+From df4ff90ba57c3a4d2c52e9cb6fb808f682b0a87c Mon Sep 17 00:00:00 2001
+From: Michel Pollet <buserror@gmail.com>
+Date: Wed, 25 Mar 2009 17:19:14 +0000
+Subject: [PATCH] MINI2440: Add machine support
+
+The MINI2440 is a chinese made s3c2440 develpment board with
+a large set of peripherals.
+This patch provides machine support for almost all the features
+of the board.
+
+Since it can come with various "options" fitted, a kernel parameter
+is used to specify the lcd size, backlight control and touchscreen.
+
+Signed-off-by: Michel Pollet <buserror@gmail.com>
+---
+ arch/arm/mach-s3c2440/Kconfig | 10 +
+ arch/arm/mach-s3c2440/Makefile | 1 +
+ arch/arm/mach-s3c2440/mach-mini2440.c | 734 +++++++++++++++++++++++++++++++++
+ 3 files changed, 745 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-s3c2440/mach-mini2440.c
+
+diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
+index cde5ae9..7953c22 100644
+--- a/arch/arm/mach-s3c2440/Kconfig
++++ b/arch/arm/mach-s3c2440/Kconfig
+@@ -79,5 +79,15 @@ config MACH_AT2440EVB
+ help
+ Say Y here if you are using the AT2440EVB development board
+
++config MACH_MINI2440
++ bool "MINI2440 development board"
++ select CPU_S3C2440
++ select EEPROM_AT24
++ select BACKLIGHT_PWM
++ select SND_S3C24XX_SOC_S3C24XX_UDA134X
++ help
++ Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
++ available via various sources. It can come with a 3.5" or 7" touch LCD.
++
+ endmenu
+
+diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
+index 0b4440e..bfadcf6 100644
+--- a/arch/arm/mach-s3c2440/Makefile
++++ b/arch/arm/mach-s3c2440/Makefile
+@@ -22,3 +22,4 @@ obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
+ obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
+ obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+ obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
++obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
+diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
+new file mode 100644
+index 0000000..0cddb11
+--- /dev/null
++++ b/arch/arm/mach-s3c2440/mach-mini2440.c
+@@ -0,0 +1,734 @@
++/* linux/arch/arm/mach-s3c2440/mach-mini2440.c
++ *
++ * Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com>
++ * Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk>
++ * and modifications by SBZ <sbz@spgui.org> and
++ * Weibing <http://weibing.blogbus.com>
++ * Michel Pollet <buserror@gmail.com>
++ *
++ * For product information, visit http://code.google.com/p/mini2440/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/list.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <linux/serial_core.h>
++#include <linux/dm9000.h>
++#include <linux/i2c/at24.h>
++#include <linux/platform_device.h>
++#include <linux/gpio_keys.h>
++#include <linux/i2c.h>
++#include <linux/mmc/host.h>
++#include <linux/pwm_backlight.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++#include <mach/hardware.h>
++#include <mach/fb.h>
++#include <asm/mach-types.h>
++
++#include <plat/regs-serial.h>
++#include <mach/regs-gpio.h>
++#include <mach/leds-gpio.h>
++#include <mach/regs-mem.h>
++#include <mach/regs-lcd.h>
++#include <mach/irqs.h>
++#include <plat/nand.h>
++#include <plat/iic.h>
++#include <plat/mci.h>
++#include <plat/udc.h>
++
++#include <plat/regs-serial.h>
++#include <mach/regs-gpio.h>
++#include <mach/regs-mem.h>
++#include <mach/regs-lcd.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/nand_ecc.h>
++#include <linux/mtd/partitions.h>
++
++#include <plat/clock.h>
++#include <plat/devs.h>
++#include <plat/cpu.h>
++
++#include <sound/s3c24xx_uda134x.h>
++
++#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)
++
++static struct map_desc mini2440_iodesc[] __initdata = {
++ /* nothing to declare, move along */
++};
++
++#define UCON S3C2410_UCON_DEFAULT
++#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
++#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
++
++
++static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = {
++ [0] = {
++ .hwport = 0,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ },
++ [1] = {
++ .hwport = 1,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ },
++ [2] = {
++ .hwport = 2,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ },
++};
++
++/* USB device UDC support */
++
++static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd)
++{
++ printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
++
++ switch (cmd) {
++ case S3C2410_UDC_P_ENABLE :
++ s3c2410_gpio_setpin(S3C2410_GPC5, 1);
++ break;
++ case S3C2410_UDC_P_DISABLE :
++ s3c2410_gpio_setpin(S3C2410_GPC5, 0);
++ break;
++ case S3C2410_UDC_P_RESET :
++ break;
++ default:
++ break;
++ }
++}
++
++static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
++ .udc_command = mini2440_udc_pullup,
++};
++
++
++/* LCD timing and setup */
++
++/*
++ * This macro simplifies the table bellow
++ */
++#define _LCD_DECLARE(_xres,margin_left,margin_right,hsync, \
++ _yres,margin_top,margin_bottom,vsync, refresh) \
++ .width = _xres, \
++ .xres = _xres, \
++ .height = _yres, \
++ .yres = _yres, \
++ .left_margin = margin_left, \
++ .right_margin = margin_right, \
++ .upper_margin = margin_top, \
++ .lower_margin = margin_bottom, \
++ .hsync_len = hsync, \
++ .vsync_len = vsync, \
++ .pixclock = (1000000000000LL / \
++ ((refresh) * \
++ (hsync + margin_left + _xres + margin_right) * \
++ (vsync + margin_top + _yres + margin_bottom))), \
++ .bpp = 16,\
++ .type = (S3C2410_LCDCON1_TFT16BPP |\
++ S3C2410_LCDCON1_TFT),
++
++struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
++ [0] = { // mini2440 + 3.5" TFT + touchscreen
++ _LCD_DECLARE(
++ 240, 21, 38, 6, /* x timing */
++ 320, 2, 6, 2, /* y timing */
++ 60) /* refresh rate */
++ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |\
++ S3C2410_LCDCON5_INVVLINE |\
++ S3C2410_LCDCON5_INVVFRAME |\
++ S3C2410_LCDCON5_INVVDEN |\
++ S3C2410_LCDCON5_PWREN),
++ },
++ [1] = { // mini2440 + 7" TFT + touchscreen
++ _LCD_DECLARE(
++ 800, 40, 40, 48, /* x timing */
++ 480, 29, 3, 3, /* y timing */
++ 50) /* refresh rate */
++ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |\
++ S3C2410_LCDCON5_INVVLINE |\
++ S3C2410_LCDCON5_INVVFRAME |\
++ S3C2410_LCDCON5_PWREN),
++ },
++ /* VGA all share the timings
++ * NOTE: The VGA board seems to always output at 1024x768
++ * unless you add the dip-switch block. The smaller resolution
++ * WILL work, but be displayed in the top/left corner on the VGA screen
++ */
++ [2] = {
++ _LCD_DECLARE(
++ 1024, 1, 2, 2, /* y timing */
++ 768, 200, 16, 16, /* x timing */
++ 24) /* refresh rate, maximum stable,
++ tested with the FPGA shield */
++ .lcdcon5 = (S3C2410_LCDCON5_FRM565 |\
++ S3C2410_LCDCON5_HWSWP),
++ },
++};
++
++/* todo - put into gpio header */
++
++#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
++#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
++
++struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
++ .displays = &mini2440_lcd_cfg[0], /* not constant! see init */
++ .num_displays = 1,
++ .default_display = 0,
++
++ /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
++ * and disable the pull down resistors on pins we are using for LCD
++ * data. */
++
++ .gpcup = (0xf << 1) | (0x3f << 10),
++
++ .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |
++ S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
++ S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |
++ S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 |
++ S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7),
++
++ .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) |
++ S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) |
++ S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
++ S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
++ S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
++
++ .gpdup = (0x3f << 2) | (0x3f << 10),
++
++ .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 |
++ S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |
++ S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |
++ S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
++ S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
++ S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
++
++ .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) |
++ S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) |
++ S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) |
++ S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
++ S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
++ S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
++};
++
++/* MMC/SD */
++
++static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = {
++ .gpio_detect = S3C2410_GPG8,
++ .gpio_wprotect = S3C2410_GPH8,
++ .set_power = NULL,
++ .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34,
++};
++
++/* NAND Flash on MINI2440 board */
++
++static struct mtd_partition mini2440_default_nand_part[] __initdata = {
++ [0] = {
++ .name = "u-boot",
++ .size = SZ_256K,
++ .offset = 0,
++ },
++ [1] = {
++ .name = "u-boot-env",
++ .size = SZ_128K,
++ .offset = SZ_256K,
++ },
++ [2] = {
++ .name = "kernel",
++ /* 5 megabytes, for a kernel with no modules
++ * or a uImage with a ramdisk attached */
++ .size = 0x00500000,
++ .offset = SZ_256K + SZ_128K,
++ },
++ [3] = {
++ .name = "root",
++ .offset = SZ_256K + SZ_128K + 0x00500000,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
++ [0] = {
++ .name = "nand",
++ .nr_chips = 1,
++ .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
++ .partitions = mini2440_default_nand_part,
++ .flash_bbt = 1, /* we use u-boot to create a BBT */
++ },
++};
++
++static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
++ .tacls = 0,
++ .twrph0 = 25,
++ .twrph1 = 15,
++ .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
++ .sets = mini2440_nand_sets,
++ .ignore_unset_ecc = 1,
++};
++
++/* DM9000AEP 10/100 ethernet controller */
++
++static struct resource mini2440_dm9k_resource[] __initdata = {
++ [0] = {
++ .start = MACH_MINI2440_DM9K_BASE,
++ .end = MACH_MINI2440_DM9K_BASE + 3,
++ .flags = IORESOURCE_MEM
++ },
++ [1] = {
++ .start = MACH_MINI2440_DM9K_BASE + 4,
++ .end = MACH_MINI2440_DM9K_BASE + 7,
++ .flags = IORESOURCE_MEM
++ },
++ [2] = {
++ .start = IRQ_EINT7,
++ .end = IRQ_EINT7,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++ }
++};
++
++static struct dm9000_plat_data mini2440_dm9k_pdata __initdata = {
++ .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
++};
++
++static struct platform_device mini2440_device_eth __initdata = {
++ .name = "dm9000",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(mini2440_dm9k_resource),
++ .resource = mini2440_dm9k_resource,
++ .dev = {
++ .platform_data = &mini2440_dm9k_pdata,
++ },
++};
++
++/* backlight */
++
++static int mini2440_backlight_init(struct device *dev)
++{
++ return 0;
++}
++/*
++ * Cut the power to the LCD if brightness reaches 0
++ */
++static int mini2440_backlight_notify(int brightness)
++{
++ if (brightness) {
++ s3c2410_gpio_setpin(S3C2410_GPB1, 1);
++ s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
++ s3c2410_gpio_setpin(S3C2410_GPG4, 1);
++ s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_LCDPWREN);
++ } else {
++ s3c2410_gpio_setpin(S3C2410_GPB1, 0);
++ s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_OUTP);
++ s3c2410_gpio_setpin(S3C2410_GPG4, 0);
++ s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_OUTP);
++ }
++ return brightness;
++}
++
++static struct platform_pwm_backlight_data mini2440_backlight_data __initdata = {
++ .pwm_id = 1,
++ .max_brightness = 1023,
++ .dft_brightness = 900,
++ .pwm_period_ns = 4000000, /* Fl = 250Hz PWM */
++ .init = mini2440_backlight_init,
++ .notify = mini2440_backlight_notify,
++};
++
++static struct platform_device mini2440_backlight_device __initdata = {
++ .name = "pwm-backlight",
++ .dev = {
++ .platform_data = &mini2440_backlight_data,
++ },
++};
++
++/* CON5
++ * +--+ /-----\
++ * | | | |
++ * | | | BAT |
++ * | | \_____/
++ * | |
++ * | | +----+ +----+
++ * | | | K5 | | K1 |
++ * | | +----+ +----+
++ * | | +----+ +----+
++ * | | | K4 | | K2 |
++ * | | +----+ +----+
++ * | | +----+ +----+
++ * | | | K6 | | K3 |
++ * | | +----+ +----+
++ * .....
++ */
++static struct gpio_keys_button mini2440_buttons[] __initdata = {
++ {
++ .gpio = S3C2410_GPG0, /* K1 */
++ .code = KEY_F1,
++ .desc = "Button 1",
++ .active_low = 1,
++ },
++ {
++ .gpio = S3C2410_GPG3, /* K2 */
++ .code = KEY_F2,
++ .desc = "Button 2",
++ .active_low = 1,
++ },
++ {
++ .gpio = S3C2410_GPG5, /* K3 */
++ .code = KEY_F3,
++ .desc = "Button 3",
++ .active_low = 1,
++ },
++ {
++ .gpio = S3C2410_GPG6, /* K4 */
++ .code = KEY_POWER,
++ .desc = "Power",
++ .active_low = 1,
++ },
++ {
++ .gpio = S3C2410_GPG7, /* K5 */
++ .code = KEY_F5,
++ .desc = "Button 5",
++ .active_low = 1,
++ },
++#if 0
++ /* this pin is also known as TCLK1 and seems to already
++ * marked as "in use" somehow in the kernel -- possibly wrongly */
++ {
++ .gpio = S3C2410_GPG11, /* K6 */
++ .code = KEY_F6,
++ .desc = "Button 6",
++ .active_low = 1,
++ },
++#endif
++};
++
++static struct gpio_keys_platform_data mini2440_button_data __initdata = {
++ .buttons = mini2440_buttons,
++ .nbuttons = ARRAY_SIZE(mini2440_buttons),
++};
++
++static struct platform_device mini2440_button_device __initdata = {
++ .name = "gpio-keys",
++ .id = -1,
++ .dev = {
++ .platform_data = &mini2440_button_data,
++ }
++};
++
++/* LEDS */
++
++static struct s3c24xx_led_platdata mini2440_led1_pdata __initdata = {
++ .name = "led1",
++ .gpio = S3C2410_GPB5,
++ .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
++ .def_trigger = "heartbeat",
++};
++
++static struct s3c24xx_led_platdata mini2440_led2_pdata __initdata = {
++ .name = "led2",
++ .gpio = S3C2410_GPB6,
++ .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
++ .def_trigger = "nand-disk",
++};
++
++static struct s3c24xx_led_platdata mini2440_led3_pdata __initdata = {
++ .name = "led3",
++ .gpio = S3C2410_GPB7,
++ .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
++ .def_trigger = "mmc0",
++};
++
++static struct s3c24xx_led_platdata mini2440_led4_pdata __initdata = {
++ .name = "led4",
++ .gpio = S3C2410_GPB8,
++ .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
++ .def_trigger = "",
++};
++
++static struct platform_device mini2440_led1 __initdata = {
++ .name = "s3c24xx_led",
++ .id = 1,
++ .dev = {
++ .platform_data = &mini2440_led1_pdata,
++ },
++};
++
++static struct platform_device mini2440_led2 __initdata = {
++ .name = "s3c24xx_led",
++ .id = 2,
++ .dev = {
++ .platform_data = &mini2440_led2_pdata,
++ },
++};
++
++static struct platform_device mini2440_led3 __initdata = {
++ .name = "s3c24xx_led",
++ .id = 3,
++ .dev = {
++ .platform_data = &mini2440_led3_pdata,
++ },
++};
++
++static struct platform_device mini2440_led4 __initdata = {
++ .name = "s3c24xx_led",
++ .id = 4,
++ .dev = {
++ .platform_data = &mini2440_led4_pdata,
++ },
++};
++
++/* AUDIO */
++
++static struct s3c24xx_uda134x_platform_data mini2440_audio_pins __initdata = {
++ .l3_clk = S3C2410_GPB4,
++ .l3_mode = S3C2410_GPB2,
++ .l3_data = S3C2410_GPB3,
++ .model = UDA134X_UDA1341
++};
++
++static struct platform_device mini2440_audio __initdata = {
++ .name = "s3c24xx_uda134x",
++ .id = 0,
++ .dev = {
++ .platform_data = &mini2440_audio_pins,
++ },
++};
++
++/*
++ * I2C devices
++ */
++static struct at24_platform_data at24c08 = {
++ .byte_len = SZ_8K / 8,
++ .page_size = 16,
++};
++
++static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
++ {
++ I2C_BOARD_INFO("24c08", 0x50),
++ .platform_data = &at24c08,
++ },
++};
++
++/* We can run that eeprom at 400khz */
++static struct s3c2410_platform_i2c mini2440_i2c_info __initdata = {
++ .flags = 0,
++ .slave_addr = 0x10,
++ .bus_freq = 400*1000,
++ .max_freq = 400*1000,
++};
++
++
++static struct platform_device *mini2440_devices[] __initdata = {
++ &s3c_device_usb,
++ &s3c_device_wdt,
++/* &s3c_device_adc,*/ /* ADC doesn't like living with touchscreen ! */
++ &s3c_device_i2c0,
++ &s3c_device_rtc,
++ &s3c_device_usbgadget,
++ &mini2440_device_eth,
++ &mini2440_led1,
++ &mini2440_led2,
++ &mini2440_led3,
++ &mini2440_led4,
++ &mini2440_button_device,
++ &s3c_device_nand,
++ &s3c_device_sdi,
++ &s3c_device_iis,
++ &mini2440_audio,
++/* &s3c_device_timer[0],*/ /* buzzer pwm, no API for it */
++ /* remaining devices are optional */
++};
++
++static void __init mini2440_map_io(void)
++{
++ s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
++ s3c24xx_init_clocks(12000000);
++ s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
++
++ s3c_device_nand.dev.platform_data = &mini2440_nand_info;
++ s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
++}
++
++/*
++ * mini2440_features string
++ *
++ * t = Touchscreen present
++ * b = PWM backlight control
++ * c = camera [TODO]
++ * 0-9 LCD configuration
++ *
++ */
++static char mini2440_features_str[12] __initdata = "0tb";
++
++static int __init mini2440_features_setup(char *str)
++{
++ if (str)
++ strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str));
++ return 1;
++}
++
++__setup("mini2440=", mini2440_features_setup);
++
++#define FEATURE_SCREEN (1 << 0)
++#define FEATURE_BACKLIGHT (1 << 1)
++#define FEATURE_TOUCH (1 << 2)
++#define FEATURE_CAMERA (1 << 3)
++
++struct mini2440_features_t {
++ int count;
++ int done;
++ int lcd_index;
++ struct platform_device *optional[8];
++};
++
++static void mini2440_parse_features(
++ struct mini2440_features_t * features,
++ const char * features_str )
++{
++ const char * fp = features_str;
++
++ features->count = 0;
++ features->done = 0;
++ features->lcd_index = -1;
++
++ while (*fp) {
++ char f = *fp++;
++
++ switch (f) {
++ case '0'...'9': /* tft screen */
++ if (features->done & FEATURE_SCREEN) {
++ printk(KERN_INFO "MINI2440: '%c' ignored, "
++ "screen type already set\n", f);
++ } else {
++ int li = f - '0';
++ if (li >= ARRAY_SIZE(mini2440_lcd_cfg))
++ printk(KERN_INFO "MINI2440: "
++ "'%c' out of range LCD mode\n", f);
++ else {
++ features->optional[features->count++] =
++ &s3c_device_lcd;
++ features->lcd_index = li;
++ }
++ }
++ features->done |= FEATURE_SCREEN;
++ break;
++ case 'b':
++ if (features->done & FEATURE_BACKLIGHT)
++ printk(KERN_INFO "MINI2440: '%c' ignored, "
++ "backlight already set\n", f);
++ else {
++ /* need this timer for the backlight */
++ features->optional[features->count++] =
++ &s3c_device_timer[1];
++ features->optional[features->count++] =
++ &mini2440_backlight_device;
++ }
++ features->done |= FEATURE_BACKLIGHT;
++ break;
++ case 't':
++ printk(KERN_INFO "MINI2440: '%c' ignored, "
++ "touchscreen not compiled in\n", f);
++ break;
++ case 'c':
++ if (features->done & FEATURE_CAMERA)
++ printk(KERN_INFO "MINI2440: '%c' ignored, "
++ "camera already registered\n", f);
++ else
++ features->optional[features->count++] =
++ &s3c_device_camif;
++ features->done |= FEATURE_CAMERA;
++ break;
++ }
++ }
++}
++
++static void __init mini2440_init(void)
++{
++ struct mini2440_features_t features = { 0 };
++ int i;
++
++ printk(KERN_INFO "MINI2440: Option string mini2440=%s\n",
++ mini2440_features_str);
++
++ /* Parse the feature string */
++ mini2440_parse_features(&features, mini2440_features_str);
++
++ /* turn LCD on */
++ s3c2410_gpio_cfgpin(S3C2410_GPC0, S3C2410_GPC0_LEND);
++
++ /* remove pullup on PWM backlight */
++ s3c2410_gpio_pullup(S3C2410_GPB1, 0);
++ s3c2410_gpio_setpin(S3C2410_GPB1, 0);
++ s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
++
++ /* Make sure the D+ pullup pin is output */
++ s3c2410_gpio_cfgpin(S3C2410_GPC5, S3C2410_GPIO_OUTPUT);
++
++ /* mark the key as inout, without pullups (there is one on the board) */
++ for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
++ s3c2410_gpio_pullup(mini2440_buttons[i].gpio, 0);
++ s3c2410_gpio_cfgpin(mini2440_buttons[i].gpio,
++ S3C2410_GPIO_INPUT);
++ }
++ if (features.lcd_index != -1) {
++ int li;
++
++ mini2440_fb_info.displays =
++ &mini2440_lcd_cfg[features.lcd_index];
++
++ printk(KERN_INFO "MINI2440: LCD");
++ for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
++ if (li == features.lcd_index)
++ printk(" [%d:%dx%d]", li,
++ mini2440_lcd_cfg[li].width,
++ mini2440_lcd_cfg[li].height);
++ else
++ printk(" %d:%dx%d", li,
++ mini2440_lcd_cfg[li].width,
++ mini2440_lcd_cfg[li].height);
++ printk("\n");
++ s3c24xx_fb_set_platdata(&mini2440_fb_info);
++ }
++ s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
++ s3c_i2c0_set_platdata(&mini2440_i2c_info);
++ i2c_register_board_info(0, mini2440_i2c_devs,
++ ARRAY_SIZE(mini2440_i2c_devs));
++
++ platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
++
++ if (features.count) /* the optional features */
++ platform_add_devices(features.optional, features.count);
++
++}
++
++
++MACHINE_START(MINI2440, "MINI2440")
++ /* Maintainer: Michel Pollet <buserror@gmail.com> */
++ .phys_io = S3C2410_PA_UART,
++ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
++ .boot_params = S3C2410_SDRAM_PA + 0x100,
++ .map_io = mini2440_map_io,
++ .init_machine = mini2440_init,
++ .init_irq = s3c24xx_init_irq,
++ .timer = &s3c24xx_timer,
++MACHINE_END
+--
+1.5.6.3
+