aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/6xx-suspend.S52
-rw-r--r--arch/powerpc/sysdev/Makefile9
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.c2
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.c95
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.h5
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.c2
-rw-r--r--arch/powerpc/sysdev/cpm1.c2
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.c2
-rw-r--r--arch/powerpc/sysdev/cpm_common.c19
-rw-r--r--arch/powerpc/sysdev/dcr.c156
-rw-r--r--arch/powerpc/sysdev/fsl_gtm.c434
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c429
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h42
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c14
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c122
-rw-r--r--arch/powerpc/sysdev/i8259.c2
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c6
-rw-r--r--arch/powerpc/sysdev/ipic.c16
-rw-r--r--arch/powerpc/sysdev/mpic.c18
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c1
-rw-r--r--arch/powerpc/sysdev/mpic_pasemi_msi.c6
-rw-r--r--arch/powerpc/sysdev/mpic_u3msi.c8
-rw-r--r--arch/powerpc/sysdev/mv64x60_dev.c10
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c14
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig13
-rw-r--r--arch/powerpc/sysdev/qe_lib/Makefile2
-rw-r--r--arch/powerpc/sysdev/qe_lib/gpio.c149
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c94
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c14
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c94
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c7
-rw-r--r--arch/powerpc/sysdev/qe_lib/usb.c55
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c3
-rw-r--r--arch/powerpc/sysdev/uic.c6
34 files changed, 1555 insertions, 348 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
441: b 1b
45
46ret_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..16a0ed28eb00 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,7 @@ endif
4 4
5mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o 5mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
6obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) 6obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
7fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o
7 8
8obj-$(CONFIG_PPC_MPC106) += grackle.o 9obj-$(CONFIG_PPC_MPC106) += grackle.o
9obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o 10obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o
@@ -11,8 +12,9 @@ obj-$(CONFIG_PPC_PMI) += pmi.o
11obj-$(CONFIG_U3_DART) += dart_iommu.o 12obj-$(CONFIG_U3_DART) += dart_iommu.o
12obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 13obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
13obj-$(CONFIG_FSL_SOC) += fsl_soc.o 14obj-$(CONFIG_FSL_SOC) += fsl_soc.o
14obj-$(CONFIG_FSL_PCI) += fsl_pci.o 15obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y)
15obj-$(CONFIG_FSL_LBC) += fsl_lbc.o 16obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
17obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
16obj-$(CONFIG_RAPIDIO) += fsl_rio.o 18obj-$(CONFIG_RAPIDIO) += fsl_rio.o
17obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o 19obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
18obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ 20obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
@@ -40,7 +42,12 @@ endif
40ifeq ($(ARCH),powerpc) 42ifeq ($(ARCH),powerpc)
41obj-$(CONFIG_CPM) += cpm_common.o 43obj-$(CONFIG_CPM) += cpm_common.o
42obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o 44obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o
45obj-$(CONFIG_QUICC_ENGINE) += cpm_common.o
43obj-$(CONFIG_PPC_DCR) += dcr.o 46obj-$(CONFIG_PPC_DCR) += dcr.o
44obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o 47obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o
45obj-$(CONFIG_UCODE_PATCH) += micropatch.o 48obj-$(CONFIG_UCODE_PATCH) += micropatch.o
46endif 49endif
50
51ifeq ($(CONFIG_SUSPEND),y)
52obj-$(CONFIG_6xx) += 6xx-suspend.o
53endif
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
index 64ec7d629363..446c9ea85b30 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -443,7 +443,7 @@ mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match)
443 443
444 /* Done ! */ 444 /* Done ! */
445 printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n", 445 printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
446 bcom_eng->regs_base); 446 (long)bcom_eng->regs_base);
447 447
448 return 0; 448 return 0;
449 449
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c
index 8d33eafbb3f4..a3a134c35b0a 100644
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.c
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.c
@@ -20,6 +20,7 @@
20#include <asm/io.h> 20#include <asm/io.h>
21 21
22#include <asm/mpc52xx.h> 22#include <asm/mpc52xx.h>
23#include <asm/mpc52xx_psc.h>
23 24
24#include "bestcomm.h" 25#include "bestcomm.h"
25#include "bestcomm_priv.h" 26#include "bestcomm_priv.h"
@@ -253,6 +254,100 @@ bcom_gen_bd_tx_release(struct bcom_task *tsk)
253} 254}
254EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release); 255EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
255 256
257/* ---------------------------------------------------------------------
258 * PSC support code
259 */
260
261/**
262 * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
263 *
264 * This structure is only used internally. It is a lookup table for PSC
265 * specific parameters to bestcomm tasks.
266 */
267static struct bcom_psc_params {
268 int rx_initiator;
269 int rx_ipr;
270 int tx_initiator;
271 int tx_ipr;
272} bcom_psc_params[] = {
273 [0] = {
274 .rx_initiator = BCOM_INITIATOR_PSC1_RX,
275 .rx_ipr = BCOM_IPR_PSC1_RX,
276 .tx_initiator = BCOM_INITIATOR_PSC1_TX,
277 .tx_ipr = BCOM_IPR_PSC1_TX,
278 },
279 [1] = {
280 .rx_initiator = BCOM_INITIATOR_PSC2_RX,
281 .rx_ipr = BCOM_IPR_PSC2_RX,
282 .tx_initiator = BCOM_INITIATOR_PSC2_TX,
283 .tx_ipr = BCOM_IPR_PSC2_TX,
284 },
285 [2] = {
286 .rx_initiator = BCOM_INITIATOR_PSC3_RX,
287 .rx_ipr = BCOM_IPR_PSC3_RX,
288 .tx_initiator = BCOM_INITIATOR_PSC3_TX,
289 .tx_ipr = BCOM_IPR_PSC3_TX,
290 },
291 [3] = {
292 .rx_initiator = BCOM_INITIATOR_PSC4_RX,
293 .rx_ipr = BCOM_IPR_PSC4_RX,
294 .tx_initiator = BCOM_INITIATOR_PSC4_TX,
295 .tx_ipr = BCOM_IPR_PSC4_TX,
296 },
297 [4] = {
298 .rx_initiator = BCOM_INITIATOR_PSC5_RX,
299 .rx_ipr = BCOM_IPR_PSC5_RX,
300 .tx_initiator = BCOM_INITIATOR_PSC5_TX,
301 .tx_ipr = BCOM_IPR_PSC5_TX,
302 },
303 [5] = {
304 .rx_initiator = BCOM_INITIATOR_PSC6_RX,
305 .rx_ipr = BCOM_IPR_PSC6_RX,
306 .tx_initiator = BCOM_INITIATOR_PSC6_TX,
307 .tx_ipr = BCOM_IPR_PSC6_TX,
308 },
309};
310
311/**
312 * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
313 * @psc_num: Number of the PSC to allocate a task for
314 * @queue_len: number of buffer descriptors to allocate for the task
315 * @fifo: physical address of FIFO register
316 * @maxbufsize: Maximum receive data size in bytes.
317 *
318 * Allocate a bestcomm task structure for receiving data from a PSC.
319 */
320struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
321 phys_addr_t fifo, int maxbufsize)
322{
323 if (psc_num >= MPC52xx_PSC_MAXNUM)
324 return NULL;
325
326 return bcom_gen_bd_rx_init(queue_len, fifo,
327 bcom_psc_params[psc_num].rx_initiator,
328 bcom_psc_params[psc_num].rx_ipr,
329 maxbufsize);
330}
331EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
332
333/**
334 * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
335 * @psc_num: Number of the PSC to allocate a task for
336 * @queue_len: number of buffer descriptors to allocate for the task
337 * @fifo: physical address of FIFO register
338 *
339 * Allocate a bestcomm task structure for transmitting data to a PSC.
340 */
341struct bcom_task *
342bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
343{
344 struct psc;
345 return bcom_gen_bd_tx_init(queue_len, fifo,
346 bcom_psc_params[psc_num].tx_initiator,
347 bcom_psc_params[psc_num].tx_ipr);
348}
349EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
350
256 351
257MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver"); 352MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
258MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>"); 353MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/arch/powerpc/sysdev/bestcomm/gen_bd.h
index 5b6fa803c6aa..de47260e69da 100644
--- a/arch/powerpc/sysdev/bestcomm/gen_bd.h
+++ b/arch/powerpc/sysdev/bestcomm/gen_bd.h
@@ -44,5 +44,10 @@ extern void
44bcom_gen_bd_tx_release(struct bcom_task *tsk); 44bcom_gen_bd_tx_release(struct bcom_task *tsk);
45 45
46 46
47/* PSC support utility wrappers */
48struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
49 phys_addr_t fifo, int maxbufsize);
50struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len,
51 phys_addr_t fifo);
47#endif /* __BESTCOMM_GEN_BD_H__ */ 52#endif /* __BESTCOMM_GEN_BD_H__ */
48 53
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
index 99784383a843..5d74ef7a651f 100644
--- a/arch/powerpc/sysdev/bestcomm/sram.c
+++ b/arch/powerpc/sysdev/bestcomm/sram.c
@@ -86,7 +86,7 @@ int bcom_sram_init(struct device_node *sram_node, char *owner)
86 if (!bcom_sram->base_virt) { 86 if (!bcom_sram->base_virt) {
87 printk(KERN_ERR "%s: bcom_sram_init: " 87 printk(KERN_ERR "%s: bcom_sram_init: "
88 "Map error SRAM zone 0x%08lx (0x%0x)!\n", 88 "Map error SRAM zone 0x%08lx (0x%0x)!\n",
89 owner, bcom_sram->base_phys, bcom_sram->size ); 89 owner, (long)bcom_sram->base_phys, bcom_sram->size );
90 rv = -ENOMEM; 90 rv = -ENOMEM;
91 goto error_release; 91 goto error_release;
92 } 92 }
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 58292a086c16..661df42830b9 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -159,7 +159,7 @@ unsigned int cpm_pic_init(void)
159 159
160 out_be32(&cpic_reg->cpic_cimr, 0); 160 out_be32(&cpic_reg->cpic_cimr, 0);
161 161
162 cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR, 162 cpm_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
163 64, &cpm_pic_host_ops, 64); 163 64, &cpm_pic_host_ops, 64);
164 if (cpm_pic_host == NULL) { 164 if (cpm_pic_host == NULL) {
165 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); 165 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 5fe65b2f8f3a..b16ca3ed65d2 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -266,7 +266,7 @@ void cpm2_pic_init(struct device_node *node)
266 out_be32(&cpm2_intctl->ic_scprrl, 0x05309770); 266 out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);
267 267
268 /* create a legacy host */ 268 /* create a legacy host */
269 cpm2_pic_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 269 cpm2_pic_host = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
270 64, &cpm2_pic_host_ops, 64); 270 64, &cpm2_pic_host_ops, 64);
271 if (cpm2_pic_host == NULL) { 271 if (cpm2_pic_host == NULL) {
272 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); 272 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index cb7df2dce44f..e4b7296acb2c 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -37,7 +37,7 @@ static void udbg_putc_cpm(char c)
37 u8 __iomem *txbuf = (u8 __iomem __force *)in_be32(&cpm_udbg_txdesc[1]); 37 u8 __iomem *txbuf = (u8 __iomem __force *)in_be32(&cpm_udbg_txdesc[1]);
38 38
39 if (c == '\n') 39 if (c == '\n')
40 udbg_putc('\r'); 40 udbg_putc_cpm('\r');
41 41
42 while (in_be32(&cpm_udbg_txdesc[0]) & 0x80000000) 42 while (in_be32(&cpm_udbg_txdesc[0]) & 0x80000000)
43 ; 43 ;
@@ -53,7 +53,6 @@ void __init udbg_init_cpm(void)
53 setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO); 53 setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO);
54#endif 54#endif
55 udbg_putc = udbg_putc_cpm; 55 udbg_putc = udbg_putc_cpm;
56 udbg_putc('X');
57 } 56 }
58} 57}
59#endif 58#endif
@@ -85,9 +84,13 @@ int __init cpm_muram_init(void)
85 84
86 np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data"); 85 np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data");
87 if (!np) { 86 if (!np) {
88 printk(KERN_ERR "Cannot find CPM muram data node"); 87 /* try legacy bindings */
89 ret = -ENODEV; 88 np = of_find_node_by_name(NULL, "data-only");
90 goto out; 89 if (!np) {
90 printk(KERN_ERR "Cannot find CPM muram data node");
91 ret = -ENODEV;
92 goto out;
93 }
91 } 94 }
92 95
93 muram_pbase = of_translate_address(np, zero); 96 muram_pbase = of_translate_address(np, zero);
@@ -189,6 +192,12 @@ void __iomem *cpm_muram_addr(unsigned long offset)
189} 192}
190EXPORT_SYMBOL(cpm_muram_addr); 193EXPORT_SYMBOL(cpm_muram_addr);
191 194
195unsigned long cpm_muram_offset(void __iomem *addr)
196{
197 return addr - (void __iomem *)muram_vbase;
198}
199EXPORT_SYMBOL(cpm_muram_offset);
200
192/** 201/**
193 * cpm_muram_dma - turn a muram virtual address into a DMA address 202 * cpm_muram_dma - turn a muram virtual address into a DMA address
194 * @offset: virtual address from cpm_muram_addr() to convert 203 * @offset: virtual address from cpm_muram_addr() to convert
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
27static 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
49bool 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}
58EXPORT_SYMBOL_GPL(dcr_map_ok_generic);
59
60dcr_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}
89EXPORT_SYMBOL_GPL(dcr_map_generic);
90
91void 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}
100EXPORT_SYMBOL_GPL(dcr_unmap_generic);
101
102u32 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}
112EXPORT_SYMBOL_GPL(dcr_read_generic);
113
114void 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}
123EXPORT_SYMBOL_GPL(dcr_write_generic);
124
125#endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */
126
26unsigned int dcr_resource_start(struct device_node *np, unsigned int index) 127unsigned 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}
48EXPORT_SYMBOL_GPL(dcr_resource_len); 149EXPORT_SYMBOL_GPL(dcr_resource_len);
49 150
50#ifndef CONFIG_PPC_DCR_NATIVE 151#ifdef CONFIG_PPC_DCR_MMIO
51
52static 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
71u64 of_translate_dcr_address(struct device_node *dev, 153u64 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
104dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, 189dcr_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}
127EXPORT_SYMBOL_GPL(dcr_map); 213EXPORT_SYMBOL_GPL(dcr_map_mmio);
128 214
129void dcr_unmap(dcr_host_t host, unsigned int dcr_c) 215void 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}
139EXPORT_SYMBOL_GPL(dcr_unmap); 225EXPORT_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
141DEFINE_SPINLOCK(dcr_ind_lock); 230DEFINE_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_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
new file mode 100644
index 000000000000..714ec02fed2e
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,434 @@
1/*
2 * Freescale General-purpose Timers Module
3 *
4 * Copyright (c) Freescale Semicondutor, Inc. 2006.
5 * Shlomi Gridish <gridish@freescale.com>
6 * Jerry Huang <Chang-Ming.Huang@freescale.com>
7 * Copyright (c) MontaVista Software, Inc. 2008.
8 * Anton Vorontsov <avorontsov@ru.mvista.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/list.h>
19#include <linux/io.h>
20#include <linux/of.h>
21#include <linux/spinlock.h>
22#include <linux/bitops.h>
23#include <asm/fsl_gtm.h>
24
25#define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1)
26#define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0)
27
28#define GTMDR_ICLK_MASK (3 << 1)
29#define GTMDR_ICLK_ICAS (0 << 1)
30#define GTMDR_ICLK_ICLK (1 << 1)
31#define GTMDR_ICLK_SLGO (2 << 1)
32#define GTMDR_FRR (1 << 3)
33#define GTMDR_ORI (1 << 4)
34#define GTMDR_SPS(x) ((x) << 8)
35
36struct gtm_timers_regs {
37 u8 gtcfr1; /* Timer 1, Timer 2 global config register */
38 u8 res0[0x3];
39 u8 gtcfr2; /* Timer 3, timer 4 global config register */
40 u8 res1[0xB];
41 __be16 gtmdr1; /* Timer 1 mode register */
42 __be16 gtmdr2; /* Timer 2 mode register */
43 __be16 gtrfr1; /* Timer 1 reference register */
44 __be16 gtrfr2; /* Timer 2 reference register */
45 __be16 gtcpr1; /* Timer 1 capture register */
46 __be16 gtcpr2; /* Timer 2 capture register */
47 __be16 gtcnr1; /* Timer 1 counter */
48 __be16 gtcnr2; /* Timer 2 counter */
49 __be16 gtmdr3; /* Timer 3 mode register */
50 __be16 gtmdr4; /* Timer 4 mode register */
51 __be16 gtrfr3; /* Timer 3 reference register */
52 __be16 gtrfr4; /* Timer 4 reference register */
53 __be16 gtcpr3; /* Timer 3 capture register */
54 __be16 gtcpr4; /* Timer 4 capture register */
55 __be16 gtcnr3; /* Timer 3 counter */
56 __be16 gtcnr4; /* Timer 4 counter */
57 __be16 gtevr1; /* Timer 1 event register */
58 __be16 gtevr2; /* Timer 2 event register */
59 __be16 gtevr3; /* Timer 3 event register */
60 __be16 gtevr4; /* Timer 4 event register */
61 __be16 gtpsr1; /* Timer 1 prescale register */
62 __be16 gtpsr2; /* Timer 2 prescale register */
63 __be16 gtpsr3; /* Timer 3 prescale register */
64 __be16 gtpsr4; /* Timer 4 prescale register */
65 u8 res2[0x40];
66} __attribute__ ((packed));
67
68struct gtm {
69 unsigned int clock;
70 struct gtm_timers_regs __iomem *regs;
71 struct gtm_timer timers[4];
72 spinlock_t lock;
73 struct list_head list_node;
74};
75
76static LIST_HEAD(gtms);
77
78/**
79 * gtm_get_timer - request GTM timer to use it with the rest of GTM API
80 * Context: non-IRQ
81 *
82 * This function reserves GTM timer for later use. It returns gtm_timer
83 * structure to use with the rest of GTM API, you should use timer->irq
84 * to manage timer interrupt.
85 */
86struct gtm_timer *gtm_get_timer16(void)
87{
88 struct gtm *gtm = NULL;
89 int i;
90
91 list_for_each_entry(gtm, &gtms, list_node) {
92 spin_lock_irq(&gtm->lock);
93
94 for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
95 if (!gtm->timers[i].requested) {
96 gtm->timers[i].requested = true;
97 spin_unlock_irq(&gtm->lock);
98 return &gtm->timers[i];
99 }
100 }
101
102 spin_unlock_irq(&gtm->lock);
103 }
104
105 if (gtm)
106 return ERR_PTR(-EBUSY);
107 return ERR_PTR(-ENODEV);
108}
109EXPORT_SYMBOL(gtm_get_timer16);
110
111/**
112 * gtm_get_specific_timer - request specific GTM timer
113 * @gtm: specific GTM, pass here GTM's device_node->data
114 * @timer: specific timer number, Timer1 is 0.
115 * Context: non-IRQ
116 *
117 * This function reserves GTM timer for later use. It returns gtm_timer
118 * structure to use with the rest of GTM API, you should use timer->irq
119 * to manage timer interrupt.
120 */
121struct gtm_timer *gtm_get_specific_timer16(struct gtm *gtm,
122 unsigned int timer)
123{
124 struct gtm_timer *ret = ERR_PTR(-EBUSY);
125
126 if (timer > 3)
127 return ERR_PTR(-EINVAL);
128
129 spin_lock_irq(&gtm->lock);
130
131 if (gtm->timers[timer].requested)
132 goto out;
133
134 ret = &gtm->timers[timer];
135 ret->requested = true;
136
137out:
138 spin_unlock_irq(&gtm->lock);
139 return ret;
140}
141EXPORT_SYMBOL(gtm_get_specific_timer16);
142
143/**
144 * gtm_put_timer16 - release 16 bits GTM timer
145 * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
146 * Context: any
147 *
148 * This function releases GTM timer so others may request it.
149 */
150void gtm_put_timer16(struct gtm_timer *tmr)
151{
152 gtm_stop_timer16(tmr);
153
154 spin_lock_irq(&tmr->gtm->lock);
155 tmr->requested = false;
156 spin_unlock_irq(&tmr->gtm->lock);
157}
158EXPORT_SYMBOL(gtm_put_timer16);
159
160/*
161 * This is back-end for the exported functions, it's used to reset single
162 * timer in reference mode.
163 */
164static int gtm_set_ref_timer16(struct gtm_timer *tmr, int frequency,
165 int reference_value, bool free_run)
166{
167 struct gtm *gtm = tmr->gtm;
168 int num = tmr - &gtm->timers[0];
169 unsigned int prescaler;
170 u8 iclk = GTMDR_ICLK_ICLK;
171 u8 psr;
172 u8 sps;
173 unsigned long flags;
174 int max_prescaler = 256 * 256 * 16;
175
176 /* CPM2 doesn't have primary prescaler */
177 if (!tmr->gtpsr)
178 max_prescaler /= 256;
179
180 prescaler = gtm->clock / frequency;
181 /*
182 * We have two 8 bit prescalers -- primary and secondary (psr, sps),
183 * plus "slow go" mode (clk / 16). So, total prescale value is
184 * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr.
185 */
186 if (prescaler > max_prescaler)
187 return -EINVAL;
188
189 if (prescaler > max_prescaler / 16) {
190 iclk = GTMDR_ICLK_SLGO;
191 prescaler /= 16;
192 }
193
194 if (prescaler <= 256) {
195 psr = 0;
196 sps = prescaler - 1;
197 } else {
198 psr = 256 - 1;
199 sps = prescaler / 256 - 1;
200 }
201
202 spin_lock_irqsave(&gtm->lock, flags);
203
204 /*
205 * Properly reset timers: stop, reset, set up prescalers, reference
206 * value and clear event register.
207 */
208 clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
209 GTCFR_STP(num) | GTCFR_RST(num));
210
211 setbits8(tmr->gtcfr, GTCFR_STP(num));
212
213 if (tmr->gtpsr)
214 out_be16(tmr->gtpsr, psr);
215 clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
216 GTMDR_ORI | (free_run ? GTMDR_FRR : 0));
217 out_be16(tmr->gtcnr, 0);
218 out_be16(tmr->gtrfr, reference_value);
219 out_be16(tmr->gtevr, 0xFFFF);
220
221 /* Let it be. */
222 clrbits8(tmr->gtcfr, GTCFR_STP(num));
223
224 spin_unlock_irqrestore(&gtm->lock, flags);
225
226 return 0;
227}
228
229/**
230 * gtm_set_timer16 - (re)set 16 bit timer with arbitrary precision
231 * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
232 * @usec: timer interval in microseconds
233 * @reload: if set, the timer will reset upon expiry rather than
234 * continue running free.
235 * Context: any
236 *
237 * This function (re)sets the GTM timer so that it counts up to the requested
238 * interval value, and fires the interrupt when the value is reached. This
239 * function will reduce the precision of the timer as needed in order for the
240 * requested timeout to fit in a 16-bit register.
241 */
242int gtm_set_timer16(struct gtm_timer *tmr, unsigned long usec, bool reload)
243{
244 /* quite obvious, frequency which is enough for µSec precision */
245 int freq = 1000000;
246 unsigned int bit;
247
248 bit = fls_long(usec);
249 if (bit > 15) {
250 freq >>= bit - 15;
251 usec >>= bit - 15;
252 }
253
254 if (!freq)
255 return -EINVAL;
256
257 return gtm_set_ref_timer16(tmr, freq, usec, reload);
258}
259EXPORT_SYMBOL(gtm_set_timer16);
260
261/**
262 * gtm_set_exact_utimer16 - (re)set 16 bits timer
263 * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
264 * @usec: timer interval in microseconds
265 * @reload: if set, the timer will reset upon expiry rather than
266 * continue running free.
267 * Context: any
268 *
269 * This function (re)sets GTM timer so that it counts up to the requested
270 * interval value, and fires the interrupt when the value is reached. If reload
271 * flag was set, timer will also reset itself upon reference value, otherwise
272 * it continues to increment.
273 *
274 * The _exact_ bit in the function name states that this function will not
275 * crop precision of the "usec" argument, thus usec is limited to 16 bits
276 * (single timer width).
277 */
278int gtm_set_exact_timer16(struct gtm_timer *tmr, u16 usec, bool reload)
279{
280 /* quite obvious, frequency which is enough for µSec precision */
281 const int freq = 1000000;
282
283 /*
284 * We can lower the frequency (and probably power consumption) by
285 * dividing both frequency and usec by 2 until there is no remainder.
286 * But we won't bother with this unless savings are measured, so just
287 * run the timer as is.
288 */
289
290 return gtm_set_ref_timer16(tmr, freq, usec, reload);
291}
292EXPORT_SYMBOL(gtm_set_exact_timer16);
293
294/**
295 * gtm_stop_timer16 - stop single timer
296 * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
297 * Context: any
298 *
299 * This function simply stops the GTM timer.
300 */
301void gtm_stop_timer16(struct gtm_timer *tmr)
302{
303 struct gtm *gtm = tmr->gtm;
304 int num = tmr - &gtm->timers[0];
305 unsigned long flags;
306
307 spin_lock_irqsave(&gtm->lock, flags);
308
309 setbits8(tmr->gtcfr, GTCFR_STP(num));
310 out_be16(tmr->gtevr, 0xFFFF);
311
312 spin_unlock_irqrestore(&gtm->lock, flags);
313}
314EXPORT_SYMBOL(gtm_stop_timer16);
315
316/**
317 * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
318 * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
319 * @events: events mask to ack
320 * Context: any
321 *
322 * Thus function used to acknowledge timer interrupt event, use it inside the
323 * interrupt handler.
324 */
325void gtm_ack_timer16(struct gtm_timer *tmr, u16 events)
326{
327 out_be16(tmr->gtevr, events);
328}
329EXPORT_SYMBOL(gtm_ack_timer16);
330
331static void __init gtm_set_shortcuts(struct device_node *np,
332 struct gtm_timer *timers,
333 struct gtm_timers_regs __iomem *regs)
334{
335 /*
336 * Yeah, I don't like this either, but timers' registers a bit messed,
337 * so we have to provide shortcuts to write timer independent code.
338 * Alternative option is to create gt*() accessors, but that will be
339 * even uglier and cryptic.
340 */
341 timers[0].gtcfr = &regs->gtcfr1;
342 timers[0].gtmdr = &regs->gtmdr1;
343 timers[0].gtcnr = &regs->gtcnr1;
344 timers[0].gtrfr = &regs->gtrfr1;
345 timers[0].gtevr = &regs->gtevr1;
346
347 timers[1].gtcfr = &regs->gtcfr1;
348 timers[1].gtmdr = &regs->gtmdr2;
349 timers[1].gtcnr = &regs->gtcnr2;
350 timers[1].gtrfr = &regs->gtrfr2;
351 timers[1].gtevr = &regs->gtevr2;
352
353 timers[2].gtcfr = &regs->gtcfr2;
354 timers[2].gtmdr = &regs->gtmdr3;
355 timers[2].gtcnr = &regs->gtcnr3;
356 timers[2].gtrfr = &regs->gtrfr3;
357 timers[2].gtevr = &regs->gtevr3;
358
359 timers[3].gtcfr = &regs->gtcfr2;
360 timers[3].gtmdr = &regs->gtmdr4;
361 timers[3].gtcnr = &regs->gtcnr4;
362 timers[3].gtrfr = &regs->gtrfr4;
363 timers[3].gtevr = &regs->gtevr4;
364
365 /* CPM2 doesn't have primary prescaler */
366 if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
367 timers[0].gtpsr = &regs->gtpsr1;
368 timers[1].gtpsr = &regs->gtpsr2;
369 timers[2].gtpsr = &regs->gtpsr3;
370 timers[3].gtpsr = &regs->gtpsr4;
371 }
372}
373
374static int __init fsl_gtm_init(void)
375{
376 struct device_node *np;
377
378 for_each_compatible_node(np, NULL, "fsl,gtm") {
379 int i;
380 struct gtm *gtm;
381 const u32 *clock;
382 int size;
383
384 gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
385 if (!gtm) {
386 pr_err("%s: unable to allocate memory\n",
387 np->full_name);
388 continue;
389 }
390
391 spin_lock_init(&gtm->lock);
392
393 clock = of_get_property(np, "clock-frequency", &size);
394 if (!clock || size != sizeof(*clock)) {
395 pr_err("%s: no clock-frequency\n", np->full_name);
396 goto err;
397 }
398 gtm->clock = *clock;
399
400 for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
401 int ret;
402 struct resource irq;
403
404 ret = of_irq_to_resource(np, i, &irq);
405 if (ret == NO_IRQ) {
406 pr_err("%s: not enough interrupts specified\n",
407 np->full_name);
408 goto err;
409 }
410 gtm->timers[i].irq = irq.start;
411 gtm->timers[i].gtm = gtm;
412 }
413
414 gtm->regs = of_iomap(np, 0);
415 if (!gtm->regs) {
416 pr_err("%s: unable to iomap registers\n",
417 np->full_name);
418 goto err;
419 }
420
421 gtm_set_shortcuts(np, gtm->timers, gtm->regs);
422 list_add(&gtm->list_node, &gtms);
423
424 /* We don't want to lose the node and its ->data */
425 np->data = gtm;
426 of_node_get(np);
427
428 continue;
429err:
430 kfree(gtm);
431 }
432 return 0;
433}
434arch_initcall(fsl_gtm_init);
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
27struct fsl_msi_feature {
28 u32 fsl_pic_ip;
29 u32 msiir_offset;
30};
31
32static struct fsl_msi *fsl_msi;
33
34static 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*/
43static void fsl_msi_end_irq(unsigned int virq)
44{
45}
46
47static 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
54static 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
66static struct irq_host_ops fsl_msi_host_ops = {
67 .map = fsl_msi_host_map,
68};
69
70static 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
89static 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
102static 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
135static 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;
153out_free:
154 kfree(msi_data->fsl_msi_bitmap);
155
156 msi_data->fsl_msi_bitmap = NULL;
157 return rc;
158
159}
160
161static 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
169static 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
185static 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
198static 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
232out_free:
233 return rc;
234}
235
236static 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 }
296unlock:
297 spin_unlock(&desc->lock);
298}
299
300static 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;
391error_out:
392 kfree(msi);
393 return err;
394}
395
396static const struct fsl_msi_feature mpic_msi_feature = {
397 .fsl_pic_ip = FSL_PIC_IP_MPIC,
398 .msiir_offset = 0x140,
399};
400
401static const struct fsl_msi_feature ipic_msi_feature = {
402 .fsl_pic_ip = FSL_PIC_IP_IPIC,
403 .msiir_offset = 0x38,
404};
405
406static 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
418static 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
424static __init int fsl_of_msi_init(void)
425{
426 return of_register_platform_driver(&fsl_of_msi_driver);
427}
428
429subsys_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
24struct 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..87b0aa13ab48 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
109static 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
109static int fsl_pcie_bus_fixup; 119static int fsl_pcie_bus_fixup;
110 120
111static void __init quirk_fsl_pcie_header(struct pci_dev *dev) 121static 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
@@ -231,6 +243,8 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_header);
231DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header); 243DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header);
232DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header); 244DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header);
233DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header); 245DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header);
246DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536E, quirk_fsl_pcie_header);
247DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
234DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); 248DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
235DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); 249DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
236DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); 250DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 019657c110b6..ebcec7362f95 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -414,128 +414,6 @@ err:
414 414
415arch_initcall(gfar_of_init); 415arch_initcall(gfar_of_init);
416 416
417#ifdef CONFIG_I2C_BOARDINFO
418#include <linux/i2c.h>
419struct i2c_driver_device {
420 char *of_device;
421 char *i2c_type;
422};
423
424static struct i2c_driver_device i2c_devices[] __initdata = {
425 {"ricoh,rs5c372a", "rs5c372a"},
426 {"ricoh,rs5c372b", "rs5c372b"},
427 {"ricoh,rv5c386", "rv5c386"},
428 {"ricoh,rv5c387a", "rv5c387a"},
429 {"dallas,ds1307", "ds1307"},
430 {"dallas,ds1337", "ds1337"},
431 {"dallas,ds1338", "ds1338"},
432 {"dallas,ds1339", "ds1339"},
433 {"dallas,ds1340", "ds1340"},
434 {"stm,m41t00", "m41t00"},
435 {"dallas,ds1374", "ds1374"},
436};
437
438static int __init of_find_i2c_driver(struct device_node *node,
439 struct i2c_board_info *info)
440{
441 int i;
442
443 for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
444 if (!of_device_is_compatible(node, i2c_devices[i].of_device))
445 continue;
446 if (strlcpy(info->type, i2c_devices[i].i2c_type,
447 I2C_NAME_SIZE) >= I2C_NAME_SIZE)
448 return -ENOMEM;
449 return 0;
450 }
451 return -ENODEV;
452}
453
454static void __init of_register_i2c_devices(struct device_node *adap_node,
455 int bus_num)
456{
457 struct device_node *node = NULL;
458
459 while ((node = of_get_next_child(adap_node, node))) {
460 struct i2c_board_info info = {};
461 const u32 *addr;
462 int len;
463
464 addr = of_get_property(node, "reg", &len);
465 if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
466 printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");
467 continue;
468 }
469
470 info.irq = irq_of_parse_and_map(node, 0);
471 if (info.irq == NO_IRQ)
472 info.irq = -1;
473
474 if (of_find_i2c_driver(node, &info) < 0)
475 continue;
476
477 info.addr = *addr;
478
479 i2c_register_board_info(bus_num, &info, 1);
480 }
481}
482
483static int __init fsl_i2c_of_init(void)
484{
485 struct device_node *np;
486 unsigned int i = 0;
487 struct platform_device *i2c_dev;
488 int ret;
489
490 for_each_compatible_node(np, NULL, "fsl-i2c") {
491 struct resource r[2];
492 struct fsl_i2c_platform_data i2c_data;
493 const unsigned char *flags = NULL;
494
495 memset(&r, 0, sizeof(r));
496 memset(&i2c_data, 0, sizeof(i2c_data));
497
498 ret = of_address_to_resource(np, 0, &r[0]);
499 if (ret)
500 goto err;
501
502 of_irq_to_resource(np, 0, &r[1]);
503
504 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
505 if (IS_ERR(i2c_dev)) {
506 ret = PTR_ERR(i2c_dev);
507 goto err;
508 }
509
510 i2c_data.device_flags = 0;
511 flags = of_get_property(np, "dfsrr", NULL);
512 if (flags)
513 i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
514
515 flags = of_get_property(np, "fsl5200-clocking", NULL);
516 if (flags)
517 i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
518
519 ret =
520 platform_device_add_data(i2c_dev, &i2c_data,
521 sizeof(struct
522 fsl_i2c_platform_data));
523 if (ret)
524 goto unreg;
525
526 of_register_i2c_devices(np, i++);
527 }
528
529 return 0;
530
531unreg:
532 platform_device_unregister(i2c_dev);
533err:
534 return ret;
535}
536
537arch_initcall(fsl_i2c_of_init);
538#endif
539 417
540#ifdef CONFIG_PPC_83xx 418#ifdef CONFIG_PPC_83xx
541static int __init mpc83xx_wdt_init(void) 419static int __init mpc83xx_wdt_init(void)
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 216c0f5680d2..a96584ab33dd 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -276,7 +276,7 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
276 spin_unlock_irqrestore(&i8259_lock, flags); 276 spin_unlock_irqrestore(&i8259_lock, flags);
277 277
278 /* create a legacy host */ 278 /* create a legacy host */
279 i8259_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY, 279 i8259_host = irq_alloc_host(node, IRQ_HOST_MAP_LEGACY,
280 0, &i8259_host_ops, 0); 280 0, &i8259_host_ops, 0);
281 if (i8259_host == NULL) { 281 if (i8259_host == NULL) {
282 printk(KERN_ERR "i8259: failed to allocate irq host !\n"); 282 printk(KERN_ERR "i8259: failed to allocate irq host !\n");
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index cfbd2aae93e8..7fd49c97501a 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -123,6 +123,12 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
123 (bus->number == hose->first_busno)) 123 (bus->number == hose->first_busno))
124 val &= 0xffffff00; 124 val &= 0xffffff00;
125 125
126 /* Workaround for PCI_28 Errata in 440EPx/GRx */
127 if ((hose->indirect_type & PPC_INDIRECT_TYPE_BROKEN_MRM) &&
128 offset == PCI_CACHE_LINE_SIZE) {
129 val = 0;
130 }
131
126 /* 132 /*
127 * Note: the caller has already checked that offset is 133 * Note: the caller has already checked that offset is
128 * suitably aligned and that len is 1, 2 or 4. 134 * suitably aligned and that len is 1, 2 or 4.
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 0f2dfb0aaa6a..caba1c0be5a7 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -725,25 +725,21 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
725 struct resource res; 725 struct resource res;
726 u32 temp = 0, ret; 726 u32 temp = 0, ret;
727 727
728 ret = of_address_to_resource(node, 0, &res);
729 if (ret)
730 return NULL;
731
728 ipic = alloc_bootmem(sizeof(struct ipic)); 732 ipic = alloc_bootmem(sizeof(struct ipic));
729 if (ipic == NULL) 733 if (ipic == NULL)
730 return NULL; 734 return NULL;
731 735
732 memset(ipic, 0, sizeof(struct ipic)); 736 memset(ipic, 0, sizeof(struct ipic));
733 737
734 ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 738 ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
735 NR_IPIC_INTS, 739 NR_IPIC_INTS,
736 &ipic_host_ops, 0); 740 &ipic_host_ops, 0);
737 if (ipic->irqhost == NULL) { 741 if (ipic->irqhost == NULL)
738 of_node_put(node);
739 return NULL;
740 }
741
742 ret = of_address_to_resource(node, 0, &res);
743 if (ret) {
744 of_node_put(node);
745 return NULL; 742 return NULL;
746 }
747 743
748 ipic->regs = ioremap(res.start, res.end - res.start + 1); 744 ipic->regs = ioremap(res.start, res.end - res.start + 1);
749 745
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6c90c95b454e..8e3478c995ef 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1016,13 +1016,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1016 memset(mpic, 0, sizeof(struct mpic)); 1016 memset(mpic, 0, sizeof(struct mpic));
1017 mpic->name = name; 1017 mpic->name = name;
1018 1018
1019 mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 1019 mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
1020 isu_size, &mpic_host_ops, 1020 isu_size, &mpic_host_ops,
1021 flags & MPIC_LARGE_VECTORS ? 2048 : 256); 1021 flags & MPIC_LARGE_VECTORS ? 2048 : 256);
1022 if (mpic->irqhost == NULL) { 1022 if (mpic->irqhost == NULL)
1023 of_node_put(node);
1024 return NULL; 1023 return NULL;
1025 }
1026 1024
1027 mpic->irqhost->host_data = mpic; 1025 mpic->irqhost->host_data = mpic;
1028 mpic->hc_irq = mpic_irq_chip; 1026 mpic->hc_irq = mpic_irq_chip;
@@ -1143,10 +1141,14 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1143 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); 1141 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1144 mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK) 1142 mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
1145 >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; 1143 >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
1146 if (isu_size == 0) 1144 if (isu_size == 0) {
1147 mpic->num_sources = 1145 if (flags & MPIC_BROKEN_FRR_NIRQS)
1148 ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) 1146 mpic->num_sources = mpic->irq_count;
1149 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; 1147 else
1148 mpic->num_sources =
1149 ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1150 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
1151 }
1150 1152
1151 /* Map the per-CPU registers */ 1153 /* Map the per-CPU registers */
1152 for (i = 0; i < mpic->num_cpus; i++) { 1154 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
20static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) 21static 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
29static 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}
489arch_initcall(mv64x60_device_setup); 499arch_initcall(mv64x60_device_setup);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index b4a54c52e880..fb368dfde5d4 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -75,6 +75,11 @@ static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
75 !of_device_is_compatible(hose->dn, "ibm,plb-pci")) 75 !of_device_is_compatible(hose->dn, "ibm,plb-pci"))
76 return; 76 return;
77 77
78 if (of_device_is_compatible(hose->dn, "ibm,plb440epx-pci") ||
79 of_device_is_compatible(hose->dn, "ibm,plb440grx-pci")) {
80 hose->indirect_type |= PPC_INDIRECT_TYPE_BROKEN_MRM;
81 }
82
78 /* Hide the PCI host BARs from the kernel as their content doesn't 83 /* Hide the PCI host BARs from the kernel as their content doesn't
79 * fit well in the resource management 84 * fit well in the resource management
80 */ 85 */
@@ -1634,6 +1639,15 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
1634 } 1639 }
1635 port = &ppc4xx_pciex_ports[portno]; 1640 port = &ppc4xx_pciex_ports[portno];
1636 port->index = portno; 1641 port->index = portno;
1642
1643 /*
1644 * Check if device is enabled
1645 */
1646 if (!of_device_is_available(np)) {
1647 printk(KERN_INFO "PCIE%d: Port disabled via device-tree\n", port->index);
1648 return;
1649 }
1650
1637 port->node = of_node_get(np); 1651 port->node = of_node_get(np);
1638 pval = of_get_property(np, "sdr-base", NULL); 1652 pval = of_get_property(np, "sdr-base", NULL);
1639 if (pval == NULL) { 1653 if (pval == NULL) {
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index adc66212a419..4bb18f57901e 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -20,3 +20,16 @@ config UCC
20 bool 20 bool
21 default y if UCC_FAST || UCC_SLOW 21 default y if UCC_FAST || UCC_SLOW
22 22
23config QE_USB
24 bool
25 help
26 QE USB Host Controller support
27
28config QE_GPIO
29 bool "QE GPIO support"
30 depends on QUICC_ENGINE
31 select GENERIC_GPIO
32 select HAVE_GPIO_LIB
33 help
34 Say Y here if you're going to use hardware that connects to the
35 QE GPIOs.
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 874fe1a5b1cf..f1855c185291 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
6obj-$(CONFIG_UCC) += ucc.o 6obj-$(CONFIG_UCC) += ucc.o
7obj-$(CONFIG_UCC_SLOW) += ucc_slow.o 7obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
8obj-$(CONFIG_UCC_FAST) += ucc_fast.o 8obj-$(CONFIG_UCC_FAST) += ucc_fast.o
9obj-$(CONFIG_QE_USB) += usb.o
10obj-$(CONFIG_QE_GPIO) += gpio.o
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
new file mode 100644
index 000000000000..8e5a0bc36d0b
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -0,0 +1,149 @@
1/*
2 * QUICC Engine GPIOs
3 *
4 * Copyright (c) MontaVista Software, Inc. 2008.
5 *
6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/spinlock.h>
17#include <linux/io.h>
18#include <linux/of.h>
19#include <linux/of_gpio.h>
20#include <linux/gpio.h>
21#include <asm/qe.h>
22
23struct qe_gpio_chip {
24 struct of_mm_gpio_chip mm_gc;
25 spinlock_t lock;
26
27 /* shadowed data register to clear/set bits safely */
28 u32 cpdata;
29};
30
31static inline struct qe_gpio_chip *
32to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc)
33{
34 return container_of(mm_gc, struct qe_gpio_chip, mm_gc);
35}
36
37static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
38{
39 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
40 struct qe_pio_regs __iomem *regs = mm_gc->regs;
41
42 qe_gc->cpdata = in_be32(&regs->cpdata);
43}
44
45static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
46{
47 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
48 struct qe_pio_regs __iomem *regs = mm_gc->regs;
49 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
50
51 return in_be32(&regs->cpdata) & pin_mask;
52}
53
54static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
55{
56 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
57 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
58 struct qe_pio_regs __iomem *regs = mm_gc->regs;
59 unsigned long flags;
60 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
61
62 spin_lock_irqsave(&qe_gc->lock, flags);
63
64 if (val)
65 qe_gc->cpdata |= pin_mask;
66 else
67 qe_gc->cpdata &= ~pin_mask;
68
69 out_be32(&regs->cpdata, qe_gc->cpdata);
70
71 spin_unlock_irqrestore(&qe_gc->lock, flags);
72}
73
74static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
75{
76 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
77 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
78 unsigned long flags;
79
80 spin_lock_irqsave(&qe_gc->lock, flags);
81
82 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0);
83
84 spin_unlock_irqrestore(&qe_gc->lock, flags);
85
86 return 0;
87}
88
89static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
90{
91 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
92 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
93 unsigned long flags;
94
95 spin_lock_irqsave(&qe_gc->lock, flags);
96
97 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
98
99 spin_unlock_irqrestore(&qe_gc->lock, flags);
100
101 qe_gpio_set(gc, gpio, val);
102
103 return 0;
104}
105
106static int __init qe_add_gpiochips(void)
107{
108 struct device_node *np;
109
110 for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
111 int ret;
112 struct qe_gpio_chip *qe_gc;
113 struct of_mm_gpio_chip *mm_gc;
114 struct of_gpio_chip *of_gc;
115 struct gpio_chip *gc;
116
117 qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
118 if (!qe_gc) {
119 ret = -ENOMEM;
120 goto err;
121 }
122
123 spin_lock_init(&qe_gc->lock);
124
125 mm_gc = &qe_gc->mm_gc;
126 of_gc = &mm_gc->of_gc;
127 gc = &of_gc->gc;
128
129 mm_gc->save_regs = qe_gpio_save_regs;
130 of_gc->gpio_cells = 2;
131 gc->ngpio = QE_PIO_PINS;
132 gc->direction_input = qe_gpio_dir_in;
133 gc->direction_output = qe_gpio_dir_out;
134 gc->get = qe_gpio_get;
135 gc->set = qe_gpio_set;
136
137 ret = of_mm_gpiochip_add(np, mm_gc);
138 if (ret)
139 goto err;
140 continue;
141err:
142 pr_err("%s: registration failed with status %d\n",
143 np->full_name, ret);
144 kfree(qe_gc);
145 /* try others anyway */
146 }
147 return 0;
148}
149arch_initcall(qe_add_gpiochips);
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index cff550eec7e8..9e82d7e725a5 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -35,7 +35,6 @@
35#include <asm/rheap.h> 35#include <asm/rheap.h>
36 36
37static void qe_snums_init(void); 37static void qe_snums_init(void);
38static void qe_muram_init(void);
39static int qe_sdma_init(void); 38static int qe_sdma_init(void);
40 39
41static DEFINE_SPINLOCK(qe_lock); 40static DEFINE_SPINLOCK(qe_lock);
@@ -88,7 +87,7 @@ phys_addr_t get_qe_base(void)
88 87
89EXPORT_SYMBOL(get_qe_base); 88EXPORT_SYMBOL(get_qe_base);
90 89
91void qe_reset(void) 90void __init qe_reset(void)
92{ 91{
93 if (qe_immr == NULL) 92 if (qe_immr == NULL)
94 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE); 93 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
@@ -325,97 +324,6 @@ static int qe_sdma_init(void)
325 return 0; 324 return 0;
326} 325}
327 326
328/*
329 * muram_alloc / muram_free bits.
330 */
331static DEFINE_SPINLOCK(qe_muram_lock);
332
333/* 16 blocks should be enough to satisfy all requests
334 * until the memory subsystem goes up... */
335static rh_block_t qe_boot_muram_rh_block[16];
336static rh_info_t qe_muram_info;
337
338static void qe_muram_init(void)
339{
340 struct device_node *np;
341 const u32 *address;
342 u64 size;
343 unsigned int flags;
344
345 /* initialize the info header */
346 rh_init(&qe_muram_info, 1,
347 sizeof(qe_boot_muram_rh_block) /
348 sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
349
350 /* Attach the usable muram area */
351 /* XXX: This is a subset of the available muram. It
352 * varies with the processor and the microcode patches activated.
353 */
354 np = of_find_compatible_node(NULL, NULL, "fsl,qe-muram-data");
355 if (!np) {
356 np = of_find_node_by_name(NULL, "data-only");
357 if (!np) {
358 WARN_ON(1);
359 return;
360 }
361 }
362
363 address = of_get_address(np, 0, &size, &flags);
364 WARN_ON(!address);
365
366 of_node_put(np);
367 if (address)
368 rh_attach_region(&qe_muram_info, *address, (int)size);
369}
370
371/* This function returns an index into the MURAM area.
372 */
373unsigned long qe_muram_alloc(int size, int align)
374{
375 unsigned long start;
376 unsigned long flags;
377
378 spin_lock_irqsave(&qe_muram_lock, flags);
379 start = rh_alloc_align(&qe_muram_info, size, align, "QE");
380 spin_unlock_irqrestore(&qe_muram_lock, flags);
381
382 return start;
383}
384EXPORT_SYMBOL(qe_muram_alloc);
385
386int qe_muram_free(unsigned long offset)
387{
388 int ret;
389 unsigned long flags;
390
391 spin_lock_irqsave(&qe_muram_lock, flags);
392 ret = rh_free(&qe_muram_info, offset);
393 spin_unlock_irqrestore(&qe_muram_lock, flags);
394
395 return ret;
396}
397EXPORT_SYMBOL(qe_muram_free);
398
399/* not sure if this is ever needed */
400unsigned long qe_muram_alloc_fixed(unsigned long offset, int size)
401{
402 unsigned long start;
403 unsigned long flags;
404
405 spin_lock_irqsave(&qe_muram_lock, flags);
406 start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc");
407 spin_unlock_irqrestore(&qe_muram_lock, flags);
408
409 return start;
410}
411EXPORT_SYMBOL(qe_muram_alloc_fixed);
412
413void qe_muram_dump(void)
414{
415 rh_dump(&qe_muram_info);
416}
417EXPORT_SYMBOL(qe_muram_dump);
418
419/* The maximum number of RISCs we support */ 327/* The maximum number of RISCs we support */
420#define MAX_QE_RISC 2 328#define MAX_QE_RISC 2
421 329
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index f59444d3be75..63cdf9887f36 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -329,21 +329,19 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
329 struct resource res; 329 struct resource res;
330 u32 temp = 0, ret, high_active = 0; 330 u32 temp = 0, ret, high_active = 0;
331 331
332 ret = of_address_to_resource(node, 0, &res);
333 if (ret)
334 return;
335
332 qe_ic = alloc_bootmem(sizeof(struct qe_ic)); 336 qe_ic = alloc_bootmem(sizeof(struct qe_ic));
333 if (qe_ic == NULL) 337 if (qe_ic == NULL)
334 return; 338 return;
335 339
336 memset(qe_ic, 0, sizeof(struct qe_ic)); 340 memset(qe_ic, 0, sizeof(struct qe_ic));
337 341
338 qe_ic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 342 qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
339 NR_QE_IC_INTS, &qe_ic_host_ops, 0); 343 NR_QE_IC_INTS, &qe_ic_host_ops, 0);
340 if (qe_ic->irqhost == NULL) { 344 if (qe_ic->irqhost == NULL)
341 of_node_put(node);
342 return;
343 }
344
345 ret = of_address_to_resource(node, 0, &res);
346 if (ret)
347 return; 345 return;
348 346
349 qe_ic->regs = ioremap(res.start, res.end - res.start + 1); 347 qe_ic->regs = ioremap(res.start, res.end - res.start + 1);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 93916a48afec..7c87460179ef 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -28,21 +28,7 @@
28 28
29#undef DEBUG 29#undef DEBUG
30 30
31#define NUM_OF_PINS 32 31static struct qe_pio_regs __iomem *par_io;
32
33struct port_regs {
34 __be32 cpodr; /* Open drain register */
35 __be32 cpdata; /* Data register */
36 __be32 cpdir1; /* Direction register */
37 __be32 cpdir2; /* Direction register */
38 __be32 cppar1; /* Pin assignment register */
39 __be32 cppar2; /* Pin assignment register */
40#ifdef CONFIG_PPC_85xx
41 u8 pad[8];
42#endif
43};
44
45static struct port_regs __iomem *par_io;
46static int num_par_io_ports = 0; 32static int num_par_io_ports = 0;
47 33
48int par_io_init(struct device_node *np) 34int par_io_init(struct device_node *np)
@@ -64,69 +50,79 @@ int par_io_init(struct device_node *np)
64 return 0; 50 return 0;
65} 51}
66 52
67int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, 53void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
68 int assignment, int has_irq) 54 int open_drain, int assignment, int has_irq)
69{ 55{
70 u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val; 56 u32 pin_mask1bit;
71 57 u32 pin_mask2bits;
72 if (!par_io) 58 u32 new_mask2bits;
73 return -1; 59 u32 tmp_val;
74 60
75 /* calculate pin location for single and 2 bits information */ 61 /* calculate pin location for single and 2 bits information */
76 pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1))); 62 pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
77 63
78 /* Set open drain, if required */ 64 /* Set open drain, if required */
79 tmp_val = in_be32(&par_io[port].cpodr); 65 tmp_val = in_be32(&par_io->cpodr);
80 if (open_drain) 66 if (open_drain)
81 out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val); 67 out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
82 else 68 else
83 out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val); 69 out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
84 70
85 /* define direction */ 71 /* define direction */
86 tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ? 72 tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
87 in_be32(&par_io[port].cpdir2) : 73 in_be32(&par_io->cpdir2) :
88 in_be32(&par_io[port].cpdir1); 74 in_be32(&par_io->cpdir1);
89 75
90 /* get all bits mask for 2 bit per port */ 76 /* get all bits mask for 2 bit per port */
91 pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS - 77 pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
92 (pin % (NUM_OF_PINS / 2) + 1) * 2)); 78 (pin % (QE_PIO_PINS / 2) + 1) * 2));
93 79
94 /* Get the final mask we need for the right definition */ 80 /* Get the final mask we need for the right definition */
95 new_mask2bits = (u32) (dir << (NUM_OF_PINS - 81 new_mask2bits = (u32) (dir << (QE_PIO_PINS -
96 (pin % (NUM_OF_PINS / 2) + 1) * 2)); 82 (pin % (QE_PIO_PINS / 2) + 1) * 2));
97 83
98 /* clear and set 2 bits mask */ 84 /* clear and set 2 bits mask */
99 if (pin > (NUM_OF_PINS / 2) - 1) { 85 if (pin > (QE_PIO_PINS / 2) - 1) {
100 out_be32(&par_io[port].cpdir2, 86 out_be32(&par_io->cpdir2,
101 ~pin_mask2bits & tmp_val); 87 ~pin_mask2bits & tmp_val);
102 tmp_val &= ~pin_mask2bits; 88 tmp_val &= ~pin_mask2bits;
103 out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val); 89 out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
104 } else { 90 } else {
105 out_be32(&par_io[port].cpdir1, 91 out_be32(&par_io->cpdir1,
106 ~pin_mask2bits & tmp_val); 92 ~pin_mask2bits & tmp_val);
107 tmp_val &= ~pin_mask2bits; 93 tmp_val &= ~pin_mask2bits;
108 out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val); 94 out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
109 } 95 }
110 /* define pin assignment */ 96 /* define pin assignment */
111 tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ? 97 tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
112 in_be32(&par_io[port].cppar2) : 98 in_be32(&par_io->cppar2) :
113 in_be32(&par_io[port].cppar1); 99 in_be32(&par_io->cppar1);
114 100
115 new_mask2bits = (u32) (assignment << (NUM_OF_PINS - 101 new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
116 (pin % (NUM_OF_PINS / 2) + 1) * 2)); 102 (pin % (QE_PIO_PINS / 2) + 1) * 2));
117 /* clear and set 2 bits mask */ 103 /* clear and set 2 bits mask */
118 if (pin > (NUM_OF_PINS / 2) - 1) { 104 if (pin > (QE_PIO_PINS / 2) - 1) {
119 out_be32(&par_io[port].cppar2, 105 out_be32(&par_io->cppar2,
120 ~pin_mask2bits & tmp_val); 106 ~pin_mask2bits & tmp_val);
121 tmp_val &= ~pin_mask2bits; 107 tmp_val &= ~pin_mask2bits;
122 out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val); 108 out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
123 } else { 109 } else {
124 out_be32(&par_io[port].cppar1, 110 out_be32(&par_io->cppar1,
125 ~pin_mask2bits & tmp_val); 111 ~pin_mask2bits & tmp_val);
126 tmp_val &= ~pin_mask2bits; 112 tmp_val &= ~pin_mask2bits;
127 out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val); 113 out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
128 } 114 }
115}
116EXPORT_SYMBOL(__par_io_config_pin);
117
118int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
119 int assignment, int has_irq)
120{
121 if (!par_io || port >= num_par_io_ports)
122 return -EINVAL;
129 123
124 __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
125 has_irq);
130 return 0; 126 return 0;
131} 127}
132EXPORT_SYMBOL(par_io_config_pin); 128EXPORT_SYMBOL(par_io_config_pin);
@@ -137,10 +133,10 @@ int par_io_data_set(u8 port, u8 pin, u8 val)
137 133
138 if (port >= num_par_io_ports) 134 if (port >= num_par_io_ports)
139 return -EINVAL; 135 return -EINVAL;
140 if (pin >= NUM_OF_PINS) 136 if (pin >= QE_PIO_PINS)
141 return -EINVAL; 137 return -EINVAL;
142 /* calculate pin location */ 138 /* calculate pin location */
143 pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin)); 139 pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
144 140
145 tmp_val = in_be32(&par_io[port].cpdata); 141 tmp_val = in_be32(&par_io[port].cpdata);
146 142
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 0e348d9af8a6..d3c7f5af9bc8 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -26,7 +26,8 @@
26#include <asm/qe.h> 26#include <asm/qe.h>
27#include <asm/ucc.h> 27#include <asm/ucc.h>
28 28
29static DEFINE_SPINLOCK(ucc_lock); 29DEFINE_SPINLOCK(cmxgcr_lock);
30EXPORT_SYMBOL(cmxgcr_lock);
30 31
31int ucc_set_qe_mux_mii_mng(unsigned int ucc_num) 32int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
32{ 33{
@@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
35 if (ucc_num > UCC_MAX_NUM - 1) 36 if (ucc_num > UCC_MAX_NUM - 1)
36 return -EINVAL; 37 return -EINVAL;
37 38
38 spin_lock_irqsave(&ucc_lock, flags); 39 spin_lock_irqsave(&cmxgcr_lock, flags);
39 clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG, 40 clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
40 ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT); 41 ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
41 spin_unlock_irqrestore(&ucc_lock, flags); 42 spin_unlock_irqrestore(&cmxgcr_lock, flags);
42 43
43 return 0; 44 return 0;
44} 45}
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c
new file mode 100644
index 000000000000..8105462078eb
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/usb.c
@@ -0,0 +1,55 @@
1/*
2 * QE USB routines
3 *
4 * Copyright (c) Freescale Semicondutor, Inc. 2006.
5 * Shlomi Gridish <gridish@freescale.com>
6 * Jerry Huang <Chang-Ming.Huang@freescale.com>
7 * Copyright (c) MontaVista Software, Inc. 2008.
8 * Anton Vorontsov <avorontsov@ru.mvista.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/io.h>
19#include <asm/immap_qe.h>
20#include <asm/qe.h>
21
22int qe_usb_clock_set(enum qe_clock clk, int rate)
23{
24 struct qe_mux __iomem *mux = &qe_immr->qmx;
25 unsigned long flags;
26 u32 val;
27
28 switch (clk) {
29 case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
30 case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
31 case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
32 case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
33 case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
34 case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
35 case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
36 case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
37 case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
38 case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
39 default:
40 pr_err("%s: requested unknown clock %d\n", __func__, clk);
41 return -EINVAL;
42 }
43
44 if (qe_clock_is_brg(clk))
45 qe_setbrg(clk, rate, 1);
46
47 spin_lock_irqsave(&cmxgcr_lock, flags);
48
49 clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
50
51 spin_unlock_irqrestore(&cmxgcr_lock, flags);
52
53 return 0;
54}
55EXPORT_SYMBOL(qe_usb_clock_set);
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index ac1a72dc21e5..24e1f5a197ae 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -426,11 +426,10 @@ void __init tsi108_pci_int_init(struct device_node *node)
426{ 426{
427 DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); 427 DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
428 428
429 pci_irq_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY, 429 pci_irq_host = irq_alloc_host(node, IRQ_HOST_MAP_LEGACY,
430 0, &pci_irq_host_ops, 0); 430 0, &pci_irq_host_ops, 0);
431 if (pci_irq_host == NULL) { 431 if (pci_irq_host == NULL) {
432 printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n"); 432 printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n");
433 of_node_put(node);
434 return; 433 return;
435 } 434 }
436 435
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 625b275c3795..d35405c59434 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -280,12 +280,10 @@ static struct uic * __init uic_init_one(struct device_node *node)
280 } 280 }
281 uic->dcrbase = *dcrreg; 281 uic->dcrbase = *dcrreg;
282 282
283 uic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, 283 uic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
284 NR_UIC_INTS, &uic_host_ops, -1); 284 NR_UIC_INTS, &uic_host_ops, -1);
285 if (! uic->irqhost) { 285 if (! uic->irqhost)
286 of_node_put(node);
287 return NULL; /* FIXME: panic? */ 286 return NULL; /* FIXME: panic? */
288 }
289 287
290 uic->irqhost->host_data = uic; 288 uic->irqhost->host_data = uic;
291 289