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-s5p/Kconfig | 8 - arch/arm/plat-s5p/Makefile | 1 - arch/arm/plat-s5p/sysmmu.c | 313 ---------------------------- arch/arm/plat-samsung/include/plat/devs.h | 1 - arch/arm/plat-samsung/include/plat/sysmmu.h | 95 --------- 5 files changed, 418 deletions(-) delete mode 100644 arch/arm/plat-s5p/sysmmu.c delete mode 100644 arch/arm/plat-samsung/include/plat/sysmmu.h diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 96bea3202304..2c1193c59928 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -50,14 +50,6 @@ config S5P_PM Common code for power management support on S5P and newer SoCs Note: Do not select this for S5P6440 and S5P6450. -comment "System MMU" - -config S5P_SYSTEM_MMU - bool "S5P SYSTEM MMU" - depends on ARCH_EXYNOS4 - help - Say Y here if you want to enable System MMU - config S5P_SLEEP bool help diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 4bd824136659..4953d50707be 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -16,7 +16,6 @@ obj-y += clock.o obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o -obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.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/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c deleted file mode 100644 index c8bec9c7655d..000000000000 --- a/arch/arm/plat-s5p/sysmmu.c +++ /dev/null @@ -1,313 +0,0 @@ -/* linux/arch/arm/plat-s5p/sysmmu.c - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define CTRL_ENABLE 0x5 -#define CTRL_BLOCK 0x7 -#define CTRL_DISABLE 0x0 - -static struct device *dev; - -static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { - S5P_PAGE_FAULT_ADDR, - S5P_AR_FAULT_ADDR, - S5P_AW_FAULT_ADDR, - S5P_DEFAULT_SLAVE_ADDR, - S5P_AR_FAULT_ADDR, - S5P_AR_FAULT_ADDR, - S5P_AW_FAULT_ADDR, - S5P_AW_FAULT_ADDR -}; - -static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { - "PAGE FAULT", - "AR MULTI-HIT FAULT", - "AW MULTI-HIT FAULT", - "BUS ERROR", - "AR SECURITY PROTECTION FAULT", - "AR ACCESS PROTECTION FAULT", - "AW SECURITY PROTECTION FAULT", - "AW ACCESS PROTECTION FAULT" -}; - -static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])( - enum S5P_SYSMMU_INTERRUPT_TYPE itype, - unsigned long pgtable_base, - unsigned long fault_addr); - -/* - * If adjacent 2 bits are true, the system MMU is enabled. - * The system MMU is disabled, otherwise. - */ -static unsigned long sysmmu_states; - -static inline void set_sysmmu_active(sysmmu_ips ips) -{ - sysmmu_states |= 3 << (ips * 2); -} - -static inline void set_sysmmu_inactive(sysmmu_ips ips) -{ - sysmmu_states &= ~(3 << (ips * 2)); -} - -static inline int is_sysmmu_active(sysmmu_ips ips) -{ - return sysmmu_states & (3 << (ips * 2)); -} - -static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM]; - -static inline void sysmmu_block(sysmmu_ips ips) -{ - __raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL); - dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]); -} - -static inline void sysmmu_unblock(sysmmu_ips ips) -{ - __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); - dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]); -} - -static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips) -{ - __raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH); - dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]); -} - -static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd) -{ - if (unlikely(pgd == 0)) { - pgd = (unsigned long)ZERO_PAGE(0); - __raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */ - } else { - __raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */ - } - - __raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR); - - dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n", - sysmmu_ips_name[ips], pgd); - __sysmmu_tlb_invalidate(ips); -} - -void sysmmu_set_fault_handler(sysmmu_ips ips, - int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, - unsigned long pgtable_base, - unsigned long fault_addr)) -{ - BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM))); - fault_handlers[ips] = handler; -} - -static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id) -{ - /* SYSMMU is in blocked when interrupt occurred. */ - unsigned long base = 0; - sysmmu_ips ips = (sysmmu_ips)dev_id; - enum S5P_SYSMMU_INTERRUPT_TYPE itype; - - itype = (enum S5P_SYSMMU_INTERRUPT_TYPE) - __ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS)); - - BUG_ON(!((itype >= 0) && (itype < 8))); - - dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype], - sysmmu_ips_name[ips]); - - if (fault_handlers[ips]) { - unsigned long addr; - - base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR); - addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]); - - if (fault_handlers[ips](itype, base, addr)) { - __raw_writel(1 << itype, - sysmmusfrs[ips] + S5P_INT_CLEAR); - dev_notice(dev, "%s from %s is resolved." - " Retrying translation.\n", - sysmmu_fault_name[itype], sysmmu_ips_name[ips]); - } else { - base = 0; - } - } - - sysmmu_unblock(ips); - - if (!base) - dev_notice(dev, "%s from %s is not handled.\n", - sysmmu_fault_name[itype], sysmmu_ips_name[ips]); - - return IRQ_HANDLED; -} - -void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd) -{ - if (is_sysmmu_active(ips)) { - sysmmu_block(ips); - __sysmmu_set_ptbase(ips, pgd); - sysmmu_unblock(ips); - } else { - dev_dbg(dev, "%s is disabled. " - "Skipping initializing page table base.\n", - sysmmu_ips_name[ips]); - } -} - -void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd) -{ - if (!is_sysmmu_active(ips)) { - sysmmu_clk_enable(ips); - - __sysmmu_set_ptbase(ips, pgd); - - __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); - - set_sysmmu_active(ips); - dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]); - } else { - dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]); - } -} - -void s5p_sysmmu_disable(sysmmu_ips ips) -{ - if (is_sysmmu_active(ips)) { - __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); - set_sysmmu_inactive(ips); - sysmmu_clk_disable(ips); - dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]); - } else { - dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]); - } -} - -void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips) -{ - if (is_sysmmu_active(ips)) { - sysmmu_block(ips); - __sysmmu_tlb_invalidate(ips); - sysmmu_unblock(ips); - } else { - dev_dbg(dev, "%s is disabled. " - "Skipping invalidating TLB.\n", sysmmu_ips_name[ips]); - } -} - -static int s5p_sysmmu_probe(struct platform_device *pdev) -{ - int i, ret; - struct resource *res, *mem; - - dev = &pdev->dev; - - for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) { - int irq; - - sysmmu_clk_init(dev, i); - sysmmu_clk_disable(i); - - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) { - dev_err(dev, "Failed to get the resource of %s.\n", - sysmmu_ips_name[i]); - ret = -ENODEV; - goto err_res; - } - - mem = request_mem_region(res->start, resource_size(res), - pdev->name); - if (!mem) { - dev_err(dev, "Failed to request the memory region of %s.\n", - sysmmu_ips_name[i]); - ret = -EBUSY; - goto err_res; - } - - sysmmusfrs[i] = ioremap(res->start, resource_size(res)); - if (!sysmmusfrs[i]) { - dev_err(dev, "Failed to ioremap() for %s.\n", - sysmmu_ips_name[i]); - ret = -ENXIO; - goto err_reg; - } - - irq = platform_get_irq(pdev, i); - if (irq <= 0) { - dev_err(dev, "Failed to get the IRQ resource of %s.\n", - sysmmu_ips_name[i]); - ret = -ENOENT; - goto err_map; - } - - if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED, - pdev->name, (void *)i)) { - dev_err(dev, "Failed to request IRQ for %s.\n", - sysmmu_ips_name[i]); - ret = -ENOENT; - goto err_map; - } - } - - return 0; - -err_map: - iounmap(sysmmusfrs[i]); -err_reg: - release_mem_region(mem->start, resource_size(mem)); -err_res: - return ret; -} - -static int s5p_sysmmu_remove(struct platform_device *pdev) -{ - return 0; -} -int s5p_sysmmu_runtime_suspend(struct device *dev) -{ - return 0; -} - -int s5p_sysmmu_runtime_resume(struct device *dev) -{ - return 0; -} - -const struct dev_pm_ops s5p_sysmmu_pm_ops = { - .runtime_suspend = s5p_sysmmu_runtime_suspend, - .runtime_resume = s5p_sysmmu_runtime_resume, -}; - -static struct platform_driver s5p_sysmmu_driver = { - .probe = s5p_sysmmu_probe, - .remove = s5p_sysmmu_remove, - .driver = { - .owner = THIS_MODULE, - .name = "s5p-sysmmu", - .pm = &s5p_sysmmu_pm_ops, - } -}; - -static int __init s5p_sysmmu_init(void) -{ - return platform_driver_register(&s5p_sysmmu_driver); -} -arch_initcall(s5p_sysmmu_init); diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 2155d4af62a3..4067d1dd7f1c 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 5fe8ee01a5ba..000000000000 --- 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 From bca10b906f8d2e4f177bff047b9d623941e454f7 Mon Sep 17 00:00:00 2001 From: KyongHo Cho Date: Wed, 4 Apr 2012 09:23:02 -0700 Subject: ARM: EXYNOS: Change System MMU platform device definitions Handling System MMUs with an identifier is not flexible to manage System MMU platform devices because of the following reasons: 1. A device driver which needs to handle System MMU must know the ID. 2. A System MMU may not present in some implementations of Exynos family. 3. Handling System MMU with IOMMU API does not require an ID. This patch is the result of removing ID of System MMUs. Instead, a device driver that needs to handle its System MMU must use IOMMU API while its descriptor of platform device is given. This patch also includes the following enhancements: - A System MMU device becomes a child if its power domain device. - clkdev Signed-off-by: KyongHo Cho Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 10 +- arch/arm/mach-exynos/Makefile | 2 +- arch/arm/mach-exynos/clock-exynos4.c | 79 ++-- arch/arm/mach-exynos/clock-exynos4.h | 2 + arch/arm/mach-exynos/clock-exynos4210.c | 11 + arch/arm/mach-exynos/clock-exynos4212.c | 28 +- arch/arm/mach-exynos/clock-exynos5.c | 90 +++++ arch/arm/mach-exynos/dev-sysmmu.c | 457 +++++++++++++----------- arch/arm/mach-exynos/include/mach/irqs.h | 25 +- arch/arm/mach-exynos/include/mach/map.h | 38 ++ arch/arm/mach-exynos/include/mach/regs-clock.h | 5 + arch/arm/mach-exynos/include/mach/regs-sysmmu.h | 28 -- arch/arm/mach-exynos/include/mach/sysmmu.h | 88 +++-- arch/arm/mach-exynos/mach-armlex4210.c | 1 - arch/arm/mach-exynos/mach-smdkv310.c | 1 - 15 files changed, 529 insertions(+), 336 deletions(-) delete mode 100644 arch/arm/mach-exynos/include/mach/regs-sysmmu.h diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 0491ceef1cda..801c738d8f0e 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -85,10 +85,10 @@ config EXYNOS4_SETUP_FIMD0 help Common setup code for FIMD0. -config EXYNOS4_DEV_SYSMMU +config EXYNOS_DEV_SYSMMU bool help - Common setup code for SYSTEM MMU in EXYNOS4 + Common setup code for SYSTEM MMU in EXYNOS platforms config EXYNOS4_DEV_DWMCI bool @@ -200,12 +200,12 @@ config MACH_SMDKV310 select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC3 select SAMSUNG_DEV_BACKLIGHT + select EXYNOS_DEV_SYSMMU select EXYNOS4_DEV_AHCI select SAMSUNG_DEV_KEYPAD select EXYNOS4_DEV_DMA select SAMSUNG_DEV_PWM select EXYNOS4_DEV_USB_OHCI - select EXYNOS4_DEV_SYSMMU select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_KEYPAD @@ -224,7 +224,6 @@ config MACH_ARMLEX4210 select S3C_DEV_HSMMC3 select EXYNOS4_DEV_AHCI select EXYNOS4_DEV_DMA - select EXYNOS4_DEV_SYSMMU select EXYNOS4_SETUP_SDHCI help Machine support for Samsung ARMLEX4210 based on EXYNOS4210 @@ -251,6 +250,7 @@ config MACH_UNIVERSAL_C210 select S5P_DEV_MFC select S5P_DEV_ONENAND select S5P_DEV_TV + select EXYNOS_DEV_SYSMMU select EXYNOS4_DEV_DMA select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_I2C1 @@ -322,6 +322,7 @@ config MACH_ORIGEN select S5P_DEV_USB_EHCI select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_PWM + select EXYNOS_DEV_SYSMMU select EXYNOS4_DEV_DMA select EXYNOS4_DEV_USB_OHCI select EXYNOS4_SETUP_FIMD0 @@ -345,6 +346,7 @@ config MACH_SMDK4212 select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_KEYPAD select SAMSUNG_DEV_PWM + select EXYNOS_DEV_SYSMMU select EXYNOS4_DEV_DMA select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_I2C3 diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 8631840d1b5e..272625231c73 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -50,7 +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_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o +obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index df54c2a92225..428731197471 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -168,7 +168,7 @@ static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable) return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable); } -static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable) +int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable); } @@ -198,6 +198,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable) return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable); } +int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable); +} + static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); @@ -678,61 +683,55 @@ static struct clk exynos4_init_clocks_off[] = { .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 14), }, { - .name = "SYSMMU_MDMA", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), + .enable = exynos4_clk_ip_mfc_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), + .enable = exynos4_clk_ip_mfc_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), + .enable = exynos4_clk_ip_tv_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), + .enable = exynos4_clk_ip_cam_ctrl, + .ctrlbit = (1 << 11), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), .enable = exynos4_clk_ip_image_ctrl, - .ctrlbit = (1 << 5), + .ctrlbit = (1 << 4), }, { - .name = "SYSMMU_FIMC0", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimc0, 5), .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit = (1 << 7), }, { - .name = "SYSMMU_FIMC1", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimc1, 6), .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit = (1 << 8), }, { - .name = "SYSMMU_FIMC2", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimc2, 7), .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit = (1 << 9), }, { - .name = "SYSMMU_FIMC3", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimc3, 8), .enable = exynos4_clk_ip_cam_ctrl, .ctrlbit = (1 << 10), }, { - .name = "SYSMMU_JPEG", - .enable = exynos4_clk_ip_cam_ctrl, - .ctrlbit = (1 << 11), - }, { - .name = "SYSMMU_FIMD0", + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimd0, 10), .enable = exynos4_clk_ip_lcd0_ctrl, .ctrlbit = (1 << 4), - }, { - .name = "SYSMMU_FIMD1", - .enable = exynos4_clk_ip_lcd1_ctrl, - .ctrlbit = (1 << 4), - }, { - .name = "SYSMMU_PCIe", - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 18), - }, { - .name = "SYSMMU_G2D", - .enable = exynos4_clk_ip_image_ctrl, - .ctrlbit = (1 << 3), - }, { - .name = "SYSMMU_ROTATOR", - .enable = exynos4_clk_ip_image_ctrl, - .ctrlbit = (1 << 4), - }, { - .name = "SYSMMU_TV", - .enable = exynos4_clk_ip_tv_ctrl, - .ctrlbit = (1 << 4), - }, { - .name = "SYSMMU_MFC_L", - .enable = exynos4_clk_ip_mfc_ctrl, - .ctrlbit = (1 << 1), - }, { - .name = "SYSMMU_MFC_R", - .enable = exynos4_clk_ip_mfc_ctrl, - .ctrlbit = (1 << 2), } }; diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h index cb71c29c14d1..28a119701182 100644 --- a/arch/arm/mach-exynos/clock-exynos4.h +++ b/arch/arm/mach-exynos/clock-exynos4.h @@ -26,5 +26,7 @@ extern struct clk *exynos4_clkset_group_list[]; extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); +extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable); +extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable); #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c index 3b131e4b6ef5..b8689ff60baf 100644 --- a/arch/arm/mach-exynos/clock-exynos4210.c +++ b/arch/arm/mach-exynos/clock-exynos4210.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "common.h" #include "clock-exynos4.h" @@ -94,6 +95,16 @@ static struct clk init_clocks_off[] = { .devname = "exynos4-fb.1", .enable = exynos4_clk_ip_lcd1_ctrl, .ctrlbit = (1 << 0), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), + .enable = exynos4_clk_ip_image_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11), + .enable = exynos4_clk_ip_lcd1_ctrl, + .ctrlbit = (1 << 4), }, }; diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c index 3ecc01e06f74..98823120570e 100644 --- a/arch/arm/mach-exynos/clock-exynos4212.c +++ b/arch/arm/mach-exynos/clock-exynos4212.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "common.h" #include "clock-exynos4.h" @@ -39,6 +40,16 @@ static struct sleep_save exynos4212_clock_save[] = { }; #endif +static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable); +} + +static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable); +} + static struct clk *clk_src_mpll_user_list[] = { [0] = &clk_fin_mpll, [1] = &exynos4_clk_mout_mpll.clk, @@ -66,7 +77,22 @@ static struct clksrc_clk clksrcs[] = { }; static struct clk init_clocks_off[] = { - /* nothing here yet */ + { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), + .enable = exynos4_clk_ip_dmc_ctrl, + .ctrlbit = (1 << 24), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), + .enable = exynos4212_clk_ip_isp0_ctrl, + .ctrlbit = (7 << 8), + }, { + .name = SYSMMU_CLOCK_NAME2, + .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), + .enable = exynos4212_clk_ip_isp1_ctrl, + .ctrlbit = (1 << 4), + } }; #ifdef CONFIG_PM_SLEEP diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index d013982d0f8e..3320ad140ebe 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -82,6 +82,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable) return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable); } +static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable); +} + static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable); @@ -127,6 +132,21 @@ static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable) return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable); } +static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable); +} + +static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable); +} + +static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable); +} + /* Core list of CMU_CPU side */ static struct clksrc_clk exynos5_clk_mout_apll = { @@ -630,6 +650,76 @@ static struct clk exynos5_init_clocks_off[] = { .parent = &exynos5_clk_aclk_66.clk, .enable = exynos5_clk_ip_peric_ctrl, .ctrlbit = (1 << 14), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0), + .enable = &exynos5_clk_ip_mfc_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1), + .enable = &exynos5_clk_ip_mfc_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(tv, 2), + .enable = &exynos5_clk_ip_disp1_ctrl, + .ctrlbit = (1 << 9) + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3), + .enable = &exynos5_clk_ip_gen_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(rot, 4), + .enable = &exynos5_clk_ip_gen_ctrl, + .ctrlbit = (1 << 6) + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(gsc0, 5), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(gsc1, 6), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(gsc2, 7), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(gsc3, 8), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), + .enable = &exynos5_clk_ip_isp0_ctrl, + .ctrlbit = (0x3F << 8), + }, { + .name = SYSMMU_CLOCK_NAME2, + .devname = SYSMMU_CLOCK_DEVNAME(isp, 9), + .enable = &exynos5_clk_ip_isp1_ctrl, + .ctrlbit = (0xF << 4), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(camif0, 12), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 11), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(camif1, 13), + .enable = &exynos5_clk_ip_gscl_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = SYSMMU_CLOCK_NAME, + .devname = SYSMMU_CLOCK_DEVNAME(2d, 14), + .enable = &exynos5_clk_ip_acp_ctrl, + .ctrlbit = (1 << 7) } }; diff --git a/arch/arm/mach-exynos/dev-sysmmu.c b/arch/arm/mach-exynos/dev-sysmmu.c index 781563fcb156..c5b1ea301df0 100644 --- a/arch/arm/mach-exynos/dev-sysmmu.c +++ b/arch/arm/mach-exynos/dev-sysmmu.c @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-exynos4/dev-sysmmu.c +/* linux/arch/arm/mach-exynos/dev-sysmmu.c * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS4 - System MMU support + * EXYNOS - System MMU 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 @@ -12,222 +12,263 @@ #include #include -#include + +#include #include #include #include -#include - -/* These names must be equal to the clock names in mach-exynos4/clock.c */ -const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = { - "SYSMMU_MDMA" , - "SYSMMU_SSS" , - "SYSMMU_FIMC0" , - "SYSMMU_FIMC1" , - "SYSMMU_FIMC2" , - "SYSMMU_FIMC3" , - "SYSMMU_JPEG" , - "SYSMMU_FIMD0" , - "SYSMMU_FIMD1" , - "SYSMMU_PCIe" , - "SYSMMU_G2D" , - "SYSMMU_ROTATOR", - "SYSMMU_MDMA2" , - "SYSMMU_TV" , - "SYSMMU_MFC_L" , - "SYSMMU_MFC_R" , -}; -static struct resource exynos4_sysmmu_resource[] = { - [0] = { - .start = EXYNOS4_PA_SYSMMU_MDMA, - .end = EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_SYSMMU_MDMA0_0, - .end = IRQ_SYSMMU_MDMA0_0, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = EXYNOS4_PA_SYSMMU_SSS, - .end = EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = IRQ_SYSMMU_SSS_0, - .end = IRQ_SYSMMU_SSS_0, - .flags = IORESOURCE_IRQ, - }, - [4] = { - .start = EXYNOS4_PA_SYSMMU_FIMC0, - .end = EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [5] = { - .start = IRQ_SYSMMU_FIMC0_0, - .end = IRQ_SYSMMU_FIMC0_0, - .flags = IORESOURCE_IRQ, - }, - [6] = { - .start = EXYNOS4_PA_SYSMMU_FIMC1, - .end = EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [7] = { - .start = IRQ_SYSMMU_FIMC1_0, - .end = IRQ_SYSMMU_FIMC1_0, - .flags = IORESOURCE_IRQ, - }, - [8] = { - .start = EXYNOS4_PA_SYSMMU_FIMC2, - .end = EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [9] = { - .start = IRQ_SYSMMU_FIMC2_0, - .end = IRQ_SYSMMU_FIMC2_0, - .flags = IORESOURCE_IRQ, - }, - [10] = { - .start = EXYNOS4_PA_SYSMMU_FIMC3, - .end = EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [11] = { - .start = IRQ_SYSMMU_FIMC3_0, - .end = IRQ_SYSMMU_FIMC3_0, - .flags = IORESOURCE_IRQ, - }, - [12] = { - .start = EXYNOS4_PA_SYSMMU_JPEG, - .end = EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [13] = { - .start = IRQ_SYSMMU_JPEG_0, - .end = IRQ_SYSMMU_JPEG_0, - .flags = IORESOURCE_IRQ, - }, - [14] = { - .start = EXYNOS4_PA_SYSMMU_FIMD0, - .end = EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [15] = { - .start = IRQ_SYSMMU_LCD0_M0_0, - .end = IRQ_SYSMMU_LCD0_M0_0, - .flags = IORESOURCE_IRQ, - }, - [16] = { - .start = EXYNOS4_PA_SYSMMU_FIMD1, - .end = EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [17] = { - .start = IRQ_SYSMMU_LCD1_M1_0, - .end = IRQ_SYSMMU_LCD1_M1_0, - .flags = IORESOURCE_IRQ, - }, - [18] = { - .start = EXYNOS4_PA_SYSMMU_PCIe, - .end = EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [19] = { - .start = IRQ_SYSMMU_PCIE_0, - .end = IRQ_SYSMMU_PCIE_0, - .flags = IORESOURCE_IRQ, - }, - [20] = { - .start = EXYNOS4_PA_SYSMMU_G2D, - .end = EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [21] = { - .start = IRQ_SYSMMU_2D_0, - .end = IRQ_SYSMMU_2D_0, - .flags = IORESOURCE_IRQ, - }, - [22] = { - .start = EXYNOS4_PA_SYSMMU_ROTATOR, - .end = EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [23] = { - .start = IRQ_SYSMMU_ROTATOR_0, - .end = IRQ_SYSMMU_ROTATOR_0, - .flags = IORESOURCE_IRQ, - }, - [24] = { - .start = EXYNOS4_PA_SYSMMU_MDMA2, - .end = EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [25] = { - .start = IRQ_SYSMMU_MDMA1_0, - .end = IRQ_SYSMMU_MDMA1_0, - .flags = IORESOURCE_IRQ, - }, - [26] = { - .start = EXYNOS4_PA_SYSMMU_TV, - .end = EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [27] = { - .start = IRQ_SYSMMU_TV_M0_0, - .end = IRQ_SYSMMU_TV_M0_0, - .flags = IORESOURCE_IRQ, - }, - [28] = { - .start = EXYNOS4_PA_SYSMMU_MFC_L, - .end = EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [29] = { - .start = IRQ_SYSMMU_MFC_M0_0, - .end = IRQ_SYSMMU_MFC_M0_0, - .flags = IORESOURCE_IRQ, - }, - [30] = { - .start = EXYNOS4_PA_SYSMMU_MFC_R, - .end = EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [31] = { - .start = IRQ_SYSMMU_MFC_M1_0, - .end = IRQ_SYSMMU_MFC_M1_0, - .flags = IORESOURCE_IRQ, - }, -}; +static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32); + +#define SYSMMU_PLATFORM_DEVICE(ipname, devid) \ +static struct sysmmu_platform_data platdata_##ipname = { \ + .dbgname = #ipname, \ +}; \ +struct platform_device SYSMMU_PLATDEV(ipname) = \ +{ \ + .name = SYSMMU_DEVNAME_BASE, \ + .id = devid, \ + .dev = { \ + .dma_mask = &exynos_sysmmu_dma_mask, \ + .coherent_dma_mask = DMA_BIT_MASK(32), \ + .platform_data = &platdata_##ipname, \ + }, \ +} + +SYSMMU_PLATFORM_DEVICE(mfc_l, 0); +SYSMMU_PLATFORM_DEVICE(mfc_r, 1); +SYSMMU_PLATFORM_DEVICE(tv, 2); +SYSMMU_PLATFORM_DEVICE(jpeg, 3); +SYSMMU_PLATFORM_DEVICE(rot, 4); +SYSMMU_PLATFORM_DEVICE(fimc0, 5); /* fimc* and gsc* exist exclusively */ +SYSMMU_PLATFORM_DEVICE(fimc1, 6); +SYSMMU_PLATFORM_DEVICE(fimc2, 7); +SYSMMU_PLATFORM_DEVICE(fimc3, 8); +SYSMMU_PLATFORM_DEVICE(gsc0, 5); +SYSMMU_PLATFORM_DEVICE(gsc1, 6); +SYSMMU_PLATFORM_DEVICE(gsc2, 7); +SYSMMU_PLATFORM_DEVICE(gsc3, 8); +SYSMMU_PLATFORM_DEVICE(isp, 9); +SYSMMU_PLATFORM_DEVICE(fimd0, 10); +SYSMMU_PLATFORM_DEVICE(fimd1, 11); +SYSMMU_PLATFORM_DEVICE(camif0, 12); +SYSMMU_PLATFORM_DEVICE(camif1, 13); +SYSMMU_PLATFORM_DEVICE(2d, 14); + +#define SYSMMU_RESOURCE_NAME(core, ipname) sysmmures_##core##_##ipname + +#define SYSMMU_RESOURCE(core, ipname) \ + static struct resource SYSMMU_RESOURCE_NAME(core, ipname)[] __initdata = + +#define DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ + DEFINE_RES_MEM_NAMED(core##_PA_SYSMMU_##mem, SZ_4K, #mem), \ + DEFINE_RES_IRQ_NAMED(core##_IRQ_SYSMMU_##irq##_0, #mem) + +#define SYSMMU_RESOURCE_DEFINE(core, ipname, mem, irq) \ + SYSMMU_RESOURCE(core, ipname) { \ + DEFINE_SYSMMU_RESOURCE(core, mem, irq) \ + } -struct platform_device exynos4_device_sysmmu = { - .name = "s5p-sysmmu", - .id = 32, - .num_resources = ARRAY_SIZE(exynos4_sysmmu_resource), - .resource = exynos4_sysmmu_resource, +struct sysmmu_resource_map { + struct platform_device *pdev; + struct resource *res; + u32 rnum; + struct device *pdd; + char *clocknames; }; -EXPORT_SYMBOL(exynos4_device_sysmmu); -static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM]; -void sysmmu_clk_init(struct device *dev, sysmmu_ips ips) -{ - sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]); - if (IS_ERR(sysmmu_clk[ips])) - sysmmu_clk[ips] = NULL; - else - clk_put(sysmmu_clk[ips]); +#define SYSMMU_RESOURCE_MAPPING(core, ipname, resname) { \ + .pdev = &SYSMMU_PLATDEV(ipname), \ + .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ + .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ + .clocknames = SYSMMU_CLOCK_NAME, \ } -void sysmmu_clk_enable(sysmmu_ips ips) -{ - if (sysmmu_clk[ips]) - clk_enable(sysmmu_clk[ips]); +#define SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) { \ + .pdev = &SYSMMU_PLATDEV(ipname), \ + .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ + .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ + .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \ +} + +#ifdef CONFIG_EXYNOS_DEV_PD +#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) { \ + .pdev = &SYSMMU_PLATDEV(ipname), \ + .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ + .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ + .clocknames = SYSMMU_CLOCK_NAME, \ + .pdd = &exynos##core##_device_pd[pd].dev, \ +} + +#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) {\ + .pdev = &SYSMMU_PLATDEV(ipname), \ + .res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \ + .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\ + .clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \ + .pdd = &exynos##core##_device_pd[pd].dev, \ } +#else +#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) \ + SYSMMU_RESOURCE_MAPPING(core, ipname, resname) +#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) \ + SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) + +#endif /* CONFIG_EXYNOS_DEV_PD */ + +#ifdef CONFIG_ARCH_EXYNOS4 +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc0, FIMC0, FIMC0); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc1, FIMC1, FIMC1); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc2, FIMC2, FIMC2); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc3, FIMC3, FIMC3); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, jpeg, JPEG, JPEG); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d, G2D, 2D); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, tv, TV, TV_M0); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d_acp, 2D_ACP, 2D); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, rot, ROTATOR, ROTATOR); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd0, FIMD0, LCD0_M0); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd1, FIMD1, LCD1_M1); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite0, FIMC_LITE0, FIMC_LITE0); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite1, FIMC_LITE1, FIMC_LITE1); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_r, MFC_R, MFC_M0); +SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_l, MFC_L, MFC_M1); +SYSMMU_RESOURCE(EXYNOS4, isp) { + DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_ISP, FIMC_ISP), + DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_DRC, FIMC_DRC), + DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_FD, FIMC_FD), + DEFINE_SYSMMU_RESOURCE(EXYNOS4, ISPCPU, FIMC_CX), +}; + +static struct sysmmu_resource_map sysmmu_resmap4[] __initdata = { + SYSMMU_RESOURCE_MAPPING_PD(4, fimc0, fimc0, PD_CAM), + SYSMMU_RESOURCE_MAPPING_PD(4, fimc1, fimc1, PD_CAM), + SYSMMU_RESOURCE_MAPPING_PD(4, fimc2, fimc2, PD_CAM), + SYSMMU_RESOURCE_MAPPING_PD(4, fimc3, fimc3, PD_CAM), + SYSMMU_RESOURCE_MAPPING_PD(4, tv, tv, PD_TV), + SYSMMU_RESOURCE_MAPPING_PD(4, mfc_r, mfc_r, PD_MFC), + SYSMMU_RESOURCE_MAPPING_PD(4, mfc_l, mfc_l, PD_MFC), + SYSMMU_RESOURCE_MAPPING_PD(4, rot, rot, PD_LCD0), + SYSMMU_RESOURCE_MAPPING_PD(4, jpeg, jpeg, PD_CAM), + SYSMMU_RESOURCE_MAPPING_PD(4, fimd0, fimd0, PD_LCD0), +}; + +static struct sysmmu_resource_map sysmmu_resmap4210[] __initdata = { + SYSMMU_RESOURCE_MAPPING_PD(4, 2d, 2d, PD_LCD0), + SYSMMU_RESOURCE_MAPPING_PD(4, fimd1, fimd1, PD_LCD1), +}; + +static struct sysmmu_resource_map sysmmu_resmap4212[] __initdata = { + SYSMMU_RESOURCE_MAPPING(4, 2d, 2d_acp), + SYSMMU_RESOURCE_MAPPING_PD(4, camif0, flite0, PD_ISP), + SYSMMU_RESOURCE_MAPPING_PD(4, camif1, flite1, PD_ISP), + SYSMMU_RESOURCE_MAPPING_PD(4, isp, isp, PD_ISP), +}; +#endif /* CONFIG_ARCH_EXYNOS4 */ -void sysmmu_clk_disable(sysmmu_ips ips) +#ifdef CONFIG_ARCH_EXYNOS5 +SYSMMU_RESOURCE_DEFINE(EXYNOS5, jpeg, JPEG, JPEG); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, fimd1, FIMD1, FIMD1); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, 2d, 2D, 2D); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, rot, ROTATOR, ROTATOR); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, tv, TV, TV); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite0, LITE0, LITE0); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite1, LITE1, LITE1); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc0, GSC0, GSC0); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc1, GSC1, GSC1); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc2, GSC2, GSC2); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc3, GSC3, GSC3); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_r, MFC_R, MFC_R); +SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_l, MFC_L, MFC_L); +SYSMMU_RESOURCE(EXYNOS5, isp) { + DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISP, ISP), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, DRC, DRC), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, FD, FD), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISPCPU, MCUISP), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERC, SCALERCISP), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERP, SCALERPISP), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, ODC, ODC), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS0, DIS0), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS1, DIS1), + DEFINE_SYSMMU_RESOURCE(EXYNOS5, 3DNR, 3DNR), +}; + +static struct sysmmu_resource_map sysmmu_resmap5[] __initdata = { + SYSMMU_RESOURCE_MAPPING(5, jpeg, jpeg), + SYSMMU_RESOURCE_MAPPING(5, fimd1, fimd1), + SYSMMU_RESOURCE_MAPPING(5, 2d, 2d), + SYSMMU_RESOURCE_MAPPING(5, rot, rot), + SYSMMU_RESOURCE_MAPPING_PD(5, tv, tv, PD_DISP1), + SYSMMU_RESOURCE_MAPPING_PD(5, camif0, flite0, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, camif1, flite1, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, gsc0, gsc0, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, gsc1, gsc1, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, gsc2, gsc2, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, gsc3, gsc3, PD_GSCL), + SYSMMU_RESOURCE_MAPPING_PD(5, mfc_r, mfc_r, PD_MFC), + SYSMMU_RESOURCE_MAPPING_PD(5, mfc_l, mfc_l, PD_MFC), + SYSMMU_RESOURCE_MAPPING_MCPD(5, isp, isp, PD_ISP, mc_platdata), +}; +#endif /* CONFIG_ARCH_EXYNOS5 */ + +static int __init init_sysmmu_platform_device(void) { - if (sysmmu_clk[ips]) - clk_disable(sysmmu_clk[ips]); + int i, j; + struct sysmmu_resource_map *resmap[2] = {NULL, NULL}; + int nmap[2] = {0, 0}; + +#ifdef CONFIG_ARCH_EXYNOS5 + if (soc_is_exynos5250()) { + resmap[0] = sysmmu_resmap5; + nmap[0] = ARRAY_SIZE(sysmmu_resmap5); + nmap[1] = 0; + } +#endif + +#ifdef CONFIG_ARCH_EXYNOS4 + if (resmap[0] == NULL) { + resmap[0] = sysmmu_resmap4; + nmap[0] = ARRAY_SIZE(sysmmu_resmap4); + } + + if (soc_is_exynos4210()) { + resmap[1] = sysmmu_resmap4210; + nmap[1] = ARRAY_SIZE(sysmmu_resmap4210); + } + + if (soc_is_exynos4412() || soc_is_exynos4212()) { + resmap[1] = sysmmu_resmap4212; + nmap[1] = ARRAY_SIZE(sysmmu_resmap4212); + } +#endif + + for (j = 0; j < 2; j++) { + for (i = 0; i < nmap[j]; i++) { + struct sysmmu_resource_map *map; + struct sysmmu_platform_data *platdata; + + map = &resmap[j][i]; + + map->pdev->dev.parent = map->pdd; + + platdata = map->pdev->dev.platform_data; + platdata->clockname = map->clocknames; + + if (platform_device_add_resources(map->pdev, map->res, + map->rnum)) { + pr_err("%s: Failed to add device resources for " + "%s.%d\n", __func__, + map->pdev->name, map->pdev->id); + continue; + } + + if (platform_device_register(map->pdev)) { + pr_err("%s: Failed to register %s.%d\n", + __func__, map->pdev->name, + map->pdev->id); + } + } + } + + return 0; } +arch_initcall(init_sysmmu_platform_device); diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 9bee8535d9e0..f140e1a2d335 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -154,6 +154,13 @@ #define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) #define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) +#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE0_0 COMBINER_IRQ(16, 0) +#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE1_0 COMBINER_IRQ(16, 1) +#define EXYNOS4_IRQ_SYSMMU_FIMC_ISP_0 COMBINER_IRQ(16, 2) +#define EXYNOS4_IRQ_SYSMMU_FIMC_DRC_0 COMBINER_IRQ(16, 3) +#define EXYNOS4_IRQ_SYSMMU_FIMC_FD_0 COMBINER_IRQ(16, 4) +#define EXYNOS4_IRQ_SYSMMU_FIMC_CX_0 COMBINER_IRQ(16, 5) + #define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) @@ -218,24 +225,6 @@ #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD #define IRQ_PMU EXYNOS4_IRQ_PMU -#define IRQ_SYSMMU_MDMA0_0 EXYNOS4_IRQ_SYSMMU_MDMA0_0 -#define IRQ_SYSMMU_SSS_0 EXYNOS4_IRQ_SYSMMU_SSS_0 -#define IRQ_SYSMMU_FIMC0_0 EXYNOS4_IRQ_SYSMMU_FIMC0_0 -#define IRQ_SYSMMU_FIMC1_0 EXYNOS4_IRQ_SYSMMU_FIMC1_0 -#define IRQ_SYSMMU_FIMC2_0 EXYNOS4_IRQ_SYSMMU_FIMC2_0 -#define IRQ_SYSMMU_FIMC3_0 EXYNOS4_IRQ_SYSMMU_FIMC3_0 -#define IRQ_SYSMMU_JPEG_0 EXYNOS4_IRQ_SYSMMU_JPEG_0 -#define IRQ_SYSMMU_2D_0 EXYNOS4_IRQ_SYSMMU_2D_0 - -#define IRQ_SYSMMU_ROTATOR_0 EXYNOS4_IRQ_SYSMMU_ROTATOR_0 -#define IRQ_SYSMMU_MDMA1_0 EXYNOS4_IRQ_SYSMMU_MDMA1_0 -#define IRQ_SYSMMU_LCD0_M0_0 EXYNOS4_IRQ_SYSMMU_LCD0_M0_0 -#define IRQ_SYSMMU_LCD1_M1_0 EXYNOS4_IRQ_SYSMMU_LCD1_M1_0 -#define IRQ_SYSMMU_TV_M0_0 EXYNOS4_IRQ_SYSMMU_TV_M0_0 -#define IRQ_SYSMMU_MFC_M0_0 EXYNOS4_IRQ_SYSMMU_MFC_M0_0 -#define IRQ_SYSMMU_MFC_M1_0 EXYNOS4_IRQ_SYSMMU_MFC_M1_0 -#define IRQ_SYSMMU_PCIE_0 EXYNOS4_IRQ_SYSMMU_PCIE_0 - #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC #define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 024d38ff1718..69f2ea6fb0d2 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -91,6 +91,7 @@ #define EXYNOS4_PA_PDMA1 0x12690000 #define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000 +#define EXYNOS4_PA_SYSMMU_2D_ACP 0x10A40000 #define EXYNOS4_PA_SYSMMU_SSS 0x10A50000 #define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000 #define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000 @@ -99,6 +100,12 @@ #define EXYNOS4_PA_SYSMMU_JPEG 0x11A60000 #define EXYNOS4_PA_SYSMMU_FIMD0 0x11E20000 #define EXYNOS4_PA_SYSMMU_FIMD1 0x12220000 +#define EXYNOS4_PA_SYSMMU_FIMC_ISP 0x12260000 +#define EXYNOS4_PA_SYSMMU_FIMC_DRC 0x12270000 +#define EXYNOS4_PA_SYSMMU_FIMC_FD 0x122A0000 +#define EXYNOS4_PA_SYSMMU_ISPCPU 0x122B0000 +#define EXYNOS4_PA_SYSMMU_FIMC_LITE0 0x123B0000 +#define EXYNOS4_PA_SYSMMU_FIMC_LITE1 0x123C0000 #define EXYNOS4_PA_SYSMMU_PCIe 0x12620000 #define EXYNOS4_PA_SYSMMU_G2D 0x12A20000 #define EXYNOS4_PA_SYSMMU_ROTATOR 0x12A30000 @@ -106,6 +113,37 @@ #define EXYNOS4_PA_SYSMMU_TV 0x12E20000 #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 + +#define EXYNOS5_PA_SYSMMU_MDMA1 0x10A40000 +#define EXYNOS5_PA_SYSMMU_SSS 0x10A50000 +#define EXYNOS5_PA_SYSMMU_2D 0x10A60000 +#define EXYNOS5_PA_SYSMMU_MFC_L 0x11200000 +#define EXYNOS5_PA_SYSMMU_MFC_R 0x11210000 +#define EXYNOS5_PA_SYSMMU_ROTATOR 0x11D40000 +#define EXYNOS5_PA_SYSMMU_MDMA2 0x11D50000 +#define EXYNOS5_PA_SYSMMU_JPEG 0x11F20000 +#define EXYNOS5_PA_SYSMMU_IOP 0x12360000 +#define EXYNOS5_PA_SYSMMU_RTIC 0x12370000 +#define EXYNOS5_PA_SYSMMU_GPS 0x12630000 +#define EXYNOS5_PA_SYSMMU_ISP 0x13260000 +#define EXYNOS5_PA_SYSMMU_DRC 0x12370000 +#define EXYNOS5_PA_SYSMMU_SCALERC 0x13280000 +#define EXYNOS5_PA_SYSMMU_SCALERP 0x13290000 +#define EXYNOS5_PA_SYSMMU_FD 0x132A0000 +#define EXYNOS5_PA_SYSMMU_ISPCPU 0x132B0000 +#define EXYNOS5_PA_SYSMMU_ODC 0x132C0000 +#define EXYNOS5_PA_SYSMMU_DIS0 0x132D0000 +#define EXYNOS5_PA_SYSMMU_DIS1 0x132E0000 +#define EXYNOS5_PA_SYSMMU_3DNR 0x132F0000 +#define EXYNOS5_PA_SYSMMU_LITE0 0x13C40000 +#define EXYNOS5_PA_SYSMMU_LITE1 0x13C50000 +#define EXYNOS5_PA_SYSMMU_GSC0 0x13E80000 +#define EXYNOS5_PA_SYSMMU_GSC1 0x13E90000 +#define EXYNOS5_PA_SYSMMU_GSC2 0x13EA0000 +#define EXYNOS5_PA_SYSMMU_GSC3 0x13EB0000 +#define EXYNOS5_PA_SYSMMU_FIMD1 0x14640000 +#define EXYNOS5_PA_SYSMMU_TV 0x14650000 + #define EXYNOS4_PA_SPI0 0x13920000 #define EXYNOS4_PA_SPI1 0x13930000 #define EXYNOS4_PA_SPI2 0x13940000 diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h index e141c1fd68d8..7395236ffc0e 100644 --- a/arch/arm/mach-exynos/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h @@ -135,6 +135,9 @@ #define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800) #define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900) +#define EXYNOS4_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x18800) +#define EXYNOS4_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x18804) + #define EXYNOS4_APLL_LOCKTIME (0x1C20) /* 300us */ #define EXYNOS4_APLLCON0_ENABLE_SHIFT (31) @@ -297,6 +300,8 @@ #define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558) #define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800) +#define EXYNOS5_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x0C800) +#define EXYNOS5_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x0C804) #define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920) #define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928) #define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C) diff --git a/arch/arm/mach-exynos/include/mach/regs-sysmmu.h b/arch/arm/mach-exynos/include/mach/regs-sysmmu.h deleted file mode 100644 index 68ff6ad08a2b..000000000000 --- a/arch/arm/mach-exynos/include/mach/regs-sysmmu.h +++ /dev/null @@ -1,28 +0,0 @@ -/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS4 - System MMU register - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_REGS_SYSMMU_H -#define __ASM_ARCH_REGS_SYSMMU_H __FILE__ - -#define S5P_MMU_CTRL 0x000 -#define S5P_MMU_CFG 0x004 -#define S5P_MMU_STATUS 0x008 -#define S5P_MMU_FLUSH 0x00C -#define S5P_PT_BASE_ADDR 0x014 -#define S5P_INT_STATUS 0x018 -#define S5P_INT_CLEAR 0x01C -#define S5P_PAGE_FAULT_ADDR 0x024 -#define S5P_AW_FAULT_ADDR 0x028 -#define S5P_AR_FAULT_ADDR 0x02C -#define S5P_DEFAULT_SLAVE_ADDR 0x030 - -#endif /* __ASM_ARCH_REGS_SYSMMU_H */ diff --git a/arch/arm/mach-exynos/include/mach/sysmmu.h b/arch/arm/mach-exynos/include/mach/sysmmu.h index 6a5fbb534e82..998daf2add92 100644 --- a/arch/arm/mach-exynos/include/mach/sysmmu.h +++ b/arch/arm/mach-exynos/include/mach/sysmmu.h @@ -1,46 +1,66 @@ -/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. +/* + * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Samsung sysmmu driver for EXYNOS4 + * EXYNOS - System MMU 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. -*/ - -#ifndef __ASM_ARM_ARCH_SYSMMU_H -#define __ASM_ARM_ARCH_SYSMMU_H __FILE__ - -enum exynos4_sysmmu_ips { - SYSMMU_MDMA, - SYSMMU_SSS, - SYSMMU_FIMC0, - SYSMMU_FIMC1, - SYSMMU_FIMC2, - SYSMMU_FIMC3, - SYSMMU_JPEG, - SYSMMU_FIMD0, - SYSMMU_FIMD1, - SYSMMU_PCIe, - SYSMMU_G2D, - SYSMMU_ROTATOR, - SYSMMU_MDMA2, - SYSMMU_TV, - SYSMMU_MFC_L, - SYSMMU_MFC_R, - EXYNOS4_SYSMMU_TOTAL_IPNUM, + */ + +#ifndef _ARM_MACH_EXYNOS_SYSMMU_H_ +#define _ARM_MACH_EXYNOS_SYSMMU_H_ + +struct sysmmu_platform_data { + char *dbgname; + /* comma(,) separated list of clock names for clock gating */ + char *clockname; }; -#define S5P_SYSMMU_TOTAL_IPNUM EXYNOS4_SYSMMU_TOTAL_IPNUM +#define SYSMMU_DEVNAME_BASE "exynos-sysmmu" + +#define SYSMMU_CLOCK_NAME "sysmmu" +#define SYSMMU_CLOCK_NAME2 "sysmmu_mc" + +#ifdef CONFIG_EXYNOS_DEV_SYSMMU +#include +struct platform_device; + +#define SYSMMU_PLATDEV(ipname) exynos_device_sysmmu_##ipname + +extern struct platform_device SYSMMU_PLATDEV(mfc_l); +extern struct platform_device SYSMMU_PLATDEV(mfc_r); +extern struct platform_device SYSMMU_PLATDEV(tv); +extern struct platform_device SYSMMU_PLATDEV(jpeg); +extern struct platform_device SYSMMU_PLATDEV(rot); +extern struct platform_device SYSMMU_PLATDEV(fimc0); +extern struct platform_device SYSMMU_PLATDEV(fimc1); +extern struct platform_device SYSMMU_PLATDEV(fimc2); +extern struct platform_device SYSMMU_PLATDEV(fimc3); +extern struct platform_device SYSMMU_PLATDEV(gsc0); +extern struct platform_device SYSMMU_PLATDEV(gsc1); +extern struct platform_device SYSMMU_PLATDEV(gsc2); +extern struct platform_device SYSMMU_PLATDEV(gsc3); +extern struct platform_device SYSMMU_PLATDEV(isp); +extern struct platform_device SYSMMU_PLATDEV(fimd0); +extern struct platform_device SYSMMU_PLATDEV(fimd1); +extern struct platform_device SYSMMU_PLATDEV(camif0); +extern struct platform_device SYSMMU_PLATDEV(camif1); +extern struct platform_device SYSMMU_PLATDEV(2d); -extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM]; +#ifdef CONFIG_IOMMU_API +static inline void platform_set_sysmmu( + struct device *sysmmu, struct device *dev) +{ + dev->archdata.iommu = sysmmu; +} +#endif -typedef enum exynos4_sysmmu_ips sysmmu_ips; +#else /* !CONFIG_EXYNOS_DEV_SYSMMU */ +#define platform_set_sysmmu(dev, sysmmu) do { } while (0) +#endif -void sysmmu_clk_init(struct device *dev, sysmmu_ips ips); -void sysmmu_clk_enable(sysmmu_ips ips); -void sysmmu_clk_disable(sysmmu_ips ips); +#define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id) -#endif /* __ASM_ARM_ARCH_SYSMMU_H */ +#endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */ diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c index d726fcd3acf9..6ce21484501e 100644 --- a/arch/arm/mach-exynos/mach-armlex4210.c +++ b/arch/arm/mach-exynos/mach-armlex4210.c @@ -157,7 +157,6 @@ static struct platform_device *armlex4210_devices[] __initdata = { &s3c_device_hsmmc3, &s3c_device_rtc, &s3c_device_wdt, - &exynos4_device_sysmmu, &samsung_asoc_dma, &armlex4210_smsc911x, &exynos4_device_ahci, diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 83b91fa777c1..495c7e502be1 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -281,7 +281,6 @@ static struct platform_device *smdkv310_devices[] __initdata = { &s5p_device_mfc_l, &s5p_device_mfc_r, &exynos4_device_spdif, - &exynos4_device_sysmmu, &samsung_asoc_dma, &samsung_asoc_idma, &s5p_device_fimd0, -- cgit 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 diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 4953d50707be..83152108af3d 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 f68a9bb11948..000000000000 --- 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 71553f410016..3a48d9de22a8 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 6012366f33cb..997ce1005700 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 000000000000..41d3dfd5dddb --- /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 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 diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 2c1193c59928..efff0a30da4a 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 83152108af3d..8701c3c36d6a 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 139c050918c5..000000000000 --- 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 82c7311017a2..000000000000 --- 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 afdaa1082b9f..000000000000 --- 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 3a48d9de22a8..e09dd4f9dc31 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 997ce1005700..5b650094628f 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 000000000000..33bd3f3d20f5 --- /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 000000000000..f9431fe5b06e --- /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 000000000000..dfb47d638f03 --- /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 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 diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index efff0a30da4a..8e45c8b15d1b 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 8701c3c36d6a..c81106f5d7c1 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 d1bfecae6c9f..000000000000 --- 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 d15dc47b0e3d..000000000000 --- 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 006bd01eda02..000000000000 --- 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 e09dd4f9dc31..218462361e31 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 5b650094628f..caa6f9af1f3d 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 000000000000..7c1e3b7072fc --- /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 000000000000..0747468f0936 --- /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 000000000000..bdf6dadf8790 --- /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 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 diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 8e45c8b15d1b..795790df7404 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 c81106f5d7c1..0a2ce38b179f 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 17c0a2c58dfd..000000000000 --- 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 218462361e31..1922413f2ee7 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 caa6f9af1f3d..6217c41e6260 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 000000000000..028b6e877eb9 --- /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 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 diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 795790df7404..33d9bc8b03a5 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 0a2ce38b179f..1dc6b1c5bd75 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 c9308db36183..000000000000 --- 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 1922413f2ee7..5ce6bc8ccf81 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 6217c41e6260..b20047b5633e 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 000000000000..cafa3deddcc1 --- /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 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 diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 33d9bc8b03a5..4ff6d7e9bf20 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 1dc6b1c5bd75..884b9a17360e 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 a30d36b7f61b..000000000000 --- 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 683c466c0e6a..000000000000 --- 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 5ce6bc8ccf81..7fec2e9cdad4 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 b20047b5633e..860b2db4db15 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 000000000000..ad6089465e2a --- /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 000000000000..683c466c0e6a --- /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 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(-) diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 4ff6d7e9bf20..e7d5d77b1b64 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 7fec2e9cdad4..8381d47027af 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 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 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 93180845ae16..60c2f9c0ba1a 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 047a20780fc1..f55b509d35c4 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 e7d5d77b1b64..000000000000 --- 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 884b9a17360e..000000000000 --- 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 8381d47027af..b54e13d09018 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