int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
	unsigned int src = virq_to_hw(d->irq);
	unsigned int vecpri, vold, vnew, prio, cpu_dest;
	unsigned long flags;

	if (flow_type == IRQ_TYPE_NONE)
		flow_type = IRQ_TYPE_LEVEL_LOW;

	irqd_set_trigger_type(d, flow_type);

	vecpri = ehv_pic_type_to_vecpri(flow_type);

	spin_lock_irqsave(&ehv_pic_lock, flags);
	ev_int_get_config(src, &vold, &prio, &cpu_dest);
	vnew = vold & ~(EHV_PIC_INFO(VECPRI_POLARITY_MASK) |
			EHV_PIC_INFO(VECPRI_SENSE_MASK));
	vnew |= vecpri;

	/*
	 * TODO : Add specific interface call for platform to set
	 * individual interrupt priorities.
	 * platform currently using static/default priority for all ints
	 */

	prio = 8;

	ev_int_set_config(src, vecpri, prio, cpu_dest);

	spin_unlock_irqrestore(&ehv_pic_lock, flags);
	return IRQ_SET_MASK_OK_NOCOPY;
}
Пример #2
0
static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id)
{
	struct pseries_errorlog *pseries_log;
	struct pseries_hp_errorlog *hp_elog;

	spin_lock(&ras_log_buf_lock);

	rtas_call(ras_check_exception_token, 6, 1, NULL,
		  RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
		  RTAS_HOTPLUG_EVENTS, 0, __pa(&ras_log_buf),
		  rtas_get_error_log_max());

	pseries_log = get_pseries_errorlog((struct rtas_error_log *)ras_log_buf,
					   PSERIES_ELOG_SECT_ID_HOTPLUG);
	hp_elog = (struct pseries_hp_errorlog *)pseries_log->data;

	/*
	 * Since PCI hotplug is not currently supported on pseries, put PCI
	 * hotplug events on the ras_log_buf to be handled by rtas_errd.
	 */
	if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM ||
	    hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU ||
	    hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_PMEM)
		queue_hotplug_event(hp_elog);
	else
		log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);

	spin_unlock(&ras_log_buf_lock);
	return IRQ_HANDLED;
}
Пример #3
0
int ps3_connect_event_irq(const struct ps3_device_id *did,
	unsigned int interrupt_id, unsigned int *virq)
{
	int result;

	result = ps3_alloc_event_irq(virq);

	if (result)
		return result;

	result = lv1_connect_interrupt_event_receive_port(did->bus_id,
		did->dev_id, virq_to_hw(*virq), interrupt_id);

	if (result) {
		pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
			" failed: %s\n", __func__, __LINE__,
			ps3_result(result));
		ps3_free_event_irq(*virq);
		*virq = NO_IRQ;
		return result;
	}

	pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
		interrupt_id, *virq);

	return 0;
}
Пример #4
0
int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
	unsigned int virq)
{
	/*                                */

	int result;

	DBG(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
		dev->interrupt_id, virq);

	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);

	if (result)
		FAIL("%s:%d: lv1_disconnect_interrupt_event_receive_port"
			" failed: %s\n", __func__, __LINE__,
			ps3_result(result));

	result = ps3_event_receive_port_destroy(virq);
	BUG_ON(result);

	/*
                                                           
                                              
  */

	result = ps3_virq_destroy(virq);
	BUG_ON(result);

	DBG(" <- %s:%d\n", __func__, __LINE__);
	return result;
}
Пример #5
0
int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
	unsigned int virq)
{
	/* this should go in system-bus.c */

	int result;

	pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
		dev->interrupt_id, virq);

	result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
		dev->dev_id, virq_to_hw(virq), dev->interrupt_id);

	if (result)
		pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
			" failed: %s\n", __func__, __LINE__,
			ps3_result(result));

	result = ps3_event_receive_port_destroy(virq);
	BUG_ON(result);

	/*
	 * ps3_event_receive_port_destroy() destroys the IRQ plug,
	 * so don't call ps3_irq_plug_destroy() here.
	 */

	result = ps3_virq_destroy(virq);
	BUG_ON(result);

	pr_debug(" <- %s:%d\n", __func__, __LINE__);
	return result;
}
Пример #6
0
/*
 * The interrupt controller is setup such that it doesn't work well with
 * the level interrupt handler in the kernel because the handler acks the
 * interrupt before calling the application interrupt handler. To deal with
 * that, we use 2 different irq chips so that different functions can be
 * used for level and edge type interrupts.
 *
 * IRQ Chip common (across level and edge) operations
 */
