Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Amstrad E3 FIQ handling
0004  *
0005  *  Copyright (C) 2009 Janusz Krzysztofik
0006  *  Copyright (c) 2006 Matt Callow
0007  *  Copyright (c) 2004 Amstrad Plc
0008  *  Copyright (C) 2001 RidgeRun, Inc.
0009  *
0010  * Parts of this code are taken from linux/arch/arm/mach-omap/irq.c
0011  * in the MontaVista 2.4 kernel (and the Amstrad changes therein)
0012  */
0013 #include <linux/gpio/consumer.h>
0014 #include <linux/gpio/machine.h>
0015 #include <linux/gpio/driver.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/irq.h>
0018 #include <linux/module.h>
0019 #include <linux/io.h>
0020 #include <linux/platform_data/ams-delta-fiq.h>
0021 #include <linux/platform_device.h>
0022 
0023 #include <asm/fiq.h>
0024 #include <linux/soc/ti/omap1-io.h>
0025 
0026 #include "hardware.h"
0027 #include "ams-delta-fiq.h"
0028 #include "board-ams-delta.h"
0029 
0030 static struct fiq_handler fh = {
0031     .name   = "ams-delta-fiq"
0032 };
0033 
0034 /*
0035  * This buffer is shared between FIQ and IRQ contexts.
0036  * The FIQ and IRQ isrs can both read and write it.
0037  * It is structured as a header section several 32bit slots,
0038  * followed by the circular buffer where the FIQ isr stores
0039  * keystrokes received from the qwerty keyboard.  See
0040  * <linux/platform_data/ams-delta-fiq.h> for details of offsets.
0041  */
0042 static unsigned int fiq_buffer[1024];
0043 
0044 static struct irq_chip *irq_chip;
0045 static struct irq_data *irq_data[16];
0046 static unsigned int irq_counter[16];
0047 
0048 static const char *pin_name[16] __initconst = {
0049     [AMS_DELTA_GPIO_PIN_KEYBRD_DATA]    = "keybrd_data",
0050     [AMS_DELTA_GPIO_PIN_KEYBRD_CLK]     = "keybrd_clk",
0051 };
0052 
0053 static irqreturn_t deferred_fiq(int irq, void *dev_id)
0054 {
0055     struct irq_data *d;
0056     int gpio, irq_num, fiq_count;
0057 
0058     /*
0059      * For each handled GPIO interrupt, keep calling its interrupt handler
0060      * until the IRQ counter catches the FIQ incremented interrupt counter.
0061      */
0062     for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
0063             gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
0064         d = irq_data[gpio];
0065         irq_num = d->irq;
0066         fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];
0067 
0068         if (irq_counter[gpio] < fiq_count &&
0069                 gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
0070             /*
0071              * handle_simple_irq() that OMAP GPIO edge
0072              * interrupts default to since commit 80ac93c27441
0073              * requires interrupt already acked and unmasked.
0074              */
0075             if (!WARN_ON_ONCE(!irq_chip->irq_unmask))
0076                 irq_chip->irq_unmask(d);
0077         }
0078         for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
0079             generic_handle_irq(irq_num);
0080     }
0081     return IRQ_HANDLED;
0082 }
0083 
0084 void __init ams_delta_init_fiq(struct gpio_chip *chip,
0085                    struct platform_device *serio)
0086 {
0087     struct gpio_desc *gpiod, *data = NULL, *clk = NULL;
0088     void *fiqhandler_start;
0089     unsigned int fiqhandler_length;
0090     struct pt_regs FIQ_regs;
0091     unsigned long val, offset;
0092     int i, retval;
0093 
0094     /* Store irq_chip location for IRQ handler use */
0095     irq_chip = chip->irq.chip;
0096     if (!irq_chip) {
0097         pr_err("%s: GPIO chip %s is missing IRQ function\n", __func__,
0098                chip->label);
0099         return;
0100     }
0101 
0102     for (i = 0; i < ARRAY_SIZE(irq_data); i++) {
0103         gpiod = gpiochip_request_own_desc(chip, i, pin_name[i],
0104                           GPIO_ACTIVE_HIGH, GPIOD_IN);
0105         if (IS_ERR(gpiod)) {
0106             pr_err("%s: failed to get GPIO pin %d (%ld)\n",
0107                    __func__, i, PTR_ERR(gpiod));
0108             return;
0109         }
0110         /* Store irq_data location for IRQ handler use */
0111         irq_data[i] = irq_get_irq_data(gpiod_to_irq(gpiod));
0112 
0113         /*
0114          * FIQ handler takes full control over serio data and clk GPIO
0115          * pins.  Initialize them and keep requested so nobody can
0116          * interfere.  Fail if any of those two couldn't be requested.
0117          */
0118         switch (i) {
0119         case AMS_DELTA_GPIO_PIN_KEYBRD_DATA:
0120             data = gpiod;
0121             gpiod_direction_input(data);
0122             break;
0123         case AMS_DELTA_GPIO_PIN_KEYBRD_CLK:
0124             clk = gpiod;
0125             gpiod_direction_input(clk);
0126             break;
0127         default:
0128             gpiochip_free_own_desc(gpiod);
0129             break;
0130         }
0131     }
0132     if (!data || !clk)
0133         goto out_gpio;
0134 
0135     fiqhandler_start = &qwerty_fiqin_start;
0136     fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
0137     pr_info("Installing fiq handler from %p, length 0x%x\n",
0138             fiqhandler_start, fiqhandler_length);
0139 
0140     retval = claim_fiq(&fh);
0141     if (retval) {
0142         pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
0143                 retval);
0144         goto out_gpio;
0145     }
0146 
0147     retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
0148             IRQ_TYPE_EDGE_RISING, "deferred_fiq", NULL);
0149     if (retval < 0) {
0150         pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
0151         release_fiq(&fh);
0152         goto out_gpio;
0153     }
0154     /*
0155      * Since no set_type() method is provided by OMAP irq chip,
0156      * switch to edge triggered interrupt type manually.
0157      */
0158     offset = IRQ_ILR0_REG_OFFSET +
0159             ((INT_DEFERRED_FIQ - NR_IRQS_LEGACY) & 0x1f) * 0x4;
0160     val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
0161     omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);
0162 
0163     set_fiq_handler(fiqhandler_start, fiqhandler_length);
0164 
0165     /*
0166      * Initialise the buffer which is shared
0167      * between FIQ mode and IRQ mode
0168      */
0169     fiq_buffer[FIQ_GPIO_INT_MASK]   = 0;
0170     fiq_buffer[FIQ_MASK]        = 0;
0171     fiq_buffer[FIQ_STATE]       = 0;
0172     fiq_buffer[FIQ_KEY]     = 0;
0173     fiq_buffer[FIQ_KEYS_CNT]    = 0;
0174     fiq_buffer[FIQ_KEYS_HICNT]  = 0;
0175     fiq_buffer[FIQ_TAIL_OFFSET] = 0;
0176     fiq_buffer[FIQ_HEAD_OFFSET] = 0;
0177     fiq_buffer[FIQ_BUF_LEN]     = 256;
0178     fiq_buffer[FIQ_MISSED_KEYS] = 0;
0179     fiq_buffer[FIQ_BUFFER_START]    =
0180             (unsigned int) &fiq_buffer[FIQ_CIRC_BUFF];
0181 
0182     for (i = FIQ_CNT_INT_00; i <= FIQ_CNT_INT_15; i++)
0183         fiq_buffer[i] = 0;
0184 
0185     /*
0186      * FIQ mode r9 always points to the fiq_buffer, because the FIQ isr
0187      * will run in an unpredictable context. The fiq_buffer is the FIQ isr's
0188      * only means of communication with the IRQ level and other kernel
0189      * context code.
0190      */
0191     FIQ_regs.ARM_r9 = (unsigned int)fiq_buffer;
0192     set_fiq_regs(&FIQ_regs);
0193 
0194     pr_info("request_fiq(): fiq_buffer = %p\n", fiq_buffer);
0195 
0196     /*
0197      * Redirect GPIO interrupts to FIQ
0198      */
0199     offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
0200     val = omap_readl(OMAP_IH1_BASE + offset) | 1;
0201     omap_writel(val, OMAP_IH1_BASE + offset);
0202 
0203     /* Initialize serio device IRQ resource and platform_data */
0204     serio->resource[0].start = gpiod_to_irq(clk);
0205     serio->resource[0].end = serio->resource[0].start;
0206     serio->dev.platform_data = fiq_buffer;
0207 
0208     /*
0209      * Since FIQ handler performs handling of GPIO registers for
0210      * "keybrd_clk" IRQ pin, ams_delta_serio driver used to set
0211      * handle_simple_irq() as active IRQ handler for that pin to avoid
0212      * bad interaction with gpio-omap driver.  This is no longer needed
0213      * as handle_simple_irq() is now the default handler for OMAP GPIO
0214      * edge interrupts.
0215      * This comment replaces the obsolete code which has been removed
0216      * from the ams_delta_serio driver and stands here only as a reminder
0217      * of that dependency on gpio-omap driver behavior.
0218      */
0219 
0220     return;
0221 
0222 out_gpio:
0223     if (data)
0224         gpiochip_free_own_desc(data);
0225     if (clk)
0226         gpiochip_free_own_desc(clk);
0227 }