Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

Pull powerpc fixes from Benjamin Herrenschmidt:
 "Here are a few fixes for powerpc.  Note the addition to the generic
  irq.h.  This is part of a 3-patches regression fix for mpic due to
  changes in how IRQ_TYPE_NONE is being handled.  Thomas agreed to the
  addition of the new IRQ_TYPE_DEFAULT contant, however he hasn't
  replied with an Ack to the actual patch yet.  I don't to wait much
  longer with these patches tho."

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/mpic: Properly set default triggers
  irq: Add IRQ_TYPE_DEFAULT for use by PIC drivers
  powerpc/mpic: Fix confusion between hw_irq and virq
  powerpc/pmac: Don't add_timer() twice
  powerpc/eeh: Fix crash caused by null eeh_dev
  powerpc/mpc85xx: add MPIC message dts node
  powerpc/mpic_msgr: fix offset error when setting mer register
  powerpc/mpic_msgr: add lock for MPIC message global variable
  powerpc/mpic_msgr: fix compile error when SMP disabled
  powerpc: fix build when CONFIG_BOOKE_WDT is enabled
  powerpc/85xx: don't call of_platform_bus_probe() twice
This commit is contained in:
Linus Torvalds 2012-04-22 21:07:51 -07:00
commit 205b9c9c6e
14 changed files with 123 additions and 73 deletions

View File

@ -0,0 +1,43 @@
/*
* PQ3 MPIC Message (Group B) device tree stub [ controller @ offset 0x42400 ]
*
* Copyright 2012 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
message@42400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x42400 0x200>;
interrupts = <
0xb4 2 0 0
0xb5 2 0 0
0xb6 2 0 0
0xb7 2 0 0>;
};

View File

@ -53,6 +53,16 @@ timer@41100 {
3 0 3 0>; 3 0 3 0>;
}; };
message@41400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x41400 0x200>;
interrupts = <
0xb0 2 0 0
0xb1 2 0 0
0xb2 2 0 0
0xb3 2 0 0>;
};
msi@41600 { msi@41600 {
compatible = "fsl,mpic-msi"; compatible = "fsl,mpic-msi";
reg = <0x41600 0x80>; reg = <0x41600 0x80>;

View File

@ -275,9 +275,6 @@ struct mpic
unsigned int isu_mask; unsigned int isu_mask;
/* Number of sources */ /* Number of sources */
unsigned int num_sources; unsigned int num_sources;
/* default senses array */
unsigned char *senses;
unsigned int senses_count;
/* vector numbers used for internal sources (ipi/timers) */ /* vector numbers used for internal sources (ipi/timers) */
unsigned int ipi_vecs[4]; unsigned int ipi_vecs[4];
@ -415,21 +412,6 @@ extern struct mpic *mpic_alloc(struct device_node *node,
extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
phys_addr_t phys_addr); phys_addr_t phys_addr);
/* Set default sense codes
*
* @mpic: controller
* @senses: array of sense codes
* @count: size of above array
*
* Optionally provide an array (indexed on hardware interrupt numbers
* for this MPIC) of default sense codes for the chip. Those are linux
* sense codes IRQ_TYPE_*
*
* The driver gets ownership of the pointer, don't dispose of it or
* anything like that. __init only.
*/
extern void mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count);
/* Initialize the controller. After this has been called, none of the above /* Initialize the controller. After this has been called, none of the above
* should be called again for this mpic * should be called again for this mpic

View File

@ -13,6 +13,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/smp.h>
struct mpic_msgr { struct mpic_msgr {
u32 __iomem *base; u32 __iomem *base;

View File

@ -15,11 +15,6 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__ #ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__ #define __ASM_POWERPC_REG_BOOKE_H__
#ifdef CONFIG_BOOKE_WDT
extern u32 booke_wdt_enabled;
extern u32 booke_wdt_period;
#endif /* CONFIG_BOOKE_WDT */
/* Machine State Register (MSR) Fields */ /* Machine State Register (MSR) Fields */
#define MSR_GS (1<<28) /* Guest state */ #define MSR_GS (1<<28) /* Guest state */
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */ #define MSR_UCLE (1<<26) /* User-mode cache lock enable */