static void xilinx_intc_mask(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void * regs = get_irq_chip_data(virq);
	pr_debug("mask: %d\n", irq);
	out_be32(regs + XINTC_CIE, 1 << irq);
}
Пример #7
0
/* Handle environmental and power warning (EPOW) interrupts. */
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
{
	int status;
	int state;
	int critical;

	status = rtas_get_sensor_fast(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX,
				      &state);

	if (state > 3)
		critical = 1;		/* Time Critical */
	else
		critical = 0;

	spin_lock(&ras_log_buf_lock);

	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
			   RTAS_VECTOR_EXTERNAL_INTERRUPT,
			   virq_to_hw(irq),
			   RTAS_EPOW_WARNING,
			   critical, __pa(&ras_log_buf),
				rtas_get_error_log_max());

	log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);

	rtas_parse_epow_errlog((struct rtas_error_log *)ras_log_buf);

	spin_unlock(&ras_log_buf_lock);
	return IRQ_HANDLED;
}
Пример #8
0
static void xilinx_intc_edge_ack(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void * regs = get_irq_chip_data(virq);
	pr_debug("ack: %d\n", irq);
	out_be32(regs + XINTC_IAR, 1 << irq);
}
Пример #9
0
int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
	enum ps3_cpu_binding cpu, unsigned int *virq)
{
	/* this should go in system-bus.c */

	int result;

	result = ps3_event_receive_port_setup(cpu, virq);

	if (result)
		return result;

	result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
		dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);

	if (result) {
		pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
			" failed: %s\n", __func__, __LINE__,
			ps3_result(result));
		ps3_event_receive_port_destroy(*virq);
		*virq = NO_IRQ;
		return result;
	}

	pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
		dev->interrupt_id, *virq);

	return 0;
}
Пример #10
0
static void flipper_pic_unmask(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void __iomem *io_base = get_irq_chip_data(virq);

	setbits32(io_base + FLIPPER_IMR, 1 << irq);
}
Пример #11
0
static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
{
	unsigned int src = virq_to_hw(virq);
	struct irq_desc *desc = irq_to_desc(virq);
	unsigned int vold, vnew, edibit;

	/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
	 * IRQ_TYPE_EDGE_BOTH (default).  All others are IRQ_TYPE_EDGE_FALLING
	 * or IRQ_TYPE_LEVEL_LOW (default)
	 */
	if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) {
		if (flow_type == IRQ_TYPE_NONE)
			flow_type = IRQ_TYPE_EDGE_BOTH;

		if (flow_type != IRQ_TYPE_EDGE_BOTH &&
		    flow_type != IRQ_TYPE_EDGE_FALLING)
			goto err_sense;
	} else {
		if (flow_type == IRQ_TYPE_NONE)
			flow_type = IRQ_TYPE_LEVEL_LOW;

		if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
			goto err_sense;
	}

	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
		desc->status |= IRQ_LEVEL;
		desc->handle_irq = handle_level_irq;
	} else
		desc->handle_irq = handle_edge_irq;

	/* internal IRQ senses are LEVEL_LOW
	 * EXT IRQ and Port C IRQ senses are programmable
	 */
	if (src >= CPM2_IRQ_EXT1 && src <= CPM2_IRQ_EXT7)
			edibit = (14 - (src - CPM2_IRQ_EXT1));
	else
		if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
			edibit = (31 - (CPM2_IRQ_PORTC0 - src));
		else
			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;

	vold = in_be32(&cpm2_intctl->ic_siexr);

	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING)
		vnew = vold | (1 << edibit);
	else
		vnew = vold & ~(1 << edibit);

	if (vold != vnew)
		out_be32(&cpm2_intctl->ic_siexr, vnew);
	return 0;

