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) ...
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#define MPC8XXX_GPIO_PINS 32
|
||||
|
||||
@@ -35,6 +36,7 @@ struct mpc8xxx_gpio_chip {
|
||||
* open drain mode safely
|
||||
*/
|
||||
u32 data;
|
||||
struct irq_host *irq;
|
||||
};
|
||||
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
|
||||
|
||||
if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
|
||||
return irq_create_mapping(mpc8xxx_gc->irq, offset);
|
||||
else
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_desc_data(desc);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned int mask;
|
||||
|
||||
mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
|
||||
if (mask)
|
||||
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
|
||||
32 - ffs(mask)));
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_unmask(unsigned int virq)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_mask(unsigned int virq)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_ack(unsigned int virq)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
|
||||
out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
}
|
||||
|
||||
static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
setbits32(mm->regs + GPIO_ICR,
|
||||
mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
clrbits32(mm->regs + GPIO_ICR,
|
||||
mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip mpc8xxx_irq_chip = {
|
||||
.name = "mpc8xxx-gpio",
|
||||
.unmask = mpc8xxx_irq_unmask,
|
||||
.mask = mpc8xxx_irq_mask,
|
||||
.ack = mpc8xxx_irq_ack,
|
||||
.set_type = mpc8xxx_irq_set_type,
|
||||
};
|
||||
|
||||
static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
set_irq_chip_data(virq, h->host_data);
|
||||
set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
|
||||
set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
|
||||
const u32 *intspec, unsigned int intsize,
|
||||
irq_hw_number_t *out_hwirq,
|
||||
unsigned int *out_flags)
|
||||
|
||||
{
|
||||
/* interrupt sense values coming from the device tree equal either
|
||||
* EDGE_FALLING or EDGE_BOTH
|
||||
*/
|
||||
*out_hwirq = intspec[0];
|
||||
*out_flags = intspec[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
|
||||
.map = mpc8xxx_gpio_irq_map,
|
||||
.xlate = mpc8xxx_gpio_irq_xlate,
|
||||
};
|
||||
|
||||
static void __init mpc8xxx_add_controller(struct device_node *np)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc;
|
||||
struct of_mm_gpio_chip *mm_gc;
|
||||
struct of_gpio_chip *of_gc;
|
||||
struct gpio_chip *gc;
|
||||
unsigned hwirq;
|
||||
int ret;
|
||||
|
||||
mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
|
||||
@@ -158,11 +284,32 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
|
||||
else
|
||||
gc->get = mpc8xxx_gpio_get;
|
||||
gc->set = mpc8xxx_gpio_set;
|
||||
gc->to_irq = mpc8xxx_gpio_to_irq;
|
||||
|
||||
ret = of_mm_gpiochip_add(np, mm_gc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
hwirq = irq_of_parse_and_map(np, 0);
|
||||
if (hwirq == NO_IRQ)
|
||||
goto skip_irq;
|
||||
|
||||
mpc8xxx_gc->irq =
|
||||
irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
|
||||
&mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
|
||||
if (!mpc8xxx_gc->irq)
|
||||
goto skip_irq;
|
||||
|
||||
mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
|
||||
|
||||
/* ack and mask all irqs */
|
||||
out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
|
||||
out_be32(mm_gc->regs + GPIO_IMR, 0);
|
||||
|
||||
set_irq_data(hwirq, mpc8xxx_gc);
|
||||
set_irq_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
|
||||
|
||||
skip_irq:
|
||||
return;
|
||||
|
||||
err:
|
||||
|
@@ -568,12 +568,12 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
|
||||
#endif /* CONFIG_MPIC_U3_HT_IRQS */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static int irq_choose_cpu(const cpumask_t *mask)
|
||||
static int irq_choose_cpu(const struct cpumask *mask)
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
if (cpumask_equal(mask, cpu_all_mask)) {
|
||||
static int irq_rover;
|
||||
static int irq_rover = 0;
|
||||
static DEFINE_RAW_SPINLOCK(irq_rover_lock);
|
||||
unsigned long flags;
|
||||
|
||||
@@ -581,15 +581,11 @@ static int irq_choose_cpu(const cpumask_t *mask)
|
||||
do_round_robin:
|
||||
raw_spin_lock_irqsave(&irq_rover_lock, flags);
|
||||
|
||||
while (!cpu_online(irq_rover)) {
|
||||
if (++irq_rover >= NR_CPUS)
|
||||
irq_rover = 0;
|
||||
}
|
||||
irq_rover = cpumask_next(irq_rover, cpu_online_mask);
|
||||
if (irq_rover >= nr_cpu_ids)
|
||||
irq_rover = cpumask_first(cpu_online_mask);
|
||||
|
||||
cpuid = irq_rover;
|
||||
do {
|
||||
if (++irq_rover >= NR_CPUS)
|
||||
irq_rover = 0;
|
||||
} while (!cpu_online(irq_rover));
|
||||
|
||||
raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
|
||||
} else {
|
||||
@@ -601,7 +597,7 @@ static int irq_choose_cpu(const cpumask_t *mask)
|
||||
return get_hard_smp_processor_id(cpuid);
|
||||
}
|
||||
#else
|
||||
static int irq_choose_cpu(const cpumask_t *mask)
|
||||
static int irq_choose_cpu(const struct cpumask *mask)
|
||||
{
|
||||
return hard_smp_processor_id();
|
||||
}
|
||||
@@ -814,12 +810,16 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
|
||||
} else {
|
||||
cpumask_t tmp;
|
||||
cpumask_var_t tmp;
|
||||
|
||||
cpumask_and(&tmp, cpumask, cpu_online_mask);
|
||||
alloc_cpumask_var(&tmp, GFP_KERNEL);
|
||||
|
||||
cpumask_and(tmp, cpumask, cpu_online_mask);
|
||||
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_physmask(cpus_addr(tmp)[0]));
|
||||
mpic_physmask(cpumask_bits(tmp)[0]));
|
||||
|
||||
free_cpumask_var(tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1479,21 +1479,6 @@ void mpic_teardown_this_cpu(int secondary)
|
||||
}
|
||||
|
||||
|
||||
void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
|
||||
{
|
||||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
#ifdef DEBUG_IPI
|
||||
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
|
||||
#endif
|
||||
|
||||
mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
|
||||
ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
|
||||
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
|
||||
}
|
||||
|
||||
static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
|
||||
{
|
||||
u32 src;
|
||||
@@ -1589,8 +1574,25 @@ void mpic_request_ipis(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void mpic_send_ipi(unsigned int ipi_no, const struct cpumask *cpu_mask)
|
||||
{
|
||||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
BUG_ON(mpic == NULL);
|
||||
|
||||
#ifdef DEBUG_IPI
|
||||
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
|
||||
#endif
|
||||
|
||||
mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
|
||||
ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
|
||||
mpic_physmask(cpumask_bits(cpu_mask)[0]));
|
||||
}
|
||||
|
||||
void smp_mpic_message_pass(int target, int msg)
|
||||
{
|
||||
cpumask_var_t tmp;
|
||||
|
||||
/* make sure we're sending something that translates to an IPI */
|
||||
if ((unsigned int)msg > 3) {
|
||||
printk("SMP %d: smp_message_pass: unknown msg %d\n",
|
||||
@@ -1599,13 +1601,17 @@ void smp_mpic_message_pass(int target, int msg)
|
||||
}
|
||||
switch (target) {
|
||||
case MSG_ALL:
|
||||
mpic_send_ipi(msg, 0xffffffff);
|
||||
mpic_send_ipi(msg, cpu_online_mask);
|
||||
break;
|
||||
case MSG_ALL_BUT_SELF:
|
||||
mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
|
||||
alloc_cpumask_var(&tmp, GFP_NOWAIT);
|
||||
cpumask_andnot(tmp, cpu_online_mask,
|
||||
cpumask_of(smp_processor_id()));
|
||||
mpic_send_ipi(msg, tmp);
|
||||
free_cpumask_var(tmp);
|
||||
break;
|
||||
default:
|
||||
mpic_send_ipi(msg, 1 << target);
|
||||
mpic_send_ipi(msg, cpumask_of(target));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1616,7 +1622,7 @@ int __init smp_mpic_probe(void)
|
||||
|
||||
DBG("smp_mpic_probe()...\n");
|
||||
|
||||
nr_cpus = cpus_weight(cpu_possible_map);
|
||||
nr_cpus = cpumask_weight(cpu_possible_mask);
|
||||
|
||||
DBG("nr_cpus: %d\n", nr_cpus);
|
||||
|
||||
|
@@ -191,11 +191,31 @@ static int __init ppc4xx_l2c_probe(void)
|
||||
arch_initcall(ppc4xx_l2c_probe);
|
||||
|
||||
/*
|
||||
* At present, this routine just applies a system reset.
|
||||
* Apply a system reset. Alternatively a board specific value may be
|
||||
* provided via the "reset-type" property in the cpu node.
|
||||
*/
|
||||
void ppc4xx_reset_system(char *cmd)
|
||||
{
|
||||
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_RST_SYSTEM);
|
||||
struct device_node *np;
|
||||
u32 reset_type = DBCR0_RST_SYSTEM;
|
||||
const u32 *prop;
|
||||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np) {
|
||||
prop = of_get_property(np, "reset-type", NULL);
|
||||
|
||||
/*
|
||||
* Check if property exists and if it is in range:
|
||||
* 1 - PPC4xx core reset
|
||||
* 2 - PPC4xx chip reset
|
||||
* 3 - PPC4xx system reset (default)
|
||||
*/
|
||||
if ((prop) && ((prop[0] >= 1) && (prop[0] <= 3)))
|
||||
reset_type = prop[0] << 28;
|
||||
}
|
||||
|
||||
mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | reset_type);
|
||||
|
||||
while (1)
|
||||
; /* Just in case the reset doesn't work */
|
||||
}
|
||||
|
Reference in New Issue
Block a user