aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/Kconfig23
-rw-r--r--arch/arm/mach-msm/Makefile10
-rw-r--r--arch/arm/mach-msm/gpio-v2.c433
-rw-r--r--arch/arm/mach-msm/gpio.c376
-rw-r--r--arch/arm/mach-msm/gpio_hw.h278
-rw-r--r--arch/arm/mach-msm/gpiomux.h17
-rw-r--r--arch/arm/mach-msm/include/mach/msm_gpiomux.h (renamed from arch/arm/mach-msm/include/mach/clkdev.h)29
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-7x00.h10
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-7x30.h10
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8x50.h10
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap.h2
-rw-r--r--arch/arm/mach-msm/io.c12
-rw-r--r--arch/arm/mach-msm/iommu.c731
-rw-r--r--arch/arm/mach-msm/iommu_dev.c422
-rw-r--r--arch/arm/mach-msm/platsmp.c25
15 files changed, 65 insertions, 2323 deletions
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1516896e8d1..ebde97f5d5f 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -11,6 +11,7 @@ config ARCH_MSM7X00A
11 select MSM_SMD 11 select MSM_SMD
12 select MSM_SMD_PKG3 12 select MSM_SMD_PKG3
13 select CPU_V6 13 select CPU_V6
14 select GPIO_MSM_V1
14 select MSM_PROC_COMM 15 select MSM_PROC_COMM
15 select HAS_MSM_DEBUG_UART_PHYS 16 select HAS_MSM_DEBUG_UART_PHYS
16 17
@@ -22,6 +23,7 @@ config ARCH_MSM7X30
22 select MSM_VIC 23 select MSM_VIC
23 select CPU_V7 24 select CPU_V7
24 select MSM_GPIOMUX 25 select MSM_GPIOMUX
26 select GPIO_MSM_V1
25 select MSM_PROC_COMM 27 select MSM_PROC_COMM
26 select HAS_MSM_DEBUG_UART_PHYS 28 select HAS_MSM_DEBUG_UART_PHYS
27 29
@@ -33,6 +35,7 @@ config ARCH_QSD8X50
33 select MSM_VIC 35 select MSM_VIC
34 select CPU_V7 36 select CPU_V7
35 select MSM_GPIOMUX 37 select MSM_GPIOMUX
38 select GPIO_MSM_V1
36 select MSM_PROC_COMM 39 select MSM_PROC_COMM
37 select HAS_MSM_DEBUG_UART_PHYS 40 select HAS_MSM_DEBUG_UART_PHYS
38 41
@@ -44,6 +47,7 @@ config ARCH_MSM8X60
44 select ARM_GIC 47 select ARM_GIC
45 select CPU_V7 48 select CPU_V7
46 select MSM_V2_TLMM 49 select MSM_V2_TLMM
50 select GPIO_MSM_V2
47 select MSM_GPIOMUX 51 select MSM_GPIOMUX
48 select MSM_SCM if SMP 52 select MSM_SCM if SMP
49 53
@@ -148,22 +152,6 @@ config MACH_MSM8960_RUMI3
148 152
149endmenu 153endmenu
150 154
151config MSM_IOMMU
152 bool "MSM IOMMU Support"
153 depends on ARCH_MSM8X60 || ARCH_MSM8960
154 select IOMMU_API
155 default n
156 help
157 Support for the IOMMUs found on certain Qualcomm SOCs.
158 These IOMMUs allow virtualization of the address space used by most
159 cores within the multimedia subsystem.
160
161 If unsure, say N here.
162
163config IOMMU_PGTABLES_L2
164 def_bool y
165 depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
166
167config MSM_DEBUG_UART 155config MSM_DEBUG_UART
168 int 156 int
169 default 1 if MSM_DEBUG_UART1 157 default 1 if MSM_DEBUG_UART1
@@ -205,9 +193,6 @@ config MSM_GPIOMUX
205config MSM_V2_TLMM 193config MSM_V2_TLMM
206 bool 194 bool
207 195
208config IOMMU_API
209 bool
210
211config MSM_SCM 196config MSM_SCM
212 bool 197 bool
213endif 198endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9519fd28a02..4285dfd80b6 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -3,7 +3,7 @@ obj-y += clock.o
3obj-$(CONFIG_DEBUG_FS) += clock-debug.o 3obj-$(CONFIG_DEBUG_FS) += clock-debug.o
4 4
5obj-$(CONFIG_MSM_VIC) += irq-vic.o 5obj-$(CONFIG_MSM_VIC) += irq-vic.o
6obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o 6obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
7 7
8obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o 8obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
9obj-$(CONFIG_ARCH_MSM7X30) += dma.o 9obj-$(CONFIG_ARCH_MSM7X30) += dma.o
@@ -29,11 +29,3 @@ obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
29obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o 29obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
30obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o 30obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
31obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o 31obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
32ifdef CONFIG_MSM_V2_TLMM
33ifndef CONFIG_ARCH_MSM8960
34# TODO: TLMM Mapping issues need to be resolved
35obj-y += gpio-v2.o
36endif
37else
38obj-y += gpio.o
39endif
diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
deleted file mode 100644
index cc9c4fd7ccc..00000000000
--- a/arch/arm/mach-msm/gpio-v2.c
+++ /dev/null
@@ -1,433 +0,0 @@
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 *
17 */
18#define pr_fmt(fmt) "%s: " fmt, __func__
19
20#include <linux/bitmap.h>
21#include <linux/bitops.h>
22#include <linux/gpio.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/io.h>
26#include <linux/irq.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/spinlock.h>
30
31#include <asm/mach/irq.h>
32
33#include <mach/msm_iomap.h>
34#include "gpiomux.h"
35
36/* Bits of interest in the GPIO_IN_OUT register.
37 */
38enum {
39 GPIO_IN = 0,
40 GPIO_OUT = 1
41};
42
43/* Bits of interest in the GPIO_INTR_STATUS register.
44 */
45enum {
46 INTR_STATUS = 0,
47};
48
49/* Bits of interest in the GPIO_CFG register.
50 */
51enum {
52 GPIO_OE = 9,
53};
54
55/* Bits of interest in the GPIO_INTR_CFG register.
56 * When a GPIO triggers, two separate decisions are made, controlled
57 * by two separate flags.
58 *
59 * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
60 * register for that GPIO will be updated to reflect the triggering of that
61 * gpio. If this bit is 0, this register will not be updated.
62 * - Second, INTR_ENABLE controls whether an interrupt is triggered.
63 *
64 * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
65 * can be triggered but the status register will not reflect it.
66 */
67enum {
68 INTR_ENABLE = 0,
69 INTR_POL_CTL = 1,
70 INTR_DECT_CTL = 2,
71 INTR_RAW_STATUS_EN = 3,
72};
73
74/* Codes of interest in GPIO_INTR_CFG_SU.
75 */
76enum {
77 TARGET_PROC_SCORPION = 4,
78 TARGET_PROC_NONE = 7,
79};
80
81
82#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio)))
83#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
84#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
85#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
86#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
87
88/**
89 * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
90 *
91 * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By
92 * keeping track of which gpios are unmasked as irq sources, we avoid
93 * having to do readl calls on hundreds of iomapped registers each time
94 * the summary interrupt fires in order to locate the active interrupts.
95 *
96 * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
97 * as wakeup sources. When the device is suspended, interrupts which are
98 * not wakeup sources are disabled.
99 *
100 * @dual_edge_irqs: a bitmap used to track which irqs are configured
101 * as dual-edge, as this is not supported by the hardware and requires
102 * some special handling in the driver.
103 */
104struct msm_gpio_dev {
105 struct gpio_chip gpio_chip;
106 DECLARE_BITMAP(enabled_irqs, NR_GPIO_IRQS);
107 DECLARE_BITMAP(wake_irqs, NR_GPIO_IRQS);
108 DECLARE_BITMAP(dual_edge_irqs, NR_GPIO_IRQS);
109};
110
111static DEFINE_SPINLOCK(tlmm_lock);
112
113static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
114{
115 return container_of(chip, struct msm_gpio_dev, gpio_chip);
116}
117
118static inline void set_gpio_bits(unsigned n, void __iomem *reg)
119{
120 writel(readl(reg) | n, reg);
121}
122
123static inline void clear_gpio_bits(unsigned n, void __iomem *reg)
124{
125 writel(readl(reg) & ~n, reg);
126}
127
128static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
129{
130 return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN);
131}
132
133static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
134{
135 writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset));
136}
137
138static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
139{
140 unsigned long irq_flags;
141
142 spin_lock_irqsave(&tlmm_lock, irq_flags);
143 clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
144 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
145 return 0;
146}
147
148static int msm_gpio_direction_output(struct gpio_chip *chip,
149 unsigned offset,
150 int val)
151{
152 unsigned long irq_flags;
153
154 spin_lock_irqsave(&tlmm_lock, irq_flags);
155 msm_gpio_set(chip, offset, val);
156 set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
157 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
158 return 0;
159}
160
161static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
162{
163 return msm_gpiomux_get(chip->base + offset);
164}
165
166static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
167{
168 msm_gpiomux_put(chip->base + offset);
169}
170
171static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
172{
173 return MSM_GPIO_TO_INT(chip->base + offset);
174}
175
176static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
177{
178 return irq - MSM_GPIO_TO_INT(chip->base);
179}
180
181static struct msm_gpio_dev msm_gpio = {
182 .gpio_chip = {
183 .base = 0,
184 .ngpio = NR_GPIO_IRQS,
185 .direction_input = msm_gpio_direction_input,
186 .direction_output = msm_gpio_direction_output,
187 .get = msm_gpio_get,
188 .set = msm_gpio_set,
189 .to_irq = msm_gpio_to_irq,
190 .request = msm_gpio_request,
191 .free = msm_gpio_free,
192 },
193};
194
195/* For dual-edge interrupts in software, since the hardware has no
196 * such support:
197 *
198 * At appropriate moments, this function may be called to flip the polarity
199 * settings of both-edge irq lines to try and catch the next edge.
200 *
201 * The attempt is considered successful if:
202 * - the status bit goes high, indicating that an edge was caught, or
203 * - the input value of the gpio doesn't change during the attempt.
204 * If the value changes twice during the process, that would cause the first
205 * test to fail but would force the second, as two opposite
206 * transitions would cause a detection no matter the polarity setting.
207 *
208 * The do-loop tries to sledge-hammer closed the timing hole between
209 * the initial value-read and the polarity-write - if the line value changes
210 * during that window, an interrupt is lost, the new polarity setting is
211 * incorrect, and the first success test will fail, causing a retry.
212 *
213 * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
214 */
215static void msm_gpio_update_dual_edge_pos(unsigned gpio)
216{
217 int loop_limit = 100;
218 unsigned val, val2, intstat;
219
220 do {
221 val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
222 if (val)
223 clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
224 else
225 set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
226 val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
227 intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS);
228 if (intstat || val == val2)
229 return;
230 } while (loop_limit-- > 0);
231 pr_err("dual-edge irq failed to stabilize, "
232 "interrupts dropped. %#08x != %#08x\n",
233 val, val2);
234}
235
236static void msm_gpio_irq_ack(struct irq_data *d)
237{
238 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
239
240 writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
241 if (test_bit(gpio, msm_gpio.dual_edge_irqs))
242 msm_gpio_update_dual_edge_pos(gpio);
243}
244
245static void msm_gpio_irq_mask(struct irq_data *d)
246{
247 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
248 unsigned long irq_flags;
249
250 spin_lock_irqsave(&tlmm_lock, irq_flags);
251 writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
252 clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
253 __clear_bit(gpio, msm_gpio.enabled_irqs);
254 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
255}
256
257static void msm_gpio_irq_unmask(struct irq_data *d)
258{
259 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
260 unsigned long irq_flags;
261
262 spin_lock_irqsave(&tlmm_lock, irq_flags);
263 __set_bit(gpio, msm_gpio.enabled_irqs);
264 set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
265 writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
266 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
267}
268
269static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
270{
271 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
272 unsigned long irq_flags;
273 uint32_t bits;
274
275 spin_lock_irqsave(&tlmm_lock, irq_flags);
276
277 bits = readl(GPIO_INTR_CFG(gpio));
278
279 if (flow_type & IRQ_TYPE_EDGE_BOTH) {
280 bits |= BIT(INTR_DECT_CTL);
281 __irq_set_handler_locked(d->irq, handle_edge_irq);
282 if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
283 __set_bit(gpio, msm_gpio.dual_edge_irqs);
284 else
285 __clear_bit(gpio, msm_gpio.dual_edge_irqs);
286 } else {
287 bits &= ~BIT(INTR_DECT_CTL);
288 __irq_set_handler_locked(d->irq, handle_level_irq);
289 __clear_bit(gpio, msm_gpio.dual_edge_irqs);
290 }
291
292 if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
293 bits |= BIT(INTR_POL_CTL);
294 else
295 bits &= ~BIT(INTR_POL_CTL);
296
297 writel(bits, GPIO_INTR_CFG(gpio));
298
299 if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
300 msm_gpio_update_dual_edge_pos(gpio);
301
302 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
303
304 return 0;
305}
306
307/*
308 * When the summary IRQ is raised, any number of GPIO lines may be high.
309 * It is the job of the summary handler to find all those GPIO lines
310 * which have been set as summary IRQ lines and which are triggered,
311 * and to call their interrupt handlers.
312 */
313static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
314{
315 unsigned long i;
316 struct irq_chip *chip = irq_desc_get_chip(desc);
317
318 chained_irq_enter(chip, desc);
319
320 for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
321 i < NR_GPIO_IRQS;
322 i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) {
323 if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
324 generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
325 i));
326 }
327
328 chained_irq_exit(chip, desc);
329}
330
331static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
332{
333 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
334
335 if (on) {
336 if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
337 irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
338 set_bit(gpio, msm_gpio.wake_irqs);
339 } else {
340 clear_bit(gpio, msm_gpio.wake_irqs);
341 if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
342 irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
343 }
344
345 return 0;
346}
347
348static struct irq_chip msm_gpio_irq_chip = {
349 .name = "msmgpio",
350 .irq_mask = msm_gpio_irq_mask,
351 .irq_unmask = msm_gpio_irq_unmask,
352 .irq_ack = msm_gpio_irq_ack,
353 .irq_set_type = msm_gpio_irq_set_type,
354 .irq_set_wake = msm_gpio_irq_set_wake,
355};
356
357static int __devinit msm_gpio_probe(struct platform_device *dev)
358{
359 int i, irq, ret;
360
361 bitmap_zero(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
362 bitmap_zero(msm_gpio.wake_irqs, NR_GPIO_IRQS);
363 bitmap_zero(msm_gpio.dual_edge_irqs, NR_GPIO_IRQS);
364 msm_gpio.gpio_chip.label = dev->name;
365 ret = gpiochip_add(&msm_gpio.gpio_chip);
366 if (ret < 0)
367 return ret;
368
369 for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
370 irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
371 irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
372 handle_level_irq);
373 set_irq_flags(irq, IRQF_VALID);
374 }
375
376 irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
377 msm_summary_irq_handler);
378 return 0;
379}
380
381static int __devexit msm_gpio_remove(struct platform_device *dev)
382{
383 int ret = gpiochip_remove(&msm_gpio.gpio_chip);
384
385 if (ret < 0)
386 return ret;
387
388 irq_set_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
389
390 return 0;
391}
392
393static struct platform_driver msm_gpio_driver = {
394 .probe = msm_gpio_probe,
395 .remove = __devexit_p(msm_gpio_remove),
396 .driver = {
397 .name = "msmgpio",
398 .owner = THIS_MODULE,
399 },
400};
401
402static struct platform_device msm_device_gpio = {
403 .name = "msmgpio",
404 .id = -1,
405};
406
407static int __init msm_gpio_init(void)
408{
409 int rc;
410
411 rc = platform_driver_register(&msm_gpio_driver);
412 if (!rc) {
413 rc = platform_device_register(&msm_device_gpio);
414 if (rc)
415 platform_driver_unregister(&msm_gpio_driver);
416 }
417
418 return rc;
419}
420
421static void __exit msm_gpio_exit(void)
422{
423 platform_device_unregister(&msm_device_gpio);
424 platform_driver_unregister(&msm_gpio_driver);
425}
426
427postcore_initcall(msm_gpio_init);
428module_exit(msm_gpio_exit);
429
430MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
431MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
432MODULE_LICENSE("GPL v2");
433MODULE_ALIAS("platform:msmgpio");
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
deleted file mode 100644
index 5ea273b00da..00000000000
--- a/arch/arm/mach-msm/gpio.c
+++ /dev/null
@@ -1,376 +0,0 @@
1/* linux/arch/arm/mach-msm/gpio.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/bitops.h>
18#include <linux/gpio.h>
19#include <linux/interrupt.h>
20#include <linux/io.h>
21#include <linux/irq.h>
22#include <linux/module.h>
23#include "gpio_hw.h"
24#include "gpiomux.h"
25
26#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
27
28#define MSM_GPIO_BANK(bank, first, last) \
29 { \
30 .regs = { \
31 .out = MSM_GPIO_OUT_##bank, \
32 .in = MSM_GPIO_IN_##bank, \
33 .int_status = MSM_GPIO_INT_STATUS_##bank, \
34 .int_clear = MSM_GPIO_INT_CLEAR_##bank, \
35 .int_en = MSM_GPIO_INT_EN_##bank, \
36 .int_edge = MSM_GPIO_INT_EDGE_##bank, \
37 .int_pos = MSM_GPIO_INT_POS_##bank, \
38 .oe = MSM_GPIO_OE_##bank, \
39 }, \
40 .chip = { \
41 .base = (first), \
42 .ngpio = (last) - (first) + 1, \
43 .get = msm_gpio_get, \
44 .set = msm_gpio_set, \
45 .direction_input = msm_gpio_direction_input, \
46 .direction_output = msm_gpio_direction_output, \
47 .to_irq = msm_gpio_to_irq, \
48 .request = msm_gpio_request, \
49 .free = msm_gpio_free, \
50 } \
51 }
52
53#define MSM_GPIO_BROKEN_INT_CLEAR 1
54
55struct msm_gpio_regs {
56 void __iomem *out;
57 void __iomem *in;
58 void __iomem *int_status;
59 void __iomem *int_clear;
60 void __iomem *int_en;
61 void __iomem *int_edge;
62 void __iomem *int_pos;
63 void __iomem *oe;
64};
65
66struct msm_gpio_chip {
67 spinlock_t lock;
68 struct gpio_chip chip;
69 struct msm_gpio_regs regs;
70#if MSM_GPIO_BROKEN_INT_CLEAR
71 unsigned int_status_copy;
72#endif
73 unsigned int both_edge_detect;
74 unsigned int int_enable[2]; /* 0: awake, 1: sleep */
75};
76
77static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
78 unsigned offset, unsigned on)
79{
80 unsigned mask = BIT(offset);
81 unsigned val;
82
83 val = readl(msm_chip->regs.out);
84 if (on)
85 writel(val | mask, msm_chip->regs.out);
86 else
87 writel(val & ~mask, msm_chip->regs.out);
88 return 0;
89}
90
91static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
92{
93 int loop_limit = 100;
94 unsigned pol, val, val2, intstat;
95 do {
96 val = readl(msm_chip->regs.in);
97 pol = readl(msm_chip->regs.int_pos);
98 pol = (pol & ~msm_chip->both_edge_detect) |
99 (~val & msm_chip->both_edge_detect);
100 writel(pol, msm_chip->regs.int_pos);
101 intstat = readl(msm_chip->regs.int_status);
102 val2 = readl(msm_chip->regs.in);
103 if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
104 return;
105 } while (loop_limit-- > 0);
106 printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
107 "failed to reach stable state %x != %x\n", val, val2);
108}
109
110static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
111 unsigned offset)
112{
113 unsigned bit = BIT(offset);
114
115#if MSM_GPIO_BROKEN_INT_CLEAR
116 /* Save interrupts that already triggered before we loose them. */
117 /* Any interrupt that triggers between the read of int_status */
118 /* and the write to int_clear will still be lost though. */
119 msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
120 msm_chip->int_status_copy &= ~bit;
121#endif
122 writel(bit, msm_chip->regs.int_clear);
123 msm_gpio_update_both_edge_detect(msm_chip);
124 return 0;
125}
126
127static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
128{
129 struct msm_gpio_chip *msm_chip;
130 unsigned long irq_flags;
131
132 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
133 spin_lock_irqsave(&msm_chip->lock, irq_flags);
134 writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
135 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
136 return 0;
137}
138
139static int
140msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
141{
142 struct msm_gpio_chip *msm_chip;
143 unsigned long irq_flags;
144
145 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
146 spin_lock_irqsave(&msm_chip->lock, irq_flags);
147 msm_gpio_write(msm_chip, offset, value);
148 writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
149 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
150 return 0;
151}
152
153static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
154{
155 struct msm_gpio_chip *msm_chip;
156
157 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
158 return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
159}
160
161static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
162{
163 struct msm_gpio_chip *msm_chip;
164 unsigned long irq_flags;
165
166 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
167 spin_lock_irqsave(&msm_chip->lock, irq_flags);
168 msm_gpio_write(msm_chip, offset, value);
169 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
170}
171
172static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
173{
174 return MSM_GPIO_TO_INT(chip->base + offset);
175}
176
177#ifdef CONFIG_MSM_GPIOMUX
178static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
179{
180 return msm_gpiomux_get(chip->base + offset);
181}
182
183static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
184{
185 msm_gpiomux_put(chip->base + offset);
186}
187#else
188#define msm_gpio_request NULL
189#define msm_gpio_free NULL
190#endif
191
192struct msm_gpio_chip msm_gpio_chips[] = {
193#if defined(CONFIG_ARCH_MSM7X00A)
194 MSM_GPIO_BANK(0, 0, 15),
195 MSM_GPIO_BANK(1, 16, 42),
196 MSM_GPIO_BANK(2, 43, 67),
197 MSM_GPIO_BANK(3, 68, 94),
198 MSM_GPIO_BANK(4, 95, 106),
199 MSM_GPIO_BANK(5, 107, 121),
200#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
201 MSM_GPIO_BANK(0, 0, 15),
202 MSM_GPIO_BANK(1, 16, 42),
203 MSM_GPIO_BANK(2, 43, 67),
204 MSM_GPIO_BANK(3, 68, 94),
205 MSM_GPIO_BANK(4, 95, 106),
206 MSM_GPIO_BANK(5, 107, 132),
207#elif defined(CONFIG_ARCH_MSM7X30)
208 MSM_GPIO_BANK(0, 0, 15),
209 MSM_GPIO_BANK(1, 16, 43),
210 MSM_GPIO_BANK(2, 44, 67),
211 MSM_GPIO_BANK(3, 68, 94),
212 MSM_GPIO_BANK(4, 95, 106),
213 MSM_GPIO_BANK(5, 107, 133),
214 MSM_GPIO_BANK(6, 134, 150),
215 MSM_GPIO_BANK(7, 151, 181),
216#elif defined(CONFIG_ARCH_QSD8X50)
217 MSM_GPIO_BANK(0, 0, 15),
218 MSM_GPIO_BANK(1, 16, 42),
219 MSM_GPIO_BANK(2, 43, 67),
220 MSM_GPIO_BANK(3, 68, 94),
221 MSM_GPIO_BANK(4, 95, 103),
222 MSM_GPIO_BANK(5, 104, 121),
223 MSM_GPIO_BANK(6, 122, 152),
224 MSM_GPIO_BANK(7, 153, 164),
225#endif
226};
227
228static void msm_gpio_irq_ack(struct irq_data *d)
229{
230 unsigned long irq_flags;
231 struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
232 spin_lock_irqsave(&msm_chip->lock, irq_flags);
233 msm_gpio_clear_detect_status(msm_chip,
234 d->irq - gpio_to_irq(msm_chip->chip.base));
235 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
236}
237
238static void msm_gpio_irq_mask(struct irq_data *d)
239{
240 unsigned long irq_flags;
241 struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
242 unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
243
244 spin_lock_irqsave(&msm_chip->lock, irq_flags);
245 /* level triggered interrupts are also latched */
246 if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
247 msm_gpio_clear_detect_status(msm_chip, offset);
248 msm_chip->int_enable[0] &= ~BIT(offset);
249 writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
250 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
251}
252
253static void msm_gpio_irq_unmask(struct irq_data *d)
254{
255 unsigned long irq_flags;
256 struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
257 unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
258
259 spin_lock_irqsave(&msm_chip->lock, irq_flags);
260 /* level triggered interrupts are also latched */
261 if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
262 msm_gpio_clear_detect_status(msm_chip, offset);
263 msm_chip->int_enable[0] |= BIT(offset);
264 writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
265 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
266}
267
268static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
269{
270 unsigned long irq_flags;
271 struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
272 unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
273
274 spin_lock_irqsave(&msm_chip->lock, irq_flags);
275
276 if (on)
277 msm_chip->int_enable[1] |= BIT(offset);
278 else
279 msm_chip->int_enable[1] &= ~BIT(offset);
280
281 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
282 return 0;
283}
284
285static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
286{
287 unsigned long irq_flags;
288 struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
289 unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
290 unsigned val, mask = BIT(offset);
291
292 spin_lock_irqsave(&msm_chip->lock, irq_flags);
293 val = readl(msm_chip->regs.int_edge);
294 if (flow_type & IRQ_TYPE_EDGE_BOTH) {
295 writel(val | mask, msm_chip->regs.int_edge);
296 __irq_set_handler_locked(d->irq, handle_edge_irq);
297 } else {
298 writel(val & ~mask, msm_chip->regs.int_edge);
299 __irq_set_handler_locked(d->irq, handle_level_irq);
300 }
301 if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
302 msm_chip->both_edge_detect |= mask;
303 msm_gpio_update_both_edge_detect(msm_chip);
304 } else {
305 msm_chip->both_edge_detect &= ~mask;
306 val = readl(msm_chip->regs.int_pos);
307 if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
308 writel(val | mask, msm_chip->regs.int_pos);
309 else
310 writel(val & ~mask, msm_chip->regs.int_pos);
311 }
312 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
313 return 0;
314}
315
316static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
317{
318 int i, j, mask;
319 unsigned val;
320
321 for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
322 struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
323 val = readl(msm_chip->regs.int_status);
324 val &= msm_chip->int_enable[0];
325 while (val) {
326 mask = val & -val;
327 j = fls(mask) - 1;
328 /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
329 __func__, v, m, j, msm_chip->chip.start + j,
330 FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
331 val &= ~mask;
332 generic_handle_irq(FIRST_GPIO_IRQ +
333 msm_chip->chip.base + j);
334 }
335 }
336 desc->irq_data.chip->irq_ack(&desc->irq_data);
337}
338
339static struct irq_chip msm_gpio_irq_chip = {
340 .name = "msmgpio",
341 .irq_ack = msm_gpio_irq_ack,
342 .irq_mask = msm_gpio_irq_mask,
343 .irq_unmask = msm_gpio_irq_unmask,
344 .irq_set_wake = msm_gpio_irq_set_wake,
345 .irq_set_type = msm_gpio_irq_set_type,
346};
347
348static int __init msm_init_gpio(void)
349{
350 int i, j = 0;
351
352 for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
353 if (i - FIRST_GPIO_IRQ >=
354 msm_gpio_chips[j].chip.base +
355 msm_gpio_chips[j].chip.ngpio)
356 j++;
357 irq_set_chip_data(i, &msm_gpio_chips[j]);
358 irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
359 handle_edge_irq);
360 set_irq_flags(i, IRQF_VALID);
361 }
362
363 for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
364 spin_lock_init(&msm_gpio_chips[i].lock);
365 writel(0, msm_gpio_chips[i].regs.int_en);
366 gpiochip_add(&msm_gpio_chips[i].chip);
367 }
368
369 irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
370 irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
371 irq_set_irq_wake(INT_GPIO_GROUP1, 1);
372 irq_set_irq_wake(INT_GPIO_GROUP2, 2);
373 return 0;
374}
375
376postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
deleted file mode 100644
index 6b5066038ba..00000000000
--- a/arch/arm/mach-msm/gpio_hw.h
+++ /dev/null
@@ -1,278 +0,0 @@
1/* arch/arm/mach-msm/gpio_hw.h
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Author: Brian Swetland <swetland@google.com>
5 * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
19#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
20
21#include <mach/msm_iomap.h>
22
23/* see 80-VA736-2 Rev C pp 695-751
24**
25** These are actually the *shadow* gpio registers, since the
26** real ones (which allow full access) are only available to the
27** ARM9 side of the world.
28**
29** Since the _BASE need to be page-aligned when we're mapping them
30** to virtual addresses, adjust for the additional offset in these
31** macros.
32*/
33
34#if defined(CONFIG_ARCH_MSM7X30)
35#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
36#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
37#else
38#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
39#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
40#endif
41
42#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
43 defined(CONFIG_ARCH_MSM7X27)
44
45/* output value */
46#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
47#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
48#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
49#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
50#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
51#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 107-121 */
52
53/* same pin map as above, output enable */
54#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
55#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
56#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
57#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
58#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
59#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
60
61/* same pin map as above, input read */
62#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
63#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
64#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
65#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
66#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
67#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
68
69/* same pin map as above, 1=edge 0=level interrup */
70#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
71#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
72#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
73#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
74#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
75#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
76
77/* same pin map as above, 1=positive 0=negative */
78#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
79#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
80#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
81#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
82#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
83#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
84
85/* same pin map as above, interrupt enable */
86#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
87#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
88#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
89#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
90#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
91#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
92
93/* same pin map as above, write 1 to clear interrupt */
94#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
95#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
96#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
97#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
98#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
99#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
100
101/* same pin map as above, 1=interrupt pending */
102#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
103#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
104#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
105#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
106#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
107#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
108
109#endif
110
111#if defined(CONFIG_ARCH_QSD8X50)
112/* output value */
113#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
114#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
115#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
116#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
117#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 103-95 */
118#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x10) /* gpio 121-104 */
119#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0x14) /* gpio 152-122 */
120#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x18) /* gpio 164-153 */
121
122/* same pin map as above, output enable */
123#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x20)
124#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
125#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x24)
126#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x28)
127#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x2C)
128#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x30)
129#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0x34)
130#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x38)
131
132/* same pin map as above, input read */
133#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x50)
134#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
135#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x54)
136#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x58)
137#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x5C)
138#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x60)
139#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0x64)
140#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x68)
141
142/* same pin map as above, 1=edge 0=level interrup */
143#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x70)
144#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
145#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x74)
146#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x78)
147#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x7C)
148#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0x80)
149#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0x84)
150#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x88)
151
152/* same pin map as above, 1=positive 0=negative */
153#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x90)
154#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
155#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x94)
156#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x98)
157#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x9C)
158#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xA0)
159#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xA4)
160#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0xA8)
161
162/* same pin map as above, interrupt enable */
163#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0xB0)
164#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
165#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0xB4)
166#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0xB8)
167#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0xBC)
168#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xC0)
169#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xC4)
170#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0xC8)
171
172/* same pin map as above, write 1 to clear interrupt */
173#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0xD0)
174#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
175#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0xD4)
176#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0xD8)
177#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0xDC)
178#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xE0)
179#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xE4)
180#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0xE8)
181
182/* same pin map as above, 1=interrupt pending */
183#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xF0)
184#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
185#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xF4)
186#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xF8)
187#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xFC)
188#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0x100)
189#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0x104)
190#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x108)
191
192#endif
193
194#if defined(CONFIG_ARCH_MSM7X30)
195
196/* output value */
197#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
198#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 43-16 */
199#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-44 */
200#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
201#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
202#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 133-107 */
203#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0xC4) /* gpio 150-134 */
204#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x214) /* gpio 181-151 */
205
206/* same pin map as above, output enable */
207#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
208#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
209#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
210#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
211#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
212#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
213#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0xC8)
214#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x218)
215
216/* same pin map as above, input read */
217#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
218#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
219#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
220#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
221#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
222#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
223#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0xCC)
224#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x21C)
225
226/* same pin map as above, 1=edge 0=level interrup */
227#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
228#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
229#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
230#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
231#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
232#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
233#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0xD0)
234#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x240)
235
236/* same pin map as above, 1=positive 0=negative */
237#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
238#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
239#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
240#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
241#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
242#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
243#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
244#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
245
246/* same pin map as above, interrupt enable */
247#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
248#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
249#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
250#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
251#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
252#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
253#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xD8)
254#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0x22C)
255
256/* same pin map as above, write 1 to clear interrupt */
257#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
258#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
259#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
260#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
261#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
262#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
263#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xDC)
264#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0x230)
265
266/* same pin map as above, 1=interrupt pending */
267#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
268#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
269#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
270#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
271#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
272#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
273#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0xE0)
274#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x234)
275
276#endif
277
278#endif
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
index b178d9cb742..00459f6ee13 100644
--- a/arch/arm/mach-msm/gpiomux.h
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -19,6 +19,7 @@
19 19
20#include <linux/bitops.h> 20#include <linux/bitops.h>
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <mach/msm_gpiomux.h>
22 23
23#if defined(CONFIG_MSM_V2_TLMM) 24#if defined(CONFIG_MSM_V2_TLMM)
24#include "gpiomux-v2.h" 25#include "gpiomux-v2.h"
@@ -71,12 +72,6 @@ enum {
71 */ 72 */
72extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS]; 73extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
73 74
74/* Increment a gpio's reference count, possibly activating the line. */
75int __must_check msm_gpiomux_get(unsigned gpio);
76
77/* Decrement a gpio's reference count, possibly suspending the line. */
78int msm_gpiomux_put(unsigned gpio);
79
80/* Install a new configuration to the gpio line. To avoid overwriting 75/* Install a new configuration to the gpio line. To avoid overwriting
81 * a configuration, leave the VALID bit out. 76 * a configuration, leave the VALID bit out.
82 */ 77 */
@@ -94,16 +89,6 @@ int msm_gpiomux_write(unsigned gpio,
94 */ 89 */
95void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val); 90void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
96#else 91#else
97static inline int __must_check msm_gpiomux_get(unsigned gpio)
98{
99 return -ENOSYS;
100}
101
102static inline int msm_gpiomux_put(unsigned gpio)
103{
104 return -ENOSYS;
105}
106
107static inline int msm_gpiomux_write(unsigned gpio, 92static inline int msm_gpiomux_write(unsigned gpio,
108 gpiomux_config_t active, 93 gpiomux_config_t active,
109 gpiomux_config_t suspended) 94 gpiomux_config_t suspended)
diff --git a/arch/arm/mach-msm/include/mach/clkdev.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
index f87a57b5953..0c7d3936e02 100644
--- a/arch/arm/mach-msm/include/mach/clkdev.h
+++ b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
@@ -9,11 +9,30 @@
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details. 10 * GNU General Public License for more details.
11 */ 11 */
12#ifndef __ASM_ARCH_MSM_CLKDEV_H
13#define __ASM_ARCH_MSM_CLKDEV_H
14 12
15struct clk; 13#ifndef _LINUX_MSM_GPIOMUX_H
14#define _LINUX_MSM_GPIOMUX_H
15
16#ifdef CONFIG_MSM_GPIOMUX
17
18/* Increment a gpio's reference count, possibly activating the line. */
19int __must_check msm_gpiomux_get(unsigned gpio);
20
21/* Decrement a gpio's reference count, possibly suspending the line. */
22int msm_gpiomux_put(unsigned gpio);
23
24#else
25
26static inline int __must_check msm_gpiomux_get(unsigned gpio)
27{
28 return -ENOSYS;
29}
30
31static inline int msm_gpiomux_put(unsigned gpio)
32{
33 return -ENOSYS;
34}
16 35
17static inline int __clk_get(struct clk *clk) { return 1; }
18static inline void __clk_put(struct clk *clk) { }
19#endif 36#endif
37
38#endif /* _LINUX_MSM_GPIOMUX_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index 8f99d97615a..94fe9fe6feb 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -55,13 +55,11 @@
55#define MSM_DMOV_PHYS 0xA9700000 55#define MSM_DMOV_PHYS 0xA9700000
56#define MSM_DMOV_SIZE SZ_4K 56#define MSM_DMOV_SIZE SZ_4K
57 57
58#define MSM_GPIO1_BASE IOMEM(0xE0003000) 58#define MSM7X00_GPIO1_PHYS 0xA9200000
59#define MSM_GPIO1_PHYS 0xA9200000 59#define MSM7X00_GPIO1_SIZE SZ_4K
60#define MSM_GPIO1_SIZE SZ_4K
61 60
62#define MSM_GPIO2_BASE IOMEM(0xE0004000) 61#define MSM7X00_GPIO2_PHYS 0xA9300000
63#define MSM_GPIO2_PHYS 0xA9300000 62#define MSM7X00_GPIO2_SIZE SZ_4K
64#define MSM_GPIO2_SIZE SZ_4K
65 63
66#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) 64#define MSM_CLK_CTL_BASE IOMEM(0xE0005000)
67#define MSM_CLK_CTL_PHYS 0xA8600000 65#define MSM_CLK_CTL_PHYS 0xA8600000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index 4d84be15955..37694442d1b 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -46,13 +46,11 @@
46#define MSM_DMOV_PHYS 0xAC400000 46#define MSM_DMOV_PHYS 0xAC400000
47#define MSM_DMOV_SIZE SZ_4K 47#define MSM_DMOV_SIZE SZ_4K
48 48
49#define MSM_GPIO1_BASE IOMEM(0xE0003000) 49#define MSM7X30_GPIO1_PHYS 0xAC001000
50#define MSM_GPIO1_PHYS 0xAC001000 50#define MSM7X30_GPIO1_SIZE SZ_4K
51#define MSM_GPIO1_SIZE SZ_4K
52 51
53#define MSM_GPIO2_BASE IOMEM(0xE0004000) 52#define MSM7X30_GPIO2_PHYS 0xAC101000
54#define MSM_GPIO2_PHYS 0xAC101000 53#define MSM7X30_GPIO2_SIZE SZ_4K
55#define MSM_GPIO2_SIZE SZ_4K
56 54
57#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) 55#define MSM_CLK_CTL_BASE IOMEM(0xE0005000)
58#define MSM_CLK_CTL_PHYS 0xAB800000 56#define MSM_CLK_CTL_PHYS 0xAB800000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index d4143201999..d67cd73316f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -46,13 +46,11 @@
46#define MSM_DMOV_PHYS 0xA9700000 46#define MSM_DMOV_PHYS 0xA9700000
47#define MSM_DMOV_SIZE SZ_4K 47#define MSM_DMOV_SIZE SZ_4K
48 48
49#define MSM_GPIO1_BASE IOMEM(0xE0003000) 49#define QSD8X50_GPIO1_PHYS 0xA9000000
50#define MSM_GPIO1_PHYS 0xA9000000 50#define QSD8X50_GPIO1_SIZE SZ_4K
51#define MSM_GPIO1_SIZE SZ_4K
52 51
53#define MSM_GPIO2_BASE IOMEM(0xE0004000) 52#define QSD8X50_GPIO2_PHYS 0xA9100000
54#define MSM_GPIO2_PHYS 0xA9100000 53#define QSD8X50_GPIO2_SIZE SZ_4K
55#define MSM_GPIO2_SIZE SZ_4K
56 54
57#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) 55#define MSM_CLK_CTL_BASE IOMEM(0xE0005000)
58#define MSM_CLK_CTL_PHYS 0xA8600000 56#define MSM_CLK_CTL_PHYS 0xA8600000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 2f494b6a9d0..4ded15238b6 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -61,5 +61,7 @@
61#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000) 61#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000)
62#define MSM_TMR_BASE IOMEM(0xF0200000) 62#define MSM_TMR_BASE IOMEM(0xF0200000)
63#define MSM_TMR0_BASE IOMEM(0xF0201000) 63#define MSM_TMR0_BASE IOMEM(0xF0201000)
64#define MSM_GPIO1_BASE IOMEM(0xE0003000)
65#define MSM_GPIO2_BASE IOMEM(0xE0004000)
64 66
65#endif 67#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index cec6ed1c91d..140ddbbc3a8 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -43,8 +43,8 @@ static struct map_desc msm_io_desc[] __initdata = {
43 MSM_DEVICE(VIC), 43 MSM_DEVICE(VIC),
44 MSM_CHIP_DEVICE(CSR, MSM7X00), 44 MSM_CHIP_DEVICE(CSR, MSM7X00),
45 MSM_DEVICE(DMOV), 45 MSM_DEVICE(DMOV),
46 MSM_DEVICE(GPIO1), 46 MSM_CHIP_DEVICE(GPIO1, MSM7X00),
47 MSM_DEVICE(GPIO2), 47 MSM_CHIP_DEVICE(GPIO2, MSM7X00),
48 MSM_DEVICE(CLK_CTL), 48 MSM_DEVICE(CLK_CTL),
49#ifdef CONFIG_MSM_DEBUG_UART 49#ifdef CONFIG_MSM_DEBUG_UART
50 MSM_DEVICE(DEBUG_UART), 50 MSM_DEVICE(DEBUG_UART),
@@ -76,8 +76,8 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
76 MSM_DEVICE(VIC), 76 MSM_DEVICE(VIC),
77 MSM_CHIP_DEVICE(CSR, QSD8X50), 77 MSM_CHIP_DEVICE(CSR, QSD8X50),
78 MSM_DEVICE(DMOV), 78 MSM_DEVICE(DMOV),
79 MSM_DEVICE(GPIO1), 79 MSM_CHIP_DEVICE(GPIO1, QSD8X50),
80 MSM_DEVICE(GPIO2), 80 MSM_CHIP_DEVICE(GPIO2, QSD8X50),
81 MSM_DEVICE(CLK_CTL), 81 MSM_DEVICE(CLK_CTL),
82 MSM_DEVICE(SIRC), 82 MSM_DEVICE(SIRC),
83 MSM_DEVICE(SCPLL), 83 MSM_DEVICE(SCPLL),
@@ -135,8 +135,8 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
135 MSM_DEVICE(VIC), 135 MSM_DEVICE(VIC),
136 MSM_CHIP_DEVICE(CSR, MSM7X30), 136 MSM_CHIP_DEVICE(CSR, MSM7X30),
137 MSM_DEVICE(DMOV), 137 MSM_DEVICE(DMOV),
138 MSM_DEVICE(GPIO1), 138 MSM_CHIP_DEVICE(GPIO1, MSM7X30),
139 MSM_DEVICE(GPIO2), 139 MSM_CHIP_DEVICE(GPIO2, MSM7X30),
140 MSM_DEVICE(CLK_CTL), 140 MSM_DEVICE(CLK_CTL),
141 MSM_DEVICE(CLK_CTL_SH2), 141 MSM_DEVICE(CLK_CTL_SH2),
142 MSM_DEVICE(AD5), 142 MSM_DEVICE(AD5),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
deleted file mode 100644
index 1a584e077c6..00000000000
--- a/arch/arm/mach-msm/iommu.c
+++ /dev/null
@@ -1,731 +0,0 @@
1/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/errno.h>
23#include <linux/io.h>
24#include <linux/interrupt.h>
25#include <linux/list.h>
26#include <linux/spinlock.h>
27#include <linux/slab.h>
28#include <linux/iommu.h>
29#include <linux/clk.h>
30
31#include <asm/cacheflush.h>
32#include <asm/sizes.h>
33
34#include <mach/iommu_hw-8xxx.h>
35#include <mach/iommu.h>
36
37#define MRC(reg, processor, op1, crn, crm, op2) \
38__asm__ __volatile__ ( \
39" mrc " #processor "," #op1 ", %0," #crn "," #crm "," #op2 "\n" \
40: "=r" (reg))
41
42#define RCP15_PRRR(reg) MRC(reg, p15, 0, c10, c2, 0)
43#define RCP15_NMRR(reg) MRC(reg, p15, 0, c10, c2, 1)
44
45static int msm_iommu_tex_class[4];
46
47DEFINE_SPINLOCK(msm_iommu_lock);
48
49struct msm_priv {
50 unsigned long *pgtable;
51 struct list_head list_attached;
52};
53
54static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
55{
56 int ret;
57
58 ret = clk_enable(drvdata->pclk);
59 if (ret)
60 goto fail;
61
62 if (drvdata->clk) {
63 ret = clk_enable(drvdata->clk);
64 if (ret)
65 clk_disable(drvdata->pclk);
66 }
67fail:
68 return ret;
69}
70
71static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
72{
73 if (drvdata->clk)
74 clk_disable(drvdata->clk);
75 clk_disable(drvdata->pclk);
76}
77
78static int __flush_iotlb(struct iommu_domain *domain)
79{
80 struct msm_priv *priv = domain->priv;
81 struct msm_iommu_drvdata *iommu_drvdata;
82 struct msm_iommu_ctx_drvdata *ctx_drvdata;
83 int ret = 0;
84#ifndef CONFIG_IOMMU_PGTABLES_L2
85 unsigned long *fl_table = priv->pgtable;
86 int i;
87
88 if (!list_empty(&priv->list_attached)) {
89 dmac_flush_range(fl_table, fl_table + SZ_16K);
90
91 for (i = 0; i < NUM_FL_PTE; i++)
92 if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
93 void *sl_table = __va(fl_table[i] &
94 FL_BASE_MASK);
95 dmac_flush_range(sl_table, sl_table + SZ_4K);
96 }
97 }
98#endif
99
100 list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
101 if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
102 BUG();
103
104 iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
105 BUG_ON(!iommu_drvdata);
106
107 ret = __enable_clocks(iommu_drvdata);
108 if (ret)
109 goto fail;
110
111 SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
112 __disable_clocks(iommu_drvdata);
113 }
114fail:
115 return ret;
116}
117
118static void __reset_context(void __iomem *base, int ctx)
119{
120 SET_BPRCOSH(base, ctx, 0);
121 SET_BPRCISH(base, ctx, 0);
122 SET_BPRCNSH(base, ctx, 0);
123 SET_BPSHCFG(base, ctx, 0);
124 SET_BPMTCFG(base, ctx, 0);
125 SET_ACTLR(base, ctx, 0);
126 SET_SCTLR(base, ctx, 0);
127 SET_FSRRESTORE(base, ctx, 0);
128 SET_TTBR0(base, ctx, 0);
129 SET_TTBR1(base, ctx, 0);
130 SET_TTBCR(base, ctx, 0);
131 SET_BFBCR(base, ctx, 0);
132 SET_PAR(base, ctx, 0);
133 SET_FAR(base, ctx, 0);
134 SET_CTX_TLBIALL(base, ctx, 0);
135 SET_TLBFLPTER(base, ctx, 0);
136 SET_TLBSLPTER(base, ctx, 0);
137 SET_TLBLKCR(base, ctx, 0);
138 SET_PRRR(base, ctx, 0);
139 SET_NMRR(base, ctx, 0);
140}
141
142static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
143{
144 unsigned int prrr, nmrr;
145 __reset_context(base, ctx);
146
147 /* Set up HTW mode */
148 /* TLB miss configuration: perform HTW on miss */
149 SET_TLBMCFG(base, ctx, 0x3);
150
151 /* V2P configuration: HTW for access */
152 SET_V2PCFG(base, ctx, 0x3);
153
154 SET_TTBCR(base, ctx, 0);
155 SET_TTBR0_PA(base, ctx, (pgtable >> 14));
156
157 /* Invalidate the TLB for this context */
158 SET_CTX_TLBIALL(base, ctx, 0);
159
160 /* Set interrupt number to "secure" interrupt */
161 SET_IRPTNDX(base, ctx, 0);
162
163 /* Enable context fault interrupt */
164 SET_CFEIE(base, ctx, 1);
165
166 /* Stall access on a context fault and let the handler deal with it */
167 SET_CFCFG(base, ctx, 1);
168
169 /* Redirect all cacheable requests to L2 slave port. */
170 SET_RCISH(base, ctx, 1);
171 SET_RCOSH(base, ctx, 1);
172 SET_RCNSH(base, ctx, 1);
173
174 /* Turn on TEX Remap */
175 SET_TRE(base, ctx, 1);
176
177 /* Set TEX remap attributes */
178 RCP15_PRRR(prrr);
179 RCP15_NMRR(nmrr);
180 SET_PRRR(base, ctx, prrr);
181 SET_NMRR(base, ctx, nmrr);
182
183 /* Turn on BFB prefetch */
184 SET_BFBDFE(base, ctx, 1);
185
186#ifdef CONFIG_IOMMU_PGTABLES_L2
187 /* Configure page tables as inner-cacheable and shareable to reduce
188 * the TLB miss penalty.
189 */
190 SET_TTBR0_SH(base, ctx, 1);
191 SET_TTBR1_SH(base, ctx, 1);
192
193 SET_TTBR0_NOS(base, ctx, 1);
194 SET_TTBR1_NOS(base, ctx, 1);
195
196 SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
197 SET_TTBR0_IRGNL(base, ctx, 1);
198
199 SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
200 SET_TTBR1_IRGNL(base, ctx, 1);
201
202 SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
203 SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
204#endif
205
206 /* Enable the MMU */
207 SET_M(base, ctx, 1);
208}
209
210static int msm_iommu_domain_init(struct iommu_domain *domain)
211{
212 struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
213
214 if (!priv)
215 goto fail_nomem;
216
217 INIT_LIST_HEAD(&priv->list_attached);
218 priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
219 get_order(SZ_16K));
220
221 if (!priv->pgtable)
222 goto fail_nomem;
223
224 memset(priv->pgtable, 0, SZ_16K);
225 domain->priv = priv;
226 return 0;
227
228fail_nomem:
229 kfree(priv);
230 return -ENOMEM;
231}
232
233static void msm_iommu_domain_destroy(struct iommu_domain *domain)
234{
235 struct msm_priv *priv;
236 unsigned long flags;
237 unsigned long *fl_table;
238 int i;
239
240 spin_lock_irqsave(&msm_iommu_lock, flags);
241 priv = domain->priv;
242 domain->priv = NULL;
243
244 if (priv) {
245 fl_table = priv->pgtable;
246
247 for (i = 0; i < NUM_FL_PTE; i++)
248 if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
249 free_page((unsigned long) __va(((fl_table[i]) &
250 FL_BASE_MASK)));
251
252 free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
253 priv->pgtable = NULL;
254 }
255
256 kfree(priv);
257 spin_unlock_irqrestore(&msm_iommu_lock, flags);
258}
259
260static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
261{
262 struct msm_priv *priv;
263 struct msm_iommu_ctx_dev *ctx_dev;
264 struct msm_iommu_drvdata *iommu_drvdata;
265 struct msm_iommu_ctx_drvdata *ctx_drvdata;
266 struct msm_iommu_ctx_drvdata *tmp_drvdata;
267 int ret = 0;
268 unsigned long flags;
269
270 spin_lock_irqsave(&msm_iommu_lock, flags);
271
272 priv = domain->priv;
273
274 if (!priv || !dev) {
275 ret = -EINVAL;
276 goto fail;
277 }
278
279 iommu_drvdata = dev_get_drvdata(dev->parent);
280 ctx_drvdata = dev_get_drvdata(dev);
281 ctx_dev = dev->platform_data;
282
283 if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
284 ret = -EINVAL;
285 goto fail;
286 }
287
288 if (!list_empty(&ctx_drvdata->attached_elm)) {
289 ret = -EBUSY;
290 goto fail;
291 }
292
293 list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
294 if (tmp_drvdata == ctx_drvdata) {
295 ret = -EBUSY;
296 goto fail;
297 }
298
299 ret = __enable_clocks(iommu_drvdata);
300 if (ret)
301 goto fail;
302
303 __program_context(iommu_drvdata->base, ctx_dev->num,
304 __pa(priv->pgtable));
305
306 __disable_clocks(iommu_drvdata);
307 list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
308 ret = __flush_iotlb(domain);
309
310fail:
311 spin_unlock_irqrestore(&msm_iommu_lock, flags);
312 return ret;
313}
314
315static void msm_iommu_detach_dev(struct iommu_domain *domain,
316 struct device *dev)
317{
318 struct msm_priv *priv;
319 struct msm_iommu_ctx_dev *ctx_dev;
320 struct msm_iommu_drvdata *iommu_drvdata;
321 struct msm_iommu_ctx_drvdata *ctx_drvdata;
322 unsigned long flags;
323 int ret;
324
325 spin_lock_irqsave(&msm_iommu_lock, flags);
326 priv = domain->priv;
327
328 if (!priv || !dev)
329 goto fail;
330
331 iommu_drvdata = dev_get_drvdata(dev->parent);
332 ctx_drvdata = dev_get_drvdata(dev);
333 ctx_dev = dev->platform_data;
334
335 if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
336 goto fail;
337
338 ret = __flush_iotlb(domain);
339 if (ret)
340 goto fail;
341
342 ret = __enable_clocks(iommu_drvdata);
343 if (ret)
344 goto fail;
345
346 __reset_context(iommu_drvdata->base, ctx_dev->num);
347 __disable_clocks(iommu_drvdata);
348 list_del_init(&ctx_drvdata->attached_elm);
349
350fail:
351 spin_unlock_irqrestore(&msm_iommu_lock, flags);
352}
353
354static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
355 phys_addr_t pa, int order, int prot)
356{
357 struct msm_priv *priv;
358 unsigned long flags;
359 unsigned long *fl_table;
360 unsigned long *fl_pte;
361 unsigned long fl_offset;
362 unsigned long *sl_table;
363 unsigned long *sl_pte;
364 unsigned long sl_offset;
365 unsigned int pgprot;
366 size_t len = 0x1000UL << order;
367 int ret = 0, tex, sh;
368
369 spin_lock_irqsave(&msm_iommu_lock, flags);
370
371 sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
372 tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
373
374 if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
375 ret = -EINVAL;
376 goto fail;
377 }
378
379 priv = domain->priv;
380 if (!priv) {
381 ret = -EINVAL;
382 goto fail;
383 }
384
385 fl_table = priv->pgtable;
386
387 if (len != SZ_16M && len != SZ_1M &&
388 len != SZ_64K && len != SZ_4K) {
389 pr_debug("Bad size: %d\n", len);
390 ret = -EINVAL;
391 goto fail;
392 }
393
394 if (!fl_table) {
395 pr_debug("Null page table\n");
396 ret = -EINVAL;
397 goto fail;
398 }
399
400 if (len == SZ_16M || len == SZ_1M) {
401 pgprot = sh ? FL_SHARED : 0;
402 pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
403 pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
404 pgprot |= tex & 0x04 ? FL_TEX0 : 0;
405 } else {
406 pgprot = sh ? SL_SHARED : 0;
407 pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
408 pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
409 pgprot |= tex & 0x04 ? SL_TEX0 : 0;
410 }
411
412 fl_offset = FL_OFFSET(va); /* Upper 12 bits */
413 fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
414
415 if (len == SZ_16M) {
416 int i = 0;
417 for (i = 0; i < 16; i++)
418 *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
419 FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
420 FL_SHARED | FL_NG | pgprot;
421 }
422
423 if (len == SZ_1M)
424 *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
425 FL_TYPE_SECT | FL_SHARED | pgprot;
426
427 /* Need a 2nd level table */
428 if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
429 unsigned long *sl;
430 sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
431 get_order(SZ_4K));
432
433 if (!sl) {
434 pr_debug("Could not allocate second level table\n");
435 ret = -ENOMEM;
436 goto fail;
437 }
438
439 memset(sl, 0, SZ_4K);
440 *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
441 }
442
443 sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
444 sl_offset = SL_OFFSET(va);
445 sl_pte = sl_table + sl_offset;
446
447
448 if (len == SZ_4K)
449 *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
450 SL_SHARED | SL_TYPE_SMALL | pgprot;
451
452 if (len == SZ_64K) {
453 int i;
454
455 for (i = 0; i < 16; i++)
456 *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
457 SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
458 }
459
460 ret = __flush_iotlb(domain);
461fail:
462 spin_unlock_irqrestore(&msm_iommu_lock, flags);
463 return ret;
464}
465
466static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
467 int order)
468{
469 struct msm_priv *priv;
470 unsigned long flags;
471 unsigned long *fl_table;
472 unsigned long *fl_pte;
473 unsigned long fl_offset;
474 unsigned long *sl_table;
475 unsigned long *sl_pte;
476 unsigned long sl_offset;
477 size_t len = 0x1000UL << order;
478 int i, ret = 0;
479
480 spin_lock_irqsave(&msm_iommu_lock, flags);
481
482 priv = domain->priv;
483
484 if (!priv) {
485 ret = -ENODEV;
486 goto fail;
487 }
488
489 fl_table = priv->pgtable;
490
491 if (len != SZ_16M && len != SZ_1M &&
492 len != SZ_64K && len != SZ_4K) {
493 pr_debug("Bad length: %d\n", len);
494 ret = -EINVAL;
495 goto fail;
496 }
497
498 if (!fl_table) {
499 pr_debug("Null page table\n");
500 ret = -EINVAL;
501 goto fail;
502 }
503
504 fl_offset = FL_OFFSET(va); /* Upper 12 bits */
505 fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
506
507 if (*fl_pte == 0) {
508 pr_debug("First level PTE is 0\n");
509 ret = -ENODEV;
510 goto fail;
511 }
512
513 /* Unmap supersection */
514 if (len == SZ_16M)
515 for (i = 0; i < 16; i++)
516 *(fl_pte+i) = 0;
517
518 if (len == SZ_1M)
519 *fl_pte = 0;
520
521 sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
522 sl_offset = SL_OFFSET(va);
523 sl_pte = sl_table + sl_offset;
524
525 if (len == SZ_64K) {
526 for (i = 0; i < 16; i++)
527 *(sl_pte+i) = 0;
528 }
529
530 if (len == SZ_4K)
531 *sl_pte = 0;
532
533 if (len == SZ_4K || len == SZ_64K) {
534 int used = 0;
535
536 for (i = 0; i < NUM_SL_PTE; i++)
537 if (sl_table[i])
538 used = 1;
539 if (!used) {
540 free_page((unsigned long)sl_table);
541 *fl_pte = 0;
542 }
543 }
544
545 ret = __flush_iotlb(domain);
546fail:
547 spin_unlock_irqrestore(&msm_iommu_lock, flags);
548 return ret;
549}
550
551static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
552 unsigned long va)
553{
554 struct msm_priv *priv;
555 struct msm_iommu_drvdata *iommu_drvdata;
556 struct msm_iommu_ctx_drvdata *ctx_drvdata;
557 unsigned int par;
558 unsigned long flags;
559 void __iomem *base;
560 phys_addr_t ret = 0;
561 int ctx;
562
563 spin_lock_irqsave(&msm_iommu_lock, flags);
564
565 priv = domain->priv;
566 if (list_empty(&priv->list_attached))
567 goto fail;
568
569 ctx_drvdata = list_entry(priv->list_attached.next,
570 struct msm_iommu_ctx_drvdata, attached_elm);
571 iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
572
573 base = iommu_drvdata->base;
574 ctx = ctx_drvdata->num;
575
576 ret = __enable_clocks(iommu_drvdata);
577 if (ret)
578 goto fail;
579
580 /* Invalidate context TLB */
581 SET_CTX_TLBIALL(base, ctx, 0);
582 SET_V2PPR(base, ctx, va & V2Pxx_VA);
583
584 par = GET_PAR(base, ctx);
585
586 /* We are dealing with a supersection */
587 if (GET_NOFAULT_SS(base, ctx))
588 ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
589 else /* Upper 20 bits from PAR, lower 12 from VA */
590 ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
591
592 if (GET_FAULT(base, ctx))
593 ret = 0;
594
595 __disable_clocks(iommu_drvdata);
596fail:
597 spin_unlock_irqrestore(&msm_iommu_lock, flags);
598 return ret;
599}
600
601static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
602 unsigned long cap)
603{
604 return 0;
605}
606
607static void print_ctx_regs(void __iomem *base, int ctx)
608{
609 unsigned int fsr = GET_FSR(base, ctx);
610 pr_err("FAR = %08x PAR = %08x\n",
611 GET_FAR(base, ctx), GET_PAR(base, ctx));
612 pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
613 (fsr & 0x02) ? "TF " : "",
614 (fsr & 0x04) ? "AFF " : "",
615 (fsr & 0x08) ? "APF " : "",
616 (fsr & 0x10) ? "TLBMF " : "",
617 (fsr & 0x20) ? "HTWDEEF " : "",
618 (fsr & 0x40) ? "HTWSEEF " : "",
619 (fsr & 0x80) ? "MHF " : "",
620 (fsr & 0x10000) ? "SL " : "",
621 (fsr & 0x40000000) ? "SS " : "",
622 (fsr & 0x80000000) ? "MULTI " : "");
623
624 pr_err("FSYNR0 = %08x FSYNR1 = %08x\n",
625 GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
626 pr_err("TTBR0 = %08x TTBR1 = %08x\n",
627 GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
628 pr_err("SCTLR = %08x ACTLR = %08x\n",
629 GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
630 pr_err("PRRR = %08x NMRR = %08x\n",
631 GET_PRRR(base, ctx), GET_NMRR(base, ctx));
632}
633
634irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
635{
636 struct msm_iommu_drvdata *drvdata = dev_id;
637 void __iomem *base;
638 unsigned int fsr;
639 int i, ret;
640
641 spin_lock(&msm_iommu_lock);
642
643 if (!drvdata) {
644 pr_err("Invalid device ID in context interrupt handler\n");
645 goto fail;
646 }
647
648 base = drvdata->base;
649
650 pr_err("Unexpected IOMMU page fault!\n");
651 pr_err("base = %08x\n", (unsigned int) base);
652
653 ret = __enable_clocks(drvdata);
654 if (ret)
655 goto fail;
656
657 for (i = 0; i < drvdata->ncb; i++) {
658 fsr = GET_FSR(base, i);
659 if (fsr) {
660 pr_err("Fault occurred in context %d.\n", i);
661 pr_err("Interesting registers:\n");
662 print_ctx_regs(base, i);
663 SET_FSR(base, i, 0x4000000F);
664 }
665 }
666 __disable_clocks(drvdata);
667fail:
668 spin_unlock(&msm_iommu_lock);
669 return 0;
670}
671
672static struct iommu_ops msm_iommu_ops = {
673 .domain_init = msm_iommu_domain_init,
674 .domain_destroy = msm_iommu_domain_destroy,
675 .attach_dev = msm_iommu_attach_dev,
676 .detach_dev = msm_iommu_detach_dev,
677 .map = msm_iommu_map,
678 .unmap = msm_iommu_unmap,
679 .iova_to_phys = msm_iommu_iova_to_phys,
680 .domain_has_cap = msm_iommu_domain_has_cap
681};
682
683static int __init get_tex_class(int icp, int ocp, int mt, int nos)
684{
685 int i = 0;
686 unsigned int prrr = 0;
687 unsigned int nmrr = 0;
688 int c_icp, c_ocp, c_mt, c_nos;
689
690 RCP15_PRRR(prrr);
691 RCP15_NMRR(nmrr);
692
693 for (i = 0; i < NUM_TEX_CLASS; i++) {
694 c_nos = PRRR_NOS(prrr, i);
695 c_mt = PRRR_MT(prrr, i);
696 c_icp = NMRR_ICP(nmrr, i);
697 c_ocp = NMRR_OCP(nmrr, i);
698
699 if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
700 return i;
701 }
702
703 return -ENODEV;
704}
705
706static void __init setup_iommu_tex_classes(void)
707{
708 msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
709 get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
710
711 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
712 get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
713
714 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
715 get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
716
717 msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
718 get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
719}
720
721static int __init msm_iommu_init(void)
722{
723 setup_iommu_tex_classes();
724 register_iommu(&msm_iommu_ops);
725 return 0;
726}
727
728subsys_initcall(msm_iommu_init);
729
730MODULE_LICENSE("GPL v2");
731MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
deleted file mode 100644
index 8e8fb079852..00000000000
--- a/arch/arm/mach-msm/iommu_dev.c
+++ /dev/null
@@ -1,422 +0,0 @@
1/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/iommu.h>
26#include <linux/interrupt.h>
27#include <linux/err.h>
28#include <linux/slab.h>
29
30#include <mach/iommu_hw-8xxx.h>
31#include <mach/iommu.h>
32#include <mach/clk.h>
33
34struct iommu_ctx_iter_data {
35 /* input */
36 const char *name;
37
38 /* output */
39 struct device *dev;
40};
41
42static struct platform_device *msm_iommu_root_dev;
43
44static int each_iommu_ctx(struct device *dev, void *data)
45{
46 struct iommu_ctx_iter_data *res = data;
47 struct msm_iommu_ctx_dev *c = dev->platform_data;
48
49 if (!res || !c || !c->name || !res->name)
50 return -EINVAL;
51
52 if (!strcmp(res->name, c->name)) {
53 res->dev = dev;
54 return 1;
55 }
56 return 0;
57}
58
59static int each_iommu(struct device *dev, void *data)
60{
61 return device_for_each_child(dev, data, each_iommu_ctx);
62}
63
64struct device *msm_iommu_get_ctx(const char *ctx_name)
65{
66 struct iommu_ctx_iter_data r;
67 int found;
68
69 if (!msm_iommu_root_dev) {
70 pr_err("No root IOMMU device.\n");
71 goto fail;
72 }
73
74 r.name = ctx_name;
75 found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
76
77 if (!found) {
78 pr_err("Could not find context <%s>\n", ctx_name);
79 goto fail;
80 }
81
82 return r.dev;
83fail:
84 return NULL;
85}
86EXPORT_SYMBOL(msm_iommu_get_ctx);
87
88static void msm_iommu_reset(void __iomem *base, int ncb)
89{
90 int ctx;
91
92 SET_RPUE(base, 0);
93 SET_RPUEIE(base, 0);
94 SET_ESRRESTORE(base, 0);
95 SET_TBE(base, 0);
96 SET_CR(base, 0);
97 SET_SPDMBE(base, 0);
98 SET_TESTBUSCR(base, 0);
99 SET_TLBRSW(base, 0);
100 SET_GLOBAL_TLBIALL(base, 0);
101 SET_RPU_ACR(base, 0);
102 SET_TLBLKCRWE(base, 1);
103
104 for (ctx = 0; ctx < ncb; ctx++) {
105 SET_BPRCOSH(base, ctx, 0);
106 SET_BPRCISH(base, ctx, 0);
107 SET_BPRCNSH(base, ctx, 0);
108 SET_BPSHCFG(base, ctx, 0);
109 SET_BPMTCFG(base, ctx, 0);
110 SET_ACTLR(base, ctx, 0);
111 SET_SCTLR(base, ctx, 0);
112 SET_FSRRESTORE(base, ctx, 0);
113 SET_TTBR0(base, ctx, 0);
114 SET_TTBR1(base, ctx, 0);
115 SET_TTBCR(base, ctx, 0);
116 SET_BFBCR(base, ctx, 0);
117 SET_PAR(base, ctx, 0);
118 SET_FAR(base, ctx, 0);
119 SET_CTX_TLBIALL(base, ctx, 0);
120 SET_TLBFLPTER(base, ctx, 0);
121 SET_TLBSLPTER(base, ctx, 0);
122 SET_TLBLKCR(base, ctx, 0);
123 SET_PRRR(base, ctx, 0);
124 SET_NMRR(base, ctx, 0);
125 SET_CONTEXTIDR(base, ctx, 0);
126 }
127}
128
129static int msm_iommu_probe(struct platform_device *pdev)
130{
131 struct resource *r, *r2;
132 struct clk *iommu_clk;
133 struct clk *iommu_pclk;
134 struct msm_iommu_drvdata *drvdata;
135 struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
136 void __iomem *regs_base;
137 resource_size_t len;
138 int ret, irq, par;
139
140 if (pdev->id == -1) {
141 msm_iommu_root_dev = pdev;
142 return 0;
143 }
144
145 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
146
147 if (!drvdata) {
148 ret = -ENOMEM;
149 goto fail;
150 }
151
152 if (!iommu_dev) {
153 ret = -ENODEV;
154 goto fail;
155 }
156
157 iommu_pclk = clk_get(NULL, "smmu_pclk");
158 if (IS_ERR(iommu_pclk)) {
159 ret = -ENODEV;
160 goto fail;
161 }
162
163 ret = clk_enable(iommu_pclk);
164 if (ret)
165 goto fail_enable;
166
167 iommu_clk = clk_get(&pdev->dev, "iommu_clk");
168
169 if (!IS_ERR(iommu_clk)) {
170 if (clk_get_rate(iommu_clk) == 0)
171 clk_set_min_rate(iommu_clk, 1);
172
173 ret = clk_enable(iommu_clk);
174 if (ret) {
175 clk_put(iommu_clk);
176 goto fail_pclk;
177 }
178 } else
179 iommu_clk = NULL;
180
181 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
182
183 if (!r) {
184 ret = -ENODEV;
185 goto fail_clk;
186 }
187
188 len = resource_size(r);
189
190 r2 = request_mem_region(r->start, len, r->name);
191 if (!r2) {
192 pr_err("Could not request memory region: start=%p, len=%d\n",
193 (void *) r->start, len);
194 ret = -EBUSY;
195 goto fail_clk;
196 }
197
198 regs_base = ioremap(r2->start, len);
199
200 if (!regs_base) {
201 pr_err("Could not ioremap: start=%p, len=%d\n",
202 (void *) r2->start, len);
203 ret = -EBUSY;
204 goto fail_mem;
205 }
206
207 irq = platform_get_irq_byname(pdev, "secure_irq");
208 if (irq < 0) {
209 ret = -ENODEV;
210 goto fail_io;
211 }
212
213 msm_iommu_reset(regs_base, iommu_dev->ncb);
214
215 SET_M(regs_base, 0, 1);
216 SET_PAR(regs_base, 0, 0);
217 SET_V2PCFG(regs_base, 0, 1);
218 SET_V2PPR(regs_base, 0, 0);
219 par = GET_PAR(regs_base, 0);
220 SET_V2PCFG(regs_base, 0, 0);
221 SET_M(regs_base, 0, 0);
222
223 if (!par) {
224 pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
225 ret = -ENODEV;
226 goto fail_io;
227 }
228
229 ret = request_irq(irq, msm_iommu_fault_handler, 0,
230 "msm_iommu_secure_irpt_handler", drvdata);
231 if (ret) {
232 pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
233 goto fail_io;
234 }
235
236
237 drvdata->pclk = iommu_pclk;
238 drvdata->clk = iommu_clk;
239 drvdata->base = regs_base;
240 drvdata->irq = irq;
241 drvdata->ncb = iommu_dev->ncb;
242
243 pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
244 iommu_dev->name, regs_base, irq, iommu_dev->ncb);
245
246 platform_set_drvdata(pdev, drvdata);
247
248 if (iommu_clk)
249 clk_disable(iommu_clk);
250
251 clk_disable(iommu_pclk);
252
253 return 0;
254fail_io:
255 iounmap(regs_base);
256fail_mem:
257 release_mem_region(r->start, len);
258fail_clk:
259 if (iommu_clk) {
260 clk_disable(iommu_clk);
261 clk_put(iommu_clk);
262 }
263fail_pclk:
264 clk_disable(iommu_pclk);
265fail_enable:
266 clk_put(iommu_pclk);
267fail:
268 kfree(drvdata);
269 return ret;
270}
271
272static int msm_iommu_remove(struct platform_device *pdev)
273{
274 struct msm_iommu_drvdata *drv = NULL;
275
276 drv = platform_get_drvdata(pdev);
277 if (drv) {
278 if (drv->clk)
279 clk_put(drv->clk);
280 clk_put(drv->pclk);
281 memset(drv, 0, sizeof(*drv));
282 kfree(drv);
283 platform_set_drvdata(pdev, NULL);
284 }
285 return 0;
286}
287
288static int msm_iommu_ctx_probe(struct platform_device *pdev)
289{
290 struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
291 struct msm_iommu_drvdata *drvdata;
292 struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
293 int i, ret;
294 if (!c || !pdev->dev.parent) {
295 ret = -EINVAL;
296 goto fail;
297 }
298
299 drvdata = dev_get_drvdata(pdev->dev.parent);
300
301 if (!drvdata) {
302 ret = -ENODEV;
303 goto fail;
304 }
305
306 ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
307 if (!ctx_drvdata) {
308 ret = -ENOMEM;
309 goto fail;
310 }
311 ctx_drvdata->num = c->num;
312 ctx_drvdata->pdev = pdev;
313
314 INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
315 platform_set_drvdata(pdev, ctx_drvdata);
316
317 ret = clk_enable(drvdata->pclk);
318 if (ret)
319 goto fail;
320
321 if (drvdata->clk) {
322 ret = clk_enable(drvdata->clk);
323 if (ret) {
324 clk_disable(drvdata->pclk);
325 goto fail;
326 }
327 }
328
329 /* Program the M2V tables for this context */
330 for (i = 0; i < MAX_NUM_MIDS; i++) {
331 int mid = c->mids[i];
332 if (mid == -1)
333 break;
334
335 SET_M2VCBR_N(drvdata->base, mid, 0);
336 SET_CBACR_N(drvdata->base, c->num, 0);
337
338 /* Set VMID = 0 */
339 SET_VMID(drvdata->base, mid, 0);
340
341 /* Set the context number for that MID to this context */
342 SET_CBNDX(drvdata->base, mid, c->num);
343
344 /* Set MID associated with this context bank to 0*/
345 SET_CBVMID(drvdata->base, c->num, 0);
346
347 /* Set the ASID for TLB tagging for this context */
348 SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
349
350 /* Set security bit override to be Non-secure */
351 SET_NSCFG(drvdata->base, mid, 3);
352 }
353
354 if (drvdata->clk)
355 clk_disable(drvdata->clk);
356 clk_disable(drvdata->pclk);
357
358 dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
359 return 0;
360fail:
361 kfree(ctx_drvdata);
362 return ret;
363}
364
365static int msm_iommu_ctx_remove(struct platform_device *pdev)
366{
367 struct msm_iommu_ctx_drvdata *drv = NULL;
368 drv = platform_get_drvdata(pdev);
369 if (drv) {
370 memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
371 kfree(drv);
372 platform_set_drvdata(pdev, NULL);
373 }
374 return 0;
375}
376
377static struct platform_driver msm_iommu_driver = {
378 .driver = {
379 .name = "msm_iommu",
380 },
381 .probe = msm_iommu_probe,
382 .remove = msm_iommu_remove,
383};
384
385static struct platform_driver msm_iommu_ctx_driver = {
386 .driver = {
387 .name = "msm_iommu_ctx",
388 },
389 .probe = msm_iommu_ctx_probe,
390 .remove = msm_iommu_ctx_remove,
391};
392
393static int __init msm_iommu_driver_init(void)
394{
395 int ret;
396 ret = platform_driver_register(&msm_iommu_driver);
397 if (ret != 0) {
398 pr_err("Failed to register IOMMU driver\n");
399 goto error;
400 }
401
402 ret = platform_driver_register(&msm_iommu_ctx_driver);
403 if (ret != 0) {
404 pr_err("Failed to register IOMMU context driver\n");
405 goto error;
406 }
407
408error:
409 return ret;
410}
411
412static void __exit msm_iommu_driver_exit(void)
413{
414 platform_driver_unregister(&msm_iommu_ctx_driver);
415 platform_driver_unregister(&msm_iommu_driver);
416}
417
418subsys_initcall(msm_iommu_driver_init);
419module_exit(msm_iommu_driver_exit);
420
421MODULE_LICENSE("GPL v2");
422MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 2034098cf01..72765952091 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -18,6 +18,7 @@
18 18
19#include <asm/hardware/gic.h> 19#include <asm/hardware/gic.h>
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/cputype.h>
21#include <asm/mach-types.h> 22#include <asm/mach-types.h>
22 23
23#include <mach/msm_iomap.h> 24#include <mach/msm_iomap.h>
@@ -40,6 +41,12 @@ volatile int pen_release = -1;
40 41
41static DEFINE_SPINLOCK(boot_lock); 42static DEFINE_SPINLOCK(boot_lock);
42 43
44static inline int get_core_count(void)
45{
46 /* 1 + the PART[1:0] field of MIDR */
47 return ((read_cpuid_id() >> 4) & 3) + 1;
48}
49
43void __cpuinit platform_secondary_init(unsigned int cpu) 50void __cpuinit platform_secondary_init(unsigned int cpu)
44{ 51{
45 /* Configure edge-triggered PPIs */ 52 /* Configure edge-triggered PPIs */
@@ -147,9 +154,15 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
147 */ 154 */
148void __init smp_init_cpus(void) 155void __init smp_init_cpus(void)
149{ 156{
150 unsigned int i; 157 unsigned int i, ncores = get_core_count();
158
159 if (ncores > nr_cpu_ids) {
160 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
161 ncores, nr_cpu_ids);
162 ncores = nr_cpu_ids;
163 }
151 164
152 for (i = 0; i < NR_CPUS; i++) 165 for (i = 0; i < ncores; i++)
153 set_cpu_possible(i, true); 166 set_cpu_possible(i, true);
154 167
155 set_smp_cross_call(gic_raise_softirq); 168 set_smp_cross_call(gic_raise_softirq);
@@ -157,12 +170,4 @@ void __init smp_init_cpus(void)
157 170
158void __init platform_smp_prepare_cpus(unsigned int max_cpus) 171void __init platform_smp_prepare_cpus(unsigned int max_cpus)
159{ 172{
160 int i;
161
162 /*
163 * Initialise the present map, which describes the set of CPUs
164 * actually populated at the present time.
165 */
166 for (i = 0; i < max_cpus; i++)
167 set_cpu_present(i, true);
168} 173}