linux/drivers/irqchip/irq-or1k-pic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
   4 * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi>
   5 */
   6
   7#include <linux/irq.h>
   8#include <linux/irqchip.h>
   9#include <linux/of.h>
  10#include <linux/of_irq.h>
  11#include <linux/of_address.h>
  12
  13/* OR1K PIC implementation */
  14
  15struct or1k_pic_dev {
  16        struct irq_chip chip;
  17        irq_flow_handler_t handle;
  18        unsigned long flags;
  19};
  20
  21/*
  22 * We're a couple of cycles faster than the generic implementations with
  23 * these 'fast' versions.
  24 */
  25
  26static void or1k_pic_mask(struct irq_data *data)
  27{
  28        mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
  29}
  30
  31static void or1k_pic_unmask(struct irq_data *data)
  32{
  33        mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
  34}
  35
  36static void or1k_pic_ack(struct irq_data *data)
  37{
  38        mtspr(SPR_PICSR, (1UL << data->hwirq));
  39}
  40
  41static void or1k_pic_mask_ack(struct irq_data *data)
  42{
  43        mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
  44        mtspr(SPR_PICSR, (1UL << data->hwirq));
  45}
  46
  47/*
  48 * There are two oddities with the OR1200 PIC implementation:
  49 * i)  LEVEL-triggered interrupts are latched and need to be cleared
  50 * ii) the interrupt latch is cleared by writing a 0 to the bit,
  51 *     as opposed to a 1 as mandated by the spec
  52 */
  53static void or1k_pic_or1200_ack(struct irq_data *data)
  54{
  55        mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
  56}
  57
  58static void or1k_pic_or1200_mask_ack(struct irq_data *data)
  59{
  60        mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
  61        mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
  62}
  63
  64static struct or1k_pic_dev or1k_pic_level = {
  65        .chip = {
  66                .name = "or1k-PIC-level",
  67                .irq_unmask = or1k_pic_unmask,
  68                .irq_mask = or1k_pic_mask,
  69                .irq_mask_ack = or1k_pic_mask_ack,
  70        },
  71        .handle = handle_level_irq,
  72        .flags = IRQ_LEVEL | IRQ_NOPROBE,
  73};
  74
  75static struct or1k_pic_dev or1k_pic_edge = {
  76        .chip = {
  77                .name = "or1k-PIC-edge",
  78                .irq_unmask = or1k_pic_unmask,
  79                .irq_mask = or1k_pic_mask,
  80                .irq_ack = or1k_pic_ack,
  81                .irq_mask_ack = or1k_pic_mask_ack,
  82        },
  83        .handle = handle_edge_irq,
  84        .flags = IRQ_LEVEL | IRQ_NOPROBE,
  85};
  86
  87static struct or1k_pic_dev or1k_pic_or1200 = {
  88        .chip = {
  89                .name = "or1200-PIC",
  90                .irq_unmask = or1k_pic_unmask,
  91                .irq_mask = or1k_pic_mask,
  92                .irq_ack = or1k_pic_or1200_ack,
  93                .irq_mask_ack = or1k_pic_or1200_mask_ack,
  94        },
  95        .handle = handle_level_irq,
  96        .flags = IRQ_LEVEL | IRQ_NOPROBE,
  97};
  98
  99static struct irq_domain *root_domain;
 100
 101static inline int pic_get_irq(int first)
 102{
 103        int hwirq;
 104
 105        hwirq = ffs(mfspr(SPR_PICSR) >> first);
 106        if (!hwirq)
 107                return NO_IRQ;
 108        else
 109                hwirq = hwirq + first - 1;
 110
 111        return hwirq;
 112}
 113
 114static void or1k_pic_handle_irq(struct pt_regs *regs)
 115{
 116        int irq = -1;
 117
 118        while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
 119                handle_domain_irq(root_domain, irq, regs);
 120}
 121
 122static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 123{
 124        struct or1k_pic_dev *pic = d->host_data;
 125
 126        irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
 127        irq_set_status_flags(irq, pic->flags);
 128
 129        return 0;
 130}
 131
 132static const struct irq_domain_ops or1k_irq_domain_ops = {
 133        .xlate = irq_domain_xlate_onecell,
 134        .map = or1k_map,
 135};
 136
 137/*
 138 * This sets up the IRQ domain for the PIC built in to the OpenRISC
 139 * 1000 CPU.  This is the "root" domain as these are the interrupts
 140 * that directly trigger an exception in the CPU.
 141 */
 142static int __init or1k_pic_init(struct device_node *node,
 143                                 struct or1k_pic_dev *pic)
 144{
 145        /* Disable all interrupts until explicitly requested */
 146        mtspr(SPR_PICMR, (0UL));
 147
 148        root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
 149                                            pic);
 150
 151        set_handle_irq(or1k_pic_handle_irq);
 152
 153        return 0;
 154}
 155
 156static int __init or1k_pic_or1200_init(struct device_node *node,
 157                                       struct device_node *parent)
 158{
 159        return or1k_pic_init(node, &or1k_pic_or1200);
 160}
 161IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic", or1k_pic_or1200_init);
 162IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic", or1k_pic_or1200_init);
 163
 164static int __init or1k_pic_level_init(struct device_node *node,
 165                                      struct device_node *parent)
 166{
 167        return or1k_pic_init(node, &or1k_pic_level);
 168}
 169IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level",
 170                or1k_pic_level_init);
 171
 172static int __init or1k_pic_edge_init(struct device_node *node,
 173                                     struct device_node *parent)
 174{
 175        return or1k_pic_init(node, &or1k_pic_edge);
 176}
 177IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge", or1k_pic_edge_init);
 178