diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/6xx-suspend.S | 52 | ||||
-rw-r--r-- | arch/powerpc/sysdev/Makefile | 7 | ||||
-rw-r--r-- | arch/powerpc/sysdev/dcr.c | 156 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 429 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 42 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 12 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 15 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 9 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_msi.c | 1 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_pasemi_msi.c | 6 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_u3msi.c | 8 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mv64x60_dev.c | 10 |
12 files changed, 703 insertions, 44 deletions
diff --git a/arch/powerpc/sysdev/6xx-suspend.S b/arch/powerpc/sysdev/6xx-suspend.S new file mode 100644 index 000000000000..21cda085d926 --- /dev/null +++ b/arch/powerpc/sysdev/6xx-suspend.S | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Enter and leave sleep state on chips with 6xx-style HID0 | ||
3 | * power management bits, which don't leave sleep state via reset. | ||
4 | * | ||
5 | * Author: Scott Wood <scottwood@freescale.com> | ||
6 | * | ||
7 | * Copyright (c) 2006-2007 Freescale Semiconductor, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <asm/ppc_asm.h> | ||
15 | #include <asm/reg.h> | ||
16 | #include <asm/thread_info.h> | ||
17 | #include <asm/asm-offsets.h> | ||
18 | |||
19 | _GLOBAL(mpc6xx_enter_standby) | ||
20 | mflr r4 | ||
21 | |||
22 | mfspr r5, SPRN_HID0 | ||
23 | rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP) | ||
24 | oris r5, r5, HID0_SLEEP@h | ||
25 | mtspr SPRN_HID0, r5 | ||
26 | isync | ||
27 | |||
28 | lis r5, ret_from_standby@h | ||
29 | ori r5, r5, ret_from_standby@l | ||
30 | mtlr r5 | ||
31 | |||
32 | rlwinm r5, r1, 0, 0, 31-THREAD_SHIFT | ||
33 | lwz r6, TI_LOCAL_FLAGS(r5) | ||
34 | ori r6, r6, _TLF_SLEEPING | ||
35 | stw r6, TI_LOCAL_FLAGS(r5) | ||
36 | |||
37 | mfmsr r5 | ||
38 | ori r5, r5, MSR_EE | ||
39 | oris r5, r5, MSR_POW@h | ||
40 | sync | ||
41 | mtmsr r5 | ||
42 | isync | ||
43 | |||
44 | 1: b 1b | ||
45 | |||
46 | ret_from_standby: | ||
47 | mfspr r5, SPRN_HID0 | ||
48 | rlwinm r5, r5, 0, ~HID0_SLEEP | ||
49 | mtspr SPRN_HID0, r5 | ||
50 | |||
51 | mtlr r4 | ||
52 | blr | ||
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 6d386d0071a0..dd6dff3ffb0f 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -4,6 +4,7 @@ endif | |||
4 | 4 | ||
5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o |
6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
7 | fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o | ||
7 | 8 | ||
8 | obj-$(CONFIG_PPC_MPC106) += grackle.o | 9 | obj-$(CONFIG_PPC_MPC106) += grackle.o |
9 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o | 10 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o |
@@ -11,7 +12,7 @@ obj-$(CONFIG_PPC_PMI) += pmi.o | |||
11 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 12 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
12 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 13 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
13 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 14 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
14 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o | 15 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) |
15 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 16 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
16 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o | 17 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o |
17 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 18 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
@@ -44,3 +45,7 @@ obj-$(CONFIG_PPC_DCR) += dcr.o | |||
44 | obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o | 45 | obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o |
45 | obj-$(CONFIG_UCODE_PATCH) += micropatch.o | 46 | obj-$(CONFIG_UCODE_PATCH) += micropatch.o |
46 | endif | 47 | endif |
48 | |||
49 | ifeq ($(CONFIG_SUSPEND),y) | ||
50 | obj-$(CONFIG_6xx) += 6xx-suspend.o | ||
51 | endif | ||
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 437e48d3ae33..a8ba9983dd5a 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
@@ -23,6 +23,107 @@ | |||
23 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
24 | #include <asm/dcr.h> | 24 | #include <asm/dcr.h> |
25 | 25 | ||
26 | #ifdef CONFIG_PPC_DCR_MMIO | ||
27 | static struct device_node *find_dcr_parent(struct device_node *node) | ||
28 | { | ||
29 | struct device_node *par, *tmp; | ||
30 | const u32 *p; | ||
31 | |||
32 | for (par = of_node_get(node); par;) { | ||
33 | if (of_get_property(par, "dcr-controller", NULL)) | ||
34 | break; | ||
35 | p = of_get_property(par, "dcr-parent", NULL); | ||
36 | tmp = par; | ||
37 | if (p == NULL) | ||
38 | par = of_get_parent(par); | ||
39 | else | ||
40 | par = of_find_node_by_phandle(*p); | ||
41 | of_node_put(tmp); | ||
42 | } | ||
43 | return par; | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | #if defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) | ||
48 | |||
49 | bool dcr_map_ok_generic(dcr_host_t host) | ||
50 | { | ||
51 | if (host.type == DCR_HOST_NATIVE) | ||
52 | return dcr_map_ok_native(host.host.native); | ||
53 | else if (host.type == DCR_HOST_MMIO) | ||
54 | return dcr_map_ok_mmio(host.host.mmio); | ||
55 | else | ||
56 | return 0; | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(dcr_map_ok_generic); | ||
59 | |||
60 | dcr_host_t dcr_map_generic(struct device_node *dev, | ||
61 | unsigned int dcr_n, | ||
62 | unsigned int dcr_c) | ||
63 | { | ||
64 | dcr_host_t host; | ||
65 | struct device_node *dp; | ||
66 | const char *prop; | ||
67 | |||
68 | host.type = DCR_HOST_INVALID; | ||
69 | |||
70 | dp = find_dcr_parent(dev); | ||
71 | if (dp == NULL) | ||
72 | return host; | ||
73 | |||
74 | prop = of_get_property(dp, "dcr-access-method", NULL); | ||
75 | |||
76 | pr_debug("dcr_map_generic(dcr-access-method = %s)\n", prop); | ||
77 | |||
78 | if (!strcmp(prop, "native")) { | ||
79 | host.type = DCR_HOST_NATIVE; | ||
80 | host.host.native = dcr_map_native(dev, dcr_n, dcr_c); | ||
81 | } else if (!strcmp(prop, "mmio")) { | ||
82 | host.type = DCR_HOST_MMIO; | ||
83 | host.host.mmio = dcr_map_mmio(dev, dcr_n, dcr_c); | ||
84 | } | ||
85 | |||
86 | of_node_put(dp); | ||
87 | return host; | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(dcr_map_generic); | ||
90 | |||
91 | void dcr_unmap_generic(dcr_host_t host, unsigned int dcr_c) | ||
92 | { | ||
93 | if (host.type == DCR_HOST_NATIVE) | ||
94 | dcr_unmap_native(host.host.native, dcr_c); | ||
95 | else if (host.type == DCR_HOST_MMIO) | ||
96 | dcr_unmap_mmio(host.host.mmio, dcr_c); | ||
97 | else /* host.type == DCR_HOST_INVALID */ | ||
98 | WARN_ON(true); | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(dcr_unmap_generic); | ||
101 | |||
102 | u32 dcr_read_generic(dcr_host_t host, unsigned int dcr_n) | ||
103 | { | ||
104 | if (host.type == DCR_HOST_NATIVE) | ||
105 | return dcr_read_native(host.host.native, dcr_n); | ||
106 | else if (host.type == DCR_HOST_MMIO) | ||
107 | return dcr_read_mmio(host.host.mmio, dcr_n); | ||
108 | else /* host.type == DCR_HOST_INVALID */ | ||
109 | WARN_ON(true); | ||
110 | return 0; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(dcr_read_generic); | ||
113 | |||
114 | void dcr_write_generic(dcr_host_t host, unsigned int dcr_n, u32 value) | ||
115 | { | ||
116 | if (host.type == DCR_HOST_NATIVE) | ||
117 | dcr_write_native(host.host.native, dcr_n, value); | ||
118 | else if (host.type == DCR_HOST_MMIO) | ||
119 | dcr_write_mmio(host.host.mmio, dcr_n, value); | ||
120 | else /* host.type == DCR_HOST_INVALID */ | ||
121 | WARN_ON(true); | ||
122 | } | ||
123 | EXPORT_SYMBOL_GPL(dcr_write_generic); | ||
124 | |||
125 | #endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */ | ||
126 | |||
26 | unsigned int dcr_resource_start(struct device_node *np, unsigned int index) | 127 | unsigned int dcr_resource_start(struct device_node *np, unsigned int index) |
27 | { | 128 | { |
28 | unsigned int ds; | 129 | unsigned int ds; |
@@ -47,26 +148,7 @@ unsigned int dcr_resource_len(struct device_node *np, unsigned int index) | |||
47 | } | 148 | } |
48 | EXPORT_SYMBOL_GPL(dcr_resource_len); | 149 | EXPORT_SYMBOL_GPL(dcr_resource_len); |
49 | 150 | ||
50 | #ifndef CONFIG_PPC_DCR_NATIVE | 151 | #ifdef CONFIG_PPC_DCR_MMIO |
51 | |||
52 | static struct device_node * find_dcr_parent(struct device_node * node) | ||
53 | { | ||
54 | struct device_node *par, *tmp; | ||
55 | const u32 *p; | ||
56 | |||
57 | for (par = of_node_get(node); par;) { | ||
58 | if (of_get_property(par, "dcr-controller", NULL)) | ||
59 | break; | ||
60 | p = of_get_property(par, "dcr-parent", NULL); | ||
61 | tmp = par; | ||
62 | if (p == NULL) | ||
63 | par = of_get_parent(par); | ||
64 | else | ||
65 | par = of_find_node_by_phandle(*p); | ||
66 | of_node_put(tmp); | ||
67 | } | ||
68 | return par; | ||
69 | } | ||
70 | 152 | ||
71 | u64 of_translate_dcr_address(struct device_node *dev, | 153 | u64 of_translate_dcr_address(struct device_node *dev, |
72 | unsigned int dcr_n, | 154 | unsigned int dcr_n, |
@@ -75,7 +157,7 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
75 | struct device_node *dp; | 157 | struct device_node *dp; |
76 | const u32 *p; | 158 | const u32 *p; |
77 | unsigned int stride; | 159 | unsigned int stride; |
78 | u64 ret; | 160 | u64 ret = OF_BAD_ADDR; |
79 | 161 | ||
80 | dp = find_dcr_parent(dev); | 162 | dp = find_dcr_parent(dev); |
81 | if (dp == NULL) | 163 | if (dp == NULL) |
@@ -90,7 +172,7 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
90 | if (p == NULL) | 172 | if (p == NULL) |
91 | p = of_get_property(dp, "dcr-mmio-space", NULL); | 173 | p = of_get_property(dp, "dcr-mmio-space", NULL); |
92 | if (p == NULL) | 174 | if (p == NULL) |
93 | return OF_BAD_ADDR; | 175 | goto done; |
94 | 176 | ||
95 | /* Maybe could do some better range checking here */ | 177 | /* Maybe could do some better range checking here */ |
96 | ret = of_translate_address(dp, p); | 178 | ret = of_translate_address(dp, p); |
@@ -98,21 +180,25 @@ u64 of_translate_dcr_address(struct device_node *dev, | |||
98 | ret += (u64)(stride) * (u64)dcr_n; | 180 | ret += (u64)(stride) * (u64)dcr_n; |
99 | if (out_stride) | 181 | if (out_stride) |
100 | *out_stride = stride; | 182 | *out_stride = stride; |
183 | |||
184 | done: | ||
185 | of_node_put(dp); | ||
101 | return ret; | 186 | return ret; |
102 | } | 187 | } |
103 | 188 | ||
104 | dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | 189 | dcr_host_mmio_t dcr_map_mmio(struct device_node *dev, |
105 | unsigned int dcr_c) | 190 | unsigned int dcr_n, |
191 | unsigned int dcr_c) | ||
106 | { | 192 | { |
107 | dcr_host_t ret = { .token = NULL, .stride = 0, .base = dcr_n }; | 193 | dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n }; |
108 | u64 addr; | 194 | u64 addr; |
109 | 195 | ||
110 | pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", | 196 | pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", |
111 | dev->full_name, dcr_n, dcr_c); | 197 | dev->full_name, dcr_n, dcr_c); |
112 | 198 | ||
113 | addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); | 199 | addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); |
114 | pr_debug("translates to addr: 0x%lx, stride: 0x%x\n", | 200 | pr_debug("translates to addr: 0x%llx, stride: 0x%x\n", |
115 | addr, ret.stride); | 201 | (unsigned long long) addr, ret.stride); |
116 | if (addr == OF_BAD_ADDR) | 202 | if (addr == OF_BAD_ADDR) |
117 | return ret; | 203 | return ret; |
118 | pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); | 204 | pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); |
@@ -124,11 +210,11 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | |||
124 | ret.token -= dcr_n * ret.stride; | 210 | ret.token -= dcr_n * ret.stride; |
125 | return ret; | 211 | return ret; |
126 | } | 212 | } |
127 | EXPORT_SYMBOL_GPL(dcr_map); | 213 | EXPORT_SYMBOL_GPL(dcr_map_mmio); |
128 | 214 | ||
129 | void dcr_unmap(dcr_host_t host, unsigned int dcr_c) | 215 | void dcr_unmap_mmio(dcr_host_mmio_t host, unsigned int dcr_c) |
130 | { | 216 | { |
131 | dcr_host_t h = host; | 217 | dcr_host_mmio_t h = host; |
132 | 218 | ||
133 | if (h.token == NULL) | 219 | if (h.token == NULL) |
134 | return; | 220 | return; |
@@ -136,7 +222,11 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_c) | |||
136 | iounmap(h.token); | 222 | iounmap(h.token); |
137 | h.token = NULL; | 223 | h.token = NULL; |
138 | } | 224 | } |
139 | EXPORT_SYMBOL_GPL(dcr_unmap); | 225 | EXPORT_SYMBOL_GPL(dcr_unmap_mmio); |
140 | #else /* defined(CONFIG_PPC_DCR_NATIVE) */ | 226 | |
227 | #endif /* defined(CONFIG_PPC_DCR_MMIO) */ | ||
228 | |||
229 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
141 | DEFINE_SPINLOCK(dcr_ind_lock); | 230 | DEFINE_SPINLOCK(dcr_ind_lock); |
142 | #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ | 231 | #endif /* defined(CONFIG_PPC_DCR_NATIVE) */ |
232 | |||
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c new file mode 100644 index 000000000000..2c5187cc8a24 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -0,0 +1,429 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: Tony Li <tony.li@freescale.com> | ||
5 | * Jason Jin <Jason.jin@freescale.com> | ||
6 | * | ||
7 | * The hwirq alloc and free code reuse from sysdev/mpic_msi.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; version 2 of the | ||
12 | * License. | ||
13 | * | ||
14 | */ | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/bootmem.h> | ||
17 | #include <linux/bitmap.h> | ||
18 | #include <linux/msi.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <sysdev/fsl_soc.h> | ||
22 | #include <asm/prom.h> | ||
23 | #include <asm/hw_irq.h> | ||
24 | #include <asm/ppc-pci.h> | ||
25 | #include "fsl_msi.h" | ||
26 | |||
27 | struct fsl_msi_feature { | ||
28 | u32 fsl_pic_ip; | ||
29 | u32 msiir_offset; | ||
30 | }; | ||
31 | |||
32 | static struct fsl_msi *fsl_msi; | ||
33 | |||
34 | static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) | ||
35 | { | ||
36 | return in_be32(base + (reg >> 2)); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * We do not need this actually. The MSIR register has been read once | ||
41 | * in the cascade interrupt. So, this MSI interrupt has been acked | ||
42 | */ | ||
43 | static void fsl_msi_end_irq(unsigned int virq) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | static struct irq_chip fsl_msi_chip = { | ||
48 | .mask = mask_msi_irq, | ||
49 | .unmask = unmask_msi_irq, | ||
50 | .ack = fsl_msi_end_irq, | ||
51 | .typename = " FSL-MSI ", | ||
52 | }; | ||
53 | |||
54 | static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, | ||
55 | irq_hw_number_t hw) | ||
56 | { | ||
57 | struct irq_chip *chip = &fsl_msi_chip; | ||
58 | |||
59 | get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; | ||
60 | |||
61 | set_irq_chip_and_handler(virq, chip, handle_edge_irq); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static struct irq_host_ops fsl_msi_host_ops = { | ||
67 | .map = fsl_msi_host_map, | ||
68 | }; | ||
69 | |||
70 | static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num) | ||
71 | { | ||
72 | unsigned long flags; | ||
73 | int order = get_count_order(num); | ||
74 | int offset; | ||
75 | |||
76 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
77 | |||
78 | offset = bitmap_find_free_region(msi->fsl_msi_bitmap, | ||
79 | NR_MSI_IRQS, order); | ||
80 | |||
81 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
82 | |||
83 | pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n", | ||
84 | __func__, num, order, offset); | ||
85 | |||
86 | return offset; | ||
87 | } | ||
88 | |||
89 | static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num) | ||
90 | { | ||
91 | unsigned long flags; | ||
92 | int order = get_count_order(num); | ||
93 | |||
94 | pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n", | ||
95 | __func__, num, order, offset); | ||
96 | |||
97 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
98 | bitmap_release_region(msi->fsl_msi_bitmap, offset, order); | ||
99 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
100 | } | ||
101 | |||
102 | static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi) | ||
103 | { | ||
104 | int i; | ||
105 | int len; | ||
106 | const u32 *p; | ||
107 | |||
108 | bitmap_allocate_region(msi->fsl_msi_bitmap, 0, | ||
109 | get_count_order(NR_MSI_IRQS)); | ||
110 | |||
111 | p = of_get_property(msi->of_node, "msi-available-ranges", &len); | ||
112 | |||
113 | if (!p) { | ||
114 | /* No msi-available-ranges property, | ||
115 | * All the 256 MSI interrupts can be used | ||
116 | */ | ||
117 | fsl_msi_free_hwirqs(msi, 0, 0x100); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | if ((len % (2 * sizeof(u32))) != 0) { | ||
122 | printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges " | ||
123 | "property on %s\n", msi->of_node->full_name); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | /* Format is: (<u32 start> <u32 count>)+ */ | ||
128 | len /= 2 * sizeof(u32); | ||
129 | for (i = 0; i < len; i++, p += 2) | ||
130 | fsl_msi_free_hwirqs(msi, *p, *(p + 1)); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int fsl_msi_init_allocator(struct fsl_msi *msi_data) | ||
136 | { | ||
137 | int rc; | ||
138 | int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32); | ||
139 | |||
140 | msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL); | ||
141 | |||
142 | if (msi_data->fsl_msi_bitmap == NULL) { | ||
143 | pr_debug("%s: ENOMEM allocating allocator bitmap!\n", | ||
144 | __func__); | ||
145 | return -ENOMEM; | ||
146 | } | ||
147 | |||
148 | rc = fsl_msi_free_dt_hwirqs(msi_data); | ||
149 | if (rc) | ||
150 | goto out_free; | ||
151 | |||
152 | return 0; | ||
153 | out_free: | ||
154 | kfree(msi_data->fsl_msi_bitmap); | ||
155 | |||
156 | msi_data->fsl_msi_bitmap = NULL; | ||
157 | return rc; | ||
158 | |||
159 | } | ||
160 | |||
161 | static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) | ||
162 | { | ||
163 | if (type == PCI_CAP_ID_MSIX) | ||
164 | pr_debug("fslmsi: MSI-X untested, trying anyway.\n"); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static void fsl_teardown_msi_irqs(struct pci_dev *pdev) | ||
170 | { | ||
171 | struct msi_desc *entry; | ||
172 | struct fsl_msi *msi_data = fsl_msi; | ||
173 | |||
174 | list_for_each_entry(entry, &pdev->msi_list, list) { | ||
175 | if (entry->irq == NO_IRQ) | ||
176 | continue; | ||
177 | set_irq_msi(entry->irq, NULL); | ||
178 | fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); | ||
179 | irq_dispose_mapping(entry->irq); | ||
180 | } | ||
181 | |||
182 | return; | ||
183 | } | ||
184 | |||
185 | static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | ||
186 | struct msi_msg *msg) | ||
187 | { | ||
188 | struct fsl_msi *msi_data = fsl_msi; | ||
189 | |||
190 | msg->address_lo = msi_data->msi_addr_lo; | ||
191 | msg->address_hi = msi_data->msi_addr_hi; | ||
192 | msg->data = hwirq; | ||
193 | |||
194 | pr_debug("%s: allocated srs: %d, ibs: %d\n", | ||
195 | __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); | ||
196 | } | ||
197 | |||
198 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | ||
199 | { | ||
200 | irq_hw_number_t hwirq; | ||
201 | int rc; | ||
202 | unsigned int virq; | ||
203 | struct msi_desc *entry; | ||
204 | struct msi_msg msg; | ||
205 | struct fsl_msi *msi_data = fsl_msi; | ||
206 | |||
207 | list_for_each_entry(entry, &pdev->msi_list, list) { | ||
208 | hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); | ||
209 | if (hwirq < 0) { | ||
210 | rc = hwirq; | ||
211 | pr_debug("%s: fail allocating msi interrupt\n", | ||
212 | __func__); | ||
213 | goto out_free; | ||
214 | } | ||
215 | |||
216 | virq = irq_create_mapping(msi_data->irqhost, hwirq); | ||
217 | |||
218 | if (virq == NO_IRQ) { | ||
219 | pr_debug("%s: fail mapping hwirq 0x%lx\n", | ||
220 | __func__, hwirq); | ||
221 | fsl_msi_free_hwirqs(msi_data, hwirq, 1); | ||
222 | rc = -ENOSPC; | ||
223 | goto out_free; | ||
224 | } | ||
225 | set_irq_msi(virq, entry); | ||
226 | |||
227 | fsl_compose_msi_msg(pdev, hwirq, &msg); | ||
228 | write_msi_msg(virq, &msg); | ||
229 | } | ||
230 | return 0; | ||
231 | |||
232 | out_free: | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | ||
237 | { | ||
238 | unsigned int cascade_irq; | ||
239 | struct fsl_msi *msi_data = fsl_msi; | ||
240 | int msir_index = -1; | ||
241 | u32 msir_value = 0; | ||
242 | u32 intr_index; | ||
243 | u32 have_shift = 0; | ||
244 | |||
245 | spin_lock(&desc->lock); | ||
246 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { | ||
247 | if (desc->chip->mask_ack) | ||
248 | desc->chip->mask_ack(irq); | ||
249 | else { | ||
250 | desc->chip->mask(irq); | ||
251 | desc->chip->ack(irq); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | if (unlikely(desc->status & IRQ_INPROGRESS)) | ||
256 | goto unlock; | ||
257 | |||
258 | msir_index = (int)desc->handler_data; | ||
259 | |||
260 | if (msir_index >= NR_MSI_REG) | ||
261 | cascade_irq = NO_IRQ; | ||
262 | |||
263 | desc->status |= IRQ_INPROGRESS; | ||
264 | switch (fsl_msi->feature & FSL_PIC_IP_MASK) { | ||
265 | case FSL_PIC_IP_MPIC: | ||
266 | msir_value = fsl_msi_read(msi_data->msi_regs, | ||
267 | msir_index * 0x10); | ||
268 | break; | ||
269 | case FSL_PIC_IP_IPIC: | ||
270 | msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4); | ||
271 | break; | ||
272 | } | ||
273 | |||
274 | while (msir_value) { | ||
275 | intr_index = ffs(msir_value) - 1; | ||
276 | |||
277 | cascade_irq = irq_linear_revmap(msi_data->irqhost, | ||
278 | msir_index * IRQS_PER_MSI_REG + | ||
279 | intr_index + have_shift); | ||
280 | if (cascade_irq != NO_IRQ) | ||
281 | generic_handle_irq(cascade_irq); | ||
282 | have_shift += intr_index + 1; | ||
283 | msir_value = msir_value >> (intr_index + 1); | ||
284 | } | ||
285 | desc->status &= ~IRQ_INPROGRESS; | ||
286 | |||
287 | switch (msi_data->feature & FSL_PIC_IP_MASK) { | ||
288 | case FSL_PIC_IP_MPIC: | ||
289 | desc->chip->eoi(irq); | ||
290 | break; | ||
291 | case FSL_PIC_IP_IPIC: | ||
292 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) | ||
293 | desc->chip->unmask(irq); | ||
294 | break; | ||
295 | } | ||
296 | unlock: | ||
297 | spin_unlock(&desc->lock); | ||
298 | } | ||
299 | |||
300 | static int __devinit fsl_of_msi_probe(struct of_device *dev, | ||
301 | const struct of_device_id *match) | ||
302 | { | ||
303 | struct fsl_msi *msi; | ||
304 | struct resource res; | ||
305 | int err, i, count; | ||
306 | int rc; | ||
307 | int virt_msir; | ||
308 | const u32 *p; | ||
309 | struct fsl_msi_feature *features = match->data; | ||
310 | |||
311 | printk(KERN_DEBUG "Setting up Freescale MSI support\n"); | ||
312 | |||
313 | msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); | ||
314 | if (!msi) { | ||
315 | dev_err(&dev->dev, "No memory for MSI structure\n"); | ||
316 | err = -ENOMEM; | ||
317 | goto error_out; | ||
318 | } | ||
319 | |||
320 | msi->of_node = of_node_get(dev->node); | ||
321 | |||
322 | msi->irqhost = irq_alloc_host(of_node_get(dev->node), | ||
323 | IRQ_HOST_MAP_LINEAR, | ||
324 | NR_MSI_IRQS, &fsl_msi_host_ops, 0); | ||
325 | if (msi->irqhost == NULL) { | ||
326 | dev_err(&dev->dev, "No memory for MSI irqhost\n"); | ||
327 | of_node_put(dev->node); | ||
328 | err = -ENOMEM; | ||
329 | goto error_out; | ||
330 | } | ||
331 | |||
332 | /* Get the MSI reg base */ | ||
333 | err = of_address_to_resource(dev->node, 0, &res); | ||
334 | if (err) { | ||
335 | dev_err(&dev->dev, "%s resource error!\n", | ||
336 | dev->node->full_name); | ||
337 | goto error_out; | ||
338 | } | ||
339 | |||
340 | msi->msi_regs = ioremap(res.start, res.end - res.start + 1); | ||
341 | if (!msi->msi_regs) { | ||
342 | dev_err(&dev->dev, "ioremap problem failed\n"); | ||
343 | goto error_out; | ||
344 | } | ||
345 | |||
346 | msi->feature = features->fsl_pic_ip; | ||
347 | |||
348 | msi->irqhost->host_data = msi; | ||
349 | |||
350 | msi->msi_addr_hi = 0x0; | ||
351 | msi->msi_addr_lo = res.start + features->msiir_offset; | ||
352 | |||
353 | rc = fsl_msi_init_allocator(msi); | ||
354 | if (rc) { | ||
355 | dev_err(&dev->dev, "Error allocating MSI bitmap\n"); | ||
356 | goto error_out; | ||
357 | } | ||
358 | |||
359 | p = of_get_property(dev->node, "interrupts", &count); | ||
360 | if (!p) { | ||
361 | dev_err(&dev->dev, "no interrupts property found on %s\n", | ||
362 | dev->node->full_name); | ||
363 | err = -ENODEV; | ||
364 | goto error_out; | ||
365 | } | ||
366 | if (count % 8 != 0) { | ||
367 | dev_err(&dev->dev, "Malformed interrupts property on %s\n", | ||
368 | dev->node->full_name); | ||
369 | err = -EINVAL; | ||
370 | goto error_out; | ||
371 | } | ||
372 | |||
373 | count /= sizeof(u32); | ||
374 | for (i = 0; i < count / 2; i++) { | ||
375 | if (i > NR_MSI_REG) | ||
376 | break; | ||
377 | virt_msir = irq_of_parse_and_map(dev->node, i); | ||
378 | if (virt_msir != NO_IRQ) { | ||
379 | set_irq_data(virt_msir, (void *)i); | ||
380 | set_irq_chained_handler(virt_msir, fsl_msi_cascade); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | fsl_msi = msi; | ||
385 | |||
386 | WARN_ON(ppc_md.setup_msi_irqs); | ||
387 | ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; | ||
388 | ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; | ||
389 | ppc_md.msi_check_device = fsl_msi_check_device; | ||
390 | return 0; | ||
391 | error_out: | ||
392 | kfree(msi); | ||
393 | return err; | ||
394 | } | ||
395 | |||
396 | static const struct fsl_msi_feature mpic_msi_feature = { | ||
397 | .fsl_pic_ip = FSL_PIC_IP_MPIC, | ||
398 | .msiir_offset = 0x140, | ||
399 | }; | ||
400 | |||
401 | static const struct fsl_msi_feature ipic_msi_feature = { | ||
402 | .fsl_pic_ip = FSL_PIC_IP_IPIC, | ||
403 | .msiir_offset = 0x38, | ||
404 | }; | ||
405 | |||
406 | static const struct of_device_id fsl_of_msi_ids[] = { | ||
407 | { | ||
408 | .compatible = "fsl,mpic-msi", | ||
409 | .data = (void *)&mpic_msi_feature, | ||
410 | }, | ||
411 | { | ||
412 | .compatible = "fsl,ipic-msi", | ||
413 | .data = (void *)&ipic_msi_feature, | ||
414 | }, | ||
415 | {} | ||
416 | }; | ||
417 | |||
418 | static struct of_platform_driver fsl_of_msi_driver = { | ||
419 | .name = "fsl-msi", | ||
420 | .match_table = fsl_of_msi_ids, | ||
421 | .probe = fsl_of_msi_probe, | ||
422 | }; | ||
423 | |||
424 | static __init int fsl_of_msi_init(void) | ||
425 | { | ||
426 | return of_register_platform_driver(&fsl_of_msi_driver); | ||
427 | } | ||
428 | |||
429 | subsys_initcall(fsl_of_msi_init); | ||
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h new file mode 100644 index 000000000000..a653468521fa --- /dev/null +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: Tony Li <tony.li@freescale.com> | ||
5 | * Jason Jin <Jason.jin@freescale.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 of the | ||
10 | * License. | ||
11 | * | ||
12 | */ | ||
13 | #ifndef _POWERPC_SYSDEV_FSL_MSI_H | ||
14 | #define _POWERPC_SYSDEV_FSL_MSI_H | ||
15 | |||
16 | #define NR_MSI_REG 8 | ||
17 | #define IRQS_PER_MSI_REG 32 | ||
18 | #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) | ||
19 | |||
20 | #define FSL_PIC_IP_MASK 0x0000000F | ||
21 | #define FSL_PIC_IP_MPIC 0x00000001 | ||
22 | #define FSL_PIC_IP_IPIC 0x00000002 | ||
23 | |||
24 | struct fsl_msi { | ||
25 | /* Device node of the MSI interrupt*/ | ||
26 | struct device_node *of_node; | ||
27 | |||
28 | struct irq_host *irqhost; | ||
29 | |||
30 | unsigned long cascade_irq; | ||
31 | |||
32 | u32 msi_addr_lo; | ||
33 | u32 msi_addr_hi; | ||
34 | void __iomem *msi_regs; | ||
35 | u32 feature; | ||
36 | |||
37 | unsigned long *fsl_msi_bitmap; | ||
38 | spinlock_t bitmap_lock; | ||
39 | }; | ||
40 | |||
41 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ | ||
42 | |||
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index bf13c2174a4e..489ca5a397b1 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -106,6 +106,16 @@ void __init setup_pci_cmd(struct pci_controller *hose) | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | static void __init setup_pci_pcsrbar(struct pci_controller *hose) | ||
110 | { | ||
111 | #ifdef CONFIG_PCI_MSI | ||
112 | phys_addr_t immr_base; | ||
113 | |||
114 | immr_base = get_immrbase(); | ||
115 | early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, immr_base); | ||
116 | #endif | ||
117 | } | ||
118 | |||
109 | static int fsl_pcie_bus_fixup; | 119 | static int fsl_pcie_bus_fixup; |
110 | 120 | ||
111 | static void __init quirk_fsl_pcie_header(struct pci_dev *dev) | 121 | static void __init quirk_fsl_pcie_header(struct pci_dev *dev) |
@@ -211,6 +221,8 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary) | |||
211 | /* Setup PEX window registers */ | 221 | /* Setup PEX window registers */ |
212 | setup_pci_atmu(hose, &rsrc); | 222 | setup_pci_atmu(hose, &rsrc); |
213 | 223 | ||
224 | /* Setup PEXCSRBAR */ | ||
225 | setup_pci_pcsrbar(hose); | ||
214 | return 0; | 226 | return 0; |
215 | } | 227 | } |
216 | 228 | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 019657c110b6..ca54563d5c7e 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -433,6 +433,7 @@ static struct i2c_driver_device i2c_devices[] __initdata = { | |||
433 | {"dallas,ds1340", "ds1340"}, | 433 | {"dallas,ds1340", "ds1340"}, |
434 | {"stm,m41t00", "m41t00"}, | 434 | {"stm,m41t00", "m41t00"}, |
435 | {"dallas,ds1374", "ds1374"}, | 435 | {"dallas,ds1374", "ds1374"}, |
436 | {"cirrus,cs4270", "cs4270"}, | ||
436 | }; | 437 | }; |
437 | 438 | ||
438 | static int __init of_find_i2c_driver(struct device_node *node, | 439 | static int __init of_find_i2c_driver(struct device_node *node, |
@@ -448,6 +449,10 @@ static int __init of_find_i2c_driver(struct device_node *node, | |||
448 | return -ENOMEM; | 449 | return -ENOMEM; |
449 | return 0; | 450 | return 0; |
450 | } | 451 | } |
452 | |||
453 | pr_warning("fsl_soc.c: unrecognized i2c node %s\n", | ||
454 | (const char *) of_get_property(node, "compatible", NULL)); | ||
455 | |||
451 | return -ENODEV; | 456 | return -ENODEV; |
452 | } | 457 | } |
453 | 458 | ||
@@ -491,6 +496,8 @@ static int __init fsl_i2c_of_init(void) | |||
491 | struct resource r[2]; | 496 | struct resource r[2]; |
492 | struct fsl_i2c_platform_data i2c_data; | 497 | struct fsl_i2c_platform_data i2c_data; |
493 | const unsigned char *flags = NULL; | 498 | const unsigned char *flags = NULL; |
499 | int idx; | ||
500 | const u32 *iprop; | ||
494 | 501 | ||
495 | memset(&r, 0, sizeof(r)); | 502 | memset(&r, 0, sizeof(r)); |
496 | memset(&i2c_data, 0, sizeof(i2c_data)); | 503 | memset(&i2c_data, 0, sizeof(i2c_data)); |
@@ -501,7 +508,10 @@ static int __init fsl_i2c_of_init(void) | |||
501 | 508 | ||
502 | of_irq_to_resource(np, 0, &r[1]); | 509 | of_irq_to_resource(np, 0, &r[1]); |
503 | 510 | ||
504 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); | 511 | iprop = of_get_property(np, "cell-index", NULL); |
512 | idx = iprop ? *iprop : i; | ||
513 | |||
514 | i2c_dev = platform_device_register_simple("fsl-i2c", idx, r, 2); | ||
505 | if (IS_ERR(i2c_dev)) { | 515 | if (IS_ERR(i2c_dev)) { |
506 | ret = PTR_ERR(i2c_dev); | 516 | ret = PTR_ERR(i2c_dev); |
507 | goto err; | 517 | goto err; |
@@ -523,7 +533,8 @@ static int __init fsl_i2c_of_init(void) | |||
523 | if (ret) | 533 | if (ret) |
524 | goto unreg; | 534 | goto unreg; |
525 | 535 | ||
526 | of_register_i2c_devices(np, i++); | 536 | of_register_i2c_devices(np, idx); |
537 | i++; | ||
527 | } | 538 | } |
528 | 539 | ||
529 | return 0; | 540 | return 0; |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7680001676a6..f99f81abbd5c 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -1144,9 +1144,12 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1144 | mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK) | 1144 | mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK) |
1145 | >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; | 1145 | >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; |
1146 | if (isu_size == 0) | 1146 | if (isu_size == 0) |
1147 | mpic->num_sources = | 1147 | if (flags & MPIC_BROKEN_FRR_NIRQS) |
1148 | ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) | 1148 | mpic->num_sources = mpic->irq_count; |
1149 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; | 1149 | else |
1150 | mpic->num_sources = | ||
1151 | ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) | ||
1152 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; | ||
1150 | 1153 | ||
1151 | /* Map the per-CPU registers */ | 1154 | /* Map the per-CPU registers */ |
1152 | for (i = 0; i < mpic->num_cpus; i++) { | 1155 | for (i = 0; i < mpic->num_cpus; i++) { |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index d272a52ecd24..de3e5e8bc324 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/hw_irq.h> | 16 | #include <asm/hw_irq.h> |
17 | #include <asm/ppc-pci.h> | 17 | #include <asm/ppc-pci.h> |
18 | 18 | ||
19 | #include <sysdev/mpic.h> | ||
19 | 20 | ||
20 | static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) | 21 | static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) |
21 | { | 22 | { |
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 33cbfb22ce3e..68aff6076675 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c | |||
@@ -95,6 +95,7 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
95 | unsigned int virq; | 95 | unsigned int virq; |
96 | struct msi_desc *entry; | 96 | struct msi_desc *entry; |
97 | struct msi_msg msg; | 97 | struct msi_msg msg; |
98 | int ret; | ||
98 | 99 | ||
99 | pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n", | 100 | pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n", |
100 | pdev, nvec, type); | 101 | pdev, nvec, type); |
@@ -108,8 +109,9 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
108 | * few MSIs for someone, but restrictions will apply to how the | 109 | * few MSIs for someone, but restrictions will apply to how the |
109 | * sources can be changed independently. | 110 | * sources can be changed independently. |
110 | */ | 111 | */ |
111 | hwirq = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK); | 112 | ret = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK); |
112 | if (hwirq < 0) { | 113 | hwirq = ret; |
114 | if (ret < 0) { | ||
113 | pr_debug("pasemi_msi: failed allocating hwirq\n"); | 115 | pr_debug("pasemi_msi: failed allocating hwirq\n"); |
114 | return hwirq; | 116 | return hwirq; |
115 | } | 117 | } |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 1d5a40899b74..6e2f8686fdfc 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
@@ -115,17 +115,19 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
115 | struct msi_desc *entry; | 115 | struct msi_desc *entry; |
116 | struct msi_msg msg; | 116 | struct msi_msg msg; |
117 | u64 addr; | 117 | u64 addr; |
118 | int ret; | ||
118 | 119 | ||
119 | addr = find_ht_magic_addr(pdev); | 120 | addr = find_ht_magic_addr(pdev); |
120 | msg.address_lo = addr & 0xFFFFFFFF; | 121 | msg.address_lo = addr & 0xFFFFFFFF; |
121 | msg.address_hi = addr >> 32; | 122 | msg.address_hi = addr >> 32; |
122 | 123 | ||
123 | list_for_each_entry(entry, &pdev->msi_list, list) { | 124 | list_for_each_entry(entry, &pdev->msi_list, list) { |
124 | hwirq = mpic_msi_alloc_hwirqs(msi_mpic, 1); | 125 | ret = mpic_msi_alloc_hwirqs(msi_mpic, 1); |
125 | if (hwirq < 0) { | 126 | if (ret < 0) { |
126 | pr_debug("u3msi: failed allocating hwirq\n"); | 127 | pr_debug("u3msi: failed allocating hwirq\n"); |
127 | return hwirq; | 128 | return ret; |
128 | } | 129 | } |
130 | hwirq = ret; | ||
129 | 131 | ||
130 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
131 | if (virq == NO_IRQ) { | 133 | if (virq == NO_IRQ) { |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index a132e0de8ca5..32e0ad0ebea8 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/console.h> | 15 | #include <linux/console.h> |
16 | #include <linux/mv643xx.h> | 16 | #include <linux/mv643xx.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/of_platform.h> | ||
18 | 19 | ||
19 | #include <asm/prom.h> | 20 | #include <asm/prom.h> |
20 | 21 | ||
@@ -25,6 +26,11 @@ | |||
25 | * PowerPC of_platform_bus_type. They support platform_bus_type instead. | 26 | * PowerPC of_platform_bus_type. They support platform_bus_type instead. |
26 | */ | 27 | */ |
27 | 28 | ||
29 | static struct of_device_id __initdata of_mv64x60_devices[] = { | ||
30 | { .compatible = "marvell,mv64306-devctrl", }, | ||
31 | {} | ||
32 | }; | ||
33 | |||
28 | /* | 34 | /* |
29 | * Create MPSC platform devices | 35 | * Create MPSC platform devices |
30 | */ | 36 | */ |
@@ -484,6 +490,10 @@ static int __init mv64x60_device_setup(void) | |||
484 | of_node_put(np); | 490 | of_node_put(np); |
485 | } | 491 | } |
486 | 492 | ||
493 | /* Now add every node that is on the device bus */ | ||
494 | for_each_compatible_node(np, NULL, "marvell,mv64360") | ||
495 | of_platform_bus_probe(np, of_mv64x60_devices, NULL); | ||
496 | |||
487 | return 0; | 497 | return 0; |
488 | } | 498 | } |
489 | arch_initcall(mv64x60_device_setup); | 499 | arch_initcall(mv64x60_device_setup); |