From e1f80f57443838f5f420c774744c50c81c178e2c Mon Sep 17 00:00:00 2001 From: KyongHo Cho Date: Wed, 4 Apr 2012 09:23:02 -0700 Subject: S5P: SYSMMU: Remove System MMU device driver This patch removes System MMU device driver from arm/plat-s5p tree for transition to implement IOMMU driver. Although controlling System MMU in this removing driver is similar to the new IOMMU driver in the following patch, the new one is almost rewrite of this driver and there is no benefit to moving the driver file from arch/arm/ to drivers/iommu. Signed-off-by: KyongHo Cho Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/devs.h | 1 - arch/arm/plat-samsung/include/plat/sysmmu.h | 95 ----------------------------- 2 files changed, 96 deletions(-) delete mode 100644 arch/arm/plat-samsung/include/plat/sysmmu.h (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2155d4af62a..4067d1dd7f1 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -133,7 +133,6 @@ extern struct platform_device exynos4_device_pcm1; extern struct platform_device exynos4_device_pcm2; extern struct platform_device exynos4_device_pd[]; extern struct platform_device exynos4_device_spdif; -extern struct platform_device exynos4_device_sysmmu; extern struct platform_device samsung_asoc_dma; extern struct platform_device samsung_asoc_idma; diff --git a/arch/arm/plat-samsung/include/plat/sysmmu.h b/arch/arm/plat-samsung/include/plat/sysmmu.h deleted file mode 100644 index 5fe8ee01a5b..00000000000 --- a/arch/arm/plat-samsung/include/plat/sysmmu.h +++ /dev/null @@ -1,95 +0,0 @@ -/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Samsung System MMU driver for S5P platform - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __PLAT_SAMSUNG_SYSMMU_H -#define __PLAT_SAMSUNG_SYSMMU_H __FILE__ - -enum S5P_SYSMMU_INTERRUPT_TYPE { - SYSMMU_PAGEFAULT, - SYSMMU_AR_MULTIHIT, - SYSMMU_AW_MULTIHIT, - SYSMMU_BUSERROR, - SYSMMU_AR_SECURITY, - SYSMMU_AR_ACCESS, - SYSMMU_AW_SECURITY, - SYSMMU_AW_PROTECTION, /* 7 */ - SYSMMU_FAULTS_NUM -}; - -#ifdef CONFIG_S5P_SYSTEM_MMU - -#include - -/** - * s5p_sysmmu_enable() - enable system mmu of ip - * @ips: The ip connected system mmu. - * #pgd: Base physical address of the 1st level page table - * - * This function enable system mmu to transfer address - * from virtual address to physical address - */ -void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd); - -/** - * s5p_sysmmu_disable() - disable sysmmu mmu of ip - * @ips: The ip connected system mmu. - * - * This function disable system mmu to transfer address - * from virtual address to physical address - */ -void s5p_sysmmu_disable(sysmmu_ips ips); - -/** - * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table - * @ips: The ip connected system mmu. - * @pgd: The page table base address. - * - * This function set page table base address - * When system mmu transfer address from virtaul address to physical address, - * system mmu refer address information from page table - */ -void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd); - -/** - * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu - * @ips: The ip connected system mmu. - * - * This function flush all TLB entry in system mmu - */ -void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips); - -/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs - * @itype: type of fault. - * @pgtable_base: the physical address of page table base. This is 0 if @ips is - * SYSMMU_BUSERROR. - * @fault_addr: the device (virtual) address that the System MMU tried to - * translated. This is 0 if @ips is SYSMMU_BUSERROR. - * Called when interrupt occurred by the System MMUs - * The device drivers of peripheral devices that has a System MMU can implement - * a fault handler to resolve address translation fault by System MMU. - * The meanings of return value and parameters are described below. - - * return value: non-zero if the fault is correctly resolved. - * zero if the fault is not handled. - */ -void s5p_sysmmu_set_fault_handler(sysmmu_ips ips, - int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, - unsigned long pgtable_base, - unsigned long fault_addr)); -#else -#define s5p_sysmmu_enable(ips, pgd) do { } while (0) -#define s5p_sysmmu_disable(ips) do { } while (0) -#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0) -#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0) -#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0) -#endif -#endif /* __ASM_PLAT_SYSMMU_H */ -- cgit v1.2.3-70-g09d2 From 18c411b7974f47f84c29507bdf3e0573890c0f0e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Sat, 12 May 2012 06:42:33 +0900 Subject: ARM: EXYNOS: add platform device for core DRM subsystem Add platform device for Exynos DRM core. This device is used for creating DRM user-space device and allocating memory for display buffers. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 5 +++++ arch/arm/mach-exynos/Makefile | 1 + arch/arm/mach-exynos/dev-drm.c | 29 +++++++++++++++++++++++++++++ arch/arm/plat-samsung/include/plat/devs.h | 2 ++ 4 files changed, 37 insertions(+) create mode 100644 arch/arm/mach-exynos/dev-drm.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index e81c35f936b..8bc89f27e9d 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -80,6 +80,11 @@ config EXYNOS4_DEV_AHCI help Compile in platform device definitions for AHCI +config EXYNOS_DEV_DRM + bool + help + Compile in platform device definitions for core DRM device + config EXYNOS4_SETUP_FIMD0 bool help diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 8631840d1b5..f67e882b9da 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o obj-y += dev-uart.o obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o +obj-$(CONFIG_EXYNOS_DEV_DRM) += dev-drm.o obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o diff --git a/arch/arm/mach-exynos/dev-drm.c b/arch/arm/mach-exynos/dev-drm.c new file mode 100644 index 00000000000..17c9c6ecc2e --- /dev/null +++ b/arch/arm/mach-exynos/dev-drm.c @@ -0,0 +1,29 @@ +/* + * linux/arch/arm/mach-exynos/dev-drm.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS - core DRM device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +#include + +static u64 exynos_drm_dma_mask = DMA_BIT_MASK(32); + +struct platform_device exynos_device_drm = { + .name = "exynos-drm", + .dev = { + .dma_mask = &exynos_drm_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2155d4af62a..62e6251e4b1 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -135,6 +135,8 @@ extern struct platform_device exynos4_device_pd[]; extern struct platform_device exynos4_device_spdif; extern struct platform_device exynos4_device_sysmmu; +extern struct platform_device exynos_device_drm; + extern struct platform_device samsung_asoc_dma; extern struct platform_device samsung_asoc_idma; extern struct platform_device samsung_device_keypad; -- cgit v1.2.3-70-g09d2 From bf46aaeacf728dad9d89ed3d604bf991035dfd77 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sun, 15 Apr 2012 21:13:29 -0700 Subject: ARM: SAMSUNG: move clock part for common s5p into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Makefile | 1 - arch/arm/plat-s5p/clock.c | 264 -------------------------------------- arch/arm/plat-samsung/Kconfig | 5 + arch/arm/plat-samsung/Makefile | 1 + arch/arm/plat-samsung/s5p-clock.c | 263 +++++++++++++++++++++++++++++++++++++ 5 files changed, 269 insertions(+), 265 deletions(-) delete mode 100644 arch/arm/plat-s5p/clock.c create mode 100644 arch/arm/plat-samsung/s5p-clock.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 4953d50707b..83152108af3 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,7 +12,6 @@ obj- := # Core files -obj-y += clock.o obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c deleted file mode 100644 index f68a9bb1194..00000000000 --- a/arch/arm/plat-s5p/clock.c +++ /dev/null @@ -1,264 +0,0 @@ -/* linux/arch/arm/plat-s5p/clock.c - * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P - Common clock support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call - * clk_ext_xtal_mux. -*/ -struct clk clk_ext_xtal_mux = { - .name = "ext_xtal", - .id = -1, -}; - -struct clk clk_xusbxti = { - .name = "xusbxti", - .id = -1, -}; - -struct clk s5p_clk_27m = { - .name = "clk_27m", - .id = -1, - .rate = 27000000, -}; - -/* 48MHz USB Phy clock output */ -struct clk clk_48m = { - .name = "clk_48m", - .id = -1, - .rate = 48000000, -}; - -/* APLL clock output - * No need .ctrlbit, this is always on -*/ -struct clk clk_fout_apll = { - .name = "fout_apll", - .id = -1, -}; - -/* BPLL clock output */ - -struct clk clk_fout_bpll = { - .name = "fout_bpll", - .id = -1, -}; - -/* CPLL clock output */ - -struct clk clk_fout_cpll = { - .name = "fout_cpll", - .id = -1, -}; - -/* MPLL clock output - * No need .ctrlbit, this is always on -*/ -struct clk clk_fout_mpll = { - .name = "fout_mpll", - .id = -1, -}; - -/* EPLL clock output */ -struct clk clk_fout_epll = { - .name = "fout_epll", - .id = -1, - .ctrlbit = (1 << 31), -}; - -/* DPLL clock output */ -struct clk clk_fout_dpll = { - .name = "fout_dpll", - .id = -1, - .ctrlbit = (1 << 31), -}; - -/* VPLL clock output */ -struct clk clk_fout_vpll = { - .name = "fout_vpll", - .id = -1, - .ctrlbit = (1 << 31), -}; - -/* Possible clock sources for APLL Mux */ -static struct clk *clk_src_apll_list[] = { - [0] = &clk_fin_apll, - [1] = &clk_fout_apll, -}; - -struct clksrc_sources clk_src_apll = { - .sources = clk_src_apll_list, - .nr_sources = ARRAY_SIZE(clk_src_apll_list), -}; - -/* Possible clock sources for BPLL Mux */ -static struct clk *clk_src_bpll_list[] = { - [0] = &clk_fin_bpll, - [1] = &clk_fout_bpll, -}; - -struct clksrc_sources clk_src_bpll = { - .sources = clk_src_bpll_list, - .nr_sources = ARRAY_SIZE(clk_src_bpll_list), -}; - -/* Possible clock sources for CPLL Mux */ -static struct clk *clk_src_cpll_list[] = { - [0] = &clk_fin_cpll, - [1] = &clk_fout_cpll, -}; - -struct clksrc_sources clk_src_cpll = { - .sources = clk_src_cpll_list, - .nr_sources = ARRAY_SIZE(clk_src_cpll_list), -}; - -/* Possible clock sources for MPLL Mux */ -static struct clk *clk_src_mpll_list[] = { - [0] = &clk_fin_mpll, - [1] = &clk_fout_mpll, -}; - -struct clksrc_sources clk_src_mpll = { - .sources = clk_src_mpll_list, - .nr_sources = ARRAY_SIZE(clk_src_mpll_list), -}; - -/* Possible clock sources for EPLL Mux */ -static struct clk *clk_src_epll_list[] = { - [0] = &clk_fin_epll, - [1] = &clk_fout_epll, -}; - -struct clksrc_sources clk_src_epll = { - .sources = clk_src_epll_list, - .nr_sources = ARRAY_SIZE(clk_src_epll_list), -}; - -/* Possible clock sources for DPLL Mux */ -static struct clk *clk_src_dpll_list[] = { - [0] = &clk_fin_dpll, - [1] = &clk_fout_dpll, -}; - -struct clksrc_sources clk_src_dpll = { - .sources = clk_src_dpll_list, - .nr_sources = ARRAY_SIZE(clk_src_dpll_list), -}; - -struct clk clk_vpll = { - .name = "vpll", - .id = -1, -}; - -int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable) -{ - unsigned int ctrlbit = clk->ctrlbit; - u32 con; - - con = __raw_readl(reg); - con = enable ? (con | ctrlbit) : (con & ~ctrlbit); - __raw_writel(con, reg); - return 0; -} - -int s5p_epll_enable(struct clk *clk, int enable) -{ - unsigned int ctrlbit = clk->ctrlbit; - unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; - - if (enable) - __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); - else - __raw_writel(epll_con, S5P_EPLL_CON); - - return 0; -} - -unsigned long s5p_epll_get_rate(struct clk *clk) -{ - return clk->rate; -} - -int s5p_spdif_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *pclk; - int ret; - - pclk = clk_get_parent(clk); - if (IS_ERR(pclk)) - return -EINVAL; - - ret = pclk->ops->set_rate(pclk, rate); - clk_put(pclk); - - return ret; -} - -unsigned long s5p_spdif_get_rate(struct clk *clk) -{ - struct clk *pclk; - int rate; - - pclk = clk_get_parent(clk); - if (IS_ERR(pclk)) - return -EINVAL; - - rate = pclk->ops->get_rate(pclk); - clk_put(pclk); - - return rate; -} - -struct clk_ops s5p_sclk_spdif_ops = { - .set_rate = s5p_spdif_set_rate, - .get_rate = s5p_spdif_get_rate, -}; - -static struct clk *s5p_clks[] __initdata = { - &clk_ext_xtal_mux, - &clk_48m, - &s5p_clk_27m, - &clk_fout_apll, - &clk_fout_mpll, - &clk_fout_epll, - &clk_fout_dpll, - &clk_fout_vpll, - &clk_vpll, - &clk_xusbxti, -}; - -void __init s5p_register_clocks(unsigned long xtal_freq) -{ - int ret; - - clk_ext_xtal_mux.rate = xtal_freq; - - ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks)); - if (ret > 0) - printk(KERN_ERR "Failed to register s5p clocks\n"); -} diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 71553f41001..3a48d9de22a 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -58,6 +58,11 @@ config SAMSUNG_CLKSRC Select the clock code for the clksrc implementation used by newer systems such as the S3C64XX. +config S5P_CLOCK + def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) + help + Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs + # options for IRQ support config SAMSUNG_IRQ_VIC_TIMER diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 6012366f33c..997ce100570 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -17,6 +17,7 @@ obj-y += clock.o obj-y += pwm-clock.o obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o +obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o diff --git a/arch/arm/plat-samsung/s5p-clock.c b/arch/arm/plat-samsung/s5p-clock.c new file mode 100644 index 00000000000..41d3dfd5ddd --- /dev/null +++ b/arch/arm/plat-samsung/s5p-clock.c @@ -0,0 +1,263 @@ +/* + * Copyright 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P - Common clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call + * clk_ext_xtal_mux. +*/ +struct clk clk_ext_xtal_mux = { + .name = "ext_xtal", + .id = -1, +}; + +struct clk clk_xusbxti = { + .name = "xusbxti", + .id = -1, +}; + +struct clk s5p_clk_27m = { + .name = "clk_27m", + .id = -1, + .rate = 27000000, +}; + +/* 48MHz USB Phy clock output */ +struct clk clk_48m = { + .name = "clk_48m", + .id = -1, + .rate = 48000000, +}; + +/* APLL clock output + * No need .ctrlbit, this is always on +*/ +struct clk clk_fout_apll = { + .name = "fout_apll", + .id = -1, +}; + +/* BPLL clock output */ + +struct clk clk_fout_bpll = { + .name = "fout_bpll", + .id = -1, +}; + +/* CPLL clock output */ + +struct clk clk_fout_cpll = { + .name = "fout_cpll", + .id = -1, +}; + +/* MPLL clock output + * No need .ctrlbit, this is always on +*/ +struct clk clk_fout_mpll = { + .name = "fout_mpll", + .id = -1, +}; + +/* EPLL clock output */ +struct clk clk_fout_epll = { + .name = "fout_epll", + .id = -1, + .ctrlbit = (1 << 31), +}; + +/* DPLL clock output */ +struct clk clk_fout_dpll = { + .name = "fout_dpll", + .id = -1, + .ctrlbit = (1 << 31), +}; + +/* VPLL clock output */ +struct clk clk_fout_vpll = { + .name = "fout_vpll", + .id = -1, + .ctrlbit = (1 << 31), +}; + +/* Possible clock sources for APLL Mux */ +static struct clk *clk_src_apll_list[] = { + [0] = &clk_fin_apll, + [1] = &clk_fout_apll, +}; + +struct clksrc_sources clk_src_apll = { + .sources = clk_src_apll_list, + .nr_sources = ARRAY_SIZE(clk_src_apll_list), +}; + +/* Possible clock sources for BPLL Mux */ +static struct clk *clk_src_bpll_list[] = { + [0] = &clk_fin_bpll, + [1] = &clk_fout_bpll, +}; + +struct clksrc_sources clk_src_bpll = { + .sources = clk_src_bpll_list, + .nr_sources = ARRAY_SIZE(clk_src_bpll_list), +}; + +/* Possible clock sources for CPLL Mux */ +static struct clk *clk_src_cpll_list[] = { + [0] = &clk_fin_cpll, + [1] = &clk_fout_cpll, +}; + +struct clksrc_sources clk_src_cpll = { + .sources = clk_src_cpll_list, + .nr_sources = ARRAY_SIZE(clk_src_cpll_list), +}; + +/* Possible clock sources for MPLL Mux */ +static struct clk *clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_fout_mpll, +}; + +struct clksrc_sources clk_src_mpll = { + .sources = clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_list), +}; + +/* Possible clock sources for EPLL Mux */ +static struct clk *clk_src_epll_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_fout_epll, +}; + +struct clksrc_sources clk_src_epll = { + .sources = clk_src_epll_list, + .nr_sources = ARRAY_SIZE(clk_src_epll_list), +}; + +/* Possible clock sources for DPLL Mux */ +static struct clk *clk_src_dpll_list[] = { + [0] = &clk_fin_dpll, + [1] = &clk_fout_dpll, +}; + +struct clksrc_sources clk_src_dpll = { + .sources = clk_src_dpll_list, + .nr_sources = ARRAY_SIZE(clk_src_dpll_list), +}; + +struct clk clk_vpll = { + .name = "vpll", + .id = -1, +}; + +int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + u32 con; + + con = __raw_readl(reg); + con = enable ? (con | ctrlbit) : (con & ~ctrlbit); + __raw_writel(con, reg); + return 0; +} + +int s5p_epll_enable(struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; + + if (enable) + __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); + else + __raw_writel(epll_con, S5P_EPLL_CON); + + return 0; +} + +unsigned long s5p_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +int s5p_spdif_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *pclk; + int ret; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + ret = pclk->ops->set_rate(pclk, rate); + clk_put(pclk); + + return ret; +} + +unsigned long s5p_spdif_get_rate(struct clk *clk) +{ + struct clk *pclk; + int rate; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + rate = pclk->ops->get_rate(pclk); + clk_put(pclk); + + return rate; +} + +struct clk_ops s5p_sclk_spdif_ops = { + .set_rate = s5p_spdif_set_rate, + .get_rate = s5p_spdif_get_rate, +}; + +static struct clk *s5p_clks[] __initdata = { + &clk_ext_xtal_mux, + &clk_48m, + &s5p_clk_27m, + &clk_fout_apll, + &clk_fout_mpll, + &clk_fout_epll, + &clk_fout_dpll, + &clk_fout_vpll, + &clk_vpll, + &clk_xusbxti, +}; + +void __init s5p_register_clocks(unsigned long xtal_freq) +{ + int ret; + + clk_ext_xtal_mux.rate = xtal_freq; + + ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks)); + if (ret > 0) + printk(KERN_ERR "Failed to register s5p clocks\n"); +} -- cgit v1.2.3-70-g09d2 From 68ae89984710d2e9f3cf2005539c8f91bcce9d40 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sun, 15 Apr 2012 21:40:33 -0700 Subject: ARM: SAMSUNG: move interrupt part for common s5p into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 11 -- arch/arm/plat-s5p/Makefile | 3 - arch/arm/plat-s5p/irq-eint.c | 219 -------------------------------- arch/arm/plat-s5p/irq-gpioint.c | 216 ------------------------------- arch/arm/plat-s5p/irq.c | 36 ------ arch/arm/plat-samsung/Kconfig | 16 +++ arch/arm/plat-samsung/Makefile | 3 + arch/arm/plat-samsung/s5p-irq-eint.c | 218 +++++++++++++++++++++++++++++++ arch/arm/plat-samsung/s5p-irq-gpioint.c | 215 +++++++++++++++++++++++++++++++ arch/arm/plat-samsung/s5p-irq.c | 35 +++++ 10 files changed, 487 insertions(+), 485 deletions(-) delete mode 100644 arch/arm/plat-s5p/irq-eint.c delete mode 100644 arch/arm/plat-s5p/irq-gpioint.c delete mode 100644 arch/arm/plat-s5p/irq.c create mode 100644 arch/arm/plat-samsung/s5p-irq-eint.c create mode 100644 arch/arm/plat-samsung/s5p-irq-gpioint.c create mode 100644 arch/arm/plat-samsung/s5p-irq.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 2c1193c5992..efff0a30da4 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -23,17 +23,6 @@ config PLAT_S5P help Base platform code for Samsung's S5P series SoC. -config S5P_EXT_INT - bool - help - Use the external interrupts (other than GPIO interrupts.) - Note: Do not choose this for S5P6440 and S5P6450. - -config S5P_GPIO_INT - bool - help - Common code for the GPIO interrupts (other than external interrupts.) - config S5P_HRT bool select SAMSUNG_DEV_PWM diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 83152108af3..8701c3c36d6 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,9 +12,6 @@ obj- := # Core files -obj-y += irq.o -obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o -obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o obj-$(CONFIG_S5P_SLEEP) += sleep.o obj-$(CONFIG_S5P_HRT) += s5p-time.o diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c deleted file mode 100644 index 139c050918c..00000000000 --- a/arch/arm/plat-s5p/irq-eint.c +++ /dev/null @@ -1,219 +0,0 @@ -/* linux/arch/arm/plat-s5p/irq-eint.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P - IRQ EINT support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include -#include - -static inline void s5p_irq_eint_mask(struct irq_data *data) -{ - u32 mask; - - mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); - mask |= eint_irq_to_bit(data->irq); - __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); -} - -static void s5p_irq_eint_unmask(struct irq_data *data) -{ - u32 mask; - - mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); - mask &= ~(eint_irq_to_bit(data->irq)); - __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); -} - -static inline void s5p_irq_eint_ack(struct irq_data *data) -{ - __raw_writel(eint_irq_to_bit(data->irq), - S5P_EINT_PEND(EINT_REG_NR(data->irq))); -} - -static void s5p_irq_eint_maskack(struct irq_data *data) -{ - /* compiler should in-line these */ - s5p_irq_eint_mask(data); - s5p_irq_eint_ack(data); -} - -static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type) -{ - int offs = EINT_OFFSET(data->irq); - int shift; - u32 ctrl, mask; - u32 newvalue = 0; - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - newvalue = S5P_IRQ_TYPE_EDGE_RISING; - break; - - case IRQ_TYPE_EDGE_FALLING: - newvalue = S5P_IRQ_TYPE_EDGE_FALLING; - break; - - case IRQ_TYPE_EDGE_BOTH: - newvalue = S5P_IRQ_TYPE_EDGE_BOTH; - break; - - case IRQ_TYPE_LEVEL_LOW: - newvalue = S5P_IRQ_TYPE_LEVEL_LOW; - break; - - case IRQ_TYPE_LEVEL_HIGH: - newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; - break; - - default: - printk(KERN_ERR "No such irq type %d", type); - return -EINVAL; - } - - shift = (offs & 0x7) * 4; - mask = 0x7 << shift; - - ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); - ctrl &= ~mask; - ctrl |= newvalue << shift; - __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); - - if ((0 <= offs) && (offs < 8)) - s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); - - else if ((8 <= offs) && (offs < 16)) - s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); - - else if ((16 <= offs) && (offs < 24)) - s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); - - else if ((24 <= offs) && (offs < 32)) - s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); - - else - printk(KERN_ERR "No such irq number %d", offs); - - return 0; -} - -static struct irq_chip s5p_irq_eint = { - .name = "s5p-eint", - .irq_mask = s5p_irq_eint_mask, - .irq_unmask = s5p_irq_eint_unmask, - .irq_mask_ack = s5p_irq_eint_maskack, - .irq_ack = s5p_irq_eint_ack, - .irq_set_type = s5p_irq_eint_set_type, -#ifdef CONFIG_PM - .irq_set_wake = s3c_irqext_wake, -#endif -}; - -/* s5p_irq_demux_eint - * - * This function demuxes the IRQ from the group0 external interrupts, - * from EINTs 16 to 31. It is designed to be inlined into the specific - * handler s5p_irq_demux_eintX_Y. - * - * Each EINT pend/mask registers handle eight of them. - */ -static inline void s5p_irq_demux_eint(unsigned int start) -{ - u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); - u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); - unsigned int irq; - - status &= ~mask; - status &= 0xff; - - while (status) { - irq = fls(status) - 1; - generic_handle_irq(irq + start); - status &= ~(1 << irq); - } -} - -static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) -{ - s5p_irq_demux_eint(IRQ_EINT(16)); - s5p_irq_demux_eint(IRQ_EINT(24)); -} - -static inline void s5p_irq_vic_eint_mask(struct irq_data *data) -{ - void __iomem *base = irq_data_get_irq_chip_data(data); - - s5p_irq_eint_mask(data); - writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR); -} - -static void s5p_irq_vic_eint_unmask(struct irq_data *data) -{ - void __iomem *base = irq_data_get_irq_chip_data(data); - - s5p_irq_eint_unmask(data); - writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE); -} - -static inline void s5p_irq_vic_eint_ack(struct irq_data *data) -{ - __raw_writel(eint_irq_to_bit(data->irq), - S5P_EINT_PEND(EINT_REG_NR(data->irq))); -} - -static void s5p_irq_vic_eint_maskack(struct irq_data *data) -{ - s5p_irq_vic_eint_mask(data); - s5p_irq_vic_eint_ack(data); -} - -static struct irq_chip s5p_irq_vic_eint = { - .name = "s5p_vic_eint", - .irq_mask = s5p_irq_vic_eint_mask, - .irq_unmask = s5p_irq_vic_eint_unmask, - .irq_mask_ack = s5p_irq_vic_eint_maskack, - .irq_ack = s5p_irq_vic_eint_ack, - .irq_set_type = s5p_irq_eint_set_type, -#ifdef CONFIG_PM - .irq_set_wake = s3c_irqext_wake, -#endif -}; - -static int __init s5p_init_irq_eint(void) -{ - int irq; - - for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++) - irq_set_chip(irq, &s5p_irq_vic_eint); - - for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) { - irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } - - irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31); - return 0; -} - -arch_initcall(s5p_init_irq_eint); diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c deleted file mode 100644 index 82c7311017a..00000000000 --- a/arch/arm/plat-s5p/irq-gpioint.c +++ /dev/null @@ -1,216 +0,0 @@ -/* linux/arch/arm/plat-s5p/irq-gpioint.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * Author: Kyungmin Park - * Author: Joonyoung Shim - * Author: Marek Szyprowski - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define GPIO_BASE(chip) (((unsigned long)(chip)->base) & 0xFFFFF000u) - -#define CON_OFFSET 0x700 -#define MASK_OFFSET 0x900 -#define PEND_OFFSET 0xA00 -#define REG_OFFSET(x) ((x) << 2) - -struct s5p_gpioint_bank { - struct list_head list; - int start; - int nr_groups; - int irq; - struct samsung_gpio_chip **chips; - void (*handler)(unsigned int, struct irq_desc *); -}; - -static LIST_HEAD(banks); - -static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct irq_chip_type *ct = gc->chip_types; - unsigned int shift = (d->irq - gc->irq_base) << 2; - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - type = S5P_IRQ_TYPE_EDGE_RISING; - break; - case IRQ_TYPE_EDGE_FALLING: - type = S5P_IRQ_TYPE_EDGE_FALLING; - break; - case IRQ_TYPE_EDGE_BOTH: - type = S5P_IRQ_TYPE_EDGE_BOTH; - break; - case IRQ_TYPE_LEVEL_HIGH: - type = S5P_IRQ_TYPE_LEVEL_HIGH; - break; - case IRQ_TYPE_LEVEL_LOW: - type = S5P_IRQ_TYPE_LEVEL_LOW; - break; - case IRQ_TYPE_NONE: - default: - printk(KERN_WARNING "No irq type\n"); - return -EINVAL; - } - - gc->type_cache &= ~(0x7 << shift); - gc->type_cache |= type << shift; - writel(gc->type_cache, gc->reg_base + ct->regs.type); - return 0; -} - -static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) -{ - struct s5p_gpioint_bank *bank = irq_get_handler_data(irq); - int group, pend_offset, mask_offset; - unsigned int pend, mask; - - struct irq_chip *chip = irq_get_chip(irq); - chained_irq_enter(chip, desc); - - for (group = 0; group < bank->nr_groups; group++) { - struct samsung_gpio_chip *chip = bank->chips[group]; - if (!chip) - continue; - - pend_offset = REG_OFFSET(group); - pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset); - if (!pend) - continue; - - mask_offset = REG_OFFSET(group); - mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset); - pend &= ~mask; - - while (pend) { - int offset = fls(pend) - 1; - int real_irq = chip->irq_base + offset; - generic_handle_irq(real_irq); - pend &= ~BIT(offset); - } - } - chained_irq_exit(chip, desc); -} - -static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip) -{ - static int used_gpioint_groups = 0; - int group = chip->group; - struct s5p_gpioint_bank *b, *bank = NULL; - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) - return -ENOMEM; - - list_for_each_entry(b, &banks, list) { - if (group >= b->start && group < b->start + b->nr_groups) { - bank = b; - break; - } - } - if (!bank) - return -EINVAL; - - if (!bank->handler) { - bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) * - bank->nr_groups, GFP_KERNEL); - if (!bank->chips) - return -ENOMEM; - - irq_set_chained_handler(bank->irq, s5p_gpioint_handler); - irq_set_handler_data(bank->irq, bank); - bank->handler = s5p_gpioint_handler; - printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n", - bank->irq); - } - - /* - * chained GPIO irq has been successfully registered, allocate new gpio - * int group and assign irq nubmers - */ - chip->irq_base = S5P_GPIOINT_BASE + - used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; - used_gpioint_groups++; - - bank->chips[group - bank->start] = chip; - - gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base, - (void __iomem *)GPIO_BASE(chip), - handle_level_irq); - if (!gc) - return -ENOMEM; - ct = gc->chip_types; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->chip.irq_set_type = s5p_gpioint_set_type, - ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start); - ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start); - ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start); - irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio), - IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST | IRQ_NOPROBE, 0); - return 0; -} - -int __init s5p_register_gpio_interrupt(int pin) -{ - struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin); - int offset, group; - int ret; - - if (!my_chip) - return -EINVAL; - - offset = pin - my_chip->chip.base; - group = my_chip->group; - - /* check if the group has been already registered */ - if (my_chip->irq_base) - return my_chip->irq_base + offset; - - /* register gpio group */ - ret = s5p_gpioint_add(my_chip); - if (ret == 0) { - my_chip->chip.to_irq = samsung_gpiolib_to_irq; - printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", - group); - return my_chip->irq_base + offset; - } - return ret; -} - -int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups) -{ - struct s5p_gpioint_bank *bank; - - bank = kzalloc(sizeof(*bank), GFP_KERNEL); - if (!bank) - return -ENOMEM; - - bank->start = start; - bank->nr_groups = nr_groups; - bank->irq = chain_irq; - - list_add_tail(&bank->list, &banks); - return 0; -} diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c deleted file mode 100644 index afdaa1082b9..00000000000 --- a/arch/arm/plat-s5p/irq.c +++ /dev/null @@ -1,36 +0,0 @@ -/* arch/arm/plat-s5p/irq.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P - Interrupt handling - * - * 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 -#include -#include -#include - -#include - -#include -#include -#include -#include - -void __init s5p_init_irq(u32 *vic, u32 num_vic) -{ -#ifdef CONFIG_ARM_VIC - int irq; - - /* initialize the VICs */ - for (irq = 0; irq < num_vic; irq++) - vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); -#endif - - s3c_init_vic_timer_irq(5, IRQ_TIMER0); -} diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 3a48d9de22a..e09dd4f9dc3 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -70,6 +70,22 @@ config SAMSUNG_IRQ_VIC_TIMER help Internal configuration to build the VIC timer interrupt code. +config S5P_IRQ + def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) + help + Support common interrup part for ARCH_S5P and ARCH_EXYNOS SoCs + +config S5P_EXT_INT + bool + help + Use the external interrupts (other than GPIO interrupts.) + Note: Do not choose this for S5P6440 and S5P6450. + +config S5P_GPIO_INT + bool + help + Common code for the GPIO interrupts (other than external interrupts.) + # options for gpio configuration support config SAMSUNG_GPIOLIB_4BIT diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 997ce100570..5b650094628 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -20,6 +20,9 @@ obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o +obj-$(CONFIG_S5P_IRQ) += s5p-irq.o +obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o +obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o # ADC diff --git a/arch/arm/plat-samsung/s5p-irq-eint.c b/arch/arm/plat-samsung/s5p-irq-eint.c new file mode 100644 index 00000000000..33bd3f3d20f --- /dev/null +++ b/arch/arm/plat-samsung/s5p-irq-eint.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P - IRQ EINT support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +static inline void s5p_irq_eint_mask(struct irq_data *data) +{ + u32 mask; + + mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); + mask |= eint_irq_to_bit(data->irq); + __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); +} + +static void s5p_irq_eint_unmask(struct irq_data *data) +{ + u32 mask; + + mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); + mask &= ~(eint_irq_to_bit(data->irq)); + __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); +} + +static inline void s5p_irq_eint_ack(struct irq_data *data) +{ + __raw_writel(eint_irq_to_bit(data->irq), + S5P_EINT_PEND(EINT_REG_NR(data->irq))); +} + +static void s5p_irq_eint_maskack(struct irq_data *data) +{ + /* compiler should in-line these */ + s5p_irq_eint_mask(data); + s5p_irq_eint_ack(data); +} + +static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type) +{ + int offs = EINT_OFFSET(data->irq); + int shift; + u32 ctrl, mask; + u32 newvalue = 0; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + newvalue = S5P_IRQ_TYPE_EDGE_RISING; + break; + + case IRQ_TYPE_EDGE_FALLING: + newvalue = S5P_IRQ_TYPE_EDGE_FALLING; + break; + + case IRQ_TYPE_EDGE_BOTH: + newvalue = S5P_IRQ_TYPE_EDGE_BOTH; + break; + + case IRQ_TYPE_LEVEL_LOW: + newvalue = S5P_IRQ_TYPE_LEVEL_LOW; + break; + + case IRQ_TYPE_LEVEL_HIGH: + newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; + break; + + default: + printk(KERN_ERR "No such irq type %d", type); + return -EINVAL; + } + + shift = (offs & 0x7) * 4; + mask = 0x7 << shift; + + ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); + ctrl &= ~mask; + ctrl |= newvalue << shift; + __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); + + if ((0 <= offs) && (offs < 8)) + s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); + + else if ((8 <= offs) && (offs < 16)) + s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); + + else if ((16 <= offs) && (offs < 24)) + s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); + + else if ((24 <= offs) && (offs < 32)) + s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); + + else + printk(KERN_ERR "No such irq number %d", offs); + + return 0; +} + +static struct irq_chip s5p_irq_eint = { + .name = "s5p-eint", + .irq_mask = s5p_irq_eint_mask, + .irq_unmask = s5p_irq_eint_unmask, + .irq_mask_ack = s5p_irq_eint_maskack, + .irq_ack = s5p_irq_eint_ack, + .irq_set_type = s5p_irq_eint_set_type, +#ifdef CONFIG_PM + .irq_set_wake = s3c_irqext_wake, +#endif +}; + +/* s5p_irq_demux_eint + * + * This function demuxes the IRQ from the group0 external interrupts, + * from EINTs 16 to 31. It is designed to be inlined into the specific + * handler s5p_irq_demux_eintX_Y. + * + * Each EINT pend/mask registers handle eight of them. + */ +static inline void s5p_irq_demux_eint(unsigned int start) +{ + u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); + u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); + unsigned int irq; + + status &= ~mask; + status &= 0xff; + + while (status) { + irq = fls(status) - 1; + generic_handle_irq(irq + start); + status &= ~(1 << irq); + } +} + +static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) +{ + s5p_irq_demux_eint(IRQ_EINT(16)); + s5p_irq_demux_eint(IRQ_EINT(24)); +} + +static inline void s5p_irq_vic_eint_mask(struct irq_data *data) +{ + void __iomem *base = irq_data_get_irq_chip_data(data); + + s5p_irq_eint_mask(data); + writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR); +} + +static void s5p_irq_vic_eint_unmask(struct irq_data *data) +{ + void __iomem *base = irq_data_get_irq_chip_data(data); + + s5p_irq_eint_unmask(data); + writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE); +} + +static inline void s5p_irq_vic_eint_ack(struct irq_data *data) +{ + __raw_writel(eint_irq_to_bit(data->irq), + S5P_EINT_PEND(EINT_REG_NR(data->irq))); +} + +static void s5p_irq_vic_eint_maskack(struct irq_data *data) +{ + s5p_irq_vic_eint_mask(data); + s5p_irq_vic_eint_ack(data); +} + +static struct irq_chip s5p_irq_vic_eint = { + .name = "s5p_vic_eint", + .irq_mask = s5p_irq_vic_eint_mask, + .irq_unmask = s5p_irq_vic_eint_unmask, + .irq_mask_ack = s5p_irq_vic_eint_maskack, + .irq_ack = s5p_irq_vic_eint_ack, + .irq_set_type = s5p_irq_eint_set_type, +#ifdef CONFIG_PM + .irq_set_wake = s3c_irqext_wake, +#endif +}; + +static int __init s5p_init_irq_eint(void) +{ + int irq; + + for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++) + irq_set_chip(irq, &s5p_irq_vic_eint); + + for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) { + irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31); + return 0; +} + +arch_initcall(s5p_init_irq_eint); diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c new file mode 100644 index 00000000000..f9431fe5b06 --- /dev/null +++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Author: Kyungmin Park + * Author: Joonyoung Shim + * Author: Marek Szyprowski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define GPIO_BASE(chip) (((unsigned long)(chip)->base) & 0xFFFFF000u) + +#define CON_OFFSET 0x700 +#define MASK_OFFSET 0x900 +#define PEND_OFFSET 0xA00 +#define REG_OFFSET(x) ((x) << 2) + +struct s5p_gpioint_bank { + struct list_head list; + int start; + int nr_groups; + int irq; + struct samsung_gpio_chip **chips; + void (*handler)(unsigned int, struct irq_desc *); +}; + +static LIST_HEAD(banks); + +static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = gc->chip_types; + unsigned int shift = (d->irq - gc->irq_base) << 2; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + type = S5P_IRQ_TYPE_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + type = S5P_IRQ_TYPE_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + type = S5P_IRQ_TYPE_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + type = S5P_IRQ_TYPE_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + type = S5P_IRQ_TYPE_LEVEL_LOW; + break; + case IRQ_TYPE_NONE: + default: + printk(KERN_WARNING "No irq type\n"); + return -EINVAL; + } + + gc->type_cache &= ~(0x7 << shift); + gc->type_cache |= type << shift; + writel(gc->type_cache, gc->reg_base + ct->regs.type); + return 0; +} + +static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) +{ + struct s5p_gpioint_bank *bank = irq_get_handler_data(irq); + int group, pend_offset, mask_offset; + unsigned int pend, mask; + + struct irq_chip *chip = irq_get_chip(irq); + chained_irq_enter(chip, desc); + + for (group = 0; group < bank->nr_groups; group++) { + struct samsung_gpio_chip *chip = bank->chips[group]; + if (!chip) + continue; + + pend_offset = REG_OFFSET(group); + pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset); + if (!pend) + continue; + + mask_offset = REG_OFFSET(group); + mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset); + pend &= ~mask; + + while (pend) { + int offset = fls(pend) - 1; + int real_irq = chip->irq_base + offset; + generic_handle_irq(real_irq); + pend &= ~BIT(offset); + } + } + chained_irq_exit(chip, desc); +} + +static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip) +{ + static int used_gpioint_groups = 0; + int group = chip->group; + struct s5p_gpioint_bank *b, *bank = NULL; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) + return -ENOMEM; + + list_for_each_entry(b, &banks, list) { + if (group >= b->start && group < b->start + b->nr_groups) { + bank = b; + break; + } + } + if (!bank) + return -EINVAL; + + if (!bank->handler) { + bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) * + bank->nr_groups, GFP_KERNEL); + if (!bank->chips) + return -ENOMEM; + + irq_set_chained_handler(bank->irq, s5p_gpioint_handler); + irq_set_handler_data(bank->irq, bank); + bank->handler = s5p_gpioint_handler; + printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n", + bank->irq); + } + + /* + * chained GPIO irq has been successfully registered, allocate new gpio + * int group and assign irq nubmers + */ + chip->irq_base = S5P_GPIOINT_BASE + + used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; + used_gpioint_groups++; + + bank->chips[group - bank->start] = chip; + + gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base, + (void __iomem *)GPIO_BASE(chip), + handle_level_irq); + if (!gc) + return -ENOMEM; + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + ct->chip.irq_set_type = s5p_gpioint_set_type, + ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start); + ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start); + ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start); + irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio), + IRQ_GC_INIT_MASK_CACHE, + IRQ_NOREQUEST | IRQ_NOPROBE, 0); + return 0; +} + +int __init s5p_register_gpio_interrupt(int pin) +{ + struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin); + int offset, group; + int ret; + + if (!my_chip) + return -EINVAL; + + offset = pin - my_chip->chip.base; + group = my_chip->group; + + /* check if the group has been already registered */ + if (my_chip->irq_base) + return my_chip->irq_base + offset; + + /* register gpio group */ + ret = s5p_gpioint_add(my_chip); + if (ret == 0) { + my_chip->chip.to_irq = samsung_gpiolib_to_irq; + printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", + group); + return my_chip->irq_base + offset; + } + return ret; +} + +int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups) +{ + struct s5p_gpioint_bank *bank; + + bank = kzalloc(sizeof(*bank), GFP_KERNEL); + if (!bank) + return -ENOMEM; + + bank->start = start; + bank->nr_groups = nr_groups; + bank->irq = chain_irq; + + list_add_tail(&bank->list, &banks); + return 0; +} diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c new file mode 100644 index 00000000000..dfb47d638f0 --- /dev/null +++ b/arch/arm/plat-samsung/s5p-irq.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P - Interrupt handling + * + * 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 +#include +#include +#include + +#include + +#include +#include +#include +#include + +void __init s5p_init_irq(u32 *vic, u32 num_vic) +{ +#ifdef CONFIG_ARM_VIC + int irq; + + /* initialize the VICs */ + for (irq = 0; irq < num_vic; irq++) + vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); +#endif + + s3c_init_vic_timer_irq(5, IRQ_TIMER0); +} -- cgit v1.2.3-70-g09d2 From 8eadcf74ec8285800f7f6a36a8f283932a69d17f Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sun, 15 Apr 2012 21:57:38 -0700 Subject: ARM: SAMSUNG: move pm part for common s5p into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 12 ----- arch/arm/plat-s5p/Makefile | 2 - arch/arm/plat-s5p/irq-pm.c | 103 ------------------------------------- arch/arm/plat-s5p/pm.c | 41 --------------- arch/arm/plat-s5p/sleep.S | 81 ----------------------------- arch/arm/plat-samsung/Kconfig | 12 +++++ arch/arm/plat-samsung/Makefile | 3 ++ arch/arm/plat-samsung/s5p-irq-pm.c | 102 ++++++++++++++++++++++++++++++++++++ arch/arm/plat-samsung/s5p-pm.c | 40 ++++++++++++++ arch/arm/plat-samsung/s5p-sleep.S | 80 ++++++++++++++++++++++++++++ 10 files changed, 237 insertions(+), 239 deletions(-) delete mode 100644 arch/arm/plat-s5p/irq-pm.c delete mode 100644 arch/arm/plat-s5p/pm.c delete mode 100644 arch/arm/plat-s5p/sleep.S create mode 100644 arch/arm/plat-samsung/s5p-irq-pm.c create mode 100644 arch/arm/plat-samsung/s5p-pm.c create mode 100644 arch/arm/plat-samsung/s5p-sleep.S (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index efff0a30da4..8e45c8b15d1 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -33,18 +33,6 @@ config S5P_DEV_UART def_bool y depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) -config S5P_PM - bool - help - Common code for power management support on S5P and newer SoCs - Note: Do not select this for S5P6440 and S5P6450. - -config S5P_SLEEP - bool - help - Internal config node to apply common S5P sleep management code. - Can be selected by S5P and newer SoCs with similar sleep procedure. - config S5P_DEV_FIMC0 bool help diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 8701c3c36d6..c81106f5d7c 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,8 +12,6 @@ obj- := # Core files -obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o -obj-$(CONFIG_S5P_SLEEP) += sleep.o obj-$(CONFIG_S5P_HRT) += s5p-time.o # devices diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c deleted file mode 100644 index d1bfecae6c9..00000000000 --- a/arch/arm/plat-s5p/irq-pm.c +++ /dev/null @@ -1,103 +0,0 @@ -/* linux/arch/arm/plat-s5p/irq-pm.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Based on arch/arm/plat-s3c24xx/irq-pm.c, - * Copyright (c) 2003,2004 Simtec Electronics - * Ben Dooks - * 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. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -/* state for IRQs over sleep */ - -/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM, - * as wakeup sources - * - * set bit to 1 in allow bitfield to enable the wakeup settings on it -*/ - -unsigned long s3c_irqwake_intallow = 0x00000006L; -unsigned long s3c_irqwake_eintallow = 0xffffffffL; - -int s3c_irq_wake(struct irq_data *data, unsigned int state) -{ - unsigned long irqbit; - unsigned int irq_rtc_tic, irq_rtc_alarm; - -#ifdef CONFIG_ARCH_EXYNOS - if (soc_is_exynos5250()) { - irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC; - irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM; - } else { - irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC; - irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM; - } -#else - irq_rtc_tic = IRQ_RTC_TIC; - irq_rtc_alarm = IRQ_RTC_ALARM; -#endif - - if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) { - irqbit = 1 << (data->irq + 1 - irq_rtc_alarm); - - if (!state) - s3c_irqwake_intmask |= irqbit; - else - s3c_irqwake_intmask &= ~irqbit; - } else { - return -ENOENT; - } - - return 0; -} - -static struct sleep_save eint_save[] = { - SAVE_ITEM(S5P_EINT_CON(0)), - SAVE_ITEM(S5P_EINT_CON(1)), - SAVE_ITEM(S5P_EINT_CON(2)), - SAVE_ITEM(S5P_EINT_CON(3)), - - SAVE_ITEM(S5P_EINT_FLTCON(0)), - SAVE_ITEM(S5P_EINT_FLTCON(1)), - SAVE_ITEM(S5P_EINT_FLTCON(2)), - SAVE_ITEM(S5P_EINT_FLTCON(3)), - SAVE_ITEM(S5P_EINT_FLTCON(4)), - SAVE_ITEM(S5P_EINT_FLTCON(5)), - SAVE_ITEM(S5P_EINT_FLTCON(6)), - SAVE_ITEM(S5P_EINT_FLTCON(7)), - - SAVE_ITEM(S5P_EINT_MASK(0)), - SAVE_ITEM(S5P_EINT_MASK(1)), - SAVE_ITEM(S5P_EINT_MASK(2)), - SAVE_ITEM(S5P_EINT_MASK(3)), -}; - -int s3c24xx_irq_suspend(void) -{ - s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); - - return 0; -} - -void s3c24xx_irq_resume(void) -{ - s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); -} - diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c deleted file mode 100644 index d15dc47b0e3..00000000000 --- a/arch/arm/plat-s5p/pm.c +++ /dev/null @@ -1,41 +0,0 @@ -/* linux/arch/arm/plat-s5p/pm.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P Power Manager (Suspend-To-RAM) support - * - * Based on arch/arm/plat-s3c24xx/pm.c - * Copyright (c) 2004,2006 Simtec Electronics - * Ben Dooks - * - * 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 -#include - -#define PFX "s5p pm: " - -/* s3c_pm_configure_extint - * - * configure all external interrupt pins -*/ - -void s3c_pm_configure_extint(void) -{ - /* nothing here yet */ -} - -void s3c_pm_restore_core(void) -{ - /* nothing here yet */ -} - -void s3c_pm_save_core(void) -{ - /* nothing here yet */ -} - diff --git a/arch/arm/plat-s5p/sleep.S b/arch/arm/plat-s5p/sleep.S deleted file mode 100644 index 006bd01eda0..00000000000 --- a/arch/arm/plat-s5p/sleep.S +++ /dev/null @@ -1,81 +0,0 @@ -/* linux/arch/arm/plat-s5p/sleep.S - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Common S5P Sleep Code - * Based on S3C64XX sleep code by: - * Ben Dooks, (c) 2008 Simtec Electronics - * - * 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 -#include -#include - -/* - * The following code is located into the .data section. This is to - * allow l2x0_regs_phys to be accessed with a relative load while we - * can't rely on any MMU translation. We could have put l2x0_regs_phys - * in the .text section as well, but some setups might insist on it to - * be truly read-only. (Reference from: arch/arm/kernel/sleep.S) - */ - .data - .align - - /* - * sleep magic, to allow the bootloader to check for an valid - * image to resume to. Must be the first word before the - * s3c_cpu_resume entry. - */ - - .word 0x2bedf00d - - /* - * s3c_cpu_resume - * - * resume code entry for bootloader to call - */ - -ENTRY(s3c_cpu_resume) -#ifdef CONFIG_CACHE_L2X0 - adr r0, l2x0_regs_phys - ldr r0, [r0] - ldr r1, [r0, #L2X0_R_PHY_BASE] - ldr r2, [r1, #L2X0_CTRL] - tst r2, #0x1 - bne resume_l2on - ldr r2, [r0, #L2X0_R_AUX_CTRL] - str r2, [r1, #L2X0_AUX_CTRL] - ldr r2, [r0, #L2X0_R_TAG_LATENCY] - str r2, [r1, #L2X0_TAG_LATENCY_CTRL] - ldr r2, [r0, #L2X0_R_DATA_LATENCY] - str r2, [r1, #L2X0_DATA_LATENCY_CTRL] - ldr r2, [r0, #L2X0_R_PREFETCH_CTRL] - str r2, [r1, #L2X0_PREFETCH_CTRL] - ldr r2, [r0, #L2X0_R_PWR_CTRL] - str r2, [r1, #L2X0_POWER_CTRL] - mov r2, #1 - str r2, [r1, #L2X0_CTRL] -resume_l2on: -#endif - b cpu_resume -ENDPROC(s3c_cpu_resume) -#ifdef CONFIG_CACHE_L2X0 - .globl l2x0_regs_phys -l2x0_regs_phys: - .long 0 -#endif diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index e09dd4f9dc3..218462361e3 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -371,6 +371,18 @@ config SAMSUNG_WAKEMASK and above. This code allows a set of interrupt to wakeup-mask mappings. See +config S5P_PM + bool + help + Common code for power management support on S5P and newer SoCs + Note: Do not select this for S5P6440 and S5P6450. + +config S5P_SLEEP + bool + help + Internal config node to apply common S5P sleep management code. + Can be selected by S5P and newer SoCs with similar sleep procedure. + comment "Power Domain" config SAMSUNG_PD diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 5b650094628..caa6f9af1f3 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -51,6 +51,9 @@ obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o +obj-$(CONFIG_S5P_PM) += s5p-pm.o s5p-irq-pm.o +obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o + # PD support obj-$(CONFIG_SAMSUNG_PD) += pd.o diff --git a/arch/arm/plat-samsung/s5p-irq-pm.c b/arch/arm/plat-samsung/s5p-irq-pm.c new file mode 100644 index 00000000000..7c1e3b7072f --- /dev/null +++ b/arch/arm/plat-samsung/s5p-irq-pm.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Based on arch/arm/plat-s3c24xx/irq-pm.c, + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks + * 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. +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/* state for IRQs over sleep */ + +/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM, + * as wakeup sources + * + * set bit to 1 in allow bitfield to enable the wakeup settings on it +*/ + +unsigned long s3c_irqwake_intallow = 0x00000006L; +unsigned long s3c_irqwake_eintallow = 0xffffffffL; + +int s3c_irq_wake(struct irq_data *data, unsigned int state) +{ + unsigned long irqbit; + unsigned int irq_rtc_tic, irq_rtc_alarm; + +#ifdef CONFIG_ARCH_EXYNOS + if (soc_is_exynos5250()) { + irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC; + irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM; + } else { + irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC; + irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM; + } +#else + irq_rtc_tic = IRQ_RTC_TIC; + irq_rtc_alarm = IRQ_RTC_ALARM; +#endif + + if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) { + irqbit = 1 << (data->irq + 1 - irq_rtc_alarm); + + if (!state) + s3c_irqwake_intmask |= irqbit; + else + s3c_irqwake_intmask &= ~irqbit; + } else { + return -ENOENT; + } + + return 0; +} + +static struct sleep_save eint_save[] = { + SAVE_ITEM(S5P_EINT_CON(0)), + SAVE_ITEM(S5P_EINT_CON(1)), + SAVE_ITEM(S5P_EINT_CON(2)), + SAVE_ITEM(S5P_EINT_CON(3)), + + SAVE_ITEM(S5P_EINT_FLTCON(0)), + SAVE_ITEM(S5P_EINT_FLTCON(1)), + SAVE_ITEM(S5P_EINT_FLTCON(2)), + SAVE_ITEM(S5P_EINT_FLTCON(3)), + SAVE_ITEM(S5P_EINT_FLTCON(4)), + SAVE_ITEM(S5P_EINT_FLTCON(5)), + SAVE_ITEM(S5P_EINT_FLTCON(6)), + SAVE_ITEM(S5P_EINT_FLTCON(7)), + + SAVE_ITEM(S5P_EINT_MASK(0)), + SAVE_ITEM(S5P_EINT_MASK(1)), + SAVE_ITEM(S5P_EINT_MASK(2)), + SAVE_ITEM(S5P_EINT_MASK(3)), +}; + +int s3c24xx_irq_suspend(void) +{ + s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); + + return 0; +} + +void s3c24xx_irq_resume(void) +{ + s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); +} + diff --git a/arch/arm/plat-samsung/s5p-pm.c b/arch/arm/plat-samsung/s5p-pm.c new file mode 100644 index 00000000000..0747468f093 --- /dev/null +++ b/arch/arm/plat-samsung/s5p-pm.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P Power Manager (Suspend-To-RAM) support + * + * Based on arch/arm/plat-s3c24xx/pm.c + * Copyright (c) 2004,2006 Simtec Electronics + * Ben Dooks + * + * 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 +#include + +#define PFX "s5p pm: " + +/* s3c_pm_configure_extint + * + * configure all external interrupt pins +*/ + +void s3c_pm_configure_extint(void) +{ + /* nothing here yet */ +} + +void s3c_pm_restore_core(void) +{ + /* nothing here yet */ +} + +void s3c_pm_save_core(void) +{ + /* nothing here yet */ +} + diff --git a/arch/arm/plat-samsung/s5p-sleep.S b/arch/arm/plat-samsung/s5p-sleep.S new file mode 100644 index 00000000000..bdf6dadf879 --- /dev/null +++ b/arch/arm/plat-samsung/s5p-sleep.S @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Common S5P Sleep Code + * Based on S3C64XX sleep code by: + * Ben Dooks, (c) 2008 Simtec Electronics + * + * 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 +#include +#include + +/* + * The following code is located into the .data section. This is to + * allow l2x0_regs_phys to be accessed with a relative load while we + * can't rely on any MMU translation. We could have put l2x0_regs_phys + * in the .text section as well, but some setups might insist on it to + * be truly read-only. (Reference from: arch/arm/kernel/sleep.S) + */ + .data + .align + + /* + * sleep magic, to allow the bootloader to check for an valid + * image to resume to. Must be the first word before the + * s3c_cpu_resume entry. + */ + + .word 0x2bedf00d + + /* + * s3c_cpu_resume + * + * resume code entry for bootloader to call + */ + +ENTRY(s3c_cpu_resume) +#ifdef CONFIG_CACHE_L2X0 + adr r0, l2x0_regs_phys + ldr r0, [r0] + ldr r1, [r0, #L2X0_R_PHY_BASE] + ldr r2, [r1, #L2X0_CTRL] + tst r2, #0x1 + bne resume_l2on + ldr r2, [r0, #L2X0_R_AUX_CTRL] + str r2, [r1, #L2X0_AUX_CTRL] + ldr r2, [r0, #L2X0_R_TAG_LATENCY] + str r2, [r1, #L2X0_TAG_LATENCY_CTRL] + ldr r2, [r0, #L2X0_R_DATA_LATENCY] + str r2, [r1, #L2X0_DATA_LATENCY_CTRL] + ldr r2, [r0, #L2X0_R_PREFETCH_CTRL] + str r2, [r1, #L2X0_PREFETCH_CTRL] + ldr r2, [r0, #L2X0_R_PWR_CTRL] + str r2, [r1, #L2X0_POWER_CTRL] + mov r2, #1 + str r2, [r1, #L2X0_CTRL] +resume_l2on: +#endif + b cpu_resume +ENDPROC(s3c_cpu_resume) +#ifdef CONFIG_CACHE_L2X0 + .globl l2x0_regs_phys +l2x0_regs_phys: + .long 0 +#endif -- cgit v1.2.3-70-g09d2 From 33bf33278fa608428c46d4fab58ae5bc3e3acfde Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 17 Apr 2012 11:20:49 -0700 Subject: ARM: SAMSUNG: move hr timer for common s5p into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 6 - arch/arm/plat-s5p/Makefile | 4 - arch/arm/plat-s5p/s5p-time.c | 406 --------------------------------------- arch/arm/plat-samsung/Kconfig | 8 + arch/arm/plat-samsung/Makefile | 2 + arch/arm/plat-samsung/s5p-time.c | 405 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 415 insertions(+), 416 deletions(-) delete mode 100644 arch/arm/plat-s5p/s5p-time.c create mode 100644 arch/arm/plat-samsung/s5p-time.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 8e45c8b15d1..795790df740 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -23,12 +23,6 @@ config PLAT_S5P help Base platform code for Samsung's S5P series SoC. -config S5P_HRT - bool - select SAMSUNG_DEV_PWM - help - Use the High Resolution timer support - config S5P_DEV_UART def_bool y depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index c81106f5d7c..0a2ce38b179 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -10,10 +10,6 @@ obj-m := obj-n := dummy.o obj- := -# Core files - -obj-$(CONFIG_S5P_HRT) += s5p-time.o - # devices obj-$(CONFIG_S5P_DEV_UART) += dev-uart.o diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c deleted file mode 100644 index 17c0a2c58df..00000000000 --- a/arch/arm/plat-s5p/s5p-time.c +++ /dev/null @@ -1,406 +0,0 @@ -/* linux/arch/arm/plat-s5p/s5p-time.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P - Common hr-timer support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct clk *tin_event; -static struct clk *tin_source; -static struct clk *tdiv_event; -static struct clk *tdiv_source; -static struct clk *timerclk; -static struct s5p_timer_source timer_source; -static unsigned long clock_count_per_tick; -static void s5p_timer_resume(void); - -static void s5p_time_stop(enum s5p_timer_mode mode) -{ - unsigned long tcon; - - tcon = __raw_readl(S3C2410_TCON); - - switch (mode) { - case S5P_PWM0: - tcon &= ~S3C2410_TCON_T0START; - break; - - case S5P_PWM1: - tcon &= ~S3C2410_TCON_T1START; - break; - - case S5P_PWM2: - tcon &= ~S3C2410_TCON_T2START; - break; - - case S5P_PWM3: - tcon &= ~S3C2410_TCON_T3START; - break; - - case S5P_PWM4: - tcon &= ~S3C2410_TCON_T4START; - break; - - default: - printk(KERN_ERR "Invalid Timer %d\n", mode); - break; - } - __raw_writel(tcon, S3C2410_TCON); -} - -static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt) -{ - unsigned long tcon; - - tcon = __raw_readl(S3C2410_TCON); - - tcnt--; - - switch (mode) { - case S5P_PWM0: - tcon &= ~(0x0f << 0); - tcon |= S3C2410_TCON_T0MANUALUPD; - break; - - case S5P_PWM1: - tcon &= ~(0x0f << 8); - tcon |= S3C2410_TCON_T1MANUALUPD; - break; - - case S5P_PWM2: - tcon &= ~(0x0f << 12); - tcon |= S3C2410_TCON_T2MANUALUPD; - break; - - case S5P_PWM3: - tcon &= ~(0x0f << 16); - tcon |= S3C2410_TCON_T3MANUALUPD; - break; - - case S5P_PWM4: - tcon &= ~(0x07 << 20); - tcon |= S3C2410_TCON_T4MANUALUPD; - break; - - default: - printk(KERN_ERR "Invalid Timer %d\n", mode); - break; - } - - __raw_writel(tcnt, S3C2410_TCNTB(mode)); - __raw_writel(tcnt, S3C2410_TCMPB(mode)); - __raw_writel(tcon, S3C2410_TCON); -} - -static void s5p_time_start(enum s5p_timer_mode mode, bool periodic) -{ - unsigned long tcon; - - tcon = __raw_readl(S3C2410_TCON); - - switch (mode) { - case S5P_PWM0: - tcon |= S3C2410_TCON_T0START; - tcon &= ~S3C2410_TCON_T0MANUALUPD; - - if (periodic) - tcon |= S3C2410_TCON_T0RELOAD; - else - tcon &= ~S3C2410_TCON_T0RELOAD; - break; - - case S5P_PWM1: - tcon |= S3C2410_TCON_T1START; - tcon &= ~S3C2410_TCON_T1MANUALUPD; - - if (periodic) - tcon |= S3C2410_TCON_T1RELOAD; - else - tcon &= ~S3C2410_TCON_T1RELOAD; - break; - - case S5P_PWM2: - tcon |= S3C2410_TCON_T2START; - tcon &= ~S3C2410_TCON_T2MANUALUPD; - - if (periodic) - tcon |= S3C2410_TCON_T2RELOAD; - else - tcon &= ~S3C2410_TCON_T2RELOAD; - break; - - case S5P_PWM3: - tcon |= S3C2410_TCON_T3START; - tcon &= ~S3C2410_TCON_T3MANUALUPD; - - if (periodic) - tcon |= S3C2410_TCON_T3RELOAD; - else - tcon &= ~S3C2410_TCON_T3RELOAD; - break; - - case S5P_PWM4: - tcon |= S3C2410_TCON_T4START; - tcon &= ~S3C2410_TCON_T4MANUALUPD; - - if (periodic) - tcon |= S3C2410_TCON_T4RELOAD; - else - tcon &= ~S3C2410_TCON_T4RELOAD; - break; - - default: - printk(KERN_ERR "Invalid Timer %d\n", mode); - break; - } - __raw_writel(tcon, S3C2410_TCON); -} - -static int s5p_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - s5p_time_setup(timer_source.event_id, cycles); - s5p_time_start(timer_source.event_id, NON_PERIODIC); - - return 0; -} - -static void s5p_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - s5p_time_stop(timer_source.event_id); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - s5p_time_setup(timer_source.event_id, clock_count_per_tick); - s5p_time_start(timer_source.event_id, PERIODIC); - break; - - case CLOCK_EVT_MODE_ONESHOT: - break; - - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - break; - - case CLOCK_EVT_MODE_RESUME: - s5p_timer_resume(); - break; - } -} - -static void s5p_timer_resume(void) -{ - /* event timer restart */ - s5p_time_setup(timer_source.event_id, clock_count_per_tick); - s5p_time_start(timer_source.event_id, PERIODIC); - - /* source timer restart */ - s5p_time_setup(timer_source.source_id, TCNT_MAX); - s5p_time_start(timer_source.source_id, PERIODIC); -} - -void __init s5p_set_timer_source(enum s5p_timer_mode event, - enum s5p_timer_mode source) -{ - s3c_device_timer[event].dev.bus = &platform_bus_type; - s3c_device_timer[source].dev.bus = &platform_bus_type; - - timer_source.event_id = event; - timer_source.source_id = source; -} - -static struct clock_event_device time_event_device = { - .name = "s5p_event_timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = s5p_set_next_event, - .set_mode = s5p_set_mode, -}; - -static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction s5p_clock_event_irq = { - .name = "s5p_time_irq", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = s5p_clock_event_isr, - .dev_id = &time_event_device, -}; - -static void __init s5p_clockevent_init(void) -{ - unsigned long pclk; - unsigned long clock_rate; - unsigned int irq_number; - struct clk *tscaler; - - pclk = clk_get_rate(timerclk); - - tscaler = clk_get_parent(tdiv_event); - - clk_set_rate(tscaler, pclk / 2); - clk_set_rate(tdiv_event, pclk / 2); - clk_set_parent(tin_event, tdiv_event); - - clock_rate = clk_get_rate(tin_event); - clock_count_per_tick = clock_rate / HZ; - - clockevents_calc_mult_shift(&time_event_device, - clock_rate, S5PTIMER_MIN_RANGE); - time_event_device.max_delta_ns = - clockevent_delta2ns(-1, &time_event_device); - time_event_device.min_delta_ns = - clockevent_delta2ns(1, &time_event_device); - - time_event_device.cpumask = cpumask_of(0); - clockevents_register_device(&time_event_device); - - irq_number = timer_source.event_id + IRQ_TIMER0; - setup_irq(irq_number, &s5p_clock_event_irq); -} - -static void __iomem *s5p_timer_reg(void) -{ - unsigned long offset = 0; - - switch (timer_source.source_id) { - case S5P_PWM0: - case S5P_PWM1: - case S5P_PWM2: - case S5P_PWM3: - offset = (timer_source.source_id * 0x0c) + 0x14; - break; - - case S5P_PWM4: - offset = 0x40; - break; - - default: - printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); - return NULL; - } - - return S3C_TIMERREG(offset); -} - -/* - * Override the global weak sched_clock symbol with this - * local implementation which uses the clocksource to get some - * better resolution when scheduling the kernel. We accept that - * this wraps around for now, since it is just a relative time - * stamp. (Inspired by U300 implementation.) - */ -static u32 notrace s5p_read_sched_clock(void) -{ - void __iomem *reg = s5p_timer_reg(); - - if (!reg) - return 0; - - return ~__raw_readl(reg); -} - -static void __init s5p_clocksource_init(void) -{ - unsigned long pclk; - unsigned long clock_rate; - - pclk = clk_get_rate(timerclk); - - clk_set_rate(tdiv_source, pclk / 2); - clk_set_parent(tin_source, tdiv_source); - - clock_rate = clk_get_rate(tin_source); - - s5p_time_setup(timer_source.source_id, TCNT_MAX); - s5p_time_start(timer_source.source_id, PERIODIC); - - setup_sched_clock(s5p_read_sched_clock, 32, clock_rate); - - if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", - clock_rate, 250, 32, clocksource_mmio_readl_down)) - panic("s5p_clocksource_timer: can't register clocksource\n"); -} - -static void __init s5p_timer_resources(void) -{ - - unsigned long event_id = timer_source.event_id; - unsigned long source_id = timer_source.source_id; - char devname[15]; - - timerclk = clk_get(NULL, "timers"); - if (IS_ERR(timerclk)) - panic("failed to get timers clock for timer"); - - clk_enable(timerclk); - - sprintf(devname, "s3c24xx-pwm.%lu", event_id); - s3c_device_timer[event_id].id = event_id; - s3c_device_timer[event_id].dev.init_name = devname; - - tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin"); - if (IS_ERR(tin_event)) - panic("failed to get pwm-tin clock for event timer"); - - tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv"); - if (IS_ERR(tdiv_event)) - panic("failed to get pwm-tdiv clock for event timer"); - - clk_enable(tin_event); - - sprintf(devname, "s3c24xx-pwm.%lu", source_id); - s3c_device_timer[source_id].id = source_id; - s3c_device_timer[source_id].dev.init_name = devname; - - tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin"); - if (IS_ERR(tin_source)) - panic("failed to get pwm-tin clock for source timer"); - - tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv"); - if (IS_ERR(tdiv_source)) - panic("failed to get pwm-tdiv clock for source timer"); - - clk_enable(tin_source); -} - -static void __init s5p_timer_init(void) -{ - s5p_timer_resources(); - s5p_clockevent_init(); - s5p_clocksource_init(); -} - -struct sys_timer s5p_timer = { - .init = s5p_timer_init, -}; diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 218462361e3..1922413f2ee 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -50,6 +50,14 @@ config S3C_LOWLEVEL_UART_PORT this configuration should be between zero and two. The port must have been initialised by the boot-loader before use. +# timer options + +config S5P_HRT + bool + select SAMSUNG_DEV_PWM + help + Use the High Resolution timer support + # clock options config SAMSUNG_CLKSRC diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index caa6f9af1f3..6217c41e626 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -13,6 +13,8 @@ obj- := obj-y += init.o cpu.o obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o +obj-$(CONFIG_S5P_HRT) += s5p-time.o + obj-y += clock.o obj-y += pwm-clock.o diff --git a/arch/arm/plat-samsung/s5p-time.c b/arch/arm/plat-samsung/s5p-time.c new file mode 100644 index 00000000000..028b6e877eb --- /dev/null +++ b/arch/arm/plat-samsung/s5p-time.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P - Common hr-timer support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct clk *tin_event; +static struct clk *tin_source; +static struct clk *tdiv_event; +static struct clk *tdiv_source; +static struct clk *timerclk; +static struct s5p_timer_source timer_source; +static unsigned long clock_count_per_tick; +static void s5p_timer_resume(void); + +static void s5p_time_stop(enum s5p_timer_mode mode) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + switch (mode) { + case S5P_PWM0: + tcon &= ~S3C2410_TCON_T0START; + break; + + case S5P_PWM1: + tcon &= ~S3C2410_TCON_T1START; + break; + + case S5P_PWM2: + tcon &= ~S3C2410_TCON_T2START; + break; + + case S5P_PWM3: + tcon &= ~S3C2410_TCON_T3START; + break; + + case S5P_PWM4: + tcon &= ~S3C2410_TCON_T4START; + break; + + default: + printk(KERN_ERR "Invalid Timer %d\n", mode); + break; + } + __raw_writel(tcon, S3C2410_TCON); +} + +static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + tcnt--; + + switch (mode) { + case S5P_PWM0: + tcon &= ~(0x0f << 0); + tcon |= S3C2410_TCON_T0MANUALUPD; + break; + + case S5P_PWM1: + tcon &= ~(0x0f << 8); + tcon |= S3C2410_TCON_T1MANUALUPD; + break; + + case S5P_PWM2: + tcon &= ~(0x0f << 12); + tcon |= S3C2410_TCON_T2MANUALUPD; + break; + + case S5P_PWM3: + tcon &= ~(0x0f << 16); + tcon |= S3C2410_TCON_T3MANUALUPD; + break; + + case S5P_PWM4: + tcon &= ~(0x07 << 20); + tcon |= S3C2410_TCON_T4MANUALUPD; + break; + + default: + printk(KERN_ERR "Invalid Timer %d\n", mode); + break; + } + + __raw_writel(tcnt, S3C2410_TCNTB(mode)); + __raw_writel(tcnt, S3C2410_TCMPB(mode)); + __raw_writel(tcon, S3C2410_TCON); +} + +static void s5p_time_start(enum s5p_timer_mode mode, bool periodic) +{ + unsigned long tcon; + + tcon = __raw_readl(S3C2410_TCON); + + switch (mode) { + case S5P_PWM0: + tcon |= S3C2410_TCON_T0START; + tcon &= ~S3C2410_TCON_T0MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T0RELOAD; + else + tcon &= ~S3C2410_TCON_T0RELOAD; + break; + + case S5P_PWM1: + tcon |= S3C2410_TCON_T1START; + tcon &= ~S3C2410_TCON_T1MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T1RELOAD; + else + tcon &= ~S3C2410_TCON_T1RELOAD; + break; + + case S5P_PWM2: + tcon |= S3C2410_TCON_T2START; + tcon &= ~S3C2410_TCON_T2MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T2RELOAD; + else + tcon &= ~S3C2410_TCON_T2RELOAD; + break; + + case S5P_PWM3: + tcon |= S3C2410_TCON_T3START; + tcon &= ~S3C2410_TCON_T3MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T3RELOAD; + else + tcon &= ~S3C2410_TCON_T3RELOAD; + break; + + case S5P_PWM4: + tcon |= S3C2410_TCON_T4START; + tcon &= ~S3C2410_TCON_T4MANUALUPD; + + if (periodic) + tcon |= S3C2410_TCON_T4RELOAD; + else + tcon &= ~S3C2410_TCON_T4RELOAD; + break; + + default: + printk(KERN_ERR "Invalid Timer %d\n", mode); + break; + } + __raw_writel(tcon, S3C2410_TCON); +} + +static int s5p_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + s5p_time_setup(timer_source.event_id, cycles); + s5p_time_start(timer_source.event_id, NON_PERIODIC); + + return 0; +} + +static void s5p_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + s5p_time_stop(timer_source.event_id); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + s5p_time_setup(timer_source.event_id, clock_count_per_tick); + s5p_time_start(timer_source.event_id, PERIODIC); + break; + + case CLOCK_EVT_MODE_ONESHOT: + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + + case CLOCK_EVT_MODE_RESUME: + s5p_timer_resume(); + break; + } +} + +static void s5p_timer_resume(void) +{ + /* event timer restart */ + s5p_time_setup(timer_source.event_id, clock_count_per_tick); + s5p_time_start(timer_source.event_id, PERIODIC); + + /* source timer restart */ + s5p_time_setup(timer_source.source_id, TCNT_MAX); + s5p_time_start(timer_source.source_id, PERIODIC); +} + +void __init s5p_set_timer_source(enum s5p_timer_mode event, + enum s5p_timer_mode source) +{ + s3c_device_timer[event].dev.bus = &platform_bus_type; + s3c_device_timer[source].dev.bus = &platform_bus_type; + + timer_source.event_id = event; + timer_source.source_id = source; +} + +static struct clock_event_device time_event_device = { + .name = "s5p_event_timer", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = s5p_set_next_event, + .set_mode = s5p_set_mode, +}; + +static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction s5p_clock_event_irq = { + .name = "s5p_time_irq", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = s5p_clock_event_isr, + .dev_id = &time_event_device, +}; + +static void __init s5p_clockevent_init(void) +{ + unsigned long pclk; + unsigned long clock_rate; + unsigned int irq_number; + struct clk *tscaler; + + pclk = clk_get_rate(timerclk); + + tscaler = clk_get_parent(tdiv_event); + + clk_set_rate(tscaler, pclk / 2); + clk_set_rate(tdiv_event, pclk / 2); + clk_set_parent(tin_event, tdiv_event); + + clock_rate = clk_get_rate(tin_event); + clock_count_per_tick = clock_rate / HZ; + + clockevents_calc_mult_shift(&time_event_device, + clock_rate, S5PTIMER_MIN_RANGE); + time_event_device.max_delta_ns = + clockevent_delta2ns(-1, &time_event_device); + time_event_device.min_delta_ns = + clockevent_delta2ns(1, &time_event_device); + + time_event_device.cpumask = cpumask_of(0); + clockevents_register_device(&time_event_device); + + irq_number = timer_source.event_id + IRQ_TIMER0; + setup_irq(irq_number, &s5p_clock_event_irq); +} + +static void __iomem *s5p_timer_reg(void) +{ + unsigned long offset = 0; + + switch (timer_source.source_id) { + case S5P_PWM0: + case S5P_PWM1: + case S5P_PWM2: + case S5P_PWM3: + offset = (timer_source.source_id * 0x0c) + 0x14; + break; + + case S5P_PWM4: + offset = 0x40; + break; + + default: + printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); + return NULL; + } + + return S3C_TIMERREG(offset); +} + +/* + * Override the global weak sched_clock symbol with this + * local implementation which uses the clocksource to get some + * better resolution when scheduling the kernel. We accept that + * this wraps around for now, since it is just a relative time + * stamp. (Inspired by U300 implementation.) + */ +static u32 notrace s5p_read_sched_clock(void) +{ + void __iomem *reg = s5p_timer_reg(); + + if (!reg) + return 0; + + return ~__raw_readl(reg); +} + +static void __init s5p_clocksource_init(void) +{ + unsigned long pclk; + unsigned long clock_rate; + + pclk = clk_get_rate(timerclk); + + clk_set_rate(tdiv_source, pclk / 2); + clk_set_parent(tin_source, tdiv_source); + + clock_rate = clk_get_rate(tin_source); + + s5p_time_setup(timer_source.source_id, TCNT_MAX); + s5p_time_start(timer_source.source_id, PERIODIC); + + setup_sched_clock(s5p_read_sched_clock, 32, clock_rate); + + if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", + clock_rate, 250, 32, clocksource_mmio_readl_down)) + panic("s5p_clocksource_timer: can't register clocksource\n"); +} + +static void __init s5p_timer_resources(void) +{ + + unsigned long event_id = timer_source.event_id; + unsigned long source_id = timer_source.source_id; + char devname[15]; + + timerclk = clk_get(NULL, "timers"); + if (IS_ERR(timerclk)) + panic("failed to get timers clock for timer"); + + clk_enable(timerclk); + + sprintf(devname, "s3c24xx-pwm.%lu", event_id); + s3c_device_timer[event_id].id = event_id; + s3c_device_timer[event_id].dev.init_name = devname; + + tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin"); + if (IS_ERR(tin_event)) + panic("failed to get pwm-tin clock for event timer"); + + tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv"); + if (IS_ERR(tdiv_event)) + panic("failed to get pwm-tdiv clock for event timer"); + + clk_enable(tin_event); + + sprintf(devname, "s3c24xx-pwm.%lu", source_id); + s3c_device_timer[source_id].id = source_id; + s3c_device_timer[source_id].dev.init_name = devname; + + tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin"); + if (IS_ERR(tin_source)) + panic("failed to get pwm-tin clock for source timer"); + + tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv"); + if (IS_ERR(tdiv_source)) + panic("failed to get pwm-tdiv clock for source timer"); + + clk_enable(tin_source); +} + +static void __init s5p_timer_init(void) +{ + s5p_timer_resources(); + s5p_clockevent_init(); + s5p_clocksource_init(); +} + +struct sys_timer s5p_timer = { + .init = s5p_timer_init, +}; -- cgit v1.2.3-70-g09d2 From cfe370f876407735041f8e02ec31ffa922cd8e45 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 17 Apr 2012 20:05:19 -0700 Subject: ARM: SAMSUNG: move platform device for s5p uart into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 4 - arch/arm/plat-s5p/Makefile | 1 - arch/arm/plat-s5p/dev-uart.c | 137 ----------------------------------- arch/arm/plat-samsung/Kconfig | 6 ++ arch/arm/plat-samsung/Makefile | 1 + arch/arm/plat-samsung/s5p-dev-uart.c | 89 +++++++++++++++++++++++ 6 files changed, 96 insertions(+), 142 deletions(-) delete mode 100644 arch/arm/plat-s5p/dev-uart.c create mode 100644 arch/arm/plat-samsung/s5p-dev-uart.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 795790df740..33d9bc8b03a 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -23,10 +23,6 @@ config PLAT_S5P help Base platform code for Samsung's S5P series SoC. -config S5P_DEV_UART - def_bool y - depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) - config S5P_DEV_FIMC0 bool help diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 0a2ce38b179..1dc6b1c5bd7 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -12,6 +12,5 @@ obj- := # devices -obj-$(CONFIG_S5P_DEV_UART) += dev-uart.o obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c deleted file mode 100644 index c9308db3618..00000000000 --- a/arch/arm/plat-s5p/dev-uart.c +++ /dev/null @@ -1,137 +0,0 @@ -/* linux/arch/arm/plat-s5p/dev-uart.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Base S5P UART resource and device definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - - /* Serial port registrations */ - -static struct resource s5p_uart0_resource[] = { - [0] = { - .start = S5P_PA_UART0, - .end = S5P_PA_UART0 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART0, - .end = IRQ_UART0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource s5p_uart1_resource[] = { - [0] = { - .start = S5P_PA_UART1, - .end = S5P_PA_UART1 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART1, - .end = IRQ_UART1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource s5p_uart2_resource[] = { - [0] = { - .start = S5P_PA_UART2, - .end = S5P_PA_UART2 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART2, - .end = IRQ_UART2, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource s5p_uart3_resource[] = { -#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 - [0] = { - .start = S5P_PA_UART3, - .end = S5P_PA_UART3 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART3, - .end = IRQ_UART3, - .flags = IORESOURCE_IRQ, - }, -#endif -}; - -static struct resource s5p_uart4_resource[] = { -#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 - [0] = { - .start = S5P_PA_UART4, - .end = S5P_PA_UART4 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART4, - .end = IRQ_UART4, - .flags = IORESOURCE_IRQ, - }, -#endif -}; - -static struct resource s5p_uart5_resource[] = { -#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 - [0] = { - .start = S5P_PA_UART5, - .end = S5P_PA_UART5 + S5P_SZ_UART - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_UART5, - .end = IRQ_UART5, - .flags = IORESOURCE_IRQ, - }, -#endif -}; - -struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { - [0] = { - .resources = s5p_uart0_resource, - .nr_resources = ARRAY_SIZE(s5p_uart0_resource), - }, - [1] = { - .resources = s5p_uart1_resource, - .nr_resources = ARRAY_SIZE(s5p_uart1_resource), - }, - [2] = { - .resources = s5p_uart2_resource, - .nr_resources = ARRAY_SIZE(s5p_uart2_resource), - }, - [3] = { - .resources = s5p_uart3_resource, - .nr_resources = ARRAY_SIZE(s5p_uart3_resource), - }, - [4] = { - .resources = s5p_uart4_resource, - .nr_resources = ARRAY_SIZE(s5p_uart4_resource), - }, - [5] = { - .resources = s5p_uart5_resource, - .nr_resources = ARRAY_SIZE(s5p_uart5_resource), - }, -}; diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 1922413f2ee..5ce6bc8ccf8 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -146,6 +146,12 @@ config S3C_GPIO_TRACK Internal configuration option to enable the s3c specific gpio chip tracking if the platform requires it. +# uart options + +config S5P_DEV_UART + def_bool y + depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) + # ADC driver config S3C_ADC diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 6217c41e626..b20047b5633 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -36,6 +36,7 @@ obj-y += platformdata.o obj-y += devs.o obj-y += dev-uart.o +obj-$(CONFIG_S5P_DEV_UART) += s5p-dev-uart.o obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o diff --git a/arch/arm/plat-samsung/s5p-dev-uart.c b/arch/arm/plat-samsung/s5p-dev-uart.c new file mode 100644 index 00000000000..cafa3deddcc --- /dev/null +++ b/arch/arm/plat-samsung/s5p-dev-uart.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009,2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Base S5P UART resource and device definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + + /* Serial port registrations */ + +static struct resource s5p_uart0_resource[] = { + [0] = DEFINE_RES_MEM(S5P_PA_UART0, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART0), +}; + +static struct resource s5p_uart1_resource[] = { + [0] = DEFINE_RES_MEM(S5P_PA_UART1, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART1), +}; + +static struct resource s5p_uart2_resource[] = { + [0] = DEFINE_RES_MEM(S5P_PA_UART2, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART2), +}; + +static struct resource s5p_uart3_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 + [0] = DEFINE_RES_MEM(S5P_PA_UART3, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART3), +#endif +}; + +static struct resource s5p_uart4_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 + [0] = DEFINE_RES_MEM(S5P_PA_UART4, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART4), +#endif +}; + +static struct resource s5p_uart5_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 + [0] = DEFINE_RES_MEM(S5P_PA_UART5, S5P_SZ_UART), + [1] = DEFINE_RES_IRQ(IRQ_UART5), +#endif +}; + +struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { + [0] = { + .resources = s5p_uart0_resource, + .nr_resources = ARRAY_SIZE(s5p_uart0_resource), + }, + [1] = { + .resources = s5p_uart1_resource, + .nr_resources = ARRAY_SIZE(s5p_uart1_resource), + }, + [2] = { + .resources = s5p_uart2_resource, + .nr_resources = ARRAY_SIZE(s5p_uart2_resource), + }, + [3] = { + .resources = s5p_uart3_resource, + .nr_resources = ARRAY_SIZE(s5p_uart3_resource), + }, + [4] = { + .resources = s5p_uart4_resource, + .nr_resources = ARRAY_SIZE(s5p_uart4_resource), + }, + [5] = { + .resources = s5p_uart5_resource, + .nr_resources = ARRAY_SIZE(s5p_uart5_resource), + }, +}; -- cgit v1.2.3-70-g09d2 From d9c452f4b4042baaa24fb91bf0c847813ff3645d Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 17 Apr 2012 20:21:30 -0700 Subject: ARM: SAMSUNG: move setup code for s5p mfc and mipiphy into plat-samsung Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 10 ----- arch/arm/plat-s5p/Makefile | 5 --- arch/arm/plat-s5p/dev-mfc.c | 73 ----------------------------------- arch/arm/plat-s5p/setup-mipiphy.c | 63 ------------------------------ arch/arm/plat-samsung/Kconfig | 10 +++++ arch/arm/plat-samsung/Makefile | 3 ++ arch/arm/plat-samsung/s5p-dev-mfc.c | 71 ++++++++++++++++++++++++++++++++++ arch/arm/plat-samsung/setup-mipiphy.c | 63 ++++++++++++++++++++++++++++++ 8 files changed, 147 insertions(+), 151 deletions(-) delete mode 100644 arch/arm/plat-s5p/dev-mfc.c delete mode 100644 arch/arm/plat-s5p/setup-mipiphy.c create mode 100644 arch/arm/plat-samsung/s5p-dev-mfc.c create mode 100644 arch/arm/plat-samsung/setup-mipiphy.c (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 33d9bc8b03a..4ff6d7e9bf2 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -63,11 +63,6 @@ config S5P_DEV_I2C_HDMIPHY help Compile in platform device definitions for I2C HDMIPHY controller -config S5P_DEV_MFC - bool - help - Compile in platform device definitions for MFC - config S5P_DEV_ONENAND bool help @@ -92,8 +87,3 @@ config S5P_DEV_USB_EHCI bool help Compile in platform device definition for USB EHCI - -config S5P_SETUP_MIPIPHY - bool - help - Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 1dc6b1c5bd7..884b9a17360 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -9,8 +9,3 @@ obj-y := obj-m := obj-n := dummy.o obj- := - -# devices - -obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o -obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c deleted file mode 100644 index a30d36b7f61..00000000000 --- a/arch/arm/plat-s5p/dev-mfc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* linux/arch/arm/plat-s5p/dev-mfc.c - * - * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd - * - * Base S5P MFC resource and device definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -struct s5p_mfc_reserved_mem { - phys_addr_t base; - unsigned long size; - struct device *dev; -}; - -static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata; - -void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, - phys_addr_t lbase, unsigned int lsize) -{ - int i; - - s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev; - s5p_mfc_mem[0].base = rbase; - s5p_mfc_mem[0].size = rsize; - - s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev; - s5p_mfc_mem[1].base = lbase; - s5p_mfc_mem[1].size = lsize; - - for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { - struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; - if (memblock_remove(area->base, area->size)) { - printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n", - area->size, (unsigned long) area->base); - area->base = 0; - } - } -} - -static int __init s5p_mfc_memory_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { - struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; - if (!area->base) - continue; - - if (dma_declare_coherent_memory(area->dev, area->base, - area->base, area->size, - DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) - printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n", - area->size, (unsigned long) area->base); - } - return 0; -} -device_initcall(s5p_mfc_memory_init); diff --git a/arch/arm/plat-s5p/setup-mipiphy.c b/arch/arm/plat-s5p/setup-mipiphy.c deleted file mode 100644 index 683c466c0e6..00000000000 --- a/arch/arm/plat-s5p/setup-mipiphy.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * - * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control - * - * 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 -#include -#include -#include -#include - -static int __s5p_mipi_phy_control(struct platform_device *pdev, - bool on, u32 reset) -{ - static DEFINE_SPINLOCK(lock); - void __iomem *addr; - unsigned long flags; - int pid; - u32 cfg; - - if (!pdev) - return -EINVAL; - - pid = (pdev->id == -1) ? 0 : pdev->id; - - if (pid != 0 && pid != 1) - return -EINVAL; - - addr = S5P_MIPI_DPHY_CONTROL(pid); - - spin_lock_irqsave(&lock, flags); - - cfg = __raw_readl(addr); - cfg = on ? (cfg | reset) : (cfg & ~reset); - __raw_writel(cfg, addr); - - if (on) { - cfg |= S5P_MIPI_DPHY_ENABLE; - } else if (!(cfg & (S5P_MIPI_DPHY_SRESETN | - S5P_MIPI_DPHY_MRESETN) & ~reset)) { - cfg &= ~S5P_MIPI_DPHY_ENABLE; - } - - __raw_writel(cfg, addr); - spin_unlock_irqrestore(&lock, flags); - - return 0; -} - -int s5p_csis_phy_enable(struct platform_device *pdev, bool on) -{ - return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN); -} - -int s5p_dsim_phy_enable(struct platform_device *pdev, bool on) -{ - return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN); -} diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 5ce6bc8ccf8..7fec2e9cdad 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -309,6 +309,11 @@ config SAMSUNG_DEV_BACKLIGHT help Compile in platform device definition LCD backlight with PWM Timer +config S5P_DEV_MFC + bool + help + Compile in setup memory (init) code for MFC + config S3C24XX_PWM bool "PWM device support" select HAVE_PWM @@ -316,6 +321,11 @@ config S3C24XX_PWM Support for exporting the PWM timer blocks via the pwm device system +config S5P_SETUP_MIPIPHY + bool + help + Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices + # DMA config S3C_DMA diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index b20047b5633..860b2db4db1 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -36,10 +36,13 @@ obj-y += platformdata.o obj-y += devs.o obj-y += dev-uart.o +obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o obj-$(CONFIG_S5P_DEV_UART) += s5p-dev-uart.o obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o +obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o + # DMA support obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c new file mode 100644 index 00000000000..ad6089465e2 --- /dev/null +++ b/arch/arm/plat-samsung/s5p-dev-mfc.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd + * + * Base S5P MFC resource and device definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct s5p_mfc_reserved_mem { + phys_addr_t base; + unsigned long size; + struct device *dev; +}; + +static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata; + +void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, + phys_addr_t lbase, unsigned int lsize) +{ + int i; + + s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev; + s5p_mfc_mem[0].base = rbase; + s5p_mfc_mem[0].size = rsize; + + s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev; + s5p_mfc_mem[1].base = lbase; + s5p_mfc_mem[1].size = lsize; + + for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { + struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; + if (memblock_remove(area->base, area->size)) { + printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n", + area->size, (unsigned long) area->base); + area->base = 0; + } + } +} + +static int __init s5p_mfc_memory_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { + struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; + if (!area->base) + continue; + + if (dma_declare_coherent_memory(area->dev, area->base, + area->base, area->size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) + printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n", + area->size, (unsigned long) area->base); + } + return 0; +} +device_initcall(s5p_mfc_memory_init); diff --git a/arch/arm/plat-samsung/setup-mipiphy.c b/arch/arm/plat-samsung/setup-mipiphy.c new file mode 100644 index 00000000000..683c466c0e6 --- /dev/null +++ b/arch/arm/plat-samsung/setup-mipiphy.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 Samsung Electronics Co., Ltd. + * + * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control + * + * 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 +#include +#include +#include +#include + +static int __s5p_mipi_phy_control(struct platform_device *pdev, + bool on, u32 reset) +{ + static DEFINE_SPINLOCK(lock); + void __iomem *addr; + unsigned long flags; + int pid; + u32 cfg; + + if (!pdev) + return -EINVAL; + + pid = (pdev->id == -1) ? 0 : pdev->id; + + if (pid != 0 && pid != 1) + return -EINVAL; + + addr = S5P_MIPI_DPHY_CONTROL(pid); + + spin_lock_irqsave(&lock, flags); + + cfg = __raw_readl(addr); + cfg = on ? (cfg | reset) : (cfg & ~reset); + __raw_writel(cfg, addr); + + if (on) { + cfg |= S5P_MIPI_DPHY_ENABLE; + } else if (!(cfg & (S5P_MIPI_DPHY_SRESETN | + S5P_MIPI_DPHY_MRESETN) & ~reset)) { + cfg &= ~S5P_MIPI_DPHY_ENABLE; + } + + __raw_writel(cfg, addr); + spin_unlock_irqrestore(&lock, flags); + + return 0; +} + +int s5p_csis_phy_enable(struct platform_device *pdev, bool on) +{ + return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN); +} + +int s5p_dsim_phy_enable(struct platform_device *pdev, bool on) +{ + return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN); +} -- cgit v1.2.3-70-g09d2 From e033ca9bfa0831889d7b8fdad516c771ad200e41 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 17 Apr 2012 20:39:10 -0700 Subject: ARM: SAMSUNG: move options for common s5p into plat-samsung/Kconfig Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/Kconfig | 65 ------------------------------------------- arch/arm/plat-samsung/Kconfig | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 65 deletions(-) (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 4ff6d7e9bf2..e7d5d77b1b6 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -22,68 +22,3 @@ config PLAT_S5P select SAMSUNG_IRQ_VIC_TIMER help Base platform code for Samsung's S5P series SoC. - -config S5P_DEV_FIMC0 - bool - help - Compile in platform device definitions for FIMC controller 0 - -config S5P_DEV_FIMC1 - bool - help - Compile in platform device definitions for FIMC controller 1 - -config S5P_DEV_FIMC2 - bool - help - Compile in platform device definitions for FIMC controller 2 - -config S5P_DEV_FIMC3 - bool - help - Compile in platform device definitions for FIMC controller 3 - -config S5P_DEV_JPEG - bool - help - Compile in platform device definitions for JPEG codec - -config S5P_DEV_G2D - bool - help - Compile in platform device definitions for G2D device - -config S5P_DEV_FIMD0 - bool - help - Compile in platform device definitions for FIMD controller 0 - -config S5P_DEV_I2C_HDMIPHY - bool - help - Compile in platform device definitions for I2C HDMIPHY controller - -config S5P_DEV_ONENAND - bool - help - Compile in platform device definition for OneNAND controller - -config S5P_DEV_CSIS0 - bool - help - Compile in platform device definitions for MIPI-CSIS channel 0 - -config S5P_DEV_CSIS1 - bool - help - Compile in platform device definitions for MIPI-CSIS channel 1 - -config S5P_DEV_TV - bool - help - Compile in platform device definition for TV interface - -config S5P_DEV_USB_EHCI - bool - help - Compile in platform device definition for USB EHCI diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 7fec2e9cdad..8381d47027a 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -309,11 +309,76 @@ config SAMSUNG_DEV_BACKLIGHT help Compile in platform device definition LCD backlight with PWM Timer +config S5P_DEV_CSIS0 + bool + help + Compile in platform device definitions for MIPI-CSIS channel 0 + +config S5P_DEV_CSIS1 + bool + help + Compile in platform device definitions for MIPI-CSIS channel 1 + +config S5P_DEV_FIMC0 + bool + help + Compile in platform device definitions for FIMC controller 0 + +config S5P_DEV_FIMC1 + bool + help + Compile in platform device definitions for FIMC controller 1 + +config S5P_DEV_FIMC2 + bool + help + Compile in platform device definitions for FIMC controller 2 + +config S5P_DEV_FIMC3 + bool + help + Compile in platform device definitions for FIMC controller 3 + +config S5P_DEV_FIMD0 + bool + help + Compile in platform device definitions for FIMD controller 0 + +config S5P_DEV_G2D + bool + help + Compile in platform device definitions for G2D device + +config S5P_DEV_I2C_HDMIPHY + bool + help + Compile in platform device definitions for I2C HDMIPHY controller + +config S5P_DEV_JPEG + bool + help + Compile in platform device definitions for JPEG codec + config S5P_DEV_MFC bool help Compile in setup memory (init) code for MFC +config S5P_DEV_ONENAND + bool + help + Compile in platform device definition for OneNAND controller + +config S5P_DEV_TV + bool + help + Compile in platform device definition for TV interface + +config S5P_DEV_USB_EHCI + bool + help + Compile in platform device definition for USB EHCI + config S3C24XX_PWM bool "PWM device support" select HAVE_PWM -- cgit v1.2.3-70-g09d2 From 199642bfe107c411f25fbfc16c9fd49cfef9785d Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Sun, 13 May 2012 07:11:38 +0900 Subject: ARM: SAMSUNG: merge plat-s5p into plat-samsung Since just plat-samsung can support all of Samsung stuff so that there is no more need to keep the plat-s5p for S5P SoCs. Signed-off-by: Kukjin Kim --- arch/arm/Kconfig | 1 - arch/arm/Makefile | 2 +- arch/arm/plat-s5p/Kconfig | 24 ------------------------ arch/arm/plat-s5p/Makefile | 11 ----------- arch/arm/plat-samsung/Kconfig | 18 ++++++++++++++++++ 5 files changed, 19 insertions(+), 37 deletions(-) delete mode 100644 arch/arm/plat-s5p/Kconfig delete mode 100644 arch/arm/plat-s5p/Makefile (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 93180845ae1..60c2f9c0ba1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1087,7 +1087,6 @@ source "arch/arm/mach-sa1100/Kconfig" source "arch/arm/plat-samsung/Kconfig" source "arch/arm/plat-s3c24xx/Kconfig" -source "arch/arm/plat-s5p/Kconfig" source "arch/arm/plat-spear/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 047a20780fc..f55b509d35c 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -209,7 +209,7 @@ plat-$(CONFIG_PLAT_NOMADIK) := nomadik plat-$(CONFIG_PLAT_ORION) := orion plat-$(CONFIG_PLAT_PXA) := pxa plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung -plat-$(CONFIG_PLAT_S5P) := s5p samsung +plat-$(CONFIG_PLAT_S5P) := samsung plat-$(CONFIG_PLAT_SPEAR) := spear plat-$(CONFIG_PLAT_VERSATILE) := versatile diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig deleted file mode 100644 index e7d5d77b1b6..00000000000 --- a/arch/arm/plat-s5p/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -# arch/arm/plat-s5p/Kconfig -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -config PLAT_S5P - bool - depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) - default y - select ARM_VIC if !ARCH_EXYNOS - select ARM_GIC if ARCH_EXYNOS - select GIC_NON_BANKED if ARCH_EXYNOS4 - select NO_IOPORT - select ARCH_REQUIRE_GPIOLIB - select S3C_GPIO_TRACK - select S5P_GPIO_DRVSTR - select SAMSUNG_GPIOLIB_4BIT - select PLAT_SAMSUNG - select SAMSUNG_CLKSRC - select SAMSUNG_IRQ_VIC_TIMER - help - Base platform code for Samsung's S5P series SoC. diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile deleted file mode 100644 index 884b9a17360..00000000000 --- a/arch/arm/plat-s5p/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# arch/arm/plat-s5p/Makefile -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -obj-y := -obj-m := -obj-n := dummy.o -obj- := diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 8381d47027a..b54e13d0901 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -13,6 +13,24 @@ config PLAT_SAMSUNG help Base platform code for all Samsung SoC based systems +config PLAT_S5P + bool + depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) + default y + select ARM_VIC if !ARCH_EXYNOS + select ARM_GIC if ARCH_EXYNOS + select GIC_NON_BANKED if ARCH_EXYNOS4 + select NO_IOPORT + select ARCH_REQUIRE_GPIOLIB + select S3C_GPIO_TRACK + select S5P_GPIO_DRVSTR + select SAMSUNG_GPIOLIB_4BIT + select PLAT_SAMSUNG + select SAMSUNG_CLKSRC + select SAMSUNG_IRQ_VIC_TIMER + help + Base platform code for Samsung's S5P series SoC. + if PLAT_SAMSUNG # boot configurations -- cgit v1.2.3-70-g09d2 From 20ef9e08d27b3f5e09c32d4d371fa97f610a3069 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Sat, 12 May 2012 16:40:52 +0900 Subject: ARM: EXYNOS: Support DMA for EXYNOS5250 SoC mach-exynos/dma.c is updated to support both exynos4 and exynos5. Signed-off-by: Boojin Kim Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 7 +- arch/arm/mach-exynos/Makefile | 2 +- arch/arm/mach-exynos/dma.c | 141 ++++++++++++++++++++----- arch/arm/plat-samsung/Kconfig | 2 +- arch/arm/plat-samsung/include/plat/dma-pl330.h | 1 + 5 files changed, 121 insertions(+), 32 deletions(-) (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 88898ef5261..4bb2f9464e2 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -61,6 +61,7 @@ config SOC_EXYNOS5250 bool "SAMSUNG EXYNOS5250" default y depends on ARCH_EXYNOS5 + select SAMSUNG_DMADEV help Enable EXYNOS5250 SoC support @@ -70,7 +71,7 @@ config EXYNOS4_MCT help Use MCT (Multi Core Timer) as kernel timers -config EXYNOS4_DEV_DMA +config EXYNOS_DEV_DMA bool help Compile in amba device definitions for DMA controller @@ -228,7 +229,7 @@ config MACH_ARMLEX4210 select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC3 select EXYNOS4_DEV_AHCI - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select EXYNOS4_SETUP_SDHCI help Machine support for Samsung ARMLEX4210 based on EXYNOS4210 @@ -352,7 +353,7 @@ config MACH_SMDK4212 select SAMSUNG_DEV_KEYPAD select SAMSUNG_DEV_PWM select EXYNOS_DEV_SYSMMU - select EXYNOS4_DEV_DMA + select EXYNOS_DEV_DMA select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C7 diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index bd7e7654a25..84c06ae53ee 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -51,7 +51,7 @@ obj-y += dev-uart.o obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o -obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o +obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o obj-$(CONFIG_EXYNOS_DEV_DRM) += dev-drm.o obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c index 69aaa450320..f60b66dbcf8 100644 --- a/arch/arm/mach-exynos/dma.c +++ b/arch/arm/mach-exynos/dma.c @@ -103,10 +103,45 @@ static u8 exynos4212_pdma0_peri[] = { DMACH_MIPI_HSI5, }; -struct dma_pl330_platdata exynos4_pdma0_pdata; +static u8 exynos5250_pdma0_peri[] = { + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM2_RX, + DMACH_PCM2_TX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI2_RX, + DMACH_SPI2_TX, + DMACH_I2S0S_TX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_SLIMBUS0_RX, + DMACH_SLIMBUS0_TX, + DMACH_SLIMBUS2_RX, + DMACH_SLIMBUS2_TX, + DMACH_SLIMBUS4_RX, + DMACH_SLIMBUS4_TX, + DMACH_AC97_MICIN, + DMACH_AC97_PCMIN, + DMACH_AC97_PCMOUT, + DMACH_MIPI_HSI0, + DMACH_MIPI_HSI2, + DMACH_MIPI_HSI4, + DMACH_MIPI_HSI6, +}; + +static struct dma_pl330_platdata exynos_pdma0_pdata; -static AMBA_AHB_DEVICE(exynos4_pdma0, "dma-pl330.0", 0x00041330, - EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos4_pdma0_pdata); +static AMBA_AHB_DEVICE(exynos_pdma0, "dma-pl330.0", 0x00041330, + EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos_pdma0_pdata); static u8 exynos4210_pdma1_peri[] = { DMACH_PCM0_RX, @@ -169,10 +204,45 @@ static u8 exynos4212_pdma1_peri[] = { DMACH_MIPI_HSI7, }; -static struct dma_pl330_platdata exynos4_pdma1_pdata; +static u8 exynos5250_pdma1_peri[] = { + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM1_RX, + DMACH_PCM1_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_PWM, + DMACH_SPDIF, + DMACH_I2S0S_TX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_SLIMBUS1_RX, + DMACH_SLIMBUS1_TX, + DMACH_SLIMBUS3_RX, + DMACH_SLIMBUS3_TX, + DMACH_SLIMBUS5_RX, + DMACH_SLIMBUS5_TX, + DMACH_SLIMBUS0AUX_RX, + DMACH_SLIMBUS0AUX_TX, + DMACH_DISP1, + DMACH_MIPI_HSI1, + DMACH_MIPI_HSI3, + DMACH_MIPI_HSI5, + DMACH_MIPI_HSI7, +}; -static AMBA_AHB_DEVICE(exynos4_pdma1, "dma-pl330.1", 0x00041330, - EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos4_pdma1_pdata); +static struct dma_pl330_platdata exynos_pdma1_pdata; + +static AMBA_AHB_DEVICE(exynos_pdma1, "dma-pl330.1", 0x00041330, + EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos_pdma1_pdata); static u8 mdma_peri[] = { DMACH_MTOM_0, @@ -185,46 +255,63 @@ static u8 mdma_peri[] = { DMACH_MTOM_7, }; -static struct dma_pl330_platdata exynos4_mdma1_pdata = { +static struct dma_pl330_platdata exynos_mdma1_pdata = { .nr_valid_peri = ARRAY_SIZE(mdma_peri), .peri_id = mdma_peri, }; -static AMBA_AHB_DEVICE(exynos4_mdma1, "dma-pl330.2", 0x00041330, - EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos4_mdma1_pdata); +static AMBA_AHB_DEVICE(exynos_mdma1, "dma-pl330.2", 0x00041330, + EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos_mdma1_pdata); -static int __init exynos4_dma_init(void) +static int __init exynos_dma_init(void) { if (of_have_populated_dt()) return 0; if (soc_is_exynos4210()) { - exynos4_pdma0_pdata.nr_valid_peri = + exynos_pdma0_pdata.nr_valid_peri = ARRAY_SIZE(exynos4210_pdma0_peri); - exynos4_pdma0_pdata.peri_id = exynos4210_pdma0_peri; - exynos4_pdma1_pdata.nr_valid_peri = + exynos_pdma0_pdata.peri_id = exynos4210_pdma0_peri; + exynos_pdma1_pdata.nr_valid_peri = ARRAY_SIZE(exynos4210_pdma1_peri); - exynos4_pdma1_pdata.peri_id = exynos4210_pdma1_peri; + exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri; } else if (soc_is_exynos4212() || soc_is_exynos4412()) { - exynos4_pdma0_pdata.nr_valid_peri = + exynos_pdma0_pdata.nr_valid_peri = ARRAY_SIZE(exynos4212_pdma0_peri); - exynos4_pdma0_pdata.peri_id = exynos4212_pdma0_peri; - exynos4_pdma1_pdata.nr_valid_peri = + exynos_pdma0_pdata.peri_id = exynos4212_pdma0_peri; + exynos_pdma1_pdata.nr_valid_peri = ARRAY_SIZE(exynos4212_pdma1_peri); - exynos4_pdma1_pdata.peri_id = exynos4212_pdma1_peri; + exynos_pdma1_pdata.peri_id = exynos4212_pdma1_peri; + } else if (soc_is_exynos5250()) { + exynos_pdma0_pdata.nr_valid_peri = + ARRAY_SIZE(exynos5250_pdma0_peri); + exynos_pdma0_pdata.peri_id = exynos5250_pdma0_peri; + exynos_pdma1_pdata.nr_valid_peri = + ARRAY_SIZE(exynos5250_pdma1_peri); + exynos_pdma1_pdata.peri_id = exynos5250_pdma1_peri; + + exynos_pdma0_device.res.start = EXYNOS5_PA_PDMA0; + exynos_pdma0_device.res.end = EXYNOS5_PA_PDMA0 + SZ_4K; + exynos_pdma0_device.irq[0] = EXYNOS5_IRQ_PDMA0; + exynos_pdma1_device.res.start = EXYNOS5_PA_PDMA1; + exynos_pdma1_device.res.end = EXYNOS5_PA_PDMA1 + SZ_4K; + exynos_pdma0_device.irq[0] = EXYNOS5_IRQ_PDMA1; + exynos_mdma1_device.res.start = EXYNOS5_PA_MDMA1; + exynos_mdma1_device.res.end = EXYNOS5_PA_MDMA1 + SZ_4K; + exynos_pdma0_device.irq[0] = EXYNOS5_IRQ_MDMA1; } - dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask); - dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask); - amba_device_register(&exynos4_pdma0_device, &iomem_resource); + dma_cap_set(DMA_SLAVE, exynos_pdma0_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, exynos_pdma0_pdata.cap_mask); + amba_device_register(&exynos_pdma0_device, &iomem_resource); - dma_cap_set(DMA_SLAVE, exynos4_pdma1_pdata.cap_mask); - dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask); - amba_device_register(&exynos4_pdma1_device, &iomem_resource); + dma_cap_set(DMA_SLAVE, exynos_pdma1_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, exynos_pdma1_pdata.cap_mask); + amba_device_register(&exynos_pdma1_device, &iomem_resource); - dma_cap_set(DMA_MEMCPY, exynos4_mdma1_pdata.cap_mask); - amba_device_register(&exynos4_mdma1_device, &iomem_resource); + dma_cap_set(DMA_MEMCPY, exynos_mdma1_pdata.cap_mask); + amba_device_register(&exynos_mdma1_device, &iomem_resource); return 0; } -arch_initcall(exynos4_dma_init); +arch_initcall(exynos_dma_init); diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index a0ffc77da80..77e65b483f9 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -291,7 +291,7 @@ config S3C_DMA config SAMSUNG_DMADEV bool select DMADEVICES - select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \ + select PL330_DMA if (ARCH_EXYNOS5 || ARCH_EXYNOS4 || CPU_S5PV210 || CPU_S5PC100 || \ CPU_S5P6450 || CPU_S5P6440) select ARM_AMBA help diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h index 0670f37aaae..d384a8016b4 100644 --- a/arch/arm/plat-samsung/include/plat/dma-pl330.h +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h @@ -90,6 +90,7 @@ enum dma_ch { DMACH_MIPI_HSI5, DMACH_MIPI_HSI6, DMACH_MIPI_HSI7, + DMACH_DISP1, DMACH_MTOM_0, DMACH_MTOM_1, DMACH_MTOM_2, -- cgit v1.2.3-70-g09d2 From 57b317f912b3f4b05c834818c73d7c8ea22642f7 Mon Sep 17 00:00:00 2001 From: Kisoo Yu Date: Tue, 24 Apr 2012 14:54:15 -0700 Subject: ARM: EXYNOS: Add pre-divider and fout mux clocks for bpll and mpll The fout clock of BPLL and MPLL have a selectable source on EXYNOS5250. The clock options are a fixed divided by 2 clock and the output of the PLL itself. Add support for these new clock instances. Signed-off-by: Kisoo Yu Signed-off-by: Thomas Abraham [kgene.kim@samsung.com: moved common pll stuff into s5p-clock.c] Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/clock-exynos5.c | 46 ++++++++++++++++++++++++-- arch/arm/mach-exynos/include/mach/regs-clock.h | 2 ++ arch/arm/plat-samsung/include/plat/s5p-clock.h | 4 +++ arch/arm/plat-samsung/s5p-clock.c | 30 +++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index 84ef35aceba..5aa460b01fd 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -165,11 +165,29 @@ static struct clksrc_clk exynos5_clk_sclk_apll = { .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 }, }; +static struct clksrc_clk exynos5_clk_mout_bpll_fout = { + .clk = { + .name = "mout_bpll_fout", + }, + .sources = &clk_src_bpll_fout, + .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 0, .size = 1 }, +}; + +static struct clk *exynos5_clk_src_bpll_list[] = { + [0] = &clk_fin_bpll, + [1] = &exynos5_clk_mout_bpll_fout.clk, +}; + +static struct clksrc_sources exynos5_clk_src_bpll = { + .sources = exynos5_clk_src_bpll_list, + .nr_sources = ARRAY_SIZE(exynos5_clk_src_bpll_list), +}; + static struct clksrc_clk exynos5_clk_mout_bpll = { .clk = { .name = "mout_bpll", }, - .sources = &clk_src_bpll, + .sources = &exynos5_clk_src_bpll, .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 }, }; @@ -207,11 +225,29 @@ static struct clksrc_clk exynos5_clk_mout_epll = { .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 }, }; +static struct clksrc_clk exynos5_clk_mout_mpll_fout = { + .clk = { + .name = "mout_mpll_fout", + }, + .sources = &clk_src_mpll_fout, + .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 4, .size = 1 }, +}; + +static struct clk *exynos5_clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &exynos5_clk_mout_mpll_fout.clk, +}; + +static struct clksrc_sources exynos5_clk_src_mpll = { + .sources = exynos5_clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(exynos5_clk_src_mpll_list), +}; + struct clksrc_clk exynos5_clk_mout_mpll = { .clk = { .name = "mout_mpll", }, - .sources = &clk_src_mpll, + .sources = &exynos5_clk_src_mpll, .reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 }, }; @@ -1036,10 +1072,12 @@ static struct clksrc_clk *exynos5_sysclks[] = { &exynos5_clk_mout_apll, &exynos5_clk_sclk_apll, &exynos5_clk_mout_bpll, + &exynos5_clk_mout_bpll_fout, &exynos5_clk_mout_bpll_user, &exynos5_clk_mout_cpll, &exynos5_clk_mout_epll, &exynos5_clk_mout_mpll, + &exynos5_clk_mout_mpll_fout, &exynos5_clk_mout_mpll_user, &exynos5_clk_vpllsrc, &exynos5_clk_sclk_vpll, @@ -1103,7 +1141,9 @@ static struct clk *exynos5_clks[] __initdata = { &exynos5_clk_sclk_hdmi27m, &exynos5_clk_sclk_hdmiphy, &clk_fout_bpll, + &clk_fout_bpll_div2, &clk_fout_cpll, + &clk_fout_mpll_div2, &exynos5_clk_armclk, }; @@ -1268,8 +1308,10 @@ void __init_or_cpufreq exynos5_setup_clocks(void) clk_fout_apll.ops = &exynos5_fout_apll_ops; clk_fout_bpll.rate = bpll; + clk_fout_bpll_div2.rate = bpll >> 1; clk_fout_cpll.rate = cpll; clk_fout_mpll.rate = mpll; + clk_fout_mpll_div2.rate = mpll >> 1; clk_fout_epll.rate = epll; clk_fout_vpll.rate = vpll; diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h index dba83e91f0f..b78b5f3ad9c 100644 --- a/arch/arm/mach-exynos/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h @@ -322,6 +322,8 @@ #define EXYNOS5_CLKSRC_CDREX EXYNOS_CLKREG(0x20200) #define EXYNOS5_CLKDIV_CDREX EXYNOS_CLKREG(0x20500) +#define EXYNOS5_PLL_DIV2_SEL EXYNOS_CLKREG(0x20A24) + #define EXYNOS5_EPLL_LOCK EXYNOS_CLKREG(0x10030) #define EXYNOS5_EPLLCON0_LOCKED_SHIFT (29) diff --git a/arch/arm/plat-samsung/include/plat/s5p-clock.h b/arch/arm/plat-samsung/include/plat/s5p-clock.h index 1de4b32f98e..8364b4bea8b 100644 --- a/arch/arm/plat-samsung/include/plat/s5p-clock.h +++ b/arch/arm/plat-samsung/include/plat/s5p-clock.h @@ -32,8 +32,10 @@ extern struct clk clk_48m; extern struct clk s5p_clk_27m; extern struct clk clk_fout_apll; extern struct clk clk_fout_bpll; +extern struct clk clk_fout_bpll_div2; extern struct clk clk_fout_cpll; extern struct clk clk_fout_mpll; +extern struct clk clk_fout_mpll_div2; extern struct clk clk_fout_epll; extern struct clk clk_fout_dpll; extern struct clk clk_fout_vpll; @@ -42,8 +44,10 @@ extern struct clk clk_vpll; extern struct clksrc_sources clk_src_apll; extern struct clksrc_sources clk_src_bpll; +extern struct clksrc_sources clk_src_bpll_fout; extern struct clksrc_sources clk_src_cpll; extern struct clksrc_sources clk_src_mpll; +extern struct clksrc_sources clk_src_mpll_fout; extern struct clksrc_sources clk_src_epll; extern struct clksrc_sources clk_src_dpll; diff --git a/arch/arm/plat-samsung/s5p-clock.c b/arch/arm/plat-samsung/s5p-clock.c index 41d3dfd5ddd..031a61899be 100644 --- a/arch/arm/plat-samsung/s5p-clock.c +++ b/arch/arm/plat-samsung/s5p-clock.c @@ -67,6 +67,11 @@ struct clk clk_fout_bpll = { .id = -1, }; +struct clk clk_fout_bpll_div2 = { + .name = "fout_bpll_div2", + .id = -1, +}; + /* CPLL clock output */ struct clk clk_fout_cpll = { @@ -82,6 +87,11 @@ struct clk clk_fout_mpll = { .id = -1, }; +struct clk clk_fout_mpll_div2 = { + .name = "fout_mpll_div2", + .id = -1, +}; + /* EPLL clock output */ struct clk clk_fout_epll = { .name = "fout_epll", @@ -125,6 +135,16 @@ struct clksrc_sources clk_src_bpll = { .nr_sources = ARRAY_SIZE(clk_src_bpll_list), }; +static struct clk *clk_src_bpll_fout_list[] = { + [0] = &clk_fout_bpll_div2, + [1] = &clk_fout_bpll, +}; + +struct clksrc_sources clk_src_bpll_fout = { + .sources = clk_src_bpll_fout_list, + .nr_sources = ARRAY_SIZE(clk_src_bpll_fout_list), +}; + /* Possible clock sources for CPLL Mux */ static struct clk *clk_src_cpll_list[] = { [0] = &clk_fin_cpll, @@ -147,6 +167,16 @@ struct clksrc_sources clk_src_mpll = { .nr_sources = ARRAY_SIZE(clk_src_mpll_list), }; +static struct clk *clk_src_mpll_fout_list[] = { + [0] = &clk_fout_mpll_div2, + [1] = &clk_fout_mpll, +}; + +struct clksrc_sources clk_src_mpll_fout = { + .sources = clk_src_mpll_fout_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_fout_list), +}; + /* Possible clock sources for EPLL Mux */ static struct clk *clk_src_epll_list[] = { [0] = &clk_fin_epll, -- cgit v1.2.3-70-g09d2 From 9ee6af9c3fad48cddc0684d0c77d3ea1329e10a1 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 15 May 2012 15:47:40 +0900 Subject: ARM: EXYNOS: Remove a new bus_type instance for EXYNOS5 A seperate bus_type instance is not required for EXYNOS5. The existing bus_type instance used with EXYNOS4 is sufficient for both EXYNOS4 and EXYNOS5. This also solves issue of uninitialized usage of exynos4_subsys in EXYNOS4 power management code that is reused for EXYNOS5 also. In addition to that, the existing exynos4_subsys bus_type is renamed to exynos_subsys to indicate that it is reused on both EXYNOS4 and EXYNOS5 platforms. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 27 ++++++--------------------- arch/arm/mach-exynos/pm.c | 2 +- arch/arm/plat-samsung/include/plat/cpu.h | 2 +- 3 files changed, 8 insertions(+), 23 deletions(-) (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index eff4446f5e3..3302a8dca4e 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -565,30 +565,18 @@ void __init exynos5_init_irq(void) s5p_init_irq(NULL, 0); } -struct bus_type exynos4_subsys = { - .name = "exynos4-core", - .dev_name = "exynos4-core", -}; - -struct bus_type exynos5_subsys = { - .name = "exynos5-core", - .dev_name = "exynos5-core", +struct bus_type exynos_subsys = { + .name = "exynos-core", + .dev_name = "exynos-core", }; static struct device exynos4_dev = { - .bus = &exynos4_subsys, -}; - -static struct device exynos5_dev = { - .bus = &exynos5_subsys, + .bus = &exynos_subsys, }; static int __init exynos_core_init(void) { - if (soc_is_exynos5250()) - return subsys_system_register(&exynos5_subsys, NULL); - else - return subsys_system_register(&exynos4_subsys, NULL); + return subsys_system_register(&exynos_subsys, NULL); } core_initcall(exynos_core_init); @@ -675,10 +663,7 @@ static int __init exynos_init(void) { printk(KERN_INFO "EXYNOS: Initializing architecture\n"); - if (soc_is_exynos5250()) - return device_register(&exynos5_dev); - else - return device_register(&exynos4_dev); + return device_register(&exynos4_dev); } /* uart registration process */ diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 428cfeb5772..7164aa95ad9 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -275,7 +275,7 @@ static void exynos4_restore_pll(void) static struct subsys_interface exynos4_pm_interface = { .name = "exynos4_pm", - .subsys = &exynos4_subsys, + .subsys = &exynos_subsys, .add_dev = exynos4_pm_add, }; diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 787ceaca0be..0721293fad6 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -202,7 +202,7 @@ extern struct bus_type s3c2443_subsys; extern struct bus_type s3c6410_subsys; extern struct bus_type s5p64x0_subsys; extern struct bus_type s5pv210_subsys; -extern struct bus_type exynos4_subsys; +extern struct bus_type exynos_subsys; extern void (*s5pc1xx_idle)(void); -- cgit v1.2.3-70-g09d2 From 0e944e276c7ebcb880d20f6e9255f596c85fc767 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 20 May 2012 01:01:35 +0900 Subject: ARM: S3C24XX: add support for second irq set of S3C2416 The S3C2416 has a separate second interrupt register-set to support additional irqs. This patch adds the necessary constants and registers the irq handlers for it. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/include/mach/irqs.h | 15 ++++- arch/arm/mach-s3c24xx/irq-s3c2416.c | 98 ++++++++++++++++++++++++++++ arch/arm/mach-s3c24xx/s3c2416.c | 1 + arch/arm/plat-samsung/include/plat/s3c2416.h | 3 + 4 files changed, 116 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-samsung') diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h index e53b2177319..b7a9f4d469e 100644 --- a/arch/arm/mach-s3c24xx/include/mach/irqs.h +++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h @@ -134,6 +134,17 @@ #define IRQ_S32416_WDT S3C2410_IRQSUB(27) #define IRQ_S32416_AC97 S3C2410_IRQSUB(28) +/* second interrupt-register of s3c2416/s3c2450 */ + +#define S3C2416_IRQ(x) S3C2410_IRQ((x) + 54 + 29) +#define IRQ_S3C2416_2D S3C2416_IRQ(0) +#define IRQ_S3C2416_IIC1 S3C2416_IRQ(1) +#define IRQ_S3C2416_RESERVED2 S3C2416_IRQ(2) +#define IRQ_S3C2416_RESERVED3 S3C2416_IRQ(3) +#define IRQ_S3C2416_PCM0 S3C2416_IRQ(4) +#define IRQ_S3C2416_PCM1 S3C2416_IRQ(5) +#define IRQ_S3C2416_I2S0 S3C2416_IRQ(6) +#define IRQ_S3C2416_I2S1 S3C2416_IRQ(7) /* extra irqs for s3c2440 */ @@ -175,7 +186,9 @@ #define IRQ_S3C2443_WDT S3C2410_IRQSUB(27) #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28) -#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) +#if defined(CONFIG_CPU_S3C2416) +#define NR_IRQS (IRQ_S3C2416_I2S1 + 1) +#elif defined(CONFIG_CPU_S3C2443) #define NR_IRQS (IRQ_S3C2443_AC97+1) #else #define NR_IRQS (IRQ_S3C2440_AC97+1) diff --git a/arch/arm/mach-s3c24xx/irq-s3c2416.c b/arch/arm/mach-s3c24xx/irq-s3c2416.c index fd49f35e448..23ec97370f3 100644 --- a/arch/arm/mach-s3c24xx/irq-s3c2416.c +++ b/arch/arm/mach-s3c24xx/irq-s3c2416.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,43 @@ static struct irq_chip s3c2416_irq_uart3 = { .irq_ack = s3c2416_irq_uart3_ack, }; +/* second interrupt register */ + +static inline void s3c2416_irq_ack_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + + __raw_writel(bitval, S3C2416_SRCPND2); + __raw_writel(bitval, S3C2416_INTPND2); +} + +static void s3c2416_irq_mask_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + unsigned long mask; + + mask = __raw_readl(S3C2416_INTMSK2); + mask |= bitval; + __raw_writel(mask, S3C2416_INTMSK2); +} + +static void s3c2416_irq_unmask_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + unsigned long mask; + + mask = __raw_readl(S3C2416_INTMSK2); + mask &= ~bitval; + __raw_writel(mask, S3C2416_INTMSK2); +} + +struct irq_chip s3c2416_irq_second = { + .irq_ack = s3c2416_irq_ack_second, + .irq_mask = s3c2416_irq_mask_second, + .irq_unmask = s3c2416_irq_unmask_second, +}; + + /* IRQ initialisation code */ static int __init s3c2416_add_sub(unsigned int base, @@ -213,6 +251,42 @@ static int __init s3c2416_add_sub(unsigned int base, return 0; } +static void __init s3c2416_irq_add_second(void) +{ + unsigned long pend; + unsigned long last; + int irqno; + int i; + + /* first, clear all interrupts pending... */ + last = 0; + for (i = 0; i < 4; i++) { + pend = __raw_readl(S3C2416_INTPND2); + + if (pend == 0 || pend == last) + break; + + __raw_writel(pend, S3C2416_SRCPND2); + __raw_writel(pend, S3C2416_INTPND2); + printk(KERN_INFO "irq: clearing pending status %08x\n", + (int)pend); + last = pend; + } + + for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { + switch (irqno) { + case IRQ_S3C2416_RESERVED2: + case IRQ_S3C2416_RESERVED3: + /* no IRQ here */ + break; + default: + irq_set_chip_and_handler(irqno, &s3c2416_irq_second, + handle_edge_irq); + set_irq_flags(irqno, IRQF_VALID); + } + } +} + static int __init s3c2416_irq_add(struct device *dev, struct subsys_interface *sif) { @@ -232,6 +306,8 @@ static int __init s3c2416_irq_add(struct device *dev, &s3c2416_irq_wdtac97, IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + s3c2416_irq_add_second(); + return 0; } @@ -248,3 +324,25 @@ static int __init s3c2416_irq_init(void) arch_initcall(s3c2416_irq_init); +#ifdef CONFIG_PM +static struct sleep_save irq_save[] = { + SAVE_ITEM(S3C2416_INTMSK2), +}; + +int s3c2416_irq_suspend(void) +{ + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); + + return 0; +} + +void s3c2416_irq_resume(void) +{ + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); +} + +struct syscore_ops s3c2416_irq_syscore_ops = { + .suspend = s3c2416_irq_suspend, + .resume = s3c2416_irq_resume, +}; +#endif diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index 7743fade50d..ed5a95ece9e 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -106,6 +106,7 @@ int __init s3c2416_init(void) register_syscore_ops(&s3c2416_pm_syscore_ops); #endif register_syscore_ops(&s3c24xx_irq_syscore_ops); + register_syscore_ops(&s3c2416_irq_syscore_ops); return device_register(&s3c2416_dev); } diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h index de2b5bdc5eb..7178e338e25 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2416.h +++ b/arch/arm/plat-samsung/include/plat/s3c2416.h @@ -24,6 +24,9 @@ extern void s3c2416_init_clocks(int xtal); extern int s3c2416_baseclk_add(void); extern void s3c2416_restart(char mode, const char *cmd); + +extern struct syscore_ops s3c2416_irq_syscore_ops; + #else #define s3c2416_init_clocks NULL #define s3c2416_init_uarts NULL -- cgit v1.2.3-70-g09d2