diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-12-24 01:16:02 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-12-24 01:16:02 -0500 |
commit | f34548cb735b7a80bbbb0bdd09ad4c2173ba92d5 (patch) | |
tree | e53c9e39b3149221779c10595bc59fa02de4f45f /arch/powerpc/sysdev | |
parent | 76382b5bdb77c29ab430e1b82ef1c604c8dd113b (diff) | |
parent | 32b53076c31ce9159740b744d5eb5d9505312add (diff) |
Merge branch 'sh/g3-prep' into sh/for-2.6.33
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/cpm2_pic.c | 28 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 8 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpc8xxx_gpio.c | 21 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 19 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_msi.c | 11 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_u3msi.c | 46 |
6 files changed, 102 insertions, 31 deletions
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 971483f0dfac..1709ac5aac7c 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c | |||
@@ -143,13 +143,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
143 | struct irq_desc *desc = irq_to_desc(virq); | 143 | struct irq_desc *desc = irq_to_desc(virq); |
144 | unsigned int vold, vnew, edibit; | 144 | unsigned int vold, vnew, edibit; |
145 | 145 | ||
146 | if (flow_type == IRQ_TYPE_NONE) | 146 | /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or |
147 | flow_type = IRQ_TYPE_LEVEL_LOW; | 147 | * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING |
148 | 148 | * or IRQ_TYPE_LEVEL_LOW (default) | |
149 | if (flow_type & IRQ_TYPE_EDGE_RISING) { | 149 | */ |
150 | printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n", | 150 | if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) { |
151 | flow_type); | 151 | if (flow_type == IRQ_TYPE_NONE) |
152 | return -EINVAL; | 152 | flow_type = IRQ_TYPE_EDGE_BOTH; |
153 | |||
154 | if (flow_type != IRQ_TYPE_EDGE_BOTH && | ||
155 | flow_type != IRQ_TYPE_EDGE_FALLING) | ||
156 | goto err_sense; | ||
157 | } else { | ||
158 | if (flow_type == IRQ_TYPE_NONE) | ||
159 | flow_type = IRQ_TYPE_LEVEL_LOW; | ||
160 | |||
161 | if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) | ||
162 | goto err_sense; | ||
153 | } | 163 | } |
154 | 164 | ||
155 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 165 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); |
@@ -181,6 +191,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
181 | if (vold != vnew) | 191 | if (vold != vnew) |
182 | out_be32(&cpm2_intctl->ic_siexr, vnew); | 192 | out_be32(&cpm2_intctl->ic_siexr, vnew); |
183 | return 0; | 193 | return 0; |
194 | |||
195 | err_sense: | ||
196 | pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); | ||
197 | return -EINVAL; | ||
184 | } | 198 | } |
185 | 199 | ||
186 | static struct irq_chip cpm2_pic = { | 200 | static struct irq_chip cpm2_pic = { |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4e3a3e345ab3..e1a028c1f18d 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -464,8 +464,7 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, | |||
464 | { | 464 | { |
465 | struct pci_controller *hose = pci_bus_to_host(bus); | 465 | struct pci_controller *hose = pci_bus_to_host(bus); |
466 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; | 466 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; |
467 | u8 bus_no = bus->number - hose->first_busno; | 467 | u32 dev_base = bus->number << 24 | devfn << 16; |
468 | u32 dev_base = bus_no << 24 | devfn << 16; | ||
469 | int ret; | 468 | int ret; |
470 | 469 | ||
471 | ret = mpc83xx_pcie_exclude_device(bus, devfn); | 470 | ret = mpc83xx_pcie_exclude_device(bus, devfn); |
@@ -515,12 +514,17 @@ static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, | |||
515 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | 514 | static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, |
516 | int offset, int len, u32 val) | 515 | int offset, int len, u32 val) |
517 | { | 516 | { |
517 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
518 | void __iomem *cfg_addr; | 518 | void __iomem *cfg_addr; |
519 | 519 | ||
520 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); | 520 | cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); |
521 | if (!cfg_addr) | 521 | if (!cfg_addr) |
522 | return PCIBIOS_DEVICE_NOT_FOUND; | 522 | return PCIBIOS_DEVICE_NOT_FOUND; |
523 | 523 | ||
524 | /* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */ | ||
525 | if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno) | ||
526 | val &= 0xffffff00; | ||
527 | |||
524 | switch (len) { | 528 | switch (len) { |
525 | case 1: | 529 | case 1: |
526 | out_8(cfg_addr, val); | 530 | out_8(cfg_addr, val); |
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 103eace36194..ee1c0e1cf4a7 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
@@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) | |||
54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); | 54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs | ||
58 | * defined as output cannot be determined by reading GPDAT register, | ||
59 | * so we use shadow data register instead. The status of input pins | ||
60 | * is determined by reading GPDAT register. | ||
61 | */ | ||
62 | static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
63 | { | ||
64 | u32 val; | ||
65 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
66 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
67 | |||
68 | val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); | ||
69 | |||
70 | return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); | ||
71 | } | ||
72 | |||
57 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) | 73 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
58 | { | 74 | { |
59 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | 75 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); |
@@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) | |||
136 | gc->ngpio = MPC8XXX_GPIO_PINS; | 152 | gc->ngpio = MPC8XXX_GPIO_PINS; |
137 | gc->direction_input = mpc8xxx_gpio_dir_in; | 153 | gc->direction_input = mpc8xxx_gpio_dir_in; |
138 | gc->direction_output = mpc8xxx_gpio_dir_out; | 154 | gc->direction_output = mpc8xxx_gpio_dir_out; |
139 | gc->get = mpc8xxx_gpio_get; | 155 | if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) |
156 | gc->get = mpc8572_gpio_get; | ||
157 | else | ||
158 | gc->get = mpc8xxx_gpio_get; | ||
140 | gc->set = mpc8xxx_gpio_set; | 159 | gc->set = mpc8xxx_gpio_set; |
141 | 160 | ||
142 | ret = of_mm_gpiochip_add(np, mm_gc); | 161 | ret = of_mm_gpiochip_add(np, mm_gc); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index aa9d06e5925b..470dc6c11d57 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -567,13 +567,11 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 567 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
568 | 568 | ||
569 | #ifdef CONFIG_SMP | 569 | #ifdef CONFIG_SMP |
570 | static int irq_choose_cpu(unsigned int virt_irq) | 570 | static int irq_choose_cpu(const cpumask_t *mask) |
571 | { | 571 | { |
572 | cpumask_t mask; | ||
573 | int cpuid; | 572 | int cpuid; |
574 | 573 | ||
575 | cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity); | 574 | if (cpumask_equal(mask, cpu_all_mask)) { |
576 | if (cpus_equal(mask, CPU_MASK_ALL)) { | ||
577 | static int irq_rover; | 575 | static int irq_rover; |
578 | static DEFINE_SPINLOCK(irq_rover_lock); | 576 | static DEFINE_SPINLOCK(irq_rover_lock); |
579 | unsigned long flags; | 577 | unsigned long flags; |
@@ -594,20 +592,15 @@ static int irq_choose_cpu(unsigned int virt_irq) | |||
594 | 592 | ||
595 | spin_unlock_irqrestore(&irq_rover_lock, flags); | 593 | spin_unlock_irqrestore(&irq_rover_lock, flags); |
596 | } else { | 594 | } else { |
597 | cpumask_t tmp; | 595 | cpuid = cpumask_first_and(mask, cpu_online_mask); |
598 | 596 | if (cpuid >= nr_cpu_ids) | |
599 | cpus_and(tmp, cpu_online_map, mask); | ||
600 | |||
601 | if (cpus_empty(tmp)) | ||
602 | goto do_round_robin; | 597 | goto do_round_robin; |
603 | |||
604 | cpuid = first_cpu(tmp); | ||
605 | } | 598 | } |
606 | 599 | ||
607 | return get_hard_smp_processor_id(cpuid); | 600 | return get_hard_smp_processor_id(cpuid); |
608 | } | 601 | } |
609 | #else | 602 | #else |
610 | static int irq_choose_cpu(unsigned int virt_irq) | 603 | static int irq_choose_cpu(const cpumask_t *mask) |
611 | { | 604 | { |
612 | return hard_smp_processor_id(); | 605 | return hard_smp_processor_id(); |
613 | } | 606 | } |
@@ -816,7 +809,7 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
816 | unsigned int src = mpic_irq_to_hw(irq); | 809 | unsigned int src = mpic_irq_to_hw(irq); |
817 | 810 | ||
818 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { | 811 | if (mpic->flags & MPIC_SINGLE_DEST_CPU) { |
819 | int cpuid = irq_choose_cpu(irq); | 812 | int cpuid = irq_choose_cpu(cpumask); |
820 | 813 | ||
821 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | 814 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
822 | } else { | 815 | } else { |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 1d44eee80fa1..0f67cd79d481 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
@@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
39 | 39 | ||
40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); | 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); |
41 | 41 | ||
42 | /* Reserve source numbers we know are reserved in the HW */ | 42 | /* Reserve source numbers we know are reserved in the HW. |
43 | * | ||
44 | * This is a bit of a mix of U3 and U4 reserves but that's going | ||
45 | * to work fine, we have plenty enugh numbers left so let's just | ||
46 | * mark anything we don't like reserved. | ||
47 | */ | ||
43 | for (i = 0; i < 8; i++) | 48 | for (i = 0; i < 8; i++) |
44 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 49 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
45 | 50 | ||
@@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
49 | for (i = 100; i < 105; i++) | 54 | for (i = 100; i < 105; i++) |
50 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | 55 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
51 | 56 | ||
57 | for (i = 124; i < mpic->irq_count; i++) | ||
58 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); | ||
59 | |||
60 | |||
52 | np = NULL; | 61 | np = NULL; |
53 | while ((np = of_find_all_nodes(np))) { | 62 | while ((np = of_find_all_nodes(np))) { |
54 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); | 63 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index d3caf23e6312..bcbfe79c704b 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
@@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) | |||
64 | return addr; | 64 | return addr; |
65 | } | 65 | } |
66 | 66 | ||
67 | static u64 find_ht_magic_addr(struct pci_dev *pdev) | 67 | static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq) |
68 | { | 68 | { |
69 | struct pci_bus *bus; | 69 | struct pci_bus *bus; |
70 | unsigned int pos; | 70 | unsigned int pos; |
71 | 71 | ||
72 | for (bus = pdev->bus; bus; bus = bus->parent) { | 72 | for (bus = pdev->bus; bus && bus->self; bus = bus->parent) { |
73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); | 73 | pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); |
74 | if (pos) | 74 | if (pos) |
75 | return read_ht_magic_addr(bus->self, pos); | 75 | return read_ht_magic_addr(bus->self, pos); |
@@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev) | |||
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
80 | 80 | ||
81 | static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq) | ||
82 | { | ||
83 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
84 | |||
85 | /* U4 PCIe MSIs need to write to the special register in | ||
86 | * the bridge that generates interrupts. There should be | ||
87 | * theorically a register at 0xf8005000 where you just write | ||
88 | * the MSI number and that triggers the right interrupt, but | ||
89 | * unfortunately, this is busted in HW, the bridge endian swaps | ||
90 | * the value and hits the wrong nibble in the register. | ||
91 | * | ||
92 | * So instead we use another register set which is used normally | ||
93 | * for converting HT interrupts to MPIC interrupts, which decodes | ||
94 | * the interrupt number as part of the low address bits | ||
95 | * | ||
96 | * This will not work if we ever use more than one legacy MSI in | ||
97 | * a block but we never do. For one MSI or multiple MSI-X where | ||
98 | * each interrupt address can be specified separately, it works | ||
99 | * just fine. | ||
100 | */ | ||
101 | if (of_device_is_compatible(hose->dn, "u4-pcie") || | ||
102 | of_device_is_compatible(hose->dn, "U4-pcie")) | ||
103 | return 0xf8004000 | (hwirq << 4); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
81 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 108 | static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
82 | { | 109 | { |
83 | if (type == PCI_CAP_ID_MSIX) | 110 | if (type == PCI_CAP_ID_MSIX) |
84 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); | 111 | pr_debug("u3msi: MSI-X untested, trying anyway.\n"); |
85 | 112 | ||
86 | /* If we can't find a magic address then MSI ain't gonna work */ | 113 | /* If we can't find a magic address then MSI ain't gonna work */ |
87 | if (find_ht_magic_addr(pdev) == 0) { | 114 | if (find_ht_magic_addr(pdev, 0) == 0 && |
115 | find_u4_magic_addr(pdev, 0) == 0) { | ||
88 | pr_debug("u3msi: no magic address found for %s\n", | 116 | pr_debug("u3msi: no magic address found for %s\n", |
89 | pci_name(pdev)); | 117 | pci_name(pdev)); |
90 | return -ENXIO; | 118 | return -ENXIO; |
@@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
118 | u64 addr; | 146 | u64 addr; |
119 | int hwirq; | 147 | int hwirq; |
120 | 148 | ||
121 | addr = find_ht_magic_addr(pdev); | ||
122 | msg.address_lo = addr & 0xFFFFFFFF; | ||
123 | msg.address_hi = addr >> 32; | ||
124 | |||
125 | list_for_each_entry(entry, &pdev->msi_list, list) { | 149 | list_for_each_entry(entry, &pdev->msi_list, list) { |
126 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); | 150 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); |
127 | if (hwirq < 0) { | 151 | if (hwirq < 0) { |
@@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
129 | return hwirq; | 153 | return hwirq; |
130 | } | 154 | } |
131 | 155 | ||
156 | addr = find_ht_magic_addr(pdev, hwirq); | ||
157 | if (addr == 0) | ||
158 | addr = find_u4_magic_addr(pdev, hwirq); | ||
159 | msg.address_lo = addr & 0xFFFFFFFF; | ||
160 | msg.address_hi = addr >> 32; | ||
161 | |||
132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 162 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
133 | if (virq == NO_IRQ) { | 163 | if (virq == NO_IRQ) { |
134 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); | 164 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); |
@@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
143 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | 173 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", |
144 | virq, hwirq, (unsigned long)addr); | 174 | virq, hwirq, (unsigned long)addr); |
145 | 175 | ||
176 | printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", | ||
177 | virq, hwirq, (unsigned long)addr); | ||
146 | msg.data = hwirq; | 178 | msg.data = hwirq; |
147 | write_msi_msg(virq, &msg); | 179 | write_msi_msg(virq, &msg); |
148 | 180 | ||