View File

@ -150,6 +150,9 @@ notrace void __init machine_init(u64 dt_ptr)
} }
#ifdef CONFIG_BOOKE_WDT #ifdef CONFIG_BOOKE_WDT
extern u32 booke_wdt_enabled;
extern u32 booke_wdt_period;
/* Checks wdt=x and wdt_period=xx command-line option */ /* Checks wdt=x and wdt_period=xx command-line option */
notrace int __init early_parse_wdt(char *p) notrace int __init early_parse_wdt(char *p)
{ {

View File

@ -21,6 +21,12 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
{ .compatible = "fsl,qe", }, { .compatible = "fsl,qe", },
{ .compatible = "fsl,cpm2", }, { .compatible = "fsl,cpm2", },
{ .compatible = "fsl,srio", }, { .compatible = "fsl,srio", },
/* So that the DMA channel nodes can be probed individually: */
{ .compatible = "fsl,eloplus-dma", },
/* For the PMC driver */
{ .compatible = "fsl,mpc8548-guts", },
/* Probably unnecessary? */
{ .compatible = "gpio-leds", },
{}, {},
}; };

View File

@ -399,12 +399,6 @@ static int __init board_fixups(void)
machine_arch_initcall(mpc8568_mds, board_fixups); machine_arch_initcall(mpc8568_mds, board_fixups);
machine_arch_initcall(mpc8569_mds, board_fixups); machine_arch_initcall(mpc8569_mds, board_fixups);
static struct of_device_id mpc85xx_ids[] = {
{ .compatible = "fsl,mpc8548-guts", },
{ .compatible = "gpio-leds", },
{},
};
static int __init mpc85xx_publish_devices(void) static int __init mpc85xx_publish_devices(void)
{ {
if (machine_is(mpc8568_mds)) if (machine_is(mpc8568_mds))
@ -412,10 +406,7 @@ static int __init mpc85xx_publish_devices(void)
if (machine_is(mpc8569_mds)) if (machine_is(mpc8569_mds))
simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio"); simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
mpc85xx_common_publish_devices(); return mpc85xx_common_publish_devices();
of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
return 0;
} }
machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);

View File

@ -460,18 +460,7 @@ static void __init p1022_ds_setup_arch(void)
pr_info("Freescale P1022 DS reference board\n"); pr_info("Freescale P1022 DS reference board\n");
} }
static struct of_device_id __initdata p1022_ds_ids[] = { machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
/* So that the DMA channel nodes can be probed individually: */
{ .compatible = "fsl,eloplus-dma", },
{},
};
static int __init p1022_ds_publish_devices(void)
{
mpc85xx_common_publish_devices();
return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
}
machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);

View File

@ -366,11 +366,20 @@ static void kw_i2c_timeout(unsigned long data)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
/*
* If the timer is pending, that means we raced with the
* irq, in which case we just return
*/
if (timer_pending(&host->timeout_timer))
goto skip;
kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr)); kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
if (host->state != state_idle) { if (host->state != state_idle) {
host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT; host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
add_timer(&host->timeout_timer); add_timer(&host->timeout_timer);
} }
skip:
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
} }

View File

