diff options
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.patch | 793 |
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 + |