diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 14:17:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 14:17:05 -0400 |
| commit | 79c4581262e225a7c96d88b632b05ab3b5e9a52c (patch) | |
| tree | 8ef030c74ab7e0d0df27cf86195f915efd2832f7 /arch/powerpc/sysdev | |
| parent | 59534f7298c5e28aaa64e6ed550e247f64ee72ae (diff) | |
| parent | 99ec28f183daa450faa7bdad6f932364ae325648 (diff) | |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (92 commits)
powerpc: Remove unused 'protect4gb' boot parameter
powerpc: Build-in e1000e for pseries & ppc64_defconfig
powerpc/pseries: Make request_ras_irqs() available to other pseries code
powerpc/numa: Use ibm,architecture-vec-5 to detect form 1 affinity
powerpc/numa: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
powerpc: Use smt_snooze_delay=-1 to always busy loop
powerpc: Remove check of ibm,smt-snooze-delay OF property
powerpc/kdump: Fix race in kdump shutdown
powerpc/kexec: Fix race in kexec shutdown
powerpc/kexec: Speedup kexec hash PTE tear down
powerpc/pseries: Add hcall to read 4 ptes at a time in real mode
powerpc: Use more accurate limit for first segment memory allocations
powerpc/kdump: Use chip->shutdown to disable IRQs
powerpc/kdump: CPUs assume the context of the oopsing CPU
powerpc/crashdump: Do not fail on NULL pointer dereferencing
powerpc/eeh: Fix oops when probing in early boot
powerpc/pci: Check devices status property when scanning OF tree
powerpc/vio: Switch VIO Bus PM to use generic helpers
powerpc: Avoid bad relocations in iSeries code
powerpc: Use common cpu_die (fixes SMP+SUSPEND build)
...
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/mpc8xxx_gpio.c | 147 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 72 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/ppc4xx_soc.c | 24 |
3 files changed, 208 insertions, 35 deletions
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 6478eb10691a..83f519655fac 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/of_gpio.h> | 16 | #include <linux/of_gpio.h> |
| 17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/irq.h> | ||
| 19 | 20 | ||
| 20 | #define MPC8XXX_GPIO_PINS 32 | 21 | #define MPC8XXX_GPIO_PINS 32 |
| 21 | 22 | ||
| @@ -35,6 +36,7 @@ struct mpc8xxx_gpio_chip { | |||
| 35 | * open drain mode safely | 36 | * open drain mode safely |
| 36 | */ | 37 | */ |
| 37 | u32 data; | 38 | u32 data; |
| 39 | struct irq_host *irq; | ||
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) | 42 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) |
| @@ -128,12 +130,136 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val | |||
| 128 | return 0; | 130 | return 0; |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 133 | static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 134 | { | ||
| 135 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
| 136 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
| 137 | |||
| 138 | if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS) | ||
| 139 | return irq_create_mapping(mpc8xxx_gc->irq, offset); | ||
| 140 | else | ||
| 141 | return -ENXIO; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc) | ||
| 145 | { | ||
| 146 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_desc_data(desc); | ||
| 147 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 148 | unsigned int mask; | ||
| 149 | |||
| 150 | mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR); | ||
| 151 | if (mask) | ||
| 152 | generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, | ||
| 153 | 32 - ffs(mask))); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void mpc8xxx_irq_unmask(unsigned int virq) | ||
| 157 | { | ||
| 158 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); | ||
| 159 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 160 | unsigned long flags; | ||
| 161 | |||
| 162 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 163 | |||
| 164 | setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq))); | ||
| 165 | |||
| 166 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 167 | } | ||
| 168 | |||
| 169 | static void mpc8xxx_irq_mask(unsigned int virq) | ||
| 170 | { | ||
| 171 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); | ||
| 172 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 173 | unsigned long flags; | ||
| 174 | |||
| 175 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 176 | |||
| 177 | clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq))); | ||
| 178 | |||
| 179 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 180 | } | ||
| 181 | |||
| 182 | static void mpc8xxx_irq_ack(unsigned int virq) | ||
| 183 | { | ||
| 184 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); | ||
| 185 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 186 | |||
| 187 | out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq))); | ||
| 188 | } | ||
| 189 | |||
| 190 | static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type) | ||
| 191 | { | ||
| 192 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); | ||
| 193 | struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; | ||
| 194 | unsigned long flags; | ||
| 195 | |||
| 196 | switch (flow_type) { | ||
| 197 | case IRQ_TYPE_EDGE_FALLING: | ||
| 198 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 199 | setbits32(mm->regs + GPIO_ICR, | ||
| 200 | mpc8xxx_gpio2mask(virq_to_hw(virq))); | ||
| 201 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 202 | break; | ||
| 203 | |||
| 204 | case IRQ_TYPE_EDGE_BOTH: | ||
| 205 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
| 206 | clrbits32(mm->regs + GPIO_ICR, | ||
| 207 | mpc8xxx_gpio2mask(virq_to_hw(virq))); | ||
| 208 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
| 209 | break; | ||
| 210 | |||
| 211 | default: | ||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | |||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | static struct irq_chip mpc8xxx_irq_chip = { | ||
| 219 | .name = "mpc8xxx-gpio", | ||
| 220 | .unmask = mpc8xxx_irq_unmask, | ||
| 221 | .mask = mpc8xxx_irq_mask, | ||
| 222 | .ack = mpc8xxx_irq_ack, | ||
| 223 | .set_type = mpc8xxx_irq_set_type, | ||
| 224 | }; | ||
| 225 | |||
| 226 | static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, | ||
| 227 | irq_hw_number_t hw) | ||
| 228 | { | ||
| 229 | set_irq_chip_data(virq, h->host_data); | ||
| 230 | set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); | ||
| 231 | set_irq_type(virq, IRQ_TYPE_NONE); | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct, | ||
| 237 | const u32 *intspec, unsigned int intsize, | ||
| 238 | irq_hw_number_t *out_hwirq, | ||
| 239 | unsigned int *out_flags) | ||
| 240 | |||
| 241 | { | ||
| 242 | /* interrupt sense values coming from the device tree equal either | ||
| 243 | * EDGE_FALLING or EDGE_BOTH | ||
| 244 | */ | ||
| 245 | *out_hwirq = intspec[0]; | ||
| 246 | *out_flags = intspec[1]; | ||
| 247 | |||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | static struct irq_host_ops mpc8xxx_gpio_irq_ops = { | ||
| 252 | .map = mpc8xxx_gpio_irq_map, | ||
| 253 | .xlate = mpc8xxx_gpio_irq_xlate, | ||
| 254 | }; | ||
| 255 | |||
| 131 | static void __init mpc8xxx_add_controller(struct device_node *np) | 256 | static void __init mpc8xxx_add_controller(struct device_node *np) |
| 132 | { | 257 | { |
| 133 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; | 258 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; |
| 134 | struct of_mm_gpio_chip *mm_gc; | 259 | struct of_mm_gpio_chip *mm_gc; |
| 135 | struct of_gpio_chip *of_gc; | 260 | struct of_gpio_chip *of_gc; |
| 136 | struct gpio_chip *gc; | 261 | struct gpio_chip *gc; |
| 262 | unsigned hwirq; | ||
| 137 | int ret; | 263 | int ret; |
| 138 | 264 | ||
| 139 | mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); | 265 | mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); |
| @@ -158,11 +284,32 @@ static void __init mpc8xxx_add_controller(struct device_node *np) | |||
| 158 | else | 284 | else |
| 159 | gc->get = mpc8xxx_gpio_get; | 285 | gc->get = mpc8xxx_gpio_get; |
| 160 | gc->set = mpc8xxx_gpio_set; | 286 | gc->set = mpc8xxx_gpio_set; |
| 287 | gc->to_irq = mpc8xxx_gpio_to_irq; | ||
| 161 | 288 | ||
| 162 | ret = of_mm_gpiochip_add(np, mm_gc); | 289 | ret = of_mm_gpiochip_add(np, mm_gc); |
| 163 | if (ret) | 290 | if (ret) |
| 164 | goto err; | 291 | goto err; |
| 165 | 292 | ||
| 293 | hwirq = irq_of_parse_and_map(np, 0); | ||
| 294 | if (hwirq == NO_IRQ) | ||
| 295 | goto skip_irq; | ||
| 296 | |||
| 297 | mpc8xxx_gc->irq = | ||
| 298 | irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS, | ||
| 299 | &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS); | ||
| 300 | if (!mpc8xxx_gc->irq) | ||
| 301 | goto skip_irq; | ||
| 302 | |||
| 303 | mpc8xxx_gc->irq->host_data = mpc8xxx_gc; | ||
| 304 | |||
| 305 | /* ack and mask all irqs */ | ||
| 306 | out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); | ||
| 307 | out_be32(mm_gc->regs + GPIO_IMR, 0); | ||
| 308 | |||
| 309 | set_irq_data(hwirq, mpc8xxx_gc); | ||
| 310 | set_irq_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade); | ||
| 311 | |||
| 312 | skip_irq: | ||
| 166 | return; | 313 | return; |
| 167 | 314 | ||
| 168 | err: | 315 | err: |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 260295b10557..2102487612a4 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -568,12 +568,12 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
| 568 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 568 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
| 569 | 569 | ||
| 570 | #ifdef CONFIG_SMP | 570 | #ifdef CONFIG_SMP |
| 571 | static int irq_choose_cpu(const cpumask_t *mask) | 571 | static int irq_choose_cpu(const struct cpumask *mask) |
| 572 | { | 572 | { |
| 573 | int cpuid; | 573 | int cpuid; |
| 574 | 574 | ||
| 575 | if (cpumask_equal(mask, cpu_all_mask)) { | 575 | if (cpumask_equal(mask, cpu_all_mask)) { |
| 576 | static int irq_rover; | 576 | static int irq_rover = 0; |
| 577 | static DEFINE_RAW_SPINLOCK(irq_rover_lock); | 577 | static DEFINE_RAW_SPINLOCK(irq_rover_lock); |
| 578 | unsigned long flags; | 578 | unsigned long flags; |
| 579 | 579 | ||
| @@ -581,15 +581,11 @@ static int irq_choose_cpu(const cpumask_t *mask) | |||
| 581 | do_round_robin: | 581 | do_round_robin: |
| 582 | raw_spin_lock_irqsave(&irq_rover_lock, flags); | 582 | raw_spin_lock_irqsave(&irq_rover_lock, flags); |
| 583 | 583 | ||
| 584 | while (!cpu_online(irq_rover)) { | 584 | irq_rover = cpumask_next(irq_rover, cpu_online_mask); |
| 585 | if (++irq_rover >= NR_CPUS) | 585 | if (irq_rover >= nr_cpu_ids) |
| 586 | irq_rover = 0; | 586 | irq_rover = cpumask_first(cpu_online_mask); |
| 587 | } | 587 | |
| 588 | cpuid = irq_rover; | 588 | cpuid = irq_rover; |
| 589 | do { | ||
| 590 | if (++irq_rover >= NR_CPUS) | ||
| 591 | irq_rover = 0; | ||
| 592 | } while (!cpu_online(irq_rover)); | ||
| 593 | 589 | ||
| 594 | raw_spin_unlock_irqrestore(&irq_rover_lock, flags); | 590 | raw_spin_unlock_irqrestore(&irq_rover_lock, flags); |
| 595 | } else { | 591 | } else { |
| @@ -601,7 +597,7 @@ static int irq_choose_cpu(const cpumask_t *mask) | |||
| 601 | return get_hard_smp_processor_id(cpuid); | 597 | return get_hard_smp_processor_id(cpuid); |
| 602 | } | 598 | } |
| 603 | #else | 599 | #else |
| 604 | static int irq_choose_cpu(const cpumask_t *mask) | 600 | static int irq_choose_cpu(const struct cpumask *mask) |
| 605 | { | 601 | { |
| 606 | return hard_smp_processor_id(); | 602 | return hard_smp_processor_id(); |
| 607 | } | 603 | } |
| @@ -814,12 +810,16 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
| 814 | 810 | ||
| 815 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | 811 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
| 816 | } else { | 812 | } else { |
| 817 | cpumask_t tmp; | 813 | cpumask_var_t tmp; |
| 818 | 814 | ||
| 819 | cpumask_and(&tmp, cpumask, cpu_online_mask); | 815 | alloc_cpumask_var(&tmp, GFP_KERNEL); |
| 816 | |||
| 817 | cpumask_and(tmp, cpumask, cpu_online_mask); | ||
| 820 | 818 | ||
| 821 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), | 819 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), |
| 822 | mpic_physmask(cpus_addr(tmp)[0])); | 820 | mpic_physmask(cpumask_bits(tmp)[0])); |
| 821 | |||
| 822 | free_cpumask_var(tmp); | ||
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | return 0; | 825 | return 0; |
| @@ -1479,21 +1479,6 @@ void mpic_teardown_this_cpu(int secondary) | |||
| 1479 | } | 1479 | } |
| 1480 | 1480 | ||
| 1481 | 1481 | ||
| 1482 | void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) | ||
| 1483 | { | ||
| 1484 | struct mpic *mpic = mpic_primary; | ||
| 1485 | |||
| 1486 | BUG_ON(mpic == NULL); | ||
| 1487 | |||
| 1488 | #ifdef DEBUG_IPI | ||
| 1489 | DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); | ||
| 1490 | #endif | ||
| 1491 | |||
| 1492 | mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) + | ||
| 1493 | ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), | ||
| 1494 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg) | 1482 | static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg) |
| 1498 | { | 1483 | { |
| 1499 | u32 src; | 1484 | u32 src; |
| @@ -1589,8 +1574,25 @@ void mpic_request_ipis(void) | |||
| 1589 | } | 1574 | } |
| 1590 | } | 1575 | } |
| 1591 | 1576 | ||
| 1577 | static void mpic_send_ipi(unsigned int ipi_no, const struct cpumask *cpu_mask) | ||
| 1578 | { | ||
| 1579 | struct mpic *mpic = mpic_primary; | ||
| 1580 | |||
| 1581 | BUG_ON(mpic == NULL); | ||
| 1582 | |||
| 1583 | #ifdef DEBUG_IPI | ||
| 1584 | DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); | ||
| 1585 | #endif | ||
| 1586 | |||
| 1587 | mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) + | ||
| 1588 | ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), | ||
| 1589 | mpic_physmask(cpumask_bits(cpu_mask)[0])); | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | void smp_mpic_message_pass(int target, int msg) | 1592 | void smp_mpic_message_pass(int target, int msg) |
| 1593 | { | 1593 | { |
| 1594 | cpumask_var_t tmp; | ||
| 1595 | |||
| 1594 | /* make sure we're sending something that translates to an IPI */ | 1596 | /* make sure we're sending something that translates to an IPI */ |
| 1595 | if ((unsigned int)msg > 3) { | 1597 | if ((unsigned int)msg > 3) { |
| 1596 | printk("SMP %d: smp_message_pass: unknown msg %d\n", | 1598 | printk("SMP %d: smp_message_pass: unknown msg %d\n", |
| @@ -1599,13 +1601,17 @@ void smp_mpic_message_pass(int target, int msg) | |||
| 1599 | } | 1601 | } |
| 1600 | switch (target) { | 1602 | switch (target) { |
| 1601 | case MSG_ALL: | 1603 | case MSG_ALL: |
| 1602 | mpic_send_ipi(msg, 0xffffffff); | 1604 | mpic_send_ipi(msg, cpu_online_mask); |
| 1603 | break; | 1605 | break; |
| 1604 | case MSG_ALL_BUT_SELF: | 1606 | case MSG_ALL_BUT_SELF: |
| 1605 | mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id())); | 1607 | alloc_cpumask_var(&tmp, GFP_NOWAIT); |
| 1608 | cpumask_andnot(tmp, cpu_online_mask, | ||
| 1609 | cpumask_of(smp_processor_id())); | ||
| 1610 | mpic_send_ipi(msg, tmp); | ||
| 1611 | free_cpumask_var(tmp); | ||
| 1606 | break; | 1612 | break; |
| 1607 | default: | 1613 | default: |
| 1608 | mpic_send_ipi(msg, 1 << target); | 1614 | mpic_send_ipi(msg, cpumask_of(target)); |
| 1609 | break; | 1615 | break; |
| 1610 | } | 1616 | } |
| 1611 | } | 1617 | } |
| @@ -1616,7 +1622,7 @@ int __init smp_mpic_probe(void) | |||
| 1616 | 1622 | ||
| 1617 | DBG("smp_mpic_probe()...\n"); | 1623 | DBG("smp_mpic_probe()...\n"); |
| 1618 | 1624 | ||
| 1619 | nr_cpus = cpus_weight(cpu_possible_map); | 1625 | nr_cpus = cpumask_weight(cpu_possible_mask); |
| 1620 | 1626 | ||
| 1621 | DBG("nr_cpus: %d\n", nr_cpus); | 1627 | DBG("nr_cpus: %d\n", nr_cpus); |
| 1622 | 1628 | ||
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c index 5c014350bf16..d3d6ce3c33b4 100644 --- a/arch/powerpc/sysdev/ppc4xx_soc.c +++ b/arch/powerpc/sysdev/ppc4xx_soc.c | |||
| @@ -191,11 +191,31 @@ static int __init ppc4xx_l2c_probe(void) | |||
| 191 | arch_initcall(ppc4xx_l2c_probe); | 191 | arch_initcall(ppc4xx_l2c_probe); |
| 192 | 192 | ||
| 193 | /* | 193 | /* |
| 194 | * At present, this routine just applies a system reset. | 194 | * Apply a system reset. Alternatively a board specific value may be |
| 195 | * provided via the "reset-type" property in the cpu node. | ||
| 195 | */ | 196 | */ |
| 196 | void ppc4xx_reset_system(char *cmd) | 197 | void ppc4xx_reset_system(char *cmd) |
| 197 | { | 198 | { |
| 198 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_RST_SYSTEM); | 199 | struct device_node *np; |
| 200 | u32 reset_type = DBCR0_RST_SYSTEM; | ||
| 201 | const u32 *prop; | ||
| 202 | |||
| 203 | np = of_find_node_by_type(NULL, "cpu"); | ||
| 204 | if (np) { | ||
| 205 | prop = of_get_property(np, "reset-type", NULL); | ||
| 206 | |||
| 207 | /* | ||
| 208 | * Check if property exists and if it is in range: | ||
| 209 | * 1 - PPC4xx core reset | ||
| 210 | * 2 - PPC4xx chip reset | ||
| 211 | * 3 - PPC4xx system reset (default) | ||
| 212 | */ | ||
| 213 | if ((prop) && ((prop[0] >= 1) && (prop[0] <= 3))) | ||
| 214 | reset_type = prop[0] << 28; | ||
| 215 | } | ||
| 216 | |||
| 217 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | reset_type); | ||
| 218 | |||
| 199 | while (1) | 219 | while (1) |
| 200 | ; /* Just in case the reset doesn't work */ | 220 | ; /* Just in case the reset doesn't work */ |
| 201 | } | 221 | } |
