diff options
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r-- | arch/arm/plat-samsung/Kconfig | 14 | ||||
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/plat-samsung/clock.c | 92 | ||||
-rw-r--r-- | arch/arm/plat-samsung/dev-nand.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-samsung/gpio-config.c | 42 | ||||
-rw-r--r-- | arch/arm/plat-samsung/gpiolib.c | 7 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/audio.h | 24 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/clock.h | 3 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/devs.h | 17 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-core.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pd.h | 30 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pm.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/sdhci.h | 35 | ||||
-rw-r--r-- | arch/arm/plat-samsung/irq-uart.c | 40 | ||||
-rw-r--r-- | arch/arm/plat-samsung/irq-vic-timer.c | 26 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pd.c | 95 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pm.c | 6 |
18 files changed, 407 insertions, 38 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index dcd6eff4ee5..32be05cf82a 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -95,6 +95,12 @@ config S3C_GPIO_PULL_UPDOWN help Internal configuration to enable the correct GPIO pull helper +config S3C_GPIO_PULL_S3C2443 + bool + select S3C_GPIO_PULL_UPDOWN + help + Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO + config S3C_GPIO_PULL_DOWN bool help @@ -333,4 +339,12 @@ config SAMSUNG_WAKEMASK and above. This code allows a set of interrupt to wakeup-mask mappings. See <plat/wakeup-mask.h> +comment "Power Domain" + +config SAMSUNG_PD + bool "Samsung Power Domain" + depends on PM_RUNTIME + help + Say Y here if you want to control Power Domain by Runtime PM. + endif diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index afcce474af8..09dbd78b56f 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -73,6 +73,10 @@ obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o +# PD support + +obj-$(CONFIG_SAMSUNG_PD) += pd.o + # PWM support obj-$(CONFIG_HAVE_PWM) += pwm.o diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index e8d20b0bc50..772892826ff 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -39,6 +39,9 @@ #include <linux/clk.h> #include <linux/spinlock.h> #include <linux/io.h> +#if defined(CONFIG_DEBUG_FS) +#include <linux/debugfs.h> +#endif #include <mach/hardware.h> #include <asm/irq.h> @@ -447,3 +450,92 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal) return 0; } +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/* debugfs support to trace clock tree hierarchy and attributes */ + +static struct dentry *clk_debugfs_root; + +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child, *child_tmp; + struct clk *pa = c->parent; + char s[255]; + char *p = s; + + p += sprintf(p, "%s", c->name); + + if (c->id >= 0) + sprintf(p, ":%d", c->id); + + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (!d) + return -ENOMEM; + + c->dent = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage); + if (!d) { + err = -ENOMEM; + goto err_out; + } + + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (!d) { + err = -ENOMEM; + goto err_out; + } + return 0; + +err_out: + d = c->dent; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, list) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; + +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} +late_initcall(clk_debugfs_init); + +#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c index 3a7b8891ba4..6927ae8fd11 100644 --- a/arch/arm/plat-samsung/dev-nand.c +++ b/arch/arm/plat-samsung/dev-nand.c @@ -126,5 +126,3 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand) s3c_device_nand.dev.platform_data = npd; } - -EXPORT_SYMBOL_GPL(s3c_nand_set_platdata); diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 0aa32f242ee..1c0b0401594 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -278,6 +278,48 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, pup &= 0x3; return (__force s3c_gpio_pull_t)pup; } + +#ifdef CONFIG_S3C_GPIO_PULL_S3C2443 +int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + switch (pull) { + case S3C_GPIO_PULL_NONE: + pull = 0x01; + break; + case S3C_GPIO_PULL_UP: + pull = 0x00; + break; + case S3C_GPIO_PULL_DOWN: + pull = 0x02; + break; + } + return s3c_gpio_setpull_updown(chip, off, pull); +} + +s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, + unsigned int off) +{ + s3c_gpio_pull_t pull; + + pull = s3c_gpio_getpull_updown(chip, off); + + switch (pull) { + case 0x00: + pull = S3C_GPIO_PULL_UP; + break; + case 0x01: + case 0x03: + pull = S3C_GPIO_PULL_NONE; + break; + case 0x02: + pull = S3C_GPIO_PULL_DOWN; + break; + } + + return pull; +} +#endif #endif #if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN) diff --git a/arch/arm/plat-samsung/gpiolib.c b/arch/arm/plat-samsung/gpiolib.c index c354089254f..ea37c046178 100644 --- a/arch/arm/plat-samsung/gpiolib.c +++ b/arch/arm/plat-samsung/gpiolib.c @@ -197,3 +197,10 @@ void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, s3c_gpiolib_add(chip); } } + +void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip, + int nr_chips) +{ + for (; nr_chips > 0; nr_chips--, chip++) + s3c_gpiolib_add(chip); +} diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h index 7712ff6336f..a0826ed2f9f 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h @@ -25,10 +25,34 @@ extern void s3c64xx_ac97_setup_gpio(int); #define S5PC100_SPDIF_GPG3 1 extern void s5pc100_spdif_setup_gpio(int); +struct samsung_i2s { +/* If the Primary DAI has 5.1 Channels */ +#define QUIRK_PRI_6CHAN (1 << 0) +/* If the I2S block has a Stereo Overlay Channel */ +#define QUIRK_SEC_DAI (1 << 1) +/* + * If the I2S block has no internal prescalar or MUX (I2SMOD[10] bit) + * The Machine driver must provide suitably set clock to the I2S block. + */ +#define QUIRK_NO_MUXPSR (1 << 2) +#define QUIRK_NEED_RSTCLR (1 << 3) + /* Quirks of the I2S controller */ + u32 quirks; + + /* + * Array of clock names that can be used to generate I2S signals. + * Also corresponds to clocks of I2SMOD[10] + */ + const char **src_clk; +}; + /** * struct s3c_audio_pdata - common platform data for audio device drivers * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode */ struct s3c_audio_pdata { int (*cfg_gpio)(struct platform_device *); + union { + struct samsung_i2s i2s; + } type; }; diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 0fbcd0effd8..9a82b887491 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -47,6 +47,9 @@ struct clk { struct clk_ops *ops; int (*enable)(struct clk *, int enable); +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ +#endif }; /* other clocks which may be registered by board support */ diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2d82a6cb144..1be192209a7 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -96,6 +96,16 @@ extern struct platform_device s5pv210_device_iis1; extern struct platform_device s5pv210_device_iis2; extern struct platform_device s5pv210_device_spdif; +extern struct platform_device s5pv310_device_ac97; +extern struct platform_device s5pv310_device_pcm0; +extern struct platform_device s5pv310_device_pcm1; +extern struct platform_device s5pv310_device_pcm2; +extern struct platform_device s5pv310_device_i2s0; +extern struct platform_device s5pv310_device_i2s1; +extern struct platform_device s5pv310_device_i2s2; +extern struct platform_device s5pv310_device_spdif; +extern struct platform_device s5pv310_device_pd[]; + extern struct platform_device s5p6442_device_pcm0; extern struct platform_device s5p6442_device_pcm1; extern struct platform_device s5p6442_device_iis0; @@ -106,6 +116,8 @@ extern struct platform_device s5p6440_device_pcm; extern struct platform_device s5p6440_device_iis; extern struct platform_device s5p6450_device_iis0; +extern struct platform_device s5p6450_device_iis1; +extern struct platform_device s5p6450_device_iis2; extern struct platform_device s5p6450_device_pcm0; extern struct platform_device s5pc100_device_ac97; @@ -122,6 +134,11 @@ extern struct platform_device s5p_device_fimc0; extern struct platform_device s5p_device_fimc1; extern struct platform_device s5p_device_fimc2; +extern struct platform_device s5p_device_mipi_csis0; +extern struct platform_device s5p_device_mipi_csis1; + +extern struct platform_device s5pv310_device_sysmmu; + /* s3c2440 specific devices */ #ifdef CONFIG_CPU_S3C2440 diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index 0d2c5703f1e..5603db0b79b 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -244,7 +244,7 @@ extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, * This helper function reads the state of the pull-{up,down} resistor for the * given GPIO in the same case as s3c_gpio_setpull_upown. */ -extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip, +extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, unsigned int off); #endif /* __PLAT_GPIO_CFG_HELPERS_H */ diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index 13a22b8861e..dac35d0a711 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -118,6 +118,8 @@ extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip, int nr_chips); extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, int nr_chips); +extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip, + int nr_chips); extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h new file mode 100644 index 00000000000..5f0ad85783d --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pd.h @@ -0,0 +1,30 @@ +/* linux/arch/arm/plat-samsung/include/plat/pd.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * 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_SAMSUNG_PD_H +#define __ASM_PLAT_SAMSUNG_PD_H __FILE__ + +struct samsung_pd_info { + int (*enable)(struct device *dev); + int (*disable)(struct device *dev); + void __iomem *base; +}; + +enum s5pv310_pd_block { + PD_MFC, + PD_G3D, + PD_LCD0, + PD_LCD1, + PD_TV, + PD_CAM, + PD_GPS +}; + +#endif /* __ASM_PLAT_SAMSUNG_PD_H */ diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 245836d9193..d9025e37767 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -15,6 +15,8 @@ * management */ +#include <linux/irq.h> + #ifdef CONFIG_PM extern __init int s3c_pm_init(void); @@ -100,7 +102,7 @@ extern void s3c_pm_do_restore(struct sleep_save *ptr, int count); extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); #ifdef CONFIG_PM -extern int s3c_irqext_wake(unsigned int irqno, unsigned int state); +extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); extern int s3c24xx_irq_resume(struct sys_device *dev); #else diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index 85853f8c4c5..5a41a0b69ee 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -107,6 +107,8 @@ extern struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata; /* Helper function availablity */ +extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w); @@ -122,6 +124,39 @@ extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w); extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w); +/* S3C2416 SDHCI setup */ + +#ifdef CONFIG_S3C2416_SETUP_SDHCI +extern char *s3c2416_hsmmc_clksrcs[4]; + +extern void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +static inline void s3c2416_default_sdhci0(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC + s3c_hsmmc0_def_platdata.clocks = s3c2416_hsmmc_clksrcs; + s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio; + s3c_hsmmc0_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card; +#endif /* CONFIG_S3C_DEV_HSMMC */ +} + +static inline void s3c2416_default_sdhci1(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC1 + s3c_hsmmc1_def_platdata.clocks = s3c2416_hsmmc_clksrcs; + s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio; + s3c_hsmmc1_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card; +#endif /* CONFIG_S3C_DEV_HSMMC1 */ +} + +#else +static inline void s3c2416_default_sdhci0(void) { } +static inline void s3c2416_default_sdhci1(void) { } + +#endif /* CONFIG_S3C2416_SETUP_SDHCI */ /* S3C64XX SDHCI setup */ #ifdef CONFIG_S3C64XX_SETUP_SDHCI diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c index 4f8c102674a..4e770355ccb 100644 --- a/arch/arm/plat-samsung/irq-uart.c +++ b/arch/arm/plat-samsung/irq-uart.c @@ -28,9 +28,9 @@ * are consecutive when looking up the interrupt in the demux routines. */ -static inline void __iomem *s3c_irq_uart_base(unsigned int irq) +static inline void __iomem *s3c_irq_uart_base(struct irq_data *data) { - struct s3c_uart_irq *uirq = get_irq_chip_data(irq); + struct s3c_uart_irq *uirq = irq_data_get_irq_chip_data(data); return uirq->regs; } @@ -39,10 +39,10 @@ static inline unsigned int s3c_irq_uart_bit(unsigned int irq) return irq & 3; } -static void s3c_irq_uart_mask(unsigned int irq) +static void s3c_irq_uart_mask(struct irq_data *data) { - void __iomem *regs = s3c_irq_uart_base(irq); - unsigned int bit = s3c_irq_uart_bit(irq); + void __iomem *regs = s3c_irq_uart_base(data); + unsigned int bit = s3c_irq_uart_bit(data->irq); u32 reg; reg = __raw_readl(regs + S3C64XX_UINTM); @@ -50,10 +50,10 @@ static void s3c_irq_uart_mask(unsigned int irq) __raw_writel(reg, regs + S3C64XX_UINTM); } -static void s3c_irq_uart_maskack(unsigned int irq) +static void s3c_irq_uart_maskack(struct irq_data *data) { - void __iomem *regs = s3c_irq_uart_base(irq); - unsigned int bit = s3c_irq_uart_bit(irq); + void __iomem *regs = s3c_irq_uart_base(data); + unsigned int bit = s3c_irq_uart_bit(data->irq); u32 reg; reg = __raw_readl(regs + S3C64XX_UINTM); @@ -62,10 +62,10 @@ static void s3c_irq_uart_maskack(unsigned int irq) __raw_writel(1 << bit, regs + S3C64XX_UINTP); } -static void s3c_irq_uart_unmask(unsigned int irq) +static void s3c_irq_uart_unmask(struct irq_data *data) { - void __iomem *regs = s3c_irq_uart_base(irq); - unsigned int bit = s3c_irq_uart_bit(irq); + void __iomem *regs = s3c_irq_uart_base(data); + unsigned int bit = s3c_irq_uart_bit(data->irq); u32 reg; reg = __raw_readl(regs + S3C64XX_UINTM); @@ -73,17 +73,17 @@ static void s3c_irq_uart_unmask(unsigned int irq) __raw_writel(reg, regs + S3C64XX_UINTM); } -static void s3c_irq_uart_ack(unsigned int irq) +static void s3c_irq_uart_ack(struct irq_data *data) { - void __iomem *regs = s3c_irq_uart_base(irq); - unsigned int bit = s3c_irq_uart_bit(irq); + void __iomem *regs = s3c_irq_uart_base(data); + unsigned int bit = s3c_irq_uart_bit(data->irq); __raw_writel(1 << bit, regs + S3C64XX_UINTP); } static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) { - struct s3c_uart_irq *uirq = desc->handler_data; + struct s3c_uart_irq *uirq = desc->irq_data.handler_data; u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); int base = uirq->base_irq; @@ -99,10 +99,10 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) static struct irq_chip s3c_irq_uart = { .name = "s3c-uart", - .mask = s3c_irq_uart_mask, - .unmask = s3c_irq_uart_unmask, - .mask_ack = s3c_irq_uart_maskack, - .ack = s3c_irq_uart_ack, + .irq_mask = s3c_irq_uart_mask, + .irq_unmask = s3c_irq_uart_unmask, + .irq_mask_ack = s3c_irq_uart_maskack, + .irq_ack = s3c_irq_uart_ack, }; static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) @@ -124,7 +124,7 @@ static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) set_irq_flags(irq, IRQF_VALID); } - desc->handler_data = uirq; + desc->irq_data.handler_data = uirq; set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); } diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index 0270519fcab..dd8692ae5c4 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -24,43 +24,46 @@ static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) { - generic_handle_irq((int)desc->handler_data); + generic_handle_irq((int)desc->irq_data.handler_data); } /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ -static void s3c_irq_timer_mask(unsigned int irq) +static void s3c_irq_timer_mask(struct irq_data *data) { u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + u32 mask = (u32)data->chip_data; reg &= 0x1f; /* mask out pending interrupts */ - reg &= ~(1 << (irq - IRQ_TIMER0)); + reg &= ~mask; __raw_writel(reg, S3C64XX_TINT_CSTAT); } -static void s3c_irq_timer_unmask(unsigned int irq) +static void s3c_irq_timer_unmask(struct irq_data *data) { u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + u32 mask = (u32)data->chip_data; reg &= 0x1f; /* mask out pending interrupts */ - reg |= 1 << (irq - IRQ_TIMER0); + reg |= mask; __raw_writel(reg, S3C64XX_TINT_CSTAT); } -static void s3c_irq_timer_ack(unsigned int irq) +static void s3c_irq_timer_ack(struct irq_data *data) { u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + u32 mask = (u32)data->chip_data; reg &= 0x1f; - reg |= (1 << 5) << (irq - IRQ_TIMER0); + reg |= mask << 5; __raw_writel(reg, S3C64XX_TINT_CSTAT); } static struct irq_chip s3c_irq_timer = { .name = "s3c-timer", - .mask = s3c_irq_timer_mask, - .unmask = s3c_irq_timer_unmask, - .ack = s3c_irq_timer_ack, + .irq_mask = s3c_irq_timer_mask, + .irq_unmask = s3c_irq_timer_unmask, + .irq_ack = s3c_irq_timer_ack, }; /** @@ -79,8 +82,9 @@ void __init s3c_init_vic_timer_irq(unsigned int parent_irq, set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer); set_irq_chip(timer_irq, &s3c_irq_timer); + set_irq_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0))); set_irq_handler(timer_irq, handle_level_irq); set_irq_flags(timer_irq, IRQF_VALID); - desc->handler_data = (void *)timer_irq; + desc->irq_data.handler_data = (void *)timer_irq; } diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c new file mode 100644 index 00000000000..efe1d564473 --- /dev/null +++ b/arch/arm/plat-samsung/pd.c @@ -0,0 +1,95 @@ +/* linux/arch/arm/plat-samsung/pd.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung Power domain support + * + * 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/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/pm_runtime.h> + +#include <plat/pd.h> + +static int samsung_pd_probe(struct platform_device *pdev) +{ + struct samsung_pd_info *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + + if (!pdata) { + dev_err(dev, "no device data specified\n"); + return -ENOENT; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + dev_info(dev, "power domain registered\n"); + return 0; +} + +static int __devexit samsung_pd_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + pm_runtime_disable(dev); + return 0; +} + +static int samsung_pd_runtime_suspend(struct device *dev) +{ + struct samsung_pd_info *pdata = dev->platform_data; + int ret = 0; + + if (pdata->disable) + ret = pdata->disable(dev); + + dev_dbg(dev, "suspended\n"); + return ret; +} + +static int samsung_pd_runtime_resume(struct device *dev) +{ + struct samsung_pd_info *pdata = dev->platform_data; + int ret = 0; + + if (pdata->enable) + ret = pdata->enable(dev); + + dev_dbg(dev, "resumed\n"); + return ret; +} + +static const struct dev_pm_ops samsung_pd_pm_ops = { + .runtime_suspend = samsung_pd_runtime_suspend, + .runtime_resume = samsung_pd_runtime_resume, +}; + +static struct platform_driver samsung_pd_driver = { + .driver = { + .name = "samsung-pd", + .owner = THIS_MODULE, + .pm = &samsung_pd_pm_ops, + }, + .probe = samsung_pd_probe, + .remove = __devexit_p(samsung_pd_remove), +}; + +static int __init samsung_pd_init(void) +{ + int ret; + + ret = platform_driver_register(&samsung_pd_driver); + if (ret) + printk(KERN_ERR "%s: failed to add PD driver\n", __func__); + + return ret; +} +arch_initcall(samsung_pd_init); diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c index 27cfca59769..eaa57dc969a 100644 --- a/arch/arm/plat-samsung/pm.c +++ b/arch/arm/plat-samsung/pm.c @@ -136,15 +136,15 @@ static void s3c_pm_restore_uarts(void) { } unsigned long s3c_irqwake_intmask = 0xffffffffL; unsigned long s3c_irqwake_eintmask = 0xffffffffL; -int s3c_irqext_wake(unsigned int irqno, unsigned int state) +int s3c_irqext_wake(struct irq_data *data, unsigned int state) { - unsigned long bit = 1L << IRQ_EINT_BIT(irqno); + unsigned long bit = 1L << IRQ_EINT_BIT(data->irq); if (!(s3c_irqwake_eintallow & bit)) return -ENOENT; printk(KERN_INFO "wake %s for irq %d\n", - state ? "enabled" : "disabled", irqno); + state ? "enabled" : "disabled", data->irq); if (!state) s3c_irqwake_eintmask |= bit; |