err_sense:
	pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
	return -EINVAL;
}
Пример #12
0
static void flipper_pic_ack(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void __iomem *io_base = get_irq_chip_data(virq);

	/* this is at least needed for RSW */
	out_be32(io_base + FLIPPER_ICR, 1 << irq);
}
Пример #13
0
static irqreturn_t opal_interrupt(int irq, void *data)
{
	uint64_t events;

	opal_handle_interrupt(virq_to_hw(irq), &events);

	/* XXX TODO: Do something with the events */

	return IRQ_HANDLED;
}
Пример #14
0
static void flipper_pic_mask_and_ack(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void __iomem *io_base = get_irq_chip_data(virq);
	u32 mask = 1 << irq;

	clrbits32(io_base + FLIPPER_IMR, mask);
	/* this is at least needed for RSW */
	out_be32(io_base + FLIPPER_ICR, mask);
}
Пример #15
0
static irqreturn_t opal_interrupt(int irq, void *data)
{
	__be64 events;

	opal_handle_interrupt(virq_to_hw(irq), &events);

	opal_do_notifier(events);

	return IRQ_HANDLED;
}
Пример #16
0
static void cpm2_ack(unsigned int virq)
{
	int	bit, word;
	unsigned int irq_nr = virq_to_hw(virq);

	bit = irq_to_siubit[irq_nr];
	word = irq_to_siureg[irq_nr];

	out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
}
Пример #17
0
static irqreturn_t opal_interrupt(int irq, void *data)
{
	__be64 events;

	opal_handle_interrupt(virq_to_hw(irq), &events);
	last_outstanding_events = be64_to_cpu(events);
	if (opal_have_pending_events())
		opal_wake_poller();

	return IRQ_HANDLED;
}
Пример #18
0
static void cpm2_unmask_irq(unsigned int virq)
{
	int	bit, word;
	unsigned int irq_nr = virq_to_hw(virq);

	bit = irq_to_siubit[irq_nr];
	word = irq_to_siureg[irq_nr];

	ppc_cached_irq_mask[word] |= 1 << bit;
	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
}
Пример #19
0
/*
 * IRQ Chip level operations
 */
