diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2012-07-10 10:19:23 -0400 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2012-07-10 10:19:23 -0400 |
| commit | b52a2c472d7fcf215e31dffdd382651e1b99f138 (patch) | |
| tree | 580fd8d833afba676fd8fdcb570297b1a7a3f3aa | |
| parent | ddb30594ee09c6f701de52222c7b2c63c484d089 (diff) | |
| parent | ce9dcb8784611c50974d1c6b600c71f5c0a29308 (diff) | |
Merge tag 'davinci-v3.6-soc' of git://gitorious.org/linux-davinci/linux-davinci into next/soc
From Sekhar Nori <nsekhar@ti.com>:
DaVinci SoC updates for v3.6
Add IRQ domain support for cp_intc and
runtime PM core support for DaVinci devices.
* tag 'davinci-v3.6-soc' of git://gitorious.org/linux-davinci/linux-davinci:
ARM: davinci: add runtime PM support for clock management
ARM: davinci: cp_intc: Add irq domain support
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
| -rw-r--r-- | arch/arm/mach-davinci/Kconfig | 1 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/Makefile | 1 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/cp_intc.c | 63 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/pm_domain.c | 64 |
4 files changed, 115 insertions, 14 deletions
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 32d837d8eab9..2ce1ef07c13d 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig | |||
| @@ -4,6 +4,7 @@ config AINTC | |||
| 4 | bool | 4 | bool |
| 5 | 5 | ||
| 6 | config CP_INTC | 6 | config CP_INTC |
| 7 | select IRQ_DOMAIN | ||
| 7 | bool | 8 | bool |
| 8 | 9 | ||
| 9 | config ARCH_DAVINCI_DMx | 10 | config ARCH_DAVINCI_DMx |
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 2db78bd5c835..2227effcb0e9 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile | |||
| @@ -39,3 +39,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o | |||
| 39 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | 39 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o |
| 40 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | 40 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o |
| 41 | obj-$(CONFIG_SUSPEND) += pm.o sleep.o | 41 | obj-$(CONFIG_SUSPEND) += pm.o sleep.o |
| 42 | obj-$(CONFIG_HAVE_CLK) += pm_domain.o | ||
diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index f83152d643c5..45d52567ced7 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c | |||
| @@ -9,8 +9,10 @@ | |||
| 9 | * kind, whether express or implied. | 9 | * kind, whether express or implied. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/export.h> | ||
| 12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 13 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
| 15 | #include <linux/irqdomain.h> | ||
| 14 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 15 | 17 | ||
| 16 | #include <mach/common.h> | 18 | #include <mach/common.h> |
| @@ -28,7 +30,7 @@ static inline void cp_intc_write(unsigned long value, unsigned offset) | |||
| 28 | 30 | ||
| 29 | static void cp_intc_ack_irq(struct irq_data *d) | 31 | static void cp_intc_ack_irq(struct irq_data *d) |
| 30 | { | 32 | { |
| 31 | cp_intc_write(d->irq, CP_INTC_SYS_STAT_IDX_CLR); | 33 | cp_intc_write(d->hwirq, CP_INTC_SYS_STAT_IDX_CLR); |
| 32 | } | 34 | } |
| 33 | 35 | ||
| 34 | /* Disable interrupt */ | 36 | /* Disable interrupt */ |
| @@ -36,20 +38,20 @@ static void cp_intc_mask_irq(struct irq_data *d) | |||
| 36 | { | 38 | { |
| 37 | /* XXX don't know why we need to disable nIRQ here... */ | 39 | /* XXX don't know why we need to disable nIRQ here... */ |
| 38 | cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR); | 40 | cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR); |
| 39 | cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_CLR); | 41 | cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_CLR); |
| 40 | cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET); | 42 | cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET); |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | /* Enable interrupt */ | 45 | /* Enable interrupt */ |
| 44 | static void cp_intc_unmask_irq(struct irq_data *d) | 46 | static void cp_intc_unmask_irq(struct irq_data *d) |
| 45 | { | 47 | { |
| 46 | cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_SET); | 48 | cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_SET); |
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type) | 51 | static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type) |
| 50 | { | 52 | { |
| 51 | unsigned reg = BIT_WORD(d->irq); | 53 | unsigned reg = BIT_WORD(d->hwirq); |
| 52 | unsigned mask = BIT_MASK(d->irq); | 54 | unsigned mask = BIT_MASK(d->hwirq); |
| 53 | unsigned polarity = cp_intc_read(CP_INTC_SYS_POLARITY(reg)); | 55 | unsigned polarity = cp_intc_read(CP_INTC_SYS_POLARITY(reg)); |
| 54 | unsigned type = cp_intc_read(CP_INTC_SYS_TYPE(reg)); | 56 | unsigned type = cp_intc_read(CP_INTC_SYS_TYPE(reg)); |
| 55 | 57 | ||
| @@ -99,18 +101,36 @@ static struct irq_chip cp_intc_irq_chip = { | |||
| 99 | .irq_set_wake = cp_intc_set_wake, | 101 | .irq_set_wake = cp_intc_set_wake, |
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | void __init cp_intc_init(void) | 104 | static struct irq_domain *cp_intc_domain; |
| 105 | |||
| 106 | static int cp_intc_host_map(struct irq_domain *h, unsigned int virq, | ||
| 107 | irq_hw_number_t hw) | ||
| 108 | { | ||
| 109 | pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw); | ||
| 110 | |||
| 111 | irq_set_chip(virq, &cp_intc_irq_chip); | ||
| 112 | set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); | ||
| 113 | irq_set_handler(virq, handle_edge_irq); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static const struct irq_domain_ops cp_intc_host_ops = { | ||
| 118 | .map = cp_intc_host_map, | ||
| 119 | .xlate = irq_domain_xlate_onetwocell, | ||
| 120 | }; | ||
| 121 | |||
| 122 | int __init __cp_intc_init(struct device_node *node) | ||
| 103 | { | 123 | { |
| 104 | unsigned long num_irq = davinci_soc_info.intc_irq_num; | 124 | u32 num_irq = davinci_soc_info.intc_irq_num; |
| 105 | u8 *irq_prio = davinci_soc_info.intc_irq_prios; | 125 | u8 *irq_prio = davinci_soc_info.intc_irq_prios; |
| 106 | u32 *host_map = davinci_soc_info.intc_host_map; | 126 | u32 *host_map = davinci_soc_info.intc_host_map; |
| 107 | unsigned num_reg = BITS_TO_LONGS(num_irq); | 127 | unsigned num_reg = BITS_TO_LONGS(num_irq); |
| 108 | int i; | 128 | int i, irq_base; |
| 109 | 129 | ||
| 110 | davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC; | 130 | davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC; |
| 111 | davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K); | 131 | davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K); |
| 112 | if (WARN_ON(!davinci_intc_base)) | 132 | if (WARN_ON(!davinci_intc_base)) |
| 113 | return; | 133 | return -EINVAL; |
| 114 | 134 | ||
| 115 | cp_intc_write(0, CP_INTC_GLOBAL_ENABLE); | 135 | cp_intc_write(0, CP_INTC_GLOBAL_ENABLE); |
| 116 | 136 | ||
| @@ -165,13 +185,28 @@ void __init cp_intc_init(void) | |||
| 165 | for (i = 0; host_map[i] != -1; i++) | 185 | for (i = 0; host_map[i] != -1; i++) |
| 166 | cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i)); | 186 | cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i)); |
| 167 | 187 | ||
| 168 | /* Set up genirq dispatching for cp_intc */ | 188 | irq_base = irq_alloc_descs(-1, 0, num_irq, 0); |
| 169 | for (i = 0; i < num_irq; i++) { | 189 | if (irq_base < 0) { |
| 170 | irq_set_chip(i, &cp_intc_irq_chip); | 190 | pr_warn("Couldn't allocate IRQ numbers\n"); |
| 171 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | 191 | irq_base = 0; |
| 172 | irq_set_handler(i, handle_edge_irq); | 192 | } |
| 193 | |||
| 194 | /* create a legacy host */ | ||
| 195 | cp_intc_domain = irq_domain_add_legacy(node, num_irq, | ||
| 196 | irq_base, 0, &cp_intc_host_ops, NULL); | ||
| 197 | |||
| 198 | if (!cp_intc_domain) { | ||
| 199 | pr_err("cp_intc: failed to allocate irq host!\n"); | ||
| 200 | return -EINVAL; | ||
| 173 | } | 201 | } |
| 174 | 202 | ||
| 175 | /* Enable global interrupt */ | 203 | /* Enable global interrupt */ |
| 176 | cp_intc_write(1, CP_INTC_GLOBAL_ENABLE); | 204 | cp_intc_write(1, CP_INTC_GLOBAL_ENABLE); |
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | void __init cp_intc_init(void) | ||
| 210 | { | ||
| 211 | __cp_intc_init(NULL); | ||
| 177 | } | 212 | } |
diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c new file mode 100644 index 000000000000..00946e23c1ee --- /dev/null +++ b/arch/arm/mach-davinci/pm_domain.c | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | /* | ||
| 2 | * Runtime PM support code for DaVinci | ||
| 3 | * | ||
| 4 | * Author: Kevin Hilman | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/pm_runtime.h> | ||
| 14 | #include <linux/pm_clock.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | |||
| 17 | #ifdef CONFIG_PM_RUNTIME | ||
| 18 | static int davinci_pm_runtime_suspend(struct device *dev) | ||
| 19 | { | ||
| 20 | int ret; | ||
| 21 | |||
| 22 | dev_dbg(dev, "%s\n", __func__); | ||
| 23 | |||
