Lines Matching +full:lock +full:- +full:offset

56  * lock: lock for guarding gpio registers
59 * p2o: function ptr for pin to offset conversion. This is required only for
60 * machines where mapping b/w pin and offset is not 1-to-1.
61 * o2p: function ptr for offset to pin conversion. This is required only for
62 * machines where mapping b/w pin and offset is not 1-to-1.
68 spinlock_t lock; member
73 int (*o2p)(int offset); /* offset_to_pin */
84 u32 offset = PIN_OFFSET(pin); in is_plgpio_set() local
90 return !!(val & (1 << offset)); in is_plgpio_set()
95 u32 offset = PIN_OFFSET(pin); in plgpio_reg_set() local
99 mask = 1 << offset; in plgpio_reg_set()
105 u32 offset = PIN_OFFSET(pin); in plgpio_reg_reset() local
109 mask = 1 << offset; in plgpio_reg_reset()
115 static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset) in plgpio_direction_input() argument
120 /* get correct offset for "offset" pin */ in plgpio_direction_input()
121 if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) { in plgpio_direction_input()
122 offset = plgpio->p2o(offset); in plgpio_direction_input()
123 if (offset == -1) in plgpio_direction_input()
124 return -EINVAL; in plgpio_direction_input()
127 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_direction_input()
128 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.dir); in plgpio_direction_input()
129 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_direction_input()
134 static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset, in plgpio_direction_output() argument
139 unsigned dir_offset = offset, wdata_offset = offset, tmp; in plgpio_direction_output()
141 /* get correct offset for "offset" pin */ in plgpio_direction_output()
142 if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) { in plgpio_direction_output()
143 tmp = plgpio->p2o(offset); in plgpio_direction_output()
144 if (tmp == -1) in plgpio_direction_output()
145 return -EINVAL; in plgpio_direction_output()
147 if (plgpio->p2o_regs & PTO_DIR_REG) in plgpio_direction_output()
149 if (plgpio->p2o_regs & PTO_WDATA_REG) in plgpio_direction_output()
153 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_direction_output()
155 plgpio_reg_set(plgpio->regmap, wdata_offset, in plgpio_direction_output()
156 plgpio->regs.wdata); in plgpio_direction_output()
158 plgpio_reg_reset(plgpio->regmap, wdata_offset, in plgpio_direction_output()
159 plgpio->regs.wdata); in plgpio_direction_output()
161 plgpio_reg_reset(plgpio->regmap, dir_offset, plgpio->regs.dir); in plgpio_direction_output()
162 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_direction_output()
167 static int plgpio_get_value(struct gpio_chip *chip, unsigned offset) in plgpio_get_value() argument
171 if (offset >= chip->ngpio) in plgpio_get_value()
172 return -EINVAL; in plgpio_get_value()
174 /* get correct offset for "offset" pin */ in plgpio_get_value()
175 if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) { in plgpio_get_value()
176 offset = plgpio->p2o(offset); in plgpio_get_value()
177 if (offset == -1) in plgpio_get_value()
178 return -EINVAL; in plgpio_get_value()
181 return is_plgpio_set(plgpio->regmap, offset, plgpio->regs.rdata); in plgpio_get_value()
184 static int plgpio_set_value(struct gpio_chip *chip, unsigned int offset, in plgpio_set_value() argument
189 if (offset >= chip->ngpio) in plgpio_set_value()
190 return -EINVAL; in plgpio_set_value()
192 /* get correct offset for "offset" pin */ in plgpio_set_value()
193 if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) { in plgpio_set_value()
194 offset = plgpio->p2o(offset); in plgpio_set_value()
195 if (offset == -1) in plgpio_set_value()
196 return -EINVAL; in plgpio_set_value()
200 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.wdata); in plgpio_set_value()
202 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.wdata); in plgpio_set_value()
207 static int plgpio_request(struct gpio_chip *chip, unsigned offset) in plgpio_request() argument
213 if (offset >= chip->ngpio) in plgpio_request()
214 return -EINVAL; in plgpio_request()
216 ret = pinctrl_gpio_request(chip, offset); in plgpio_request()
220 if (!IS_ERR(plgpio->clk)) { in plgpio_request()
221 ret = clk_enable(plgpio->clk); in plgpio_request()
226 if (plgpio->regs.enb == -1) in plgpio_request()
232 ret = plgpio_direction_input(chip, offset); in plgpio_request()
236 /* get correct offset for "offset" pin */ in plgpio_request()
237 if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { in plgpio_request()
238 offset = plgpio->p2o(offset); in plgpio_request()
239 if (offset == -1) { in plgpio_request()
240 ret = -EINVAL; in plgpio_request()
245 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_request()
246 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.enb); in plgpio_request()
247 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_request()
251 if (!IS_ERR(plgpio->clk)) in plgpio_request()
252 clk_disable(plgpio->clk); in plgpio_request()
254 pinctrl_gpio_free(chip, offset); in plgpio_request()
258 static void plgpio_free(struct gpio_chip *chip, unsigned offset) in plgpio_free() argument
263 if (offset >= chip->ngpio) in plgpio_free()
266 if (plgpio->regs.enb == -1) in plgpio_free()
269 /* get correct offset for "offset" pin */ in plgpio_free()
270 if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) { in plgpio_free()
271 offset = plgpio->p2o(offset); in plgpio_free()
272 if (offset == -1) in plgpio_free()
276 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_free()
277 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.enb); in plgpio_free()
278 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_free()
281 if (!IS_ERR(plgpio->clk)) in plgpio_free()
282 clk_disable(plgpio->clk); in plgpio_free()
284 pinctrl_gpio_free(chip, offset); in plgpio_free()
292 int offset = d->hwirq; in plgpio_irq_disable() local
295 /* get correct offset for "offset" pin */ in plgpio_irq_disable()
296 if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { in plgpio_irq_disable()
297 offset = plgpio->p2o(offset); in plgpio_irq_disable()
298 if (offset == -1) in plgpio_irq_disable()
302 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_irq_disable()
303 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.ie); in plgpio_irq_disable()
304 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_irq_disable()
312 int offset = d->hwirq; in plgpio_irq_enable() local
315 /* get correct offset for "offset" pin */ in plgpio_irq_enable()
316 if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) { in plgpio_irq_enable()
317 offset = plgpio->p2o(offset); in plgpio_irq_enable()
318 if (offset == -1) in plgpio_irq_enable()
323 spin_lock_irqsave(&plgpio->lock, flags); in plgpio_irq_enable()
324 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.ie); in plgpio_irq_enable()
325 spin_unlock_irqrestore(&plgpio->lock, flags); in plgpio_irq_enable()
332 int offset = d->hwirq; in plgpio_irq_set_type() local
336 if (offset >= plgpio->chip.ngpio) in plgpio_irq_set_type()
337 return -EINVAL; in plgpio_irq_set_type()
339 if (plgpio->regs.eit == -1) in plgpio_irq_set_type()
345 return -EINVAL; in plgpio_irq_set_type()
347 if (plgpio->regs.eit == -1) in plgpio_irq_set_type()
350 reg_off = REG_OFFSET(0, plgpio->regs.eit, offset); in plgpio_irq_set_type()
351 regmap_read(plgpio->regmap, reg_off, &val); in plgpio_irq_set_type()
353 offset = PIN_OFFSET(offset); in plgpio_irq_set_type()
355 regmap_write(plgpio->regmap, reg_off, val | (1 << offset)); in plgpio_irq_set_type()
357 regmap_write(plgpio->regmap, reg_off, val & ~(1 << offset)); in plgpio_irq_set_type()
376 int regs_count, count, pin, offset, i = 0; in plgpio_irq_handler() local
380 count = plgpio->chip.ngpio; in plgpio_irq_handler()
386 regmap_read(plgpio->regmap, plgpio->regs.mis + in plgpio_irq_handler()
392 regmap_write(plgpio->regmap, plgpio->regs.mis + in plgpio_irq_handler()
397 * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits in plgpio_irq_handler()
401 count = count - i * MAX_GPIO_PER_REG; in plgpio_irq_handler()
403 pending &= (1 << count) - 1; in plgpio_irq_handler()
406 for_each_set_bit(offset, &pendingl, MAX_GPIO_PER_REG) { in plgpio_irq_handler()
407 /* get correct pin for "offset" */ in plgpio_irq_handler()
408 if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) { in plgpio_irq_handler()
409 pin = plgpio->o2p(offset); in plgpio_irq_handler()
410 if (pin == -1) in plgpio_irq_handler()
413 pin = offset; in plgpio_irq_handler()
417 generic_handle_domain_irq(gc->irq.domain, pin); in plgpio_irq_handler()
424 * pin to offset and offset to pin converter functions
427 * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
428 * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
432 int offset = pin; in spear310_p2o() local
435 offset += 4; in spear310_p2o()
437 offset = -1; in spear310_p2o()
439 offset -= 2; in spear310_p2o()
441 offset = 101 - pin; in spear310_p2o()
443 offset = -1; in spear310_p2o()
445 return offset; in spear310_p2o()
448 static int spear310_o2p(int offset) in spear310_o2p() argument
450 if (offset <= 3) in spear310_o2p()
451 return 101 - offset; in spear310_o2p()
452 else if (offset <= 31) in spear310_o2p()
453 return offset - 4; in spear310_o2p()
455 return offset + 2; in spear310_o2p()
460 struct device_node *np = pdev->dev.of_node; in plgpio_probe_dt()
461 int ret = -EINVAL; in plgpio_probe_dt()
465 plgpio->p2o = spear310_p2o; in plgpio_probe_dt()
466 plgpio->o2p = spear310_o2p; in plgpio_probe_dt()
467 plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG | in plgpio_probe_dt()
471 if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) { in plgpio_probe_dt()
472 plgpio->chip.ngpio = val; in plgpio_probe_dt()
474 dev_err(&pdev->dev, "DT: Invalid ngpio field\n"); in plgpio_probe_dt()
478 if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val)) in plgpio_probe_dt()
479 plgpio->regs.enb = val; in plgpio_probe_dt()
481 plgpio->regs.enb = -1; in plgpio_probe_dt()
483 if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) { in plgpio_probe_dt()
484 plgpio->regs.wdata = val; in plgpio_probe_dt()
486 dev_err(&pdev->dev, "DT: Invalid wdata reg\n"); in plgpio_probe_dt()
490 if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) { in plgpio_probe_dt()
491 plgpio->regs.dir = val; in plgpio_probe_dt()
493 dev_err(&pdev->dev, "DT: Invalid dir reg\n"); in plgpio_probe_dt()
497 if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) { in plgpio_probe_dt()
498 plgpio->regs.ie = val; in plgpio_probe_dt()
500 dev_err(&pdev->dev, "DT: Invalid ie reg\n"); in plgpio_probe_dt()
504 if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) { in plgpio_probe_dt()
505 plgpio->regs.rdata = val; in plgpio_probe_dt()
507 dev_err(&pdev->dev, "DT: Invalid rdata reg\n"); in plgpio_probe_dt()
511 if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) { in plgpio_probe_dt()
512 plgpio->regs.mis = val; in plgpio_probe_dt()
514 dev_err(&pdev->dev, "DT: Invalid mis reg\n"); in plgpio_probe_dt()
518 if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val)) in plgpio_probe_dt()
519 plgpio->regs.eit = val; in plgpio_probe_dt()
521 plgpio->regs.eit = -1; in plgpio_probe_dt()
535 plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL); in plgpio_probe()
537 return -ENOMEM; in plgpio_probe()
539 regmap_np = of_parse_phandle(pdev->dev.of_node, "regmap", 0); in plgpio_probe()
541 plgpio->regmap = device_node_to_regmap(regmap_np); in plgpio_probe()
543 if (IS_ERR(plgpio->regmap)) { in plgpio_probe()
544 dev_err(&pdev->dev, "Retrieve regmap failed (%pe)\n", in plgpio_probe()
545 plgpio->regmap); in plgpio_probe()
546 return PTR_ERR(plgpio->regmap); in plgpio_probe()
549 plgpio->regmap = device_node_to_regmap(pdev->dev.of_node); in plgpio_probe()
550 if (IS_ERR(plgpio->regmap)) { in plgpio_probe()
551 dev_err(&pdev->dev, "Init regmap failed (%pe)\n", in plgpio_probe()
552 plgpio->regmap); in plgpio_probe()
553 return PTR_ERR(plgpio->regmap); in plgpio_probe()
559 dev_err(&pdev->dev, "DT probe failed\n"); in plgpio_probe()
563 plgpio->clk = devm_clk_get(&pdev->dev, NULL); in plgpio_probe()
564 if (IS_ERR(plgpio->clk)) in plgpio_probe()
565 dev_warn(&pdev->dev, "clk_get() failed, work without it\n"); in plgpio_probe()
568 plgpio->csave_regs = devm_kcalloc(&pdev->dev, in plgpio_probe()
569 DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG), in plgpio_probe()
570 sizeof(*plgpio->csave_regs), in plgpio_probe()
572 if (!plgpio->csave_regs) in plgpio_probe()
573 return -ENOMEM; in plgpio_probe()
577 spin_lock_init(&plgpio->lock); in plgpio_probe()
579 plgpio->chip.base = -1; in plgpio_probe()
580 plgpio->chip.request = plgpio_request; in plgpio_probe()
581 plgpio->chip.free = plgpio_free; in plgpio_probe()
582 plgpio->chip.direction_input = plgpio_direction_input; in plgpio_probe()
583 plgpio->chip.direction_output = plgpio_direction_output; in plgpio_probe()
584 plgpio->chip.get = plgpio_get_value; in plgpio_probe()
585 plgpio->chip.set_rv = plgpio_set_value; in plgpio_probe()
586 plgpio->chip.label = dev_name(&pdev->dev); in plgpio_probe()
587 plgpio->chip.parent = &pdev->dev; in plgpio_probe()
588 plgpio->chip.owner = THIS_MODULE; in plgpio_probe()
590 if (!IS_ERR(plgpio->clk)) { in plgpio_probe()
591 ret = clk_prepare(plgpio->clk); in plgpio_probe()
593 dev_err(&pdev->dev, "clk prepare failed\n"); in plgpio_probe()
602 girq = &plgpio->chip.irq; in plgpio_probe()
604 girq->parent_handler = plgpio_irq_handler; in plgpio_probe()
605 girq->num_parents = 1; in plgpio_probe()
606 girq->parents = devm_kcalloc(&pdev->dev, 1, in plgpio_probe()
607 sizeof(*girq->parents), in plgpio_probe()
609 if (!girq->parents) in plgpio_probe()
610 return -ENOMEM; in plgpio_probe()
611 girq->parents[0] = irq; in plgpio_probe()
612 girq->default_type = IRQ_TYPE_NONE; in plgpio_probe()
613 girq->handler = handle_simple_irq; in plgpio_probe()
614 dev_info(&pdev->dev, "PLGPIO registering with IRQs\n"); in plgpio_probe()
616 dev_info(&pdev->dev, "PLGPIO registering without IRQs\n"); in plgpio_probe()
619 ret = gpiochip_add_data(&plgpio->chip, plgpio); in plgpio_probe()
621 dev_err(&pdev->dev, "unable to add gpio chip\n"); in plgpio_probe()
628 if (!IS_ERR(plgpio->clk)) in plgpio_probe()
629 clk_unprepare(plgpio->clk); in plgpio_probe()
638 int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); in plgpio_suspend()
644 if (plgpio->regs.enb != -1) in plgpio_suspend()
645 regmap_read(plgpio->regmap, plgpio->regs.enb + off, in plgpio_suspend()
646 &plgpio->csave_regs[i].enb); in plgpio_suspend()
647 if (plgpio->regs.eit != -1) in plgpio_suspend()
648 regmap_read(plgpio->regmap, plgpio->regs.eit + off, in plgpio_suspend()
649 &plgpio->csave_regs[i].eit); in plgpio_suspend()
650 regmap_read(plgpio->regmap, plgpio->regs.wdata + off, in plgpio_suspend()
651 &plgpio->csave_regs[i].wdata); in plgpio_suspend()
652 regmap_read(plgpio->regmap, plgpio->regs.dir + off, in plgpio_suspend()
653 &plgpio->csave_regs[i].dir); in plgpio_suspend()
654 regmap_read(plgpio->regmap, plgpio->regs.ie + off, in plgpio_suspend()
655 &plgpio->csave_regs[i].ie); in plgpio_suspend()
665 * bit values (non-plgpio bits), and retain captured value (plgpio bits).
669 regmap_read(plgpio->regmap, plgpio->regs.__reg + _off, &_tmp); \
671 plgpio->csave_regs[i].__reg = \
672 _tmp | (plgpio->csave_regs[i].__reg & _mask); \
678 int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG); in plgpio_resume()
685 if (i == reg_count - 1) { in plgpio_resume()
686 mask = (1 << (plgpio->chip.ngpio - i * in plgpio_resume()
687 MAX_GPIO_PER_REG)) - 1; in plgpio_resume()
689 if (plgpio->regs.enb != -1) in plgpio_resume()
692 if (plgpio->regs.eit != -1) in plgpio_resume()
700 regmap_write(plgpio->regmap, plgpio->regs.wdata + off, in plgpio_resume()
701 plgpio->csave_regs[i].wdata); in plgpio_resume()
703 regmap_write(plgpio->regmap, plgpio->regs.dir + off, in plgpio_resume()
704 plgpio->csave_regs[i].dir); in plgpio_resume()
706 if (plgpio->regs.eit != -1) in plgpio_resume()
707 regmap_write(plgpio->regmap, plgpio->regs.eit + off, in plgpio_resume()
708 plgpio->csave_regs[i].eit); in plgpio_resume()
710 regmap_write(plgpio->regmap, plgpio->regs.ie + off, in plgpio_resume()
711 plgpio->csave_regs[i].ie); in plgpio_resume()
713 if (plgpio->regs.enb != -1) in plgpio_resume()
714 regmap_write(plgpio->regmap, plgpio->regs.enb + off, in plgpio_resume()
715 plgpio->csave_regs[i].enb); in plgpio_resume()
725 { .compatible = "st,spear-plgpio" },
732 .name = "spear-plgpio",