summaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 10:15:40 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 10:15:40 -0700
commitbac65d9d87b383471d8d29128319508d71b74180 (patch)
treec087cca1f1db1045cce08a3bff7c775c66e437bf /arch/powerpc/sysdev
parentf92e3da18b7d5941468040af962c201235148301 (diff)
parent265601f034df3566f22da11240977aab8860f6a7 (diff)
Merge tag 'powerpc-4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman: "Nothing really major this release, despite quite a lot of activity. Just lots of things all over the place. Some things of note include: - Access via perf to a new type of PMU (IMC) on Power9, which can count both core events as well as nest unit events (Memory controller etc). - Optimisations to the radix MMU TLB flushing, mostly to avoid unnecessary Page Walk Cache (PWC) flushes when the structure of the tree is not changing. - Reworks/cleanups of do_page_fault() to modernise it and bring it closer to other architectures where possible. - Rework of our page table walking so that THP updates only need to send IPIs to CPUs where the affected mm has run, rather than all CPUs. - The size of our vmalloc area is increased to 56T on 64-bit hash MMU systems. This avoids problems with the percpu allocator on systems with very sparse NUMA layouts. - STRICT_KERNEL_RWX support on PPC32. - A new sched domain topology for Power9, to capture the fact that pairs of cores may share an L2 cache. - Power9 support for VAS, which is a new mechanism for accessing coprocessors, and initial support for using it with the NX compression accelerator. - Major work on the instruction emulation support, adding support for many new instructions, and reworking it so it can be used to implement the emulation needed to fixup alignment faults. - Support for guests under PowerVM to use the Power9 XIVE interrupt controller. And probably that many things again that are almost as interesting, but I had to keep the list short. Plus the usual fixes and cleanups as always. Thanks to: Alexey Kardashevskiy, Alistair Popple, Andreas Schwab, Aneesh Kumar K.V, Anju T Sudhakar, Arvind Yadav, Balbir Singh, Benjamin Herrenschmidt, Bhumika Goyal, Breno Leitao, Bryant G. Ly, Christophe Leroy, Cédric Le Goater, Dan Carpenter, Dou Liyang, Frederic Barrat, Gautham R. Shenoy, Geliang Tang, Geoff Levand, Hannes Reinecke, Haren Myneni, Ivan Mikhaylov, John Allen, Julia Lawall, LABBE Corentin, Laurentiu Tudor, Madhavan Srinivasan, Markus Elfring, Masahiro Yamada, Matt Brown, Michael Neuling, Murilo Opsfelder Araujo, Nathan Fontenot, Naveen N. Rao, Nicholas Piggin, Oliver O'Halloran, Paul Mackerras, Rashmica Gupta, Rob Herring, Rui Teng, Sam Bobroff, Santosh Sivaraj, Scott Wood, Shilpasri G Bhat, Sukadev Bhattiprolu, Suraj Jitindar Singh, Tobin C. Harding, Victor Aoqui" * tag 'powerpc-4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (321 commits) powerpc/xive: Fix section __init warning powerpc: Fix kernel crash in emulation of vector loads and stores powerpc/xive: improve debugging macros powerpc/xive: add XIVE Exploitation Mode to CAS powerpc/xive: introduce H_INT_ESB hcall powerpc/xive: add the HW IRQ number under xive_irq_data powerpc/xive: introduce xive_esb_write() powerpc/xive: rename xive_poke_esb() in xive_esb_read() powerpc/xive: guest exploitation of the XIVE interrupt controller powerpc/xive: introduce a common routine xive_queue_page_alloc() powerpc/sstep: Avoid used uninitialized error axonram: Return directly after a failed kzalloc() in axon_ram_probe() axonram: Improve a size determination in axon_ram_probe() axonram: Delete an error message for a failed memory allocation in axon_ram_probe() powerpc/powernv/npu: Move tlb flush before launching ATSD powerpc/macintosh: constify wf_sensor_ops structures powerpc/iommu: Use permission-specific DEVICE_ATTR variants powerpc/eeh: Delete an error out of memory message at init time powerpc/mm: Use seq_putc() in two functions macintosh: Convert to using %pOF instead of full_name ...
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile12
-rw-r--r--arch/powerpc/sysdev/axonram.c46
-rw-r--r--arch/powerpc/sysdev/dcr.c4
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_cache_sram.c12
-rw-r--r--arch/powerpc/sysdev/fsl_gtm.c14
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c16
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c47
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c36
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c12
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h2
-rw-r--r--arch/powerpc/sysdev/ipic.c1
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c163
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.h19
-rw-r--r--arch/powerpc/sysdev/mpic.c4
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c2
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c2
-rw-r--r--arch/powerpc/sysdev/mpic_timer.c19
-rw-r--r--arch/powerpc/sysdev/msi_bitmap.c4
-rw-r--r--arch/powerpc/sysdev/mv64x60_dev.c20
-rw-r--r--arch/powerpc/sysdev/mv64x60_pci.c6
-rw-r--r--arch/powerpc/sysdev/of_rtc.c12
-rw-r--r--arch/powerpc/sysdev/ppc4xx_cpm.c346
-rw-r--r--arch/powerpc/sysdev/ppc4xx_gpio.c208
-rw-r--r--arch/powerpc/sysdev/ppc4xx_hsta_msi.c212
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c286
-rw-r--r--arch/powerpc/sysdev/ppc4xx_ocm.c416
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c2202
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.h505
-rw-r--r--arch/powerpc/sysdev/ppc4xx_soc.c222
-rw-r--r--arch/powerpc/sysdev/scom.c5
-rw-r--r--arch/powerpc/sysdev/simple_gpio.c3
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c4
-rw-r--r--arch/powerpc/sysdev/uic.c334
-rw-r--r--arch/powerpc/sysdev/xive/Kconfig5
-rw-r--r--arch/powerpc/sysdev/xive/Makefile1
-rw-r--r--arch/powerpc/sysdev/xive/common.c90
-rw-r--r--arch/powerpc/sysdev/xive/native.c22
-rw-r--r--arch/powerpc/sysdev/xive/spapr.c662
-rw-r--r--arch/powerpc/sysdev/xive/xive-internal.h7
40 files changed, 887 insertions, 5098 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index c0ae11d4f62f..79416fa2e3ba 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -36,25 +36,15 @@ obj-$(CONFIG_AXON_RAM) += axonram.o
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_IPIC) += ipic.o
-obj-$(CONFIG_4xx) += uic.o
-obj-$(CONFIG_PPC4xx_OCM) += ppc4xx_ocm.o
-obj-$(CONFIG_4xx_SOC) += ppc4xx_soc.o
obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o
obj-$(CONFIG_XILINX_PCI) += xilinx_pci.o
obj-$(CONFIG_OF_RTC) += of_rtc.o
-ifeq ($(CONFIG_PCI),y)
-obj-$(CONFIG_4xx) += ppc4xx_pci.o
-endif
-obj-$(CONFIG_PPC4xx_HSTA_MSI) += ppc4xx_hsta_msi.o
-obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o
-obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o
-obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
obj-$(CONFIG_CPM) += cpm_common.o
+obj-$(CONFIG_CPM1) += cpm1.o
obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o
obj-$(CONFIG_QUICC_ENGINE) += cpm_common.o
obj-$(CONFIG_PPC_DCR) += dcr.o
-obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
obj-$(CONFIG_PPC_MPC512x) += mpc5xxx_clocks.o
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 2799706106c6..58507c3fbcd0 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -188,15 +188,12 @@ static int axon_ram_probe(struct platform_device *device)
axon_ram_bank_id++;
- dev_info(&device->dev, "Found memory controller on %s\n",
- device->dev.of_node->full_name);
+ dev_info(&device->dev, "Found memory controller on %pOF\n",
+ device->dev.of_node);
- bank = kzalloc(sizeof(struct axon_ram_bank), GFP_KERNEL);
- if (bank == NULL) {
- dev_err(&device->dev, "Out of memory\n");
- rc = -ENOMEM;
- goto failed;
- }
+ bank = kzalloc(sizeof(*bank), GFP_KERNEL);
+ if (!bank)
+ return -ENOMEM;
device->dev.platform_data = bank;
@@ -292,25 +289,22 @@ static int axon_ram_probe(struct platform_device *device)
return 0;
failed:
- if (bank != NULL) {
- if (bank->irq_id)
- free_irq(bank->irq_id, device);
- if (bank->disk != NULL) {
- if (bank->disk->major > 0)
- unregister_blkdev(bank->disk->major,
- bank->disk->disk_name);
- if (bank->disk->flags & GENHD_FL_UP)
- del_gendisk(bank->disk);
- put_disk(bank->disk);
- }
- kill_dax(bank->dax_dev);
- put_dax(bank->dax_dev);
- device->dev.platform_data = NULL;
- if (bank->io_addr != 0)
- iounmap((void __iomem *) bank->io_addr);
- kfree(bank);
+ if (bank->irq_id)
+ free_irq(bank->irq_id, device);
+ if (bank->disk != NULL) {
+ if (bank->disk->major > 0)
+ unregister_blkdev(bank->disk->major,
+ bank->disk->disk_name);
+ if (bank->disk->flags & GENHD_FL_UP)
+ del_gendisk(bank->disk);
+ put_disk(bank->disk);
}
-
+ kill_dax(bank->dax_dev);
+ put_dax(bank->dax_dev);
+ device->dev.platform_data = NULL;
+ if (bank->io_addr != 0)
+ iounmap((void __iomem *) bank->io_addr);
+ kfree(bank);
return rc;
}
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 121e26fffd50..d72eda568b7d 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -195,8 +195,8 @@ dcr_host_mmio_t dcr_map_mmio(struct device_node *dev,
dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
u64 addr;
- pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
- dev->full_name, dcr_n, dcr_c);
+ pr_debug("dcr_map(%pOF, 0x%x, 0x%x)\n",
+ dev, dcr_n, dcr_c);
addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
pr_debug("translates to addr: 0x%llx, stride: 0x%x\n",
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
index 37a69097e022..00ccf3e4fcb4 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -101,8 +101,8 @@ int __init instantiate_cache_sram(struct platform_device *dev,
if (!request_mem_region(cache_sram->base_phys, cache_sram->size,
"fsl_85xx_cache_sram")) {
- dev_err(&dev->dev, "%s: request memory failed\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "%pOF: request memory failed\n",
+ dev->dev.of_node);
ret = -ENXIO;
goto out_free;
}
@@ -110,16 +110,16 @@ int __init instantiate_cache_sram(struct platform_device *dev,
cache_sram->base_virt = ioremap_prot(cache_sram->base_phys,
cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL);
if (!cache_sram->base_virt) {
- dev_err(&dev->dev, "%s: ioremap_prot failed\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "%pOF: ioremap_prot failed\n",
+ dev->dev.of_node);
ret = -ENOMEM;
goto out_release;
}
cache_sram->rh = rh_create(sizeof(unsigned int));
if (IS_ERR(cache_sram->rh)) {
- dev_err(&dev->dev, "%s: Unable to create remote heap\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "%pOF: Unable to create remote heap\n",
+ dev->dev.of_node);
ret = PTR_ERR(cache_sram->rh);
goto out_unmap;
}
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index a6f0b96ce2c9..d902306f4718 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -388,8 +388,8 @@ static int __init fsl_gtm_init(void)
gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
if (!gtm) {
- pr_err("%s: unable to allocate memory\n",
- np->full_name);
+ pr_err("%pOF: unable to allocate memory\n",
+ np);
continue;
}
@@ -397,7 +397,7 @@ static int __init fsl_gtm_init(void)
clock = of_get_property(np, "clock-frequency", &size);
if (!clock || size != sizeof(*clock)) {
- pr_err("%s: no clock-frequency\n", np->full_name);
+ pr_err("%pOF: no clock-frequency\n", np);
goto err;
}
gtm->clock = *clock;
@@ -407,8 +407,8 @@ static int __init fsl_gtm_init(void)
irq = irq_of_parse_and_map(np, i);
if (!irq) {
- pr_err("%s: not enough interrupts specified\n",
- np->full_name);
+ pr_err("%pOF: not enough interrupts specified\n",
+ np);
goto err;
}
gtm->timers[i].irq = irq;
@@ -417,8 +417,8 @@ static int __init fsl_gtm_init(void)
gtm->regs = of_iomap(np, 0);
if (!gtm->regs) {
- pr_err("%s: unable to iomap registers\n",
- np->full_name);
+ pr_err("%pOF: unable to iomap registers\n",
+ np);
goto err;
}
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 8a244828782e..44cbf4c12ea1 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -214,8 +214,8 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
phandle = np->phandle;
else {
dev_err(&pdev->dev,
- "node %s has an invalid fsl,msi phandle %u\n",
- hose->dn->full_name, np->phandle);
+ "node %pOF has an invalid fsl,msi phandle %u\n",
+ hose->dn, np->phandle);
return -EINVAL;
}
}
@@ -438,16 +438,16 @@ static int fsl_of_msi_probe(struct platform_device *dev)
if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC) {
err = of_address_to_resource(dev->dev.of_node, 0, &res);
if (err) {
- dev_err(&dev->dev, "invalid resource for node %s\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "invalid resource for node %pOF\n",
+ dev->dev.of_node);
goto error_out;
}
msi->msi_regs = ioremap(res.start, resource_size(&res));
if (!msi->msi_regs) {
err = -ENOMEM;
- dev_err(&dev->dev, "could not map node %s\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "could not map node %pOF\n",
+ dev->dev.of_node);
goto error_out;
}
msi->msiir_offset =
@@ -522,8 +522,8 @@ static int fsl_of_msi_probe(struct platform_device *dev)
for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
if (p[i * 2] % IRQS_PER_MSI_REG ||
p[i * 2 + 1] % IRQS_PER_MSI_REG) {
- pr_warn("%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
- __func__, dev->dev.of_node->full_name,
+ pr_warn("%s: %pOF: msi available range of %u at %u is not IRQ-aligned\n",
+ __func__, dev->dev.of_node,
p[i * 2 + 1], p[i * 2]);
err = -EINVAL;
goto error_out;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index d3a597456b6e..22d98057f773 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -202,7 +202,6 @@ static void setup_pci_atmu(struct pci_controller *hose)
u32 pcicsrbar = 0, pcicsrbar_sz;
u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
- const char *name = hose->dn->full_name;
const u64 *reg;
int len;
bool setup_inbound;
@@ -290,12 +289,12 @@ static void setup_pci_atmu(struct pci_controller *hose)
paddr_lo -= offset;
if (paddr_hi == paddr_lo) {
- pr_err("%s: No outbound window space\n", name);
+ pr_err("%pOF: No outbound window space\n", hose->dn);
return;
}
if (paddr_lo == 0) {
- pr_err("%s: No space for inbound window\n", name);
+ pr_err("%pOF: No space for inbound window\n", hose->dn);
return;
}
@@ -313,7 +312,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
paddr_lo = min(paddr_lo, (u64)pcicsrbar);
- pr_info("%s: PCICSRBAR @ 0x%x\n", name, pcicsrbar);
+ pr_info("%pOF: PCICSRBAR @ 0x%x\n", hose->dn, pcicsrbar);
/* Setup inbound mem window */
mem = memblock_end_of_DRAM();
@@ -336,12 +335,12 @@ static void setup_pci_atmu(struct pci_controller *hose)
u64 address = be64_to_cpup(reg);
if ((address >= mem) && (address < (mem + PAGE_SIZE))) {
- pr_info("%s: extending DDR ATMU to cover MSIIR", name);
+ pr_info("%pOF: extending DDR ATMU to cover MSIIR", hose->dn);
mem += PAGE_SIZE;
} else {
/* TODO: Create a new ATMU for MSIIR */
- pr_warn("%s: msi-address-64 address of %llx is "
- "unsupported\n", name, address);
+ pr_warn("%pOF: msi-address-64 address of %llx is "
+ "unsupported\n", hose->dn, address);
}
}
@@ -354,8 +353,8 @@ static void setup_pci_atmu(struct pci_controller *hose)
if ((1ull << mem_log) != mem) {
mem_log++;
if ((1ull << mem_log) > mem)
- pr_info("%s: Setting PCI inbound window "
- "greater than memory size\n", name);
+ pr_info("%pOF: Setting PCI inbound window "
+ "greater than memory size\n", hose->dn);
}
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
@@ -402,7 +401,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
*/
ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
- pr_info("%s: Setup 64-bit PCI DMA window\n", name);
+ pr_info("%pOF: Setup 64-bit PCI DMA window\n", hose->dn);
}
} else {
u64 paddr = 0;
@@ -443,18 +442,18 @@ static void setup_pci_atmu(struct pci_controller *hose)
#ifdef CONFIG_SWIOTLB
ppc_swiotlb_enable = 1;
#else
- pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to "
+ pr_err("%pOF: ERROR: Memory size exceeds PCI ATMU ability to "
"map - enable CONFIG_SWIOTLB to avoid dma errors.\n",
- name);
+ hose->dn);
#endif
/* adjusting outbound windows could reclaim space in mem map */
if (paddr_hi < 0xffffffffull)
- pr_warning("%s: WARNING: Outbound window cfg leaves "
+ pr_warning("%pOF: WARNING: Outbound window cfg leaves "
"gaps in memory map. Adjusting the memory map "
"could reduce unnecessary bounce buffering.\n",
- name);
+ hose->dn);
- pr_info("%s: DMA window size is 0x%llx\n", name,
+ pr_info("%pOF: DMA window size is 0x%llx\n", hose->dn,
(u64)hose->dma_window_size);
}
}
@@ -532,11 +531,11 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary)
dev = pdev->dev.of_node;
if (!of_device_is_available(dev)) {
- pr_warning("%s: disabled\n", dev->full_name);
+ pr_warning("%pOF: disabled\n", dev);
return -ENODEV;
}
- pr_debug("Adding PCI host bridge %s\n", dev->full_name);
+ pr_debug("Adding PCI host bridge %pOF\n", dev);
/* Fetch host bridge registers address */
if (of_address_to_resource(dev, 0, &rsrc)) {
@@ -547,8 +546,8 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary)
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int))
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
+ printk(KERN_WARNING "Can't get bus-range for %pOF, assume"
+ " bus 0\n", dev);
pci_add_flags(PCI_REASSIGN_ALL_BUS);
hose = pcibios_alloc_controller(dev);
@@ -809,11 +808,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
is_mpc83xx_pci = 1;
if (!of_device_is_available(dev)) {
- pr_warning("%s: disabled by the firmware.\n",
- dev->full_name);
+ pr_warning("%pOF: disabled by the firmware.\n",
+ dev);
return -ENODEV;
}
- pr_debug("Adding PCI host bridge %s\n", dev->full_name);
+ pr_debug("Adding PCI host bridge %pOF\n", dev);
/* Fetch host bridge registers address */
if (of_address_to_resource(dev, 0, &rsrc_reg)) {
@@ -848,8 +847,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
+ printk(KERN_WARNING "Can't get bus-range for %pOF, assume"
+ " bus 0\n", dev);
}
pci_add_flags(PCI_REASSIGN_ALL_BUS);
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 1c41c51f22cb..9234be1e66f5 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -450,12 +450,12 @@ int fsl_rio_setup(struct platform_device *dev)
rc = of_address_to_resource(dev->dev.of_node, 0, &regs);
if (rc) {
- dev_err(&dev->dev, "Can't get %s property 'reg'\n",
- dev->dev.of_node->full_name);
+ dev_err(&dev->dev, "Can't get %pOF property 'reg'\n",
+ dev->dev.of_node);
return -EFAULT;
}
- dev_info(&dev->dev, "Of-device full name %s\n",
- dev->dev.of_node->full_name);
+ dev_info(&dev->dev, "Of-device full name %pOF\n",
+ dev->dev.of_node);
dev_info(&dev->dev, "Regs: %pR\n", &regs);
rio_regs_win = ioremap(regs.start, resource_size(&regs));
@@ -494,8 +494,8 @@ int fsl_rio_setup(struct platform_device *dev)
}
rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
if (rc) {
- dev_err(&dev->dev, "Can't get %s property 'reg'\n",
- rmu_node->full_name);
+ dev_err(&dev->dev, "Can't get %pOF property 'reg'\n",
+ rmu_node);
goto err_rmu;
}
rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs));
@@ -529,8 +529,8 @@ int fsl_rio_setup(struct platform_device *dev)
aw = of_n_addr_cells(np);
dt_range = of_get_property(np, "reg", &rlen);
if (!dt_range) {
- pr_err("%s: unable to find 'reg' property\n",
- np->full_name);
+ pr_err("%pOF: unable to find 'reg' property\n",
+ np);
rc = -ENOMEM;
goto err_pw;
}
@@ -557,8 +557,8 @@ int fsl_rio_setup(struct platform_device *dev)
aw = of_n_addr_cells(np);
dt_range = of_get_property(np, "reg", &rlen);
if (!dt_range) {
- pr_err("%s: unable to find 'reg' property\n",
- np->full_name);
+ pr_err("%pOF: unable to find 'reg' property\n",
+ np);
rc = -ENOMEM;
goto err;
}
@@ -569,15 +569,15 @@ int fsl_rio_setup(struct platform_device *dev)
for_each_child_of_node(dev->dev.of_node, np) {
port_index = of_get_property(np, "cell-index", NULL);
if (!port_index) {
- dev_err(&dev->dev, "Can't get %s property 'cell-index'\n",
- np->full_name);
+ dev_err(&dev->dev, "Can't get %pOF property 'cell-index'\n",
+ np);
continue;
}
dt_range = of_get_property(np, "ranges", &rlen);
if (!dt_range) {
- dev_err(&dev->dev, "Can't get %s property 'ranges'\n",
- np->full_name);
+ dev_err(&dev->dev, "Can't get %pOF property 'ranges'\n",
+ np);
continue;
}
@@ -598,8 +598,8 @@ int fsl_rio_setup(struct platform_device *dev)
range_start = of_read_number(dt_range + aw, paw);
range_size = of_read_number(dt_range + aw + paw, sw);
- dev_info(&dev->dev, "%s: LAW start 0x%016llx, size 0x%016llx.\n",
- np->full_name, range_start, range_size);
+ dev_info(&dev->dev, "%pOF: LAW start 0x%016llx, size 0x%016llx.\n",
+ np, range_start, range_size);
port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
if (!port)
@@ -757,8 +757,8 @@ err_rio_regs:
*/
static int fsl_of_rio_rpn_probe(struct platform_device *dev)
{
- printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
- dev->dev.of_node->full_name);
+ printk(KERN_INFO "Setting up RapidIO peer-to-peer network %pOF\n",
+ dev->dev.of_node);
return fsl_rio_setup(dev);
};
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index c1826de4e749..ab7a74c75be8 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -1074,8 +1074,8 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node)
priv = mport->priv;
if (!node) {
- dev_warn(priv->dev, "Can't get %s property 'fsl,rmu'\n",
- priv->dev->of_node->full_name);
+ dev_warn(priv->dev, "Can't get %pOF property 'fsl,rmu'\n",
+ priv->dev->of_node);
return -EINVAL;
}
@@ -1086,8 +1086,8 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node)
aw = of_n_addr_cells(node);
msg_addr = of_get_property(node, "reg", &mlen);
if (!msg_addr) {
- pr_err("%s: unable to find 'reg' property of message-unit\n",
- node->full_name);
+ pr_err("%pOF: unable to find 'reg' property of message-unit\n",
+ node);
kfree(rmu);
return -ENOMEM;
}
@@ -1098,8 +1098,8 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node)
rmu->txirq = irq_of_parse_and_map(node, 0);
rmu->rxirq = irq_of_parse_and_map(node, 1);
- printk(KERN_INFO "%s: txirq: %d, rxirq %d\n",
- node->full_name, rmu->txirq, rmu->rxirq);
+ printk(KERN_INFO "%pOF: txirq: %d, rxirq %d\n",
+ node, rmu->txirq, rmu->rxirq);
priv->rmm_handle = rmu;
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 19101f9cfcfc..1f614fb2be56 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -98,7 +98,7 @@ u32 fsl_get_sys_freq(void)
}
EXPORT_SYMBOL(fsl_get_sys_freq);
-#if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
+#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
u32 get_brgfreq(void)
{
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index d73daa4f0ccf..2640446f8bc4 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -7,7 +7,7 @@
struct spi_device;
extern phys_addr_t get_immrbase(void);
-#if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
+#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
extern u32 get_brgfreq(void);
extern u32 get_baudrate(void);
#else
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index f267ee0afc08..16f1edd78c40 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -315,6 +315,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 7,
},
[48] = {
+ .ack = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_A,
.force = IPIC_SEFCR,
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
deleted file mode 100644
index 2842f9d63d21..000000000000
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ /dev/null
@@ -1,163 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/irq.h>
-#include <linux/dma-mapping.h>
-#include <asm/prom.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/8xx_immap.h>
-
-#include "mpc8xx_pic.h"
-
-
-#define PIC_VEC_SPURRIOUS 15
-
-extern int cpm_get_irq(struct pt_regs *regs);
-
-static struct irq_domain *mpc8xx_pic_host;
-static unsigned long mpc8xx_cached_irq_mask;
-static sysconf8xx_t __iomem *siu_reg;
-
-static inline unsigned long mpc8xx_irqd_to_bit(struct irq_data *d)
-{
- return 0x80000000 >> irqd_to_hwirq(d);
-}
-
-static void mpc8xx_unmask_irq(struct irq_data *d)
-{
- mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
- out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
-}
-
-static void mpc8xx_mask_irq(struct irq_data *d)
-{
- mpc8xx_cached_irq_mask &= ~mpc8xx_irqd_to_bit(d);
- out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
-}
-
-static void mpc8xx_ack(struct irq_data *d)
-{
- out_be32(&siu_reg->sc_sipend, mpc8xx_irqd_to_bit(d));
-}
-
-static void mpc8xx_end_irq(struct irq_data *d)
-{
- mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
- out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
-}
-
-static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
-{
- /* only external IRQ senses are programmable */
- if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !(irqd_to_hwirq(d) & 1)) {
- unsigned int siel = in_be32(&siu_reg->sc_siel);
- siel |= mpc8xx_irqd_to_bit(d);
- out_be32(&siu_reg->sc_siel, siel);
- irq_set_handler_locked(d, handle_edge_irq);
- }
- return 0;
-}
-
-static struct irq_chip mpc8xx_pic = {
- .name = "8XX SIU",
- .irq_unmask = mpc8xx_unmask_irq,
- .irq_mask = mpc8xx_mask_irq,
- .irq_ack = mpc8xx_ack,
- .irq_eoi = mpc8xx_end_irq,
- .irq_set_type = mpc8xx_set_irq_type,
-};
-
-unsigned int mpc8xx_get_irq(void)
-{
- int irq;
-
- /* For MPC8xx, read the SIVEC register and shift the bits down
- * to get the irq number.
- */
- irq = in_be32(&siu_reg->sc_sivec) >> 26;
-
- if (irq == PIC_VEC_SPURRIOUS)
- return 0;
-
- return irq_linear_revmap(mpc8xx_pic_host, irq);
-
-}
-
-static int mpc8xx_pic_host_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
-
- /* Set default irq handle */
- irq_set_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
- return 0;
-}
-
-
-static int mpc8xx_pic_host_xlate(struct irq_domain *h, struct device_node *ct,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq, unsigned int *out_flags)
-{
- static unsigned char map_pic_senses[4] = {
- IRQ_TYPE_EDGE_RISING,
- IRQ_TYPE_LEVEL_LOW,
- IRQ_TYPE_LEVEL_HIGH,
- IRQ_TYPE_EDGE_FALLING,
- };
-
- if (intspec[0] > 0x1f)
- return 0;
-
- *out_hwirq = intspec[0];
- if (intsize > 1 && intspec[1] < 4)
- *out_flags = map_pic_senses[intspec[1]];
- else
- *out_flags = IRQ_TYPE_NONE;
-
- return 0;
-}
-
-
-static const struct irq_domain_ops mpc8xx_pic_host_ops = {
- .map = mpc8xx_pic_host_map,
- .xlate = mpc8xx_pic_host_xlate,
-};
-
-int mpc8xx_pic_init(void)
-{
- struct resource res;
- struct device_node *np;
- int ret;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,pq1-pic");
- if (np == NULL)
- np = of_find_node_by_type(NULL, "mpc8xx-pic");
- if (np == NULL) {
- printk(KERN_ERR "Could not find fsl,pq1-pic node\n");
- return -ENOMEM;
- }
-
- ret = of_address_to_resource(np, 0, &res);
- if (ret)
- goto out;
-
- siu_reg = ioremap(res.start, resource_size(&res));
- if (siu_reg == NULL) {
- ret = -EINVAL;
- goto out;
- }
-
- mpc8xx_pic_host = irq_domain_add_linear(np, 64, &mpc8xx_pic_host_ops, NULL);
- if (mpc8xx_pic_host == NULL) {
- printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
- ret = -ENOMEM;
- goto out;
- }
- return 0;
-
-out:
- of_node_put(np);
- return ret;
-}
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
deleted file mode 100644
index 9fe00eebdc8b..000000000000
--- a/arch/powerpc/sysdev/mpc8xx_pic.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _PPC_KERNEL_MPC8xx_H
-#define _PPC_KERNEL_MPC8xx_H
-
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-int mpc8xx_pic_init(void);
-unsigned int mpc8xx_get_irq(void);
-
-/*
- * Some internal interrupt registers use an 8-bit mask for the interrupt
- * level instead of a number.
- */
-static inline uint mk_int_int_mask(uint mask)
-{
- return (1 << (7 - (mask/2)));
-}
-
-#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index b9aac951a90f..ead3e2549ebf 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1650,8 +1650,8 @@ void __init mpic_init(struct mpic *mpic)
if (mpic->flags & MPIC_SECONDARY) {
int virq = irq_of_parse_and_map(mpic->node, 0);
if (virq) {
- printk(KERN_INFO "%s: hooking up to IRQ %d\n",
- mpic->node->full_name, virq);
+ printk(KERN_INFO "%pOF: hooking up to IRQ %d\n",
+ mpic->node, virq);
irq_set_handler_data(virq, mpic);
irq_set_chained_handler(virq, &mpic_cascade);
}
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index db2286be5d9a..eb69a5186243 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -192,7 +192,7 @@ static int mpic_msgr_probe(struct platform_device *dev)
return -ENOMEM;
}
}
- dev_info(&dev->dev, "Of-device full name %s\n", np->full_name);
+ dev_info(&dev->dev, "Of-device full name %pOF\n", np);
/* IO map the message register block. */
of_address_to_resource(np, 0, &rsrc);
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 1d48a5385905..9ed860aee9c3 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -60,7 +60,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
np = NULL;
while ((np = of_find_all_nodes(np))) {
- pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+ pr_debug("mpic: mapping hwirqs for %pOF\n", np);
index = 0;
while (of_irq_parse_one(np, index++, &oirq) == 0) {
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index 9d9b06217f8b..a418579591be 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -466,8 +466,7 @@ static int timer_group_get_irq(struct device_node *np,
p = of_get_property(np, "fsl,available-ranges", &len);
if (p && len % (2 * sizeof(u32)) != 0) {
- pr_err("%s: malformed available-ranges property.\n",
- np->full_name);
+ pr_err("%pOF: malformed available-ranges property.\n", np);
return -EINVAL;
}
@@ -484,8 +483,7 @@ static int timer_group_get_irq(struct device_node *np,
for (j = 0; j < count; j++) {
irq = irq_of_parse_and_map(np, irq_index);
if (!irq) {
- pr_err("%s: irq parse and map failed.\n",
- np->full_name);
+ pr_err("%pOF: irq parse and map failed.\n", np);
return -EINVAL;
}
@@ -508,8 +506,7 @@ static void timer_group_init(struct device_node *np)
priv = kzalloc(sizeof(struct timer_group_priv), GFP_KERNEL);
if (!priv) {
- pr_err("%s: cannot allocate memory for group.\n",
- np->full_name);
+ pr_err("%pOF: cannot allocate memory for group.\n", np);
return;
}
@@ -518,29 +515,27 @@ static void timer_group_init(struct device_node *np)
priv->regs = of_iomap(np, i++);
if (!priv->regs) {
- pr_err("%s: cannot ioremap timer register address.\n",
- np->full_name);
+ pr_err("%pOF: cannot ioremap timer register address.\n", np);
goto out;
}
if (priv->flags & FSL_GLOBAL_TIMER) {
priv->group_tcr = of_iomap(np, i++);
if (!priv->group_tcr) {
- pr_err("%s: cannot ioremap tcr address.\n",
- np->full_name);
+ pr_err("%pOF: cannot ioremap tcr address.\n", np);
goto out;
}
}
ret = timer_group_get_freq(np, priv);
if (ret < 0) {
- pr_err("%s: cannot get timer frequency.\n", np->full_name);
+ pr_err("%pOF: cannot get timer frequency.\n", np);
goto out;
}
ret = timer_group_get_irq(np, priv);
if (ret < 0) {
- pr_err("%s: cannot get timer irqs.\n", np->full_name);
+ pr_err("%pOF: cannot get timer irqs.\n", np);
goto out;
}
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 5ebd3f018295..c4dae27172b3 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -86,13 +86,13 @@ int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp)
p = of_get_property(bmp->of_node, "msi-available-ranges", &len);
if (!p) {
pr_debug("msi_bitmap: no msi-available-ranges property " \
- "found on %s\n", bmp->of_node->full_name);
+ "found on %pOF\n", bmp->of_node);
return 1;
}
if (len % (2 * sizeof(u32)) != 0) {
printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges"
- " property on %s\n", bmp->of_node->full_name);
+ " property on %pOF\n", bmp->of_node);
return -EINVAL;
}
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 026bbc3b2c47..185a67e742a6 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -452,8 +452,8 @@ static int __init mv64x60_device_setup(void)
err = mv64x60_mpsc_device_setup(np, id++);
if (err)
printk(KERN_ERR "Failed to initialize MV64x60 "
- "serial device %s: error %d.\n",
- np->full_name, err);
+ "serial device %pOF: error %d.\n",
+ np, err);
}
id = 0;
@@ -463,8 +463,8 @@ static int __init mv64x60_device_setup(void)
if (IS_ERR(pdev)) {
err = PTR_ERR(pdev);
printk(KERN_ERR "Failed to initialize MV64x60 "
- "network block %s: error %d.\n",
- np->full_name, err);
+ "network block %pOF: error %d.\n",
+ np, err);
continue;
}
for_each_child_of_node(np, np2) {
@@ -474,9 +474,9 @@ static int __init mv64x60_device_setup(void)
err = mv64x60_eth_device_setup(np2, id2++, pdev);
if (err)
printk(KERN_ERR "Failed to initialize "
- "MV64x60 network device %s: "
+ "MV64x60 network device %pOF: "
"error %d.\n",
- np2->full_name, err);
+ np2, err);
}
}
@@ -485,8 +485,8 @@ static int __init mv64x60_device_setup(void)
err = mv64x60_i2c_device_setup(np, id++);
if (err)
printk(KERN_ERR "Failed to initialize MV64x60 I2C "
- "bus %s: error %d.\n",
- np->full_name, err);
+ "bus %pOF: error %d.\n",
+ np, err);
}
/* support up to one watchdog timer */
@@ -494,8 +494,8 @@ static int __init mv64x60_device_setup(void)
if (np) {
if ((err = mv64x60_wdt_device_setup(np, id)))
printk(KERN_ERR "Failed to initialize MV64x60 "
- "Watchdog %s: error %d.\n",
- np->full_name, err);
+ "Watchdog %pOF: error %d.\n",
+ np, err);
of_node_put(np);
}
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
index 330d56613c5a..d52b3b81e05f 100644
--- a/arch/powerpc/sysdev/mv64x60_pci.c
+++ b/arch/powerpc/sysdev/mv64x60_pci.c
@@ -70,7 +70,7 @@ static ssize_t mv64x60_hs_reg_write(struct file *filp, struct kobject *kobj,
return count;
}
-static struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */
+static const struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */
.attr = {
.name = "hs_reg",
.mode = S_IRUGO | S_IWUSR,
@@ -136,8 +136,8 @@ static int __init mv64x60_add_bridge(struct device_node *dev)
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int))
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
+ printk(KERN_WARNING "Can't get bus-range for %pOF, assume"
+ " bus 0\n", dev);
hose = pcibios_alloc_controller(dev);
if (!hose)
diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c
index 6f54b54b1328..153fdac4720f 100644
--- a/arch/powerpc/sysdev/of_rtc.c
+++ b/arch/powerpc/sysdev/of_rtc.c
@@ -38,21 +38,21 @@ void __init of_instantiate_rtc(void)
res = kmalloc(sizeof(*res), GFP_KERNEL);
if (!res) {
printk(KERN_ERR "OF RTC: Out of memory "
- "allocating resource structure for %s\n",
- node->full_name);
+ "allocating resource structure for %pOF\n",
+ node);
continue;
}
err = of_address_to_resource(node, 0, res);
if (err) {
printk(KERN_ERR "OF RTC: Error "
- "translating resources for %s\n",
- node->full_name);
+ "translating resources for %pOF\n",
+ node);
continue;
}
- printk(KERN_INFO "OF_RTC: %s is a %s @ 0x%llx-0x%llx\n",
- node->full_name, plat_name,
+ printk(KERN_INFO "OF_RTC: %pOF is a %s @ 0x%llx-0x%llx\n",
+ node, plat_name,
(unsigned long long)res->start,
(unsigned long long)res->end);
platform_device_register_simple(plat_name, -1, res, 1);
diff --git a/arch/powerpc/sysdev/ppc4xx_cpm.c b/arch/powerpc/sysdev/ppc4xx_cpm.c
deleted file mode 100644
index ba95adf81d8d..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_cpm.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * PowerPC 4xx Clock and Power Management
- *
- * Copyright (C) 2010, Applied Micro Circuits Corporation
- * Victor Gallardo (vgallardo@apm.com)
- *
- * Based on arch/powerpc/platforms/44x/idle.c:
- * Jerone Young <jyoung5@us.ibm.com>
- * Copyright 2008 IBM Corp.
- *
- * Based on arch/powerpc/sysdev/fsl_pmc.c:
- * Anton Vorontsov <avorontsov@ru.mvista.com>
- * Copyright 2009 MontaVista Software, Inc.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-#include <linux/sysfs.h>
-#include <linux/cpu.h>
-#include <linux/suspend.h>
-#include <asm/dcr.h>
-#include <asm/dcr-native.h>
-#include <asm/machdep.h>
-
-#define CPM_ER 0
-#define CPM_FR 1
-#define CPM_SR 2
-
-#define CPM_IDLE_WAIT 0
-#define CPM_IDLE_DOZE 1
-
-struct cpm {
- dcr_host_t dcr_host;
- unsigned int dcr_offset[3];
- unsigned int powersave_off;
- unsigned int unused;
- unsigned int idle_doze;
- unsigned int standby;
- unsigned int suspend;
-};
-
-static struct cpm cpm;
-
-struct cpm_idle_mode {
- unsigned int enabled;
- const char *name;
-};
-
-static struct cpm_idle_mode idle_mode[] = {
- [CPM_IDLE_WAIT] = { 1, "wait" }, /* default */
- [CPM_IDLE_DOZE] = { 0, "doze" },
-};
-
-static unsigned int cpm_set(unsigned int cpm_reg, unsigned int mask)
-{
- unsigned int value;
-
- /* CPM controller supports 3 different types of sleep interface
- * known as class 1, 2 and 3. For class 1 units, they are
- * unconditionally put to sleep when the corresponding CPM bit is
- * set. For class 2 and 3 units this is not case; if they can be
- * put to to sleep, they will. Here we do not verify, we just
- * set them and expect them to eventually go off when they can.
- */
- value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]);
- dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value | mask);
-
- /* return old state, to restore later if needed */
- return value;
-}
-
-static void cpm_idle_wait(void)
-{
- unsigned long msr_save;
-
- /* save off initial state */
- msr_save = mfmsr();
- /* sync required when CPM0_ER[CPU] is set */
- mb();
- /* set wait state MSR */
- mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
- isync();
- /* return to initial state */
- mtmsr(msr_save);
- isync();
-}
-
-static void cpm_idle_sleep(unsigned int mask)
-{
- unsigned int er_save;
-
- /* update CPM_ER state */
- er_save = cpm_set(CPM_ER, mask);
-
- /* go to wait state so that CPM0_ER[CPU] can take effect */
- cpm_idle_wait();
-
- /* restore CPM_ER state */
- dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save);
-}
-
-static void cpm_idle_doze(void)
-{
- cpm_idle_sleep(cpm.idle_doze);
-}
-
-static void cpm_idle_config(int mode)
-{
- int i;
-
- if (idle_mode[mode].enabled)
- return;
-
- for (i = 0; i < ARRAY_SIZE(idle_mode); i++)
- idle_mode[i].enabled = 0;
-
- idle_mode[mode].enabled = 1;
-}
-
-static ssize_t cpm_idle_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
-{
- char *s = buf;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
- if (idle_mode[i].enabled)
- s += sprintf(s, "[%s] ", idle_mode[i].name);
- else
- s += sprintf(s, "%s ", idle_mode[i].name);
- }
-
- *(s-1) = '\n'; /* convert the last space to a newline */
-
- return s - buf;
-}
-
-static ssize_t cpm_idle_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- int i;
- char *p;
- int len;
-
- p = memchr(buf, '\n', n);
- len = p ? p - buf : n;
-
- for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
- if (strncmp(buf, idle_mode[i].name, len) == 0) {
- cpm_idle_config(i);
- return n;
- }
- }
-
- return -EINVAL;
-}
-
-static struct kobj_attribute cpm_idle_attr =
- __ATTR(idle, 0644, cpm_idle_show, cpm_idle_store);
-
-static void cpm_idle_config_sysfs(void)
-{
- struct device *dev;
- unsigned long ret;
-
- dev = get_cpu_device(0);
-
- ret = sysfs_create_file(&dev->kobj,
- &cpm_idle_attr.attr);
- if (ret)
- printk(KERN_WARNING
- "cpm: failed to create idle sysfs entry\n");
-}
-
-static void cpm_idle(void)
-{
- if (idle_mode[CPM_IDLE_DOZE].enabled)
- cpm_idle_doze();
- else
- cpm_idle_wait();
-}
-
-static int cpm_suspend_valid(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_STANDBY:
- return !!cpm.standby;
- case PM_SUSPEND_MEM:
- return !!cpm.suspend;
- default:
- return 0;
- }
-}
-
-static void cpm_suspend_standby(unsigned int mask)
-{
- unsigned long tcr_save;
-
- /* disable decrement interrupt */
- tcr_save = mfspr(SPRN_TCR);
- mtspr(SPRN_TCR, tcr_save & ~TCR_DIE);
-
- /* go to sleep state */
- cpm_idle_sleep(mask);
-
- /* restore decrement interrupt */
- mtspr(SPRN_TCR, tcr_save);
-}
-
-static int cpm_suspend_enter(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_STANDBY:
- cpm_suspend_standby(cpm.standby);
- break;
- case PM_SUSPEND_MEM:
- cpm_suspend_standby(cpm.suspend);
- break;
- }
-
- return 0;
-}
-
-static struct platform_suspend_ops cpm_suspend_ops = {
- .valid = cpm_suspend_valid,
- .enter = cpm_suspend_enter,
-};
-
-static int cpm_get_uint_property(struct device_node *np,
- const char *name)
-{
- int len;
- const unsigned int *prop = of_get_property(np, name, &len);
-
- if (prop == NULL || len < sizeof(u32))
- return 0;
-
- return *prop;
-}
-
-static int __init cpm_init(void)
-{
- struct device_node *np;
- int dcr_base, dcr_len;
- int ret = 0;
-
- if (!cpm.powersave_off) {
- cpm_idle_config(CPM_IDLE_WAIT);
- ppc_md.power_save = &cpm_idle;
- }
-
- np = of_find_compatible_node(NULL, NULL, "ibm,cpm");
- if (!np) {
- ret = -EINVAL;
- goto out;
- }
-
- dcr_base = dcr_resource_start(np, 0);
- dcr_len = dcr_resource_len(np, 0);
-
- if (dcr_base == 0 || dcr_len == 0) {
- printk(KERN_ERR "cpm: could not parse dcr property for %s\n",
- np->full_name);
- ret = -EINVAL;
- goto node_put;
- }
-
- cpm.dcr_host = dcr_map(np, dcr_base, dcr_len);
-
- if (!DCR_MAP_OK(cpm.dcr_host)) {
- printk(KERN_ERR "cpm: failed to map dcr property for %s\n",
- np->full_name);
- ret = -EINVAL;
- goto node_put;
- }
-
- /* All 4xx SoCs with a CPM controller have one of two
- * different order for the CPM registers. Some have the
- * CPM registers in the following order (ER,FR,SR). The
- * others have them in the following order (SR,ER,FR).
- */
-
- if (cpm_get_uint_property(np, "er-offset") == 0) {
- cpm.dcr_offset[CPM_ER] = 0;
- cpm.dcr_offset[CPM_FR] = 1;
- cpm.dcr_offset[CPM_SR] = 2;
- } else {
- cpm.dcr_offset[CPM_ER] = 1;
- cpm.dcr_offset[CPM_FR] = 2;
- cpm.dcr_offset[CPM_SR] = 0;
- }
-
- /* Now let's see what IPs to turn off for the following modes */
-
- cpm.unused = cpm_get_uint_property(np, "unused-units");
- cpm.idle_doze = cpm_get_uint_property(np, "idle-doze");
- cpm.standby = cpm_get_uint_property(np, "standby");
- cpm.suspend = cpm_get_uint_property(np, "suspend");
-
- /* If some IPs are unused let's turn them off now */
-
- if (cpm.unused) {
- cpm_set(CPM_ER, cpm.unused);
- cpm_set(CPM_FR, cpm.unused);
- }
-
- /* Now let's export interfaces */
-
- if (!cpm.powersave_off && cpm.idle_doze)
- cpm_idle_config_sysfs();
-
- if (cpm.standby || cpm.suspend)
- suspend_set_ops(&cpm_suspend_ops);
-node_put:
- of_node_put(np);
-out:
- return ret;
-}
-
-late_initcall(cpm_init);
-
-static int __init cpm_powersave_off(char *arg)
-{
- cpm.powersave_off = 1;
- return 0;
-}
-__setup("powersave=off", cpm_powersave_off);
diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c
deleted file mode 100644
index 5382d04dd872..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_gpio.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * PPC4xx gpio driver
- *
- * Copyright (c) 2008 Harris Corporation
- * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- * Copyright (c) MontaVista Software, Inc. 2008.
- *
- * Author: Steve Falco <sfalco@harris.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio/driver.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#define GPIO_MASK(gpio) (0x80000000 >> (gpio))
-#define GPIO_MASK2(gpio) (0xc0000000 >> ((gpio) * 2))
-
-/* Physical GPIO register layout */
-struct ppc4xx_gpio {
- __be32 or;
- __be32 tcr;
- __be32 osrl;
- __be32 osrh;
- __be32 tsrl;
- __be32 tsrh;
- __be32 odr;
- __be32 ir;
- __be32 rr1;
- __be32 rr2;
- __be32 rr3;
- __be32 reserved1;
- __be32 isr1l;
- __be32 isr1h;
- __be32 isr2l;
- __be32 isr2h;
- __be32 isr3l;
- __be32 isr3h;
-};
-
-struct ppc4xx_gpio_chip {
- struct of_mm_gpio_chip mm_gc;
- spinlock_t lock;
-};
-
-/*
- * GPIO LIB API implementation for GPIOs
- *
- * There are a maximum of 32 gpios in each gpio controller.
- */
-
-static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
-
- return !!(in_be32(&regs->ir) & GPIO_MASK(gpio));
-}
-
-static inline void
-__ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
-
- if (val)
- setbits32(&regs->or, GPIO_MASK(gpio));
- else
- clrbits32(&regs->or, GPIO_MASK(gpio));
-}
-
-static void
-ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
- unsigned long flags;
-
- spin_lock_irqsave(&chip->lock, flags);
-
- __ppc4xx_gpio_set(gc, gpio, val);
-
- spin_unlock_irqrestore(&chip->lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
- struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&chip->lock, flags);
-
- /* Disable open-drain function */
- clrbits32(&regs->odr, GPIO_MASK(gpio));
-
- /* Float the pin */
- clrbits32(&regs->tcr, GPIO_MASK(gpio));
-
- /* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
- if (gpio < 16) {
- clrbits32(&regs->osrl, GPIO_MASK2(gpio));
- clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
- } else {
- clrbits32(&regs->osrh, GPIO_MASK2(gpio));
- clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
- }
-
- spin_unlock_irqrestore(&chip->lock, flags);
-
- return 0;
-}
-
-static int
-ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
- struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&chip->lock, flags);
-
- /* First set initial value */
- __ppc4xx_gpio_set(gc, gpio, val);
-
- /* Disable open-drain function */
- clrbits32(&regs->odr, GPIO_MASK(gpio));
-
- /* Drive the pin */
- setbits32(&regs->tcr, GPIO_MASK(gpio));
-
- /* Bits 0-15 use TSRL, bits 16-31 use TSRH */
- if (gpio < 16) {
- clrbits32(&regs->osrl, GPIO_MASK2(gpio));
- clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
- } else {
- clrbits32(&regs->osrh, GPIO_MASK2(gpio));
- clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
- }
-
- spin_unlock_irqrestore(&chip->lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
- return 0;
-}
-
-static int __init ppc4xx_add_gpiochips(void)
-{
- struct device_node *np;
-
- for_each_compatible_node(np, NULL, "ibm,ppc4xx-gpio") {
- int ret;
- struct ppc4xx_gpio_chip *ppc4xx_gc;
- struct of_mm_gpio_chip *mm_gc;
- struct gpio_chip *gc;
-
- ppc4xx_gc = kzalloc(sizeof(*ppc4xx_gc), GFP_KERNEL);
- if (!ppc4xx_gc) {
- ret = -ENOMEM;
- goto err;
- }
-
- spin_lock_init(&ppc4xx_gc->lock);
-
- mm_gc = &ppc4xx_gc->mm_gc;
- gc = &mm_gc->gc;
-
- gc->ngpio = 32;
- gc->direction_input = ppc4xx_gpio_dir_in;
- gc->direction_output = ppc4xx_gpio_dir_out;
- gc->get = ppc4xx_gpio_get;
- gc->set = ppc4xx_gpio_set;
-
- ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc);
- if (ret)
- goto err;
- continue;
-err:
- pr_err("%s: registration failed with status %d\n",
- np->full_name, ret);
- kfree(ppc4xx_gc);
- /* try others anyway */
- }
- return 0;
-}
-arch_initcall(ppc4xx_add_gpiochips);
diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
deleted file mode 100644
index 9926ad67af76..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * MSI support for PPC4xx SoCs using High Speed Transfer Assist (HSTA) for
- * generation of the interrupt.
- *
- * Copyright © 2013 Alistair Popple <alistair@popple.id.au> IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/msi.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/pci.h>
-#include <linux/semaphore.h>
-#include <asm/msi_bitmap.h>
-#include <asm/ppc-pci.h>
-
-struct ppc4xx_hsta_msi {
- struct device *dev;
-
- /* The ioremapped HSTA MSI IO space */
- u32 __iomem *data;
-
- /* Physical address of HSTA MSI IO space */
- u64 address;
- struct msi_bitmap bmp;
-
- /* An array mapping offsets to hardware IRQs */
- int *irq_map;
-
- /* Number of hwirqs supported */
- int irq_count;
-};
-static struct ppc4xx_hsta_msi ppc4xx_hsta_msi;
-
-static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
- struct msi_msg msg;
- struct msi_desc *entry;
- int irq, hwirq;
- u64 addr;
-
- /* We don't support MSI-X */
- if (type == PCI_CAP_ID_MSIX) {
- pr_debug("%s: MSI-X not supported.\n", __func__);
- return -EINVAL;
- }
-
- for_each_pci_msi_entry(entry, dev) {
- irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
- if (irq < 0) {
- pr_debug("%s: Failed to allocate msi interrupt\n",
- __func__);
- return irq;
- }
-
- hwirq = ppc4xx_hsta_msi.irq_map[irq];
- if (!hwirq) {
- pr_err("%s: Failed mapping irq %d\n", __func__, irq);
- return -EINVAL;
- }
-
- /*
- * HSTA generates interrupts on writes to 128-bit aligned
- * addresses.
- */
- addr = ppc4xx_hsta_msi.address + irq*0x10;
- msg.address_hi = upper_32_bits(addr);
- msg.address_lo = lower_32_bits(addr);
-
- /* Data is not used by the HSTA. */
- msg.data = 0;
-
- pr_debug("%s: Setup irq %d (0x%0llx)\n", __func__, hwirq,
- (((u64) msg.address_hi) << 32) | msg.address_lo);
-
- if (irq_set_msi_desc(hwirq, entry)) {
- pr_err(
- "%s: Invalid hwirq %d specified in device tree\n",
- __func__, hwirq);
- msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
- return -EINVAL;
- }
- pci_write_msi_msg(hwirq, &msg);
- }
-
- return 0;
-}
-
-static int hsta_find_hwirq_offset(int hwirq)
-{
- int irq;
-
- /* Find the offset given the hwirq */
- for (irq = 0; irq < ppc4xx_hsta_msi.irq_count; irq++)
- if (ppc4xx_hsta_msi.irq_map[irq] == hwirq)
- return irq;
-
- return -EINVAL;
-}
-
-static void hsta_teardown_msi_irqs(struct pci_dev *dev)
-{
- struct msi_desc *entry;
- int irq;
-
- for_each_pci_msi_entry(entry, dev) {
- if (!entry->irq)
- continue;
-
- irq = hsta_find_hwirq_offset(entry->irq);
-
- /* entry->irq should always be in irq_map */
- BUG_ON(irq < 0);
- irq_set_msi_desc(entry->irq, NULL);
- msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
- pr_debug("%s: Teardown IRQ %u (index %u)\n", __func__,
- entry->irq, irq);
- }
-}
-
-static int hsta_msi_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *mem;
- int irq, ret, irq_count;
- struct pci_controller *phb;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(dev, "Unable to get mmio space\n");
- return -EINVAL;
- }
-
- irq_count = of_irq_count(dev->of_node);
- if (!irq_count) {
- dev_err(dev, "Unable to find IRQ range\n");
- return -EINVAL;
- }
-
- ppc4xx_hsta_msi.dev = dev;
- ppc4xx_hsta_msi.address = mem->start;
- ppc4xx_hsta_msi.data = ioremap(mem->start, resource_size(mem));
- ppc4xx_hsta_msi.irq_count = irq_count;
- if (!ppc4xx_hsta_msi.data) {
- dev_err(dev, "Unable to map memory\n");
- return -ENOMEM;
- }
-
- ret = msi_bitmap_alloc(&ppc4xx_hsta_msi.bmp, irq_count, dev->of_node);
- if (ret)
- goto out;
-
- ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL);
- if (!ppc4xx_hsta_msi.irq_map) {
- ret = -ENOMEM;
- goto out1;
- }
-
- /* Setup a mapping from irq offsets to hardware irq numbers */
- for (irq = 0; irq < irq_count; irq++) {
- ppc4xx_hsta_msi.irq_map[irq] =
- irq_of_parse_and_map(dev->of_node, irq);
- if (!ppc4xx_hsta_msi.irq_map[irq]) {
- dev_err(dev, "Unable to map IRQ\n");
- ret = -EINVAL;
- goto out2;
- }
- }
-
- list_for_each_entry(phb, &hose_list, list_node) {
- phb->controller_ops.setup_msi_irqs = hsta_setup_msi_irqs;
- phb->controller_ops.teardown_msi_irqs = hsta_teardown_msi_irqs;
- }
- return 0;
-
-out2:
- kfree(ppc4xx_hsta_msi.irq_map);
-
-out1:
- msi_bitmap_free(&ppc4xx_hsta_msi.bmp);
-
-out:
- iounmap(ppc4xx_hsta_msi.data);
- return ret;
-}
-
-static const struct of_device_id hsta_msi_ids[] = {
- {
- .compatible = "ibm,hsta-msi",
- },
- {}
-};
-
-static struct platform_driver hsta_msi_driver = {
- .probe = hsta_msi_probe,
- .driver = {
- .name = "hsta-msi",
- .of_match_table = hsta_msi_ids,
- },
-};
-
-static int hsta_msi_init(void)
-{
- return platform_driver_register(&hsta_msi_driver);
-}
-subsys_initcall(hsta_msi_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
deleted file mode 100644
index 590dab4f47d6..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Adding PCI-E MSI support for PPC4XX SoCs.
- *
- * Copyright (c) 2010, Applied Micro Circuits Corporation
- * Authors: Tirumala R Marri <tmarri@apm.com>
- * Feng Kan <fkan@apm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/msi.h>
-#include <linux/of_platform.h>
-#include <linux/interrupt.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <asm/prom.h>
-#include <asm/hw_irq.h>
-#include <asm/ppc-pci.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#include <asm/msi_bitmap.h>
-
-#define PEIH_TERMADH 0x00
-#define PEIH_TERMADL 0x08
-#define PEIH_MSIED 0x10
-#define PEIH_MSIMK 0x18
-#define PEIH_MSIASS 0x20
-#define PEIH_FLUSH0 0x30
-#define PEIH_FLUSH1 0x38
-#define PEIH_CNTRST 0x48
-
-static int msi_irqs;
-
-struct ppc4xx_msi {
- u32 msi_addr_lo;
- u32 msi_addr_hi;
- void __iomem *msi_regs;
- int *msi_virqs;
- struct msi_bitmap bitmap;
- struct device_node *msi_dev;
-};
-
-static struct ppc4xx_msi ppc4xx_msi;
-
-static int ppc4xx_msi_init_allocator(struct platform_device *dev,
- struct ppc4xx_msi *msi_data)
-{
- int err;
-
- err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
- dev->dev.of_node);
- if (err)
- return err;
-
- err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
- if (err < 0) {
- msi_bitmap_free(&msi_data->bitmap);
- return err;
- }
-
- return 0;
-}
-
-static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
- int int_no = -ENOMEM;
- unsigned int virq;
- struct msi_msg msg;
- struct msi_desc *entry;
- struct ppc4xx_msi *msi_data = &ppc4xx_msi;
-
- dev_dbg(&dev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
- __func__, nvec, type);
- if (type == PCI_CAP_ID_MSIX)
- pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
-
- msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL);
- if (!msi_data->msi_virqs)
- return -ENOMEM;
-
- for_each_pci_msi_entry(entry, dev) {
- int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
- if (int_no >= 0)
- break;
- if (int_no < 0) {
- pr_debug("%s: fail allocating msi interrupt\n",
- __func__);
- }
- virq = irq_of_parse_and_map(msi_data->msi_dev, int_no);
- if (!virq) {
- dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
- msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
- return -ENOSPC;
- }
- dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq);
-
- /* Setup msi address space */
- msg.address_hi = msi_data->msi_addr_hi;
- msg.address_lo = msi_data->msi_addr_lo;
-
- irq_set_msi_desc(virq, entry);
- msg.data = int_no;
- pci_write_msi_msg(virq, &msg);
- }
- return 0;
-}
-
-void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
-{
- struct msi_desc *entry;
- struct ppc4xx_msi *msi_data = &ppc4xx_msi;
- irq_hw_number_t hwirq;
-
- dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
-
- for_each_pci_msi_entry(entry, dev) {
- if (!entry->irq)
- continue;
- hwirq = virq_to_hw(entry->irq);
- irq_set_msi_desc(entry->irq, NULL);
- irq_dispose_mapping(entry->irq);
- msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
- }
-}
-
-static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
- struct resource res, struct ppc4xx_msi *msi)
-{
- const u32 *msi_data;
- const u32 *msi_mask;
- const u32 *sdr_addr;
- dma_addr_t msi_phys;
- void *msi_virt;
-
- sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL);
- if (!sdr_addr)
- return -1;
-
- mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
- mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
-
- msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
- if (!msi->msi_dev)
- return -ENODEV;
-
- msi->msi_regs = of_iomap(msi->msi_dev, 0);
- if (!msi->msi_regs) {
- dev_err(&dev->dev, "of_iomap problem failed\n");
- return -ENOMEM;
- }
- dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n",
- (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
-
- msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
- if (!msi_virt)
- return -ENOMEM;
- msi->msi_addr_hi = upper_32_bits(msi_phys);
- msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
- dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
- msi->msi_addr_hi, msi->msi_addr_lo);
-
- /* Progam the Interrupt handler Termination addr registers */
- out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
- out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo);
-
- msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL);
- if (!msi_data)
- return -1;
- msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL);
- if (!msi_mask)
- return -1;
- /* Program MSI Expected data and Mask bits */
- out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
- out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
-
- dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
-
- return 0;
-}
-
-static int ppc4xx_of_msi_remove(struct platform_device *dev)
-{
- struct ppc4xx_msi *msi = dev->dev.platform_data;
- int i;
- int virq;
-
- for (i = 0; i < msi_irqs; i++) {
- virq = msi->msi_virqs[i];
- if (virq)
- irq_dispose_mapping(virq);
- }
-
- if (msi->bitmap.bitmap)
- msi_bitmap_free(&msi->bitmap);
- iounmap(msi->msi_regs);
- of_node_put(msi->msi_dev);
- kfree(msi);
-
- return 0;
-}
-
-static int ppc4xx_msi_probe(struct platform_device *dev)
-{
- struct ppc4xx_msi *msi;
- struct resource res;
- int err = 0;
- struct pci_controller *phb;
-
- dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
-
- msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
- if (!msi) {
- dev_err(&dev->dev, "No memory for MSI structure\n");
- return -ENOMEM;
- }
- dev->dev.platform_data = msi;
-
- /* Get MSI ranges */
- err = of_address_to_resource(dev->dev.of_node, 0, &res);
- if (err) {
- dev_err(&dev->dev, "%s resource error!\n",
- dev->dev.of_node->full_name);
- goto error_out;
- }
-
- msi_irqs = of_irq_count(dev->dev.of_node);
- if (!msi_irqs)
- return -ENODEV;
-
- if (ppc4xx_setup_pcieh_hw(dev, res, msi))
- goto error_out;
-
- err = ppc4xx_msi_init_allocator(dev, msi);
- if (err) {
- dev_err(&dev->dev, "Error allocating MSI bitmap\n");
- goto error_out;
- }
- ppc4xx_msi = *msi;
-
- list_for_each_entry(phb, &hose_list, list_node) {
- phb->controller_ops.setup_msi_irqs = ppc4xx_setup_msi_irqs;
- phb->controller_ops.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
- }
- return err;
-
-error_out:
- ppc4xx_of_msi_remove(dev);
- return err;
-}
-static const struct of_device_id ppc4xx_msi_ids[] = {
- {
- .compatible = "amcc,ppc4xx-msi",
- },
- {}
-};
-static struct platform_driver ppc4xx_msi_driver = {
- .probe = ppc4xx_msi_probe,
- .remove = ppc4xx_of_msi_remove,
- .driver = {
- .name = "ppc4xx-msi",
- .of_match_table = ppc4xx_msi_ids,
- },
-
-};
-
-static __init int ppc4xx_msi_init(void)
-{
- return platform_driver_register(&ppc4xx_msi_driver);
-}
-
-subsys_initcall(ppc4xx_msi_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
deleted file mode 100644
index 85d9e37f5ccb..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_ocm.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * PowerPC 4xx OCM memory allocation support
- *
- * (C) Copyright 2009, Applied Micro Circuits Corporation
- * Victor Gallardo (vgallardo@amcc.com)
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <asm/rheap.h>
-#include <asm/ppc4xx_ocm.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-
-#define OCM_DISABLED 0
-#define OCM_ENABLED 1
-
-struct ocm_block {
- struct list_head list;
- void __iomem *addr;
- int size;
- const char *owner;
-};
-
-/* non-cached or cached region */
-struct ocm_region {
- phys_addr_t phys;
- void __iomem *virt;
-
- int memtotal;
- int memfree;
-
- rh_info_t *rh;
- struct list_head list;
-};
-
-struct ocm_info {
- int index;
- int status;
- int ready;
-
- phys_addr_t phys;
-
- int alignment;
- int memtotal;
- int cache_size;
-
- struct ocm_region nc; /* non-cached region */
- struct ocm_region c; /* cached region */
-};
-
-static struct ocm_info *ocm_nodes;
-static int ocm_count;
-
-static struct ocm_info *ocm_get_node(unsigned int index)
-{
- if (index >= ocm_count) {
- printk(KERN_ERR "PPC4XX OCM: invalid index");
- return NULL;
- }
-
- return &ocm_nodes[index];
-}
-
-static int ocm_free_region(struct ocm_region *ocm_reg, const void *addr)
-{
- struct ocm_block *blk, *tmp;
- unsigned long offset;
-
- if (!ocm_reg->virt)
- return 0;
-
- list_for_each_entry_safe(blk, tmp, &ocm_reg->list, list) {
- if (blk->addr == addr) {
- offset = addr - ocm_reg->virt;
- ocm_reg->memfree += blk->size;
- rh_free(ocm_reg->rh, offset);
- list_del(&blk->list);
- kfree(blk);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void __init ocm_init_node(int count, struct device_node *node)
-{
- struct ocm_info *ocm;
-
- const unsigned int *cell_index;
- const unsigned int *cache_size;
- int len;
-
- struct resource rsrc;
- int ioflags;
-
- ocm = ocm_get_node(count);
-
- cell_index = of_get_property(node, "cell-index", &len);
- if (!cell_index) {
- printk(KERN_ERR "PPC4XX OCM: missing cell-index property");
- return;
- }
- ocm->index = *cell_index;
-
- if (of_device_is_available(node))
- ocm->status = OCM_ENABLED;
-
- cache_size = of_get_property(node, "cached-region-size", &len);
- if (cache_size)
- ocm->cache_size = *cache_size;
-
- if (of_address_to_resource(node, 0, &rsrc)) {
- printk(KERN_ERR "PPC4XX OCM%d: could not get resource address\n",
- ocm->index);
- return;
- }
-
- ocm->phys = rsrc.start;
- ocm->memtotal = (rsrc.end - rsrc.start + 1);
-
- printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (%s)\n",
- ocm->index, ocm->memtotal,
- (ocm->status == OCM_DISABLED) ? "disabled" : "enabled");
-
- if (ocm->status == OCM_DISABLED)
- return;
-
- /* request region */
-
- if (!request_mem_region(ocm->phys, ocm->memtotal, "ppc4xx_ocm")) {
- printk(KERN_ERR "PPC4XX OCM%d: could not request region\n",
- ocm->index);
- return;
- }
-
- /* Configure non-cached and cached regions */
-
- ocm->nc.phys = ocm->phys;
- ocm->nc.memtotal = ocm->memtotal - ocm->cache_size;
- ocm->nc.memfree = ocm->nc.memtotal;
-
- ocm->c.phys = ocm->phys + ocm->nc.memtotal;
- ocm->c.memtotal = ocm->cache_size;
- ocm->c.memfree = ocm->c.memtotal;
-
- if (ocm->nc.memtotal == 0)
- ocm->nc.phys = 0;
-
- if (ocm->c.memtotal == 0)
- ocm->c.phys = 0;
-
- printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (non-cached)\n",
- ocm->index, ocm->nc.memtotal);
-
- printk(KERN_INFO "PPC4XX OCM%d: %d Bytes (cached)\n",
- ocm->index, ocm->c.memtotal);
-
- /* ioremap the non-cached region */
- if (ocm->nc.memtotal) {
- ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC;
- ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal,
- ioflags);
-
- if (!ocm->nc.virt) {
- printk(KERN_ERR
- "PPC4XX OCM%d: failed to ioremap non-cached memory\n",
- ocm->index);
- ocm->nc.memfree = 0;
- return;
- }
- }
-
- /* ioremap the cached region */
-
- if (ocm->c.memtotal) {
- ioflags = _PAGE_EXEC;
- ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal,
- ioflags);
-
- if (!ocm->c.virt) {
- printk(KERN_ERR
- "PPC4XX OCM%d: failed to ioremap cached memory\n",
- ocm->index);
- ocm->c.memfree = 0;
- return;
- }
- }
-
- /* Create Remote Heaps */
-
- ocm->alignment = 4; /* default 4 byte alignment */
-
- if (ocm->nc.virt) {
- ocm->nc.rh = rh_create(ocm->alignment);
- rh_attach_region(ocm->nc.rh, 0, ocm->nc.memtotal);
- }
-
- if (ocm->c.virt) {
- ocm->c.rh = rh_create(ocm->alignment);
- rh_attach_region(ocm->c.rh, 0, ocm->c.memtotal);
- }
-
- INIT_LIST_HEAD(&ocm->nc.list);
- INIT_LIST_HEAD(&ocm->c.list);
-
- ocm->ready = 1;
-
- return;
-}
-
-static int ocm_debugfs_show(struct seq_file *m, void *v)
-{
- struct ocm_block *blk, *tmp;
- unsigned int i;
-
- for (i = 0; i < ocm_count; i++) {
- struct ocm_info *ocm = ocm_get_node(i);
-
- if (!ocm || !ocm->ready)
- continue;
-
- seq_printf(m, "PPC4XX OCM : %d\n", ocm->index);
- seq_printf(m, "PhysAddr : 0x%llx\n", ocm->phys);
- seq_printf(m, "MemTotal : %d Bytes\n", ocm->memtotal);
- seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
- seq_printf(m, "MemTotal(C) : %d Bytes\n", ocm->c.memtotal);
-
- seq_printf(m, "\n");
-
- seq_printf(m, "NC.PhysAddr : 0x%llx\n", ocm->nc.phys);
- seq_printf(m, "NC.VirtAddr : 0x%p\n", ocm->nc.virt);
- seq_printf(m, "NC.MemTotal : %d Bytes\n", ocm->nc.memtotal);
- seq_printf(m, "NC.MemFree : %d Bytes\n", ocm->nc.memfree);
-
- list_for_each_entry_safe(blk, tmp, &ocm->nc.list, list) {
- seq_printf(m, "NC.MemUsed : %d Bytes (%s)\n",
- blk->size, blk->owner);
- }
-
- seq_printf(m, "\n");
-
- seq_printf(m, "C.PhysAddr : 0x%llx\n", ocm->c.phys);
- seq_printf(m, "C.VirtAddr : 0x%p\n", ocm->c.virt);
- seq_printf(m, "C.MemTotal : %d Bytes\n", ocm->c.memtotal);
- seq_printf(m, "C.MemFree : %d Bytes\n", ocm->c.memfree);
-
- list_for_each_entry_safe(blk, tmp, &ocm->c.list, list) {
- seq_printf(m, "C.MemUsed : %d Bytes (%s)\n",
- blk->size, blk->owner);
- }
-
- seq_printf(m, "\n");
- }
-
- return 0;
-}
-
-static int ocm_debugfs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ocm_debugfs_show, NULL);
-}
-
-static const struct file_operations ocm_debugfs_fops = {
- .open = ocm_debugfs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int ocm_debugfs_init(void)
-{
- struct dentry *junk;
-
- junk = debugfs_create_dir("ppc4xx_ocm", 0);
- if (!junk) {
- printk(KERN_ALERT "debugfs ppc4xx ocm: failed to create dir\n");
- return -1;
- }
-
- if (debugfs_create_file("info", 0644, junk, NULL, &ocm_debugfs_fops)) {
- printk(KERN_ALERT "debugfs ppc4xx ocm: failed to create file\n");
- return -1;
- }
-
- return 0;
-}
-
-void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
- int flags, const char *owner)
-{
- void __iomem *addr = NULL;
- unsigned long offset;
- struct ocm_info *ocm;
- struct ocm_region *ocm_reg;
- struct ocm_block *ocm_blk;
- int i;
-
- for (i = 0; i < ocm_count; i++) {
- ocm = ocm_get_node(i);
-
- if (!ocm || !ocm->ready)
- continue;
-
- if (flags == PPC4XX_OCM_NON_CACHED)
- ocm_reg = &ocm->nc;
- else
- ocm_reg = &ocm->c;
-
- if (!ocm_reg->virt)
- continue;
-
- if (align < ocm->alignment)
- align = ocm->alignment;
-
- offset = rh_alloc_align(ocm_reg->rh, size, align, NULL);
-
- if (IS_ERR_VALUE(offset))
- continue;
-
- ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
- if (!ocm_blk) {
- printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
- rh_free(ocm_reg->rh, offset);
- break;
- }
-
- *phys = ocm_reg->phys + offset;
- addr = ocm_reg->virt + offset;
- size = ALIGN(size, align);
-
- ocm_blk->addr = addr;
- ocm_blk->size = size;
- ocm_blk->owner = owner;
- list_add_tail(&ocm_blk->list, &ocm_reg->list);
-
- ocm_reg->memfree -= size;
-
- break;
- }
-
- return addr;
-}
-
-void ppc4xx_ocm_free(const void *addr)
-{
- int i;
-
- if (!addr)
- return;
-
- for (i = 0; i < ocm_count; i++) {
- struct ocm_info *ocm = ocm_get_node(i);
-
- if (!ocm || !ocm->ready)
- continue;
-
- if (ocm_free_region(&ocm->nc, addr) ||
- ocm_free_region(&ocm->c, addr))
- return;
- }
-}
-
-static int __init ppc4xx_ocm_init(void)
-{
- struct device_node *np;
- int count;
-
- count = 0;
- for_each_compatible_node(np, NULL, "ibm,ocm")
- count++;
-
- if (!count)
- return 0;
-
- ocm_nodes = kzalloc((count * sizeof(struct ocm_info)), GFP_KERNEL);
- if (!ocm_nodes) {
- printk(KERN_ERR "PPC4XX OCM: failed to allocate OCM nodes!\n");
- return -ENOMEM;
- }
-
- ocm_count = count;
- count = 0;
-
- for_each_compatible_node(np, NULL, "ibm,ocm") {
- ocm_init_node(count, np);
- count++;
- }
-
- ocm_debugfs_init();
-
- return 0;
-}
-
-arch_initcall(ppc4xx_ocm_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
deleted file mode 100644
index 086aca69ecae..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ /dev/null
@@ -1,2202 +0,0 @@
-/*
- * PCI / PCI-X / PCI-Express support for 4xx parts
- *
- * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- *
- * Most PCI Express code is coming from Stefan Roese implementation for
- * arch/ppc in the Denx tree, slightly reworked by me.
- *
- * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
- *
- * Some of that comes itself from a previous implementation for 440SPE only
- * by Roland Dreier:
- *
- * Copyright (c) 2005 Cisco Systems. All rights reserved.
- * Roland Dreier <rolandd@cisco.com>
- *
- */
-
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#include <mm/mmu_decl.h>
-
-#include "ppc4xx_pci.h"
-
-static int dma_offset_set;
-
-#define U64_TO_U32_LOW(val) ((u32)((val) & 0x00000000ffffffffULL))
-#define U64_TO_U32_HIGH(val) ((u32)((val) >> 32))
-
-#define RES_TO_U32_LOW(val) \
- ((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_LOW(val) : (val))
-#define RES_TO_U32_HIGH(val) \
- ((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_HIGH(val) : (0))
-
-static inline int ppc440spe_revA(void)
-{
- /* Catch both 440SPe variants, with and without RAID6 support */
- if ((mfspr(SPRN_PVR) & 0xffefffff) == 0x53421890)
- return 1;
- else
- return 0;
-}
-
-static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
-{
- struct pci_controller *hose;
- int i;
-
- if (dev->devfn != 0 || dev->bus->self != NULL)
- return;
-
- hose = pci_bus_to_host(dev->bus);
- if (hose == NULL)
- return;
-
- if (!of_device_is_compatible(hose->dn, "ibm,plb-pciex") &&
- !of_device_is_compatible(hose->dn, "ibm,plb-pcix") &&
- !of_device_is_compatible(hose->dn, "ibm,plb-pci"))
- return;
-
- if (of_device_is_compatible(hose->dn, "ibm,plb440epx-pci") ||
- of_device_is_compatible(hose->dn, "ibm,plb440grx-pci")) {
- hose->indirect_type |= PPC_INDIRECT_TYPE_BROKEN_MRM;
- }
-
- /* Hide the PCI host BARs from the kernel as their content doesn't
- * fit well in the resource management
- */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- }
-
- printk(KERN_INFO "PCI: Hiding 4xx host bridge resources %s\n",
- pci_name(dev));
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_ppc4xx_pci_bridge);
-
-static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
- void __iomem *reg,
- struct resource *res)
-{
- u64 size;
- const u32 *ranges;
- int rlen;
- int pna = of_n_addr_cells(hose->dn);
- int np = pna + 5;
-
- /* Default */
- res->start = 0;
- size = 0x80000000;
- res->end = size - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
- /* Get dma-ranges property */
- ranges = of_get_property(hose->dn, "dma-ranges", &rlen);
- if (ranges == NULL)
- goto out;
-
- /* Walk it */
- while ((rlen -= np * 4) >= 0) {
- u32 pci_space = ranges[0];
- u64 pci_addr = of_read_number(ranges + 1, 2);
- u64 cpu_addr = of_translate_dma_address(hose->dn, ranges + 3);
- size = of_read_number(ranges + pna + 3, 2);
- ranges += np;
- if (cpu_addr == OF_BAD_ADDR || size == 0)
- continue;
-
- /* We only care about memory */
- if ((pci_space & 0x03000000) != 0x02000000)
- continue;
-
- /* We currently only support memory at 0, and pci_addr
- * within 32 bits space
- */
- if (cpu_addr != 0 || pci_addr > 0xffffffff) {
- printk(KERN_WARNING "%s: Ignored unsupported dma range"
- " 0x%016llx...0x%016llx -> 0x%016llx\n",
- hose->dn->full_name,
- pci_addr, pci_addr + size - 1, cpu_addr);
- continue;
- }
-
- /* Check if not prefetchable */
- if (!(pci_space & 0x40000000))
- res->flags &= ~IORESOURCE_PREFETCH;
-
-
- /* Use that */
- res->start = pci_addr;
- /* Beware of 32 bits resources */
- if (sizeof(resource_size_t) == sizeof(u32) &&
- (pci_addr + size) > 0x100000000ull)
- res->end = 0xffffffff;
- else
- res->end = res->start + size - 1;
- break;
- }
-
- /* We only support one global DMA offset */
- if (dma_offset_set && pci_dram_offset != res->start) {
- printk(KERN_ERR "%s: dma-ranges(s) mismatch\n",
- hose->dn->full_name);
- return -ENXIO;
- }
-
- /* Check that we can fit all of memory as we don't support
- * DMA bounce buffers
- */
- if (size < total_memory) {
- printk(KERN_ERR "%s: dma-ranges too small "
- "(size=%llx total_memory=%llx)\n",
- hose->dn->full_name, size, (u64)total_memory);
- return -ENXIO;
- }
-
- /* Check we are a power of 2 size and that base is a multiple of size*/
- if ((size & (size - 1)) != 0 ||
- (res->start & (size - 1)) != 0) {
- printk(KERN_ERR "%s: dma-ranges unaligned\n",
- hose->dn->full_name);
- return -ENXIO;
- }
-
- /* Check that we are fully contained within 32 bits space if we are not
- * running on a 460sx or 476fpe which have 64 bit bus addresses.
- */
- if (res->end > 0xffffffff &&
- !(of_device_is_compatible(hose->dn, "ibm,plb-pciex-460sx")
- || of_device_is_compatible(hose->dn, "ibm,plb-pciex-476fpe"))) {
- printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
- hose->dn->full_name);
- return -ENXIO;
- }
- out:
- dma_offset_set = 1;
- pci_dram_offset = res->start;
- hose->dma_window_base_cur = res->start;
- hose->dma_window_size = resource_size(res);
-
- printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n",
- pci_dram_offset);
- printk(KERN_INFO "4xx PCI DMA window base to 0x%016llx\n",
- (unsigned long long)hose->dma_window_base_cur);
- printk(KERN_INFO "DMA window size 0x%016llx\n",
- (unsigned long long)hose->dma_window_size);
- return 0;
-}
-
-/*
- * 4xx PCI 2.x part
- */
-
-static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller *hose,
- void __iomem *reg,
- u64 plb_addr,
- u64 pci_addr,
- u64 size,
- unsigned int flags,
- int index)
-{
- u32 ma, pcila, pciha;
-
- /* Hack warning ! The "old" PCI 2.x cell only let us configure the low
- * 32-bit of incoming PLB addresses. The top 4 bits of the 36-bit
- * address are actually hard wired to a value that appears to depend
- * on the specific SoC. For example, it's 0 on 440EP and 1 on 440EPx.
- *
- * The trick here is we just crop those top bits and ignore them when
- * programming the chip. That means the device-tree has to be right
- * for the specific part used (we don't print a warning if it's wrong
- * but on the other hand, you'll crash quickly enough), but at least
- * this code should work whatever the hard coded value is
- */
- plb_addr &= 0xffffffffull;
-
- /* Note: Due to the above hack, the test below doesn't actually test
- * if you address is above 4G, but it tests that address and
- * (address + size) are both contained in the same 4G
- */
- if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
- size < 0x1000 || (plb_addr & (size - 1)) != 0) {
- printk(KERN_WARNING "%s: Resource out of range\n",
- hose->dn->full_name);
- return -1;
- }
- ma = (0xffffffffu << ilog2(size)) | 1;
- if (flags & IORESOURCE_PREFETCH)
- ma |= 2;
-
- pciha = RES_TO_U32_HIGH(pci_addr);
- pcila = RES_TO_U32_LOW(pci_addr);
-
- writel(plb_addr, reg + PCIL0_PMM0LA + (0x10 * index));
- writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * index));
- writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * index));
- writel(ma, reg + PCIL0_PMM0MA + (0x10 * index));
-
- return 0;
-}
-
-static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
- void __iomem *reg)
-{
- int i, j, found_isa_hole = 0;
-
- /* Setup outbound memory windows */
- for (i = j = 0; i < 3; i++) {
- struct resource *res = &hose->mem_resources[i];
- resource_size_t offset = hose->mem_offset[i];
-
- /* we only care about memory windows */
- if (!(res->flags & IORESOURCE_MEM))
- continue;
- if (j > 2) {
- printk(KERN_WARNING "%s: Too many ranges\n",
- hose->dn->full_name);
- break;
- }
-
- /* Configure the resource */
- if (ppc4xx_setup_one_pci_PMM(hose, reg,
- res->start,
- res->start - offset,
- resource_size(res),
- res->flags,
- j) == 0) {
- j++;
-
- /* If the resource PCI address is 0 then we have our
- * ISA memory hole
- */
- if (res->start == offset)
- found_isa_hole = 1;
- }
- }
-
- /* Handle ISA memory hole if not already covered */
- if (j <= 2 && !found_isa_hole && hose->isa_mem_size)
- if (ppc4xx_setup_one_pci_PMM(hose, reg, hose->isa_mem_phys, 0,
- hose->isa_mem_size, 0, j) == 0)
- printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
- hose->dn->full_name);
-}
-
-static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
- void __iomem *reg,
- const struct resource *res)
-{
- resource_size_t size = resource_size(res);
- u32 sa;
-
- /* Calculate window size */
- sa = (0xffffffffu << ilog2(size)) | 1;
- sa |= 0x1;
-
- /* RAM is always at 0 local for now */
- writel(0, reg + PCIL0_PTM1LA);
- writel(sa, reg + PCIL0_PTM1MS);
-
- /* Map on PCI side */
- early_write_config_dword(hose, hose->first_busno, 0,
- PCI_BASE_ADDRESS_1, res->start);
- early_write_config_dword(hose, hose->first_busno, 0,
- PCI_BASE_ADDRESS_2, 0x00000000);
- early_write_config_word(hose, hose->first_busno, 0,
- PCI_COMMAND, 0x0006);
-}
-
-static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
-{
- /* NYI */
- struct resource rsrc_cfg;
- struct resource rsrc_reg;
- struct resource dma_window;
- struct pci_controller *hose = NULL;
- void __iomem *reg = NULL;
- const int *bus_range;
- int primary = 0;
-
- /* Check if device is enabled */
- if (!of_device_is_available(np)) {
- printk(KERN_INFO "%s: Port disabled via device-tree\n",
- np->full_name);
- return;
- }
-
- /* Fetch config space registers address */
- if (of_address_to_resource(np, 0, &rsrc_cfg)) {
- printk(KERN_ERR "%s: Can't get PCI config register base !",
- np->full_name);
- return;
- }
- /* Fetch host bridge internal registers address */
- if (of_address_to_resource(np, 3, &rsrc_reg)) {
- printk(KERN_ERR "%s: Can't get PCI internal register base !",
- np->full_name);
- return;
- }
-
- /* Check if primary bridge */
- if (of_get_property(np, "primary", NULL))
- primary = 1;
-
- /* Get bus range if any */
- bus_range = of_get_property(np, "bus-range", NULL);
-
- /* Map registers */
- reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
- if (reg == NULL) {
- printk(KERN_ERR "%s: Can't map registers !", np->full_name);
- goto fail;
- }
-
- /* Allocate the host controller data structure */
- hose = pcibios_alloc_controller(np);
- if (!hose)
- goto fail;
-
- hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- /* Setup config space */
- setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);
-
- /* Disable all windows */
- writel(0, reg + PCIL0_PMM0MA);
- writel(0, reg + PCIL0_PMM1MA);
- writel(0, reg + PCIL0_PMM2MA);
- writel(0, reg + PCIL0_PTM1MS);
- writel(0, reg + PCIL0_PTM2MS);
-
- /* Parse outbound mapping resources */
- pci_process_bridge_OF_ranges(hose, np, primary);
-
- /* Parse inbound mapping resources */
- if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
- goto fail;
-
- /* Configure outbound ranges POMs */
- ppc4xx_configure_pci_PMMs(hose, reg);
-
- /* Configure inbound ranges PIMs */
- ppc4xx_configure_pci_PTMs(hose, reg, &dma_window);
-
- /* We don't need the registers anymore */
- iounmap(reg);
- return;
-
- fail:
- if (hose)
- pcibios_free_controller(hose);
- if (reg)
- iounmap(reg);
-}
-
-/*
- * 4xx PCI-X part
- */
-
-static int __init ppc4xx_setup_one_pcix_POM(struct pci_controller *hose,
- void __iomem *reg,
- u64 plb_addr,
- u64 pci_addr,
- u64 size,
- unsigned int flags,
- int index)
-{
- u32 lah, lal, pciah, pcial, sa;
-
- if (!is_power_of_2(size) || size < 0x1000 ||
- (plb_addr & (size - 1)) != 0) {
- printk(KERN_WARNING "%s: Resource out of range\n",
- hose->dn->full_name);
- return -1;
- }
-
- /* Calculate register values */
- lah = RES_TO_U32_HIGH(plb_addr);
- lal = RES_TO_U32_LOW(plb_addr);
- pciah = RES_TO_U32_HIGH(pci_addr);
- pcial = RES_TO_U32_LOW(pci_addr);
- sa = (0xffffffffu << ilog2(size)) | 0x1;
-
- /* Program register values */
- if (index == 0) {
- writel(lah, reg + PCIX0_POM0LAH);
- writel(lal, reg + PCIX0_POM0LAL);
- writel(pciah, reg + PCIX0_POM0PCIAH);
- writel(pcial, reg + PCIX0_POM0PCIAL);
- writel(sa, reg + PCIX0_POM0SA);
- } else {
- writel(lah, reg + PCIX0_POM1LAH);
- writel(lal, reg + PCIX0_POM1LAL);
- writel(pciah, reg + PCIX0_POM1PCIAH);
- writel(pcial, reg + PCIX0_POM1PCIAL);
- writel(sa, reg + PCIX0_POM1SA);
- }
-
- return 0;
-}
-
-static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
- void __iomem *reg)
-{
- int i, j, found_isa_hole = 0;
-
- /* Setup outbound memory windows */
- for (i = j = 0; i < 3; i++) {
- struct resource *res = &hose->mem_resources[i];
- resource_size_t offset = hose->mem_offset[i];
-
- /* we only care about memory windows */
- if (!(res->flags & IORESOURCE_MEM))
- continue;
- if (j > 1) {
- printk(KERN_WARNING "%s: Too many ranges\n",
- hose->dn->full_name);
- break;
- }
-
- /* Configure the resource */
- if (ppc4xx_setup_one_pcix_POM(hose, reg,
- res->start,
- res->start - offset,
- resource_size(res),
- res->flags,
- j) == 0) {
- j++;
-
- /* If the resource PCI address is 0 then we have our
- * ISA memory hole
- */
- if (res->start == offset)
- found_isa_hole = 1;
- }
- }
-
- /* Handle ISA memory hole if not already covered */
- if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
- if (ppc4xx_setup_one_pcix_POM(hose, reg, hose->isa_mem_phys, 0,
- hose->isa_mem_size, 0, j) == 0)
- printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
- hose->dn->full_name);
-}
-
-static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
- void __iomem *reg,
- const struct resource *res,
- int big_pim,
- int enable_msi_hole)
-{
- resource_size_t size = resource_size(res);
- u32 sa;
-
- /* RAM is always at 0 */
- writel(0x00000000, reg + PCIX0_PIM0LAH);
- writel(0x00000000, reg + PCIX0_PIM0LAL);
-
- /* Calculate window size */
- sa = (0xffffffffu << ilog2(size)) | 1;
- sa |= 0x1;
- if (res->flags & IORESOURCE_PREFETCH)
- sa |= 0x2;
- if (enable_msi_hole)
- sa |= 0x4;
- writel(sa, reg + PCIX0_PIM0SA);
- if (big_pim)
- writel(0xffffffff, reg + PCIX0_PIM0SAH);
-
- /* Map on PCI side */
- writel(0x00000000, reg + PCIX0_BAR0H);
- writel(res->start, reg + PCIX0_BAR0L);
- writew(0x0006, reg + PCIX0_COMMAND);
-}
-
-static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
-{
- struct resource rsrc_cfg;
- struct resource rsrc_reg;
- struct resource dma_window;
- struct pci_controller *hose = NULL;
- void __iomem *reg = NULL;
- const int *bus_range;
- int big_pim = 0, msi = 0, primary = 0;
-
- /* Fetch config space registers address */
- if (of_address_to_resource(np, 0, &rsrc_cfg)) {
- printk(KERN_ERR "%s:Can't get PCI-X config register base !",
- np->full_name);
- return;
- }
- /* Fetch host bridge internal registers address */
- if (of_address_to_resource(np, 3, &rsrc_reg)) {
- printk(KERN_ERR "%s: Can't get PCI-X internal register base !",
- np->full_name);
- return;
- }
-
- /* Check if it supports large PIMs (440GX) */
- if (of_get_property(np, "large-inbound-windows", NULL))
- big_pim = 1;
-
- /* Check if we should enable MSIs inbound hole */
- if (of_get_property(np, "enable-msi-hole", NULL))
- msi = 1;
-
- /* Check if primary bridge */
- if (of_get_property(np, "primary", NULL))
- primary = 1;
-
- /* Get bus range if any */
- bus_range = of_get_property(np, "bus-range", NULL);
-
- /* Map registers */
- reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
- if (reg == NULL) {
- printk(KERN_ERR "%s: Can't map registers !", np->full_name);
- goto fail;
- }
-
- /* Allocate the host controller data structure */
- hose = pcibios_alloc_controller(np);
- if (!hose)
- goto fail;
-
- hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- /* Setup config space */
- setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4,
- PPC_INDIRECT_TYPE_SET_CFG_TYPE);
-
- /* Disable all windows */
- writel(0, reg + PCIX0_POM0SA);
- writel(0, reg + PCIX0_POM1SA);
- writel(0, reg + PCIX0_POM2SA);
- writel(0, reg + PCIX0_PIM0SA);
- writel(0, reg + PCIX0_PIM1SA);
- writel(0, reg + PCIX0_PIM2SA);
- if (big_pim) {
- writel(0, reg + PCIX0_PIM0SAH);
- writel(0, reg + PCIX0_PIM2SAH);
- }
-
- /* Parse outbound mapping resources */
- pci_process_bridge_OF_ranges(hose, np, primary);
-
- /* Parse inbound mapping resources */
- if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
- goto fail;
-
- /* Configure outbound ranges POMs */
- ppc4xx_configure_pcix_POMs(hose, reg);
-
- /* Configure inbound ranges PIMs */
- ppc4xx_configure_pcix_PIMs(hose, reg, &dma_window, big_pim, msi);
-
- /* We don't need the registers anymore */
- iounmap(reg);
- return;
-
- fail:
- if (hose)
- pcibios_free_controller(hose);
- if (reg)
- iounmap(reg);
-}
-
-#ifdef CONFIG_PPC4xx_PCI_EXPRESS
-
-/*
- * 4xx PCI-Express part
- *
- * We support 3 parts currently based on the compatible property:
- *
- * ibm,plb-pciex-440spe
- * ibm,plb-pciex-405ex
- * ibm,plb-pciex-460ex
- *
- * Anything else will be rejected for now as they are all subtly
- * different unfortunately.
- *
- */
-
-#define MAX_PCIE_BUS_MAPPED 0x40
-
-struct ppc4xx_pciex_port
-{
- struct pci_controller *hose;
- struct device_node *node;
- unsigned int index;
- int endpoint;
- int link;
- int has_ibpre;
- unsigned int sdr_base;
- dcr_host_t dcrs;
- struct resource cfg_space;
- struct resource utl_regs;
- void __iomem *utl_base;
-};
-
-static struct ppc4xx_pciex_port *ppc4xx_pciex_ports;
-static unsigned int ppc4xx_pciex_port_count;
-
-struct ppc4xx_pciex_hwops
-{
- bool want_sdr;
- int (*core_init)(struct device_node *np);
- int (*port_init_hw)(struct ppc4xx_pciex_port *port);
- int (*setup_utl)(struct ppc4xx_pciex_port *port);
- void (*check_link)(struct ppc4xx_pciex_port *port);
-};
-
-static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;
-
-static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
- unsigned int sdr_offset,
- unsigned int mask,
- unsigned int value,
- int timeout_ms)
-{
- u32 val;
-
- while(timeout_ms--) {
- val = mfdcri(SDR0, port->sdr_base + sdr_offset);
- if ((val & mask) == value) {
- pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
- port->index, sdr_offset, timeout_ms, val);
- return 0;
- }
- msleep(1);
- }
- return -1;
-}
-
-static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
-{
- /* Wait for reset to complete */
- if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
- printk(KERN_WARNING "PCIE%d: PGRST failed\n",
- port->index);
- return -1;
- }
- return 0;
-}
-
-
-static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
-{
- printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
-
- /* Check for card presence detect if supported, if not, just wait for
- * link unconditionally.
- *
- * note that we don't fail if there is no link, we just filter out
- * config space accesses. That way, it will be easier to implement
- * hotplug later on.
- */
- if (!port->has_ibpre ||
- !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
- 1 << 28, 1 << 28, 100)) {
- printk(KERN_INFO
- "PCIE%d: Device detected, waiting for link...\n",
- port->index);
- if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
- 0x1000, 0x1000, 2000))
- printk(KERN_WARNING
- "PCIE%d: Link up failed\n", port->index);
- else {
- printk(KERN_INFO
- "PCIE%d: link is up !\n", port->index);
- port->link = 1;
- }
- } else
- printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
-}
-
-#ifdef CONFIG_44x
-
-/* Check various reset bits of the 440SPe PCIe core */
-static int __init ppc440spe_pciex_check_reset(struct device_node *np)
-{
- u32 valPE0, valPE1, valPE2;
- int err = 0;
-
- /* SDR0_PEGPLLLCT1 reset */
- if (!(mfdcri(SDR0, PESDR0_PLLLCT1) & 0x01000000)) {
- /*
- * the PCIe core was probably already initialised
- * by firmware - let's re-reset RCSSET regs
- *
- * -- Shouldn't we also re-reset the whole thing ? -- BenH
- */
- pr_debug("PCIE: SDR0_PLLLCT1 already reset.\n");
- mtdcri(SDR0, PESDR0_440SPE_RCSSET, 0x01010000);
- mtdcri(SDR0, PESDR1_440SPE_RCSSET, 0x01010000);
- mtdcri(SDR0, PESDR2_440SPE_RCSSET, 0x01010000);
- }
-
- valPE0 = mfdcri(SDR0, PESDR0_440SPE_RCSSET);
- valPE1 = mfdcri(SDR0, PESDR1_440SPE_RCSSET);
- valPE2 = mfdcri(SDR0, PESDR2_440SPE_RCSSET);
-
- /* SDR0_PExRCSSET rstgu */
- if (!(valPE0 & 0x01000000) ||
- !(valPE1 & 0x01000000) ||
- !(valPE2 & 0x01000000)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstgu error\n");
- err = -1;
- }
-
- /* SDR0_PExRCSSET rstdl */
- if (!(valPE0 & 0x00010000) ||
- !(valPE1 & 0x00010000) ||
- !(valPE2 & 0x00010000)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstdl error\n");
- err = -1;
- }
-
- /* SDR0_PExRCSSET rstpyn */
- if ((valPE0 & 0x00001000) ||
- (valPE1 & 0x00001000) ||
- (valPE2 & 0x00001000)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstpyn error\n");
- err = -1;
- }
-
- /* SDR0_PExRCSSET hldplb */
- if ((valPE0 & 0x10000000) ||
- (valPE1 & 0x10000000) ||
- (valPE2 & 0x10000000)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET hldplb error\n");
- err = -1;
- }
-
- /* SDR0_PExRCSSET rdy */
- if ((valPE0 & 0x00100000) ||
- (valPE1 & 0x00100000) ||
- (valPE2 & 0x00100000)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET rdy error\n");
- err = -1;
- }
-
- /* SDR0_PExRCSSET shutdown */
- if ((valPE0 & 0x00000100) ||
- (valPE1 & 0x00000100) ||
- (valPE2 & 0x00000100)) {
- printk(KERN_INFO "PCIE: SDR0_PExRCSSET shutdown error\n");
- err = -1;
- }
-
- return err;
-}
-
-/* Global PCIe core initializations for 440SPe core */
-static int __init ppc440spe_pciex_core_init(struct device_node *np)
-{
- int time_out = 20;
-
- /* Set PLL clock receiver to LVPECL */
- dcri_clrset(SDR0, PESDR0_PLLLCT1, 0, 1 << 28);
-
- /* Shouldn't we do all the calibration stuff etc... here ? */
- if (ppc440spe_pciex_check_reset(np))
- return -ENXIO;
-
- if (!(mfdcri(SDR0, PESDR0_PLLLCT2) & 0x10000)) {
- printk(KERN_INFO "PCIE: PESDR_PLLCT2 resistance calibration "
- "failed (0x%08x)\n",
- mfdcri(SDR0, PESDR0_PLLLCT2));
- return -1;
- }
-
- /* De-assert reset of PCIe PLL, wait for lock */
- dcri_clrset(SDR0, PESDR0_PLLLCT1, 1 << 24, 0);
- udelay(3);
-
- while (time_out) {
- if (!(mfdcri(SDR0, PESDR0_PLLLCT3) & 0x10000000)) {
- time_out--;
- udelay(1);
- } else
- break;
- }
- if (!time_out) {
- printk(KERN_INFO "PCIE: VCO output not locked\n");
- return -1;
- }
-
- pr_debug("PCIE initialization OK\n");
-
- return 3;
-}
-
-static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- u32 val = 1 << 24;
-
- if (port->endpoint)
- val = PTYPE_LEGACY_ENDPOINT << 20;
- else
- val = PTYPE_ROOT_PORT << 20;
-
- if (port->index == 0)
- val |= LNKW_X8 << 12;
- else
- val |= LNKW_X4 << 12;
-
- mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x20222222);
- if (ppc440spe_revA())
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x11000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL0SET1, 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL1SET1, 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL2SET1, 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL3SET1, 0x35000000);
- if (port->index == 0) {
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL4SET1,
- 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL5SET1,
- 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL6SET1,
- 0x35000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1,
- 0x35000000);
- }
- dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
- (1 << 24) | (1 << 16), 1 << 12);
-
- return ppc4xx_pciex_port_reset_sdr(port);
-}
-
-static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- return ppc440spe_pciex_init_port_hw(port);
-}
-
-static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- int rc = ppc440spe_pciex_init_port_hw(port);
-
- port->has_ibpre = 1;
-
- return rc;
-}
-
-static int ppc440speA_pciex_init_utl(struct ppc4xx_pciex_port *port)
-{
- /* XXX Check what that value means... I hate magic */
- dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x68782800);
-
- /*
- * Set buffer allocations and then assert VRB and TXE.
- */
- out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000);
- out_be32(port->utl_base + PEUTL_INTR, 0x02000000);
- out_be32(port->utl_base + PEUTL_OPDBSZ, 0x10000000);
- out_be32(port->utl_base + PEUTL_PBBSZ, 0x53000000);
- out_be32(port->utl_base + PEUTL_IPHBSZ, 0x08000000);
- out_be32(port->utl_base + PEUTL_IPDBSZ, 0x10000000);
- out_be32(port->utl_base + PEUTL_RCIRQEN, 0x00f00000);
- out_be32(port->utl_base + PEUTL_PCTL, 0x80800066);
-
- return 0;
-}
-
-static int ppc440speB_pciex_init_utl(struct ppc4xx_pciex_port *port)
-{
- /* Report CRS to the operating system */
- out_be32(port->utl_base + PEUTL_PBCTL, 0x08000000);
-
- return 0;
-}
-
-static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata =
-{
- .want_sdr = true,
- .core_init = ppc440spe_pciex_core_init,
- .port_init_hw = ppc440speA_pciex_init_port_hw,
- .setup_utl = ppc440speA_pciex_init_utl,
- .check_link = ppc4xx_pciex_check_link_sdr,
-};
-
-static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
-{
- .want_sdr = true,
- .core_init = ppc440spe_pciex_core_init,
- .port_init_hw = ppc440speB_pciex_init_port_hw,
- .setup_utl = ppc440speB_pciex_init_utl,
- .check_link = ppc4xx_pciex_check_link_sdr,
-};
-
-static int __init ppc460ex_pciex_core_init(struct device_node *np)
-{
- /* Nothing to do, return 2 ports */
- return 2;
-}
-
-static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- u32 val;
- u32 utlset1;
-
- if (port->endpoint)
- val = PTYPE_LEGACY_ENDPOINT << 20;
- else
- val = PTYPE_ROOT_PORT << 20;
-
- if (port->index == 0) {
- val |= LNKW_X1 << 12;
- utlset1 = 0x20000000;
- } else {
- val |= LNKW_X4 << 12;
- utlset1 = 0x20101101;
- }
-
- mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, utlset1);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01210000);
-
- switch (port->index) {
- case 0:
- mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130);
- mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
-
- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000);
- break;
-
- case 1:
- mtdcri(SDR0, PESDR1_460EX_L0CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000130);
- mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000130);
- mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000130);
- mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000130);
- mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);
- mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);
- mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006);
- mtdcri(SDR0, PESDR1_460EX_L3CLK, 0x00000006);
-
- mtdcri(SDR0, PESDR1_460EX_PHY_CTL_RST,0x10000000);
- break;
- }
-
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
- mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
- (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
-
- /* Poll for PHY reset */
- /* XXX FIXME add timeout */
- switch (port->index) {
- case 0:
- while (!(mfdcri(SDR0, PESDR0_460EX_RSTSTA) & 0x1))
- udelay(10);
- break;
- case 1:
- while (!(mfdcri(SDR0, PESDR1_460EX_RSTSTA) & 0x1))
- udelay(10);
- break;
- }
-
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
- (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
- ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
- PESDRx_RCSSET_RSTPYN);
-
- port->has_ibpre = 1;
-
- return ppc4xx_pciex_port_reset_sdr(port);
-}
-
-static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
-{
- dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0);
-
- /*
- * Set buffer allocations and then assert VRB and TXE.
- */
- out_be32(port->utl_base + PEUTL_PBCTL, 0x0800000c);
- out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000);
- out_be32(port->utl_base + PEUTL_INTR, 0x02000000);
- out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000);
- out_be32(port->utl_base + PEUTL_PBBSZ, 0x00000000);
- out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000);
- out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000);
- out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000);
- out_be32(port->utl_base + PEUTL_PCTL, 0x80800066);
-
- return 0;
-}
-
-static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
-{
- .want_sdr = true,
- .core_init = ppc460ex_pciex_core_init,
- .port_init_hw = ppc460ex_pciex_init_port_hw,
- .setup_utl = ppc460ex_pciex_init_utl,
- .check_link = ppc4xx_pciex_check_link_sdr,
-};
-
-static int __init apm821xx_pciex_core_init(struct device_node *np)
-{
- /* Return the number of pcie port */
- return 1;
-}
-
-static int __init apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- u32 val;
-
- /*
- * Do a software reset on PCIe ports.
- * This code is to fix the issue that pci drivers doesn't re-assign
- * bus number for PCIE devices after Uboot
- * scanned and configured all the buses (eg. PCIE NIC IntelPro/1000
- * PT quad port, SAS LSI 1064E)
- */
-
- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x0);
- mdelay(10);
-
- if (port->endpoint)
- val = PTYPE_LEGACY_ENDPOINT << 20;
- else
- val = PTYPE_ROOT_PORT << 20;
-
- val |= LNKW_X1 << 12;
-
- mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000);
-
- mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
- mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130);
- mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
-
- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x10000000);
- mdelay(50);
- mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x30000000);
-
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
- mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
- (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
-
- /* Poll for PHY reset */
- val = PESDR0_460EX_RSTSTA - port->sdr_base;
- if (ppc4xx_pciex_wait_on_sdr(port, val, 0x1, 1, 100)) {
- printk(KERN_WARNING "%s: PCIE: Can't reset PHY\n", __func__);
- return -EBUSY;
- } else {
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
- (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
- ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
- PESDRx_RCSSET_RSTPYN);
-
- port->has_ibpre = 1;
- return 0;
- }
-}
-
-static struct ppc4xx_pciex_hwops apm821xx_pcie_hwops __initdata = {
- .want_sdr = true,
- .core_init = apm821xx_pciex_core_init,
- .port_init_hw = apm821xx_pciex_init_port_hw,
- .setup_utl = ppc460ex_pciex_init_utl,
- .check_link = ppc4xx_pciex_check_link_sdr,
-};
-
-static int __init ppc460sx_pciex_core_init(struct device_node *np)
-{
- /* HSS drive amplitude */
- mtdcri(SDR0, PESDR0_460SX_HSSL0DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL1DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL2DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL3DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL4DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL5DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL6DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR0_460SX_HSSL7DAMP, 0xB9843211);
-
- mtdcri(SDR0, PESDR1_460SX_HSSL0DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR1_460SX_HSSL1DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR1_460SX_HSSL2DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR1_460SX_HSSL3DAMP, 0xB9843211);
-
- mtdcri(SDR0, PESDR2_460SX_HSSL0DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR2_460SX_HSSL1DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR2_460SX_HSSL2DAMP, 0xB9843211);
- mtdcri(SDR0, PESDR2_460SX_HSSL3DAMP, 0xB9843211);
-
- /* HSS TX pre-emphasis */
- mtdcri(SDR0, PESDR0_460SX_HSSL0COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL1COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL2COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL3COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL4COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL5COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL6COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR0_460SX_HSSL7COEFA, 0xDCB98987);
-
- mtdcri(SDR0, PESDR1_460SX_HSSL0COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR1_460SX_HSSL1COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR1_460SX_HSSL2COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR1_460SX_HSSL3COEFA, 0xDCB98987);
-
- mtdcri(SDR0, PESDR2_460SX_HSSL0COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR2_460SX_HSSL1COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR2_460SX_HSSL2COEFA, 0xDCB98987);
- mtdcri(SDR0, PESDR2_460SX_HSSL3COEFA, 0xDCB98987);
-
- /* HSS TX calibration control */
- mtdcri(SDR0, PESDR0_460SX_HSSL1CALDRV, 0x22222222);
- mtdcri(SDR0, PESDR1_460SX_HSSL1CALDRV, 0x22220000);
- mtdcri(SDR0, PESDR2_460SX_HSSL1CALDRV, 0x22220000);
-
- /* HSS TX slew control */
- mtdcri(SDR0, PESDR0_460SX_HSSSLEW, 0xFFFFFFFF);
- mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
- mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
-
- /* Set HSS PRBS enabled */
- mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
- mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
-
- udelay(100);
-
- /* De-assert PLLRESET */
- dcri_clrset(SDR0, PESDR0_PLLLCT2, 0x00000100, 0);
-
- /* Reset DL, UTL, GPL before configuration */
- mtdcri(SDR0, PESDR0_460SX_RCSSET,
- PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
- mtdcri(SDR0, PESDR1_460SX_RCSSET,
- PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
- mtdcri(SDR0, PESDR2_460SX_RCSSET,
- PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
-
- udelay(100);
-
- /*
- * If bifurcation is not enabled, u-boot would have disabled the
- * third PCIe port
- */
- if (((mfdcri(SDR0, PESDR1_460SX_HSSCTLSET) & 0x00000001) ==
- 0x00000001)) {
- printk(KERN_INFO "PCI: PCIE bifurcation setup successfully.\n");
- printk(KERN_INFO "PCI: Total 3 PCIE ports are present\n");
- return 3;
- }
-
- printk(KERN_INFO "PCI: Total 2 PCIE ports are present\n");
- return 2;
-}
-
-static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
-
- if (port->endpoint)
- dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
- 0x01000000, 0);
- else
- dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
- 0, 0x01000000);
-
- dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
- (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
- PESDRx_RCSSET_RSTPYN);
-
- port->has_ibpre = 1;
-
- return ppc4xx_pciex_port_reset_sdr(port);
-}
-
-static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
-{
- /* Max 128 Bytes */
- out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000);
- /* Assert VRB and TXE - per datasheet turn off addr validation */
- out_be32(port->utl_base + PEUTL_PCTL, 0x80800000);
- return 0;
-}
-
-static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
-{
- void __iomem *mbase;
- int attempt = 50;
-
- port->link = 0;
-
- mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
- if (mbase == NULL) {
- printk(KERN_ERR "%s: Can't map internal config space !",
- port->node->full_name);
- goto done;
- }
-
- while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
- & PECFG_460SX_DLLSTA_LINKUP))) {
- attempt--;
- mdelay(10);
- }
- if (attempt)
- port->link = 1;
-done:
- iounmap(mbase);
-
-}
-
-static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
- .want_sdr = true,
- .core_init = ppc460sx_pciex_core_init,
- .port_init_hw = ppc460sx_pciex_init_port_hw,
- .setup_utl = ppc460sx_pciex_init_utl,
- .check_link = ppc460sx_pciex_check_link,
-};
-
-#endif /* CONFIG_44x */
-
-#ifdef CONFIG_40x
-
-static int __init ppc405ex_pciex_core_init(struct device_node *np)
-{
- /* Nothing to do, return 2 ports */
- return 2;
-}
-
-static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port)
-{
- /* Assert the PE0_PHY reset */
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01010000);
- msleep(1);
-
- /* deassert the PE0_hotreset */
- if (port->endpoint)
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01111000);
- else
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01101000);
-
- /* poll for phy !reset */
- /* XXX FIXME add timeout */
- while (!(mfdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSTA) & 0x00001000))
- ;
-
- /* deassert the PE0_gpl_utl_reset */
- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);
-}
-
-static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
-{
- u32 val;
-
- if (port->endpoint)
- val = PTYPE_LEGACY_ENDPOINT;
- else
- val = PTYPE_ROOT_PORT;
-
- mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET,
- 1 << 24 | val << 20 | LNKW_X1 << 12);
-
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000);
- mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000);
- mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET1, 0x720F0000);
- mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET2, 0x70600003);
-
- /*
- * Only reset the PHY when no link is currently established.
- * This is for the Atheros PCIe board which has problems to establish
- * the link (again) after this PHY reset. All other currently tested
- * PCIe boards don't show this problem.
- * This has to be re-tested and fixed in a later release!
- */
- val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP);
- if (!(val & 0x00001000))
- ppc405ex_pcie_phy_reset(port);
-
- dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */
-
- port->has_ibpre = 1;
-
- return ppc4xx_pciex_port_reset_sdr(port);
-}
-
-static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
-{
- dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0);
-
- /*
- * Set buffer allocations and then assert VRB and TXE.
- */
- out_be32(port->utl_base + PEUTL_OUTTR, 0x02000000);
- out_be32(port->utl_base + PEUTL_INTR, 0x02000000);
- out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000);
- out_be32(port->utl_base + PEUTL_PBBSZ, 0x21000000);
- out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000);
- out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000);
- out_be32(port->utl_base + PEUTL_RCIRQEN, 0x00f00000);
- out_be32(port->utl_base + PEUTL_PCTL, 0x80800066);
-
- out_be32(port->utl_base + PEUTL_PBCTL, 0x08000000);
-
- return 0;
-}
-
-static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
-{
- .want_sdr = true,
- .core_init = ppc405ex_pciex_core_init,
- .port_init_hw = ppc405ex_pciex_init_port_hw,
- .setup_utl = ppc405ex_pciex_init_utl,
- .check_link = ppc4xx_pciex_check_link_sdr,
-};
-
-#endif /* CONFIG_40x */
-
-#ifdef CONFIG_476FPE
-static int __init ppc_476fpe_pciex_core_init(struct device_node *np)
-{
- return 4;
-}
-
-static void __init ppc_476fpe_pciex_check_link(struct ppc4xx_pciex_port *port)
-{
- u32 timeout_ms = 20;
- u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT);
- void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000,
- 0x1000);
-
- printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
-
- if (mbase == NULL) {
- printk(KERN_WARNING "PCIE%d: failed to get cfg space\n",
- port->index);
- return;
- }
-
- while (timeout_ms--) {
- val = in_le32(mbase + PECFG_TLDLP);
-
- if ((val & mask) == mask)
- break;
- msleep(10);
- }
-
- if (val & PECFG_TLDLP_PRESENT) {
- printk(KERN_INFO "PCIE%d: link is up !\n", port->index);
- port->link = 1;
- } else
- printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index);
-
- iounmap(mbase);
- return;
-}
-
-static struct ppc4xx_pciex_hwops ppc_476fpe_pcie_hwops __initdata =
-{
- .core_init = ppc_476fpe_pciex_core_init,
- .check_link = ppc_476fpe_pciex_check_link,
-};
-#endif /* CONFIG_476FPE */
-
-/* Check that the core has been initied and if not, do it */
-static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
-{
- static int core_init;
- int count = -ENODEV;
-
- if (core_init++)
- return 0;
-
-#ifdef CONFIG_44x
- if (of_device_is_compatible(np, "ibm,plb-pciex-440spe")) {
- if (ppc440spe_revA())
- ppc4xx_pciex_hwops = &ppc440speA_pcie_hwops;
- else
- ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops;
- }
- if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
- ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
- if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
- ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops;
- if (of_device_is_compatible(np, "ibm,plb-pciex-apm821xx"))
- ppc4xx_pciex_hwops = &apm821xx_pcie_hwops;
-#endif /* CONFIG_44x */
-#ifdef CONFIG_40x
- if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
- ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
-#endif
-#ifdef CONFIG_476FPE
- if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe")
- || of_device_is_compatible(np, "ibm,plb-pciex-476gtr"))
- ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops;
-#endif
- if (ppc4xx_pciex_hwops == NULL) {
- printk(KERN_WARNING "PCIE: unknown host type %s\n",
- np->full_name);
- return -ENODEV;
- }
-
- count = ppc4xx_pciex_hwops->core_init(np);
- if (count > 0) {
- ppc4xx_pciex_ports =
- kzalloc(count * sizeof(struct ppc4xx_pciex_port),
- GFP_KERNEL);
- if (ppc4xx_pciex_ports) {
- ppc4xx_pciex_port_count = count;
- return 0;
- }
- printk(KERN_WARNING "PCIE: failed to allocate ports array\n");
- return -ENOMEM;
- }
- return -ENODEV;
-}
-
-static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port)
-{
- /* We map PCI Express configuration based on the reg property */
- dcr_write(port->dcrs, DCRO_PEGPL_CFGBAH,
- RES_TO_U32_HIGH(port->cfg_space.start));
- dcr_write(port->dcrs, DCRO_PEGPL_CFGBAL,
- RES_TO_U32_LOW(port->cfg_space.start));
-
- /* XXX FIXME: Use size from reg property. For now, map 512M */
- dcr_write(port->dcrs, DCRO_PEGPL_CFGMSK, 0xe0000001);
-
- /* We map UTL registers based on the reg property */
- dcr_write(port->dcrs, DCRO_PEGPL_REGBAH,
- RES_TO_U32_HIGH(port->utl_regs.start));
- dcr_write(port->dcrs, DCRO_PEGPL_REGBAL,
- RES_TO_U32_LOW(port->utl_regs.start));
-
- /* XXX FIXME: Use size from reg property */
- dcr_write(port->dcrs, DCRO_PEGPL_REGMSK, 0x00007001);
-
- /* Disable all other outbound windows */
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, 0);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, 0);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0);
- dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);
-}
-
-static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
-{
- int rc = 0;
-
- /* Init HW */
- if (ppc4xx_pciex_hwops->port_init_hw)
- rc = ppc4xx_pciex_hwops->port_init_hw(port);
- if (rc != 0)
- return rc;
-
- /*
- * Initialize mapping: disable all regions and configure
- * CFG and REG regions based on resources in the device tree
- */
- ppc4xx_pciex_port_init_mapping(port);
-
- if (ppc4xx_pciex_hwops->check_link)
- ppc4xx_pciex_hwops->check_link(port);
-
- /*
- * Map UTL
- */
- port->utl_base = ioremap(port->utl_regs.start, 0x100);
- BUG_ON(port->utl_base == NULL);
-
- /*
- * Setup UTL registers --BenH.
- */
- if (ppc4xx_pciex_hwops->setup_utl)
- ppc4xx_pciex_hwops->setup_utl(port);
-
- /*
- * Check for VC0 active or PLL Locked and assert RDY.
- */
- if (port->sdr_base) {
- if (of_device_is_compatible(port->node,
- "ibm,plb-pciex-460sx")){
- if (port->link && ppc4xx_pciex_wait_on_sdr(port,
- PESDRn_RCSSTS,
- 1 << 12, 1 << 12, 5000)) {
- printk(KERN_INFO "PCIE%d: PLL not locked\n",
- port->index);
- port->link = 0;
- }
- } else if (port->link &&
- ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
- 1 << 16, 1 << 16, 5000)) {
- printk(KERN_INFO "PCIE%d: VC0 not active\n",
- port->index);
- port->link = 0;
- }
-
- dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
- }
-
- msleep(100);
-
- return 0;
-}
-
-static int ppc4xx_pciex_validate_bdf(struct ppc4xx_pciex_port *port,
- struct pci_bus *bus,
- unsigned int devfn)
-{
- static int message;
-
- /* Endpoint can not generate upstream(remote) config cycles */
- if (port->endpoint && bus->number != port->hose->first_busno)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Check we are within the mapped range */
- if (bus->number > port->hose->last_busno) {
- if (!message) {
- printk(KERN_WARNING "Warning! Probing bus %u"
- " out of range !\n", bus->number);
- message++;
- }
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- /* The root complex has only one device / function */
- if (bus->number == port->hose->first_busno && devfn != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* The other side of the RC has only one device as well */
- if (bus->number == (port->hose->first_busno + 1) &&
- PCI_SLOT(devfn) != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Check if we have a link */
- if ((bus->number != port->hose->first_busno) && !port->link)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return 0;
-}
-
-static void __iomem *ppc4xx_pciex_get_config_base(struct ppc4xx_pciex_port *port,
- struct pci_bus *bus,
- unsigned int devfn)
-{
- int relbus;
-
- /* Remove the casts when we finally remove the stupid volatile
- * in struct pci_controller
- */
- if (bus->number == port->hose->first_busno)
- return (void __iomem *)port->hose->cfg_addr;
-
- relbus = bus->number - (port->hose->first_busno + 1);
- return (void __iomem *)port->hose->cfg_data +
- ((relbus << 20) | (devfn << 12));
-}
-
-static int ppc4xx_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct ppc4xx_pciex_port *port =
- &ppc4xx_pciex_ports[hose->indirect_type];
- void __iomem *addr;
- u32 gpl_cfg;
-
- BUG_ON(hose != port->hose);
-
- if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = ppc4xx_pciex_get_config_base(port, bus, devfn);
-
- /*
- * Reading from configuration space of non-existing device can
- * generate transaction errors. For the read duration we suppress
- * assertion of machine check exceptions to avoid those.
- */
- gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG);
- dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA);
-
- /* Make sure no CRS is recorded */
- out_be32(port->utl_base + PEUTL_RCSTA, 0x00040000);
-
- switch (len) {
- case 1:
- *val = in_8((u8 *)(addr + offset));
- break;
- case 2:
- *val = in_le16((u16 *)(addr + offset));
- break;
- default:
- *val = in_le32((u32 *)(addr + offset));
- break;
- }
-
- pr_debug("pcie-config-read: bus=%3d [%3d..%3d] devfn=0x%04x"
- " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n",
- bus->number, hose->first_busno, hose->last_busno,
- devfn, offset, len, addr + offset, *val);
-
- /* Check for CRS (440SPe rev B does that for us but heh ..) */
- if (in_be32(port->utl_base + PEUTL_RCSTA) & 0x00040000) {
- pr_debug("Got CRS !\n");
- if (len != 4 || offset != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- *val = 0xffff0001;
- }
-
- dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int ppc4xx_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct ppc4xx_pciex_port *port =
- &ppc4xx_pciex_ports[hose->indirect_type];
- void __iomem *addr;
- u32 gpl_cfg;
-
- if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr = ppc4xx_pciex_get_config_base(port, bus, devfn);
-
- /*
- * Reading from configuration space of non-existing device can
- * generate transaction errors. For the read duration we suppress
- * assertion of machine check exceptions to avoid those.
- */
- gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG);
- dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA);
-
- pr_debug("pcie-config-write: bus=%3d [%3d..%3d] devfn=0x%04x"
- " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n",
- bus->number, hose->first_busno, hose->last_busno,
- devfn, offset, len, addr + offset, val);
-
- switch (len) {
- case 1:
- out_8((u8 *)(addr + offset), val);
- break;
- case 2:
- out_le16((u16 *)(addr + offset), val);
- break;
- default:
- out_le32((u32 *)(addr + offset), val);
- break;
- }
-
- dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops ppc4xx_pciex_pci_ops =
-{
- .read = ppc4xx_pciex_read_config,
- .write = ppc4xx_pciex_write_config,
-};
-
-static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
- struct pci_controller *hose,
- void __iomem *mbase,
- u64 plb_addr,
- u64 pci_addr,
- u64 size,
- unsigned int flags,
- int index)
-{
- u32 lah, lal, pciah, pcial, sa;
-
- if (!is_power_of_2(size) ||
- (index < 2 && size < 0x100000) ||
- (index == 2 && size < 0x100) ||
- (plb_addr & (size - 1)) != 0) {
- printk(KERN_WARNING "%s: Resource out of range\n",
- hose->dn->full_name);
- return -1;
- }
-
- /* Calculate register values */
- lah = RES_TO_U32_HIGH(plb_addr);
- lal = RES_TO_U32_LOW(plb_addr);
- pciah = RES_TO_U32_HIGH(pci_addr);
- pcial = RES_TO_U32_LOW(pci_addr);
- sa = (0xffffffffu << ilog2(size)) | 0x1;
-
- /* Program register values */
- switch (index) {
- case 0:
- out_le32(mbase + PECFG_POM0LAH, pciah);
- out_le32(mbase + PECFG_POM0LAL, pcial);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
- /*Enabled and single region */
- if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
- sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
- | DCRO_PEGPL_OMRxMSKL_VAL);
- else if (of_device_is_compatible(
- port->node, "ibm,plb-pciex-476fpe") ||
- of_device_is_compatible(
- port->node, "ibm,plb-pciex-476gtr"))
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
- sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT
- | DCRO_PEGPL_OMRxMSKL_VAL);
- else
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
- sa | DCRO_PEGPL_OMR1MSKL_UOT
- | DCRO_PEGPL_OMRxMSKL_VAL);
- break;
- case 1:
- out_le32(mbase + PECFG_POM1LAH, pciah);
- out_le32(mbase + PECFG_POM1LAL, pcial);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
- sa | DCRO_PEGPL_OMRxMSKL_VAL);
- break;
- case 2:
- out_le32(mbase + PECFG_POM2LAH, pciah);
- out_le32(mbase + PECFG_POM2LAL, pcial);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
- /* Note that 3 here means enabled | IO space !!! */
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
- sa | DCRO_PEGPL_OMR3MSKL_IO
- | DCRO_PEGPL_OMRxMSKL_VAL);
- break;
- }
-
- return 0;
-}
-
-static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
- struct pci_controller *hose,
- void __iomem *mbase)
-{
- int i, j, found_isa_hole = 0;
-
- /* Setup outbound memory windows */
- for (i = j = 0; i < 3; i++) {
- struct resource *res = &hose->mem_resources[i];
- resource_size_t offset = hose->mem_offset[i];
-
- /* we only care about memory windows */
- if (!(res->flags & IORESOURCE_MEM))
- continue;
- if (j > 1) {
- printk(KERN_WARNING "%s: Too many ranges\n",
- port->node->full_name);
- break;
- }
-
- /* Configure the resource */
- if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
- res->start,
- res->start - offset,
- resource_size(res),
- res->flags,
- j) == 0) {
- j++;
-
- /* If the resource PCI address is 0 then we have our
- * ISA memory hole
- */
- if (res->start == offset)
- found_isa_hole = 1;
- }
- }
-
- /* Handle ISA memory hole if not already covered */
- if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
- if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
- hose->isa_mem_phys, 0,
- hose->isa_mem_size, 0, j) == 0)
- printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
- hose->dn->full_name);
-
- /* Configure IO, always 64K starting at 0. We hard wire it to 64K !
- * Note also that it -has- to be region index 2 on this HW
- */
- if (hose->io_resource.flags & IORESOURCE_IO)
- ppc4xx_setup_one_pciex_POM(port, hose, mbase,
- hose->io_base_phys, 0,
- 0x10000, IORESOURCE_IO, 2);
-}
-
-static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
- struct pci_controller *hose,
- void __iomem *mbase,
- struct resource *res)
-{
- resource_size_t size = resource_size(res);
- u64 sa;
-
- if (port->endpoint) {
- resource_size_t ep_addr = 0;
- resource_size_t ep_size = 32 << 20;
-
- /* Currently we map a fixed 64MByte window to PLB address
- * 0 (SDRAM). This should probably be configurable via a dts
- * property.
- */
-
- /* Calculate window size */
- sa = (0xffffffffffffffffull << ilog2(ep_size));
-
- /* Setup BAR0 */
- out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
- out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) |
- PCI_BASE_ADDRESS_MEM_TYPE_64);
-
- /* Disable BAR1 & BAR2 */
- out_le32(mbase + PECFG_BAR1MPA, 0);
- out_le32(mbase + PECFG_BAR2HMPA, 0);
- out_le32(mbase + PECFG_BAR2LMPA, 0);
-
- out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa));
- out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa));
-
- out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr));
- out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr));
- } else {
- /* Calculate window size */
- sa = (0xffffffffffffffffull << ilog2(size));
- if (res->flags & IORESOURCE_PREFETCH)
- sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
-
- if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
- of_device_is_compatible(
- port->node, "ibm,plb-pciex-476fpe") ||
- of_device_is_compatible(
- port->node, "ibm,plb-pciex-476gtr"))
- sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
-
- out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
- out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
-
- /* The setup of the split looks weird to me ... let's see
- * if it works
- */
- out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
- out_le32(mbase + PECFG_PIM0LAH, 0x00000000);
- out_le32(mbase + PECFG_PIM1LAL, 0x00000000);
- out_le32(mbase + PECFG_PIM1LAH, 0x00000000);
- out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
- out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
-
- out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start));
- out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start));
- }
-
- /* Enable inbound mapping */
- out_le32(mbase + PECFG_PIMEN, 0x1);
-
- /* Enable I/O, Mem, and Busmaster cycles */
- out_le16(mbase + PCI_COMMAND,
- in_le16(mbase + PCI_COMMAND) |
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-}
-
-static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port)
-{
- struct resource dma_window;
- struct pci_controller *hose = NULL;
- const int *bus_range;
- int primary = 0, busses;
- void __iomem *mbase = NULL, *cfg_data = NULL;
- const u32 *pval;
- u32 val;
-
- /* Check if primary bridge */
- if (of_get_property(port->node, "primary", NULL))
- primary = 1;
-
- /* Get bus range if any */
- bus_range = of_get_property(port->node, "bus-range", NULL);
-
- /* Allocate the host controller data structure */
- hose = pcibios_alloc_controller(port->node);
- if (!hose)
- goto fail;
-
- /* We stick the port number in "indirect_type" so the config space
- * ops can retrieve the port data structure easily
- */
- hose->indirect_type = port->index;
-
- /* Get bus range */
- hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- /* Because of how big mapping the config space is (1M per bus), we
- * limit how many busses we support. In the long run, we could replace
- * that with something akin to kmap_atomic instead. We set aside 1 bus
- * for the host itself too.
- */
- busses = hose->last_busno - hose->first_busno; /* This is off by 1 */
- if (busses > MAX_PCIE_BUS_MAPPED) {
- busses = MAX_PCIE_BUS_MAPPED;
- hose->last_busno = hose->first_busno + busses;
- }
-
- if (!port->endpoint) {
- /* Only map the external config space in cfg_data for
- * PCIe root-complexes. External space is 1M per bus
- */
- cfg_data = ioremap(port->cfg_space.start +
- (hose->first_busno + 1) * 0x100000,
- busses * 0x100000);
- if (cfg_data == NULL) {
- printk(KERN_ERR "%s: Can't map external config space !",
- port->node->full_name);
- goto fail;
- }
- hose->cfg_data = cfg_data;
- }
-
- /* Always map the host config space in cfg_addr.
- * Internal space is 4K
- */
- mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
- if (mbase == NULL) {
- printk(KERN_ERR "%s: Can't map internal config space !",
- port->node->full_name);
- goto fail;
- }
- hose->cfg_addr = mbase;
-
- pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name,
- hose->first_busno, hose->last_busno);
- pr_debug(" config space mapped at: root @0x%p, other @0x%p\n",
- hose->cfg_addr, hose->cfg_data);
-
- /* Setup config space */
- hose->ops = &ppc4xx_pciex_pci_ops;
- port->hose = hose;
- mbase = (void __iomem *)hose->cfg_addr;
-
- if (!port->endpoint) {
- /*
- * Set bus numbers on our root port
- */
- out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno);
- out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1);
- out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno);
- }
-
- /*
- * OMRs are already reset, also disable PIMs
- */
- out_le32(mbase + PECFG_PIMEN, 0);
-
- /* Parse outbound mapping resources */
- pci_process_bridge_OF_ranges(hose, port->node, primary);
-
- /* Parse inbound mapping resources */
- if (ppc4xx_parse_dma_ranges(hose, mbase, &dma_window) != 0)
- goto fail;
-
- /* Configure outbound ranges POMs */
- ppc4xx_configure_pciex_POMs(port, hose, mbase);
-
- /* Configure inbound ranges PIMs */
- ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window);
-
- /* The root complex doesn't show up if we don't set some vendor
- * and device IDs into it. The defaults below are the same bogus
- * one that the initial code in arch/ppc had. This can be
- * overwritten by setting the "vendor-id/device-id" properties
- * in the pciex node.
- */
-
- /* Get the (optional) vendor-/device-id from the device-tree */
- pval = of_get_property(port->node, "vendor-id", NULL);
- if (pval) {
- val = *pval;
- } else {
- if (!port->endpoint)
- val = 0xaaa0 + port->index;
- else
- val = 0xeee0 + port->index;
- }
- out_le16(mbase + 0x200, val);
-
- pval = of_get_property(port->node, "device-id", NULL);
- if (pval) {
- val = *pval;
- } else {
- if (!port->endpoint)
- val = 0xbed0 + port->index;
- else
- val = 0xfed0 + port->index;
- }
- out_le16(mbase + 0x202, val);
-
- /* Enable Bus master, memory, and io space */
- if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
- out_le16(mbase + 0x204, 0x7);
-
- if (!port->endpoint) {
- /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
- out_le32(mbase + 0x208, 0x06040001);
-
- printk(KERN_INFO "PCIE%d: successfully set as root-complex\n",
- port->index);
- } else {
- /* Set Class Code to Processor/PPC */
- out_le32(mbase + 0x208, 0x0b200001);
-
- printk(KERN_INFO "PCIE%d: successfully set as endpoint\n",
- port->index);
- }
-
- return;
- fail:
- if (hose)
- pcibios_free_controller(hose);
- if (cfg_data)
- iounmap(cfg_data);
- if (mbase)
- iounmap(mbase);
-}
-
-static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
-{
- struct ppc4xx_pciex_port *port;
- const u32 *pval;
- int portno;
- unsigned int dcrs;
- const char *val;
-
- /* First, proceed to core initialization as we assume there's
- * only one PCIe core in the system
- */
- if (ppc4xx_pciex_check_core_init(np))
- return;
-
- /* Get the port number from the device-tree */
- pval = of_get_property(np, "port", NULL);
- if (pval == NULL) {
- printk(KERN_ERR "PCIE: Can't find port number for %s\n",
- np->full_name);
- return;
- }
- portno = *pval;
- if (portno >= ppc4xx_pciex_port_count) {
- printk(KERN_ERR "PCIE: port number out of range for %s\n",
- np->full_name);
- return;
- }
- port = &ppc4xx_pciex_ports[portno];
- port->index = portno;
-
- /*
- * Check if device is enabled
- */
- if (!of_device_is_available(np)) {
- printk(KERN_INFO "PCIE%d: Port disabled via device-tree\n", port->index);
- return;
- }
-
- port->node = of_node_get(np);
- if (ppc4xx_pciex_hwops->want_sdr) {
- pval = of_get_property(np, "sdr-base", NULL);
- if (pval == NULL) {
- printk(KERN_ERR "PCIE: missing sdr-base for %s\n",
- np->full_name);
- return;
- }
- port->sdr_base = *pval;
- }
-
- /* Check if device_type property is set to "pci" or "pci-endpoint".
- * Resulting from this setup this PCIe port will be configured
- * as root-complex or as endpoint.
- */
- val = of_get_property(port->node, "device_type", NULL);
- if (!strcmp(val, "pci-endpoint")) {
- port->endpoint = 1;
- } else if (!strcmp(val, "pci")) {
- port->endpoint = 0;
- } else {
- printk(KERN_ERR "PCIE: missing or incorrect device_type for %s\n",
- np->full_name);
- return;
- }
-
- /* Fetch config space registers address */
- if (of_address_to_resource(np, 0, &port->cfg_space)) {
- printk(KERN_ERR "%s: Can't get PCI-E config space !",
- np->full_name);
- return;
- }
- /* Fetch host bridge internal registers address */
- if (of_address_to_resource(np, 1, &port->utl_regs)) {
- printk(KERN_ERR "%s: Can't get UTL register base !",
- np->full_name);
- return;
- }
-
- /* Map DCRs */
- dcrs = dcr_resource_start(np, 0);
- if (dcrs == 0) {
- printk(KERN_ERR "%s: Can't get DCR register base !",
- np->full_name);
- return;
- }
- port->dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
-
- /* Initialize the port specific registers */
- if (ppc4xx_pciex_port_init(port)) {
- printk(KERN_WARNING "PCIE%d: Port init failed\n", port->index);
- return;
- }
-
- /* Setup the linux hose data structure */
- ppc4xx_pciex_port_setup_hose(port);
-}
-
-#endif /* CONFIG_PPC4xx_PCI_EXPRESS */
-
-static int __init ppc4xx_pci_find_bridges(void)
-{
- struct device_node *np;
-
- pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
-
-#ifdef CONFIG_PPC4xx_PCI_EXPRESS
- for_each_compatible_node(np, NULL, "ibm,plb-pciex")
- ppc4xx_probe_pciex_bridge(np);
-#endif
- for_each_compatible_node(np, NULL, "ibm,plb-pcix")
- ppc4xx_probe_pcix_bridge(np);
- for_each_compatible_node(np, NULL, "ibm,plb-pci")
- ppc4xx_probe_pci_bridge(np);
-
- return 0;
-}
-arch_initcall(ppc4xx_pci_find_bridges);
-
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
deleted file mode 100644
index bb4821938ab1..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_pci.h
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * PCI / PCI-X / PCI-Express support for 4xx parts
- *
- * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- *
- * Bits and pieces extracted from arch/ppc support by
- *
- * Matt Porter <mporter@kernel.crashing.org>
- *
- * Copyright 2002-2005 MontaVista Software Inc.
- */
-#ifndef __PPC4XX_PCI_H__
-#define __PPC4XX_PCI_H__
-
-/*
- * 4xx PCI-X bridge register definitions
- */
-#define PCIX0_VENDID 0x000
-#define PCIX0_DEVID 0x002
-#define PCIX0_COMMAND 0x004
-#define PCIX0_STATUS 0x006
-#define PCIX0_REVID 0x008
-#define PCIX0_CLS 0x009
-#define PCIX0_CACHELS 0x00c
-#define PCIX0_LATTIM 0x00d
-#define PCIX0_HDTYPE 0x00e
-#define PCIX0_BIST 0x00f
-#define PCIX0_BAR0L 0x010
-#define PCIX0_BAR0H 0x014
-#define PCIX0_BAR1 0x018
-#define PCIX0_BAR2L 0x01c
-#define PCIX0_BAR2H 0x020
-#define PCIX0_BAR3 0x024
-#define PCIX0_CISPTR 0x028
-#define PCIX0_SBSYSVID 0x02c
-#define PCIX0_SBSYSID 0x02e
-#define PCIX0_EROMBA 0x030
-#define PCIX0_CAP 0x034
-#define PCIX0_RES0 0x035
-#define PCIX0_RES1 0x036
-#define PCIX0_RES2 0x038
-#define PCIX0_INTLN 0x03c
-#define PCIX0_INTPN 0x03d
-#define PCIX0_MINGNT 0x03e
-#define PCIX0_MAXLTNCY 0x03f
-#define PCIX0_BRDGOPT1 0x040
-#define PCIX0_BRDGOPT2 0x044
-#define PCIX0_ERREN 0x050
-#define PCIX0_ERRSTS 0x054
-#define PCIX0_PLBBESR 0x058
-#define PCIX0_PLBBEARL 0x05c
-#define PCIX0_PLBBEARH 0x060
-#define PCIX0_POM0LAL 0x068
-#define PCIX0_POM0LAH 0x06c
-#define PCIX0_POM0SA 0x070
-#define PCIX0_POM0PCIAL 0x074
-#define PCIX0_POM0PCIAH 0x078
-#define PCIX0_POM1LAL 0x07c
-#define PCIX0_POM1LAH 0x080
-#define PCIX0_POM1SA 0x084
-#define PCIX0_POM1PCIAL 0x088
-#define PCIX0_POM1PCIAH 0x08c
-#define PCIX0_POM2SA 0x090
-#define PCIX0_PIM0SAL 0x098
-#define PCIX0_PIM0SA PCIX0_PIM0SAL
-#define PCIX0_PIM0LAL 0x09c
-#define PCIX0_PIM0LAH 0x0a0
-#define PCIX0_PIM1SA 0x0a4
-#define PCIX0_PIM1LAL 0x0a8
-#define PCIX0_PIM1LAH 0x0ac
-#define PCIX0_PIM2SAL 0x0b0
-#define PCIX0_PIM2SA PCIX0_PIM2SAL
-#define PCIX0_PIM2LAL 0x0b4
-#define PCIX0_PIM2LAH 0x0b8
-#define PCIX0_OMCAPID 0x0c0
-#define PCIX0_OMNIPTR 0x0c1
-#define PCIX0_OMMC 0x0c2
-#define PCIX0_OMMA 0x0c4
-#define PCIX0_OMMUA 0x0c8
-#define PCIX0_OMMDATA 0x0cc
-#define PCIX0_OMMEOI 0x0ce
-#define PCIX0_PMCAPID 0x0d0
-#define PCIX0_PMNIPTR 0x0d1
-#define PCIX0_PMC 0x0d2
-#define PCIX0_PMCSR 0x0d4
-#define PCIX0_PMCSRBSE 0x0d6
-#define PCIX0_PMDATA 0x0d7
-#define PCIX0_PMSCRR 0x0d8
-#define PCIX0_CAPID 0x0dc
-#define PCIX0_NIPTR 0x0dd
-#define PCIX0_CMD 0x0de
-#define PCIX0_STS 0x0e0
-#define PCIX0_IDR 0x0e4
-#define PCIX0_CID 0x0e8
-#define PCIX0_RID 0x0ec
-#define PCIX0_PIM0SAH 0x0f8
-#define PCIX0_PIM2SAH 0x0fc
-#define PCIX0_MSGIL 0x100
-#define PCIX0_MSGIH 0x104
-#define PCIX0_MSGOL 0x108
-#define PCIX0_MSGOH 0x10c
-#define PCIX0_IM 0x1f8
-
-/*
- * 4xx PCI bridge register definitions
- */
-#define PCIL0_PMM0LA 0x00
-#define PCIL0_PMM0MA 0x04
-#define PCIL0_PMM0PCILA 0x08
-#define PCIL0_PMM0PCIHA 0x0c
-#define PCIL0_PMM1LA 0x10
-#define PCIL0_PMM1MA 0x14
-#define PCIL0_PMM1PCILA 0x18
-#define PCIL0_PMM1PCIHA 0x1c
-#define PCIL0_PMM2LA 0x20
-#define PCIL0_PMM2MA 0x24
-#define PCIL0_PMM2PCILA 0x28
-#define PCIL0_PMM2PCIHA 0x2c
-#define PCIL0_PTM1MS 0x30
-#define PCIL0_PTM1LA 0x34
-#define PCIL0_PTM2MS 0x38
-#define PCIL0_PTM2LA 0x3c
-
-/*
- * 4xx PCIe bridge register definitions
- */
-
-/* DCR offsets */
-#define DCRO_PEGPL_CFGBAH 0x00
-#define DCRO_PEGPL_CFGBAL 0x01
-#define DCRO_PEGPL_CFGMSK 0x02
-#define DCRO_PEGPL_MSGBAH 0x03
-#define DCRO_PEGPL_MSGBAL 0x04
-#define DCRO_PEGPL_MSGMSK 0x05
-#define DCRO_PEGPL_OMR1BAH 0x06
-#define DCRO_PEGPL_OMR1BAL 0x07
-#define DCRO_PEGPL_OMR1MSKH 0x08
-#define DCRO_PEGPL_OMR1MSKL 0x09
-#define DCRO_PEGPL_OMR2BAH 0x0a
-#define DCRO_PEGPL_OMR2BAL 0x0b
-#define DCRO_PEGPL_OMR2MSKH 0x0c
-#define DCRO_PEGPL_OMR2MSKL 0x0d
-#define DCRO_PEGPL_OMR3BAH 0x0e
-#define DCRO_PEGPL_OMR3BAL 0x0f
-#define DCRO_PEGPL_OMR3MSKH 0x10
-#define DCRO_PEGPL_OMR3MSKL 0x11
-#define DCRO_PEGPL_REGBAH 0x12
-#define DCRO_PEGPL_REGBAL 0x13
-#define DCRO_PEGPL_REGMSK 0x14
-#define DCRO_PEGPL_SPECIAL 0x15
-#define DCRO_PEGPL_CFG 0x16
-#define DCRO_PEGPL_ESR 0x17
-#define DCRO_PEGPL_EARH 0x18
-#define DCRO_PEGPL_EARL 0x19
-#define DCRO_PEGPL_EATR 0x1a
-
-/* DMER mask */
-#define GPL_DMER_MASK_DISA 0x02000000
-
-/*
- * System DCRs (SDRs)
- */
-#define PESDR0_PLLLCT1 0x03a0
-#define PESDR0_PLLLCT2 0x03a1
-#define PESDR0_PLLLCT3 0x03a2
-
-/*
- * 440SPe additional DCRs
- */
-#define PESDR0_440SPE_UTLSET1 0x0300
-#define PESDR0_440SPE_UTLSET2 0x0301
-#define PESDR0_440SPE_DLPSET 0x0302
-#define PESDR0_440SPE_LOOP 0x0303
-#define PESDR0_440SPE_RCSSET 0x0304
-#define PESDR0_440SPE_RCSSTS 0x0305
-#define PESDR0_440SPE_HSSL0SET1 0x0306
-#define PESDR0_440SPE_HSSL0SET2 0x0307
-#define PESDR0_440SPE_HSSL0STS 0x0308
-#define PESDR0_440SPE_HSSL1SET1 0x0309
-#define PESDR0_440SPE_HSSL1SET2 0x030a
-#define PESDR0_440SPE_HSSL1STS 0x030b
-#define PESDR0_440SPE_HSSL2SET1 0x030c
-#define PESDR0_440SPE_HSSL2SET2 0x030d
-#define PESDR0_440SPE_HSSL2STS 0x030e
-#define PESDR0_440SPE_HSSL3SET1 0x030f
-#define PESDR0_440SPE_HSSL3SET2 0x0310
-#define PESDR0_440SPE_HSSL3STS 0x0311
-#define PESDR0_440SPE_HSSL4SET1 0x0312
-#define PESDR0_440SPE_HSSL4SET2 0x0313
-#define PESDR0_440SPE_HSSL4STS 0x0314
-#define PESDR0_440SPE_HSSL5SET1 0x0315
-#define PESDR0_440SPE_HSSL5SET2 0x0316
-#define PESDR0_440SPE_HSSL5STS 0x0317
-#define PESDR0_440SPE_HSSL6SET1 0x0318
-#define PESDR0_440SPE_HSSL6SET2 0x0319
-#define PESDR0_440SPE_HSSL6STS 0x031a
-#define PESDR0_440SPE_HSSL7SET1 0x031b
-#define PESDR0_440SPE_HSSL7SET2 0x031c
-#define PESDR0_440SPE_HSSL7STS 0x031d
-#define PESDR0_440SPE_HSSCTLSET 0x031e
-#define PESDR0_440SPE_LANE_ABCD 0x031f
-#define PESDR0_440SPE_LANE_EFGH 0x0320
-
-#define PESDR1_440SPE_UTLSET1 0x0340
-#define PESDR1_440SPE_UTLSET2 0x0341
-#define PESDR1_440SPE_DLPSET 0x0342
-#define PESDR1_440SPE_LOOP 0x0343
-#define PESDR1_440SPE_RCSSET 0x0344
-#define PESDR1_440SPE_RCSSTS 0x0345
-#define PESDR1_440SPE_HSSL0SET1 0x0346
-#define PESDR1_440SPE_HSSL0SET2 0x0347
-#define PESDR1_440SPE_HSSL0STS 0x0348
-#define PESDR1_440SPE_HSSL1SET1 0x0349
-#define PESDR1_440SPE_HSSL1SET2 0x034a
-#define PESDR1_440SPE_HSSL1STS 0x034b
-#define PESDR1_440SPE_HSSL2SET1 0x034c
-#define PESDR1_440SPE_HSSL2SET2 0x034d
-#define PESDR1_440SPE_HSSL2STS 0x034e
-#define PESDR1_440SPE_HSSL3SET1 0x034f
-#define PESDR1_440SPE_HSSL3SET2 0x0350
-#define PESDR1_440SPE_HSSL3STS 0x0351
-#define PESDR1_440SPE_HSSCTLSET 0x0352
-#define PESDR1_440SPE_LANE_ABCD 0x0353
-
-#define PESDR2_440SPE_UTLSET1 0x0370
-#define PESDR2_440SPE_UTLSET2 0x0371
-#define PESDR2_440SPE_DLPSET 0x0372
-#define PESDR2_440SPE_LOOP 0x0373
-#define PESDR2_440SPE_RCSSET 0x0374
-#define PESDR2_440SPE_RCSSTS 0x0375
-#define PESDR2_440SPE_HSSL0SET1 0x0376
-#define PESDR2_440SPE_HSSL0SET2 0x0377
-#define PESDR2_440SPE_HSSL0STS 0x0378
-#define PESDR2_440SPE_HSSL1SET1 0x0379
-#define PESDR2_440SPE_HSSL1SET2 0x037a
-#define PESDR2_440SPE_HSSL1STS 0x037b
-#define PESDR2_440SPE_HSSL2SET1 0x037c
-#define PESDR2_440SPE_HSSL2SET2 0x037d
-#define PESDR2_440SPE_HSSL2STS 0x037e
-#define PESDR2_440SPE_HSSL3SET1 0x037f
-#define PESDR2_440SPE_HSSL3SET2 0x0380
-#define PESDR2_440SPE_HSSL3STS 0x0381
-#define PESDR2_440SPE_HSSCTLSET 0x0382
-#define PESDR2_440SPE_LANE_ABCD 0x0383
-
-/*
- * 405EX additional DCRs
- */
-#define PESDR0_405EX_UTLSET1 0x0400
-#define PESDR0_405EX_UTLSET2 0x0401
-#define PESDR0_405EX_DLPSET 0x0402
-#define PESDR0_405EX_LOOP 0x0403
-#define PESDR0_405EX_RCSSET 0x0404
-#define PESDR0_405EX_RCSSTS 0x0405
-#define PESDR0_405EX_PHYSET1 0x0406
-#define PESDR0_405EX_PHYSET2 0x0407
-#define PESDR0_405EX_BIST 0x0408
-#define PESDR0_405EX_LPB 0x040B
-#define PESDR0_405EX_PHYSTA 0x040C
-
-#define PESDR1_405EX_UTLSET1 0x0440
-#define PESDR1_405EX_UTLSET2 0x0441
-#define PESDR1_405EX_DLPSET 0x0442
-#define PESDR1_405EX_LOOP 0x0443
-#define PESDR1_405EX_RCSSET 0x0444
-#define PESDR1_405EX_RCSSTS 0x0445
-#define PESDR1_405EX_PHYSET1 0x0446
-#define PESDR1_405EX_PHYSET2 0x0447
-#define PESDR1_405EX_BIST 0x0448
-#define PESDR1_405EX_LPB 0x044B
-#define PESDR1_405EX_PHYSTA 0x044C
-
-/*
- * 460EX additional DCRs
- */
-#define PESDR0_460EX_L0BIST 0x0308
-#define PESDR0_460EX_L0BISTSTS 0x0309
-#define PESDR0_460EX_L0CDRCTL 0x030A
-#define PESDR0_460EX_L0DRV 0x030B
-#define PESDR0_460EX_L0REC 0x030C
-#define PESDR0_460EX_L0LPB 0x030D
-#define PESDR0_460EX_L0CLK 0x030E
-#define PESDR0_460EX_PHY_CTL_RST 0x030F
-#define PESDR0_460EX_RSTSTA 0x0310
-#define PESDR0_460EX_OBS 0x0311
-#define PESDR0_460EX_L0ERRC 0x0320
-
-#define PESDR1_460EX_L0BIST 0x0348
-#define PESDR1_460EX_L1BIST 0x0349
-#define PESDR1_460EX_L2BIST 0x034A
-#define PESDR1_460EX_L3BIST 0x034B
-#define PESDR1_460EX_L0BISTSTS 0x034C
-#define PESDR1_460EX_L1BISTSTS 0x034D
-#define PESDR1_460EX_L2BISTSTS 0x034E
-#define PESDR1_460EX_L3BISTSTS 0x034F
-#define PESDR1_460EX_L0CDRCTL 0x0350
-#define PESDR1_460EX_L1CDRCTL 0x0351
-#define PESDR1_460EX_L2CDRCTL 0x0352
-#define PESDR1_460EX_L3CDRCTL 0x0353
-#define PESDR1_460EX_L0DRV 0x0354
-#define PESDR1_460EX_L1DRV 0x0355
-#define PESDR1_460EX_L2DRV 0x0356
-#define PESDR1_460EX_L3DRV 0x0357
-#define PESDR1_460EX_L0REC 0x0358
-#define PESDR1_460EX_L1REC 0x0359
-#define PESDR1_460EX_L2REC 0x035A
-#define PESDR1_460EX_L3REC 0x035B
-#define PESDR1_460EX_L0LPB 0x035C
-#define PESDR1_460EX_L1LPB 0x035D
-#define PESDR1_460EX_L2LPB 0x035E
-#define PESDR1_460EX_L3LPB 0x035F
-#define PESDR1_460EX_L0CLK 0x0360
-#define PESDR1_460EX_L1CLK 0x0361
-#define PESDR1_460EX_L2CLK 0x0362
-#define PESDR1_460EX_L3CLK 0x0363
-#define PESDR1_460EX_PHY_CTL_RST 0x0364
-#define PESDR1_460EX_RSTSTA 0x0365
-#define PESDR1_460EX_OBS 0x0366
-#define PESDR1_460EX_L0ERRC 0x0368
-#define PESDR1_460EX_L1ERRC 0x0369
-#define PESDR1_460EX_L2ERRC 0x036A
-#define PESDR1_460EX_L3ERRC 0x036B
-#define PESDR0_460EX_IHS1 0x036C
-#define PESDR0_460EX_IHS2 0x036D
-
-/*
- * 460SX additional DCRs
- */
-#define PESDRn_460SX_RCEI 0x02
-
-#define PESDR0_460SX_HSSL0DAMP 0x320
-#define PESDR0_460SX_HSSL1DAMP 0x321
-#define PESDR0_460SX_HSSL2DAMP 0x322
-#define PESDR0_460SX_HSSL3DAMP 0x323
-#define PESDR0_460SX_HSSL4DAMP 0x324
-#define PESDR0_460SX_HSSL5DAMP 0x325
-#define PESDR0_460SX_HSSL6DAMP 0x326
-#define PESDR0_460SX_HSSL7DAMP 0x327
-
-#define PESDR1_460SX_HSSL0DAMP 0x354
-#define PESDR1_460SX_HSSL1DAMP 0x355
-#define PESDR1_460SX_HSSL2DAMP 0x356
-#define PESDR1_460SX_HSSL3DAMP 0x357
-
-#define PESDR2_460SX_HSSL0DAMP 0x384
-#define PESDR2_460SX_HSSL1DAMP 0x385
-#define PESDR2_460SX_HSSL2DAMP 0x386
-#define PESDR2_460SX_HSSL3DAMP 0x387
-
-#define PESDR0_460SX_HSSL0COEFA 0x328
-#define PESDR0_460SX_HSSL1COEFA 0x329
-#define PESDR0_460SX_HSSL2COEFA 0x32A
-#define PESDR0_460SX_HSSL3COEFA 0x32B
-#define PESDR0_460SX_HSSL4COEFA 0x32C
-#define PESDR0_460SX_HSSL5COEFA 0x32D
-#define PESDR0_460SX_HSSL6COEFA 0x32E
-#define PESDR0_460SX_HSSL7COEFA 0x32F
-
-#define PESDR1_460SX_HSSL0COEFA 0x358
-#define PESDR1_460SX_HSSL1COEFA 0x359
-#define PESDR1_460SX_HSSL2COEFA 0x35A
-#define PESDR1_460SX_HSSL3COEFA 0x35B
-
-#define PESDR2_460SX_HSSL0COEFA 0x388
-#define PESDR2_460SX_HSSL1COEFA 0x389
-#define PESDR2_460SX_HSSL2COEFA 0x38A
-#define PESDR2_460SX_HSSL3COEFA 0x38B
-
-#define PESDR0_460SX_HSSL1CALDRV 0x339
-#define PESDR1_460SX_HSSL1CALDRV 0x361
-#define PESDR2_460SX_HSSL1CALDRV 0x391
-
-#define PESDR0_460SX_HSSSLEW 0x338
-#define PESDR1_460SX_HSSSLEW 0x360
-#define PESDR2_460SX_HSSSLEW 0x390
-
-#define PESDR0_460SX_HSSCTLSET 0x31E
-#define PESDR1_460SX_HSSCTLSET 0x352
-#define PESDR2_460SX_HSSCTLSET 0x382
-
-#define PESDR0_460SX_RCSSET 0x304
-#define PESDR1_460SX_RCSSET 0x344
-#define PESDR2_460SX_RCSSET 0x374
-/*
- * Of the above, some are common offsets from the base
- */
-#define PESDRn_UTLSET1 0x00
-#define PESDRn_UTLSET2 0x01
-#define PESDRn_DLPSET 0x02
-#define PESDRn_LOOP 0x03
-#define PESDRn_RCSSET 0x04
-#define PESDRn_RCSSTS 0x05
-
-/* 440spe only */
-#define PESDRn_440SPE_HSSL0SET1 0x06
-#define PESDRn_440SPE_HSSL0SET2 0x07
-#define PESDRn_440SPE_HSSL0STS 0x08
-#define PESDRn_440SPE_HSSL1SET1 0x09
-#define PESDRn_440SPE_HSSL1SET2 0x0a
-#define PESDRn_440SPE_HSSL1STS 0x0b
-#define PESDRn_440SPE_HSSL2SET1 0x0c
-#define PESDRn_440SPE_HSSL2SET2 0x0d
-#define PESDRn_440SPE_HSSL2STS 0x0e
-#define PESDRn_440SPE_HSSL3SET1 0x0f
-#define PESDRn_440SPE_HSSL3SET2 0x10
-#define PESDRn_440SPE_HSSL3STS 0x11
-
-/* 440spe port 0 only */
-#define PESDRn_440SPE_HSSL4SET1 0x12
-#define PESDRn_440SPE_HSSL4SET2 0x13
-#define PESDRn_440SPE_HSSL4STS 0x14
-#define PESDRn_440SPE_HSSL5SET1 0x15
-#define PESDRn_440SPE_HSSL5SET2 0x16
-#define PESDRn_440SPE_HSSL5STS 0x17
-#define PESDRn_440SPE_HSSL6SET1 0x18
-#define PESDRn_440SPE_HSSL6SET2 0x19
-#define PESDRn_440SPE_HSSL6STS 0x1a
-#define PESDRn_440SPE_HSSL7SET1 0x1b
-#define PESDRn_440SPE_HSSL7SET2 0x1c
-#define PESDRn_440SPE_HSSL7STS 0x1d
-
-/* 405ex only */
-#define PESDRn_405EX_PHYSET1 0x06
-#define PESDRn_405EX_PHYSET2 0x07
-#define PESDRn_405EX_PHYSTA 0x0c
-
-/*
- * UTL register offsets
- */
-#define PEUTL_PBCTL 0x00
-#define PEUTL_PBBSZ 0x20
-#define PEUTL_OPDBSZ 0x68
-#define PEUTL_IPHBSZ 0x70
-#define PEUTL_IPDBSZ 0x78
-#define PEUTL_OUTTR 0x90
-#define PEUTL_INTR 0x98
-#define PEUTL_PCTL 0xa0
-#define PEUTL_RCSTA 0xB0
-#define PEUTL_RCIRQEN 0xb8
-
-/*
- * Config space register offsets
- */
-#define PECFG_ECRTCTL 0x074
-
-#define PECFG_BAR0LMPA 0x210
-#define PECFG_BAR0HMPA 0x214
-#define PECFG_BAR1MPA 0x218
-#define PECFG_BAR2LMPA 0x220
-#define PECFG_BAR2HMPA 0x224
-
-#define PECFG_PIMEN 0x33c
-#define PECFG_PIM0LAL 0x340
-#define PECFG_PIM0LAH 0x344
-#define PECFG_PIM1LAL 0x348
-#define PECFG_PIM1LAH 0x34c
-#define PECFG_PIM01SAL 0x350
-#define PECFG_PIM01SAH 0x354
-
-#define PECFG_POM0LAL 0x380
-#define PECFG_POM0LAH 0x384
-#define PECFG_POM1LAL 0x388
-#define PECFG_POM1LAH 0x38c
-#define PECFG_POM2LAL 0x390
-#define PECFG_POM2LAH 0x394
-
-/* 460sx only */
-#define PECFG_460SX_DLLSTA 0x3f8
-
-/* 460sx Bit Mappings */
-#define PECFG_460SX_DLLSTA_LINKUP 0x00000010
-#define DCRO_PEGPL_460SX_OMR1MSKL_UOT 0x00000004
-
-/* PEGPL Bit Mappings */
-#define DCRO_PEGPL_OMRxMSKL_VAL 0x00000001
-#define DCRO_PEGPL_OMR1MSKL_UOT 0x00000002
-#define DCRO_PEGPL_OMR3MSKL_IO 0x00000002
-
-/* 476FPE */
-#define PCCFG_LCPA 0x270
-#define PECFG_TLDLP 0x3F8
-#define PECFG_TLDLP_LNKUP 0x00000008
-#define PECFG_TLDLP_PRESENT 0x00000010
-#define DCRO_PEGPL_476FPE_OMR1MSKL_UOT 0x00000004
-
-/* SDR Bit Mappings */
-#define PESDRx_RCSSET_HLDPLB 0x10000000
-#define PESDRx_RCSSET_RSTGU 0x01000000
-#define PESDRx_RCSSET_RDY 0x00100000
-#define PESDRx_RCSSET_RSTDL 0x00010000
-#define PESDRx_RCSSET_RSTPYN 0x00001000
-
-enum
-{
- PTYPE_ENDPOINT = 0x0,
- PTYPE_LEGACY_ENDPOINT = 0x1,
- PTYPE_ROOT_PORT = 0x4,
-
- LNKW_X1 = 0x1,
- LNKW_X4 = 0x4,
- LNKW_X8 = 0x8
-};
-
-
-#endif /* __PPC4XX_PCI_H__ */
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
deleted file mode 100644
index d41134d2f786..000000000000
--- a/arch/powerpc/sysdev/ppc4xx_soc.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * IBM/AMCC PPC4xx SoC setup code
- *
- * Copyright 2008 DENX Software Engineering, Stefan Roese <sr@denx.de>
- *
- * L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is:
- * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003 - 2006 Zultys Technologies
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#include <asm/reg.h>
-
-static u32 dcrbase_l2c;
-
-/*
- * L2-cache
- */
-
-/* Issue L2C diagnostic command */
-static inline u32 l2c_diag(u32 addr)
-{
- mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr);
- mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG);
- while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
- ;
-
- return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA);
-}
-
-static irqreturn_t l2c_error_handler(int irq, void *dev)
-{
- u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR);
-
- if (sr & L2C_SR_CPE) {
- /* Read cache trapped address */
- u32 addr = l2c_diag(0x42000000);
- printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n",
- addr);
- }
- if (sr & L2C_SR_TPE) {
- /* Read tag trapped address */
- u32 addr = l2c_diag(0x82000000) >> 16;
- printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n",
- addr);
- }
-
- /* Clear parity errors */
- if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
- mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
- mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
- } else {
- printk(KERN_EMERG "L2C: LRU error\n");
- }
-
- return IRQ_HANDLED;
-}
-
-static int __init ppc4xx_l2c_probe(void)
-{
- struct device_node *np;
- u32 r;
- unsigned long flags;
- int irq;
- const u32 *dcrreg;
- u32 dcrbase_isram;
- int len;
- const u32 *prop;
- u32 l2_size;
-
- np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache");
- if (!np)
- return 0;
-
- /* Get l2 cache size */
- prop = of_get_property(np, "cache-size", NULL);
- if (prop == NULL) {
- printk(KERN_ERR "%s: Can't get cache-size!\n", np->full_name);
- of_node_put(np);
- return -ENODEV;
- }
- l2_size = prop[0];
-
- /* Map DCRs */
- dcrreg = of_get_property(np, "dcr-reg", &len);
- if (!dcrreg || (len != 4 * sizeof(u32))) {
- printk(KERN_ERR "%s: Can't get DCR register base !",
- np->full_name);
- of_node_put(np);
- return -ENODEV;
- }
- dcrbase_isram = dcrreg[0];
- dcrbase_l2c = dcrreg[2];
-
- /* Get and map irq number from device tree */
- irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- printk(KERN_ERR "irq_of_parse_and_map failed\n");
- of_node_put(np);
- return -ENODEV;
- }
-
- /* Install error handler */
- if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
- printk(KERN_ERR "Cannot install L2C error handler"
- ", cache is not enabled\n");
- of_node_put(np);
- return -ENODEV;
- }
-
- local_irq_save(flags);
- asm volatile ("sync" ::: "memory");
-
- /* Disable SRAM */
- mtdcr(dcrbase_isram + DCRN_SRAM0_DPC,
- mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE);
- mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR,
- mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
- mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR,
- mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
- mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR,
- mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
- mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR,
- mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
-
- /* Enable L2_MODE without ICU/DCU */
- r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) &
- ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
- r |= L2C_CFG_L2M | L2C_CFG_SS_256;
- mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
-
- mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
-
- /* Hardware Clear Command */
- mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC);
- while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
- ;
-
- /* Clear Cache Parity and Tag Errors */
- mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
-
- /* Enable 64G snoop region starting at 0 */
- r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) &
- ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
- r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
- mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r);
-
- r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) &
- ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
- r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
- mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r);
-
- asm volatile ("sync" ::: "memory");
-
- /* Enable ICU/DCU ports */
- r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG);
- r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM
- | L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
- r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
- | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
-
- /* Check for 460EX/GT special handling */
- if (of_device_is_compatible(np, "ibm,l2-cache-460ex") ||
- of_device_is_compatible(np, "ibm,l2-cache-460gt"))
- r |= L2C_CFG_RDBW;
-
- mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
-
- asm volatile ("sync; isync" ::: "memory");
- local_irq_restore(flags);
-
- printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10);
-
- of_node_put(np);
- return 0;
-}
-arch_initcall(ppc4xx_l2c_probe);
-
-/*
- * Apply a system reset. Alternatively a board specific value may be
- * provided via the "reset-type" property in the cpu node.
- */
-void ppc4xx_reset_system(char *cmd)
-{
- struct device_node *np;
- u32 reset_type = DBCR0_RST_SYSTEM;
- const u32 *prop;
-
- np = of_find_node_by_type(NULL, "cpu");
- if (np) {
- prop = of_get_property(np, "reset-type", NULL);
-
- /*
- * Check if property exists and if it is in range:
- * 1 - PPC4xx core reset
- * 2 - PPC4xx chip reset
- * 3 - PPC4xx system reset (default)
- */
- if ((prop) && ((prop[0] >= 1) && (prop[0] <= 3)))
- reset_type = prop[0] << 28;
- }
-
- mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | reset_type);
-
- while (1)
- ; /* Just in case the reset doesn't work */
-}
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 76ea32c1b664..0f6fd5d04d33 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -194,12 +194,13 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
ent->dn = of_node_get(dn);
snprintf(ent->name, 16, "%08x", i);
- ent->path.data = (void*) dn->full_name;
- ent->path.size = strlen(dn->full_name);
+ ent->path.data = (void*)kasprintf(GFP_KERNEL, "%pOF", dn);
+ ent->path.size = strlen((char *)ent->path.data);
dir = debugfs_create_dir(ent->name, root);
if (!dir) {
of_node_put(dn);
+ kfree(ent->path.data);
kfree(ent);
return -1;
}
diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c
index 6afddae2fb47..f02d4576138c 100644
--- a/arch/powerpc/sysdev/simple_gpio.c
+++ b/arch/powerpc/sysdev/simple_gpio.c
@@ -142,7 +142,6 @@ void __init simple_gpiochip_init(const char *compatible)
}
continue;
err:
- pr_err("%s: registration failed, status %d\n",
- np->full_name, ret);
+ pr_err("%pOF: registration failed, status %d\n", np, ret);
}
}
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 5692dd569b9b..28ff1f53cefc 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -213,8 +213,8 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
/* Get bus range if any */
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
+ printk(KERN_WARNING "Can't get bus-range for %pOF, assume"
+ " bus 0\n", dev);
}
hose = pcibios_alloc_controller(dev);
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
deleted file mode 100644
index a00949f3e378..000000000000
--- a/arch/powerpc/sysdev/uic.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * arch/powerpc/sysdev/uic.c
- *
- * IBM PowerPC 4xx Universal Interrupt Controller
- *
- * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/dcr.h>
-
-#define NR_UIC_INTS 32
-
-#define UIC_SR 0x0
-#define UIC_ER 0x2
-#define UIC_CR 0x3
-#define UIC_PR 0x4
-#define UIC_TR 0x5
-#define UIC_MSR 0x6
-#define UIC_VR 0x7
-#define UIC_VCR 0x8
-
-struct uic *primary_uic;
-
-struct uic {
- int index;
- int dcrbase;
-
- raw_spinlock_t lock;
-
- /* The remapper for this UIC */
- struct irq_domain *irqhost;
-};
-
-static void uic_unmask_irq(struct irq_data *d)
-{
- struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- u32 er, sr;
-
- sr = 1 << (31-src);
- raw_spin_lock_irqsave(&uic->lock, flags);
- /* ack level-triggered interrupts here */
- if (irqd_is_level_type(d))
- mtdcr(uic->dcrbase + UIC_SR, sr);
- er = mfdcr(uic->dcrbase + UIC_ER);
- er |= sr;
- mtdcr(uic->dcrbase + UIC_ER, er);
- raw_spin_unlock_irqrestore(&uic->lock, flags);
-}
-
-static void uic_mask_irq(struct irq_data *d)
-{
- struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- u32 er;
-
- raw_spin_lock_irqsave(&uic->lock, flags);
- er = mfdcr(uic->dcrbase + UIC_ER);
- er &= ~(1 << (31 - src));
- mtdcr(uic->dcrbase + UIC_ER, er);
- raw_spin_unlock_irqrestore(&uic->lock, flags);
-}
-
-static void uic_ack_irq(struct irq_data *d)
-{
- struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
-
- raw_spin_lock_irqsave(&uic->lock, flags);
- mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
- raw_spin_unlock_irqrestore(&uic->lock, flags);
-}
-
-static void uic_mask_ack_irq(struct irq_data *d)
-{
- struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- u32 er, sr;
-
- sr = 1 << (31-src);
- raw_spin_lock_irqsave(&uic->lock, flags);
- er = mfdcr(uic->dcrbase + UIC_ER);
- er &= ~sr;
- mtdcr(uic->dcrbase + UIC_ER, er);
- /* On the UIC, acking (i.e. clearing the SR bit)
- * a level irq will have no effect if the interrupt
- * is still asserted by the device, even if
- * the interrupt is already masked. Therefore
- * we only ack the egde interrupts here, while
- * level interrupts are ack'ed after the actual
- * isr call in the uic_unmask_irq()
- */
- if (!irqd_is_level_type(d))
- mtdcr(uic->dcrbase + UIC_SR, sr);
- raw_spin_unlock_irqrestore(&uic->lock, flags);
-}
-
-static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
-{
- struct uic *uic = irq_data_get_irq_chip_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- int trigger, polarity;
- u32 tr, pr, mask;
-
- switch (flow_type & IRQ_TYPE_SENSE_MASK) {
- case IRQ_TYPE_NONE:
- uic_mask_irq(d);
- return 0;
-
- case IRQ_TYPE_EDGE_RISING:
- trigger = 1; polarity = 1;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- trigger = 1; polarity = 0;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- trigger = 0; polarity = 1;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- trigger = 0; polarity = 0;
- break;
- default:
- return -EINVAL;
- }
-
- mask = ~(1 << (31 - src));
-
- raw_spin_lock_irqsave(&uic->lock, flags);
- tr = mfdcr(uic->dcrbase + UIC_TR);
- pr = mfdcr(uic->dcrbase + UIC_PR);
- tr = (tr & mask) | (trigger << (31-src));
- pr = (pr & mask) | (polarity << (31-src));
-
- mtdcr(uic->dcrbase + UIC_PR, pr);
- mtdcr(uic->dcrbase + UIC_TR, tr);
-
- raw_spin_unlock_irqrestore(&uic->lock, flags);
-
- return 0;
-}
-
-static struct irq_chip uic_irq_chip = {
- .name = "UIC",
- .irq_unmask = uic_unmask_irq,
- .irq_mask = uic_mask_irq,
- .irq_mask_ack = uic_mask_ack_irq,
- .irq_ack = uic_ack_irq,
- .irq_set_type = uic_set_irq_type,
-};
-
-static int uic_host_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct uic *uic = h->host_data;
-
- irq_set_chip_data(virq, uic);
- /* Despite the name, handle_level_irq() works for both level
- * and edge irqs on UIC. FIXME: check this is correct */
- irq_set_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
-
- /* Set default irq type */
- irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static const struct irq_domain_ops uic_host_ops = {
- .map = uic_host_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-static void uic_irq_cascade(struct irq_desc *desc)
-{
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct irq_data *idata = irq_desc_get_irq_data(desc);
- struct uic *uic = irq_desc_get_handler_data(desc);
- u32 msr;
- int src;
- int subvirq;
-
- raw_spin_lock(&desc->lock);
- if (irqd_is_level_type(idata))
- chip->irq_mask(idata);
- else
- chip->irq_mask_ack(idata);
- raw_spin_unlock(&desc->lock);
-
- msr = mfdcr(uic->dcrbase + UIC_MSR);
- if (!msr) /* spurious interrupt */
- goto uic_irq_ret;
-
- src = 32 - ffs(msr);
-
- subvirq = irq_linear_revmap(uic->irqhost, src);
- generic_handle_irq(subvirq);
-
-uic_irq_ret:
- raw_spin_lock(&desc->lock);
- if (irqd_is_level_type(idata))
- chip->irq_ack(idata);
- if (!irqd_irq_disabled(idata) && chip->irq_unmask)
- chip->irq_unmask(idata);
- raw_spin_unlock(&desc->lock);
-}
-
-static struct uic * __init uic_init_one(struct device_node *node)
-{
- struct uic *uic;
- const u32 *indexp, *dcrreg;
- int len;
-
- BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
-
- uic = kzalloc(sizeof(*uic), GFP_KERNEL);
- if (! uic)
- return NULL; /* FIXME: panic? */
-
- raw_spin_lock_init(&uic->lock);
- indexp = of_get_property(node, "cell-index", &len);
- if (!indexp || (len != sizeof(u32))) {
- printk(KERN_ERR "uic: Device node %s has missing or invalid "
- "cell-index property\n", node->full_name);
- return NULL;
- }
- uic->index = *indexp;
-
- dcrreg = of_get_property(node, "dcr-reg", &len);
- if (!dcrreg || (len != 2*sizeof(u32))) {
- printk(KERN_ERR "uic: Device node %s has missing or invalid "
- "dcr-reg property\n", node->full_name);
- return NULL;
- }
- uic->dcrbase = *dcrreg;
-
- uic->irqhost = irq_domain_add_linear(node, NR_UIC_INTS, &uic_host_ops,
- uic);
- if (! uic->irqhost)
- return NULL; /* FIXME: panic? */
-
- /* Start with all interrupts disabled, level and non-critical */
- mtdcr(uic->dcrbase + UIC_ER, 0);
- mtdcr(uic->dcrbase + UIC_CR, 0);
- mtdcr(uic->dcrbase + UIC_TR, 0);
- /* Clear any pending interrupts, in case the firmware left some */
- mtdcr(uic->dcrbase + UIC_SR, 0xffffffff);
-
- printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index,
- NR_UIC_INTS, uic->dcrbase);
-
- return uic;
-}
-
-void __init uic_init_tree(void)
-{
- struct device_node *np;
- struct uic *uic;
- const u32 *interrupts;
-
- /* First locate and initialize the top-level UIC */
- for_each_compatible_node(np, NULL, "ibm,uic") {
- interrupts = of_get_property(np, "interrupts", NULL);
- if (!interrupts)
- break;
- }
-
- BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the
- * top-level interrupt controller */
- primary_uic = uic_init_one(np);
- if (!primary_uic)
- panic("Unable to initialize primary UIC %s\n", np->full_name);
-
- irq_set_default_host(primary_uic->irqhost);
- of_node_put(np);
-
- /* The scan again for cascaded UICs */
- for_each_compatible_node(np, NULL, "ibm,uic") {
- interrupts = of_get_property(np, "interrupts", NULL);
- if (interrupts) {
- /* Secondary UIC */
- int cascade_virq;
-
- uic = uic_init_one(np);
- if (! uic)
- panic("Unable to initialize a secondary UIC %s\n",
- np->full_name);
-
- cascade_virq = irq_of_parse_and_map(np, 0);
-
- irq_set_handler_data(cascade_virq, uic);
- irq_set_chained_handler(cascade_virq, uic_irq_cascade);
-
- /* FIXME: setup critical cascade?? */
- }
- }
-}
-
-/* Return an interrupt vector or 0 if no interrupt is pending. */
-unsigned int uic_get_irq(void)
-{
- u32 msr;
- int src;
-
- BUG_ON(! primary_uic);
-
- msr = mfdcr(primary_uic->dcrbase + UIC_MSR);
- src = 32 - ffs(msr);
-
- return irq_linear_revmap(primary_uic->irqhost, src);
-}
diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig
index 12ccd7373d2f..3e3e25b5e30d 100644
--- a/arch/powerpc/sysdev/xive/Kconfig
+++ b/arch/powerpc/sysdev/xive/Kconfig
@@ -9,3 +9,8 @@ config PPC_XIVE_NATIVE
default n
select PPC_XIVE
depends on PPC_POWERNV
+
+config PPC_XIVE_SPAPR
+ bool
+ default n
+ select PPC_XIVE
diff --git a/arch/powerpc/sysdev/xive/Makefile b/arch/powerpc/sysdev/xive/Makefile
index 3fab303fc169..536d6e5706e3 100644
--- a/arch/powerpc/sysdev/xive/Makefile
+++ b/arch/powerpc/sysdev/xive/Makefile
@@ -2,3 +2,4 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
obj-y += common.o
obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o
+obj-$(CONFIG_PPC_XIVE_SPAPR) += spapr.o
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index 6595462b1fc8..f387318678b9 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -40,7 +40,8 @@
#undef DEBUG_ALL
#ifdef DEBUG_ALL
-#define DBG_VERBOSE(fmt...) pr_devel(fmt)
+#define DBG_VERBOSE(fmt, ...) pr_devel("cpu %d - " fmt, \
+ smp_processor_id(), ## __VA_ARGS__)
#else
#define DBG_VERBOSE(fmt...) do { } while(0)
#endif
@@ -190,7 +191,7 @@ static u32 xive_scan_interrupts(struct xive_cpu *xc, bool just_peek)
* This is used to perform the magic loads from an ESB
* described in xive.h
*/
-static u8 xive_poke_esb(struct xive_irq_data *xd, u32 offset)
+static notrace u8 xive_esb_read(struct xive_irq_data *xd, u32 offset)
{
u64 val;
@@ -198,13 +199,28 @@ static u8 xive_poke_esb(struct xive_irq_data *xd, u32 offset)
if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG)
offset |= offset << 4;
- val = in_be64(xd->eoi_mmio + offset);
+ if ((xd->flags & XIVE_IRQ_FLAG_H_INT_ESB) && xive_ops->esb_rw)
+ val = xive_ops->esb_rw(xd->hw_irq, offset, 0, 0);
+ else
+ val = in_be64(xd->eoi_mmio + offset);
return (u8)val;
}
+static void xive_esb_write(struct xive_irq_data *xd, u32 offset, u64 data)
+{
+ /* Handle HW errata */
+ if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG)
+ offset |= offset << 4;
+
+ if ((xd->flags & XIVE_IRQ_FLAG_H_INT_ESB) && xive_ops->esb_rw)
+ xive_ops->esb_rw(xd->hw_irq, offset, data, 1);
+ else
+ out_be64(xd->eoi_mmio + offset, data);
+}
+
#ifdef CONFIG_XMON
-static void xive_dump_eq(const char *name, struct xive_q *q)
+static notrace void xive_dump_eq(const char *name, struct xive_q *q)
{
u32 i0, i1, idx;
@@ -218,7 +234,7 @@ static void xive_dump_eq(const char *name, struct xive_q *q)
q->toggle, i0, i1);
}
-void xmon_xive_do_dump(int cpu)
+notrace void xmon_xive_do_dump(int cpu)
{
struct xive_cpu *xc = per_cpu(xive_cpu, cpu);
@@ -227,7 +243,7 @@ void xmon_xive_do_dump(int cpu)
xive_dump_eq("IRQ", &xc->queue[xive_irq_priority]);
#ifdef CONFIG_SMP
{
- u64 val = xive_poke_esb(&xc->ipi_data, XIVE_ESB_GET);
+ u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET);
xmon_printf(" IPI state: %x:%c%c\n", xc->hw_ipi,
val & XIVE_ESB_VAL_P ? 'P' : 'p',
val & XIVE_ESB_VAL_P ? 'Q' : 'q');
@@ -297,7 +313,7 @@ void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd)
{
/* If the XIVE supports the new "store EOI facility, use it */
if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI)
- out_be64(xd->eoi_mmio + XIVE_ESB_STORE_EOI, 0);
+ xive_esb_write(xd, XIVE_ESB_STORE_EOI, 0);
else if (hw_irq && xd->flags & XIVE_IRQ_FLAG_EOI_FW) {
/*
* The FW told us to call it. This happens for some
@@ -326,10 +342,10 @@ void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd)
* properly.
*/
if (xd->flags & XIVE_IRQ_FLAG_LSI)
- in_be64(xd->eoi_mmio);
+ xive_esb_read(xd, XIVE_ESB_LOAD_EOI);
else {
- eoi_val = xive_poke_esb(xd, XIVE_ESB_SET_PQ_00);
- DBG_VERBOSE("eoi_val=%x\n", offset, eoi_val);
+ eoi_val = xive_esb_read(xd, XIVE_ESB_SET_PQ_00);
+ DBG_VERBOSE("eoi_val=%x\n", eoi_val);
/* Re-trigger if needed */
if ((eoi_val & XIVE_ESB_VAL_Q) && xd->trig_mmio)
@@ -383,12 +399,12 @@ static void xive_do_source_set_mask(struct xive_irq_data *xd,
* ESB accordingly on unmask.
*/
if (mask) {
- val = xive_poke_esb(xd, XIVE_ESB_SET_PQ_01);
+ val = xive_esb_read(xd, XIVE_ESB_SET_PQ_01);
xd->saved_p = !!(val & XIVE_ESB_VAL_P);
} else if (xd->saved_p)
- xive_poke_esb(xd, XIVE_ESB_SET_PQ_10);
+ xive_esb_read(xd, XIVE_ESB_SET_PQ_10);
else
- xive_poke_esb(xd, XIVE_ESB_SET_PQ_00);
+ xive_esb_read(xd, XIVE_ESB_SET_PQ_00);
}
/*
@@ -447,7 +463,7 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
int cpu, first, num, i;
/* Pick up a starting point CPU in the mask based on fuzz */
- num = cpumask_weight(mask);
+ num = min_t(int, cpumask_weight(mask), nr_cpu_ids);
first = fuzz % num;
/* Locate it */
@@ -672,6 +688,10 @@ static int xive_irq_set_affinity(struct irq_data *d,
if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids)
return -EINVAL;
+ /* Don't do anything if the interrupt isn't started */
+ if (!irqd_is_started(d))
+ return IRQ_SET_MASK_OK;
+
/*
* If existing target is already in the new mask, and is
* online then do nothing.
@@ -768,7 +788,7 @@ static int xive_irq_retrigger(struct irq_data *d)
* To perform a retrigger, we first set the PQ bits to
* 11, then perform an EOI.
*/
- xive_poke_esb(xd, XIVE_ESB_SET_PQ_11);
+ xive_esb_read(xd, XIVE_ESB_SET_PQ_11);
/*
* Note: We pass "0" to the hw_irq argument in order to
@@ -803,7 +823,7 @@ static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state)
irqd_set_forwarded_to_vcpu(d);
/* Set it to PQ=10 state to prevent further sends */
- pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_10);
+ pq = xive_esb_read(xd, XIVE_ESB_SET_PQ_10);
/* No target ? nothing to do */
if (xd->target == XIVE_INVALID_TARGET) {
@@ -832,7 +852,7 @@ static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state)
* for sure the queue slot is no longer in use.
*/
if (pq & 2) {
- pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_11);
+ pq = xive_esb_read(xd, XIVE_ESB_SET_PQ_11);
xd->saved_p = true;
/*
@@ -989,6 +1009,9 @@ static void xive_ipi_eoi(struct irq_data *d)
{
struct xive_cpu *xc = __this_cpu_read(xive_cpu);
+ DBG_VERBOSE("IPI eoi: irq=%d [0x%lx] (HW IRQ 0x%x) pending=%02x\n",
+ d->irq, irqd_to_hwirq(d), xc->hw_ipi, xc->pending_prio);
+
/* Handle possible race with unplug and drop stale IPIs */
if (!xc)
return;
@@ -1368,6 +1391,19 @@ void xive_flush_interrupt(void)
#endif /* CONFIG_SMP */
+void xive_teardown_cpu(void)
+{
+ struct xive_cpu *xc = __this_cpu_read(xive_cpu);
+ unsigned int cpu = smp_processor_id();
+
+ /* Set CPPR to 0 to disable flow of interrupts */
+ xc->cppr = 0;
+ out_8(xive_tima + xive_tima_offset + TM_CPPR, 0);
+
+ if (xive_ops->teardown_cpu)
+ xive_ops->teardown_cpu(cpu, xc);
+}
+
void xive_kexec_teardown_cpu(int secondary)
{
struct xive_cpu *xc = __this_cpu_read(xive_cpu);
@@ -1395,8 +1431,8 @@ void xive_shutdown(void)
xive_ops->shutdown();
}
-bool xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 offset,
- u8 max_prio)
+bool __init xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 offset,
+ u8 max_prio)
{
xive_tima = area;
xive_tima_offset = offset;
@@ -1424,6 +1460,22 @@ bool xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 offset,
return true;
}
+__be32 *xive_queue_page_alloc(unsigned int cpu, u32 queue_shift)
+{
+ unsigned int alloc_order;
+ struct page *pages;
+ __be32 *qpage;
+
+ alloc_order = xive_alloc_order(queue_shift);
+ pages = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, alloc_order);
+ if (!pages)
+ return ERR_PTR(-ENOMEM);
+ qpage = (__be32 *)page_address(pages);
+ memset(qpage, 0, 1 << queue_shift);
+
+ return qpage;
+}
+
static int __init xive_off(char *arg)
{
xive_cmdline_disabled = true;
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 0f95476b01f6..44f3a25ca630 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -82,6 +82,8 @@ int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)
return -ENOMEM;
}
+ data->hw_irq = hw_irq;
+
if (!data->trig_page)
return 0;
if (data->trig_page == data->eoi_page) {
@@ -202,17 +204,12 @@ EXPORT_SYMBOL_GPL(xive_native_disable_queue);
static int xive_native_setup_queue(unsigned int cpu, struct xive_cpu *xc, u8 prio)
{
struct xive_q *q = &xc->queue[prio];
- unsigned int alloc_order;
- struct page *pages;
__be32 *qpage;
- alloc_order = (xive_queue_shift > PAGE_SHIFT) ?
- (xive_queue_shift - PAGE_SHIFT) : 0;
- pages = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, alloc_order);
- if (!pages)
- return -ENOMEM;
- qpage = (__be32 *)page_address(pages);
- memset(qpage, 0, 1 << xive_queue_shift);
+ qpage = xive_queue_page_alloc(cpu, xive_queue_shift);
+ if (IS_ERR(qpage))
+ return PTR_ERR(qpage);
+
return xive_native_configure_queue(get_hard_smp_processor_id(cpu),
q, prio, qpage, xive_queue_shift, false);
}
@@ -227,8 +224,7 @@ static void xive_native_cleanup_queue(unsigned int cpu, struct xive_cpu *xc, u8
* from an IPI and iounmap isn't safe
*/
__xive_native_disable_queue(get_hard_smp_processor_id(cpu), q, prio);
- alloc_order = (xive_queue_shift > PAGE_SHIFT) ?
- (xive_queue_shift - PAGE_SHIFT) : 0;
+ alloc_order = xive_alloc_order(xive_queue_shift);
free_pages((unsigned long)q->qpage, alloc_order);
q->qpage = NULL;
}
@@ -531,7 +527,7 @@ u32 xive_native_default_eq_shift(void)
}
EXPORT_SYMBOL_GPL(xive_native_default_eq_shift);
-bool xive_native_init(void)
+bool __init xive_native_init(void)
{
struct device_node *np;
struct resource r;
@@ -551,7 +547,7 @@ bool xive_native_init(void)
pr_devel("not found !\n");
return false;
}
- pr_devel("Found %s\n", np->full_name);
+ pr_devel("Found %pOF\n", np);
/* Resource 1 is HV window */
if (of_address_to_resource(np, 1, &r)) {
diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c
new file mode 100644
index 000000000000..f24a70bc6855
--- /dev/null
+++ b/arch/powerpc/sysdev/xive/spapr.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright 2016,2017 IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "xive: " fmt
+
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/cpumask.h>
+#include <linux/mm.h>
+
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xive.h>
+#include <asm/xive-regs.h>
+#include <asm/hvcall.h>
+
+#include "xive-internal.h"
+
+static u32 xive_queue_shift;
+
+struct xive_irq_bitmap {
+ unsigned long *bitmap;
+ unsigned int base;
+ unsigned int count;
+ spinlock_t lock;
+ struct list_head list;
+};
+
+static LIST_HEAD(xive_irq_bitmaps);
+
+static int xive_irq_bitmap_add(int base, int count)
+{
+ struct xive_irq_bitmap *xibm;
+
+ xibm = kzalloc(sizeof(*xibm), GFP_ATOMIC);
+ if (!xibm)
+ return -ENOMEM;
+
+ spin_lock_init(&xibm->lock);
+ xibm->base = base;
+ xibm->count = count;
+ xibm->bitmap = kzalloc(xibm->count, GFP_KERNEL);
+ list_add(&xibm->list, &xive_irq_bitmaps);
+
+ pr_info("Using IRQ range [%x-%x]", xibm->base,
+ xibm->base + xibm->count - 1);
+ return 0;
+}
+
+static int __xive_irq_bitmap_alloc(struct xive_irq_bitmap *xibm)
+{
+ int irq;
+
+ irq = find_first_zero_bit(xibm->bitmap, xibm->count);
+ if (irq != xibm->count) {
+ set_bit(irq, xibm->bitmap);
+ irq += xibm->base;
+ } else {
+ irq = -ENOMEM;
+ }
+
+ return irq;
+}
+
+static int xive_irq_bitmap_alloc(void)
+{
+ struct xive_irq_bitmap *xibm;
+ unsigned long flags;
+ int irq = -ENOENT;
+
+ list_for_each_entry(xibm, &xive_irq_bitmaps, list) {
+ spin_lock_irqsave(&xibm->lock, flags);
+ irq = __xive_irq_bitmap_alloc(xibm);
+ spin_unlock_irqrestore(&xibm->lock, flags);
+ if (irq >= 0)
+ break;
+ }
+ return irq;
+}
+
+static void xive_irq_bitmap_free(int irq)
+{
+ unsigned long flags;
+ struct xive_irq_bitmap *xibm;
+
+ list_for_each_entry(xibm, &xive_irq_bitmaps, list) {
+ if ((irq >= xibm->base) && (irq < xibm->base + xibm->count)) {
+ spin_lock_irqsave(&xibm->lock, flags);
+ clear_bit(irq - xibm->base, xibm->bitmap);
+ spin_unlock_irqrestore(&xibm->lock, flags);
+ break;
+ }
+ }
+}
+
+static long plpar_int_get_source_info(unsigned long flags,
+ unsigned long lisn,
+ unsigned long *src_flags,
+ unsigned long *eoi_page,
+ unsigned long *trig_page,
+ unsigned long *esb_shift)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ rc = plpar_hcall(H_INT_GET_SOURCE_INFO, retbuf, flags, lisn);
+ if (rc) {
+ pr_err("H_INT_GET_SOURCE_INFO lisn=%ld failed %ld\n", lisn, rc);
+ return rc;
+ }
+
+ *src_flags = retbuf[0];
+ *eoi_page = retbuf[1];
+ *trig_page = retbuf[2];
+ *esb_shift = retbuf[3];
+
+ pr_devel("H_INT_GET_SOURCE_INFO flags=%lx eoi=%lx trig=%lx shift=%lx\n",
+ retbuf[0], retbuf[1], retbuf[2], retbuf[3]);
+
+ return 0;
+}
+
+#define XIVE_SRC_SET_EISN (1ull << (63 - 62))
+#define XIVE_SRC_MASK (1ull << (63 - 63)) /* unused */
+
+static long plpar_int_set_source_config(unsigned long flags,
+ unsigned long lisn,
+ unsigned long target,
+ unsigned long prio,
+ unsigned long sw_irq)
+{
+ long rc;
+
+
+ pr_devel("H_INT_SET_SOURCE_CONFIG flags=%lx lisn=%lx target=%lx prio=%lx sw_irq=%lx\n",
+ flags, lisn, target, prio, sw_irq);
+
+
+ rc = plpar_hcall_norets(H_INT_SET_SOURCE_CONFIG, flags, lisn,
+ target, prio, sw_irq);
+ if (rc) {
+ pr_err("H_INT_SET_SOURCE_CONFIG lisn=%ld target=%lx prio=%lx failed %ld\n",
+ lisn, target, prio, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static long plpar_int_get_queue_info(unsigned long flags,
+ unsigned long target,
+ unsigned long priority,
+ unsigned long *esn_page,
+ unsigned long *esn_size)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ rc = plpar_hcall(H_INT_GET_QUEUE_INFO, retbuf, flags, target, priority);
+ if (rc) {
+ pr_err("H_INT_GET_QUEUE_INFO cpu=%ld prio=%ld failed %ld\n",
+ target, priority, rc);
+ return rc;
+ }
+
+ *esn_page = retbuf[0];
+ *esn_size = retbuf[1];
+
+ pr_devel("H_INT_GET_QUEUE_INFO page=%lx size=%lx\n",
+ retbuf[0], retbuf[1]);
+
+ return 0;
+}
+
+#define XIVE_EQ_ALWAYS_NOTIFY (1ull << (63 - 63))
+
+static long plpar_int_set_queue_config(unsigned long flags,
+ unsigned long target,
+ unsigned long priority,
+ unsigned long qpage,
+ unsigned long qsize)
+{
+ long rc;
+
+ pr_devel("H_INT_SET_QUEUE_CONFIG flags=%lx target=%lx priority=%lx qpage=%lx qsize=%lx\n",
+ flags, target, priority, qpage, qsize);
+
+ rc = plpar_hcall_norets(H_INT_SET_QUEUE_CONFIG, flags, target,
+ priority, qpage, qsize);
+ if (rc) {
+ pr_err("H_INT_SET_QUEUE_CONFIG cpu=%ld prio=%ld qpage=%lx returned %ld\n",
+ target, priority, qpage, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static long plpar_int_sync(unsigned long flags, unsigned long lisn)
+{
+ long rc;
+
+ rc = plpar_hcall_norets(H_INT_SYNC, flags, lisn);
+ if (rc) {
+ pr_err("H_INT_SYNC lisn=%ld returned %ld\n", lisn, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+#define XIVE_ESB_FLAG_STORE (1ull << (63 - 63))
+
+static long plpar_int_esb(unsigned long flags,
+ unsigned long lisn,
+ unsigned long offset,
+ unsigned long in_data,
+ unsigned long *out_data)
+{
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+ long rc;
+
+ pr_devel("H_INT_ESB flags=%lx lisn=%lx offset=%lx in=%lx\n",
+ flags, lisn, offset, in_data);
+
+ rc = plpar_hcall(H_INT_ESB, retbuf, flags, lisn, offset, in_data);
+ if (rc) {
+ pr_err("H_INT_ESB lisn=%ld offset=%ld returned %ld\n",
+ lisn, offset, rc);
+ return rc;
+ }
+
+ *out_data = retbuf[0];
+
+ return 0;
+}
+
+static u64 xive_spapr_esb_rw(u32 lisn, u32 offset, u64 data, bool write)
+{
+ unsigned long read_data;
+ long rc;
+
+ rc = plpar_int_esb(write ? XIVE_ESB_FLAG_STORE : 0,
+ lisn, offset, data, &read_data);
+ if (rc)
+ return -1;
+
+ return write ? 0 : read_data;
+}
+
+#define XIVE_SRC_H_INT_ESB (1ull << (63 - 60))
+#define XIVE_SRC_LSI (1ull << (63 - 61))
+#define XIVE_SRC_TRIGGER (1ull << (63 - 62))
+#define XIVE_SRC_STORE_EOI (1ull << (63 - 63))
+
+static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)
+{
+ long rc;
+ unsigned long flags;
+ unsigned long eoi_page;
+ unsigned long trig_page;
+ unsigned long esb_shift;
+
+ memset(data, 0, sizeof(*data));
+
+ rc = plpar_int_get_source_info(0, hw_irq, &flags, &eoi_page, &trig_page,
+ &esb_shift);
+ if (rc)
+ return -EINVAL;
+
+ if (flags & XIVE_SRC_H_INT_ESB)
+ data->flags |= XIVE_IRQ_FLAG_H_INT_ESB;
+ if (flags & XIVE_SRC_STORE_EOI)
+ data->flags |= XIVE_IRQ_FLAG_STORE_EOI;
+ if (flags & XIVE_SRC_LSI)
+ data->flags |= XIVE_IRQ_FLAG_LSI;
+ data->eoi_page = eoi_page;
+ data->esb_shift = esb_shift;
+ data->trig_page = trig_page;
+
+ /*
+ * No chip-id for the sPAPR backend. This has an impact how we
+ * pick a target. See xive_pick_irq_target().
+ */
+ data->src_chip = XIVE_INVALID_CHIP_ID;
+
+ data->eoi_mmio = ioremap(data->eoi_page, 1u << data->esb_shift);
+ if (!data->eoi_mmio) {
+ pr_err("Failed to map EOI page for irq 0x%x\n", hw_irq);
+ return -ENOMEM;
+ }
+
+ data->hw_irq = hw_irq;
+
+ /* Full function page supports trigger */
+ if (flags & XIVE_SRC_TRIGGER) {
+ data->trig_mmio = data->eoi_mmio;
+ return 0;
+ }
+
+ data->trig_mmio = ioremap(data->trig_page, 1u << data->esb_shift);
+ if (!data->trig_mmio) {
+ pr_err("Failed to map trigger page for irq 0x%x\n", hw_irq);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int xive_spapr_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
+{
+ long rc;
+
+ rc = plpar_int_set_source_config(XIVE_SRC_SET_EISN, hw_irq, target,
+ prio, sw_irq);
+
+ return rc == 0 ? 0 : -ENXIO;
+}
+
+/* This can be called multiple time to change a queue configuration */
+static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio,
+ __be32 *qpage, u32 order)
+{
+ s64 rc = 0;
+ unsigned long esn_page;
+ unsigned long esn_size;
+ u64 flags, qpage_phys;
+
+ /* If there's an actual queue page, clean it */
+ if (order) {
+ if (WARN_ON(!qpage))
+ return -EINVAL;
+ qpage_phys = __pa(qpage);
+ } else {
+ qpage_phys = 0;
+ }
+
+ /* Initialize the rest of the fields */
+ q->msk = order ? ((1u << (order - 2)) - 1) : 0;
+ q->idx = 0;
+ q->toggle = 0;
+
+ rc = plpar_int_get_queue_info(0, target, prio, &esn_page, &esn_size);
+ if (rc) {
+ pr_err("Error %lld getting queue info prio %d\n", rc, prio);
+ rc = -EIO;
+ goto fail;
+ }
+
+ /* TODO: add support for the notification page */
+ q->eoi_phys = esn_page;
+
+ /* Default is to always notify */
+ flags = XIVE_EQ_ALWAYS_NOTIFY;
+
+ /* Configure and enable the queue in HW */
+ rc = plpar_int_set_queue_config(flags, target, prio, qpage_phys, order);
+ if (rc) {
+ pr_err("Error %lld setting queue for prio %d\n", rc, prio);
+ rc = -EIO;
+ } else {
+ q->qpage = qpage;
+ }
+fail:
+ return rc;
+}
+
+static int xive_spapr_setup_queue(unsigned int cpu, struct xive_cpu *xc,
+ u8 prio)
+{
+ struct xive_q *q = &xc->queue[prio];
+ __be32 *qpage;
+
+ qpage = xive_queue_page_alloc(cpu, xive_queue_shift);
+ if (IS_ERR(qpage))
+ return PTR_ERR(qpage);
+
+ return xive_spapr_configure_queue(cpu, q, prio, qpage,
+ xive_queue_shift);
+}
+
+static void xive_spapr_cleanup_queue(unsigned int cpu, struct xive_cpu *xc,
+ u8 prio)
+{
+ struct xive_q *q = &xc->queue[prio];
+ unsigned int alloc_order;
+ long rc;
+
+ rc = plpar_int_set_queue_config(0, cpu, prio, 0, 0);
+ if (rc)
+ pr_err("Error %ld setting queue for prio %d\n", rc, prio);
+
+ alloc_order = xive_alloc_order(xive_queue_shift);
+ free_pages((unsigned long)q->qpage, alloc_order);
+ q->qpage = NULL;
+}
+
+static bool xive_spapr_match(struct device_node *node)
+{
+ /* Ignore cascaded controllers for the moment */
+ return 1;
+}
+
+#ifdef CONFIG_SMP
+static int xive_spapr_get_ipi(unsigned int cpu, struct xive_cpu *xc)
+{
+ int irq = xive_irq_bitmap_alloc();
+
+ if (irq < 0) {
+ pr_err("Failed to allocate IPI on CPU %d\n", cpu);
+ return -ENXIO;
+ }
+
+ xc->hw_ipi = irq;
+ return 0;
+}
+
+static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc)
+{
+ xive_irq_bitmap_free(xc->hw_ipi);
+}
+#endif /* CONFIG_SMP */
+
+static void xive_spapr_shutdown(void)
+{
+ long rc;
+
+ rc = plpar_hcall_norets(H_INT_RESET, 0);
+ if (rc)
+ pr_err("H_INT_RESET failed %ld\n", rc);
+}
+
+/*
+ * Perform an "ack" cycle on the current thread. Grab the pending
+ * active priorities and update the CPPR to the most favored one.
+ */
+static void xive_spapr_update_pending(struct xive_cpu *xc)
+{
+ u8 nsr, cppr;
+ u16 ack;
+
+ /*
+ * Perform the "Acknowledge O/S to Register" cycle.
+ *
+ * Let's speedup the access to the TIMA using the raw I/O
+ * accessor as we don't need the synchronisation routine of
+ * the higher level ones
+ */
+ ack = be16_to_cpu(__raw_readw(xive_tima + TM_SPC_ACK_OS_REG));
+
+ /* Synchronize subsequent queue accesses */
+ mb();
+
+ /*
+ * Grab the CPPR and the "NSR" field which indicates the source
+ * of the interrupt (if any)
+ */
+ cppr = ack & 0xff;
+ nsr = ack >> 8;
+
+ if (nsr & TM_QW1_NSR_EO) {
+ if (cppr == 0xff)
+ return;
+ /* Mark the priority pending */
+ xc->pending_prio |= 1 << cppr;
+
+ /*
+ * A new interrupt should never have a CPPR less favored
+ * than our current one.
+ */
+ if (cppr >= xc->cppr)
+ pr_err("CPU %d odd ack CPPR, got %d at %d\n",
+ smp_processor_id(), cppr, xc->cppr);
+
+ /* Update our idea of what the CPPR is */
+ xc->cppr = cppr;
+ }
+}
+
+static void xive_spapr_eoi(u32 hw_irq)
+{
+ /* Not used */;
+}
+
+static void xive_spapr_setup_cpu(unsigned int cpu, struct xive_cpu *xc)
+{
+ /* Only some debug on the TIMA settings */
+ pr_debug("(HW value: %08x %08x %08x)\n",
+ in_be32(xive_tima + TM_QW1_OS + TM_WORD0),
+ in_be32(xive_tima + TM_QW1_OS + TM_WORD1),
+ in_be32(xive_tima + TM_QW1_OS + TM_WORD2));
+}
+
+static void xive_spapr_teardown_cpu(unsigned int cpu, struct xive_cpu *xc)
+{
+ /* Nothing to do */;
+}
+
+static void xive_spapr_sync_source(u32 hw_irq)
+{
+ /* Specs are unclear on what this is doing */
+ plpar_int_sync(0, hw_irq);
+}
+
+static const struct xive_ops xive_spapr_ops = {
+ .populate_irq_data = xive_spapr_populate_irq_data,
+ .configure_irq = xive_spapr_configure_irq,
+ .setup_queue = xive_spapr_setup_queue,
+ .cleanup_queue = xive_spapr_cleanup_queue,
+ .match = xive_spapr_match,
+ .shutdown = xive_spapr_shutdown,
+ .update_pending = xive_spapr_update_pending,
+ .eoi = xive_spapr_eoi,
+ .setup_cpu = xive_spapr_setup_cpu,
+ .teardown_cpu = xive_spapr_teardown_cpu,
+ .sync_source = xive_spapr_sync_source,
+ .esb_rw = xive_spapr_esb_rw,
+#ifdef CONFIG_SMP
+ .get_ipi = xive_spapr_get_ipi,
+ .put_ipi = xive_spapr_put_ipi,
+#endif /* CONFIG_SMP */
+ .name = "spapr",
+};
+
+/*
+ * get max priority from "/ibm,plat-res-int-priorities"
+ */
+static bool xive_get_max_prio(u8 *max_prio)
+{
+ struct device_node *rootdn;
+ const __be32 *reg;
+ u32 len;
+ int prio, found;
+
+ rootdn = of_find_node_by_path("/");
+ if (!rootdn) {
+ pr_err("not root node found !\n");
+ return false;
+ }
+
+ reg = of_get_property(rootdn, "ibm,plat-res-int-priorities", &len);
+ if (!reg) {
+ pr_err("Failed to read 'ibm,plat-res-int-priorities' property\n");
+ return false;
+ }
+
+ if (len % (2 * sizeof(u32)) != 0) {
+ pr_err("invalid 'ibm,plat-res-int-priorities' property\n");
+ return false;
+ }
+
+ /* HW supports priorities in the range [0-7] and 0xFF is a
+ * wildcard priority used to mask. We scan the ranges reserved
+ * by the hypervisor to find the lowest priority we can use.
+ */
+ found = 0xFF;
+ for (prio = 0; prio < 8; prio++) {
+ int reserved = 0;
+ int i;
+
+ for (i = 0; i < len / (2 * sizeof(u32)); i++) {
+ int base = be32_to_cpu(reg[2 * i]);
+ int range = be32_to_cpu(reg[2 * i + 1]);
+
+ if (prio >= base && prio < base + range)
+ reserved++;
+ }
+
+ if (!reserved)
+ found = prio;
+ }
+
+ if (found == 0xFF) {
+ pr_err("no valid priority found in 'ibm,plat-res-int-priorities'\n");
+ return false;
+ }
+
+ *max_prio = found;
+ return true;
+}
+
+bool __init xive_spapr_init(void)
+{
+ struct device_node *np;
+ struct resource r;
+ void __iomem *tima;
+ struct property *prop;
+ u8 max_prio;
+ u32 val;
+ u32 len;
+ const __be32 *reg;
+ int i;
+
+ if (xive_cmdline_disabled)
+ return false;
+
+ pr_devel("%s()\n", __func__);
+ np = of_find_compatible_node(NULL, NULL, "ibm,power-ivpe");
+ if (!np) {
+ pr_devel("not found !\n");
+ return false;
+ }
+ pr_devel("Found %s\n", np->full_name);
+
+ /* Resource 1 is the OS ring TIMA */
+ if (of_address_to_resource(np, 1, &r)) {
+ pr_err("Failed to get thread mgmnt area resource\n");
+ return false;
+ }
+ tima = ioremap(r.start, resource_size(&r));
+ if (!tima) {
+ pr_err("Failed to map thread mgmnt area\n");
+ return false;
+ }
+
+ if (!xive_get_max_prio(&max_prio))
+ return false;
+
+ /* Feed the IRQ number allocator with the ranges given in the DT */
+ reg = of_get_property(np, "ibm,xive-lisn-ranges", &len);
+ if (!reg) {
+ pr_err("Failed to read 'ibm,xive-lisn-ranges' property\n");
+ return false;
+ }
+
+ if (len % (2 * sizeof(u32)) != 0) {
+ pr_err("invalid 'ibm,xive-lisn-ranges' property\n");
+ return false;
+ }
+
+ for (i = 0; i < len / (2 * sizeof(u32)); i++, reg += 2)
+ xive_irq_bitmap_add(be32_to_cpu(reg[0]),
+ be32_to_cpu(reg[1]));
+
+ /* Iterate the EQ sizes and pick one */
+ of_property_for_each_u32(np, "ibm,xive-eq-sizes", prop, reg, val) {
+ xive_queue_shift = val;
+ if (val == PAGE_SHIFT)
+ break;
+ }
+
+ /* Initialize XIVE core with our backend */
+ if (!xive_core_init(&xive_spapr_ops, tima, TM_QW1_OS, max_prio))
+ return false;
+
+ pr_info("Using %dkB queues\n", 1 << (xive_queue_shift - 10));
+ return true;
+}
diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h
index d07ef2d29caf..f34abed0c05f 100644
--- a/arch/powerpc/sysdev/xive/xive-internal.h
+++ b/arch/powerpc/sysdev/xive/xive-internal.h
@@ -47,6 +47,7 @@ struct xive_ops {
void (*update_pending)(struct xive_cpu *xc);
void (*eoi)(u32 hw_irq);
void (*sync_source)(u32 hw_irq);
+ u64 (*esb_rw)(u32 hw_irq, u32 offset, u64 data, bool write);
#ifdef CONFIG_SMP
int (*get_ipi)(unsigned int cpu, struct xive_cpu *xc);
void (*put_ipi)(unsigned int cpu, struct xive_cpu *xc);
@@ -56,6 +57,12 @@ struct xive_ops {
bool xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 offset,
u8 max_prio);
+__be32 *xive_queue_page_alloc(unsigned int cpu, u32 queue_shift);
+
+static inline u32 xive_alloc_order(u32 queue_shift)
+{
+ return (queue_shift > PAGE_SHIFT) ? (queue_shift - PAGE_SHIFT) : 0;
+}
extern bool xive_cmdline_disabled;