Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * GPIO driver for the ACCES 104-IDI-48 family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2015 William Breathitt Gray
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This driver supports the following ACCES devices: 104-IDI-48A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/gpio/driver.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/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/irqdesc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/isa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define IDI_48_EXTENT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static unsigned int base[MAX_NUM_IDI_48];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static unsigned int num_idi_48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) module_param_hw_array(base, uint, ioport, &num_idi_48, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static unsigned int irq[MAX_NUM_IDI_48];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) module_param_hw_array(irq, uint, irq, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * struct idi_48_gpio - GPIO device private data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * @chip:	instance of the gpio_chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * @lock:	synchronization lock to prevent I/O race conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * @ack_lock:	synchronization lock to prevent IRQ handler race conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * @irq_mask:	input bits affected by interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * @base:	base port address of the GPIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * @cos_enb:	Change-Of-State IRQ enable boundaries mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) struct idi_48_gpio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	raw_spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	spinlock_t ack_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	unsigned char irq_mask[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned char cos_enb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	return GPIO_LINE_DIRECTION_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	static const unsigned int register_offset[6] = { 0, 1, 2, 4, 5, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	unsigned base_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	unsigned mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	for (i = 0; i < 48; i += 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		if (offset < i + 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			base_offset = register_offset[i / 8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			mask = BIT(offset - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			return !!(inb(idi48gpio->base + base_offset) & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	/* The following line should never execute since offset < 48 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned long *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	unsigned long gpio_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	unsigned int port_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	unsigned long port_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	/* clear bits array to a clean slate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	bitmap_zero(bits, chip->ngpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		port_addr = idi48gpio->base + ports[offset / 8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		port_state = inb(port_addr) & gpio_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		bitmap_set_value8(bits, port_state, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	return 0;
^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 idi_48_irq_ack(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static void idi_48_irq_mask(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	const unsigned offset = irqd_to_hwirq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	unsigned mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	unsigned boundary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	for (i = 0; i < 48; i += 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		if (offset < i + 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			mask = BIT(offset - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			boundary = i / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			idi48gpio->irq_mask[boundary] &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			if (!idi48gpio->irq_mask[boundary]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 				idi48gpio->cos_enb &= ~BIT(boundary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 				raw_spin_lock_irqsave(&idi48gpio->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				raw_spin_unlock_irqrestore(&idi48gpio->lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 						           flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		}
^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 idi_48_irq_unmask(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	const unsigned offset = irqd_to_hwirq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	unsigned mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	unsigned boundary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	unsigned prev_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	for (i = 0; i < 48; i += 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (offset < i + 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			mask = BIT(offset - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			boundary = i / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			prev_irq_mask = idi48gpio->irq_mask[boundary];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			idi48gpio->irq_mask[boundary] |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			if (!prev_irq_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 				idi48gpio->cos_enb |= BIT(boundary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				raw_spin_lock_irqsave(&idi48gpio->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				raw_spin_unlock_irqrestore(&idi48gpio->lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 						           flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static int idi_48_irq_set_type(struct irq_data *data, unsigned flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	/* The only valid irq types are none and both-edges */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (flow_type != IRQ_TYPE_NONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static struct irq_chip idi_48_irqchip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	.name = "104-idi-48",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	.irq_ack = idi_48_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	.irq_mask = idi_48_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.irq_unmask = idi_48_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.irq_set_type = idi_48_irq_set_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	struct idi_48_gpio *const idi48gpio = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	unsigned long cos_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	unsigned long boundary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	unsigned long irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	unsigned long bit_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	unsigned long gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	struct gpio_chip *const chip = &idi48gpio->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	spin_lock(&idi48gpio->ack_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	raw_spin_lock(&idi48gpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	cos_status = inb(idi48gpio->base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	raw_spin_unlock(&idi48gpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	if (cos_status & BIT(6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		spin_unlock(&idi48gpio->ack_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	/* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	cos_status &= 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	for_each_set_bit(boundary, &cos_status, 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		irq_mask = idi48gpio->irq_mask[boundary];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		for_each_set_bit(bit_num, &irq_mask, 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			gpio = bit_num + boundary * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			generic_handle_irq(irq_find_mapping(chip->irq.domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 				gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	spin_unlock(&idi48gpio->ack_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define IDI48_NGPIO 48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static const char *idi48_names[IDI48_NGPIO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	"Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	"Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	"Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A",	"Bit 16 A", "Bit 17 A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	"Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	"Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	"Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	"Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B",	"Bit 16 B", "Bit 17 B",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	"Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int idi_48_irq_init_hw(struct gpio_chip *gc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	/* Disable IRQ by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	outb(0, idi48gpio->base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	inb(idi48gpio->base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int idi_48_probe(struct device *dev, unsigned int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	struct idi_48_gpio *idi48gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	const char *const name = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct gpio_irq_chip *girq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	if (!idi48gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			base[id], base[id] + IDI_48_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	idi48gpio->chip.label = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	idi48gpio->chip.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	idi48gpio->chip.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	idi48gpio->chip.base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	idi48gpio->chip.ngpio = IDI48_NGPIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	idi48gpio->chip.names = idi48_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	idi48gpio->chip.get = idi_48_gpio_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	idi48gpio->base = base[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	girq = &idi48gpio->chip.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	girq->chip = &idi_48_irqchip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	/* This will let us handle the parent IRQ in the driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	girq->parent_handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	girq->num_parents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	girq->parents = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	girq->default_type = IRQ_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	girq->handler = handle_edge_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	girq->init_hw = idi_48_irq_init_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	raw_spin_lock_init(&idi48gpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	spin_lock_init(&idi48gpio->ack_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		dev_err(dev, "GPIO registering failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		name, idi48gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static struct isa_driver idi_48_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	.probe = idi_48_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		.name = "104-idi-48"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) module_isa_driver(idi_48_driver, num_idi_48);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) MODULE_LICENSE("GPL v2");