diff options
author | Scott Wood <scottwood@freescale.com> | 2013-12-14 01:15:24 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2013-12-14 01:15:24 (GMT) |
commit | b7c81aa3ab2ac2c140e278b6d0e9a0b95112cf0b (patch) | |
tree | 87828aaf5f82c7042bfc0307bc4ac499e10f93fb /arch/powerpc/sysdev | |
parent | 22c782a4b14773fab7eab3c1db54ad7ad077e9b8 (diff) | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-b7c81aa3ab2ac2c140e278b6d0e9a0b95112cf0b.tar.xz |
Merge remote-tracking branch 'linus/master' into merge
Conflicts:
Documentation/hwmon/ina2xx
arch/powerpc/Kconfig
arch/powerpc/boot/dts/b4860emu.dts
arch/powerpc/boot/dts/b4qds.dtsi
arch/powerpc/boot/dts/fsl/b4si-post.dtsi
arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi
arch/powerpc/boot/dts/p1023rdb.dts
arch/powerpc/boot/dts/t4240emu.dts
arch/powerpc/boot/dts/t4240qds.dts
arch/powerpc/configs/85xx/p1023_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/epapr_hcalls.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/kernel/epapr_paravirt.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/swsusp_asm64.S
arch/powerpc/kernel/swsusp_booke.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/booke.h
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500.h
arch/powerpc/kvm/e500_emulate.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/perf/e6500-pmu.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/b4_qds.c
arch/powerpc/platforms/85xx/c293pcie.c
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/corenet_ds.h
arch/powerpc/platforms/85xx/p1023_rds.c
arch/powerpc/platforms/85xx/p2041_rdb.c
arch/powerpc/platforms/85xx/p3041_ds.c
arch/powerpc/platforms/85xx/p4080_ds.c
arch/powerpc/platforms/85xx/p5020_ds.c
arch/powerpc/platforms/85xx/p5040_ds.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/85xx/t4240_qds.c
arch/powerpc/platforms/Kconfig
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_pci.h
arch/powerpc/sysdev/fsl_soc.h
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_timer.c
drivers/Kconfig
drivers/clk/Kconfig
drivers/clk/clk-ppc-corenet.c
drivers/cpufreq/Kconfig.powerpc
drivers/cpufreq/Makefile
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/crypto/caam/Kconfig
drivers/crypto/caam/Makefile
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/desc_constr.h
drivers/crypto/caam/intern.h
drivers/crypto/caam/jr.c
drivers/crypto/caam/regs.h
drivers/dma/fsldma.c
drivers/hwmon/ina2xx.c
drivers/iommu/Kconfig
drivers/iommu/fsl_pamu.c
drivers/iommu/fsl_pamu.h
drivers/iommu/fsl_pamu_domain.c
drivers/iommu/fsl_pamu_domain.h
drivers/misc/Makefile
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mmc/host/sdhci-pltfm.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar.h
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/phy/at803x.c
drivers/net/phy/phy_device.c
drivers/net/phy/vitesse.c
drivers/pci/msi.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/uio/Kconfig
drivers/uio/Makefile
drivers/uio/uio.c
drivers/usb/host/ehci-fsl.c
drivers/vfio/Kconfig
drivers/vfio/Makefile
include/crypto/algapi.h
include/linux/iommu.h
include/linux/mmc/sdhci.h
include/linux/msi.h
include/linux/netdev_features.h
include/linux/phy.h
include/linux/skbuff.h
include/net/ip.h
include/uapi/linux/vfio.h
net/core/ethtool.c
net/ipv4/route.c
net/ipv6/route.c
Diffstat (limited to 'arch/powerpc/sysdev')
31 files changed, 348 insertions, 252 deletions
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index acdbf95..0dc5aa1 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig @@ -28,7 +28,7 @@ config PPC_SCOM config SCOM_DEBUGFS bool "Expose SCOM controllers via debugfs" - depends on PPC_SCOM + depends on PPC_SCOM && DEBUG_FS default n config GE_FPGA diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 4a66c65..a6ada64 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -5,7 +5,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o -obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o +obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y) obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index d4fa03f..5e6ff38 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -120,6 +120,7 @@ static irqreturn_t cpm_error_interrupt(int irq, void *dev) static struct irqaction cpm_error_irqaction = { .handler = cpm_error_interrupt, + .flags = IRQF_NO_THREAD, .name = "error", }; diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 4dd5341..4f78695 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -22,6 +22,7 @@ #include <linux/spinlock.h> #include <linux/export.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/slab.h> #include <asm/udbg.h> diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index 9cd0e60..b74085c 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c @@ -19,6 +19,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/of.h> +#include <linux/of_address.h> #include <asm/io.h> #include <asm/irq.h> diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c index 5d7384c..c50cac1 100644 --- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c +++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <asm/io.h> diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c index 0eb871c..06ac3c6 100644 --- a/arch/powerpc/sysdev/fsl_gtm.c +++ b/arch/powerpc/sysdev/fsl_gtm.c @@ -19,6 +19,8 @@ #include <linux/list.h> #include <linux/io.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/spinlock.h> #include <linux/bitops.h> #include <linux/slab.h> @@ -401,16 +403,15 @@ static int __init fsl_gtm_init(void) gtm->clock = *clock; for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) { - int ret; - struct resource irq; + unsigned int irq; - ret = of_irq_to_resource(np, i, &irq); - if (ret == NO_IRQ) { + irq = irq_of_parse_and_map(np, i); + if (irq == NO_IRQ) { pr_err("%s: not enough interrupts specified\n", np->full_name); goto err; } - gtm->timers[i].irq = irq.start; + gtm->timers[i].irq = irq; gtm->timers[i].gtm = gtm; } diff --git a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c index e94ba65..1707bf0 100644 --- a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c +++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c @@ -17,6 +17,7 @@ #include <linux/device.h> #include <asm/mpic_timer.h> +#include <asm/mpic.h> struct fsl_mpic_timer_wakeup { struct mpic_timer *timer; @@ -47,7 +48,8 @@ static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id) struct fsl_mpic_timer_wakeup *wakeup = dev_id; schedule_work(&wakeup->free_work); - return IRQ_HANDLED; + + return wakeup->timer ? IRQ_HANDLED : IRQ_NONE; } static ssize_t fsl_timer_wakeup_show(struct device *dev, @@ -81,18 +83,15 @@ static ssize_t fsl_timer_wakeup_store(struct device *dev, mutex_lock(&sysfs_lock); - if (fsl_wakeup->timer && !interval.tv_sec) { + if (fsl_wakeup->timer) { disable_irq_wake(fsl_wakeup->timer->irq); mpic_free_timer(fsl_wakeup->timer); fsl_wakeup->timer = NULL; - mutex_unlock(&sysfs_lock); - - return count; } - if (fsl_wakeup->timer) { + if (!interval.tv_sec) { mutex_unlock(&sysfs_lock); - return -EBUSY; + return count; } fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq, @@ -110,6 +109,7 @@ static ssize_t fsl_timer_wakeup_store(struct device *dev, return ret; } + mpic_start_timer(fsl_wakeup->timer); mutex_unlock(&sysfs_lock); @@ -117,23 +117,12 @@ static ssize_t fsl_timer_wakeup_store(struct device *dev, return count; } -static struct bus_type mpic_subsys = { - .name = "mpic", - .dev_name = "mpic", -}; - -static DEVICE_ATTR(timer_wakeup, 0644, +static struct device_attribute mpic_attributes = __ATTR(timer_wakeup, 0644, fsl_timer_wakeup_show, fsl_timer_wakeup_store); -static struct device_attribute *mpic_attributes[] = { - &dev_attr_timer_wakeup, - NULL -}; - static int __init fsl_wakeup_sys_init(void) { int ret; - int i; fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL); if (!fsl_wakeup) @@ -141,40 +130,27 @@ static int __init fsl_wakeup_sys_init(void) INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource); - ret = subsys_system_register(&mpic_subsys, NULL); + ret = device_create_file(mpic_subsys.dev_root, &mpic_attributes); if (ret) - goto err; - - for (i = 0; mpic_attributes[i]; i++) { - ret = device_create_file(mpic_subsys.dev_root, - mpic_attributes[i]); - if (ret) - goto err2; - } - - return ret; - -err2: - while(--i >= 0) - device_remove_file(mpic_subsys.dev_root, mpic_attributes[i]); - - bus_unregister(&mpic_subsys); - -err: - kfree(fsl_wakeup); + kfree(fsl_wakeup); return ret; } static void __exit fsl_wakeup_sys_exit(void) { - int i; + device_remove_file(mpic_subsys.dev_root, &mpic_attributes); + + mutex_lock(&sysfs_lock); + + if (fsl_wakeup->timer) { + disable_irq_wake(fsl_wakeup->timer->irq); + mpic_free_timer(fsl_wakeup->timer); + } - for (i = 0; mpic_attributes[i]; i++) - device_remove_file(mpic_subsys.dev_root, - mpic_attributes[i]); - bus_unregister(&mpic_subsys); kfree(fsl_wakeup); + + mutex_unlock(&sysfs_lock); } module_init(fsl_wakeup_sys_init); diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index b346247..909169b 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -29,6 +29,18 @@ #include "fsl_msi.h" #include "fsl_pci.h" +#define MSIIR_OFFSET_MASK 0xfffff +#define MSIIR_IBS_SHIFT 0 +#define MSIIR_SRS_SHIFT 5 +#define MSIIR1_IBS_SHIFT 4 +#define MSIIR1_SRS_SHIFT 0 +#define MSI_SRS_MASK 0xf +#define MSI_IBS_MASK 0x1f + +#define msi_hwirq(msi, msir_index, intr_index) \ + ((msir_index) << (msi)->srs_shift | \ + ((intr_index) << (msi)->ibs_shift)) + static LIST_HEAD(msi_head); struct fsl_msi_feature { @@ -81,18 +93,19 @@ static const struct irq_domain_ops fsl_msi_host_ops = { static int fsl_msi_init_allocator(struct fsl_msi *msi_data) { - int rc; + int rc, hwirq; - rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, + rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS_MAX, msi_data->irqhost->of_node); if (rc) return rc; - rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); - if (rc < 0) { - msi_bitmap_free(&msi_data->bitmap); - return rc; - } + /* + * Reserve all the hwirqs + * The available hwirqs will be released in fsl_msi_setup_hwirq() + */ + for (hwirq = 0; hwirq < NR_MSI_IRQS_MAX; hwirq++) + msi_bitmap_reserve_hwirq(&msi_data->bitmap, hwirq); return 0; } @@ -245,9 +258,9 @@ static int fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, else msg->data = hwirq; - pr_debug("%s: allocated srs: %d, ibs: %d\n", - __func__, hwirq / IRQS_PER_MSI_REG, hwirq % IRQS_PER_MSI_REG); - + pr_debug("%s: allocated srs: %d, ibs: %d\n", __func__, + (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK, + (hwirq >> msi_data->ibs_shift) & MSI_IBS_MASK); return ret; } @@ -364,7 +377,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) msir_index = cascade_data->index; - if (msir_index >= NR_MSI_REG) + if (msir_index >= NR_MSI_REG_MAX) cascade_irq = NO_IRQ; irqd_set_chained_irq_inprogress(idata); @@ -394,8 +407,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) intr_index = ffs(msir_value) - 1; cascade_irq = irq_linear_revmap(msi_data->irqhost, - msir_index * IRQS_PER_MSI_REG + - intr_index + have_shift); + msi_hwirq(msi_data, msir_index, + intr_index + have_shift)); if (cascade_irq != NO_IRQ) generic_handle_irq(cascade_irq); have_shift += intr_index + 1; @@ -425,7 +438,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) if (msi->list.prev != NULL) list_del(&msi->list); - for (i = 0; i < NR_MSI_REG; i++) { + for (i = 0; i < NR_MSI_REG_MAX; i++) { virq = msi->msi_virqs[i]; if (virq != NO_IRQ) { cascade_data = irq_get_handler_data(virq); @@ -448,7 +461,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, int offset, int irq_index) { struct fsl_msi_cascade_data *cascade_data = NULL; - int virt_msir; + int virt_msir, i; virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index); if (virt_msir == NO_IRQ) { @@ -469,6 +482,11 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, irq_set_handler_data(virt_msir, cascade_data); irq_set_chained_handler(virt_msir, fsl_msi_cascade); + /* Release the hwirqs corresponding to this MSI register */ + for (i = 0; i < IRQS_PER_MSI_REG; i++) + msi_bitmap_free_hwirqs(&msi->bitmap, + msi_hwirq(msi, offset, i), 1); + return 0; } @@ -486,14 +504,12 @@ static int fsl_of_msi_probe(struct platform_device *dev) { const struct of_device_id *match; struct fsl_msi *msi; - struct resource res; + struct resource res, msiir; int err, i, j, irq_index, count; - int rc; const u32 *p; const struct fsl_msi_feature *features; int len; u32 offset; - static const u32 all_avail[] = { 0, NR_MSI_IRQS }; static int bank_index; match = of_match_device(fsl_of_msi_ids, &dev->dev); @@ -511,7 +527,7 @@ static int fsl_of_msi_probe(struct platform_device *dev) platform_set_drvdata(dev, msi); msi->irqhost = irq_domain_add_linear(dev->dev.of_node, - NR_MSI_IRQS, &fsl_msi_host_ops, msi); + NR_MSI_IRQS_MAX, &fsl_msi_host_ops, msi); if (msi->irqhost == NULL) { dev_err(&dev->dev, "No memory for MSI irqhost\n"); @@ -540,6 +556,16 @@ static int fsl_of_msi_probe(struct platform_device *dev) } msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); + + /* + * First read the MSIIR/MSIIR1 offset from dts + * On failure use the hardcode MSIIR offset + */ + if (of_address_to_resource(dev->dev.of_node, 1, &msiir)) + msi->msiir_offset = features->msiir_offset + + (res.start & MSIIR_OFFSET_MASK); + else + msi->msiir_offset = msiir.start & MSIIR_OFFSET_MASK; } msi->feature = features->fsl_pic_ip; @@ -555,42 +581,66 @@ static int fsl_of_msi_probe(struct platform_device *dev) */ msi->phandle = dev->dev.of_node->phandle; - rc = fsl_msi_init_allocator(msi); - if (rc) { + err = fsl_msi_init_allocator(msi); + if (err) { dev_err(&dev->dev, "Error allocating MSI bitmap\n"); goto error_out; } p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); - if (p && len % (2 * sizeof(u32)) != 0) { - dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", - __func__); - err = -EINVAL; - goto error_out; - } - if (!p) { - p = all_avail; - len = sizeof(all_avail); - } + if (of_device_is_compatible(dev->dev.of_node, "fsl,mpic-msi-v4.3")) { + msi->srs_shift = MSIIR1_SRS_SHIFT; + msi->ibs_shift = MSIIR1_IBS_SHIFT; + if (p) + dev_warn(&dev->dev, "%s: dose not support msi-available-ranges property\n", + __func__); + + for (irq_index = 0; irq_index < NR_MSI_REG_MSIIR1; + irq_index++) { + err = fsl_msi_setup_hwirq(msi, dev, + irq_index, irq_index); + if (err) + goto error_out; + } + } else { + static const u32 all_avail[] = + { 0, NR_MSI_REG_MSIIR * IRQS_PER_MSI_REG }; + + msi->srs_shift = MSIIR_SRS_SHIFT; + msi->ibs_shift = MSIIR_IBS_SHIFT; - 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) { - printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n", - __func__, dev->dev.of_node->full_name, - p[i * 2 + 1], p[i * 2]); + if (p && len % (2 * sizeof(u32)) != 0) { + dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", + __func__); err = -EINVAL; goto error_out; } - offset = p[i * 2] / IRQS_PER_MSI_REG; - count = p[i * 2 + 1] / IRQS_PER_MSI_REG; + if (!p) { + p = all_avail; + len = sizeof(all_avail); + } - for (j = 0; j < count; j++, irq_index++) { - err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index); - if (err) + 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, + p[i * 2 + 1], p[i * 2]); + err = -EINVAL; goto error_out; + } + + offset = p[i * 2] / IRQS_PER_MSI_REG; + count = p[i * 2 + 1] / IRQS_PER_MSI_REG; + + for (j = 0; j < count; j++, irq_index++) { + err = fsl_msi_setup_hwirq(msi, dev, offset + j, + irq_index); + if (err) + goto error_out; + } } } @@ -636,6 +686,10 @@ static const struct of_device_id fsl_of_msi_ids[] = { .data = &mpic_msi_feature, }, { + .compatible = "fsl,mpic-msi-v4.3", + .data = &mpic_msi_feature, + }, + { .compatible = "fsl,ipic-msi", .data = &ipic_msi_feature, }, diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 7a427be..a871110 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -16,9 +16,11 @@ #include <linux/of.h> #include <asm/msi_bitmap.h> -#define NR_MSI_REG 8 +#define NR_MSI_REG_MSIIR 8 /* MSIIR can index 8 MSI registers */ +#define NR_MSI_REG_MSIIR1 16 /* MSIIR1 can index 16 MSI registers */ +#define NR_MSI_REG_MAX NR_MSI_REG_MSIIR1 #define IRQS_PER_MSI_REG 32 -#define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) +#define NR_MSI_IRQS_MAX (NR_MSI_REG_MAX * IRQS_PER_MSI_REG) #define FSL_PIC_IP_MASK 0x0000000F #define FSL_PIC_IP_MPIC 0x00000001 @@ -33,9 +35,11 @@ struct fsl_msi { unsigned long cascade_irq; u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */ + u32 ibs_shift; /* Shift of interrupt bit select */ + u32 srs_shift; /* Shift of the shared interrupt register select */ void __iomem *msi_regs; u32 feature; - int msi_virqs[NR_MSI_REG]; + int msi_virqs[NR_MSI_REG_MAX]; /* * During probe each bank is assigned a index number. diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 74064e1..82ed982 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -35,9 +35,9 @@ #include <asm/machdep.h> #include <asm/disassemble.h> #include <asm/ppc-opcode.h> -#include <asm/mpc85xx.h> #include <sysdev/fsl_soc.h> #include <sysdev/fsl_pci.h> +#include <asm/mpc85xx.h> static int fsl_pcie_bus_fixup, is_mpc83xx_pci; @@ -46,7 +46,7 @@ static void quirk_fsl_pcie_early(struct pci_dev *dev) u8 hdr_type; /* if we aren't a PCIe don't bother */ - if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) + if (!pci_is_pcie(dev)) return; /* if we aren't in host mode don't bother */ @@ -339,10 +339,10 @@ static void setup_pci_atmu(struct pci_controller *hose) #endif /* Size window to exact size if power-of-two or one size up */ 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); - mem_log++; } piwar |= ((mem_log - 1) & PIWAR_SZ_MASK); @@ -415,7 +415,9 @@ static void setup_pci_atmu(struct pci_controller *hose) } if (hose->dma_window_size < mem) { -#ifndef CONFIG_SWIOTLB +#ifdef CONFIG_SWIOTLB + ppc_swiotlb_enable = 1; +#else pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to " "map - enable CONFIG_SWIOTLB to avoid dma errors.\n", name); @@ -976,6 +978,15 @@ static int mcheck_handle_load(struct pt_regs *regs, u32 inst) regs->gpr[ra] += regs->gpr[rb]; break; + case OP_31_XOP_LHAX: + regs->gpr[rd] = ~0UL; + break; + + case OP_31_XOP_LHAUX: + regs->gpr[rd] = ~0UL; + regs->gpr[ra] += regs->gpr[rb]; + break; + default: return 0; } @@ -1008,6 +1019,15 @@ static int mcheck_handle_load(struct pt_regs *regs, u32 inst) regs->gpr[ra] += (s16)d; break; + case OP_LHA: + regs->gpr[rd] = ~0UL; + break; + + case OP_LHAU: + regs->gpr[rd] = ~0UL; + regs->gpr[ra] += (s16)d; + break; + default: return 0; } @@ -1032,7 +1052,6 @@ static int is_in_pci_mem_space(phys_addr_t addr) return 1; } } - return 0; } @@ -1131,28 +1150,10 @@ static int fsl_pci_probe(struct platform_device *pdev) { int ret; struct device_node *node; -#ifdef CONFIG_SWIOTLB - struct pci_controller *hose; -#endif node = pdev->dev.of_node; ret = fsl_add_bridge(pdev, fsl_pci_primary == node); -#ifdef CONFIG_SWIOTLB - if (ret == 0) { - hose = pci_find_hose_for_OF_device(pdev->dev.of_node); - - /* - * if we couldn't map all of DRAM via the dma windows - * we need SWIOTLB to handle buffers located outside of - * dma capable memory region - */ - if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur + - hose->dma_window_size) - ppc_swiotlb_enable = 1; - } -#endif - mpc85xx_pci_err_probe(pdev); return ret; diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index c95738b..2707da9 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -16,6 +16,7 @@ struct platform_device; + /* FSL PCI controller BRR1 register */ #define PCI_FSL_BRR1 0xbf8 #define PCI_FSL_BRR1_VER 0xffff diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c index 61dba33..81d75a6 100644 --- a/arch/powerpc/sysdev/fsl_pmc.c +++ b/arch/powerpc/sysdev/fsl_pmc.c @@ -19,6 +19,7 @@ #include <linux/suspend.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/pm.h> #include <asm/switch_to.h> diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c index ecf43a2..cd9d160 100644 --- a/arch/powerpc/sysdev/fsl_rcpm.c +++ b/arch/powerpc/sysdev/fsl_rcpm.c @@ -13,6 +13,7 @@ #include <linux/suspend.h> #include <linux/device.h> #include <linux/delay.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/export.h> diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8f315a5..499b9c2 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -28,6 +28,8 @@ #include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/device.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/slab.h> diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c index 14bd522..00e224a 100644 --- a/arch/powerpc/sysdev/fsl_rmu.c +++ b/arch/powerpc/sysdev/fsl_rmu.c @@ -27,6 +27,7 @@ #include <linux/types.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/slab.h> diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index a272feb..99fa2e5 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -32,8 +32,6 @@ static inline int mpc85xx_pmc_set_wake(struct device *dev, bool enable) #define mpc85xx_pmc_set_lossless_ethernet(enable) do { } while (0) #endif -#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) - /* The different ports that the DIU can be connected to */ enum fsl_diu_monitor_port { FSL_DIU_PORT_DVI, /* DVI */ @@ -54,7 +52,6 @@ struct platform_diu_data_ops { }; extern struct platform_diu_data_ops diu_ops; -#endif void fsl_hv_restart(char *cmd); void fsl_hv_halt(void); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index e500517..9152dbf 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -48,6 +48,12 @@ #define DBG(fmt...) #endif +struct bus_type mpic_subsys = { + .name = "mpic", + .dev_name = "mpic", +}; +EXPORT_SYMBOL_GPL(mpic_subsys); + static struct mpic *mpics; static struct mpic *mpic_primary; static DEFINE_RAW_SPINLOCK(mpic_lock); @@ -529,7 +535,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, mpic->fixups[irq].data = readl(base + 4) | 0x80000000; } } - + static void __init mpic_scan_ht_pics(struct mpic *mpic) { @@ -923,6 +929,10 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) static int mpic_irq_set_wake(struct irq_data *d, unsigned int on) { struct irq_desc *desc = container_of(d, struct irq_desc, irq_data); + struct mpic *mpic = mpic_from_irq_data(d); + + if (!(mpic->flags & MPIC_FSL)) + return -ENXIO; if (on) desc->action->flags |= IRQF_NO_SUSPEND; @@ -1079,8 +1089,14 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, * is done here. */ if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) { + int cpu; + + preempt_disable(); + cpu = mpic_processor_id(mpic); + preempt_enable(); + mpic_set_vector(virq, hw); - mpic_set_destination(virq, mpic_processor_id(mpic)); + mpic_set_destination(virq, cpu); mpic_irq_set_priority(virq, 8); } @@ -1466,7 +1482,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, * as a default instead of the value read from the HW. */ last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) - >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; + >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; if (isu_size) last_irq = isu_size * MPIC_MAX_ISU - 1; of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq); @@ -1616,7 +1632,7 @@ void __init mpic_init(struct mpic *mpic) /* start with vector = source number, and masked */ u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); - + /* check if protected */ if (mpic->protected && test_bit(i, mpic->protected)) continue; @@ -1625,7 +1641,7 @@ void __init mpic_init(struct mpic *mpic) mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); } } - + /* Init spurious vector */ mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec); @@ -2032,6 +2048,8 @@ static struct syscore_ops mpic_syscore_ops = { static int mpic_init_sys(void) { register_syscore_ops(&mpic_syscore_ops); + subsys_system_register(&mpic_subsys, NULL); + return 0; } diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index c753258..2c9b52a 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c @@ -237,15 +237,13 @@ static int mpic_msgr_probe(struct platform_device *dev) raw_spin_lock_init(&msgr->lock); if (receive_mask & (1 << i)) { - struct resource irq; - - if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) { + msgr->irq = irq_of_parse_and_map(np, irq_index); + if (msgr->irq == NO_IRQ) { dev_err(&dev->dev, "Missing interrupt specifier"); kfree(msgr); return -EFAULT; } - msgr->irq = irq.start; irq_index += 1; } else { msgr->irq = NO_IRQ; diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index bbf342c..7dc39f3 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -35,7 +35,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) const struct irq_domain_ops *ops = mpic->irqhost->ops; struct device_node *np; int flags, index, i; - struct of_irq oirq; + struct of_phandle_args oirq; pr_debug("mpic: found U3, guessing msi allocator setup\n"); @@ -63,9 +63,9 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); index = 0; - while (of_irq_map_one(np, index++, &oirq) == 0) { - ops->xlate(mpic->irqhost, NULL, oirq.specifier, - oirq.size, &hwirq, &flags); + while (of_irq_parse_one(np, index++, &oirq) == 0) { + ops->xlate(mpic->irqhost, NULL, oirq.args, + oirq.args_count, &hwirq, &flags); msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); } } diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c index 3aaa3d4..22d7d57 100644 --- a/arch/powerpc/sysdev/mpic_timer.c +++ b/arch/powerpc/sysdev/mpic_timer.c @@ -19,7 +19,9 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/syscore_ops.h> #include <sysdev/fsl_soc.h> #include <asm/io.h> @@ -28,7 +30,14 @@ #define FSL_GLOBAL_TIMER 0x1 -#define MPIC_TIMER_TCR_CLKDIV_64 0x00000300 +/* Clock Ratio + * Divide by 64 0x00000300 + * Divide by 32 0x00000200 + * Divide by 16 0x00000100 + * Divide by 8 0x00000000 (Hardware default div) + */ +#define MPIC_TIMER_TCR_CLKDIV 0x00000300 + #define MPIC_TIMER_TCR_ROVR_OFFSET 24 #define TIMER_STOP 0x80000000 @@ -83,26 +92,12 @@ static void convert_ticks_to_time(struct timer_group_priv *priv, const u64 ticks, struct timeval *time) { u64 tmp_sec; - u32 rem_us; - u32 div; - - if (!(priv->flags & FSL_GLOBAL_TIMER)) { - time->tv_sec = (__kernel_time_t) - div_u64_rem(ticks, priv->timerfreq, &rem_us); - tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq; - time->tv_usec = (__kernel_suseconds_t) - div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq); - - return; - } - - div = (1 << (MPIC_TIMER_TCR_CLKDIV_64 >> 8)) * 8; - time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq / div); - tmp_sec = div_u64((u64)time->tv_sec * (u64)priv->timerfreq, div); + time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq); + tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq; time->tv_usec = (__kernel_suseconds_t) - div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq / div); + div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq); return; } @@ -117,7 +112,6 @@ static int convert_time_to_ticks(struct timer_group_priv *priv, u64 tmp_sec; u64 tmp_ms; u64 tmp_us; - u32 div; max_value = div_u64(ULLONG_MAX, priv->timerfreq); @@ -125,27 +119,15 @@ static int convert_time_to_ticks(struct timer_group_priv *priv, (time->tv_sec == max_value && time->tv_usec > 0)) return -EINVAL; - if (!(priv->flags & FSL_GLOBAL_TIMER)) { - tmp_sec = time->tv_sec * priv->timerfreq; - tmp_ms = time->tv_usec / 1000 * priv->timerfreq / 1000; - tmp_us = time->tv_usec % 1000 * priv->timerfreq / 1000000; - - *ticks = tmp_sec + tmp_ms + tmp_us; - - return 0; - } - - div = (1 << (MPIC_TIMER_TCR_CLKDIV_64 >> 8)) * 8; - - tmp_sec = div_u64((u64)time->tv_sec * (u64)priv->timerfreq, div); + tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq; tmp += tmp_sec; tmp_ms = time->tv_usec / 1000; - tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, div * 1000); + tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, 1000); tmp += tmp_ms; tmp_us = time->tv_usec % 1000; - tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, div * 1000000); + tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, 1000000); tmp += tmp_us; *ticks = tmp; @@ -260,8 +242,8 @@ static struct mpic_timer *get_timer(const struct timeval *time) timer = get_cascade_timer(priv, ticks); if (!timer) continue; - else - return timer; + + return timer; } for (i = 0; i < TIMERS_PER_GROUP; i++) { @@ -438,6 +420,8 @@ EXPORT_SYMBOL(mpic_request_timer); static int timer_group_get_freq(struct device_node *np, struct timer_group_priv *priv) { + u32 div; + if (priv->flags & FSL_GLOBAL_TIMER) { struct device_node *dn; @@ -452,6 +436,11 @@ static int timer_group_get_freq(struct device_node *np, if (priv->timerfreq <= 0) return -EINVAL; + if (priv->flags & FSL_GLOBAL_TIMER) { + div = (1 << (MPIC_TIMER_TCR_CLKDIV >> 8)) * 8; + priv->timerfreq /= div; + } + return 0; } @@ -553,7 +542,7 @@ static void timer_group_init(struct device_node *np) /* Init FSL timer hardware */ if (priv->flags & FSL_GLOBAL_TIMER) - setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV_64); + setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV); list_add_tail(&priv->node, &timer_group_list); @@ -576,7 +565,7 @@ static void mpic_timer_resume(void) list_for_each_entry(priv, &timer_group_list, node) { /* Init FSL timer hardware */ if (priv->flags & FSL_GLOBAL_TIMER) - setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV_64); + setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV); } } diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 4a25c26..a3a8fad 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -228,7 +228,7 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev( if (id == 0) { pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1); - if (!pdev) + if (IS_ERR(pdev)) return pdev; } diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c index c9e803f..6f54b54 100644 --- a/arch/powerpc/sysdev/of_rtc.c +++ b/arch/powerpc/sysdev/of_rtc.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/of.h> #include <linux/init.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/slab.h> diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c index 1b15f93..b7c4345 100644 --- a/arch/powerpc/sysdev/ppc4xx_ocm.c +++ b/arch/powerpc/sysdev/ppc4xx_ocm.c @@ -26,6 +26,7 @@ #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> diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c index 0debcc3..5c77c9b 100644 --- a/arch/powerpc/sysdev/ppc4xx_soc.c +++ b/arch/powerpc/sysdev/ppc4xx_soc.c @@ -19,6 +19,7 @@ #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> diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c index af79e1e..af0f9be 100644 --- a/arch/powerpc/sysdev/rtc_cmos_setup.c +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c @@ -62,7 +62,7 @@ static int __init add_rtc(void) pd = platform_device_register_simple("rtc_cmos", -1, &res[0], num_res); - return PTR_RET(pd); + return PTR_ERR_OR_ZERO(pd); } fs_initcall(add_rtc); diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c index 9193e12..6f5a8d1 100644 --- a/arch/powerpc/sysdev/scom.c +++ b/arch/powerpc/sysdev/scom.c @@ -25,6 +25,7 @@ #include <asm/debug.h> #include <asm/prom.h> #include <asm/scom.h> +#include <asm/uaccess.h> const struct scom_controller *scom_controller; EXPORT_SYMBOL_GPL(scom_controller); @@ -53,7 +54,7 @@ scom_map_t scom_map_device(struct device_node *dev, int index) { struct device_node *parent; unsigned int cells, size; - const u32 *prop; + const __be32 *prop, *sprop; u64 reg, cnt; scom_map_t ret; @@ -62,12 +63,24 @@ scom_map_t scom_map_device(struct device_node *dev, int index) if (parent == NULL) return 0; - prop = of_get_property(parent, "#scom-cells", NULL); - cells = prop ? *prop : 1; - + /* + * We support "scom-reg" properties for adding scom registers + * to a random device-tree node with an explicit scom-parent + * + * We also support the simple "reg" property if the device is + * a direct child of a scom controller. + * + * In case both exist, "scom-reg" takes precedence. + */ prop = of_get_property(dev, "scom-reg", &size); + sprop = of_get_property(parent, "#scom-cells", NULL); + if (!prop && parent == dev->parent) { + prop = of_get_property(dev, "reg", &size); + sprop = of_get_property(parent, "#address-cells", NULL); + } if (!prop) - return 0; + return NULL; + cells = sprop ? be32_to_cpup(sprop) : 1; size >>= 2; if (index >= (size / (2*cells))) @@ -86,62 +99,89 @@ EXPORT_SYMBOL_GPL(scom_map_device); #ifdef CONFIG_SCOM_DEBUGFS struct scom_debug_entry { struct device_node *dn; - unsigned long addr; - scom_map_t map; - spinlock_t lock; - char name[8]; - struct debugfs_blob_wrapper blob; + struct debugfs_blob_wrapper path; + char name[16]; }; -static int scom_addr_set(void *data, u64 val) +static ssize_t scom_debug_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos) { - struct scom_debug_entry *ent = data; - - ent->addr = 0; - scom_unmap(ent->map); - - ent->map = scom_map(ent->dn, val, 1); - if (scom_map_ok(ent->map)) - ent->addr = val; - else - return -EFAULT; - - return 0; -} - -static int scom_addr_get(void *data, u64 *val) -{ - struct scom_debug_entry *ent = data; - *val = ent->addr; - return 0; + struct scom_debug_entry *ent = filp->private_data; + u64 __user *ubuf64 = (u64 __user *)ubuf; + loff_t off = *ppos; + ssize_t done = 0; + u64 reg, reg_cnt, val; + scom_map_t map; + int rc; + + if (off < 0 || (off & 7) || (count & 7)) + return -EINVAL; + reg = off >> 3; + reg_cnt = count >> 3; + + map = scom_map(ent->dn, reg, reg_cnt); + if (!scom_map_ok(map)) + return -ENXIO; + + for (reg = 0; reg < reg_cnt; reg++) { + rc = scom_read(map, reg, &val); + if (!rc) + rc = put_user(val, ubuf64); + if (rc) { + if (!done) + done = rc; + break; + } + ubuf64++; + *ppos += 8; + done += 8; + } + scom_unmap(map); + return done; } -DEFINE_SIMPLE_ATTRIBUTE(scom_addr_fops, scom_addr_get, scom_addr_set, - "0x%llx\n"); -static int scom_val_set(void *data, u64 val) +static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf, + size_t count, loff_t *ppos) { - struct scom_debug_entry *ent = data; - - if (!scom_map_ok(ent->map)) - return -EFAULT; - - scom_write(ent->map, 0, val); - - return 0; + struct scom_debug_entry *ent = filp->private_data; + u64 __user *ubuf64 = (u64 __user *)ubuf; + loff_t off = *ppos; + ssize_t done = 0; + u64 reg, reg_cnt, val; + scom_map_t map; + int rc; + + if (off < 0 || (off & 7) || (count & 7)) + return -EINVAL; + reg = off >> 3; + reg_cnt = count >> 3; + + map = scom_map(ent->dn, reg, reg_cnt); + if (!scom_map_ok(map)) + return -ENXIO; + + for (reg = 0; reg < reg_cnt; reg++) { + rc = get_user(val, ubuf64); + if (!rc) + rc = scom_write(map, reg, val); + if (rc) { + if (!done) + done = rc; + break; + } + ubuf64++; + done += 8; + } + scom_unmap(map); + return done; } -static int scom_val_get(void *data, u64 *val) -{ - struct scom_debug_entry *ent = data; - - if (!scom_map_ok(ent->map)) - return -EFAULT; - - *val = scom_read(ent->map, 0); - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set, - "0x%llx\n"); +static const struct file_operations scom_debug_fops = { + .read = scom_debug_read, + .write = scom_debug_write, + .open = simple_open, + .llseek = default_llseek, +}; static int scom_debug_init_one(struct dentry *root, struct device_node *dn, int i) @@ -154,11 +194,9 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn, return -ENOMEM; ent->dn = of_node_get(dn); - ent->map = SCOM_MAP_INVALID; - spin_lock_init(&ent->lock); - snprintf(ent->name, 8, "scom%d", i); - ent->blob.data = (void*) dn->full_name; - ent->blob.size = strlen(dn->full_name); + snprintf(ent->name, 16, "%08x", i); + ent->path.data = (void*) dn->full_name; + ent->path.size = strlen(dn->full_name); dir = debugfs_create_dir(ent->name, root); if (!dir) { @@ -167,9 +205,8 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn, return -1; } - debugfs_create_file("addr", 0600, dir, ent, &scom_addr_fops); - debugfs_create_file("value", 0600, dir, ent, &scom_val_fops); - debugfs_create_blob("path", 0400, dir, &ent->blob); + debugfs_create_blob("devspec", 0400, dir, &ent->path); + debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops); return 0; } @@ -185,8 +222,13 @@ static int scom_debug_init(void) return -1; i = rc = 0; - for_each_node_with_property(dn, "scom-controller") - rc |= scom_debug_init_one(root, dn, i++); + for_each_node_with_property(dn, "scom-controller") { + int id = of_get_ibm_chip_id(dn); + if (id == -1) + id = i; + rc |= scom_debug_init_one(root, dn, id); + i++; + } return rc; } diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 7cd728b..9dee470 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c @@ -216,7 +216,7 @@ static int __init icp_native_init_one_node(struct device_node *np, unsigned int *indx) { unsigned int ilen; - const u32 *ireg; + const __be32 *ireg; int i; int reg_tuple_size; int num_servers = 0; diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index 39d7221..3c6ee1b 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c @@ -112,6 +112,7 @@ static int ics_opal_set_affinity(struct irq_data *d, bool force) { unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); + __be16 oserver; int16_t server; int8_t priority; int64_t rc; @@ -120,13 +121,13 @@ static int ics_opal_set_affinity(struct irq_data *d, if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) return -1; - rc = opal_get_xive(hw_irq, &server, &priority); + rc = opal_get_xive(hw_irq, &oserver, &priority); if (rc != OPAL_SUCCESS) { - pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)" - " error %lld\n", - __func__, d->irq, hw_irq, server, rc); + pr_err("%s: opal_get_xive(irq=%d [hw 0x%x]) error %lld\n", + __func__, d->irq, hw_irq, rc); return -1; } + server = be16_to_cpu(oserver); wanted_server = xics_get_irq_server(d->irq, cpumask, 1); if (wanted_server < 0) { @@ -181,7 +182,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq) { unsigned int hw_irq = (unsigned int)virq_to_hw(virq); int64_t rc; - int16_t server; + __be16 server; int8_t priority; if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)) @@ -201,7 +202,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq) static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) { int64_t rc; - int16_t server; + __be16 server; int8_t priority; /* Check if HAL knows about this interrupt */ @@ -215,14 +216,14 @@ static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) static long ics_opal_get_server(struct ics *ics, unsigned long vec) { int64_t rc; - int16_t server; + __be16 server; int8_t priority; /* Check if HAL knows about this interrupt */ rc = opal_get_xive(vec, &server, &priority); if (rc != OPAL_SUCCESS) return -1; - return ics_opal_unmangle_server(server); + return ics_opal_unmangle_server(be16_to_cpu(server)); } int __init ics_opal_init(void) diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 9049d9f..fe0cca4 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -49,7 +49,7 @@ void xics_update_irq_servers(void) int i, j; struct device_node *np; u32 ilen; - const u32 *ireg; + const __be32 *ireg; u32 hcpuid; /* Find the server numbers for the boot cpu. */ @@ -75,8 +75,8 @@ void xics_update_irq_servers(void) * default distribution server */ for (j = 0; j < i; j += 2) { - if (ireg[j] == hcpuid) { - xics_default_distrib_server = ireg[j+1]; + if (be32_to_cpu(ireg[j]) == hcpuid) { + xics_default_distrib_server = be32_to_cpu(ireg[j+1]); break; } } @@ -383,7 +383,7 @@ void __init xics_register_ics(struct ics *ics) static void __init xics_get_server_size(void) { struct device_node *np; - const u32 *isize; + const __be32 *isize; /* We fetch the interrupt server size from the first ICS node * we find if any @@ -394,7 +394,7 @@ static void __init xics_get_server_size(void) isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); if (!isize) return; - xics_interrupt_server_size = *isize; + xics_interrupt_server_size = be32_to_cpu(*isize); of_node_put(np); } diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c index 8d73c3c..83f943a 100644 --- a/arch/powerpc/sysdev/xilinx_intc.c +++ b/arch/powerpc/sysdev/xilinx_intc.c @@ -23,6 +23,8 @@ #include <linux/kernel.h> #include <linux/irq.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/i8259.h> |