diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 21:46:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 21:46:13 -0400 |
commit | 8f446a7a069e0af0639385f67c78ee2279bca04c (patch) | |
tree | 580cf495616b36ca0af0826afa87c430cdc1e7cb /arch/arm/plat-omap | |
parent | 84be4ae2c038e2b03d650cbf2a7cfd9e8d6e9e51 (diff) | |
parent | 04ef037c926ddb31088c976538e29eada4fd1490 (diff) |
Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM soc driver specific changes from Olof Johansson:
- A long-coming conversion of various platforms to a common LED
infrastructure
- AT91 is moved over to use the newer MCI driver for MMC
- Pincontrol conversions for samsung platforms
- DT bindings for gscaler on samsung
- i2c driver fixes for tegra, acked by i2c maintainer
Fix up conflicts as per Olof.
* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (48 commits)
drivers: bus: omap_l3: use resources instead of hardcoded irqs
pinctrl: exynos: Fix wakeup IRQ domain registration check
pinctrl: samsung: Uninline samsung_pinctrl_get_soc_data
pinctrl: exynos: Correct the detection of wakeup-eint node
pinctrl: exynos: Mark exynos_irq_demux_eint as inline
pinctrl: exynos: Handle only unmasked wakeup interrupts
pinctrl: exynos: Fix typos in gpio/wkup _irq_mask
pinctrl: exynos: Set pin function to EINT in irq_set_type of GPIO EINTa
drivers: bus: Move the OMAP interconnect driver to drivers/bus/
i2c: tegra: dynamically control fast clk
i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
ARM: tegra: clock: remove unused clock entry for i2c
ARM: tegra: clock: add connection name in i2c clock entry
i2c: tegra: pass proper name for getting clock
ARM: tegra: clock: add i2c fast clock entry in clock table
ARM: EXYNOS: Adds G-Scaler device from Device Tree
ARM: EXYNOS: Add clock support for G-Scaler
ARM: EXYNOS: Enable pinctrl driver support for EXYNOS4 device tree enabled platform
ARM: dts: Add pinctrl node entries for SAMSUNG EXYNOS4210 SoC
ARM: EXYNOS: skip wakeup interrupt setup if pinctrl driver is used
...
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/debug-leds.c | 293 |
2 files changed, 68 insertions, 228 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index d15a4a6d6146..ca83a7659aef 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -42,9 +42,8 @@ config OMAP_DEBUG_DEVICES | |||
42 | For debug cards on TI reference boards. | 42 | For debug cards on TI reference boards. |
43 | 43 | ||
44 | config OMAP_DEBUG_LEDS | 44 | config OMAP_DEBUG_LEDS |
45 | bool | 45 | def_bool y if NEW_LEDS |
46 | depends on OMAP_DEBUG_DEVICES | 46 | depends on OMAP_DEBUG_DEVICES |
47 | default y if LEDS_CLASS | ||
48 | 47 | ||
49 | config POWER_AVS_OMAP | 48 | config POWER_AVS_OMAP |
50 | bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2" | 49 | bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2" |
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 195aaae65872..ea29bbe8e5cf 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c | |||
@@ -1,280 +1,119 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/debug-leds.c | 2 | * linux/arch/arm/plat-omap/debug-leds.c |
3 | * | 3 | * |
4 | * Copyright 2011 by Bryan Wu <bryan.wu@canonical.com> | ||
4 | * Copyright 2003 by Texas Instruments Incorporated | 5 | * Copyright 2003 by Texas Instruments Incorporated |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
9 | */ | 10 | */ |
10 | #include <linux/gpio.h> | 11 | |
12 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | 13 | #include <linux/init.h> |
12 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
13 | #include <linux/leds.h> | 15 | #include <linux/leds.h> |
14 | #include <linux/io.h> | 16 | #include <linux/io.h> |
15 | #include <linux/platform_data/gpio-omap.h> | 17 | #include <linux/platform_data/gpio-omap.h> |
18 | #include <linux/slab.h> | ||
16 | 19 | ||
17 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
18 | #include <asm/leds.h> | ||
19 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
20 | 22 | ||
21 | #include <plat/fpga.h> | 23 | #include <plat/fpga.h> |
22 | 24 | ||
23 | |||
24 | /* Many OMAP development platforms reuse the same "debug board"; these | 25 | /* Many OMAP development platforms reuse the same "debug board"; these |
25 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the | 26 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the |
26 | * debug board (all green), accessed through FPGA registers. | 27 | * debug board (all green), accessed through FPGA registers. |
27 | * | ||
28 | * The "surfer" expansion board and H2 sample board also have two-color | ||
29 | * green+red LEDs (in parallel), used here for timer and idle indicators | ||
30 | * in preference to the ones on the debug board, for a "Disco LED" effect. | ||
31 | * | ||
32 | * This driver exports either the original ARM LED API, the new generic | ||
33 | * one, or both. | ||
34 | */ | ||
35 | |||
36 | static spinlock_t lock; | ||
37 | static struct h2p2_dbg_fpga __iomem *fpga; | ||
38 | static u16 led_state, hw_led_state; | ||
39 | |||
40 | |||
41 | #ifdef CONFIG_OMAP_DEBUG_LEDS | ||
42 | #define new_led_api() 1 | ||
43 | #else | ||
44 | #define new_led_api() 0 | ||
45 | #endif | ||
46 | |||
47 | |||
48 | /*-------------------------------------------------------------------------*/ | ||
49 | |||
50 | /* original ARM debug LED API: | ||
51 | * - timer and idle leds (some boards use non-FPGA leds here); | ||
52 | * - up to 4 generic leds, easily accessed in-kernel (any context) | ||
53 | */ | 28 | */ |
54 | 29 | ||
55 | #define GPIO_LED_RED 3 | 30 | static struct h2p2_dbg_fpga __iomem *fpga; |
56 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
57 | |||
58 | #define LED_STATE_ENABLED 0x01 | ||
59 | #define LED_STATE_CLAIMED 0x02 | ||
60 | #define LED_TIMER_ON 0x04 | ||
61 | |||
62 | #define GPIO_IDLE GPIO_LED_GREEN | ||
63 | #define GPIO_TIMER GPIO_LED_RED | ||
64 | |||
65 | static void h2p2_dbg_leds_event(led_event_t evt) | ||
66 | { | ||
67 | unsigned long flags; | ||
68 | |||
69 | spin_lock_irqsave(&lock, flags); | ||
70 | |||
71 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
72 | goto done; | ||
73 | |||
74 | switch (evt) { | ||
75 | case led_start: | ||
76 | if (fpga) | ||
77 | led_state |= LED_STATE_ENABLED; | ||
78 | break; | ||
79 | |||
80 | case led_stop: | ||
81 | case led_halted: | ||
82 | /* all leds off during suspend or shutdown */ | ||
83 | |||
84 | if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { | ||
85 | gpio_set_value(GPIO_TIMER, 0); | ||
86 | gpio_set_value(GPIO_IDLE, 0); | ||
87 | } | ||
88 | |||
89 | __raw_writew(~0, &fpga->leds); | ||
90 | led_state &= ~LED_STATE_ENABLED; | ||
91 | goto done; | ||
92 | |||
93 | case led_claim: | ||
94 | led_state |= LED_STATE_CLAIMED; | ||
95 | hw_led_state = 0; | ||
96 | break; | ||
97 | |||
98 | case led_release: | ||
99 | led_state &= ~LED_STATE_CLAIMED; | ||
100 | break; | ||
101 | |||
102 | #ifdef CONFIG_LEDS_TIMER | ||
103 | case led_timer: | ||
104 | led_state ^= LED_TIMER_ON; | ||
105 | |||
106 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
107 | hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; | ||
108 | else { | ||
109 | gpio_set_value(GPIO_TIMER, | ||
110 | led_state & LED_TIMER_ON); | ||
111 | goto done; | ||
112 | } | ||
113 | |||
114 | break; | ||
115 | #endif | ||
116 | |||
117 | #ifdef CONFIG_LEDS_CPU | ||
118 | /* LED lit iff busy */ | ||
119 | case led_idle_start: | ||
120 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
121 | hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; | ||
122 | else { | ||
123 | gpio_set_value(GPIO_IDLE, 1); | ||
124 | goto done; | ||
125 | } | ||
126 | |||
127 | break; | ||
128 | 31 | ||
129 | case led_idle_end: | 32 | static u16 fpga_led_state; |
130 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
131 | hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; | ||
132 | else { | ||
133 | gpio_set_value(GPIO_IDLE, 0); | ||
134 | goto done; | ||
135 | } | ||
136 | |||
137 | break; | ||
138 | #endif | ||
139 | |||
140 | case led_green_on: | ||
141 | hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; | ||
142 | break; | ||
143 | case led_green_off: | ||
144 | hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; | ||
145 | break; | ||
146 | |||
147 | case led_amber_on: | ||
148 | hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; | ||
149 | break; | ||
150 | case led_amber_off: | ||
151 | hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; | ||
152 | break; | ||
153 | |||
154 | case led_red_on: | ||
155 | hw_led_state |= H2P2_DBG_FPGA_LED_RED; | ||
156 | break; | ||
157 | case led_red_off: | ||
158 | hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; | ||
159 | break; | ||
160 | |||
161 | case led_blue_on: | ||
162 | hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; | ||
163 | break; | ||
164 | case led_blue_off: | ||
165 | hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; | ||
166 | break; | ||
167 | |||
168 | default: | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | * Actually burn the LEDs | ||
175 | */ | ||
176 | if (led_state & LED_STATE_ENABLED) | ||
177 | __raw_writew(~hw_led_state, &fpga->leds); | ||
178 | |||
179 | done: | ||
180 | spin_unlock_irqrestore(&lock, flags); | ||
181 | } | ||
182 | |||
183 | /*-------------------------------------------------------------------------*/ | ||
184 | |||
185 | /* "new" LED API | ||
186 | * - with syfs access and generic triggering | ||
187 | * - not readily accessible to in-kernel drivers | ||
188 | */ | ||
189 | 33 | ||
190 | struct dbg_led { | 34 | struct dbg_led { |
191 | struct led_classdev cdev; | 35 | struct led_classdev cdev; |
192 | u16 mask; | 36 | u16 mask; |
193 | }; | 37 | }; |
194 | 38 | ||
195 | static struct dbg_led dbg_leds[] = { | 39 | static const struct { |
196 | /* REVISIT at least H2 uses different timer & cpu leds... */ | 40 | const char *name; |
197 | #ifndef CONFIG_LEDS_TIMER | 41 | const char *trigger; |
198 | { .mask = 1 << 0, .cdev.name = "d4:green", | 42 | } dbg_leds[] = { |
199 | .cdev.default_trigger = "heartbeat", }, | 43 | { "dbg:d4", "heartbeat", }, |
200 | #endif | 44 | { "dbg:d5", "cpu0", }, |
201 | #ifndef CONFIG_LEDS_CPU | 45 | { "dbg:d6", "default-on", }, |
202 | { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ | 46 | { "dbg:d7", }, |
203 | #endif | 47 | { "dbg:d8", }, |
204 | { .mask = 1 << 2, .cdev.name = "d6:green", }, | 48 | { "dbg:d9", }, |
205 | { .mask = 1 << 3, .cdev.name = "d7:green", }, | 49 | { "dbg:d10", }, |
206 | 50 | { "dbg:d11", }, | |
207 | { .mask = 1 << 4, .cdev.name = "d8:green", }, | 51 | { "dbg:d12", }, |
208 | { .mask = 1 << 5, .cdev.name = "d9:green", }, | 52 | { "dbg:d13", }, |
209 | { .mask = 1 << 6, .cdev.name = "d10:green", }, | 53 | { "dbg:d14", }, |
210 | { .mask = 1 << 7, .cdev.name = "d11:green", }, | 54 | { "dbg:d15", }, |
211 | 55 | { "dbg:d16", }, | |
212 | { .mask = 1 << 8, .cdev.name = "d12:green", }, | 56 | { "dbg:d17", }, |
213 | { .mask = 1 << 9, .cdev.name = "d13:green", }, | 57 | { "dbg:d18", }, |
214 | { .mask = 1 << 10, .cdev.name = "d14:green", }, | 58 | { "dbg:d19", }, |
215 | { .mask = 1 << 11, .cdev.name = "d15:green", }, | ||
216 | |||
217 | #ifndef CONFIG_LEDS | ||
218 | { .mask = 1 << 12, .cdev.name = "d16:green", }, | ||
219 | { .mask = 1 << 13, .cdev.name = "d17:green", }, | ||
220 | { .mask = 1 << 14, .cdev.name = "d18:green", }, | ||
221 | { .mask = 1 << 15, .cdev.name = "d19:green", }, | ||
222 | #endif | ||
223 | }; | 59 | }; |
224 | 60 | ||
225 | static void | 61 | /* |
226 | fpga_led_set(struct led_classdev *cdev, enum led_brightness value) | 62 | * The triggers lines up below will only be used if the |
63 | * LED triggers are compiled in. | ||
64 | */ | ||
65 | static void dbg_led_set(struct led_classdev *cdev, | ||
66 | enum led_brightness b) | ||
227 | { | 67 | { |
228 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); | 68 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); |
229 | unsigned long flags; | 69 | u16 reg; |
230 | 70 | ||
231 | spin_lock_irqsave(&lock, flags); | 71 | reg = __raw_readw(&fpga->leds); |
232 | if (value == LED_OFF) | 72 | if (b != LED_OFF) |
233 | hw_led_state &= ~led->mask; | 73 | reg |= led->mask; |
234 | else | 74 | else |
235 | hw_led_state |= led->mask; | 75 | reg &= ~led->mask; |
236 | __raw_writew(~hw_led_state, &fpga->leds); | 76 | __raw_writew(reg, &fpga->leds); |
237 | spin_unlock_irqrestore(&lock, flags); | ||
238 | } | 77 | } |
239 | 78 | ||
240 | static void __init newled_init(struct device *dev) | 79 | static enum led_brightness dbg_led_get(struct led_classdev *cdev) |
241 | { | 80 | { |
242 | unsigned i; | 81 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); |
243 | struct dbg_led *led; | 82 | u16 reg; |
244 | int status; | ||
245 | 83 | ||
246 | for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { | 84 | reg = __raw_readw(&fpga->leds); |
247 | led->cdev.brightness_set = fpga_led_set; | 85 | return (reg & led->mask) ? LED_FULL : LED_OFF; |
248 | status = led_classdev_register(dev, &led->cdev); | ||
249 | if (status < 0) | ||
250 | break; | ||
251 | } | ||
252 | return; | ||
253 | } | 86 | } |
254 | 87 | ||
255 | 88 | static int fpga_probe(struct platform_device *pdev) | |
256 | /*-------------------------------------------------------------------------*/ | ||
257 | |||
258 | static int /* __init */ fpga_probe(struct platform_device *pdev) | ||
259 | { | 89 | { |
260 | struct resource *iomem; | 90 | struct resource *iomem; |
261 | 91 | int i; | |
262 | spin_lock_init(&lock); | ||
263 | 92 | ||
264 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 93 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
265 | if (!iomem) | 94 | if (!iomem) |
266 | return -ENODEV; | 95 | return -ENODEV; |
267 | 96 | ||
268 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); | 97 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); |
269 | __raw_writew(~0, &fpga->leds); | 98 | __raw_writew(0xff, &fpga->leds); |
99 | |||
100 | for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) { | ||
101 | struct dbg_led *led; | ||
102 | |||
103 | led = kzalloc(sizeof(*led), GFP_KERNEL); | ||
104 | if (!led) | ||
105 | break; | ||
270 | 106 | ||
271 | #ifdef CONFIG_LEDS | 107 | led->cdev.name = dbg_leds[i].name; |
272 | leds_event = h2p2_dbg_leds_event; | 108 | led->cdev.brightness_set = dbg_led_set; |
273 | leds_event(led_start); | 109 | led->cdev.brightness_get = dbg_led_get; |
274 | #endif | 110 | led->cdev.default_trigger = dbg_leds[i].trigger; |
111 | led->mask = BIT(i); | ||
275 | 112 | ||
276 | if (new_led_api()) { | 113 | if (led_classdev_register(NULL, &led->cdev) < 0) { |
277 | newled_init(&pdev->dev); | 114 | kfree(led); |
115 | break; | ||
116 | } | ||
278 | } | 117 | } |
279 | 118 | ||
280 | return 0; | 119 | return 0; |
@@ -282,13 +121,15 @@ static int /* __init */ fpga_probe(struct platform_device *pdev) | |||
282 | 121 | ||
283 | static int fpga_suspend_noirq(struct device *dev) | 122 | static int fpga_suspend_noirq(struct device *dev) |
284 | { | 123 | { |
285 | __raw_writew(~0, &fpga->leds); | 124 | fpga_led_state = __raw_readw(&fpga->leds); |
125 | __raw_writew(0xff, &fpga->leds); | ||
126 | |||
286 | return 0; | 127 | return 0; |
287 | } | 128 | } |
288 | 129 | ||
289 | static int fpga_resume_noirq(struct device *dev) | 130 | static int fpga_resume_noirq(struct device *dev) |
290 | { | 131 | { |
291 | __raw_writew(~hw_led_state, &fpga->leds); | 132 | __raw_writew(~fpga_led_state, &fpga->leds); |
292 | return 0; | 133 | return 0; |
293 | } | 134 | } |
294 | 135 | ||