^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for NEC VR4100 series General-purpose I/O Unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2002 MontaVista Software Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Yoichi Yuasa <source@mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/vr41xx/giu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/vr41xx/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/vr41xx/vr41xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define GIUIOSELL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define GIUIOSELH 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define GIUPIODL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define GIUPIODH 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define GIUINTSTATL 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define GIUINTSTATH 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define GIUINTENL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define GIUINTENH 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define GIUINTTYPL 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define GIUINTTYPH 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define GIUINTALSELL 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define GIUINTALSELH 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define GIUINTHTSELL 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define GIUINTHTSELH 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define GIUPODATL 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define GIUPODATEN 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define GIUPODATH 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define PIOEN0 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define PIOEN1 0x0200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define GIUPODAT 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define GIUFEDGEINHL 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define GIUFEDGEINHH 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define GIUREDGEINHL 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define GIUREDGEINHH 0x26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define GIUUSEUPDN 0x1e0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define GIUTERMUPDN 0x1e2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define GPIO_HAS_PULLUPDOWN_IO 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define GPIO_HAS_OUTPUT_ENABLE 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) GPIO_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) GPIO_OUTPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static DEFINE_SPINLOCK(giu_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static unsigned long giu_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void __iomem *giu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static struct gpio_chip vr41xx_gpio_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define giu_read(offset) readw(giu_base + (offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define giu_write(offset, value) writew((value), giu_base + (offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define GIUINT_HIGH_OFFSET 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define GIUINT_HIGH_MAX 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline u16 giu_set(u16 offset, u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) data = giu_read(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) data |= set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) giu_write(offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static inline u16 giu_clear(u16 offset, u16 clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) data = giu_read(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) data &= ~clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) giu_write(offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void ack_giuint_low(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static void mask_giuint_low(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void mask_ack_giuint_low(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pin = GPIO_PIN_OF_IRQ(d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) giu_clear(GIUINTENL, 1 << pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) giu_write(GIUINTSTATL, 1 << pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void unmask_giuint_low(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static unsigned int startup_giuint(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ret = gpiochip_lock_as_irq(&vr41xx_gpio_chip, irqd_to_hwirq(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) dev_err(vr41xx_gpio_chip.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "unable to lock HW IRQ %lu for IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) data->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Satisfy the .enable semantics by unmasking the line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unmask_giuint_low(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void shutdown_giuint(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mask_giuint_low(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) gpiochip_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static struct irq_chip giuint_low_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .name = "GIUINTL",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .irq_ack = ack_giuint_low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .irq_mask = mask_giuint_low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .irq_mask_ack = mask_ack_giuint_low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .irq_unmask = unmask_giuint_low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .irq_startup = startup_giuint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .irq_shutdown = shutdown_giuint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void ack_giuint_high(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) giu_write(GIUINTSTATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void mask_giuint_high(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void mask_ack_giuint_high(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) giu_clear(GIUINTENH, 1 << pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) giu_write(GIUINTSTATH, 1 << pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void unmask_giuint_high(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static struct irq_chip giuint_high_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .name = "GIUINTH",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .irq_ack = ack_giuint_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .irq_mask = mask_giuint_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .irq_mask_ack = mask_ack_giuint_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .irq_unmask = unmask_giuint_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int giu_get_irq(unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u16 pendl, pendh, maskl, maskh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) pendl = giu_read(GIUINTSTATL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) pendh = giu_read(GIUINTSTATH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) maskl = giu_read(GIUINTENL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) maskh = giu_read(GIUINTENH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) maskl &= pendl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) maskh &= pendh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (maskl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (maskl & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return GIU_IRQ(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) } else if (maskh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (maskh & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) maskl, pendl, maskh, pendh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) atomic_inc(&irq_err_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) irq_signal_t signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (pin < GIUINT_HIGH_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) mask = 1 << pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (trigger != IRQ_TRIGGER_LEVEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) giu_set(GIUINTTYPL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (signal == IRQ_SIGNAL_HOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) giu_set(GIUINTHTSELL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) giu_clear(GIUINTHTSELL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) switch (trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case IRQ_TRIGGER_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) giu_set(GIUFEDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) giu_clear(GIUREDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case IRQ_TRIGGER_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) giu_clear(GIUFEDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) giu_set(GIUREDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) giu_set(GIUFEDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) giu_set(GIUREDGEINHL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) irq_set_chip_and_handler(GIU_IRQ(pin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) &giuint_low_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) giu_clear(GIUINTTYPL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) giu_clear(GIUINTHTSELL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) irq_set_chip_and_handler(GIU_IRQ(pin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) &giuint_low_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) giu_write(GIUINTSTATL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) } else if (pin < GIUINT_HIGH_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mask = 1 << (pin - GIUINT_HIGH_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (trigger != IRQ_TRIGGER_LEVEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) giu_set(GIUINTTYPH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (signal == IRQ_SIGNAL_HOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) giu_set(GIUINTHTSELH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) giu_clear(GIUINTHTSELH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) switch (trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case IRQ_TRIGGER_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) giu_set(GIUFEDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) giu_clear(GIUREDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case IRQ_TRIGGER_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) giu_clear(GIUFEDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) giu_set(GIUREDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) giu_set(GIUFEDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) giu_set(GIUREDGEINHH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) irq_set_chip_and_handler(GIU_IRQ(pin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) &giuint_high_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) giu_clear(GIUINTTYPH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) giu_clear(GIUINTHTSELH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) irq_set_chip_and_handler(GIU_IRQ(pin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) &giuint_high_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) giu_write(GIUINTSTATH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (pin < GIUINT_HIGH_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) mask = 1 << pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (level == IRQ_LEVEL_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) giu_set(GIUINTALSELL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) giu_clear(GIUINTALSELL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) giu_write(GIUINTSTATL, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else if (pin < GIUINT_HIGH_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mask = 1 << (pin - GIUINT_HIGH_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (level == IRQ_LEVEL_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) giu_set(GIUINTALSELH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) giu_clear(GIUINTALSELH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) giu_write(GIUINTSTATH, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u16 offset, mask, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (pin >= chip->ngpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (pin < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) offset = GIUIOSELL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mask = 1 << pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else if (pin < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) offset = GIUIOSELH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) mask = 1 << (pin - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) offset = GIUPODATEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) mask = 1 << (pin - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) switch (pin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case 48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) offset = GIUPODATH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mask = PIOEN0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case 49:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) offset = GIUPODATH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) mask = PIOEN1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) spin_lock_irqsave(&giu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) reg = giu_read(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (dir == GPIO_OUTPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) reg |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) reg &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) giu_write(offset, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) spin_unlock_irqrestore(&giu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u16 reg, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (pin >= chip->ngpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (pin < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) reg = giu_read(GIUPIODL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) mask = 1 << pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } else if (pin < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) reg = giu_read(GIUPIODH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) mask = 1 << (pin - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) } else if (pin < 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) reg = giu_read(GIUPODATL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mask = 1 << (pin - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) reg = giu_read(GIUPODATH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mask = 1 << (pin - 48);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (reg & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u16 offset, mask, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (pin >= chip->ngpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (pin < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) offset = GIUPIODL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) mask = 1 << pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) } else if (pin < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) offset = GIUPIODH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) mask = 1 << (pin - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else if (pin < 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) offset = GIUPODATL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mask = 1 << (pin - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) offset = GIUPODATH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mask = 1 << (pin - 48);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) spin_lock_irqsave(&giu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) reg = giu_read(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) reg |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) reg &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) giu_write(offset, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) spin_unlock_irqrestore(&giu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return giu_set_direction(chip, offset, GPIO_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) vr41xx_gpio_set(chip, offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return giu_set_direction(chip, offset, GPIO_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (offset >= chip->ngpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return GIU_IRQ_BASE + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static struct gpio_chip vr41xx_gpio_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .label = "vr41xx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .direction_input = vr41xx_gpio_direction_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .get = vr41xx_gpio_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .direction_output = vr41xx_gpio_direction_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .set = vr41xx_gpio_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .to_irq = vr41xx_gpio_to_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int giu_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned int trigger, i, pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct irq_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) switch (pdev->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) case GPIO_50PINS_PULLUPDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) giu_flags = GPIO_HAS_PULLUPDOWN_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) vr41xx_gpio_chip.ngpio = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case GPIO_36PINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) vr41xx_gpio_chip.ngpio = 36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) case GPIO_48PINS_EDGE_SELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) vr41xx_gpio_chip.ngpio = 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) giu_base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (IS_ERR(giu_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return PTR_ERR(giu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) vr41xx_gpio_chip.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (gpiochip_add_data(&vr41xx_gpio_chip, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) giu_write(GIUINTENL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) giu_write(GIUINTENH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) trigger = giu_read(GIUINTTYPH) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) trigger |= giu_read(GIUINTTYPL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) pin = GPIO_PIN_OF_IRQ(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (pin < GIUINT_HIGH_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) chip = &giuint_low_irq_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) chip = &giuint_high_irq_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (trigger & (1 << pin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) irq_set_chip_and_handler(i, chip, handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) irq_set_chip_and_handler(i, chip, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (irq < 0 || irq >= nr_irqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return cascade_irq(irq, giu_get_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int giu_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (giu_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) giu_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static struct platform_driver giu_device_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) .probe = giu_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) .remove = giu_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .name = "GIU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) module_platform_driver(giu_device_driver);