Lines Matching +full:lock +full:- +full:offset
1 // SPDX-License-Identifier: GPL-2.0-only
34 * struct ws16c48_gpio - GPIO device private data structure
38 * @lock: synchronization lock to prevent I/O race conditions
47 raw_spinlock_t lock; member
53 static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset) in ws16c48_gpio_get_direction() argument
56 const unsigned port = offset / 8; in ws16c48_gpio_get_direction()
57 const unsigned mask = BIT(offset % 8); in ws16c48_gpio_get_direction()
59 if (ws16c48gpio->io_state[port] & mask) in ws16c48_gpio_get_direction()
65 static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) in ws16c48_gpio_direction_input() argument
68 const unsigned port = offset / 8; in ws16c48_gpio_direction_input()
69 const unsigned mask = BIT(offset % 8); in ws16c48_gpio_direction_input()
72 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_gpio_direction_input()
74 ws16c48gpio->io_state[port] |= mask; in ws16c48_gpio_direction_input()
75 ws16c48gpio->out_state[port] &= ~mask; in ws16c48_gpio_direction_input()
76 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); in ws16c48_gpio_direction_input()
78 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_direction_input()
84 unsigned offset, int value) in ws16c48_gpio_direction_output() argument
87 const unsigned port = offset / 8; in ws16c48_gpio_direction_output()
88 const unsigned mask = BIT(offset % 8); in ws16c48_gpio_direction_output()
91 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_gpio_direction_output()
93 ws16c48gpio->io_state[port] &= ~mask; in ws16c48_gpio_direction_output()
95 ws16c48gpio->out_state[port] |= mask; in ws16c48_gpio_direction_output()
97 ws16c48gpio->out_state[port] &= ~mask; in ws16c48_gpio_direction_output()
98 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); in ws16c48_gpio_direction_output()
100 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_direction_output()
105 static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) in ws16c48_gpio_get() argument
108 const unsigned port = offset / 8; in ws16c48_gpio_get()
109 const unsigned mask = BIT(offset % 8); in ws16c48_gpio_get()
113 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_gpio_get()
116 if (!(ws16c48gpio->io_state[port] & mask)) { in ws16c48_gpio_get()
117 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_get()
118 return -EINVAL; in ws16c48_gpio_get()
121 port_state = inb(ws16c48gpio->base + port); in ws16c48_gpio_get()
123 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_get()
132 unsigned long offset; in ws16c48_gpio_get_multiple() local
138 bitmap_zero(bits, chip->ngpio); in ws16c48_gpio_get_multiple()
140 for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { in ws16c48_gpio_get_multiple()
141 port_addr = ws16c48gpio->base + offset / 8; in ws16c48_gpio_get_multiple()
144 bitmap_set_value8(bits, port_state, offset); in ws16c48_gpio_get_multiple()
150 static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) in ws16c48_gpio_set() argument
153 const unsigned port = offset / 8; in ws16c48_gpio_set()
154 const unsigned mask = BIT(offset % 8); in ws16c48_gpio_set()
157 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_gpio_set()
160 if (ws16c48gpio->io_state[port] & mask) { in ws16c48_gpio_set()
161 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_set()
166 ws16c48gpio->out_state[port] |= mask; in ws16c48_gpio_set()
168 ws16c48gpio->out_state[port] &= ~mask; in ws16c48_gpio_set()
169 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); in ws16c48_gpio_set()
171 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_set()
178 unsigned long offset; in ws16c48_gpio_set_multiple() local
185 for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { in ws16c48_gpio_set_multiple()
186 index = offset / 8; in ws16c48_gpio_set_multiple()
187 port_addr = ws16c48gpio->base + index; in ws16c48_gpio_set_multiple()
190 gpio_mask &= ~ws16c48gpio->io_state[index]; in ws16c48_gpio_set_multiple()
191 bitmask = bitmap_get_value8(bits, offset) & gpio_mask; in ws16c48_gpio_set_multiple()
193 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_gpio_set_multiple()
196 ws16c48gpio->out_state[index] &= ~gpio_mask; in ws16c48_gpio_set_multiple()
197 ws16c48gpio->out_state[index] |= bitmask; in ws16c48_gpio_set_multiple()
198 outb(ws16c48gpio->out_state[index], port_addr); in ws16c48_gpio_set_multiple()
200 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_gpio_set_multiple()
208 const unsigned long offset = irqd_to_hwirq(data); in ws16c48_irq_ack() local
209 const unsigned port = offset / 8; in ws16c48_irq_ack()
210 const unsigned mask = BIT(offset % 8); in ws16c48_irq_ack()
218 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_irq_ack()
220 port_state = ws16c48gpio->irq_mask >> (8*port); in ws16c48_irq_ack()
222 outb(0x80, ws16c48gpio->base + 7); in ws16c48_irq_ack()
223 outb(port_state & ~mask, ws16c48gpio->base + 8 + port); in ws16c48_irq_ack()
224 outb(port_state | mask, ws16c48gpio->base + 8 + port); in ws16c48_irq_ack()
225 outb(0xC0, ws16c48gpio->base + 7); in ws16c48_irq_ack()
227 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_irq_ack()
234 const unsigned long offset = irqd_to_hwirq(data); in ws16c48_irq_mask() local
235 const unsigned long mask = BIT(offset); in ws16c48_irq_mask()
236 const unsigned port = offset / 8; in ws16c48_irq_mask()
243 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_irq_mask()
245 ws16c48gpio->irq_mask &= ~mask; in ws16c48_irq_mask()
247 outb(0x80, ws16c48gpio->base + 7); in ws16c48_irq_mask()
248 outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); in ws16c48_irq_mask()
249 outb(0xC0, ws16c48gpio->base + 7); in ws16c48_irq_mask()
251 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_irq_mask()
258 const unsigned long offset = irqd_to_hwirq(data); in ws16c48_irq_unmask() local
259 const unsigned long mask = BIT(offset); in ws16c48_irq_unmask()
260 const unsigned port = offset / 8; in ws16c48_irq_unmask()
267 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_irq_unmask()
269 ws16c48gpio->irq_mask |= mask; in ws16c48_irq_unmask()
271 outb(0x80, ws16c48gpio->base + 7); in ws16c48_irq_unmask()
272 outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); in ws16c48_irq_unmask()
273 outb(0xC0, ws16c48gpio->base + 7); in ws16c48_irq_unmask()
275 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_irq_unmask()
282 const unsigned long offset = irqd_to_hwirq(data); in ws16c48_irq_set_type() local
283 const unsigned long mask = BIT(offset); in ws16c48_irq_set_type()
284 const unsigned port = offset / 8; in ws16c48_irq_set_type()
289 return -EINVAL; in ws16c48_irq_set_type()
291 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); in ws16c48_irq_set_type()
297 ws16c48gpio->flow_mask |= mask; in ws16c48_irq_set_type()
300 ws16c48gpio->flow_mask &= ~mask; in ws16c48_irq_set_type()
303 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_irq_set_type()
304 return -EINVAL; in ws16c48_irq_set_type()
307 outb(0x40, ws16c48gpio->base + 7); in ws16c48_irq_set_type()
308 outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port); in ws16c48_irq_set_type()
309 outb(0xC0, ws16c48gpio->base + 7); in ws16c48_irq_set_type()
311 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); in ws16c48_irq_set_type()
327 struct gpio_chip *const chip = &ws16c48gpio->chip; in ws16c48_irq_handler()
333 int_pending = inb(ws16c48gpio->base + 6) & 0x7; in ws16c48_irq_handler()
340 int_id = inb(ws16c48gpio->base + 8 + port); in ws16c48_irq_handler()
343 chip->irq.domain, gpio + 8*port)); in ws16c48_irq_handler()
346 int_pending = inb(ws16c48gpio->base + 6) & 0x7; in ws16c48_irq_handler()
373 outb(0x80, ws16c48gpio->base + 7); in ws16c48_irq_init_hw()
374 outb(0, ws16c48gpio->base + 8); in ws16c48_irq_init_hw()
375 outb(0, ws16c48gpio->base + 9); in ws16c48_irq_init_hw()
376 outb(0, ws16c48gpio->base + 10); in ws16c48_irq_init_hw()
377 outb(0xC0, ws16c48gpio->base + 7); in ws16c48_irq_init_hw()
391 return -ENOMEM; in ws16c48_probe()
394 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", in ws16c48_probe()
396 return -EBUSY; in ws16c48_probe()
399 ws16c48gpio->chip.label = name; in ws16c48_probe()
400 ws16c48gpio->chip.parent = dev; in ws16c48_probe()
401 ws16c48gpio->chip.owner = THIS_MODULE; in ws16c48_probe()
402 ws16c48gpio->chip.base = -1; in ws16c48_probe()
403 ws16c48gpio->chip.ngpio = WS16C48_NGPIO; in ws16c48_probe()
404 ws16c48gpio->chip.names = ws16c48_names; in ws16c48_probe()
405 ws16c48gpio->chip.get_direction = ws16c48_gpio_get_direction; in ws16c48_probe()
406 ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; in ws16c48_probe()
407 ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; in ws16c48_probe()
408 ws16c48gpio->chip.get = ws16c48_gpio_get; in ws16c48_probe()
409 ws16c48gpio->chip.get_multiple = ws16c48_gpio_get_multiple; in ws16c48_probe()
410 ws16c48gpio->chip.set = ws16c48_gpio_set; in ws16c48_probe()
411 ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple; in ws16c48_probe()
412 ws16c48gpio->base = base[id]; in ws16c48_probe()
414 girq = &ws16c48gpio->chip.irq; in ws16c48_probe()
415 girq->chip = &ws16c48_irqchip; in ws16c48_probe()
417 girq->parent_handler = NULL; in ws16c48_probe()
418 girq->num_parents = 0; in ws16c48_probe()
419 girq->parents = NULL; in ws16c48_probe()
420 girq->default_type = IRQ_TYPE_NONE; in ws16c48_probe()
421 girq->handler = handle_edge_irq; in ws16c48_probe()
422 girq->init_hw = ws16c48_irq_init_hw; in ws16c48_probe()
424 raw_spin_lock_init(&ws16c48gpio->lock); in ws16c48_probe()
426 err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio); in ws16c48_probe()