diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx')
| -rw-r--r-- | arch/arm/plat-s3c24xx/Kconfig | 107 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/Makefile | 30 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/clock.c | 461 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/common-smdk.c | 200 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/cpu.c | 330 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/devs.c | 600 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/dma.c | 1498 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/gpio.c | 188 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/irq.c | 800 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/pm-simtec.c | 66 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/pm.c | 633 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/s3c244x-irq.c | 145 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/s3c244x.c | 184 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/s3c244x.h | 25 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/sleep.S | 157 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/time.c | 262 |
16 files changed, 0 insertions, 5686 deletions
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig deleted file mode 100644 index b972f36d547..00000000000 --- a/arch/arm/plat-s3c24xx/Kconfig +++ /dev/null @@ -1,107 +0,0 @@ -# arch/arm/plat-s3c24xx/Kconfig -# -# Copyright 2007 Simtec Electronics -# -# Licensed under GPLv2 - -config PLAT_S3C24XX - bool - depends on ARCH_S3C2410 - default y if ARCH_S3C2410 - select NO_IOPORT - help - Base platform code for any Samsung S3C device - -if PLAT_S3C24XX - -config CPU_S3C244X - bool - depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442) - help - Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems. - -config PM_SIMTEC - bool - help - Common power management code for systems that are - compatible with the Simtec style of power management - -config S3C2410_BOOT_WATCHDOG - bool "S3C2410 Initialisation watchdog" - depends on ARCH_S3C2410 && S3C2410_WATCHDOG - help - Say y to enable the watchdog during the kernel decompression - stage. If the kernel fails to uncompress, then the watchdog - will trigger a reset and the system should restart. - -config S3C2410_BOOT_ERROR_RESET - bool "S3C2410 Reboot on decompression error" - depends on ARCH_S3C2410 - help - Say y here to use the watchdog to reset the system if the - kernel decompressor detects an error during decompression. - -config S3C2410_PM_DEBUG - bool "S3C2410 PM Suspend debug" - depends on ARCH_S3C2410 && PM - help - Say Y here if you want verbose debugging from the PM Suspend and - Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> - for more information. - -config S3C2410_PM_CHECK - bool "S3C2410 PM Suspend Memory CRC" - depends on ARCH_S3C2410 && PM && CRC32 - help - Enable the PM code's memory area checksum over sleep. This option - will generate CRCs of all blocks of memory, and store them before - going to sleep. The blocks are then checked on resume for any - errors. - - Note, this can take several seconds depending on memory size - and CPU speed. - - See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> - -config S3C2410_PM_CHECK_CHUNKSIZE - int "S3C2410 PM Suspend CRC Chunksize (KiB)" - depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK - default 64 - help - Set the chunksize in Kilobytes of the CRC for checking memory - corruption over suspend and resume. A smaller value will mean that - the CRC data block will take more memory, but wil identify any - faults with better precision. - - See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> - -config S3C2410_LOWLEVEL_UART_PORT - int "S3C2410 UART to use for low-level messages" - default 0 - help - Choice of which UART port to use for the low-level messages, - such as the `Uncompressing...` at start time. The value of - this configuration should be between zero and two. The port - must have been initialised by the boot-loader before use. - -config S3C2410_DMA - bool "S3C2410 DMA support" - depends on ARCH_S3C2410 - help - S3C2410 DMA support. This is needed for drivers like sound which - use the S3C2410's DMA system to move data to and from the - peripheral blocks. - -config S3C2410_DMA_DEBUG - bool "S3C2410 DMA support debug" - depends on ARCH_S3C2410 && S3C2410_DMA - help - Enable debugging output for the DMA code. This option sends info - to the kernel log, at priority KERN_DEBUG. - -config MACH_SMDK - bool - help - Common machine code for SMDK2410 and SMDK2440 - -endif diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile deleted file mode 100644 index 8e5ccaa1f03..00000000000 --- a/arch/arm/plat-s3c24xx/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# arch/arm/plat-s3c24xx/Makefile -# -# Copyright 2007 Simtec Electronics -# -# Licensed under GPLv2 - -obj-y := -obj-m := -obj-n := -obj- := - - -# Core files - -obj-y += cpu.o -obj-y += irq.o -obj-y += devs.o -obj-y += gpio.o -obj-y += time.o -obj-y += clock.o - -# Architecture dependant builds - -obj-$(CONFIG_CPU_S3C244X) += s3c244x.o -obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o -obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += sleep.o -obj-$(CONFIG_S3C2410_DMA) += dma.o -obj-$(CONFIG_MACH_SMDK) += common-smdk.o diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c deleted file mode 100644 index 79cda0faec8..00000000000 --- a/arch/arm/plat-s3c24xx/clock.c +++ /dev/null @@ -1,461 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/clock.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C24XX Core clock control support - * - * Based on, and code from linux/arch/arm/mach-versatile/clock.c - ** - ** Copyright (C) 2004 ARM Limited. - ** Written by Deep Blue Solutions Limited. - * - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/sysdev.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/clk.h> -#include <linux/mutex.h> -#include <linux/delay.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> - -#include <asm/arch/regs-clock.h> -#include <asm/arch/regs-gpio.h> - -#include <asm/plat-s3c24xx/clock.h> -#include <asm/plat-s3c24xx/cpu.h> - -/* clock information */ - -static LIST_HEAD(clocks); - -DEFINE_MUTEX(clocks_mutex); - -/* enable and disable calls for use with the clk struct */ - -static int clk_null_enable(struct clk *clk, int enable) -{ - return 0; -} - -/* 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->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - 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; - } - } - } - - mutex_unlock(&clocks_mutex); - return clk; -} - -void clk_put(struct clk *clk) -{ - module_put(clk->owner); -} - -int clk_enable(struct clk *clk) -{ - if (IS_ERR(clk) || clk == NULL) - return -EINVAL; - - clk_enable(clk->parent); - - mutex_lock(&clocks_mutex); - - if ((clk->usage++) == 0) - (clk->enable)(clk, 1); - - mutex_unlock(&clocks_mutex); - return 0; -} - -void clk_disable(struct clk *clk) -{ - if (IS_ERR(clk) || clk == NULL) - return; - - mutex_lock(&clocks_mutex); - - if ((--clk->usage) == 0) - (clk->enable)(clk, 0); - - mutex_unlock(&clocks_mutex); - clk_disable(clk->parent); -} - - -unsigned long clk_get_rate(struct clk *clk) -{ - if (IS_ERR(clk)) - return 0; - - if (clk->rate != 0) - return clk->rate; - - if (clk->get_rate != NULL) - return (clk->get_rate)(clk); - - if (clk->parent != NULL) - return clk_get_rate(clk->parent); - - return clk->rate; -} - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (!IS_ERR(clk) && clk->round_rate) - return (clk->round_rate)(clk, rate); - - return rate; -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - - if (IS_ERR(clk)) - return -EINVAL; - - mutex_lock(&clocks_mutex); - ret = (clk->set_rate)(clk, rate); - mutex_unlock(&clocks_mutex); - - return ret; -} - -struct clk *clk_get_parent(struct clk *clk) -{ - return clk->parent; -} - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - int ret = 0; - - if (IS_ERR(clk)) - return -EINVAL; - - mutex_lock(&clocks_mutex); - - if (clk->set_parent) - ret = (clk->set_parent)(clk, parent); - - mutex_unlock(&clocks_mutex); - - return ret; -} - -EXPORT_SYMBOL(clk_get); -EXPORT_SYMBOL(clk_put); -EXPORT_SYMBOL(clk_enable); -EXPORT_SYMBOL(clk_disable); -EXPORT_SYMBOL(clk_get_rate); -EXPORT_SYMBOL(clk_round_rate); -EXPORT_SYMBOL(clk_set_rate); -EXPORT_SYMBOL(clk_get_parent); -EXPORT_SYMBOL(clk_set_parent); - -/* base clocks */ - -struct clk clk_xtal = { - .name = "xtal", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_mpll = { - .name = "mpll", - .id = -1, -}; - -struct clk clk_upll = { - .name = "upll", - .id = -1, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_f = { - .name = "fclk", - .id = -1, - .rate = 0, - .parent = &clk_mpll, - .ctrlbit = 0, -}; - -struct clk clk_h = { - .name = "hclk", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_p = { - .name = "pclk", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, -}; - -struct clk clk_usb_bus = { - .name = "usb-bus", - .id = -1, - .rate = 0, - .parent = &clk_upll, -}; - -/* clocks that could be registered by external code */ - -static int s3c24xx_dclk_enable(struct clk *clk, int enable) -{ - unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (enable) - dclkcon |= clk->ctrlbit; - else - dclkcon &= ~clk->ctrlbit; - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - -static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long dclkcon; - unsigned int uclk; - - if (parent == &clk_upll) - uclk = 1; - else if (parent == &clk_p) - uclk = 0; - else - return -EINVAL; - - clk->parent = parent; - - dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; - } else { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; - } - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - - -static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long mask; - unsigned long source; - - /* calculate the MISCCR setting for the clock */ - - if (parent == &clk_xtal) - source = S3C2410_MISCCR_CLK0_MPLL; - else if (parent == &clk_upll) - source = S3C2410_MISCCR_CLK0_UPLL; - else if (parent == &clk_f) - source = S3C2410_MISCCR_CLK0_FCLK; - else if (parent == &clk_h) - source = S3C2410_MISCCR_CLK0_HCLK; - else if (parent == &clk_p) - source = S3C2410_MISCCR_CLK0_PCLK; - else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) - source = S3C2410_MISCCR_CLK0_DCLK0; - else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) - source = S3C2410_MISCCR_CLK0_DCLK0; - else - return -EINVAL; - - clk->parent = parent; - - if (clk == &s3c24xx_dclk0) - mask = S3C2410_MISCCR_CLK0_MASK; - else { - source <<= 4; - mask = S3C2410_MISCCR_CLK1_MASK; - } - - s3c2410_modify_misccr(mask, source); - return 0; -} - -/* external clock definitions */ - -struct clk s3c24xx_dclk0 = { - .name = "dclk0", - .id = -1, - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, - .enable = s3c24xx_dclk_enable, - .set_parent = s3c24xx_dclk_setparent, -}; - -struct clk s3c24xx_dclk1 = { - .name = "dclk1", - .id = -1, - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, - .enable = s3c24xx_dclk_enable, - .set_parent = s3c24xx_dclk_setparent, -}; - -struct clk s3c24xx_clkout0 = { - .name = "clkout0", - .id = -1, - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_clkout1 = { - .name = "clkout1", - .id = -1, - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_uclk = { - .name = "uclk", - .id = -1, -}; - -/* initialise the clock system */ - -int s3c24xx_register_clock(struct clk *clk) -{ - clk->owner = THIS_MODULE; - - if (clk->enable == NULL) - clk->enable = clk_null_enable; - - /* add to the list of available clocks */ - - mutex_lock(&clocks_mutex); - list_add(&clk->list, &clocks); - mutex_unlock(&clocks_mutex); - - return 0; -} - -int s3c24xx_register_clocks(struct clk **clks, int nr_clks) -{ - int fails = 0; - - for (; nr_clks > 0; nr_clks--, clks++) { - if (s3c24xx_register_clock(*clks) < 0) - fails++; - } - - return fails; -} - -/* initalise all the clocks */ - -int __init s3c24xx_setup_clocks(unsigned long xtal, - unsigned long fclk, - unsigned long hclk, - unsigned long pclk) -{ - printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); - - /* initialise the main system clocks */ - - clk_xtal.rate = xtal; - clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); - - clk_mpll.rate = fclk; - clk_h.rate = hclk; - clk_p.rate = pclk; - clk_f.rate = fclk; - - /* assume uart clocks are correctly setup */ - - /* register our clocks */ - - if (s3c24xx_register_clock(&clk_xtal) < 0) - printk(KERN_ERR "failed to register master xtal\n"); - - if (s3c24xx_register_clock(&clk_mpll) < 0) - printk(KERN_ERR "failed to register mpll clock\n"); - - if (s3c24xx_register_clock(&clk_upll) < 0) - printk(KERN_ERR "failed to register upll clock\n"); - - if (s3c24xx_register_clock(&clk_f) < 0) - printk(KERN_ERR "failed to register cpu fclk\n"); - - if (s3c24xx_register_clock(&clk_h) < 0) - printk(KERN_ERR "failed to register cpu hclk\n"); - - if (s3c24xx_register_clock(&clk_p) < 0) - printk(KERN_ERR "failed to register cpu pclk\n"); - - return 0; -} diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c deleted file mode 100644 index 908efa7d745..00000000000 --- a/arch/arm/plat-s3c24xx/common-smdk.c +++ /dev/null @@ -1,200 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/common-smdk.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Common code for SMDK2410 and SMDK2440 boards - * - * http://www.fluff.org/ben/smdk2440/ - * - * 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/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/platform_device.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/nand_ecc.h> -#include <linux/mtd/partitions.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> - -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/irq.h> - -#include <asm/arch/regs-gpio.h> -#include <asm/arch/leds-gpio.h> - -#include <asm/arch/nand.h> - -#include <asm/plat-s3c24xx/common-smdk.h> -#include <asm/plat-s3c24xx/devs.h> -#include <asm/plat-s3c24xx/pm.h> - -/* LED devices */ - -static struct s3c24xx_led_platdata smdk_pdata_led4 = { - .gpio = S3C2410_GPF4, - .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, - .name = "led4", - .def_trigger = "timer", -}; - -static struct s3c24xx_led_platdata smdk_pdata_led5 = { - .gpio = S3C2410_GPF5, - .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, - .name = "led5", - .def_trigger = "nand-disk", -}; - -static struct s3c24xx_led_platdata smdk_pdata_led6 = { - .gpio = S3C2410_GPF6, - .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, - .name = "led6", -}; - -static struct s3c24xx_led_platdata smdk_pdata_led7 = { - .gpio = S3C2410_GPF7, - .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, - .name = "led7", -}; - -static struct platform_device smdk_led4 = { - .name = "s3c24xx_led", - .id = 0, - .dev = { - .platform_data = &smdk_pdata_led4, - }, -}; - -static struct platform_device smdk_led5 = { - .name = "s3c24xx_led", - .id = 1, - .dev = { - .platform_data = &smdk_pdata_led5, - }, -}; - -static struct platform_device smdk_led6 = { - .name = "s3c24xx_led", - .id = 2, - .dev = { - .platform_data = &smdk_pdata_led6, - }, -}; - -static struct platform_device smdk_led7 = { - .name = "s3c24xx_led", - .id = 3, - .dev = { - .platform_data = &smdk_pdata_led7, - }, -}; - -/* NAND parititon from 2.4.18-swl5 */ - -static struct mtd_partition smdk_default_nand_part[] = { - [0] = { - .name = "Boot Agent", - .size = SZ_16K, - .offset = 0, - }, - [1] = { - .name = "S3C2410 flash partition 1", - .offset = 0, - .size = SZ_2M, - }, - [2] = { - .name = "S3C2410 flash partition 2", - .offset = SZ_4M, - .size = SZ_4M, - }, - [3] = { - .name = "S3C2410 flash partition 3", - .offset = SZ_8M, - .size = SZ_2M, - }, - [4] = { - .name = "S3C2410 flash partition 4", - .offset = SZ_1M * 10, - .size = SZ_4M, - }, - [5] = { - .name = "S3C2410 flash partition 5", - .offset = SZ_1M * 14, - .size = SZ_1M * 10, - }, - [6] = { - .name = "S3C2410 flash partition 6", - .offset = SZ_1M * 24, - .size = SZ_1M * 24, - }, - [7] = { - .name = "S3C2410 flash partition 7", - .offset = SZ_1M * 48, - .size = SZ_16M, - } -}; - -static struct s3c2410_nand_set smdk_nand_sets[] = { - [0] = { - .name = "NAND", - .nr_chips = 1, - .nr_partitions = ARRAY_SIZE(smdk_default_nand_part), - .partitions = smdk_default_nand_part, - }, -}; - -/* choose a set of timings which should suit most 512Mbit - * chips and beyond. -*/ - -static struct s3c2410_platform_nand smdk_nand_info = { - .tacls = 20, - .twrph0 = 60, - .twrph1 = 20, - .nr_sets = ARRAY_SIZE(smdk_nand_sets), - .sets = smdk_nand_sets, -}; - -/* devices we initialise */ - -static struct platform_device __initdata *smdk_devs[] = { - &s3c_device_nand, - &smdk_led4, - &smdk_led5, - &smdk_led6, - &smdk_led7, -}; - -void __init smdk_machine_init(void) -{ - /* Configure the LEDs (even if we have no LED support)*/ - - s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP); - s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP); - s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP); - s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP); - - s3c2410_gpio_setpin(S3C2410_GPF4, 1); - s3c2410_gpio_setpin(S3C2410_GPF5, 1); - s3c2410_gpio_setpin(S3C2410_GPF6, 1); - s3c2410_gpio_setpin(S3C2410_GPF7, 1); - - s3c_device_nand.dev.platform_data = &smdk_nand_info; - - platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs)); - - s3c2410_pm_init(); -} diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c deleted file mode 100644 index 8ce4904d313..00000000000 --- a/arch/arm/plat-s3c24xx/cpu.c +++ /dev/null @@ -1,330 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/cpu.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * http://www.simtec.co.uk/products/SWLINUX/ - * Ben Dooks <ben@simtec.co.uk> - * - * S3C24XX CPU Support - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/serial_core.h> -#include <linux/platform_device.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/delay.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-serial.h> - -#include <asm/plat-s3c24xx/cpu.h> -#include <asm/plat-s3c24xx/devs.h> -#include <asm/plat-s3c24xx/clock.h> -#include <asm/plat-s3c24xx/s3c2400.h> -#include <asm/plat-s3c24xx/s3c2410.h> -#include <asm/plat-s3c24xx/s3c2412.h> -#include "s3c244x.h" -#include <asm/plat-s3c24xx/s3c2440.h> -#include <asm/plat-s3c24xx/s3c2442.h> -#include <asm/plat-s3c24xx/s3c2443.h> - -struct cpu_table { - unsigned long idcode; - unsigned long idmask; - void (*map_io)(struct map_desc *mach_desc, int size); - void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no); - void (*init_clocks)(int xtal); - int (*init)(void); - const char *name; -}; - -/* table of supported CPUs */ - -static const char name_s3c2400[] = "S3C2400"; -static const char name_s3c2410[] = "S3C2410"; -static const char name_s3c2412[] = "S3C2412"; -static const char name_s3c2440[] = "S3C2440"; -static const char name_s3c2442[] = "S3C2442"; -static const char name_s3c2443[] = "S3C2443"; -static const char name_s3c2410a[] = "S3C2410A"; -static const char name_s3c2440a[] = "S3C2440A"; - -static struct cpu_table cpu_ids[] __initdata = { - { - .idcode = 0x32410000, - .idmask = 0xffffffff, - .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, - .init_uarts = s3c2410_init_uarts, - .init = s3c2410_init, - .name = name_s3c2410 - }, - { - .idcode = 0x32410002, - .idmask = 0xffffffff, - .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, - .init_uarts = s3c2410_init_uarts, - .init = s3c2410_init, - .name = name_s3c2410a - }, - { - .idcode = 0x32440000, - .idmask = 0xffffffff, - .map_io = s3c244x_map_io, - .init_clocks = s3c244x_init_clocks, - .init_uarts = s3c244x_init_uarts, - .init = s3c2440_init, - .name = name_s3c2440 - }, - { - .idcode = 0x32440001, - .idmask = 0xffffffff, - .map_io = s3c244x_map_io, - .init_clocks = s3c244x_init_clocks, - .init_uarts = s3c244x_init_uarts, - .init = s3c2440_init, - .name = name_s3c2440a - }, - { - .idcode = 0x32440aaa, - .idmask = 0xffffffff, - .map_io = s3c244x_map_io, - .init_clocks = s3c244x_init_clocks, - .init_uarts = s3c244x_init_uarts, - .init = s3c2442_init, - .name = name_s3c2442 - }, - { - .idcode = 0x32412001, - .idmask = 0xffffffff, - .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, - .init_uarts = s3c2412_init_uarts, - .init = s3c2412_init, - .name = name_s3c2412, - }, - { /* a newer version of the s3c2412 */ - .idcode = 0x32412003, - .idmask = 0xffffffff, - .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, - .init_uarts = s3c2412_init_uarts, - .init = s3c2412_init, - .name = name_s3c2412, - }, - { - .idcode = 0x32443001, - .idmask = 0xffffffff, - .map_io = s3c2443_map_io, - .init_clocks = s3c2443_init_clocks, - .init_uarts = s3c2443_init_uarts, - .init = s3c2443_init, - .name = name_s3c2443, - }, - { - .idcode = 0x0, /* S3C2400 doesn't have an idcode */ - .idmask = 0xffffffff, - .map_io = s3c2400_map_io, - .init_clocks = s3c2400_init_clocks, - .init_uarts = s3c2400_init_uarts, - .init = s3c2400_init, - .name = name_s3c2400 - }, -}; - -/* minimal IO mapping */ - -static struct map_desc s3c_iodesc[] __initdata = { - IODESC_ENT(GPIO), - IODESC_ENT(IRQ), - IODESC_ENT(MEMCTRL), - IODESC_ENT(UART) -}; - - -static struct cpu_table * -s3c_lookup_cpu(unsigned long idcode) -{ - struct cpu_table *tab; - int count; - - tab = cpu_ids; - for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) { - if ((idcode & tab->idmask) == tab->idcode) - return tab; - } - - return NULL; -} - -/* cpu information */ - -static struct cpu_table *cpu; - -static unsigned long s3c24xx_read_idcode_v5(void) -{ -#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) - return __raw_readl(S3C2412_GSTATUS1); -#else - return 1UL; /* don't look like an 2400 */ -#endif -} - -static unsigned long s3c24xx_read_idcode_v4(void) -{ -#ifndef CONFIG_CPU_S3C2400 - return __raw_readl(S3C2410_GSTATUS1); -#else - return 0UL; -#endif -} - -void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) -{ - unsigned long idcode = 0x0; - - /* initialise the io descriptors we need for initialisation */ - iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); - - if (cpu_architecture() >= CPU_ARCH_ARMv5) { - idcode = s3c24xx_read_idcode_v5(); - } else { - idcode = s3c24xx_read_idcode_v4(); - } - - cpu = s3c_lookup_cpu(idcode); - - if (cpu == NULL) { - printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode); - panic("Unknown S3C24XX CPU"); - } - - printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); - - if (cpu->map_io == NULL || cpu->init == NULL) { - printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); - panic("Unsupported S3C24XX CPU"); - } - - (cpu->map_io)(mach_desc, size); -} - -/* s3c24xx_init_clocks - * - * Initialise the clock subsystem and associated information from the - * given master crystal value. - * - * xtal = 0 -> use default PLL crystal value (normally 12MHz) - * != 0 -> PLL crystal value in Hz -*/ - -void __init s3c24xx_init_clocks(int xtal) -{ - if (xtal == 0) - xtal = 12*1000*1000; - - if (cpu == NULL) - panic("s3c24xx_init_clocks: no cpu setup?\n"); - - if (cpu->init_clocks == NULL) - panic("s3c24xx_init_clocks: cpu has no clock init\n"); - else - (cpu->init_clocks)(xtal); -} - -/* uart management */ - -static int nr_uarts __initdata = 0; - -static struct s3c2410_uartcfg uart_cfgs[3]; - -/* s3c24xx_init_uartdevs - * - * copy the specified platform data and configuration into our central - * set of devices, before the data is thrown away after the init process. - * - * This also fills in the array passed to the serial driver for the - * early initialisation of the console. -*/ - -void __init s3c24xx_init_uartdevs(char *name, - struct s3c24xx_uart_resources *res, - struct s3c2410_uartcfg *cfg, int no) -{ - struct platform_device *platdev; - struct s3c2410_uartcfg *cfgptr = uart_cfgs; - struct s3c24xx_uart_resources *resp; - int uart; - - memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); - - for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { - platdev = s3c24xx_uart_src[cfgptr->hwport]; - - resp = res + cfgptr->hwport; - - s3c24xx_uart_devs[uart] = platdev; - - platdev->name = name; - platdev->resource = resp->resources; - platdev->num_resources = resp->nr_resources; - - platdev->dev.platform_data = cfgptr; - } - - nr_uarts = no; -} - -void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - if (cpu == NULL) - return; - - if (cpu->init_uarts == NULL) { - printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); - } else - (cpu->init_uarts)(cfg, no); -} - -static int __init s3c_arch_init(void) -{ - int ret; - - // do the correct init for cpu - - if (cpu == NULL) - panic("s3c_arch_init: NULL cpu\n"); - - ret = (cpu->init)(); - if (ret != 0) - return ret; - - ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); - return ret; -} - -arch_initcall(s3c_arch_init); diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c deleted file mode 100644 index 0fe53b39cb2..00000000000 --- a/arch/arm/plat-s3c24xx/devs.c +++ /dev/null @@ -1,600 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/devs.c - * - * Copyright (c) 2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Base S3C24XX platform device definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * -*/ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/platform_device.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> -#include <asm/arch/fb.h> -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/irq.h> - -#include <asm/arch/regs-serial.h> -#include <asm/arch/udc.h> - -#include <asm/plat-s3c24xx/devs.h> -#include <asm/plat-s3c24xx/cpu.h> - -/* Serial port registrations */ - -static struct resource s3c2410_uart0_resource[] = { - [0] = { - .start = S3C2410_PA_UART0, - .end = S3C2410_PA_UART0 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX0, - .end = IRQ_S3CUART_ERR0, - .flags = IORESOURCE_IRQ, - } -}; - -static struct resource s3c2410_uart1_resource[] = { - [0] = { - .start = S3C2410_PA_UART1, - .end = S3C2410_PA_UART1 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX1, - .end = IRQ_S3CUART_ERR1, - .flags = IORESOURCE_IRQ, - } -}; - -static struct resource s3c2410_uart2_resource[] = { - [0] = { - .start = S3C2410_PA_UART2, - .end = S3C2410_PA_UART2 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX2, - .end = IRQ_S3CUART_ERR2, - .flags = IORESOURCE_IRQ, - } -}; - -struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { - [0] = { - .resources = s3c2410_uart0_resource, - .nr_resources = ARRAY_SIZE(s3c2410_uart0_resource), - }, - [1] = { - .resources = s3c2410_uart1_resource, - .nr_resources = ARRAY_SIZE(s3c2410_uart1_resource), - }, - [2] = { - .resources = s3c2410_uart2_resource, - .nr_resources = ARRAY_SIZE(s3c2410_uart2_resource), - }, -}; - -/* yart devices */ - -static struct platform_device s3c24xx_uart_device0 = { - .id = 0, -}; - -static struct platform_device s3c24xx_uart_device1 = { - .id = 1, -}; - -static struct platform_device s3c24xx_uart_device2 = { - .id = 2, -}; - -struct platform_device *s3c24xx_uart_src[3] = { - &s3c24xx_uart_device0, - &s3c24xx_uart_device1, - &s3c24xx_uart_device2, -}; - -struct platform_device *s3c24xx_uart_devs[3] = { -}; - -/* USB Host Controller */ - -static struct resource s3c_usb_resource[] = { - [0] = { - .start = S3C24XX_PA_USBHOST, - .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_USBH, - .end = IRQ_USBH, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 s3c_device_usb_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_usb = { - .name = "s3c2410-ohci", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_usb_resource), - .resource = s3c_usb_resource, - .dev = { - .dma_mask = &s3c_device_usb_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_usb); - -/* LCD Controller */ - -static struct resource s3c_lcd_resource[] = { - [0] = { - .start = S3C24XX_PA_LCD, - .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_LCD, - .end = IRQ_LCD, - .flags = IORESOURCE_IRQ, - } - -}; - -static u64 s3c_device_lcd_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_lcd = { - .name = "s3c2410-lcd", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_lcd_resource), - .resource = s3c_lcd_resource, - .dev = { - .dma_mask = &s3c_device_lcd_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_lcd); - -void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) -{ - struct s3c2410fb_mach_info *npd; - - npd = kmalloc(sizeof(*npd), GFP_KERNEL); - if (npd) { - memcpy(npd, pd, sizeof(*npd)); - s3c_device_lcd.dev.platform_data = npd; - } else { - printk(KERN_ERR "no memory for LCD platform data\n"); - } -} - -/* NAND Controller */ - -static struct resource s3c_nand_resource[] = { - [0] = { - .start = S3C2410_PA_NAND, - .end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1, - .flags = IORESOURCE_MEM, - } -}; - -struct platform_device s3c_device_nand = { - .name = "s3c2410-nand", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_nand_resource), - .resource = s3c_nand_resource, -}; - -EXPORT_SYMBOL(s3c_device_nand); - -/* USB Device (Gadget)*/ - -static struct resource s3c_usbgadget_resource[] = { - [0] = { - .start = S3C24XX_PA_USBDEV, - .end = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_USBD, - .end = IRQ_USBD, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_usbgadget = { - .name = "s3c2410-usbgadget", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_usbgadget_resource), - .resource = s3c_usbgadget_resource, -}; - -EXPORT_SYMBOL(s3c_device_usbgadget); - -void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd) -{ - struct s3c2410_udc_mach_info *npd; - - npd = kmalloc(sizeof(*npd), GFP_KERNEL); - if (npd) { - memcpy(npd, pd, sizeof(*npd)); - s3c_device_usbgadget.dev.platform_data = npd; - } else { - printk(KERN_ERR "no memory for udc platform data\n"); - } -} - - -/* Watchdog */ - -static struct resource s3c_wdt_resource[] = { - [0] = { - .start = S3C24XX_PA_WATCHDOG, - .end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_WDT, - .end = IRQ_WDT, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_wdt = { - .name = "s3c2410-wdt", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_wdt_resource), - .resource = s3c_wdt_resource, -}; - -EXPORT_SYMBOL(s3c_device_wdt); - -/* I2C */ - -static struct resource s3c_i2c_resource[] = { - [0] = { - .start = S3C24XX_PA_IIC, - .end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_IIC, - .end = IRQ_IIC, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_i2c = { - .name = "s3c2410-i2c", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_i2c_resource), - .resource = s3c_i2c_resource, -}; - -EXPORT_SYMBOL(s3c_device_i2c); - -/* IIS */ - -static struct resource s3c_iis_resource[] = { - [0] = { - .start = S3C24XX_PA_IIS, - .end = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1, - .flags = IORESOURCE_MEM, - } -}; - -static u64 s3c_device_iis_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_iis = { - .name = "s3c2410-iis", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_iis_resource), - .resource = s3c_iis_resource, - .dev = { - .dma_mask = &s3c_device_iis_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_iis); - -/* RTC */ - -static struct resource s3c_rtc_resource[] = { - [0] = { - .start = S3C24XX_PA_RTC, - .end = S3C24XX_PA_RTC + 0xff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_RTC, - .end = IRQ_RTC, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_TICK, - .end = IRQ_TICK, - .flags = IORESOURCE_IRQ - } -}; - -struct platform_device s3c_device_rtc = { - .name = "s3c2410-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_rtc_resource), - .resource = s3c_rtc_resource, -}; - -EXPORT_SYMBOL(s3c_device_rtc); - -/* ADC */ - -static struct resource s3c_adc_resource[] = { - [0] = { - .start = S3C24XX_PA_ADC, - .end = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TC, - .end = IRQ_TC, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_ADC, - .end = IRQ_ADC, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_adc = { - .name = "s3c2410-adc", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_adc_resource), - .resource = s3c_adc_resource, -}; - -/* SDI */ - -static struct resource s3c_sdi_resource[] = { - [0] = { - .start = S3C2410_PA_SDI, - .end = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_SDI, - .end = IRQ_SDI, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_sdi = { - .name = "s3c2410-sdi", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_sdi_resource), - .resource = s3c_sdi_resource, -}; - -EXPORT_SYMBOL(s3c_device_sdi); - -/* SPI (0) */ - -static struct resource s3c_spi0_resource[] = { - [0] = { - .start = S3C24XX_PA_SPI, - .end = S3C24XX_PA_SPI + 0x1f, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_SPI0, - .end = IRQ_SPI0, - .flags = IORESOURCE_IRQ, - } - -}; - -static u64 s3c_device_spi0_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_spi0 = { - .name = "s3c2410-spi", - .id = 0, - .num_resources = ARRAY_SIZE(s3c_spi0_resource), - .resource = s3c_spi0_resource, - .dev = { - .dma_mask = &s3c_device_spi0_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_spi0); - -/* SPI (1) */ - -static struct resource s3c_spi1_resource[] = { - [0] = { - .start = S3C24XX_PA_SPI + 0x20, - .end = S3C24XX_PA_SPI + 0x20 + 0x1f, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_SPI1, - .end = IRQ_SPI1, - .flags = IORESOURCE_IRQ, - } - -}; - -static u64 s3c_device_spi1_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_spi1 = { - .name = "s3c2410-spi", - .id = 1, - .num_resources = ARRAY_SIZE(s3c_spi1_resource), - .resource = s3c_spi1_resource, - .dev = { - .dma_mask = &s3c_device_spi1_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_spi1); - -/* pwm timer blocks */ - -static struct resource s3c_timer0_resource[] = { - [0] = { - .start = S3C24XX_PA_TIMER + 0x0C, - .end = S3C24XX_PA_TIMER + 0x0C + 0xB, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TIMER0, - .end = IRQ_TIMER0, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_timer0 = { - .name = "s3c2410-timer", - .id = 0, - .num_resources = ARRAY_SIZE(s3c_timer0_resource), - .resource = s3c_timer0_resource, -}; - -EXPORT_SYMBOL(s3c_device_timer0); - -/* timer 1 */ - -static struct resource s3c_timer1_resource[] = { - [0] = { - .start = S3C24XX_PA_TIMER + 0x18, - .end = S3C24XX_PA_TIMER + 0x23, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TIMER1, - .end = IRQ_TIMER1, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_timer1 = { - .name = "s3c2410-timer", - .id = 1, - .num_resources = ARRAY_SIZE(s3c_timer1_resource), - .resource = s3c_timer1_resource, -}; - -EXPORT_SYMBOL(s3c_device_timer1); - -/* timer 2 */ - -static struct resource s3c_timer2_resource[] = { - [0] = { - .start = S3C24XX_PA_TIMER + 0x24, - .end = S3C24XX_PA_TIMER + 0x2F, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TIMER2, - .end = IRQ_TIMER2, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_timer2 = { - .name = "s3c2410-timer", - .id = 2, - .num_resources = ARRAY_SIZE(s3c_timer2_resource), - .resource = s3c_timer2_resource, -}; - -EXPORT_SYMBOL(s3c_device_timer2); - -/* timer 3 */ - -static struct resource s3c_timer3_resource[] = { - [0] = { - .start = S3C24XX_PA_TIMER + 0x30, - .end = S3C24XX_PA_TIMER + 0x3B, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TIMER3, - .end = IRQ_TIMER3, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device s3c_device_timer3 = { - .name = "s3c2410-timer", - .id = 3, - .num_resources = ARRAY_SIZE(s3c_timer3_resource), - .resource = s3c_timer3_resource, -}; - -EXPORT_SYMBOL(s3c_device_timer3); - -#ifdef CONFIG_CPU_S3C2440 - -/* Camif Controller */ - -static struct resource s3c_camif_resource[] = { - [0] = { - .start = S3C2440_PA_CAMIF, - .end = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_CAM, - .end = IRQ_CAM, - .flags = IORESOURCE_IRQ, - } - -}; - -static u64 s3c_device_camif_dmamask = 0xffffffffUL; - -struct platform_device s3c_device_camif = { - .name = "s3c2440-camif", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_camif_resource), - .resource = s3c_camif_resource, - .dev = { - .dma_mask = &s3c_device_camif_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -EXPORT_SYMBOL(s3c_device_camif); - -#endif // CONFIG_CPU_S32440 diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c deleted file mode 100644 index 6f03c937097..00000000000 --- a/arch/arm/plat-s3c24xx/dma.c +++ /dev/null @@ -1,1498 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/dma.c - * - * Copyright (c) 2003-2005,2006 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C2410 DMA core - * - * http://armlinux.simtec.co.uk/ - * - * 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. -*/ - - -#ifdef CONFIG_S3C2410_DMA_DEBUG -#define DEBUG -#endif - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/sysdev.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/delay.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <asm/mach/dma.h> -#include <asm/arch/map.h> - -#include <asm/plat-s3c24xx/dma.h> - -/* io map for dma */ -static void __iomem *dma_base; -static struct kmem_cache *dma_kmem; - -static int dma_channels; - -static struct s3c24xx_dma_selection dma_sel; - -/* dma channel state information */ -struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; - -/* debugging functions */ - -#define BUF_MAGIC (0xcafebabe) - -#define dmawarn(fmt...) printk(KERN_DEBUG fmt) - -#define dma_regaddr(chan, reg) ((chan)->regs + (reg)) - -#if 1 -#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) -#else -static inline void -dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val) -{ - pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg); - writel(val, dma_regaddr(chan, reg)); -} -#endif - -#define dma_rdreg(chan, reg) readl((chan)->regs + (reg)) - -/* captured register state for debug */ - -struct s3c2410_dma_regstate { - unsigned long dcsrc; - unsigned long disrc; - unsigned long dstat; - unsigned long dcon; - unsigned long dmsktrig; -}; - -#ifdef CONFIG_S3C2410_DMA_DEBUG - -/* dmadbg_showregs - * - * simple debug routine to print the current state of the dma registers -*/ - -static void -dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) -{ - regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC); - regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC); - regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT); - regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON); - regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); -} - -static void -dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan, - struct s3c2410_dma_regstate *regs) -{ - printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n", - chan->number, fname, line, - regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig, - regs->dcon); -} - -static void -dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan) -{ - struct s3c2410_dma_regstate state; - - dmadbg_capture(chan, &state); - - printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n", - chan->number, fname, line, chan->load_state, - chan->curr, chan->next, chan->end); - - dmadbg_dumpregs(fname, line, chan, &state); -} - -static void -dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) -{ - struct s3c2410_dma_regstate state; - - dmadbg_capture(chan, &state); - dmadbg_dumpregs(fname, line, chan, &state); -} - -#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan)) -#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan)) -#else -#define dbg_showregs(chan) do { } while(0) -#define dbg_showchan(chan) do { } while(0) -#endif /* CONFIG_S3C2410_DMA_DEBUG */ - -static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX]; - -/* lookup_dma_channel - * - * change the dma channel number given into a real dma channel id -*/ - -static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel) -{ - if (channel & DMACH_LOW_LEVEL) - return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL]; - else - return dma_chan_map[channel]; -} - -/* s3c2410_dma_stats_timeout - * - * Update DMA stats from timeout info -*/ - -static void -s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val) -{ - if (stats == NULL) - return; - - if (val > stats->timeout_longest) - stats->timeout_longest = val; - if (val < stats->timeout_shortest) - stats->timeout_shortest = val; - - stats->timeout_avg += val; -} - -/* s3c2410_dma_waitforload - * - * wait for the DMA engine to load a buffer, and update the state accordingly -*/ - -static int -s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) -{ - int timeout = chan->load_timeout; - int took; - - if (chan->load_state != S3C2410_DMALOAD_1LOADED) { - printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line); - return 0; - } - - if (chan->stats != NULL) - chan->stats->loads++; - - while (--timeout > 0) { - if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) { - took = chan->load_timeout - timeout; - - s3c2410_dma_stats_timeout(chan->stats, took); - - switch (chan->load_state) { - case S3C2410_DMALOAD_1LOADED: - chan->load_state = S3C2410_DMALOAD_1RUNNING; - break; - - default: - printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state); - } - - return 1; - } - } - - if (chan->stats != NULL) { - chan->stats->timeout_failed++; - } - - return 0; -} - - - -/* s3c2410_dma_loadbuffer - * - * load a buffer, and update the channel state -*/ - -static inline int -s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, - struct s3c2410_dma_buf *buf) -{ - unsigned long reload; - - pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n", - buf, (unsigned long)buf->data, buf->size); - - if (buf == NULL) { - dmawarn("buffer is NULL\n"); - return -EINVAL; - } - - /* check the state of the channel before we do anything */ - - if (chan->load_state == S3C2410_DMALOAD_1LOADED) { - dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n"); - } - - if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) { - dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n"); - } - - /* it would seem sensible if we are the last buffer to not bother - * with the auto-reload bit, so that the DMA engine will not try - * and load another transfer after this one has finished... - */ - if (chan->load_state == S3C2410_DMALOAD_NONE) { - pr_debug("load_state is none, checking for noreload (next=%p)\n", - buf->next); - reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0; - } else { - //pr_debug("load_state is %d => autoreload\n", chan->load_state); - reload = S3C2410_DCON_AUTORELOAD; - } - - if ((buf->data & 0xf0000000) != 0x30000000) { - dmawarn("dmaload: buffer is %p\n", (void *)buf->data); - } - - writel(buf->data, chan->addr_reg); - - dma_wrreg(chan, S3C2410_DMA_DCON, - chan->dcon | reload | (buf->size/chan->xfer_unit)); - - chan->next = buf->next; - - /* update the state of the channel */ - - switch (chan->load_state) { - case S3C2410_DMALOAD_NONE: - chan->load_state = S3C2410_DMALOAD_1LOADED; - break; - - case S3C2410_DMALOAD_1RUNNING: - chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING; - break; - - default: - dmawarn("dmaload: unknown state %d in loadbuffer\n", - chan->load_state); - break; - } - - return 0; -} - -/* s3c2410_dma_call_op - * - * small routine to call the op routine with the given op if it has been - * registered -*/ - -static void -s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op) -{ - if (chan->op_fn != NULL) { - (chan->op_fn)(chan, op); - } -} - -/* s3c2410_dma_buffdone - * - * small wrapper to check if callback routine needs to be called, and - * if so, call it -*/ - -static inline void -s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, - enum s3c2410_dma_buffresult result) -{ -#if 0 - pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n", - chan->callback_fn, buf, buf->id, buf->size, result); -#endif - - if (chan->callback_fn != NULL) { - (chan->callback_fn)(chan, buf->id, buf->size, result); - } -} - -/* s3c2410_dma_start - * - * start a dma channel going -*/ - -static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) -{ - unsigned long tmp; - unsigned long flags; - - pr_debug("s3c2410_start_dma: channel=%d\n", chan->number); - - local_irq_save(flags); - - if (chan->state == S3C2410_DMA_RUNNING) { - pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state); - local_irq_restore(flags); - return 0; - } - - chan->state = S3C2410_DMA_RUNNING; - - /* check wether there is anything to load, and if not, see - * if we can find anything to load - */ - - if (chan->load_state == S3C2410_DMALOAD_NONE) { - if (chan->next == NULL) { - printk(KERN_ERR "dma%d: channel has nothing loaded\n", - chan->number); - chan->state = S3C2410_DMA_IDLE; - local_irq_restore(flags); - return -EINVAL; - } - - s3c2410_dma_loadbuffer(chan, chan->next); - } - - dbg_showchan(chan); - - /* enable the channel */ - - if (!chan->irq_enabled) { - enable_irq(chan->irq); - chan->irq_enabled = 1; - } - - /* start the channel going */ - - tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); - tmp &= ~S3C2410_DMASKTRIG_STOP; - tmp |= S3C2410_DMASKTRIG_ON; - dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp); - - pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp); - -#if 0 - /* the dma buffer loads should take care of clearing the AUTO - * reloading feature */ - tmp = dma_rdreg(chan, S3C2410_DMA_DCON); - tmp &= ~S3C2410_DCON_NORELOAD; - dma_wrreg(chan, S3C2410_DMA_DCON, tmp); -#endif - - s3c2410_dma_call_op(chan, S3C2410_DMAOP_START); - - dbg_showchan(chan); - - /* if we've only loaded one buffer onto the channel, then chec - * to see if we have another, and if so, try and load it so when - * the first buffer is finished, the new one will be loaded onto - * the channel */ - - if (chan->next != NULL) { - if (chan->load_state == S3C2410_DMALOAD_1LOADED) { - - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - pr_debug("%s: buff not yet loaded, no more todo\n", - __FUNCTION__); - } else { - chan->load_state = S3C2410_DMALOAD_1RUNNING; - s3c2410_dma_loadbuffer(chan, chan->next); - } - - } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) { - s3c2410_dma_loadbuffer(chan, chan->next); - } - } - - - local_irq_restore(flags); - - return 0; -} - -/* s3c2410_dma_canload - * - * work out if we can queue another buffer into the DMA engine -*/ - -static int -s3c2410_dma_canload(struct s3c2410_dma_chan *chan) -{ - if (chan->load_state == S3C2410_DMALOAD_NONE || - chan->load_state == S3C2410_DMALOAD_1RUNNING) - return 1; - - return 0; -} - -/* s3c2410_dma_enqueue - * - * queue an given buffer for dma transfer. - * - * id the device driver's id information for this buffer - * data the physical address of the buffer data - * size the size of the buffer in bytes - * - * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART - * is checked, and if set, the channel is started. If this flag isn't set, - * then an error will be returned. - * - * It is possible to queue more than one DMA buffer onto a channel at - * once, and the code will deal with the re-loading of the next buffer - * when necessary. -*/ - -int s3c2410_dma_enqueue(unsigned int channel, void *id, - dma_addr_t data, int size) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - struct s3c2410_dma_buf *buf; - unsigned long flags; - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: id=%p, data=%08x, size=%d\n", - __FUNCTION__, id, (unsigned int)data, size); - - buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC); - if (buf == NULL) { - pr_debug("%s: out of memory (%ld alloc)\n", - __FUNCTION__, (long)sizeof(*buf)); - return -ENOMEM; - } - - //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf); - //dbg_showchan(chan); - - buf->next = NULL; - buf->data = buf->ptr = data; - buf->size = size; - buf->id = id; - buf->magic = BUF_MAGIC; - - local_irq_save(flags); - - if (chan->curr == NULL) { - /* we've got nothing loaded... */ - pr_debug("%s: buffer %p queued onto empty channel\n", - __FUNCTION__, buf); - - chan->curr = buf; - chan->end = buf; - chan->next = NULL; - } else { - pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n", - chan->number, __FUNCTION__, buf); - - if (chan->end == NULL) - pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n", - chan->number, __FUNCTION__, chan); - - chan->end->next = buf; - chan->end = buf; - } - - /* if necessary, update the next buffer field */ - if (chan->next == NULL) - chan->next = buf; - - /* check to see if we can load a buffer */ - if (chan->state == S3C2410_DMA_RUNNING) { - if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) { - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - printk(KERN_ERR "dma%d: loadbuffer:" - "timeout loading buffer\n", - chan->number); - dbg_showchan(chan); - local_irq_restore(flags); - return -EINVAL; - } - } - - while (s3c2410_dma_canload(chan) && chan->next != NULL) { - s3c2410_dma_loadbuffer(chan, chan->next); - } - } else if (chan->state == S3C2410_DMA_IDLE) { - if (chan->flags & S3C2410_DMAF_AUTOSTART) { - s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START); - } - } - - local_irq_restore(flags); - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_enqueue); - -static inline void -s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf) -{ - int magicok = (buf->magic == BUF_MAGIC); - - buf->magic = -1; - - if (magicok) { - kmem_cache_free(dma_kmem, buf); - } else { - printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf); - } -} - -/* s3c2410_dma_lastxfer - * - * called when the system is out of buffers, to ensure that the channel - * is prepared for shutdown. -*/ - -static inline void -s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) -{ -#if 0 - pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n", - chan->number, chan->load_state); -#endif - - switch (chan->load_state) { - case S3C2410_DMALOAD_NONE: - break; - - case S3C2410_DMALOAD_1LOADED: - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - /* flag error? */ - printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n", - chan->number, __FUNCTION__); - return; - } - break; - - case S3C2410_DMALOAD_1LOADED_1RUNNING: - /* I belive in this case we do not have anything to do - * until the next buffer comes along, and we turn off the - * reload */ - return; - - default: - pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n", - chan->number, chan->load_state); - return; - - } - - /* hopefully this'll shut the damned thing up after the transfer... */ - dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD); -} - - -#define dmadbg2(x...) - -static irqreturn_t -s3c2410_dma_irq(int irq, void *devpw) -{ - struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw; - struct s3c2410_dma_buf *buf; - - buf = chan->curr; - - dbg_showchan(chan); - - /* modify the channel state */ - - switch (chan->load_state) { - case S3C2410_DMALOAD_1RUNNING: - /* TODO - if we are running only one buffer, we probably - * want to reload here, and then worry about the buffer - * callback */ - - chan->load_state = S3C2410_DMALOAD_NONE; - break; - - case S3C2410_DMALOAD_1LOADED: - /* iirc, we should go back to NONE loaded here, we - * had a buffer, and it was never verified as being - * loaded. - */ - - chan->load_state = S3C2410_DMALOAD_NONE; - break; - - case S3C2410_DMALOAD_1LOADED_1RUNNING: - /* we'll worry about checking to see if another buffer is - * ready after we've called back the owner. This should - * ensure we do not wait around too long for the DMA - * engine to start the next transfer - */ - - chan->load_state = S3C2410_DMALOAD_1LOADED; - break; - - case S3C2410_DMALOAD_NONE: - printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n", - chan->number); - break; - - default: - printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n", - chan->number, chan->load_state); - break; - } - - if (buf != NULL) { - /* update the chain to make sure that if we load any more - * buffers when we call the callback function, things should - * work properly */ - - chan->curr = buf->next; - buf->next = NULL; - - if (buf->magic != BUF_MAGIC) { - printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n", - chan->number, __FUNCTION__, buf); - return IRQ_HANDLED; - } - - s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK); - - /* free resouces */ - s3c2410_dma_freebuf(buf); - } else { - } - - /* only reload if the channel is still running... our buffer done - * routine may have altered the state by requesting the dma channel - * to stop or shutdown... */ - - /* todo: check that when the channel is shut-down from inside this - * function, we cope with unsetting reload, etc */ - - if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) { - unsigned long flags; - - switch (chan->load_state) { - case S3C2410_DMALOAD_1RUNNING: - /* don't need to do anything for this state */ - break; - - case S3C2410_DMALOAD_NONE: - /* can load buffer immediately */ - break; - - case S3C2410_DMALOAD_1LOADED: - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - /* flag error? */ - printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n", - chan->number, __FUNCTION__); - return IRQ_HANDLED; - } - - break; - - case S3C2410_DMALOAD_1LOADED_1RUNNING: - goto no_load; - - default: - printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n", - chan->number, chan->load_state); - return IRQ_HANDLED; - } - - local_irq_save(flags); - s3c2410_dma_loadbuffer(chan, chan->next); - local_irq_restore(flags); - } else { - s3c2410_dma_lastxfer(chan); - - /* see if we can stop this channel.. */ - if (chan->load_state == S3C2410_DMALOAD_NONE) { - pr_debug("dma%d: end of transfer, stopping channel (%ld)\n", - chan->number, jiffies); - s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL, - S3C2410_DMAOP_STOP); - } - } - - no_load: - return IRQ_HANDLED; -} - -static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel); - -/* s3c2410_request_dma - * - * get control of an dma channel -*/ - -int s3c2410_dma_request(unsigned int channel, - struct s3c2410_dma_client *client, - void *dev) -{ - struct s3c2410_dma_chan *chan; - unsigned long flags; - int err; - - pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n", - channel, client->name, dev); - - local_irq_save(flags); - - chan = s3c2410_dma_map_channel(channel); - if (chan == NULL) { - local_irq_restore(flags); - return -EBUSY; - } - - dbg_showchan(chan); - - chan->client = client; - chan->in_use = 1; - - if (!chan->irq_claimed) { - pr_debug("dma%d: %s : requesting irq %d\n", - channel, __FUNCTION__, chan->irq); - - chan->irq_claimed = 1; - local_irq_restore(flags); - - err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED, - client->name, (void *)chan); - - local_irq_save(flags); - - if (err) { - chan->in_use = 0; - chan->irq_claimed = 0; - local_irq_restore(flags); - - printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n", - client->name, chan->irq, chan->number); - return err; - } - - chan->irq_enabled = 1; - } - - local_irq_restore(flags); - - /* need to setup */ - - pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan); - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_request); - -/* s3c2410_dma_free - * - * release the given channel back to the system, will stop and flush - * any outstanding transfers, and ensure the channel is ready for the - * next claimant. - * - * Note, although a warning is currently printed if the freeing client - * info is not the same as the registrant's client info, the free is still - * allowed to go through. -*/ - -int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - unsigned long flags; - - if (chan == NULL) - return -EINVAL; - - local_irq_save(flags); - - if (chan->client != client) { - printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n", - channel, chan->client, client); - } - - /* sort out stopping and freeing the channel */ - - if (chan->state != S3C2410_DMA_IDLE) { - pr_debug("%s: need to stop dma channel %p\n", - __FUNCTION__, chan); - - /* possibly flush the channel */ - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP); - } - - chan->client = NULL; - chan->in_use = 0; - - if (chan->irq_claimed) - free_irq(chan->irq, (void *)chan); - - chan->irq_claimed = 0; - - if (!(channel & DMACH_LOW_LEVEL)) - dma_chan_map[channel] = NULL; - - local_irq_restore(flags); - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_free); - -static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) -{ - unsigned long flags; - unsigned long tmp; - - pr_debug("%s:\n", __FUNCTION__); - - dbg_showchan(chan); - - local_irq_save(flags); - - s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP); - - tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); - tmp |= S3C2410_DMASKTRIG_STOP; - //tmp &= ~S3C2410_DMASKTRIG_ON; - dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp); - -#if 0 - /* should also clear interrupts, according to WinCE BSP */ - tmp = dma_rdreg(chan, S3C2410_DMA_DCON); - tmp |= S3C2410_DCON_NORELOAD; - dma_wrreg(chan, S3C2410_DMA_DCON, tmp); -#endif - - /* should stop do this, or should we wait for flush? */ - chan->state = S3C2410_DMA_IDLE; - chan->load_state = S3C2410_DMALOAD_NONE; - - local_irq_restore(flags); - - return 0; -} - -static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) -{ - unsigned long tmp; - unsigned int timeout = 0x10000; - - while (timeout-- > 0) { - tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); - - if (!(tmp & S3C2410_DMASKTRIG_ON)) - return; - } - - pr_debug("dma%d: failed to stop?\n", chan->number); -} - - -/* s3c2410_dma_flush - * - * stop the channel, and remove all current and pending transfers -*/ - -static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan) -{ - struct s3c2410_dma_buf *buf, *next; - unsigned long flags; - - pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number); - - dbg_showchan(chan); - - local_irq_save(flags); - - if (chan->state != S3C2410_DMA_IDLE) { - pr_debug("%s: stopping channel...\n", __FUNCTION__ ); - s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP); - } - - buf = chan->curr; - if (buf == NULL) - buf = chan->next; - - chan->curr = chan->next = chan->end = NULL; - - if (buf != NULL) { - for ( ; buf != NULL; buf = next) { - next = buf->next; - - pr_debug("%s: free buffer %p, next %p\n", - __FUNCTION__, buf, buf->next); - - s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT); - s3c2410_dma_freebuf(buf); - } - } - - dbg_showregs(chan); - - s3c2410_dma_waitforstop(chan); - -#if 0 - /* should also clear interrupts, according to WinCE BSP */ - { - unsigned long tmp; - - tmp = dma_rdreg(chan, S3C2410_DMA_DCON); - tmp |= S3C2410_DCON_NORELOAD; - dma_wrreg(chan, S3C2410_DMA_DCON, tmp); - } -#endif - - dbg_showregs(chan); - - local_irq_restore(flags); - - return 0; -} - -static int s3c2410_dma_started(struct s3c2410_dma_chan *chan) -{ - unsigned long flags; - - local_irq_save(flags); - - dbg_showchan(chan); - - /* if we've only loaded one buffer onto the channel, then chec - * to see if we have another, and if so, try and load it so when - * the first buffer is finished, the new one will be loaded onto - * the channel */ - - if (chan->next != NULL) { - if (chan->load_state == S3C2410_DMALOAD_1LOADED) { - - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - pr_debug("%s: buff not yet loaded, no more todo\n", - __FUNCTION__); - } else { - chan->load_state = S3C2410_DMALOAD_1RUNNING; - s3c2410_dma_loadbuffer(chan, chan->next); - } - - } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) { - s3c2410_dma_loadbuffer(chan, chan->next); - } - } - - - local_irq_restore(flags); - - return 0; - -} - -int -s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - switch (op) { - case S3C2410_DMAOP_START: - return s3c2410_dma_start(chan); - - case S3C2410_DMAOP_STOP: - return s3c2410_dma_dostop(chan); - - case S3C2410_DMAOP_PAUSE: - case S3C2410_DMAOP_RESUME: - return -ENOENT; - - case S3C2410_DMAOP_FLUSH: - return s3c2410_dma_flush(chan); - - case S3C2410_DMAOP_STARTED: - return s3c2410_dma_started(chan); - - case S3C2410_DMAOP_TIMEOUT: - return 0; - - } - - return -ENOENT; /* unknown, don't bother */ -} - -EXPORT_SYMBOL(s3c2410_dma_ctrl); - -/* DMA configuration for each channel - * - * DISRCC -> source of the DMA (AHB,APB) - * DISRC -> source address of the DMA - * DIDSTC -> destination of the DMA (AHB,APD) - * DIDST -> destination address of the DMA -*/ - -/* s3c2410_dma_config - * - * xfersize: size of unit in bytes (1,2,4) - * dcon: base value of the DCONx register -*/ - -int s3c2410_dma_config(dmach_t channel, - int xferunit, - int dcon) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", - __FUNCTION__, channel, xferunit, dcon); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon); - - dcon |= chan->dcon & dma_sel.dcon_mask; - - pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon); - - switch (xferunit) { - case 1: - dcon |= S3C2410_DCON_BYTE; - break; - - case 2: - dcon |= S3C2410_DCON_HALFWORD; - break; - - case 4: - dcon |= S3C2410_DCON_WORD; - break; - - default: - pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit); - return -EINVAL; - } - - dcon |= S3C2410_DCON_HWTRIG; - dcon |= S3C2410_DCON_INTREQ; - - pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon); - - chan->dcon = dcon; - chan->xfer_unit = xferunit; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_config); - -int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags); - - chan->flags = flags; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_setflags); - - -/* do we need to protect the settings of the fields from - * irq? -*/ - -int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn); - - chan->op_fn = rtn; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_set_opfn); - -int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn); - - chan->callback_fn = rtn; - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); - -/* s3c2410_dma_devconfig - * - * configure the dma source/destination hardware type and address - * - * source: S3C2410_DMASRC_HW: source is hardware - * S3C2410_DMASRC_MEM: source is memory - * - * hwcfg: the value for xxxSTCn register, - * bit 0: 0=increment pointer, 1=leave pointer - * bit 1: 0=soucre is AHB, 1=soucre is APB - * - * devaddr: physical address of the source -*/ - -int s3c2410_dma_devconfig(int channel, - enum s3c2410_dmasrc source, - int hwcfg, - unsigned long devaddr) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n", - __FUNCTION__, (int)source, hwcfg, devaddr); - - chan->source = source; - chan->dev_addr = devaddr; - - switch (source) { - case S3C2410_DMASRC_HW: - /* source is hardware */ - pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n", - __FUNCTION__, devaddr, hwcfg); - dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3); - dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr); - dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0)); - - chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST); - return 0; - - case S3C2410_DMASRC_MEM: - /* source is memory */ - pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n", - __FUNCTION__, devaddr, hwcfg); - dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0)); - dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr); - dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3); - - chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC); - return 0; - } - - printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source); - return -EINVAL; -} - -EXPORT_SYMBOL(s3c2410_dma_devconfig); - -/* s3c2410_dma_getposition - * - * returns the current transfer points for the dma source and destination -*/ - -int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst) -{ - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - - if (chan == NULL) - return -EINVAL; - - if (src != NULL) - *src = dma_rdreg(chan, S3C2410_DMA_DCSRC); - - if (dst != NULL) - *dst = dma_rdreg(chan, S3C2410_DMA_DCDST); - - return 0; -} - -EXPORT_SYMBOL(s3c2410_dma_getposition); - - -/* system device class */ - -#ifdef CONFIG_PM - -static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) -{ - struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev); - - printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); - - if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) { - /* the dma channel is still working, which is probably - * a bad thing to do over suspend/resume. We stop the - * channel and assume that the client is either going to - * retry after resume, or that it is broken. - */ - - printk(KERN_INFO "dma: stopping channel %d due to suspend\n", - cp->number); - - s3c2410_dma_dostop(cp); - } - - return 0; -} - -static int s3c2410_dma_resume(struct sys_device *dev) -{ - return 0; -} - -#else -#define s3c2410_dma_suspend NULL -#define s3c2410_dma_resume NULL -#endif /* CONFIG_PM */ - -struct sysdev_class dma_sysclass = { - set_kset_name("s3c24xx-dma"), - .suspend = s3c2410_dma_suspend, - .resume = s3c2410_dma_resume, -}; - -/* kmem cache implementation */ - -static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f) -{ - memset(p, 0, sizeof(struct s3c2410_dma_buf)); -} - -/* initialisation code */ - -static int __init s3c24xx_dma_sysclass_init(void) -{ - int ret = sysdev_class_register(&dma_sysclass); - - if (ret != 0) - printk(KERN_ERR "dma sysclass registration failed\n"); - - return ret; -} - -core_initcall(s3c24xx_dma_sysclass_init); - -static int __init s3c24xx_dma_sysdev_register(void) -{ - struct s3c2410_dma_chan *cp = s3c2410_chans; - int channel, ret; - - for (channel = 0; channel < dma_channels; cp++, channel++) { - cp->dev.cls = &dma_sysclass; - cp->dev.id = channel; - ret = sysdev_register(&cp->dev); - - if (ret) { - printk(KERN_ERR "error registering dev for dma %d\n", - channel); - return ret; - } - } - - return 0; -} - -late_initcall(s3c24xx_dma_sysdev_register); - -int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq, - unsigned int stride) -{ - struct s3c2410_dma_chan *cp; - int channel; - int ret; - - printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n"); - - dma_channels = channels; - - dma_base = ioremap(S3C24XX_PA_DMA, stride * channels); - if (dma_base == NULL) { - printk(KERN_ERR "dma failed to remap register block\n"); - return -ENOMEM; - } - - dma_kmem = kmem_cache_create("dma_desc", - sizeof(struct s3c2410_dma_buf), 0, - SLAB_HWCACHE_ALIGN, - s3c2410_dma_cache_ctor, NULL); - - if (dma_kmem == NULL) { - printk(KERN_ERR "dma failed to make kmem cache\n"); - ret = -ENOMEM; - goto err; - } - - for (channel = 0; channel < channels; channel++) { - cp = &s3c2410_chans[channel]; - - memset(cp, 0, sizeof(struct s3c2410_dma_chan)); - - /* dma channel irqs are in order.. */ - cp->number = channel; - cp->irq = channel + irq; - cp->regs = dma_base + (channel * stride); - - /* point current stats somewhere */ - cp->stats = &cp->stats_store; - cp->stats_store.timeout_shortest = LONG_MAX; - - /* basic channel configuration */ - - cp->load_timeout = 1<<18; - - printk("DMA channel %d at %p, irq %d\n", - cp->number, cp->regs, cp->irq); - } - - return 0; - - err: - kmem_cache_destroy(dma_kmem); - iounmap(dma_base); - dma_base = NULL; - return ret; -} - -int s3c2410_dma_init(void) -{ - return s3c24xx_dma_init(4, IRQ_DMA0, 0x40); -} - -static inline int is_channel_valid(unsigned int channel) -{ - return (channel & DMA_CH_VALID); -} - -static struct s3c24xx_dma_order *dma_order; - - -/* s3c2410_dma_map_channel() - * - * turn the virtual channel number into a real, and un-used hardware - * channel. - * - * first, try the dma ordering given to us by either the relevant - * dma code, or the board. Then just find the first usable free - * channel -*/ - -static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) -{ - struct s3c24xx_dma_order_ch *ord = NULL; - struct s3c24xx_dma_map *ch_map; - struct s3c2410_dma_chan *dmach; - int ch; - - if (dma_sel.map == NULL || channel > dma_sel.map_size) - return NULL; - - ch_map = dma_sel.map + channel; - - /* first, try the board mapping */ - - if (dma_order) { - ord = &dma_order->channels[channel]; - - for (ch = 0; ch < dma_channels; ch++) { - if (!is_channel_valid(ord->list[ch])) - continue; - - if (s3c2410_chans[ord->list[ch]].in_use == 0) { - ch = ord->list[ch] & ~DMA_CH_VALID; - goto found; - } - } - - if (ord->flags & DMA_CH_NEVER) - return NULL; - } - - /* second, search the channel map for first free */ - - for (ch = 0; ch < dma_channels; ch++) { - if (!is_channel_valid(ch_map->channels[ch])) - continue; - - if (s3c2410_chans[ch].in_use == 0) { - printk("mapped channel %d to %d\n", channel, ch); - break; - } - } - - if (ch >= dma_channels) - return NULL; - - /* update our channel mapping */ - - found: - dmach = &s3c2410_chans[ch]; - dma_chan_map[channel] = dmach; - - /* select the channel */ - - (dma_sel.select)(dmach, ch_map); - - return dmach; -} - -static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch) -{ - return 0; -} - -int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel) -{ - struct s3c24xx_dma_map *nmap; - size_t map_sz = sizeof(*nmap) * sel->map_size; - int ptr; - - nmap = kmalloc(map_sz, GFP_KERNEL); - if (nmap == NULL) - return -ENOMEM; - - memcpy(nmap, sel->map, map_sz); - memcpy(&dma_sel, sel, sizeof(*sel)); - - dma_sel.map = nmap; - - for (ptr = 0; ptr < sel->map_size; ptr++) - s3c24xx_dma_check_entry(nmap+ptr, ptr); - - return 0; -} - -int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord) -{ - struct s3c24xx_dma_order *nord = dma_order; - - if (nord == NULL) - nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL); - - if (nord == NULL) { - printk(KERN_ERR "no memory to store dma channel order\n"); - return -ENOMEM; - } - - dma_order = nord; - memcpy(nord, ord, sizeof(struct s3c24xx_dma_order)); - return 0; -} diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c deleted file mode 100644 index ec3a09c4d18..00000000000 --- a/arch/arm/plat-s3c24xx/gpio.c +++ /dev/null @@ -1,188 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/gpio.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C24XX GPIO support - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> - -#include <asm/arch/regs-gpio.h> - -void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long mask; - unsigned long con; - unsigned long flags; - - if (pin < S3C2410_GPIO_BANKB) { - mask = 1 << S3C2410_GPIO_OFFSET(pin); - } else { - mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; - } - - switch (function) { - case S3C2410_GPIO_LEAVE: - mask = 0; - function = 0; - break; - - case S3C2410_GPIO_INPUT: - case S3C2410_GPIO_OUTPUT: - case S3C2410_GPIO_SFN2: - case S3C2410_GPIO_SFN3: - if (pin < S3C2410_GPIO_BANKB) { - function -= 1; - function &= 1; - function <<= S3C2410_GPIO_OFFSET(pin); - } else { - function &= 3; - function <<= S3C2410_GPIO_OFFSET(pin)*2; - } - } - - /* modify the specified register wwith IRQs off */ - - local_irq_save(flags); - - con = __raw_readl(base + 0x00); - con &= ~mask; - con |= function; - - __raw_writel(con, base + 0x00); - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(s3c2410_gpio_cfgpin); - -unsigned int s3c2410_gpio_getcfg(unsigned int pin) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long val = __raw_readl(base); - - if (pin < S3C2410_GPIO_BANKB) { - val >>= S3C2410_GPIO_OFFSET(pin); - val &= 1; - val += 1; - } else { - val >>= S3C2410_GPIO_OFFSET(pin)*2; - val &= 3; - } - - return val | S3C2410_GPIO_INPUT; -} - -EXPORT_SYMBOL(s3c2410_gpio_getcfg); - -void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - unsigned long flags; - unsigned long up; - - if (pin < S3C2410_GPIO_BANKB) - return; - - local_irq_save(flags); - - up = __raw_readl(base + 0x08); - up &= ~(1L << offs); - up |= to << offs; - __raw_writel(up, base + 0x08); - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(s3c2410_gpio_pullup); - -void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - unsigned long flags; - unsigned long dat; - - local_irq_save(flags); - - dat = __raw_readl(base + 0x04); - dat &= ~(1 << offs); - dat |= to << offs; - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(s3c2410_gpio_setpin); - -unsigned int s3c2410_gpio_getpin(unsigned int pin) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - - return __raw_readl(base + 0x04) & (1<< offs); -} - -EXPORT_SYMBOL(s3c2410_gpio_getpin); - -unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) -{ - unsigned long flags; - unsigned long misccr; - - local_irq_save(flags); - misccr = __raw_readl(S3C24XX_MISCCR); - misccr &= ~clear; - misccr ^= change; - __raw_writel(misccr, S3C24XX_MISCCR); - local_irq_restore(flags); - - return misccr; -} - -EXPORT_SYMBOL(s3c2410_modify_misccr); - -int s3c2410_gpio_getirq(unsigned int pin) -{ - if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15) - return -1; /* not valid interrupts */ - - if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) - return -1; /* not valid pin */ - - if (pin < S3C2410_GPF4) - return (pin - S3C2410_GPF0) + IRQ_EINT0; - - if (pin < S3C2410_GPG0) - return (pin - S3C2410_GPF4) + IRQ_EINT4; - - return (pin - S3C2410_GPG0) + IRQ_EINT8; -} - -EXPORT_SYMBOL(s3c2410_gpio_getirq); diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c deleted file mode 100644 index 8fbc8847026..00000000000 --- a/arch/arm/plat-s3c24xx/irq.c +++ /dev/null @@ -1,800 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/irq.c - * - * Copyright (c) 2003,2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Changelog: - * - * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk> - * Fixed compile warnings - * - * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn> - * Fixed s3c_extirq_type - * - * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org> - * Addition of ADC/TC demux - * - * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de> - * Fix for set_irq_type() on low EINT numbers - * - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk> - * Tidy up KF's patch and sort out new release - * - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk> - * Add support for power management controls - * - * 04-Nov-2004 Ben Dooks - * Fix standard IRQ wake for EINT0..4 and RTC - * - * 22-Feb-2005 Ben Dooks - * Fixed edge-triggering on ADC IRQ - * - * 28-Jun-2005 Ben Dooks - * Mark IRQ_LCD valid - * - * 25-Jul-2005 Ben Dooks - * Split the S3C2440 IRQ code to seperate file -*/ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/sysdev.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> - -#include <asm/mach/irq.h> - -#include <asm/arch/regs-irq.h> -#include <asm/arch/regs-gpio.h> - -#include <asm/plat-s3c24xx/cpu.h> -#include <asm/plat-s3c24xx/pm.h> -#include <asm/plat-s3c24xx/irq.h> - -/* wakeup irq control */ - -#ifdef CONFIG_PM - -/* state for IRQs over sleep */ - -/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources - * - * set bit to 1 in allow bitfield to enable the wakeup settings on it -*/ - -unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; -unsigned long s3c_irqwake_intmask = 0xffffffffL; -unsigned long s3c_irqwake_eintallow = 0x0000fff0L; -unsigned long s3c_irqwake_eintmask = 0xffffffffL; - -int -s3c_irq_wake(unsigned int irqno, unsigned int state) -{ - unsigned long irqbit = 1 << (irqno - IRQ_EINT0); - - if (!(s3c_irqwake_intallow & irqbit)) - return -ENOENT; - - printk(KERN_INFO "wake %s for irq %d\n", - state ? "enabled" : "disabled", irqno); - - if (!state) - s3c_irqwake_intmask |= irqbit; - else - s3c_irqwake_intmask &= ~irqbit; - - return 0; -} - -static int -s3c_irqext_wake(unsigned int irqno, unsigned int state) -{ - unsigned long bit = 1L << (irqno - EXTINT_OFF); - - if (!(s3c_irqwake_eintallow & bit)) - return -ENOENT; - - printk(KERN_INFO "wake %s for irq %d\n", - state ? "enabled" : "disabled", irqno); - - if (!state) - s3c_irqwake_eintmask |= bit; - else - s3c_irqwake_eintmask &= ~bit; - - return 0; -} - -#else -#define s3c_irqext_wake NULL -#define s3c_irq_wake NULL -#endif - - -static void -s3c_irq_mask(unsigned int irqno) -{ - unsigned long mask; - - irqno -= IRQ_EINT0; - - mask = __raw_readl(S3C2410_INTMSK); - mask |= 1UL << irqno; - __raw_writel(mask, S3C2410_INTMSK); -} - -static inline void -s3c_irq_ack(unsigned int irqno) -{ - unsigned long bitval = 1UL << (irqno - IRQ_EINT0); - - __raw_writel(bitval, S3C2410_SRCPND); - __raw_writel(bitval, S3C2410_INTPND); -} - -static inline void -s3c_irq_maskack(unsigned int irqno) -{ - unsigned long bitval = 1UL << (irqno - IRQ_EINT0); - unsigned long mask; - - mask = __raw_readl(S3C2410_INTMSK); - __raw_writel(mask|bitval, S3C2410_INTMSK); - - __raw_writel(bitval, S3C2410_SRCPND); - __raw_writel(bitval, S3C2410_INTPND); -} - - -static void -s3c_irq_unmask(unsigned int irqno) -{ - unsigned long mask; - - if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23) - irqdbf2("s3c_irq_unmask %d\n", irqno); - - irqno -= IRQ_EINT0; - - mask = __raw_readl(S3C2410_INTMSK); - mask &= ~(1UL << irqno); - __raw_writel(mask, S3C2410_INTMSK); -} - -struct irq_chip s3c_irq_level_chip = { - .name = "s3c-level", - .ack = s3c_irq_maskack, - .mask = s3c_irq_mask, - .unmask = s3c_irq_unmask, - .set_wake = s3c_irq_wake -}; - -static struct irq_chip s3c_irq_chip = { - .name = "s3c", - .ack = s3c_irq_ack, - .mask = s3c_irq_mask, - .unmask = s3c_irq_unmask, - .set_wake = s3c_irq_wake -}; - -static void -s3c_irqext_mask(unsigned int irqno) -{ - unsigned long mask; - - irqno -= EXTINT_OFF; - - mask = __raw_readl(S3C24XX_EINTMASK); - mask |= ( 1UL << irqno); - __raw_writel(mask, S3C24XX_EINTMASK); -} - -static void -s3c_irqext_ack(unsigned int irqno) -{ - unsigned long req; - unsigned long bit; - unsigned long mask; - - bit = 1UL << (irqno - EXTINT_OFF); - - mask = __raw_readl(S3C24XX_EINTMASK); - - __raw_writel(bit, S3C24XX_EINTPEND); - - req = __raw_readl(S3C24XX_EINTPEND); - req &= ~mask; - - /* not sure if we should be acking the parent irq... */ - - if (irqno <= IRQ_EINT7 ) { - if ((req & 0xf0) == 0) - s3c_irq_ack(IRQ_EINT4t7); - } else { - if ((req >> 8) == 0) - s3c_irq_ack(IRQ_EINT8t23); - } -} - -static void -s3c_irqext_unmask(unsigned int irqno) -{ - unsigned long mask; - - irqno -= EXTINT_OFF; - - mask = __raw_readl(S3C24XX_EINTMASK); - mask &= ~( 1UL << irqno); - __raw_writel(mask, S3C24XX_EINTMASK); -} - -int -s3c_irqext_type(unsigned int irq, unsigned int type) -{ - void __iomem *extint_reg; - void __iomem *gpcon_reg; - unsigned long gpcon_offset, extint_offset; - unsigned long newvalue = 0, value; - - if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) - { - gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C24XX_EXTINT0; - gpcon_offset = (irq - IRQ_EINT0) * 2; - extint_offset = (irq - IRQ_EINT0) * 4; - } - else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) - { - gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C24XX_EXTINT0; - gpcon_offset = (irq - (EXTINT_OFF)) * 2; - extint_offset = (irq - (EXTINT_OFF)) * 4; - } - else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) - { - gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C24XX_EXTINT1; - gpcon_offset = (irq - IRQ_EINT8) * 2; - extint_offset = (irq - IRQ_EINT8) * 4; - } - else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23)) - { - gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C24XX_EXTINT2; - gpcon_offset = (irq - IRQ_EINT8) * 2; - extint_offset = (irq - IRQ_EINT16) * 4; - } else - return -1; - - /* Set the GPIO to external interrupt mode */ - value = __raw_readl(gpcon_reg); - value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); - __raw_writel(value, gpcon_reg); - - /* Set the external interrupt to pointed trigger type */ - switch (type) - { - case IRQT_NOEDGE: - printk(KERN_WARNING "No edge setting!\n"); - break; - - case IRQT_RISING: - newvalue = S3C2410_EXTINT_RISEEDGE; - break; - - case IRQT_FALLING: - newvalue = S3C2410_EXTINT_FALLEDGE; - break; - - case IRQT_BOTHEDGE: - newvalue = S3C2410_EXTINT_BOTHEDGE; - break; - - case IRQT_LOW: - newvalue = S3C2410_EXTINT_LOWLEV; - break; - - case IRQT_HIGH: - newvalue = S3C2410_EXTINT_HILEV; - break; - - default: - printk(KERN_ERR "No such irq type %d", type); - return -1; - } - - value = __raw_readl(extint_reg); - value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset); - __raw_writel(value, extint_reg); - - return 0; -} - -static struct irq_chip s3c_irqext_chip = { - .name = "s3c-ext", - .mask = s3c_irqext_mask, - .unmask = s3c_irqext_unmask, - .ack = s3c_irqext_ack, - .set_type = s3c_irqext_type, - .set_wake = s3c_irqext_wake -}; - -static struct irq_chip s3c_irq_eint0t4 = { - .name = "s3c-ext0", - .ack = s3c_irq_ack, - .mask = s3c_irq_mask, - .unmask = s3c_irq_unmask, - .set_wake = s3c_irq_wake, - .set_type = s3c_irqext_type, -}; - -/* mask values for the parent registers for each of the interrupt types */ - -#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0)) -#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) -#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) -#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) - - -/* UART0 */ - -static void -s3c_irq_uart0_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_UART0, 7); -} - -static void -s3c_irq_uart0_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_UART0); -} - -static void -s3c_irq_uart0_ack(unsigned int irqno) -{ - s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); -} - -static struct irq_chip s3c_irq_uart0 = { - .name = "s3c-uart0", - .mask = s3c_irq_uart0_mask, - .unmask = s3c_irq_uart0_unmask, - .ack = s3c_irq_uart0_ack, -}; - -/* UART1 */ - -static void -s3c_irq_uart1_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3); -} - -static void -s3c_irq_uart1_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_UART1); -} - -static void -s3c_irq_uart1_ack(unsigned int irqno) -{ - s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); -} - -static struct irq_chip s3c_irq_uart1 = { - .name = "s3c-uart1", - .mask = s3c_irq_uart1_mask, - .unmask = s3c_irq_uart1_unmask, - .ack = s3c_irq_uart1_ack, -}; - -/* UART2 */ - -static void -s3c_irq_uart2_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6); -} - -static void -s3c_irq_uart2_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_UART2); -} - -static void -s3c_irq_uart2_ack(unsigned int irqno) -{ - s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); -} - -static struct irq_chip s3c_irq_uart2 = { - .name = "s3c-uart2", - .mask = s3c_irq_uart2_mask, - .unmask = s3c_irq_uart2_unmask, - .ack = s3c_irq_uart2_ack, -}; - -/* ADC and Touchscreen */ - -static void -s3c_irq_adc_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9); -} - -static void -s3c_irq_adc_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT); -} - -static void -s3c_irq_adc_ack(unsigned int irqno) -{ - s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); -} - -static struct irq_chip s3c_irq_adc = { - .name = "s3c-adc", - .mask = s3c_irq_adc_mask, - .unmask = s3c_irq_adc_unmask, - .ack = s3c_irq_adc_ack, -}; - -/* irq demux for adc */ -static void s3c_irq_demux_adc(unsigned int irq, - struct irq_desc *desc) -{ - unsigned int subsrc, submsk; - unsigned int offset = 9; - struct irq_desc *mydesc; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= offset; - subsrc &= 3; - - if (subsrc != 0) { - if (subsrc & 1) { - mydesc = irq_desc + IRQ_TC; - desc_handle_irq(IRQ_TC, mydesc); - } - if (subsrc & 2) { - mydesc = irq_desc + IRQ_ADC; - desc_handle_irq(IRQ_ADC, mydesc); - } - } -} - -static void s3c_irq_demux_uart(unsigned int start) -{ - unsigned int subsrc, submsk; - unsigned int offset = start - IRQ_S3CUART_RX0; - struct irq_desc *desc; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n", - start, offset, subsrc, submsk); - - subsrc &= ~submsk; - subsrc >>= offset; - subsrc &= 7; - - if (subsrc != 0) { - desc = irq_desc + start; - - if (subsrc & 1) - desc_handle_irq(start, desc); - - desc++; - - if (subsrc & 2) - desc_handle_irq(start+1, desc); - - desc++; - - if (subsrc & 4) - desc_handle_irq(start+2, desc); - } -} - -/* uart demux entry points */ - -static void -s3c_irq_demux_uart0(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX0); -} - -static void -s3c_irq_demux_uart1(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX1); -} - -static void -s3c_irq_demux_uart2(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX2); -} - -static void -s3c_irq_demux_extint8(unsigned int irq, - struct irq_desc *desc) -{ - unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); - unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); - - eintpnd &= ~eintmsk; - eintpnd &= ~0xff; /* ignore lower irqs */ - - /* we may as well handle all the pending IRQs here */ - - while (eintpnd) { - irq = __ffs(eintpnd); - eintpnd &= ~(1<<irq); - - irq += (IRQ_EINT4 - 4); - desc_handle_irq(irq, irq_desc + irq); - } - -} - -static void -s3c_irq_demux_extint4t7(unsigned int irq, - struct irq_desc *desc) -{ - unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); - unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); - - eintpnd &= ~eintmsk; - eintpnd &= 0xff; /* only lower irqs */ - - /* we may as well handle all the pending IRQs here */ - - while (eintpnd) { - irq = __ffs(eintpnd); - eintpnd &= ~(1<<irq); - - irq += (IRQ_EINT4 - 4); - - desc_handle_irq(irq, irq_desc + irq); - } -} - -#ifdef CONFIG_PM - -static struct sleep_save irq_save[] = { - SAVE_ITEM(S3C2410_INTMSK), - SAVE_ITEM(S3C2410_INTSUBMSK), -}; - -/* the extint values move between the s3c2410/s3c2440 and the s3c2412 - * so we use an array to hold them, and to calculate the address of - * the register at run-time -*/ - -static unsigned long save_extint[3]; -static unsigned long save_eintflt[4]; -static unsigned long save_eintmask; - -int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(save_extint); i++) - save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4)); - - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) - save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4)); - - s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); - save_eintmask = __raw_readl(S3C24XX_EINTMASK); - - return 0; -} - -int s3c24xx_irq_resume(struct sys_device *dev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(save_extint); i++) - __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4)); - - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) - __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4)); - - s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); - __raw_writel(save_eintmask, S3C24XX_EINTMASK); - - return 0; -} - -#else -#define s3c24xx_irq_suspend NULL -#define s3c24xx_irq_resume NULL -#endif - -/* s3c24xx_init_irq - * - * Initialise S3C2410 IRQ system -*/ - -void __init s3c24xx_init_irq(void) -{ - unsigned long pend; - unsigned long last; - int irqno; - int i; - - irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); - - /* first, clear all interrupts pending... */ - - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C24XX_EINTPEND); - - if (pend == 0 || pend == last) - break; - - __raw_writel(pend, S3C24XX_EINTPEND); - printk("irq: clearing pending ext status %08x\n", (int)pend); - last = pend; - } - - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2410_INTPND); - - if (pend == 0 || pend == last) - break; - - __raw_writel(pend, S3C2410_SRCPND); - __raw_writel(pend, S3C2410_INTPND); - printk("irq: clearing pending status %08x\n", (int)pend); - last = pend; - } - - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2410_SUBSRCPND); - - if (pend == 0 || pend == last) - break; - - printk("irq: clearing subpending status %08x\n", (int)pend); - __raw_writel(pend, S3C2410_SUBSRCPND); - last = pend; - } - - /* register the main interrupts */ - - irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); - - for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { - /* set all the s3c2410 internal irqs */ - - switch (irqno) { - /* deal with the special IRQs (cascaded) */ - - case IRQ_EINT4t7: - case IRQ_EINT8t23: - case IRQ_UART0: - case IRQ_UART1: - case IRQ_UART2: - case IRQ_ADCPARENT: - set_irq_chip(irqno, &s3c_irq_level_chip); - set_irq_handler(irqno, handle_level_irq); - break; - - case IRQ_RESERVED6: - case IRQ_RESERVED24: - /* no IRQ here */ - break; - - default: - //irqdbf("registering irq %d (s3c irq)\n", irqno); - set_irq_chip(irqno, &s3c_irq_chip); - set_irq_handler(irqno, handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - } - - /* setup the cascade irq handlers */ - - set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); - set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); - - set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); - set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); - set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); - set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); - - /* external interrupts */ - - for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { - irqdbf("registering irq %d (ext int)\n", irqno); - set_irq_chip(irqno, &s3c_irq_eint0t4); - set_irq_handler(irqno, handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { - irqdbf("registering irq %d (extended s3c irq)\n", irqno); - set_irq_chip(irqno, &s3c_irqext_chip); - set_irq_handler(irqno, handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - /* register the uart interrupts */ - - irqdbf("s3c2410: registering external interrupts\n"); - - for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { - irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); - set_irq_chip(irqno, &s3c_irq_uart0); - set_irq_handler(irqno, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { - irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); - set_irq_chip(irqno, &s3c_irq_uart1); - set_irq_handler(irqno, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { - irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); - set_irq_chip(irqno, &s3c_irq_uart2); - set_irq_handler(irqno, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { - irqdbf("registering irq %d (s3c adc irq)\n", irqno); - set_irq_chip(irqno, &s3c_irq_adc); - set_irq_handler(irqno, handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - irqdbf("s3c2410: registered interrupt handlers\n"); -} diff --git a/arch/arm/plat-s3c24xx/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c deleted file mode 100644 index bd965f2feec..00000000000 --- a/arch/arm/plat-s3c24xx/pm-simtec.c +++ /dev/null @@ -1,66 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/pm-simtec.c - * - * Copyright (c) 2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * http://armlinux.simtec.co.uk/ - * - * Power Management helpers for Simtec S3C24XX implementations - * - * 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/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/device.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include <asm/hardware.h> -#include <asm/io.h> - -#include <asm/arch/map.h> -#include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-mem.h> - -#include <asm/mach-types.h> - -#include <asm/plat-s3c24xx/pm.h> - -#define COPYRIGHT ", (c) 2005 Simtec Electronics" - -/* pm_simtec_init - * - * enable the power management functions -*/ - -static __init int pm_simtec_init(void) -{ - unsigned long gstatus4; - - /* check which machine we are running on */ - - if (!machine_is_bast() && !machine_is_vr1000() && - !machine_is_anubis() && !machine_is_osiris() && - !machine_is_aml_m5900()) - return 0; - - printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n"); - - gstatus4 = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30; - gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28; - gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK); - - __raw_writel(gstatus4, S3C2410_GSTATUS4); - - return s3c2410_pm_init(); -} - -arch_initcall(pm_simtec_init); diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c deleted file mode 100644 index c6b03f8ab26..00000000000 --- a/arch/arm/plat-s3c24xx/pm.c +++ /dev/null @@ -1,633 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/pm.c - * - * Copyright (c) 2004,2006 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C24XX Power Manager (Suspend-To-RAM) support - * - * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Parts based on arch/arm/mach-pxa/pm.c - * - * Thanks to Dimitry Andric for debugging -*/ - -#include <linux/init.h> -#include <linux/suspend.h> -#include <linux/errno.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/crc32.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/serial_core.h> - -#include <asm/cacheflush.h> -#include <asm/hardware.h> -#include <asm/io.h> - -#include <asm/arch/regs-serial.h> -#include <asm/arch/regs-clock.h> -#include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-mem.h> -#include <asm/arch/regs-irq.h> - -#include <asm/mach/time.h> - -#include <asm/plat-s3c24xx/pm.h> - -/* for external use */ - -unsigned long s3c_pm_flags; - -#define PFX "s3c24xx-pm: " - -static struct sleep_save core_save[] = { - SAVE_ITEM(S3C2410_LOCKTIME), - SAVE_ITEM(S3C2410_CLKCON), - - /* we restore the timings here, with the proviso that the board - * brings the system up in an slower, or equal frequency setting - * to the original system. - * - * if we cannot guarantee this, then things are going to go very - * wrong here, as we modify the refresh and both pll settings. - */ - - SAVE_ITEM(S3C2410_BWSCON), - SAVE_ITEM(S3C2410_BANKCON0), - SAVE_ITEM(S3C2410_BANKCON1), - SAVE_ITEM(S3C2410_BANKCON2), - SAVE_ITEM(S3C2410_BANKCON3), - SAVE_ITEM(S3C2410_BANKCON4), - SAVE_ITEM(S3C2410_BANKCON5), - - SAVE_ITEM(S3C2410_CLKDIVN), - SAVE_ITEM(S3C2410_MPLLCON), - SAVE_ITEM(S3C2410_UPLLCON), - SAVE_ITEM(S3C2410_CLKSLOW), - SAVE_ITEM(S3C2410_REFRESH), -}; - -static struct sleep_save gpio_save[] = { - SAVE_ITEM(S3C2410_GPACON), - SAVE_ITEM(S3C2410_GPADAT), - - SAVE_ITEM(S3C2410_GPBCON), - SAVE_ITEM(S3C2410_GPBDAT), - SAVE_ITEM(S3C2410_GPBUP), - - SAVE_ITEM(S3C2410_GPCCON), - SAVE_ITEM(S3C2410_GPCDAT), - SAVE_ITEM(S3C2410_GPCUP), - - SAVE_ITEM(S3C2410_GPDCON), - SAVE_ITEM(S3C2410_GPDDAT), - SAVE_ITEM(S3C2410_GPDUP), - - SAVE_ITEM(S3C2410_GPECON), - SAVE_ITEM(S3C2410_GPEDAT), - SAVE_ITEM(S3C2410_GPEUP), - - SAVE_ITEM(S3C2410_GPFCON), - SAVE_ITEM(S3C2410_GPFDAT), - SAVE_ITEM(S3C2410_GPFUP), - - SAVE_ITEM(S3C2410_GPGCON), - SAVE_ITEM(S3C2410_GPGDAT), - SAVE_ITEM(S3C2410_GPGUP), - - SAVE_ITEM(S3C2410_GPHCON), - SAVE_ITEM(S3C2410_GPHDAT), - SAVE_ITEM(S3C2410_GPHUP), - - SAVE_ITEM(S3C2410_DCLKCON), -}; - -#ifdef CONFIG_S3C2410_PM_DEBUG - -#define SAVE_UART(va) \ - SAVE_ITEM((va) + S3C2410_ULCON), \ - SAVE_ITEM((va) + S3C2410_UCON), \ - SAVE_ITEM((va) + S3C2410_UFCON), \ - SAVE_ITEM((va) + S3C2410_UMCON), \ - SAVE_ITEM((va) + S3C2410_UBRDIV) - -static struct sleep_save uart_save[] = { - SAVE_UART(S3C24XX_VA_UART0), - SAVE_UART(S3C24XX_VA_UART1), -#ifndef CONFIG_CPU_S3C2400 - SAVE_UART(S3C24XX_VA_UART2), -#endif -}; - -/* debug - * - * we send the debug to printascii() to allow it to be seen if the - * system never wakes up from the sleep -*/ - -extern void printascii(const char *); - -void pm_dbg(const char *fmt, ...) -{ - va_list va; - char buff[256]; - - va_start(va, fmt); - vsprintf(buff, fmt, va); - va_end(va); - - printascii(buff); -} - -static void s3c2410_pm_debug_init(void) -{ - unsigned long tmp = __raw_readl(S3C2410_CLKCON); - - /* re-start uart clocks */ - tmp |= S3C2410_CLKCON_UART0; - tmp |= S3C2410_CLKCON_UART1; - tmp |= S3C2410_CLKCON_UART2; - - __raw_writel(tmp, S3C2410_CLKCON); - udelay(10); -} - -#define DBG(fmt...) pm_dbg(fmt) -#else -#define DBG(fmt...) printk(KERN_DEBUG fmt) - -#define s3c2410_pm_debug_init() do { } while(0) - -static struct sleep_save uart_save[] = {}; -#endif - -#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0 - -/* suspend checking code... - * - * this next area does a set of crc checks over all the installed - * memory, so the system can verify if the resume was ok. - * - * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC, - * increasing it will mean that the area corrupted will be less easy to spot, - * and reducing the size will cause the CRC save area to grow -*/ - -#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024) - -static u32 crc_size; /* size needed for the crc block */ -static u32 *crcs; /* allocated over suspend/resume */ - -typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg); - -/* s3c2410_pm_run_res - * - * go thorugh the given resource list, and look for system ram -*/ - -static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg) -{ - while (ptr != NULL) { - if (ptr->child != NULL) - s3c2410_pm_run_res(ptr->child, fn, arg); - - if ((ptr->flags & IORESOURCE_MEM) && - strcmp(ptr->name, "System RAM") == 0) { - DBG("Found system RAM at %08lx..%08lx\n", - ptr->start, ptr->end); - arg = (fn)(ptr, arg); - } - - ptr = ptr->sibling; - } -} - -static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg) -{ - s3c2410_pm_run_res(&iomem_resource, fn, arg); -} - -static u32 *s3c2410_pm_countram(struct resource *res, u32 *val) -{ - u32 size = (u32)(res->end - res->start)+1; - - size += CHECK_CHUNKSIZE-1; - size /= CHECK_CHUNKSIZE; - - DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size); - - *val += size * sizeof(u32); - return val; -} - -/* s3c2410_pm_prepare_check - * - * prepare the necessary information for creating the CRCs. This - * must be done before the final save, as it will require memory - * allocating, and thus touching bits of the kernel we do not - * know about. -*/ - -static void s3c2410_pm_check_prepare(void) -{ - crc_size = 0; - - s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size); - - DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size); - - crcs = kmalloc(crc_size+4, GFP_KERNEL); - if (crcs == NULL) - printk(KERN_ERR "Cannot allocated CRC save area\n"); -} - -static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val) -{ - unsigned long addr, left; - - for (addr = res->start; addr < res->end; - addr += CHECK_CHUNKSIZE) { - left = res->end - addr; - - if (left > CHECK_CHUNKSIZE) - left = CHECK_CHUNKSIZE; - - *val = crc32_le(~0, phys_to_virt(addr), left); - val++; - } - - return val; -} - -/* s3c2410_pm_check_store - * - * compute the CRC values for the memory blocks before the final - * sleep. -*/ - -static void s3c2410_pm_check_store(void) -{ - if (crcs != NULL) - s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs); -} - -/* in_region - * - * return TRUE if the area defined by ptr..ptr+size contatins the - * what..what+whatsz -*/ - -static inline int in_region(void *ptr, int size, void *what, size_t whatsz) -{ - if ((what+whatsz) < ptr) - return 0; - - if (what > (ptr+size)) - return 0; - - return 1; -} - -static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val) -{ - void *save_at = phys_to_virt(s3c2410_sleep_save_phys); - unsigned long addr; - unsigned long left; - void *ptr; - u32 calc; - - for (addr = res->start; addr < res->end; - addr += CHECK_CHUNKSIZE) { - left = res->end - addr; - - if (left > CHECK_CHUNKSIZE) - left = CHECK_CHUNKSIZE; - - ptr = phys_to_virt(addr); - - if (in_region(ptr, left, crcs, crc_size)) { - DBG("skipping %08lx, has crc block in\n", addr); - goto skip_check; - } - - if (in_region(ptr, left, save_at, 32*4 )) { - DBG("skipping %08lx, has save block in\n", addr); - goto skip_check; - } - - /* calculate and check the checksum */ - - calc = crc32_le(~0, ptr, left); - if (calc != *val) { - printk(KERN_ERR PFX "Restore CRC error at " - "%08lx (%08x vs %08x)\n", addr, calc, *val); - - DBG("Restore CRC error at %08lx (%08x vs %08x)\n", - addr, calc, *val); - } - - skip_check: - val++; - } - - return val; -} - -/* s3c2410_pm_check_restore - * - * check the CRCs after the restore event and free the memory used - * to hold them -*/ - -static void s3c2410_pm_check_restore(void) -{ - if (crcs != NULL) { - s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs); - kfree(crcs); - crcs = NULL; - } -} - -#else - -#define s3c2410_pm_check_prepare() do { } while(0) -#define s3c2410_pm_check_restore() do { } while(0) -#define s3c2410_pm_check_store() do { } while(0) -#endif - -/* helper functions to save and restore register state */ - -void s3c2410_pm_do_save(struct sleep_save *ptr, int count) -{ - for (; count > 0; count--, ptr++) { - ptr->val = __raw_readl(ptr->reg); - DBG("saved %p value %08lx\n", ptr->reg, ptr->val); - } -} - -/* s3c2410_pm_do_restore - * - * restore the system from the given list of saved registers - * - * Note, we do not use DBG() in here, as the system may not have - * restore the UARTs state yet -*/ - -void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) -{ - for (; count > 0; count--, ptr++) { - printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n", - ptr->reg, ptr->val, __raw_readl(ptr->reg)); - - __raw_writel(ptr->val, ptr->reg); - } -} - -/* s3c2410_pm_do_restore_core - * - * similar to s3c2410_pm_do_restore_core - * - * WARNING: Do not put any debug in here that may effect memory or use - * peripherals, as things may be changing! -*/ - -static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count) -{ - for (; count > 0; count--, ptr++) { - __raw_writel(ptr->val, ptr->reg); - } -} - -/* s3c2410_pm_show_resume_irqs - * - * print any IRQs asserted at resume time (ie, we woke from) -*/ - -static void s3c2410_pm_show_resume_irqs(int start, unsigned long which, - unsigned long mask) -{ - int i; - - which &= ~mask; - - for (i = 0; i <= 31; i++) { - if ((which) & (1L<<i)) { - DBG("IRQ %d asserted at resume\n", start+i); - } - } -} - -/* s3c2410_pm_check_resume_pin - * - * check to see if the pin is configured correctly for sleep mode, and - * make any necessary adjustments if it is not -*/ - -static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) -{ - unsigned long irqstate; - unsigned long pinstate; - int irq = s3c2410_gpio_getirq(pin); - - if (irqoffs < 4) - irqstate = s3c_irqwake_intmask & (1L<<irqoffs); - else - irqstate = s3c_irqwake_eintmask & (1L<<irqoffs); - - pinstate = s3c2410_gpio_getcfg(pin); - - if (!irqstate) { - if (pinstate == S3C2410_GPIO_IRQ) - DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin); - } else { - if (pinstate == S3C2410_GPIO_IRQ) { - DBG("Disabling IRQ %d (pin %d)\n", irq, pin); - s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); - } - } -} - -/* s3c2410_pm_configure_extint - * - * configure all external interrupt pins -*/ - -static void s3c2410_pm_configure_extint(void) -{ - int pin; - - /* for each of the external interrupts (EINT0..EINT15) we - * need to check wether it is an external interrupt source, - * and then configure it as an input if it is not - */ - - for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) { - s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0); - } - - for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) { - s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8); - } -} - -void (*pm_cpu_prep)(void); -void (*pm_cpu_sleep)(void); - -#define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) - -/* s3c2410_pm_enter - * - * central control for sleep/resume process -*/ - -static int s3c2410_pm_enter(suspend_state_t state) -{ - unsigned long regs_save[16]; - - /* ensure the debug is initialised (if enabled) */ - - s3c2410_pm_debug_init(); - - DBG("s3c2410_pm_enter(%d)\n", state); - - if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { - printk(KERN_ERR PFX "error: no cpu sleep functions set\n"); - return -EINVAL; - } - - /* check if we have anything to wake-up with... bad things seem - * to happen if you suspend with no wakeup (system will often - * require a full power-cycle) - */ - - if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && - !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { - printk(KERN_ERR PFX "No sources enabled for wake-up!\n"); - printk(KERN_ERR PFX "Aborting sleep\n"); - return -EINVAL; - } - - /* prepare check area if configured */ - - s3c2410_pm_check_prepare(); - - /* store the physical address of the register recovery block */ - - s3c2410_sleep_save_phys = virt_to_phys(regs_save); - - DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys); - - /* save all necessary core registers not covered by the drivers */ - - s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); - s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); - s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); - - /* set the irq configuration for wake */ - - s3c2410_pm_configure_extint(); - - DBG("sleep: irq wakeup masks: %08lx,%08lx\n", - s3c_irqwake_intmask, s3c_irqwake_eintmask); - - __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK); - __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK); - - /* ack any outstanding external interrupts before we go to sleep */ - - __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); - __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND); - __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND); - - /* call cpu specific preperation */ - - pm_cpu_prep(); - - /* flush cache back to ram */ - - flush_cache_all(); - - s3c2410_pm_check_store(); - - /* send the cpu to sleep... */ - - __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */ - - /* s3c2410_cpu_save will also act as our return point from when - * we resume as it saves its own register state, so use the return - * code to differentiate return from save and return from sleep */ - - if (s3c2410_cpu_save(regs_save) == 0) { - flush_cache_all(); - pm_cpu_sleep(); - } - - /* restore the cpu state */ - - cpu_init(); - - /* restore the system state */ - - s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); - s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); - s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); - - s3c2410_pm_debug_init(); - - /* check what irq (if any) restored the system */ - - DBG("post sleep: IRQs 0x%08x, 0x%08x\n", - __raw_readl(S3C2410_SRCPND), - __raw_readl(S3C2410_EINTPEND)); - - s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND), - s3c_irqwake_intmask); - - s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND), - s3c_irqwake_eintmask); - - DBG("post sleep, preparing to return\n"); - - s3c2410_pm_check_restore(); - - /* ok, let's return from sleep */ - - DBG("S3C2410 PM Resume (post-restore)\n"); - return 0; -} - -static struct pm_ops s3c2410_pm_ops = { - .enter = s3c2410_pm_enter, - .valid = pm_valid_only_mem, -}; - -/* s3c2410_pm_init - * - * Attach the power management functions. This should be called - * from the board specific initialisation if the board supports - * it. -*/ - -int __init s3c2410_pm_init(void) -{ - printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n"); - - pm_set_ops(&s3c2410_pm_ops); - return 0; -} diff --git a/arch/arm/plat-s3c24xx/s3c244x-irq.c b/arch/arm/plat-s3c24xx/s3c244x-irq.c deleted file mode 100644 index 2dbb2606d44..00000000000 --- a/arch/arm/plat-s3c24xx/s3c244x-irq.c +++ /dev/null @@ -1,145 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c - * - * Copyright (c) 2003,2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/sysdev.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/io.h> - -#include <asm/mach/irq.h> - -#include <asm/arch/regs-irq.h> -#include <asm/arch/regs-gpio.h> - -#include <asm/plat-s3c24xx/cpu.h> -#include <asm/plat-s3c24xx/pm.h> -#include <asm/plat-s3c24xx/irq.h> - -/* camera irq */ - -static void s3c_irq_demux_cam(unsigned int irq, - struct irq_desc *desc) -{ - unsigned int subsrc, submsk; - struct irq_desc *mydesc; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= 11; - subsrc &= 3; - - if (subsrc != 0) { - if (subsrc & 1) { - mydesc = irq_desc + IRQ_S3C2440_CAM_C; - desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc); - } - if (subsrc & 2) { - mydesc = irq_desc + IRQ_S3C2440_CAM_P; - desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc); - } - } -} - -#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) - -static void -s3c_irq_cam_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11); -} - -static void -s3c_irq_cam_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_CAM); -} - -static void -s3c_irq_cam_ack(unsigned int irqno) -{ - s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); -} - -static struct irq_chip s3c_irq_cam = { - .mask = s3c_irq_cam_mask, - .unmask = s3c_irq_cam_unmask, - .ack = s3c_irq_cam_ack, -}; - -static int s3c244x_irq_add(struct sys_device *sysdev) -{ - unsigned int irqno; - - set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); - set_irq_handler(IRQ_NFCON, handle_level_irq); - set_irq_flags(IRQ_NFCON, IRQF_VALID); - - /* add chained handler for camera */ - - set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); - set_irq_handler(IRQ_CAM, handle_level_irq); - set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); - - for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { - set_irq_chip(irqno, &s3c_irq_cam); - set_irq_handler(irqno, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - return 0; -} - -static struct sysdev_driver s3c2440_irq_driver = { - .add = s3c244x_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; - -static int s3c2440_irq_init(void) -{ - return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); -} - -arch_initcall(s3c2440_irq_init); - -static struct sysdev_driver s3c2442_irq_driver = { - .add = s3c244x_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; - - -static int s3c2442_irq_init(void) -{ - return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver); -} - -arch_initcall(s3c2442_irq_init); diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c deleted file mode 100644 index 767f2e9a3a5..00000000000 --- a/arch/arm/plat-s3c24xx/s3c244x.c +++ /dev/null @@ -1,184 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/s3c244x.c - * - * Copyright (c) 2004-2006 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443) - * - * 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/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/platform_device.h> -#include <linux/sysdev.h> -#include <linux/clk.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> - -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/irq.h> - -#include <asm/arch/regs-clock.h> -#include <asm/arch/regs-serial.h> -#include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-gpioj.h> -#include <asm/arch/regs-dsc.h> - -#include <asm/plat-s3c24xx/s3c2410.h> -#include <asm/plat-s3c24xx/s3c2440.h> -#include "s3c244x.h" -#include <asm/plat-s3c24xx/clock.h> -#include <asm/plat-s3c24xx/devs.h> -#include <asm/plat-s3c24xx/cpu.h> -#include <asm/plat-s3c24xx/pm.h> - -static struct map_desc s3c244x_iodesc[] __initdata = { - IODESC_ENT(CLKPWR), - IODESC_ENT(TIMER), - IODESC_ENT(WATCHDOG), - IODESC_ENT(LCD), -}; - -/* uart initialisation */ - -void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); -} - -void __init s3c244x_map_io(struct map_desc *mach_desc, int size) -{ - /* register our io-tables */ - - iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc)); - iotable_init(mach_desc, size); - - /* rename any peripherals used differing from the s3c2410 */ - - s3c_device_i2c.name = "s3c2440-i2c"; - s3c_device_nand.name = "s3c2440-nand"; - s3c_device_usbgadget.name = "s3c2440-usbgadget"; -} - -void __init s3c244x_init_clocks(int xtal) -{ - unsigned long clkdiv; - unsigned long camdiv; - unsigned long hclk, fclk, pclk; - int hdiv = 1; - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - camdiv = __raw_readl(S3C2440_CAMDIVN); - - /* work out clock scalings */ - - switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { - case S3C2440_CLKDIVN_HDIVN_1: - hdiv = 1; - break; - - case S3C2440_CLKDIVN_HDIVN_2: - hdiv = 2; - break; - - case S3C2440_CLKDIVN_HDIVN_4_8: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; - break; - - case S3C2440_CLKDIVN_HDIVN_3_6: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; - break; - } - - hclk = fclk / hdiv; - pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); - - /* print brief summary of clocks, etc */ - - printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - /* initialise the clocks here, to allow other things like the - * console to use them, and to add new ones after the initialisation - */ - - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); - s3c2410_baseclk_add(); -} - -#ifdef CONFIG_PM - -static struct sleep_save s3c244x_sleep[] = { - SAVE_ITEM(S3C2440_DSC0), - SAVE_ITEM(S3C2440_DSC1), - SAVE_ITEM(S3C2440_GPJDAT), - SAVE_ITEM(S3C2440_GPJCON), - SAVE_ITEM(S3C2440_GPJUP) -}; - -static int s3c244x_suspend(struct sys_device *dev, pm_message_t state) -{ - s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); - return 0; -} - -static int s3c244x_resume(struct sys_device *dev) -{ - s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); - return 0; -} - -#else -#define s3c244x_suspend NULL -#define s3c244x_resume NULL -#endif - -/* Since the S3C2442 and S3C2440 share items, put both sysclasses here */ - -struct sysdev_class s3c2440_sysclass = { - set_kset_name("s3c2440-core"), - .suspend = s3c244x_suspend, - .resume = s3c244x_resume -}; - -struct sysdev_class s3c2442_sysclass = { - set_kset_name("s3c2442-core"), - .suspend = s3c244x_suspend, - .resume = s3c244x_resume -}; - -/* need to register class before we actually register the device, and - * we also need to ensure that it has been initialised before any of the - * drivers even try to use it (even if not on an s3c2440 based system) - * as a driver which may support both 2410 and 2440 may try and use it. -*/ - -static int __init s3c2440_core_init(void) -{ - return sysdev_class_register(&s3c2440_sysclass); -} - -core_initcall(s3c2440_core_init); - -static int __init s3c2442_core_init(void) -{ - return sysdev_class_register(&s3c2442_sysclass); -} - -core_initcall(s3c2442_core_init); diff --git a/arch/arm/plat-s3c24xx/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h deleted file mode 100644 index f8ed17676a3..00000000000 --- a/arch/arm/plat-s3c24xx/s3c244x.h +++ /dev/null @@ -1,25 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/s3c244x.h - * - * Copyright (c) 2004-2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Header file for S3C2440 and S3C2442 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. -*/ - -#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) - -extern void s3c244x_map_io(struct map_desc *mach_desc, int size); - -extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); - -extern void s3c244x_init_clocks(int xtal); - -#else -#define s3c244x_init_clocks NULL -#define s3c244x_init_uarts NULL -#define s3c244x_map_io NULL -#endif diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S deleted file mode 100644 index 7b7ae790b00..00000000000 --- a/arch/arm/plat-s3c24xx/sleep.S +++ /dev/null @@ -1,157 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/sleep.S - * - * Copyright (c) 2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C2410 Power Manager (Suspend-To-RAM) support - * - * Based on PXA/SA1100 sleep code by: - * Nicolas Pitre, (c) 2002 Monta Vista Software Inc - * Cliff Brake, (c) 2001 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <linux/linkage.h> -#include <asm/assembler.h> -#include <asm/hardware.h> -#include <asm/arch/map.h> - -#include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-clock.h> -#include <asm/arch/regs-mem.h> -#include <asm/arch/regs-serial.h> - -/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not - * reset the UART configuration, only enable if you really need this! -*/ -//#define CONFIG_DEBUG_RESUME - - .text - - /* s3c2410_cpu_save - * - * save enough of the CPU state to allow us to re-start - * pm.c code. as we store items like the sp/lr, we will - * end up returning from this function when the cpu resumes - * so the return value is set to mark this. - * - * This arangement means we avoid having to flush the cache - * from this code. - * - * entry: - * r0 = pointer to save block - * - * exit: - * r0 = 0 => we stored everything - * 1 => resumed from sleep - */ - -ENTRY(s3c2410_cpu_save) - stmfd sp!, { r4 - r12, lr } - - @@ store co-processor registers - - mrc p15, 0, r4, c13, c0, 0 @ PID - mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ translation table base address - mrc p15, 0, r7, c1, c0, 0 @ control register - - stmia r0, { r4 - r13 } - - mov r0, #0 - ldmfd sp, { r4 - r12, pc } - - @@ return to the caller, after having the MMU - @@ turned on, this restores the last bits from the - @@ stack -resume_with_mmu: - mov r0, #1 - ldmfd sp!, { r4 - r12, pc } - - .ltorg - - @@ the next bits sit in the .data segment, even though they - @@ happen to be code... the s3c2410_sleep_save_phys needs to be - @@ accessed by the resume code before it can restore the MMU. - @@ This means that the variable has to be close enough for the - @@ code to read it... since the .text segment needs to be RO, - @@ the data segment can be the only place to put this code. - - .data - - .global s3c2410_sleep_save_phys -s3c2410_sleep_save_phys: - .word 0 - - /* s3c2410_cpu_resume - * - * resume code entry for bootloader to call - * - * we must put this code here in the data segment as we have no - * other way of restoring the stack pointer after sleep, and we - * must not write to the code segment (code is read-only) - */ - -ENTRY(s3c2410_cpu_resume) - mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE - msr cpsr_c, r0 - - @@ load UART to allow us to print the two characters for - @@ resume debug - - mov r2, #S3C24XX_PA_UART & 0xff000000 - orr r2, r2, #S3C24XX_PA_UART & 0xff000 - -#if 0 - /* SMDK2440 LED set */ - mov r14, #S3C24XX_PA_GPIO - ldr r12, [ r14, #0x54 ] - bic r12, r12, #3<<4 - orr r12, r12, #1<<7 - str r12, [ r14, #0x54 ] -#endif - -#ifdef CONFIG_DEBUG_RESUME - mov r3, #'L' - strb r3, [ r2, #S3C2410_UTXH ] -1001: - ldrb r14, [ r3, #S3C2410_UTRSTAT ] - tst r14, #S3C2410_UTRSTAT_TXE - beq 1001b -#endif /* CONFIG_DEBUG_RESUME */ - - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs - mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches - - ldr r0, s3c2410_sleep_save_phys @ address of restore block - ldmia r0, { r4 - r13 } - - mcr p15, 0, r4, c13, c0, 0 @ PID - mcr p15, 0, r5, c3, c0, 0 @ Domain ID - mcr p15, 0, r6, c2, c0, 0 @ translation table base - -#ifdef CONFIG_DEBUG_RESUME - mov r3, #'R' - strb r3, [ r2, #S3C2410_UTXH ] -#endif - - ldr r2, =resume_with_mmu - mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc - nop @ second-to-last before mmu - mov pc, r2 @ go back to virtual address - - .ltorg diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c deleted file mode 100644 index b7667375bce..00000000000 --- a/arch/arm/plat-s3c24xx/time.c +++ /dev/null @@ -1,262 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/time.c - * - * Copyright (C) 2003-2005 Simtec Electronics - * Ben Dooks, <ben@simtec.co.uk> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/err.h> -#include <linux/clk.h> - -#include <asm/system.h> -#include <asm/leds.h> -#include <asm/mach-types.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/arch/map.h> -#include <asm/arch/regs-timer.h> -#include <asm/arch/regs-irq.h> -#include <asm/mach/time.h> - -#include <asm/plat-s3c24xx/clock.h> -#include <asm/plat-s3c24xx/cpu.h> - -static unsigned long timer_startval; -static unsigned long timer_usec_ticks; - -#define TIMER_USEC_SHIFT 16 - -/* we use the shifted arithmetic to work out the ratio of timer ticks - * to usecs, as often the peripheral clock is not a nice even multiple - * of 1MHz. - * - * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok - * for the current HZ value of 200 without producing overflows. - * - * Original patch by Dimitry Andric, updated by Ben Dooks -*/ - - -/* timer_mask_usec_ticks - * - * given a clock and divisor, make the value to pass into timer_ticks_to_usec - * to scale the ticks into usecs -*/ - -static inline unsigned long -timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk) -{ - unsigned long den = pclk / 1000; - - return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den; -} - -/* timer_ticks_to_usec - * - * convert timer ticks to usec. -*/ - -static inline unsigned long timer_ticks_to_usec(unsigned long ticks) -{ - unsigned long res; - - res = ticks * timer_usec_ticks; - res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */ - - return res >> TIMER_USEC_SHIFT; -} - -/*** - * Returns microsecond since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - * IRQs are disabled before entering here from do_gettimeofday() - */ - -#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) - -static unsigned long s3c2410_gettimeoffset (void) -{ - unsigned long tdone; - unsigned long irqpend; - unsigned long tval; - - /* work out how many ticks have gone since last timer interrupt */ - - tval = __raw_readl(S3C2410_TCNTO(4)); - tdone = timer_startval - tval; - - /* check to see if there is an interrupt pending */ - - irqpend = __raw_readl(S3C2410_SRCPND); - if (irqpend & SRCPND_TIMER4) { - /* re-read the timer, and try and fix up for the missed - * interrupt. Note, the interrupt may go off before the - * timer has re-loaded from wrapping. - */ - - tval = __raw_readl(S3C2410_TCNTO(4)); - tdone = timer_startval - tval; - - if (tval != 0) - tdone += timer_startval; - } - - return timer_ticks_to_usec(tdone); -} - - -/* - * IRQ handler for the timer - */ -static irqreturn_t -s3c2410_timer_interrupt(int irq, void *dev_id) -{ - write_seqlock(&xtime_lock); - timer_tick(); - write_sequnlock(&xtime_lock); - return IRQ_HANDLED; -} - -static struct irqaction s3c2410_timer_irq = { - .name = "S3C2410 Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = s3c2410_timer_interrupt, -}; - -#define use_tclk1_12() ( \ - machine_is_bast() || \ - machine_is_vr1000() || \ - machine_is_anubis() || \ - machine_is_osiris() ) - -/* - * Set up timer interrupt, and return the current time in seconds. - * - * Currently we only use timer4, as it is the only timer which has no - * other function that can be exploited externally - */ -static void s3c2410_timer_setup (void) -{ - unsigned long tcon; - unsigned long tcnt; - unsigned long tcfg1; - unsigned long tcfg0; - - tcnt = 0xffff; /* default value for tcnt */ - - /* read the current timer configuration bits */ - - tcon = __raw_readl(S3C2410_TCON); - tcfg1 = __raw_readl(S3C2410_TCFG1); - tcfg0 = __raw_readl(S3C2410_TCFG0); - - /* configure the system for whichever machine is in use */ - - if (use_tclk1_12()) { - /* timer is at 12MHz, scaler is 1 */ - timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); - tcnt = 12000000 / HZ; - - tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; - tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; - } else { - unsigned long pclk; - struct clk *clk; - - /* for the h1940 (and others), we use the pclk from the core - * to generate the timer values. since values around 50 to - * 70MHz are not values we can directly generate the timer - * value from, we need to pre-scale and divide before using it. - * - * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz - * (8.45 ticks per usec) - */ - - /* this is used as default if no other timer can be found */ - - clk = clk_get(NULL, "timers"); - if (IS_ERR(clk)) - panic("failed to get clock for system timer"); - - clk_enable(clk); - - pclk = clk_get_rate(clk); - - /* configure clock tick */ - - timer_usec_ticks = timer_mask_usec_ticks(6, pclk); - - tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; - tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; - - tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; - tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; - - tcnt = (pclk / 6) / HZ; - } - - /* timers reload after counting zero, so reduce the count by 1 */ - - tcnt--; - - printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", - tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); - - /* check to see if timer is within 16bit range... */ - if (tcnt > 0xffff) { - panic("setup_timer: HZ is too small, cannot configure timer!"); - return; - } - - __raw_writel(tcfg1, S3C2410_TCFG1); - __raw_writel(tcfg0, S3C2410_TCFG0); - - timer_startval = tcnt; - __raw_writel(tcnt, S3C2410_TCNTB(4)); - - /* ensure timer is stopped... */ - - tcon &= ~(7<<20); - tcon |= S3C2410_TCON_T4RELOAD; - tcon |= S3C2410_TCON_T4MANUALUPD; - - __raw_writel(tcon, S3C2410_TCON); - __raw_writel(tcnt, S3C2410_TCNTB(4)); - __raw_writel(tcnt, S3C2410_TCMPB(4)); - - /* start the timer running */ - tcon |= S3C2410_TCON_T4START; - tcon &= ~S3C2410_TCON_T4MANUALUPD; - __raw_writel(tcon, S3C2410_TCON); -} - -static void __init s3c2410_timer_init (void) -{ - s3c2410_timer_setup(); - setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); -} - -struct sys_timer s3c24xx_timer = { - .init = s3c2410_timer_init, - .offset = s3c2410_gettimeoffset, - .resume = s3c2410_timer_setup -}; |
