diff options
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r-- | arch/arm/plat-samsung/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 4 | ||||
-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/devs.h | 15 | ||||
-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/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 |
12 files changed, 226 insertions, 35 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 4ecb15531b9..32be05cf82a 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -339,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/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/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2d82a6cb144..165fa8496c9 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,9 @@ 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; + /* s3c2440 specific devices */ #ifdef CONFIG_CPU_S3C2440 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/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; |