Lines Matching +full:48 +full:- +full:bit
1 // SPDX-License-Identifier: GPL-2.0-only
3 * GPIO driver for the ACCES 104-IDI-48 family
6 * This driver supports the following ACCES devices: 104-IDI-48A,
7 * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
30 MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
34 MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
37 * struct idi_48_gpio - GPIO device private data structure
43 * @cos_enb: Change-Of-State IRQ enable boundaries mask
72 for (i = 0; i < 48; i += 8) in idi_48_gpio_get()
75 mask = BIT(offset - i); in idi_48_gpio_get()
77 return !!(inb(idi48gpio->base + base_offset) & mask); in idi_48_gpio_get()
80 /* The following line should never execute since offset < 48 */ in idi_48_gpio_get()
95 bitmap_zero(bits, chip->ngpio); in idi_48_gpio_get_multiple()
98 port_addr = idi48gpio->base + ports[offset / 8]; in idi_48_gpio_get_multiple()
121 for (i = 0; i < 48; i += 8) in idi_48_irq_mask()
123 mask = BIT(offset - i); in idi_48_irq_mask()
126 idi48gpio->irq_mask[boundary] &= ~mask; in idi_48_irq_mask()
128 if (!idi48gpio->irq_mask[boundary]) { in idi_48_irq_mask()
129 idi48gpio->cos_enb &= ~BIT(boundary); in idi_48_irq_mask()
131 raw_spin_lock_irqsave(&idi48gpio->lock, flags); in idi_48_irq_mask()
133 outb(idi48gpio->cos_enb, idi48gpio->base + 7); in idi_48_irq_mask()
135 raw_spin_unlock_irqrestore(&idi48gpio->lock, in idi_48_irq_mask()
154 for (i = 0; i < 48; i += 8) in idi_48_irq_unmask()
156 mask = BIT(offset - i); in idi_48_irq_unmask()
158 prev_irq_mask = idi48gpio->irq_mask[boundary]; in idi_48_irq_unmask()
160 idi48gpio->irq_mask[boundary] |= mask; in idi_48_irq_unmask()
163 idi48gpio->cos_enb |= BIT(boundary); in idi_48_irq_unmask()
165 raw_spin_lock_irqsave(&idi48gpio->lock, flags); in idi_48_irq_unmask()
167 outb(idi48gpio->cos_enb, idi48gpio->base + 7); in idi_48_irq_unmask()
169 raw_spin_unlock_irqrestore(&idi48gpio->lock, in idi_48_irq_unmask()
179 /* The only valid irq types are none and both-edges */ in idi_48_irq_set_type()
182 return -EINVAL; in idi_48_irq_set_type()
188 .name = "104-idi-48",
203 struct gpio_chip *const chip = &idi48gpio->chip; in idi_48_irq_handler()
205 spin_lock(&idi48gpio->ack_lock); in idi_48_irq_handler()
207 raw_spin_lock(&idi48gpio->lock); in idi_48_irq_handler()
209 cos_status = inb(idi48gpio->base + 7); in idi_48_irq_handler()
211 raw_spin_unlock(&idi48gpio->lock); in idi_48_irq_handler()
213 /* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */ in idi_48_irq_handler()
214 if (cos_status & BIT(6)) { in idi_48_irq_handler()
215 spin_unlock(&idi48gpio->ack_lock); in idi_48_irq_handler()
219 /* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */ in idi_48_irq_handler()
223 irq_mask = idi48gpio->irq_mask[boundary]; in idi_48_irq_handler()
228 generic_handle_irq(irq_find_mapping(chip->irq.domain, in idi_48_irq_handler()
233 spin_unlock(&idi48gpio->ack_lock); in idi_48_irq_handler()
238 #define IDI48_NGPIO 48
240 "Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
241 "Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
242 "Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A", "Bit 16 A", "Bit 17 A",
243 "Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
244 "Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
245 "Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
246 "Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B", "Bit 16 B", "Bit 17 B",
247 "Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
255 outb(0, idi48gpio->base + 7); in idi_48_irq_init_hw()
256 inb(idi48gpio->base + 7); in idi_48_irq_init_hw()
270 return -ENOMEM; in idi_48_probe()
273 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", in idi_48_probe()
275 return -EBUSY; in idi_48_probe()
278 idi48gpio->chip.label = name; in idi_48_probe()
279 idi48gpio->chip.parent = dev; in idi_48_probe()
280 idi48gpio->chip.owner = THIS_MODULE; in idi_48_probe()
281 idi48gpio->chip.base = -1; in idi_48_probe()
282 idi48gpio->chip.ngpio = IDI48_NGPIO; in idi_48_probe()
283 idi48gpio->chip.names = idi48_names; in idi_48_probe()
284 idi48gpio->chip.get_direction = idi_48_gpio_get_direction; in idi_48_probe()
285 idi48gpio->chip.direction_input = idi_48_gpio_direction_input; in idi_48_probe()
286 idi48gpio->chip.get = idi_48_gpio_get; in idi_48_probe()
287 idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple; in idi_48_probe()
288 idi48gpio->base = base[id]; in idi_48_probe()
290 girq = &idi48gpio->chip.irq; in idi_48_probe()
291 girq->chip = &idi_48_irqchip; in idi_48_probe()
293 girq->parent_handler = NULL; in idi_48_probe()
294 girq->num_parents = 0; in idi_48_probe()
295 girq->parents = NULL; in idi_48_probe()
296 girq->default_type = IRQ_TYPE_NONE; in idi_48_probe()
297 girq->handler = handle_edge_irq; in idi_48_probe()
298 girq->init_hw = idi_48_irq_init_hw; in idi_48_probe()
300 raw_spin_lock_init(&idi48gpio->lock); in idi_48_probe()
301 spin_lock_init(&idi48gpio->ack_lock); in idi_48_probe()
303 err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio); in idi_48_probe()
322 .name = "104-idi-48"
328 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");