diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 16:21:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 16:21:16 -0400 |
commit | 8e73e367f7dc50f1d1bc22a63e5764bb4eea9b48 (patch) | |
tree | 9bf593c1fc7612bcdd64b9ba46e41d340f9e94d3 /arch/arm/plat-samsung | |
parent | d2f3e9eb7c9e12e89f0ac5f0dbc7a9aed0ea925d (diff) | |
parent | 7323f219533e01cc075ba45a76f3e5b214adb23f (diff) |
Merge tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Olof Johansson:
"This branch contains code cleanups, moves and removals for 3.12.
There's a large number of various cleanups, and a nice net removal of
13500 lines of code.
Highlights worth mentioning are:
- A series of patches from Stephen Boyd removing the ARM local timer
API.
- Move of Qualcomm MSM IOMMU code to drivers/iommu.
- Samsung PWM driver cleanups from Tomasz Figa, removing legacy PWM
driver and switching over to the drivers/pwm one.
- Removal of some unusued auto-generated headers for OMAP2+ (PRM/CM).
There's also a move of a header file out of include/linux/i2c/ to
platform_data, where it really belongs. It touches mostly ARM
platform code for include changes so we took it through our tree"
* tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (83 commits)
ARM: OMAP2+: Add back the define for AM33XX_RST_GLOBAL_WARM_SW_MASK
gpio: (gpio-pca953x) move header to linux/platform_data/
arm: zynq: hotplug: Remove unreachable code
ARM: SAMSUNG: Remove unnecessary exynos4_default_sdhci*()
tegra: simplify use of devm_ioremap_resource
ARM: SAMSUNG: Remove plat/regs-timer.h header
ARM: SAMSUNG: Remove remaining uses of plat/regs-timer.h header
ARM: SAMSUNG: Remove pwm-clock infrastructure
ARM: SAMSUNG: Remove old PWM timer platform devices
pwm: Remove superseded pwm-samsung-legacy driver
ARM: SAMSUNG: Modify board files to use new PWM platform device
ARM: SAMSUNG: Rework private data handling in dev-backlight
pwm: Add new pwm-samsung driver
ARM: mach-mvebu: remove redundant DT parsing and validation
ARM: msm: Only compile io.c on platforms that use it
iommu/msm: Move mach includes to iommu directory
ARM: msm: Remove devices-iommu.c
ARM: msm: Move mach/board.h contents to common.h
ARM: msm: Migrate msm_timer to CLOCKSOURCE_OF_DECLARE
ARM: msm: Remove TMR and TMR0 static mappings
...
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r-- | arch/arm/plat-samsung/Kconfig | 14 | ||||
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/plat-samsung/dev-backlight.c | 61 | ||||
-rw-r--r-- | arch/arm/plat-samsung/devs.c | 42 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/clock.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/devs.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/irq-vic-timer.h | 13 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/irqs.h | 9 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pwm-clock.h | 81 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pwm-core.h | 22 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/regs-timer.h | 124 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/samsung-time.h | 23 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/sdhci.h | 38 | ||||
-rw-r--r-- | arch/arm/plat-samsung/irq-vic-timer.c | 98 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pwm-clock.c | 474 | ||||
-rw-r--r-- | arch/arm/plat-samsung/s5p-irq.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-samsung/samsung-time.c | 394 |
17 files changed, 66 insertions, 1339 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index a5b5ff6e68d2..7dfba937d8fc 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig | |||
@@ -25,7 +25,6 @@ config PLAT_S5P | |||
25 | select S5P_GPIO_DRVSTR | 25 | select S5P_GPIO_DRVSTR |
26 | select SAMSUNG_CLKSRC if !COMMON_CLK | 26 | select SAMSUNG_CLKSRC if !COMMON_CLK |
27 | select SAMSUNG_GPIOLIB_4BIT | 27 | select SAMSUNG_GPIOLIB_4BIT |
28 | select SAMSUNG_IRQ_VIC_TIMER | ||
29 | help | 28 | help |
30 | Base platform code for Samsung's S5P series SoC. | 29 | Base platform code for Samsung's S5P series SoC. |
31 | 30 | ||
@@ -79,14 +78,6 @@ config SAMSUNG_ATAGS | |||
79 | 78 | ||
80 | if SAMSUNG_ATAGS | 79 | if SAMSUNG_ATAGS |
81 | 80 | ||
82 | # timer options | ||
83 | |||
84 | config SAMSUNG_HRT | ||
85 | bool | ||
86 | select SAMSUNG_DEV_PWM | ||
87 | help | ||
88 | Use the High Resolution timer support | ||
89 | |||
90 | # clock options | 81 | # clock options |
91 | 82 | ||
92 | config SAMSUNG_CLOCK | 83 | config SAMSUNG_CLOCK |
@@ -106,11 +97,6 @@ config S5P_CLOCK | |||
106 | 97 | ||
107 | # options for IRQ support | 98 | # options for IRQ support |
108 | 99 | ||
109 | config SAMSUNG_IRQ_VIC_TIMER | ||
110 | bool | ||
111 | help | ||
112 | Internal configuration to build the VIC timer interrupt code. | ||
113 | |||
114 | config S5P_IRQ | 100 | config S5P_IRQ |
115 | def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) | 101 | def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) |
116 | help | 102 | help |
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 199bbe304d02..498c7c23e9f4 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -12,15 +12,12 @@ obj- := | |||
12 | # Objects we always build independent of SoC choice | 12 | # Objects we always build independent of SoC choice |
13 | 13 | ||
14 | obj-y += init.o cpu.o | 14 | obj-y += init.o cpu.o |
15 | obj-$(CONFIG_SAMSUNG_HRT) += samsung-time.o | ||
16 | 15 | ||
17 | obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o | 16 | obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o |
18 | obj-$(CONFIG_SAMSUNG_CLOCK) += pwm-clock.o | ||
19 | 17 | ||
20 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | 18 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
21 | obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o | 19 | obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o |
22 | 20 | ||
23 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o | ||
24 | obj-$(CONFIG_S5P_IRQ) += s5p-irq.o | 21 | obj-$(CONFIG_S5P_IRQ) += s5p-irq.o |
25 | obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o | 22 | obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o |
26 | obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o | 23 | obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o |
diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c index 5f197dcaf10c..d51f9565567c 100644 --- a/arch/arm/plat-samsung/dev-backlight.c +++ b/arch/arm/plat-samsung/dev-backlight.c | |||
@@ -20,13 +20,18 @@ | |||
20 | #include <plat/gpio-cfg.h> | 20 | #include <plat/gpio-cfg.h> |
21 | #include <plat/backlight.h> | 21 | #include <plat/backlight.h> |
22 | 22 | ||
23 | struct samsung_bl_drvdata { | ||
24 | struct platform_pwm_backlight_data plat_data; | ||
25 | struct samsung_bl_gpio_info *gpio_info; | ||
26 | }; | ||
27 | |||
23 | static int samsung_bl_init(struct device *dev) | 28 | static int samsung_bl_init(struct device *dev) |
24 | { | 29 | { |
25 | int ret = 0; | 30 | int ret = 0; |
26 | struct platform_device *timer_dev = | 31 | struct platform_pwm_backlight_data *pdata = dev->platform_data; |
27 | container_of(dev->parent, struct platform_device, dev); | 32 | struct samsung_bl_drvdata *drvdata = container_of(pdata, |
28 | struct samsung_bl_gpio_info *bl_gpio_info = | 33 | struct samsung_bl_drvdata, plat_data); |
29 | timer_dev->dev.platform_data; | 34 | struct samsung_bl_gpio_info *bl_gpio_info = drvdata->gpio_info; |
30 | 35 | ||
31 | ret = gpio_request(bl_gpio_info->no, "Backlight"); | 36 | ret = gpio_request(bl_gpio_info->no, "Backlight"); |
32 | if (ret) { | 37 | if (ret) { |
@@ -42,10 +47,10 @@ static int samsung_bl_init(struct device *dev) | |||
42 | 47 | ||
43 | static void samsung_bl_exit(struct device *dev) | 48 | static void samsung_bl_exit(struct device *dev) |
44 | { | 49 | { |
45 | struct platform_device *timer_dev = | 50 | struct platform_pwm_backlight_data *pdata = dev->platform_data; |
46 | container_of(dev->parent, struct platform_device, dev); | 51 | struct samsung_bl_drvdata *drvdata = container_of(pdata, |
47 | struct samsung_bl_gpio_info *bl_gpio_info = | 52 | struct samsung_bl_drvdata, plat_data); |
48 | timer_dev->dev.platform_data; | 53 | struct samsung_bl_gpio_info *bl_gpio_info = drvdata->gpio_info; |
49 | 54 | ||
50 | s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT); | 55 | s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT); |
51 | gpio_free(bl_gpio_info->no); | 56 | gpio_free(bl_gpio_info->no); |
@@ -60,12 +65,14 @@ static void samsung_bl_exit(struct device *dev) | |||
60 | * for their specific boards | 65 | * for their specific boards |
61 | */ | 66 | */ |
62 | 67 | ||
63 | static struct platform_pwm_backlight_data samsung_dfl_bl_data __initdata = { | 68 | static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = { |
64 | .max_brightness = 255, | 69 | .plat_data = { |
65 | .dft_brightness = 255, | 70 | .max_brightness = 255, |
66 | .pwm_period_ns = 78770, | 71 | .dft_brightness = 255, |
67 | .init = samsung_bl_init, | 72 | .pwm_period_ns = 78770, |
68 | .exit = samsung_bl_exit, | 73 | .init = samsung_bl_init, |
74 | .exit = samsung_bl_exit, | ||
75 | }, | ||
69 | }; | 76 | }; |
70 | 77 | ||
71 | static struct platform_device samsung_dfl_bl_device __initdata = { | 78 | static struct platform_device samsung_dfl_bl_device __initdata = { |
@@ -82,6 +89,7 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, | |||
82 | { | 89 | { |
83 | int ret = 0; | 90 | int ret = 0; |
84 | struct platform_device *samsung_bl_device; | 91 | struct platform_device *samsung_bl_device; |
92 | struct samsung_bl_drvdata *samsung_bl_drvdata; | ||
85 | struct platform_pwm_backlight_data *samsung_bl_data; | 93 | struct platform_pwm_backlight_data *samsung_bl_data; |
86 | 94 | ||
87 | samsung_bl_device = kmemdup(&samsung_dfl_bl_device, | 95 | samsung_bl_device = kmemdup(&samsung_dfl_bl_device, |
@@ -91,17 +99,19 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, | |||
91 | return; | 99 | return; |
92 | } | 100 | } |
93 | 101 | ||
94 | samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data, | 102 | samsung_bl_drvdata = kmemdup(&samsung_dfl_bl_data, |
95 | sizeof(struct platform_pwm_backlight_data), samsung_bl_device); | 103 | sizeof(samsung_dfl_bl_data), GFP_KERNEL); |
96 | if (!samsung_bl_data) { | 104 | if (!samsung_bl_drvdata) { |
97 | printk(KERN_ERR "%s: no memory for platform dev\n", __func__); | 105 | printk(KERN_ERR "%s: no memory for platform dev\n", __func__); |
98 | goto err_data; | 106 | goto err_data; |
99 | } | 107 | } |
108 | samsung_bl_device->dev.platform_data = &samsung_bl_drvdata->plat_data; | ||
109 | samsung_bl_drvdata->gpio_info = gpio_info; | ||
110 | samsung_bl_data = &samsung_bl_drvdata->plat_data; | ||
100 | 111 | ||
101 | /* Copy board specific data provided by user */ | 112 | /* Copy board specific data provided by user */ |
102 | samsung_bl_data->pwm_id = bl_data->pwm_id; | 113 | samsung_bl_data->pwm_id = bl_data->pwm_id; |
103 | samsung_bl_device->dev.parent = | 114 | samsung_bl_device->dev.parent = &samsung_device_pwm.dev; |
104 | &s3c_device_timer[samsung_bl_data->pwm_id].dev; | ||
105 | 115 | ||
106 | if (bl_data->max_brightness) | 116 | if (bl_data->max_brightness) |
107 | samsung_bl_data->max_brightness = bl_data->max_brightness; | 117 | samsung_bl_data->max_brightness = bl_data->max_brightness; |
@@ -122,17 +132,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, | |||
122 | if (bl_data->check_fb) | 132 | if (bl_data->check_fb) |
123 | samsung_bl_data->check_fb = bl_data->check_fb; | 133 | samsung_bl_data->check_fb = bl_data->check_fb; |
124 | 134 | ||
125 | /* Keep the GPIO info for future use */ | ||
126 | s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info; | ||
127 | |||
128 | /* Register the specific PWM timer dev for Backlight control */ | ||
129 | ret = platform_device_register( | ||
130 | &s3c_device_timer[samsung_bl_data->pwm_id]); | ||
131 | if (ret) { | ||
132 | printk(KERN_ERR "failed to register pwm timer for backlight: %d\n", ret); | ||
133 | goto err_plat_reg1; | ||
134 | } | ||
135 | |||
136 | /* Register the Backlight dev */ | 135 | /* Register the Backlight dev */ |
137 | ret = platform_device_register(samsung_bl_device); | 136 | ret = platform_device_register(samsung_bl_device); |
138 | if (ret) { | 137 | if (ret) { |
@@ -143,8 +142,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, | |||
143 | return; | 142 | return; |
144 | 143 | ||
145 | err_plat_reg2: | 144 | err_plat_reg2: |
146 | platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]); | ||
147 | err_plat_reg1: | ||
148 | kfree(samsung_bl_data); | 145 | kfree(samsung_bl_data); |
149 | err_data: | 146 | err_data: |
150 | kfree(samsung_bl_device); | 147 | kfree(samsung_bl_device); |
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 0f9c3f431a5f..8ce0ac007eb9 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <plat/keypad.h> | 58 | #include <plat/keypad.h> |
59 | #include <linux/platform_data/mmc-s3cmci.h> | 59 | #include <linux/platform_data/mmc-s3cmci.h> |
60 | #include <linux/platform_data/mtd-nand-s3c2410.h> | 60 | #include <linux/platform_data/mtd-nand-s3c2410.h> |
61 | #include <plat/pwm-core.h> | ||
61 | #include <plat/sdhci.h> | 62 | #include <plat/sdhci.h> |
62 | #include <linux/platform_data/touchscreen-s3c2410.h> | 63 | #include <linux/platform_data/touchscreen-s3c2410.h> |
63 | #include <linux/platform_data/usb-s3c2410_udc.h> | 64 | #include <linux/platform_data/usb-s3c2410_udc.h> |
@@ -1097,36 +1098,21 @@ arch_initcall(s5p_pmu_init); | |||
1097 | /* PWM Timer */ | 1098 | /* PWM Timer */ |
1098 | 1099 | ||
1099 | #ifdef CONFIG_SAMSUNG_DEV_PWM | 1100 | #ifdef CONFIG_SAMSUNG_DEV_PWM |
1101 | static struct resource samsung_pwm_resource[] = { | ||
1102 | DEFINE_RES_MEM(SAMSUNG_PA_TIMER, SZ_4K), | ||
1103 | }; | ||
1100 | 1104 | ||
1101 | #define TIMER_RESOURCE_SIZE (1) | 1105 | struct platform_device samsung_device_pwm = { |
1102 | 1106 | .name = "samsung-pwm", | |
1103 | #define TIMER_RESOURCE(_tmr, _irq) \ | 1107 | .id = -1, |
1104 | (struct resource [TIMER_RESOURCE_SIZE]) { \ | 1108 | .num_resources = ARRAY_SIZE(samsung_pwm_resource), |
1105 | [0] = { \ | 1109 | .resource = samsung_pwm_resource, |
1106 | .start = _irq, \ | ||
1107 | .end = _irq, \ | ||
1108 | .flags = IORESOURCE_IRQ \ | ||
1109 | } \ | ||
1110 | } | ||
1111 | |||
1112 | #define DEFINE_S3C_TIMER(_tmr_no, _irq) \ | ||
1113 | .name = "s3c24xx-pwm", \ | ||
1114 | .id = _tmr_no, \ | ||
1115 | .num_resources = TIMER_RESOURCE_SIZE, \ | ||
1116 | .resource = TIMER_RESOURCE(_tmr_no, _irq), \ | ||
1117 | |||
1118 | /* | ||
1119 | * since we already have an static mapping for the timer, | ||
1120 | * we do not bother setting any IO resource for the base. | ||
1121 | */ | ||
1122 | |||
1123 | struct platform_device s3c_device_timer[] = { | ||
1124 | [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) }, | ||
1125 | [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) }, | ||
1126 | [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) }, | ||
1127 | [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) }, | ||
1128 | [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) }, | ||
1129 | }; | 1110 | }; |
1111 | |||
1112 | void __init samsung_pwm_set_platdata(struct samsung_pwm_variant *pd) | ||
1113 | { | ||
1114 | samsung_device_pwm.dev.platform_data = pd; | ||
1115 | } | ||
1130 | #endif /* CONFIG_SAMSUNG_DEV_PWM */ | 1116 | #endif /* CONFIG_SAMSUNG_DEV_PWM */ |
1131 | 1117 | ||
1132 | /* RTC */ | 1118 | /* RTC */ |
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index df45d6edc98d..63239f409807 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h | |||
@@ -145,10 +145,6 @@ extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable); | |||
145 | 145 | ||
146 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); | 146 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); |
147 | 147 | ||
148 | /* Init for pwm clock code */ | ||
149 | |||
150 | extern void s3c_pwmclk_init(void); | ||
151 | |||
152 | /* Global watchdog clock used by arch_wtd_reset() callback */ | 148 | /* Global watchdog clock used by arch_wtd_reset() callback */ |
153 | 149 | ||
154 | extern struct clk *s3c2410_wdtclk; | 150 | extern struct clk *s3c2410_wdtclk; |
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 87d501ff3328..0dc4ac4909b0 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h | |||
@@ -134,6 +134,7 @@ extern struct platform_device exynos4_device_spdif; | |||
134 | 134 | ||
135 | extern struct platform_device samsung_asoc_idma; | 135 | extern struct platform_device samsung_asoc_idma; |
136 | extern struct platform_device samsung_device_keypad; | 136 | extern struct platform_device samsung_device_keypad; |
137 | extern struct platform_device samsung_device_pwm; | ||
137 | 138 | ||
138 | /* s3c2440 specific devices */ | 139 | /* s3c2440 specific devices */ |
139 | 140 | ||
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h deleted file mode 100644 index 5b9c42fd32d7..000000000000 --- a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/irq-vic-timer.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for Samsung SoC IRQ VIC timer | ||
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 | extern void s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq); | ||
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h index df46b776976a..039001c0ef05 100644 --- a/arch/arm/plat-samsung/include/plat/irqs.h +++ b/arch/arm/plat-samsung/include/plat/irqs.h | |||
@@ -44,15 +44,6 @@ | |||
44 | #define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x)) | 44 | #define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x)) |
45 | #define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x)) | 45 | #define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x)) |
46 | 46 | ||
47 | #define S5P_TIMER_IRQ(x) (IRQ_TIMER_BASE + (x)) | ||
48 | |||
49 | #define IRQ_TIMER0 S5P_TIMER_IRQ(0) | ||
50 | #define IRQ_TIMER1 S5P_TIMER_IRQ(1) | ||
51 | #define IRQ_TIMER2 S5P_TIMER_IRQ(2) | ||
52 | #define IRQ_TIMER3 S5P_TIMER_IRQ(3) | ||
53 | #define IRQ_TIMER4 S5P_TIMER_IRQ(4) | ||
54 | #define IRQ_TIMER_COUNT (5) | ||
55 | |||
56 | #define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \ | 47 | #define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \ |
57 | : ((x) - 16 + S5P_EINT_BASE2)) | 48 | : ((x) - 16 + S5P_EINT_BASE2)) |
58 | 49 | ||
diff --git a/arch/arm/plat-samsung/include/plat/pwm-clock.h b/arch/arm/plat-samsung/include/plat/pwm-clock.h deleted file mode 100644 index bf6a60eb6237..000000000000 --- a/arch/arm/plat-samsung/include/plat/pwm-clock.h +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Copyright 2008 Openmoko, Inc. | ||
7 | * Copyright 2008 Simtec Electronics | ||
8 | * Ben Dooks <ben@simtec.co.uk> | ||
9 | * http://armlinux.simtec.co.uk/ | ||
10 | * | ||
11 | * SAMSUNG - pwm clock and timer support | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #ifndef __ASM_PLAT_PWM_CLOCK_H | ||
19 | #define __ASM_PLAT_PWM_CLOCK_H __FILE__ | ||
20 | |||
21 | /** | ||
22 | * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk | ||
23 | * @tcfg: The timer TCFG1 register bits shifted down to 0. | ||
24 | * | ||
25 | * Return true if the given configuration from TCFG1 is a TCLK instead | ||
26 | * any of the TDIV clocks. | ||
27 | */ | ||
28 | static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) | ||
29 | { | ||
30 | if (soc_is_s3c24xx()) | ||
31 | return tcfg == S3C2410_TCFG1_MUX_TCLK; | ||
32 | else if (soc_is_s3c64xx() || soc_is_s5pc100()) | ||
33 | return tcfg >= S3C64XX_TCFG1_MUX_TCLK; | ||
34 | else if (soc_is_s5p6440() || soc_is_s5p6450()) | ||
35 | return 0; | ||
36 | else | ||
37 | return tcfg == S3C64XX_TCFG1_MUX_TCLK; | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * tcfg_to_divisor() - convert tcfg1 setting to a divisor | ||
42 | * @tcfg1: The tcfg1 setting, shifted down. | ||
43 | * | ||
44 | * Get the divisor value for the given tcfg1 setting. We assume the | ||
45 | * caller has already checked to see if this is not a TCLK source. | ||
46 | */ | ||
47 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
48 | { | ||
49 | if (soc_is_s3c24xx()) | ||
50 | return 1 << (tcfg1 + 1); | ||
51 | else | ||
52 | return 1 << tcfg1; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * pwm_tdiv_has_div1() - does the tdiv setting have a /1 | ||
57 | * | ||
58 | * Return true if we have a /1 in the tdiv setting. | ||
59 | */ | ||
60 | static inline unsigned int pwm_tdiv_has_div1(void) | ||
61 | { | ||
62 | if (soc_is_s3c24xx()) | ||
63 | return 0; | ||
64 | else | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. | ||
70 | * @div: The divisor to calculate the bit information for. | ||
71 | * | ||
72 | * Turn a divisor into the necessary bit field for TCFG1. | ||
73 | */ | ||
74 | static inline unsigned long pwm_tdiv_div_bits(unsigned int div) | ||
75 | { | ||
76 | if (soc_is_s3c24xx()) | ||
77 | return ilog2(div) - 1; | ||
78 | else | ||
79 | return ilog2(div); | ||
80 | } | ||
81 | #endif /* __ASM_PLAT_PWM_CLOCK_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/pwm-core.h b/arch/arm/plat-samsung/include/plat/pwm-core.h new file mode 100644 index 000000000000..5bff1facb672 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pwm-core.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Tomasz Figa <tomasz.figa@gmail.com> | ||
3 | * | ||
4 | * Samsung PWM controller platform data helpers. | ||
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_ARCH_PWM_CORE_H | ||
12 | #define __ASM_ARCH_PWM_CORE_H __FILE__ | ||
13 | |||
14 | #include <clocksource/samsung_pwm.h> | ||
15 | |||
16 | #ifdef CONFIG_SAMSUNG_DEV_PWM | ||
17 | extern void samsung_pwm_set_platdata(struct samsung_pwm_variant *pd); | ||
18 | #else | ||
19 | static inline void samsung_pwm_set_platdata(struct samsung_pwm_variant *pd) { } | ||
20 | #endif | ||
21 | |||
22 | #endif /* __ASM_ARCH_PWM_CORE_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-timer.h b/arch/arm/plat-samsung/include/plat/regs-timer.h deleted file mode 100644 index d097d92f8cc7..000000000000 --- a/arch/arm/plat-samsung/include/plat/regs-timer.h +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-timer.h | ||
2 | * | ||
3 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
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 | * S3C2410 Timer configuration | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_TIMER_H | ||
14 | #define __ASM_ARCH_REGS_TIMER_H | ||
15 | |||
16 | #define S3C_TIMERREG(x) (S3C_VA_TIMER + (x)) | ||
17 | #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c)) | ||
18 | |||
19 | #define S3C2410_TCFG0 S3C_TIMERREG(0x00) | ||
20 | #define S3C2410_TCFG1 S3C_TIMERREG(0x04) | ||
21 | #define S3C2410_TCON S3C_TIMERREG(0x08) | ||
22 | |||
23 | #define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44) | ||
24 | |||
25 | #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) | ||
26 | #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) | ||
27 | #define S3C2410_TCFG_PRESCALER1_SHIFT (8) | ||
28 | #define S3C2410_TCFG_DEADZONE_MASK (255<<16) | ||
29 | #define S3C2410_TCFG_DEADZONE_SHIFT (16) | ||
30 | |||
31 | #define S3C2410_TCFG1_MUX4_DIV2 (0<<16) | ||
32 | #define S3C2410_TCFG1_MUX4_DIV4 (1<<16) | ||
33 | #define S3C2410_TCFG1_MUX4_DIV8 (2<<16) | ||
34 | #define S3C2410_TCFG1_MUX4_DIV16 (3<<16) | ||
35 | #define S3C2410_TCFG1_MUX4_TCLK1 (4<<16) | ||
36 | #define S3C2410_TCFG1_MUX4_MASK (15<<16) | ||
37 | #define S3C2410_TCFG1_MUX4_SHIFT (16) | ||
38 | |||
39 | #define S3C2410_TCFG1_MUX3_DIV2 (0<<12) | ||
40 | #define S3C2410_TCFG1_MUX3_DIV4 (1<<12) | ||
41 | #define S3C2410_TCFG1_MUX3_DIV8 (2<<12) | ||
42 | #define S3C2410_TCFG1_MUX3_DIV16 (3<<12) | ||
43 | #define S3C2410_TCFG1_MUX3_TCLK1 (4<<12) | ||
44 | #define S3C2410_TCFG1_MUX3_MASK (15<<12) | ||
45 | |||
46 | |||
47 | #define S3C2410_TCFG1_MUX2_DIV2 (0<<8) | ||
48 | #define S3C2410_TCFG1_MUX2_DIV4 (1<<8) | ||
49 | #define S3C2410_TCFG1_MUX2_DIV8 (2<<8) | ||
50 | #define S3C2410_TCFG1_MUX2_DIV16 (3<<8) | ||
51 | #define S3C2410_TCFG1_MUX2_TCLK1 (4<<8) | ||
52 | #define S3C2410_TCFG1_MUX2_MASK (15<<8) | ||
53 | |||
54 | |||
55 | #define S3C2410_TCFG1_MUX1_DIV2 (0<<4) | ||
56 | #define S3C2410_TCFG1_MUX1_DIV4 (1<<4) | ||
57 | #define S3C2410_TCFG1_MUX1_DIV8 (2<<4) | ||
58 | #define S3C2410_TCFG1_MUX1_DIV16 (3<<4) | ||
59 | #define S3C2410_TCFG1_MUX1_TCLK0 (4<<4) | ||
60 | #define S3C2410_TCFG1_MUX1_MASK (15<<4) | ||
61 | |||
62 | #define S3C2410_TCFG1_MUX0_DIV2 (0<<0) | ||
63 | #define S3C2410_TCFG1_MUX0_DIV4 (1<<0) | ||
64 | #define S3C2410_TCFG1_MUX0_DIV8 (2<<0) | ||
65 | #define S3C2410_TCFG1_MUX0_DIV16 (3<<0) | ||
66 | #define S3C2410_TCFG1_MUX0_TCLK0 (4<<0) | ||
67 | #define S3C2410_TCFG1_MUX0_MASK (15<<0) | ||
68 | |||
69 | #define S3C2410_TCFG1_MUX_DIV2 (0<<0) | ||
70 | #define S3C2410_TCFG1_MUX_DIV4 (1<<0) | ||
71 | #define S3C2410_TCFG1_MUX_DIV8 (2<<0) | ||
72 | #define S3C2410_TCFG1_MUX_DIV16 (3<<0) | ||
73 | #define S3C2410_TCFG1_MUX_TCLK (4<<0) | ||
74 | #define S3C2410_TCFG1_MUX_MASK (15<<0) | ||
75 | |||
76 | #define S3C64XX_TCFG1_MUX_DIV1 (0<<0) | ||
77 | #define S3C64XX_TCFG1_MUX_DIV2 (1<<0) | ||
78 | #define S3C64XX_TCFG1_MUX_DIV4 (2<<0) | ||
79 | #define S3C64XX_TCFG1_MUX_DIV8 (3<<0) | ||
80 | #define S3C64XX_TCFG1_MUX_DIV16 (4<<0) | ||
81 | #define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */ | ||
82 | #define S3C64XX_TCFG1_MUX_MASK (15<<0) | ||
83 | |||
84 | #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) | ||
85 | |||
86 | /* for each timer, we have an count buffer, an compare buffer and | ||
87 | * an observation buffer | ||
88 | */ | ||
89 | |||
90 | /* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */ | ||
91 | |||
92 | #define S3C2410_TCNTB(tmr) S3C_TIMERREG2(tmr, 0x00) | ||
93 | #define S3C2410_TCMPB(tmr) S3C_TIMERREG2(tmr, 0x04) | ||
94 | #define S3C2410_TCNTO(tmr) S3C_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08)) | ||
95 | |||
96 | #define S3C2410_TCON_T4RELOAD (1<<22) | ||
97 | #define S3C2410_TCON_T4MANUALUPD (1<<21) | ||
98 | #define S3C2410_TCON_T4START (1<<20) | ||
99 | |||
100 | #define S3C2410_TCON_T3RELOAD (1<<19) | ||
101 | #define S3C2410_TCON_T3INVERT (1<<18) | ||
102 | #define S3C2410_TCON_T3MANUALUPD (1<<17) | ||
103 | #define S3C2410_TCON_T3START (1<<16) | ||
104 | |||
105 | #define S3C2410_TCON_T2RELOAD (1<<15) | ||
106 | #define S3C2410_TCON_T2INVERT (1<<14) | ||
107 | #define S3C2410_TCON_T2MANUALUPD (1<<13) | ||
108 | #define S3C2410_TCON_T2START (1<<12) | ||
109 | |||
110 | #define S3C2410_TCON_T1RELOAD (1<<11) | ||
111 | #define S3C2410_TCON_T1INVERT (1<<10) | ||
112 | #define S3C2410_TCON_T1MANUALUPD (1<<9) | ||
113 | #define S3C2410_TCON_T1START (1<<8) | ||
114 | |||
115 | #define S3C2410_TCON_T0DEADZONE (1<<4) | ||
116 | #define S3C2410_TCON_T0RELOAD (1<<3) | ||
117 | #define S3C2410_TCON_T0INVERT (1<<2) | ||
118 | #define S3C2410_TCON_T0MANUALUPD (1<<1) | ||
119 | #define S3C2410_TCON_T0START (1<<0) | ||
120 | |||
121 | #endif /* __ASM_ARCH_REGS_TIMER_H */ | ||
122 | |||
123 | |||
124 | |||
diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h index 4cc99bb1f176..209464adef97 100644 --- a/arch/arm/plat-samsung/include/plat/samsung-time.h +++ b/arch/arm/plat-samsung/include/plat/samsung-time.h | |||
@@ -22,29 +22,6 @@ enum samsung_timer_mode { | |||
22 | SAMSUNG_PWM4, | 22 | SAMSUNG_PWM4, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct samsung_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 SAMSUNG_TIMER_MIN_RANGE 4 | ||
32 | |||
33 | #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100) | ||
34 | #define TCNT_MAX 0xffff | ||
35 | #define TSCALER_DIV 25 | ||
36 | #define TDIV 50 | ||
37 | #define TSIZE 16 | ||
38 | #else | ||
39 | #define TCNT_MAX 0xffffffff | ||
40 | #define TSCALER_DIV 2 | ||
41 | #define TDIV 2 | ||
42 | #define TSIZE 32 | ||
43 | #endif | ||
44 | |||
45 | #define NON_PERIODIC 0 | ||
46 | #define PERIODIC 1 | ||
47 | |||
48 | extern void __init samsung_set_timer_source(enum samsung_timer_mode event, | 25 | extern void __init samsung_set_timer_source(enum samsung_timer_mode event, |
49 | enum samsung_timer_mode source); | 26 | enum samsung_timer_mode source); |
50 | 27 | ||
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index ce1d0f785efd..bf650218b40e 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h | |||
@@ -260,44 +260,6 @@ static inline void s5pv210_default_sdhci3(void) { } | |||
260 | 260 | ||
261 | #endif /* CONFIG_S5PV210_SETUP_SDHCI */ | 261 | #endif /* CONFIG_S5PV210_SETUP_SDHCI */ |
262 | 262 | ||
263 | /* EXYNOS4 SDHCI setup */ | ||
264 | #ifdef CONFIG_EXYNOS4_SETUP_SDHCI | ||
265 | static inline void exynos4_default_sdhci0(void) | ||
266 | { | ||
267 | #ifdef CONFIG_S3C_DEV_HSMMC | ||
268 | s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio; | ||
269 | #endif | ||
270 | } | ||
271 | |||
272 | static inline void exynos4_default_sdhci1(void) | ||
273 | { | ||
274 | #ifdef CONFIG_S3C_DEV_HSMMC1 | ||
275 | s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio; | ||
276 | #endif | ||
277 | } | ||
278 | |||
279 | static inline void exynos4_default_sdhci2(void) | ||
280 | { | ||
281 | #ifdef CONFIG_S3C_DEV_HSMMC2 | ||
282 | s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio; | ||
283 | #endif | ||
284 | } | ||
285 | |||
286 | static inline void exynos4_default_sdhci3(void) | ||
287 | { | ||
288 | #ifdef CONFIG_S3C_DEV_HSMMC3 | ||
289 | s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio; | ||
290 | #endif | ||
291 | } | ||
292 | |||
293 | #else | ||
294 | static inline void exynos4_default_sdhci0(void) { } | ||
295 | static inline void exynos4_default_sdhci1(void) { } | ||
296 | static inline void exynos4_default_sdhci2(void) { } | ||
297 | static inline void exynos4_default_sdhci3(void) { } | ||
298 | |||
299 | #endif /* CONFIG_EXYNOS4_SETUP_SDHCI */ | ||
300 | |||
301 | static inline void s3c_sdhci_setname(int id, char *name) | 263 | static inline void s3c_sdhci_setname(int id, char *name) |
302 | { | 264 | { |
303 | switch (id) { | 265 | switch (id) { |
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c deleted file mode 100644 index 0fceb4273824..000000000000 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | /* arch/arm/plat-samsung/irq-vic-timer.c | ||
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * S3C64XX - Interrupt handling | ||
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/interrupt.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/irqchip/chained_irq.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <mach/map.h> | ||
23 | #include <mach/irqs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | #include <plat/irq-vic-timer.h> | ||
26 | #include <plat/regs-timer.h> | ||
27 | |||
28 | static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) | ||
29 | { | ||
30 | struct irq_chip *chip = irq_get_chip(irq); | ||
31 | chained_irq_enter(chip, desc); | ||
32 | generic_handle_irq((int)desc->irq_data.handler_data); | ||
33 | chained_irq_exit(chip, desc); | ||
34 | } | ||
35 | |||
36 | /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ | ||
37 | static void s3c_irq_timer_ack(struct irq_data *d) | ||
38 | { | ||
39 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
40 | u32 mask = (1 << 5) << (d->irq - gc->irq_base); | ||
41 | |||
42 | irq_reg_writel(mask | gc->mask_cache, gc->reg_base); | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\ | ||
47 | * @num: Number of timers to initialize | ||
48 | * @timer_irq: Base IRQ number to be used for the timers. | ||
49 | * | ||
50 | * Register the necessary IRQ chaining and support for the timer IRQs | ||
51 | * chained of the VIC. | ||
52 | */ | ||
53 | void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq) | ||
54 | { | ||
55 | unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC, | ||
56 | IRQ_TIMER3_VIC, IRQ_TIMER4_VIC }; | ||
57 | struct irq_chip_generic *s3c_tgc; | ||
58 | struct irq_chip_type *ct; | ||
59 | unsigned int i; | ||
60 | |||
61 | #ifdef CONFIG_ARCH_EXYNOS | ||
62 | if (soc_is_exynos5250()) { | ||
63 | pirq[0] = EXYNOS5_IRQ_TIMER0_VIC; | ||
64 | pirq[1] = EXYNOS5_IRQ_TIMER1_VIC; | ||
65 | pirq[2] = EXYNOS5_IRQ_TIMER2_VIC; | ||
66 | pirq[3] = EXYNOS5_IRQ_TIMER3_VIC; | ||
67 | pirq[4] = EXYNOS5_IRQ_TIMER4_VIC; | ||
68 | } else { | ||
69 | pirq[0] = EXYNOS4_IRQ_TIMER0_VIC; | ||
70 | pirq[1] = EXYNOS4_IRQ_TIMER1_VIC; | ||
71 | pirq[2] = EXYNOS4_IRQ_TIMER2_VIC; | ||
72 | pirq[3] = EXYNOS4_IRQ_TIMER3_VIC; | ||
73 | pirq[4] = EXYNOS4_IRQ_TIMER4_VIC; | ||
74 | } | ||
75 | #endif | ||
76 | s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq, | ||
77 | S3C64XX_TINT_CSTAT, handle_level_irq); | ||
78 | |||
79 | if (!s3c_tgc) { | ||
80 | pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n", | ||
81 | __func__, timer_irq); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | ct = s3c_tgc->chip_types; | ||
86 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
87 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
88 | ct->chip.irq_ack = s3c_irq_timer_ack; | ||
89 | irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | ||
90 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
91 | /* Clear the upper bits of the mask_cache*/ | ||
92 | s3c_tgc->mask_cache &= 0x1f; | ||
93 | |||
94 | for (i = 0; i < num; i++, timer_irq++) { | ||
95 | irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer); | ||
96 | irq_set_handler_data(pirq[i], (void *)timer_irq); | ||
97 | } | ||
98 | } | ||
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c deleted file mode 100644 index a35ff3bcffe4..000000000000 --- a/arch/arm/plat-samsung/pwm-clock.c +++ /dev/null | |||
@@ -1,474 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/pwm-clock.c | ||
2 | * | ||
3 | * Copyright (c) 2007 Simtec Electronics | ||
4 | * Copyright (c) 2007, 2008 Ben Dooks | ||
5 | * Ben Dooks <ben-linux@fluff.org> | ||
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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/log2.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/map.h> | ||
24 | #include <asm/irq.h> | ||
25 | |||
26 | #include <plat/clock.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | #include <plat/regs-timer.h> | ||
30 | #include <plat/pwm-clock.h> | ||
31 | |||
32 | /* Each of the timers 0 through 5 go through the following | ||
33 | * clock tree, with the inputs depending on the timers. | ||
34 | * | ||
35 | * pclk ---- [ prescaler 0 ] -+---> timer 0 | ||
36 | * +---> timer 1 | ||
37 | * | ||
38 | * pclk ---- [ prescaler 1 ] -+---> timer 2 | ||
39 | * +---> timer 3 | ||
40 | * \---> timer 4 | ||
41 | * | ||
42 | * Which are fed into the timers as so: | ||
43 | * | ||
44 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
45 | * [mux] -> timer 0 | ||
46 | * tclk 0 ------------------------------/ | ||
47 | * | ||
48 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
49 | * [mux] -> timer 1 | ||
50 | * tclk 0 ------------------------------/ | ||
51 | * | ||
52 | * | ||
53 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
54 | * [mux] -> timer 2 | ||
55 | * tclk 1 ------------------------------/ | ||
56 | * | ||
57 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
58 | * [mux] -> timer 3 | ||
59 | * tclk 1 ------------------------------/ | ||
60 | * | ||
61 | * prescaled 1 ---- [ div 2,4,8, 16 ] --\ | ||
62 | * [mux] -> timer 4 | ||
63 | * tclk 1 ------------------------------/ | ||
64 | * | ||
65 | * Since the mux and the divider are tied together in the | ||
66 | * same register space, it is impossible to set the parent | ||
67 | * and the rate at the same time. To avoid this, we add an | ||
68 | * intermediate 'prescaled-and-divided' clock to select | ||
69 | * as the parent for the timer input clock called tdiv. | ||
70 | * | ||
71 | * prescaled clk --> pwm-tdiv ---\ | ||
72 | * [ mux ] --> timer X | ||
73 | * tclk -------------------------/ | ||
74 | */ | ||
75 | |||
76 | static struct clk clk_timer_scaler[]; | ||
77 | |||
78 | static unsigned long clk_pwm_scaler_get_rate(struct clk *clk) | ||
79 | { | ||
80 | unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
81 | |||
82 | if (clk == &clk_timer_scaler[1]) { | ||
83 | tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK; | ||
84 | tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT; | ||
85 | } else { | ||
86 | tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK; | ||
87 | } | ||
88 | |||
89 | return clk_get_rate(clk->parent) / (tcfg0 + 1); | ||
90 | } | ||
91 | |||
92 | static unsigned long clk_pwm_scaler_round_rate(struct clk *clk, | ||
93 | unsigned long rate) | ||
94 | { | ||
95 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
96 | unsigned long divisor = parent_rate / rate; | ||
97 | |||
98 | if (divisor > 256) | ||
99 | divisor = 256; | ||
100 | else if (divisor < 2) | ||
101 | divisor = 2; | ||
102 | |||
103 | return parent_rate / divisor; | ||
104 | } | ||
105 | |||
106 | static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate) | ||
107 | { | ||
108 | unsigned long round = clk_pwm_scaler_round_rate(clk, rate); | ||
109 | unsigned long tcfg0; | ||
110 | unsigned long divisor; | ||
111 | unsigned long flags; | ||
112 | |||
113 | divisor = clk_get_rate(clk->parent) / round; | ||
114 | divisor--; | ||
115 | |||
116 | local_irq_save(flags); | ||
117 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
118 | |||
119 | if (clk == &clk_timer_scaler[1]) { | ||
120 | tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; | ||
121 | tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT; | ||
122 | } else { | ||
123 | tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; | ||
124 | tcfg0 |= divisor; | ||
125 | } | ||
126 | |||
127 | __raw_writel(tcfg0, S3C2410_TCFG0); | ||
128 | local_irq_restore(flags); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct clk_ops clk_pwm_scaler_ops = { | ||
134 | .get_rate = clk_pwm_scaler_get_rate, | ||
135 | .set_rate = clk_pwm_scaler_set_rate, | ||
136 | .round_rate = clk_pwm_scaler_round_rate, | ||
137 | }; | ||
138 | |||
139 | static struct clk clk_timer_scaler[] = { | ||
140 | [0] = { | ||
141 | .name = "pwm-scaler0", | ||
142 | .id = -1, | ||
143 | .ops = &clk_pwm_scaler_ops, | ||
144 | }, | ||
145 | [1] = { | ||
146 | .name = "pwm-scaler1", | ||
147 | .id = -1, | ||
148 | .ops = &clk_pwm_scaler_ops, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | static struct clk clk_timer_tclk[] = { | ||
153 | [0] = { | ||
154 | .name = "pwm-tclk0", | ||
155 | .id = -1, | ||
156 | }, | ||
157 | [1] = { | ||
158 | .name = "pwm-tclk1", | ||
159 | .id = -1, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | struct pwm_tdiv_clk { | ||
164 | struct clk clk; | ||
165 | unsigned int divisor; | ||
166 | }; | ||
167 | |||
168 | static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) | ||
169 | { | ||
170 | return container_of(clk, struct pwm_tdiv_clk, clk); | ||
171 | } | ||
172 | |||
173 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | ||
174 | { | ||
175 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
176 | unsigned int divisor; | ||
177 | |||
178 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
179 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
180 | |||
181 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
182 | divisor = to_tdiv(clk)->divisor; | ||
183 | else | ||
184 | divisor = tcfg_to_divisor(tcfg1); | ||
185 | |||
186 | return clk_get_rate(clk->parent) / divisor; | ||
187 | } | ||
188 | |||
189 | static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | ||
190 | unsigned long rate) | ||
191 | { | ||
192 | unsigned long parent_rate; | ||
193 | unsigned long divisor; | ||
194 | |||
195 | parent_rate = clk_get_rate(clk->parent); | ||
196 | divisor = parent_rate / rate; | ||
197 | |||
198 | if (divisor <= 1 && pwm_tdiv_has_div1()) | ||
199 | divisor = 1; | ||
200 | else if (divisor <= 2) | ||
201 | divisor = 2; | ||
202 | else if (divisor <= 4) | ||
203 | divisor = 4; | ||
204 | else if (divisor <= 8) | ||
205 | divisor = 8; | ||
206 | else | ||
207 | divisor = 16; | ||
208 | |||
209 | return parent_rate / divisor; | ||
210 | } | ||
211 | |||
212 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) | ||
213 | { | ||
214 | return pwm_tdiv_div_bits(divclk->divisor); | ||
215 | } | ||
216 | |||
217 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) | ||
218 | { | ||
219 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
220 | unsigned long bits = clk_pwm_tdiv_bits(divclk); | ||
221 | unsigned long flags; | ||
222 | unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id); | ||
223 | |||
224 | local_irq_save(flags); | ||
225 | |||
226 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
227 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
228 | tcfg1 |= bits << shift; | ||
229 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
230 | |||
231 | local_irq_restore(flags); | ||
232 | } | ||
233 | |||
234 | static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) | ||
235 | { | ||
236 | struct pwm_tdiv_clk *divclk = to_tdiv(clk); | ||
237 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
238 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
239 | unsigned long divisor; | ||
240 | |||
241 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
242 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
243 | |||
244 | rate = clk_round_rate(clk, rate); | ||
245 | divisor = parent_rate / rate; | ||
246 | |||
247 | if (divisor > 16) | ||
248 | return -EINVAL; | ||
249 | |||
250 | divclk->divisor = divisor; | ||
251 | |||
252 | /* Update the current MUX settings if we are currently | ||
253 | * selected as the clock source for this clock. */ | ||
254 | |||
255 | if (!pwm_cfg_src_is_tclk(tcfg1)) | ||
256 | clk_pwm_tdiv_update(divclk); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static struct clk_ops clk_tdiv_ops = { | ||
262 | .get_rate = clk_pwm_tdiv_get_rate, | ||
263 | .set_rate = clk_pwm_tdiv_set_rate, | ||
264 | .round_rate = clk_pwm_tdiv_round_rate, | ||
265 | }; | ||
266 | |||
267 | static struct pwm_tdiv_clk clk_timer_tdiv[] = { | ||
268 | [0] = { | ||
269 | .clk = { | ||
270 | .name = "pwm-tdiv", | ||
271 | .devname = "s3c24xx-pwm.0", | ||
272 | .ops = &clk_tdiv_ops, | ||
273 | .parent = &clk_timer_scaler[0], | ||
274 | }, | ||
275 | }, | ||
276 | [1] = { | ||
277 | .clk = { | ||
278 | .name = "pwm-tdiv", | ||
279 | .devname = "s3c24xx-pwm.1", | ||
280 | .ops = &clk_tdiv_ops, | ||
281 | .parent = &clk_timer_scaler[0], | ||
282 | } | ||
283 | }, | ||
284 | [2] = { | ||
285 | .clk = { | ||
286 | .name = "pwm-tdiv", | ||
287 | .devname = "s3c24xx-pwm.2", | ||
288 | .ops = &clk_tdiv_ops, | ||
289 | .parent = &clk_timer_scaler[1], | ||
290 | }, | ||
291 | }, | ||
292 | [3] = { | ||
293 | .clk = { | ||
294 | .name = "pwm-tdiv", | ||
295 | .devname = "s3c24xx-pwm.3", | ||
296 | .ops = &clk_tdiv_ops, | ||
297 | .parent = &clk_timer_scaler[1], | ||
298 | }, | ||
299 | }, | ||
300 | [4] = { | ||
301 | .clk = { | ||
302 | .name = "pwm-tdiv", | ||
303 | .devname = "s3c24xx-pwm.4", | ||
304 | .ops = &clk_tdiv_ops, | ||
305 | .parent = &clk_timer_scaler[1], | ||
306 | }, | ||
307 | }, | ||
308 | }; | ||
309 | |||
310 | static int __init clk_pwm_tdiv_register(unsigned int id) | ||
311 | { | ||
312 | struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id]; | ||
313 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
314 | |||
315 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
316 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
317 | |||
318 | divclk->clk.id = id; | ||
319 | divclk->divisor = tcfg_to_divisor(tcfg1); | ||
320 | |||
321 | return s3c24xx_register_clock(&divclk->clk); | ||
322 | } | ||
323 | |||
324 | static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id) | ||
325 | { | ||
326 | return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0]; | ||
327 | } | ||
328 | |||
329 | static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id) | ||
330 | { | ||
331 | return &clk_timer_tdiv[id].clk; | ||
332 | } | ||
333 | |||
334 | static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) | ||
335 | { | ||
336 | unsigned int id = clk->id; | ||
337 | unsigned long tcfg1; | ||
338 | unsigned long flags; | ||
339 | unsigned long bits; | ||
340 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); | ||
341 | |||
342 | unsigned long mux_tclk; | ||
343 | |||
344 | if (soc_is_s3c24xx()) | ||
345 | mux_tclk = S3C2410_TCFG1_MUX_TCLK; | ||
346 | else if (soc_is_s5p6440() || soc_is_s5p6450()) | ||
347 | mux_tclk = 0; | ||
348 | else | ||
349 | mux_tclk = S3C64XX_TCFG1_MUX_TCLK; | ||
350 | |||
351 | if (parent == s3c24xx_pwmclk_tclk(id)) | ||
352 | bits = mux_tclk << shift; | ||
353 | else if (parent == s3c24xx_pwmclk_tdiv(id)) | ||
354 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; | ||
355 | else | ||
356 | return -EINVAL; | ||
357 | |||
358 | clk->parent = parent; | ||
359 | |||
360 | local_irq_save(flags); | ||
361 | |||
362 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
363 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
364 | __raw_writel(tcfg1 | bits, S3C2410_TCFG1); | ||
365 | |||
366 | local_irq_restore(flags); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct clk_ops clk_tin_ops = { | ||
372 | .set_parent = clk_pwm_tin_set_parent, | ||
373 | }; | ||
374 | |||
375 | static struct clk clk_tin[] = { | ||
376 | [0] = { | ||
377 | .name = "pwm-tin", | ||
378 | .devname = "s3c24xx-pwm.0", | ||
379 | .id = 0, | ||
380 | .ops = &clk_tin_ops, | ||
381 | }, | ||
382 | [1] = { | ||
383 | .name = "pwm-tin", | ||
384 | .devname = "s3c24xx-pwm.1", | ||
385 | .id = 1, | ||
386 | .ops = &clk_tin_ops, | ||
387 | }, | ||
388 | [2] = { | ||
389 | .name = "pwm-tin", | ||
390 | .devname = "s3c24xx-pwm.2", | ||
391 | .id = 2, | ||
392 | .ops = &clk_tin_ops, | ||
393 | }, | ||
394 | [3] = { | ||
395 | .name = "pwm-tin", | ||
396 | .devname = "s3c24xx-pwm.3", | ||
397 | .id = 3, | ||
398 | .ops = &clk_tin_ops, | ||
399 | }, | ||
400 | [4] = { | ||
401 | .name = "pwm-tin", | ||
402 | .devname = "s3c24xx-pwm.4", | ||
403 | .id = 4, | ||
404 | .ops = &clk_tin_ops, | ||
405 | }, | ||
406 | }; | ||
407 | |||
408 | static __init int clk_pwm_tin_register(struct clk *pwm) | ||
409 | { | ||
410 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
411 | unsigned int id = pwm->id; | ||
412 | |||
413 | struct clk *parent; | ||
414 | int ret; | ||
415 | |||
416 | ret = s3c24xx_register_clock(pwm); | ||
417 | if (ret < 0) | ||
418 | return ret; | ||
419 | |||
420 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
421 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
422 | |||
423 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
424 | parent = s3c24xx_pwmclk_tclk(id); | ||
425 | else | ||
426 | parent = s3c24xx_pwmclk_tdiv(id); | ||
427 | |||
428 | return clk_set_parent(pwm, parent); | ||
429 | } | ||
430 | |||
431 | /** | ||
432 | * s3c_pwmclk_init() - initialise pwm clocks | ||
433 | * | ||
434 | * Initialise and register the clocks which provide the inputs for the | ||
435 | * pwm timer blocks. | ||
436 | * | ||
437 | * Note, this call is required by the time core, so must be called after | ||
438 | * the base clocks are added and before any of the initcalls are run. | ||
439 | */ | ||
440 | __init void s3c_pwmclk_init(void) | ||
441 | { | ||
442 | struct clk *clk_timers; | ||
443 | unsigned int clk; | ||
444 | int ret; | ||
445 | |||
446 | clk_timers = clk_get(NULL, "timers"); | ||
447 | if (IS_ERR(clk_timers)) { | ||
448 | printk(KERN_ERR "%s: no parent clock\n", __func__); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) | ||
453 | clk_timer_scaler[clk].parent = clk_timers; | ||
454 | |||
455 | s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler)); | ||
456 | s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk)); | ||
457 | |||
458 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) { | ||
459 | ret = clk_pwm_tdiv_register(clk); | ||
460 | |||
461 | if (ret < 0) { | ||
462 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); | ||
463 | return; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) { | ||
468 | ret = clk_pwm_tin_register(&clk_tin[clk]); | ||
469 | if (ret < 0) { | ||
470 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); | ||
471 | return; | ||
472 | } | ||
473 | } | ||
474 | } | ||
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c index ff1a76011b1e..ddfaca9c79d8 100644 --- a/arch/arm/plat-samsung/s5p-irq.c +++ b/arch/arm/plat-samsung/s5p-irq.c | |||
@@ -17,9 +17,7 @@ | |||
17 | 17 | ||
18 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
19 | #include <mach/map.h> | 19 | #include <mach/map.h> |
20 | #include <plat/regs-timer.h> | ||
21 | #include <plat/cpu.h> | 20 | #include <plat/cpu.h> |
22 | #include <plat/irq-vic-timer.h> | ||
23 | 21 | ||
24 | void __init s5p_init_irq(u32 *vic, u32 num_vic) | 22 | void __init s5p_init_irq(u32 *vic, u32 num_vic) |
25 | { | 23 | { |
@@ -30,6 +28,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) | |||
30 | for (irq = 0; irq < num_vic; irq++) | 28 | for (irq = 0; irq < num_vic; irq++) |
31 | vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); | 29 | vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); |
32 | #endif | 30 | #endif |
33 | |||
34 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); | ||
35 | } | 31 | } |
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c deleted file mode 100644 index 2957075ca836..000000000000 --- a/arch/arm/plat-samsung/samsung-time.c +++ /dev/null | |||
@@ -1,394 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
3 | * http://www.samsung.com/ | ||
4 | * | ||
5 | * samsung - Common hr-timer support (s3c and s5p) | ||
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/interrupt.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/clockchips.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/sched_clock.h> | ||
19 | |||
20 | #include <asm/smp_twd.h> | ||
21 | #include <asm/mach/time.h> | ||
22 | #include <asm/mach/arch.h> | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
25 | #include <mach/map.h> | ||
26 | #include <plat/devs.h> | ||
27 | #include <plat/regs-timer.h> | ||
28 | #include <plat/samsung-time.h> | ||
29 | |||
30 | static struct clk *tin_event; | ||
31 | static struct clk *tin_source; | ||
32 | static struct clk *tdiv_event; | ||
33 | static struct clk *tdiv_source; | ||
34 | static struct clk *timerclk; | ||
35 | static struct samsung_timer_source timer_source; | ||
36 | static unsigned long clock_count_per_tick; | ||
37 | static void samsung_timer_resume(void); | ||
38 | |||
39 | static void samsung_time_stop(enum samsung_timer_mode mode) | ||
40 | { | ||
41 | unsigned long tcon; | ||
42 | |||
43 | tcon = __raw_readl(S3C2410_TCON); | ||
44 | |||
45 | switch (mode) { | ||
46 | case SAMSUNG_PWM0: | ||
47 | tcon &= ~S3C2410_TCON_T0START; | ||
48 | break; | ||
49 | |||
50 | case SAMSUNG_PWM1: | ||
51 | tcon &= ~S3C2410_TCON_T1START; | ||
52 | break; | ||
53 | |||
54 | case SAMSUNG_PWM2: | ||
55 | tcon &= ~S3C2410_TCON_T2START; | ||
56 | break; | ||
57 | |||
58 | case SAMSUNG_PWM3: | ||
59 | tcon &= ~S3C2410_TCON_T3START; | ||
60 | break; | ||
61 | |||
62 | case SAMSUNG_PWM4: | ||
63 | tcon &= ~S3C2410_TCON_T4START; | ||
64 | break; | ||
65 | |||
66 | default: | ||
67 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
68 | break; | ||
69 | } | ||
70 | __raw_writel(tcon, S3C2410_TCON); | ||
71 | } | ||
72 | |||
73 | static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt) | ||
74 | { | ||
75 | unsigned long tcon; | ||
76 | |||
77 | tcon = __raw_readl(S3C2410_TCON); | ||
78 | |||
79 | tcnt--; | ||
80 | |||
81 | switch (mode) { | ||
82 | case SAMSUNG_PWM0: | ||
83 | tcon &= ~(0x0f << 0); | ||
84 | tcon |= S3C2410_TCON_T0MANUALUPD; | ||
85 | break; | ||
86 | |||
87 | case SAMSUNG_PWM1: | ||
88 | tcon &= ~(0x0f << 8); | ||
89 | tcon |= S3C2410_TCON_T1MANUALUPD; | ||
90 | break; | ||
91 | |||
92 | case SAMSUNG_PWM2: | ||
93 | tcon &= ~(0x0f << 12); | ||
94 | tcon |= S3C2410_TCON_T2MANUALUPD; | ||
95 | break; | ||
96 | |||
97 | case SAMSUNG_PWM3: | ||
98 | tcon &= ~(0x0f << 16); | ||
99 | tcon |= S3C2410_TCON_T3MANUALUPD; | ||
100 | break; | ||
101 | |||
102 | case SAMSUNG_PWM4: | ||
103 | tcon &= ~(0x07 << 20); | ||
104 | tcon |= S3C2410_TCON_T4MANUALUPD; | ||
105 | break; | ||
106 | |||
107 | default: | ||
108 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | __raw_writel(tcnt, S3C2410_TCNTB(mode)); | ||
113 | __raw_writel(tcnt, S3C2410_TCMPB(mode)); | ||
114 | __raw_writel(tcon, S3C2410_TCON); | ||
115 | } | ||
116 | |||
117 | static void samsung_time_start(enum samsung_timer_mode mode, bool periodic) | ||
118 | { | ||
119 | unsigned long tcon; | ||
120 | |||
121 | tcon = __raw_readl(S3C2410_TCON); | ||
122 | |||
123 | switch (mode) { | ||
124 | case SAMSUNG_PWM0: | ||
125 | tcon |= S3C2410_TCON_T0START; | ||
126 | tcon &= ~S3C2410_TCON_T0MANUALUPD; | ||
127 | |||
128 | if (periodic) | ||
129 | tcon |= S3C2410_TCON_T0RELOAD; | ||
130 | else | ||
131 | tcon &= ~S3C2410_TCON_T0RELOAD; | ||
132 | break; | ||
133 | |||
134 | case SAMSUNG_PWM1: | ||
135 | tcon |= S3C2410_TCON_T1START; | ||
136 | tcon &= ~S3C2410_TCON_T1MANUALUPD; | ||
137 | |||
138 | if (periodic) | ||
139 | tcon |= S3C2410_TCON_T1RELOAD; | ||
140 | else | ||
141 | tcon &= ~S3C2410_TCON_T1RELOAD; | ||
142 | break; | ||
143 | |||
144 | case SAMSUNG_PWM2: | ||
145 | tcon |= S3C2410_TCON_T2START; | ||
146 | tcon &= ~S3C2410_TCON_T2MANUALUPD; | ||
147 | |||
148 | if (periodic) | ||
149 | tcon |= S3C2410_TCON_T2RELOAD; | ||
150 | else | ||
151 | tcon &= ~S3C2410_TCON_T2RELOAD; | ||
152 | break; | ||
153 | |||
154 | case SAMSUNG_PWM3: | ||
155 | tcon |= S3C2410_TCON_T3START; | ||
156 | tcon &= ~S3C2410_TCON_T3MANUALUPD; | ||
157 | |||
158 | if (periodic) | ||
159 | tcon |= S3C2410_TCON_T3RELOAD; | ||
160 | else | ||
161 | tcon &= ~S3C2410_TCON_T3RELOAD; | ||
162 | break; | ||
163 | |||
164 | case SAMSUNG_PWM4: | ||
165 | tcon |= S3C2410_TCON_T4START; | ||
166 | tcon &= ~S3C2410_TCON_T4MANUALUPD; | ||
167 | |||
168 | if (periodic) | ||
169 | tcon |= S3C2410_TCON_T4RELOAD; | ||
170 | else | ||
171 | tcon &= ~S3C2410_TCON_T4RELOAD; | ||
172 | break; | ||
173 | |||
174 | default: | ||
175 | printk(KERN_ERR "Invalid Timer %d\n", mode); | ||
176 | break; | ||
177 | } | ||
178 | __raw_writel(tcon, S3C2410_TCON); | ||
179 | } | ||
180 | |||
181 | static int samsung_set_next_event(unsigned long cycles, | ||
182 | struct clock_event_device *evt) | ||
183 | { | ||
184 | samsung_time_setup(timer_source.event_id, cycles); | ||
185 | samsung_time_start(timer_source.event_id, NON_PERIODIC); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void samsung_set_mode(enum clock_event_mode mode, | ||
191 | struct clock_event_device *evt) | ||
192 | { | ||
193 | samsung_time_stop(timer_source.event_id); | ||
194 | |||
195 | switch (mode) { | ||
196 | case CLOCK_EVT_MODE_PERIODIC: | ||
197 | samsung_time_setup(timer_source.event_id, clock_count_per_tick); | ||
198 | samsung_time_start(timer_source.event_id, PERIODIC); | ||
199 | break; | ||
200 | |||
201 | case CLOCK_EVT_MODE_ONESHOT: | ||
202 | break; | ||
203 | |||
204 | case CLOCK_EVT_MODE_UNUSED: | ||
205 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
206 | break; | ||
207 | |||
208 | case CLOCK_EVT_MODE_RESUME: | ||
209 | samsung_timer_resume(); | ||
210 | break; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void samsung_timer_resume(void) | ||
215 | { | ||
216 | /* event timer restart */ | ||
217 | samsung_time_setup(timer_source.event_id, clock_count_per_tick); | ||
218 | samsung_time_start(timer_source.event_id, PERIODIC); | ||
219 | |||
220 | /* source timer restart */ | ||
221 | samsung_time_setup(timer_source.source_id, TCNT_MAX); | ||
222 | samsung_time_start(timer_source.source_id, PERIODIC); | ||
223 | } | ||
224 | |||
225 | void __init samsung_set_timer_source(enum samsung_timer_mode event, | ||
226 | enum samsung_timer_mode source) | ||
227 | { | ||
228 | s3c_device_timer[event].dev.bus = &platform_bus_type; | ||
229 | s3c_device_timer[source].dev.bus = &platform_bus_type; | ||
230 | |||
231 | timer_source.event_id = event; | ||
232 | timer_source.source_id = source; | ||
233 | } | ||
234 | |||
235 | static struct clock_event_device time_event_device = { | ||
236 | .name = "samsung_event_timer", | ||
237 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
238 | .rating = 200, | ||
239 | .set_next_event = samsung_set_next_event, | ||
240 | .set_mode = samsung_set_mode, | ||
241 | }; | ||
242 | |||
243 | static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) | ||
244 | { | ||
245 | struct clock_event_device *evt = dev_id; | ||
246 | |||
247 | evt->event_handler(evt); | ||
248 | |||
249 | return IRQ_HANDLED; | ||
250 | } | ||
251 | |||
252 | static struct irqaction samsung_clock_event_irq = { | ||
253 | .name = "samsung_time_irq", | ||
254 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
255 | .handler = samsung_clock_event_isr, | ||
256 | .dev_id = &time_event_device, | ||
257 | }; | ||
258 | |||
259 | static void __init samsung_clockevent_init(void) | ||
260 | { | ||
261 | unsigned long pclk; | ||
262 | unsigned long clock_rate; | ||
263 | unsigned int irq_number; | ||
264 | struct clk *tscaler; | ||
265 | |||
266 | pclk = clk_get_rate(timerclk); | ||
267 | |||
268 | tscaler = clk_get_parent(tdiv_event); | ||
269 | |||
270 | clk_set_rate(tscaler, pclk / TSCALER_DIV); | ||
271 | clk_set_rate(tdiv_event, pclk / TDIV); | ||
272 | clk_set_parent(tin_event, tdiv_event); | ||
273 | |||
274 | clock_rate = clk_get_rate(tin_event); | ||
275 | clock_count_per_tick = clock_rate / HZ; | ||
276 | |||
277 | time_event_device.cpumask = cpumask_of(0); | ||
278 | clockevents_config_and_register(&time_event_device, clock_rate, 1, -1); | ||
279 | |||
280 | irq_number = timer_source.event_id + IRQ_TIMER0; | ||
281 | setup_irq(irq_number, &samsung_clock_event_irq); | ||
282 | } | ||
283 | |||
284 | static void __iomem *samsung_timer_reg(void) | ||
285 | { | ||
286 | unsigned long offset = 0; | ||
287 | |||
288 | switch (timer_source.source_id) { | ||
289 | case SAMSUNG_PWM0: | ||
290 | case SAMSUNG_PWM1: | ||
291 | case SAMSUNG_PWM2: | ||
292 | case SAMSUNG_PWM3: | ||
293 | offset = (timer_source.source_id * 0x0c) + 0x14; | ||
294 | break; | ||
295 | |||
296 | case SAMSUNG_PWM4: | ||
297 | offset = 0x40; | ||
298 | break; | ||
299 | |||
300 | default: | ||
301 | printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
305 | return S3C_TIMERREG(offset); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * Override the global weak sched_clock symbol with this | ||
310 | * local implementation which uses the clocksource to get some | ||
311 | * better resolution when scheduling the kernel. We accept that | ||
312 | * this wraps around for now, since it is just a relative time | ||
313 | * stamp. (Inspired by U300 implementation.) | ||
314 | */ | ||
315 | static u32 notrace samsung_read_sched_clock(void) | ||
316 | { | ||
317 | void __iomem *reg = samsung_timer_reg(); | ||
318 | |||
319 | if (!reg) | ||
320 | return 0; | ||
321 | |||
322 | return ~__raw_readl(reg); | ||
323 | } | ||
324 | |||
325 | static void __init samsung_clocksource_init(void) | ||
326 | { | ||
327 | unsigned long pclk; | ||
328 | unsigned long clock_rate; | ||
329 | |||
330 | pclk = clk_get_rate(timerclk); | ||
331 | |||
332 | clk_set_rate(tdiv_source, pclk / TDIV); | ||
333 | clk_set_parent(tin_source, tdiv_source); | ||
334 | |||
335 | clock_rate = clk_get_rate(tin_source); | ||
336 | |||
337 | samsung_time_setup(timer_source.source_id, TCNT_MAX); | ||
338 | samsung_time_start(timer_source.source_id, PERIODIC); | ||
339 | |||
340 | setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate); | ||
341 | |||
342 | if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer", | ||
343 | clock_rate, 250, TSIZE, clocksource_mmio_readl_down)) | ||
344 | panic("samsung_clocksource_timer: can't register clocksource\n"); | ||
345 | } | ||
346 | |||
347 | static void __init samsung_timer_resources(void) | ||
348 | { | ||
349 | |||
350 | unsigned long event_id = timer_source.event_id; | ||
351 | unsigned long source_id = timer_source.source_id; | ||
352 | char devname[15]; | ||
353 | |||
354 | timerclk = clk_get(NULL, "timers"); | ||
355 | if (IS_ERR(timerclk)) | ||
356 | panic("failed to get timers clock for timer"); | ||
357 | |||
358 | clk_enable(timerclk); | ||
359 | |||
360 | sprintf(devname, "s3c24xx-pwm.%lu", event_id); | ||
361 | s3c_device_timer[event_id].id = event_id; | ||
362 | s3c_device_timer[event_id].dev.init_name = devname; | ||
363 | |||
364 | tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin"); | ||
365 | if (IS_ERR(tin_event)) | ||
366 | panic("failed to get pwm-tin clock for event timer"); | ||
367 | |||
368 | tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv"); | ||
369 | if (IS_ERR(tdiv_event)) | ||
370 | panic("failed to get pwm-tdiv clock for event timer"); | ||
371 | |||
372 | clk_enable(tin_event); | ||
373 | |||
374 | sprintf(devname, "s3c24xx-pwm.%lu", source_id); | ||
375 | s3c_device_timer[source_id].id = source_id; | ||
376 | s3c_device_timer[source_id].dev.init_name = devname; | ||
377 | |||
378 | tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin"); | ||
379 | if (IS_ERR(tin_source)) | ||
380 | panic("failed to get pwm-tin clock for source timer"); | ||
381 | |||
382 | tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv"); | ||
383 | if (IS_ERR(tdiv_source)) | ||
384 | panic("failed to get pwm-tdiv clock for source timer"); | ||
385 | |||
386 | clk_enable(tin_source); | ||
387 | } | ||
388 | |||
389 | void __init samsung_timer_init(void) | ||
390 | { | ||
391 | samsung_timer_resources(); | ||
392 | samsung_clockevent_init(); | ||
393 | samsung_clocksource_init(); | ||
394 | } | ||