diff options
Diffstat (limited to 'arch/arm/plat-s5p')
43 files changed, 3627 insertions, 0 deletions
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig new file mode 100644 index 00000000000..9843c954c04 --- /dev/null +++ b/arch/arm/plat-s5p/Kconfig | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | # arch/arm/plat-s5p/Kconfig | ||
| 2 | # | ||
| 3 | # Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | # http://www.samsung.com/ | ||
| 5 | # | ||
| 6 | # Licensed under GPLv2 | ||
| 7 | |||
| 8 | config PLAT_S5P | ||
| 9 | bool | ||
| 10 | depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4) | ||
| 11 | default y | ||
| 12 | select ARM_VIC if !ARCH_EXYNOS4 | ||
| 13 | select ARM_GIC if ARCH_EXYNOS4 | ||
| 14 | select NO_IOPORT | ||
| 15 | select ARCH_REQUIRE_GPIOLIB | ||
| 16 | select S3C_GPIO_TRACK | ||
| 17 | select S5P_GPIO_DRVSTR | ||
| 18 | select SAMSUNG_GPIOLIB_4BIT | ||
| 19 | select S3C_GPIO_CFG_S3C64XX | ||
| 20 | select S3C_GPIO_PULL_UPDOWN | ||
| 21 | select S3C_GPIO_CFG_S3C24XX | ||
| 22 | select PLAT_SAMSUNG | ||
| 23 | select SAMSUNG_CLKSRC | ||
| 24 | select SAMSUNG_IRQ_VIC_TIMER | ||
| 25 | select SAMSUNG_IRQ_UART | ||
| 26 | help | ||
| 27 | Base platform code for Samsung's S5P series SoC. | ||
| 28 | |||
| 29 | config S5P_EXT_INT | ||
| 30 | bool | ||
| 31 | help | ||
| 32 | Use the external interrupts (other than GPIO interrupts.) | ||
| 33 | Note: Do not choose this for S5P6440 and S5P6450. | ||
| 34 | |||
| 35 | config S5P_GPIO_INT | ||
| 36 | bool | ||
| 37 | help | ||
| 38 | Common code for the GPIO interrupts (other than external interrupts.) | ||
| 39 | |||
| 40 | config S5P_HRT | ||
| 41 | bool | ||
| 42 | select SAMSUNG_DEV_PWM | ||
| 43 | help | ||
| 44 | Use the High Resolution timer support | ||
| 45 | |||
| 46 | comment "System MMU" | ||
| 47 | |||
| 48 | config S5P_SYSTEM_MMU | ||
| 49 | bool "S5P SYSTEM MMU" | ||
| 50 | depends on ARCH_EXYNOS4 | ||
| 51 | help | ||
| 52 | Say Y here if you want to enable System MMU | ||
| 53 | |||
| 54 | config S5P_DEV_FIMC0 | ||
| 55 | bool | ||
| 56 | help | ||
| 57 | Compile in platform device definitions for FIMC controller 0 | ||
| 58 | |||
| 59 | config S5P_DEV_FIMC1 | ||
| 60 | bool | ||
| 61 | help | ||
| 62 | Compile in platform device definitions for FIMC controller 1 | ||
| 63 | |||
| 64 | config S5P_DEV_FIMC2 | ||
| 65 | bool | ||
| 66 | help | ||
| 67 | Compile in platform device definitions for FIMC controller 2 | ||
| 68 | |||
| 69 | config S5P_DEV_FIMC3 | ||
| 70 | bool | ||
| 71 | help | ||
| 72 | Compile in platform device definitions for FIMC controller 3 | ||
| 73 | |||
| 74 | config S5P_DEV_FIMD0 | ||
| 75 | bool | ||
| 76 | help | ||
| 77 | Compile in platform device definitions for FIMD controller 0 | ||
| 78 | |||
| 79 | config S5P_DEV_MFC | ||
| 80 | bool | ||
| 81 | help | ||
| 82 | Compile in platform device definitions for MFC | ||
| 83 | |||
| 84 | config S5P_DEV_ONENAND | ||
| 85 | bool | ||
| 86 | help | ||
| 87 | Compile in platform device definition for OneNAND controller | ||
| 88 | |||
| 89 | config S5P_DEV_CSIS0 | ||
| 90 | bool | ||
| 91 | help | ||
| 92 | Compile in platform device definitions for MIPI-CSIS channel 0 | ||
| 93 | |||
| 94 | config S5P_DEV_CSIS1 | ||
| 95 | bool | ||
| 96 | help | ||
| 97 | Compile in platform device definitions for MIPI-CSIS channel 1 | ||
| 98 | |||
| 99 | config S5P_DEV_USB_EHCI | ||
| 100 | bool | ||
| 101 | help | ||
| 102 | Compile in platform device definition for USB EHCI | ||
| 103 | |||
| 104 | config S5P_SETUP_MIPIPHY | ||
| 105 | bool | ||
| 106 | help | ||
| 107 | 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 new file mode 100644 index 00000000000..4b53e04eeca --- /dev/null +++ b/arch/arm/plat-s5p/Makefile | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | # arch/arm/plat-s5p/Makefile | ||
| 2 | # | ||
| 3 | # Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | # http://www.samsung.com/ | ||
| 5 | # | ||
| 6 | # Licensed under GPLv2 | ||
| 7 | |||
| 8 | obj-y := | ||
| 9 | obj-m := | ||
| 10 | obj-n := dummy.o | ||
| 11 | obj- := | ||
| 12 | |||
| 13 | # Core files | ||
| 14 | |||
| 15 | obj-y += dev-pmu.o | ||
| 16 | obj-y += dev-uart.o | ||
| 17 | obj-y += cpu.o | ||
| 18 | obj-y += clock.o | ||
| 19 | obj-y += irq.o | ||
| 20 | obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o | ||
| 21 | obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o | ||
| 22 | obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o | ||
| 23 | obj-$(CONFIG_PM) += pm.o | ||
| 24 | obj-$(CONFIG_PM) += irq-pm.o | ||
| 25 | obj-$(CONFIG_S5P_HRT) += s5p-time.o | ||
| 26 | |||
| 27 | # devices | ||
| 28 | obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o | ||
| 29 | obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o | ||
| 30 | obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o | ||
| 31 | obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o | ||
| 32 | obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o | ||
| 33 | obj-$(CONFIG_S5P_DEV_FIMD0) += dev-fimd0.o | ||
| 34 | obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o | ||
| 35 | obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o | ||
| 36 | obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o | ||
| 37 | obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o | ||
| 38 | obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o | ||
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c new file mode 100644 index 00000000000..5f84a3f13ef --- /dev/null +++ b/arch/arm/plat-s5p/clock.c | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/clock.c | ||
| 2 | * | ||
| 3 | * Copyright 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P - Common clock support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/sysdev.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <asm/div64.h> | ||
| 23 | |||
| 24 | #include <mach/regs-clock.h> | ||
| 25 | |||
| 26 | #include <plat/clock.h> | ||
| 27 | #include <plat/clock-clksrc.h> | ||
| 28 | #include <plat/s5p-clock.h> | ||
| 29 | |||
| 30 | /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call | ||
| 31 | * clk_ext_xtal_mux. | ||
| 32 | */ | ||
| 33 | struct clk clk_ext_xtal_mux = { | ||
| 34 | .name = "ext_xtal", | ||
| 35 | .id = -1, | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct clk clk_xusbxti = { | ||
| 39 | .name = "xusbxti", | ||
| 40 | .id = -1, | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct clk s5p_clk_27m = { | ||
| 44 | .name = "clk_27m", | ||
| 45 | .id = -1, | ||
| 46 | .rate = 27000000, | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* 48MHz USB Phy clock output */ | ||
| 50 | struct clk clk_48m = { | ||
| 51 | .name = "clk_48m", | ||
| 52 | .id = -1, | ||
| 53 | .rate = 48000000, | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* APLL clock output | ||
| 57 | * No need .ctrlbit, this is always on | ||
| 58 | */ | ||
| 59 | struct clk clk_fout_apll = { | ||
| 60 | .name = "fout_apll", | ||
| 61 | .id = -1, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* MPLL clock output | ||
| 65 | * No need .ctrlbit, this is always on | ||
| 66 | */ | ||
| 67 | struct clk clk_fout_mpll = { | ||
| 68 | .name = "fout_mpll", | ||
| 69 | .id = -1, | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* EPLL clock output */ | ||
| 73 | struct clk clk_fout_epll = { | ||
| 74 | .name = "fout_epll", | ||
| 75 | .id = -1, | ||
| 76 | .ctrlbit = (1 << 31), | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* DPLL clock output */ | ||
| 80 | struct clk clk_fout_dpll = { | ||
| 81 | .name = "fout_dpll", | ||
| 82 | .id = -1, | ||
| 83 | .ctrlbit = (1 << 31), | ||
| 84 | }; | ||
| 85 | |||
| 86 | /* VPLL clock output */ | ||
| 87 | struct clk clk_fout_vpll = { | ||
| 88 | .name = "fout_vpll", | ||
| 89 | .id = -1, | ||
| 90 | .ctrlbit = (1 << 31), | ||
| 91 | }; | ||
| 92 | |||
| 93 | /* Possible clock sources for APLL Mux */ | ||
| 94 | static struct clk *clk_src_apll_list[] = { | ||
| 95 | [0] = &clk_fin_apll, | ||
| 96 | [1] = &clk_fout_apll, | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct clksrc_sources clk_src_apll = { | ||
| 100 | .sources = clk_src_apll_list, | ||
| 101 | .nr_sources = ARRAY_SIZE(clk_src_apll_list), | ||
| 102 | }; | ||
| 103 | |||
| 104 | /* Possible clock sources for MPLL Mux */ | ||
| 105 | static struct clk *clk_src_mpll_list[] = { | ||
| 106 | [0] = &clk_fin_mpll, | ||
| 107 | [1] = &clk_fout_mpll, | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct clksrc_sources clk_src_mpll = { | ||
| 111 | .sources = clk_src_mpll_list, | ||
| 112 | .nr_sources = ARRAY_SIZE(clk_src_mpll_list), | ||
| 113 | }; | ||
| 114 | |||
| 115 | /* Possible clock sources for EPLL Mux */ | ||
| 116 | static struct clk *clk_src_epll_list[] = { | ||
| 117 | [0] = &clk_fin_epll, | ||
| 118 | [1] = &clk_fout_epll, | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct clksrc_sources clk_src_epll = { | ||
| 122 | .sources = clk_src_epll_list, | ||
| 123 | .nr_sources = ARRAY_SIZE(clk_src_epll_list), | ||
| 124 | }; | ||
| 125 | |||
| 126 | /* Possible clock sources for DPLL Mux */ | ||
| 127 | static struct clk *clk_src_dpll_list[] = { | ||
| 128 | [0] = &clk_fin_dpll, | ||
| 129 | [1] = &clk_fout_dpll, | ||
| 130 | }; | ||
| 131 | |||
| 132 | struct clksrc_sources clk_src_dpll = { | ||
| 133 | .sources = clk_src_dpll_list, | ||
| 134 | .nr_sources = ARRAY_SIZE(clk_src_dpll_list), | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct clk clk_vpll = { | ||
| 138 | .name = "vpll", | ||
| 139 | .id = -1, | ||
| 140 | }; | ||
| 141 | |||
| 142 | int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable) | ||
| 143 | { | ||
| 144 | unsigned int ctrlbit = clk->ctrlbit; | ||
| 145 | u32 con; | ||
| 146 | |||
| 147 | con = __raw_readl(reg); | ||
| 148 | con = enable ? (con | ctrlbit) : (con & ~ctrlbit); | ||
| 149 | __raw_writel(con, reg); | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | int s5p_epll_enable(struct clk *clk, int enable) | ||
| 154 | { | ||
| 155 | unsigned int ctrlbit = clk->ctrlbit; | ||
| 156 | unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; | ||
| 157 | |||
| 158 | if (enable) | ||
| 159 | __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); | ||
| 160 | else | ||
| 161 | __raw_writel(epll_con, S5P_EPLL_CON); | ||
| 162 | |||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | unsigned long s5p_epll_get_rate(struct clk *clk) | ||
| 167 | { | ||
| 168 | return clk->rate; | ||
| 169 | } | ||
| 170 | |||
| 171 | int s5p_spdif_set_rate(struct clk *clk, unsigned long rate) | ||
| 172 | { | ||
| 173 | struct clk *pclk; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | pclk = clk_get_parent(clk); | ||
| 177 | if (IS_ERR(pclk)) | ||
| 178 | return -EINVAL; | ||
| 179 | |||
| 180 | ret = pclk->ops->set_rate(pclk, rate); | ||
| 181 | clk_put(pclk); | ||
| 182 | |||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | |||
| 186 | unsigned long s5p_spdif_get_rate(struct clk *clk) | ||
| 187 | { | ||
| 188 | struct clk *pclk; | ||
| 189 | int rate; | ||
| 190 | |||
| 191 | pclk = clk_get_parent(clk); | ||
| 192 | if (IS_ERR(pclk)) | ||
| 193 | return -EINVAL; | ||
| 194 | |||
| 195 | rate = pclk->ops->get_rate(pclk); | ||
| 196 | clk_put(pclk); | ||
| 197 | |||
| 198 | return rate; | ||
| 199 | } | ||
| 200 | |||
| 201 | struct clk_ops s5p_sclk_spdif_ops = { | ||
| 202 | .set_rate = s5p_spdif_set_rate, | ||
| 203 | .get_rate = s5p_spdif_get_rate, | ||
| 204 | }; | ||
| 205 | |||
| 206 | static struct clk *s5p_clks[] __initdata = { | ||
| 207 | &clk_ext_xtal_mux, | ||
| 208 | &clk_48m, | ||
| 209 | &s5p_clk_27m, | ||
| 210 | &clk_fout_apll, | ||
| 211 | &clk_fout_mpll, | ||
| 212 | &clk_fout_epll, | ||
| 213 | &clk_fout_dpll, | ||
| 214 | &clk_fout_vpll, | ||
| 215 | &clk_vpll, | ||
| 216 | &clk_xusbxti, | ||
| 217 | }; | ||
| 218 | |||
| 219 | void __init s5p_register_clocks(unsigned long xtal_freq) | ||
| 220 | { | ||
| 221 | int ret; | ||
| 222 | |||
| 223 | clk_ext_xtal_mux.rate = xtal_freq; | ||
| 224 | |||
| 225 | ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks)); | ||
| 226 | if (ret > 0) | ||
| 227 | printk(KERN_ERR "Failed to register s5p clocks\n"); | ||
| 228 | } | ||
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c new file mode 100644 index 00000000000..bbc2aa7449c --- /dev/null +++ b/arch/arm/plat-s5p/cpu.c | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/cpu.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * S5P CPU Support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | |||
| 16 | #include <asm/mach/arch.h> | ||
| 17 | #include <asm/mach/map.h> | ||
| 18 | |||
| 19 | #include <mach/map.h> | ||
| 20 | #include <mach/regs-clock.h> | ||
| 21 | |||
| 22 | #include <plat/cpu.h> | ||
| 23 | #include <plat/s5p6440.h> | ||
| 24 | #include <plat/s5p6450.h> | ||
| 25 | #include <plat/s5pc100.h> | ||
| 26 | #include <plat/s5pv210.h> | ||
| 27 | #include <plat/exynos4.h> | ||
| 28 | |||
| 29 | /* table of supported CPUs */ | ||
| 30 | |||
| 31 | static const char name_s5p6440[] = "S5P6440"; | ||
| 32 | static const char name_s5p6450[] = "S5P6450"; | ||
| 33 | static const char name_s5pc100[] = "S5PC100"; | ||
| 34 | static const char name_s5pv210[] = "S5PV210/S5PC110"; | ||
| 35 | static const char name_exynos4210[] = "EXYNOS4210"; | ||
| 36 | |||
| 37 | static struct cpu_table cpu_ids[] __initdata = { | ||
| 38 | { | ||
| 39 | .idcode = 0x56440100, | ||
| 40 | .idmask = 0xfffff000, | ||
| 41 | .map_io = s5p6440_map_io, | ||
| 42 | .init_clocks = s5p6440_init_clocks, | ||
| 43 | .init_uarts = s5p6440_init_uarts, | ||
| 44 | .init = s5p64x0_init, | ||
| 45 | .name = name_s5p6440, | ||
| 46 | }, { | ||
| 47 | .idcode = 0x36450000, | ||
| 48 | .idmask = 0xfffff000, | ||
| 49 | .map_io = s5p6450_map_io, | ||
| 50 | .init_clocks = s5p6450_init_clocks, | ||
| 51 | .init_uarts = s5p6450_init_uarts, | ||
| 52 | .init = s5p64x0_init, | ||
| 53 | .name = name_s5p6450, | ||
| 54 | }, { | ||
| 55 | .idcode = 0x43100000, | ||
| 56 | .idmask = 0xfffff000, | ||
| 57 | .map_io = s5pc100_map_io, | ||
| 58 | .init_clocks = s5pc100_init_clocks, | ||
| 59 | .init_uarts = s5pc100_init_uarts, | ||
| 60 | .init = s5pc100_init, | ||
| 61 | .name = name_s5pc100, | ||
| 62 | }, { | ||
| 63 | .idcode = 0x43110000, | ||
| 64 | .idmask = 0xfffff000, | ||
| 65 | .map_io = s5pv210_map_io, | ||
| 66 | .init_clocks = s5pv210_init_clocks, | ||
| 67 | .init_uarts = s5pv210_init_uarts, | ||
| 68 | .init = s5pv210_init, | ||
| 69 | .name = name_s5pv210, | ||
| 70 | }, { | ||
| 71 | .idcode = 0x43210000, | ||
| 72 | .idmask = 0xfffe0000, | ||
| 73 | .map_io = exynos4_map_io, | ||
| 74 | .init_clocks = exynos4_init_clocks, | ||
| 75 | .init_uarts = exynos4_init_uarts, | ||
| 76 | .init = exynos4_init, | ||
| 77 | .name = name_exynos4210, | ||
| 78 | }, | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* minimal IO mapping */ | ||
| 82 | |||
| 83 | static struct map_desc s5p_iodesc[] __initdata = { | ||
| 84 | { | ||
| 85 | .virtual = (unsigned long)S5P_VA_CHIPID, | ||
| 86 | .pfn = __phys_to_pfn(S5P_PA_CHIPID), | ||
| 87 | .length = SZ_4K, | ||
| 88 | .type = MT_DEVICE, | ||
| 89 | }, { | ||
| 90 | .virtual = (unsigned long)S3C_VA_SYS, | ||
| 91 | .pfn = __phys_to_pfn(S5P_PA_SYSCON), | ||
| 92 | .length = SZ_64K, | ||
| 93 | .type = MT_DEVICE, | ||
| 94 | }, { | ||
| 95 | .virtual = (unsigned long)S3C_VA_TIMER, | ||
| 96 | .pfn = __phys_to_pfn(S5P_PA_TIMER), | ||
| 97 | .length = SZ_16K, | ||
| 98 | .type = MT_DEVICE, | ||
| 99 | }, { | ||
| 100 | .virtual = (unsigned long)S3C_VA_WATCHDOG, | ||
| 101 | .pfn = __phys_to_pfn(S3C_PA_WDT), | ||
| 102 | .length = SZ_4K, | ||
| 103 | .type = MT_DEVICE, | ||
| 104 | }, { | ||
| 105 | .virtual = (unsigned long)S5P_VA_SROMC, | ||
| 106 | .pfn = __phys_to_pfn(S5P_PA_SROMC), | ||
| 107 | .length = SZ_4K, | ||
| 108 | .type = MT_DEVICE, | ||
| 109 | }, | ||
| 110 | }; | ||
| 111 | |||
| 112 | /* read cpu identification code */ | ||
| 113 | |||
| 114 | void __init s5p_init_io(struct map_desc *mach_desc, | ||
| 115 | int size, void __iomem *cpuid_addr) | ||
| 116 | { | ||
| 117 | unsigned long idcode; | ||
| 118 | |||
| 119 | /* initialize the io descriptors we need for initialization */ | ||
| 120 | iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc)); | ||
| 121 | if (mach_desc) | ||
| 122 | iotable_init(mach_desc, size); | ||
| 123 | |||
| 124 | idcode = __raw_readl(cpuid_addr); | ||
| 125 | s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); | ||
| 126 | } | ||
diff --git a/arch/arm/plat-s5p/dev-csis0.c b/arch/arm/plat-s5p/dev-csis0.c new file mode 100644 index 00000000000..e3aabef5e34 --- /dev/null +++ b/arch/arm/plat-s5p/dev-csis0.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * S5P series device definition for MIPI-CSIS channel 0 | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <mach/map.h> | ||
| 15 | |||
| 16 | static struct resource s5p_mipi_csis0_resource[] = { | ||
| 17 | [0] = { | ||
| 18 | .start = S5P_PA_MIPI_CSIS0, | ||
| 19 | .end = S5P_PA_MIPI_CSIS0 + SZ_4K - 1, | ||
| 20 | .flags = IORESOURCE_MEM, | ||
| 21 | }, | ||
| 22 | [1] = { | ||
| 23 | .start = IRQ_MIPI_CSIS0, | ||
| 24 | .end = IRQ_MIPI_CSIS0, | ||
| 25 | .flags = IORESOURCE_IRQ, | ||
| 26 | } | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct platform_device s5p_device_mipi_csis0 = { | ||
| 30 | .name = "s5p-mipi-csis", | ||
| 31 | .id = 0, | ||
| 32 | .num_resources = ARRAY_SIZE(s5p_mipi_csis0_resource), | ||
| 33 | .resource = s5p_mipi_csis0_resource, | ||
| 34 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-csis1.c b/arch/arm/plat-s5p/dev-csis1.c new file mode 100644 index 00000000000..08b91b58020 --- /dev/null +++ b/arch/arm/plat-s5p/dev-csis1.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * S5P series device definition for MIPI-CSIS channel 1 | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <mach/map.h> | ||
| 15 | |||
| 16 | static struct resource s5p_mipi_csis1_resource[] = { | ||
| 17 | [0] = { | ||
| 18 | .start = S5P_PA_MIPI_CSIS1, | ||
| 19 | .end = S5P_PA_MIPI_CSIS1 + SZ_4K - 1, | ||
| 20 | .flags = IORESOURCE_MEM, | ||
| 21 | }, | ||
| 22 | [1] = { | ||
| 23 | .start = IRQ_MIPI_CSIS1, | ||
| 24 | .end = IRQ_MIPI_CSIS1, | ||
| 25 | .flags = IORESOURCE_IRQ, | ||
| 26 | }, | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct platform_device s5p_device_mipi_csis1 = { | ||
| 30 | .name = "s5p-mipi-csis", | ||
| 31 | .id = 1, | ||
| 32 | .num_resources = ARRAY_SIZE(s5p_mipi_csis1_resource), | ||
| 33 | .resource = s5p_mipi_csis1_resource, | ||
| 34 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-ehci.c b/arch/arm/plat-s5p/dev-ehci.c new file mode 100644 index 00000000000..94080fff9e9 --- /dev/null +++ b/arch/arm/plat-s5p/dev-ehci.c | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
| 3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <mach/irqs.h> | ||
| 14 | #include <mach/map.h> | ||
| 15 | #include <plat/devs.h> | ||
| 16 | #include <plat/ehci.h> | ||
| 17 | #include <plat/usb-phy.h> | ||
| 18 | |||
| 19 | /* USB EHCI Host Controller registration */ | ||
| 20 | static struct resource s5p_ehci_resource[] = { | ||
| 21 | [0] = { | ||
| 22 | .start = S5P_PA_EHCI, | ||
| 23 | .end = S5P_PA_EHCI + SZ_256 - 1, | ||
| 24 | .flags = IORESOURCE_MEM, | ||
| 25 | }, | ||
| 26 | [1] = { | ||
| 27 | .start = IRQ_USB_HOST, | ||
| 28 | .end = IRQ_USB_HOST, | ||
| 29 | .flags = IORESOURCE_IRQ, | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | |||
| 33 | static u64 s5p_device_ehci_dmamask = 0xffffffffUL; | ||
| 34 | |||
| 35 | struct platform_device s5p_device_ehci = { | ||
| 36 | .name = "s5p-ehci", | ||
| 37 | .id = -1, | ||
| 38 | .num_resources = ARRAY_SIZE(s5p_ehci_resource), | ||
| 39 | .resource = s5p_ehci_resource, | ||
| 40 | .dev = { | ||
| 41 | .dma_mask = &s5p_device_ehci_dmamask, | ||
| 42 | .coherent_dma_mask = 0xffffffffUL | ||
| 43 | } | ||
| 44 | }; | ||
| 45 | |||
| 46 | void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd) | ||
| 47 | { | ||
| 48 | struct s5p_ehci_platdata *npd; | ||
| 49 | |||
| 50 | npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata), | ||
| 51 | &s5p_device_ehci); | ||
| 52 | |||
| 53 | if (!npd->phy_init) | ||
| 54 | npd->phy_init = s5p_usb_phy_init; | ||
| 55 | if (!npd->phy_exit) | ||
| 56 | npd->phy_exit = s5p_usb_phy_exit; | ||
| 57 | } | ||
diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c new file mode 100644 index 00000000000..608770fc153 --- /dev/null +++ b/arch/arm/plat-s5p/dev-fimc0.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-fimc0.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics | ||
| 4 | * | ||
| 5 | * Base S5P FIMC0 resource and device definitions | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/dma-mapping.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/ioport.h> | ||
| 17 | #include <mach/map.h> | ||
| 18 | |||
| 19 | static struct resource s5p_fimc0_resource[] = { | ||
| 20 | [0] = { | ||
| 21 | .start = S5P_PA_FIMC0, | ||
| 22 | .end = S5P_PA_FIMC0 + SZ_4K - 1, | ||
| 23 | .flags = IORESOURCE_MEM, | ||
| 24 | }, | ||
| 25 | [1] = { | ||
| 26 | .start = IRQ_FIMC0, | ||
| 27 | .end = IRQ_FIMC0, | ||
| 28 | .flags = IORESOURCE_IRQ, | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32); | ||
| 33 | |||
| 34 | struct platform_device s5p_device_fimc0 = { | ||
| 35 | .name = "s5p-fimc", | ||
| 36 | .id = 0, | ||
| 37 | .num_resources = ARRAY_SIZE(s5p_fimc0_resource), | ||
| 38 | .resource = s5p_fimc0_resource, | ||
| 39 | .dev = { | ||
| 40 | .dma_mask = &s5p_fimc0_dma_mask, | ||
| 41 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 42 | }, | ||
| 43 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c new file mode 100644 index 00000000000..76e3a97a87d --- /dev/null +++ b/arch/arm/plat-s5p/dev-fimc1.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-fimc1.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics | ||
| 4 | * | ||
| 5 | * Base S5P FIMC1 resource and device definitions | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/dma-mapping.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/ioport.h> | ||
| 17 | #include <mach/map.h> | ||
| 18 | |||
| 19 | static struct resource s5p_fimc1_resource[] = { | ||
| 20 | [0] = { | ||
| 21 | .start = S5P_PA_FIMC1, | ||
| 22 | .end = S5P_PA_FIMC1 + SZ_4K - 1, | ||
| 23 | .flags = IORESOURCE_MEM, | ||
| 24 | }, | ||
| 25 | [1] = { | ||
| 26 | .start = IRQ_FIMC1, | ||
| 27 | .end = IRQ_FIMC1, | ||
| 28 | .flags = IORESOURCE_IRQ, | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32); | ||
| 33 | |||
| 34 | struct platform_device s5p_device_fimc1 = { | ||
| 35 | .name = "s5p-fimc", | ||
| 36 | .id = 1, | ||
| 37 | .num_resources = ARRAY_SIZE(s5p_fimc1_resource), | ||
| 38 | .resource = s5p_fimc1_resource, | ||
| 39 | .dev = { | ||
| 40 | .dma_mask = &s5p_fimc1_dma_mask, | ||
| 41 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 42 | }, | ||
| 43 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c new file mode 100644 index 00000000000..24d29816fa2 --- /dev/null +++ b/arch/arm/plat-s5p/dev-fimc2.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-fimc2.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics | ||
| 4 | * | ||
| 5 | * Base S5P FIMC2 resource and device definitions | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/dma-mapping.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/ioport.h> | ||
| 17 | #include <mach/map.h> | ||
| 18 | |||
| 19 | static struct resource s5p_fimc2_resource[] = { | ||
| 20 | [0] = { | ||
| 21 | .start = S5P_PA_FIMC2, | ||
| 22 | .end = S5P_PA_FIMC2 + SZ_4K - 1, | ||
| 23 | .flags = IORESOURCE_MEM, | ||
| 24 | }, | ||
| 25 | [1] = { | ||
| 26 | .start = IRQ_FIMC2, | ||
| 27 | .end = IRQ_FIMC2, | ||
| 28 | .flags = IORESOURCE_IRQ, | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32); | ||
| 33 | |||
| 34 | struct platform_device s5p_device_fimc2 = { | ||
| 35 | .name = "s5p-fimc", | ||
| 36 | .id = 2, | ||
| 37 | .num_resources = ARRAY_SIZE(s5p_fimc2_resource), | ||
| 38 | .resource = s5p_fimc2_resource, | ||
| 39 | .dev = { | ||
| 40 | .dma_mask = &s5p_fimc2_dma_mask, | ||
| 41 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 42 | }, | ||
| 43 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-fimc3.c b/arch/arm/plat-s5p/dev-fimc3.c new file mode 100644 index 00000000000..ef31beca386 --- /dev/null +++ b/arch/arm/plat-s5p/dev-fimc3.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-fimc3.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics | ||
| 4 | * | ||
| 5 | * Base S5P FIMC3 resource and device definitions | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/dma-mapping.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/ioport.h> | ||
| 17 | #include <mach/map.h> | ||
| 18 | |||
| 19 | static struct resource s5p_fimc3_resource[] = { | ||
| 20 | [0] = { | ||
| 21 | .start = S5P_PA_FIMC3, | ||
| 22 | .end = S5P_PA_FIMC3 + SZ_4K - 1, | ||
| 23 | .flags = IORESOURCE_MEM, | ||
| 24 | }, | ||
| 25 | [1] = { | ||
| 26 | .start = IRQ_FIMC3, | ||
| 27 | .end = IRQ_FIMC3, | ||
| 28 | .flags = IORESOURCE_IRQ, | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32); | ||
| 33 | |||
| 34 | struct platform_device s5p_device_fimc3 = { | ||
| 35 | .name = "s5p-fimc", | ||
| 36 | .id = 3, | ||
| 37 | .num_resources = ARRAY_SIZE(s5p_fimc3_resource), | ||
| 38 | .resource = s5p_fimc3_resource, | ||
| 39 | .dev = { | ||
| 40 | .dma_mask = &s5p_fimc3_dma_mask, | ||
| 41 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 42 | }, | ||
| 43 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c new file mode 100644 index 00000000000..f728bb5abce --- /dev/null +++ b/arch/arm/plat-s5p/dev-fimd0.c | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-fimd0.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Core file for Samsung Display Controller (FIMD) driver | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/string.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/fb.h> | ||
| 17 | #include <linux/gfp.h> | ||
| 18 | #include <linux/dma-mapping.h> | ||
| 19 | |||
| 20 | #include <mach/irqs.h> | ||
| 21 | #include <mach/map.h> | ||
| 22 | |||
| 23 | #include <plat/fb.h> | ||
| 24 | #include <plat/devs.h> | ||
| 25 | #include <plat/cpu.h> | ||
| 26 | |||
| 27 | static struct resource s5p_fimd0_resource[] = { | ||
| 28 | [0] = { | ||
| 29 | .start = S5P_PA_FIMD0, | ||
| 30 | .end = S5P_PA_FIMD0 + SZ_32K - 1, | ||
| 31 | .flags = IORESOURCE_MEM, | ||
| 32 | }, | ||
| 33 | [1] = { | ||
| 34 | .start = IRQ_FIMD0_VSYNC, | ||
| 35 | .end = IRQ_FIMD0_VSYNC, | ||
| 36 | .flags = IORESOURCE_IRQ, | ||
| 37 | }, | ||
| 38 | [2] = { | ||
| 39 | .start = IRQ_FIMD0_FIFO, | ||
| 40 | .end = IRQ_FIMD0_FIFO, | ||
| 41 | .flags = IORESOURCE_IRQ, | ||
| 42 | }, | ||
| 43 | [3] = { | ||
| 44 | .start = IRQ_FIMD0_SYSTEM, | ||
| 45 | .end = IRQ_FIMD0_SYSTEM, | ||
| 46 | .flags = IORESOURCE_IRQ, | ||
| 47 | }, | ||
| 48 | }; | ||
| 49 | |||
| 50 | static u64 fimd0_dmamask = DMA_BIT_MASK(32); | ||
| 51 | |||
| 52 | struct platform_device s5p_device_fimd0 = { | ||
| 53 | .name = "s5p-fb", | ||
| 54 | .id = 0, | ||
| 55 | .num_resources = ARRAY_SIZE(s5p_fimd0_resource), | ||
| 56 | .resource = s5p_fimd0_resource, | ||
| 57 | .dev = { | ||
| 58 | .dma_mask = &fimd0_dmamask, | ||
| 59 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 60 | }, | ||
| 61 | }; | ||
| 62 | |||
| 63 | void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd) | ||
| 64 | { | ||
| 65 | s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata), | ||
| 66 | &s5p_device_fimd0); | ||
| 67 | } | ||
diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c new file mode 100644 index 00000000000..94226a0010f --- /dev/null +++ b/arch/arm/plat-s5p/dev-mfc.c | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-mfc.c | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd | ||
| 4 | * | ||
| 5 | * Base S5P MFC resource and device definitions | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/dma-mapping.h> | ||
| 17 | #include <linux/memblock.h> | ||
| 18 | #include <linux/ioport.h> | ||
| 19 | |||
| 20 | #include <mach/map.h> | ||
| 21 | #include <plat/devs.h> | ||
| 22 | #include <plat/irqs.h> | ||
| 23 | #include <plat/mfc.h> | ||
| 24 | |||
| 25 | static struct resource s5p_mfc_resource[] = { | ||
| 26 | [0] = { | ||
| 27 | .start = S5P_PA_MFC, | ||
| 28 | .end = S5P_PA_MFC + SZ_64K - 1, | ||
| 29 | .flags = IORESOURCE_MEM, | ||
| 30 | }, | ||
| 31 | [1] = { | ||
| 32 | .start = IRQ_MFC, | ||
| 33 | .end = IRQ_MFC, | ||
| 34 | .flags = IORESOURCE_IRQ, | ||
| 35 | } | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct platform_device s5p_device_mfc = { | ||
| 39 | .name = "s5p-mfc", | ||
| 40 | .id = -1, | ||
| 41 | .num_resources = ARRAY_SIZE(s5p_mfc_resource), | ||
| 42 | .resource = s5p_mfc_resource, | ||
| 43 | }; | ||
| 44 | |||
| 45 | /* | ||
| 46 | * MFC hardware has 2 memory interfaces which are modelled as two separate | ||
| 47 | * platform devices to let dma-mapping distinguish between them. | ||
| 48 | * | ||
| 49 | * MFC parent device (s5p_device_mfc) must be registered before memory | ||
| 50 | * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r). | ||
| 51 | */ | ||
| 52 | |||
| 53 | static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32); | ||
| 54 | |||
| 55 | struct platform_device s5p_device_mfc_l = { | ||
| 56 | .name = "s5p-mfc-l", | ||
| 57 | .id = -1, | ||
| 58 | .dev = { | ||
| 59 | .parent = &s5p_device_mfc.dev, | ||
| 60 | .dma_mask = &s5p_mfc_dma_mask, | ||
| 61 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 62 | }, | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct platform_device s5p_device_mfc_r = { | ||
| 66 | .name = "s5p-mfc-r", | ||
| 67 | .id = -1, | ||
| 68 | .dev = { | ||
| 69 | .parent = &s5p_device_mfc.dev, | ||
| 70 | .dma_mask = &s5p_mfc_dma_mask, | ||
| 71 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 72 | }, | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct s5p_mfc_reserved_mem { | ||
| 76 | phys_addr_t base; | ||
| 77 | unsigned long size; | ||
| 78 | struct device *dev; | ||
| 79 | }; | ||
| 80 | |||
| 81 | static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata; | ||
| 82 | |||
| 83 | void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, | ||
| 84 | phys_addr_t lbase, unsigned int lsize) | ||
| 85 | { | ||
| 86 | int i; | ||
| 87 | |||
| 88 | s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev; | ||
| 89 | s5p_mfc_mem[0].base = rbase; | ||
| 90 | s5p_mfc_mem[0].size = rsize; | ||
| 91 | |||
| 92 | s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev; | ||
| 93 | s5p_mfc_mem[1].base = lbase; | ||
| 94 | s5p_mfc_mem[1].size = lsize; | ||
| 95 | |||
| 96 | for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { | ||
| 97 | struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; | ||
| 98 | if (memblock_remove(area->base, area->size)) { | ||
| 99 | printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n", | ||
| 100 | area->size, (unsigned long) area->base); | ||
| 101 | area->base = 0; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | static int __init s5p_mfc_memory_init(void) | ||
| 107 | { | ||
| 108 | int i; | ||
| 109 | |||
| 110 | for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { | ||
| 111 | struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; | ||
| 112 | if (!area->base) | ||
| 113 | continue; | ||
| 114 | |||
| 115 | if (dma_declare_coherent_memory(area->dev, area->base, | ||
| 116 | area->base, area->size, | ||
| 117 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) | ||
| 118 | printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n", | ||
| 119 | area->size, (unsigned long) area->base); | ||
| 120 | } | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | device_initcall(s5p_mfc_memory_init); | ||
diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c new file mode 100644 index 00000000000..20336c8f247 --- /dev/null +++ b/arch/arm/plat-s5p/dev-onenand.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-onenand.c | ||
| 2 | * | ||
| 3 | * Copyright 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Copyright (c) 2008-2010 Samsung Electronics | ||
| 7 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
| 8 | * | ||
| 9 | * S5P series device definition for OneNAND devices | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | |||
| 19 | #include <mach/irqs.h> | ||
| 20 | #include <mach/map.h> | ||
| 21 | |||
| 22 | static struct resource s5p_onenand_resources[] = { | ||
| 23 | [0] = { | ||
| 24 | .start = S5P_PA_ONENAND, | ||
| 25 | .end = S5P_PA_ONENAND + SZ_128K - 1, | ||
| 26 | .flags = IORESOURCE_MEM, | ||
| 27 | }, | ||
| 28 | [1] = { | ||
| 29 | .start = S5P_PA_ONENAND_DMA, | ||
| 30 | .end = S5P_PA_ONENAND_DMA + SZ_8K - 1, | ||
| 31 | .flags = IORESOURCE_MEM, | ||
| 32 | }, | ||
| 33 | [2] = { | ||
| 34 | .start = IRQ_ONENAND_AUDI, | ||
| 35 | .end = IRQ_ONENAND_AUDI, | ||
| 36 | .flags = IORESOURCE_IRQ, | ||
| 37 | }, | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct platform_device s5p_device_onenand = { | ||
| 41 | .name = "s5pc110-onenand", | ||
| 42 | .id = -1, | ||
| 43 | .num_resources = ARRAY_SIZE(s5p_onenand_resources), | ||
| 44 | .resource = s5p_onenand_resources, | ||
| 45 | }; | ||
diff --git a/arch/arm/plat-s5p/dev-pmu.c b/arch/arm/plat-s5p/dev-pmu.c new file mode 100644 index 00000000000..a08576da72b --- /dev/null +++ b/arch/arm/plat-s5p/dev-pmu.c | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/plat-s5p/dev-pmu.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
| 5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <asm/pmu.h> | ||
| 16 | #include <mach/irqs.h> | ||
| 17 | |||
| 18 | static struct resource s5p_pmu_resource = { | ||
| 19 | .start = IRQ_PMU, | ||
| 20 | .end = IRQ_PMU, | ||
| 21 | .flags = IORESOURCE_IRQ, | ||
| 22 | }; | ||
| 23 | |||
| 24 | struct platform_device s5p_device_pmu = { | ||
| 25 | .name = "arm-pmu", | ||
| 26 | .id = ARM_PMU_DEVICE_CPU, | ||
| 27 | .num_resources = 1, | ||
| 28 | .resource = &s5p_pmu_resource, | ||
| 29 | }; | ||
| 30 | |||
| 31 | static int __init s5p_pmu_init(void) | ||
| 32 | { | ||
| 33 | platform_device_register(&s5p_device_pmu); | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | arch_initcall(s5p_pmu_init); | ||
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c new file mode 100644 index 00000000000..afaf87fdb93 --- /dev/null +++ b/arch/arm/plat-s5p/dev-uart.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/dev-uart.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * Base S5P UART resource and device definitions | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | |||
| 19 | #include <asm/mach/arch.h> | ||
| 20 | #include <asm/mach/irq.h> | ||
| 21 | #include <mach/hardware.h> | ||
| 22 | #include <mach/map.h> | ||
| 23 | |||
| 24 | #include <plat/devs.h> | ||
| 25 | |||
| 26 | /* Serial port registrations */ | ||
| 27 | |||
| 28 | static struct resource s5p_uart0_resource[] = { | ||
| 29 | [0] = { | ||
| 30 | .start = S5P_PA_UART0, | ||
| 31 | .end = S5P_PA_UART0 + S5P_SZ_UART - 1, | ||
| 32 | .flags = IORESOURCE_MEM, | ||
| 33 | }, | ||
| 34 | [1] = { | ||
| 35 | .start = IRQ_S5P_UART_RX0, | ||
| 36 | .end = IRQ_S5P_UART_RX0, | ||
| 37 | .flags = IORESOURCE_IRQ, | ||
| 38 | }, | ||
| 39 | [2] = { | ||
| 40 | .start = IRQ_S5P_UART_TX0, | ||
| 41 | .end = IRQ_S5P_UART_TX0, | ||
| 42 | .flags = IORESOURCE_IRQ, | ||
| 43 | }, | ||
| 44 | [3] = { | ||
| 45 | .start = IRQ_S5P_UART_ERR0, | ||
| 46 | .end = IRQ_S5P_UART_ERR0, | ||
| 47 | .flags = IORESOURCE_IRQ, | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct resource s5p_uart1_resource[] = { | ||
| 52 | [0] = { | ||
| 53 | .start = S5P_PA_UART1, | ||
| 54 | .end = S5P_PA_UART1 + S5P_SZ_UART - 1, | ||
| 55 | .flags = IORESOURCE_MEM, | ||
| 56 | }, | ||
| 57 | [1] = { | ||
| 58 | .start = IRQ_S5P_UART_RX1, | ||
| 59 | .end = IRQ_S5P_UART_RX1, | ||
| 60 | .flags = IORESOURCE_IRQ, | ||
| 61 | }, | ||
| 62 | [2] = { | ||
| 63 | .start = IRQ_S5P_UART_TX1, | ||
| 64 | .end = IRQ_S5P_UART_TX1, | ||
| 65 | .flags = IORESOURCE_IRQ, | ||
| 66 | }, | ||
| 67 | [3] = { | ||
| 68 | .start = IRQ_S5P_UART_ERR1, | ||
| 69 | .end = IRQ_S5P_UART_ERR1, | ||
| 70 | .flags = IORESOURCE_IRQ, | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static struct resource s5p_uart2_resource[] = { | ||
| 75 | [0] = { | ||
| 76 | .start = S5P_PA_UART2, | ||
| 77 | .end = S5P_PA_UART2 + S5P_SZ_UART - 1, | ||
| 78 | .flags = IORESOURCE_MEM, | ||
| 79 | }, | ||
| 80 | [1] = { | ||
| 81 | .start = IRQ_S5P_UART_RX2, | ||
| 82 | .end = IRQ_S5P_UART_RX2, | ||
| 83 | .flags = IORESOURCE_IRQ, | ||
| 84 | }, | ||
| 85 | [2] = { | ||
| 86 | .start = IRQ_S5P_UART_TX2, | ||
| 87 | .end = IRQ_S5P_UART_TX2, | ||
| 88 | .flags = IORESOURCE_IRQ, | ||
| 89 | }, | ||
| 90 | [3] = { | ||
| 91 | .start = IRQ_S5P_UART_ERR2, | ||
| 92 | .end = IRQ_S5P_UART_ERR2, | ||
| 93 | .flags = IORESOURCE_IRQ, | ||
| 94 | }, | ||
| 95 | }; | ||
| 96 | |||
| 97 | static struct resource s5p_uart3_resource[] = { | ||
| 98 | #if CONFIG_SERIAL_SAMSUNG_UARTS > 3 | ||
| 99 | [0] = { | ||
| 100 | .start = S5P_PA_UART3, | ||
| 101 | .end = S5P_PA_UART3 + S5P_SZ_UART - 1, | ||
| 102 | .flags = IORESOURCE_MEM, | ||
| 103 | }, | ||
| 104 | [1] = { | ||
| 105 | .start = IRQ_S5P_UART_RX3, | ||
| 106 | .end = IRQ_S5P_UART_RX3, | ||
| 107 | .flags = IORESOURCE_IRQ, | ||
| 108 | }, | ||
| 109 | [2] = { | ||
| 110 | .start = IRQ_S5P_UART_TX3, | ||
| 111 | .end = IRQ_S5P_UART_TX3, | ||
| 112 | .flags = IORESOURCE_IRQ, | ||
| 113 | }, | ||
| 114 | [3] = { | ||
| 115 | .start = IRQ_S5P_UART_ERR3, | ||
| 116 | .end = IRQ_S5P_UART_ERR3, | ||
| 117 | .flags = IORESOURCE_IRQ, | ||
| 118 | }, | ||
| 119 | #endif | ||
| 120 | }; | ||
| 121 | |||
| 122 | static struct resource s5p_uart4_resource[] = { | ||
| 123 | #if CONFIG_SERIAL_SAMSUNG_UARTS > 4 | ||
| 124 | [0] = { | ||
| 125 | .start = S5P_PA_UART4, | ||
| 126 | .end = S5P_PA_UART4 + S5P_SZ_UART - 1, | ||
| 127 | .flags = IORESOURCE_MEM, | ||
| 128 | }, | ||
| 129 | [1] = { | ||
| 130 | .start = IRQ_S5P_UART_RX4, | ||
| 131 | .end = IRQ_S5P_UART_RX4, | ||
| 132 | .flags = IORESOURCE_IRQ, | ||
| 133 | }, | ||
| 134 | [2] = { | ||
| 135 | .start = IRQ_S5P_UART_TX4, | ||
| 136 | .end = IRQ_S5P_UART_TX4, | ||
| 137 | .flags = IORESOURCE_IRQ, | ||
| 138 | }, | ||
| 139 | [3] = { | ||
| 140 | .start = IRQ_S5P_UART_ERR4, | ||
| 141 | .end = IRQ_S5P_UART_ERR4, | ||
| 142 | .flags = IORESOURCE_IRQ, | ||
| 143 | }, | ||
| 144 | #endif | ||
| 145 | }; | ||
| 146 | |||
| 147 | static struct resource s5p_uart5_resource[] = { | ||
| 148 | #if CONFIG_SERIAL_SAMSUNG_UARTS > 5 | ||
| 149 | [0] = { | ||
| 150 | .start = S5P_PA_UART5, | ||
| 151 | .end = S5P_PA_UART5 + S5P_SZ_UART - 1, | ||
| 152 | .flags = IORESOURCE_MEM, | ||
| 153 | }, | ||
| 154 | [1] = { | ||
| 155 | .start = IRQ_S5P_UART_RX5, | ||
| 156 | .end = IRQ_S5P_UART_RX5, | ||
| 157 | .flags = IORESOURCE_IRQ, | ||
| 158 | }, | ||
| 159 | [2] = { | ||
| 160 | .start = IRQ_S5P_UART_TX5, | ||
| 161 | .end = IRQ_S5P_UART_TX5, | ||
| 162 | .flags = IORESOURCE_IRQ, | ||
| 163 | }, | ||
| 164 | [3] = { | ||
| 165 | .start = IRQ_S5P_UART_ERR5, | ||
| 166 | .end = IRQ_S5P_UART_ERR5, | ||
| 167 | .flags = IORESOURCE_IRQ, | ||
| 168 | }, | ||
| 169 | #endif | ||
| 170 | }; | ||
| 171 | |||
| 172 | struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { | ||
| 173 | [0] = { | ||
| 174 | .resources = s5p_uart0_resource, | ||
| 175 | .nr_resources = ARRAY_SIZE(s5p_uart0_resource), | ||
| 176 | }, | ||
| 177 | [1] = { | ||
| 178 | .resources = s5p_uart1_resource, | ||
| 179 | .nr_resources = ARRAY_SIZE(s5p_uart1_resource), | ||
| 180 | }, | ||
| 181 | [2] = { | ||
| 182 | .resources = s5p_uart2_resource, | ||
| 183 | .nr_resources = ARRAY_SIZE(s5p_uart2_resource), | ||
| 184 | }, | ||
| 185 | [3] = { | ||
| 186 | .resources = s5p_uart3_resource, | ||
| 187 | .nr_resources = ARRAY_SIZE(s5p_uart3_resource), | ||
| 188 | }, | ||
| 189 | [4] = { | ||
| 190 | .resources = s5p_uart4_resource, | ||
| 191 | .nr_resources = ARRAY_SIZE(s5p_uart4_resource), | ||
| 192 | }, | ||
| 193 | [5] = { | ||
| 194 | .resources = s5p_uart5_resource, | ||
| 195 | .nr_resources = ARRAY_SIZE(s5p_uart5_resource), | ||
| 196 | }, | ||
| 197 | }; | ||
diff --git a/arch/arm/plat-s5p/include/plat/camport.h b/arch/arm/plat-s5p/include/plat/camport.h new file mode 100644 index 00000000000..71688c8ba28 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/camport.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * S5P series camera interface helper functions | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef PLAT_S5P_CAMPORT_H_ | ||
| 12 | #define PLAT_S5P_CAMPORT_H_ __FILE__ | ||
| 13 | |||
| 14 | enum s5p_camport_id { | ||
| 15 | S5P_CAMPORT_A, | ||
| 16 | S5P_CAMPORT_B, | ||
| 17 | }; | ||
| 18 | |||
| 19 | /* | ||
| 20 | * The helper functions to configure GPIO for the camera parallel bus. | ||
| 21 | * The camera port can be multiplexed with any FIMC entity, even multiple | ||
| 22 | * FIMC entities are allowed to be attached to a single port simultaneously. | ||
| 23 | * These functions are to be used in the board setup code. | ||
| 24 | */ | ||
| 25 | int s5pv210_fimc_setup_gpio(enum s5p_camport_id id); | ||
| 26 | int exynos4_fimc_setup_gpio(enum s5p_camport_id id); | ||
| 27 | |||
| 28 | #endif | ||
diff --git a/arch/arm/plat-s5p/include/plat/ehci.h b/arch/arm/plat-s5p/include/plat/ehci.h new file mode 100644 index 00000000000..6ae6810c756 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/ehci.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
| 3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __PLAT_S5P_EHCI_H | ||
| 12 | #define __PLAT_S5P_EHCI_H | ||
| 13 | |||
| 14 | struct s5p_ehci_platdata { | ||
| 15 | int (*phy_init)(struct platform_device *pdev, int type); | ||
| 16 | int (*phy_exit)(struct platform_device *pdev, int type); | ||
| 17 | }; | ||
| 18 | |||
| 19 | extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd); | ||
| 20 | |||
| 21 | #endif /* __PLAT_S5P_EHCI_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h new file mode 100644 index 00000000000..907caab53dc --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/exynos4.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/exynos4.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Header file for exynos4 cpu support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* Common init code for EXYNOS4 related SoCs */ | ||
| 14 | |||
| 15 | extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
| 16 | extern void exynos4_register_clocks(void); | ||
| 17 | extern void exynos4_setup_clocks(void); | ||
| 18 | |||
| 19 | #ifdef CONFIG_CPU_EXYNOS4210 | ||
| 20 | |||
| 21 | extern int exynos4_init(void); | ||
| 22 | extern void exynos4_init_irq(void); | ||
| 23 | extern void exynos4_map_io(void); | ||
| 24 | extern void exynos4_init_clocks(int xtal); | ||
| 25 | extern struct sys_timer exynos4_timer; | ||
| 26 | |||
| 27 | #define exynos4_init_uarts exynos4_common_init_uarts | ||
| 28 | |||
| 29 | #else | ||
| 30 | #define exynos4_init_clocks NULL | ||
| 31 | #define exynos4_init_uarts NULL | ||
| 32 | #define exynos4_map_io NULL | ||
| 33 | #define exynos4_init NULL | ||
| 34 | #endif | ||
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h new file mode 100644 index 00000000000..ba9121c60a2 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/irqs.h | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/irqs.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P Common IRQ support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM_PLAT_S5P_IRQS_H | ||
| 14 | #define __ASM_PLAT_S5P_IRQS_H __FILE__ | ||
| 15 | |||
| 16 | /* we keep the first set of CPU IRQs out of the range of | ||
| 17 | * the ISA space, so that the PC104 has them to itself | ||
| 18 | * and we don't end up having to do horrible things to the | ||
| 19 | * standard ISA drivers.... | ||
| 20 | * | ||
| 21 | * note, since we're using the VICs, our start must be a | ||
| 22 | * mulitple of 32 to allow the common code to work | ||
| 23 | */ | ||
| 24 | |||
| 25 | #define S5P_IRQ_OFFSET (32) | ||
| 26 | |||
| 27 | #define S5P_IRQ(x) ((x) + S5P_IRQ_OFFSET) | ||
| 28 | |||
| 29 | #define S5P_VIC0_BASE S5P_IRQ(0) | ||
| 30 | #define S5P_VIC1_BASE S5P_IRQ(32) | ||
| 31 | #define S5P_VIC2_BASE S5P_IRQ(64) | ||
| 32 | #define S5P_VIC3_BASE S5P_IRQ(96) | ||
| 33 | |||
| 34 | #define VIC_BASE(x) (S5P_VIC0_BASE + ((x)*32)) | ||
| 35 | |||
| 36 | #define IRQ_VIC0_BASE S5P_VIC0_BASE | ||
| 37 | #define IRQ_VIC1_BASE S5P_VIC1_BASE | ||
| 38 | #define IRQ_VIC2_BASE S5P_VIC2_BASE | ||
| 39 | |||
| 40 | /* UART interrupts, each UART has 4 intterupts per channel so | ||
| 41 | * use the space between the ISA and S3C main interrupts. Note, these | ||
| 42 | * are not in the same order as the S3C24XX series! */ | ||
| 43 | |||
| 44 | #define IRQ_S5P_UART_BASE0 (16) | ||
| 45 | #define IRQ_S5P_UART_BASE1 (20) | ||
| 46 | #define IRQ_S5P_UART_BASE2 (24) | ||
| 47 | #define IRQ_S5P_UART_BASE3 (28) | ||
| 48 | |||
| 49 | #define UART_IRQ_RXD (0) | ||
| 50 | #define UART_IRQ_ERR (1) | ||
| 51 | #define UART_IRQ_TXD (2) | ||
| 52 | |||
| 53 | #define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD) | ||
| 54 | #define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD) | ||
| 55 | #define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR) | ||
| 56 | |||
| 57 | #define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD) | ||
| 58 | #define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD) | ||
| 59 | #define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR) | ||
| 60 | |||
| 61 | #define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD) | ||
| 62 | #define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD) | ||
| 63 | #define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR) | ||
| 64 | |||
| 65 | #define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD) | ||
| 66 | #define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD) | ||
| 67 | #define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR) | ||
| 68 | |||
| 69 | /* S3C compatibilty defines */ | ||
| 70 | #define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0 | ||
| 71 | #define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1 | ||
| 72 | #define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2 | ||
| 73 | #define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3 | ||
| 74 | |||
| 75 | /* VIC based IRQs */ | ||
| 76 | |||
| 77 | #define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x)) | ||
| 78 | #define S5P_IRQ_VIC1(x) (S5P_VIC1_BASE + (x)) | ||
| 79 | #define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x)) | ||
| 80 | #define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x)) | ||
| 81 | |||
| 82 | #define S5P_TIMER_IRQ(x) (11 + (x)) | ||
| 83 | |||
| 84 | #define IRQ_TIMER0 S5P_TIMER_IRQ(0) | ||
| 85 | #define IRQ_TIMER1 S5P_TIMER_IRQ(1) | ||
| 86 | #define IRQ_TIMER2 S5P_TIMER_IRQ(2) | ||
| 87 | #define IRQ_TIMER3 S5P_TIMER_IRQ(3) | ||
| 88 | #define IRQ_TIMER4 S5P_TIMER_IRQ(4) | ||
| 89 | |||
| 90 | #define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \ | ||
| 91 | : ((x) - 16 + S5P_EINT_BASE2)) | ||
| 92 | |||
| 93 | #define EINT_OFFSET(irq) ((irq) < S5P_EINT_BASE2 ? \ | ||
| 94 | ((irq) - S5P_EINT_BASE1) : \ | ||
| 95 | ((irq) + 16 - S5P_EINT_BASE2)) | ||
| 96 | |||
| 97 | #define IRQ_EINT_BIT(x) EINT_OFFSET(x) | ||
| 98 | |||
| 99 | /* Typically only a few gpio chips require gpio interrupt support. | ||
| 100 | To avoid memory waste irq descriptors are allocated only for | ||
| 101 | S5P_GPIOINT_GROUP_COUNT chips, each with total number of | ||
| 102 | S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged | ||
| 103 | to any gpio chip with the s5p_register_gpio_interrupt() function */ | ||
| 104 | #define S5P_GPIOINT_GROUP_COUNT 4 | ||
| 105 | #define S5P_GPIOINT_GROUP_SIZE 8 | ||
| 106 | #define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE) | ||
| 107 | |||
| 108 | /* IRQ types common for all s5p platforms */ | ||
| 109 | #define S5P_IRQ_TYPE_LEVEL_LOW (0x00) | ||
| 110 | #define S5P_IRQ_TYPE_LEVEL_HIGH (0x01) | ||
| 111 | #define S5P_IRQ_TYPE_EDGE_FALLING (0x02) | ||
| 112 | #define S5P_IRQ_TYPE_EDGE_RISING (0x03) | ||
| 113 | #define S5P_IRQ_TYPE_EDGE_BOTH (0x04) | ||
| 114 | |||
| 115 | #endif /* __ASM_PLAT_S5P_IRQS_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h new file mode 100644 index 00000000000..36d3551173b --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/map-s5p.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P - Memory map definitions | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM_PLAT_MAP_S5P_H | ||
| 14 | #define __ASM_PLAT_MAP_S5P_H __FILE__ | ||
| 15 | |||
| 16 | #define S5P_VA_CHIPID S3C_ADDR(0x02000000) | ||
| 17 | #define S5P_VA_CMU S3C_ADDR(0x02100000) | ||
| 18 | #define S5P_VA_PMU S3C_ADDR(0x02180000) | ||
| 19 | #define S5P_VA_GPIO S3C_ADDR(0x02200000) | ||
| 20 | #define S5P_VA_GPIO1 S5P_VA_GPIO | ||
| 21 | #define S5P_VA_GPIO2 S3C_ADDR(0x02240000) | ||
| 22 | #define S5P_VA_GPIO3 S3C_ADDR(0x02280000) | ||
| 23 | |||
| 24 | #define S5P_VA_SYSRAM S3C_ADDR(0x02400000) | ||
| 25 | #define S5P_VA_DMC0 S3C_ADDR(0x02440000) | ||
| 26 | #define S5P_VA_DMC1 S3C_ADDR(0x02480000) | ||
| 27 | #define S5P_VA_SROMC S3C_ADDR(0x024C0000) | ||
| 28 | |||
| 29 | #define S5P_VA_SYSTIMER S3C_ADDR(0x02500000) | ||
| 30 | #define S5P_VA_L2CC S3C_ADDR(0x02600000) | ||
| 31 | |||
| 32 | #define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000) | ||
| 33 | #define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) | ||
| 34 | |||
| 35 | #define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) | ||
| 36 | #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) | ||
| 37 | #define S5P_VA_SCU S5P_VA_COREPERI(0x0) | ||
| 38 | #define S5P_VA_TWD S5P_VA_COREPERI(0x600) | ||
| 39 | |||
| 40 | #define S5P_VA_GIC_CPU S3C_ADDR(0x02810000) | ||
| 41 | #define S5P_VA_GIC_DIST S3C_ADDR(0x02820000) | ||
| 42 | |||
| 43 | #define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) | ||
| 44 | |||
| 45 | #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) | ||
| 46 | #define VA_VIC0 VA_VIC(0) | ||
| 47 | #define VA_VIC1 VA_VIC(1) | ||
| 48 | #define VA_VIC2 VA_VIC(2) | ||
| 49 | #define VA_VIC3 VA_VIC(3) | ||
| 50 | |||
| 51 | #define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) | ||
| 52 | #define S5P_VA_UART0 S5P_VA_UART(0) | ||
| 53 | #define S5P_VA_UART1 S5P_VA_UART(1) | ||
| 54 | #define S5P_VA_UART2 S5P_VA_UART(2) | ||
| 55 | #define S5P_VA_UART3 S5P_VA_UART(3) | ||
| 56 | |||
| 57 | #ifndef S3C_UART_OFFSET | ||
| 58 | #define S3C_UART_OFFSET (0x400) | ||
| 59 | #endif | ||
| 60 | |||
| 61 | #endif /* __ASM_PLAT_MAP_S5P_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/mfc.h b/arch/arm/plat-s5p/include/plat/mfc.h new file mode 100644 index 00000000000..6697f8cb294 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/mfc.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms of the GNU General Public License as published by the | ||
| 6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 7 | * option) any later version. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef __PLAT_S5P_MFC_H | ||
| 11 | #define __PLAT_S5P_MFC_H | ||
| 12 | |||
| 13 | /** | ||
| 14 | * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver | ||
| 15 | * @rbase: base address for MFC 'right' memory interface | ||
| 16 | * @rsize: size of the memory reserved for MFC 'right' interface | ||
| 17 | * @lbase: base address for MFC 'left' memory interface | ||
| 18 | * @lsize: size of the memory reserved for MFC 'left' interface | ||
| 19 | * | ||
| 20 | * This function reserves system memory for both MFC device memory | ||
| 21 | * interfaces and registers it to respective struct device entries as | ||
| 22 | * coherent memory. | ||
| 23 | */ | ||
| 24 | void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, | ||
| 25 | phys_addr_t lbase, unsigned int lsize); | ||
| 26 | |||
| 27 | #endif /* __PLAT_S5P_MFC_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/mipi_csis.h b/arch/arm/plat-s5p/include/plat/mipi_csis.h new file mode 100644 index 00000000000..9bd254c5ed2 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/mipi_csis.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * S5P series MIPI CSI slave device support | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef PLAT_S5P_MIPI_CSIS_H_ | ||
| 12 | #define PLAT_S5P_MIPI_CSIS_H_ __FILE__ | ||
| 13 | |||
| 14 | struct platform_device; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver | ||
| 18 | * @clk_rate: bus clock frequency | ||
| 19 | * @lanes: number of data lanes used | ||
| 20 | * @alignment: data alignment in bits | ||
| 21 | * @hs_settle: HS-RX settle time | ||
| 22 | * @fixed_phy_vdd: false to enable external D-PHY regulator management in the | ||
| 23 | * driver or true in case this regulator has no enable function | ||
| 24 | * @phy_enable: pointer to a callback controlling D-PHY enable/reset | ||
| 25 | */ | ||
| 26 | struct s5p_platform_mipi_csis { | ||
| 27 | unsigned long clk_rate; | ||
| 28 | u8 lanes; | ||
| 29 | u8 alignment; | ||
| 30 | u8 hs_settle; | ||
| 31 | bool fixed_phy_vdd; | ||
| 32 | int (*phy_enable)(struct platform_device *pdev, bool on); | ||
| 33 | }; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control | ||
| 37 | * @pdev: MIPI-CSIS platform device | ||
| 38 | * @on: true to enable D-PHY and deassert its reset | ||
| 39 | * false to disable D-PHY | ||
| 40 | */ | ||
| 41 | int s5p_csis_phy_enable(struct platform_device *pdev, bool on); | ||
| 42 | |||
| 43 | #endif /* PLAT_S5P_MIPI_CSIS_H_ */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h new file mode 100644 index 00000000000..bf28fadee7a --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/pll.h | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /* arch/arm/plat-s5p/include/plat/pll.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P PLL code | ||
| 7 | * | ||
| 8 | * Based on arch/arm/plat-s3c64xx/include/plat/pll.h | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define PLL45XX_MDIV_MASK (0x3FF) | ||
| 16 | #define PLL45XX_PDIV_MASK (0x3F) | ||
| 17 | #define PLL45XX_SDIV_MASK (0x7) | ||
| 18 | #define PLL45XX_MDIV_SHIFT (16) | ||
| 19 | #define PLL45XX_PDIV_SHIFT (8) | ||
| 20 | #define PLL45XX_SDIV_SHIFT (0) | ||
| 21 | |||
| 22 | #include <asm/div64.h> | ||
| 23 | |||
| 24 | enum pll45xx_type_t { | ||
| 25 | pll_4500, | ||
| 26 | pll_4502, | ||
| 27 | pll_4508 | ||
| 28 | }; | ||
| 29 | |||
| 30 | static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, | ||
| 31 | enum pll45xx_type_t pll_type) | ||
| 32 | { | ||
| 33 | u32 mdiv, pdiv, sdiv; | ||
| 34 | u64 fvco = baseclk; | ||
| 35 | |||
| 36 | mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK; | ||
| 37 | pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK; | ||
| 38 | sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK; | ||
| 39 | |||
| 40 | if (pll_type == pll_4508) | ||
| 41 | sdiv = sdiv - 1; | ||
| 42 | |||
| 43 | fvco *= mdiv; | ||
| 44 | do_div(fvco, (pdiv << sdiv)); | ||
| 45 | |||
| 46 | return (unsigned long)fvco; | ||
| 47 | } | ||
| 48 | |||
| 49 | #define PLL46XX_KDIV_MASK (0xFFFF) | ||
| 50 | #define PLL4650C_KDIV_MASK (0xFFF) | ||
| 51 | #define PLL46XX_MDIV_MASK (0x1FF) | ||
| 52 | #define PLL46XX_PDIV_MASK (0x3F) | ||
| 53 | #define PLL46XX_SDIV_MASK (0x7) | ||
| 54 | #define PLL46XX_MDIV_SHIFT (16) | ||
| 55 | #define PLL46XX_PDIV_SHIFT (8) | ||
| 56 | #define PLL46XX_SDIV_SHIFT (0) | ||
| 57 | |||
| 58 | enum pll46xx_type_t { | ||
| 59 | pll_4600, | ||
| 60 | pll_4650, | ||
| 61 | pll_4650c, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, | ||
| 65 | u32 pll_con0, u32 pll_con1, | ||
| 66 | enum pll46xx_type_t pll_type) | ||
| 67 | { | ||
| 68 | unsigned long result; | ||
| 69 | u32 mdiv, pdiv, sdiv, kdiv; | ||
| 70 | u64 tmp; | ||
| 71 | |||
| 72 | mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; | ||
| 73 | pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; | ||
| 74 | sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; | ||
| 75 | kdiv = pll_con1 & PLL46XX_KDIV_MASK; | ||
| 76 | |||
| 77 | if (pll_type == pll_4650c) | ||
| 78 | kdiv = pll_con1 & PLL4650C_KDIV_MASK; | ||
| 79 | else | ||
| 80 | kdiv = pll_con1 & PLL46XX_KDIV_MASK; | ||
| 81 | |||
| 82 | tmp = baseclk; | ||
| 83 | |||
| 84 | if (pll_type == pll_4600) { | ||
| 85 | tmp *= (mdiv << 16) + kdiv; | ||
| 86 | do_div(tmp, (pdiv << sdiv)); | ||
| 87 | result = tmp >> 16; | ||
| 88 | } else { | ||
| 89 | tmp *= (mdiv << 10) + kdiv; | ||
| 90 | do_div(tmp, (pdiv << sdiv)); | ||
| 91 | result = tmp >> 10; | ||
| 92 | } | ||
| 93 | |||
| 94 | return result; | ||
| 95 | } | ||
| 96 | |||
| 97 | #define PLL90XX_MDIV_MASK (0xFF) | ||
| 98 | #define PLL90XX_PDIV_MASK (0x3F) | ||
| 99 | #define PLL90XX_SDIV_MASK (0x7) | ||
| 100 | #define PLL90XX_KDIV_MASK (0xffff) | ||
| 101 | #define PLL90XX_MDIV_SHIFT (16) | ||
| 102 | #define PLL90XX_PDIV_SHIFT (8) | ||
| 103 | #define PLL90XX_SDIV_SHIFT (0) | ||
| 104 | #define PLL90XX_KDIV_SHIFT (0) | ||
| 105 | |||
| 106 | static inline unsigned long s5p_get_pll90xx(unsigned long baseclk, | ||
| 107 | u32 pll_con, u32 pll_conk) | ||
| 108 | { | ||
| 109 | unsigned long result; | ||
| 110 | u32 mdiv, pdiv, sdiv, kdiv; | ||
| 111 | u64 tmp; | ||
| 112 | |||
| 113 | mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK; | ||
| 114 | pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK; | ||
| 115 | sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK; | ||
| 116 | kdiv = pll_conk & PLL90XX_KDIV_MASK; | ||
| 117 | |||
| 118 | /* We need to multiple baseclk by mdiv (the integer part) and kdiv | ||
| 119 | * which is in 2^16ths, so shift mdiv up (does not overflow) and | ||
| 120 | * add kdiv before multiplying. The use of tmp is to avoid any | ||
| 121 | * overflows before shifting bac down into result when multipling | ||
| 122 | * by the mdiv and kdiv pair. | ||
| 123 | */ | ||
| 124 | |||
| 125 | tmp = baseclk; | ||
| 126 | tmp *= (mdiv << 16) + kdiv; | ||
| 127 | do_div(tmp, (pdiv << sdiv)); | ||
| 128 | result = tmp >> 16; | ||
| 129 | |||
| 130 | return result; | ||
| 131 | } | ||
| 132 | |||
| 133 | #define PLL65XX_MDIV_MASK (0x3FF) | ||
| 134 | #define PLL65XX_PDIV_MASK (0x3F) | ||
| 135 | #define PLL65XX_SDIV_MASK (0x7) | ||
| 136 | #define PLL65XX_MDIV_SHIFT (16) | ||
| 137 | #define PLL65XX_PDIV_SHIFT (8) | ||
| 138 | #define PLL65XX_SDIV_SHIFT (0) | ||
| 139 | |||
| 140 | static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con) | ||
| 141 | { | ||
| 142 | u32 mdiv, pdiv, sdiv; | ||
| 143 | u64 fvco = baseclk; | ||
| 144 | |||
| 145 | mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK; | ||
| 146 | pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK; | ||
| 147 | sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK; | ||
| 148 | |||
| 149 | fvco *= mdiv; | ||
| 150 | do_div(fvco, (pdiv << sdiv)); | ||
| 151 | |||
| 152 | return (unsigned long)fvco; | ||
| 153 | } | ||
diff --git a/arch/arm/plat-s5p/include/plat/regs-srom.h b/arch/arm/plat-s5p/include/plat/regs-srom.h new file mode 100644 index 00000000000..f121ab5e76c --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/regs-srom.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/regs-srom.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * S5P SROMC register definitions | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM_PLAT_S5P_REGS_SROM_H | ||
| 14 | #define __ASM_PLAT_S5P_REGS_SROM_H __FILE__ | ||
| 15 | |||
| 16 | #include <mach/map.h> | ||
| 17 | |||
| 18 | #define S5P_SROMREG(x) (S5P_VA_SROMC + (x)) | ||
| 19 | |||
| 20 | #define S5P_SROM_BW S5P_SROMREG(0x0) | ||
| 21 | #define S5P_SROM_BC0 S5P_SROMREG(0x4) | ||
| 22 | #define S5P_SROM_BC1 S5P_SROMREG(0x8) | ||
| 23 | #define S5P_SROM_BC2 S5P_SROMREG(0xc) | ||
| 24 | #define S5P_SROM_BC3 S5P_SROMREG(0x10) | ||
| 25 | #define S5P_SROM_BC4 S5P_SROMREG(0x14) | ||
| 26 | #define S5P_SROM_BC5 S5P_SROMREG(0x18) | ||
| 27 | |||
| 28 | /* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ | ||
| 29 | |||
| 30 | #define S5P_SROM_BW__DATAWIDTH__SHIFT 0 | ||
| 31 | #define S5P_SROM_BW__ADDRMODE__SHIFT 1 | ||
| 32 | #define S5P_SROM_BW__WAITENABLE__SHIFT 2 | ||
| 33 | #define S5P_SROM_BW__BYTEENABLE__SHIFT 3 | ||
| 34 | |||
| 35 | #define S5P_SROM_BW__CS_MASK 0xf | ||
| 36 | |||
| 37 | #define S5P_SROM_BW__NCS0__SHIFT 0 | ||
| 38 | #define S5P_SROM_BW__NCS1__SHIFT 4 | ||
| 39 | #define S5P_SROM_BW__NCS2__SHIFT 8 | ||
| 40 | #define S5P_SROM_BW__NCS3__SHIFT 12 | ||
| 41 | #define S5P_SROM_BW__NCS4__SHIFT 16 | ||
| 42 | #define S5P_SROM_BW__NCS5__SHIFT 20 | ||
| 43 | |||
| 44 | /* applies to same to BCS0 - BCS3 */ | ||
| 45 | |||
| 46 | #define S5P_SROM_BCX__PMC__SHIFT 0 | ||
| 47 | #define S5P_SROM_BCX__TACP__SHIFT 4 | ||
| 48 | #define S5P_SROM_BCX__TCAH__SHIFT 8 | ||
| 49 | #define S5P_SROM_BCX__TCOH__SHIFT 12 | ||
| 50 | #define S5P_SROM_BCX__TACC__SHIFT 16 | ||
| 51 | #define S5P_SROM_BCX__TCOS__SHIFT 24 | ||
| 52 | #define S5P_SROM_BCX__TACS__SHIFT 28 | ||
| 53 | |||
| 54 | #endif /* __ASM_PLAT_S5P_REGS_SROM_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/reset.h b/arch/arm/plat-s5p/include/plat/reset.h new file mode 100644 index 00000000000..335e97812ee --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/reset.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/reset.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __ASM_PLAT_S5P_RESET_H | ||
| 12 | #define __ASM_PLAT_S5P_RESET_H __FILE__ | ||
| 13 | |||
| 14 | extern void (*s5p_reset_hook)(void); | ||
| 15 | |||
| 16 | #endif /* __ASM_PLAT_S5P_RESET_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h new file mode 100644 index 00000000000..769b5bdfb04 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Header file for s5p clock support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM_PLAT_S5P_CLOCK_H | ||
| 14 | #define __ASM_PLAT_S5P_CLOCK_H __FILE__ | ||
| 15 | |||
| 16 | #include <linux/clk.h> | ||
| 17 | |||
| 18 | #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) | ||
| 19 | |||
| 20 | #define clk_fin_apll clk_ext_xtal_mux | ||
| 21 | #define clk_fin_mpll clk_ext_xtal_mux | ||
| 22 | #define clk_fin_epll clk_ext_xtal_mux | ||
| 23 | #define clk_fin_dpll clk_ext_xtal_mux | ||
| 24 | #define clk_fin_vpll clk_ext_xtal_mux | ||
| 25 | #define clk_fin_hpll clk_ext_xtal_mux | ||
| 26 | |||
| 27 | extern struct clk clk_ext_xtal_mux; | ||
| 28 | extern struct clk clk_xusbxti; | ||
| 29 | extern struct clk clk_48m; | ||
| 30 | extern struct clk s5p_clk_27m; | ||
| 31 | extern struct clk clk_fout_apll; | ||
| 32 | extern struct clk clk_fout_mpll; | ||
| 33 | extern struct clk clk_fout_epll; | ||
| 34 | extern struct clk clk_fout_dpll; | ||
| 35 | extern struct clk clk_fout_vpll; | ||
| 36 | extern struct clk clk_arm; | ||
| 37 | extern struct clk clk_vpll; | ||
| 38 | |||
| 39 | extern struct clksrc_sources clk_src_apll; | ||
| 40 | extern struct clksrc_sources clk_src_mpll; | ||
| 41 | extern struct clksrc_sources clk_src_epll; | ||
| 42 | extern struct clksrc_sources clk_src_dpll; | ||
| 43 | |||
| 44 | extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); | ||
| 45 | |||
| 46 | /* Common EPLL operations for S5P platform */ | ||
| 47 | extern int s5p_epll_enable(struct clk *clk, int enable); | ||
| 48 | extern unsigned long s5p_epll_get_rate(struct clk *clk); | ||
| 49 | |||
| 50 | /* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */ | ||
| 51 | extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate); | ||
| 52 | extern unsigned long s5p_spdif_get_rate(struct clk *clk); | ||
| 53 | |||
| 54 | extern struct clk_ops s5p_sclk_spdif_ops; | ||
| 55 | #endif /* __ASM_PLAT_S5P_CLOCK_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5p-time.h b/arch/arm/plat-s5p/include/plat/s5p-time.h new file mode 100644 index 00000000000..575e88109db --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p-time.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/s5p-time.h | ||
| 2 | * | ||
| 3 | * Copyright 2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * Header file for s5p time support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM_PLAT_S5P_TIME_H | ||
| 14 | #define __ASM_PLAT_S5P_TIME_H __FILE__ | ||
| 15 | |||
| 16 | /* S5P HR-Timer Clock mode */ | ||
| 17 | enum s5p_timer_mode { | ||
| 18 | S5P_PWM0, | ||
| 19 | S5P_PWM1, | ||
| 20 | S5P_PWM2, | ||
| 21 | S5P_PWM3, | ||
| 22 | S5P_PWM4, | ||
| 23 | }; | ||
| 24 | |||
| 25 | struct s5p_timer_source { | ||
| 26 | unsigned int event_id; | ||
| 27 | unsigned int source_id; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* Be able to sleep for atleast 4 seconds (usually more) */ | ||
| 31 | #define S5PTIMER_MIN_RANGE 4 | ||
| 32 | |||
| 33 | #define TCNT_MAX 0xffffffff | ||
| 34 | #define NON_PERIODIC 0 | ||
| 35 | #define PERIODIC 1 | ||
| 36 | |||
| 37 | extern void __init s5p_set_timer_source(enum s5p_timer_mode event, | ||
| 38 | enum s5p_timer_mode source); | ||
| 39 | extern struct sys_timer s5p_timer; | ||
| 40 | #endif /* __ASM_PLAT_S5P_TIME_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h new file mode 100644 index 00000000000..528585d2caf --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p6440.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* arch/arm/plat-s5p/include/plat/s5p6440.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * Header file for s5p6440 cpu support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* Common init code for S5P6440 related SoCs */ | ||
| 14 | |||
| 15 | extern void s5p6440_register_clocks(void); | ||
| 16 | extern void s5p6440_setup_clocks(void); | ||
| 17 | |||
| 18 | #ifdef CONFIG_CPU_S5P6440 | ||
| 19 | |||
| 20 | extern int s5p64x0_init(void); | ||
| 21 | extern void s5p6440_init_irq(void); | ||
| 22 | extern void s5p6440_map_io(void); | ||
| 23 | extern void s5p6440_init_clocks(int xtal); | ||
| 24 | |||
| 25 | extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
| 26 | |||
| 27 | #else | ||
| 28 | #define s5p6440_init_clocks NULL | ||
| 29 | #define s5p6440_init_uarts NULL | ||
| 30 | #define s5p6440_map_io NULL | ||
| 31 | #define s5p64x0_init NULL | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* S5P6440 timer */ | ||
| 35 | |||
| 36 | extern struct sys_timer s5p6440_timer; | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h new file mode 100644 index 00000000000..640a41c26be --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p6450.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* arch/arm/plat-s5p/include/plat/s5p6450.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Header file for s5p6450 cpu support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* Common init code for S5P6450 related SoCs */ | ||
| 14 | |||
| 15 | extern void s5p6450_register_clocks(void); | ||
| 16 | extern void s5p6450_setup_clocks(void); | ||
| 17 | |||
| 18 | #ifdef CONFIG_CPU_S5P6450 | ||
| 19 | |||
| 20 | extern int s5p64x0_init(void); | ||
| 21 | extern void s5p6450_init_irq(void); | ||
| 22 | extern void s5p6450_map_io(void); | ||
| 23 | extern void s5p6450_init_clocks(int xtal); | ||
| 24 | |||
| 25 | extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
| 26 | |||
| 27 | #else | ||
| 28 | #define s5p6450_init_clocks NULL | ||
| 29 | #define s5p6450_init_uarts NULL | ||
| 30 | #define s5p6450_map_io NULL | ||
| 31 | #define s5p64x0_init NULL | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* S5P6450 timer */ | ||
| 35 | |||
| 36 | extern struct sys_timer s5p6450_timer; | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5pc100.h b/arch/arm/plat-s5p/include/plat/s5pc100.h new file mode 100644 index 00000000000..5f6099dd7ca --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5pc100.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* arch/arm/plat-s5p/include/plat/s5pc100.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * Header file for s5pc100 cpu support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* Common init code for S5PC100 related SoCs */ | ||
| 14 | |||
| 15 | extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
| 16 | extern void s5pc100_register_clocks(void); | ||
| 17 | extern void s5pc100_setup_clocks(void); | ||
| 18 | |||
| 19 | #ifdef CONFIG_CPU_S5PC100 | ||
| 20 | |||
| 21 | extern int s5pc100_init(void); | ||
| 22 | extern void s5pc100_init_irq(void); | ||
| 23 | extern void s5pc100_map_io(void); | ||
| 24 | extern void s5pc100_init_clocks(int xtal); | ||
| 25 | |||
| 26 | #define s5pc100_init_uarts s5pc100_common_init_uarts | ||
| 27 | |||
| 28 | #else | ||
| 29 | #define s5pc100_init_clocks NULL | ||
| 30 | #define s5pc100_init_uarts NULL | ||
| 31 | #define s5pc100_map_io NULL | ||
| 32 | #define s5pc100_init NULL | ||
| 33 | #endif | ||
diff --git a/arch/arm/plat-s5p/include/plat/s5pv210.h b/arch/arm/plat-s5p/include/plat/s5pv210.h new file mode 100644 index 00000000000..6c93a0c7810 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5pv210.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/s5pv210.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * Header file for s5pv210 cpu support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* Common init code for S5PV210 related SoCs */ | ||
| 14 | |||
| 15 | extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
| 16 | extern void s5pv210_register_clocks(void); | ||
| 17 | extern void s5pv210_setup_clocks(void); | ||
| 18 | |||
| 19 | #ifdef CONFIG_CPU_S5PV210 | ||
| 20 | |||
| 21 | extern int s5pv210_init(void); | ||
| 22 | extern void s5pv210_init_irq(void); | ||
| 23 | extern void s5pv210_map_io(void); | ||
| 24 | extern void s5pv210_init_clocks(int xtal); | ||
| 25 | |||
| 26 | #define s5pv210_init_uarts s5pv210_common_init_uarts | ||
| 27 | |||
| 28 | #else | ||
| 29 | #define s5pv210_init_clocks NULL | ||
| 30 | #define s5pv210_init_uarts NULL | ||
| 31 | #define s5pv210_map_io NULL | ||
| 32 | #define s5pv210_init NULL | ||
| 33 | #endif | ||
diff --git a/arch/arm/plat-s5p/include/plat/sysmmu.h b/arch/arm/plat-s5p/include/plat/sysmmu.h new file mode 100644 index 00000000000..bf5283c2a19 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/sysmmu.h | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/sysmmu.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Samsung System MMU driver for S5P platform | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __ASM__PLAT_SYSMMU_H | ||
| 14 | #define __ASM__PLAT_SYSMMU_H __FILE__ | ||
| 15 | |||
| 16 | enum S5P_SYSMMU_INTERRUPT_TYPE { | ||
| 17 | SYSMMU_PAGEFAULT, | ||
| 18 | SYSMMU_AR_MULTIHIT, | ||
| 19 | SYSMMU_AW_MULTIHIT, | ||
| 20 | SYSMMU_BUSERROR, | ||
| 21 | SYSMMU_AR_SECURITY, | ||
| 22 | SYSMMU_AR_ACCESS, | ||
| 23 | SYSMMU_AW_SECURITY, | ||
| 24 | SYSMMU_AW_PROTECTION, /* 7 */ | ||
| 25 | SYSMMU_FAULTS_NUM | ||
| 26 | }; | ||
| 27 | |||
| 28 | #ifdef CONFIG_S5P_SYSTEM_MMU | ||
| 29 | |||
| 30 | #include <mach/sysmmu.h> | ||
| 31 | |||
| 32 | /** | ||
| 33 | * s5p_sysmmu_enable() - enable system mmu of ip | ||
| 34 | * @ips: The ip connected system mmu. | ||
| 35 | * #pgd: Base physical address of the 1st level page table | ||
| 36 | * | ||
| 37 | * This function enable system mmu to transfer address | ||
| 38 | * from virtual address to physical address | ||
| 39 | */ | ||
| 40 | void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd); | ||
| 41 | |||
| 42 | /** | ||
| 43 | * s5p_sysmmu_disable() - disable sysmmu mmu of ip | ||
| 44 | * @ips: The ip connected system mmu. | ||
| 45 | * | ||
| 46 | * This function disable system mmu to transfer address | ||
| 47 | * from virtual address to physical address | ||
| 48 | */ | ||
| 49 | void s5p_sysmmu_disable(sysmmu_ips ips); | ||
| 50 | |||
| 51 | /** | ||
| 52 | * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table | ||
| 53 | * @ips: The ip connected system mmu. | ||
| 54 | * @pgd: The page table base address. | ||
| 55 | * | ||
| 56 | * This function set page table base address | ||
| 57 | * When system mmu transfer address from virtaul address to physical address, | ||
| 58 | * system mmu refer address information from page table | ||
| 59 | */ | ||
| 60 | void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu | ||
| 64 | * @ips: The ip connected system mmu. | ||
| 65 | * | ||
| 66 | * This function flush all TLB entry in system mmu | ||
| 67 | */ | ||
| 68 | void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips); | ||
| 69 | |||
| 70 | /** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs | ||
| 71 | * @itype: type of fault. | ||
| 72 | * @pgtable_base: the physical address of page table base. This is 0 if @ips is | ||
| 73 | * SYSMMU_BUSERROR. | ||
| 74 | * @fault_addr: the device (virtual) address that the System MMU tried to | ||
| 75 | * translated. This is 0 if @ips is SYSMMU_BUSERROR. | ||
| 76 | * Called when interrupt occurred by the System MMUs | ||
| 77 | * The device drivers of peripheral devices that has a System MMU can implement | ||
| 78 | * a fault handler to resolve address translation fault by System MMU. | ||
| 79 | * The meanings of return value and parameters are described below. | ||
| 80 | |||
| 81 | * return value: non-zero if the fault is correctly resolved. | ||
| 82 | * zero if the fault is not handled. | ||
| 83 | */ | ||
| 84 | void s5p_sysmmu_set_fault_handler(sysmmu_ips ips, | ||
| 85 | int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
| 86 | unsigned long pgtable_base, | ||
| 87 | unsigned long fault_addr)); | ||
| 88 | #else | ||
| 89 | #define s5p_sysmmu_enable(ips, pgd) do { } while (0) | ||
| 90 | #define s5p_sysmmu_disable(ips) do { } while (0) | ||
| 91 | #define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0) | ||
| 92 | #define s5p_sysmmu_tlb_invalidate(ips) do { } while (0) | ||
| 93 | #define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0) | ||
| 94 | #endif | ||
| 95 | #endif /* __ASM_PLAT_SYSMMU_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/system-reset.h b/arch/arm/plat-s5p/include/plat/system-reset.h new file mode 100644 index 00000000000..f307f34e642 --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/system-reset.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/include/plat/system-reset.h | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h | ||
| 7 | * | ||
| 8 | * S5P - System define for arch_reset() | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <plat/watchdog-reset.h> | ||
| 16 | |||
| 17 | void (*s5p_reset_hook)(void); | ||
| 18 | |||
| 19 | static void arch_reset(char mode, const char *cmd) | ||
| 20 | { | ||
| 21 | /* SWRESET support in s5p_reset_hook() */ | ||
| 22 | |||
| 23 | if (s5p_reset_hook) | ||
| 24 | s5p_reset_hook(); | ||
| 25 | |||
| 26 | /* Perform reset using Watchdog reset | ||
| 27 | * if there is no s5p_reset_hook() | ||
| 28 | */ | ||
| 29 | |||
| 30 | arch_wdt_reset(); | ||
| 31 | } | ||
diff --git a/arch/arm/plat-s5p/include/plat/usb-phy.h b/arch/arm/plat-s5p/include/plat/usb-phy.h new file mode 100644 index 00000000000..6dd6bcfca3c --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/usb-phy.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
| 3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __PLAT_S5P_USB_PHY_H | ||
| 12 | #define __PLAT_S5P_USB_PHY_H | ||
| 13 | |||
| 14 | enum s5p_usb_phy_type { | ||
| 15 | S5P_USB_PHY_DEVICE, | ||
| 16 | S5P_USB_PHY_HOST, | ||
| 17 | }; | ||
| 18 | |||
| 19 | extern int s5p_usb_phy_init(struct platform_device *pdev, int type); | ||
| 20 | extern int s5p_usb_phy_exit(struct platform_device *pdev, int type); | ||
| 21 | |||
| 22 | #endif /* __PLAT_S5P_REGS_USB_PHY_H */ | ||
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c new file mode 100644 index 00000000000..b5bb774985b --- /dev/null +++ b/arch/arm/plat-s5p/irq-eint.c | |||
| @@ -0,0 +1,219 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/irq-eint.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * S5P - IRQ EINT support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/irq.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/sysdev.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | |||
| 20 | #include <asm/hardware/vic.h> | ||
| 21 | |||
| 22 | #include <plat/regs-irqtype.h> | ||
| 23 | |||
| 24 | #include <mach/map.h> | ||
| 25 | #include <plat/cpu.h> | ||
| 26 | #include <plat/pm.h> | ||
| 27 | |||
| 28 | #include <plat/gpio-cfg.h> | ||
| 29 | #include <mach/regs-gpio.h> | ||
| 30 | |||
| 31 | static inline void s5p_irq_eint_mask(struct irq_data *data) | ||
| 32 | { | ||
| 33 | u32 mask; | ||
| 34 | |||
| 35 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); | ||
| 36 | mask |= eint_irq_to_bit(data->irq); | ||
| 37 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); | ||
| 38 | } | ||
| 39 | |||
| 40 | static void s5p_irq_eint_unmask(struct irq_data *data) | ||
| 41 | { | ||
| 42 | u32 mask; | ||
| 43 | |||
| 44 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); | ||
| 45 | mask &= ~(eint_irq_to_bit(data->irq)); | ||
| 46 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline void s5p_irq_eint_ack(struct irq_data *data) | ||
| 50 | { | ||
| 51 | __raw_writel(eint_irq_to_bit(data->irq), | ||
| 52 | S5P_EINT_PEND(EINT_REG_NR(data->irq))); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void s5p_irq_eint_maskack(struct irq_data *data) | ||
| 56 | { | ||
| 57 | /* compiler should in-line these */ | ||
| 58 | s5p_irq_eint_mask(data); | ||
| 59 | s5p_irq_eint_ack(data); | ||
| 60 | } | ||
| 61 | |||
| 62 | static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type) | ||
| 63 | { | ||
| 64 | int offs = EINT_OFFSET(data->irq); | ||
| 65 | int shift; | ||
| 66 | u32 ctrl, mask; | ||
| 67 | u32 newvalue = 0; | ||
| 68 | |||
| 69 | switch (type) { | ||
| 70 | case IRQ_TYPE_EDGE_RISING: | ||
| 71 | newvalue = S5P_IRQ_TYPE_EDGE_RISING; | ||
| 72 | break; | ||
| 73 | |||
| 74 | case IRQ_TYPE_EDGE_FALLING: | ||
| 75 | newvalue = S5P_IRQ_TYPE_EDGE_FALLING; | ||
| 76 | break; | ||
| 77 | |||
| 78 | case IRQ_TYPE_EDGE_BOTH: | ||
| 79 | newvalue = S5P_IRQ_TYPE_EDGE_BOTH; | ||
| 80 | break; | ||
| 81 | |||
| 82 | case IRQ_TYPE_LEVEL_LOW: | ||
| 83 | newvalue = S5P_IRQ_TYPE_LEVEL_LOW; | ||
| 84 | break; | ||
| 85 | |||
| 86 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 87 | newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; | ||
| 88 | break; | ||
| 89 | |||
| 90 | default: | ||
| 91 | printk(KERN_ERR "No such irq type %d", type); | ||
| 92 | return -EINVAL; | ||
| 93 | } | ||
| 94 | |||
| 95 | shift = (offs & 0x7) * 4; | ||
| 96 | mask = 0x7 << shift; | ||
| 97 | |||
| 98 | ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); | ||
| 99 | ctrl &= ~mask; | ||
| 100 | ctrl |= newvalue << shift; | ||
| 101 | __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); | ||
| 102 | |||
| 103 | if ((0 <= offs) && (offs < 8)) | ||
| 104 | s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); | ||
| 105 | |||
| 106 | else if ((8 <= offs) && (offs < 16)) | ||
| 107 | s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); | ||
| 108 | |||
| 109 | else if ((16 <= offs) && (offs < 24)) | ||
| 110 | s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); | ||
| 111 | |||
| 112 | else if ((24 <= offs) && (offs < 32)) | ||
| 113 | s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); | ||
| 114 | |||
| 115 | else | ||
| 116 | printk(KERN_ERR "No such irq number %d", offs); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static struct irq_chip s5p_irq_eint = { | ||
| 122 | .name = "s5p-eint", | ||
| 123 | .irq_mask = s5p_irq_eint_mask, | ||
| 124 | .irq_unmask = s5p_irq_eint_unmask, | ||
| 125 | .irq_mask_ack = s5p_irq_eint_maskack, | ||
| 126 | .irq_ack = s5p_irq_eint_ack, | ||
| 127 | .irq_set_type = s5p_irq_eint_set_type, | ||
| 128 | #ifdef CONFIG_PM | ||
| 129 | .irq_set_wake = s3c_irqext_wake, | ||
| 130 | #endif | ||
| 131 | }; | ||
| 132 | |||
| 133 | /* s5p_irq_demux_eint | ||
| 134 | * | ||
| 135 | * This function demuxes the IRQ from the group0 external interrupts, | ||
| 136 | * from EINTs 16 to 31. It is designed to be inlined into the specific | ||
| 137 | * handler s5p_irq_demux_eintX_Y. | ||
| 138 | * | ||
| 139 | * Each EINT pend/mask registers handle eight of them. | ||
| 140 | */ | ||
| 141 | static inline void s5p_irq_demux_eint(unsigned int start) | ||
| 142 | { | ||
| 143 | u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); | ||
| 144 | u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); | ||
| 145 | unsigned int irq; | ||
| 146 | |||
| 147 | status &= ~mask; | ||
| 148 | status &= 0xff; | ||
| 149 | |||
| 150 | while (status) { | ||
| 151 | irq = fls(status) - 1; | ||
| 152 | generic_handle_irq(irq + start); | ||
| 153 | status &= ~(1 << irq); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) | ||
| 158 | { | ||
| 159 | s5p_irq_demux_eint(IRQ_EINT(16)); | ||
| 160 | s5p_irq_demux_eint(IRQ_EINT(24)); | ||
| 161 | } | ||
| 162 | |||
| 163 | static inline void s5p_irq_vic_eint_mask(struct irq_data *data) | ||
| 164 | { | ||
| 165 | void __iomem *base = irq_data_get_irq_chip_data(data); | ||
| 166 | |||
| 167 | s5p_irq_eint_mask(data); | ||
| 168 | writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR); | ||
| 169 | } | ||
| 170 | |||
| 171 | static void s5p_irq_vic_eint_unmask(struct irq_data *data) | ||
| 172 | { | ||
| 173 | void __iomem *base = irq_data_get_irq_chip_data(data); | ||
| 174 | |||
| 175 | s5p_irq_eint_unmask(data); | ||
| 176 | writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE); | ||
| 177 | } | ||
| 178 | |||
| 179 | static inline void s5p_irq_vic_eint_ack(struct irq_data *data) | ||
| 180 | { | ||
| 181 | __raw_writel(eint_irq_to_bit(data->irq), | ||
| 182 | S5P_EINT_PEND(EINT_REG_NR(data->irq))); | ||
| 183 | } | ||
| 184 | |||
| 185 | static void s5p_irq_vic_eint_maskack(struct irq_data *data) | ||
| 186 | { | ||
| 187 | s5p_irq_vic_eint_mask(data); | ||
| 188 | s5p_irq_vic_eint_ack(data); | ||
| 189 | } | ||
| 190 | |||
| 191 | static struct irq_chip s5p_irq_vic_eint = { | ||
| 192 | .name = "s5p_vic_eint", | ||
| 193 | .irq_mask = s5p_irq_vic_eint_mask, | ||
| 194 | .irq_unmask = s5p_irq_vic_eint_unmask, | ||
| 195 | .irq_mask_ack = s5p_irq_vic_eint_maskack, | ||
| 196 | .irq_ack = s5p_irq_vic_eint_ack, | ||
| 197 | .irq_set_type = s5p_irq_eint_set_type, | ||
| 198 | #ifdef CONFIG_PM | ||
| 199 | .irq_set_wake = s3c_irqext_wake, | ||
| 200 | #endif | ||
| 201 | }; | ||
| 202 | |||
| 203 | int __init s5p_init_irq_eint(void) | ||
| 204 | { | ||
| 205 | int irq; | ||
| 206 | |||
| 207 | for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++) | ||
| 208 | irq_set_chip(irq, &s5p_irq_vic_eint); | ||
| 209 | |||
| 210 | for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) { | ||
| 211 | irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq); | ||
| 212 | set_irq_flags(irq, IRQF_VALID); | ||
| 213 | } | ||
| 214 | |||
| 215 | irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31); | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | arch_initcall(s5p_init_irq_eint); | ||
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c new file mode 100644 index 00000000000..c65eb791d1b --- /dev/null +++ b/arch/arm/plat-s5p/irq-gpioint.c | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/irq-gpioint.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * Author: Kyungmin Park <kyungmin.park@samsung.com> | ||
| 5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 6 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/irq.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/gpio.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | |||
| 22 | #include <mach/map.h> | ||
| 23 | #include <plat/gpio-core.h> | ||
| 24 | #include <plat/gpio-cfg.h> | ||
| 25 | |||
| 26 | #include <asm/mach/irq.h> | ||
| 27 | |||
| 28 | #define GPIO_BASE(chip) (((unsigned long)(chip)->base) & 0xFFFFF000u) | ||
| 29 | |||
| 30 | #define CON_OFFSET 0x700 | ||
| 31 | #define MASK_OFFSET 0x900 | ||
| 32 | #define PEND_OFFSET 0xA00 | ||
| 33 | #define REG_OFFSET(x) ((x) << 2) | ||
| 34 | |||
| 35 | struct s5p_gpioint_bank { | ||
| 36 | struct list_head list; | ||
| 37 | int start; | ||
| 38 | int nr_groups; | ||
| 39 | int irq; | ||
| 40 | struct s3c_gpio_chip **chips; | ||
| 41 | void (*handler)(unsigned int, struct irq_desc *); | ||
| 42 | }; | ||
| 43 | |||
| 44 | LIST_HEAD(banks); | ||
| 45 | |||
| 46 | static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type) | ||
| 47 | { | ||
| 48 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 49 | struct irq_chip_type *ct = gc->chip_types; | ||
| 50 | unsigned int shift = (d->irq - gc->irq_base) << 2; | ||
| 51 | |||
| 52 | switch (type) { | ||
| 53 | case IRQ_TYPE_EDGE_RISING: | ||
| 54 | type = S5P_IRQ_TYPE_EDGE_RISING; | ||
| 55 | break; | ||
| 56 | case IRQ_TYPE_EDGE_FALLING: | ||
| 57 | type = S5P_IRQ_TYPE_EDGE_FALLING; | ||
| 58 | break; | ||
| 59 | case IRQ_TYPE_EDGE_BOTH: | ||
| 60 | type = S5P_IRQ_TYPE_EDGE_BOTH; | ||
| 61 | break; | ||
| 62 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 63 | type = S5P_IRQ_TYPE_LEVEL_HIGH; | ||
| 64 | break; | ||
| 65 | case IRQ_TYPE_LEVEL_LOW: | ||
| 66 | type = S5P_IRQ_TYPE_LEVEL_LOW; | ||
| 67 | break; | ||
| 68 | case IRQ_TYPE_NONE: | ||
| 69 | default: | ||
| 70 | printk(KERN_WARNING "No irq type\n"); | ||
| 71 | return -EINVAL; | ||
| 72 | } | ||
| 73 | |||
| 74 | gc->type_cache &= ~(0x7 << shift); | ||
| 75 | gc->type_cache |= type << shift; | ||
| 76 | writel(gc->type_cache, gc->reg_base + ct->regs.type); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) | ||
| 81 | { | ||
| 82 | struct s5p_gpioint_bank *bank = irq_get_handler_data(irq); | ||
| 83 | int group, pend_offset, mask_offset; | ||
| 84 | unsigned int pend, mask; | ||
| 85 | |||
| 86 | struct irq_chip *chip = irq_get_chip(irq); | ||
| 87 | chained_irq_enter(chip, desc); | ||
| 88 | |||
| 89 | for (group = 0; group < bank->nr_groups; group++) { | ||
| 90 | struct s3c_gpio_chip *chip = bank->chips[group]; | ||
| 91 | if (!chip) | ||
| 92 | continue; | ||
| 93 | |||
| 94 | pend_offset = REG_OFFSET(group); | ||
| 95 | pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset); | ||
| 96 | if (!pend) | ||
| 97 | continue; | ||
| 98 | |||
| 99 | mask_offset = REG_OFFSET(group); | ||
| 100 | mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset); | ||
| 101 | pend &= ~mask; | ||
| 102 | |||
| 103 | while (pend) { | ||
| 104 | int offset = fls(pend) - 1; | ||
| 105 | int real_irq = chip->irq_base + offset; | ||
| 106 | generic_handle_irq(real_irq); | ||
| 107 | pend &= ~BIT(offset); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | chained_irq_exit(chip, desc); | ||
| 111 | } | ||
| 112 | |||
| 113 | static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) | ||
| 114 | { | ||
| 115 | static int used_gpioint_groups = 0; | ||
| 116 | int group = chip->group; | ||
| 117 | struct s5p_gpioint_bank *b, *bank = NULL; | ||
| 118 | struct irq_chip_generic *gc; | ||
| 119 | struct irq_chip_type *ct; | ||
| 120 | |||
| 121 | if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) | ||
| 122 | return -ENOMEM; | ||
| 123 | |||
| 124 | list_for_each_entry(b, &banks, list) { | ||
| 125 | if (group >= b->start && group < b->start + b->nr_groups) { | ||
| 126 | bank = b; | ||
| 127 | break; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | if (!bank) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 133 | if (!bank->handler) { | ||
| 134 | bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) * | ||
| 135 | bank->nr_groups, GFP_KERNEL); | ||
| 136 | if (!bank->chips) | ||
| 137 | return -ENOMEM; | ||
| 138 | |||
| 139 | irq_set_chained_handler(bank->irq, s5p_gpioint_handler); | ||
| 140 | irq_set_handler_data(bank->irq, bank); | ||
| 141 | bank->handler = s5p_gpioint_handler; | ||
| 142 | printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n", | ||
| 143 | bank->irq); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * chained GPIO irq has been successfully registered, allocate new gpio | ||
| 148 | * int group and assign irq nubmers | ||
| 149 | */ | ||
| 150 | chip->irq_base = S5P_GPIOINT_BASE + | ||
| 151 | used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; | ||
| 152 | used_gpioint_groups++; | ||
| 153 | |||
| 154 | bank->chips[group - bank->start] = chip; | ||
| 155 | |||
| 156 | gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base, | ||
| 157 | (void __iomem *)GPIO_BASE(chip), | ||
| 158 | handle_level_irq); | ||
| 159 | if (!gc) | ||
| 160 | return -ENOMEM; | ||
| 161 | ct = gc->chip_types; | ||
| 162 | ct->chip.irq_ack = irq_gc_ack_set_bit; | ||
| 163 | ct->chip.irq_mask = irq_gc_mask_set_bit; | ||
| 164 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; | ||
| 165 | ct->chip.irq_set_type = s5p_gpioint_set_type, | ||
| 166 | ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start); | ||
| 167 | ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start); | ||
| 168 | ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start); | ||
| 169 | irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio), | ||
| 170 | IRQ_GC_INIT_MASK_CACHE, | ||
| 171 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | int __init s5p_register_gpio_interrupt(int pin) | ||
| 176 | { | ||
| 177 | struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin); | ||
| 178 | int offset, group; | ||
| 179 | int ret; | ||
| 180 | |||
| 181 | if (!my_chip) | ||
| 182 | return -EINVAL; | ||
| 183 | |||
| 184 | offset = pin - my_chip->chip.base; | ||
| 185 | group = my_chip->group; | ||
| 186 | |||
| 187 | /* check if the group has been already registered */ | ||
| 188 | if (my_chip->irq_base) | ||
| 189 | return my_chip->irq_base + offset; | ||
| 190 | |||
| 191 | /* register gpio group */ | ||
| 192 | ret = s5p_gpioint_add(my_chip); | ||
| 193 | if (ret == 0) { | ||
| 194 | my_chip->chip.to_irq = samsung_gpiolib_to_irq; | ||
| 195 | printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", | ||
| 196 | group); | ||
| 197 | return my_chip->irq_base + offset; | ||
| 198 | } | ||
| 199 | return ret; | ||
| 200 | } | ||
| 201 | |||
| 202 | int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups) | ||
| 203 | { | ||
| 204 | struct s5p_gpioint_bank *bank; | ||
| 205 | |||
| 206 | bank = kzalloc(sizeof(*bank), GFP_KERNEL); | ||
| 207 | if (!bank) | ||
| 208 | return -ENOMEM; | ||
| 209 | |||
| 210 | bank->start = start; | ||
| 211 | bank->nr_groups = nr_groups; | ||
| 212 | bank->irq = chain_irq; | ||
| 213 | |||
| 214 | list_add_tail(&bank->list, &banks); | ||
| 215 | return 0; | ||
| 216 | } | ||
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c new file mode 100644 index 00000000000..327acb3a446 --- /dev/null +++ b/arch/arm/plat-s5p/irq-pm.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/irq-pm.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Based on arch/arm/plat-s3c24xx/irq-pm.c, | ||
| 7 | * Copyright (c) 2003,2004 Simtec Electronics | ||
| 8 | * Ben Dooks <ben@simtec.co.uk> | ||
| 9 | * http://armlinux.simtec.co.uk/ | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | |||
| 20 | #include <plat/cpu.h> | ||
| 21 | #include <plat/irqs.h> | ||
| 22 | #include <plat/pm.h> | ||
| 23 | #include <mach/map.h> | ||
| 24 | |||
| 25 | #include <mach/regs-gpio.h> | ||
| 26 | #include <mach/regs-irq.h> | ||
| 27 | |||
| 28 | /* state for IRQs over sleep */ | ||
| 29 | |||
| 30 | /* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM, | ||
| 31 | * as wakeup sources | ||
| 32 | * | ||
| 33 | * set bit to 1 in allow bitfield to enable the wakeup settings on it | ||
| 34 | */ | ||
| 35 | |||
| 36 | unsigned long s3c_irqwake_intallow = 0x00000006L; | ||
| 37 | unsigned long s3c_irqwake_eintallow = 0xffffffffL; | ||
| 38 | |||
| 39 | int s3c_irq_wake(struct irq_data *data, unsigned int state) | ||
| 40 | { | ||
| 41 | unsigned long irqbit; | ||
| 42 | |||
| 43 | switch (data->irq) { | ||
| 44 | case IRQ_RTC_TIC: | ||
| 45 | case IRQ_RTC_ALARM: | ||
| 46 | irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM); | ||
| 47 | if (!state) | ||
| 48 | s3c_irqwake_intmask |= irqbit; | ||
| 49 | else | ||
| 50 | s3c_irqwake_intmask &= ~irqbit; | ||
| 51 | break; | ||
| 52 | default: | ||
| 53 | return -ENOENT; | ||
| 54 | } | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | static struct sleep_save eint_save[] = { | ||
| 59 | SAVE_ITEM(S5P_EINT_CON(0)), | ||
| 60 | SAVE_ITEM(S5P_EINT_CON(1)), | ||
| 61 | SAVE_ITEM(S5P_EINT_CON(2)), | ||
| 62 | SAVE_ITEM(S5P_EINT_CON(3)), | ||
| 63 | |||
| 64 | SAVE_ITEM(S5P_EINT_FLTCON(0)), | ||
| 65 | SAVE_ITEM(S5P_EINT_FLTCON(1)), | ||
| 66 | SAVE_ITEM(S5P_EINT_FLTCON(2)), | ||
| 67 | SAVE_ITEM(S5P_EINT_FLTCON(3)), | ||
| 68 | SAVE_ITEM(S5P_EINT_FLTCON(4)), | ||
| 69 | SAVE_ITEM(S5P_EINT_FLTCON(5)), | ||
| 70 | SAVE_ITEM(S5P_EINT_FLTCON(6)), | ||
| 71 | SAVE_ITEM(S5P_EINT_FLTCON(7)), | ||
| 72 | |||
| 73 | SAVE_ITEM(S5P_EINT_MASK(0)), | ||
| 74 | SAVE_ITEM(S5P_EINT_MASK(1)), | ||
| 75 | SAVE_ITEM(S5P_EINT_MASK(2)), | ||
| 76 | SAVE_ITEM(S5P_EINT_MASK(3)), | ||
| 77 | }; | ||
| 78 | |||
| 79 | int s3c24xx_irq_suspend(void) | ||
| 80 | { | ||
| 81 | s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | void s3c24xx_irq_resume(void) | ||
| 87 | { | ||
| 88 | s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); | ||
| 89 | } | ||
| 90 | |||
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c new file mode 100644 index 00000000000..a97c08957f4 --- /dev/null +++ b/arch/arm/plat-s5p/irq.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* arch/arm/plat-s5p/irq.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P - Interrupt handling | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/irq.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | |||
| 18 | #include <asm/hardware/vic.h> | ||
| 19 | |||
| 20 | #include <linux/serial_core.h> | ||
| 21 | #include <mach/map.h> | ||
| 22 | #include <plat/regs-timer.h> | ||
| 23 | #include <plat/regs-serial.h> | ||
| 24 | #include <plat/cpu.h> | ||
| 25 | #include <plat/irq-vic-timer.h> | ||
| 26 | #include <plat/irq-uart.h> | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | ||
| 30 | * are consecutive when looking up the interrupt in the demux routines. | ||
| 31 | */ | ||
| 32 | static struct s3c_uart_irq uart_irqs[] = { | ||
| 33 | [0] = { | ||
| 34 | .regs = S5P_VA_UART0, | ||
| 35 | .base_irq = IRQ_S5P_UART_BASE0, | ||
| 36 | .parent_irq = IRQ_UART0, | ||
| 37 | }, | ||
| 38 | [1] = { | ||
| 39 | .regs = S5P_VA_UART1, | ||
| 40 | .base_irq = IRQ_S5P_UART_BASE1, | ||
| 41 | .parent_irq = IRQ_UART1, | ||
| 42 | }, | ||
| 43 | [2] = { | ||
| 44 | .regs = S5P_VA_UART2, | ||
| 45 | .base_irq = IRQ_S5P_UART_BASE2, | ||
| 46 | .parent_irq = IRQ_UART2, | ||
| 47 | }, | ||
| 48 | #if CONFIG_SERIAL_SAMSUNG_UARTS > 3 | ||
| 49 | [3] = { | ||
| 50 | .regs = S5P_VA_UART3, | ||
| 51 | .base_irq = IRQ_S5P_UART_BASE3, | ||
| 52 | .parent_irq = IRQ_UART3, | ||
| 53 | }, | ||
| 54 | #endif | ||
| 55 | }; | ||
| 56 | |||
| 57 | void __init s5p_init_irq(u32 *vic, u32 num_vic) | ||
| 58 | { | ||
| 59 | #ifdef CONFIG_ARM_VIC | ||
| 60 | int irq; | ||
| 61 | |||
| 62 | /* initialize the VICs */ | ||
| 63 | for (irq = 0; irq < num_vic; irq++) | ||
| 64 | vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); | ||
| 65 | #endif | ||
| 66 | |||
| 67 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); | ||
| 68 | |||
| 69 | s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); | ||
| 70 | } | ||
diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c new file mode 100644 index 00000000000..d15dc47b0e3 --- /dev/null +++ b/arch/arm/plat-s5p/pm.c | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/pm.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * S5P Power Manager (Suspend-To-RAM) support | ||
| 7 | * | ||
| 8 | * Based on arch/arm/plat-s3c24xx/pm.c | ||
| 9 | * Copyright (c) 2004,2006 Simtec Electronics | ||
| 10 | * Ben Dooks <ben@simtec.co.uk> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License version 2 as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/suspend.h> | ||
| 18 | #include <plat/pm.h> | ||
| 19 | |||
| 20 | #define PFX "s5p pm: " | ||
| 21 | |||
| 22 | /* s3c_pm_configure_extint | ||
| 23 | * | ||
| 24 | * configure all external interrupt pins | ||
| 25 | */ | ||
| 26 | |||
| 27 | void s3c_pm_configure_extint(void) | ||
| 28 | { | ||
| 29 | /* nothing here yet */ | ||
| 30 | } | ||
| 31 | |||
| 32 | void s3c_pm_restore_core(void) | ||
| 33 | { | ||
| 34 | /* nothing here yet */ | ||
| 35 | } | ||
| 36 | |||
| 37 | void s3c_pm_save_core(void) | ||
| 38 | { | ||
| 39 | /* nothing here yet */ | ||
| 40 | } | ||
| 41 | |||
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c new file mode 100644 index 00000000000..c833e7b5759 --- /dev/null +++ b/arch/arm/plat-s5p/s5p-time.c | |||
| @@ -0,0 +1,419 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/s5p-time.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com/ | ||
| 5 | * | ||
| 6 | * S5P - Common hr-timer support | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/sched.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/irq.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/clockchips.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | |||
| 21 | #include <asm/smp_twd.h> | ||
| 22 | #include <asm/mach/time.h> | ||
| 23 | #include <asm/mach/arch.h> | ||
| 24 | #include <asm/mach/map.h> | ||
| 25 | #include <asm/sched_clock.h> | ||
| 26 | |||
| 27 | #include <mach/map.h> | ||
| 28 | #include <plat/devs.h> | ||
| 29 | #include <plat/regs-timer.h> | ||
| 30 | #include <plat/s5p-time.h> | ||
| 31 | |||
| 32 | static struct clk *tin_event; | ||
| 33 | static struct clk *tin_source; | ||
| 34 | static struct clk *tdiv_event; | ||
| 35 | static struct clk *tdiv_source; | ||
| 36 | static struct clk *timerclk; | ||
| 37 | static struct s5p_timer_source timer_source; | ||
| 38 | static unsigned long clock_count_per_tick; | ||
| 39 | static void s5p_timer_resume(void); | ||
| 40 | |||
| 41 | static void s5p_time_stop(enum s5p_timer_mode mode) | ||
| 42 | { | ||
| 43 | unsigned long tcon; | ||
| 44 | |||
| 45 | tcon = __raw_readl(S3C2410_TCON); | ||
| 46 | |||
| 47 | switch (mode) { | ||
| 48 | case S5P_PWM0: | ||
| 49 | tcon &= ~S3C2410_TCON_T0START; | ||
| 50 | break; | ||
| 51 | |||
| 52 | case S5P_PWM1: | ||
| 53 | tcon &= ~S3C2410_TCON_T1START; | ||
| 54 | break; | ||
| 55 | |||
| 56 | case S5P_PWM2: | ||
| 57 | tcon &= ~S3C2410_TCON_T2START; | ||
| 58 | break; | ||
| 59 | |||
| 60 | case S5P_PWM3: | ||
| 61 | tcon &= ~S3C2410_TCON_T3START; | ||
| 62 | break; | ||
| 63 | |||
| 64 | case S5P_PWM4: | ||
| 65 | tcon &= ~S3C2410_TCON_T4START; | ||
| 66 | break; | ||
| 67 | |||
| 68 | default: | ||
| 69 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | __raw_writel(tcon, S3C2410_TCON); | ||
| 73 | } | ||
| 74 | |||
| 75 | static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt) | ||
| 76 | { | ||
| 77 | unsigned long tcon; | ||
| 78 | |||
| 79 | tcon = __raw_readl(S3C2410_TCON); | ||
| 80 | |||
| 81 | tcnt--; | ||
| 82 | |||
| 83 | switch (mode) { | ||
| 84 | case S5P_PWM0: | ||
| 85 | tcon &= ~(0x0f << 0); | ||
| 86 | tcon |= S3C2410_TCON_T0MANUALUPD; | ||
| 87 | break; | ||
| 88 | |||
| 89 | case S5P_PWM1: | ||
| 90 | tcon &= ~(0x0f << 8); | ||
| 91 | tcon |= S3C2410_TCON_T1MANUALUPD; | ||
| 92 | break; | ||
| 93 | |||
| 94 | case S5P_PWM2: | ||
| 95 | tcon &= ~(0x0f << 12); | ||
| 96 | tcon |= S3C2410_TCON_T2MANUALUPD; | ||
| 97 | break; | ||
| 98 | |||
| 99 | case S5P_PWM3: | ||
| 100 | tcon &= ~(0x0f << 16); | ||
| 101 | tcon |= S3C2410_TCON_T3MANUALUPD; | ||
| 102 | break; | ||
| 103 | |||
| 104 | case S5P_PWM4: | ||
| 105 | tcon &= ~(0x07 << 20); | ||
| 106 | tcon |= S3C2410_TCON_T4MANUALUPD; | ||
| 107 | break; | ||
| 108 | |||
| 109 | default: | ||
| 110 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | |||
| 114 | __raw_writel(tcnt, S3C2410_TCNTB(mode)); | ||
| 115 | __raw_writel(tcnt, S3C2410_TCMPB(mode)); | ||
| 116 | __raw_writel(tcon, S3C2410_TCON); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void s5p_time_start(enum s5p_timer_mode mode, bool periodic) | ||
| 120 | { | ||
| 121 | unsigned long tcon; | ||
| 122 | |||
| 123 | tcon = __raw_readl(S3C2410_TCON); | ||
| 124 | |||
| 125 | switch (mode) { | ||
| 126 | case S5P_PWM0: | ||
| 127 | tcon |= S3C2410_TCON_T0START; | ||
| 128 | tcon &= ~S3C2410_TCON_T0MANUALUPD; | ||
| 129 | |||
| 130 | if (periodic) | ||
| 131 | tcon |= S3C2410_TCON_T0RELOAD; | ||
| 132 | else | ||
| 133 | tcon &= ~S3C2410_TCON_T0RELOAD; | ||
| 134 | break; | ||
| 135 | |||
| 136 | case S5P_PWM1: | ||
| 137 | tcon |= S3C2410_TCON_T1START; | ||
| 138 | tcon &= ~S3C2410_TCON_T1MANUALUPD; | ||
| 139 | |||
| 140 | if (periodic) | ||
| 141 | tcon |= S3C2410_TCON_T1RELOAD; | ||
| 142 | else | ||
| 143 | tcon &= ~S3C2410_TCON_T1RELOAD; | ||
| 144 | break; | ||
| 145 | |||
| 146 | case S5P_PWM2: | ||
| 147 | tcon |= S3C2410_TCON_T2START; | ||
| 148 | tcon &= ~S3C2410_TCON_T2MANUALUPD; | ||
| 149 | |||
| 150 | if (periodic) | ||
| 151 | tcon |= S3C2410_TCON_T2RELOAD; | ||
| 152 | else | ||
| 153 | tcon &= ~S3C2410_TCON_T2RELOAD; | ||
| 154 | break; | ||
| 155 | |||
| 156 | case S5P_PWM3: | ||
| 157 | tcon |= S3C2410_TCON_T3START; | ||
| 158 | tcon &= ~S3C2410_TCON_T3MANUALUPD; | ||
| 159 | |||
| 160 | if (periodic) | ||
| 161 | tcon |= S3C2410_TCON_T3RELOAD; | ||
| 162 | else | ||
| 163 | tcon &= ~S3C2410_TCON_T3RELOAD; | ||
| 164 | break; | ||
| 165 | |||
| 166 | case S5P_PWM4: | ||
| 167 | tcon |= S3C2410_TCON_T4START; | ||
| 168 | tcon &= ~S3C2410_TCON_T4MANUALUPD; | ||
| 169 | |||
| 170 | if (periodic) | ||
| 171 | tcon |= S3C2410_TCON_T4RELOAD; | ||
| 172 | else | ||
| 173 | tcon &= ~S3C2410_TCON_T4RELOAD; | ||
| 174 | break; | ||
| 175 | |||
| 176 | default: | ||
| 177 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | __raw_writel(tcon, S3C2410_TCON); | ||
| 181 | } | ||
| 182 | |||
| 183 | static int s5p_set_next_event(unsigned long cycles, | ||
| 184 | struct clock_event_device *evt) | ||
| 185 | { | ||
| 186 | s5p_time_setup(timer_source.event_id, cycles); | ||
| 187 | s5p_time_start(timer_source.event_id, NON_PERIODIC); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void s5p_set_mode(enum clock_event_mode mode, | ||
| 193 | struct clock_event_device *evt) | ||
| 194 | { | ||
| 195 | s5p_time_stop(timer_source.event_id); | ||
| 196 | |||
| 197 | switch (mode) { | ||
| 198 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 199 | s5p_time_setup(timer_source.event_id, clock_count_per_tick); | ||
| 200 | s5p_time_start(timer_source.event_id, PERIODIC); | ||
| 201 | break; | ||
| 202 | |||
| 203 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 204 | break; | ||
| 205 | |||
| 206 | case CLOCK_EVT_MODE_UNUSED: | ||
| 207 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 208 | break; | ||
| 209 | |||
| 210 | case CLOCK_EVT_MODE_RESUME: | ||
| 211 | s5p_timer_resume(); | ||
| 212 | break; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | static void s5p_timer_resume(void) | ||
| 217 | { | ||
| 218 | /* event timer restart */ | ||
| 219 | s5p_time_setup(timer_source.event_id, clock_count_per_tick); | ||
| 220 | s5p_time_start(timer_source.event_id, PERIODIC); | ||
| 221 | |||
| 222 | /* source timer restart */ | ||
| 223 | s5p_time_setup(timer_source.source_id, TCNT_MAX); | ||
| 224 | s5p_time_start(timer_source.source_id, PERIODIC); | ||
| 225 | } | ||
| 226 | |||
| 227 | void __init s5p_set_timer_source(enum s5p_timer_mode event, | ||
| 228 | enum s5p_timer_mode source) | ||
| 229 | { | ||
| 230 | s3c_device_timer[event].dev.bus = &platform_bus_type; | ||
| 231 | s3c_device_timer[source].dev.bus = &platform_bus_type; | ||
| 232 | |||
| 233 | timer_source.event_id = event; | ||
| 234 | timer_source.source_id = source; | ||
| 235 | } | ||
| 236 | |||
| 237 | static struct clock_event_device time_event_device = { | ||
| 238 | .name = "s5p_event_timer", | ||
| 239 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
| 240 | .rating = 200, | ||
| 241 | .set_next_event = s5p_set_next_event, | ||
| 242 | .set_mode = s5p_set_mode, | ||
| 243 | }; | ||
| 244 | |||
| 245 | static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id) | ||
| 246 | { | ||
| 247 | struct clock_event_device *evt = dev_id; | ||
| 248 | |||
| 249 | evt->event_handler(evt); | ||
| 250 | |||
| 251 | return IRQ_HANDLED; | ||
| 252 | } | ||
| 253 | |||
| 254 | static struct irqaction s5p_clock_event_irq = { | ||
| 255 | .name = "s5p_time_irq", | ||
| 256 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
| 257 | .handler = s5p_clock_event_isr, | ||
| 258 | .dev_id = &time_event_device, | ||
| 259 | }; | ||
| 260 | |||
| 261 | static void __init s5p_clockevent_init(void) | ||
| 262 | { | ||
| 263 | unsigned long pclk; | ||
| 264 | unsigned long clock_rate; | ||
| 265 | unsigned int irq_number; | ||
| 266 | struct clk *tscaler; | ||
| 267 | |||
| 268 | pclk = clk_get_rate(timerclk); | ||
| 269 | |||
| 270 | tscaler = clk_get_parent(tdiv_event); | ||
| 271 | |||
| 272 | clk_set_rate(tscaler, pclk / 2); | ||
| 273 | clk_set_rate(tdiv_event, pclk / 2); | ||
| 274 | clk_set_parent(tin_event, tdiv_event); | ||
| 275 | |||
| 276 | clock_rate = clk_get_rate(tin_event); | ||
| 277 | clock_count_per_tick = clock_rate / HZ; | ||
| 278 | |||
| 279 | clockevents_calc_mult_shift(&time_event_device, | ||
| 280 | clock_rate, S5PTIMER_MIN_RANGE); | ||
| 281 | time_event_device.max_delta_ns = | ||
| 282 | clockevent_delta2ns(-1, &time_event_device); | ||
| 283 | time_event_device.min_delta_ns = | ||
| 284 | clockevent_delta2ns(1, &time_event_device); | ||
| 285 | |||
| 286 | time_event_device.cpumask = cpumask_of(0); | ||
| 287 | clockevents_register_device(&time_event_device); | ||
| 288 | |||
| 289 | irq_number = timer_source.event_id + IRQ_TIMER0; | ||
| 290 | setup_irq(irq_number, &s5p_clock_event_irq); | ||
| 291 | } | ||
| 292 | |||
| 293 | static void __iomem *s5p_timer_reg(void) | ||
| 294 | { | ||
| 295 | unsigned long offset = 0; | ||
| 296 | |||
| 297 | switch (timer_source.source_id) { | ||
| 298 | case S5P_PWM0: | ||
| 299 | case S5P_PWM1: | ||
| 300 | case S5P_PWM2: | ||
| 301 | case S5P_PWM3: | ||
| 302 | offset = (timer_source.source_id * 0x0c) + 0x14; | ||
| 303 | break; | ||
| 304 | |||
| 305 | case S5P_PWM4: | ||
| 306 | offset = 0x40; | ||
| 307 | break; | ||
| 308 | |||
| 309 | default: | ||
| 310 | printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); | ||
| 311 | return NULL; | ||
| 312 | } | ||
| 313 | |||
| 314 | return S3C_TIMERREG(offset); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Override the global weak sched_clock symbol with this | ||
| 319 | * local implementation which uses the clocksource to get some | ||
| 320 | * better resolution when scheduling the kernel. We accept that | ||
| 321 | * this wraps around for now, since it is just a relative time | ||
| 322 | * stamp. (Inspired by U300 implementation.) | ||
| 323 | */ | ||
| 324 | static DEFINE_CLOCK_DATA(cd); | ||
| 325 | |||
| 326 | unsigned long long notrace sched_clock(void) | ||
| 327 | { | ||
| 328 | void __iomem *reg = s5p_timer_reg(); | ||
| 329 | |||
| 330 | if (!reg) | ||
| 331 | return 0; | ||
| 332 | |||
| 333 | return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | ||
| 334 | } | ||
| 335 | |||
| 336 | static void notrace s5p_update_sched_clock(void) | ||
| 337 | { | ||
| 338 | void __iomem *reg = s5p_timer_reg(); | ||
| 339 | |||
| 340 | if (!reg) | ||
| 341 | return; | ||
| 342 | |||
| 343 | update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | ||
| 344 | } | ||
| 345 | |||
| 346 | static void __init s5p_clocksource_init(void) | ||
| 347 | { | ||
| 348 | unsigned long pclk; | ||
| 349 | unsigned long clock_rate; | ||
| 350 | |||
| 351 | pclk = clk_get_rate(timerclk); | ||
| 352 | |||
| 353 | clk_set_rate(tdiv_source, pclk / 2); | ||
| 354 | clk_set_parent(tin_source, tdiv_source); | ||
| 355 | |||
| 356 | clock_rate = clk_get_rate(tin_source); | ||
| 357 | |||
| 358 | s5p_time_setup(timer_source.source_id, TCNT_MAX); | ||
| 359 | s5p_time_start(timer_source.source_id, PERIODIC); | ||
| 360 | |||
| 361 | init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate); | ||
| 362 | |||
| 363 | if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", | ||
| 364 | clock_rate, 250, 32, clocksource_mmio_readl_down)) | ||
| 365 | panic("s5p_clocksource_timer: can't register clocksource\n"); | ||
| 366 | } | ||
| 367 | |||
| 368 | static void __init s5p_timer_resources(void) | ||
| 369 | { | ||
| 370 | |||
| 371 | unsigned long event_id = timer_source.event_id; | ||
| 372 | unsigned long source_id = timer_source.source_id; | ||
| 373 | char devname[15]; | ||
| 374 | |||
| 375 | timerclk = clk_get(NULL, "timers"); | ||
| 376 | if (IS_ERR(timerclk)) | ||
| 377 | panic("failed to get timers clock for timer"); | ||
| 378 | |||
| 379 | clk_enable(timerclk); | ||
| 380 | |||
| 381 | sprintf(devname, "s3c24xx-pwm.%lu", event_id); | ||
| 382 | s3c_device_timer[event_id].id = event_id; | ||
| 383 | s3c_device_timer[event_id].dev.init_name = devname; | ||
| 384 | |||
| 385 | tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin"); | ||
| 386 | if (IS_ERR(tin_event)) | ||
| 387 | panic("failed to get pwm-tin clock for event timer"); | ||
| 388 | |||
| 389 | tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv"); | ||
| 390 | if (IS_ERR(tdiv_event)) | ||
| 391 | panic("failed to get pwm-tdiv clock for event timer"); | ||
| 392 | |||
| 393 | clk_enable(tin_event); | ||
| 394 | |||
| 395 | sprintf(devname, "s3c24xx-pwm.%lu", source_id); | ||
| 396 | s3c_device_timer[source_id].id = source_id; | ||
| 397 | s3c_device_timer[source_id].dev.init_name = devname; | ||
| 398 | |||
| 399 | tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin"); | ||
| 400 | if (IS_ERR(tin_source)) | ||
| 401 | panic("failed to get pwm-tin clock for source timer"); | ||
| 402 | |||
| 403 | tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv"); | ||
| 404 | if (IS_ERR(tdiv_source)) | ||
| 405 | panic("failed to get pwm-tdiv clock for source timer"); | ||
| 406 | |||
| 407 | clk_enable(tin_source); | ||
| 408 | } | ||
| 409 | |||
| 410 | static void __init s5p_timer_init(void) | ||
| 411 | { | ||
| 412 | s5p_timer_resources(); | ||
| 413 | s5p_clockevent_init(); | ||
| 414 | s5p_clocksource_init(); | ||
| 415 | } | ||
| 416 | |||
| 417 | struct sys_timer s5p_timer = { | ||
| 418 | .init = s5p_timer_init, | ||
| 419 | }; | ||
diff --git a/arch/arm/plat-s5p/setup-mipiphy.c b/arch/arm/plat-s5p/setup-mipiphy.c new file mode 100644 index 00000000000..683c466c0e6 --- /dev/null +++ b/arch/arm/plat-s5p/setup-mipiphy.c | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/spinlock.h> | ||
| 15 | #include <mach/regs-clock.h> | ||
| 16 | |||
| 17 | static int __s5p_mipi_phy_control(struct platform_device *pdev, | ||
| 18 | bool on, u32 reset) | ||
| 19 | { | ||
| 20 | static DEFINE_SPINLOCK(lock); | ||
| 21 | void __iomem *addr; | ||
| 22 | unsigned long flags; | ||
| 23 | int pid; | ||
| 24 | u32 cfg; | ||
| 25 | |||
| 26 | if (!pdev) | ||
| 27 | return -EINVAL; | ||
| 28 | |||
| 29 | pid = (pdev->id == -1) ? 0 : pdev->id; | ||
| 30 | |||
| 31 | if (pid != 0 && pid != 1) | ||
| 32 | return -EINVAL; | ||
| 33 | |||
| 34 | addr = S5P_MIPI_DPHY_CONTROL(pid); | ||
| 35 | |||
| 36 | spin_lock_irqsave(&lock, flags); | ||
| 37 | |||
| 38 | cfg = __raw_readl(addr); | ||
| 39 | cfg = on ? (cfg | reset) : (cfg & ~reset); | ||
| 40 | __raw_writel(cfg, addr); | ||
| 41 | |||
| 42 | if (on) { | ||
| 43 | cfg |= S5P_MIPI_DPHY_ENABLE; | ||
| 44 | } else if (!(cfg & (S5P_MIPI_DPHY_SRESETN | | ||
| 45 | S5P_MIPI_DPHY_MRESETN) & ~reset)) { | ||
| 46 | cfg &= ~S5P_MIPI_DPHY_ENABLE; | ||
| 47 | } | ||
| 48 | |||
| 49 | __raw_writel(cfg, addr); | ||
| 50 | spin_unlock_irqrestore(&lock, flags); | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | int s5p_csis_phy_enable(struct platform_device *pdev, bool on) | ||
| 56 | { | ||
| 57 | return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN); | ||
| 58 | } | ||
| 59 | |||
| 60 | int s5p_dsim_phy_enable(struct platform_device *pdev, bool on) | ||
| 61 | { | ||
| 62 | return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN); | ||
| 63 | } | ||
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c new file mode 100644 index 00000000000..e1cbc728c77 --- /dev/null +++ b/arch/arm/plat-s5p/sysmmu.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | /* linux/arch/arm/plat-s5p/sysmmu.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/io.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 15 | #include <asm/pgtable.h> | ||
| 16 | |||
| 17 | #include <mach/map.h> | ||
| 18 | #include <mach/regs-sysmmu.h> | ||
| 19 | #include <plat/sysmmu.h> | ||
| 20 | |||
| 21 | #define CTRL_ENABLE 0x5 | ||
| 22 | #define CTRL_BLOCK 0x7 | ||
| 23 | #define CTRL_DISABLE 0x0 | ||
| 24 | |||
| 25 | static struct device *dev; | ||
| 26 | |||
| 27 | static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { | ||
| 28 | S5P_PAGE_FAULT_ADDR, | ||
| 29 | S5P_AR_FAULT_ADDR, | ||
| 30 | S5P_AW_FAULT_ADDR, | ||
| 31 | S5P_DEFAULT_SLAVE_ADDR, | ||
| 32 | S5P_AR_FAULT_ADDR, | ||
| 33 | S5P_AR_FAULT_ADDR, | ||
| 34 | S5P_AW_FAULT_ADDR, | ||
| 35 | S5P_AW_FAULT_ADDR | ||
| 36 | }; | ||
| 37 | |||
| 38 | static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { | ||
| 39 | "PAGE FAULT", | ||
| 40 | "AR MULTI-HIT FAULT", | ||
| 41 | "AW MULTI-HIT FAULT", | ||
| 42 | "BUS ERROR", | ||
| 43 | "AR SECURITY PROTECTION FAULT", | ||
| 44 | "AR ACCESS PROTECTION FAULT", | ||
| 45 | "AW SECURITY PROTECTION FAULT", | ||
| 46 | "AW ACCESS PROTECTION FAULT" | ||
| 47 | }; | ||
| 48 | |||
| 49 | static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])( | ||
| 50 | enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
| 51 | unsigned long pgtable_base, | ||
| 52 | unsigned long fault_addr); | ||
| 53 | |||
| 54 | /* | ||
| 55 | * If adjacent 2 bits are true, the system MMU is enabled. | ||
| 56 | * The system MMU is disabled, otherwise. | ||
| 57 | */ | ||
| 58 | static unsigned long sysmmu_states; | ||
| 59 | |||
| 60 | static inline void set_sysmmu_active(sysmmu_ips ips) | ||
| 61 | { | ||
| 62 | sysmmu_states |= 3 << (ips * 2); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void set_sysmmu_inactive(sysmmu_ips ips) | ||
| 66 | { | ||
| 67 | sysmmu_states &= ~(3 << (ips * 2)); | ||
| 68 | } | ||
| 69 | |||
| 70 | static inline int is_sysmmu_active(sysmmu_ips ips) | ||
| 71 | { | ||
| 72 | return sysmmu_states & (3 << (ips * 2)); | ||
| 73 | } | ||
| 74 | |||
| 75 | static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM]; | ||
| 76 | |||
| 77 | static inline void sysmmu_block(sysmmu_ips ips) | ||
| 78 | { | ||
| 79 | __raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
| 80 | dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]); | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline void sysmmu_unblock(sysmmu_ips ips) | ||
| 84 | { | ||
| 85 | __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
| 86 | dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]); | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips) | ||
| 90 | { | ||
| 91 | __raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH); | ||
| 92 | dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]); | ||
| 93 | } | ||
| 94 | |||
| 95 | static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd) | ||
| 96 | { | ||
| 97 | if (unlikely(pgd == 0)) { | ||
| 98 | pgd = (unsigned long)ZERO_PAGE(0); | ||
| 99 | __raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */ | ||
| 100 | } else { | ||
| 101 | __raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */ | ||
| 102 | } | ||
| 103 | |||
| 104 | __raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR); | ||
| 105 | |||
| 106 | dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n", | ||
| 107 | sysmmu_ips_name[ips], pgd); | ||
| 108 | __sysmmu_tlb_invalidate(ips); | ||
| 109 | } | ||
| 110 | |||
| 111 | void sysmmu_set_fault_handler(sysmmu_ips ips, | ||
| 112 | int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype, | ||
| 113 | unsigned long pgtable_base, | ||
| 114 | unsigned long fault_addr)) | ||
| 115 | { | ||
| 116 | BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM))); | ||
| 117 | fault_handlers[ips] = handler; | ||
| 118 | } | ||
| 119 | |||
| 120 | static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id) | ||
| 121 | { | ||
| 122 | /* SYSMMU is in blocked when interrupt occurred. */ | ||
| 123 | unsigned long base = 0; | ||
| 124 | sysmmu_ips ips = (sysmmu_ips)dev_id; | ||
| 125 | enum S5P_SYSMMU_INTERRUPT_TYPE itype; | ||
| 126 | |||
| 127 | itype = (enum S5P_SYSMMU_INTERRUPT_TYPE) | ||
| 128 | __ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS)); | ||
| 129 | |||
| 130 | BUG_ON(!((itype >= 0) && (itype < 8))); | ||
| 131 | |||
| 132 | dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype], | ||
| 133 | sysmmu_ips_name[ips]); | ||
| 134 | |||
| 135 | if (fault_handlers[ips]) { | ||
| 136 | unsigned long addr; | ||
| 137 | |||
| 138 | base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR); | ||
| 139 | addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]); | ||
| 140 | |||
| 141 | if (fault_handlers[ips](itype, base, addr)) { | ||
| 142 | __raw_writel(1 << itype, | ||
| 143 | sysmmusfrs[ips] + S5P_INT_CLEAR); | ||
| 144 | dev_notice(dev, "%s from %s is resolved." | ||
| 145 | " Retrying translation.\n", | ||
| 146 | sysmmu_fault_name[itype], sysmmu_ips_name[ips]); | ||
| 147 | } else { | ||
| 148 | base = 0; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | sysmmu_unblock(ips); | ||
| 153 | |||
| 154 | if (!base) | ||
| 155 | dev_notice(dev, "%s from %s is not handled.\n", | ||
| 156 | sysmmu_fault_name[itype], sysmmu_ips_name[ips]); | ||
| 157 | |||
| 158 | return IRQ_HANDLED; | ||
| 159 | } | ||
| 160 | |||
| 161 | void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd) | ||
| 162 | { | ||
| 163 | if (is_sysmmu_active(ips)) { | ||
| 164 | sysmmu_block(ips); | ||
| 165 | __sysmmu_set_ptbase(ips, pgd); | ||
| 166 | sysmmu_unblock(ips); | ||
| 167 | } else { | ||
| 168 | dev_dbg(dev, "%s is disabled. " | ||
| 169 | "Skipping initializing page table base.\n", | ||
| 170 | sysmmu_ips_name[ips]); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd) | ||
| 175 | { | ||
| 176 | if (!is_sysmmu_active(ips)) { | ||
| 177 | sysmmu_clk_enable(ips); | ||
| 178 | |||
| 179 | __sysmmu_set_ptbase(ips, pgd); | ||
| 180 | |||
| 181 | __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
| 182 | |||
| 183 | set_sysmmu_active(ips); | ||
| 184 | dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]); | ||
| 185 | } else { | ||
| 186 | dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | void s5p_sysmmu_disable(sysmmu_ips ips) | ||
| 191 | { | ||
| 192 | if (is_sysmmu_active(ips)) { | ||
| 193 | __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL); | ||
| 194 | set_sysmmu_inactive(ips); | ||
| 195 | sysmmu_clk_disable(ips); | ||
| 196 | dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]); | ||
| 197 | } else { | ||
| 198 | dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips) | ||
| 203 | { | ||
| 204 | if (is_sysmmu_active(ips)) { | ||
| 205 | sysmmu_block(ips); | ||
| 206 | __sysmmu_tlb_invalidate(ips); | ||
| 207 | sysmmu_unblock(ips); | ||
| 208 | } else { | ||
| 209 | dev_dbg(dev, "%s is disabled. " | ||
| 210 | "Skipping invalidating TLB.\n", sysmmu_ips_name[ips]); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | static int s5p_sysmmu_probe(struct platform_device *pdev) | ||
| 215 | { | ||
| 216 | int i, ret; | ||
| 217 | struct resource *res, *mem; | ||
| 218 | |||
| 219 | dev = &pdev->dev; | ||
| 220 | |||
| 221 | for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) { | ||
| 222 | int irq; | ||
| 223 | |||
| 224 | sysmmu_clk_init(dev, i); | ||
| 225 | sysmmu_clk_disable(i); | ||
| 226 | |||
| 227 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
| 228 | if (!res) { | ||
| 229 | dev_err(dev, "Failed to get the resource of %s.\n", | ||
| 230 | sysmmu_ips_name[i]); | ||
| 231 | ret = -ENODEV; | ||
| 232 | goto err_res; | ||
| 233 | } | ||
| 234 | |||
| 235 | mem = request_mem_region(res->start, resource_size(res), | ||
| 236 | pdev->name); | ||
| 237 | if (!mem) { | ||
| 238 | dev_err(dev, "Failed to request the memory region of %s.\n", | ||
| 239 | sysmmu_ips_name[i]); | ||
| 240 | ret = -EBUSY; | ||
| 241 | goto err_res; | ||
| 242 | } | ||
| 243 | |||
| 244 | sysmmusfrs[i] = ioremap(res->start, resource_size(res)); | ||
| 245 | if (!sysmmusfrs[i]) { | ||
| 246 | dev_err(dev, "Failed to ioremap() for %s.\n", | ||
| 247 | sysmmu_ips_name[i]); | ||
| 248 | ret = -ENXIO; | ||
| 249 | goto err_reg; | ||
| 250 | } | ||
| 251 | |||
| 252 | irq = platform_get_irq(pdev, i); | ||
| 253 | if (irq <= 0) { | ||
| 254 | dev_err(dev, "Failed to get the IRQ resource of %s.\n", | ||
| 255 | sysmmu_ips_name[i]); | ||
| 256 | ret = -ENOENT; | ||
| 257 | goto err_map; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED, | ||
| 261 | pdev->name, (void *)i)) { | ||
| 262 | dev_err(dev, "Failed to request IRQ for %s.\n", | ||
| 263 | sysmmu_ips_name[i]); | ||
| 264 | ret = -ENOENT; | ||
| 265 | goto err_map; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | |||
| 271 | err_map: | ||
| 272 | iounmap(sysmmusfrs[i]); | ||
| 273 | err_reg: | ||
| 274 | release_mem_region(mem->start, resource_size(mem)); | ||
| 275 | err_res: | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int s5p_sysmmu_remove(struct platform_device *pdev) | ||
| 280 | { | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | int s5p_sysmmu_runtime_suspend(struct device *dev) | ||
| 284 | { | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | int s5p_sysmmu_runtime_resume(struct device *dev) | ||
| 289 | { | ||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | const struct dev_pm_ops s5p_sysmmu_pm_ops = { | ||
| 294 | .runtime_suspend = s5p_sysmmu_runtime_suspend, | ||
| 295 | .runtime_resume = s5p_sysmmu_runtime_resume, | ||
| 296 | }; | ||
| 297 | |||
| 298 | static struct platform_driver s5p_sysmmu_driver = { | ||
| 299 | .probe = s5p_sysmmu_probe, | ||
| 300 | .remove = s5p_sysmmu_remove, | ||
| 301 | .driver = { | ||
| 302 | .owner = THIS_MODULE, | ||
| 303 | .name = "s5p-sysmmu", | ||
| 304 | .pm = &s5p_sysmmu_pm_ops, | ||
| 305 | } | ||
| 306 | }; | ||
| 307 | |||
| 308 | static int __init s5p_sysmmu_init(void) | ||
| 309 | { | ||
| 310 | return platform_driver_register(&s5p_sysmmu_driver); | ||
| 311 | } | ||
| 312 | arch_initcall(s5p_sysmmu_init); | ||
