diff options
Diffstat (limited to 'package/lqtapi/src/mps/mps-irq.c')
-rw-r--r-- | package/lqtapi/src/mps/mps-irq.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/package/lqtapi/src/mps/mps-irq.c b/package/lqtapi/src/mps/mps-irq.c new file mode 100644 index 0000000..8da0c00 --- /dev/null +++ b/package/lqtapi/src/mps/mps-irq.c @@ -0,0 +1,157 @@ +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> +#include <ifxmips_irq.h> + +#include "mps.h" +#include "mps-irq.h" + +#define MPS_REG_AD0_IRQ_BASE 0x40 +#define MPS_REG_AD1_IRQ_BASE 0x44 + +#define MPS_REG_AD_IRQ_STATUS 0x00 +#define MPS_REG_AD_IRQ_SET 0x08 +#define MPS_REG_AD_IRQ_CLEAR 0x10 +#define MPS_REG_AD_IRQ_ENABLE 0x18 + +struct mps_irq_desc +{ + void __iomem *base; + unsigned int irq_base; +}; + +static inline unsigned int mps_irq_bit(struct mps_irq_desc *mps_desc, int irq) +{ + return BIT(irq - mps_desc->irq_base); +} + +static void mps_irq_ack(unsigned int irq) +{ + struct mps_irq_desc *mps_desc = get_irq_chip_data(irq); + + __raw_writel(mps_irq_bit(mps_desc, irq), + mps_desc->base + MPS_REG_AD_IRQ_CLEAR); +} + +static void mps_irq_mask(unsigned int irq) +{ + struct mps_irq_desc *mps_desc = get_irq_chip_data(irq); + uint32_t mask; + + mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE); + mask &= ~mps_irq_bit(mps_desc, irq); + __raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE); +} + +static void mps_irq_unmask(unsigned int irq) +{ + struct mps_irq_desc *mps_desc = get_irq_chip_data(irq); + uint32_t mask; + + mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE); + mask |= mps_irq_bit(mps_desc, irq) | 0xffff; + __raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE); +} + +static struct irq_chip mps_irq_chip = { + .name = "mps", + .ack = mps_irq_ack, + .mask = mps_irq_mask, + .unmask = mps_irq_unmask, +}; + +static void mps_irq_demux_handler(unsigned int irq, struct irq_desc *desc) +{ + struct mps_irq_desc *mps_desc = get_irq_data(irq); + uint32_t val; + int mps_irq; + + desc->chip->mask(irq); + + val = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_STATUS); + mps_irq = ffs(val); + +/* printk("irq: %d %x\n", mps_irq, val);*/ + + if (mps_irq > 16) + printk("PANIC!\n"); + + if (mps_irq) + generic_handle_irq(mps_irq + mps_desc->irq_base - 1); + + desc->chip->ack(irq); + desc->chip->unmask(irq); +} + +#if 0 + +static const uint32_t ring_msg[] = { +0x01010004, 0x00030000, +}; + +static irqreturn_t mps_irq_ad0(int irq, void *devid) +{ + struct mps *mps = devid; + uint32_t val; + + val = __raw_readl(mps->base + MPS_REG_AD0_IRQ_STATUS); + printk("WOHO ein IRQ: %x\n", val); + __raw_writel(val, mps->base + MPS_REG_AD0_IRQ_CLEAR); + + if (val & BIT(MPS_IRQ_DOWNLOAD_DONE)) + complete(&mps->init_completion); + + if (val & BIT(MPS_IRQ_EVENT)) + mps_fifo_in(&mps->mbox_cmd.downstream, ring_msg, ARRAY_SIZE(ring_msg)); + + return IRQ_HANDLED; +} +#endif + +#define MPS_NUM_AD_IRQS 32 + +struct mps_irq_desc mps_irq_descs[2]; + +int mps_irq_init(struct mps *mps) +{ + int ret = 0; + int irq; + + mps_irq_descs[0].base = mps->base + MPS_REG_AD0_IRQ_BASE; + mps_irq_descs[0].irq_base = mps->irq_base; + mps_irq_descs[1].base = mps->base + MPS_REG_AD1_IRQ_BASE; + mps_irq_descs[1].irq_base = mps->irq_base + 16; + + + set_irq_data(mps->irq_ad0, &mps_irq_descs[0]); + set_irq_chained_handler(mps->irq_ad0, mps_irq_demux_handler); + set_irq_data(mps->irq_ad1, &mps_irq_descs[1]); + set_irq_chained_handler(mps->irq_ad1, mps_irq_demux_handler); + +/* + ret = request_irq(mps->irq_ad0, mps_irq_demux_handler, IRQF_DISABLED, + "mps ad0", &mps_irq_descs[0]); + ret = request_irq(mps->irq_ad1, mps_irq_demux_handler, IRQF_DISABLED, + "mps ad0", &mps_irq_descs[1]); +*/ + for (irq = 0; irq < MPS_NUM_AD_IRQS; ++irq) { + set_irq_chip_data(irq + mps->irq_base, &mps_irq_descs[irq / 16]); + set_irq_chip_and_handler(irq + mps->irq_base, &mps_irq_chip, handle_level_irq); + } + + +/* + res = request_irq(INT_NUM_IM4_IRL18, mps_irq_ad0, IRQF_DISABLED, + "mps ad0", mps); + + irqs = BIT(MPS_IRQ_CMD_UPSTREAM) | BIT(MPS_IRQ_DATA_UPSTREAM) + | BIT(MPS_IRQ_DOWNLOAD_DONE) | BIT(MPS_IRQ_EVENT) | BIT(MPS_IRQ_CMD_ERROR); + + __raw_writel(irqs, mps->base + MPS_REG_AD0_IRQ_ENA); +*/ + return ret; +} + +void mps_irq_exit(struct mps *mps) +{ + free_irq(INT_NUM_IM4_IRL18, mps); +} |