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:
commit
205b9c9c6e
43
arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi
Normal file
43
arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi
Normal 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>;
|
||||
};
|
|
@ -53,6 +53,16 @@ timer@41100 {
|
|||
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 {
|
||||
compatible = "fsl,mpic-msi";
|
||||
reg = <0x41600 0x80>;
|
||||
|
|
|
@ -275,9 +275,6 @@ struct mpic
|
|||
unsigned int isu_mask;
|
||||
/* Number of sources */
|
||||
unsigned int num_sources;
|
||||
/* default senses array */
|
||||
unsigned char *senses;
|
||||
unsigned int senses_count;
|
||||
|
||||
/* vector numbers used for internal sources (ipi/timers) */
|
||||
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,
|
||||
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
|
||||
* should be called again for this mpic
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
struct mpic_msgr {
|
||||
u32 __iomem *base;
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
#ifndef __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 */
|
||||
#define MSR_GS (1<<28) /* Guest state */
|
||||
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
|
||||
|
|
|
@ -150,6 +150,9 @@ notrace void __init machine_init(u64 dt_ptr)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_BOOKE_WDT
|
||||
extern u32 booke_wdt_enabled;
|
||||
extern u32 booke_wdt_period;
|
||||
|
||||
/* Checks wdt=x and wdt_period=xx command-line option */
|
||||
notrace int __init early_parse_wdt(char *p)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,12 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
|
|||
{ .compatible = "fsl,qe", },
|
||||
{ .compatible = "fsl,cpm2", },
|
||||
{ .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", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -399,12 +399,6 @@ static int __init board_fixups(void)
|
|||
machine_arch_initcall(mpc8568_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)
|
||||
{
|
||||
if (machine_is(mpc8568_mds))
|
||||
|
@ -412,10 +406,7 @@ static int __init mpc85xx_publish_devices(void)
|
|||
if (machine_is(mpc8569_mds))
|
||||
simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
|
||||
|
||||
mpc85xx_common_publish_devices();
|
||||
of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
|
||||
|
||||
return 0;
|
||||
return mpc85xx_common_publish_devices();
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
|
||||
|
|
|
@ -460,18 +460,7 @@ static void __init p1022_ds_setup_arch(void)
|
|||
pr_info("Freescale P1022 DS reference board\n");
|
||||
}
|
||||
|
||||
static struct of_device_id __initdata p1022_ds_ids[] = {
|
||||
/* 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_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
|
||||
|
||||
machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
|
||||
|
||||
|
|
|
@ -366,11 +366,20 @@ static void kw_i2c_timeout(unsigned long data)
|
|||
unsigned long 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));
|
||||
if (host->state != state_idle) {
|
||||
host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
|
||||
add_timer(&host->timeout_timer);
|
||||
}
|
||||
skip:
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -1076,7 +1076,7 @@ static void eeh_add_device_late(struct pci_dev *dev)
|
|||
pr_debug("EEH: Adding device %s\n", pci_name(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) {
|
||||
pr_debug("EEH: Already referenced !\n");
|
||||
return;
|
||||
|
|
|
@ -604,18 +604,14 @@ static struct mpic *mpic_find(unsigned int irq)
|
|||
}
|
||||
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
|
@ -876,21 +872,45 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
|||
if (src >= mpic->num_sources)
|
||||
return -EINVAL;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
if (mpic->senses && src < mpic->senses_count)
|
||||
flow_type = mpic->senses[src];
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Apply to HW */
|
||||
if (mpic_is_ht_interrupt(mpic, src))
|
||||
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
|
||||
MPIC_VECPRI_SENSE_EDGE;
|
||||
else
|
||||
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) |
|
||||
MPIC_INFO(VECPRI_SENSE_MASK));
|
||||
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);
|
||||
|
||||
/* 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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i, cpu;
|
||||
|
@ -1555,12 +1569,12 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
|
|||
return;
|
||||
|
||||
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]) &
|
||||
~MPIC_VECPRI_PRIORITY_MASK;
|
||||
mpic_ipi_write(src - mpic->ipi_vecs[0],
|
||||
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]) &
|
||||
~MPIC_VECPRI_PRIORITY_MASK;
|
||||
mpic_tm_write(src - mpic->timer_vecs[0],
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
static struct mpic_msgr **mpic_msgrs;
|
||||
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)
|
||||
{
|
||||
|
@ -56,12 +57,11 @@ struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
|
|||
if (reg_num >= mpic_msgr_count)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
raw_spin_lock_irqsave(&msgr->lock, flags);
|
||||
if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) {
|
||||
msgr = mpic_msgrs[reg_num];
|
||||
raw_spin_lock_irqsave(&msgrs_lock, flags);
|
||||
msgr = mpic_msgrs[reg_num];
|
||||
if (msgr->in_use == MSGR_FREE)
|
||||
msgr->in_use = MSGR_INUSE;
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&msgr->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&msgrs_lock, flags);
|
||||
|
||||
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;
|
||||
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->num = i;
|
||||
raw_spin_lock_init(&msgr->lock);
|
||||
|
|
|
@ -49,6 +49,12 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
|
|||
* IRQ_TYPE_LEVEL_LOW - low level triggered
|
||||
* IRQ_TYPE_LEVEL_MASK - Mask to filter out the level 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
|
||||
*
|
||||
* 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_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
|
||||
IRQ_TYPE_SENSE_MASK = 0x0000000f,
|
||||
IRQ_TYPE_DEFAULT = IRQ_TYPE_SENSE_MASK,
|
||||
|
||||
IRQ_TYPE_PROBE = 0x00000010,
|
||||
|
||||
|
|
Loading…
Reference in a new issue