static void xilinx_intc_level_unmask(unsigned int virq)
{
	int irq = virq_to_hw(virq);
	void * regs = get_irq_chip_data(virq);
	pr_debug("unmask: %d\n", irq);
	out_be32(regs + XINTC_SIE, 1 << irq);

	/* ack level irqs because they can't be acked during
	 * ack function since the handle_level_irq function
	 * acks the irq before calling the inerrupt handler
	 */
	out_be32(regs + XINTC_IAR, 1 << irq);
}
static void pq2ads_pci_unmask_irq(unsigned int virq)
{
	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
	int irq = NUM_IRQS - virq_to_hw(virq) - 1;

	if (irq != -1) {
		unsigned long flags;

		spin_lock_irqsave(&pci_pic_lock, flags);
		clrbits32(&priv->regs->mask, 1 << irq);
		spin_unlock_irqrestore(&pci_pic_lock, flags);
	}
}
Пример #21
0
int ps3_free_io_irq(unsigned int virq)
{
	int result;

	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));

	if (result)
		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
			__func__, __LINE__, ps3_result(result));

	irq_dispose_mapping(virq);

	return result;
}
int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest,
			 bool force)
{
	unsigned int src = virq_to_hw(d->irq);
	unsigned int config, prio, cpu_dest;
	int cpuid = irq_choose_cpu(dest);
	unsigned long flags;

	spin_lock_irqsave(&ehv_pic_lock, flags);
	ev_int_get_config(src, &config, &prio, &cpu_dest);
	ev_int_set_config(src, config, prio, cpuid);
	spin_unlock_irqrestore(&ehv_pic_lock, flags);

	return IRQ_SET_MASK_OK;
}
Пример #23
0
int ps3_io_irq_destroy(unsigned int virq)
{
	int result;

	result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));

	if (result)
		pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
			__func__, __LINE__, ps3_result(result));

	result = ps3_irq_plug_destroy(virq);
	BUG_ON(result);

	return result;
}
Пример #24
0
int ps3_free_event_irq(unsigned int virq)
{
	int result;

	pr_debug(" -> %s:%d\n", __func__, __LINE__);

	result = lv1_destruct_event_receive_port(virq_to_hw(virq));

	if (result)
		pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
			__func__, __LINE__, ps3_result(result));

	irq_dispose_mapping(virq);

	pr_debug(" <- %s:%d\n", __func__, __LINE__);
	return result;
}
Пример #25
0
static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
{
    unsigned int src = virq_to_hw(virq);
    struct irq_desc *desc = get_irq_desc(virq);
    unsigned int vold, vnew, edibit;

    if (flow_type == IRQ_TYPE_NONE)
        flow_type = IRQ_TYPE_LEVEL_LOW;

    if (flow_type & IRQ_TYPE_EDGE_RISING) {
        printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n",
            flow_type);
        return -EINVAL;
    }

    desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
    desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
    if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
        desc->status |= IRQ_LEVEL;
        desc->handle_irq = handle_level_irq;
    } else
        desc->handle_irq = handle_edge_irq;

    /* internal IRQ senses are LEVEL_LOW
     * EXT IRQ and Port C IRQ senses are programmable
     */
    if (src >= CPM2_IRQ_EXT1 && src <= CPM2_IRQ_EXT7)
            edibit = (14 - (src - CPM2_IRQ_EXT1));
    else
        if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
            edibit = (31 - (src - CPM2_IRQ_PORTC15));
        else
            return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;

    vold = in_be32(&cpm2_intctl->ic_siexr);

    if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING)
        vnew = vold | (1 << edibit);
    else
        vnew = vold & ~(1 << edibit);

    if (vold != vnew)
        out_be32(&cpm2_intctl->ic_siexr, vnew);
    return 0;
}
Пример #26
0
static int ics_rtas_map(struct ics *ics, unsigned int virq)
{
	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
	int status[2];
	int rc;

	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
		return -EINVAL;

	/* Check if RTAS knows about this interrupt */
	rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq);
	if (rc)
		return -ENXIO;

	irq_set_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq);
	irq_set_chip_data(virq, &ics_rtas);

	return 0;
}
Пример #27
0
static void cpm2_end_irq(unsigned int virq)
{
	struct irq_desc *desc;
	int	bit, word;
	unsigned int irq_nr = virq_to_hw(virq);

	desc = irq_to_desc(irq_nr);
	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
			&& desc->action) {

		bit = irq_to_siubit[irq_nr];
		word = irq_to_siureg[irq_nr];

		ppc_cached_irq_mask[word] |= 1 << bit;
		out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);

		mb();
	}
}
Пример #28
0
static int ics_opal_map(struct ics *ics, unsigned int virq)
{
	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
	int64_t rc;
	int16_t server;
	int8_t priority;

	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
		return -EINVAL;

	
	rc = opal_get_xive(hw_irq, &server, &priority);
	if (rc != OPAL_SUCCESS)
		return -ENXIO;

	irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
	irq_set_chip_data(virq, &ics_hal);

	return 0;
}
Пример #29
0
static void cpm2_end_irq(unsigned int virq)
{
    int    bit, word;
    unsigned int irq_nr = virq_to_hw(virq);

    if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
            && irq_desc[irq_nr].action) {

        bit = irq_to_siubit[irq_nr];
        word = irq_to_siureg[irq_nr];

        ppc_cached_irq_mask[word] |= 1 << bit;
        out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);

        /*
         * Work around large numbers of spurious IRQs on PowerPC 82xx
         * systems.
         */
        mb();
    }
}
Пример #30
0
int ps3_disconnect_event_irq(const struct ps3_device_id *did,
	unsigned int interrupt_id, unsigned int virq)
{
	int result;

	pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
		interrupt_id, virq);

	result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
		did->dev_id, virq_to_hw(virq), interrupt_id);

	if (result)
		pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
			" failed: %s\n", __func__, __LINE__,
			ps3_result(result));

	ps3_free_event_irq(virq);

	pr_debug(" <- %s:%d\n", __func__, __LINE__);
	return result;
}