cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fsl_mpic_err.c (3488B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2012 Freescale Semiconductor, Inc.
      4 *
      5 * Author: Varun Sethi <varun.sethi@freescale.com>
      6 */
      7
      8#include <linux/irq.h>
      9#include <linux/smp.h>
     10#include <linux/interrupt.h>
     11#include <linux/irqdomain.h>
     12
     13#include <asm/io.h>
     14#include <asm/irq.h>
     15#include <asm/mpic.h>
     16
     17#include "mpic.h"
     18
     19#define MPIC_ERR_INT_BASE	0x3900
     20#define MPIC_ERR_INT_EISR	0x0000
     21#define MPIC_ERR_INT_EIMR	0x0010
     22
     23static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int err_reg)
     24{
     25	return in_be32(base + (err_reg >> 2));
     26}
     27
     28static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value)
     29{
     30	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value);
     31}
     32
     33static void fsl_mpic_mask_err(struct irq_data *d)
     34{
     35	u32 eimr;
     36	struct mpic *mpic = irq_data_get_irq_chip_data(d);
     37	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
     38
     39	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
     40	eimr |= (1 << (31 - src));
     41	mpic_fsl_err_write(mpic->err_regs, eimr);
     42}
     43
     44static void fsl_mpic_unmask_err(struct irq_data *d)
     45{
     46	u32 eimr;
     47	struct mpic *mpic = irq_data_get_irq_chip_data(d);
     48	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
     49
     50	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
     51	eimr &= ~(1 << (31 - src));
     52	mpic_fsl_err_write(mpic->err_regs, eimr);
     53}
     54
     55static struct irq_chip fsl_mpic_err_chip = {
     56	.irq_disable	= fsl_mpic_mask_err,
     57	.irq_mask	= fsl_mpic_mask_err,
     58	.irq_unmask	= fsl_mpic_unmask_err,
     59};
     60
     61int __init mpic_setup_error_int(struct mpic *mpic, int intvec)
     62{
     63	int i;
     64
     65	mpic->err_regs = ioremap(mpic->paddr + MPIC_ERR_INT_BASE, 0x1000);
     66	if (!mpic->err_regs) {
     67		pr_err("could not map mpic error registers\n");
     68		return -ENOMEM;
     69	}
     70	mpic->hc_err = fsl_mpic_err_chip;
     71	mpic->hc_err.name = mpic->name;
     72	mpic->flags |= MPIC_FSL_HAS_EIMR;
     73	/* allocate interrupt vectors for error interrupts */
     74	for (i = MPIC_MAX_ERR - 1; i >= 0; i--)
     75		mpic->err_int_vecs[i] = intvec--;
     76
     77	return 0;
     78}
     79
     80int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
     81{
     82	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
     83	    (hw >= mpic->err_int_vecs[0] &&
     84	     hw <= mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
     85		WARN_ON(mpic->flags & MPIC_SECONDARY);
     86
     87		pr_debug("mpic: mapping as Error Interrupt\n");
     88		irq_set_chip_data(virq, mpic);
     89		irq_set_chip_and_handler(virq, &mpic->hc_err,
     90					 handle_level_irq);
     91		return 1;
     92	}
     93
     94	return 0;
     95}
     96
     97static irqreturn_t fsl_error_int_handler(int irq, void *data)
     98{
     99	struct mpic *mpic = (struct mpic *) data;
    100	u32 eisr, eimr;
    101	int errint;
    102
    103	eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
    104	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
    105
    106	if (!(eisr & ~eimr))
    107		return IRQ_NONE;
    108
    109	while (eisr) {
    110		int ret;
    111		errint = __builtin_clz(eisr);
    112		ret = generic_handle_domain_irq(mpic->irqhost,
    113						mpic->err_int_vecs[errint]);
    114		if (WARN_ON(ret)) {
    115			eimr |=  1 << (31 - errint);
    116			mpic_fsl_err_write(mpic->err_regs, eimr);
    117		}
    118		eisr &= ~(1 << (31 - errint));
    119	}
    120
    121	return IRQ_HANDLED;
    122}
    123
    124void __init mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
    125{
    126	unsigned int virq;
    127	int ret;
    128
    129	virq = irq_create_mapping(mpic->irqhost, irqnum);
    130	if (!virq) {
    131		pr_err("Error interrupt setup failed\n");
    132		return;
    133	}
    134
    135	/* Mask all error interrupts */
    136	mpic_fsl_err_write(mpic->err_regs, ~0);
    137
    138	ret = request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
    139		    "mpic-error-int", mpic);
    140	if (ret)
    141		pr_err("Failed to register error interrupt handler\n");
    142}