diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/clock.c linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/clock.c --- linux-2.6.28.5/arch/arm/mach-s3c2410/clock.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/clock.c 2009-02-14 15:49:39.000000000 +0100 @@ -89,12 +89,6 @@ static int s3c2410_upll_enable(struct cl static struct clk init_clocks_disable[] = { { - .name = "nand", - .id = -1, - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND, - }, { .name = "sdi", .id = -1, .parent = &clk_p, @@ -129,6 +123,12 @@ static struct clk init_clocks_disable[] static struct clk init_clocks[] = { { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_NAND, + }, { .name = "lcd", .id = -1, .parent = &clk_h, @@ -160,18 +160,21 @@ static struct clk init_clocks[] = { .ctrlbit = S3C2410_CLKCON_PWMT, }, { .name = "uart", + .sys_name = "uart.0", .id = 0, .parent = &clk_p, .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_UART0, }, { .name = "uart", + .sys_name = "uart.1", .id = 1, .parent = &clk_p, .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_UART1, }, { .name = "uart", + .sys_name = "uart.2", .id = 2, .parent = &clk_p, .enable = s3c2410_clkcon_enable, diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/Kconfig linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Kconfig --- linux-2.6.28.5/arch/arm/mach-s3c2410/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Kconfig 2009-01-06 18:24:37.000000000 +0100 @@ -133,4 +133,10 @@ config MACH_QT2410 help Say Y here if you are using the Armzone QT2410 +config MACH_RD129 + bool "RD129" + select CPU_S3C2410 + help + Say Y here if you are using the Elpa RD129 Cpu board + endmenu diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/mach-rd129.c linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/mach-rd129.c --- linux-2.6.28.5/arch/arm/mach-s3c2410/mach-rd129.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/mach-rd129.c 2009-02-15 12:02:06.000000000 +0100 @@ -0,0 +1,790 @@ +/* + * linux/arch/arm/mach-s3c2410/mach-rd129.c + * + * Copyright (c) 2007 ELPA sas + * Davide Rizzo + * + * RD129 card specific code + * + * RD129 is based on a Samsung S3C2410 SoC + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 rd129_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, + } +}; + +/* NAND parititions for rd129 */ +static struct mtd_partition rd129_default_nand_part[] = { + [0] = { + .name = "boot", + .size = SZ_1M, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, + [1] = { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + }, + [2] = { + .name = "root", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, + [3] = { + .name = "dummy", + .offset = MTDPART_OFS_APPEND, + .size = 0, + }, + [4] = { + .name = "dummy", + .offset = MTDPART_OFS_APPEND, + .size = 0, + }, + [5] = { + .name = "dummy", + .offset = MTDPART_OFS_APPEND, + .size = 0, + }, + [6] = { + .name = "dummy", + .offset = MTDPART_OFS_APPEND, + .size = 0, + }, + [7] = { + .name = "dummy", + .offset = MTDPART_OFS_APPEND, + .size = 0, + } +}; + +static struct s3c2410_nand_set rd129_nand_sets[] = { + [0] = { + .name = "s3c2410-nand", + .nr_chips = 1, + .nr_partitions = 3, + .partitions = rd129_default_nand_part, + }, +}; + +static struct s3c2410_platform_nand rd129_nand_info = { + .tacls = 10, + .twrph0 = 30, + .twrph1 = 10, + .nr_sets = ARRAY_SIZE(rd129_nand_sets), + .sets = rd129_nand_sets, +}; + +static struct s3c24xx_mci_pdata rd129_mmc_cfg = { + .gpio_detect = S3C2410_GPG0, + .gpio_wprotect = S3C2410_GPG1, + .set_power = NULL, + .ocr_avail = MMC_VDD_32_33, +}; + +static struct s3c24xx_gpio_platdata rd129_gpio_cfg = { + .port_mask = { + 0x21F000, 0x00001F, 0x00FF1F, 0x00FFFF, + 0x00FFFF, 0x0000FF, 0x00FFFF, 0x0006FF + } +}; + +static struct platform_device s3c_device_gpio = { + .name = "s3c2410-gpio", + .id = -1, + .dev = { + .platform_data = &rd129_gpio_cfg, + } +}; + +#ifdef CONFIG_BACKLIGHT_PWM +static struct platform_pwm_backlight_data rd129_backlight = { +/* Timer 0 is used by LCD backlight driver */ + .pwm_id = 0, + .max_brightness = 100, + .dft_brightness = 100, + .pwm_period_ns = 1000000000 / CONFIG_BACKLIGHT_PWM_FREQUENCY, +}; + +static struct platform_device s3c_device_backlight = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .platform_data = &rd129_backlight, + } +}; +#else /* CONFIG_BACKLIGHT_PWM */ +static struct platform_device s3c_device_timer0 = { + .name = "um_timer", + .id = 0, +}; +#endif /* CONFIG_BACKLIGHT_PWM */ + +static struct platform_device s3c_device_timer1 = { + .name = "um_timer", + .id = 1, +}; + +static struct platform_device s3c_device_timer2 = { + .name = "um_timer", + .id = 2, +}; + +static struct platform_device s3c_device_timer3 = { + .name = "um_timer", + .id = 3, +}; + +/* + * GPIO Buttons + */ +static struct gpio_keys_button buttons[] = { + { + .gpio = S3C2410_GPF0, + .code = KEY_LEFT, + .desc = "Left", + .active_low = 1, + }, + { + .gpio = S3C2410_GPF1, + .code = KEY_RIGHT, + .desc = "Right", + .active_low = 1, + }, + { + .gpio = S3C2410_GPF2, + .code = KEY_SPACE, + .desc = "Space", + .active_low = 1, + }, + { + .gpio = S3C2410_GPF3, + .code = KEY_TAB, + .desc = "Tab", + .active_low = 1, + }, + { + .gpio = S3C2410_GPF4, + .code = KEY_ESC, + .desc = "Escape", + .active_low = 1, + } +}; + +static struct gpio_keys_platform_data button_data = { + .buttons = buttons, + .nbuttons = ARRAY_SIZE(buttons), +}; + +static struct platform_device button_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &button_data, + } +}; + +/* devices we initialise */ +static struct platform_device *rd129_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_adc, + &s3c_device_i2c, + &s3c_device_iis, + &s3c_device_sdi, + &s3c_device_nand, + &s3c_device_timer[0], + &s3c_device_timer[1], + &s3c_device_timer[2], + &s3c_device_timer[3], + &s3c_device_gpio, + &s3c_device_spi0, + &s3c_device_spi1, +#ifdef CONFIG_BACKLIGHT_PWM + &s3c_device_backlight, +#else /* CONFIG_BACKLIGHT_PWM */ + &s3c_device_timer0, +#endif /* CONFIG_BACKLIGHT_PWM */ + &s3c_device_timer1, + &s3c_device_timer2, + &s3c_device_timer3, + &button_device, +}; + +static struct map_desc rd129_iodesc[] __initdata = { +}; + +static struct s3c2410fb_display s3c2410_fb_displays[] = { + { + /* Hitachi TX09D70VM1CCA 3.5" 240x320 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + .xres = 240, + .yres = 320, + .bpp = 8, + .pixclock = 186697, /* 327*273*60=5.35626MHz */ + .left_margin = 17, + .right_margin = 11, + .hsync_len = 5, + .upper_margin = 4, + .lower_margin = 2, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Hitachi TX09D70VM1CCA 3.5" 240x320 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + .xres = 240, + .yres = 320, + .bpp = 16, + .pixclock = 186697, /* 327*273*60=5.35626MHz */ + .left_margin = 17, + .right_margin = 11, + .hsync_len = 5, + .upper_margin = 4, + .lower_margin = 2, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Hitachi TX14D11VM1CAA 5.7" 320x240 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 320, + .height = 240, + .xres = 320, + .yres = 240, + .bpp = 8, + .pixclock = 156250, /* 357*245*73.17=6.4MHz */ + .left_margin = 16, + .right_margin = 16, + .hsync_len = 5, + .upper_margin = 2, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */ + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Hitachi TX14D11VM1CAA 5.7" 320x240 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 320, + .height = 240, + .xres = 320, + .yres = 240, + .bpp = 16, + .pixclock = 156250, /* 357*245*73.17=6.4MHz */ + .left_margin = 16, + .right_margin = 16, + .hsync_len = 5, + .upper_margin = 2, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */ + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM320240N1TMQWT30H(R) e AM320240NTMQWT30H 5.7" + 320x240 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 320, + .height = 240, + .xres = 320, + .yres = 241, /* This panel needs one dummy line */ + .bpp = 8, + .pixclock = 156250, /* 357*245*73.17=6.4MHz */ + .left_margin = 16, + .right_margin = 16, + .hsync_len = 5, + .upper_margin = 2, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */ + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_INVVCLK | /* Clocks on rising edge */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM320240N1TMQWT30H(R) e AM320240NTMQWT30H 5.7" + 320x240 64K colori*/ + .type = S3C2410_LCDCON1_TFT, + .width = 320, + .height = 240, + .xres = 320, + .yres = 241, /* This panel needs one dummy line */ + .bpp = 16, + .pixclock = 156250, /* 357*245*73.17=6.4MHz */ + .left_margin = 16, + .right_margin = 16, + .hsync_len = 5, + .upper_margin = 2, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */ + S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */ + S3C2410_LCDCON5_INVVCLK | /* Clocks on rising edge */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM640480GTMQWT00H 5.7" 640x480 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + .xres = 640, + .yres = 480, + .bpp = 8, + .pixclock = 40000, /* 25MHz */ + .left_margin = 53, + .right_margin = 53, + .hsync_len = 54, + .upper_margin = 15, + .lower_margin = 15, + .vsync_len = 15, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM640480GTMQWT00H 5.7" 640x480 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 640, + .height = 480, + .xres = 640, + .yres = 480, + .bpp = 16, + .pixclock = 40000, /* 25MHz */ + .left_margin = 53, + .right_margin = 53, + .hsync_len = 54, + .upper_margin = 15, + .lower_margin = 15, + .vsync_len = 15, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* Varitronix TLM-T700MPZC-01 7" 800x480 256 colori */ + /* Samsung LMS700KF07-004 7" 800x480 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 800, + .height = 480, + .xres = 800, + .yres = 480, + .bpp = 8, + .pixclock = 45115, /* 22.167MHz 56Hz */ + .left_margin = 6, /* Varitronix needs 45, Frate = 53.4Hz */ + .right_margin = 1, + .hsync_len = 1, + .upper_margin = 8, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* Varitronix TLM-T700MPZC-01 7" 800x480 64K colori */ + /* Samsung LMS700KF07-004 7" 800x480 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 800, + .height = 480, + .xres = 800, + .yres = 480, + .bpp = 16, + .pixclock = 45115, /* 22.167MHz 56Hz */ + .left_margin = 6, /* Varitronix needs 45, Frate = 53.4Hz */ + .right_margin = 1, + .hsync_len = 1, + .upper_margin = 8, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM800600CL-TMQW01H 800x600 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 800, + .height = 600, + .xres = 800, + .yres = 600, + .bpp = 8, + .pixclock = 45115, /* 22.167MHz 41.82Hz */ + /*.pixclock = 30076, 33.25MHz 62.74Hz */ + .left_margin = 46, + .right_margin = 1, + .hsync_len = 1, + .upper_margin = 33, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* Ampire AM800600CL-TMQW01H 800x600 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 800, + .height = 600, + .xres = 800, + .yres = 600, + .bpp = 16, + .pixclock = 45115, /* 22.167MHz 41.82Hz */ + /*.pixclock = 30076, 33.25MHz 62.74Hz */ + .left_margin = 46, + .right_margin = 1, + .hsync_len = 1, + .upper_margin = 33, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, +#if 0 + { + /* 1024x768 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 1024, + .height = 768, + .xres = 1024, + .yres = 768, + .bpp = 8, + .pixclock = 15038, /* 66.5MHz */ + .left_margin = 3, + .right_margin = 3, + .hsync_len = 3, + .upper_margin = 1, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* 1024x768 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 1024, + .height = 768, + .xres = 1024, + .yres = 768, + .bpp = 16, + .pixclock = 15038, /* 66.5MHz */ + .left_margin = 3, + .right_margin = 3, + .hsync_len = 3, + .upper_margin = 1, + .lower_margin = 1, + .vsync_len = 1, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* 1280x800 256 colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 1280, + .height = 800, + .xres = 1280, + .yres = 800, + .bpp = 8, + .pixclock = 15038, /* 66.5MHz */ + .left_margin = 32, + .right_margin = 32, + .hsync_len = 64, + .upper_margin = 4, + .lower_margin = 4, + .vsync_len = 8, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + { + /* 1280x800 64K colori */ + .type = S3C2410_LCDCON1_TFT, + .width = 1280, + .height = 800, + .xres = 1280, + .yres = 800, + .bpp = 16, + .pixclock = 15038, /* 66.5MHz */ + .left_margin = 32, + .right_margin = 32, + .hsync_len = 64, + .upper_margin = 4, + .lower_margin = 4, + .vsync_len = 8, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, +#endif + { + /* tft 384x256 */ + .type = S3C2410_LCDCON1_TFT, + .width = 384, + .height = 256, + .xres = 384, + .yres = 256, + .bpp = 16, + .pixclock = 117318, /* 396*287*75=8.5239MHz */ + .left_margin = 4, + .right_margin = 4, + .hsync_len = 4, + .upper_margin = 10, + .lower_margin = 10, + .vsync_len = 11, + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVCLK | /* Clocks on rising edge */ + S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, + }, +}; + +static struct s3c2410fb_mach_info fbinfo = { + .displays = s3c2410_fb_displays, + .num_displays = ARRAY_SIZE(s3c2410_fb_displays), + .default_display = 0, + .gpcup = 0xfc1e, + .gpcup_mask = 0xfc1e, + .gpccon = 0xaaa002a8, + .gpccon_mask = 0xfff003fc, + .gpdup = 0xfcfc, + .gpdup_mask = 0xfcfc, + .gpdcon = 0xaaa0aaa0, + .gpdcon_mask = 0xfff0fff0, + .lpcsel = 0, +}; + +static void __init usb_init(void) +{ +#ifdef CONFIG_RD129_USB_1HOST + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0); + platform_device_register(&s3c_device_usbgadget); + printk(KERN_INFO "Usb: 1 Host port, 1 Device port\n"); +#endif +#ifdef CONFIG_RD129_USB_2HOST + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, S3C2410_MISCCR_USBHOST); + printk(KERN_INFO "Usb: 2 Host ports\n"); +#endif +#ifdef CONFIG_RD129_USB_AUTO + s3c2410_gpio_cfgpin(S3C2410_GPD0, S3C2410_GPD0_INP); + s3c2410_gpio_pullup(S3C2410_GPD0, 0); /* Enable pullup */ + if (s3c2410_gpio_getpin(S3C2410_GPD0)) { + /* Host */ + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, + S3C2410_MISCCR_USBHOST); + printk(KERN_INFO "Autodetected Usb: 2 Host ports\n"); + } else { + /* Device */ + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0); + platform_device_register(&s3c_device_usbgadget); + printk(KERN_INFO + "Autodetected Usb: 1 Host port, 1 Device port\n"); + } +#endif +} + +static struct clk *rd129_clocks[] __initdata = { + &s3c24xx_dclk0, + &s3c24xx_dclk1, + &s3c24xx_clkout0, + &s3c24xx_clkout1, +}; + +static void __init rd129_map_io(void) +{ + s3c24xx_register_clocks(rd129_clocks, ARRAY_SIZE(rd129_clocks)); + s3c24xx_init_io(rd129_iodesc, ARRAY_SIZE(rd129_iodesc)); + s3c24xx_init_clocks(0); + s3c24xx_init_uarts(rd129_uartcfgs, ARRAY_SIZE(rd129_uartcfgs)); +} + +static struct i2c_board_info rd126_i2c_devices[] = { +#ifdef CONFIG_AT24 + { + I2C_BOARD_INFO("at24", 0x50), + .type = CONFIG_AT24_TYPE, + }, +#endif /* CONFIG_AT24 */ +#ifdef CONFIG_RTC_DRV_DS1307 + { + I2C_BOARD_INFO("rtc-ds1307", 0x68), + .type = "ds1338", + }, +#endif /* CONFIG_RTC_DRV_DS1307 */ +#ifdef CONFIG_RTC_DRV_FM3130 + { + I2C_BOARD_INFO("rtc-fm3130", 0x68), + .type = "fm3130", + }, +#endif /* CONFIG_RTC_DRV_FM3130 */ +#ifdef CONFIG_LM75 + { + I2C_BOARD_INFO("lm75", 0x48), + .type = "lm75a", + }, +#endif /* CONFIG_LM75 */ +#ifdef CONFIG_LM95241 + { + I2C_BOARD_INFO("lm95241", 0x2b), + .type = "lm95241", + }, +#endif /* CONFIG_LM95241 */ +}; + + +/* This can be used only directly from user, CS is GPA16 */ +static struct s3c2410_spi_info spi0_platform_data = { + .pin_cs = S3C2410_GPA16, + .num_cs = 1, + .bus_num = 0, +}; + +/* This can be used: + - directly from user, CS is GPA14 + - to connect a Microchip ENC28J60 Ethernet controller, CS is GPA15 + interrupt is GPG10 */ + +static const unsigned int spi1_cs[] = { + S3C2410_GPA14, S3C2410_GPA15 +}; + +static void s3c2410_spi1_cs(struct s3c2410_spi_info *spi, int cs, int pol) +{ + if (cs < 0) + cs = 0; + if (cs > 1) + cs = 1; + s3c2410_gpio_setpin(spi1_cs[cs], pol ? 1 : 0); +} + +static struct s3c2410_spi_info spi1_platform_data = { + .num_cs = 2, + .bus_num = 1, + .set_cs = s3c2410_spi1_cs, +}; + +/* Generic spidev device */ +static struct spi_board_info rd126_spi_devices[] __initdata = { + { + .modalias = "spidev", + .max_speed_hz = 25000000, + .bus_num = 0, + .chip_select = 0, + }, + { + .modalias = "spidev", + .max_speed_hz = 25000000, + .bus_num = 1, + .chip_select = 0, + }, +#ifdef CONFIG_ENC28J60 + { + .modalias = "enc28j60", + .max_speed_hz = 25000000, + .bus_num = 1, + .chip_select = 1, + .irq = IRQ_EINT18, /* GPG10 */ + }, +#endif /* CONFIG_ENC28J60 */ +}; + +static void __init rd129_init(void) +{ + s3c_device_nand.dev.platform_data = &rd129_nand_info; + s3c_device_sdi.dev.platform_data = &rd129_mmc_cfg; + usb_init(); + s3c24xx_fb_set_platdata(&fbinfo); + s3c_device_spi0.dev.platform_data = &spi0_platform_data; + s3c_device_spi1.dev.platform_data = &spi1_platform_data; + i2c_register_board_info(0, rd126_i2c_devices, + ARRAY_SIZE(rd126_i2c_devices)); + spi_register_board_info(rd126_spi_devices, + ARRAY_SIZE(rd126_spi_devices)); + platform_add_devices(rd129_devices, ARRAY_SIZE(rd129_devices)); +} + +MACHINE_START(RD129, "Elpa RD129") +/* Maintainer: Davide Rizzo */ +.phys_io = S3C2410_PA_UART, +.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, +.boot_params = S3C2410_SDRAM_PA + 0x100, +.map_io = rd129_map_io, +.init_irq = s3c24xx_init_irq, +.init_machine = rd129_init, +.timer = &s3c24xx_timer, +MACHINE_END diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/Makefile linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Makefile --- linux-2.6.28.5/arch/arm/mach-s3c2410/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Makefile 2009-01-08 08:10:01.000000000 +0100 @@ -19,6 +19,7 @@ obj-$(CONFIG_S3C2410_CLOCK) += clock.o # Machine support +obj-$(CONFIG_MACH_RD129) += mach-rd129.o obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o obj-$(CONFIG_ARCH_H1940) += mach-h1940.o h1940-bluetooth.o obj-$(CONFIG_PM_H1940) += pm-h1940.o diff -urNp linux-2.6.28.5/arch/arm/plat-s3c/include/plat/gpio.h linux-2.6.28.5.elpa/arch/arm/plat-s3c/include/plat/gpio.h --- linux-2.6.28.5/arch/arm/plat-s3c/include/plat/gpio.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c/include/plat/gpio.h 2009-01-28 20:08:31.000000000 +0100 @@ -0,0 +1,24 @@ +/* arch/arm/plat-s3c/include/plat/gpio.h + * + * Copyright (c) 2008 ELPA sas + * Davide Rizzo + * + * S3C2410 - GPIO platfrom_device info + * + * 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. +*/ + +/* struct s3c24xx_gpio_platdata + * + * define one set of hardwired gpio pins + * + * port_mask = bitmask, each bit enables corresponding pin in the bank + * +*/ + + +struct s3c24xx_gpio_platdata { + unsigned long port_mask[8]; /* One for each bank of IO pins */ +}; diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/clock.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/clock.c --- linux-2.6.28.5/arch/arm/plat-s3c24xx/clock.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/clock.c 2009-02-15 17:04:54.000000000 +0100 @@ -392,7 +392,7 @@ static int s3c24xx_clkout_setparent(stru /* calculate the MISCCR setting for the clock */ - if (parent == &clk_xtal) + if (parent == &clk_mpll) source = S3C2410_MISCCR_CLK0_MPLL; else if (parent == &clk_upll) source = S3C2410_MISCCR_CLK0_UPLL; @@ -422,6 +422,27 @@ static int s3c24xx_clkout_setparent(stru return 0; } +int clk_for_each(int(*fn)(struct clk *, void *), void *data) +{ + struct clk *clk; + int ret = 0; + + list_for_each_entry(clk, &clocks, list) + { + ret = fn(clk, data); + if (ret) + break; + } + return ret; +} +EXPORT_SYMBOL(clk_for_each); + +const char *clk_get_sysname(struct clk *clk) +{ + return clk->sys_name; +} +EXPORT_SYMBOL(clk_get_sysname); + /* external clock definitions */ struct clk s3c24xx_dclk0 = { @@ -473,6 +494,21 @@ int s3c24xx_register_clock(struct clk *c /* add to the list of available clocks */ mutex_lock(&clocks_mutex); + + if(clk->sys_name == NULL) { + if(clk->id < 0) + clk->sys_name = clk->name; + else { + int sys_name_len = strlen(clk->name) + 4; + char *sys_name = kmalloc(sys_name_len, GFP_KERNEL); + if(sys_name) { + snprintf(sys_name, sys_name_len - 1, "%s.%d", + clk->name, clk->id); + sys_name[sys_name_len - 1] = '\0'; + clk->sys_name = sys_name; + } + } + } list_add(&clk->list, &clocks); mutex_unlock(&clocks_mutex); diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/dma.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/dma.c --- linux-2.6.28.5/arch/arm/plat-s3c24xx/dma.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/dma.c 2009-01-04 08:06:00.000000000 +0100 @@ -1232,7 +1232,7 @@ int s3c2410_dma_getposition(dmach_t chan if (dst != NULL) *dst = dma_rdreg(chan, S3C2410_DMA_DCDST); - return 0; + return s3c2410_dma_started(chan); } EXPORT_SYMBOL(s3c2410_dma_getposition); diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/include/plat/clock.h linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/include/plat/clock.h --- linux-2.6.28.5/arch/arm/plat-s3c24xx/include/plat/clock.h 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/include/plat/clock.h 2009-02-12 18:58:31.000000000 +0100 @@ -15,6 +15,7 @@ struct clk { struct module *owner; struct clk *parent; const char *name; + const char *sys_name; int id; int usage; unsigned long rate; diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm.c --- linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm.c 2009-01-06 19:04:44.000000000 +0100 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,8 @@ #include #include +#define DEV_NAME "s3c24xx-pwm" + struct pwm_device { struct list_head list; struct platform_device *pdev; @@ -37,6 +40,11 @@ struct pwm_device { unsigned char running; unsigned char use_count; unsigned char pwm_id; + + /* For one-shot mode callback*/ + int irq; + void (*expired)(struct pwm_device *, void *arg); + void *arg; }; #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) @@ -57,7 +65,7 @@ static struct clk *clk_scaler[2]; } #define DEFINE_S3C_TIMER(_tmr_no, _irq) \ - .name = "s3c24xx-pwm", \ + .name = DEV_NAME, \ .id = _tmr_no, \ .num_resources = TIMER_RESOURCE_SIZE, \ .resource = TIMER_RESOURCE(_tmr_no, _irq), \ @@ -272,6 +280,88 @@ int pwm_config(struct pwm_device *pwm, i EXPORT_SYMBOL(pwm_config); +static irqreturn_t timer_isr(int irq, void *arg) +{ + struct pwm_device *pwm = arg; + + if (pwm->expired) { + disable_irq(irq); + pwm_disable(pwm); + pwm->expired(pwm, pwm->arg); + pwm->expired = NULL; + } + return IRQ_HANDLED; +} + +int pwm_one_shot(struct pwm_device *pwm, int timeout_ns, + void(*expired)(struct pwm_device *, void *arg), void *arg) +{ + unsigned long tin_rate; + unsigned long tin_ns; + unsigned long period; + unsigned long flags; + unsigned long tcon; + unsigned long tcnt; + + /* We currently avoid using 64bit arithmetic by using the + * fact that anything faster than 1Hz is easily representable + * by 32bits. */ + + if (timeout_ns > NS_IN_HZ) + return -ERANGE; + + /* The TCMP and TCNT can be read without a lock, they're not + * shared between the timers. */ + + tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); + + period = NS_IN_HZ / timeout_ns; + + pwm_dbg(pwm, "one shot timeout_ns=%d\n", timeout_ns); + + if (pwm_is_tdiv(pwm)) { + tin_rate = pwm_calc_tin(pwm, period); + clk_set_rate(pwm->clk_div, tin_rate); + } else + tin_rate = clk_get_rate(pwm->clk); + + pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate); + + tin_ns = NS_IN_HZ / tin_rate; + tcnt = timeout_ns / tin_ns; + /* Note, counters count down */ + + pwm_dbg(pwm, "tin_ns=%lu\n", tin_ns); + + /* Update the PWM register block. */ + + local_irq_save(flags); + + if (!pwm->expired) + enable_irq(pwm->irq); + + __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); + + tcon = __raw_readl(S3C2410_TCON); + tcon |= pwm_tcon_manulupdate(pwm); + tcon &= ~pwm_tcon_autoreload(pwm); + tcon &= ~pwm_tcon_start(pwm); + __raw_writel(tcon, S3C2410_TCON); + + + pwm->expired = expired; + pwm->arg = arg; + + tcon &= ~pwm_tcon_manulupdate(pwm); + tcon |= pwm_tcon_start(pwm); + __raw_writel(tcon, S3C2410_TCON); + + local_irq_restore(flags); + + return 0; +} +EXPORT_SYMBOL(pwm_one_shot); + static int pwm_register(struct pwm_device *pwm) { pwm->duty_ns = -1; @@ -288,6 +378,7 @@ static int s3c_pwm_probe(struct platform { struct device *dev = &pdev->dev; struct pwm_device *pwm; + struct resource *res; unsigned long flags; unsigned long tcon; unsigned int id = pdev->id; @@ -306,6 +397,22 @@ static int s3c_pwm_probe(struct platform pwm->pdev = pdev; pwm->pwm_id = id; + pwm->expired = NULL; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "cannot get platform interrupt resource\n"); + ret = -EBUSY; + goto err_getresources; + } + pwm->irq = res->start; + ret = request_irq(pwm->irq, timer_isr, IRQF_DISABLED, + DEV_NAME, pwm); + if (ret) { + dev_err(dev, "request_irq failed\n"); + goto err_getirq; + } + disable_irq(pwm->irq); /* calculate base of control bits in TCON */ pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4; @@ -354,6 +461,10 @@ static int s3c_pwm_probe(struct platform clk_put(pwm->clk_div); err_clk_tin: + err_getresources: + free_irq(pwm->irq, DEV_NAME); + + err_getirq: clk_put(pwm->clk); err_alloc: @@ -365,6 +476,7 @@ static int s3c_pwm_remove(struct platfor { struct pwm_device *pwm = platform_get_drvdata(pdev); + free_irq(pwm->irq, DEV_NAME); clk_put(pwm->clk_div); clk_put(pwm->clk); kfree(pwm); @@ -374,7 +486,7 @@ static int s3c_pwm_remove(struct platfor static struct platform_driver s3c_pwm_driver = { .driver = { - .name = "s3c24xx-pwm", + .name = DEV_NAME, .owner = THIS_MODULE, }, .probe = s3c_pwm_probe, diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm-clock.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm-clock.c --- linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm-clock.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm-clock.c 2009-01-08 08:25:39.000000000 +0100 @@ -77,7 +77,7 @@ static unsigned long clk_pwm_scaler_getr { unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); - if (clk->id == 1) { + if (strcmp(clk->name, "pwm-scaler1") == 0) { tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK; tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT; } else { @@ -87,6 +87,39 @@ static unsigned long clk_pwm_scaler_getr return clk_get_rate(clk->parent) / (tcfg0 + 1); } +/* WARNING! By changing the scalers rates you influence all child timers */ +/* Use this with care, you could corrupt the main tick generator */ + +static int clk_pwm_scaler_setrate(struct clk *clk, unsigned long rate) +{ + unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); + int div; + + if (IS_ERR(clk)) + return -EINVAL; + + if (rate <= 0) + return -EINVAL; + + div = clk_get_rate(clk->parent) / rate - 1; + + if (div < 0) + div = 0; + if (div > 255) + div = 255; + + if (strcmp(clk->name, "pwm-scaler1") == 0) { + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; + tcfg0 |= div << S3C2410_TCFG_PRESCALER1_SHIFT; + } else { + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; + tcfg0 |= div; + } + __raw_writel(tcfg0, S3C2410_TCFG0); + + return clk_pwm_scaler_getrate(clk); +} + /* TODO - add set rate calls. */ static struct clk clk_timer_scaler[] = { @@ -94,11 +127,13 @@ static struct clk clk_timer_scaler[] = { .name = "pwm-scaler0", .id = -1, .get_rate = clk_pwm_scaler_getrate, + .set_rate = clk_pwm_scaler_setrate, }, [1] = { .name = "pwm-scaler1", .id = -1, .get_rate = clk_pwm_scaler_getrate, + .set_rate = clk_pwm_scaler_setrate, }, }; @@ -399,7 +434,8 @@ static __init int s3c24xx_pwmclk_init(vo clk_timer_scaler[clk].parent = clk_timers; ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); if (ret < 0) { - printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); + printk(KERN_ERR "error adding pwm scaler%d clock\n", + clk); goto err; } } @@ -407,7 +443,7 @@ static __init int s3c24xx_pwmclk_init(vo for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) { ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); if (ret < 0) { - printk(KERN_ERR "error adding pww tclk%d\n", clk); + printk(KERN_ERR "error adding pwm tclk%d\n", clk); goto err; } } diff -urNp linux-2.6.28.5/.config linux-2.6.28.5.elpa/.config --- linux-2.6.28.5/.config 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/.config 2009-02-15 18:16:12.000000000 +0100 @@ -0,0 +1,1572 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28.5 +# Sun Feb 15 18:16:12 2009 +# +CONFIG_ARM=y +CONFIG_HAVE_PWM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_MMU=y +CONFIG_NO_IOPORT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +CONFIG_ARCH_S3C2410=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +CONFIG_PLAT_S3C24XX=y +CONFIG_S3C24XX_PWM=y +CONFIG_S3C2410_DMA=y +# CONFIG_S3C2410_DMA_DEBUG is not set +CONFIG_PLAT_S3C=y +CONFIG_CPU_LLSERIAL_S3C2410_ONLY=y +CONFIG_CPU_LLSERIAL_S3C2410=y + +# +# Boot options +# +# CONFIG_S3C_BOOT_WATCHDOG is not set +# CONFIG_S3C_BOOT_ERROR_RESET is not set + +# +# Power management +# +CONFIG_S3C_LOWLEVEL_UART_PORT=2 + +# +# S3C2400 Machines +# +CONFIG_CPU_S3C2410=y +CONFIG_CPU_S3C2410_DMA=y +CONFIG_S3C2410_GPIO=y +CONFIG_S3C2410_CLOCK=y + +# +# S3C2410 Machines +# +# CONFIG_ARCH_SMDK2410 is not set +# CONFIG_ARCH_H1940 is not set +# CONFIG_MACH_N30 is not set +# CONFIG_ARCH_BAST is not set +# CONFIG_MACH_OTOM is not set +# CONFIG_MACH_AML_M5900 is not set +# CONFIG_MACH_TCT_HAMMER is not set +# CONFIG_MACH_VR1000 is not set +# CONFIG_MACH_QT2410 is not set +CONFIG_MACH_RD129=y + +# +# S3C2412 Machines +# +# CONFIG_MACH_JIVE is not set +# CONFIG_MACH_SMDK2413 is not set +# CONFIG_MACH_SMDK2412 is not set +# CONFIG_MACH_VSTMS is not set + +# +# S3C2440 Machines +# +# CONFIG_MACH_ANUBIS is not set +# CONFIG_MACH_OSIRIS is not set +# CONFIG_MACH_RX3715 is not set +# CONFIG_ARCH_S3C2440 is not set +# CONFIG_MACH_NEXCODER_2440 is not set +# CONFIG_MACH_AT2440EVB is not set + +# +# S3C2442 Machines +# + +# +# S3C2443 Machines +# +# CONFIG_MACH_SMDK2443 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4T=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=200 +# CONFIG_AEABI is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE=y +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=y +CONFIG_NL80211=y +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_MAC80211=y + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_IEEE80211=y +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=y +CONFIG_IEEE80211_CRYPT_CCMP=y +CONFIG_IEEE80211_CRYPT_TKIP=y +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_BLOCK2MTD=y + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_S3C2410=y +# CONFIG_MTD_NAND_S3C2410_DEBUG is not set +CONFIG_MTD_NAND_S3C2410_HWECC=y +CONFIG_MTD_NAND_S3C2410_CLKSTOP=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set +CONFIG_UM_TIMER=y +CONFIG_UM_TIMER_ONESHOT=y +CONFIG_UM_CLOCK=y +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_IWLWIFI_LEDS is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_ZD1211RW=y +# CONFIG_ZD1211RW_DEBUG is not set +# CONFIG_RT2X00 is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=y +CONFIG_USB_RTL8150=y +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +CONFIG_TOUCHSCREEN_S3C2410=y +CONFIG_TOUCHSCREEN_ENABLE_S3C2410=y +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SAMSUNG=y +CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_S3C2410=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_S3C2410=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +CONFIG_AT24=y +CONFIG_AT24_TYPE="24c64" +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_TPS65010 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_S3C24XX=y +# CONFIG_SPI_S3C24XX_GPIO is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +CONFIG_SENSORS_LM75=y +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +CONFIG_SENSORS_LM95241=y +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_S3C2410_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_S3C2410=y +# CONFIG_FB_S3C2410_DEBUG is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_CORGI is not set +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_PWM_FREQUENCY=20000 + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_LOGO is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_SEQUENCER=y +# CONFIG_SND_SEQ_DUMMY is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_SEQUENCER_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_S3C24XX_SOC=y +CONFIG_SND_S3C24XX_SOC_I2S=y +CONFIG_SND_S3C24XX_SOC_RD126_PCM3006=y +# CONFIG_SND_S3C24XX_SOC_RD126_WM8731 is not set +# CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650 is not set +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_PCM3006=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_BRIGHT=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DELL=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GYRATION=y +CONFIG_HID_LOGITECH=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_RD129_USB_1HOST is not set +# CONFIG_RD129_USB_2HOST is not set +CONFIG_RD129_USB_AUTO=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +CONFIG_USB_GADGET_S3C2410=y +CONFIG_USB_S3C2410=y +# CONFIG_USB_S3C2410_DEBUG is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +CONFIG_MMC_S3C=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_S3C is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +CONFIG_UIO=y +CONFIG_UIO_S3C2410_GPIO=y +# CONFIG_UIO_PDRV is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_SMX is not set +# CONFIG_UIO_SERCOS3 is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_S3C_UART=2 + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y diff -urNp linux-2.6.28.5/Documentation/ABI/testing/sysfs-class-clock linux-2.6.28.5.elpa/Documentation/ABI/testing/sysfs-class-clock --- linux-2.6.28.5/Documentation/ABI/testing/sysfs-class-clock 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/Documentation/ABI/testing/sysfs-class-clock 2009-01-28 19:10:42.000000000 +0100 @@ -0,0 +1,20 @@ +What: /sys/class/clock +Date: January 2009 +Contact: Davide Rizzo +Description: + The /sys/class/clock directory will consist of a group of + subdirectories each one describing an internal clock in the kernel. + The name of the subdirectory is the clock's name. + If a clock is device specific, its name is in the form "name.id". + In each directory there are 2 virtual files: rate and parent. + Both these files are r/w, but there can be some architecture-dependent + limitations on write access on one or both of them. + For this interface to work, it needs some low-level implementations (look + at include/linux/clk.h): + - clk_for_each() + - clk_name() + - clk_get() should recognize also the "name.id" format + Actually I implemented these only for Samsung S3C SoC in + arch/arm/plat-s3c/clock.c + +Users: diff -urNp linux-2.6.28.5/drivers/hwmon/Kconfig linux-2.6.28.5.elpa/drivers/hwmon/Kconfig --- linux-2.6.28.5/drivers/hwmon/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/hwmon/Kconfig 2009-01-04 08:07:39.000000000 +0100 @@ -548,6 +548,15 @@ config SENSORS_LM93 This driver can also be built as a module. If so, the module will be called lm93. +config SENSORS_LM95241 + tristate "National Semiconductor LM95241 sensor chip" + depends on I2C + help + If you say yes here you get support for LM95241 sensor chip. + + This driver can also be built as a module. If so, the module + will be called lm95241. + config SENSORS_MAX1111 tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" depends on SPI_MASTER diff -urNp linux-2.6.28.5/drivers/hwmon/lm95241.c linux-2.6.28.5.elpa/drivers/hwmon/lm95241.c --- linux-2.6.28.5/drivers/hwmon/lm95241.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/hwmon/lm95241.c 2009-01-28 20:08:54.000000000 +0100 @@ -0,0 +1,527 @@ +/* + * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * Copyright (C) 2008 Davide Rizzo + * + * Based on the max1619 driver. The LM95241 is a sensor chip made by National + * Semiconductors. + * It reports up to three temperatures (its own plus up to + * two external ones). Complete datasheet can be + * obtained from National's website at: + * http://www.national.com/ds.cgi/LM/LM95241.pdf + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const unsigned short normal_i2c[] = { + 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(lm95241); + +/* LM95241 registers */ +#define LM95241_REG_R_MAN_ID 0xFE +#define LM95241_REG_R_CHIP_ID 0xFF +#define LM95241_REG_R_STATUS 0x02 +#define LM95241_REG_RW_CONFIG 0x03 +#define LM95241_REG_RW_REM_FILTER 0x06 +#define LM95241_REG_RW_TRUTHERM 0x07 +#define LM95241_REG_W_ONE_SHOT 0x0F +#define LM95241_REG_R_LOCAL_TEMPH 0x10 +#define LM95241_REG_R_REMOTE1_TEMPH 0x11 +#define LM95241_REG_R_REMOTE2_TEMPH 0x12 +#define LM95241_REG_R_LOCAL_TEMPL 0x20 +#define LM95241_REG_R_REMOTE1_TEMPL 0x21 +#define LM95241_REG_R_REMOTE2_TEMPL 0x22 +#define LM95241_REG_RW_REMOTE_MODEL 0x30 + +/* LM95241 specific bitfields */ +#define CFG_STOP 0x40 +#define CFG_CR0076 0x00 +#define CFG_CR0182 0x10 +#define CFG_CR1000 0x20 +#define CFG_CR2700 0x30 +#define R1MS_SHIFT 0 +#define R2MS_SHIFT 2 +#define R1MS_MASK (0x01 << (R1MS_SHIFT)) +#define R2MS_MASK (0x01 << (R2MS_SHIFT)) +#define R1DF_SHIFT 1 +#define R2DF_SHIFT 2 +#define R1DF_MASK (0x01 << (R1DF_SHIFT)) +#define R2DF_MASK (0x01 << (R2DF_SHIFT)) +#define R1FE_MASK 0x01 +#define R2FE_MASK 0x05 +#define TT1_SHIFT 0 +#define TT2_SHIFT 4 +#define TT_OFF 0 +#define TT_ON 1 +#define TT_MASK 7 +#define MANUFACTURER_ID 0x01 +#define DEFAULT_REVISION 0xA4 + +/* Conversions and various macros */ +#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ + (val_h)) * 1000 + (val_l) * 1000 / 256) + +/* Functions declaration */ +static int lm95241_attach_adapter(struct i2c_adapter *adapter); +static int lm95241_detect(struct i2c_adapter *adapter, int address, + int kind); +static void lm95241_init_client(struct i2c_client *client); +static int lm95241_detach_client(struct i2c_client *client); +static struct lm95241_data *lm95241_update_device(struct device *dev); + +/* Driver data (common to all clients) */ +static struct i2c_driver lm95241_driver = { + .driver = { + .name = "lm95241", + }, + .attach_adapter = lm95241_attach_adapter, + .detach_client = lm95241_detach_client, +}; + +/* Client data (each client gets its own) */ +struct lm95241_data { + struct i2c_client client; + struct device *hwmon_dev; + struct mutex update_lock; + unsigned long last_updated, rate; /* in jiffies */ + char valid; /* zero until following fields are valid */ + /* registers values */ + u8 local_h, local_l; /* local */ + u8 remote1_h, remote1_l; /* remote1 */ + u8 remote2_h, remote2_l; /* remote2 */ + u8 config, model, trutherm; +}; + +/* Sysfs stuff */ +#define show_temp(value) \ +static ssize_t show_##value(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct lm95241_data *data = lm95241_update_device(dev); \ + snprintf(buf, PAGE_SIZE - 1, "%d\n", \ + TEMP_FROM_REG(data->value##_h, data->value##_l)); \ + return strlen(buf); \ +} +show_temp(local); +show_temp(remote1); +show_temp(remote2); + +static ssize_t show_rate(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct lm95241_data *data = lm95241_update_device(dev); + + snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); + return strlen(buf); +} + +static ssize_t set_rate(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + strict_strtol(buf, 10, &data->rate); + data->rate = data->rate * HZ / 1000; + + return count; +} + +#define show_type(flag) \ +static ssize_t show_type##flag(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + snprintf(buf, PAGE_SIZE - 1, \ + data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ + return strlen(buf); \ +} +show_type(1); +show_type(2); + +#define show_min(flag) \ +static ssize_t show_min##flag(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + snprintf(buf, PAGE_SIZE - 1, \ + data->config & R##flag##DF_MASK ? \ + "-127000\n" : "0\n"); \ + return strlen(buf); \ +} +show_min(1); +show_min(2); + +#define show_max(flag) \ +static ssize_t show_max##flag(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + snprintf(buf, PAGE_SIZE - 1, \ + data->config & R##flag##DF_MASK ? \ + "127000\n" : "255000\n"); \ + return strlen(buf); \ +} +show_max(1); +show_max(2); + +#define set_type(flag) \ +static ssize_t set_type##flag(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + long val; \ + strict_strtol(buf, 10, &val); \ +\ + if ((val == 1) || (val == 2)) { \ +\ + mutex_lock(&data->update_lock); \ +\ + data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ + if (val == 1) { \ + data->model |= R##flag##MS_MASK; \ + data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ + } \ + else { \ + data->model &= ~R##flag##MS_MASK; \ + data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ + } \ +\ + data->valid = 0; \ +\ + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ + data->model); \ + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ + data->trutherm); \ +\ + mutex_unlock(&data->update_lock); \ +\ + } \ + return count; \ +} +set_type(1); +set_type(2); + +#define set_min(flag) \ +static ssize_t set_min##flag(struct device *dev, \ + struct device_attribute *devattr, const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + long val; \ + strict_strtol(buf, 10, &val); \ +\ + mutex_lock(&data->update_lock); \ +\ + if (val < 0) \ + data->config |= R##flag##DF_MASK; \ + else \ + data->config &= ~R##flag##DF_MASK; \ +\ + data->valid = 0; \ +\ + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ + data->config); \ +\ + mutex_unlock(&data->update_lock); \ +\ + return count; \ +} +set_min(1); +set_min(2); + +#define set_max(flag) \ +static ssize_t set_max##flag(struct device *dev, \ + struct device_attribute *devattr, const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct lm95241_data *data = i2c_get_clientdata(client); \ +\ + long val; \ + strict_strtol(buf, 10, &val); \ +\ + mutex_lock(&data->update_lock); \ +\ + if (val <= 127000) \ + data->config |= R##flag##DF_MASK; \ + else \ + data->config &= ~R##flag##DF_MASK; \ +\ + data->valid = 0; \ +\ + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ + data->config); \ +\ + mutex_unlock(&data->update_lock); \ +\ + return count; \ +} +set_max(1); +set_max(2); + +static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); +static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); +static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); +static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); +static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); +static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); +static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); +static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); +static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); +static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); + +static struct attribute *lm95241_attributes[] = { + &dev_attr_temp1_input.attr, + &dev_attr_temp2_input.attr, + &dev_attr_temp3_input.attr, + &dev_attr_temp2_type.attr, + &dev_attr_temp3_type.attr, + &dev_attr_temp2_min.attr, + &dev_attr_temp3_min.attr, + &dev_attr_temp2_max.attr, + &dev_attr_temp3_max.attr, + &dev_attr_rate.attr, + NULL +}; + +static const struct attribute_group lm95241_group = { + .attrs = lm95241_attributes, +}; + +/* Init/exit code */ +static int lm95241_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, lm95241_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int lm95241_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct lm95241_data *data; + int err = 0; + const char *name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + /* The common I2C client data is placed right before the + LM95241-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &lm95241_driver; + new_client->flags = 0; + + /* + * Now we do the remaining detection. A negative kind means that + * the driver was loaded with no force parameter (default), so we + * must both detect and identify the chip. A zero kind means that + * the driver was loaded with the force parameter, the detection + * step shall be skipped. A positive kind means that the driver + * was loaded with the force parameter and a given kind of chip is + * requested, so both the detection and the identification steps + * are skipped. + */ + if (kind < 0) { /* detection */ + if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) + != MANUFACTURER_ID) + || (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) + < DEFAULT_REVISION)) { + dev_dbg(&adapter->dev, + "LM95241 detection failed at 0x%02x.\n", + address); + goto exit_free; + } + } + + if (kind <= 0) { /* identification */ + if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) + == MANUFACTURER_ID) + && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) + >= DEFAULT_REVISION)) { + + kind = lm95241; + + if (kind <= 0) { /* identification failed */ + dev_info(&adapter->dev, "Unsupported chip\n"); + goto exit_free; + } + } + } + + if (kind == lm95241) + name = "lm95241"; + + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; + mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + err = i2c_attach_client(new_client); + if (err) + goto exit_free; + + /* Initialize the LM95241 chip */ + lm95241_init_client(new_client); + + /* Register sysfs hooks */ + err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); + if (err) + goto exit_detach; + + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_files; + } + + return 0; + +exit_remove_files: + sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); +exit_detach: + i2c_detach_client(new_client); +exit_free: + kfree(data); +exit: + return err; +} + +static void lm95241_init_client(struct i2c_client *client) +{ + struct lm95241_data *data = i2c_get_clientdata(client); + + data->rate = HZ; /* 1 sec default */ + data->valid = 0; + data->config = CFG_CR0076; + data->model = 0; + data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, + data->config); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, + R1FE_MASK | R2FE_MASK); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, + data->trutherm); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, + data->model); +} + +static int lm95241_detach_client(struct i2c_client *client) +{ + struct lm95241_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &lm95241_group); + + err = i2c_detach_client(client); + if (err) + return err; + + kfree(data); + return 0; +} + +static struct lm95241_data *lm95241_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + data->rate) || + !data->valid) { + dev_dbg(&client->dev, "Updating lm95241 data.\n"); + data->local_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_LOCAL_TEMPH); + data->local_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_LOCAL_TEMPL); + data->remote1_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE1_TEMPH); + data->remote1_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE1_TEMPL); + data->remote2_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE2_TEMPH); + data->remote2_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE2_TEMPL); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init sensors_lm95241_init(void) +{ + return i2c_add_driver(&lm95241_driver); +} + +static void __exit sensors_lm95241_exit(void) +{ + i2c_del_driver(&lm95241_driver); +} + +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("LM95241 sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_lm95241_init); +module_exit(sensors_lm95241_exit); diff -urNp linux-2.6.28.5/drivers/hwmon/Makefile linux-2.6.28.5.elpa/drivers/hwmon/Makefile --- linux-2.6.28.5/drivers/hwmon/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/hwmon/Makefile 2009-01-04 08:14:42.000000000 +0100 @@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_LM92) += lm92.o obj-$(CONFIG_SENSORS_LM93) += lm93.o +obj-$(CONFIG_SENSORS_LM95241) += lm95241.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o diff -urNp linux-2.6.28.5/drivers/i2c/chips/Kconfig linux-2.6.28.5.elpa/drivers/i2c/chips/Kconfig --- linux-2.6.28.5/drivers/i2c/chips/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/i2c/chips/Kconfig 2009-01-06 18:24:39.000000000 +0100 @@ -42,6 +42,16 @@ config AT24 This driver can also be built as a module. If so, the module will be called at24. +config AT24_TYPE + string "Eeprom model" + depends on AT24 + default "24c64" + help + IICBus Eeprom model (must be specified, driver cannot automatically + recognize it). Valid values: + 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08, + 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024 + config SENSORS_EEPROM tristate "EEPROM reader" depends on EXPERIMENTAL diff -urNp linux-2.6.28.5/drivers/input/touchscreen/Kconfig linux-2.6.28.5.elpa/drivers/input/touchscreen/Kconfig --- linux-2.6.28.5/drivers/input/touchscreen/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/input/touchscreen/Kconfig 2009-01-04 07:40:45.000000000 +0100 @@ -287,6 +287,18 @@ config TOUCHSCREEN_WM97XX_MAINSTONE To compile this driver as a module, choose M here: the module will be called mainstone-wm97xx. +config TOUCHSCREEN_S3C2410 + tristate "Samsung S3C2410 ADC/Touchscreen" + depends on ARCH_S3C2410 + help + This enables support for S3C2410 internal ADC/Touchscreen driver + +config TOUCHSCREEN_ENABLE_S3C2410 + bool "Samsung S3C2410 Touchscreen" + depends on TOUCHSCREEN_S3C2410 + help + This enables support for S3C2410 internal Touchscreen driver + config TOUCHSCREEN_USB_COMPOSITE tristate "USB Touchscreen Driver" depends on USB_ARCH_HAS_HCD diff -urNp linux-2.6.28.5/drivers/input/touchscreen/Makefile linux-2.6.28.5.elpa/drivers/input/touchscreen/Makefile --- linux-2.6.28.5/drivers/input/touchscreen/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/input/touchscreen/Makefile 2009-01-04 07:40:45.000000000 +0100 @@ -31,3 +31,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) + wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o +obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410ts.o diff -urNp linux-2.6.28.5/drivers/input/touchscreen/s3c2410ts.c linux-2.6.28.5.elpa/drivers/input/touchscreen/s3c2410ts.c --- linux-2.6.28.5/drivers/input/touchscreen/s3c2410ts.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/input/touchscreen/s3c2410ts.c 2009-01-28 20:09:11.000000000 +0100 @@ -0,0 +1,573 @@ +/* + drivers/input/touchscreen/s3c2410ts.c + + Written Feb 2008 by Davide Rizzo + + This is a Touchscreen/ADC driver for the Samsung S3C2410 ARM9 SoC + ADC samples can be requested by reading "ainX" virtual files. + Touchscreen interface generates standard input events. + Touchscreen's parameters "samples" and "trigger" are exposed by virtual files + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +/* At least FILTER_SAMPLES must be within NOISE_TRIGGER interval */ +#define DEFAULT_FILTER_SAMPLES 16 +#define DEFAULT_NOISE_TRIGGER 64 +#define ADC_DELAY_TIME 0xFFFF /* Maximum allovable */ +#define ADC_CLK 1000000 +#define DRIVER_NAME "s3c2410-adc" +#define TS_INT_NAME "touchscreen" +#define ADC_INT_NAME "adc" + +enum pen_state { + IDLE, /* Touchscreen not pressed */ + TOUCHING, /*Performing double ADC conversion because touch pressed */ + DUMMY, /*Dummy conversion between Touch samples groups to check if the + touch is still pressed */ + CONVERTING, /* Performing single ADC conversion (external request) */ +}; + +struct s3c2410_ts_info { + struct clk *adc_clk, *pclk; + void __iomem *regs; + wait_queue_head_t waitq; /* Wait queue for reading adc values */ + struct mutex mtx; /* Mutex to synchronize multithread adc access */ + spinlock_t lock; /* To sync with isr */ + unsigned int adc_data_ready, adc_data, adc_channel; + unsigned int adc_conversion_request, prescaler, irq_adc, irq_ts; + enum pen_state state, old_state; +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + struct input_dev *idev; + unsigned int x_avrg, y_avrg, samples, trigger; + unsigned int x_min, x_max, y_min, y_max, sample; +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ +}; + +static void AdcWait(struct s3c2410_ts_info *info) +{ + writel( +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + S3C2410_ADCTSC_XY_PST(3) | +#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + S3C2410_ADCTSC_XY_PST(0) | +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + S3C2410_ADCTSC_YM_SEN | + S3C2410_ADCTSC_YP_SEN | + S3C2410_ADCTSC_XP_SEN, + info->regs + S3C2410_ADCTSC); + writel(S3C2410_ADCCON_PRSCEN | + S3C2410_ADCCON_PRSCVL(info->prescaler) | + S3C2410_ADCCON_SELMUX(7), + info->regs + S3C2410_ADCCON); +} + +/* Setups ADC for next state manages stylus-up messages + It should be called from isr or with lock held (and int disabled) */ +static void isr_common(struct s3c2410_ts_info *info) +{ + /* If there is a direct adc conversion pending request, + interrupts current state and performs conversion */ + if (info->adc_conversion_request) { + info->old_state = info->state; + info->state = CONVERTING; + info->adc_conversion_request = 0; + } + + switch (info->state) { + case IDLE: + AdcWait(info); +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + input_report_key(info->idev, BTN_TOUCH, 0); + input_sync(info->idev); +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + break; + case CONVERTING: + /* Adc Single conversion */ + writel( + S3C2410_ADCTSC_YM_SEN | + S3C2410_ADCTSC_YP_SEN | + S3C2410_ADCTSC_XM_SEN | + S3C2410_ADCTSC_XP_SEN | + S3C2410_ADCTSC_PULL_UP_DISABLE | + S3C2410_ADCTSC_XY_PST(0), + info->regs + S3C2410_ADCTSC); + writel(S3C2410_ADCCON_PRSCEN | + S3C2410_ADCCON_PRSCVL(info->prescaler) | + S3C2410_ADCCON_SELMUX(info->adc_channel) | + S3C2410_ADCCON_ENABLE_START, + info->regs + S3C2410_ADCCON); + break; +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + case DUMMY: + /* Adc Single conversion */ + writel( + S3C2410_ADCTSC_YM_SEN | + S3C2410_ADCTSC_YP_SEN | + S3C2410_ADCTSC_XP_SEN | + S3C2410_ADCTSC_XY_PST(3), + info->regs + S3C2410_ADCTSC); + writel(S3C2410_ADCCON_PRSCEN | + S3C2410_ADCCON_PRSCVL(info->prescaler) | + S3C2410_ADCCON_SELMUX(0) | + S3C2410_ADCCON_ENABLE_START, + info->regs + S3C2410_ADCCON); + break; + case TOUCHING: + /* Adc Auto conversion mode */ + writel( + S3C2410_ADCTSC_YM_SEN | + S3C2410_ADCTSC_YP_SEN | + S3C2410_ADCTSC_XP_SEN | + S3C2410_ADCTSC_AUTO_PST | + S3C2410_ADCTSC_XY_PST(0), + info->regs + S3C2410_ADCTSC); + writel(S3C2410_ADCCON_PRSCEN | + S3C2410_ADCCON_PRSCVL(info->prescaler) | + S3C2410_ADCCON_SELMUX(7) | + S3C2410_ADCCON_ENABLE_START, + info->regs + S3C2410_ADCCON); + break; +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + default: + break; + } +} + +static irqreturn_t isr_adc(int irq, void *dev_id) +{ + struct s3c2410_ts_info *info = dev_id; + unsigned int x, y; + + switch (info->state) { + case CONVERTING: + info->adc_data = readl(info->regs + S3C2410_ADCDAT0) & 0x3FF; + info->adc_data_ready = 1; + wake_up(&info->waitq); + info->state = info->old_state; /* Restore previous state */ + break; +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + case TOUCHING: + x = readl(info->regs + S3C2410_ADCDAT0) & 0x3FF; + y = readl(info->regs + S3C2410_ADCDAT1) & 0x3FF; + writel( + S3C2410_ADCTSC_YM_SEN | + S3C2410_ADCTSC_YP_SEN | + S3C2410_ADCTSC_XM_SEN | + S3C2410_ADCTSC_XP_SEN | + S3C2410_ADCTSC_XY_PST(3), + info->regs + S3C2410_ADCTSC); + info->x_avrg += x; + info->y_avrg += y; + if (x < info->x_min) + info->x_min = x; + if (x > info->x_max) + info->x_max = x; + if (y < info->y_min) + info->y_min = y; + if (y > info->y_max) + info->y_max = y; + if ((info->x_max - info->x_min < info->trigger) && + (info->y_max - info->y_min < info->trigger)) { + if (++info->sample < info->samples) + break; + input_report_key(info->idev, BTN_TOUCH, 1); + input_report_abs(info->idev, ABS_X, + info->x_avrg / info->samples); + input_report_abs(info->idev, ABS_Y, + info->y_avrg / info->samples); + input_sync(info->idev); + } + info->state = DUMMY; + break; + case DUMMY: + AdcWait(info); + if ((readl(info->regs + S3C2410_ADCDAT0) & + S3C2410_ADCDAT0_UPDOWN) && + (readl(info->regs + S3C2410_ADCDAT1) & + S3C2410_ADCDAT1_UPDOWN)) + info->state = IDLE; + else { + info->state = TOUCHING; + info->sample = 0; + info->x_avrg = info->y_avrg = 0; + info->x_min = info->y_min = 32767; + info->x_max = info->y_max = 0; + } + break; +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + default: + break; + } + isr_common(info); + return IRQ_HANDLED; +} + +static ssize_t adc_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_ts_info *info = dev_get_drvdata(dev); + unsigned long flags; + int t; + + mutex_lock(&info->mtx); /* It should always succeed in a short time */ + + spin_lock_irqsave(&info->lock, flags); + + info->adc_channel = attr->attr.name[3] - '0'; + info->adc_data_ready = 0; + info->adc_conversion_request = 1; + if (info->state == IDLE) + isr_common(info); + + spin_unlock_irqrestore(&info->lock, flags); + + wait_event(info->waitq, info->adc_data_ready); /* It should always + succeed in a short time */ + t = info->adc_data; + + mutex_unlock(&info->mtx); + + snprintf(buffer, PAGE_SIZE - 1, "%d\n", t); + return strlen(buffer); +} + +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + +static irqreturn_t isr_ts(int irq, void *dev_id) +{ + struct s3c2410_ts_info *info = dev_id; + + if ((readl(info->regs + S3C2410_ADCDAT0) & S3C2410_ADCDAT0_UPDOWN) || + (readl(info->regs + S3C2410_ADCDAT1) & + S3C2410_ADCDAT1_UPDOWN)) + info->state = IDLE; + else if (info->state == IDLE) { + info->state = TOUCHING; + info->sample = 0; + info->x_avrg = info->y_avrg = 0; + info->x_min = info->y_min = 32767; + info->x_max = info->y_max = 0; + } + isr_common(info); + return IRQ_HANDLED; +} + +static ssize_t samples_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_ts_info *info = dev_get_drvdata(dev); + + snprintf(buffer, PAGE_SIZE - 1, "%d\n", info->samples); + return strlen(buffer); +} + +static ssize_t samples_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct s3c2410_ts_info *info = dev_get_drvdata(dev); + unsigned long samples, flags; + int err = strict_strtoul(buffer, 10, &samples); + + if (err) + return err; + + spin_lock_irqsave(&info->lock, flags); + + info->samples = samples; + + spin_unlock_irqrestore(&info->lock, flags); + + return count; +} + +static ssize_t trigger_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_ts_info *info = dev_get_drvdata(dev); + + snprintf(buffer, PAGE_SIZE - 1, "%d\n", info->trigger); + return strlen(buffer); +} + +static ssize_t trigger_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct s3c2410_ts_info *info = dev_get_drvdata(dev); + unsigned long trigger, flags; + int err = strict_strtoul(buffer, 10, &trigger); + + if (err) + return err; + + spin_lock_irqsave(&info->lock, flags); + + info->trigger = trigger; + + spin_unlock_irqrestore(&info->lock, flags); + + return count; +} + +static DEVICE_ATTR(samples, S_IRUGO | S_IWUSR, samples_show, samples_store); +static DEVICE_ATTR(trigger, S_IRUGO | S_IWUSR, trigger_show, trigger_store); + +#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + +static DEVICE_ATTR(ain5, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain7, S_IRUGO, adc_show, NULL); + +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + +static DEVICE_ATTR(ain0, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain1, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain2, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain3, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain4, S_IRUGO, adc_show, NULL); +static DEVICE_ATTR(ain6, S_IRUGO, adc_show, NULL); + +static struct device_attribute *at[] = { +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + &dev_attr_samples, + &dev_attr_trigger, +#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + &dev_attr_ain5, + &dev_attr_ain7, +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + &dev_attr_ain0, + &dev_attr_ain1, + &dev_attr_ain2, + &dev_attr_ain3, + &dev_attr_ain4, + &dev_attr_ain6, + NULL +}; + +static int s3c2410ts_probe(struct platform_device *pdev) +{ + int ret; + struct resource *res; + struct s3c2410_ts_info *info; + struct device_attribute **curr_at; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + dev_err(&pdev->dev, "out of kernel memory\n"); + ret = -ENOMEM; + goto fail_malloc; + } + platform_set_drvdata(pdev, info); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "cannot get platform memory resource\n"); + ret = -EBUSY; + goto fail_getresources1; + } + if (!request_mem_region(res->start, res->end - res->start + 1, + DRIVER_NAME)) { + dev_err(&pdev->dev, "request_mem_region failed\n"); + ret = -EBUSY; + goto fail_reqmem; + } + info->regs = ioremap(res->start, res->end - res->start + 1); + if (!info->regs) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENXIO; + goto fail_ioremap; + } + info->pclk = clk_get(&pdev->dev, "pclk"); + if (IS_ERR(info->pclk)) { + dev_err(&pdev->dev, "failed to get pclk\n"); + ret = PTR_ERR(info->pclk); + goto fail_getpclk; + } + info->prescaler = clk_get_rate(info->pclk) / ADC_CLK - 1; + info->adc_clk = clk_get(&pdev->dev, "adc"); + if (IS_ERR(info->adc_clk)) { + dev_err(&pdev->dev, "failed to get adc_clk\n"); + ret = PTR_ERR(info->pclk); + goto fail_getadcclk; + } + clk_enable(info->adc_clk); /* Abilita clock su ADC */ + mutex_init(&info->mtx); + init_waitqueue_head(&info->waitq); + spin_lock_init(&info->lock); + info->state = IDLE; +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + /* Set GPG15 to use as nYPON, GPG14 to use as YMON, + GPG13 to use as nXPON, GPG12 to use as XMON */ + s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON); + s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON); + s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON); + s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON); + /* Disable pull up function */ + s3c2410_gpio_pullup(S3C2410_GPG12, 1); + s3c2410_gpio_pullup(S3C2410_GPG13, 1); + s3c2410_gpio_pullup(S3C2410_GPG14, 1); + s3c2410_gpio_pullup(S3C2410_GPG15, 1); + info->idev = input_allocate_device(); + if (!info->idev) { + dev_err(&pdev->dev, "Unable to allocate device\n"); + ret = -ENOMEM; + goto fail_inputalloc; + } + info->idev->name = "S3C2410 Touchscreen"; + info->idev->phys = "s3c2410ts"; + info->samples = DEFAULT_FILTER_SAMPLES; + info->trigger = DEFAULT_NOISE_TRIGGER; + input_set_abs_params(info->idev, ABS_X, 0, 1023, 3, 0); + input_set_abs_params(info->idev, ABS_Y, 0, 1023, 3, 0); + set_bit(EV_KEY, info->idev->evbit); + set_bit(EV_ABS, info->idev->evbit); + set_bit(BTN_TOUCH, info->idev->keybit); + ret = input_register_device(info->idev); + if (ret) { + input_free_device(info->idev); + dev_err(&pdev->dev, "Unable to register input driver\n"); + goto fail_inputregister; + } + /* Allocate IRQ_TC, Touchscreen interrupt must be the 1st in the list */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "cannot get platform interrupt resource\n"); + ret = -EBUSY; + goto fail_getresources2; + } + info->irq_ts = res->start; + ret = request_irq(info->irq_ts, isr_ts, IRQF_DISABLED, TS_INT_NAME, + info); + if (ret) { + dev_err(&pdev->dev, "failed to get IRQ_TC\n"); + goto fail_reqtcirq; + } +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + /* Allocate IRQ_ADC, Adc interrupt must be the 2nd in the list */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + if (!res) { + dev_err(&pdev->dev, "cannot get platform interrupt resource\n"); + ret = -EBUSY; + goto fail_getresources3; + } + info->irq_adc = res->start; + ret = request_irq(info->irq_adc, isr_adc, IRQF_DISABLED, ADC_INT_NAME, + info); + if (ret) { + dev_err(&pdev->dev, "failed to get IRQ_ADC\n"); + goto fail_reqadcirq; + } + for (curr_at = at; *curr_at; curr_at++) { + ret = device_create_file(&pdev->dev, *curr_at); + if (ret != 0) { + dev_err(&pdev->dev, "Unable to create virtual file\n"); + goto fail_vf; + } + } + /* ADC Start or Interval Delay */ + writel(ADC_DELAY_TIME, info->regs + S3C2410_ADCDLY); + AdcWait(info); + dev_notice(&pdev->dev, "S3C2410 Touch Screen / ADC Driver loaded OK\n"); + return ret; +fail_vf: + while (--curr_at >= at) + device_remove_file(&pdev->dev, *curr_at); + free_irq(info->irq_adc, info); +fail_reqadcirq: +fail_getresources3: +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + free_irq(info->irq_ts, info); +fail_reqtcirq: +fail_getresources2: + input_unregister_device(info->idev); +fail_inputregister: +fail_inputalloc: +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + clk_disable(info->adc_clk); + clk_put(info->adc_clk); +fail_getadcclk: + clk_put(info->pclk); +fail_getpclk: + iounmap(info->regs); +fail_ioremap: + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); +fail_reqmem: +fail_getresources1: + platform_set_drvdata(pdev, NULL); + kfree(info); +fail_malloc: + return ret; +} + +static int s3c2410ts_remove(struct platform_device *pdev) +{ + struct s3c2410_ts_info *info = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct device_attribute **curr_at; + + dev_notice(&pdev->dev, "S3C2410 Touch Screen / ADC Exit !!!\n"); + for (curr_at = at; *curr_at; curr_at++) + device_remove_file(&pdev->dev, *curr_at); + + while (mutex_is_locked(&info->mtx)) + schedule(); + free_irq(info->irq_adc, info); +#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410 + free_irq(info->irq_ts, info); + input_unregister_device(info->idev); +#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */ + clk_disable(info->adc_clk); + clk_put(info->adc_clk); + clk_put(info->pclk); + iounmap(info->regs); + release_mem_region(res->start, res->end - res->start + 1); + platform_set_drvdata(pdev, NULL); + kfree(info); + return 0; +} + +static struct platform_driver s3c2410ts_driver = { + .probe = s3c2410ts_probe, + .remove = s3c2410ts_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init s3c2410_ts_init_module(void) +{ + return platform_driver_register(&s3c2410ts_driver); +} + +static void __exit s3c2410_ts_cleanup_module(void) +{ + platform_driver_unregister(&s3c2410ts_driver); +} + +module_init(s3c2410_ts_init_module); +module_exit(s3c2410_ts_cleanup_module); + +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("S3C2410 ELPA ADC/Touchscreen driver"); +MODULE_SUPPORTED_DEVICE("touchscreen/s3c2410"); +MODULE_LICENSE("GPL"); diff -urNp linux-2.6.28.5/drivers/misc/Kconfig linux-2.6.28.5.elpa/drivers/misc/Kconfig --- linux-2.6.28.5/drivers/misc/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/misc/Kconfig 2009-01-28 19:15:29.000000000 +0100 @@ -500,4 +500,41 @@ config SGI_GRU_DEBUG source "drivers/misc/c2port/Kconfig" +config UM_TIMER + bool "User mode timer driver" + depends on SYSFS + default n + ---help--- + Allows user mode programs to configure and control general purpose + timers. + + If unsure, say N. + +config UM_TIMER_ONESHOT + bool "User mode timer driver uses one-shot mode" + depends on UM_TIMER + default n + ---help--- + Enable this to allow general purpose timer driver to use timers + in one-shot mode. For this to work, the function pwm_one_shot() + must be implemented in low-level drivers. + Currently it's implemented only on Samsung S3C24xx platforms. + + If unsure, say N. + +config UM_CLOCK + bool "User mode clock driver" + depends on SYSFS + default n + ---help--- + Allows user mode programs to configure and control internal clocks' + rates and parents through virtual files in sysfs. + This driver requires implementation of some additional functions + in architecture specific low-level drivers: clk_for_each() and + clk_get_name(). Moreover, it requires clk_get() to recognize the + "name.id" format + Currently they're implemented only on Samsung S3C24xx platforms. + + If unsure, say N. + endif # MISC_DEVICES diff -urNp linux-2.6.28.5/drivers/misc/Makefile linux-2.6.28.5.elpa/drivers/misc/Makefile --- linux-2.6.28.5/drivers/misc/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/misc/Makefile 2009-01-17 11:42:09.000000000 +0100 @@ -33,3 +33,5 @@ obj-$(CONFIG_SGI_XP) += sgi-xp/ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_HP_ILO) += hpilo.o obj-$(CONFIG_C2PORT) += c2port/ +obj-$(CONFIG_UM_CLOCK) += um_clock.o +obj-$(CONFIG_UM_TIMER) += um_timer.o diff -urNp linux-2.6.28.5/drivers/misc/um_clock.c linux-2.6.28.5.elpa/drivers/misc/um_clock.c --- linux-2.6.28.5/drivers/misc/um_clock.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/misc/um_clock.c 2009-02-12 19:07:25.000000000 +0100 @@ -0,0 +1,169 @@ +/* + driver/misc/clock.c + + Written Feb 2008 by Davide Rizzo + + This driver allows to read and modify internal clocks' rates using + virtual files. User can also read and modify parents. + + This driver requires implementation of clk_name() and clk_enum() functions + in architecture specific clock.c + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +static DEFINE_MUTEX(mutex); + +static ssize_t rate_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + unsigned long rate; + struct clk *clk; + + clk = dev_get_drvdata(dev); + rate = 0; + + mutex_lock(&mutex); + + rate = clk_get_rate(clk); + + mutex_unlock(&mutex); + + return sprintf(buffer, "%ld\n", rate); +} + +static ssize_t rate_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + unsigned long rate; + struct clk *clk; + int err; + + clk = dev_get_drvdata(dev); + err = strict_strtoul(buffer, 10, &rate); + if (err) + return err; + + mutex_lock(&mutex); + + if (rate != 0) { + clk_set_rate(clk, clk_round_rate(clk, rate)); + clk_enable(clk); + } else + clk_disable(clk); + + mutex_unlock(&mutex); + + return count; +} + +static ssize_t parent_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct clk *parent, *clk; + + clk = dev_get_drvdata(dev); + + mutex_lock(&mutex); + + parent = clk_get_parent(clk); + if (parent && !IS_ERR(parent)) + strlcpy(buffer, clk_get_sysname(parent), PAGE_SIZE); + else + buffer[0] = '\0'; + strlcat(buffer, "\n", PAGE_SIZE); + + mutex_unlock(&mutex); + + return strlen(buffer); +} + +static ssize_t parent_store(struct device *dev, + struct device_attribute *attr, const char *buffer, size_t count) +{ + struct clk *parent; + + char *s = kstrdup(buffer, GFP_KERNEL); + + if (!s) + return -ENOMEM; + if (s[strlen(s) - 1] == '\n') + s[strlen(s) - 1] = '\0'; + parent = clk_get(dev, s); + kfree(s); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + mutex_lock(&mutex); + + clk_set_parent(dev_get_drvdata(dev), parent); + + mutex_unlock(&mutex); + + clk_put(parent); + return count; +} + +static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, rate_show, rate_store); +static DEVICE_ATTR(parent, S_IRUGO | S_IWUSR, parent_show, parent_store); + +static const struct attribute *clock_attrs[] = { + &dev_attr_rate.attr, + &dev_attr_parent.attr, + NULL, +}; + +static const struct attribute_group clock_attr_group = { + .attrs = (struct attribute **) clock_attrs, +}; + +static struct class gpclock_class = { + .name = "clock", + .owner = THIS_MODULE, +}; + +static int create_clock_attr(struct clk *clk, void *data) +{ + struct device *dev; + const char *name; + + name = clk_get_sysname(clk); + if (name == NULL || IS_ERR(name)) { + pr_debug("Invalid clock's name\n"); + return PTR_ERR(name); + } + dev = device_create(&gpclock_class, (struct device *)data, MKDEV(0, 0), + clk, name); + if (!dev) + return -ENODEV; + return sysfs_create_group(&dev->kobj, &clock_attr_group); +} + +static int __init gpclock_init(void) +{ + int ret; + + ret = class_register(&gpclock_class); + if (ret >= 0) + ret = clk_for_each(create_clock_attr, NULL); + return ret; +} +subsys_initcall(gpclock_init); + diff -urNp linux-2.6.28.5/drivers/misc/um_timer.c linux-2.6.28.5.elpa/drivers/misc/um_timer.c --- linux-2.6.28.5/drivers/misc/um_timer.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/misc/um_timer.c 2009-01-28 20:09:40.000000000 +0100 @@ -0,0 +1,281 @@ +/* + * drivers/misc/timer.c + * + * Written Jan 2009 by Davide Rizzo + * + * This driver allows user to access internal timers + * You can use any timer to generate a fixed frequency signal, or to wait for a + * defined short time (if hardware can do it). + * To generate a PWM signal, you have to write the frequency value in Hz into + * the virtual file "freq". After that you can program the duty cycle in the + * virtual file "duty", in 1/1000 units (500 = 50%). + * To wait for a time, you have to write the number of microseconds in virtual + * file "wait". Reading from same file will complete when timer will expire. + * Licensed under the GPLv2 only. + * + */ + +#include +#include +#include + +struct timer_info { + int id; + struct pwm_device *pwm; + unsigned long period_ns, duty_ns; + struct mutex mtx; +#ifdef CONFIG_UM_TIMER_ONESHOT + int flag; + wait_queue_head_t wq; +#endif /* CONFIG_UM_TIMER_ONESHOT */ +}; + +#ifdef CONFIG_UM_TIMER_ONESHOT +static void expired(struct pwm_device *pwm, void *arg) +{ + struct timer_info *info = dev_get_drvdata((struct device *)arg); + + info->flag = 1; + + wake_up_interruptible(&info->wq); +} + +/* Delay is in usec */ +static ssize_t wait_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct timer_info *info = dev_get_drvdata(dev); + unsigned long delay; + int err = strict_strtoul(buffer, 10, &delay); + + if (err) + return err; + + mutex_lock(&info->mtx); + + info->flag = 0; + pwm_one_shot(info->pwm, delay * 1000, expired, dev); + + mutex_unlock(&info->mtx); + + return count; +} + +/* Waits for delay */ +static ssize_t wait_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct timer_info *info = dev_get_drvdata(dev); + int ret; + + mutex_lock(&info->mtx); + + /* !=0 if interrupted by some other signal */ + ret = wait_event_interruptible(info->wq, info->flag); + + mutex_unlock(&info->mtx); + + snprintf(buffer, PAGE_SIZE - 1, "%d\n", ret); + return strlen(buffer); +} +#endif /* CONFIG_UM_TIMER_ONESHOT */ + +#define NS_IN_HZ (1000000000UL) + +/* Freq is in Hz */ +static ssize_t freq_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct timer_info *info = dev_get_drvdata(dev); + unsigned long output_freq; + int err = strict_strtoul(buffer, 10, &output_freq); + if (err) + return err; + + mutex_lock(&info->mtx); + + if (output_freq == 0) { /* Stop timer */ + pwm_disable(info->pwm); + info->period_ns = 0; + info->duty_ns = 0; + } else { + unsigned long new_period = NS_IN_HZ / output_freq; + if (info->period_ns == 0) + info->duty_ns = new_period / 2; + else { + unsigned long long ll = (unsigned long long)new_period * + info->duty_ns ; + do_div(ll, info->period_ns); + info->duty_ns = ll; + } + info->period_ns = new_period; + pwm_config(info->pwm, info->duty_ns, info->period_ns); + pwm_enable(info->pwm); + } + + mutex_unlock(&info->mtx); + + return count; +} + +/* Freq is in Hz */ +static ssize_t freq_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct timer_info *info = dev_get_drvdata(dev); + if (info->period_ns) + snprintf(buffer, PAGE_SIZE - 1, "%ld\n", NS_IN_HZ / + info->period_ns); + else + strlcpy(buffer, "0\n", PAGE_SIZE); + return strlen(buffer); +} + +/* Duty is in 1/1000 units */ +static ssize_t duty_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct timer_info *info = dev_get_drvdata(dev); + unsigned long duty; + int err = strict_strtoul(buffer, 10, &duty); + if (err) + return err; + if (duty > 1000) + return -ERANGE; + + mutex_lock(&info->mtx); + + if ((info->period_ns == 0) || (duty == 0)) { /* Stop timer */ + info->duty_ns = 0; + pwm_disable(info->pwm); + } else { + unsigned long long ll = (unsigned long long)duty * + info->period_ns; + do_div(ll, 1000); + info->duty_ns = ll; + pwm_config(info->pwm, info->duty_ns, info->period_ns); + pwm_enable(info->pwm); + } + + mutex_unlock(&info->mtx); + + return count; +} + +/* Duty is in 1/1000 units */ +static ssize_t duty_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct timer_info *info = dev_get_drvdata(dev); + + mutex_lock(&info->mtx); + + if (info->period_ns) { + volatile unsigned long long ll = info->duty_ns * 1000; + do_div(ll, info->period_ns); + snprintf(buffer, PAGE_SIZE - 1, "%ld\n", (long int)ll); + } else + strlcpy(buffer, "0\n", PAGE_SIZE); + + mutex_unlock(&info->mtx); + + return strlen(buffer); +} + +#ifdef CONFIG_UM_TIMER_ONESHOT +DEVICE_ATTR(wait, S_IRUGO | S_IWUSR, wait_show, wait_store); +#endif /* CONFIG_UM_TIMER_ONESHOT */ +DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, freq_show, freq_store); +DEVICE_ATTR(duty, S_IRUGO | S_IWUSR, duty_show, duty_store); + +static struct attribute *attrs[] = { +#ifdef CONFIG_UM_TIMER_ONESHOT + &dev_attr_wait.attr, +#endif /* CONFIG_UM_TIMER_ONESHOT */ + &dev_attr_frequency.attr, + &dev_attr_duty.attr, + NULL, +}; + +static struct attribute_group attr_grp = { + .attrs = attrs, +}; + +static int timer_probe(struct platform_device *pdev) +{ + struct timer_info *info; + int err; + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + dev_err(&pdev->dev, "out of kernel memory\n"); + err = -ENOMEM; + goto fail_malloc; + } + platform_set_drvdata(pdev, info); + mutex_init(&info->mtx); + info->pwm = pwm_request(pdev->id, "timer driver"); + if (IS_ERR(info->pwm)) { + err = PTR_ERR(info->pwm); + goto fail_req; + } +#ifdef CONFIG_UM_TIMER_ONESHOT + init_waitqueue_head(&info->wq); + info->flag = 1; +#endif /* CONFIG_UM_TIMER_ONESHOT */ + err = sysfs_create_group(&pdev->dev.kobj, &attr_grp); + if (err) { + dev_err(&pdev->dev, "Unable to create virtual files\n"); + goto fail_req; + } + dev_notice(&pdev->dev, "timer %d device driver loaded OK\n", pdev->id); + return 0; +fail_req: + platform_set_drvdata(pdev, NULL); + kfree(info); +fail_malloc: + return err; +} + +static int timer_remove(struct platform_device *pdev) +{ + struct timer_info *info = platform_get_drvdata(pdev); + + mutex_lock(&info->mtx); + + sysfs_remove_group(&pdev->dev.kobj, &attr_grp); + + pwm_free(info->pwm); + platform_set_drvdata(pdev, NULL); + + mutex_unlock(&info->mtx); + + kfree(info); + return 0; +} + +static struct platform_driver timer_driver = { + .probe = timer_probe, + .remove = timer_remove, + .driver = { + .name = "um_timer", + .owner = THIS_MODULE, + }, +}; + +static int __init timer_init_module(void) +{ + return platform_driver_register(&timer_driver); +} + +static void __exit timer_cleanup_module(void) +{ + platform_driver_unregister(&timer_driver); +} + +module_init(timer_init_module); +module_exit(timer_cleanup_module); + +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("Timers driver"); +MODULE_SUPPORTED_DEVICE("um_timers"); +MODULE_LICENSE("GPL v2"); diff -urNp linux-2.6.28.5/drivers/mtd/nand/s3c2410.c linux-2.6.28.5.elpa/drivers/mtd/nand/s3c2410.c --- linux-2.6.28.5/drivers/mtd/nand/s3c2410.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/mtd/nand/s3c2410.c 2009-01-04 07:40:59.000000000 +0100 @@ -898,6 +898,18 @@ static int s3c24xx_nand_probe(struct pla (sets) ? sets->nr_chips : 1); if (nmtd->scan_res == 0) { +#ifdef CONFIG_MTD_CMDLINE_PARTS + /* Replaces 1st set parsing cmdline */ + if (setno == 0) { + const char *part_probes[] = { + "cmdlinepart", NULL + }; + info->mtds->mtd.name = sets->name; + sets->nr_partitions = parse_mtd_partitions( + &info->mtds->mtd, part_probes, + &sets->partitions, 0); + } +#endif s3c2410_nand_update_chip(info, nmtd); nand_scan_tail(&nmtd->mtd); s3c2410_nand_add_partition(info, nmtd, sets); diff -urNp linux-2.6.28.5/drivers/net/enc28j60.c linux-2.6.28.5.elpa/drivers/net/enc28j60.c --- linux-2.6.28.5/drivers/net/enc28j60.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/net/enc28j60.c 2009-01-04 07:40:59.000000000 +0100 @@ -88,26 +88,25 @@ static struct { static int spi_read_buf(struct enc28j60_net *priv, int len, u8 *data) { - u8 *rx_buf = priv->spi_transfer_buf + 4; - u8 *tx_buf = priv->spi_transfer_buf; struct spi_transfer t = { - .tx_buf = tx_buf, - .rx_buf = rx_buf, - .len = SPI_OPLEN + len, + .tx_buf = priv->spi_transfer_buf, + .len = SPI_OPLEN, + }; + struct spi_transfer r = { + .rx_buf = data, + .len = len, }; struct spi_message msg; int ret; - tx_buf[0] = ENC28J60_READ_BUF_MEM; - tx_buf[1] = tx_buf[2] = tx_buf[3] = 0; /* don't care */ + priv->spi_transfer_buf[0] = ENC28J60_READ_BUF_MEM; spi_message_init(&msg); spi_message_add_tail(&t, &msg); + spi_message_add_tail(&r, &msg); ret = spi_sync(priv->spi, &msg); - if (ret == 0) { - memcpy(data, &rx_buf[SPI_OPLEN], len); + if (ret == 0) ret = msg.status; - } if (ret && netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n", __func__, ret); diff -urNp linux-2.6.28.5/drivers/spi/spi_s3c24xx.c linux-2.6.28.5.elpa/drivers/spi/spi_s3c24xx.c --- linux-2.6.28.5/drivers/spi/spi_s3c24xx.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/spi/spi_s3c24xx.c 2009-01-04 07:40:59.000000000 +0100 @@ -120,15 +120,13 @@ static int s3c24xx_spi_setupxfer(struct return -EINVAL; } - div = clk_get_rate(hw->clk) / hz; + if (hz > 25000000) + hz = 25000000; - /* is clk = pclk / (2 * (pre+1)), or is it - * clk = (pclk * 2) / ( pre + 1) */ + div = clk_get_rate(hw->clk) / (hz + 1) / 2; - div /= 2; - - if (div > 0) - div -= 1; + if (div < 0) + div = 0; if (div > 255) div = 255; diff -urNp linux-2.6.28.5/drivers/uio/Kconfig linux-2.6.28.5.elpa/drivers/uio/Kconfig --- linux-2.6.28.5/drivers/uio/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/uio/Kconfig 2009-01-08 16:38:52.000000000 +0100 @@ -13,6 +13,14 @@ menuconfig UIO if UIO +config UIO_S3C2410_GPIO + tristate "S3C2410 general purpose digital I/O driver" + depends on ARCH_S3C2410 + default y + ---help--- + This allows to configure and control general purpose digital + I/O lines from user level code on Samsung S3C2410 SoC + config UIO_CIF tristate "generic Hilscher CIF Card driver" depends on PCI diff -urNp linux-2.6.28.5/drivers/uio/Makefile linux-2.6.28.5.elpa/drivers/uio/Makefile --- linux-2.6.28.5/drivers/uio/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/uio/Makefile 2009-01-08 16:37:43.000000000 +0100 @@ -1,4 +1,5 @@ obj-$(CONFIG_UIO) += uio.o +obj-$(CONFIG_UIO_S3C2410_GPIO) += s3c2410-gpio.o obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o diff -urNp linux-2.6.28.5/drivers/uio/s3c2410-gpio.c linux-2.6.28.5.elpa/drivers/uio/s3c2410-gpio.c --- linux-2.6.28.5/drivers/uio/s3c2410-gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/uio/s3c2410-gpio.c 2009-01-28 20:09:54.000000000 +0100 @@ -0,0 +1,715 @@ +/* + drivers/uio/s3c2410-gpio.c + + Written Feb 2008 by Davide Rizzo + + This driver allows users to read/write general purpose digital I/O functions + and values. + Pin's functions can be accessed with XX-cfg virtual files (can be one of: + input, output, fn1, fn2 or direct function name). + Pin's status (when function is input or output) can be read/set by XX virtual + file. + Pin's pullup can be read/set with XX-pup virtual file (1=on, 0=off). + When a pin is programmed for external interrupt, you can use 2 additional + virtual files: + eintX-cfg access interrupt's mode, can be one of: rising, falling or both. + eintX when read waits until interrupt triggers. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EXT_INTS_NR 24 + +#define S3C2410_GPIO_BANK(x) ((x) * 32) +#define S3C2410_BANKNUM S3C2400_BANKNUM + +struct fn_name { + unsigned int pin; + const char *fn1_name, *fn2_name; +}; + +static const struct fn_name pins[] = +{ + {S3C2410_GPA0, "addr0", NULL}, + {S3C2410_GPA1, "addr16", NULL}, + {S3C2410_GPA2, "addr17", NULL}, + {S3C2410_GPA3, "addr18", NULL}, + {S3C2410_GPA4, "addr19", NULL}, + {S3C2410_GPA5, "addr20", NULL}, + {S3C2410_GPA6, "addr21", NULL}, + {S3C2410_GPA7, "addr22", NULL}, + {S3C2410_GPA8, "addr23", NULL}, + {S3C2410_GPA9, "addr24", NULL}, + {S3C2410_GPA10, "addr25", NULL}, + {S3C2410_GPA11, "addr26", NULL}, + {S3C2410_GPA12, "gcs1", NULL}, + {S3C2410_GPA13, "gcs2", NULL}, + {S3C2410_GPA14, "gcs3", NULL}, + {S3C2410_GPA15, "gcs4", NULL}, + {S3C2410_GPA16, "gcs5", NULL}, + {S3C2410_GPA17, "cle", NULL}, + {S3C2410_GPA18, "ale", NULL}, + {S3C2410_GPA19, "fwe", NULL}, + {S3C2410_GPA20, "fre", NULL}, + {S3C2410_GPA21, "rstout", NULL}, + {S3C2410_GPA22, "fce", NULL}, + {S3C2410_GPB0, "tout0", NULL}, + {S3C2410_GPB1, "tout1", NULL}, + {S3C2410_GPB2, "tout2", NULL}, + {S3C2410_GPB3, "tout3", NULL}, + {S3C2410_GPB4, "tclk0", NULL}, + {S3C2410_GPB5, "xback", NULL}, + {S3C2410_GPB6, "xbreq", NULL}, + {S3C2410_GPB7, "xdack1", NULL}, + {S3C2410_GPB8, "xdreq1", NULL}, + {S3C2410_GPB9, "xdack0", NULL}, + {S3C2410_GPB10, "xdreq0", NULL}, + {S3C2410_GPC0, "lend", NULL}, + {S3C2410_GPC1, "vclk", NULL}, + {S3C2410_GPC2, "vline", NULL}, + {S3C2410_GPC3, "vframe", NULL}, + {S3C2410_GPC4, "vm", NULL}, + {S3C2410_GPC5, "lcdvf0", NULL}, + {S3C2410_GPC6, "lcdvf1", NULL}, + {S3C2410_GPC7, "lcdvf2", NULL}, + {S3C2410_GPC8, "vd0", NULL}, + {S3C2410_GPC9, "vd1", NULL}, + {S3C2410_GPC10, "vd2", NULL}, + {S3C2410_GPC11, "vd3", NULL}, + {S3C2410_GPC12, "vd4", NULL}, + {S3C2410_GPC13, "vd5", NULL}, + {S3C2410_GPC14, "vd6", NULL}, + {S3C2410_GPC15, "vd7", NULL}, + {S3C2410_GPD0, "vd8", NULL}, + {S3C2410_GPD1, "vd9", NULL}, + {S3C2410_GPD2, "vd10", NULL}, + {S3C2410_GPD3, "vd11", NULL}, + {S3C2410_GPD4, "vd12", NULL}, + {S3C2410_GPD5, "vd13", NULL}, + {S3C2410_GPD6, "vd14", NULL}, + {S3C2410_GPD7, "vd15", NULL}, + {S3C2410_GPD8, "vd16", NULL}, + {S3C2410_GPD9, "vd17", NULL}, + {S3C2410_GPD10, "vd18", NULL}, + {S3C2410_GPD11, "vd19", NULL}, + {S3C2410_GPD12, "vd20", NULL}, + {S3C2410_GPD13, "vd21", NULL}, + {S3C2410_GPD14, "vd22", "ss1"}, + {S3C2410_GPD15, "vd23", "ss0"}, + {S3C2410_GPE0, "i2slrck", NULL}, + {S3C2410_GPE1, "i2ssclk", NULL}, + {S3C2410_GPE2, "cdclk", NULL}, + {S3C2410_GPE3, "i2ssdi", "ss0"}, + {S3C2410_GPE4, "i2ssdo", "i2ssdi"}, + {S3C2410_GPE5, "sdclk", NULL}, + {S3C2410_GPE6, "sdcmd", NULL}, + {S3C2410_GPE7, "sddat0", NULL}, + {S3C2410_GPE8, "sddat1", NULL}, + {S3C2410_GPE9, "sddat2", NULL}, + {S3C2410_GPE10, "sddat3", NULL}, + {S3C2410_GPE11, "spimiso0", NULL}, + {S3C2410_GPE12, "spimosi0", NULL}, + {S3C2410_GPE13, "spiclk0", NULL}, + {S3C2410_GPE14, "iicscl", NULL}, + {S3C2410_GPE15, "iicsda", NULL}, + {S3C2410_GPF0, "eint0", NULL}, + {S3C2410_GPF1, "eint1", NULL}, + {S3C2410_GPF2, "eint2", NULL}, + {S3C2410_GPF3, "eint3", NULL}, + {S3C2410_GPF4, "eint4", NULL}, + {S3C2410_GPF5, "eint5", NULL}, + {S3C2410_GPF6, "eint6", NULL}, + {S3C2410_GPF7, "eint7", NULL}, + {S3C2410_GPG0, "eint8", NULL}, + {S3C2410_GPG1, "eint9", NULL}, + {S3C2410_GPG2, "eint10", "ss0"}, + {S3C2410_GPG3, "eint11", "ss1"}, + {S3C2410_GPG4, "eint12", "lcdpwren"}, + {S3C2410_GPG5, "eint13", "spimiso1"}, + {S3C2410_GPG6, "eint14", "spimosi1"}, + {S3C2410_GPG7, "eint15", "spiclk1"}, + {S3C2410_GPG8, "eint16", NULL}, + {S3C2410_GPG9, "eint17", NULL}, + {S3C2410_GPG10, "eint18", NULL}, + {S3C2410_GPG11, "eint19", "tclk1"}, + {S3C2410_GPG12, "eint20", "xmon"}, + {S3C2410_GPG13, "eint21", "xpon"}, + {S3C2410_GPG14, "eint22", "ymon"}, + {S3C2410_GPG15, "eint23", "ypon"}, + {S3C2410_GPH0, "cts0", NULL}, + {S3C2410_GPH1, "rts0", NULL}, + {S3C2410_GPH2, "txd0", NULL}, + {S3C2410_GPH3, "rxd0", NULL}, + {S3C2410_GPH4, "txd1", NULL}, + {S3C2410_GPH5, "rxd1", NULL}, + {S3C2410_GPH6, "txd2", "rts1"}, + {S3C2410_GPH7, "rxd2", "cts1"}, + {S3C2410_GPH8, "uextclk", NULL}, + {S3C2410_GPH9, "clkout0", NULL}, + {S3C2410_GPH10, "clkout1", NULL} +}; + +struct ext_int { + unsigned int on, flag; + struct device_attribute int_wait, int_cfg; + wait_queue_head_t wq; + struct mutex mtx; + char int_wait_name[8], int_cfg_name[12]; + unsigned long irqflags; +}; + +struct s3c2410_gpio_info { + struct mutex mtx; + struct device_attribute at[3 * ARRAY_SIZE(pins)]; + struct device_attribute at_pd[8]; + struct device_attribute at_pwrmask[8]; + struct ext_int eint[EXT_INTS_NR]; + const struct s3c24xx_gpio_platdata *pdata; + unsigned long wrmask[8]; + char pd_name[8][2]; + char pwmsk_name[8][6]; + char at_name[ARRAY_SIZE(pins)][3][8]; +}; + +static const struct s3c24xx_gpio_platdata s3c2410_gpio_defplat = { + .port_mask = { + 0xFFFFFF, 0x0007FF, 0x00FFFF, 0x00FFFF, + 0x00FFFF, 0x0000FF, 0x00FFFF, 0x0007FF } +}; + +static const char *pin_fn1_name(unsigned int pin) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(pins); i++) + if (pins[i].pin == pin) + return pins[i].fn1_name; + return NULL; +} + +static const char *pin_fn2_name(unsigned int pin) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(pins); i++) + if (pins[i].pin == pin) + return pins[i].fn2_name; + return NULL; +} + +static unsigned int getpin(const char *name) +{ + return S3C2410_GPIONO(S3C2410_GPIO_BANK(name[0] - 'a'), + simple_strtoul(name + 1, NULL, 10)); +} + +static irqreturn_t eint_isr(int irq, void *arg) +{ + struct ext_int *ext = arg; + + ext->flag = 1; + wake_up_interruptible(&ext->wq); + return IRQ_HANDLED; +} + +static void update_interrupt_handler(struct device *dev, unsigned int pin) +{ + struct ext_int *ei; + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + int eintnr; + + if ((pin >= S3C2410_GPF0) && (pin <= S3C2410_GPF7)) + eintnr = pin - S3C2410_GPF0; + else if ((pin >= S3C2410_GPG0) && (pin <= S3C2410_GPG15)) + eintnr = pin - S3C2410_GPG0 + 8; + else + return; + + ei = &info->eint[eintnr]; + if (s3c2410_gpio_getcfg(pin) == S3C2410_GPIO_IRQ) { + if (!ei->on) { + /* Create device nodes and allocate irq */ + ei->irqflags = IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED; + if (!device_create_file(dev, &ei->int_cfg)) { + if (!device_create_file(dev, &ei->int_wait)) + ei->on = 1; + else + device_remove_file(dev, &ei->int_cfg); + } + } + } else { + if (ei->on) { + /* Remove device nodes and deallocate irq */ + device_remove_file(dev, &ei->int_cfg); + device_remove_file(dev, &ei->int_wait); + while (mutex_is_locked(&ei->mtx)) { + ei->flag = 1; + wake_up_interruptible(&ei->wq); + schedule(); + } + ei->on = 0; + } + } +} + +static ssize_t pullup_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + snprintf(buffer, PAGE_SIZE - 1, "%d\n", + s3c2410_gpio_getpull(getpin(attr->attr.name)) ? 0 : 1); + return strlen(buffer); +} + +static ssize_t config_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + const char *name; + unsigned int pin = getpin(attr->attr.name); + + switch (s3c2410_gpio_getcfg(pin)) { + case S3C2410_GPIO_INPUT: + strlcpy(buffer, "in\n", PAGE_SIZE); + break; + case S3C2410_GPIO_OUTPUT: + strlcpy(buffer, "out\n", PAGE_SIZE); + break; + case S3C2410_GPIO_SFN2: + name = pin_fn1_name(pin); + strlcpy(buffer, name ? name : "invalid", PAGE_SIZE); + strlcat(buffer, "\n", PAGE_SIZE); + break; + case S3C2410_GPIO_SFN3: + name = pin_fn2_name(pin); + strlcpy(buffer, name ? name : "invalid", PAGE_SIZE); + strlcat(buffer, "\n", PAGE_SIZE); + break; + default: + buffer[0] = '\0'; + break; + } + return strlen(buffer); +} + +static ssize_t value_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + snprintf(buffer, PAGE_SIZE - 1, "%d\n", + s3c2410_gpio_getpin(getpin(attr->attr.name)) ? 1 : 0); + return strlen(buffer); +} + +static ssize_t pullup_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + s3c2410_gpio_pullup(getpin(attr->attr.name), (buf[0] == '0') ? 1 : 0); + return count; +} + +static ssize_t config_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + const char *name; + unsigned int pin = getpin(attr->attr.name); + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + + mutex_lock(&info->mtx); + + do { + if (S3C2410_BANKNUM(pin) != 0) { + /* No input on bank A */ + if (!strncasecmp(buffer, "in", 2)) { + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); + break; + } + } + if (!strncasecmp(buffer, "out", 3)) { + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_OUTPUT); + break; + } + name = pin_fn1_name(pin); + if (name) { + if ((!strncasecmp(buffer, name, strlen(name))) || + !strncasecmp(buffer, "fn1", 3)) { + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_SFN2); + break; + } + } + name = pin_fn2_name(pin); + if (name) { + if ((!strncasecmp(buffer, name, strlen(name))) || + !strncasecmp(buffer, "fn2", 3)) { + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_SFN3); + break; + } + } + } while (0); + update_interrupt_handler(dev, pin); + + mutex_unlock(&info->mtx); + + return count; +} + +static ssize_t value_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + s3c2410_gpio_setpin(getpin(attr->attr.name), (buf[0] == '0') ? 0 : 1); + return count; +} + +static ssize_t eint_cfg_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + + switch (info->eint[simple_strtoul(attr->attr.name + 4, NULL, 10)] + .irqflags) { + case IRQ_TYPE_EDGE_RISING | IRQF_DISABLED: + strlcpy(buffer, "rising\n", PAGE_SIZE); + break; + case IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED: + strlcpy(buffer, "falling\n", PAGE_SIZE); + break; + case IRQ_TYPE_EDGE_BOTH | IRQF_DISABLED: + strlcpy(buffer, "bothedge\n", PAGE_SIZE); + break; + case IRQ_TYPE_LEVEL_LOW | IRQF_DISABLED: + strlcpy(buffer, "low\n", PAGE_SIZE); + break; + case IRQ_TYPE_LEVEL_HIGH | IRQF_DISABLED: + strlcpy(buffer, "high\n", PAGE_SIZE); + break; + default: + buffer[0] = 0; + } + return strlen(buffer); +} + +static ssize_t eint_cfg_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + int eint = simple_strtoul(attr->attr.name + 4, NULL, 10); + struct ext_int *ei = &info->eint[eint]; + + mutex_lock(&ei->mtx); + + if (!strncasecmp(buffer, "rising", 6)) + ei->irqflags = IRQ_TYPE_EDGE_RISING | IRQF_DISABLED; + else if (!strncasecmp(buffer, "bothedge", 8)) + ei->irqflags = IRQ_TYPE_EDGE_BOTH | IRQF_DISABLED; + else if (!strncasecmp(buffer, "low", 3)) + ei->irqflags = IRQ_TYPE_LEVEL_LOW | IRQF_DISABLED; + else if (!strncasecmp(buffer, "high", 4)) + ei->irqflags = IRQ_TYPE_LEVEL_HIGH | IRQF_DISABLED; + else /* Default: falling edge */ + ei->irqflags = IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED; + + update_interrupt_handler(dev, eint < 8 ? + eint + S3C2410_GPF0 : eint - 8 + S3C2410_GPG0); + + mutex_unlock(&ei->mtx); + + return strlen(buffer); +} + +/* Waits for eint */ +static ssize_t eint_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + unsigned long eint = simple_strtoul(attr->attr.name + 4, NULL, 10); + struct ext_int *ei = &info->eint[eint]; + int ret; + + mutex_lock(&ei->mtx); + + ei->flag = 0; + ret = request_irq(IRQ_EINT(eint), eint_isr, ei->irqflags, + ei->int_wait_name, ei); + if (ret == 0) { + ret = wait_event_interruptible(ei->wq, ei->flag); + /* ret!=0 if interrupted by some other signal */ + free_irq(IRQ_EINT(eint), ei); + } + + mutex_unlock(&ei->mtx); + + snprintf(buffer, PAGE_SIZE - 1, "%d\n", ret); + return strlen(buffer); +} + +static ssize_t port_mask_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + int port = attr->attr.name[0] - 'a'; + + snprintf(buffer, PAGE_SIZE - 1, "%lu\n", info->wrmask[port]); + return strlen(buffer); +} + +static ssize_t port_mask_store(struct device *dev, + struct device_attribute *attr, const char *buffer, size_t count) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + unsigned long mask; + int port = attr->attr.name[0] - 'a'; + int err = strict_strtoul(buffer, 10, &mask); + + if (err) + return err; + + info->wrmask[port] = mask & info->pdata->port_mask[port]; + return strlen(buffer); +} + +static ssize_t port_show(struct device *dev, struct device_attribute *attr, + char *buffer) +{ + int port = attr->attr.name[0] - 'a'; + + snprintf(buffer, PAGE_SIZE - 1, "%u\n", + readl(S3C2410_GPADAT + 16 * port)); + return strlen(buffer); +} + +static ssize_t port_store(struct device *dev, struct device_attribute *attr, + const char *buffer, size_t count) +{ + struct s3c2410_gpio_info *info = dev_get_drvdata(dev); + int port = attr->attr.name[0] - 'a'; + unsigned long new, old; + int err = strict_strtoul(buffer, 10, &new); + + if (err) + return err; + + mutex_lock(&info->mtx); + + old = readl(S3C2410_GPADAT + 16 * port); + + writel(((old & ~info->wrmask[port]) | (new & info->wrmask[port])), + S3C2410_GPADAT + 16 * port); + + mutex_unlock(&info->mtx); + + return strlen(buffer); +} + +static int s3c2410gpio_probe(struct platform_device *pdev) +{ + int i, err; + struct s3c2410_gpio_info *info = kzalloc(sizeof(*info), GFP_KERNEL); + struct device_attribute *at; + + if (!info) { + dev_err(&pdev->dev, "out of kernel memory\n"); + err = -ENOMEM; + goto fail_malloc; + } + mutex_init(&info->mtx); + platform_set_drvdata(pdev, info); + info->pdata = pdev->dev.platform_data ? + pdev->dev.platform_data : &s3c2410_gpio_defplat; + + for (i = 0; i < 8; i++) { + snprintf(info->pd_name[i], + sizeof(info->pd_name[0]), "%c", 'a' + i); + info->at_pd[i].attr.mode = S_IRUGO | S_IWUSR; + info->at_pd[i].attr.name = info->pd_name[i]; + info->at_pd[i].show = port_show; + info->at_pd[i].store = port_store; + err = device_create_file(&pdev->dev, &info->at_pd[i]); + if (err) { + dev_err(&pdev->dev, + "Unable to create virtual file\n"); + goto fail_create; + } + snprintf(info->pwmsk_name[i], + sizeof(info->pwmsk_name[0]), "%c-msk", 'a' + i); + info->at_pwrmask[i].attr.mode = S_IRUGO | S_IWUSR; + info->at_pwrmask[i].attr.name = info->pwmsk_name[i]; + info->at_pwrmask[i].show = port_mask_show; + info->at_pwrmask[i].store = port_mask_store; + err = device_create_file(&pdev->dev, &info->at_pwrmask[i]); + if (err) { + dev_err(&pdev->dev, + "Unable to create virtual file\n"); + goto fail_create; + } + } + + for (i = 0; i < EXT_INTS_NR; i++) { + /* Initialize eint device attributes */ + snprintf(info->eint[i].int_cfg_name, + sizeof(info->eint[0].int_cfg_name), "eint%d-cfg", i); + info->eint[i].int_cfg.attr.mode = S_IRUGO | S_IWUSR; + info->eint[i].int_cfg.attr.name = info->eint[i].int_cfg_name; + info->eint[i].int_cfg.show = eint_cfg_show; + info->eint[i].int_cfg.store = eint_cfg_store; + snprintf(info->eint[i].int_wait_name, + sizeof(info->eint[0].int_wait_name), "eint%d", i); + info->eint[i].int_wait.attr.mode = S_IRUGO; + info->eint[i].int_wait.attr.name = info->eint[i].int_wait_name; + info->eint[i].int_wait.show = eint_show; + mutex_init(&info->eint[i].mtx); + init_waitqueue_head(&info->eint[i].wq); + } + + for (at = info->at, i = 0; i < ARRAY_SIZE(pins); i++) { + int pin = pins[i].pin; + int bank = S3C2410_BANKNUM(pin); + int offset = S3C2410_GPIO_OFFSET(pin); + if ((info->pdata->port_mask[bank]) & (1 << offset)) { + if (bank > 0) { + /* No pullup on bank A */ + at->attr.mode = S_IRUGO | S_IWUSR; + snprintf(info->at_name[i][0], + sizeof(info->at_name[0][0]), + "%c%d-pup", + bank + 'a', offset); + at->attr.name = info->at_name[i][0]; + at->show = pullup_show; + at->store = pullup_store; + err = device_create_file(&pdev->dev, at++); + if (err) { + dev_err(&pdev->dev, + "Unable to create virtual file\n"); + goto fail_create; + } + } + at->attr.mode = S_IRUGO | S_IWUSR; + snprintf(info->at_name[i][1], + sizeof(info->at_name[0][0]), + "%c%d-cfg", bank + 'a', + offset); + at->attr.name = info->at_name[i][1]; + at->show = config_show; + at->store = config_store; + err = device_create_file(&pdev->dev, at++); + if (err) { + dev_err(&pdev->dev, + "Unable to create virtual file\n"); + goto fail_create; + } + at->attr.mode = S_IRUGO | S_IWUSR; + snprintf(info->at_name[i][2], + sizeof(info->at_name[0][0]), + "%c%d", bank + 'a', + offset); + at->attr.name = info->at_name[i][2]; + at->show = value_show; + at->store = value_store; + err = device_create_file(&pdev->dev, at++); + if (err) { + dev_err(&pdev->dev, + "Unable to create virtual file\n"); + goto fail_create; + } + update_interrupt_handler(&pdev->dev, pin); + } + } + dev_notice(&pdev->dev, "S3C2410 gpio driver loaded OK\n"); + return 0; + +fail_create: + at = info->at; + while (at-- >= info->at) + device_remove_file(&pdev->dev, at); + + for (i = 0; i < EXT_INTS_NR; i++) + if (info->eint[i].on) { + device_remove_file(&pdev->dev, &info->eint[i].int_cfg); + device_remove_file(&pdev->dev, &info->eint[i].int_wait); + } + + for (i = 0; i < 8; i++) { + device_remove_file(&pdev->dev, &info->at_pd[i]); + device_remove_file(&pdev->dev, &info->at_pwrmask[i]); + } + + platform_set_drvdata(pdev, NULL); + kfree(info); + +fail_malloc: + return err; +} + +static int s3c2410gpio_remove(struct platform_device *pdev) +{ + struct s3c2410_gpio_info *info = platform_get_drvdata(pdev); + struct device_attribute *at; + int i; + + for (at = info->at, i = 0; i < 3 * ARRAY_SIZE(pins); i++, at++) + if (at->attr.name) + device_remove_file(&pdev->dev, at); + + for (i = 0; i < EXT_INTS_NR; i++) + if (info->eint[i].on) { + device_remove_file(&pdev->dev, &info->eint[i].int_cfg); + device_remove_file(&pdev->dev, &info->eint[i].int_wait); + while (mutex_is_locked(&info->eint[i].mtx)) { + info->eint[i].flag = 1; + wake_up_interruptible(&info->eint[i].wq); + schedule(); + } + } + + for (i = 0; i < 8; i++) { + device_remove_file(&pdev->dev, &info->at_pd[i]); + device_remove_file(&pdev->dev, &info->at_pwrmask[i]); + } + + platform_set_drvdata(pdev, NULL); + kfree(info); + dev_notice(&pdev->dev, "S3C2410 gpio driver exit\n"); + return 0; +} + +static struct platform_driver s3c2410gpio_driver = { + .probe = s3c2410gpio_probe, + .remove = s3c2410gpio_remove, + .driver = { + .name = "s3c2410-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c2410_gpio_init_module(void) +{ + return platform_driver_register(&s3c2410gpio_driver); +} + +static void __exit s3c2410_gpio_cleanup_module(void) +{ + platform_driver_unregister(&s3c2410gpio_driver); +} + +module_init(s3c2410_gpio_init_module); +module_exit(s3c2410_gpio_cleanup_module); + +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("S3C2410 ELPA Gpio driver"); +MODULE_SUPPORTED_DEVICE("gpio/s3c2410"); +MODULE_LICENSE("GPL"); diff -urNp linux-2.6.28.5/drivers/usb/gadget/Kconfig linux-2.6.28.5.elpa/drivers/usb/gadget/Kconfig --- linux-2.6.28.5/drivers/usb/gadget/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/usb/gadget/Kconfig 2009-01-04 07:40:59.000000000 +0100 @@ -272,7 +272,7 @@ config USB_PXA27X config USB_GADGET_S3C2410 boolean "S3C2410 USB Device Controller" - depends on ARCH_S3C2410 + depends on ARCH_S3C2410 && (RD129_USB_1HOST || RD129_USB_AUTO || !MACH_RD129) help Samsung's S3C2410 is an ARM-4 processor with an integrated full speed USB 1.1 device controller. It has 4 configurable diff -urNp linux-2.6.28.5/drivers/usb/host/Kconfig linux-2.6.28.5.elpa/drivers/usb/host/Kconfig --- linux-2.6.28.5/drivers/usb/host/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/usb/host/Kconfig 2009-01-04 07:40:59.000000000 +0100 @@ -140,6 +140,32 @@ config USB_OHCI_HCD To compile this driver as a module, choose M here: the module will be called ohci-hcd. ++choice + depends on USB_OHCI_HCD && MACH_RD129 + prompt "Samsung S3C2410 USB Host ports" + default RD129_USB_2HOST + +config RD129_USB_1HOST + bool "1 Usb Host port, 1 Usb Device (gadget) port" + select USB_GADGET_S3C2410 + help + Usb port 2 is configured like usb device (gadget) + +config RD129_USB_2HOST + bool "2 Usb Host ports" + help + Usb port 2 is configured like usb host + +config RD129_USB_AUTO + bool "Autoselect" + select USB_GADGET_S3C2410 + depends on ARCH_S3C2410 + help + If GPD0 is strapped down, Usb port 2 is configured like usb device + Otherwise, it's configured like usb host + +endchoice + config USB_OHCI_HCD_PPC_SOC bool "OHCI support for on-chip PPC USB controller" depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) diff -urNp linux-2.6.28.5/drivers/video/backlight/Kconfig linux-2.6.28.5.elpa/drivers/video/backlight/Kconfig --- linux-2.6.28.5/drivers/video/backlight/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/video/backlight/Kconfig 2009-01-06 18:31:15.000000000 +0100 @@ -183,6 +183,13 @@ config BACKLIGHT_PWM If you have a LCD backlight adjustable by PWM, say Y to enable this driver. +config BACKLIGHT_PWM_FREQUENCY + int "PWM Backlight Dimming Frequency" + depends on BACKLIGHT_PWM + default 20000 + help + Frequency of PWM signal for backlight dimming + config BACKLIGHT_DA903X tristate "Backlight Driver for DA9030/DA9034 using WLED" depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X diff -urNp linux-2.6.28.5/drivers/video/s3c2410fb.c linux-2.6.28.5.elpa/drivers/video/s3c2410fb.c --- linux-2.6.28.5/drivers/video/s3c2410fb.c 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/video/s3c2410fb.c 2009-01-06 19:31:16.000000000 +0100 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,8 @@ static int debug = 0; /* useful functions */ +static int s3c2410fb_init_registers(struct fb_info *info); + static int is_s3c2412(struct s3c2410fb_info *fbi) { return (fbi->drv_type == DRV_S3C2412); @@ -124,6 +127,12 @@ static int s3c2410fb_check_var(struct fb dprintk("check_var(var=%p, info=%p)\n", var, info); + if (var->nonstd) { + fbi->regs.lcdcon1 = var->nonstd & 0xFFFF; + fbi->regs.lcdcon5 = var->nonstd >> 16; + return 0; + } + /* validate x/y resolution */ /* choose default mode if possible */ if (var->yres == default_display->yres && @@ -245,7 +254,7 @@ static void s3c2410fb_calculate_stn_lcd_ { const struct s3c2410fb_info *fbi = info->par; const struct fb_var_screeninfo *var = &info->var; - int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT; + int type = regs->lcdcon1 & S3C2410_LCDCON1_TFT; int hs = var->xres >> 2; unsigned wdly = (var->left_margin >> 4) - 1; unsigned wlh = (var->hsync_len >> 4) - 1; @@ -350,8 +359,8 @@ static void s3c2410fb_calculate_tft_lcd_ S3C2410_LCDCON2_VFPD(var->lower_margin - 1) | S3C2410_LCDCON2_VSPW(var->vsync_len - 1); - regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) | - S3C2410_LCDCON3_HFPD(var->left_margin - 1) | + regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->left_margin - 1) | + S3C2410_LCDCON3_HFPD(var->right_margin - 1) | S3C2410_LCDCON3_HOZVAL(var->xres - 1); regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1); @@ -396,15 +405,22 @@ static void s3c2410fb_activate_var(struc dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4); dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5); - writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, - regs + S3C2410_LCDCON1); - writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); - writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); - writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); - writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); - - /* set lcd address pointers */ - s3c2410fb_set_lcdaddr(info); + /* This was added to change refresh without stopping LCD controller */ + if (((fbi->regs.lcdcon1 & 0xFE) != + (readl(regs + S3C2410_LCDCON1) & 0xFE)) || + (fbi->regs.lcdcon2 != readl(regs + S3C2410_LCDCON2)) || + (fbi->regs.lcdcon3 != readl(regs + S3C2410_LCDCON3)) || + (fbi->regs.lcdcon4 != readl(regs + S3C2410_LCDCON4)) || + (fbi->regs.lcdcon5 != readl(regs + S3C2410_LCDCON5))) { + writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, + regs + S3C2410_LCDCON1); + writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); + writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); + writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); + writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); + /* set lcd address pointers */ + s3c2410fb_set_lcdaddr(info); + } fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID, writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); @@ -419,6 +435,8 @@ static int s3c2410fb_set_par(struct fb_i { struct fb_var_screeninfo *var = &info->var; + s3c2410fb_init_registers(info); + switch (var->bits_per_pixel) { case 32: case 16: @@ -607,6 +625,28 @@ static int s3c2410fb_debug_store(struct return len; } +static int s3c2410fb_wait_vsync_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + long ret; + struct fb_info *info = dev_get_drvdata(dev); + struct s3c2410fb_info *fbi = info->par; + void __iomem *irq_base = fbi->irq_base; + fbi->flag_endframe = 0; + /* enable IRQ */ + writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); + writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); + writel(readl(fbi->io + S3C2410_LCDINTMSK) & ~S3C2410_LCDINT_FRSYNC, + fbi->io + S3C2410_LCDINTMSK); + ret = wait_event_interruptible_timeout(fbi->ctrlr_wait, + fbi->flag_endframe, HZ / 5); + /* disable IRQ */ + writel(readl(fbi->io + S3C2410_LCDINTMSK) | S3C2410_LCDINT_FRSYNC, + fbi->io + S3C2410_LCDINTMSK); + return snprintf(buf, PAGE_SIZE, "%ld\n", ret); +} + +static DEVICE_ATTR(wait_vsync, S_IRUGO, s3c2410fb_wait_vsync_show, NULL); static DEVICE_ATTR(debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store); static struct fb_ops s3c2410fb_ops = { @@ -753,6 +793,10 @@ static irqreturn_t s3c2410fb_irq(int irq writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); + + fbi->flag_endframe = 1; + wake_up_interruptible(&fbi->ctrlr_wait); + } return IRQ_HANDLED; @@ -773,7 +817,9 @@ static int __init s3c24xxfb_probe(struct int i; int size; u32 lcdcon1; + int base; /* To store address of original image */ + base = 0; mach_info = pdev->dev.platform_data; if (mach_info == NULL) { dev_err(&pdev->dev, @@ -831,11 +877,18 @@ static int __init s3c24xxfb_probe(struct dprintk("devinit\n"); - strcpy(fbinfo->fix.id, driver_name); + init_waitqueue_head(&info->ctrlr_wait); - /* Stop the video */ lcdcon1 = readl(info->io + S3C2410_LCDCON1); - writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); + if (S3C2410_LCDCON1_ENVID & lcdcon1) + /* Store bootloader image's address */ + base = 2 * readl(info->io + S3C2410_LCDSADDR1); + else + /* Stop the video */ + writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, + info->io + S3C2410_LCDCON1); + + strlcpy(fbinfo->fix.id, driver_name, sizeof(fbinfo->fix.id)); fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; fbinfo->fix.type_aux = 0; @@ -900,8 +953,6 @@ static int __init s3c24xxfb_probe(struct fbinfo->var.yres = display->yres; fbinfo->var.bits_per_pixel = display->bpp; - s3c2410fb_init_registers(fbinfo); - s3c2410fb_check_var(&fbinfo->var, fbinfo); ret = register_framebuffer(fbinfo); @@ -917,9 +968,16 @@ static int __init s3c24xxfb_probe(struct printk(KERN_ERR "failed to add debug attribute\n"); } + device_create_file(&pdev->dev, &dev_attr_wait_vsync); + printk(KERN_INFO "fb%d: %s frame buffer device\n", fbinfo->node, fbinfo->fix.id); + /* To restore bootloader image */ + if (base) + memcpy((void *)fbinfo->screen_base, __va((const void *)base), + fbinfo->fix.smem_len); + return 0; free_video_memory: @@ -960,6 +1018,9 @@ static int s3c2410fb_remove(struct platf struct s3c2410fb_info *info = fbinfo->par; int irq; + device_remove_file(&pdev->dev, &dev_attr_debug); + device_remove_file(&pdev->dev, &dev_attr_wait_vsync); + unregister_framebuffer(fbinfo); s3c2410fb_lcd_enable(info, 0); diff -urNp linux-2.6.28.5/drivers/video/s3c2410fb.h linux-2.6.28.5.elpa/drivers/video/s3c2410fb.h --- linux-2.6.28.5/drivers/video/s3c2410fb.h 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/drivers/video/s3c2410fb.h 2009-01-04 07:40:59.000000000 +0100 @@ -31,6 +31,9 @@ struct s3c2410fb_info { unsigned int palette_ready; + wait_queue_head_t ctrlr_wait; + int flag_endframe; + /* keep these registers in case we need to re-write palette */ u32 palette_buffer[256]; u32 pseudo_pal[16]; diff -urNp linux-2.6.28.5/include/linux/clk.h linux-2.6.28.5.elpa/include/linux/clk.h --- linux-2.6.28.5/include/linux/clk.h 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/include/linux/clk.h 2009-02-12 19:05:31.000000000 +0100 @@ -125,4 +125,21 @@ int clk_set_parent(struct clk *clk, stru */ struct clk *clk_get_parent(struct clk *clk); +/** + * clk_for_each - calls fn, iterating between registered clocks + * @fn: function to be called, passing each clk structure in 1st argument + * @data: 2nd argument to pass to fn function + * + * Returns 0 or the called fn return code if != 0 + */ +int clk_for_each(int(*fn)(struct clk *, void *), void *data); + +/** + * clk_name - get clock name + * @clk: clock source + * + * Returns clock's sysname + */ +const char *clk_get_sysname(struct clk *clk); + #endif diff -urNp linux-2.6.28.5/include/linux/pwm.h linux-2.6.28.5.elpa/include/linux/pwm.h --- linux-2.6.28.5/include/linux/pwm.h 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/include/linux/pwm.h 2009-01-06 19:35:19.000000000 +0100 @@ -19,6 +19,13 @@ void pwm_free(struct pwm_device *pwm); int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); /* + * pwm_one_shot - programs and starts a timer for one-shot operation + * when expired calls callback + */ +int pwm_one_shot(struct pwm_device *pwm, int timeout_ns, + void(*expired)(struct pwm_device *, void *arg), void *arg); + +/* * pwm_enable - start a PWM output toggling */ int pwm_enable(struct pwm_device *pwm); diff -urNp linux-2.6.28.5/sound/soc/codecs/Kconfig linux-2.6.28.5.elpa/sound/soc/codecs/Kconfig --- linux-2.6.28.5/sound/soc/codecs/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/codecs/Kconfig 2009-01-08 12:19:02.000000000 +0100 @@ -6,6 +6,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AD73311 select SND_SOC_AK4535 select SND_SOC_CS4270 + select SND_SOC_PCM3006 select SND_SOC_SSM2602 select SND_SOC_TLV320AIC23 select SND_SOC_TLV320AIC26 @@ -60,6 +61,9 @@ config SND_SOC_CS4270_VD33_ERRATA bool depends on SND_SOC_CS4270 +config SND_SOC_PCM3006 + tristate + config SND_SOC_SSM2602 tristate diff -urNp linux-2.6.28.5/sound/soc/codecs/Makefile linux-2.6.28.5.elpa/sound/soc/codecs/Makefile --- linux-2.6.28.5/sound/soc/codecs/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/codecs/Makefile 2009-01-04 09:00:28.000000000 +0100 @@ -3,6 +3,7 @@ snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-ak4535-objs := ak4535.o snd-soc-cs4270-objs := cs4270.o +snd-soc-pcm3006-objs := pcm3006.o snd-soc-ssm2602-objs := ssm2602.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o @@ -25,6 +26,7 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc- obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o +obj-$(CONFIG_SND_SOC_PCM3006) += snd-soc-pcm3006.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o diff -urNp linux-2.6.28.5/sound/soc/codecs/pcm3006.c linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.c --- linux-2.6.28.5/sound/soc/codecs/pcm3006.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.c 2009-01-28 20:10:17.000000000 +0100 @@ -0,0 +1,104 @@ +/* + * pcm3006.c -- ALSA Soc PCM3006 codec support + * + * Copyright 2008 ELPA sas + * Author: Davide Rizzo + * elpa.rizzo@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 +#include +#include + +#define STD_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +struct snd_soc_dai pcm3006_dai = { + .name = "PCM3006", + .type = SND_SOC_DAI_I2S, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, + .formats = STD_I2S_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, + .formats = STD_I2S_FORMATS,}, +}; +EXPORT_SYMBOL_GPL(pcm3006_dai); + +static int pcm3006_soc_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret; + + printk(KERN_INFO "PCM3006 SoC Audio Codec\n"); + + socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->codec == NULL) + return -ENOMEM; + codec = socdev->codec; + mutex_init(&codec->mutex); + + codec->name = "PCM3006"; + codec->owner = THIS_MODULE; + codec->dai = &pcm3006_dai; + codec->num_dai = 1; + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) + goto err; + + ret = snd_soc_register_card(socdev); + if (ret < 0) + goto bus_err; + return 0; + +bus_err: + snd_soc_free_pcms(socdev); + +err: + kfree(socdev->codec->reg_cache); + kfree(socdev->codec); + socdev->codec = NULL; + return ret; +} + +static int pcm3006_soc_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->codec; + + if (codec == NULL) + return 0; + + snd_soc_free_pcms(socdev); + kfree(socdev->codec->reg_cache); + kfree(socdev->codec); + + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_pcm3006 = { + .probe = pcm3006_soc_probe, + .remove = pcm3006_soc_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3006); + +MODULE_DESCRIPTION("PCM3006 audio codec driver"); +MODULE_AUTHOR("Davide Rizzo "); +MODULE_LICENSE("GPL"); diff -urNp linux-2.6.28.5/sound/soc/codecs/pcm3006.h linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.h --- linux-2.6.28.5/sound/soc/codecs/pcm3006.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.h 2009-01-28 20:10:07.000000000 +0100 @@ -0,0 +1,19 @@ +/* + * linux/sound/soc/codecs/pcm3006.h -- ALSA SoC Layer + * + * Author: Davide Rizzo + * Created: Mar 20 2008 + * Copyright: ELPA sas + * + * 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. + */ + +#ifndef __LINUX_SND_SOC_PCM3006_H +#define __LINUX_SND_SOC_PCM3006_H + +extern struct snd_soc_codec_device soc_codec_dev_pcm3006; +extern struct snd_soc_dai pcm3006_dai; + +#endif diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/Kconfig linux-2.6.28.5.elpa/sound/soc/s3c24xx/Kconfig --- linux-2.6.28.5/sound/soc/s3c24xx/Kconfig 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/Kconfig 2009-01-04 07:43:58.000000000 +0100 @@ -7,7 +7,26 @@ config SND_S3C24XX_SOC to select the audio interfaces to support below. config SND_S3C24XX_SOC_I2S - tristate + tristate "Soc Audio dor the Samsung S3C24XX chips through I2S interface" + depends on SND_S3C24XX_SOC + +config SND_S3C24XX_SOC_RD126_PCM3006 + tristate "SoC I2S Audio support for RD126 with PCM3006 codec" + depends on SND_S3C24XX_SOC_I2S && MACH_RD129 + select SND_SOC_PCM3006 + help + Say Y if you want to add support for SoC audio on RD126 boards. + RD126 is the starter kit for ELPA RD129 CPU board. + RD126 has a PCM3006 stereo codec connected on I2S port. + +config SND_S3C24XX_SOC_RD126_WM8731 + tristate "SoC I2S Audio support for RD126 with WM8731 codec" + depends on SND_S3C24XX_SOC_I2S && MACH_RD129 + select SND_SOC_WM8731 + help + Say Y if you want to add support for SoC audio on RD126 boards. + RD126 is the starter kit for ELPA RD129 CPU board. + WM8731 audio codec can be optionally mounted on RD126. config SND_S3C2412_SOC_I2S tristate diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/Makefile linux-2.6.28.5.elpa/sound/soc/s3c24xx/Makefile --- linux-2.6.28.5/sound/soc/s3c24xx/Makefile 2008-12-25 00:26:37.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/Makefile 2009-01-04 07:43:58.000000000 +0100 @@ -13,7 +13,11 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o +snd-soc-rd126-pcm3006-objs := rd126_pcm3006.o +snd-soc-rd126-wm8731-objs := rd126_wm8731.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o +obj-$(CONFIG_SND_S3C24XX_SOC_RD126_PCM3006) += snd-soc-rd126-pcm3006.o +obj-$(CONFIG_SND_S3C24XX_SOC_RD126_WM8731) += snd-soc-rd126-wm8731.o diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/rd126_pcm3006.c linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_pcm3006.c --- linux-2.6.28.5/sound/soc/s3c24xx/rd126_pcm3006.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_pcm3006.c 2009-02-05 12:15:12.000000000 +0100 @@ -0,0 +1,209 @@ +/* + * rd126_pcm3006 -- SoC audio for S3C2410-based RD129+RD126 board. + * + * Author: Davide Rizzo + * ELPA sas + * Created: Jul 26, 2007 + * + * 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 +#include +#include + +#include "../codecs/pcm3006.h" +#include "s3c24xx-pcm.h" +#include "s3c24xx-i2s.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO "rd129_snd: " x) +#else +#define DBG(x...) +#endif + +static int rd129_startup(struct snd_pcm_substream *substream) +{ + DBG("rd129_startup\n"); + + return 0; +} + +static void rd129_shutdown(struct snd_pcm_substream *substream) +{ + DBG("rd129_shutdown\n"); +} + +static int rd129_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret, t, div, div256, div384, err, best; + + unsigned long rate = params_rate(params); + unsigned long iis_clkrate = s3c24xx_i2s_get_clockrate(); + + DBG("rd129_hw_params\n"); + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* set MCLK division for sample rate */ +/* ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, 0, 0); + ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL, 0, 0); + if (ret < 0) + return ret;*/ + + div256 = iis_clkrate / rate / 256; + err = iis_clkrate / div256 / 256 - rate; + best = 256; + t = rate - iis_clkrate / (div256 + 1) / 256; + if (t < err) { + div256++; + err = t; + } + div384 = iis_clkrate / rate / 384; + t = iis_clkrate / div384 / 384 - rate; + if (t < err) { + err = t; + best = 384; + } + t = rate - iis_clkrate / (div384 + 1) / 384; + if (t < err) { + div384++; + best = 384; + } + if (best == 256) { + /* set BCLK division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, + S3C2410_IISMOD_256FS); + div = div256; + if (ret < 0) + return ret; + } else { + /* set BCLK division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, + S3C2410_IISMOD_384FS); + div = div384; + if (ret < 0) + return ret; + } + /* set prescaler division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, + S3C24XX_DIV_PRESCALER, S3C24XX_PRESCALE(div, div)); + if (ret < 0) + return ret; + + /* set MCLK division for sample rate */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, + S3C2410_IISMOD_32FS); + if (ret < 0) + return ret; + + return 0; +} + +/* It must start i2s peripheral BEFORE triggering DMA stuff */ +/* in this way i2s is retriggered by soc-sore.c after triggering DMA */ +/* but creates no problem */ +static int rd129_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai_link *machine = rtd->dai; + struct snd_soc_dai *cpu_dai = machine->cpu_dai; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +printk("RD129 TRIGGER\n"); + if (cpu_dai->ops.trigger) { + ret = cpu_dai->ops.trigger(substream, cmd); + if (ret < 0) + return ret; + } + break; + } + return 0; +} + +static struct snd_soc_ops rd129_ops = { + .startup = rd129_startup, + .hw_params = rd129_hw_params, + .shutdown = rd129_shutdown, + .trigger = rd129_trigger, +}; + +/* + * Logic for a pcm3006 connected on a S3C2410 + */ +static int pcm3006_init(struct snd_soc_codec *codec) +{ + + DBG("pcm3006_init() called\n"); + + return 0; +} + +static struct snd_soc_dai_link rd129_dai = { + .name = "PCM3006", + .stream_name = "PCM3006 PCM", + .cpu_dai = &s3c24xx_i2s_dai, + .codec_dai = &pcm3006_dai, + .init = pcm3006_init, + .ops = &rd129_ops, +}; + +static struct snd_soc_machine snd_soc_machine_rd129 = { + .name = "RD129-PCM3006", + .dai_link = &rd129_dai, + .num_links = 1, +}; + +static struct snd_soc_device rd129_snd_devdata = { + .machine = &snd_soc_machine_rd129, + .platform = &s3c24xx_soc_platform, + .codec_dev = &soc_codec_dev_pcm3006, +}; + +static struct platform_device *rd129_snd_device; + +static int __init rd129_snd_init(void) +{ + int ret; + DBG("Installing RD129 PCM3006 driver\n"); + rd129_snd_device = platform_device_alloc("soc-audio", -1); + if (!rd129_snd_device) + return -ENOMEM; + platform_set_drvdata(rd129_snd_device, &rd129_snd_devdata); + rd129_snd_devdata.dev = &rd129_snd_device->dev; + ret = platform_device_add(rd129_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rd129_snd_device); + } + return ret; +} + +static void __exit rd129_snd_exit(void) +{ + platform_device_unregister(rd129_snd_device); +} + +module_init(rd129_snd_init); +module_exit(rd129_snd_exit); + +/* Module information */ +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("ALSA SoC RD129 + PCM3006"); +MODULE_LICENSE("GPL"); + diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/rd126_wm8731.c linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_wm8731.c --- linux-2.6.28.5/sound/soc/s3c24xx/rd126_wm8731.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_wm8731.c 2009-02-14 17:32:59.000000000 +0100 @@ -0,0 +1,189 @@ +/* + * rd126_wm8731 -- SoC audio for S3C2410-based RD129+RD126 board. + * + * Author: Davide Rizzo + * ELPA sas + * Created: Apr 25, 2008 + * + * 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 +#include +#include +#include +#include +#include + +#include "../codecs/wm8731.h" +#include "s3c24xx-pcm.h" +#include "s3c24xx-i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO "rd129_snd: " x) +#else +#define DBG(x...) +#endif + +/* Clkout1 generates 12MHz and is connected to Xin, WM8731 is master */ +#define FCLOCK 12000000 + +static int rd129_startup(struct snd_pcm_substream *substream) +{ + DBG("rd129_startup\n"); + return 0; +} + +static void rd129_shutdown(struct snd_pcm_substream *substream) +{ + DBG("rd129_shutdown\n"); +} + +static int rd129_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret; + + DBG("rd129_hw_params\n"); + + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + return ret; + + /* set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, FCLOCK, + SND_SOC_CLOCK_OUT); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops rd129_ops = { + .startup = rd129_startup, + .hw_params = rd129_hw_params, + .shutdown = rd129_shutdown, +}; + +static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Audio Out", NULL), +}; + +static const struct snd_soc_dapm_route dapm_routes[] = { + {"Audio Out", NULL, "LHPOUT"}, + {"Audio Out", NULL, "RHPOUT"}, +}; + +/* + * Logic for a wm8731 connected on a S3C2410 + */ +static int rd129_wm8731_init(struct snd_soc_codec *codec) +{ + struct clk *upll, *dclk1, *clkout1; + + /* Program CLKOUT1 to generate 12MHz */ + upll = clk_get(NULL, "upll"); + dclk1 = clk_get(NULL, "dclk1"); + clkout1 = clk_get(NULL, "clkout1"); + clk_set_parent(dclk1, upll); + clk_set_rate(dclk1, FCLOCK); + clk_set_parent(clkout1, dclk1); + clk_put(dclk1); + clk_put(upll); + clk_enable(clkout1); + s3c2410_gpio_cfgpin(S3C2410_GPH10, S3C2410_GPH10_CLKOUT1); + + snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets, + ARRAY_SIZE(wm8731_dapm_widgets)); + + snd_soc_dapm_enable_pin(codec, "Audio Out"); + + snd_soc_dapm_add_routes(codec, dapm_routes, ARRAY_SIZE(dapm_routes)); + + snd_soc_dapm_sync(codec); + snd_soc_dapm_enable_pin(codec, "HiFi Playback"); + snd_soc_dapm_enable_pin(codec, "HiFi Playback Switch"); + +/* snd_soc_dapm_enable_pin(codec, "LHPOUT"); + snd_soc_dapm_enable_pin(codec, "RHPOUT"); + snd_soc_dapm_enable_pin(codec, "DAC"); + snd_soc_dapm_sync(codec);*/ + DBG("rd129_wm8731_init() called\n"); + + return 0; +} + +static struct snd_soc_dai_link rd129_dai = { + .name = "WM8731", + .stream_name = "WM8731 PCM", + .cpu_dai = &s3c24xx_i2s_dai, + .codec_dai = &wm8731_dai, + .init = rd129_wm8731_init, + .ops = &rd129_ops, +}; + +static struct snd_soc_machine snd_soc_machine_rd129 = { + .name = "RD129-WM8731", + .dai_link = &rd129_dai, + .num_links = 1, +}; + +static struct wm8731_setup_data rd129_wm8731_setup = { + .i2c_bus = 0, + .i2c_address = 0x1a, +}; + +static struct snd_soc_device rd129_snd_devdata = { + .machine = &snd_soc_machine_rd129, + .platform = &s3c24xx_soc_platform, + .codec_dev = &soc_codec_dev_wm8731, + .codec_data = &rd129_wm8731_setup, +}; + +static struct platform_device *rd129_snd_device; + +static int __init rd129_wm8731_snd_init(void) +{ + int ret; + DBG("Installing RD129 WM8731 driver\n"); + rd129_snd_device = platform_device_alloc("soc-audio", -1); + if (!rd129_snd_device) + return -ENOMEM; + platform_set_drvdata(rd129_snd_device, &rd129_snd_devdata); + rd129_snd_devdata.dev = &rd129_snd_device->dev; + ret = platform_device_add(rd129_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rd129_snd_device); + } + return ret; +} + +static void __exit rd129_wm8731_snd_exit(void) +{ + platform_device_unregister(rd129_snd_device); +} + +module_init(rd129_wm8731_snd_init); +module_exit(rd129_wm8731_snd_exit); + +/* Module information */ +MODULE_AUTHOR("Davide Rizzo "); +MODULE_DESCRIPTION("ALSA SoC RD129 + WM8731"); +MODULE_LICENSE("GPL"); +