@ -1076,7 +1076,7 @@ static void eeh_add_device_late(struct pci_dev *dev)
pr_debug("EEH: Adding device %s\n", pci_name(dev)); pr_debug("EEH: Adding device %s\n", pci_name(dev));
dn = pci_device_to_OF_node(dev); dn = pci_device_to_OF_node(dev);
edev = pci_dev_to_eeh_dev(dev); edev = of_node_to_eeh_dev(dn);
if (edev->pdev == dev) { if (edev->pdev == dev) {
pr_debug("EEH: Already referenced !\n"); pr_debug("EEH: Already referenced !\n");
return; return;

View File

@ -604,18 +604,14 @@ static struct mpic *mpic_find(unsigned int irq)
} }
/* Determine if the linux irq is an IPI */ /* Determine if the linux irq is an IPI */
static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq) static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int src)
{ {
unsigned int src = virq_to_hw(irq);
return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]); return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
} }
/* Determine if the linux irq is a timer */ /* Determine if the linux irq is a timer */
static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq) static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int src)
{ {
unsigned int src = virq_to_hw(irq);
return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]); return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]);
} }
@ -876,21 +872,45 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
if (src >= mpic->num_sources) if (src >= mpic->num_sources)
return -EINVAL; return -EINVAL;
if (flow_type == IRQ_TYPE_NONE) vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
if (mpic->senses && src < mpic->senses_count)
flow_type = mpic->senses[src];
if (flow_type == IRQ_TYPE_NONE)
flow_type = IRQ_TYPE_LEVEL_LOW;
/* We don't support "none" type */
if (flow_type == IRQ_TYPE_NONE)
flow_type = IRQ_TYPE_DEFAULT;
/* Default: read HW settings */
if (flow_type == IRQ_TYPE_DEFAULT) {
switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
MPIC_INFO(VECPRI_SENSE_MASK))) {
case MPIC_INFO(VECPRI_SENSE_EDGE) |
MPIC_INFO(VECPRI_POLARITY_POSITIVE):
flow_type = IRQ_TYPE_EDGE_RISING;
break;
case MPIC_INFO(VECPRI_SENSE_EDGE) |
MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
flow_type = IRQ_TYPE_EDGE_FALLING;
break;
case MPIC_INFO(VECPRI_SENSE_LEVEL) |
MPIC_INFO(VECPRI_POLARITY_POSITIVE):
flow_type = IRQ_TYPE_LEVEL_HIGH;
break;
case MPIC_INFO(VECPRI_SENSE_LEVEL) |
MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
flow_type = IRQ_TYPE_LEVEL_LOW;
break;
}
}
/* Apply to irq desc */
irqd_set_trigger_type(d, flow_type); irqd_set_trigger_type(d, flow_type);
/* Apply to HW */
if (mpic_is_ht_interrupt(mpic, src)) if (mpic_is_ht_interrupt(mpic, src))
vecpri = MPIC_VECPRI_POLARITY_POSITIVE | vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
MPIC_VECPRI_SENSE_EDGE; MPIC_VECPRI_SENSE_EDGE;
else else
vecpri = mpic_type_to_vecpri(mpic, flow_type); vecpri = mpic_type_to_vecpri(mpic, flow_type);
vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) | vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
MPIC_INFO(VECPRI_SENSE_MASK)); MPIC_INFO(VECPRI_SENSE_MASK));
vnew |= vecpri; vnew |= vecpri;
@ -1026,7 +1046,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq); irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
/* Set default irq type */ /* Set default irq type */
irq_set_irq_type(virq, IRQ_TYPE_NONE); irq_set_irq_type(virq, IRQ_TYPE_DEFAULT);
/* If the MPIC was reset, then all vectors have already been /* If the MPIC was reset, then all vectors have already been
* initialized. Otherwise, a per source lazy initialization * initialized. Otherwise, a per source lazy initialization
@ -1417,12 +1437,6 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
mpic->num_sources = isu_first + mpic->isu_size; mpic->num_sources = isu_first + mpic->isu_size;
} }
void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
{
mpic->senses = senses;
mpic->senses_count = count;
}
void __init mpic_init(struct mpic *mpic) void __init mpic_init(struct mpic *mpic)
{ {
int i, cpu; int i, cpu;
@ -1555,12 +1569,12 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
return; return;
raw_spin_lock_irqsave(&mpic_lock, flags); raw_spin_lock_irqsave(&mpic_lock, flags);
if (mpic_is_ipi(mpic, irq)) { if (mpic_is_ipi(mpic, src)) {
reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) & reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
~MPIC_VECPRI_PRIORITY_MASK; ~MPIC_VECPRI_PRIORITY_MASK;
mpic_ipi_write(src - mpic->ipi_vecs[0], mpic_ipi_write(src - mpic->ipi_vecs[0],
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
} else if (mpic_is_tm(mpic, irq)) { } else if (mpic_is_tm(mpic, src)) {
reg = mpic_tm_read(src - mpic->timer_vecs[0]) & reg = mpic_tm_read(src - mpic->timer_vecs[0]) &
~MPIC_VECPRI_PRIORITY_MASK; ~MPIC_VECPRI_PRIORITY_MASK;
mpic_tm_write(src - mpic->timer_vecs[0], mpic_tm_write(src - mpic->timer_vecs[0],

View File

@ -27,6 +27,7 @@
static struct mpic_msgr **mpic_msgrs; static struct mpic_msgr **mpic_msgrs;
static unsigned int mpic_msgr_count; static unsigned int mpic_msgr_count;
static DEFINE_RAW_SPINLOCK(msgrs_lock);
static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value) static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
{ {
@ -56,12 +57,11 @@ struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
if (reg_num >= mpic_msgr_count) if (reg_num >= mpic_msgr_count)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
raw_spin_lock_irqsave(&msgr->lock, flags); raw_spin_lock_irqsave(&msgrs_lock, flags);
if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) { msgr = mpic_msgrs[reg_num];
msgr = mpic_msgrs[reg_num]; if (msgr->in_use == MSGR_FREE)
msgr->in_use = MSGR_INUSE; msgr->in_use = MSGR_INUSE;
} raw_spin_unlock_irqrestore(&msgrs_lock, flags);
raw_spin_unlock_irqrestore(&msgr->lock, flags);
return msgr; return msgr;
} }
@ -228,7 +228,7 @@ static __devinit int mpic_msgr_probe(struct platform_device *dev)
reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i; reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE; msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
msgr->mer = msgr->base + MPIC_MSGR_MER_OFFSET; msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
msgr->in_use = MSGR_FREE; msgr->in_use = MSGR_FREE;
msgr->num = i; msgr->num = i;
raw_spin_lock_init(&msgr->lock); raw_spin_lock_init(&msgr->lock);

View File

@ -49,6 +49,12 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
* IRQ_TYPE_LEVEL_LOW - low level triggered * IRQ_TYPE_LEVEL_LOW - low level triggered
* IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits * IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits
* IRQ_TYPE_SENSE_MASK - Mask for all the above bits * IRQ_TYPE_SENSE_MASK - Mask for all the above bits
* IRQ_TYPE_DEFAULT - For use by some PICs to ask irq_set_type
* to setup the HW to a sane default (used
* by irqdomain map() callbacks to synchronize
* the HW state and SW flags for a newly
* allocated descriptor).
*
* IRQ_TYPE_PROBE - Special flag for probing in progress * IRQ_TYPE_PROBE - Special flag for probing in progress
* *
* Bits which can be modified via irq_set/clear/modify_status_flags() * Bits which can be modified via irq_set/clear/modify_status_flags()
@ -77,6 +83,7 @@ enum {
IRQ_TYPE_LEVEL_LOW = 0x00000008, IRQ_TYPE_LEVEL_LOW = 0x00000008,
IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH), IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
IRQ_TYPE_SENSE_MASK = 0x0000000f, IRQ_TYPE_SENSE_MASK = 0x0000000f,
IRQ_TYPE_DEFAULT = IRQ_TYPE_SENSE_MASK,
IRQ_TYPE_PROBE = 0x00000010, IRQ_TYPE_PROBE = 0x00000010,