Commit d61bd77f authored by Kukjin Kim's avatar Kukjin Kim

Merge branch 'next-samsung' into for-next

Conflicts:
	arch/arm/mach-s5p6440/Kconfig
	arch/arm/mach-s5p6442/Kconfig
	arch/arm/mach-s5pc100/Kconfig
	arch/arm/mach-s5pv210/Kconfig
	arch/arm/mach-s5pv210/cpu.c
	arch/arm/plat-samsung/include/plat/sdhci.h
parents f2b7e3c5 1c739c7f
......@@ -634,6 +634,7 @@ config ARCH_S3C2410
select ARCH_HAS_CPUFREQ
select HAVE_CLK
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
......@@ -663,6 +664,8 @@ config ARCH_S3C64XX
select S3C_DEV_NAND
select USB_ARCH_HAS_OHCI
select SAMSUNG_GPIOLIB_4BIT
select HAVE_S3C2410_I2C
select HAVE_S3C2410_WATCHDOG
help
Samsung S3C64XX series based systems
......@@ -671,7 +674,10 @@ config ARCH_S5P6440
select CPU_V6
select GENERIC_GPIO
select HAVE_CLK
select HAVE_S3C2410_WATCHDOG
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C
select HAVE_S3C_RTC
help
Samsung S5P6440 CPU based systems
......@@ -681,6 +687,7 @@ config ARCH_S5P6442
select GENERIC_GPIO
select HAVE_CLK
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_WATCHDOG
help
Samsung S5P6442 CPU based systems
......@@ -691,6 +698,9 @@ config ARCH_S5PC100
select CPU_V7
select ARM_L1_CACHE_SHIFT_6
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C
select HAVE_S3C_RTC
select HAVE_S3C2410_WATCHDOG
help
Samsung S5PC100 series based systems
......@@ -701,6 +711,9 @@ config ARCH_S5PV210
select HAVE_CLK
select ARM_L1_CACHE_SHIFT_6
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C
select HAVE_S3C_RTC
select HAVE_S3C2410_WATCHDOG
help
Samsung S5PV210/S5PC110 series based systems
......
......@@ -57,11 +57,21 @@ config S3C64XX_SETUP_I2C1
help
Common setup code for i2c bus 1.
config S3C64XX_SETUP_IDE
bool
help
Common setup code for S3C64XX IDE.
config S3C64XX_SETUP_FB_24BPP
bool
help
Common setup code for S3C64XX with an 24bpp RGB display helper.
config S3C64XX_SETUP_KEYPAD
bool
help
Common setup code for S3C64XX KEYPAD GPIO configurations
config S3C64XX_SETUP_SDHCI_GPIO
bool
help
......@@ -95,15 +105,20 @@ config MACH_SMDK6410
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_I2C1
select SAMSUNG_DEV_IDE
select S3C_DEV_FB
select S3C_DEV_RTC
select SAMSUNG_DEV_TS
select S3C_DEV_USB_HOST
select S3C_DEV_USB_HSOTG
select S3C_DEV_WDT
select SAMSUNG_DEV_KEYPAD
select HAVE_S3C2410_WATCHDOG
select S3C64XX_SETUP_SDHCI
select S3C64XX_SETUP_I2C1
select S3C64XX_SETUP_IDE
select S3C64XX_SETUP_FB_24BPP
select S3C64XX_SETUP_KEYPAD
help
Machine support for the Samsung SMDK6410
......
......@@ -35,6 +35,8 @@ obj-$(CONFIG_S3C64XX_DMA) += dma.o
obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S3C64XX_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
......
......@@ -132,6 +132,12 @@ static struct clk init_clocks_disable[] = {
.name = "nand",
.id = -1,
.parent = &clk_h,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_RTC,
}, {
.name = "adc",
.id = -1,
......@@ -165,6 +171,12 @@ static struct clk init_clocks_disable[] = {
.ctrlbit = S3C6410_CLKCON_PCLK_IIS2,
}, {
#endif
.name = "keypad",
.id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_KEYPAD,
}, {
.name = "spi",
.id = 0,
.parent = &clk_p,
......@@ -294,12 +306,6 @@ static struct clk init_clocks[] = {
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_UART3,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_RTC,
}, {
.name = "watchdog",
.id = -1,
......@@ -310,6 +316,12 @@ static struct clk init_clocks[] = {
.id = -1,
.parent = &clk_p,
.ctrlbit = S3C_CLKCON_PCLK_AC97,
}, {
.name = "cfcon",
.id = -1,
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_IHOST,
}
};
......
......@@ -12,11 +12,11 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/gpio.h>
#include <plat/devs.h>
#include <plat/audio.h>
......
......@@ -12,10 +12,10 @@
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/gpio-bank-c.h>
#include <mach/spi-clocks.h>
......
......@@ -15,9 +15,9 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
......
......@@ -67,6 +67,7 @@
#define S3C64XX_PA_USB_HSOTG (0x7C000000)
#define S3C64XX_PA_WATCHDOG (0x7E004000)
#define S3C64XX_PA_RTC (0x7E005000)
#define S3C64XX_PA_KEYPAD (0x7E00A000)
#define S3C64XX_PA_ADC (0x7E00B000)
#define S3C64XX_PA_SYSCON (0x7E00F000)
#define S3C64XX_PA_AC97 (0x7F001000)
......@@ -86,6 +87,9 @@
#define S3C64XX_SZ_GPIO SZ_4K
#define S3C64XX_PA_SDRAM (0x50000000)
#define S3C64XX_PA_CFCON (0x70300000)
#define S3C64XX_PA_VIC0 (0x71200000)
#define S3C64XX_PA_VIC1 (0x71300000)
......@@ -120,5 +124,7 @@
#define S3C_PA_WDT S3C64XX_PA_WATCHDOG
#define SAMSUNG_PA_ADC S3C64XX_PA_ADC
#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
#define SAMSUNG_PA_KEYPAD S3C64XX_PA_KEYPAD
#endif /* __ASM_ARCH_6400_MAP_H */
......@@ -34,6 +34,7 @@
#define S3C_SCLK_GATE S3C_CLKREG(0x38)
#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
#define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
/* CLKDIV0 */
#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
......@@ -154,4 +155,8 @@
#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
#define S3C6400_CLKSRC_MFC (1 << 4)
/* MEM_SYS_CFG */
#define MEM_SYS_CFG_INDEP_CF 0x4000
#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
#endif /* _PLAT_REGS_CLOCK_H */
......@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
......@@ -56,6 +57,7 @@
#include <mach/regs-gpio.h>
#include <mach/regs-sys.h>
#include <mach/regs-srom.h>
#include <plat/ata.h>
#include <plat/iic.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
......@@ -66,6 +68,7 @@
#include <plat/cpu.h>
#include <plat/adc.h>
#include <plat/ts.h>
#include <plat/keypad.h>
#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
......@@ -242,6 +245,29 @@ static struct platform_device smdk6410_b_pwr_5v = {
};
#endif
static struct s3c_ide_platdata smdk6410_ide_pdata __initdata = {
.setup_gpio = s3c64xx_ide_setup_gpio,
};
static uint32_t smdk6410_keymap[] __initdata = {
/* KEY(row, col, keycode) */
KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
};
static struct matrix_keymap_data smdk6410_keymap_data __initdata = {
.keymap = smdk6410_keymap,
.keymap_size = ARRAY_SIZE(smdk6410_keymap),
};
static struct samsung_keypad_platdata smdk6410_keypad_data __initdata = {
.keymap_data = &smdk6410_keymap_data,
.rows = 2,
.cols = 8,
};
static struct map_desc smdk6410_iodesc[] = {};
static struct platform_device *smdk6410_devices[] __initdata = {
......@@ -257,6 +283,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_ohci,
&s3c_device_usb_hsotg,
&s3c64xx_device_iisv4,
&samsung_device_keypad,
#ifdef CONFIG_REGULATOR
&smdk6410_b_pwr_5v,
......@@ -265,6 +292,8 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&smdk6410_smsc911x,
&s3c_device_adc,
&s3c_device_cfcon,
&s3c_device_rtc,
&s3c_device_ts,
&s3c_device_wdt,
};
......@@ -636,6 +665,8 @@ static void __init smdk6410_machine_init(void)
s3c_i2c1_set_platdata(NULL);
s3c_fb_set_platdata(&smdk6410_lcd_pdata);
samsung_keypad_set_platdata(&smdk6410_keypad_data);
s3c24xx_ts_set_platdata(&s3c_ts_platform);
/* configure nCS1 width to 16 bits */
......@@ -665,6 +696,8 @@ static void __init smdk6410_machine_init(void)
i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
s3c_ide_set_platdata(&smdk6410_ide_pdata);
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
}
......
......@@ -37,8 +37,9 @@
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/ata-core.h>
#include <plat/adc-core.h>
#include <plat/iic-core.h>
#include <plat/adc.h>
#include <plat/onenand-core.h>
#include <mach/s3c6400.h>
#include <mach/s3c6410.h>
......@@ -54,10 +55,11 @@ void __init s3c6410_map_io(void)
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_device_adc.name = "s3c64xx-adc";
s3c_adc_setname("s3c64xx-adc");
s3c_device_nand.name = "s3c6400-nand";
s3c_onenand_setname("s3c6410-onenand");
s3c64xx_onenand1_setname("s3c6410-onenand");
s3c_cfcon_setname("s3c64xx-pata");
}
void __init s3c6410_init_clocks(int xtal)
......
......@@ -15,9 +15,9 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <mach/regs-fb.h>
#include <mach/gpio.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
......
......@@ -14,10 +14,10 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/gpio.h>
#include <mach/gpio-bank-b.h>
#include <plat/iic.h>
#include <plat/gpio-cfg.h>
......
......@@ -14,10 +14,10 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/gpio.h>
#include <mach/gpio-bank-b.h>
#include <plat/iic.h>
#include <plat/gpio-cfg.h>
......
/* linux/arch/arm/mach-s3c64xx/setup-ide.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S3C64XX setup information for IDE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <plat/gpio-cfg.h>
void s3c64xx_ide_setup_gpio(void)
{
u32 reg;
u32 gpio = 0;
reg = readl(S3C_MEM_SYS_CFG) & (~0x3f);
/* Independent CF interface, CF chip select configuration */
writel(reg | MEM_SYS_CFG_INDEP_CF |
MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S3C_MEM_SYS_CFG);
s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));
/* Set XhiDATA[15:0] pins as CF Data[15:0] */
for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++)
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5));
/* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++)
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
/* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++)
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
}
/* linux/arch/arm/mach-s3c64xx/setup-keypad.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* GPIO configuration for S3C64XX KeyPad device
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
{
unsigned int gpio;
unsigned int end;
/* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */
end = S3C64XX_GPK(8 + rows);
for (gpio = S3C64XX_GPK(8); gpio < end; gpio++) {
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
/* Set all the necessary GPL pins to special-function 3: KP_COL[x] */
end = S3C64XX_GPL(0 + cols);
for (gpio = S3C64XX_GPL(0); gpio < end; gpio++) {
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
}
......@@ -16,12 +16,14 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/sdhci.h>
void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
unsigned int end;
......@@ -33,12 +35,15 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
}
}
void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
unsigned int end;
......@@ -50,8 +55,10 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
}
}
void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
......
......@@ -21,13 +21,11 @@ config S5P6440_SETUP_I2C1
config MACH_SMDK6440
bool "SMDK6440"
select CPU_S5P6440
select SAMSUNG_DEV_TS
select SAMSUNG_DEV_ADC
select S3C_DEV_RTC
select S3C_DEV_I2C1
select S3C_DEV_RTC
select S3C_DEV_WDT
select HAVE_S3C_RTC
select HAVE_S3C2410_WATCHDOG
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_TS
select S5P6440_SETUP_I2C1
help
Machine support for the Samsung SMDK6440
......
......@@ -37,6 +37,7 @@
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/s5p6440.h>
#include <plat/adc-core.h>
static void s5p6440_idle(void)
{
......@@ -61,7 +62,7 @@ static void s5p6440_idle(void)
void __init s5p6440_map_io(void)
{
/* initialize any device information early */
s3c_device_adc.name = "s3c64xx-adc";
s3c_adc_setname("s3c64xx-adc");
}
void __init s5p6440_init_clocks(int xtal)
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/spi-clocks.h>
#include <plat/s3c64xx-spi.h>
......
......@@ -13,9 +13,11 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
......
......@@ -20,7 +20,6 @@ config MACH_SMDK6442
bool "SMDK6442"
select CPU_S5P6442
select S3C_DEV_WDT
select HAVE_S3C2410_WATCHDOG
help
Machine support for Samsung SMDK6442
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/spi-clocks.h>
#include <plat/s3c64xx-spi.h>
......
......@@ -49,24 +49,22 @@ config S5PC100_SETUP_SDHCI_GPIO
config MACH_SMDKC100
bool "SMDKC100"
select CPU_S5PC100
select SAMSUNG_DEV_ADC
select S3C_DEV_FB
select S3C_DEV_I2C1
select SAMSUNG_DEV_IDE
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select SAMSUNG_DEV_KEYPAD
select S3C_DEV_I2C1
select S3C_DEV_RTC
select SAMSUNG_DEV_TS
select S3C_DEV_WDT
select HAVE_S3C2410_WATCHDOG
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_IDE
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_TS
select S5PC100_SETUP_FB_24BPP
select S5PC100_SETUP_I2C1
select S5PC100_SETUP_IDE
select S5PC100_SETUP_KEYPAD
select S5PC100_SETUP_SDHCI
select HAVE_S3C_RTC
help
Machine support for the Samsung SMDKC100
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
......
......@@ -10,10 +10,10 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/spi-clocks.h>
#include <plat/s3c64xx-spi.h>
......
......@@ -99,6 +99,10 @@
#define S5PC100_PA_FB (0xEE000000)
#define S5PC100_PA_FIMC0 (0xEE200000)
#define S5PC100_PA_FIMC1 (0xEE300000)
#define S5PC100_PA_FIMC2 (0xEE400000)
#define S5PC100_PA_I2S0 (0xF2000000)
#define S5PC100_PA_I2S1 (0xF2100000)
#define S5PC100_PA_I2S2 (0xF2200000)
......@@ -148,4 +152,8 @@
#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON
#define SAMSUNG_PA_KEYPAD S5PC100_PA_KEYPAD
#define S5P_PA_FIMC0 S5PC100_PA_FIMC0
#define S5P_PA_FIMC1 S5PC100_PA_FIMC1
#define S5P_PA_FIMC2 S5PC100_PA_FIMC2
#endif /* __ASM_ARCH_C100_MAP_H */
......@@ -20,9 +20,11 @@
#include <plat/gpio-cfg.h>
#include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
unsigned int end;
unsigned int num;
......@@ -47,12 +49,15 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
}
}
s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
}
}
void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
unsigned int end;
......@@ -64,12 +69,15 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
}
}
void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
unsigned int end;
......@@ -81,6 +89,8 @@ void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
}
}
......@@ -53,19 +53,24 @@ config S5PV210_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
config S5PC110_DEV_ONENAND
bool
help
Compile in platform device definition for OneNAND1 controller
menu "S5PC110 Machines"
config MACH_AQUILA
bool "Aquila"
select CPU_S5PV210
select ARCH_SPARSEMEM_ENABLE
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
select S3C_DEV_FB
select S5PC110_DEV_ONENAND
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S5PC110_DEV_ONENAND
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
help
Machine support for the Samsung Aquila target based on S5PC110 SoC
......@@ -73,13 +78,13 @@ config MACH_GONI
bool "GONI"
select CPU_S5PV210
select ARCH_SPARSEMEM_ENABLE
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
select S3C_DEV_FB
select S5PC110_DEV_ONENAND
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S5PC110_DEV_ONENAND
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
help
Machine support for Samsung GONI board
S5PC110(MCP) is one of package option of S5PV210
......@@ -90,11 +95,9 @@ config MACH_SMDKC110
select ARCH_SPARSEMEM_ENABLE
select S3C_DEV_I2C1
select S3C_DEV_I2C2
select SAMSUNG_DEV_IDE
select S3C_DEV_RTC
select S3C_DEV_WDT
select HAVE_S3C_RTC
select HAVE_S3C2410_WATCHDOG
select SAMSUNG_DEV_IDE
select S5PV210_SETUP_I2C1
select S5PV210_SETUP_I2C2
select S5PV210_SETUP_IDE
......@@ -104,31 +107,24 @@ config MACH_SMDKC110
endmenu
config S5PC110_DEV_ONENAND
bool
help
Compile in platform device definition for OneNAND1 controller
menu "S5PV210 Machines"
config MACH_SMDKV210
bool "SMDKV210"
select CPU_S5PV210
select ARCH_SPARSEMEM_ENABLE
select SAMSUNG_DEV_ADC
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select S3C_DEV_I2C1
select S3C_DEV_I2C2
select S3C_DEV_RTC
select S3C_DEV_WDT
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_IDE
select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_TS
select S3C_DEV_RTC
select S3C_DEV_WDT
select HAVE_S3C_RTC
select HAVE_S3C2410_WATCHDOG
select S5PV210_SETUP_I2C1
select S5PV210_SETUP_I2C2
select S5PV210_SETUP_IDE
......
......@@ -32,7 +32,9 @@
#include <plat/devs.h>
#include <plat/clock.h>
#include <plat/s5pv210.h>
#include <plat/adc-core.h>
#include <plat/ata-core.h>
#include <plat/fimc-core.h>
#include <plat/iic-core.h>
#include <plat/keypad-core.h>
#include <plat/sdhci.h>
......@@ -84,9 +86,6 @@ static void s5pv210_sw_reset(void)
void __init s5pv210_map_io(void)
{
#ifdef CONFIG_S3C_DEV_ADC
s3c_device_adc.name = "s3c64xx-adc";
#endif
iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
/* initialise device information early */
......@@ -95,8 +94,14 @@ void __init s5pv210_map_io(void)
s5pv210_default_sdhci2();
s5pv210_default_sdhci3();
s3c_adc_setname("s3c64xx-adc");
s3c_cfcon_setname("s5pv210-pata");
s3c_fimc_setname(0, "s5pv210-fimc");
s3c_fimc_setname(1, "s5pv210-fimc");
s3c_fimc_setname(2, "s5pv210-fimc");
/* the i2c devices are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/audio.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <mach/dma.h>
#include <mach/irqs.h>
......
......@@ -10,11 +10,11 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/spi-clocks.h>
#include <plat/s3c64xx-spi.h>
......
......@@ -65,6 +65,10 @@
#define S5PV210_PA_FB (0xF8000000)
#define S5PV210_PA_FIMC0 (0xFB200000)
#define S5PV210_PA_FIMC1 (0xFB300000)
#define S5PV210_PA_FIMC2 (0xFB400000)
#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
#define S5PV210_PA_VIC0 (0xF2000000)
......@@ -109,6 +113,9 @@
#define S3C_PA_FB S5PV210_PA_FB
#define S3C_PA_RTC S5PV210_PA_RTC
#define S3C_PA_WDT S5PV210_PA_WATCHDOG
#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
#define SAMSUNG_PA_ADC S5PV210_PA_ADC
#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON
......
......@@ -13,9 +13,9 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <mach/regs-fb.h>
#include <mach/gpio.h>
#include <mach/map.h>
#include <plat/fb.h>
#include <mach/regs-clock.h>
......
......@@ -14,10 +14,10 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/gpio.h>
#include <plat/iic.h>
#include <plat/gpio-cfg.h>
......
......@@ -14,10 +14,10 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/gpio.h>
#include <plat/iic.h>
#include <plat/gpio-cfg.h>
......
......@@ -14,10 +14,10 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
#include <mach/gpio.h>
#include <plat/iic.h>
#include <plat/gpio-cfg.h>
......
......@@ -15,15 +15,17 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
/* Set all the necessary GPG0/GPG1 pins to special-function 2 */
......@@ -48,12 +50,15 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
break;
}
s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
}
}
void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
/* Set all the necessary GPG1[0:1] pins to special-function 2 */
......@@ -68,12 +73,15 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
}
s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
}
}
void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{
struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
unsigned int gpio;
/* Set all the necessary GPG2[0:1] pins to special-function 2 */
......@@ -99,8 +107,10 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
break;
}
s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
}
}
void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
......
......@@ -19,3 +19,8 @@ obj-y += clock.o
obj-y += irq.o
obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
# devices
obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
/* linux/arch/arm/plat-s5p/dev-fimc0.c
*
* Copyright (c) 2010 Samsung Electronics
*
* Base S5P FIMC0 resource and device definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <mach/map.h>
static struct resource s5p_fimc0_resource[] = {
[0] = {
.start = S5P_PA_FIMC0,
.end = S5P_PA_FIMC0 + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC0,
.end = IRQ_FIMC0,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s5p_device_fimc0 = {
.name = "s5p-fimc",
.id = 0,
.num_resources = ARRAY_SIZE(s5p_fimc0_resource),
.resource = s5p_fimc0_resource,
};
/* linux/arch/arm/plat-s5p/dev-fimc1.c
*
* Copyright (c) 2010 Samsung Electronics
*
* Base S5P FIMC1 resource and device definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <mach/map.h>
static struct resource s5p_fimc1_resource[] = {
[0] = {
.start = S5P_PA_FIMC1,
.end = S5P_PA_FIMC1 + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC1,
.end = IRQ_FIMC1,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s5p_device_fimc1 = {
.name = "s5p-fimc",
.id = 1,
.num_resources = ARRAY_SIZE(s5p_fimc1_resource),
.resource = s5p_fimc1_resource,
};
/* linux/arch/arm/plat-s5p/dev-fimc2.c
*
* Copyright (c) 2010 Samsung Electronics
*
* Base S5P FIMC2 resource and device definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <mach/map.h>
static struct resource s5p_fimc2_resource[] = {
[0] = {
.start = S5P_PA_FIMC2,
.end = S5P_PA_FIMC2 + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC2,
.end = IRQ_FIMC2,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s5p_device_fimc2 = {
.name = "s5p-fimc",
.id = 2,
.num_resources = ARRAY_SIZE(s5p_fimc2_resource),
.resource = s5p_fimc2_resource,
};
......@@ -160,6 +160,11 @@ config S3C_DEV_HSMMC2
help
Compile in platform device definitions for HSMMC channel 2
config S3C_DEV_HSMMC3
bool
help
Compile in platform device definitions for HSMMC channel 3
config S3C_DEV_HWMON
bool
help
......@@ -216,6 +221,11 @@ config SAMSUNG_DEV_ADC
help
Compile in platform device definition for ADC controller
config SAMSUNG_DEV_IDE
bool
help
Compile in platform device definitions for IDE
config S3C64XX_DEV_SPI
bool
help
......@@ -227,6 +237,11 @@ config SAMSUNG_DEV_TS
help
Common in platform device definitions for touchscreen device
config SAMSUNG_DEV_KEYPAD
bool
help
Compile in platform device definitions for keypad
# DMA
config S3C_DMA
......
......@@ -30,9 +30,12 @@ obj-$(CONFIG_S3C_ADC) += adc.o
# devices
obj-y += platformdata.o
obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o
obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o
obj-$(CONFIG_S3C_DEV_HSMMC2) += dev-hsmmc2.o
obj-$(CONFIG_S3C_DEV_HSMMC3) += dev-hsmmc3.o
obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o
obj-y += dev-i2c0.o
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
......@@ -47,7 +50,9 @@ obj-$(CONFIG_S3C_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o
obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o
obj-$(CONFIG_SAMSUNG_DEV_IDE) += dev-ide.o
obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
obj-$(CONFIG_SAMSUNG_DEV_KEYPAD) += dev-keypad.o
# DMA support
......
......@@ -60,6 +60,11 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
set->max_width = pd->max_width;
set->cd_type = pd->cd_type;
set->ext_cd_init = pd->ext_cd_init;
set->ext_cd_cleanup = pd->ext_cd_cleanup;
set->ext_cd_gpio = pd->ext_cd_gpio;
set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio;
......
......@@ -60,6 +60,11 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
set->max_width = pd->max_width;
set->cd_type = pd->cd_type;
set->ext_cd_init = pd->ext_cd_init;
set->ext_cd_cleanup = pd->ext_cd_cleanup;
set->ext_cd_gpio = pd->ext_cd_gpio;
set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio;
......
......@@ -61,6 +61,11 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
set->max_width = pd->max_width;
set->cd_type = pd->cd_type;
set->ext_cd_init = pd->ext_cd_init;
set->ext_cd_cleanup = pd->ext_cd_cleanup;
set->ext_cd_gpio = pd->ext_cd_gpio;
set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio;
......
/* linux/arch/arm/plat-samsung/dev-hsmmc3.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright (c) 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* Based on arch/arm/plat-samsung/dev-hsmmc1.c
*
* Samsung device definition for hsmmc device 3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/mmc/host.h>
#include <mach/map.h>
#include <plat/sdhci.h>
#include <plat/devs.h>
#define S3C_SZ_HSMMC (0x1000)
static struct resource s3c_hsmmc3_resource[] = {
[0] = {
.start = S3C_PA_HSMMC3,
.end = S3C_PA_HSMMC3 + S3C_SZ_HSMMC - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_MMC3,
.end = IRQ_MMC3,
.flags = IORESOURCE_IRQ,
}
};
static u64 s3c_device_hsmmc3_dmamask = 0xffffffffUL;
struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
.max_width = 4,
.host_caps = (MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
};
struct platform_device s3c_device_hsmmc3 = {
.name = "s3c-sdhci",
.id = 3,
.num_resources = ARRAY_SIZE(s3c_hsmmc3_resource),
.resource = s3c_hsmmc3_resource,
.dev = {
.dma_mask = &s3c_device_hsmmc3_dmamask,
.coherent_dma_mask = 0xffffffffUL,
.platform_data = &s3c_hsmmc3_def_platdata,
},
};
void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
{
struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
set->max_width = pd->max_width;
set->cd_type = pd->cd_type;
set->ext_cd_init = pd->ext_cd_init;
set->ext_cd_cleanup = pd->ext_cd_cleanup;
set->ext_cd_gpio = pd->ext_cd_gpio;
set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
if (pd->cfg_gpio)
set->cfg_gpio = pd->cfg_gpio;
if (pd->cfg_card)
set->cfg_card = pd->cfg_card;
}
/* linux/arch/arm/plat-samsung/dev-ide.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA device definition.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <mach/map.h>
#include <plat/ata.h>
#include <plat/devs.h>
static struct resource s3c_cfcon_resource[] = {
[0] = {
.start = SAMSUNG_PA_CFCON,
.end = SAMSUNG_PA_CFCON + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_CFCON,
.end = IRQ_CFCON,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s3c_device_cfcon = {
.id = 0,
.num_resources = ARRAY_SIZE(s3c_cfcon_resource),
.resource = s3c_cfcon_resource,
};
void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
{
s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
&s3c_device_cfcon);
}
/*
* linux/arch/arm/plat-samsung/dev-keypad.c
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/platform_device.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/keypad.h>
static struct resource samsung_keypad_resources[] = {
[0] = {
.start = SAMSUNG_PA_KEYPAD,
.end = SAMSUNG_PA_KEYPAD + 0x20 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_KEYPAD,
.end = IRQ_KEYPAD,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device samsung_device_keypad = {
.name = "samsung-keypad",
.id = -1,
.num_resources = ARRAY_SIZE(samsung_keypad_resources),
.resource = samsung_keypad_resources,
};
void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
{
struct samsung_keypad_platdata *npd;
npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
&samsung_device_keypad);
if (!npd->cfg_gpio)
npd->cfg_gpio = samsung_keypad_cfg_gpio;
}
......@@ -21,7 +21,7 @@
static struct resource s3c_wdt_resource[] = {
[0] = {
.start = S3C_PA_WDT,
.end = S3C_PA_WDT + SZ_1M - 1,
.end = S3C_PA_WDT + SZ_1K,
.flags = IORESOURCE_MEM,
},
[1] = {
......
......@@ -18,7 +18,7 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach/gpio.h>
#include <linux/gpio.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
......
/* linux/arch/arm/plat-samsung/include/plat/adc-core.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* Samsung ADC Controller core functions
*
* 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 __ASM_PLAT_ADC_CORE_H
#define __ASM_PLAT_ADC_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_adc_setname(char *name)
{
#ifdef CONFIG_SAMSUNG_DEV_ADC
s3c_device_adc.name = name;
#endif
}
#endif /* __ASM_PLAT_ADC_CORE_H */
/* linux/arch/arm/plat-samsung/include/plat/ata-core.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA Controller core functions
*
* 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 __ASM_PLAT_ATA_CORE_H
#define __ASM_PLAT_ATA_CORE_H __FILE__
/* These functions are only for use with the core support code, such as
* the cpu specific initialisation code
*/
/* re-define device name depending on support. */
static inline void s3c_cfcon_setname(char *name)
{
#ifdef CONFIG_SAMSUNG_DEV_IDE
s3c_device_cfcon.name = name;
#endif
}
#endif /* __ASM_PLAT_ATA_CORE_H */
/* linux/arch/arm/plat-samsung/include/plat/ata.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA platform_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.
*/
#ifndef __ASM_PLAT_ATA_H
#define __ASM_PLAT_ATA_H __FILE__
/**
* struct s3c_ide_platdata - S3C IDE driver platform data.
* @setup_gpio: Setup the external GPIO pins to the right state for data
* transfer in true-ide mode.
*/
struct s3c_ide_platdata {
void (*setup_gpio)(void);
};
/*
* s3c_ide_set_platdata() - Setup the platform specifc data for IDE driver.
* @pdata: Platform data for IDE driver.
*/
extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata);
/* architecture-specific IDE configuration */
extern void s3c64xx_ide_setup_gpio(void);
extern void s5pc100_ide_setup_gpio(void);
extern void s5pv210_ide_setup_gpio(void);
#endif /*__ASM_PLAT_ATA_H */
......@@ -54,6 +54,8 @@ extern struct platform_device s3c_device_hwmon;
extern struct platform_device s3c_device_hsmmc0;
extern struct platform_device s3c_device_hsmmc1;
extern struct platform_device s3c_device_hsmmc2;
extern struct platform_device s3c_device_hsmmc3;
extern struct platform_device s3c_device_cfcon;
extern struct platform_device s3c_device_spi0;
extern struct platform_device s3c_device_spi1;
......@@ -100,6 +102,12 @@ extern struct platform_device s5pc100_device_iis0;
extern struct platform_device s5pc100_device_iis1;
extern struct platform_device s5pc100_device_iis2;
extern struct platform_device samsung_device_keypad;
extern struct platform_device s5p_device_fimc0;
extern struct platform_device s5p_device_fimc1;
extern struct platform_device s5p_device_fimc2;
/* s3c2440 specific devices */
#ifdef CONFIG_CPU_S3C2440
......@@ -108,3 +116,15 @@ extern struct platform_device s3c_device_camif;
extern struct platform_device s3c_device_ac97;
#endif
/**
* s3c_set_platdata() - helper for setting platform data
* @pd: The default platform data for this device.
* @pdsize: The size of the platform data.
* @pdev: Pointer to the device to fill in.
*
* This helper replaces a number of calls that copy and then set the
* platform data of the device.
*/
extern void *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev);
/*
* arch/arm/plat-samsung/include/plat/fimc-core.h
*
* Copyright 2010 Samsung Electronics Co., Ltd.
* Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* Samsung camera interface driver core functions
*
* 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 __ASM_PLAT_FIMC_CORE_H
#define __ASM_PLAT_FIMC_CORE_H __FILE__
/*
* These functions are only for use with the core support code, such as
* the CPU-specific initialization code.
*/
/* Re-define device name to differentiate the subsystem in various SoCs. */
static inline void s3c_fimc_setname(int id, char *name)
{
switch (id) {
#ifdef CONFIG_S5P_DEV_FIMC0
case 0:
s5p_device_fimc0.name = name;
break;
#endif
#ifdef CONFIG_S5P_DEV_FIMC1
case 1:
s5p_device_fimc1.name = name;
break;
#endif
#ifdef CONFIG_S5P_DEV_FIMC2
case 2:
s5p_device_fimc2.name = name;
break;
#endif
}
}
#endif /* __ASM_PLAT_FIMC_CORE_H */
/*
* Samsung Platform - Keypad platform data definitions
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __PLAT_SAMSUNG_KEYPAD_H
#define __PLAT_SAMSUNG_KEYPAD_H
#include <linux/input/matrix_keypad.h>
#define SAMSUNG_MAX_ROWS 8
#define SAMSUNG_MAX_COLS 8
/**
* struct samsung_keypad_platdata - Platform device data for Samsung Keypad.
* @keymap_data: pointer to &matrix_keymap_data.
* @rows: number of keypad row supported.
* @cols: number of keypad col supported.
* @no_autorepeat: disable key autorepeat.
* @wakeup: controls whether the device should be set up as wakeup source.
* @cfg_gpio: configure the GPIO.
*
* Initialisation data specific to either the machine or the platform
* for the device driver to use or call-back when configuring gpio.
*/
struct samsung_keypad_platdata {
const struct matrix_keymap_data *keymap_data;
unsigned int rows;
unsigned int cols;
bool no_autorepeat;
bool wakeup;
void (*cfg_gpio)(unsigned int rows, unsigned int cols);
};
/**
* samsung_keypad_set_platdata - Set platform data for Samsung Keypad device.
* @pd: Platform data to register to device.
*
* Register the given platform data for use with Samsung Keypad device.
* The call will copy the platform data, so the board definitions can
* make the structure itself __initdata.
*/
extern void samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd);
/* defined by architecture to configure gpio. */
extern void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols);
#endif /* __PLAT_SAMSUNG_KEYPAD_H */
/* linux/arch/arm/plat-samsung/include/plat/regs-ata.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA register definitions
*
* 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 __ASM_PLAT_REGS_ATA_H
#define __ASM_PLAT_REGS_ATA_H __FILE__
#define S3C_CFATA_REG(x) (x)
#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
#define S3C_CFATA_MUX_TRUEIDE 0x01
#define S3C_ATA_CFG_SWAP 0x40
#define S3C_ATA_CFG_IORDYEN 0x02
#endif /* __ASM_PLAT_REGS_ATA_H */
......@@ -14,6 +14,9 @@
#define __ASM_ARCH_REGS_RTC_H __FILE__
#define S3C2410_RTCREG(x) (x)
#define S3C2410_INTP S3C2410_RTCREG(0x30)
#define S3C2410_INTP_ALM (1 << 1)
#define S3C2410_INTP_TIC (1 << 0)
#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
#define S3C2410_RTCCON_RTCEN (1<<0)
......
This diff is collapsed.
/* linux/arch/arm/plat-samsung/platformdata.c
*
* Copyright 2010 Ben Dooks <ben-linux <at> fluff.org>
*
* Helper for platform data setting
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <plat/devs.h>
void __init *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev)
{
void *npd;
if (!pd) {
/* too early to use dev_name(), may not be registered */
printk(KERN_ERR "%s: no platform data supplied\n", pdev->name);
return NULL;
}
npd = kmemdup(pd, pdsize, GFP_KERNEL);
if (!npd) {
printk(KERN_ERR "%s: cannot clone platform data\n", pdev->name);
return NULL;
}
pdev->dev.platform_data = npd;
return npd;
}
......@@ -1315,10 +1315,14 @@ static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
if (test_bit(EV_SND, dev->evbit))
return true;
if (test_bit(EV_KEY, dev->evbit))
if (test_bit(EV_KEY, dev->evbit)) {
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
return true;
for (i = KEY_BRL_DOT1; i <= KEY_BRL_DOT10; i++)
if (test_bit(i, dev->keybit))
return true;
}
return false;
}
......
......@@ -1586,6 +1586,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
......
......@@ -198,6 +198,7 @@
#define USB_VENDOR_ID_ETT 0x0664
#define USB_DEVICE_ID_TC5UH 0x0309
#define USB_DEVICE_ID_TC4UM 0x0306
#define USB_VENDOR_ID_EZKEY 0x0518
#define USB_DEVICE_ID_BTC_8193 0x0002
......
......@@ -534,6 +534,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
else input_set_abs_params(input, usage->code, a, b, 0, 0);
/* use a larger default input buffer for MT devices */
if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0)
input_set_events_per_packet(input, 60);
}
if (usage->type == EV_ABS &&
......
......@@ -521,12 +521,19 @@ config I2C_PXA_SLAVE
is necessary for systems where the PXA may be a target on the
I2C bus.
config HAVE_S3C2410_I2C
bool
help
This will include I2C support for Samsung SoCs. If you want to
include I2C support for any machine, kindly select this in the
respective Kconfig file.
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410 || ARCH_S3C64XX
depends on HAVE_S3C2410_I2C
help
Say Y here to include support for I2C controller in the
Samsung S3C2410 based System-on-Chip devices.
Samsung SoCs.
config I2C_S6000
tristate "S6000 I2C support"
......
......@@ -10,7 +10,8 @@
#define EVDEV_MINOR_BASE 64
#define EVDEV_MINORS 32
#define EVDEV_BUFFER_SIZE 64
#define EVDEV_MIN_BUFFER_SIZE 64U
#define EVDEV_BUF_PACKETS 8
#include <linux/poll.h>
#include <linux/sched.h>
......@@ -23,7 +24,6 @@
#include "input-compat.h"
struct evdev {
int exist;
int open;
int minor;
struct input_handle handle;
......@@ -33,16 +33,18 @@ struct evdev {
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
struct device dev;
bool exist;
};
struct evdev_client {
struct input_event buffer[EVDEV_BUFFER_SIZE];
int head;
int tail;
spinlock_t buffer_lock; /* protects access to buffer, head and tail */
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
int bufsize;
struct input_event buffer[];
};
static struct evdev *evdev_table[EVDEV_MINORS];
......@@ -52,11 +54,15 @@ static void evdev_pass_event(struct evdev_client *client,
struct input_event *event)
{
/*
* Interrupts are disabled, just acquire the lock
* Interrupts are disabled, just acquire the lock.
* Make sure we don't leave with the client buffer
* "empty" by having client->head == client->tail.
*/
spin_lock(&client->buffer_lock);
client->buffer[client->head++] = *event;
client->head &= EVDEV_BUFFER_SIZE - 1;
do {
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
} while (client->head == client->tail);
spin_unlock(&client->buffer_lock);
if (event->type == EV_SYN)
......@@ -242,11 +248,21 @@ static int evdev_release(struct inode *inode, struct file *file)
return 0;
}
static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
{
unsigned int n_events =
max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS,
EVDEV_MIN_BUFFER_SIZE);
return roundup_pow_of_two(n_events);
}
static int evdev_open(struct inode *inode, struct file *file)
{
struct evdev *evdev;
struct evdev_client *client;
int i = iminor(inode) - EVDEV_MINOR_BASE;
unsigned int bufsize;
int error;
if (i >= EVDEV_MINORS)
......@@ -263,12 +279,17 @@ static int evdev_open(struct inode *inode, struct file *file)
if (!evdev)
return -ENODEV;
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
bufsize = evdev_compute_buffer_size(evdev->handle.dev);
client = kzalloc(sizeof(struct evdev_client) +
bufsize * sizeof(struct input_event),
GFP_KERNEL);
if (!client) {
error = -ENOMEM;
goto err_put_evdev;
}
client->bufsize = bufsize;
spin_lock_init(&client->buffer_lock);
client->evdev = evdev;
evdev_attach_client(evdev, client);
......@@ -334,7 +355,7 @@ static int evdev_fetch_next_event(struct evdev_client *client,
have_event = client->head != client->tail;
if (have_event) {
*event = client->buffer[client->tail++];
client->tail &= EVDEV_BUFFER_SIZE - 1;
client->tail &= client->bufsize - 1;
}
spin_unlock_irq(&client->buffer_lock);
......@@ -382,10 +403,15 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
unsigned int mask;
poll_wait(file, &evdev->wait, wait);
return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
(evdev->exist ? 0 : (POLLHUP | POLLERR));
mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
if (client->head != client->tail)
mask |= POLLIN | POLLRDNORM;
return mask;
}
#ifdef CONFIG_COMPAT
......@@ -665,6 +691,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
sizeof(struct input_absinfo))))
return -EFAULT;
/* We can't change number of reserved MT slots */
if (t == ABS_MT_SLOT)
return -EINVAL;
/*
* Take event lock to ensure that we are not
* changing device parameters in the middle
......@@ -768,7 +798,7 @@ static void evdev_remove_chrdev(struct evdev *evdev)
static void evdev_mark_dead(struct evdev *evdev)
{
mutex_lock(&evdev->mutex);
evdev->exist = 0;
evdev->exist = false;
mutex_unlock(&evdev->mutex);
}
......@@ -817,7 +847,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
init_waitqueue_head(&evdev->wait);
dev_set_name(&evdev->dev, "event%d", minor);
evdev->exist = 1;
evdev->exist = true;
evdev->minor = minor;
evdev->handle.dev = input_get_device(dev);
......
......@@ -33,25 +33,6 @@ MODULE_LICENSE("GPL");
#define INPUT_DEVICES 256
/*
* EV_ABS events which should not be cached are listed here.
*/
static unsigned int input_abs_bypass_init_data[] __initdata = {
ABS_MT_TOUCH_MAJOR,
ABS_MT_TOUCH_MINOR,
ABS_MT_WIDTH_MAJOR,
ABS_MT_WIDTH_MINOR,
ABS_MT_ORIENTATION,
ABS_MT_POSITION_X,
ABS_MT_POSITION_Y,
ABS_MT_TOOL_TYPE,
ABS_MT_BLOB_ID,
ABS_MT_TRACKING_ID,
ABS_MT_PRESSURE,
0
};
static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
......@@ -181,6 +162,56 @@ static void input_stop_autorepeat(struct input_dev *dev)
#define INPUT_PASS_TO_DEVICE 2
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
static int input_handle_abs_event(struct input_dev *dev,
unsigned int code, int *pval)
{
bool is_mt_event;
int *pold;
if (code == ABS_MT_SLOT) {
/*
* "Stage" the event; we'll flush it later, when we
* get actiual touch data.
*/
if (*pval >= 0 && *pval < dev->mtsize)
dev->slot = *pval;
return INPUT_IGNORE_EVENT;
}
is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
if (!is_mt_event) {
pold = &dev->abs[code];
} else if (dev->mt) {
struct input_mt_slot *mtslot = &dev->mt[dev->slot];
pold = &mtslot->abs[code - ABS_MT_FIRST];
} else {
/*
* Bypass filtering for multitouch events when
* not employing slots.
*/
pold = NULL;
}
if (pold) {
*pval = input_defuzz_abs_event(*pval, *pold,
dev->absfuzz[code]);
if (*pold == *pval)
return INPUT_IGNORE_EVENT;
*pold = *pval;
}
/* Flush pending "slot" event */
if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) {
dev->abs[ABS_MT_SLOT] = dev->slot;
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
}
return INPUT_PASS_TO_HANDLERS;
}
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
......@@ -196,12 +227,12 @@ static void input_handle_event(struct input_dev *dev,
case SYN_REPORT:
if (!dev->sync) {
dev->sync = 1;
dev->sync = true;
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
case SYN_MT_REPORT:
dev->sync = 0;
dev->sync = false;
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
......@@ -233,21 +264,9 @@ static void input_handle_event(struct input_dev *dev,
break;
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) {
if (test_bit(code, input_abs_bypass)) {
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value);
value = input_defuzz_abs_event(value,
dev->abs[code], dev->absfuzz[code]);
if (dev->abs[code] != value) {
dev->abs[code] = value;
disposition = INPUT_PASS_TO_HANDLERS;
}
}
break;
case EV_REL:
......@@ -298,7 +317,7 @@ static void input_handle_event(struct input_dev *dev,
}
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = 0;
dev->sync = false;
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
......@@ -527,13 +546,31 @@ void input_close_device(struct input_handle *handle)
}
EXPORT_SYMBOL(input_close_device);
/*
* Simulate keyup events for all keys that are marked as pressed.
* The function must be called with dev->event_lock held.
*/
static void input_dev_release_keys(struct input_dev *dev)
{
int code;
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
}
}
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
}
}
/*
* Prepare device for unregistering
*/
static void input_disconnect_device(struct input_dev *dev)
{
struct input_handle *handle;
int code;
/*
* Mark device as going away. Note that we take dev->mutex here
......@@ -552,15 +589,7 @@ static void input_disconnect_device(struct input_dev *dev)
* generate events even after we done here but they will not
* reach any handlers.
*/
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
}
}
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
}
input_dev_release_keys(dev);
list_for_each_entry(handle, &dev->h_list, d_node)
handle->open = 0;
......@@ -684,7 +713,7 @@ int input_set_keycode(struct input_dev *dev,
unsigned int scancode, unsigned int keycode)
{
unsigned long flags;
int old_keycode;
unsigned int old_keycode;
int retval;
if (keycode > KEY_MAX)
......@@ -1278,6 +1307,7 @@ static void input_dev_release(struct device *device)
struct input_dev *dev = to_input_dev(device);
input_ff_destroy(dev);
input_mt_destroy_slots(dev);
kfree(dev);
module_put(THIS_MODULE);
......@@ -1433,6 +1463,15 @@ static int input_dev_resume(struct device *dev)
mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, true);
/*
* Keys that have been pressed at suspend time are unlikely
* to be still pressed when we resume.
*/
spin_lock_irq(&input_dev->event_lock);
input_dev_release_keys(input_dev);
spin_unlock_irq(&input_dev->event_lock);
mutex_unlock(&input_dev->mutex);
return 0;
......@@ -1517,6 +1556,45 @@ void input_free_device(struct input_dev *dev)
}
EXPORT_SYMBOL(input_free_device);
/**
* input_mt_create_slots() - create MT input slots
* @dev: input device supporting MT events and finger tracking
* @num_slots: number of slots used by the device
*
* This function allocates all necessary memory for MT slot handling
* in the input device, and adds ABS_MT_SLOT to the device capabilities.
*/
int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
{
if (!num_slots)
return 0;
dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
if (!dev->mt)
return -ENOMEM;
dev->mtsize = num_slots;
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
return 0;
}
EXPORT_SYMBOL(input_mt_create_slots);
/**
* input_mt_destroy_slots() - frees the MT slots of the input device
* @dev: input device with allocated MT slots
*
* This function is only needed in error path as the input core will
* automatically free the MT slots when the device is destroyed.
*/
void input_mt_destroy_slots(struct input_dev *dev)
{
kfree(dev->mt);
dev->mt = NULL;
dev->mtsize = 0;
}
EXPORT_SYMBOL(input_mt_destroy_slots);
/**
* input_set_capability - mark device as capable of a certain event
* @dev: device that is capable of emitting or accepting event
......@@ -1926,20 +2004,10 @@ static const struct file_operations input_fops = {
.open = input_open_file,
};
static void __init input_init_abs_bypass(void)
{
const unsigned int *p;
for (p = input_abs_bypass_init_data; *p; p++)
input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
}
static int __init input_init(void)
{
int err;
input_init_abs_bypass();
err = class_register(&input_class);
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
......
......@@ -37,7 +37,6 @@ MODULE_LICENSE("GPL");
#define JOYDEV_BUFFER_SIZE 64
struct joydev {
int exist;
int open;
int minor;
struct input_handle handle;
......@@ -46,6 +45,7 @@ struct joydev {
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
struct device dev;
bool exist;
struct js_corr corr[ABS_CNT];
struct JS_DATA_SAVE_TYPE glue;
......@@ -760,7 +760,7 @@ static void joydev_remove_chrdev(struct joydev *joydev)
static void joydev_mark_dead(struct joydev *joydev)
{
mutex_lock(&joydev->mutex);
joydev->exist = 0;
joydev->exist = false;
mutex_unlock(&joydev->mutex);
}
......@@ -817,10 +817,9 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
init_waitqueue_head(&joydev->wait);
dev_set_name(&joydev->dev, "js%d", minor);
joydev->exist = 1;
joydev->exist = true;
joydev->minor = minor;
joydev->exist = 1;
joydev->handle.dev = input_get_device(dev);
joydev->handle.name = dev_name(&joydev->dev);
joydev->handle.handler = handler;
......
......@@ -9,6 +9,7 @@
* 2005 Dominic Cerquetti <binary1230@yahoo.com>
* 2006 Adam Buchbinder <adam.buchbinder@gmail.com>
* 2007 Jan Kratochvil <honza@jikos.cz>
* 2010 Christoph Fritz <chf.fritz@googlemail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -88,6 +89,9 @@
but we map them to axes when possible to simplify things */
#define MAP_DPAD_TO_BUTTONS (1 << 0)
#define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
#define MAP_STICKS_TO_NULL (1 << 2)
#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
......@@ -102,6 +106,10 @@ static int triggers_to_buttons;
module_param(triggers_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads");
static int sticks_to_null;
module_param(sticks_to_null, bool, S_IRUGO);
MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
static const struct xpad_device {
u16 idVendor;
u16 idProduct;
......@@ -114,7 +122,7 @@ static const struct xpad_device {
{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
......@@ -151,6 +159,7 @@ static const struct xpad_device {
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
};
......@@ -158,7 +167,7 @@ static const struct xpad_device {
/* buttons shared with xbox and xbox360 */
static const signed short xpad_common_btn[] = {
BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */
BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
-1 /* terminating entry */
};
......@@ -168,10 +177,10 @@ static const signed short xpad_btn[] = {
-1 /* terminating entry */
};
/* used when dpad is mapped to nuttons */
/* used when dpad is mapped to buttons */
static const signed short xpad_btn_pad[] = {
BTN_LEFT, BTN_RIGHT, /* d-pad left, right */
BTN_0, BTN_1, /* d-pad up, down (XXX names??) */
BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2, /* d-pad left, right */
BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* d-pad up, down */
-1 /* terminating entry */
};
......@@ -279,17 +288,19 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
{
struct input_dev *dev = xpad->dev;
/* left stick */
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 12)));
input_report_abs(dev, ABS_Y,
~(__s16) le16_to_cpup((__le16 *)(data + 14)));
/* right stick */
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 16)));
input_report_abs(dev, ABS_RY,
~(__s16) le16_to_cpup((__le16 *)(data + 18)));
if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
/* left stick */
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 12)));
input_report_abs(dev, ABS_Y,
~(__s16) le16_to_cpup((__le16 *)(data + 14)));
/* right stick */
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 16)));
input_report_abs(dev, ABS_RY,
~(__s16) le16_to_cpup((__le16 *)(data + 18)));
}
/* triggers left/right */
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
......@@ -302,10 +313,11 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
/* digital pad */
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
/* dpad as buttons (left, right, up, down) */
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
} else {
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
......@@ -315,7 +327,7 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
/* start/back buttons and stick press left/right */
input_report_key(dev, BTN_START, data[2] & 0x10);
input_report_key(dev, BTN_BACK, data[2] & 0x20);
input_report_key(dev, BTN_SELECT, data[2] & 0x20);
input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
......@@ -349,11 +361,11 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
/* digital pad */
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (right, left, down, up) */
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
/* dpad as buttons (left, right, up, down) */
input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
} else {
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
......@@ -363,7 +375,7 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
/* start/back buttons */
input_report_key(dev, BTN_START, data[2] & 0x10);
input_report_key(dev, BTN_BACK, data[2] & 0x20);
input_report_key(dev, BTN_SELECT, data[2] & 0x20);
/* stick press left/right */
input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
......@@ -378,17 +390,19 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
input_report_key(dev, BTN_TR, data[3] & 0x02);
input_report_key(dev, BTN_MODE, data[3] & 0x04);
/* left stick */
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 6)));
input_report_abs(dev, ABS_Y,
~(__s16) le16_to_cpup((__le16 *)(data + 8)));
/* right stick */
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 10)));
input_report_abs(dev, ABS_RY,
~(__s16) le16_to_cpup((__le16 *)(data + 12)));
if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
/* left stick */
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 6)));
input_report_abs(dev, ABS_Y,
~(__s16) le16_to_cpup((__le16 *)(data + 8)));
/* right stick */
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 10)));
input_report_abs(dev, ABS_RY,
~(__s16) le16_to_cpup((__le16 *)(data + 12)));
}
/* triggers left/right */
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
......@@ -814,6 +828,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->mapping |= MAP_DPAD_TO_BUTTONS;
if (triggers_to_buttons)
xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;
if (sticks_to_null)
xpad->mapping |= MAP_STICKS_TO_NULL;
}
xpad->dev = input_dev;
......@@ -830,16 +846,20 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
input_dev->open = xpad_open;
input_dev->close = xpad_close;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
input_dev->evbit[0] |= BIT_MASK(EV_ABS);
/* set up axes */
for (i = 0; xpad_abs[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs[i]);
}
/* set up standard buttons and axes */
/* set up standard buttons */
for (i = 0; xpad_common_btn[i] >= 0; i++)
__set_bit(xpad_common_btn[i], input_dev->keybit);
for (i = 0; xpad_abs[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs[i]);
/* Now set up model-specific ones */
/* set up model-specific ones */
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
for (i = 0; xpad360_btn[i] >= 0; i++)
__set_bit(xpad360_btn[i], input_dev->keybit);
......
......@@ -297,6 +297,18 @@ config KEYBOARD_MAX7359
To compile this driver as a module, choose M here: the
module will be called max7359_keypad.
config KEYBOARD_MCS
tristate "MELFAS MCS Touchkey"
depends on I2C
help
Say Y here if you have the MELFAS MCS5000/5080 touchkey controller
chip in your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called mcs_touchkey.
config KEYBOARD_IMX
tristate "IMX keypad support"
depends on ARCH_MXC
......@@ -342,6 +354,15 @@ config KEYBOARD_PXA930_ROTARY
To compile this driver as a module, choose M here: the
module will be called pxa930_rotary.
config KEYBOARD_SAMSUNG
tristate "Samsung keypad support"
depends on SAMSUNG_DEV_KEYPAD
help
Say Y here if you want to use the Samsung keypad.
To compile this driver as a module, choose M here: the
module will be called samsung-keypad.
config KEYBOARD_STOWAWAY
tristate "Stowaway keyboard"
select SERIO
......
......@@ -26,12 +26,14 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o
obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
......
This diff is collapsed.
......@@ -31,6 +31,7 @@ struct gpio_button_data {
struct input_dev *input;
struct timer_list timer;
struct work_struct work;
int timer_debounce; /* in msecs */
bool disabled;
};
......@@ -109,7 +110,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
* Disable IRQ and possible debouncing timer.
*/
disable_irq(gpio_to_irq(bdata->button->gpio));
if (bdata->button->debounce_interval)
if (bdata->timer_debounce)
del_timer_sync(&bdata->timer);
bdata->disabled = true;
......@@ -347,9 +348,9 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
BUG_ON(irq != gpio_to_irq(button->gpio));
if (button->debounce_interval)
if (bdata->timer_debounce)
mod_timer(&bdata->timer,
jiffies + msecs_to_jiffies(button->debounce_interval));
jiffies + msecs_to_jiffies(bdata->timer_debounce));
else
schedule_work(&bdata->work);
......@@ -383,6 +384,14 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
goto fail3;
}
if (button->debounce_interval) {
error = gpio_set_debounce(button->gpio,
button->debounce_interval * 1000);
/* use timer if gpiolib doesn't provide debounce */
if (error < 0)
bdata->timer_debounce = button->debounce_interval;
}
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
......@@ -498,7 +507,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail2:
while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
if (ddata->data[i].timer_debounce)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio);
......@@ -526,7 +535,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, &ddata->data[i]);
if (pdata->buttons[i].debounce_interval)
if (ddata->data[i].timer_debounce)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio);
......
......@@ -642,6 +642,7 @@ static int __devinit lm8323_probe(struct i2c_client *client,
struct lm8323_platform_data *pdata = client->dev.platform_data;
struct input_dev *idev;
struct lm8323_chip *lm;
int pwm;
int i, err;
unsigned long tmo;
u8 data[2];
......@@ -710,8 +711,9 @@ static int __devinit lm8323_probe(struct i2c_client *client,
goto fail1;
}
for (i = 0; i < LM8323_NUM_PWMS; i++) {
err = init_pwm(lm, i + 1, &client->dev, pdata->pwm_names[i]);
for (pwm = 0; pwm < LM8323_NUM_PWMS; pwm++) {
err = init_pwm(lm, pwm + 1, &client->dev,
pdata->pwm_names[pwm]);
if (err < 0)
goto fail2;
}
......@@ -764,9 +766,9 @@ static int __devinit lm8323_probe(struct i2c_client *client,
fail3:
device_remove_file(&client->dev, &dev_attr_disable_kp);
fail2:
while (--i >= 0)
if (lm->pwm[i].enabled)
led_classdev_unregister(&lm->pwm[i].cdev);
while (--pwm >= 0)
if (lm->pwm[pwm].enabled)
led_classdev_unregister(&lm->pwm[pwm].cdev);
fail1:
input_free_device(idev);
kfree(lm);
......
......@@ -37,6 +37,7 @@ struct matrix_keypad {
spinlock_t lock;
bool scan_pending;
bool stopped;
bool gpio_all_disabled;
};
/*
......@@ -87,8 +88,12 @@ static void enable_row_irqs(struct matrix_keypad *keypad)
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
for (i = 0; i < pdata->num_row_gpios; i++)
enable_irq(gpio_to_irq(pdata->row_gpios[i]));
if (pdata->clustered_irq > 0)
enable_irq(pdata->clustered_irq);
else {
for (i = 0; i < pdata->num_row_gpios; i++)
enable_irq(gpio_to_irq(pdata->row_gpios[i]));
}
}
static void disable_row_irqs(struct matrix_keypad *keypad)
......@@ -96,8 +101,12 @@ static void disable_row_irqs(struct matrix_keypad *keypad)
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
for (i = 0; i < pdata->num_row_gpios; i++)
disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
if (pdata->clustered_irq > 0)
disable_irq_nosync(pdata->clustered_irq);
else {
for (i = 0; i < pdata->num_row_gpios; i++)
disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
}
}
/*
......@@ -216,45 +225,69 @@ static void matrix_keypad_stop(struct input_dev *dev)
}
#ifdef CONFIG_PM
static int matrix_keypad_suspend(struct device *dev)
static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
unsigned int gpio;
int i;
matrix_keypad_stop(keypad->input_dev);
if (pdata->clustered_irq > 0) {
if (enable_irq_wake(pdata->clustered_irq) == 0)
keypad->gpio_all_disabled = true;
} else {
if (device_may_wakeup(&pdev->dev)) {
for (i = 0; i < pdata->num_row_gpios; i++) {
if (!test_bit(i, keypad->disabled_gpios)) {
unsigned int gpio = pdata->row_gpios[i];
gpio = pdata->row_gpios[i];
if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
__set_bit(i, keypad->disabled_gpios);
}
}
}
return 0;
}
static int matrix_keypad_resume(struct device *dev)
static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
unsigned int gpio;
int i;
if (device_may_wakeup(&pdev->dev)) {
if (pdata->clustered_irq > 0) {
if (keypad->gpio_all_disabled) {
disable_irq_wake(pdata->clustered_irq);
keypad->gpio_all_disabled = false;
}
} else {
for (i = 0; i < pdata->num_row_gpios; i++) {
if (test_and_clear_bit(i, keypad->disabled_gpios)) {
unsigned int gpio = pdata->row_gpios[i];
gpio = pdata->row_gpios[i];
disable_irq_wake(gpio_to_irq(gpio));
}
}
}
}
static int matrix_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
matrix_keypad_stop(keypad->input_dev);
if (device_may_wakeup(&pdev->dev))
matrix_keypad_enable_wakeup(keypad);
return 0;
}
static int matrix_keypad_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
matrix_keypad_disable_wakeup(keypad);
matrix_keypad_start(keypad->input_dev);
......@@ -296,17 +329,31 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev,
gpio_direction_input(pdata->row_gpios[i]);
}
for (i = 0; i < pdata->num_row_gpios; i++) {
err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
if (pdata->clustered_irq > 0) {
err = request_irq(pdata->clustered_irq,
matrix_keypad_interrupt,
IRQF_DISABLED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
pdata->clustered_irq_flags,
"matrix-keypad", keypad);
if (err) {
dev_err(&pdev->dev,
"Unable to acquire interrupt for GPIO line %i\n",
pdata->row_gpios[i]);
goto err_free_irqs;
"Unable to acquire clustered interrupt\n");
goto err_free_rows;
}
} else {
for (i = 0; i < pdata->num_row_gpios; i++) {
err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
matrix_keypad_interrupt,
IRQF_DISABLED |
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
"matrix-keypad", keypad);
if (err) {
dev_err(&pdev->dev,
"Unable to acquire interrupt "
"for GPIO line %i\n",
pdata->row_gpios[i]);
goto err_free_irqs;
}
}
}
......@@ -418,11 +465,16 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->num_row_gpios; i++) {
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
gpio_free(pdata->row_gpios[i]);
if (pdata->clustered_irq > 0) {
free_irq(pdata->clustered_irq, keypad);
} else {
for (i = 0; i < pdata->num_row_gpios; i++)
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
}
for (i = 0; i < pdata->num_row_gpios; i++)
gpio_free(pdata->row_gpios[i]);
for (i = 0; i < pdata->num_col_gpios; i++)
gpio_free(pdata->col_gpios[i]);
......
/*
* mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: HeungJun Kim <riverful.kim@samsung.com>
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c/mcs.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/slab.h>
/* MCS5000 Touchkey */
#define MCS5000_TOUCHKEY_STATUS 0x04
#define MCS5000_TOUCHKEY_STATUS_PRESS 7
#define MCS5000_TOUCHKEY_FW 0x0a
#define MCS5000_TOUCHKEY_BASE_VAL 0x61
/* MCS5080 Touchkey */
#define MCS5080_TOUCHKEY_STATUS 0x00
#define MCS5080_TOUCHKEY_STATUS_PRESS 3
#define MCS5080_TOUCHKEY_FW 0x01
#define MCS5080_TOUCHKEY_BASE_VAL 0x1
enum mcs_touchkey_type {
MCS5000_TOUCHKEY,
MCS5080_TOUCHKEY,
};
struct mcs_touchkey_chip {
unsigned int status_reg;
unsigned int pressbit;
unsigned int press_invert;
unsigned int baseval;
};
struct mcs_touchkey_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct mcs_touchkey_chip chip;
unsigned int key_code;
unsigned int key_val;
unsigned short keycodes[];
};
static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
{
struct mcs_touchkey_data *data = dev_id;
struct mcs_touchkey_chip *chip = &data->chip;
struct i2c_client *client = data->client;
struct input_dev *input = data->input_dev;
unsigned int key_val;
unsigned int pressed;
int val;
val = i2c_smbus_read_byte_data(client, chip->status_reg);
if (val < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", val);
goto out;
}
pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
if (chip->press_invert)
pressed ^= chip->press_invert;
/* key_val is 0 when released, so we should use key_val of press. */
if (pressed) {
key_val = val & (0xff >> (8 - chip->pressbit));
if (!key_val)
goto out;
key_val -= chip->baseval;
data->key_code = data->keycodes[key_val];
data->key_val = key_val;
}
input_event(input, EV_MSC, MSC_SCAN, data->key_val);
input_report_key(input, data->key_code, pressed);
input_sync(input);
dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code,
pressed ? "pressed" : "released");
out:
return IRQ_HANDLED;
}
static int __devinit mcs_touchkey_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct mcs_platform_data *pdata;
struct mcs_touchkey_data *data;
struct input_dev *input_dev;
unsigned int fw_reg;
int fw_ver;
int error;
int i;
pdata = client->dev.platform_data;
if (!pdata) {
dev_err(&client->dev, "no platform data defined\n");
return -EINVAL;
}
data = kzalloc(sizeof(struct mcs_touchkey_data) +
sizeof(data->keycodes[0]) * (pdata->key_maxval + 1),
GFP_KERNEL);
input_dev = input_allocate_device();
if (!data || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM;
goto err_free_mem;
}
data->client = client;
data->input_dev = input_dev;
if (id->driver_data == MCS5000_TOUCHKEY) {
data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
fw_reg = MCS5000_TOUCHKEY_FW;
} else {
data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
data->chip.press_invert = 1;
data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
fw_reg = MCS5080_TOUCHKEY_FW;
}
fw_ver = i2c_smbus_read_byte_data(client, fw_reg);
if (fw_ver < 0) {
error = fw_ver;
dev_err(&client->dev, "i2c read error[%d]\n", error);
goto err_free_mem;
}
dev_info(&client->dev, "Firmware version: %d\n", fw_ver);
input_dev->name = "MELPAS MCS Touchkey";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
if (!pdata->no_autorepeat)
input_dev->evbit[0] |= BIT_MASK(EV_REP);
input_dev->keycode = data->keycodes;
input_dev->keycodesize = sizeof(data->keycodes[0]);
input_dev->keycodemax = pdata->key_maxval + 1;
for (i = 0; i < pdata->keymap_size; i++) {
unsigned int val = MCS_KEY_VAL(pdata->keymap[i]);
unsigned int code = MCS_KEY_CODE(pdata->keymap[i]);
data->keycodes[val] = code;
__set_bit(code, input_dev->keybit);
}
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, data);
if (pdata->cfg_pin)
pdata->cfg_pin();
error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
goto err_free_mem;
}
error = input_register_device(input_dev);
if (error)
goto err_free_irq;
i2c_set_clientdata(client, data);
return 0;
err_free_irq:
free_irq(client->irq, data);
err_free_mem:
input_free_device(input_dev);
kfree(data);
return error;
}
static int __devexit mcs_touchkey_remove(struct i2c_client *client)
{
struct mcs_touchkey_data *data = i2c_get_clientdata(client);
free_irq(client->irq, data);
input_unregister_device(data->input_dev);
kfree(data);
return 0;
}
static const struct i2c_device_id mcs_touchkey_id[] = {
{ "mcs5000_touchkey", MCS5000_TOUCHKEY },
{ "mcs5080_touchkey", MCS5080_TOUCHKEY },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
static struct i2c_driver mcs_touchkey_driver = {
.driver = {
.name = "mcs_touchkey",
.owner = THIS_MODULE,
},
.probe = mcs_touchkey_probe,
.remove = __devexit_p(mcs_touchkey_remove),
.id_table = mcs_touchkey_id,
};
static int __init mcs_touchkey_init(void)
{
return i2c_add_driver(&mcs_touchkey_driver);
}
static void __exit mcs_touchkey_exit(void)
{
i2c_del_driver(&mcs_touchkey_driver);
}
module_init(mcs_touchkey_init);
module_exit(mcs_touchkey_exit);
/* Module information */
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -327,6 +327,17 @@ config INPUT_PCF8574
To compile this driver as a module, choose M here: the
module will be called pcf8574_keypad.
config INPUT_PWM_BEEPER
tristate "PWM beeper support"
depends on HAVE_PWM
help
Say Y here to get support for PWM based beeper devices.
If unsure, say N.
To compile this driver as a module, choose M here: the module will be
called pwm-beeper.
config INPUT_GPIO_ROTARY_ENCODER
tristate "Rotary encoders connected to GPIO pins"
depends on GPIOLIB && GENERIC_GPIO
......@@ -390,4 +401,41 @@ config INPUT_PCAP
To compile this driver as a module, choose M here: the
module will be called pcap_keys.
config INPUT_ADXL34X
tristate "Analog Devices ADXL34x Three-Axis Digital Accelerometer"
default n
help
Say Y here if you have a Accelerometer interface using the
ADXL345/6 controller, and your board-specific initialization
code includes that in its table of devices.
This driver can use either I2C or SPI communication to the
ADXL345/6 controller. Select the appropriate method for
your system.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called adxl34x.
config INPUT_ADXL34X_I2C
tristate "support I2C bus connection"
depends on INPUT_ADXL34X && I2C
default y
help
Say Y here if you have ADXL345/6 hooked to an I2C bus.
To compile this driver as a module, choose M here: the
module will be called adxl34x-i2c.
config INPUT_ADXL34X_SPI
tristate "support SPI bus connection"
depends on INPUT_ADXL34X && SPI
default y
help
Say Y here if you have ADXL345/6 hooked to a SPI bus.
To compile this driver as a module, choose M here: the
module will be called adxl34x-spi.
endif
......@@ -8,6 +8,9 @@ obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
obj-$(CONFIG_INPUT_AD714X) += ad714x.o
obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o
obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o
obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o
obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o
obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
......@@ -26,6 +29,7 @@ obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
......
/*
* ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface)
*
* Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/
#include <linux/input.h> /* BUS_I2C */
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/types.h>
#include "adxl34x.h"
static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
{
struct i2c_client *client = to_i2c_client(dev);
return i2c_smbus_read_byte_data(client, reg);
}
static int adxl34x_smbus_write(struct device *dev,
unsigned char reg, unsigned char val)
{
struct i2c_client *client = to_i2c_client(dev);
return i2c_smbus_write_byte_data(client, reg, val);
}
static int adxl34x_smbus_read_block(struct device *dev,
unsigned char reg, int count,
void *buf)
{
struct i2c_client *client = to_i2c_client(dev);
return i2c_smbus_read_i2c_block_data(client, reg, count, buf);
}
static int adxl34x_i2c_read_block(struct device *dev,
unsigned char reg, int count,
void *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int ret;
ret = i2c_master_send(client, &reg, 1);
if (ret < 0)
return ret;
ret = i2c_master_recv(client, buf, count);
if (ret < 0)
return ret;
if (ret != count)
return -EIO;
return 0;
}
static const struct adxl34x_bus_ops adxl34x_smbus_bops = {
.bustype = BUS_I2C,
.write = adxl34x_smbus_write,
.read = adxl34x_smbus_read,
.read_block = adxl34x_smbus_read_block,
};
static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
.bustype = BUS_I2C,
.write = adxl34x_smbus_write,
.read = adxl34x_smbus_read,
.read_block = adxl34x_i2c_read_block,
};
static int __devinit adxl34x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adxl34x *ac;
int error;
error = i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA);
if (!error) {
dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
return -EIO;
}
ac = adxl34x_probe(&client->dev, client->irq, false,
i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_I2C_BLOCK) ?
&adxl34x_smbus_bops : &adxl34x_i2c_bops);
if (IS_ERR(ac))
return PTR_ERR(ac);
i2c_set_clientdata(client, ac);
return 0;
}
static int __devexit adxl34x_i2c_remove(struct i2c_client *client)
{
struct adxl34x *ac = i2c_get_clientdata(client);
return adxl34x_remove(ac);
}
#ifdef CONFIG_PM
static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
{
struct adxl34x *ac = i2c_get_clientdata(client);
adxl34x_suspend(ac);
return 0;
}
static int adxl34x_i2c_resume(struct i2c_client *client)
{
struct adxl34x *ac = i2c_get_clientdata(client);
adxl34x_resume(ac);
return 0;
}
#else
# define adxl34x_i2c_suspend NULL
# define adxl34x_i2c_resume NULL
#endif
static const struct i2c_device_id adxl34x_id[] = {
{ "adxl34x", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl34x_id);
static struct i2c_driver adxl34x_driver = {
.driver = {
.name = "adxl34x",
.owner = THIS_MODULE,
},
.probe = adxl34x_i2c_probe,
.remove = __devexit_p(adxl34x_i2c_remove),
.suspend = adxl34x_i2c_suspend,
.resume = adxl34x_i2c_resume,
.id_table = adxl34x_id,
};
static int __init adxl34x_i2c_init(void)
{
return i2c_add_driver(&adxl34x_driver);
}
module_init(adxl34x_i2c_init);
static void __exit adxl34x_i2c_exit(void)
{
i2c_del_driver(&adxl34x_driver);
}
module_exit(adxl34x_i2c_exit);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver");
MODULE_LICENSE("GPL");
/*
* ADLX345/346 Three-Axis Digital Accelerometers (SPI Interface)
*
* Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/
#include <linux/input.h> /* BUS_SPI */
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
#include "adxl34x.h"
#define MAX_SPI_FREQ_HZ 5000000
#define MAX_FREQ_NO_FIFODELAY 1500000
#define ADXL34X_CMD_MULTB (1 << 6)
#define ADXL34X_CMD_READ (1 << 7)
#define ADXL34X_WRITECMD(reg) (reg & 0x3F)
#define ADXL34X_READCMD(reg) (ADXL34X_CMD_READ | (reg & 0x3F))
#define ADXL34X_READMB_CMD(reg) (ADXL34X_CMD_READ | ADXL34X_CMD_MULTB \
| (reg & 0x3F))
static int adxl34x_spi_read(struct device *dev, unsigned char reg)
{
struct spi_device *spi = to_spi_device(dev);
unsigned char cmd;
cmd = ADXL34X_READCMD(reg);
return spi_w8r8(spi, cmd);
}
static int adxl34x_spi_write(struct device *dev,
unsigned char reg, unsigned char val)
{
struct spi_device *spi = to_spi_device(dev);
unsigned char buf[2];
buf[0] = ADXL34X_WRITECMD(reg);
buf[1] = val;
return spi_write(spi, buf, sizeof(buf));
}
static int adxl34x_spi_read_block(struct device *dev,
unsigned char reg, int count,
void *buf)
{
struct spi_device *spi = to_spi_device(dev);
ssize_t status;
reg = ADXL34X_READMB_CMD(reg);
status = spi_write_then_read(spi, &reg, 1, buf, count);
return (status < 0) ? status : 0;
}
static const struct adxl34x_bus_ops adx134x_spi_bops = {
.bustype = BUS_SPI,
.write = adxl34x_spi_write,
.read = adxl34x_spi_read,
.read_block = adxl34x_spi_read_block,
};
static int __devinit adxl34x_spi_probe(struct spi_device *spi)
{
struct adxl34x *ac;
/* don't exceed max specified SPI CLK frequency */
if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) {
dev_err(&spi->dev, "SPI CLK %d Hz too fast\n", spi->max_speed_hz);
return -EINVAL;
}
ac = adxl34x_probe(&spi->dev, spi->irq,
spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY,
&adx134x_spi_bops);
if (IS_ERR(ac))
return PTR_ERR(ac);
spi_set_drvdata(spi, ac);
return 0;
}
static int __devexit adxl34x_spi_remove(struct spi_device *spi)
{
struct adxl34x *ac = dev_get_drvdata(&spi->dev);
return adxl34x_remove(ac);
}
#ifdef CONFIG_PM
static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
{
struct adxl34x *ac = dev_get_drvdata(&spi->dev);
adxl34x_suspend(ac);
return 0;
}
static int adxl34x_spi_resume(struct spi_device *spi)
{
struct adxl34x *ac = dev_get_drvdata(&spi->dev);
adxl34x_resume(ac);
return 0;
}
#else
# define adxl34x_spi_suspend NULL
# define adxl34x_spi_resume NULL
#endif
static struct spi_driver adxl34x_driver = {
.driver = {
.name = "adxl34x",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = adxl34x_spi_probe,
.remove = __devexit_p(adxl34x_spi_remove),
.suspend = adxl34x_spi_suspend,
.resume = adxl34x_spi_resume,
};
static int __init adxl34x_spi_init(void)
{
return spi_register_driver(&adxl34x_driver);
}
module_init(adxl34x_spi_init);
static void __exit adxl34x_spi_exit(void)
{
spi_unregister_driver(&adxl34x_driver);
}
module_exit(adxl34x_spi_exit);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
/*
* ADXL345/346 Three-Axis Digital Accelerometers (I2C/SPI Interface)
*
* Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/
#ifndef _ADXL34X_H_
#define _ADXL34X_H_
struct device;
struct adxl34x;
struct adxl34x_bus_ops {
u16 bustype;
int (*read)(struct device *, unsigned char);
int (*read_block)(struct device *, unsigned char, int, void *);
int (*write)(struct device *, unsigned char, unsigned char);
};
void adxl34x_suspend(struct adxl34x *ac);
void adxl34x_resume(struct adxl34x *ac);
struct adxl34x *adxl34x_probe(struct device *dev, int irq,
bool fifo_delay_default,
const struct adxl34x_bus_ops *bops);
int adxl34x_remove(struct adxl34x *ac);
#endif
......@@ -21,6 +21,8 @@
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......@@ -60,12 +62,11 @@ static acpi_status acpi_atlas_button_handler(u32 function,
input_report_key(input_dev, atlas_keymap[code], key_down);
input_sync(input_dev);
status = 0;
status = AE_OK;
} else {
printk(KERN_WARNING "atlas: shrugged on unexpected function"
":function=%x,address=%lx,value=%x\n",
pr_warn("shrugged on unexpected function: function=%x,address=%lx,value=%x\n",
function, (unsigned long)address, (u32)*value);
status = -EINVAL;
status = AE_BAD_PARAMETER;
}
return status;
......@@ -79,7 +80,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "atlas: unable to allocate input device\n");
pr_err("unable to allocate input device\n");
return -ENOMEM;
}
......@@ -102,7 +103,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
err = input_register_device(input_dev);
if (err) {
printk(KERN_ERR "atlas: couldn't register input device\n");
pr_err("couldn't register input device\n");
input_free_device(input_dev);
return err;
}
......@@ -112,12 +113,12 @@ static int atlas_acpi_button_add(struct acpi_device *device)
0x81, &acpi_atlas_button_handler,
&acpi_atlas_button_setup, device);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR "Atlas: Error installing addr spc handler\n");
pr_err("error installing addr spc handler\n");
input_unregister_device(input_dev);
status = -EINVAL;
err = -EINVAL;
}
return status;
return err;
}
static int atlas_acpi_button_remove(struct acpi_device *device, int type)
......@@ -126,14 +127,12 @@ static int atlas_acpi_button_remove(struct acpi_device *device, int type)
status = acpi_remove_address_space_handler(device->handle,
0x81, &acpi_atlas_button_handler);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR "Atlas: Error removing addr spc handler\n");
status = -EINVAL;
}
if (ACPI_FAILURE(status))
pr_err("error removing addr spc handler\n");
input_unregister_device(input_dev);
return status;
return 0;
}
static const struct acpi_device_id atlas_device_ids[] = {
......@@ -145,6 +144,7 @@ MODULE_DEVICE_TABLE(acpi, atlas_device_ids);
static struct acpi_driver atlas_acpi_driver = {
.name = ACPI_ATLAS_NAME,
.class = ACPI_ATLAS_CLASS,
.owner = THIS_MODULE,
.ids = atlas_device_ids,
.ops = {
.add = atlas_acpi_button_add,
......@@ -154,18 +154,10 @@ static struct acpi_driver atlas_acpi_driver = {
static int __init atlas_acpi_init(void)
{
int result;
if (acpi_disabled)
return -ENODEV;
result = acpi_bus_register_driver(&atlas_acpi_driver);
if (result < 0) {
printk(KERN_ERR "Atlas ACPI: Unable to register driver\n");
return -ENODEV;
}
return 0;
return acpi_bus_register_driver(&atlas_acpi_driver);
}
static void __exit atlas_acpi_exit(void)
......
This diff is collapsed.
......@@ -52,7 +52,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)
return IRQ_HANDLED;
}
static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
static int __init twl4030_pwrbutton_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
int irq = platform_get_irq(pdev, 0);
......@@ -95,7 +95,7 @@ static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
return err;
}
static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev)
static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev)
{
struct input_dev *pwr = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
......@@ -106,9 +106,8 @@ static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev)
return 0;
}
struct platform_driver twl4030_pwrbutton_driver = {
.probe = twl4030_pwrbutton_probe,
.remove = __devexit_p(twl4030_pwrbutton_remove),
static struct platform_driver twl4030_pwrbutton_driver = {
.remove = __exit_p(twl4030_pwrbutton_remove),
.driver = {
.name = "twl4030_pwrbutton",
.owner = THIS_MODULE,
......@@ -117,7 +116,8 @@ struct platform_driver twl4030_pwrbutton_driver = {
static int __init twl4030_pwrbutton_init(void)
{
return platform_driver_register(&twl4030_pwrbutton_driver);
return platform_driver_probe(&twl4030_pwrbutton_driver,
twl4030_pwrbutton_probe);
}
module_init(twl4030_pwrbutton_init);
......
......@@ -1347,7 +1347,7 @@ static int __init wb_module_init(void)
err = map_bios();
if (err)
return err;
goto err_free_keymap;
err = platform_driver_register(&wistron_driver);
if (err)
......@@ -1371,6 +1371,8 @@ static int __init wb_module_init(void)
platform_driver_unregister(&wistron_driver);
err_unmap_bios:
unmap_bios();
err_free_keymap:
kfree(keymap);
return err;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -43,6 +43,7 @@ enum {
WACOM_G4,
PTU,
PL,
DTU,
INTUOS,
INTUOS3S,
INTUOS3,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment