diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /arch/arm/plat-samsung | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2 |
samsung update 1
Diffstat (limited to 'arch/arm/plat-samsung')
72 files changed, 3304 insertions, 511 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 4d79519..8c0b49f 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -15,6 +15,17 @@ config PLAT_SAMSUNG if PLAT_SAMSUNG +# vmalloc area and io map configurations + +comment "Base Address for SFR mapping" + +config S3C_ADDR_BASE + hex "S3C Base Address for SFR mapping" + default 0xF6000000 + help + This value will be base address for S3C SFR mapping and + VMALLC_END should be less or euqal to this value. + # boot configurations comment "Boot options" @@ -149,6 +160,23 @@ config S3C_ADC Core support for the ADC block found in the Samsung SoC systems for drivers such as the touchscreen and hwmon to use to share this resource. +choice + prompt "Select ADC Number" + depends on S3C_ADC + default S3C_DEV_ADC + +config S3C_DEV_ADC + bool "ADC 0 selection" + depends on S3C_ADC + help + Say Y here if you want to use S3C SMDK ADC 0. + +config S3C_DEV_ADC1 + bool "ADC 1 selection" + depends on S3C_ADC + help + Say Y here if you want to use S3C SMDK ADC 1. +endchoice # device definitions to compile in @@ -172,6 +200,11 @@ config S3C_DEV_HSMMC3 help Compile in platform device definitions for HSMMC channel 3 +config EXYNOS4_DEV_MSHC + bool + help + Compile in platform device definitions for MSHC + config S3C_DEV_HWMON bool help @@ -212,6 +245,36 @@ config S3C_DEV_I2C7 help Compile in platform device definition for I2C controller 7 +config S3C_DEV_I2C8_EMUL + depends on CPU_EXYNOS4210 + bool "I2C8 Information GPIO bitbanging emulation" + help + Compile in platform device definitions for I2C channel 8 + +config S3C_DEV_I2C9_EMUL + bool "I2C9 Information GPIO bitbanging emulation" + depends on CPU_EXYNOS4210 + help + Compile in platform device definitions for I2C channel 9 + +config S3C_DEV_I2C11_EMUL + bool "I2C11 Information GPIO bitbanging emulation" + depends on CPU_EXYNOS4210 + help + Compile in platform device definitions for I2C channel 11 + +config S3C_DEV_I2C14_EMUL + bool "I2C14 Information GPIO bitbanging emulation" + depends on CPU_EXYNOS4210 + help + Compile in platform device definitions for I2C channel 14 + +config S3C_DEV_I2C16_EMUL + bool "I2C16 Information GPIO bitbanging emulation" + depends on CPU_EXYNOS4210 + help + Compile in platform device definitions for I2C channel 16 + config S3C_DEV_FB bool help @@ -227,6 +290,12 @@ config S3C_DEV_USB_HSOTG help Compile in platform device definition for USB high-speed OtG +config EXYNOS_DEV_SS_UDC + bool + help + Compile in platform device definition for EXYNOS SuperSpeed USB 3.0 + Device controller + config S3C_DEV_WDT bool default y if ARCH_S3C2410 @@ -260,6 +329,7 @@ config SAMSUNG_DEV_IDE config S3C64XX_DEV_SPI bool + default y if SPI_S3C64XX help Compile in platform device definitions for S3C64XX's type SPI controllers. @@ -267,7 +337,12 @@ config S3C64XX_DEV_SPI config SAMSUNG_DEV_TS bool help - Common in platform device definitions for touchscreen device + Common in platform device definitions for touchscreen device + +config SAMSUNG_DEV_TS1 + bool + help + Common in platform device definitions for touchscreen-1 device config SAMSUNG_DEV_KEYPAD bool @@ -280,6 +355,12 @@ config SAMSUNG_DEV_PWM help Compile in platform device definition for PWM Timer +config SAMSUNG_DEV_BACKLIGHT + bool + depends on SAMSUNG_DEV_PWM + help + Compile in platform device definition LCD backlight with PWM Timer + config S3C24XX_PWM bool "PWM device support" select HAVE_PWM @@ -300,6 +381,12 @@ config S3C_PL330_DMA help S3C DMA API Driver for PL330 DMAC. +config DMA_M2M_TEST + tristate "S3C DMA API Test client" + help + Samsung DMA API test client. Say N unless you're debugging a + DMA Device driver. + comment "Power management" config SAMSUNG_PM_DEBUG diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 53eb15b..ab0fa91 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -11,7 +11,7 @@ obj- := # Objects we always build independent of SoC choice -obj-y += init.o +obj-y += init.o cpu.o obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o obj-y += clock.o obj-y += pwm-clock.o @@ -36,6 +36,7 @@ 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_EXYNOS4_DEV_MSHC) += dev-mshc.o obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o @@ -50,6 +51,7 @@ obj-y += dev-uart.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o obj-$(CONFIG_S3C_DEV_WDT) += dev-wdt.o +obj-$(CONFIG_EXYNOS_DEV_SS_UDC) += dev-usb3-exynos-drd.o obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o obj-$(CONFIG_S3C_DEV_ONENAND) += dev-onenand.o obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o @@ -57,8 +59,10 @@ 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_TS1) += dev-ts1.o obj-$(CONFIG_SAMSUNG_DEV_KEYPAD) += dev-keypad.o -obj-$(CONFIG_SAMSUNG_DEV_PWM) += dev-pwm.o +obj-$(CONFIG_HAVE_PWM) += dev-pwm.o +obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o # DMA support @@ -66,6 +70,8 @@ obj-$(CONFIG_S3C_DMA) += dma.o obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o +obj-$(CONFIG_DMA_M2M_TEST) += dma_m2m_test.o + # PM support obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index e8f2be2..389e7e0 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -39,24 +39,28 @@ */ enum s3c_cpu_type { - TYPE_S3C24XX, - TYPE_S3C64XX + TYPE_ADCV1, /* S3C24XX */ + TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */ + TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */ + TYPE_ADCV4, /* EXYNOS4412, EXYNOS5250 */ }; struct s3c_adc_client { struct platform_device *pdev; - struct list_head pend; + struct list_head pend; wait_queue_head_t *wait; - unsigned int nr_samples; - int result; - unsigned char is_ts; - unsigned char channel; + unsigned int nr_samples; + int result; + unsigned char is_ts; + unsigned char channel; void (*select_cb)(struct s3c_adc_client *c, unsigned selected); void (*convert_cb)(struct s3c_adc_client *c, unsigned val1, unsigned val2, unsigned *samples_left); + atomic_t running; + int error_count; }; struct adc_device { @@ -91,30 +95,37 @@ static inline void s3c_adc_select(struct adc_device *adc, struct s3c_adc_client *client) { unsigned con = readl(adc->regs + S3C2410_ADCCON); + enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data; client->select_cb(client, 1); con &= ~S3C2410_ADCCON_MUXMASK; con &= ~S3C2410_ADCCON_STDBM; con &= ~S3C2410_ADCCON_STARTMASK; - - if (!client->is_ts) - con |= S3C2410_ADCCON_SELMUX(client->channel); + con |= S3C2410_ADCCON_PRSCEN; + + if (!client->is_ts) { + if (cpu >= TYPE_ADCV3) + writel(S5PV210_ADCCON_SELMUX(client->channel), + adc->regs + S5P_ADCMUX); + else + con |= S3C2410_ADCCON_SELMUX(client->channel); + } writel(con, adc->regs + S3C2410_ADCCON); } static void s3c_adc_dbgshow(struct adc_device *adc) { - adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n", + adc_dbg(adc, "CON=%08x, DLY=%08x\n", readl(adc->regs + S3C2410_ADCCON), - readl(adc->regs + S3C2410_ADCTSC), readl(adc->regs + S3C2410_ADCDLY)); } static void s3c_adc_try(struct adc_device *adc) { struct s3c_adc_client *next = adc->ts_pend; + unsigned int con = readl(adc->regs + S3C2410_ADCCON); if (!next && !list_empty(&adc_pending)) { next = list_first_entry(&adc_pending, @@ -129,25 +140,43 @@ static void s3c_adc_try(struct adc_device *adc) s3c_adc_select(adc, next); s3c_adc_convert(adc); s3c_adc_dbgshow(adc); + } else { + con &= ~S3C2410_ADCCON_PRSCEN; + con |= S3C2410_ADCCON_STDBM; + writel(con, adc->regs + S3C2410_ADCCON); } } +static void s3c_convert_done(struct s3c_adc_client *client, + unsigned v, unsigned u, unsigned *left) +{ + client->result = v; + wake_up(client->wait); +} + int s3c_adc_start(struct s3c_adc_client *client, - unsigned int channel, unsigned int nr_samples) + unsigned int channel, unsigned int nr_samples, + wait_queue_head_t *pwake) { struct adc_device *adc = adc_dev; unsigned long flags; - if (!adc) { - printk(KERN_ERR "%s: failed to find adc\n", __func__); - return -EINVAL; - } + BUG_ON(!adc); if (client->is_ts && adc->ts_pend) return -EAGAIN; + if (atomic_xchg(&client->running, 1)) { + WARN(1, "%s: %p is already running\n", __func__, client); + return -EAGAIN; + } + spin_lock_irqsave(&adc->lock, flags); + client->convert_cb = s3c_convert_done; + client->wait = pwake; + client->result = -1; + client->channel = channel; client->nr_samples = nr_samples; @@ -165,30 +194,68 @@ int s3c_adc_start(struct s3c_adc_client *client, } EXPORT_SYMBOL_GPL(s3c_adc_start); -static void s3c_convert_done(struct s3c_adc_client *client, - unsigned v, unsigned u, unsigned *left) +static void s3c_adc_stop(struct s3c_adc_client *client) { - client->result = v; - wake_up(client->wait); + unsigned long flags; + + spin_lock_irqsave(&adc_dev->lock, flags); + + /* We should really check that nothing is in progress. */ + if (adc_dev->cur == client) + adc_dev->cur = NULL; + if (adc_dev->ts_pend == client) + adc_dev->ts_pend = NULL; + else { + struct list_head *p, *n; + struct s3c_adc_client *tmp; + + list_for_each_safe(p, n, &adc_pending) { + tmp = list_entry(p, struct s3c_adc_client, pend); + if (tmp == client) + list_del(&tmp->pend); + } + } + + if (!atomic_xchg(&client->running, 0)) + WARN(1, "%s: %p is already stopped\n", __func__, client); + + if (adc_dev->cur == NULL) + s3c_adc_try(adc_dev); + + spin_unlock_irqrestore(&adc_dev->lock, flags); } int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + struct adc_device *adc = adc_dev; + unsigned long flags; int ret; - client->convert_cb = s3c_convert_done; - client->wait = &wake; - client->result = -1; - - ret = s3c_adc_start(client, ch, 1); + ret = s3c_adc_start(client, ch, 1, &wake); if (ret < 0) goto err; ret = wait_event_timeout(wake, client->result >= 0, HZ / 2); if (client->result < 0) { + s3c_adc_stop(client); + dev_warn(&adc_dev->pdev->dev, "%s: %p is timed out\n", + __func__, client); + ++client->error_count; + BUG_ON(client->error_count > 10); ret = -ETIMEDOUT; goto err; + } else { + client->error_count = 0; + + spin_lock_irqsave(&adc->lock, flags); + /* client->result >=0 means s3c_adc_irq -> + s3c_convert_done is running or finished. Make sure + it is *finished* (not running) by lock/unlocking + spin lock. Otherwise, after return of this + function, wake_up() on destroyed 'wake' may be + executed which will destroy stack */ + spin_unlock_irqrestore(&adc->lock, flags); } client->convert_cb = NULL; @@ -239,30 +306,7 @@ EXPORT_SYMBOL_GPL(s3c_adc_register); void s3c_adc_release(struct s3c_adc_client *client) { - unsigned long flags; - - spin_lock_irqsave(&adc_dev->lock, flags); - - /* We should really check that nothing is in progress. */ - if (adc_dev->cur == client) - adc_dev->cur = NULL; - if (adc_dev->ts_pend == client) - adc_dev->ts_pend = NULL; - else { - struct list_head *p, *n; - struct s3c_adc_client *tmp; - - list_for_each_safe(p, n, &adc_pending) { - tmp = list_entry(p, struct s3c_adc_client, pend); - if (tmp == client) - list_del(&tmp->pend); - } - } - - if (adc_dev->cur == NULL) - s3c_adc_try(adc_dev); - - spin_unlock_irqrestore(&adc_dev->lock, flags); + s3c_adc_stop(client); kfree(client); } EXPORT_SYMBOL_GPL(s3c_adc_release); @@ -272,50 +316,60 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw) struct adc_device *adc = pw; struct s3c_adc_client *client = adc->cur; enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data; - unsigned data0, data1; + unsigned data0 = 0, data1 = 0; - if (!client) { + spin_lock(&adc->lock); + + if (!client || !client->nr_samples) { dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__); goto exit; } data0 = readl(adc->regs + S3C2410_ADCDAT0); - data1 = readl(adc->regs + S3C2410_ADCDAT1); + if (cpu != TYPE_ADCV4) + data1 = readl(adc->regs + S3C2410_ADCDAT1); + adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); - client->nr_samples--; + if (client->nr_samples > 0) + client->nr_samples--; - if (cpu == TYPE_S3C64XX) { - /* S3C64XX ADC resolution is 12-bit */ - data0 &= 0xfff; - data1 &= 0xfff; - } else { + if (cpu == TYPE_ADCV1) { data0 &= 0x3ff; data1 &= 0x3ff; + } else { + /* S3C64XX/S5P ADC resolution is 12-bit */ + data0 &= 0xfff; + data1 &= 0xfff; } if (client->convert_cb) (client->convert_cb)(client, data0, data1, &client->nr_samples); if (client->nr_samples > 0) { - /* fire another conversion for this */ - - client->select_cb(client, 1); + /* fire another conversion for this client */ + (client->select_cb)(client, 1); s3c_adc_convert(adc); } else { - spin_lock(&adc->lock); + /* finish conversion for this client */ (client->select_cb)(client, 0); - adc->cur = NULL; + if (!atomic_xchg(&client->running, 0)) + WARN(1, "%s: %p is already stopped\n", __func__, + client); + /* fire conversion for next client if any */ + adc->cur = NULL; s3c_adc_try(adc); - spin_unlock(&adc->lock); } exit: - if (cpu == TYPE_S3C64XX) { + if (cpu != TYPE_ADCV1) { /* Clear ADC interrupt */ writel(0, adc->regs + S3C64XX_ADCCLRINT); } + + spin_unlock(&adc->lock); + return IRQ_HANDLED; } @@ -324,11 +378,12 @@ static int s3c_adc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct adc_device *adc; struct resource *regs; + enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data; int ret; unsigned tmp; adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL); - if (adc == NULL) { + if (unlikely(adc == NULL)) { dev_err(dev, "failed to allocate adc_device\n"); return -ENOMEM; } @@ -338,35 +393,22 @@ static int s3c_adc_probe(struct platform_device *pdev) adc->pdev = pdev; adc->prescale = S3C2410_ADCCON_PRSCVL(49); - adc->irq = platform_get_irq(pdev, 1); - if (adc->irq <= 0) { - dev_err(dev, "failed to get adc irq\n"); - ret = -ENOENT; - goto err_alloc; - } - - ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); - if (ret < 0) { - dev_err(dev, "failed to attach adc irq\n"); - goto err_alloc; - } - - adc->clk = clk_get(dev, "adc"); - if (IS_ERR(adc->clk)) { + adc->clk = clk_get(NULL, "adc"); + if (unlikely(IS_ERR(adc->clk))) { dev_err(dev, "failed to get adc clock\n"); ret = PTR_ERR(adc->clk); - goto err_irq; + goto err_alloc; } regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { + if (unlikely(!regs)) { dev_err(dev, "failed to find registers\n"); ret = -ENXIO; goto err_clk; } adc->regs = ioremap(regs->start, resource_size(regs)); - if (!adc->regs) { + if (unlikely(!adc->regs)) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_clk; @@ -374,13 +416,35 @@ static int s3c_adc_probe(struct platform_device *pdev) clk_enable(adc->clk); +#if defined(CONFIG_S3C_DEV_ADC1) + tmp = readl(adc->regs + S3C2410_ADCCON); + tmp |= S3C64XX_ADCCON_TSSEL; + writel(tmp, adc->regs + S3C2410_ADCCON); + adc->regs += 0x1000; +#endif + tmp = adc->prescale | S3C2410_ADCCON_PRSCEN; - if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) { - /* Enable 12-bit ADC resolution */ + + /* Enable 12-bit ADC resolution */ + if (cpu != TYPE_ADCV1) { tmp |= S3C64XX_ADCCON_RESSEL; } + tmp |= S3C2410_ADCCON_STDBM; writel(tmp, adc->regs + S3C2410_ADCCON); + adc->irq = platform_get_irq(pdev, 1); + if (unlikely(adc->irq <= 0)) { + dev_err(dev, "failed to get adc irq\n"); + ret = -ENOENT; + goto err_clk; + } + + ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); + if (unlikely(ret < 0)) { + dev_err(dev, "failed to attach adc irq\n"); + goto err_clk; + } + dev_info(dev, "attached adc driver\n"); platform_set_drvdata(pdev, adc); @@ -391,9 +455,6 @@ static int s3c_adc_probe(struct platform_device *pdev) err_clk: clk_put(adc->clk); - err_irq: - free_irq(adc->irq, adc); - err_alloc: kfree(adc); return ret; @@ -435,12 +496,24 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) static int s3c_adc_resume(struct platform_device *pdev) { struct adc_device *adc = platform_get_drvdata(pdev); + enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data; + unsigned int tmp = 0; clk_enable(adc->clk); enable_irq(adc->irq); - writel(adc->prescale | S3C2410_ADCCON_PRSCEN, - adc->regs + S3C2410_ADCCON); +#if defined(CONFIG_S3C_DEV_ADC1) + adc->regs -= 0x1000; + tmp = readl(adc->regs + S3C2410_ADCCON); + tmp |= S3C64XX_ADCCON_TSSEL; + writel(tmp, adc->regs + S3C2410_ADCCON); + adc->regs += 0x1000; +#endif + tmp = adc->prescale | S3C2410_ADCCON_PRSCEN; + /* Enable 12-bit ADC resolution */ + if (cpu != TYPE_ADCV1) + tmp |= S3C64XX_ADCCON_RESSEL; + writel(tmp, adc->regs + S3C2410_ADCCON); return 0; } @@ -452,11 +525,17 @@ static int s3c_adc_resume(struct platform_device *pdev) static struct platform_device_id s3c_adc_driver_ids[] = { { - .name = "s3c24xx-adc", - .driver_data = TYPE_S3C24XX, + .name = "s3c24xx-adc", + .driver_data = TYPE_ADCV1, + }, { + .name = "s3c64xx-adc", + .driver_data = TYPE_ADCV2, + }, { + .name = "samsung-adc-v3", + .driver_data = TYPE_ADCV3, }, { - .name = "s3c64xx-adc", - .driver_data = TYPE_S3C64XX, + .name = "samsung-adc-v4", + .driver_data = TYPE_ADCV4, }, { } }; diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 7728928..40454d7 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -27,7 +27,6 @@ */ #include <linux/init.h> -#include <linux/module.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/errno.h> @@ -64,108 +63,55 @@ static LIST_HEAD(clocks); */ DEFINE_SPINLOCK(clocks_lock); -/* enable and disable calls for use with the clk struct */ - -static int clk_null_enable(struct clk *clk, int enable) -{ - return 0; -} - -static int dev_is_s3c_uart(struct device *dev) +/* Global watchdog clock used by arch_wtd_reset() callback */ +struct clk *s3c2410_wdtclk; +static int __init s3c_wdt_reset_init(void) { - struct platform_device **pdev = s3c24xx_uart_devs; - int i; - for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++) - if (*pdev && dev == &(*pdev)->dev) - return 1; + s3c2410_wdtclk = clk_get(NULL, "watchdog"); + if (IS_ERR(s3c2410_wdtclk)) + printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__); return 0; } +arch_initcall(s3c_wdt_reset_init); -/* - * Serial drivers call get_clock() very early, before platform bus - * has been set up, this requires a special check to let them get - * a proper clock - */ - -static int dev_is_platform_device(struct device *dev) -{ - return dev->bus == &platform_bus_type || - (dev->bus == NULL && dev_is_s3c_uart(dev)); -} - -/* Clock API calls */ - -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p; - struct clk *clk = ERR_PTR(-ENOENT); - int idno; - - if (dev == NULL || !dev_is_platform_device(dev)) - idno = -1; - else - idno = to_platform_device(dev)->id; - - spin_lock(&clocks_lock); - - list_for_each_entry(p, &clocks, list) { - if (p->id == idno && - strcmp(id, p->name) == 0 && - try_module_get(p->owner)) { - clk = p; - break; - } - } - - /* check for the case where a device was supplied, but the - * clock that was being searched for is not device specific */ - - if (IS_ERR(clk)) { - list_for_each_entry(p, &clocks, list) { - if (p->id == -1 && strcmp(id, p->name) == 0 && - try_module_get(p->owner)) { - clk = p; - break; - } - } - } - - spin_unlock(&clocks_lock); - return clk; -} +/* enable and disable calls for use with the clk struct */ -void clk_put(struct clk *clk) +static int clk_null_enable(struct clk *clk, int enable) { - module_put(clk->owner); + return 0; } int clk_enable(struct clk *clk) { + unsigned long flags; + if (IS_ERR(clk) || clk == NULL) return -EINVAL; clk_enable(clk->parent); - spin_lock(&clocks_lock); + spin_lock_irqsave(&clocks_lock, flags); if ((clk->usage++) == 0) (clk->enable)(clk, 1); - spin_unlock(&clocks_lock); + spin_unlock_irqrestore(&clocks_lock, flags); return 0; } void clk_disable(struct clk *clk) { + unsigned long flags; + if (IS_ERR(clk) || clk == NULL) return; - spin_lock(&clocks_lock); + spin_lock_irqsave(&clocks_lock, flags); if ((--clk->usage) == 0) (clk->enable)(clk, 0); - spin_unlock(&clocks_lock); + spin_unlock_irqrestore(&clocks_lock, flags); clk_disable(clk->parent); } @@ -197,6 +143,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) int clk_set_rate(struct clk *clk, unsigned long rate) { + unsigned long flags; int ret; if (IS_ERR(clk)) @@ -212,9 +159,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->ops == NULL || clk->ops->set_rate == NULL) return -EINVAL; - spin_lock(&clocks_lock); + spin_lock_irqsave(&clocks_lock, flags); ret = (clk->ops->set_rate)(clk, rate); - spin_unlock(&clocks_lock); + spin_unlock_irqrestore(&clocks_lock, flags); return ret; } @@ -226,23 +173,22 @@ struct clk *clk_get_parent(struct clk *clk) int clk_set_parent(struct clk *clk, struct clk *parent) { + unsigned long flags; int ret = 0; if (IS_ERR(clk)) return -EINVAL; - spin_lock(&clocks_lock); + spin_lock_irqsave(&clocks_lock, flags); if (clk->ops && clk->ops->set_parent) ret = (clk->ops->set_parent)(clk, parent); - spin_unlock(&clocks_lock); + spin_unlock_irqrestore(&clocks_lock, flags); return ret; } -EXPORT_SYMBOL(clk_get); -EXPORT_SYMBOL(clk_put); EXPORT_SYMBOL(clk_enable); EXPORT_SYMBOL(clk_disable); EXPORT_SYMBOL(clk_get_rate); @@ -343,17 +289,20 @@ struct clk s3c24xx_uclk = { */ int s3c24xx_register_clock(struct clk *clk) { + unsigned long flags; + if (clk->enable == NULL) clk->enable = clk_null_enable; - /* add to the list of available clocks */ + /* fill up the clk_lookup structure and register it*/ + clk->lookup.dev_id = clk->devname; + clk->lookup.con_id = clk->name; + clk->lookup.clk = clk; + clkdev_add(&clk->lookup); - /* Quick check to see if this clock has already been registered. */ - BUG_ON(clk->list.prev != clk->list.next); - - spin_lock(&clocks_lock); - list_add(&clk->list, &clocks); - spin_unlock(&clocks_lock); + spin_lock_irqsave(&clocks_lock, flags); + list_add_tail(&clk->list, &clocks); + spin_unlock_irqrestore(&clocks_lock, flags); return 0; } @@ -458,15 +407,12 @@ static struct dentry *clk_debugfs_root; static int clk_debugfs_register_one(struct clk *c) { int err; - struct dentry *d, *child, *child_tmp; + struct dentry *d; 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); + p += sprintf(p, "%s", c->devname ?: c->name); d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); if (!d) @@ -488,10 +434,7 @@ static int clk_debugfs_register_one(struct clk *c) 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); + debugfs_remove_recursive(c->dent); return err; } diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c new file mode 100644 index 0000000..81c06d4 --- /dev/null +++ b/arch/arm/plat-samsung/cpu.c @@ -0,0 +1,58 @@ +/* linux/arch/arm/plat-samsung/cpu.c + * + * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung CPU 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/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <asm/system.h> + +#include <mach/map.h> +#include <plat/cpu.h> + +unsigned long samsung_cpu_id; +static unsigned int samsung_cpu_rev; + +unsigned int samsung_rev(void) +{ + return samsung_cpu_rev; +} +EXPORT_SYMBOL(samsung_rev); + +void __init s3c24xx_init_cpu(void) +{ + /* nothing here yet */ + + samsung_cpu_rev = 0; +} + +void __init s3c64xx_init_cpu(void) +{ + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118); + if (!samsung_cpu_id) { + /* + * S3C6400 has the ID register in a different place, + * and needs a write before it can be read. + */ + __raw_writel(0x0, S3C_VA_SYS + 0xA1C); + samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C); + } + + samsung_cpu_rev = 0; +} + +void __init s5p_init_cpu(void __iomem *cpuid_addr) +{ + samsung_cpu_id = __raw_readl(cpuid_addr); + samsung_cpu_rev = samsung_cpu_id & 0xFF; +} diff --git a/arch/arm/plat-samsung/dev-adc.c b/arch/arm/plat-samsung/dev-adc.c index 9d903d4..d9d0357 100644 --- a/arch/arm/plat-samsung/dev-adc.c +++ b/arch/arm/plat-samsung/dev-adc.c @@ -23,12 +23,14 @@ static struct resource s3c_adc_resource[] = { [0] = { .start = SAMSUNG_PA_ADC, - .end = SAMSUNG_PA_ADC + SZ_256 - 1, + .end = SAMSUNG_PA_ADC + SZ_8K - 1, .flags = IORESOURCE_MEM, }, [1] = { +#if defined(CONFIG_TOUCHSCREEN_S3C2410) .start = IRQ_TC, .end = IRQ_TC, +#endif .flags = IORESOURCE_IRQ, }, [2] = { diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c index a068c4f..aabee5e 100644 --- a/arch/arm/plat-samsung/dev-asocdma.c +++ b/arch/arm/plat-samsung/dev-asocdma.c @@ -23,3 +23,17 @@ struct platform_device samsung_asoc_dma = { } }; EXPORT_SYMBOL(samsung_asoc_dma); + +#ifndef CONFIG_SND_SOC_SAMSUNG_USE_DMA_WRAPPER +static u64 audio_idmamask = DMA_BIT_MASK(32); + +struct platform_device samsung_asoc_idma = { + .name = "samsung-audio-idma", + .id = -1, + .dev = { + .dma_mask = &audio_idmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; +EXPORT_SYMBOL(samsung_asoc_idma); +#endif
\ No newline at end of file diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c new file mode 100644 index 0000000..8ebb41c --- /dev/null +++ b/arch/arm/plat-samsung/dev-backlight.c @@ -0,0 +1,149 @@ +/* linux/arch/arm/plat-samsung/dev-backlight.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common infrastructure for PWM Backlight for Samsung boards + * + * 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 <linux/platform_device.h> +#include <linux/io.h> +#include <linux/pwm_backlight.h> + +#include <plat/devs.h> +#include <plat/gpio-cfg.h> +#include <plat/backlight.h> + +static int samsung_bl_init(struct device *dev) +{ + int ret = 0; + struct platform_device *timer_dev = + container_of(dev->parent, struct platform_device, dev); + struct samsung_bl_gpio_info *bl_gpio_info = + timer_dev->dev.platform_data; + + ret = gpio_request(bl_gpio_info->no, "Backlight"); + if (ret) { + printk(KERN_ERR "failed to request GPIO for LCD Backlight\n"); + return ret; + } + + /* Configure GPIO pin with specific GPIO function for PWM timer */ + s3c_gpio_cfgpin(bl_gpio_info->no, bl_gpio_info->func); + + return 0; +} + +static void samsung_bl_exit(struct device *dev) +{ + struct platform_device *timer_dev = + container_of(dev->parent, struct platform_device, dev); + struct samsung_bl_gpio_info *bl_gpio_info = + timer_dev->dev.platform_data; + + s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT); + gpio_free(bl_gpio_info->no); +} + +/* Initialize few important fields of platform_pwm_backlight_data + * structure with default values. These fields can be overridden by + * board-specific values sent from machine file. + * For ease of operation, these fields are initialized with values + * used by most samsung boards. + * Users has the option of sending info about other parameters + * for their specific boards + */ + +static struct platform_pwm_backlight_data samsung_dfl_bl_data = { + .max_brightness = 255, + .dft_brightness = 255, + .pwm_period_ns = 78770, + .init = samsung_bl_init, + .exit = samsung_bl_exit, +}; + +static struct platform_device samsung_dfl_bl_device = { + .name = "pwm-backlight", +}; + +/* samsung_bl_set - Set board specific data (if any) provided by user for + * PWM Backlight control and register specific PWM and backlight device. + * @gpio_info: structure containing GPIO info for PWM timer + * @bl_data: structure containing Backlight control data + */ +void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, + struct platform_pwm_backlight_data *bl_data) +{ + int ret = 0; + struct platform_device *samsung_bl_device; + struct platform_pwm_backlight_data *samsung_bl_data; + + samsung_bl_device = kmemdup(&samsung_dfl_bl_device, + sizeof(struct platform_device), GFP_KERNEL); + if (!samsung_bl_device) { + printk(KERN_ERR "%s: no memory for platform dev\n", __func__); + return; + } + + samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data, + sizeof(struct platform_pwm_backlight_data), samsung_bl_device); + if (!samsung_bl_data) { + printk(KERN_ERR "%s: no memory for platform dev\n", __func__); + goto err_data; + } + + /* Copy board specific data provided by user */ + samsung_bl_data->pwm_id = bl_data->pwm_id; + samsung_bl_device->dev.parent = + &s3c_device_timer[samsung_bl_data->pwm_id].dev; + + if (bl_data->max_brightness) + samsung_bl_data->max_brightness = bl_data->max_brightness; + if (bl_data->dft_brightness) + samsung_bl_data->dft_brightness = bl_data->dft_brightness; + if (bl_data->lth_brightness) + samsung_bl_data->lth_brightness = bl_data->lth_brightness; + if (bl_data->pwm_period_ns) + samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns; + if (bl_data->init) + samsung_bl_data->init = bl_data->init; + if (bl_data->notify) + samsung_bl_data->notify = bl_data->notify; + if (bl_data->exit) + samsung_bl_data->exit = bl_data->exit; + if (bl_data->check_fb) + samsung_bl_data->check_fb = bl_data->check_fb; + + /* Keep the GPIO info for future use */ + s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info; + + /* Register the specific PWM timer dev for Backlight control */ + ret = platform_device_register( + &s3c_device_timer[samsung_bl_data->pwm_id]); + if (ret) { + printk(KERN_ERR "failed to register pwm timer for backlight: %d\n", ret); + goto err_plat_reg1; + } + + /* Register the Backlight dev */ + ret = platform_device_register(samsung_bl_device); + if (ret) { + printk(KERN_ERR "failed to register backlight device: %d\n", ret); + goto err_plat_reg2; + } + + return; + +err_plat_reg2: + platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]); +err_plat_reg1: + kfree(samsung_bl_data); +err_data: + kfree(samsung_bl_device); + return; +} diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c index bf60204..49a1362 100644 --- a/arch/arm/plat-samsung/dev-fb.c +++ b/arch/arm/plat-samsung/dev-fb.c @@ -58,16 +58,6 @@ struct platform_device s3c_device_fb = { void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd) { - struct s3c_fb_platdata *npd; - - if (!pd) { - printk(KERN_ERR "%s: no platform data\n", __func__); - return; - } - - npd = kmemdup(pd, sizeof(struct s3c_fb_platdata), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - - s3c_device_fb.dev.platform_data = npd; + s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata), + &s3c_device_fb); } diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c index db7a65c..e5ee2df 100644 --- a/arch/arm/plat-samsung/dev-hsmmc.c +++ b/arch/arm/plat-samsung/dev-hsmmc.c @@ -65,7 +65,10 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) 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; + set->pm_flags = pd->pm_flags; + if (pd->vmmc_name) + set->vmmc_name = pd->vmmc_name; if (pd->max_width) set->max_width = pd->max_width; if (pd->cfg_gpio) diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c index 2497321..40160c6 100644 --- a/arch/arm/plat-samsung/dev-hsmmc1.c +++ b/arch/arm/plat-samsung/dev-hsmmc1.c @@ -65,6 +65,7 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) 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; + set->pm_flags = pd->pm_flags; if (pd->max_width) set->max_width = pd->max_width; diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c index f60aedb..27bd631 100644 --- a/arch/arm/plat-samsung/dev-hsmmc2.c +++ b/arch/arm/plat-samsung/dev-hsmmc2.c @@ -20,6 +20,7 @@ #include <mach/map.h> #include <plat/sdhci.h> #include <plat/devs.h> +#include <plat/gpio-cfg.h> #define S3C_SZ_HSMMC (0x1000) @@ -65,8 +66,15 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) set->ext_cd_init = pd->ext_cd_init; set->ext_cd_cleanup = pd->ext_cd_cleanup; set->ext_cd_gpio = pd->ext_cd_gpio; + /* if it uses eint as cd pin, pull up/down value of eint port + should be NONE */ + if (pd->ext_cd_gpio) + s3c_gpio_setpull(pd->ext_cd_gpio, S3C_GPIO_PULL_NONE); set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; + set->pm_flags = pd->pm_flags; + if (pd->vmmc_name) + set->vmmc_name = pd->vmmc_name; if (pd->max_width) set->max_width = pd->max_width; if (pd->cfg_gpio) diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c index ede776f..1973ef4 100644 --- a/arch/arm/plat-samsung/dev-hsmmc3.c +++ b/arch/arm/plat-samsung/dev-hsmmc3.c @@ -69,6 +69,13 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd) 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; + set->pm_flags = pd->pm_flags; + + if (pd->vmmc_name) + set->vmmc_name = pd->vmmc_name; +#ifdef CONFIG_MACH_PX + set->ext_pdev = pd->ext_pdev; +#endif if (pd->max_width) set->max_width = pd->max_width; diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c index b3ffb95..c91a79c 100644 --- a/arch/arm/plat-samsung/dev-hwmon.c +++ b/arch/arm/plat-samsung/dev-hwmon.c @@ -27,16 +27,6 @@ struct platform_device s3c_device_hwmon = { void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd) { - struct s3c_hwmon_pdata *npd; - - if (!pd) { - printk(KERN_ERR "%s: no platform data\n", __func__); - return; - } - - npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - - s3c_device_hwmon.dev.platform_data = npd; + s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata), + &s3c_device_hwmon); } diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c index 3a601c1..1edd343 100644 --- a/arch/arm/plat-samsung/dev-i2c0.c +++ b/arch/arm/plat-samsung/dev-i2c0.c @@ -48,10 +48,10 @@ struct platform_device s3c_device_i2c0 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { +struct s3c2410_platform_i2c default_i2c_data __initdata = { .flags = 0, .slave_addr = 0x10, - .frequency = 100*1000, + .frequency = 400*1000, .sda_delay = 100, }; @@ -60,13 +60,11 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) struct s3c2410_platform_i2c *npd; if (!pd) - pd = &default_i2c_data0; + pd = &default_i2c_data; - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c0_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c0); - s3c_device_i2c0.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c0_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c index 858ee2a..3b7c7be 100644 --- a/arch/arm/plat-samsung/dev-i2c1.c +++ b/arch/arm/plat-samsung/dev-i2c1.c @@ -44,26 +44,18 @@ struct platform_device s3c_device_i2c1 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data1 __initdata = { - .flags = 0, - .bus_num = 1, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data1; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 1; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c1_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c1); - s3c_device_i2c1.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c1_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c index ff4ba69..07e9fd0 100644 --- a/arch/arm/plat-samsung/dev-i2c2.c +++ b/arch/arm/plat-samsung/dev-i2c2.c @@ -45,26 +45,18 @@ struct platform_device s3c_device_i2c2 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data2 __initdata = { - .flags = 0, - .bus_num = 2, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data2; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 2; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c2_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c2); - s3c_device_i2c2.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c2_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c index 8586a10..d48efa9 100644 --- a/arch/arm/plat-samsung/dev-i2c3.c +++ b/arch/arm/plat-samsung/dev-i2c3.c @@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c3 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data3 __initdata = { - .flags = 0, - .bus_num = 3, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data3; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 3; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c3_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c3); - s3c_device_i2c3.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c3_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c index df2159e..07e2644 100644 --- a/arch/arm/plat-samsung/dev-i2c4.c +++ b/arch/arm/plat-samsung/dev-i2c4.c @@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c4 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data4 __initdata = { - .flags = 0, - .bus_num = 4, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data4; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 4; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c4_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c4); - s3c_device_i2c4.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c4_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c index 0499c2c..f496557 100644 --- a/arch/arm/plat-samsung/dev-i2c5.c +++ b/arch/arm/plat-samsung/dev-i2c5.c @@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c5 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data5 __initdata = { - .flags = 0, - .bus_num = 5, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data5; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 5; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c5_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c5); - s3c_device_i2c5.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c5_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c index 4083108..141d799 100644 --- a/arch/arm/plat-samsung/dev-i2c6.c +++ b/arch/arm/plat-samsung/dev-i2c6.c @@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c6 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data6 __initdata = { - .flags = 0, - .bus_num = 6, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data6; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 6; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c6_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c6); - s3c_device_i2c6.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c6_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c index 1182451..9dddcd1 100644 --- a/arch/arm/plat-samsung/dev-i2c7.c +++ b/arch/arm/plat-samsung/dev-i2c7.c @@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c7 = { .resource = s3c_i2c_resource, }; -static struct s3c2410_platform_i2c default_i2c_data7 __initdata = { - .flags = 0, - .bus_num = 7, - .slave_addr = 0x10, - .frequency = 100*1000, - .sda_delay = 100, -}; - void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; - if (!pd) - pd = &default_i2c_data7; + if (!pd) { + pd = &default_i2c_data; + pd->bus_num = 7; + } - npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - else if (!npd->cfg_gpio) - npd->cfg_gpio = s3c_i2c7_cfg_gpio; + npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), + &s3c_device_i2c7); - s3c_device_i2c7.dev.platform_data = npd; + if (!npd->cfg_gpio) + npd->cfg_gpio = s3c_i2c7_cfg_gpio; } diff --git a/arch/arm/plat-samsung/dev-mshc.c b/arch/arm/plat-samsung/dev-mshc.c new file mode 100644 index 0000000..ca2cbf8 --- /dev/null +++ b/arch/arm/plat-samsung/dev-mshc.c @@ -0,0 +1,101 @@ +/* linux/arch/arm/plat-samsung/dev-mshc.c + * + * 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 + * + * Device definition for mshc devices + * + * 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/mshci.h> +#include <plat/devs.h> +#include <plat/cpu.h> +#include <plat/exynos4.h> + +#define S5P_SZ_MSHC (0x1000) + +static struct resource s3c_mshci_resource[] = { + [0] = { + .start = EXYNOS_PA_DWMCI, + .end = EXYNOS_PA_DWMCI + S5P_SZ_MSHC - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_DWMCI, + .end = IRQ_DWMCI, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL; + +struct s3c_mshci_platdata s3c_mshci_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_mshci = { + .name = "dw_mmc", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_mshci_resource), + .resource = s3c_mshci_resource, + .dev = { + .dma_mask = &s3c_device_hsmmc_dmamask, + .coherent_dma_mask = 0xffffffffUL, + .platform_data = &s3c_mshci_def_platdata, + }, +}; + + +void s3c_mshci_set_platdata(struct s3c_mshci_platdata *pd) +{ + struct s3c_mshci_platdata *set = &s3c_mshci_def_platdata; + + 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; + set->wp_gpio = pd->wp_gpio; + set->has_wp_gpio = pd->has_wp_gpio; + set->int_power_gpio = pd->int_power_gpio; + if(pd->fifo_depth) + set->fifo_depth = pd->fifo_depth; + else + set->fifo_depth = 0x20; /* exynos4210 size. */ + + if (pd->max_width) + set->max_width = pd->max_width; + if (pd->host_caps) + set->host_caps |= pd->host_caps; + if (pd->host_caps2) + set->host_caps2 |= pd->host_caps2; + if (soc_is_exynos4210()) { + if (pd->host_caps && samsung_rev() < EXYNOS4210_REV_1_1) { + printk(KERN_INFO "MSHC: This exynos4 is EVT1.0. " + "Disable DDR R/W for eMMC.\n"); + set->host_caps &= ~(MMC_CAP_1_8V_DDR | + MMC_CAP_UHS_DDR50); + } + } + if (pd->cfg_gpio) + set->cfg_gpio = pd->cfg_gpio; + if (pd->cfg_card) + set->cfg_card = pd->cfg_card; + if (pd->cfg_ddr) + set->cfg_ddr = pd->cfg_ddr; + if (pd->init_card) + set->init_card = pd->init_card; +} diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c index 6927ae8..b8e30ec 100644 --- a/arch/arm/plat-samsung/dev-nand.c +++ b/arch/arm/plat-samsung/dev-nand.c @@ -91,11 +91,10 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand) * time then there is little chance the system is going to run. */ - npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL); - if (!npd) { - printk(KERN_ERR "%s: failed copying platform data\n", __func__); + npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand), + &s3c_device_nand); + if (!npd) return; - } /* now see if we need to copy any of the nand set data */ @@ -123,6 +122,4 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand) to++; } } - - s3c_device_nand.dev.platform_data = npd; } diff --git a/arch/arm/plat-samsung/dev-pwm.c b/arch/arm/plat-samsung/dev-pwm.c index dab47b0..cda8e47 100644 --- a/arch/arm/plat-samsung/dev-pwm.c +++ b/arch/arm/plat-samsung/dev-pwm.c @@ -20,6 +20,7 @@ #include <mach/irqs.h> #include <plat/devs.h> +#include <mach/gpio.h> #define TIMER_RESOURCE_SIZE (1) @@ -32,22 +33,88 @@ } \ } -#define DEFINE_S3C_TIMER(_tmr_no, _irq) \ - .name = "s3c24xx-pwm", \ - .id = _tmr_no, \ - .num_resources = TIMER_RESOURCE_SIZE, \ - .resource = TIMER_RESOURCE(_tmr_no, _irq), \ +#define DEFINE_S3C_TIMER(_tmr_no, _irq, _plat_data) \ + .name = "s3c24xx-pwm", \ + .id = _tmr_no, \ + .num_resources = TIMER_RESOURCE_SIZE, \ + .resource = TIMER_RESOURCE(_tmr_no, _irq), \ + .dev = { \ + .platform_data = _plat_data, \ + } + +#define GPD0_0_TOUT (0x2 << 0) +#ifdef CONFIG_FB_MDNIE_PWM +#define GPD0_1_TOUT (0x3 << 4) +#else +#define GPD0_1_TOUT (0x2 << 4) +#endif +#define GPD0_2_TOUT (0x2 << 8) +#define GPD0_3_TOUT (0x2 << 12) -/* - * since we already have an static mapping for the timer, - * we do not bother setting any IO resource for the base. +/* since we already have an static mapping for the timer, we do not + * bother setting any IO resource for the base. */ +struct s3c_pwm_pdata { + /* PWM output port */ + int gpio_no; + const char *gpio_name; + int gpio_set_value; +}; + +struct s3c_pwm_pdata pwm_data[] = { +#ifdef CONFIG_ARCH_EXYNOS5 + { + .gpio_no = EXYNOS5_GPB2(0), + .gpio_name = "GPB", + .gpio_set_value = GPD0_0_TOUT, + }, { + .gpio_no = EXYNOS5_GPB2(1), + .gpio_name = "GPB", + .gpio_set_value = GPD0_1_TOUT, + }, { + .gpio_no = EXYNOS5_GPB2(2), + .gpio_name = "GPB", + .gpio_set_value = GPD0_2_TOUT, + }, { + .gpio_no = EXYNOS5_GPB2(3), + .gpio_name = "GPB", + .gpio_set_value = GPD0_3_TOUT, + }, { + .gpio_no = 0, + .gpio_name = NULL, + .gpio_set_value = 0, + } +#else + { + .gpio_no = EXYNOS4_GPD0(0), + .gpio_name = "GPD", + .gpio_set_value = GPD0_0_TOUT, + }, { + .gpio_no = EXYNOS4_GPD0(1), + .gpio_name = "GPD", + .gpio_set_value = GPD0_1_TOUT, + }, { + .gpio_no = EXYNOS4_GPD0(2), + .gpio_name = "GPD", + .gpio_set_value = GPD0_2_TOUT, + }, { + .gpio_no = EXYNOS4_GPD0(3), + .gpio_name = "GPD", + .gpio_set_value = GPD0_3_TOUT, + }, { + .gpio_no = 0, + .gpio_name = NULL, + .gpio_set_value = 0, + } +#endif +}; + struct platform_device s3c_device_timer[] = { - [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) }, - [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) }, - [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) }, - [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) }, - [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) }, + [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0, &pwm_data[0]) }, + [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1, &pwm_data[1]) }, + [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2, &pwm_data[2]) }, + [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3, &pwm_data[3]) }, + [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4, &pwm_data[4]) }, }; EXPORT_SYMBOL(s3c_device_timer); diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c index 3e4bd81..f9af090 100644 --- a/arch/arm/plat-samsung/dev-ts.c +++ b/arch/arm/plat-samsung/dev-ts.c @@ -38,23 +38,13 @@ static struct resource s3c_ts_resource[] = { struct platform_device s3c_device_ts = { .name = "s3c64xx-ts", - .id = -1, + .id = 0, .num_resources = ARRAY_SIZE(s3c_ts_resource), .resource = s3c_ts_resource, }; void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) { - struct s3c2410_ts_mach_info *npd; - - if (!pd) { - printk(KERN_ERR "%s: no platform data\n", __func__); - return; - } - - npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - - s3c_device_ts.dev.platform_data = npd; + s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info), + &s3c_device_ts); } diff --git a/arch/arm/plat-samsung/dev-ts1.c b/arch/arm/plat-samsung/dev-ts1.c new file mode 100644 index 0000000..99cc63f --- /dev/null +++ b/arch/arm/plat-samsung/dev-ts1.c @@ -0,0 +1,60 @@ +/* linux/arch/arm/plat-samsung/dev-ts1.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> + * + * Adapted by Maurus Cuelenaere for s3c64xx + * + * S3C64XX series device definition for touchscreen 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/kernel.h> +#include <linux/string.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/devs.h> +#include <plat/ts.h> + +static struct resource s3c_ts_resource[] = { + [0] = { + .start = SAMSUNG_PA_ADC1, + .end = SAMSUNG_PA_ADC1 + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PEN1, + .end = IRQ_PEN1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_ts1 = { + .name = "s3c64xx-ts", + .id = 1, + .num_resources = ARRAY_SIZE(s3c_ts_resource), + .resource = s3c_ts_resource, +}; + +void __init s3c24xx_ts1_set_platdata(struct s3c2410_ts_mach_info *pd) +{ + struct s3c2410_ts_mach_info *npd; + + if (!pd) { + printk(KERN_ERR "%s: no platform data\n", __func__); + return; + } + + npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + + s3c_device_ts1.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c index 0e0a3bf..33fbaa9 100644 --- a/arch/arm/plat-samsung/dev-usb.c +++ b/arch/arm/plat-samsung/dev-usb.c @@ -60,11 +60,6 @@ EXPORT_SYMBOL(s3c_device_ohci); */ void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info) { - struct s3c2410_hcd_info *npd; - - npd = kmemdup(info, sizeof(struct s3c2410_hcd_info), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - - s3c_device_ohci.dev.platform_data = npd; + s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info), + &s3c_device_ohci); } diff --git a/arch/arm/plat-samsung/dev-usb3-exynos-drd.c b/arch/arm/plat-samsung/dev-usb3-exynos-drd.c new file mode 100644 index 0000000..6ce72c4 --- /dev/null +++ b/arch/arm/plat-samsung/dev-usb3-exynos-drd.c @@ -0,0 +1,103 @@ +/* arch/arm/plat-samsung/dev-usb3-dwc-drd.c + * + * Copyright (c) 2011 Samsung Electronics Co. Ltd + * Author: Anton Tikhomirov <av.tikhomirov@samsung.com> + * + * Device definition for EXYNOS SuperSpeed USB 3.0 DRD Controller + * + * 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 <linux/dma-mapping.h> + +#include <linux/platform_data/exynos_usb3_drd.h> + +#include <mach/irqs.h> +#include <mach/map.h> + +#include <plat/devs.h> +#include <plat/usb-phy.h> + +static struct resource exynos_ss_udc_resources[] = { + [0] = { + .start = EXYNOS5_PA_SS_DRD, + .end = EXYNOS5_PA_SS_DRD + 0x100000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB3_DRD, + .end = IRQ_USB3_DRD, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource exynos_xhci_resources[] = { + [0] = { + .start = EXYNOS5_PA_SS_DRD, + .end = EXYNOS5_PA_SS_DRD + 0x100000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB3_DRD, + .end = IRQ_USB3_DRD, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 exynos_ss_udc_dmamask = DMA_BIT_MASK(32); +static u64 exynos_xhci_dmamask = DMA_BIT_MASK(32); + +struct platform_device exynos_device_ss_udc = { + .name = "exynos-ss-udc", + .id = -1, + .num_resources = ARRAY_SIZE(exynos_ss_udc_resources), + .resource = exynos_ss_udc_resources, + .dev = { + .dma_mask = &exynos_ss_udc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +struct platform_device exynos_device_xhci = { + .name = "exynos-xhci", + .id = -1, + .num_resources = ARRAY_SIZE(exynos_xhci_resources), + .resource = exynos_xhci_resources, + .dev = { + .dma_mask = &exynos_xhci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init exynos_ss_udc_set_platdata(struct exynos_usb3_drd_pdata *pd) +{ + struct exynos_usb3_drd_pdata *npd; + + npd = s3c_set_platdata(pd, sizeof(struct exynos_usb3_drd_pdata), + &exynos_device_ss_udc); + + npd->phy_type = S5P_USB_PHY_DRD; + if (!npd->phy_init) + npd->phy_init = s5p_usb_phy_init; + if (!npd->phy_exit) + npd->phy_exit = s5p_usb_phy_exit; +} + +void __init exynos_xhci_set_platdata(struct exynos_usb3_drd_pdata *pd) +{ + struct exynos_usb3_drd_pdata *npd; + + npd = s3c_set_platdata(pd, sizeof(struct exynos_usb3_drd_pdata), + &exynos_device_xhci); + + npd->phy_type = S5P_USB_PHY_DRD; + if (!npd->phy_init) + npd->phy_init = s5p_usb_phy_init; + if (!npd->phy_exit) + npd->phy_exit = s5p_usb_phy_exit; +} diff --git a/arch/arm/plat-samsung/dev-wdt.c b/arch/arm/plat-samsung/dev-wdt.c index 019b5b8..c9d8f2c 100644 --- a/arch/arm/plat-samsung/dev-wdt.c +++ b/arch/arm/plat-samsung/dev-wdt.c @@ -21,7 +21,7 @@ static struct resource s3c_wdt_resource[] = { [0] = { .start = S3C_PA_WDT, - .end = S3C_PA_WDT + SZ_1K, + .end = S3C_PA_WDT + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-samsung/dma_m2m_test.c b/arch/arm/plat-samsung/dma_m2m_test.c new file mode 100644 index 0000000..b1ca128 --- /dev/null +++ b/arch/arm/plat-samsung/dma_m2m_test.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh <jassi.brar@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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * MemToMem DMA Xfer Test Driver for S3C DMA API + * + */ +#include <linux/init.h> +#include <linux/kthread.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/wait.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> + +#include <mach/dma.h> + +#define XFER_UNIT 1024 + +static unsigned int xfer_size = 256; +module_param(xfer_size, uint, S_IRUGO); +MODULE_PARM_DESC(xfer_size, "Size of each DMA enqueue request in KB"); + +#define DMATEST_BRSTSZ 1 +static unsigned short burst = 1; +module_param(burst, ushort, S_IRUGO); +MODULE_PARM_DESC(burst, "For which parts of API to calc performance"); + +static unsigned short perf_test = 1; +module_param(perf_test, ushort, S_IRUGO); +MODULE_PARM_DESC(perf_test, "For which parts of API to calc performance"); + +static unsigned int sec = 60 * 60; /* 1 hour by default */ +module_param(sec, uint, S_IRUGO); +MODULE_PARM_DESC(sec, "Number of seconds to run the test (default: 24hr)"); + +static unsigned int channels = 10000; /* Use all channels by default */ +module_param(channels, uint, S_IRUGO); +MODULE_PARM_DESC(channels, "Number of channels to test (default: 8)"); + +struct s3cdma_thread { + unsigned id; /* For Channel index */ + struct task_struct *task; +#define SRC 0 +#define DST 1 + void *buff_cpu[2]; /* CPU address of the Source & Destination buffer */ + dma_addr_t buff_phys[2]; /* Physical address of the Source & Destination buffer */ + unsigned long jiffies; + int stopped; + enum s3c2410_dma_buffresult res; + int size; + unsigned done; + struct s3c2410_dma_client cl; + struct completion xfer_cmplt; + struct list_head node; +}; + +static unsigned int delta; +static unsigned long cycles, maxtime; +static LIST_HEAD(channel_list); + +void s3cdma_cb(struct s3c2410_dma_chan *chan, void *buf_id, + int size, enum s3c2410_dma_buffresult res) +{ + struct s3cdma_thread *thread = buf_id; + + thread->res = res; + thread->size = size; + + complete(&thread->xfer_cmplt); +} + +static void dmatest_init_buf(u32 buf[], int clr, unsigned int bytes) +{ + unsigned int i; + + for (i = 0; i < bytes / 4; i++) + buf[i] = clr ? 0 : i; +} + +static bool dmatest_buf_same(u32 src[], u32 dst[], unsigned int bytes) +{ + unsigned int i; + + for (i = 0; i < (bytes - delta) / 4; i++) + if (src[i] != dst[i]) + return false; + + for (; i < bytes / 4; i++) + if (dst[i]) + return false; + + return true; +} + +static int dmatest_func(void *data) +{ + struct s3cdma_thread *thread = data; + enum dma_ch chan = DMACH_MTOM_0 + thread->id; + unsigned long tout = jiffies + msecs_to_jiffies(sec * 1000); + int src_idx = 0; + unsigned val; + + thread->jiffies = jiffies; + thread->done = 0; + + while (!kthread_should_stop() && time_before(jiffies, tout)) { + + u32 *srcbuf = thread->buff_cpu[src_idx]; + u32 *dstbuf = thread->buff_cpu[1 - src_idx]; + + if (!perf_test) { + dmatest_init_buf(srcbuf, 0, xfer_size); + dmatest_init_buf(dstbuf, 1, xfer_size); + delta = 1024; + } + + s3c2410_dma_devconfig(chan, S3C_DMA_MEM2MEM, + thread->buff_phys[src_idx]); + + s3c2410_dma_enqueue(chan, (void *)thread, + thread->buff_phys[1 - src_idx], xfer_size - delta); + + s3c2410_dma_ctrl(chan, S3C2410_DMAOP_START); + + val = wait_for_completion_timeout(&thread->xfer_cmplt, msecs_to_jiffies(5*1000)); + if (!val) { + dma_addr_t src, dst; + s3c2410_dma_getposition(DMACH_MTOM_0 + thread->id, + &src, &dst); + + printk("\n%s:%d Thrd-%u Done-%u <%x,%x>/<%x,%x>\n", + __func__, __LINE__, thread->id, thread->done, + src, dst, thread->buff_phys[src_idx], thread->buff_phys[1 - src_idx]); + break; + } + + if (thread->res != S3C2410_RES_OK + || thread->size != xfer_size - delta) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Cycle-%u Res-%u Xfer_size-%d!\n", + thread->id, thread->done, thread->res, thread->size); + } else { + thread->done++; + } + + if (!perf_test && + !dmatest_buf_same(srcbuf, dstbuf, xfer_size)) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Cycle-%u Xfer_cmp failed!\n", + thread->id, thread->done); + break; + } + + src_idx = 1 - src_idx; + } + + thread->jiffies = jiffies - thread->jiffies; + + thread->stopped = 1; + + return 0; +} + +static int __init dmatest_init(void) +{ + struct s3cdma_thread *thread; + int ret, i = 0; + + xfer_size *= XFER_UNIT; + + if (sec < 5) { + sec = 5; + printk(KERN_INFO "S3C DMA M2M Test: Using 5secs test time\n"); + } + + while (i < 10) { + if (burst == (1 << i)) + break; + i++; + } + /* If invalid burst value provided */ + if (i == 10) { + burst = 1; + printk(KERN_INFO "S3C DMA M2M Test: Using 1 burst size\n"); + } + + for (i = 0; i < channels; i++) { + thread = kzalloc(sizeof(struct s3cdma_thread), GFP_KERNEL); + if (!thread) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for channel\n", i); + goto thrd_alloc_err; + } + + thread->buff_cpu[SRC] = dma_alloc_coherent(NULL, xfer_size, + &thread->buff_phys[SRC], GFP_KERNEL); + if (!thread->buff_cpu[SRC]) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for src buff\n", i); + goto src_alloc_err; + } + + thread->buff_cpu[DST] = dma_alloc_coherent(NULL, xfer_size, + &thread->buff_phys[DST], GFP_KERNEL); + if (!thread->buff_cpu[DST]) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for dst buff\n", i); + goto dst_alloc_err; + } + + dmatest_init_buf(thread->buff_cpu[SRC], 0, xfer_size); + dmatest_init_buf(thread->buff_cpu[DST], 1, xfer_size); + + thread->id = i; + thread->cl.name = (char *) thread; + thread->stopped = 0; + + init_completion(&thread->xfer_cmplt); + + ret = s3c2410_dma_request(DMACH_MTOM_0 + thread->id, + &thread->cl, NULL); + if (ret) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%d acq(%d)\n", i, ret); + goto thrd_dma_acq_err; + } + + s3c2410_dma_set_buffdone_fn(DMACH_MTOM_0 + thread->id, s3cdma_cb); + + ret = s3c2410_dma_config(DMACH_MTOM_0 + thread->id, burst); + if (ret) { + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%d config(%d)\n", i, ret); + goto thrd_dma_cfg_err; + } + + thread->task = kthread_run(dmatest_func, thread, + "dma-m2m-test%u", i); + if (IS_ERR(thread->task)) { + printk(KERN_INFO "S3C DMA M2M Test: Failed to run thread dma-m2m-test%u\n", i); + goto thrd_run_err; + } + + list_add_tail(&thread->node, &channel_list); + + continue; + +thrd_run_err: +thrd_dma_cfg_err: + s3c2410_dma_free(DMACH_MTOM_0 + thread->id, &thread->cl); +thrd_dma_acq_err: + dma_free_coherent(NULL, xfer_size, + thread->buff_cpu[DST], thread->buff_phys[DST]); +dst_alloc_err: + dma_free_coherent(NULL, xfer_size, + thread->buff_cpu[SRC], thread->buff_phys[SRC]); +src_alloc_err: + kfree(thread); +thrd_alloc_err: + break; + } + + printk(KERN_INFO "S3C DMA M2M Test: Testing with %u Channels\n", i); + + return 0; +} +module_init(dmatest_init); + +static void __exit dmatest_exit(void) +{ + struct s3cdma_thread *thread; + + while (!list_empty(&channel_list)) { + thread = list_entry(channel_list.next, + struct s3cdma_thread, node); + + list_del(&thread->node); + + if (perf_test && !dmatest_buf_same(thread->buff_cpu[SRC], + thread->buff_cpu[DST], xfer_size)) + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Xfer_cmp failed!\n", thread->id); + + if (!thread->stopped) + kthread_stop(thread->task); + + if (jiffies_to_msecs(thread->jiffies) > maxtime) + maxtime = jiffies_to_msecs(thread->jiffies); + + cycles += thread->done; + + printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u %ux%u Kb in %ums\n", + thread->id, thread->done, xfer_size / XFER_UNIT, + jiffies_to_msecs(thread->jiffies)); + + s3c2410_dma_free(DMACH_MTOM_0 + thread->id, &thread->cl); + + dma_free_coherent(NULL, xfer_size, + thread->buff_cpu[DST], thread->buff_phys[DST]); + + dma_free_coherent(NULL, xfer_size, + thread->buff_cpu[SRC], thread->buff_phys[SRC]); + + kfree(thread); + } + + printk(KERN_INFO "S3C DMA M2M Test: Overall %lux%u Kb in %lums\n", + cycles, xfer_size / XFER_UNIT, maxtime); + printk(KERN_INFO "S3C DMA M2M Test: %lu MB/Sec\n", + cycles * 1000 / maxtime * xfer_size / XFER_UNIT / 1024); +} +module_exit(dmatest_exit); + +MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); +MODULE_DESCRIPTION("S3C DMA MemToMem Test Driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 1c0b040..712ec09 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -429,3 +429,99 @@ int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) } EXPORT_SYMBOL(s5p_gpio_set_drvstr); #endif /* CONFIG_S5P_GPIO_DRVSTR */ + +s5p_gpio_pd_cfg_t s5p_gpio_get_pd_cfg(unsigned int pin) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 pd_cfg; + + if (!chip) + return -EINVAL; + + off = pin - chip->chip.base; + shift = off * 2; + reg = chip->base + 0x10; + + pd_cfg = __raw_readl(reg); + pd_cfg = pd_cfg >> shift; + pd_cfg &= 0x3; + + return (__force s5p_gpio_pd_cfg_t)pd_cfg; +} +EXPORT_SYMBOL(s5p_gpio_get_pd_cfg); + +int s5p_gpio_set_pd_cfg(unsigned int pin, s5p_gpio_pd_cfg_t pd_cfg) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 tmp; + + if (!chip) + return -EINVAL; + + off = pin - chip->chip.base; + shift = off * 2; + reg = chip->base + 0x10; + + tmp = __raw_readl(reg); + tmp &= ~(0x3 << shift); + tmp |= pd_cfg << shift; + + __raw_writel(tmp, reg); + + return 0; +} +EXPORT_SYMBOL(s5p_gpio_set_pd_cfg); + +s5p_gpio_pd_pull_t s5p_gpio_get_pd_pull(unsigned int pin) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 pd_pull; + + if (!chip) + return -EINVAL; + + off = pin - chip->chip.base; + shift = off * 2; + reg = chip->base + 0x14; + + pd_pull = __raw_readl(reg); + pd_pull = pd_pull >> shift; + pd_pull &= 0x3; + + return (__force s5p_gpio_pd_pull_t)pd_pull; +} +EXPORT_SYMBOL(s5p_gpio_get_pd_pull); + +int s5p_gpio_set_pd_pull(unsigned int pin, s5p_gpio_pd_pull_t pd_pull) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 tmp; + + if (!chip) + return -EINVAL; + + off = pin - chip->chip.base; + shift = off * 2; + reg = chip->base + 0x14; + + tmp = __raw_readl(reg); + tmp &= ~(0x3 << shift); + tmp |= pd_pull << shift; + + __raw_writel(tmp, reg); + + return 0; +} +EXPORT_SYMBOL(s5p_gpio_set_pd_pull); diff --git a/arch/arm/plat-samsung/include/plat/adc.h b/arch/arm/plat-samsung/include/plat/adc.h index b258a08..449f409 100644 --- a/arch/arm/plat-samsung/include/plat/adc.h +++ b/arch/arm/plat-samsung/include/plat/adc.h @@ -17,7 +17,8 @@ struct s3c_adc_client; extern int s3c_adc_start(struct s3c_adc_client *client, - unsigned int channel, unsigned int nr_samples); + unsigned int channel, unsigned int nr_samples, + wait_queue_head_t *pwake); extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch); diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h index a0826ed..bfee644 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h @@ -36,6 +36,10 @@ struct samsung_i2s { */ #define QUIRK_NO_MUXPSR (1 << 2) #define QUIRK_NEED_RSTCLR (1 << 3) +/* If the idma will be enabled */ +#define QUIRK_ENABLED_IDMA (1 << 4) +/* If the srp will be enabled */ +#define QUIRK_ENABLED_SRP (1 << 5) /* Quirks of the I2S controller */ u32 quirks; @@ -56,3 +60,5 @@ struct s3c_audio_pdata { struct samsung_i2s i2s; } type; }; + +extern void __init exynos4_i2sv3_setup_resource(void); diff --git a/arch/arm/plat-samsung/include/plat/backlight.h b/arch/arm/plat-samsung/include/plat/backlight.h new file mode 100644 index 0000000..ad530c7 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/backlight.h @@ -0,0 +1,26 @@ +/* linux/arch/arm/plat-samsung/include/plat/backlight.h + * + * Copyright (c) 2011 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_BACKLIGHT_H +#define __ASM_PLAT_BACKLIGHT_H __FILE__ + +/* samsung_bl_gpio_info - GPIO info for PWM Backlight control + * @no: GPIO number for PWM timer out + * @func: Special function of GPIO line for PWM timer + */ +struct samsung_bl_gpio_info { + int no; + int func; +}; + +extern void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, + struct platform_pwm_backlight_data *bl_data); + +#endif /* __ASM_PLAT_BACKLIGHT_H */ diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 983c578..76198a7 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -9,7 +9,11 @@ * published by the Free Software Foundation. */ +#ifndef __ASM_PLAT_CLOCK_H +#define __ASM_PLAT_CLOCK_H __FILE__ + #include <linux/spinlock.h> +#include <linux/clkdev.h> struct clk; @@ -40,6 +44,7 @@ struct clk { struct module *owner; struct clk *parent; const char *name; + const char *devname; int id; int usage; unsigned long rate; @@ -47,6 +52,7 @@ struct clk { struct clk_ops *ops; int (*enable)(struct clk *, int enable); + struct clk_lookup lookup; #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) struct dentry *dent; /* For visible tree hierarchy */ #endif @@ -78,6 +84,7 @@ extern struct clk clk_h2; extern struct clk clk_27m; extern struct clk clk_48m; extern struct clk clk_xusbxti; +extern struct clk clk_xxti; extern int clk_default_setrate(struct clk *clk, unsigned long rate); extern struct clk_ops clk_ops_def_setrate; @@ -118,3 +125,8 @@ extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); extern void s3c_pwmclk_init(void); +/* Global watchdog clock used by arch_wtd_reset() callback */ + +extern struct clk *s3c2410_wdtclk; + +#endif /* __ASM_PLAT_CLOCK_H */ diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index c0a5741..f68c5a6 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -1,9 +1,12 @@ /* linux/arch/arm/plat-samsung/include/plat/cpu.h * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * - * Header file for S3C24XX CPU support + * Header file for Samsung CPU 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 @@ -15,6 +18,139 @@ #ifndef __SAMSUNG_PLAT_CPU_H #define __SAMSUNG_PLAT_CPU_H +extern unsigned long samsung_cpu_id; + +#define S3C24XX_CPU_ID 0x32400000 +#define S3C24XX_CPU_MASK 0xFFF00000 + +#define S3C6400_CPU_ID 0x36400000 +#define S3C6410_CPU_ID 0x36410000 +#define S3C64XX_CPU_ID (S3C6400_CPU_ID & S3C6410_CPU_ID) +#define S3C64XX_CPU_MASK 0x1FF40000 + +#define S5P6440_CPU_ID 0x56440000 +#define S5P6450_CPU_ID 0x36450000 +#define S5P64XX_CPU_MASK 0x1FF40000 + +#define S5PC100_CPU_ID 0x43100000 +#define S5PC100_CPU_MASK 0xFFFFF000 + +#define S5PV210_CPU_ID 0x43110000 +#define S5PV210_CPU_MASK 0xFFFFF000 + +#define EXYNOS4210_CPU_ID 0x43210000 +#define EXYNOS4212_CPU_ID 0x43220000 +#define EXYNOS4412_CPU_ID 0xE4412200 +#define EXYNOS5210_CPU_ID 0x43510000 +#define EXYNOS5250_CPU_ID 0x43520000 +#define EXYNOS_CPU_MASK 0xFFFE0000 + +#define IS_SAMSUNG_CPU(name, id, mask) \ +static inline int is_samsung_##name(void) \ +{ \ + return ((samsung_cpu_id & mask) == (id & mask)); \ +} + +IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK) +IS_SAMSUNG_CPU(s3c64xx, S3C64XX_CPU_ID, S3C64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK) +IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK) +IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK) +IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS_CPU_MASK) +IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS_CPU_MASK) +IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS_CPU_MASK) +IS_SAMSUNG_CPU(exynos5210, EXYNOS5210_CPU_ID, EXYNOS_CPU_MASK) +IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_CPU_ID, EXYNOS_CPU_MASK) + +#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ + defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \ + defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \ + defined(CONFIG_CPU_S3C2443) +# define soc_is_s3c24xx() is_samsung_s3c24xx() +#else +# define soc_is_s3c24xx() 0 +#endif + +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) +# define soc_is_s3c64xx() is_samsung_s3c64xx() +#else +# define soc_is_s3c64xx() 0 +#endif + +#if defined(CONFIG_CPU_S5P6440) +# define soc_is_s5p6440() is_samsung_s5p6440() +#else +# define soc_is_s5p6440() 0 +#endif + +#if defined(CONFIG_CPU_S5P6450) +# define soc_is_s5p6450() is_samsung_s5p6450() +#else +# define soc_is_s5p6450() 0 +#endif + +#if defined(CONFIG_CPU_S5PC100) +# define soc_is_s5pc100() is_samsung_s5pc100() +#else +# define soc_is_s5pc100() 0 +#endif + +#if defined(CONFIG_CPU_S5PV210) +# define soc_is_s5pv210() is_samsung_s5pv210() +#else +# define soc_is_s5pv210() 0 +#endif + +#if defined(CONFIG_CPU_EXYNOS4210) +# define soc_is_exynos4210() is_samsung_exynos4210() +#else +# define soc_is_exynos4210() 0 +#endif + +#define EXYNOS4210_REV_0 (0x0) +#define EXYNOS4210_REV_1_0 (0x10) +#define EXYNOS4210_REV_1_1 (0x11) +#define EXYNOS4210_REV_1_2 (0x12) + +#if defined(CONFIG_CPU_EXYNOS4212) +# define soc_is_exynos4212() is_samsung_exynos4212() +#else +# define soc_is_exynos4212() 0 +#endif + +#define EXYNOS4212_REV_0 (0x0) +#define EXYNOS4212_REV_1_0 (0x10) + +#if defined(CONFIG_CPU_EXYNOS4412) +# define soc_is_exynos4412() is_samsung_exynos4412() +#else +# define soc_is_exynos4412() 0 +#endif + +#define EXYNOS4412_REV_0 (0x0) +#define EXYNOS4412_REV_0_1 (0x01) +#define EXYNOS4412_REV_1_0 (0x10) +#define EXYNOS4412_REV_1_1 (0x11) + +#if defined(CONFIG_CPU_EXYNOS5210) +# define soc_is_exynos5210() is_samsung_exynos5210() +#else +# define soc_is_exynos5210() 0 +#endif + +#if defined(CONFIG_CPU_EXYNOS5250) +# define soc_is_exynos5250() is_samsung_exynos5250() +# define soc_is_exynos5250_rev1 (soc_is_exynos5250() && \ + samsung_rev() >= EXYNOS5250_REV_1_0) +#else +# define soc_is_exynos5250() 0 +# define soc_is_exynos5250_rev1 0 +#endif + +#define EXYNOS5250_REV_0 (0x0) +#define EXYNOS5250_REV_1_0 (0x10) + #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ @@ -55,6 +191,12 @@ extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); extern void s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr); +extern void s3c24xx_init_cpu(void); +extern void s3c64xx_init_cpu(void); +extern void s5p_init_cpu(void __iomem *cpuid_addr); + +extern unsigned int samsung_rev(void); + extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s3c24xx_init_clocks(int xtal); @@ -88,6 +230,7 @@ extern struct sysdev_class s3c64xx_sysclass; extern struct sysdev_class s5p64x0_sysclass; extern struct sysdev_class s5pv210_sysclass; extern struct sysdev_class exynos4_sysclass; +extern struct sysdev_class exynos5_sysclass; extern void (*s5pc1xx_idle)(void); diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index e3b31c2..1321d7b 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -17,6 +17,7 @@ #define __PLAT_DEVS_H __FILE__ #include <linux/platform_device.h> +#include <linux/platform_data/exynos_usb3_drd.h> struct s3c24xx_uart_resources { struct resource *resources; @@ -40,6 +41,7 @@ extern struct platform_device s3c64xx_device_spi0; extern struct platform_device s3c64xx_device_spi1; extern struct platform_device samsung_asoc_dma; +extern struct platform_device samsung_asoc_idma; extern struct platform_device s3c64xx_device_pcm0; extern struct platform_device s3c64xx_device_pcm1; @@ -47,8 +49,16 @@ extern struct platform_device s3c64xx_device_pcm1; extern struct platform_device s3c64xx_device_ac97; extern struct platform_device s3c_device_ts; +extern struct platform_device s3c_device_ts1; extern struct platform_device s3c_device_fb; +#ifdef CONFIG_FB_S5P_EXTDSP +extern struct platform_device s3c_device_extdsp; +#endif +extern struct platform_device s5p_device_fimd0; +extern struct platform_device s5p_device_fimd1; +extern struct platform_device s5p_device_mipi_dsim0; +extern struct platform_device s5p_device_mipi_dsim1; extern struct platform_device s3c_device_ohci; extern struct platform_device s3c_device_lcd; extern struct platform_device s3c_device_wdt; @@ -60,6 +70,7 @@ extern struct platform_device s3c_device_i2c4; extern struct platform_device s3c_device_i2c5; extern struct platform_device s3c_device_i2c6; extern struct platform_device s3c_device_i2c7; +extern struct platform_device s5p_device_i2c_hdmiphy; extern struct platform_device s3c_device_rtc; extern struct platform_device s3c_device_adc; extern struct platform_device s3c_device_sdi; @@ -69,6 +80,7 @@ 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_mshci; extern struct platform_device s3c_device_cfcon; extern struct platform_device s3c_device_spi0; @@ -81,6 +93,9 @@ extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; extern struct platform_device s5p64x0_device_spi0; extern struct platform_device s5p64x0_device_spi1; +extern struct platform_device exynos_device_spi0; +extern struct platform_device exynos_device_spi1; +extern struct platform_device exynos_device_spi2; extern struct platform_device s3c_device_hwmon; @@ -92,6 +107,13 @@ extern struct platform_device s5p_device_onenand; extern struct platform_device s3c_device_usbgadget; extern struct platform_device s3c_device_usb_hsudc; extern struct platform_device s3c_device_usb_hsotg; +extern struct platform_device s3c_device_usb_hsudc; +extern struct platform_device s3c_device_android_usb; +extern struct platform_device s3c_device_usb_mass_storage; +#ifdef CONFIG_USB_ANDROID_RNDIS +extern struct platform_device s3c_device_rndis; +#endif +extern struct platform_device s5p_device_usbswitch; extern struct platform_device s5pv210_device_ac97; extern struct platform_device s5pv210_device_pcm0; @@ -101,17 +123,45 @@ extern struct platform_device s5pv210_device_iis0; 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 exynos4_device_ac97; -extern struct platform_device exynos4_device_pcm0; -extern struct platform_device exynos4_device_pcm1; -extern struct platform_device exynos4_device_pcm2; -extern struct platform_device exynos4_device_i2s0; -extern struct platform_device exynos4_device_i2s1; -extern struct platform_device exynos4_device_i2s2; -extern struct platform_device exynos4_device_spdif; +extern struct platform_device s5pv210_device_cpufreq; +extern struct platform_device s5pv210_device_pdma0; +extern struct platform_device s5pv210_device_pdma1; +extern struct platform_device s5pv210_device_mdma; + +extern struct platform_device exynos_device_ac97; +extern struct platform_device exynos_device_pcm0; +extern struct platform_device exynos_device_pcm1; +extern struct platform_device exynos_device_pcm2; +extern struct platform_device exynos_device_i2s0; +extern struct platform_device exynos_device_i2s1; +extern struct platform_device exynos_device_i2s2; +extern struct platform_device exynos_device_spdif; +extern struct platform_device exynos_device_srp; extern struct platform_device exynos4_device_pd[]; extern struct platform_device exynos4_device_ahci; +extern struct platform_device exynos_device_pdma0; +extern struct platform_device exynos_device_pdma1; +extern struct platform_device exynos_device_mdma; +extern struct platform_device exynos_device_dwmci; +extern struct platform_device exynos_device_dwmci0; +extern struct platform_device exynos_device_dwmci1; +extern struct platform_device exynos_device_dwmci2; +extern struct platform_device exynos_device_dwmci3; +extern struct platform_device exynos_device_flite0; +extern struct platform_device exynos_device_flite1; +extern struct platform_device exynos4_device_c2c; +extern struct platform_device exynos_device_flite2; +extern struct platform_device exynos4_device_fimc_is; +extern struct platform_device exynos5_device_fimc_is; +extern struct platform_device exynos5_device_pd[]; +extern struct platform_device exynos5_device_gsc0; +extern struct platform_device exynos5_device_gsc1; +extern struct platform_device exynos5_device_gsc2; +extern struct platform_device exynos5_device_gsc3; +extern struct platform_device exynos5_device_ahci; +extern struct platform_device exynos_device_c2c; +extern struct platform_device exynos_device_ss_udc; +extern struct platform_device exynos_device_xhci; extern struct platform_device s5p6440_device_pcm; extern struct platform_device s5p6440_device_iis; @@ -130,18 +180,57 @@ extern struct platform_device s5pc100_device_iis2; extern struct platform_device s5pc100_device_spdif; extern struct platform_device samsung_device_keypad; - +#ifndef CONFIG_VIDEO_FIMC 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_fimc3; - +#else +extern struct platform_device s3c_device_fimc0; +extern struct platform_device s3c_device_fimc1; +extern struct platform_device s3c_device_fimc2; +extern struct platform_device s3c_device_fimc3; +#endif +#ifndef CONFIG_VIDEO_FIMC_MIPI extern struct platform_device s5p_device_mipi_csis0; extern struct platform_device s5p_device_mipi_csis1; +#else +extern struct platform_device s3c_device_csis0; +extern struct platform_device s3c_device_csis1; +#endif +extern struct platform_device s5p_device_dp; + +extern struct platform_device s5p_device_jpeg; +extern struct platform_device s5p_device_tvout; +extern struct platform_device s5p_device_cec; +extern struct platform_device s5p_device_hpd; +extern struct platform_device s5p_device_ace; +extern struct platform_device s5p_device_fimg2d; +extern struct platform_device exynos_device_rotator; extern struct platform_device s5p_device_ehci; +extern struct platform_device s5p_device_ohci; +#ifdef CONFIG_USB_HOST_NOTIFY +extern struct platform_device host_notifier_device; +#endif -extern struct platform_device exynos4_device_sysmmu; +extern struct platform_device exynos_device_sysmmu[]; + +extern struct platform_device s5p_device_mfc; +extern struct platform_device s5p_device_mipi_dsim; +extern struct platform_device s5p_device_dsim; + +extern struct platform_device s5p_device_hdmi; +extern struct platform_device s5p_device_mixer; +extern struct platform_device s5p_device_sdo; + +#ifdef CONFIG_FB_S5P_MIPI_DSIM +extern struct platform_device s5p_device_dsim; +#endif + +#ifdef CONFIG_SENSORS_EXYNOS4_TMU +extern struct platform_device exynos4_device_tmu; +#endif /* s3c2440 specific devices */ @@ -152,6 +241,13 @@ extern struct platform_device s3c_device_ac97; #endif +#if defined(CONFIG_VIDEO_TSI) +extern struct platform_device s3c_device_tsi; +#endif + +extern void exynos_ss_udc_set_platdata(struct exynos_usb3_drd_pdata *pd); +extern void exynos_xhci_set_platdata(struct exynos_usb3_drd_pdata *pd); + /** * s3c_set_platdata() - helper for setting platform data * @pd: The default platform data for this device. diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h index 8c273b7..816d505 100644 --- a/arch/arm/plat-samsung/include/plat/dma.h +++ b/arch/arm/plat-samsung/include/plat/dma.h @@ -18,7 +18,9 @@ enum s3c2410_dma_buffresult { enum s3c2410_dmasrc { S3C2410_DMASRC_HW, /* source is memory */ - S3C2410_DMASRC_MEM /* source is hardware */ + S3C2410_DMASRC_MEM, /* source is hardware */ + S3C_DMA_MEM2MEM, + S3C_DMA_MEM2MEM_SET, }; /* enum s3c2410_chan_op @@ -96,8 +98,18 @@ extern int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *); * drained before the buffer is given to the DMA system. */ -extern int s3c2410_dma_enqueue(enum dma_ch channel, void *id, - dma_addr_t data, int size); +#define s3c2410_dma_enqueue(id, token, addr, size) \ + s3c2410_dma_enqueue_ring(id, token, addr, size, 0) + +/* s3c2410_dma_enqueue_ring + * + * place the given buffer onto the queue of operations for the channel. + * The buffer must be allocated from dma coherent memory, or the Dcache/WB + * drained before the buffer is given to the DMA system. +*/ + +extern int s3c2410_dma_enqueue_ring(enum dma_ch channel, void *id, + dma_addr_t data, int size, int numofblock); /* s3c2410_dma_config * diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h index bca383e..4335840 100644 --- a/arch/arm/plat-samsung/include/plat/fb-core.h +++ b/arch/arm/plat-samsung/include/plat/fb-core.h @@ -26,4 +26,25 @@ static inline void s3c_fb_setname(char *name) #endif } +/* Re-define device name depending on support. */ +static inline void s5p_fb_setname(int id, char *name) +{ + switch (id) { +#ifdef CONFIG_S5P_DEV_FIMD0 + case 0: + s5p_device_fimd0.name = name; + break; +#endif + +#ifdef CONFIG_S5P_DEV_FIMD1 + case 1: + s5p_device_fimd1.name = name; + break; +#endif + default: + printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id); + break; + } +} + #endif /* __ASM_PLAT_FB_CORE_H */ diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index cb3ca3a..2e1813f 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -15,6 +15,8 @@ #ifndef __PLAT_S3C_FB_H #define __PLAT_S3C_FB_H __FILE__ +#include <plat/gpio-cfg.h> + /* S3C_FB_MAX_WIN * Set to the maximum number of windows that any of the supported hardware * can use. Since the platform data uses this for an array size, having it @@ -22,11 +24,28 @@ */ #define S3C_FB_MAX_WIN (5) +#if defined(CONFIG_MACH_P11) || defined(CONFIG_MACH_P10) +/* IOCTL commands */ +#define S3CFB_WIN_POSITION _IOW('F', 203, \ + struct s3c_fb_user_window) +#define S3CFB_WIN_SET_PLANE_ALPHA _IOW('F', 204, \ + struct s3c_fb_user_plane_alpha) +#define S3CFB_WIN_SET_CHROMA _IOW('F', 205, \ + struct s3c_fb_user_chroma) +#define S3CFB_SET_VSYNC_INT _IOW('F', 206, u32) + +#define S3CFB_GET_ION_USER_HANDLE _IOWR('F', 208, \ + struct s3c_fb_user_ion_client) +#define S3CFB_PAN_DISPLAY_INDEX _IOW('F', 209, __u32) + +#endif /** * struct s3c_fb_pd_win - per window setup data * @win_mode: The display parameters to initialise (not for window 0) * @virtual_x: The virtual X size. * @virtual_y: The virtual Y size. + * @width: The width of display in mm + * @height: The height of display in mm */ struct s3c_fb_pd_win { struct fb_videomode win_mode; @@ -35,6 +54,8 @@ struct s3c_fb_pd_win { unsigned short max_bpp; unsigned short virtual_x; unsigned short virtual_y; + unsigned short width; + unsigned short height; }; /** @@ -74,6 +95,22 @@ struct s3c_fb_platdata { extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd); /** + * s5p_fimd0_set_platdata() - Setup the FB device with platform data. + * @pd: The platform data to set. The data is copied from the passed structure + * so the machine data can mark the data __initdata so that any unused + * machines will end up dumping their data at runtime. + */ +extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd); + +/** + * s5p_fimd1_set_platdata() - Setup the FB device with platform data. + * @pd: The platform data to set. The data is copied from the passed structure + * so the machine data can mark the data __initdata so that any unused + * machines will end up dumping their data at runtime. + */ +extern void s5p_fimd1_set_platdata(struct s3c_fb_platdata *pd); + +/** * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD * * Initialise the GPIO for an 24bpp LCD display on the RGB interface. @@ -94,4 +131,30 @@ extern void s5pc100_fb_gpio_setup_24bpp(void); */ extern void s5pv210_fb_gpio_setup_24bpp(void); +/** + * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0 + * + * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0. + */ +extern void exynos4_fimd0_gpio_setup_24bpp(void); + +/** + * exynos4_fimd_cfg_gpios() - Exynos4 setup function for 24bpp LCD + * + * Initialise the GPIO for an 24bpp LCD display on the RGB interface. + */ +extern void exynos4_fimd_cfg_gpios(unsigned int base, unsigned int nr, + unsigned int cfg, s5p_gpio_drvstr_t drvstr); + +/** + * exynos4_fimd0_setup_clock() = Exynos4 setup function for parent clock. + * @dev: device pointer + * @parent: parent clock used for LCD pixel clock + * @clk_rate: clock rate for parent clock + */ +int __init exynos4_fimd0_setup_clock(struct device *dev, const char *parent, + unsigned long clk_rate); + +int __init exynos4_fimd_setup_clock(struct device *dev, const char *bus_clk, + const char *parent, unsigned long clk_rate); #endif /* __PLAT_S3C_FB_H */ diff --git a/arch/arm/plat-samsung/include/plat/fimd_lite_ext.h b/arch/arm/plat-samsung/include/plat/fimd_lite_ext.h new file mode 100644 index 0000000..b4e131a --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/fimd_lite_ext.h @@ -0,0 +1,99 @@ +/* linux/arch/arm/plat/mdnie_ext.h + * + * Samsung SoC FIMD Extension Framework Header. + * + * InKi Dae <inki.dae@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. +*/ + +struct s5p_fimd_ext_device; + +#define fimd_ext_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) +#define fimd_ext_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data)) + +struct s5p_fimd_dynamic_refresh { + void __iomem *regs; + unsigned int dynamic_refresh; + unsigned int clkdiv; +}; + +/** + * driver structure for fimd extension based driver. + * + * this structure should be registered by any extension driver. + * fimd extension driveer seeks a driver registered through name field + * and calls these callback functions in appropriate time. + */ +struct s5p_fimd_ext_driver { + struct device_driver driver; + + void (*change_clock)(struct s5p_fimd_dynamic_refresh *fimd_refresh, + struct s5p_fimd_ext_device *fx_dev); + void (*set_clock)(struct s5p_fimd_ext_device *fx_dev); + int (*setup)(struct s5p_fimd_ext_device *fx_dev, + unsigned int enable); + void (*power_on)(struct s5p_fimd_ext_device *fx_dev); + void (*power_off)(struct s5p_fimd_ext_device *fx_dev); + int (*start)(struct s5p_fimd_ext_device *fx_dev); + void (*stop)(struct s5p_fimd_ext_device *fx_dev); + int (*probe)(struct s5p_fimd_ext_device *fx_dev); + int (*remove)(struct s5p_fimd_ext_device *fx_dev); + int (*suspend)(struct s5p_fimd_ext_device *fx_dev); + int (*resume)(struct s5p_fimd_ext_device *fx_dev); +}; + +/** + * device structure for fimd extension based driver. + * + * @name: platform device name. + * @dev: driver model representation of the device. + * @id: id of device registered and when device is registered + * id would be counted. + * @num_resources: hardware resource count. + * @resource: a pointer to hardware resource definitions. + * @modalias: name of the driver to use with the device, or an + * alias for that name. + */ +struct s5p_fimd_ext_device { + char *name; + struct device dev; + int id; + unsigned int num_resources; + struct resource *resource; + bool mdnie_enabled; + bool enabled; +}; + +struct mdnie_platform_data { + unsigned int width; + unsigned int height; +}; + +/* workaround: fix it later */ +void s6e8aa0_panel_cond(int high_freq); + +#ifdef CONFIG_MDNIE_SUPPORT +/** + * register extension driver to fimd extension framework. + */ +int s5p_fimd_ext_register(struct s5p_fimd_ext_driver *fx_drv); +int s5p_fimd_ext_device_register(struct s5p_fimd_ext_device *fx_dev); + +/** + * find a driver object registered to fimd extension framework. + */ +struct s5p_fimd_ext_device *s5p_fimd_ext_find_device(const char *name); + +/** + * convert device driver object to fimd extension device. + */ +struct s5p_fimd_ext_driver *to_fimd_ext_driver(struct device_driver *drv); +#else +#define s5p_fimd_ext_register(dev) NULL +#define s5p_fimd_ext_device_register(dev) NULL +#define s5p_fimd_ext_find_device(name) NULL +#define to_fimd_ext_driver(drv) NULL +#endif diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 1762dcb..943789c 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -26,6 +26,8 @@ typedef unsigned int __bitwise__ s3c_gpio_pull_t; typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; +typedef unsigned int __bitwise__ s5p_gpio_pd_cfg_t; +typedef unsigned int __bitwise__ s5p_gpio_pd_pull_t; /* forward declaration if gpio-core.h hasn't been included */ struct s3c_gpio_chip; @@ -125,12 +127,30 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, * * These values control the state of the weak pull-{up,down} resistors * available on most pins on the S3C series. Not all chips support both - * up or down settings, and it may be dependent on the chip that is being + * up or down settings, and it may be dependant on the chip that is being * used to whether the particular mode is available. */ +#if defined(CONFIG_ARCH_S5PV310) || defined(CONFIG_ARCH_EXYNOS) +#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) +#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01) +#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x03) +#else #define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) #define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01) #define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02) +#endif + +#if defined(CONFIG_ARCH_S5PV310) || defined(CONFIG_ARCH_EXYNOS) +/* need to move to mach/gpio.h */ +#define S3C_GPIO_SLP_OUT0 ((__force s3c_gpio_pull_t)0x00) +#define S3C_GPIO_SLP_OUT1 ((__force s3c_gpio_pull_t)0x01) +#define S3C_GPIO_SLP_INPUT ((__force s3c_gpio_pull_t)0x02) +#define S3C_GPIO_SLP_PREV ((__force s3c_gpio_pull_t)0x03) + +#define S3C_GPIO_SETPIN_ZERO 0 +#define S3C_GPIO_SETPIN_ONE 1 +#define S3C_GPIO_SETPIN_NONE 2 +#endif /** * s3c_gpio_setpull() - set the state of a gpio pin pull resistor @@ -207,6 +227,65 @@ extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin); */ extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); +/* Define values for the power down configuration available for each gpio pin. + * + * These values control the state of the power down configuration resistors + * available on most pins on the S5P series. + */ +#define S5P_GPIO_PD_OUTPUT0 ((__force s5p_gpio_pd_cfg_t)0x00) +#define S5P_GPIO_PD_OUTPUT1 ((__force s5p_gpio_pd_cfg_t)0x01) +#define S5P_GPIO_PD_INPUT ((__force s5p_gpio_pd_cfg_t)0x02) +#define S5P_GPIO_PD_PREV_STATE ((__force s5p_gpio_pd_cfg_t)0x03) + +/** + * s5p_gpio_set_pd_cfg() - set the configuration of a gpio power down mode + * @pin: The pin number to configure the pull resistor. + * @pd_cfg: The configuration for the pwer down mode configuration register. + * + * This function sets the configuration of the power down mode resistor for the + * specified pin. It will return 0 if successful, or a negative error + * code if the pin cannot support the requested power down mode. + * +*/ +extern int s5p_gpio_set_pd_cfg(unsigned int pin, s5p_gpio_pd_cfg_t pd_cfg); + +/** + * s5p_gpio_get_pd_cfg() - get the power down mode configuration of a gpio pin + * @pin: The pin number to get the settings for + * + * Read the power down mode resistor value for the specified pin. +*/ +extern s5p_gpio_pd_cfg_t s5p_gpio_get_pd_cfg(unsigned int pin); + +/* Define values for the power down pull-{up,down} available for each gpio pin. + * + * These values control the state of the power down mode pull-{up,down} + * resistors available on most pins on the S5P series. + */ +#define S5P_GPIO_PD_UPDOWN_DISABLE ((__force s5p_gpio_pd_pull_t)0x00) +#define S5P_GPIO_PD_DOWN_ENABLE ((__force s5p_gpio_pd_pull_t)0x01) +#define S5P_GPIO_PD_UP_ENABLE ((__force s5p_gpio_pd_pull_t)0x03) + +/** + * s5p_gpio_set_pd_pull() - set the pull-{up,down} of a gpio pin power down mode + * @pin: The pin number to configure the pull resistor. + * @pd_pull: The configuration for the power down mode pull resistor. + * + * This function sets the configuration of the pull-{up,down} resistor for the + * specified pin. It will return 0 if successful, or a negative error + * code if the pin cannot support the requested pull setting. + * +*/ +extern int s5p_gpio_set_pd_pull(unsigned int pin, s5p_gpio_pd_pull_t pd_pull); + +/** + * s5p_gpio_get_pd_pull() - get the power down pull resistor config of gpio pin + * @pin: The pin number to get the settings for + * + * Read the power mode pull resistor value for the specified pin. +*/ +extern s5p_gpio_pd_pull_t s5p_gpio_get_pd_pull(unsigned int pin); + /** * s5p_register_gpio_interrupt() - register interrupt support for a gpio group * @pin: The pin number from the group to be registered diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index 8cad4cf..792fdb0 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -67,7 +67,8 @@ struct s3c_gpio_chip { void __iomem *base; int irq_base; int group; - spinlock_t lock; + unsigned int eint_offset; + spinlock_t lock; #ifdef CONFIG_PM u32 pm_save[4]; #endif @@ -116,6 +117,8 @@ extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip); */ extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip, int nr_chips); +extern void samsung_gpiolib_add_4bit_chips_no_pm(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, @@ -141,9 +144,9 @@ extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; #ifdef CONFIG_S3C_GPIO_TRACK extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; -static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) +static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) { - return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL; + return (pin < S3C_GPIO_END) ? s3c_gpios[pin] : NULL; } #else /* machine specific code should provide s3c_gpiolib_getchip */ diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h index 1543da8..51d52e7 100644 --- a/arch/arm/plat-samsung/include/plat/iic.h +++ b/arch/arm/plat-samsung/include/plat/iic.h @@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c); extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c); extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c); extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c); +extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c); /* defined by architecture to configure gpio */ extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); @@ -71,4 +72,6 @@ extern void s3c_i2c5_cfg_gpio(struct platform_device *dev); extern void s3c_i2c6_cfg_gpio(struct platform_device *dev); extern void s3c_i2c7_cfg_gpio(struct platform_device *dev); +extern struct s3c2410_platform_i2c default_i2c_data; + #endif /* __ASM_ARCH_IIC_H */ diff --git a/arch/arm/plat-samsung/include/plat/iovmm.h b/arch/arm/plat-samsung/include/plat/iovmm.h new file mode 100644 index 0000000..53d2e77 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/iovmm.h @@ -0,0 +1,76 @@ +/* linux/arch/arm/plat-s5p/include/plat/iovmm.h + * + * Copyright (c) 2011 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_IOVMM_H +#define __ASM_PLAT_IOVMM_H + +#ifdef CONFIG_EXYNOS_IOVMM + +struct scatterlist; + +int iovmm_setup(struct device *dev); +void iovmm_cleanup(struct device *dev); +int iovmm_activate(struct device *dev); +void iovmm_deactivate(struct device *dev); + +/* iovmm_map() - Maps a list of physical memory chunks + * @dev: the owner of the IO address space where the mapping is created + * @sg: list of physical memory chunks to map + * @offset: length in bytes where the mapping starts + * @size: how much memory to map in bytes. @offset + @size must not exceed + * total size of @sg + * + * This function returns mapped IO address in the address space of @dev. + * Returns 0 if mapping fails. + * + * The caller of this function must ensure that iovmm_cleanup() is not called + * while this function is called. + * + */ +dma_addr_t iovmm_map(struct device *dev, struct scatterlist *sg, off_t offset, + size_t size); + +/* iovmm_map() - unmaps the given IO address + * @dev: the owner of the IO address space where @iova belongs + * @iova: IO address that needs to be unmapped and freed. + * + * The caller of this function must ensure that iovmm_cleanup() is not called + * while this function is called. + */ +void iovmm_unmap(struct device *dev, dma_addr_t iova); + +/* iovmm_map_oto - create one to one mapping for the given physical address + * @dev: the owner of the IO address space to map + * @phys: physical address to map + * @size: size of the mapping to create + * + * This function return 0 if mapping is successful. Otherwise, minus error + * value. + */ +int iovmm_map_oto(struct device *dev, phys_addr_t phys, size_t size); + +/* iovmm_unmap_oto - remove one to one mapping + * @dev: the owner ofthe IO address space + * @phys: physical address to remove mapping + */ +void iovmm_unmap_oto(struct device *dev, phys_addr_t phys); + +#else +#define iovmm_setup(dev) (-ENOSYS) +#define iovmm_cleanup(dev) do { } while (0) +#define iovmm_activate(dev) (-ENOSYS) +#define iovmm_deactivate(dev) do { } while (0) +#define iovmm_map(dev, sg) (0) +#define iovmm_unmap(dev, iova) do { } while (0) +#define iovmm_map_oto(dev, phys, size) (0) +#define iovmm_unmap_oto(dev, phys) do { } while (0) +#endif /* CONFIG_EXYNOS_IOVMM */ + +#endif /*__ASM_PLAT_IOVMM_H*/ diff --git a/arch/arm/plat-samsung/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h index 3ffac4d..ec28c99 100644 --- a/arch/arm/plat-samsung/include/plat/map-base.h +++ b/arch/arm/plat-samsung/include/plat/map-base.h @@ -14,15 +14,15 @@ #ifndef __ASM_PLAT_MAP_H #define __ASM_PLAT_MAP_H __FILE__ -/* Fit all our registers in at 0xF6000000 upwards, trying to use as - * little of the VA space as possible so vmalloc and friends have a - * better chance of getting memory. +/* Fit all our registers in at CONFIG_S3C_BASE_ADDR upwards, trying to + * use as little of the VA space as possible so vmalloc and friends + * have a better chance of getting memory. * * we try to ensure stuff like the IRQ registers are available for * an single MOVS instruction (ie, only 8 bits of set data) */ -#define S3C_ADDR_BASE 0xF6000000 +#define S3C_ADDR_BASE CONFIG_S3C_ADDR_BASE #ifndef __ASSEMBLY__ #define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x)) @@ -35,8 +35,14 @@ #define S3C_VA_MEM S3C_ADDR(0x00200000) /* memory control */ #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */ #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */ +#define S3C_VA_HSOTG S3C_ADDR(0x00E00000) /* OTG */ +#define S3C_VA_HSPHY S3C_ADDR(0x00F00000) /* OTG PHY */ #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */ +#define S3C_VA_KLOG_BUF S3C_ADDR(0x01100000) /* non-cached log buf */ +#define S3C_VA_SLOG_BUF S3C_ADDR(0x01400000) /* non-cached sched log buf */ +#define S3C_VA_AUXLOG_BUF S3C_ADDR(0x01600000) /* auxiliary log buf */ + /* This is used for the CPU specific mappings that may be needed, so that * they do not need to directly used S3C_ADDR() and thus make it easier to * modify the space for mapping. diff --git a/arch/arm/plat-samsung/include/plat/mshci.h b/arch/arm/plat-samsung/include/plat/mshci.h new file mode 100644 index 0000000..0333500 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/mshci.h @@ -0,0 +1,161 @@ +/* linux/arch/arm/plat-samsung/include/plat/mshci.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * EXYNOS4 - MSHCI (HSMMC) platform data 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 __PLAT_S3C_MSHCI_H +#define __PLAT_S3C_MSHCI_H __FILE__ + +struct platform_device; +struct mmc_host; +struct mmc_card; +struct mmc_ios; + +enum ms_cd_types { + S3C_MSHCI_CD_INTERNAL, /* use mmc internal CD line */ + S3C_MSHCI_CD_EXTERNAL, /* use external callback */ + S3C_MSHCI_CD_GPIO, /* use external gpio pin for CD line */ + S3C_MSHCI_CD_NONE, /* no CD line, use polling to detect card */ + S3C_MSHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */ +}; + +/** + * struct s3c_mshci_platdata() - Platform device data for Samsung MSHCI + * @max_width: The maximum number of data bits supported. + * @host_caps: Standard MMC host capabilities bit field. + * @cd_type: Type of Card Detection method (see cd_types enum above) + * @wp_gpio: The gpio number using for WP. + * @has_wp_gpio: Check using wp_gpio or not. + * @ext_cd_init: Initialize external card detect subsystem. Called on + * mshci-s3c driver probe when cd_type == S3C_MSHCI_CD_EXTERNAL. + * notify_func argument is a callback to the mshci-s3c driver + * that triggers the card detection event. Callback arguments: + * dev is pointer to platform device of the host controller, + * state is new state of the card (0 - removed, 1 - inserted). + * @ext_cd_cleanup: Cleanup external card detect subsystem. Called on + * mshci-s3c driver remove when cd_type == S3C_MSHCI_CD_EXTERNAL. + * notify_func argument is the same callback as for ext_cd_init. + * @ext_cd_gpio: gpio pin used for external CD line, valid only if + * cd_type == S3C_MSHCI_CD_GPIO + * @ext_cd_gpio_invert: invert values for external CD gpio line + * @cfg_gpio: Configure the GPIO for a specific card bit-width + * @cfg_card: Configure the interface for a specific card and speed. This + * is necessary the controllers and/or GPIO blocks require the + * changing of driver-strength and other controls dependant on + * the card and speed of operation. + * + * Initialisation data specific to either the machine or the platform + * for the device driver to use or call-back when configuring gpio or + * card speed information. +*/ +struct s3c_mshci_platdata { + unsigned int max_width; + unsigned int host_caps; + unsigned int host_caps2; + enum ms_cd_types cd_type; + + char **clocks; /* set of clock sources */ + + int wp_gpio; + int ext_cd_gpio; + int int_power_gpio; + int fifo_depth; + bool ext_cd_gpio_invert; + bool has_wp_gpio; + int (*ext_cd_init)(void (*notify_func)(struct platform_device *, + int state)); + int (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *, + int state)); + + void (*cfg_gpio)(struct platform_device *dev, int width); + void (*cfg_ddr)(struct platform_device *dev, int ddr); + void (*init_card)(struct platform_device *dev); + void (*set_power)(struct platform_device *dev, int en); + void (*cfg_card)(struct platform_device *dev, + void __iomem *regbase, + struct mmc_ios *ios, + struct mmc_card *card); + void (*shutdown)(void); +}; + +/** + * s3c_mshci_set_platdata - Set platform data for S3C MSHCI device. + * @pd: Platform data to register to device. + * + * Register the given platform data for use withe S3C MSHCI device. + * The call will copy the platform data, so the board definitions can + * make the structure itself __initdata. + */ +extern void s3c_mshci_set_platdata(struct s3c_mshci_platdata *pd); + +/* Default platform data, exported so that per-cpu initialisation can + * set the correct one when there are more than one cpu type selected. +*/ + +extern struct s3c_mshci_platdata s3c_mshci_def_platdata; + +/* Helper function availablity */ + +extern void s5p6450_setup_mshci_cfg_gpio(struct platform_device *, int w); + +/* S5P6450 MSHCI setup */ +extern char *s5p6450_mshc_clksrcs[1]; + +extern void s5p6450_setup_mshci_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +static inline void s5p6450_default_mshci(void) +{ +#ifdef CONFIG_EXYNOS4_DEV_MSHC + s3c_mshci_def_platdata.clocks = s5p6450_mshc_clksrcs; + s3c_mshci_def_platdata.cfg_gpio = s5p6450_setup_mshci_cfg_gpio; + s3c_mshci_def_platdata.cfg_card = s5p6450_setup_mshci_cfg_card; +#endif /* CONFIG_EXYNOS4_DEV_MSHC */ +} + +extern void exynos4_setup_mshci_cfg_gpio(struct platform_device *, int w); + +/* EXYNOS4 MSHCI setup */ +#ifdef CONFIG_EXYNOS4_SETUP_MSHCI +extern char *exynos4_mshci_clksrcs[1]; +#endif + +extern void exynos4_setup_mshci_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +extern void exynos4_setup_mshci_cfg_ddr(struct platform_device *dev, + int ddr); +extern void exynos4_setup_mshci_init_card(struct platform_device *dev); +extern void exynos4_setup_mshci_shutdown(void); + +extern void exynos4_setup_mshci_set_power(struct platform_device *dev, int en); + +#ifdef CONFIG_EXYNOS4_DEV_MSHC +static inline void exynos4_default_mshci(void) +{ + s3c_mshci_def_platdata.clocks = exynos4_mshci_clksrcs; + s3c_mshci_def_platdata.cfg_gpio = exynos4_setup_mshci_cfg_gpio; + s3c_mshci_def_platdata.cfg_card = exynos4_setup_mshci_cfg_card; + s3c_mshci_def_platdata.cfg_ddr = exynos4_setup_mshci_cfg_ddr; + s3c_mshci_def_platdata.init_card = exynos4_setup_mshci_init_card; + s3c_mshci_def_platdata.set_power = exynos4_setup_mshci_set_power; + s3c_mshci_def_platdata.shutdown = exynos4_setup_mshci_shutdown; +} +#else +static inline void exynos4_default_mshci(void) { } +#endif /* CONFIG_EXYNOS4_DEV_MSHC */ + +#endif /* __PLAT_S3C_MSHCI_H */ diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h index abb4bc3..832a403 100644 --- a/arch/arm/plat-samsung/include/plat/pd.h +++ b/arch/arm/plat-samsung/include/plat/pd.h @@ -11,20 +11,41 @@ #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 exynos4_pd_block { +enum exynos_pd_block { PD_MFC, PD_G3D, PD_LCD0, PD_LCD1, PD_TV, PD_CAM, - PD_GPS + PD_GPS, + PD_GPS_ALIVE, + PD_ISP, + PD_MAUDIO, + PD_GSCL, + PD_DISP1, + PD_TOP, +}; + +struct samsung_pd_info { + int (*init)(struct device *dev); + int (*enable)(struct device *dev); + int (*disable)(struct device *dev); + int (*save)(struct device *dev); + int (*restore)(struct device *dev); + void __iomem *base; + void *data; + enum exynos_pd_block id; +}; + +struct exynos_pd_data { + void __iomem *clk_base; + void __iomem *clksrc_base; + void __iomem *read_base; + unsigned long read_phy_addr; }; +int exynos_pd_init(struct device *dev); +int exynos_pd_enable(struct device *dev); +int exynos_pd_disable(struct device *dev); #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 7fb6f6b..c306634 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -43,6 +43,9 @@ extern unsigned long s3c_irqwake_eintallow; extern void (*pm_cpu_prep)(void); extern void (*pm_cpu_sleep)(void); +extern void (*pm_cpu_restore)(void); +extern int (*pm_prepare)(void); +extern void (*pm_finish)(void); /* Flags for PM Control */ @@ -102,10 +105,12 @@ 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_irq_wake(struct irq_data *data, unsigned int state); extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); extern int s3c24xx_irq_suspend(void); extern void s3c24xx_irq_resume(void); #else +#define s3c_irq_wake NULL #define s3c_irqext_wake NULL #define s3c24xx_irq_suspend NULL #define s3c24xx_irq_resume NULL @@ -128,7 +133,7 @@ extern void s3c_pm_dbg(const char *msg, ...); #define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt) #else -#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt) +#define S3C_PMDBG(fmt...) pr_debug(fmt) #endif #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK @@ -151,10 +156,10 @@ extern void s3c_pm_check_restore(void); extern void s3c_pm_check_cleanup(void); extern void s3c_pm_check_store(void); #else -#define s3c_pm_check_prepare() do { } while(0) -#define s3c_pm_check_restore() do { } while(0) -#define s3c_pm_check_cleanup() do { } while(0) -#define s3c_pm_check_store() do { } while(0) +#define s3c_pm_check_prepare() do { } while (0) +#define s3c_pm_check_restore() do { } while (0) +#define s3c_pm_check_cleanup() do { } while (0) +#define s3c_pm_check_store() do { } while (0) #endif /** @@ -183,3 +188,5 @@ extern void s3c_pm_save_gpios(void); extern void s3c_pm_save_core(void); extern void s3c_pm_restore_core(void); + +extern unsigned long s3c_suspend_wakeup_stat; diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h index 7554c4f..b0759b1 100644 --- a/arch/arm/plat-samsung/include/plat/regs-adc.h +++ b/arch/arm/plat-samsung/include/plat/regs-adc.h @@ -21,16 +21,19 @@ #define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10) #define S3C64XX_ADCUPDN S3C2410_ADCREG(0x14) #define S3C64XX_ADCCLRINT S3C2410_ADCREG(0x18) +#define S5P_ADCMUX S3C2410_ADCREG(0x1C) #define S3C64XX_ADCCLRINTPNDNUP S3C2410_ADCREG(0x20) /* ADCCON Register Bits */ +#define S3C64XX_ADCCON_TSSEL (1<<17) #define S3C64XX_ADCCON_RESSEL (1<<16) #define S3C2410_ADCCON_ECFLG (1<<15) #define S3C2410_ADCCON_PRSCEN (1<<14) #define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6) #define S3C2410_ADCCON_PRSCVLMASK (0xFF<<6) #define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3) +#define S5PV210_ADCCON_SELMUX(x) (((x)&0xF)<<0) #define S3C2410_ADCCON_MUXMASK (0x7<<3) #define S3C2410_ADCCON_STDBM (1<<2) #define S3C2410_ADCCON_READ_START (1<<1) diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h index 4c3647f..9c5534e 100644 --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h +++ b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h @@ -30,9 +30,17 @@ #define VIDCON1_FSTATUS_EVEN (1 << 15) /* Video timing controls */ +#ifdef CONFIG_FB_EXYNOS_FIMD_V8 +#define VIDTCON0 (0x20010) +#define VIDTCON1 (0x20014) +#define VIDTCON2 (0x20018) +#define VIDTCON3 (0x2001C) +#else #define VIDTCON0 (0x10) #define VIDTCON1 (0x14) #define VIDTCON2 (0x18) +#define VIDTCON3 (0x1C) +#endif /* Window position controls */ @@ -43,9 +51,12 @@ #define VIDOSD_BASE (0x40) #define VIDINTCON0 (0x130) +#define VIDINTCON1 (0x134) /* WINCONx */ +#define WINCONx_CSC_CON_EQ709 (1 << 28) +#define WINCONx_CSC_CON_EQ601 (0 << 28) #define WINCONx_CSCWIDTH_MASK (0x3 << 26) #define WINCONx_CSCWIDTH_SHIFT (26) #define WINCONx_CSCWIDTH_WIDE (0x0 << 26) diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h index 8f39aa5..f6c450b 100644 --- a/arch/arm/plat-samsung/include/plat/regs-fb.h +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h @@ -32,12 +32,27 @@ #define VIDCON0 (0x00) #define VIDCON0_INTERLACE (1 << 29) -#define VIDCON0_VIDOUT_MASK (0x3 << 26) + +#ifdef CONFIG_FB_EXYNOS_FIMD_V8 +#define VIDOUT_CON_VIDOUT_UP_MASK (0x1 << 16) +#define VIDOUT_CON_VIDOUT_UP_SHIFT (16) +#define VIDOUT_CON_VIDOUT_UP_ALWAYS (0x0 << 16) +#define VIDOUT_CON_VIDOUT_UP_START_FRAME (0x1 << 16) +#define VIDOUT_CON_VIDOUT_F_MASK (0x7 << 8) +#define VIDOUT_CON_VIDOUT_F_SHIFT (8) +#define VIDOUT_CON_VIDOUT_F_RGB (0x0 << 8) +#define VIDOUT_CON_VIDOUT_F_I80_LDI0 (0x2 << 8) +#define VIDOUT_CON_VIDOUT_F_I80_LDI1 (0x3 << 8) +#define VIDOUT_CON_VIDOUT_F_WB (0x4 << 8) +#endif + +#define VIDCON0_VIDOUT_MASK (0x7 << 26) #define VIDCON0_VIDOUT_SHIFT (26) #define VIDCON0_VIDOUT_RGB (0x0 << 26) #define VIDCON0_VIDOUT_TV (0x1 << 26) #define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) #define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) +#define VIDCON0_VIDOUT_WB (0x4 << 26) #define VIDCON0_L1_DATA_MASK (0x7 << 23) #define VIDCON0_L1_DATA_SHIFT (23) @@ -81,7 +96,17 @@ #define VIDCON0_ENVID (1 << 1) #define VIDCON0_ENVID_F (1 << 0) +#ifdef CONFIG_FB_EXYNOS_FIMD_V8 +#define VIDOUT_CON (0x20000) +#define VIDCON1 (0x20004) +#define REG_TIME2INIT (0x01b4) +#define REG_TIME2SNP (0x01b8) +#define DP_MIE_CLKCON (0x027c) +#define FREERUNCON (0x005c) +#else #define VIDCON1 (0x04) +#endif + #define VIDCON1_LINECNT_MASK (0x7ff << 16) #define VIDCON1_LINECNT_SHIFT (16) #define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff) @@ -90,7 +115,11 @@ #define VIDCON1_VSTATUS_VSYNC (0x0 << 13) #define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13) #define VIDCON1_VSTATUS_ACTIVE (0x2 << 13) -#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13) +#define VIDCON1_VSTATUS_FRONTPORCH (0x3 << 13) +#define VIDCON1_VSTATUS_MASK (0x3 << 13) +#define VIDCON1_VCLK_MASK (0x3 << 9) +#define VIDCON1_VCLK_HOLD (0x0 << 9) +#define VIDCON1_VCLK_RUN (0x1 << 9) #define VIDCON1_INV_VCLK (1 << 7) #define VIDCON1_INV_HSYNC (1 << 6) @@ -99,18 +128,27 @@ /* VIDCON2 */ -#define VIDCON2 (0x08) -#define VIDCON2_EN601 (1 << 23) -#define VIDCON2_TVFMTSEL_SW (1 << 14) - -#define VIDCON2_TVFMTSEL1_MASK (0x3 << 12) -#define VIDCON2_TVFMTSEL1_SHIFT (12) -#define VIDCON2_TVFMTSEL1_RGB (0x0 << 12) -#define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12) -#define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12) - -#define VIDCON2_ORGYCbCr (1 << 8) -#define VIDCON2_YUVORDCrCb (1 << 7) +#define VIDCON2 (0x08) +#define VIDCON2_WB_SKIP_1_2 (1 << 0) +#define VIDCON2_WB_SKIP_1_3 (1 << 1) +#define VIDCON2_WB_SKIP_1_4 (3 << 0) +#define VIDCON2_WB_SKIP_1_5 (1 << 2) +#define VIDCON2_WB_SKIP_MASK (0x1f << 0) +#define VIDCON2_EN601 (1 << 23) +#define VIDCON2_WB_DISABLE (0 << 15) +#define VIDCON2_WB_ENABLE (1 << 15) +#define VIDCON2_WB_MASK (1 << 15) +#define VIDCON2_TVFORMATSEL_HW (0 << 14) +#define VIDCON2_TVFORMATSEL_SW (1 << 14) +#define VIDCON2_TVFORMATSEL_HW_SW_MASK (1 << 14) +#define VIDCON2_TVFORMATSEL_MASK (0x3 << 12) +#define VIDCON2_TVFORMATSEL_SHIFT (12) +#define VIDCON2_TVFORMATSEL_RGB (0x0 << 12) +#define VIDCON2_TVFORMATSEL_YUV422 (0x1 << 12) +#define VIDCON2_TVFORMATSEL_YUV444 (0x2 << 12) + +#define VIDCON2_ORGYCbCr (1 << 8) +#define VIDCON2_YUVORDCrCb (1 << 7) /* PRTCON (S3C6410, S5PC100) * Might not be present in the S3C6410 documentation, @@ -163,24 +201,29 @@ #define VIDTCON1_HSPW_LIMIT (0xff) #define VIDTCON1_HSPW(_x) ((_x) << 0) -#define VIDTCON2 (0x18) +/* VIDTCON2 */ + +#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23) #define VIDTCON2_LINEVAL_MASK (0x7ff << 11) #define VIDTCON2_LINEVAL_SHIFT (11) #define VIDTCON2_LINEVAL_LIMIT (0x7ff) -#define VIDTCON2_LINEVAL(_x) ((_x) << 11) +#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11) +#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22) #define VIDTCON2_HOZVAL_MASK (0x7ff << 0) #define VIDTCON2_HOZVAL_SHIFT (0) #define VIDTCON2_HOZVAL_LIMIT (0x7ff) -#define VIDTCON2_HOZVAL(_x) ((_x) << 0) +#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0) /* WINCONx */ - #define WINCONx_BITSWP (1 << 18) #define WINCONx_BYTSWP (1 << 17) #define WINCONx_HAWSWP (1 << 16) #define WINCONx_WSWP (1 << 15) +#define WINCONx_ENLOCAL_MASK (0xf << 15) +#define WINCONx_INRGB_RGB (0 << 13) +#define WINCONx_INRGB_YCBCR (1 << 13) #define WINCONx_BURSTLEN_MASK (0x3 << 9) #define WINCONx_BURSTLEN_SHIFT (9) #define WINCONx_BURSTLEN_16WORD (0x0 << 9) @@ -200,6 +243,7 @@ #define WINCON0_BPPMODE_24BPP_888 (0xb << 2) #define WINCON1_BLD_PIX (1 << 6) +#define WINCON1_BLD_PLANE (0 << 6) #define WINCON1_ALPHA_SEL (1 << 1) #define WINCON1_BPPMODE_MASK (0xf << 2) @@ -228,25 +272,29 @@ /* Local input channels (windows 0-2) */ #define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) +#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23) #define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) #define VIDOSDxA_TOPLEFT_X_SHIFT (11) #define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) -#define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) +#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11) +#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22) #define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) #define VIDOSDxA_TOPLEFT_Y_SHIFT (0) #define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) -#define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) +#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0) +#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23) #define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) #define VIDOSDxB_BOTRIGHT_X_SHIFT (11) #define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) -#define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) +#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11) +#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22) #define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) #define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) #define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) -#define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) +#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0) /* For VIDOSD[1..4]C */ #define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) @@ -278,15 +326,17 @@ #define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) #define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) +#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27) #define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) #define VIDW_BUF_SIZE_OFFSET_SHIFT (13) #define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) -#define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) +#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13) +#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26) #define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) #define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) #define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) -#define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) +#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0) /* Interrupt controls and status */ @@ -384,3 +434,22 @@ #define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) #define WPALCON_W0PAL_16BPP_565 (0x6 << 0) +/* Clock gate mode control */ +#define REG_CLKGATE_MODE (0x1b0) +#define REG_CLKGATE_MODE_AUTO_CLOCK_GATE (0 << 0) +#define REG_CLKGATE_MODE_NON_CLOCK_GATE (1 << 0) + +/* Blending equation control */ +#define BLENDCON (0x260) +#define BLENDCON_NEW_MASK (1 << 0) +#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0) +#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0) + +/* DP clock control */ +#define DPCLKCON (0x27c) +#define DPCLKCON_ENABLE (1 << 1) + +/* Window alpha control */ +#define VIDW0ALPHA0 (0x200) +#define VIDW0ALPHA1 (0x204) +#define DUALRGB (0x27c) diff --git a/arch/arm/plat-samsung/include/plat/regs-otg.h b/arch/arm/plat-samsung/include/plat/regs-otg.h new file mode 100644 index 0000000..baeda10 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-otg.h @@ -0,0 +1,260 @@ +/* linux/arch/arm/plat-samsung/include/plat/regs-otg.h + * + * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at> + * + * This include file 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 __ASM_ARCH_REGS_USB_OTG_HS_H +#define __ASM_ARCH_REGS_USB_OTG_HS_H + +/* USB2.0 OTG Controller register */ +#define S3C_USBOTG_PHYREG(x) ((x) + S3C_VA_HSPHY) +#define S3C_USBOTG_PHYPWR S3C_USBOTG_PHYREG(0x0) +#define S3C_USBOTG_PHYCLK S3C_USBOTG_PHYREG(0x4) +#define S3C_USBOTG_RSTCON S3C_USBOTG_PHYREG(0x8) +#define S3C_USBOTG_PHYTUNE S3C_USBOTG_PHYREG(0x24) +#define S3C_USBOTG_PHY1CON S3C_USBOTG_PHYREG(0x34) + +/* USB2.0 OTG Controller register */ +#define S3C_USBOTGREG(x) (x) +/*============================================================================================== */ + /* Core Global Registers */ +#define S3C_UDC_OTG_GOTGCTL S3C_USBOTGREG(0x000) /* OTG Control & Status */ +#define S3C_UDC_OTG_GOTGINT S3C_USBOTGREG(0x004) /* OTG Interrupt */ +#define S3C_UDC_OTG_GAHBCFG S3C_USBOTGREG(0x008) /* Core AHB Configuration */ +#define S3C_UDC_OTG_GUSBCFG S3C_USBOTGREG(0x00C) /* Core USB Configuration */ +#define S3C_UDC_OTG_GRSTCTL S3C_USBOTGREG(0x010) /* Core Reset */ +#define S3C_UDC_OTG_GINTSTS S3C_USBOTGREG(0x014) /* Core Interrupt */ +#define S3C_UDC_OTG_GINTMSK S3C_USBOTGREG(0x018) /* Core Interrupt Mask */ +#define S3C_UDC_OTG_GRXSTSR S3C_USBOTGREG(0x01C) /* Receive Status Debug Read/Status Read */ +#define S3C_UDC_OTG_GRXSTSP S3C_USBOTGREG(0x020) /* Receive Status Debug Pop/Status Pop */ +#define S3C_UDC_OTG_GRXFSIZ S3C_USBOTGREG(0x024) /* Receive FIFO Size */ +#define S3C_UDC_OTG_GNPTXFSIZ S3C_USBOTGREG(0x028) /* Non-Periodic Transmit FIFO Size */ +#define S3C_UDC_OTG_GNPTXSTS S3C_USBOTGREG(0x02C) /* Non-Periodic Transmit FIFO/Queue Status */ + +#define S3C_UDC_OTG_HPTXFSIZ S3C_USBOTGREG(0x100) /* Host Periodic Transmit FIFO Size */ +#define S3C_UDC_OTG_DIEPTXF(n) S3C_USBOTGREG(0x104 + (n-1)*0x4)/* Device IN EP Transmit FIFO Size Register */ + +/*============================================================================================== */ +/* Host Mode Registers */ +/*------------------------------------------------ */ +/* Host Global Registers */ +#define S3C_UDC_OTG_HCFG S3C_USBOTGREG(0x400) /* Host Configuration */ +#define S3C_UDC_OTG_HFIR S3C_USBOTGREG(0x404) /* Host Frame Interval */ +#define S3C_UDC_OTG_HFNUM S3C_USBOTGREG(0x408) /* Host Frame Number/Frame Time Remaining */ +#define S3C_UDC_OTG_HPTXSTS S3C_USBOTGREG(0x410) /* Host Periodic Transmit FIFO/Queue Status */ +#define S3C_UDC_OTG_HAINT S3C_USBOTGREG(0x414) /* Host All Channels Interrupt */ +#define S3C_UDC_OTG_HAINTMSK S3C_USBOTGREG(0x418) /* Host All Channels Interrupt Mask */ + +/*------------------------------------------------ */ +/* Host Port Control & Status Registers */ +#define S3C_UDC_OTG_HPRT S3C_USBOTGREG(0x440) /* Host Port Control & Status */ + +/*------------------------------------------------ */ +/* Host Channel-Specific Registers */ +#define S3C_UDC_OTG_HCCHAR0 S3C_USBOTGREG(0x500) /* Host Channel-0 Characteristics */ +#define S3C_UDC_OTG_HCSPLT0 S3C_USBOTGREG(0x504) /* Host Channel-0 Split Control */ +#define S3C_UDC_OTG_HCINT0 S3C_USBOTGREG(0x508) /* Host Channel-0 Interrupt */ +#define S3C_UDC_OTG_HCINTMSK0 S3C_USBOTGREG(0x50C) /* Host Channel-0 Interrupt Mask */ +#define S3C_UDC_OTG_HCTSIZ0 S3C_USBOTGREG(0x510) /* Host Channel-0 Transfer Size */ +#define S3C_UDC_OTG_HCDMA0 S3C_USBOTGREG(0x514) /* Host Channel-0 DMA Address */ + +/*============================================================================================== */ +/* Device Mode Registers */ +/*------------------------------------------------ */ +/* Device Global Registers */ +#define S3C_UDC_OTG_DCFG S3C_USBOTGREG(0x800) /* Device Configuration */ +#define S3C_UDC_OTG_DCTL S3C_USBOTGREG(0x804) /* Device Control */ +#define S3C_UDC_OTG_DSTS S3C_USBOTGREG(0x808) /* Device Status */ +#define S3C_UDC_OTG_DIEPMSK S3C_USBOTGREG(0x810) /* Device IN Endpoint Common Interrupt Mask */ +#define S3C_UDC_OTG_DOEPMSK S3C_USBOTGREG(0x814) /* Device OUT Endpoint Common Interrupt Mask */ +#define S3C_UDC_OTG_DAINT S3C_USBOTGREG(0x818) /* Device All Endpoints Interrupt */ +#define S3C_UDC_OTG_DAINTMSK S3C_USBOTGREG(0x81C) /* Device All Endpoints Interrupt Mask */ +#define S3C_UDC_OTG_DTKNQR1 S3C_USBOTGREG(0x820) /* Device IN Token Sequence Learning Queue Read 1 */ +#define S3C_UDC_OTG_DTKNQR2 S3C_USBOTGREG(0x824) /* Device IN Token Sequence Learning Queue Read 2 */ +#define S3C_UDC_OTG_DVBUSDIS S3C_USBOTGREG(0x828) /* Device VBUS Discharge Time */ +#define S3C_UDC_OTG_DVBUSPULSE S3C_USBOTGREG(0x82C) /* Device VBUS Pulsing Time */ +#define S3C_UDC_OTG_DTKNQR3 S3C_USBOTGREG(0x830) /* Device IN Token Sequence Learning Queue Read 3 */ +#define S3C_UDC_OTG_DTKNQR4 S3C_USBOTGREG(0x834) /* Device IN Token Sequence Learning Queue Read 4 */ + +/*------------------------------------------------ */ +/* Device Logical IN Endpoint-Specific Registers */ +#define S3C_UDC_OTG_DIEPCTL(n) S3C_USBOTGREG(0x900 + n*0x20) /* Device IN Endpoint n Control */ +#define S3C_UDC_OTG_DIEPINT(n) S3C_USBOTGREG(0x908 + n*0x20) /* Device IN Endpoint n Interrupt */ +#define S3C_UDC_OTG_DIEPTSIZ(n) S3C_USBOTGREG(0x910 + n*0x20) /* Device IN Endpoint n Transfer Size */ +#define S3C_UDC_OTG_DIEPDMA(n) S3C_USBOTGREG(0x914 + n*0x20) /* Device IN Endpoint n DMA Address */ + +/*------------------------------------------------ */ +/* Device Logical OUT Endpoint-Specific Registers */ +#define S3C_UDC_OTG_DOEPCTL(n) S3C_USBOTGREG(0xB00 + n*0x20) /* Device OUT Endpoint n Control */ +#define S3C_UDC_OTG_DOEPINT(n) S3C_USBOTGREG(0xB08 + n*0x20) /* Device OUT Endpoint n Interrupt */ +#define S3C_UDC_OTG_DOEPTSIZ(n) S3C_USBOTGREG(0xB10 + n*0x20) /* Device OUT Endpoint n Transfer Size */ +#define S3C_UDC_OTG_DOEPDMA(n) S3C_USBOTGREG(0xB14 + n*0x20) /* Device OUT Endpoint n DMA Address */ + +/*------------------------------------------------ */ +/* Endpoint FIFO address */ +#define S3C_UDC_OTG_EP0_FIFO S3C_USBOTGREG(0x1000) +#define S3C_UDC_OTG_EP1_FIFO S3C_USBOTGREG(0x2000) +#define S3C_UDC_OTG_EP2_FIFO S3C_USBOTGREG(0x3000) +#define S3C_UDC_OTG_EP3_FIFO S3C_USBOTGREG(0x4000) +#define S3C_UDC_OTG_EP4_FIFO S3C_USBOTGREG(0x5000) +#define S3C_UDC_OTG_EP5_FIFO S3C_USBOTGREG(0x6000) +#define S3C_UDC_OTG_EP6_FIFO S3C_USBOTGREG(0x7000) +#define S3C_UDC_OTG_EP7_FIFO S3C_USBOTGREG(0x8000) +#define S3C_UDC_OTG_EP8_FIFO S3C_USBOTGREG(0x9000) +#define S3C_UDC_OTG_EP9_FIFO S3C_USBOTGREG(0xA000) +#define S3C_UDC_OTG_EP10_FIFO S3C_USBOTGREG(0xB000) +#define S3C_UDC_OTG_EP11_FIFO S3C_USBOTGREG(0xC000) +#define S3C_UDC_OTG_EP12_FIFO S3C_USBOTGREG(0xD000) +#define S3C_UDC_OTG_EP13_FIFO S3C_USBOTGREG(0xE000) +#define S3C_UDC_OTG_EP14_FIFO S3C_USBOTGREG(0xF000) +#define S3C_UDC_OTG_EP15_FIFO S3C_USBOTGREG(0x10000) + +/*===================================================================== */ +/*definitions related to CSR setting */ + +/* S3C_UDC_OTG_GOTGCTL */ +#define B_SESSION_VALID (0x1<<19) +#define A_SESSION_VALID (0x1<<18) + +/* S3C_UDC_OTG_GAHBCFG */ +#define PTXFE_HALF (0<<8) +#define PTXFE_ZERO (1<<8) +#define NPTXFE_HALF (0<<7) +#define NPTXFE_ZERO (1<<7) +#define MODE_SLAVE (0<<5) +#define MODE_DMA (1<<5) +#define BURST_SINGLE (0<<1) +#define BURST_INCR (1<<1) +#define BURST_INCR4 (3<<1) +#define BURST_INCR8 (5<<1) +#define BURST_INCR16 (7<<1) +#define GBL_INT_UNMASK (1<<0) +#define GBL_INT_MASK (0<<0) + +/* S3C_UDC_OTG_GRSTCTL */ +#define AHB_MASTER_IDLE (1u<<31) +#define CORE_SOFT_RESET (0x1<<0) + +/* S3C_UDC_OTG_GINTSTS/S3C_UDC_OTG_GINTMSK core interrupt register */ +#define INT_RESUME (1u<<31) +#define INT_DISCONN (0x1<<29) +#define INT_CONN_ID_STS_CNG (0x1<<28) +#define INT_OUT_EP (0x1<<19) +#define INT_IN_EP (0x1<<18) +#define INT_ENUMDONE (0x1<<13) +#define INT_RESET (0x1<<12) +#define INT_SUSPEND (0x1<<11) +#define INT_EARLY_SUSPEND (0x1<<10) +#define INT_NP_TX_FIFO_EMPTY (0x1<<5) +#define INT_RX_FIFO_NOT_EMPTY (0x1<<4) +#define INT_SOF (0x1<<3) +#define INT_DEV_MODE (0x0<<0) +#define INT_HOST_MODE (0x1<<1) +#define INT_GOUTNakEff (0x01<<7) +#define INT_GINNakEff (0x01<<6) + +#define FULL_SPEED_CONTROL_PKT_SIZE 8 +#define FULL_SPEED_BULK_PKT_SIZE 64 + +#define HIGH_SPEED_CONTROL_PKT_SIZE 64 +#define HIGH_SPEED_BULK_PKT_SIZE 512 + +#ifdef CONFIG_CPU_S5P6450 +#define RX_FIFO_SIZE (4096>>2) +#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE +#define NPTX_FIFO_SIZE (4096>>2) +#define PTX_FIFO_SIZE (1520>>2) +#else +#define RX_FIFO_SIZE (4096>>2) +#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE +#define NPTX_FIFO_SIZE (4096>>2) +#define PTX_FIFO_SIZE (1024>>2) +#endif + +/* Enumeration speed */ +#define USB_HIGH_30_60MHZ (0x0<<1) +#define USB_FULL_30_60MHZ (0x1<<1) +#define USB_LOW_6MHZ (0x2<<1) +#define USB_FULL_48MHZ (0x3<<1) + +/* S3C_UDC_OTG_GRXSTSP STATUS */ +#define OUT_PKT_RECEIVED (0x2<<17) +#define OUT_TRANSFER_COMPLELTED (0x3<<17) +#define SETUP_TRANSACTION_COMPLETED (0x4<<17) +#define SETUP_PKT_RECEIVED (0x6<<17) +#define GLOBAL_OUT_NAK (0x1<<17) + +/* S3C_UDC_OTG_DCTL device control register */ +#define NORMAL_OPERATION (0x1<<0) +#define SOFT_DISCONNECT (0x1<<1) +#define TEST_CONTROL_MASK (0x7<<4) +#define TEST_J_MODE (0x1<<4) +#define TEST_K_MODE (0x2<<4) +#define TEST_SE0_NAK_MODE (0x3<<4) +#define TEST_PACKET_MODE (0x4<<4) +#define TEST_FORCE_ENABLE_MODE (0x5<<4) + +/* S3C_UDC_OTG_DAINT device all endpoint interrupt register */ +#define DAINT_OUT_BIT (16) +#define DAINT_MASK (0xFFFF) + +/* S3C_UDC_OTG_DIEPCTL0/DOEPCTL0 device control IN/OUT endpoint 0 control register */ +#define DEPCTL_EPENA (0x1<<31) +#define DEPCTL_EPDIS (0x1<<30) +#define DEPCTL_SETD1PID (0x1<<29) +#define DEPCTL_SETD0PID (0x1<<28) +#define DEPCTL_SNAK (0x1<<27) +#define DEPCTL_CNAK (0x1<<26) +#define DEPCTL_STALL (0x1<<21) +#define DEPCTL_TYPE_BIT (18) +#define DEPCTL_TXFNUM_BIT (22) +#define DEPCTL_TXFNUM_MASK (0xF<<22) +#define DEPCTL_TYPE_MASK (0x3<<18) +#define DEPCTL_CTRL_TYPE (0x0<<18) +#define DEPCTL_ISO_TYPE (0x1<<18) +#define DEPCTL_BULK_TYPE (0x2<<18) +#define DEPCTL_INTR_TYPE (0x3<<18) +#define DEPCTL_NAKSTS (0x1<<17) +#define DEPCTL_USBACTEP (0x1<<15) +#define DEPCTL_NEXT_EP_BIT (11) +#define DEPCTL_MPS_BIT (0) +#define DEPCTL_MPS_MASK (0x7FF) + +#define DEPCTL0_MPS_64 (0x0<<0) +#define DEPCTL0_MPS_32 (0x1<<0) +#define DEPCTL0_MPS_16 (0x2<<0) +#define DEPCTL0_MPS_8 (0x3<<0) +#define DEPCTL_MPS_BULK_512 (512<<0) +#define DEPCTL_MPS_INT_MPS_16 (16<<0) + +#define DIEPCTL0_NEXT_EP_BIT (11) + +/* S3C_UDC_OTG_DIEPCTLn/DOEPCTLn device control IN/OUT endpoint n control register */ + +/* S3C_UDC_OTG_DIEPMSK/DOEPMSK device IN/OUT endpoint common interrupt mask register */ +/* S3C_UDC_OTG_DIEPINTn/DOEPINTn device IN/OUT endpoint interrupt register */ +#define BACK2BACK_SETUP_RECEIVED (0x1<<6) +#define INTKNEPMIS (0x1<<5) +#define INTKN_TXFEMP (0x1<<4) +#define NON_ISO_IN_EP_TIMEOUT (0x1<<3) +#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3) +#define AHB_ERROR (0x1<<2) +#define EPDISBLD (0x1<<1) +#define TRANSFER_DONE (0x1<<0) + +/*DIEPTSIZ0 / DOEPTSIZ0 */ + +/* DEPTSIZ common bit */ +#define DEPTSIZ_PKT_CNT_BIT (19) +#define DEPTSIZ_XFER_SIZE_BIT (0) + +#define DEPTSIZ_SETUP_PKCNT_1 (1<<29) +#define DEPTSIZ_SETUP_PKCNT_2 (2<<29) +#define DEPTSIZ_SETUP_PKCNT_3 (3<<29) + +#endif diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index 116edfe..5adf78f 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -255,6 +255,8 @@ struct s3c24xx_uart_clksrc { * arch/arm/mach-s3c2410/ directory. */ +struct uart_port; + struct s3c2410_uartcfg { unsigned char hwport; /* hardware port number */ unsigned char unused; @@ -269,6 +271,9 @@ struct s3c2410_uartcfg { struct s3c24xx_uart_clksrc *clocks; unsigned int clocks_size; + + void (*wake_peer)(struct uart_port *); + void (*set_runstate)(int onoff); }; /* s3c24xx_uart_devs @@ -282,4 +287,3 @@ extern struct platform_device *s3c24xx_uart_devs[4]; #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARM_REGS_SERIAL_H */ - diff --git a/arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h b/arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h new file mode 100644 index 0000000..50d2954 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-usb3-exynos-drd-phy.h @@ -0,0 +1,75 @@ +/* arch/arm/plat-samsung/include/plat/regs-usb3-exynos-udc-drd.h + * + * Copyright (c) 2011 Samsung Electronics Co. Ltd + * Author: Anton Tikhomirov <av.tikhomirov@samsung.com> + * + * Exynos SuperSpeed USB 3.0 DRD Controller PHY registers + * + * 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 __PLAT_SAMSUNG_REGS_USB3_EXYNOS_DRD_PHY_H +#define __PLAT_SAMSUNG_REGS_USB3_EXYNOS_DRD_PHY_H __FILE__ + +#define EXYNOS_USB3_PHYREG(x) ((x) + S5P_VA_SS_PHY) + + +#define EXYNOS_USB3_LINKSYSTEM EXYNOS_USB3_PHYREG(0x04) +#define EXYNOS_USB3_PHYUTMI EXYNOS_USB3_PHYREG(0x08) + +#define EXYNOS_USB3_PHYUTMI_OTGDISABLE (1 << 6) +#define EXYNOS_USB3_PHYUTMI_FORCESUSPEND (1 << 1) +#define EXYNOS_USB3_PHYUTMI_FORCESLEEP (1 << 0) + +#define EXYNOS_USB3_PHYPIPE EXYNOS_USB3_PHYREG(0x0C) + + +#define EXYNOS_USB3_PHYCLKRST EXYNOS_USB3_PHYREG(0x10) + +#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_MASK (0xff << 23) +#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_SHIFT (23) +#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_LIMIT (0xff) +#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(_x) ((_x) << 23) + +#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) +#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_SHIFT (21) +#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_LIMIT (0x03) +#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) + +#define EXYNOS_USB3_PHYCLKRST_SSC_EN (1 << 20) +#define EXYNOS_USB3_PHYCLKRST_REF_SSP_EN (1 << 19) +#define EXYNOS_USB3_PHYCLKRST_REF_CLKDIV2 (1 << 18) + +#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) +#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_SHIFT (11) +#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_LIMIT (0x7f) +#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(_x) ((_x) << 11) + +#define EXYNOS_USB3_PHYCLKRST_FSEL_MASK (0x3f << 5) +#define EXYNOS_USB3_PHYCLKRST_FSEL_SHIFT (5) +#define EXYNOS_USB3_PHYCLKRST_FSEL_LIMIT (0x3f) +#define EXYNOS_USB3_PHYCLKRST_FSEL(_x) ((_x) << 5) + +#define EXYNOS_USB3_PHYCLKRST_RETENABLEN (1 << 4) + +#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) +#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_SHIFT (2) +#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_LIMIT (0x03) +#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL(_x) ((_x) << 2) + +#define EXYNOS_USB3_PHYCLKRST_PORTRESET (1 << 1) +#define EXYNOS_USB3_PHYCLKRST_COMMONONN (1 << 0) + +#define EXYNOS_USB3_PHYREG0 EXYNOS_USB3_PHYREG(0x14) +#define EXYNOS_USB3_PHYREG1 EXYNOS_USB3_PHYREG(0x18) +#define EXYNOS_USB3_PHYPARAM0 EXYNOS_USB3_PHYREG(0x1C) +#define EXYNOS_USB3_PHYPARAM1 EXYNOS_USB3_PHYREG(0x20) +#define EXYNOS_USB3_PHYTERM EXYNOS_USB3_PHYREG(0x24) +#define EXYNOS_USB3_PHYTEST EXYNOS_USB3_PHYREG(0x28) +#define EXYNOS_USB3_PHYADP EXYNOS_USB3_PHYREG(0x2C) +#define EXYNOS_USB3_PHYBATCHG EXYNOS_USB3_PHYREG(0x30) +#define EXYNOS_USB3_PHYRESUME EXYNOS_USB3_PHYREG(0x34) +#define EXYNOS_USB3_LINKPORT EXYNOS_USB3_PHYREG(0x44) +#endif /* __PLAT_SAMSUNG_REGS_USB3_EXYNOS_DRD_PHY_H */ diff --git a/arch/arm/plat-samsung/include/plat/rtc-core.h b/arch/arm/plat-samsung/include/plat/rtc-core.h new file mode 100644 index 0000000..65967ca --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/rtc-core.h @@ -0,0 +1,28 @@ +/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Samsung RTC Device core function + * + * This program is free software; you can redistribute it and/or modify + * it under the term of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __ASM_PLAT_RTC_CORE_H +#define __ASM_PLAT_RTC_CORE_H __FILE__ + +/* These function are only for use with the core support code, such as + * the cpu specific initialization code + */ + +/* re-define device name depending on support. */ +static inline void s3c_rtc_setname(char *name) +{ +#ifdef CONFIG_S3C_DEV_RTC + s3c_device_rtc.name = name; +#endif +} + +#endif /* __ASM_PLAT_RTC_CORE_H */ diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h index 8107442..ee155ad 100644 --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h @@ -84,6 +84,23 @@ enum dma_ch { DMACH_SLIMBUS4_TX, DMACH_SLIMBUS5_RX, DMACH_SLIMBUS5_TX, + DMACH_MIPI_HSI0, + DMACH_MIPI_HSI1, + DMACH_MIPI_HSI2, + DMACH_MIPI_HSI3, + DMACH_MIPI_HSI4, + DMACH_MIPI_HSI5, + DMACH_MIPI_HSI6, + DMACH_MIPI_HSI7, + DMACH_DISP1, + DMACH_MTOM_0, + DMACH_MTOM_1, + DMACH_MTOM_2, + DMACH_MTOM_3, + DMACH_MTOM_4, + DMACH_MTOM_5, + DMACH_MTOM_6, + DMACH_MTOM_7, /* END Marker, also used to denote a reserved channel */ DMACH_MAX, }; @@ -93,6 +110,11 @@ static inline bool s3c_dma_has_circular(void) return true; } +static inline bool s3c_dma_has_infiniteloop(void) +{ + return true; +} + #include <plat/dma.h> #endif /* __S3C_DMA_PL330_H_ */ diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index 4c16fa3..353ceb6 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -71,5 +71,6 @@ extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); +extern void exynos_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); #endif /* __S3C64XX_PLAT_SPI_H */ diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index 058e096..c0e3799 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h @@ -18,6 +18,8 @@ #ifndef __PLAT_S3C_SDHCI_H #define __PLAT_S3C_SDHCI_H __FILE__ +/* ignore mmc suspend/resume for BCM WIFI */ +#define S3C_SDHCI_PM_IGNORE_SUSPEND_RESUME (1 << 30) struct platform_device; struct mmc_host; struct mmc_card; @@ -72,8 +74,11 @@ struct s3c_sdhci_platdata { char **clocks; /* set of clock sources */ + char *vmmc_name; /* name for regulator */ int ext_cd_gpio; bool ext_cd_gpio_invert; + unsigned int pm_flags; + int (*ext_cd_init)(void (*notify_func)(struct platform_device *, int state)); int (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *, @@ -84,6 +89,10 @@ struct s3c_sdhci_platdata { void __iomem *regbase, struct mmc_ios *ios, struct mmc_card *card); +#ifdef CONFIG_MACH_PX + int (*ext_pdev)(struct platform_device *dev_id); +#endif + }; /** @@ -126,6 +135,10 @@ extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w); +extern void exynos5_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void exynos5_setup_sdhci1_cfg_gpio(struct platform_device *, int w); +extern void exynos5_setup_sdhci2_cfg_gpio(struct platform_device *, int w); +extern void exynos5_setup_sdhci3_cfg_gpio(struct platform_device *, int w); /* S3C2416 SDHCI setup */ @@ -390,4 +403,58 @@ static inline void exynos4_default_sdhci3(void) { } #endif /* CONFIG_EXYNOS4_SETUP_SDHCI */ +extern void mmc_force_presence_change(struct platform_device *pdev); + +/* EXYNOS5 SDHCI setup */ +#ifdef CONFIG_EXYNOS4_SETUP_SDHCI +extern char *exynos4_hsmmc_clksrcs[4]; + +extern void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, + void __iomem *r, + struct mmc_ios *ios, + struct mmc_card *card); + +static inline void exynos5_default_sdhci0(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC + s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs; + s3c_hsmmc0_def_platdata.cfg_gpio = exynos5_setup_sdhci0_cfg_gpio; + s3c_hsmmc0_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card; +#endif +} + +static inline void exynos5_default_sdhci1(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC1 + s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs; + s3c_hsmmc1_def_platdata.cfg_gpio = exynos5_setup_sdhci1_cfg_gpio; + s3c_hsmmc1_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card; +#endif +} + +static inline void exynos5_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs; + s3c_hsmmc2_def_platdata.cfg_gpio = exynos5_setup_sdhci2_cfg_gpio; + s3c_hsmmc2_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card; +#endif +} + +static inline void exynos5_default_sdhci3(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC3 + s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs; + s3c_hsmmc3_def_platdata.cfg_gpio = exynos5_setup_sdhci3_cfg_gpio; + s3c_hsmmc3_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card; +#endif +} + +#else +static inline void exynos5_default_sdhci0(void) { } +static inline void exynos5_default_sdhci1(void) { } +static inline void exynos5_default_sdhci2(void) { } +static inline void exynos5_default_sdhci3(void) { } + +#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */ #endif /* __PLAT_S3C_SDHCI_H */ diff --git a/arch/arm/plat-samsung/include/plat/sysmmu.h b/arch/arm/plat-samsung/include/plat/sysmmu.h new file mode 100644 index 0000000..bbe2091 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/sysmmu.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung System MMU driver for Exynos platforms + * + * 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_SYSMMU_H +#define __ASM__PLAT_SYSMMU_H __FILE__ + +#include <linux/list.h> +#include <linux/atomic.h> +#include <linux/spinlock.h> + +enum exynos_sysmmu_inttype { + SYSMMU_PAGEFAULT, + SYSMMU_AR_MULTIHIT, + SYSMMU_AW_MULTIHIT, + SYSMMU_BUSERROR, + SYSMMU_AR_SECURITY, + SYSMMU_AR_ACCESS, + SYSMMU_AW_SECURITY, + SYSMMU_AW_PROTECTION, /* 7 */ + SYSMMU_FAULT_UNKNOWN, + SYSMMU_FAULTS_NUM +}; + +/* + * @itype: type of fault. + * @pgtable_base: the physical address of page table base. This is 0 if @itype + * is SYSMMU_BUSERROR. + * @fault_addr: the device (virtual) address that the System MMU tried to + * translated. This is 0 if @itype is SYSMMU_BUSERROR. + */ +typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, + unsigned long pgtable_base, unsigned long fault_addr); + +#ifdef CONFIG_EXYNOS_IOMMU +/** + * exynos_sysmmu_enable() - enable system mmu + * @owner: The device whose System MMU is about to be enabled. + * @pgd: Base physical address of the 1st level page table + * + * This function enable system mmu to transfer address + * from virtual address to physical address. + * Return non-zero if it fails to enable System MMU. + */ +int exynos_sysmmu_enable(struct device *owner, unsigned long pgd); + +/** + * exynos_sysmmu_disable() - disable sysmmu mmu of ip + * @owner: The device whose System MMU is about to be disabled. + * + * This function disable system mmu to transfer address + * from virtual address to physical address + */ +bool exynos_sysmmu_disable(struct device *owner); + +/** + * exynos_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu + * @owner: The device whose System MMU. + * + * This function flush all TLB entry in system mmu + */ +void exynos_sysmmu_tlb_invalidate(struct device *owner); + +/** exynos_sysmmu_set_fault_handler() - Fault handler for System MMUs + * Called when interrupt occurred by the System MMUs + * The device drivers of peripheral devices that has a System MMU can implement + * a fault handler to resolve address translation fault by System MMU. + * The meanings of return value and parameters are described below. + * + * return value: non-zero if the fault is correctly resolved. + * zero if the fault is not handled. + */ +void exynos_sysmmu_set_fault_handler(struct device *sysmmu, + sysmmu_fault_handler_t handler); + +/** exynos_sysmmu_set_prefbuf() - Initialize prefetch buffers of System MMU v3 + * @owner: The device which need to set the prefetch buffers + * @base0: The start virtual address of the area of the @owner device that the + * first prefetch buffer loads translation descriptors + * @size0: The last virtual address of the area of the @owner device that the + * first prefetch buffer loads translation descriptors. + * @base1: The start virtual address of the area of the @owner device that the + * second prefetch buffer loads translation descriptors. This will be + * ignored if @size1 is 0 and this function assigns the 2 prefetch + * buffers with each half of the area specified by @base0 and @size0 + * @size1: The last virtual address of the area of the @owner device that the + * prefetch buffer loads translation descriptors. This can be 0. See + * the description of @base1 for more information with @size1 = 0 + */ +void exynos_sysmmu_set_prefbuf(struct device *owner, + unsigned long base0, unsigned long size0, + unsigned long base1, unsigned long size1); +#else /* CONFIG_EXYNOS_IOMMU */ +#define exynos_sysmmu_enable(owner, pgd) do { } while (0) +#define exynos_sysmmu_disable(owner) do { } while (0) +#define exynos_sysmmu_tlb_invalidate(owner) do { } while (0) +#define exynos_sysmmu_set_fault_handler(sysmmu, handler) do { } while (0) +#define exynos_sysmmu_set_prefbuf(owner, b0, s0, b1, s1) do { } while (0) +#endif +#endif /* __ASM_PLAT_SYSMMU_H */ diff --git a/arch/arm/plat-samsung/include/plat/ts.h b/arch/arm/plat-samsung/include/plat/ts.h index 26fdb22..3fb52b9 100644 --- a/arch/arm/plat-samsung/include/plat/ts.h +++ b/arch/arm/plat-samsung/include/plat/ts.h @@ -14,10 +14,16 @@ struct s3c2410_ts_mach_info { int delay; int presc; int oversampling_shift; + + int cal_x_max; + int cal_y_max; + int cal_param[7]; + void (*cfg_gpio)(struct platform_device *dev); }; extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *); +extern void s3c24xx_ts1_set_platdata(struct s3c2410_ts_mach_info *); /* defined by architecture to configure gpio */ extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev); diff --git a/arch/arm/plat-samsung/include/plat/tv-core.h b/arch/arm/plat-samsung/include/plat/tv-core.h new file mode 100644 index 0000000..d647eec --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/tv-core.h @@ -0,0 +1,37 @@ +/* + * arch/arm/plat-samsung/include/plat/tv.h + * + * Copyright 2011 Samsung Electronics Co., Ltd. + * Tomasz Stanislawski <t.stanislaws@samsung.com> + * + * Samsung TV 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 __SAMSUNG_PLAT_TV_H +#define __SAMSUNG_PLAT_TV_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 s5p_hdmi_setname(char *name) +{ +#ifdef CONFIG_S5P_DEV_TV + s5p_device_hdmi.name = name; +#endif +} + +static inline void s5p_mixer_setname(char *name) +{ +#ifdef CONFIG_S5P_DEV_TV + s5p_device_mixer.name = name; +#endif +} + +#endif /* __SAMSUNG_PLAT_TV_H */ diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/arch/arm/plat-samsung/include/plat/udc-hs.h index a22a4f2..9b90b08 100644 --- a/arch/arm/plat-samsung/include/plat/udc-hs.h +++ b/arch/arm/plat-samsung/include/plat/udc-hs.h @@ -27,3 +27,14 @@ struct s3c_hsotg_plat { enum s3c_hsotg_dmamode dma; unsigned int is_osc : 1; }; + +typedef enum usb_cable_status { + USB_CABLE_DETACHED = 0, + USB_CABLE_ATTACHED, + USB_OTGHOST_DETACHED, + USB_OTGHOST_ATTACHED, + USB_POWERED_HOST_DETACHED, + USB_POWERED_HOST_ATTACHED, + USB_CABLE_DETACHED_WITHOUT_NOTI, +} usb_cable_status; + diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h index 54b762a..4dc5adf 100644 --- a/arch/arm/plat-samsung/include/plat/watchdog-reset.h +++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h @@ -10,26 +10,24 @@ * published by the Free Software Foundation. */ +#include <plat/clock.h> #include <plat/regs-watchdog.h> #include <mach/map.h> +#include <linux/kernel.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> static inline void arch_wdt_reset(void) { - struct clk *wdtclk; - printk("arch_reset: attempting watchdog reset\n"); __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ - wdtclk = clk_get(NULL, "watchdog"); - if (!IS_ERR(wdtclk)) { - clk_enable(wdtclk); - } else - printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__); + if (s3c2410_wdtclk) + clk_enable(s3c2410_wdtclk); /* put initial values into count and data */ __raw_writel(0x80, S3C2410_WTCNT); diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c index 657405c..384f131 100644 --- a/arch/arm/plat-samsung/irq-uart.c +++ b/arch/arm/plat-samsung/irq-uart.c @@ -23,6 +23,7 @@ #include <plat/irq-uart.h> #include <plat/regs-serial.h> #include <plat/cpu.h> +#include <asm/mach/irq.h> /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] * are consecutive when looking up the interrupt in the demux routines. @@ -32,6 +33,12 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) struct s3c_uart_irq *uirq = desc->irq_data.handler_data; u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); int base = uirq->base_irq; + struct irq_chip *chip = irq_get_chip(irq); + + chained_irq_enter(chip, desc); + + if (!(pend & 0xf)) + do_bad_IRQ(irq, desc); if (pend & (1 << 0)) generic_handle_irq(base); @@ -41,6 +48,8 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) generic_handle_irq(base + 2); if (pend & (1 << 3)) generic_handle_irq(base + 3); + + chained_irq_exit(chip, desc); } static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) @@ -65,6 +74,8 @@ static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_set_bit; ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_mask_ack = irq_gc_mask_and_ack_set; + ct->chip.irq_disable = irq_gc_mask_and_ack_set; ct->regs.ack = S3C64XX_UINTP; ct->regs.mask = S3C64XX_UINTM; irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE, diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index f714d06..7837f48 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -21,10 +21,15 @@ #include <mach/map.h> #include <plat/irq-vic-timer.h> #include <plat/regs-timer.h> +#include <asm/mach/irq.h> static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) { + struct irq_chip *chip = irq_get_chip(irq); + + chained_irq_enter(chip, desc); generic_handle_irq((int)desc->irq_data.handler_data); + chained_irq_exit(chip, desc); } /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c index efe1d56..2d40889 100644 --- a/arch/arm/plat-samsung/pd.c +++ b/arch/arm/plat-samsung/pd.c @@ -22,12 +22,22 @@ static int samsung_pd_probe(struct platform_device *pdev) { struct samsung_pd_info *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; + int ret = 0; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } + pdata->id = pdev->id; + if (pdata->init) { + ret = pdata->init(dev); + if (ret) { + dev_err(dev, "init fails"); + return ret; + } + } + pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -43,6 +53,32 @@ static int __devexit samsung_pd_remove(struct platform_device *pdev) return 0; } +static int samsung_pd_suspend(struct device *dev) +{ + struct samsung_pd_info *pdata = dev->platform_data; + int ret = 0; + + if (pdata->save) + ret = pdata->save(dev); + + dev_dbg(dev, "suspended\n"); + + return ret; +} + +static int samsung_pd_resume(struct device *dev) +{ + struct samsung_pd_info *pdata = dev->platform_data; + int ret = 0; + + if (pdata->restore) + ret = pdata->restore(dev); + + dev_dbg(dev, "resumed\n"); + + return ret; +} + static int samsung_pd_runtime_suspend(struct device *dev) { struct samsung_pd_info *pdata = dev->platform_data; @@ -51,7 +87,7 @@ static int samsung_pd_runtime_suspend(struct device *dev) if (pdata->disable) ret = pdata->disable(dev); - dev_dbg(dev, "suspended\n"); + dev_dbg(dev, "runtime suspended\n"); return ret; } @@ -63,11 +99,13 @@ static int samsung_pd_runtime_resume(struct device *dev) if (pdata->enable) ret = pdata->enable(dev); - dev_dbg(dev, "resumed\n"); + dev_dbg(dev, "runtime resumed\n"); return ret; } static const struct dev_pm_ops samsung_pd_pm_ops = { + .suspend = samsung_pd_suspend, + .resume = samsung_pd_resume, .runtime_suspend = samsung_pd_runtime_suspend, .runtime_resume = samsung_pd_runtime_resume, }; diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c index 9652820..c365b40 100644 --- a/arch/arm/plat-samsung/pm-gpio.c +++ b/arch/arm/plat-samsung/pm-gpio.c @@ -21,6 +21,7 @@ #include <plat/gpio-core.h> #include <plat/pm.h> +#include <plat/cpu.h> /* PM GPIO helpers */ @@ -318,6 +319,26 @@ static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip) pm->save(ourchip); } +static int s3c_get_gpio_max_nr (void) +{ + static int gpio_max_nr = 0; + + if (unlikely(!gpio_max_nr)) { + if (soc_is_exynos4210()) + gpio_max_nr = EXYNOS4210_GPIO_END; + else if (soc_is_exynos4212() || soc_is_exynos4412()) + gpio_max_nr = EXYNOS4212_GPIO_END; + else if (soc_is_exynos5210()) + gpio_max_nr = EXYNOS5210_GPIO_END; + else if (soc_is_exynos5250()) + gpio_max_nr = EXYNOS5250_GPIO_END; + else + gpio_max_nr = S3C_GPIO_END; + } + + return gpio_max_nr; +} + /** * s3c_pm_save_gpios() - Save the state of the GPIO banks. * @@ -328,9 +349,12 @@ void s3c_pm_save_gpios(void) { struct s3c_gpio_chip *ourchip; unsigned int gpio_nr; + unsigned int gpio_max_nr; - for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { - ourchip = s3c_gpiolib_getchip(gpio_nr); + gpio_max_nr = s3c_get_gpio_max_nr(); + + for (gpio_nr = 0; gpio_nr < gpio_max_nr;) { + ourchip = s3c_gpiolib_getchip(gpio_nr); if (!ourchip) { gpio_nr++; continue; @@ -368,8 +392,11 @@ void s3c_pm_restore_gpios(void) { struct s3c_gpio_chip *ourchip; unsigned int gpio_nr; + unsigned int gpio_max_nr; + + gpio_max_nr = s3c_get_gpio_max_nr(); - for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { + for (gpio_nr = 0; gpio_nr < gpio_max_nr;) { ourchip = s3c_gpiolib_getchip(gpio_nr); if (!ourchip) { gpio_nr++; diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c index 5c0a440..e46ecce 100644 --- a/arch/arm/plat-samsung/pm.c +++ b/arch/arm/plat-samsung/pm.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/serial_core.h> #include <linux/io.h> +#include <linux/power/charger-manager.h> #include <asm/cacheflush.h> #include <mach/hardware.h> @@ -32,6 +33,7 @@ #include <mach/pm-core.h> /* for external use */ +unsigned long s3c_suspend_wakeup_stat; unsigned long s3c_pm_flags; @@ -53,7 +55,9 @@ void s3c_pm_dbg(const char *fmt, ...) vsprintf(buff, fmt, va); va_end(va); +#ifdef CONFIG_DEBUG_LL printascii(buff); +#endif } static inline void s3c_pm_debug_init(void) @@ -63,7 +67,7 @@ static inline void s3c_pm_debug_init(void) } #else -#define s3c_pm_debug_init() do { } while(0) +#define s3c_pm_debug_init() do { } while (0) #endif /* CONFIG_SAMSUNG_PM_DEBUG */ @@ -186,8 +190,13 @@ void s3c_pm_do_save(struct sleep_save *ptr, int count) void s3c_pm_do_restore(struct sleep_save *ptr, int count) { for (; count > 0; count--, ptr++) { - printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n", +#if defined(CONFIG_CPU_EXYNOS4210) + S3C_PMDBG("restore %p (restore %08lx, was %08x)\n", + ptr->reg, ptr->val, __raw_readl(ptr->reg)); +#else + S3C_PMDBG("restore %p (restore %08lx, was %08x)\n", ptr->reg, ptr->val, __raw_readl(ptr->reg)); +#endif __raw_writel(ptr->val, ptr->reg); } @@ -206,8 +215,13 @@ void s3c_pm_do_restore(struct sleep_save *ptr, int count) void s3c_pm_do_restore_core(struct sleep_save *ptr, int count) { - for (; count > 0; count--, ptr++) + for (; count > 0; count--, ptr++) { +#if !defined(CONFIG_CPU_EXYNOS4210) + pr_debug("restore_core %p (restore %08lx, was %08x)\n", + ptr->reg, ptr->val, __raw_readl(ptr->reg)); +#endif __raw_writel(ptr->val, ptr->reg); + } } /* s3c2410_pm_show_resume_irqs @@ -223,15 +237,16 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start, which &= ~mask; for (i = 0; i <= 31; i++) { - if (which & (1L<<i)) { + if (which & (1L<<i)) S3C_PMDBG("IRQ %d asserted at resume\n", start+i); - } } } - void (*pm_cpu_prep)(void); void (*pm_cpu_sleep)(void); +void (*pm_cpu_restore)(void); +int (*pm_prepare)(void); +void (*pm_finish)(void); #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) @@ -268,6 +283,7 @@ static int s3c_pm_enter(suspend_state_t state) /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); + s3c_pm_saved_gpios(); s3c_pm_save_uarts(); s3c_pm_save_core(); @@ -294,24 +310,35 @@ static int s3c_pm_enter(suspend_state_t state) s3c_pm_arch_stop_clocks(); + printk(KERN_ALERT "PM: SLEEP\n"); + /* s3c_cpu_save will also act as our return point from when * we resume as it saves its own register state and restores it * during the resume. */ + printk(KERN_ALERT "ARM_COREx_STATUS CORE1[0x%08x], CORE2[0x%08x], CORE3[0x%08x]\n", + __raw_readl(S5P_VA_PMU + 0x2084), + __raw_readl(S5P_VA_PMU + 0x2104), + __raw_readl(S5P_VA_PMU + 0x2184)); + s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET); /* restore the cpu state using the kernel's cpu init code. */ cpu_init(); - /* restore the system state */ - s3c_pm_restore_core(); s3c_pm_restore_uarts(); s3c_pm_restore_gpios(); + s3c_pm_restored_gpios(); s3c_pm_debug_init(); + /* restore the system state */ + + if (pm_cpu_restore) + pm_cpu_restore(); + /* check what irq (if any) restored the system */ s3c_pm_arch_show_resume_irqs(); @@ -334,19 +361,43 @@ static int s3c_pm_prepare(void) /* prepare check area if configured */ s3c_pm_check_prepare(); + + if (pm_prepare) + pm_prepare(); + return 0; } static void s3c_pm_finish(void) { + if (pm_finish) + pm_finish(); + s3c_pm_check_cleanup(); } +#if defined(CONFIG_CHARGER_MANAGER) +static bool s3c_cm_suspend_again(void) +{ + bool ret; + + if (!is_charger_manager_active()) + return false; + + ret = cm_suspend_again(); + + return ret; +} +#endif + static const struct platform_suspend_ops s3c_pm_ops = { .enter = s3c_pm_enter, .prepare = s3c_pm_prepare, .finish = s3c_pm_finish, .valid = suspend_valid_only_mem, +#if defined(CONFIG_CHARGER_MANAGER) + .suspend_again = s3c_cm_suspend_again, +#endif }; /* s3c_pm_init @@ -358,7 +409,7 @@ static const struct platform_suspend_ops s3c_pm_ops = { int __init s3c_pm_init(void) { - printk("S3C Power Management, Copyright 2004 Simtec Electronics\n"); + printk(KERN_INFO "S3C Power Management, Copyright 2004 Simtec Electronics\n"); suspend_set_ops(&s3c_pm_ops); return 0; diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c index f37457c..bdc892a 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/arch/arm/plat-samsung/pwm.c @@ -19,10 +19,12 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/pwm.h> +#include <linux/gpio.h> #include <mach/map.h> #include <plat/regs-timer.h> +#include <plat/gpio-cfg.h> struct pwm_device { struct list_head list; @@ -39,11 +41,28 @@ struct pwm_device { unsigned char running; unsigned char use_count; unsigned char pwm_id; + + unsigned long tcfg0; +}; + +struct s3c_pwm_pdata { + /* PWM output port */ + unsigned int gpio_no; + const char *gpio_name; + unsigned int gpio_set_value; }; +struct s3c_pwm_pdata *to_pwm_pdata(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return (struct s3c_pwm_pdata *)pdev->dev.platform_data; +} + #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) static struct clk *clk_scaler[2]; +static DEFINE_SPINLOCK(pwm_spin_lock); static inline int pwm_is_tdiv(struct pwm_device *pwm) { @@ -108,15 +127,21 @@ int pwm_enable(struct pwm_device *pwm) unsigned long flags; unsigned long tcon; - local_irq_save(flags); + spin_lock_irqsave(&pwm_spin_lock, flags); - tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_start(pwm); - __raw_writel(tcon, S3C2410_TCON); + if (!pwm->running) { + clk_enable(pwm->clk); + clk_enable(pwm->clk_div); + + tcon = __raw_readl(S3C2410_TCON); + tcon |= pwm_tcon_start(pwm); + __raw_writel(tcon, S3C2410_TCON); - local_irq_restore(flags); + pwm->running = 1; + } + + spin_unlock_irqrestore(&pwm_spin_lock, flags); - pwm->running = 1; return 0; } @@ -127,15 +152,19 @@ void pwm_disable(struct pwm_device *pwm) unsigned long flags; unsigned long tcon; - local_irq_save(flags); + spin_lock_irqsave(&pwm_spin_lock, flags); - tcon = __raw_readl(S3C2410_TCON); - tcon &= ~pwm_tcon_start(pwm); - __raw_writel(tcon, S3C2410_TCON); + if (pwm->running) { + tcon = __raw_readl(S3C2410_TCON); + tcon &= ~pwm_tcon_start(pwm); + __raw_writel(tcon, S3C2410_TCON); - local_irq_restore(flags); + clk_disable(pwm->clk); + clk_disable(pwm->clk_div); + pwm->running = 0; + } - pwm->running = 0; + spin_unlock_irqrestore(&pwm_spin_lock, flags); } EXPORT_SYMBOL(pwm_disable); @@ -185,6 +214,9 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) /* The TCMP and TCNT can be read without a lock, they're not * shared between the timers. */ + clk_enable(pwm->clk); + clk_enable(pwm->clk_div); + tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id)); tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); @@ -227,12 +259,13 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) /* Update the PWM register block. */ - local_irq_save(flags); + spin_lock_irqsave(&pwm_spin_lock, flags); __raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id)); __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); tcon = __raw_readl(S3C2410_TCON); + tcon |= pwm_tcon_invert(pwm); tcon |= pwm_tcon_manulupdate(pwm); tcon |= pwm_tcon_autoreload(pwm); __raw_writel(tcon, S3C2410_TCON); @@ -240,7 +273,10 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) tcon &= ~pwm_tcon_manulupdate(pwm); __raw_writel(tcon, S3C2410_TCON); - local_irq_restore(flags); + spin_unlock_irqrestore(&pwm_spin_lock, flags); + + clk_disable(pwm->clk); + clk_disable(pwm->clk_div); return 0; } @@ -263,11 +299,21 @@ static int s3c_pwm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct pwm_device *pwm; - unsigned long flags; - unsigned long tcon; + struct s3c_pwm_pdata *pdata = to_pwm_pdata(dev); unsigned int id = pdev->id; int ret; + if (gpio_is_valid(pdata->gpio_no)) { + ret = gpio_request(pdata->gpio_no, pdata->gpio_name); + if (ret) + printk(KERN_ERR "failed to get GPIO for PWM0\n"); + s3c_gpio_cfgpin(pdata->gpio_no, pdata->gpio_set_value); + + /* Inserting the following for commit 2010.02.26: [BACKLIGHT] Fix PWM + driver handling GPIO routine (request but not free)*/ + gpio_free(pdata->gpio_no); + } + if (id == 4) { dev_err(dev, "TIMER4 is currently not supported\n"); return -ENXIO; @@ -299,15 +345,6 @@ static int s3c_pwm_probe(struct platform_device *pdev) goto err_clk_tin; } - local_irq_save(flags); - - tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_invert(pwm); - __raw_writel(tcon, S3C2410_TCON); - - local_irq_restore(flags); - - ret = pwm_register(pwm); if (ret) { dev_err(dev, "failed to register pwm\n"); @@ -359,18 +396,24 @@ static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) pwm->period_ns = 0; pwm->duty_ns = 0; + clk_enable(pwm->clk); + + pwm->tcfg0 = __raw_readl(S3C2410_TCFG0); + + clk_disable(pwm->clk); + return 0; } static int s3c_pwm_resume(struct platform_device *pdev) { struct pwm_device *pwm = platform_get_drvdata(pdev); - unsigned long tcon; - /* Restore invertion */ - tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_invert(pwm); - __raw_writel(tcon, S3C2410_TCON); + clk_enable(pwm->clk); + + __raw_writel(pwm->tcfg0, S3C2410_TCFG0); + + clk_disable(pwm->clk); return 0; } diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c index f85638c..92f30f7 100644 --- a/arch/arm/plat-samsung/s3c-pl330.c +++ b/arch/arm/plat-samsung/s3c-pl330.c @@ -17,6 +17,9 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/err.h> +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) +#include <linux/pm_runtime.h> +#endif #include <asm/hardware/pl330.h> @@ -498,9 +501,11 @@ static void s3c_pl330_rq(struct s3c_pl330_chan *ch, spin_lock_irqsave(&res_lock, flags); - r->x = NULL; + if (!r->infiniteloop) { + r->x = NULL; - s3c_pl330_submit(ch, r); + s3c_pl330_submit(ch, r); + } spin_unlock_irqrestore(&res_lock, flags); @@ -513,12 +518,20 @@ static void s3c_pl330_rq(struct s3c_pl330_chan *ch, res = S3C2410_RES_ERR; /* If last request had some xfer */ - if (xl) { - xfer = container_of(xl, struct s3c_pl330_xfer, px); - _finish_off(xfer, res, 0); + if (!r->infiniteloop) { + if (xl) { + xfer = container_of(xl, struct s3c_pl330_xfer, px); + _finish_off(xfer, res, 0); + } else { + dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n", + __func__, __LINE__); + } } else { - dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n", - __func__, __LINE__); + /* Do callback */ + + xfer = container_of(xl, struct s3c_pl330_xfer, px); + if (ch->callback_fn) + ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res); } } @@ -660,8 +673,8 @@ ctrl_exit: } EXPORT_SYMBOL(s3c2410_dma_ctrl); -int s3c2410_dma_enqueue(enum dma_ch id, void *token, - dma_addr_t addr, int size) +int s3c2410_dma_enqueue_ring(enum dma_ch id, void *token, + dma_addr_t addr, int size, int numofblock) { struct s3c_pl330_chan *ch; struct s3c_pl330_xfer *xfer; @@ -669,7 +682,6 @@ int s3c2410_dma_enqueue(enum dma_ch id, void *token, int idx, ret = 0; spin_lock_irqsave(&res_lock, flags); - ch = id_to_chan(id); /* Error if invalid or free channel */ @@ -709,11 +721,13 @@ int s3c2410_dma_enqueue(enum dma_ch id, void *token, /* Try submitting on either request */ idx = (ch->lrq == &ch->req[0]) ? 1 : 0; - if (!ch->req[idx].x) + if (!ch->req[idx].x) { + ch->req[idx].infiniteloop = numofblock; s3c_pl330_submit(ch, &ch->req[idx]); - else + } else { + ch->req[1 - idx].infiniteloop = numofblock; s3c_pl330_submit(ch, &ch->req[1 - idx]); - + } spin_unlock_irqrestore(&res_lock, flags); if (ch->options & S3C2410_DMAF_AUTOSTART) @@ -726,7 +740,7 @@ enq_exit: return ret; } -EXPORT_SYMBOL(s3c2410_dma_enqueue); +EXPORT_SYMBOL(s3c2410_dma_enqueue_ring); int s3c2410_dma_request(enum dma_ch id, struct s3c2410_dma_client *client, @@ -747,9 +761,24 @@ int s3c2410_dma_request(enum dma_ch id, dmac = ch->dmac; +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* enable the power domain */ + spin_unlock_irqrestore(&res_lock, flags); + pm_runtime_get_sync(dmac->pi->dev); + spin_lock_irqsave(&res_lock, flags); +#endif + clk_enable(dmac->clk); + ch->pl330_chan_id = pl330_request_channel(dmac->pi); if (!ch->pl330_chan_id) { chan_release(ch); + clk_disable(dmac->clk); +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* disable the power domain */ + spin_unlock_irqrestore(&res_lock, flags); + pm_runtime_put(dmac->pi->dev); + spin_lock_irqsave(&res_lock, flags); +#endif ret = -EBUSY; goto req_exit; } @@ -860,7 +889,14 @@ int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client) pl330_release_channel(ch->pl330_chan_id); ch->pl330_chan_id = NULL; + clk_disable(ch->dmac->clk); +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* disable the power domain */ + spin_unlock_irqrestore(&res_lock, flags); + pm_runtime_put(ch->dmac->pi->dev); + spin_lock_irqsave(&res_lock, flags); +#endif chan_release(ch); free_exit: @@ -986,6 +1022,18 @@ int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source, ch->rqcfg.src_inc = 1; ch->rqcfg.dst_inc = 0; break; + case S3C_DMA_MEM2MEM: + ch->req[0].rqtype = MEMTOMEM; + ch->req[1].rqtype = MEMTOMEM; + ch->rqcfg.src_inc = 1; + ch->rqcfg.dst_inc = 1; + break; + case S3C_DMA_MEM2MEM_SET: + ch->req[0].rqtype = MEMTOMEM; + ch->req[1].rqtype = MEMTOMEM; + ch->rqcfg.src_inc = 0; + ch->rqcfg.dst_inc = 1; + break; default: ret = -EINVAL; goto devcfg_exit; @@ -1057,6 +1105,16 @@ static int pl330_probe(struct platform_device *pdev) goto probe_err1; } +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* to use the runtime PM helper functions */ + pm_runtime_enable(&pdev->dev); + /* enable the power domain */ + if (pm_runtime_get_sync(&pdev->dev)) { + dev_err(&pdev->dev, "failed to get runtime pm\n"); + ret = -ENODEV; + goto probe_err1; + } +#endif request_mem_region(res->start, resource_size(res), pdev->name); pl330_info->base = ioremap(res->start, resource_size(res)); @@ -1131,6 +1189,11 @@ static int pl330_probe(struct platform_device *pdev) pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); + clk_disable(s3c_pl330_dmac->clk); +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* disable the power domain */ + pm_runtime_put(&pdev->dev); +#endif return 0; probe_err8: @@ -1147,6 +1210,11 @@ probe_err3: iounmap(pl330_info->base); probe_err2: release_mem_region(res->start, resource_size(res)); +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* disable the power domain */ + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); +#endif probe_err1: kfree(pl330_info); @@ -1156,7 +1224,7 @@ probe_err1: static int pl330_remove(struct platform_device *pdev) { struct s3c_pl330_dmac *dmac, *d; - struct s3c_pl330_chan *ch; + struct s3c_pl330_chan *ch, *ch_tmp; unsigned long flags; int del, found; @@ -1180,7 +1248,7 @@ static int pl330_remove(struct platform_device *pdev) dmac = d; /* Remove all Channels that are managed only by this DMAC */ - list_for_each_entry(ch, &chan_list, node) { + list_for_each_entry_safe(ch, ch_tmp, &chan_list, node) { /* Only channels that are handled by this DMAC */ if (iface_of_dmac(dmac, ch->id)) @@ -1205,15 +1273,20 @@ static int pl330_remove(struct platform_device *pdev) } /* Disable operation clock */ - clk_disable(dmac->clk); clk_put(dmac->clk); /* Remove the DMAC */ list_del(&dmac->node); kfree(dmac); +#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)) + /* disable the power domain */ spin_unlock_irqrestore(&res_lock, flags); - + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); +#else + spin_unlock_irqrestore(&res_lock, flags); +#endif return 0; } |