diff options
Diffstat (limited to 'arch/powerpc/sysdev')
38 files changed, 441 insertions, 489 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index cf736ca0cf05..84e13253aec5 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
| @@ -18,7 +18,6 @@ obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) | |||
| 18 | obj-$(CONFIG_FSL_PMC) += fsl_pmc.o | 18 | obj-$(CONFIG_FSL_PMC) += fsl_pmc.o |
| 19 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 19 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
| 20 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o | 20 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o |
| 21 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o | ||
| 22 | obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o | 21 | obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o |
| 23 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o | 22 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o |
| 24 | obj-$(CONFIG_FSL_RIO) += fsl_rio.o | 23 | obj-$(CONFIG_FSL_RIO) += fsl_rio.o |
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 265f0f09395a..ba4271919062 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c | |||
| @@ -104,7 +104,7 @@ axon_ram_irq_handler(int irq, void *dev) | |||
| 104 | * axon_ram_make_request - make_request() method for block device | 104 | * axon_ram_make_request - make_request() method for block device |
| 105 | * @queue, @bio: see blk_queue_make_request() | 105 | * @queue, @bio: see blk_queue_make_request() |
| 106 | */ | 106 | */ |
| 107 | static int | 107 | static void |
| 108 | axon_ram_make_request(struct request_queue *queue, struct bio *bio) | 108 | axon_ram_make_request(struct request_queue *queue, struct bio *bio) |
| 109 | { | 109 | { |
| 110 | struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data; | 110 | struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data; |
| @@ -113,7 +113,6 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) | |||
| 113 | struct bio_vec *vec; | 113 | struct bio_vec *vec; |
| 114 | unsigned int transfered; | 114 | unsigned int transfered; |
| 115 | unsigned short idx; | 115 | unsigned short idx; |
| 116 | int rc = 0; | ||
| 117 | 116 | ||
| 118 | phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT); | 117 | phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT); |
| 119 | phys_end = bank->io_addr + bank->size; | 118 | phys_end = bank->io_addr + bank->size; |
| @@ -121,8 +120,7 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) | |||
| 121 | bio_for_each_segment(vec, bio, idx) { | 120 | bio_for_each_segment(vec, bio, idx) { |
| 122 | if (unlikely(phys_mem + vec->bv_len > phys_end)) { | 121 | if (unlikely(phys_mem + vec->bv_len > phys_end)) { |
| 123 | bio_io_error(bio); | 122 | bio_io_error(bio); |
| 124 | rc = -ERANGE; | 123 | return; |
| 125 | break; | ||
| 126 | } | 124 | } |
| 127 | 125 | ||
| 128 | user_mem = page_address(vec->bv_page) + vec->bv_offset; | 126 | user_mem = page_address(vec->bv_page) + vec->bv_offset; |
| @@ -135,8 +133,6 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) | |||
| 135 | transfered += vec->bv_len; | 133 | transfered += vec->bv_len; |
| 136 | } | 134 | } |
| 137 | bio_endio(bio, 0); | 135 | bio_endio(bio, 0); |
| 138 | |||
| 139 | return rc; | ||
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | /** | 138 | /** |
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c index 1225012a681a..b6db23e085fb 100644 --- a/arch/powerpc/sysdev/bestcomm/sram.c +++ b/arch/powerpc/sysdev/bestcomm/sram.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/export.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index d55d0ad0deab..bf6c7cc0a6af 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Author: Scott Wood <scottwood@freescale.com> | 4 | * Author: Scott Wood <scottwood@freescale.com> |
| 5 | * | 5 | * |
| 6 | * Copyright 2007 Freescale Semiconductor, Inc. | 6 | * Copyright 2007-2008,2010 Freescale Semiconductor, Inc. |
| 7 | * | 7 | * |
| 8 | * Some parts derived from commproc.c/cpm2_common.c, which is: | 8 | * Some parts derived from commproc.c/cpm2_common.c, which is: |
| 9 | * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) | 9 | * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) |
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
| 22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| 23 | #include <linux/export.h> | ||
| 23 | #include <linux/of.h> | 24 | #include <linux/of.h> |
| 24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 25 | 26 | ||
| @@ -146,6 +147,7 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) | |||
| 146 | spin_lock_irqsave(&cpm_muram_lock, flags); | 147 | spin_lock_irqsave(&cpm_muram_lock, flags); |
| 147 | cpm_muram_info.alignment = align; | 148 | cpm_muram_info.alignment = align; |
| 148 | start = rh_alloc(&cpm_muram_info, size, "commproc"); | 149 | start = rh_alloc(&cpm_muram_info, size, "commproc"); |
| 150 | memset(cpm_muram_addr(start), 0, size); | ||
| 149 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | 151 | spin_unlock_irqrestore(&cpm_muram_lock, flags); |
| 150 | 152 | ||
| 151 | return start; | 153 | return start; |
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index bb44aa9fd470..1bd0eba4d355 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #undef DEBUG | 20 | #undef DEBUG |
| 21 | 21 | ||
| 22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| 23 | #include <linux/export.h> | ||
| 23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
| 24 | #include <asm/dcr.h> | 25 | #include <asm/dcr.h> |
| 25 | 26 | ||
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c index 7dd2885321ad..02cf1e7e77fc 100644 --- a/arch/powerpc/sysdev/fsl_gtm.c +++ b/arch/powerpc/sysdev/fsl_gtm.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| 23 | #include <linux/bitops.h> | 23 | #include <linux/bitops.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/export.h> | ||
| 25 | #include <asm/fsl_gtm.h> | 26 | #include <asm/fsl_gtm.h> |
| 26 | 27 | ||
| 27 | #define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1) | 28 | #define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1) |
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index d917573cf1a8..c4d96fa32ba5 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/export.h> |
| 19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/compiler.h> | 20 | #include <linux/compiler.h> |
| 21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/sched.h> | ||
| 26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 27 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
| 28 | #include <linux/mod_devicetable.h> | 29 | #include <linux/mod_devicetable.h> |
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 419a77239bd7..e5c344d336ea 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
| @@ -30,7 +30,7 @@ LIST_HEAD(msi_head); | |||
| 30 | 30 | ||
| 31 | struct fsl_msi_feature { | 31 | struct fsl_msi_feature { |
| 32 | u32 fsl_pic_ip; | 32 | u32 fsl_pic_ip; |
| 33 | u32 msiir_offset; | 33 | u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */ |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | struct fsl_msi_cascade_data { | 36 | struct fsl_msi_cascade_data { |
| @@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
| 126 | { | 126 | { |
| 127 | struct fsl_msi *msi_data = fsl_msi_data; | 127 | struct fsl_msi *msi_data = fsl_msi_data; |
| 128 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 128 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
| 129 | u64 base = fsl_pci_immrbar_base(hose); | 129 | u64 address; /* Physical address of the MSIIR */ |
| 130 | int len; | ||
| 131 | const u64 *reg; | ||
| 132 | |||
| 133 | /* If the msi-address-64 property exists, then use it */ | ||
| 134 | reg = of_get_property(hose->dn, "msi-address-64", &len); | ||
| 135 | if (reg && (len == sizeof(u64))) | ||
| 136 | address = be64_to_cpup(reg); | ||
| 137 | else | ||
| 138 | address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset; | ||
| 130 | 139 | ||
| 131 | msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); | 140 | msg->address_lo = lower_32_bits(address); |
| 132 | msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); | 141 | msg->address_hi = upper_32_bits(address); |
| 133 | 142 | ||
| 134 | msg->data = hwirq; | 143 | msg->data = hwirq; |
| 135 | 144 | ||
| @@ -296,7 +305,7 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi, | |||
| 296 | } | 305 | } |
| 297 | 306 | ||
| 298 | msi->msi_virqs[irq_index] = virt_msir; | 307 | msi->msi_virqs[irq_index] = virt_msir; |
| 299 | cascade_data->index = offset + irq_index; | 308 | cascade_data->index = offset; |
| 300 | cascade_data->msi_data = msi; | 309 | cascade_data->msi_data = msi; |
| 301 | irq_set_handler_data(virt_msir, cascade_data); | 310 | irq_set_handler_data(virt_msir, cascade_data); |
| 302 | irq_set_chained_handler(virt_msir, fsl_msi_cascade); | 311 | irq_set_chained_handler(virt_msir, fsl_msi_cascade); |
| @@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 359 | 368 | ||
| 360 | msi->irqhost->host_data = msi; | 369 | msi->irqhost->host_data = msi; |
| 361 | 370 | ||
| 362 | msi->msi_addr_hi = 0x0; | 371 | msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); |
| 363 | msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff); | ||
| 364 | 372 | ||
| 365 | rc = fsl_msi_init_allocator(msi); | 373 | rc = fsl_msi_init_allocator(msi); |
| 366 | if (rc) { | 374 | if (rc) { |
| @@ -376,8 +384,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 376 | goto error_out; | 384 | goto error_out; |
| 377 | } | 385 | } |
| 378 | 386 | ||
| 379 | if (!p) | 387 | if (!p) { |
| 380 | p = all_avail; | 388 | p = all_avail; |
| 389 | len = sizeof(all_avail); | ||
| 390 | } | ||
| 381 | 391 | ||
| 382 | for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { | 392 | for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { |
| 383 | if (p[i * 2] % IRQS_PER_MSI_REG || | 393 | if (p[i * 2] % IRQS_PER_MSI_REG || |
| @@ -393,7 +403,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 393 | count = p[i * 2 + 1] / IRQS_PER_MSI_REG; | 403 | count = p[i * 2 + 1] / IRQS_PER_MSI_REG; |
| 394 | 404 | ||
| 395 | for (j = 0; j < count; j++, irq_index++) { | 405 | for (j = 0; j < count; j++, irq_index++) { |
| 396 | err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index); | 406 | err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index); |
| 397 | if (err) | 407 | if (err) |
| 398 | goto error_out; | 408 | goto error_out; |
| 399 | } | 409 | } |
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 624580c252d7..1313abbc5200 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
| @@ -28,8 +28,7 @@ struct fsl_msi { | |||
| 28 | 28 | ||
| 29 | unsigned long cascade_irq; | 29 | unsigned long cascade_irq; |
| 30 | 30 | ||
| 31 | u32 msi_addr_lo; | 31 | u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */ |
| 32 | u32 msi_addr_hi; | ||
| 33 | void __iomem *msi_regs; | 32 | void __iomem *msi_regs; |
| 34 | u32 feature; | 33 | u32 feature; |
| 35 | int msi_virqs[NR_MSI_REG]; | 34 | int msi_virqs[NR_MSI_REG]; |
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c index f122e8961d32..592a0f8d527a 100644 --- a/arch/powerpc/sysdev/fsl_pmc.c +++ b/arch/powerpc/sysdev/fsl_pmc.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
| 17 | #include <linux/export.h> | ||
| 17 | #include <linux/suspend.h> | 18 | #include <linux/suspend.h> |
| 18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index c65f75aa7ff7..22ffccd8bef5 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
| @@ -1608,6 +1608,7 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 1608 | return 0; | 1608 | return 0; |
| 1609 | err: | 1609 | err: |
| 1610 | iounmap(priv->regs_win); | 1610 | iounmap(priv->regs_win); |
| 1611 | release_resource(&port->iores); | ||
| 1611 | err_res: | 1612 | err_res: |
| 1612 | kfree(priv); | 1613 | kfree(priv); |
| 1613 | err_priv: | 1614 | err_priv: |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 2d66275e489f..e8f385fbf549 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/export.h> |
| 23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 2ece02beb8ff..c6d00736f07f 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
| @@ -22,15 +22,24 @@ struct device_node; | |||
| 22 | extern void fsl_rstcr_restart(char *cmd); | 22 | extern void fsl_rstcr_restart(char *cmd); |
| 23 | 23 | ||
| 24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | 24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
| 25 | |||
| 26 | /* The different ports that the DIU can be connected to */ | ||
| 27 | enum fsl_diu_monitor_port { | ||
| 28 | FSL_DIU_PORT_DVI, /* DVI */ | ||
| 29 | FSL_DIU_PORT_LVDS, /* Single-link LVDS */ | ||
| 30 | FSL_DIU_PORT_DLVDS /* Dual-link LVDS */ | ||
| 31 | }; | ||
| 32 | |||
| 25 | struct platform_diu_data_ops { | 33 | struct platform_diu_data_ops { |
| 26 | unsigned int (*get_pixel_format) (unsigned int bits_per_pixel, | 34 | u32 (*get_pixel_format)(enum fsl_diu_monitor_port port, |
| 27 | int monitor_port); | 35 | unsigned int bpp); |
| 28 | void (*set_gamma_table) (int monitor_port, char *gamma_table_base); | 36 | void (*set_gamma_table)(enum fsl_diu_monitor_port port, |
| 29 | void (*set_monitor_port) (int monitor_port); | 37 | char *gamma_table_base); |
| 30 | void (*set_pixel_clock) (unsigned int pixclock); | 38 | void (*set_monitor_port)(enum fsl_diu_monitor_port port); |
| 31 | ssize_t (*show_monitor_port) (int monitor_port, char *buf); | 39 | void (*set_pixel_clock)(unsigned int pixclock); |
| 32 | int (*set_sysfs_monitor_port) (int val); | 40 | enum fsl_diu_monitor_port (*valid_monitor_port) |
| 33 | void (*release_bootmem) (void); | 41 | (enum fsl_diu_monitor_port port); |
| 42 | void (*release_bootmem)(void); | ||
| 34 | }; | 43 | }; |
| 35 | 44 | ||
| 36 | extern struct platform_diu_data_ops diu_ops; | 45 | extern struct platform_diu_data_ops diu_ops; |
diff --git a/arch/powerpc/sysdev/mpc5xxx_clocks.c b/arch/powerpc/sysdev/mpc5xxx_clocks.c index 34e12f9995fe..96f815a55dfd 100644 --- a/arch/powerpc/sysdev/mpc5xxx_clocks.c +++ b/arch/powerpc/sysdev/mpc5xxx_clocks.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/of_platform.h> | 10 | #include <linux/of_platform.h> |
| 11 | #include <linux/export.h> | ||
| 11 | 12 | ||
| 12 | unsigned int | 13 | unsigned int |
| 13 | mpc5xxx_get_bus_frequency(struct device_node *node) | 14 | mpc5xxx_get_bus_frequency(struct device_node *node) |
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index 22e48e2d71f1..2ca0a85fcce9 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
| 2 | #include <linux/module.h> | ||
| 3 | #include <linux/stddef.h> | 2 | #include <linux/stddef.h> |
| 4 | #include <linux/init.h> | 3 | #include <linux/init.h> |
| 5 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c deleted file mode 100644 index fb4963abdf55..000000000000 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ /dev/null | |||
| @@ -1,395 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * GPIOs on MPC512x/8349/8572/8610 and compatible | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public License | ||
| 7 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 8 | * kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/spinlock.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_gpio.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/irq.h> | ||
| 20 | |||
| 21 | #define MPC8XXX_GPIO_PINS 32 | ||
| 22 | |||
| 23 | #define GPIO_DIR 0x00 | ||
| 24 | #define GPIO_ODR 0x04 | ||
| 25 | #define GPIO_DAT 0x08 | ||
| 26 | #define GPIO_IER 0x0c | ||
| 27 | #define GPIO_IMR 0x10 | ||
| 28 | #define GPIO_ICR 0x14 | ||
| 29 | #define GPIO_ICR2 0x18 | ||
| 30 | |||
| 31 | struct mpc8xxx_gpio_chip { | ||
| 32 | struct of_mm_gpio_chip mm_gc; | ||
| 33 | spinlock_t lock; | ||
| 34 | |||
| 35 | /* | ||
| 36 | * shadowed data register to be able to clear/set output pins in | ||
| 37 | * open drain mode safely | ||
| 38 | */ | ||
| 39 | u32 data; | ||
| 40 | struct irq_host *irq; | ||
| 41 | void *of_dev_id_data; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) | ||
| 45 | { | ||
| 46 | return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline struct mpc8xxx_gpio_chip * | ||
| 50 | to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm) | ||
| 51 | { | ||
| 52 | return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) | ||
| 56 | { | ||
| 57 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 58 | |||
| 59 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs | ||
| 63 | * defined as output cannot be determined by reading GPDAT register, | ||
| 64 | * so we use shadow data register instead. The status of input pins | ||
| 65 | * is determined by reading GPDAT register. | ||
| 66 | */ | ||
| 67 | static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 68 | { | ||
| 69 | u32 val; | ||
| 70 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 71 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 72 | |||
| 73 | val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); | ||
| 74 | |||
| 75 | return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); | ||
| 76 | } | ||
| 77 | |||
| 78 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 79 | { | ||
| 80 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 81 | |||
| 82 | return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 86 | { | ||
| 87 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 88 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 89 | unsigned long flags; | ||
| 90 | |||
| 91 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 92 | |||
| 93 | if (val) | ||
| 94 | mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); | ||
| 95 | else | ||
| 96 | mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); | ||
| 97 | |||
| 98 | out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); | ||
| 99 | |||
| 100 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 104 | { | ||
| 105 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 106 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 107 | unsigned long flags; | ||
| 108 | |||
| 109 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 110 | |||
| 111 | clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); | ||
| 112 | |||
| 113 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 119 | { | ||
| 120 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 121 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 122 | unsigned long flags; | ||
| 123 | |||
| 124 | mpc8xxx_gpio_set(gc, gpio, val); | ||
| 125 | |||
| 126 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 127 | |||
| 128 | setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); | ||
| 129 | |||
| 130 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 131 | |||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 136 | { | ||
| 137 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 138 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 139 | |||
| 140 | if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS) | ||
| 141 | return irq_create_mapping(mpc8xxx_gc->irq, offset); | ||
| 142 | else | ||
| 143 | return -ENXIO; | ||
| 144 | } | ||
| 145 | |||
| 146 | static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc) | ||
| 147 | { | ||
| 148 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc); | ||
| 149 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 150 | unsigned int mask; | ||
| 151 | |||
| 152 | mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR); | ||
| 153 | if (mask) | ||
| 154 | generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, | ||
| 155 | 32 - ffs(mask))); | ||
| 156 | } | ||
| 157 | |||
| 158 | static void mpc8xxx_irq_unmask(struct irq_data *d) | ||
| 159 | { | ||
| 160 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); | ||
| 161 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 162 | unsigned long flags; | ||
| 163 | |||
| 164 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 165 | |||
| 166 | setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); | ||
| 167 | |||
| 168 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 169 | } | ||
| 170 | |||
| 171 | static void mpc8xxx_irq_mask(struct irq_data *d) | ||
| 172 | { | ||
| 173 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); | ||
| 174 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 175 | unsigned long flags; | ||
| 176 | |||
| 177 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 178 | |||
| 179 | clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); | ||
| 180 | |||
| 181 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void mpc8xxx_irq_ack(struct irq_data *d) | ||
| 185 | { | ||
| 186 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); | ||
| 187 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 188 | |||
| 189 | out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) | ||
| 193 | { | ||
| 194 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); | ||
| 195 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 196 | unsigned long flags; | ||
| 197 | |||
| 198 | switch (flow_type) { | ||
| 199 | case IRQ_TYPE_EDGE_FALLING: | ||
| 200 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 201 | setbits32(mm->regs + GPIO_ICR, | ||
| 202 | mpc8xxx_gpio2mask(irqd_to_hwirq(d))); | ||
| 203 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 204 | break; | ||
| 205 | |||
| 206 | case IRQ_TYPE_EDGE_BOTH: | ||
| 207 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 208 | clrbits32(mm->regs + GPIO_ICR, | ||
| 209 | mpc8xxx_gpio2mask(irqd_to_hwirq(d))); | ||
| 210 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 211 | break; | ||
| 212 | |||
| 213 | default: | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type) | ||
| 221 | { | ||
| 222 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); | ||
| 223 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 224 | unsigned long gpio = irqd_to_hwirq(d); | ||
| 225 | void __iomem *reg; | ||
| 226 | unsigned int shift; | ||
| 227 | unsigned long flags; | ||
| 228 | |||
| 229 | if (gpio < 16) { | ||
| 230 | reg = mm->regs + GPIO_ICR; | ||
| 231 | shift = (15 - gpio) * 2; | ||
| 232 | } else { | ||
| 233 | reg = mm->regs + GPIO_ICR2; | ||
| 234 | shift = (15 - (gpio % 16)) * 2; | ||
| 235 | } | ||
| 236 | |||
| 237 | switch (flow_type) { | ||
| 238 | case IRQ_TYPE_EDGE_FALLING: | ||
| 239 | case IRQ_TYPE_LEVEL_LOW: | ||
| 240 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 241 | clrsetbits_be32(reg, 3 << shift, 2 << shift); | ||
| 242 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 243 | break; | ||
| 244 | |||
| 245 | case IRQ_TYPE_EDGE_RISING: | ||
| 246 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 247 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 248 | clrsetbits_be32(reg, 3 << shift, 1 << shift); | ||
| 249 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 250 | break; | ||
| 251 | |||
| 252 | case IRQ_TYPE_EDGE_BOTH: | ||
| 253 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 254 | clrbits32(reg, 3 << shift); | ||
| 255 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 256 | break; | ||
| 257 | |||
| 258 | default: | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static struct irq_chip mpc8xxx_irq_chip = { | ||
| 266 | .name = "mpc8xxx-gpio", | ||
| 267 | .irq_unmask = mpc8xxx_irq_unmask, | ||
| 268 | .irq_mask = mpc8xxx_irq_mask, | ||
| 269 | .irq_ack = mpc8xxx_irq_ack, | ||
| 270 | .irq_set_type = mpc8xxx_irq_set_type, | ||
| 271 | }; | ||
| 272 | |||
| 273 | static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, | ||
| 274 | irq_hw_number_t hw) | ||
| 275 | { | ||
| 276 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data; | ||
| 277 | |||
| 278 | if (mpc8xxx_gc->of_dev_id_data) | ||
| 279 | mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data; | ||
| 280 | |||
| 281 | irq_set_chip_data(virq, h->host_data); | ||
| 282 | irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); | ||
| 283 | irq_set_irq_type(virq, IRQ_TYPE_NONE); | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct, | ||
| 289 | const u32 *intspec, unsigned int intsize, | ||
| 290 | irq_hw_number_t *out_hwirq, | ||
| 291 | unsigned int *out_flags) | ||
| 292 | |||
| 293 | { | ||
| 294 | /* interrupt sense values coming from the device tree equal either | ||
| 295 | * EDGE_FALLING or EDGE_BOTH | ||
| 296 | */ | ||
| 297 | *out_hwirq = intspec[0]; | ||
| 298 | *out_flags = intspec[1]; | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static struct irq_host_ops mpc8xxx_gpio_irq_ops = { | ||
| 304 | .map = mpc8xxx_gpio_irq_map, | ||
| 305 | .xlate = mpc8xxx_gpio_irq_xlate, | ||
| 306 | }; | ||
| 307 | |||
| 308 | static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { | ||
| 309 | { .compatible = "fsl,mpc8349-gpio", }, | ||
| 310 | { .compatible = "fsl,mpc8572-gpio", }, | ||
| 311 | { .compatible = "fsl,mpc8610-gpio", }, | ||
| 312 | { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, }, | ||
| 313 | { .compatible = "fsl,qoriq-gpio", }, | ||
| 314 | {} | ||
| 315 | }; | ||
| 316 | |||
| 317 | static void __init mpc8xxx_add_controller(struct device_node *np) | ||
| 318 | { | ||
| 319 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; | ||
| 320 | struct of_mm_gpio_chip *mm_gc; | ||
| 321 | struct gpio_chip *gc; | ||
| 322 | const struct of_device_id *id; | ||
| 323 | unsigned hwirq; | ||
| 324 | int ret; | ||
| 325 | |||
| 326 | mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); | ||
| 327 | if (!mpc8xxx_gc) { | ||
| 328 | ret = -ENOMEM; | ||
| 329 | goto err; | ||
| 330 | } | ||
| 331 | |||
| 332 | spin_lock_init(&mpc8xxx_gc->lock); | ||
| 333 | |||
| 334 | mm_gc = &mpc8xxx_gc->mm_gc; | ||
| 335 | gc = &mm_gc->gc; | ||
| 336 | |||
| 337 | mm_gc->save_regs = mpc8xxx_gpio_save_regs; | ||
| 338 | gc->ngpio = MPC8XXX_GPIO_PINS; | ||
| 339 | gc->direction_input = mpc8xxx_gpio_dir_in; | ||
| 340 | gc->direction_output = mpc8xxx_gpio_dir_out; | ||
| 341 | if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) | ||
| 342 | gc->get = mpc8572_gpio_get; | ||
| 343 | else | ||
| 344 | gc->get = mpc8xxx_gpio_get; | ||
| 345 | gc->set = mpc8xxx_gpio_set; | ||
| 346 | gc->to_irq = mpc8xxx_gpio_to_irq; | ||
| 347 | |||
| 348 | ret = of_mm_gpiochip_add(np, mm_gc); | ||
| 349 | if (ret) | ||
| 350 | goto err; | ||
| 351 | |||
| 352 | hwirq = irq_of_parse_and_map(np, 0); | ||
| 353 | if (hwirq == NO_IRQ) | ||
| 354 | goto skip_irq; | ||
| 355 | |||
| 356 | mpc8xxx_gc->irq = | ||
| 357 | irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS, | ||
| 358 | &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS); | ||
| 359 | if (!mpc8xxx_gc->irq) | ||
| 360 | goto skip_irq; | ||
| 361 | |||
| 362 | id = of_match_node(mpc8xxx_gpio_ids, np); | ||
| 363 | if (id) | ||
| 364 | mpc8xxx_gc->of_dev_id_data = id->data; | ||
| 365 | |||
| 366 | mpc8xxx_gc->irq->host_data = mpc8xxx_gc; | ||
| 367 | |||
| 368 | /* ack and mask all irqs */ | ||
| 369 | out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); | ||
| 370 | out_be32(mm_gc->regs + GPIO_IMR, 0); | ||
| 371 | |||
| 372 | irq_set_handler_data(hwirq, mpc8xxx_gc); | ||
| 373 | irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade); | ||
| 374 | |||
| 375 | skip_irq: | ||
| 376 | return; | ||
| 377 | |||
| 378 | err: | ||
| 379 | pr_err("%s: registration failed with status %d\n", | ||
| 380 | np->full_name, ret); | ||
| 381 | kfree(mpc8xxx_gc); | ||
| 382 | |||
| 383 | return; | ||
| 384 | } | ||
| 385 | |||
| 386 | static int __init mpc8xxx_add_gpiochips(void) | ||
| 387 | { | ||
| 388 | struct device_node *np; | ||
| 389 | |||
| 390 | for_each_matching_node(np, mpc8xxx_gpio_ids) | ||
| 391 | mpc8xxx_add_controller(np); | ||
| 392 | |||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | arch_initcall(mpc8xxx_add_gpiochips); | ||
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d5d3ff3d757e..8c7e8528e7c4 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data *d) | |||
| 800 | * IPIs are marked IRQ_PER_CPU. This has the side effect of | 800 | * IPIs are marked IRQ_PER_CPU. This has the side effect of |
| 801 | * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from | 801 | * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from |
| 802 | * applying to them. We EOI them late to avoid re-entering. | 802 | * applying to them. We EOI them late to avoid re-entering. |
| 803 | * We mark IPI's with IRQF_DISABLED as they must run with | ||
| 804 | * irqs disabled. | ||
| 805 | */ | 803 | */ |
| 806 | mpic_eoi(mpic); | 804 | mpic_eoi(mpic); |
| 807 | } | 805 | } |
| @@ -1285,13 +1283,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1285 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | 1283 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
| 1286 | | MPIC_GREG_GCONF_MCK); | 1284 | | MPIC_GREG_GCONF_MCK); |
| 1287 | 1285 | ||
| 1288 | /* Read feature register, calculate num CPUs and, for non-ISU | 1286 | /* |
| 1289 | * MPICs, num sources as well. On ISU MPICs, sources are counted | 1287 | * Read feature register. For non-ISU MPICs, num sources as well. On |
| 1290 | * as ISUs are added | 1288 | * ISU MPICs, sources are counted as ISUs are added |
| 1291 | */ | 1289 | */ |
| 1292 | greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); | 1290 | greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); |
| 1293 | mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK) | ||
| 1294 | >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; | ||
| 1295 | if (isu_size == 0) { | 1291 | if (isu_size == 0) { |
| 1296 | if (flags & MPIC_BROKEN_FRR_NIRQS) | 1292 | if (flags & MPIC_BROKEN_FRR_NIRQS) |
| 1297 | mpic->num_sources = mpic->irq_count; | 1293 | mpic->num_sources = mpic->irq_count; |
| @@ -1301,10 +1297,18 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1301 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; | 1297 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; |
| 1302 | } | 1298 | } |
| 1303 | 1299 | ||
| 1300 | /* | ||
| 1301 | * The MPIC driver will crash if there are more cores than we | ||
| 1302 | * can initialize, so we may as well catch that problem here. | ||
| 1303 | */ | ||
| 1304 | BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS); | ||
| 1305 | |||
| 1304 | /* Map the per-CPU registers */ | 1306 | /* Map the per-CPU registers */ |
| 1305 | for (i = 0; i < mpic->num_cpus; i++) { | 1307 | for_each_possible_cpu(i) { |
| 1306 | mpic_map(mpic, node, paddr, &mpic->cpuregs[i], | 1308 | unsigned int cpu = get_hard_smp_processor_id(i); |
| 1307 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), | 1309 | |
| 1310 | mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu], | ||
| 1311 | MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE), | ||
| 1308 | 0x1000); | 1312 | 0x1000); |
| 1309 | } | 1313 | } |
| 1310 | 1314 | ||
| @@ -1343,7 +1347,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1343 | } | 1347 | } |
| 1344 | printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx," | 1348 | printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx," |
| 1345 | " max %d CPUs\n", | 1349 | " max %d CPUs\n", |
| 1346 | name, vers, (unsigned long long)paddr, mpic->num_cpus); | 1350 | name, vers, (unsigned long long)paddr, num_possible_cpus()); |
| 1347 | printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", | 1351 | printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", |
| 1348 | mpic->isu_size, mpic->isu_shift, mpic->isu_mask); | 1352 | mpic->isu_size, mpic->isu_shift, mpic->isu_mask); |
| 1349 | 1353 | ||
| @@ -1742,6 +1746,7 @@ void mpic_reset_core(int cpu) | |||
| 1742 | struct mpic *mpic = mpic_primary; | 1746 | struct mpic *mpic = mpic_primary; |
| 1743 | u32 pir; | 1747 | u32 pir; |
| 1744 | int cpuid = get_hard_smp_processor_id(cpu); | 1748 | int cpuid = get_hard_smp_processor_id(cpu); |
| 1749 | int i; | ||
| 1745 | 1750 | ||
| 1746 | /* Set target bit for core reset */ | 1751 | /* Set target bit for core reset */ |
| 1747 | pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT)); | 1752 | pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT)); |
| @@ -1753,6 +1758,15 @@ void mpic_reset_core(int cpu) | |||
| 1753 | pir &= ~(1 << cpuid); | 1758 | pir &= ~(1 << cpuid); |
| 1754 | mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir); | 1759 | mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir); |
| 1755 | mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT)); | 1760 | mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT)); |
| 1761 | |||
| 1762 | /* Perform 15 EOI on each reset core to clear pending interrupts. | ||
| 1763 | * This is required for FSL CoreNet based devices */ | ||
| 1764 | if (mpic->flags & MPIC_FSL) { | ||
| 1765 | for (i = 0; i < 15; i++) { | ||
| 1766 | _mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid], | ||
| 1767 | MPIC_CPU_EOI, 0); | ||
| 1768 | } | ||
| 1769 | } | ||
| 1756 | } | 1770 | } |
| 1757 | #endif /* CONFIG_SMP */ | 1771 | #endif /* CONFIG_SMP */ |
| 1758 | 1772 | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index 77bb3f4d530a..b0037cefaada 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/stddef.h> | 12 | #include <linux/stddef.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/stat.h> | ||
| 15 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
| 16 | 17 | ||
| 17 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 8ce4fc3d9828..8f0465422b1e 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/module.h> | ||
| 31 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
| 32 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
| 33 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c index 367af0241851..1c2d7af17bbe 100644 --- a/arch/powerpc/sysdev/ppc4xx_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_msi.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/msi.h> | 27 | #include <linux/msi.h> |
| 28 | #include <linux/of_platform.h> | 28 | #include <linux/of_platform.h> |
| 29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 30 | #include <linux/export.h> | ||
| 30 | #include <asm/prom.h> | 31 | #include <asm/prom.h> |
| 31 | #include <asm/hw_irq.h> | 32 | #include <asm/hw_irq.h> |
| 32 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index dbfe96bc878a..862f11b3821e 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
| @@ -834,7 +834,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np) | |||
| 834 | return 3; | 834 | return 3; |
| 835 | } | 835 | } |
| 836 | 836 | ||
| 837 | static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 837 | static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 838 | { | 838 | { |
| 839 | u32 val = 1 << 24; | 839 | u32 val = 1 << 24; |
| 840 | 840 | ||
| @@ -872,12 +872,12 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
| 872 | return ppc4xx_pciex_port_reset_sdr(port); | 872 | return ppc4xx_pciex_port_reset_sdr(port); |
| 873 | } | 873 | } |
| 874 | 874 | ||
| 875 | static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 875 | static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 876 | { | 876 | { |
| 877 | return ppc440spe_pciex_init_port_hw(port); | 877 | return ppc440spe_pciex_init_port_hw(port); |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 880 | static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 881 | { | 881 | { |
| 882 | int rc = ppc440spe_pciex_init_port_hw(port); | 882 | int rc = ppc440spe_pciex_init_port_hw(port); |
| 883 | 883 | ||
| @@ -936,7 +936,7 @@ static int __init ppc460ex_pciex_core_init(struct device_node *np) | |||
| 936 | return 2; | 936 | return 2; |
| 937 | } | 937 | } |
| 938 | 938 | ||
| 939 | static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 939 | static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 940 | { | 940 | { |
| 941 | u32 val; | 941 | u32 val; |
| 942 | u32 utlset1; | 942 | u32 utlset1; |
| @@ -1092,6 +1092,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np) | |||
| 1092 | mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000); | 1092 | mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000); |
| 1093 | mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); | 1093 | mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); |
| 1094 | 1094 | ||
| 1095 | /* Set HSS PRBS enabled */ | ||
| 1096 | mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130); | ||
| 1097 | mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130); | ||
| 1098 | |||
| 1095 | udelay(100); | 1099 | udelay(100); |
| 1096 | 1100 | ||
| 1097 | /* De-assert PLLRESET */ | 1101 | /* De-assert PLLRESET */ |
| @@ -1122,7 +1126,7 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np) | |||
| 1122 | return 2; | 1126 | return 2; |
| 1123 | } | 1127 | } |
| 1124 | 1128 | ||
| 1125 | static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 1129 | static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 1126 | { | 1130 | { |
| 1127 | 1131 | ||
| 1128 | if (port->endpoint) | 1132 | if (port->endpoint) |
| @@ -1132,9 +1136,6 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
| 1132 | dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2, | 1136 | dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2, |
| 1133 | 0, 0x01000000); | 1137 | 0, 0x01000000); |
| 1134 | 1138 | ||
| 1135 | /*Gen-1*/ | ||
| 1136 | mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000); | ||
| 1137 | |||
| 1138 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, | 1139 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, |
| 1139 | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL), | 1140 | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL), |
| 1140 | PESDRx_RCSSET_RSTPYN); | 1141 | PESDRx_RCSSET_RSTPYN); |
| @@ -1148,14 +1149,42 @@ static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) | |||
| 1148 | { | 1149 | { |
| 1149 | /* Max 128 Bytes */ | 1150 | /* Max 128 Bytes */ |
| 1150 | out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000); | 1151 | out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000); |
| 1152 | /* Assert VRB and TXE - per datasheet turn off addr validation */ | ||
| 1153 | out_be32(port->utl_base + PEUTL_PCTL, 0x80800000); | ||
| 1151 | return 0; | 1154 | return 0; |
| 1152 | } | 1155 | } |
| 1153 | 1156 | ||
| 1157 | static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port) | ||
| 1158 | { | ||
| 1159 | void __iomem *mbase; | ||
| 1160 | int attempt = 50; | ||
| 1161 | |||
| 1162 | port->link = 0; | ||
| 1163 | |||
| 1164 | mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); | ||
| 1165 | if (mbase == NULL) { | ||
| 1166 | printk(KERN_ERR "%s: Can't map internal config space !", | ||
| 1167 | port->node->full_name); | ||
| 1168 | goto done; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA) | ||
| 1172 | & PECFG_460SX_DLLSTA_LINKUP))) { | ||
| 1173 | attempt--; | ||
| 1174 | mdelay(10); | ||
| 1175 | } | ||
| 1176 | if (attempt) | ||
| 1177 | port->link = 1; | ||
| 1178 | done: | ||
| 1179 | iounmap(mbase); | ||
| 1180 | |||
| 1181 | } | ||
| 1182 | |||
| 1154 | static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { | 1183 | static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { |
| 1155 | .core_init = ppc460sx_pciex_core_init, | 1184 | .core_init = ppc460sx_pciex_core_init, |
| 1156 | .port_init_hw = ppc460sx_pciex_init_port_hw, | 1185 | .port_init_hw = ppc460sx_pciex_init_port_hw, |
| 1157 | .setup_utl = ppc460sx_pciex_init_utl, | 1186 | .setup_utl = ppc460sx_pciex_init_utl, |
| 1158 | .check_link = ppc4xx_pciex_check_link_sdr, | 1187 | .check_link = ppc460sx_pciex_check_link, |
| 1159 | }; | 1188 | }; |
| 1160 | 1189 | ||
| 1161 | #endif /* CONFIG_44x */ | 1190 | #endif /* CONFIG_44x */ |
| @@ -1189,7 +1218,7 @@ static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port) | |||
| 1189 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000); | 1218 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000); |
| 1190 | } | 1219 | } |
| 1191 | 1220 | ||
| 1192 | static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 1221 | static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
| 1193 | { | 1222 | { |
| 1194 | u32 val; | 1223 | u32 val; |
| 1195 | 1224 | ||
| @@ -1338,15 +1367,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
| 1338 | if (rc != 0) | 1367 | if (rc != 0) |
| 1339 | return rc; | 1368 | return rc; |
| 1340 | 1369 | ||
| 1341 | if (ppc4xx_pciex_hwops->check_link) | ||
| 1342 | ppc4xx_pciex_hwops->check_link(port); | ||
| 1343 | |||
| 1344 | /* | 1370 | /* |
| 1345 | * Initialize mapping: disable all regions and configure | 1371 | * Initialize mapping: disable all regions and configure |
| 1346 | * CFG and REG regions based on resources in the device tree | 1372 | * CFG and REG regions based on resources in the device tree |
| 1347 | */ | 1373 | */ |
| 1348 | ppc4xx_pciex_port_init_mapping(port); | 1374 | ppc4xx_pciex_port_init_mapping(port); |
| 1349 | 1375 | ||
| 1376 | if (ppc4xx_pciex_hwops->check_link) | ||
| 1377 | ppc4xx_pciex_hwops->check_link(port); | ||
| 1378 | |||
| 1350 | /* | 1379 | /* |
| 1351 | * Map UTL | 1380 | * Map UTL |
| 1352 | */ | 1381 | */ |
| @@ -1360,13 +1389,23 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
| 1360 | ppc4xx_pciex_hwops->setup_utl(port); | 1389 | ppc4xx_pciex_hwops->setup_utl(port); |
| 1361 | 1390 | ||
| 1362 | /* | 1391 | /* |
| 1363 | * Check for VC0 active and assert RDY. | 1392 | * Check for VC0 active or PLL Locked and assert RDY. |
| 1364 | */ | 1393 | */ |
| 1365 | if (port->sdr_base) { | 1394 | if (port->sdr_base) { |
| 1366 | if (port->link && | 1395 | if (of_device_is_compatible(port->node, |
| 1367 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, | 1396 | "ibm,plb-pciex-460sx")){ |
| 1368 | 1 << 16, 1 << 16, 5000)) { | 1397 | if (port->link && ppc4xx_pciex_wait_on_sdr(port, |
| 1369 | printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); | 1398 | PESDRn_RCSSTS, |
| 1399 | 1 << 12, 1 << 12, 5000)) { | ||
| 1400 | printk(KERN_INFO "PCIE%d: PLL not locked\n", | ||
| 1401 | port->index); | ||
| 1402 | port->link = 0; | ||
| 1403 | } | ||
| 1404 | } else if (port->link && | ||
| 1405 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, | ||
| 1406 | 1 << 16, 1 << 16, 5000)) { | ||
| 1407 | printk(KERN_INFO "PCIE%d: VC0 not active\n", | ||
| 1408 | port->index); | ||
| 1370 | port->link = 0; | 1409 | port->link = 0; |
| 1371 | } | 1410 | } |
| 1372 | 1411 | ||
| @@ -1573,8 +1612,15 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
| 1573 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); | 1612 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); |
| 1574 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); | 1613 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); |
| 1575 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); | 1614 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); |
| 1576 | /* Note that 3 here means enabled | single region */ | 1615 | /*Enabled and single region */ |
| 1577 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); | 1616 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) |
| 1617 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, | ||
| 1618 | sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT | ||
| 1619 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
| 1620 | else | ||
| 1621 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, | ||
| 1622 | sa | DCRO_PEGPL_OMR1MSKL_UOT | ||
| 1623 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
| 1578 | break; | 1624 | break; |
| 1579 | case 1: | 1625 | case 1: |
| 1580 | out_le32(mbase + PECFG_POM1LAH, pciah); | 1626 | out_le32(mbase + PECFG_POM1LAH, pciah); |
| @@ -1582,8 +1628,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
| 1582 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); | 1628 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); |
| 1583 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); | 1629 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); |
| 1584 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); | 1630 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); |
| 1585 | /* Note that 3 here means enabled | single region */ | 1631 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, |
| 1586 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); | 1632 | sa | DCRO_PEGPL_OMRxMSKL_VAL); |
| 1587 | break; | 1633 | break; |
| 1588 | case 2: | 1634 | case 2: |
| 1589 | out_le32(mbase + PECFG_POM2LAH, pciah); | 1635 | out_le32(mbase + PECFG_POM2LAH, pciah); |
| @@ -1592,7 +1638,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
| 1592 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); | 1638 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); |
| 1593 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); | 1639 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); |
| 1594 | /* Note that 3 here means enabled | IO space !!! */ | 1640 | /* Note that 3 here means enabled | IO space !!! */ |
| 1595 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); | 1641 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, |
| 1642 | sa | DCRO_PEGPL_OMR3MSKL_IO | ||
| 1643 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
| 1596 | break; | 1644 | break; |
| 1597 | } | 1645 | } |
| 1598 | 1646 | ||
| @@ -1693,6 +1741,9 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, | |||
| 1693 | if (res->flags & IORESOURCE_PREFETCH) | 1741 | if (res->flags & IORESOURCE_PREFETCH) |
| 1694 | sa |= 0x8; | 1742 | sa |= 0x8; |
| 1695 | 1743 | ||
| 1744 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) | ||
| 1745 | sa |= PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
| 1746 | |||
| 1696 | out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); | 1747 | out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); |
| 1697 | out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); | 1748 | out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); |
| 1698 | 1749 | ||
| @@ -1854,6 +1905,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) | |||
| 1854 | } | 1905 | } |
| 1855 | out_le16(mbase + 0x202, val); | 1906 | out_le16(mbase + 0x202, val); |
| 1856 | 1907 | ||
| 1908 | /* Enable Bus master, memory, and io space */ | ||
| 1909 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) | ||
| 1910 | out_le16(mbase + 0x204, 0x7); | ||
| 1911 | |||
| 1857 | if (!port->endpoint) { | 1912 | if (!port->endpoint) { |
| 1858 | /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ | 1913 | /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ |
| 1859 | out_le32(mbase + 0x208, 0x06040001); | 1914 | out_le32(mbase + 0x208, 0x06040001); |
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h index c39a134e8684..32ce763a375a 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.h +++ b/arch/powerpc/sysdev/ppc4xx_pci.h | |||
| @@ -464,6 +464,18 @@ | |||
| 464 | #define PECFG_POM2LAL 0x390 | 464 | #define PECFG_POM2LAL 0x390 |
| 465 | #define PECFG_POM2LAH 0x394 | 465 | #define PECFG_POM2LAH 0x394 |
| 466 | 466 | ||
| 467 | /* 460sx only */ | ||
| 468 | #define PECFG_460SX_DLLSTA 0x3f8 | ||
| 469 | |||
| 470 | /* 460sx Bit Mappings */ | ||
| 471 | #define PECFG_460SX_DLLSTA_LINKUP 0x00000010 | ||
| 472 | #define DCRO_PEGPL_460SX_OMR1MSKL_UOT 0x00000004 | ||
| 473 | |||
| 474 | /* PEGPL Bit Mappings */ | ||
| 475 | #define DCRO_PEGPL_OMRxMSKL_VAL 0x00000001 | ||
| 476 | #define DCRO_PEGPL_OMR1MSKL_UOT 0x00000002 | ||
| 477 | #define DCRO_PEGPL_OMR3MSKL_IO 0x00000002 | ||
| 478 | |||
| 467 | /* SDR Bit Mappings */ | 479 | /* SDR Bit Mappings */ |
| 468 | #define PESDRx_RCSSET_HLDPLB 0x10000000 | 480 | #define PESDRx_RCSSET_HLDPLB 0x10000000 |
| 469 | #define PESDRx_RCSSET_RSTGU 0x01000000 | 481 | #define PESDRx_RCSSET_RSTGU 0x01000000 |
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c index d3d6ce3c33b4..0debcc31ad70 100644 --- a/arch/powerpc/sysdev/ppc4xx_soc.c +++ b/arch/powerpc/sysdev/ppc4xx_soc.c | |||
| @@ -115,7 +115,7 @@ static int __init ppc4xx_l2c_probe(void) | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | /* Install error handler */ | 117 | /* Install error handler */ |
| 118 | if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) { | 118 | if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) { |
| 119 | printk(KERN_ERR "Cannot install L2C error handler" | 119 | printk(KERN_ERR "Cannot install L2C error handler" |
| 120 | ", cache is not enabled\n"); | 120 | ", cache is not enabled\n"); |
| 121 | of_node_put(np); | 121 | of_node_put(np); |
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c index 36bf845df127..e23f23cf9f5c 100644 --- a/arch/powerpc/sysdev/qe_lib/gpio.c +++ b/arch/powerpc/sysdev/qe_lib/gpio.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
| 21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/export.h> | ||
| 23 | #include <asm/qe.h> | 24 | #include <asm/qe.h> |
| 24 | 25 | ||
| 25 | struct qe_gpio_chip { | 26 | struct qe_gpio_chip { |
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 904c6cbaf45b..3363fbc964f8 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
| @@ -382,7 +382,7 @@ static void qe_upload_microcode(const void *base, | |||
| 382 | /* | 382 | /* |
| 383 | * Upload a microcode to the I-RAM at a specific address. | 383 | * Upload a microcode to the I-RAM at a specific address. |
| 384 | * | 384 | * |
| 385 | * See Documentation/powerpc/qe-firmware.txt for information on QE microcode | 385 | * See Documentation/powerpc/qe_firmware.txt for information on QE microcode |
| 386 | * uploading. | 386 | * uploading. |
| 387 | * | 387 | * |
| 388 | * Currently, only version 1 is supported, so the 'version' field must be | 388 | * Currently, only version 1 is supported, so the 'version' field must be |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c index fa589b21dbcd..04677505f20f 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc.c +++ b/arch/powerpc/sysdev/qe_lib/ucc.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
| 20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/export.h> |
| 22 | 22 | ||
| 23 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
| 24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 25fbbfaa837d..fba02440d122 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/export.h> |
| 23 | 23 | ||
| 24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 25 | #include <asm/immap_qe.h> | 25 | #include <asm/immap_qe.h> |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index e1d6a1340157..524c0ead941d 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/export.h> |
| 23 | 23 | ||
| 24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 25 | #include <asm/immap_qe.h> | 25 | #include <asm/immap_qe.h> |
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c index 8105462078eb..9162828f5da7 100644 --- a/arch/powerpc/sysdev/qe_lib/usb.c +++ b/arch/powerpc/sysdev/qe_lib/usb.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
| 18 | #include <linux/export.h> | ||
| 18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 19 | #include <asm/immap_qe.h> | 20 | #include <asm/immap_qe.h> |
| 20 | #include <asm/qe.h> | 21 | #include <asm/qe.h> |
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c index c1879ebfd4f4..9afba924e94f 100644 --- a/arch/powerpc/sysdev/rtc_cmos_setup.c +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/module.h> | ||
| 15 | #include <linux/mc146818rtc.h> | 16 | #include <linux/mc146818rtc.h> |
| 16 | 17 | ||
| 17 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c index b2593ce30c9b..49a3ece1c6b3 100644 --- a/arch/powerpc/sysdev/scom.c +++ b/arch/powerpc/sysdev/scom.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/debugfs.h> | 22 | #include <linux/debugfs.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/export.h> | ||
| 24 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
| 25 | #include <asm/scom.h> | 26 | #include <asm/scom.h> |
| 26 | 27 | ||
diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c index b6defda5ccc9..ff5e73230a36 100644 --- a/arch/powerpc/sysdev/simple_gpio.c +++ b/arch/powerpc/sysdev/simple_gpio.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
| 18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 19 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 9f51f97abb5d..2370e1c63379 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <linux/major.h> | 16 | #include <linux/major.h> |
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/export.h> |
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/of_net.h> | 22 | #include <linux/of_net.h> |
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 984cd2029158..3330feca7502 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c | |||
| @@ -47,7 +47,7 @@ struct uic { | |||
| 47 | int index; | 47 | int index; |
| 48 | int dcrbase; | 48 | int dcrbase; |
| 49 | 49 | ||
| 50 | spinlock_t lock; | 50 | raw_spinlock_t lock; |
| 51 | 51 | ||
| 52 | /* The remapper for this UIC */ | 52 | /* The remapper for this UIC */ |
| 53 | struct irq_host *irqhost; | 53 | struct irq_host *irqhost; |
| @@ -61,14 +61,14 @@ static void uic_unmask_irq(struct irq_data *d) | |||
| 61 | u32 er, sr; | 61 | u32 er, sr; |
| 62 | 62 | ||
| 63 | sr = 1 << (31-src); | 63 | sr = 1 << (31-src); |
| 64 | spin_lock_irqsave(&uic->lock, flags); | 64 | raw_spin_lock_irqsave(&uic->lock, flags); |
| 65 | /* ack level-triggered interrupts here */ | 65 | /* ack level-triggered interrupts here */ |
| 66 | if (irqd_is_level_type(d)) | 66 | if (irqd_is_level_type(d)) |
| 67 | mtdcr(uic->dcrbase + UIC_SR, sr); | 67 | mtdcr(uic->dcrbase + UIC_SR, sr); |
| 68 | er = mfdcr(uic->dcrbase + UIC_ER); | 68 | er = mfdcr(uic->dcrbase + UIC_ER); |
| 69 | er |= sr; | 69 | er |= sr; |
| 70 | mtdcr(uic->dcrbase + UIC_ER, er); | 70 | mtdcr(uic->dcrbase + UIC_ER, er); |
| 71 | spin_unlock_irqrestore(&uic->lock, flags); | 71 | raw_spin_unlock_irqrestore(&uic->lock, flags); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void uic_mask_irq(struct irq_data *d) | 74 | static void uic_mask_irq(struct irq_data *d) |
| @@ -78,11 +78,11 @@ static void uic_mask_irq(struct irq_data *d) | |||
| 78 | unsigned long flags; | 78 | unsigned long flags; |
| 79 | u32 er; | 79 | u32 er; |
| 80 | 80 | ||
| 81 | spin_lock_irqsave(&uic->lock, flags); | 81 | raw_spin_lock_irqsave(&uic->lock, flags); |
| 82 | er = mfdcr(uic->dcrbase + UIC_ER); | 82 | er = mfdcr(uic->dcrbase + UIC_ER); |
| 83 | er &= ~(1 << (31 - src)); | 83 | er &= ~(1 << (31 - src)); |
| 84 | mtdcr(uic->dcrbase + UIC_ER, er); | 84 | mtdcr(uic->dcrbase + UIC_ER, er); |
| 85 | spin_unlock_irqrestore(&uic->lock, flags); | 85 | raw_spin_unlock_irqrestore(&uic->lock, flags); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static void uic_ack_irq(struct irq_data *d) | 88 | static void uic_ack_irq(struct irq_data *d) |
| @@ -91,9 +91,9 @@ static void uic_ack_irq(struct irq_data *d) | |||
| 91 | unsigned int src = irqd_to_hwirq(d); | 91 | unsigned int src = irqd_to_hwirq(d); |
| 92 | unsigned long flags; | 92 | unsigned long flags; |
| 93 | 93 | ||
| 94 | spin_lock_irqsave(&uic->lock, flags); | 94 | raw_spin_lock_irqsave(&uic->lock, flags); |
| 95 | mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); | 95 | mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); |
| 96 | spin_unlock_irqrestore(&uic->lock, flags); | 96 | raw_spin_unlock_irqrestore(&uic->lock, flags); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | static void uic_mask_ack_irq(struct irq_data *d) | 99 | static void uic_mask_ack_irq(struct irq_data *d) |
| @@ -104,7 +104,7 @@ static void uic_mask_ack_irq(struct irq_data *d) | |||
| 104 | u32 er, sr; | 104 | u32 er, sr; |
| 105 | 105 | ||
| 106 | sr = 1 << (31-src); | 106 | sr = 1 << (31-src); |
| 107 | spin_lock_irqsave(&uic->lock, flags); | 107 | raw_spin_lock_irqsave(&uic->lock, flags); |
| 108 | er = mfdcr(uic->dcrbase + UIC_ER); | 108 | er = mfdcr(uic->dcrbase + UIC_ER); |
| 109 | er &= ~sr; | 109 | er &= ~sr; |
| 110 | mtdcr(uic->dcrbase + UIC_ER, er); | 110 | mtdcr(uic->dcrbase + UIC_ER, er); |
| @@ -118,7 +118,7 @@ static void uic_mask_ack_irq(struct irq_data *d) | |||
| 118 | */ | 118 | */ |
| 119 | if (!irqd_is_level_type(d)) | 119 | if (!irqd_is_level_type(d)) |
| 120 | mtdcr(uic->dcrbase + UIC_SR, sr); | 120 | mtdcr(uic->dcrbase + UIC_SR, sr); |
| 121 | spin_unlock_irqrestore(&uic->lock, flags); | 121 | raw_spin_unlock_irqrestore(&uic->lock, flags); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) | 124 | static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) |
| @@ -152,7 +152,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) | |||
| 152 | 152 | ||
| 153 | mask = ~(1 << (31 - src)); | 153 | mask = ~(1 << (31 - src)); |
| 154 | 154 | ||
| 155 | spin_lock_irqsave(&uic->lock, flags); | 155 | raw_spin_lock_irqsave(&uic->lock, flags); |
| 156 | tr = mfdcr(uic->dcrbase + UIC_TR); | 156 | tr = mfdcr(uic->dcrbase + UIC_TR); |
| 157 | pr = mfdcr(uic->dcrbase + UIC_PR); | 157 | pr = mfdcr(uic->dcrbase + UIC_PR); |
| 158 | tr = (tr & mask) | (trigger << (31-src)); | 158 | tr = (tr & mask) | (trigger << (31-src)); |
| @@ -161,7 +161,7 @@ static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type) | |||
| 161 | mtdcr(uic->dcrbase + UIC_PR, pr); | 161 | mtdcr(uic->dcrbase + UIC_PR, pr); |
| 162 | mtdcr(uic->dcrbase + UIC_TR, tr); | 162 | mtdcr(uic->dcrbase + UIC_TR, tr); |
| 163 | 163 | ||
| 164 | spin_unlock_irqrestore(&uic->lock, flags); | 164 | raw_spin_unlock_irqrestore(&uic->lock, flags); |
| 165 | 165 | ||
| 166 | return 0; | 166 | return 0; |
| 167 | } | 167 | } |
| @@ -254,7 +254,7 @@ static struct uic * __init uic_init_one(struct device_node *node) | |||
| 254 | if (! uic) | 254 | if (! uic) |
| 255 | return NULL; /* FIXME: panic? */ | 255 | return NULL; /* FIXME: panic? */ |
| 256 | 256 | ||
| 257 | spin_lock_init(&uic->lock); | 257 | raw_spin_lock_init(&uic->lock); |
| 258 | indexp = of_get_property(node, "cell-index", &len); | 258 | indexp = of_get_property(node, "cell-index", &len); |
| 259 | if (!indexp || (len != sizeof(u32))) { | 259 | if (!indexp || (len != sizeof(u32))) { |
| 260 | printk(KERN_ERR "uic: Device node %s has missing or invalid " | 260 | printk(KERN_ERR "uic: Device node %s has missing or invalid " |
diff --git a/arch/powerpc/sysdev/xics/Makefile b/arch/powerpc/sysdev/xics/Makefile index b75a6059337f..c606aa8ba60a 100644 --- a/arch/powerpc/sysdev/xics/Makefile +++ b/arch/powerpc/sysdev/xics/Makefile | |||
| @@ -4,3 +4,4 @@ obj-y += xics-common.o | |||
| 4 | obj-$(CONFIG_PPC_ICP_NATIVE) += icp-native.o | 4 | obj-$(CONFIG_PPC_ICP_NATIVE) += icp-native.o |
| 5 | obj-$(CONFIG_PPC_ICP_HV) += icp-hv.o | 5 | obj-$(CONFIG_PPC_ICP_HV) += icp-hv.o |
| 6 | obj-$(CONFIG_PPC_ICS_RTAS) += ics-rtas.o | 6 | obj-$(CONFIG_PPC_ICS_RTAS) += ics-rtas.o |
| 7 | obj-$(CONFIG_PPC_POWERNV) += ics-opal.o | ||
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 50e32afe392e..4c79b6fbee1c 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c | |||
| @@ -276,7 +276,7 @@ static const struct icp_ops icp_native_ops = { | |||
| 276 | #endif | 276 | #endif |
| 277 | }; | 277 | }; |
| 278 | 278 | ||
| 279 | int icp_native_init(void) | 279 | int __init icp_native_init(void) |
| 280 | { | 280 | { |
| 281 | struct device_node *np; | 281 | struct device_node *np; |
| 282 | u32 indx = 0; | 282 | u32 indx = 0; |
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c new file mode 100644 index 000000000000..f7e8609df0d5 --- /dev/null +++ b/arch/powerpc/sysdev/xics/ics-opal.c | |||
| @@ -0,0 +1,244 @@ | |||
| 1 | /* | ||
| 2 | * ICS backend for OPAL managed interrupts. | ||
| 3 | * | ||
| 4 | * Copyright 2011 IBM Corp. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #undef DEBUG | ||
| 13 | |||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/smp.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/cpu.h> | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/msi.h> | ||
| 24 | |||
| 25 | #include <asm/prom.h> | ||
| 26 | #include <asm/smp.h> | ||
| 27 | #include <asm/machdep.h> | ||
| 28 | #include <asm/irq.h> | ||
| 29 | #include <asm/errno.h> | ||
| 30 | #include <asm/xics.h> | ||
| 31 | #include <asm/opal.h> | ||
| 32 | #include <asm/firmware.h> | ||
| 33 | |||
| 34 | static int ics_opal_mangle_server(int server) | ||
| 35 | { | ||
| 36 | /* No link for now */ | ||
| 37 | return server << 2; | ||
| 38 | } | ||
| 39 | |||
| 40 | static int ics_opal_unmangle_server(int server) | ||
| 41 | { | ||
| 42 | /* No link for now */ | ||
| 43 | return server >> 2; | ||
| 44 | } | ||
| 45 | |||
| 46 | static void ics_opal_unmask_irq(struct irq_data *d) | ||
| 47 | { | ||
| 48 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); | ||
| 49 | int64_t rc; | ||
| 50 | int server; | ||
| 51 | |||
| 52 | pr_devel("ics-hal: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq); | ||
| 53 | |||
| 54 | if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) | ||
| 55 | return; | ||
| 56 | |||
| 57 | server = xics_get_irq_server(d->irq, d->affinity, 0); | ||
| 58 | server = ics_opal_mangle_server(server); | ||
| 59 | |||
| 60 | rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY); | ||
| 61 | if (rc != OPAL_SUCCESS) | ||
| 62 | pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)" | ||
| 63 | " error %lld\n", | ||
| 64 | __func__, d->irq, hw_irq, server, rc); | ||
| 65 | } | ||
| 66 | |||
| 67 | static unsigned int ics_opal_startup(struct irq_data *d) | ||
| 68 | { | ||
| 69 | #ifdef CONFIG_PCI_MSI | ||
| 70 | /* | ||
| 71 | * The generic MSI code returns with the interrupt disabled on the | ||
| 72 | * card, using the MSI mask bits. Firmware doesn't appear to unmask | ||
| 73 | * at that level, so we do it here by hand. | ||
| 74 | */ | ||
| 75 | if (d->msi_desc) | ||
| 76 | unmask_msi_irq(d); | ||
| 77 | #endif | ||
| 78 | |||
| 79 | /* unmask it */ | ||
| 80 | ics_opal_unmask_irq(d); | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void ics_opal_mask_real_irq(unsigned int hw_irq) | ||
| 85 | { | ||
| 86 | int server = ics_opal_mangle_server(xics_default_server); | ||
| 87 | int64_t rc; | ||
| 88 | |||
| 89 | if (hw_irq == XICS_IPI) | ||
| 90 | return; | ||
| 91 | |||
| 92 | /* Have to set XIVE to 0xff to be able to remove a slot */ | ||
| 93 | rc = opal_set_xive(hw_irq, server, 0xff); | ||
| 94 | if (rc != OPAL_SUCCESS) | ||
| 95 | pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n", | ||
| 96 | __func__, hw_irq, rc); | ||
| 97 | } | ||
| 98 | |||
| 99 | static void ics_opal_mask_irq(struct irq_data *d) | ||
| 100 | { | ||
| 101 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); | ||
| 102 | |||
| 103 | pr_devel("ics-hal: mask virq %d [hw 0x%x]\n", d->irq, hw_irq); | ||
| 104 | |||
| 105 | if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) | ||
| 106 | return; | ||
| 107 | ics_opal_mask_real_irq(hw_irq); | ||
| 108 | } | ||
| 109 | |||
| 110 | static int ics_opal_set_affinity(struct irq_data *d, | ||
| 111 | const struct cpumask *cpumask, | ||
| 112 | bool force) | ||
| 113 | { | ||
| 114 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); | ||
| 115 | int16_t server; | ||
| 116 | int8_t priority; | ||
| 117 | int64_t rc; | ||
| 118 | int wanted_server; | ||
| 119 | |||
| 120 | if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) | ||
| 121 | return -1; | ||
| 122 | |||
| 123 | rc = opal_get_xive(hw_irq, &server, &priority); | ||
| 124 | if (rc != OPAL_SUCCESS) { | ||
| 125 | pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)" | ||
| 126 | " error %lld\n", | ||
| 127 | __func__, d->irq, hw_irq, server, rc); | ||
| 128 | return -1; | ||
| 129 | } | ||
| 130 | |||
| 131 | wanted_server = xics_get_irq_server(d->irq, cpumask, 1); | ||
| 132 | if (wanted_server < 0) { | ||
| 133 | char cpulist[128]; | ||
| 134 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); | ||
| 135 | pr_warning("%s: No online cpus in the mask %s for irq %d\n", | ||
| 136 | __func__, cpulist, d->irq); | ||
| 137 | return -1; | ||
| 138 | } | ||
| 139 | server = ics_opal_mangle_server(wanted_server); | ||
| 140 | |||
| 141 | pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n", | ||
| 142 | d->irq, hw_irq, wanted_server, server); | ||
| 143 | |||
| 144 | rc = opal_set_xive(hw_irq, server, priority); | ||
| 145 | if (rc != OPAL_SUCCESS) { | ||
| 146 | pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)" | ||
| 147 | " error %lld\n", | ||
| 148 | __func__, d->irq, hw_irq, server, rc); | ||
| 149 | return -1; | ||
| 150 | } | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static struct irq_chip ics_opal_irq_chip = { | ||
| 155 | .name = "OPAL ICS", | ||
| 156 | .irq_startup = ics_opal_startup, | ||
| 157 | .irq_mask = ics_opal_mask_irq, | ||
| 158 | .irq_unmask = ics_opal_unmask_irq, | ||
| 159 | .irq_eoi = NULL, /* Patched at init time */ | ||
| 160 | .irq_set_affinity = ics_opal_set_affinity | ||
| 161 | }; | ||
| 162 | |||
| 163 | static int ics_opal_map(struct ics *ics, unsigned int virq); | ||
| 164 | static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec); | ||
| 165 | static long ics_opal_get_server(struct ics *ics, unsigned long vec); | ||
| 166 | |||
| 167 | static int ics_opal_host_match(struct ics *ics, struct device_node *node) | ||
| 168 | { | ||
| 169 | return 1; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* Only one global & state struct ics */ | ||
| 173 | static struct ics ics_hal = { | ||
| 174 | .map = ics_opal_map, | ||
| 175 | .mask_unknown = ics_opal_mask_unknown, | ||
| 176 | .get_server = ics_opal_get_server, | ||
| 177 | .host_match = ics_opal_host_match, | ||
| 178 | }; | ||
| 179 | |||
| 180 | static int ics_opal_map(struct ics *ics, unsigned int virq) | ||
| 181 | { | ||
| 182 | unsigned int hw_irq = (unsigned int)virq_to_hw(virq); | ||
| 183 | int64_t rc; | ||
| 184 | int16_t server; | ||
| 185 | int8_t priority; | ||
| 186 | |||
| 187 | if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)) | ||
| 188 | return -EINVAL; | ||
| 189 | |||
| 190 | /* Check if HAL knows about this interrupt */ | ||
| 191 | rc = opal_get_xive(hw_irq, &server, &priority); | ||
| 192 | if (rc != OPAL_SUCCESS) | ||
| 193 | return -ENXIO; | ||
| 194 | |||
| 195 | irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq); | ||
| 196 | irq_set_chip_data(virq, &ics_hal); | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) | ||
| 202 | { | ||
| 203 | int64_t rc; | ||
| 204 | int16_t server; | ||
| 205 | int8_t priority; | ||
| 206 | |||
| 207 | /* Check if HAL knows about this interrupt */ | ||
| 208 | rc = opal_get_xive(vec, &server, &priority); | ||
| 209 | if (rc != OPAL_SUCCESS) | ||
| 210 | return; | ||
| 211 | |||
| 212 | ics_opal_mask_real_irq(vec); | ||
| 213 | } | ||
| 214 | |||
| 215 | static long ics_opal_get_server(struct ics *ics, unsigned long vec) | ||
| 216 | { | ||
| 217 | int64_t rc; | ||
| 218 | int16_t server; | ||
| 219 | int8_t priority; | ||
| 220 | |||
| 221 | /* Check if HAL knows about this interrupt */ | ||
| 222 | rc = opal_get_xive(vec, &server, &priority); | ||
| 223 | if (rc != OPAL_SUCCESS) | ||
| 224 | return -1; | ||
| 225 | return ics_opal_unmangle_server(server); | ||
| 226 | } | ||
| 227 | |||
| 228 | int __init ics_opal_init(void) | ||
| 229 | { | ||
| 230 | if (!firmware_has_feature(FW_FEATURE_OPAL)) | ||
| 231 | return -ENODEV; | ||
| 232 | |||
| 233 | /* We need to patch our irq chip's EOI to point to the | ||
| 234 | * right ICP | ||
| 235 | */ | ||
| 236 | ics_opal_irq_chip.irq_eoi = icp_ops->eoi; | ||
| 237 | |||
| 238 | /* Register ourselves */ | ||
| 239 | xics_register_ics(&ics_hal); | ||
| 240 | |||
| 241 | pr_info("ICS OPAL backend registered\n"); | ||
| 242 | |||
| 243 | return 0; | ||
| 244 | } | ||
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 445c5a01b766..63762c672a03 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c | |||
| @@ -134,11 +134,10 @@ static void xics_request_ipi(void) | |||
| 134 | BUG_ON(ipi == NO_IRQ); | 134 | BUG_ON(ipi == NO_IRQ); |
| 135 | 135 | ||
| 136 | /* | 136 | /* |
| 137 | * IPIs are marked IRQF_DISABLED as they must run with irqs | 137 | * IPIs are marked IRQF_PERCPU. The handler was set in map. |
| 138 | * disabled, and PERCPU. The handler was set in map. | ||
| 139 | */ | 138 | */ |
| 140 | BUG_ON(request_irq(ipi, icp_ops->ipi_action, | 139 | BUG_ON(request_irq(ipi, icp_ops->ipi_action, |
| 141 | IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL)); | 140 | IRQF_PERCPU, "IPI", NULL)); |
| 142 | } | 141 | } |
| 143 | 142 | ||
| 144 | int __init xics_smp_probe(void) | 143 | int __init xics_smp_probe(void) |
| @@ -409,14 +408,10 @@ void __init xics_init(void) | |||
| 409 | int rc = -1; | 408 | int rc = -1; |
| 410 | 409 | ||
| 411 | /* Fist locate ICP */ | 410 | /* Fist locate ICP */ |
| 412 | #ifdef CONFIG_PPC_ICP_HV | ||
| 413 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 411 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
| 414 | rc = icp_hv_init(); | 412 | rc = icp_hv_init(); |
| 415 | #endif | ||
| 416 | #ifdef CONFIG_PPC_ICP_NATIVE | ||
| 417 | if (rc < 0) | 413 | if (rc < 0) |
| 418 | rc = icp_native_init(); | 414 | rc = icp_native_init(); |
| 419 | #endif | ||
| 420 | if (rc < 0) { | 415 | if (rc < 0) { |
| 421 | pr_warning("XICS: Cannot find a Presentation Controller !\n"); | 416 | pr_warning("XICS: Cannot find a Presentation Controller !\n"); |
| 422 | return; | 417 | return; |
| @@ -429,9 +424,9 @@ void __init xics_init(void) | |||
| 429 | xics_ipi_chip.irq_eoi = icp_ops->eoi; | 424 | xics_ipi_chip.irq_eoi = icp_ops->eoi; |
| 430 | 425 | ||
| 431 | /* Now locate ICS */ | 426 | /* Now locate ICS */ |
| 432 | #ifdef CONFIG_PPC_ICS_RTAS | ||
| 433 | rc = ics_rtas_init(); | 427 | rc = ics_rtas_init(); |
| 434 | #endif | 428 | if (rc < 0) |
| 429 | rc = ics_opal_init(); | ||
| 435 | if (rc < 0) | 430 | if (rc < 0) |
| 436 | pr_warning("XICS: Cannot find a Source Controller !\n"); | 431 | pr_warning("XICS: Cannot find a Source Controller !\n"); |
| 437 | 432 | ||
