Lines Matching +full:reset +full:- +full:mask
1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/mfd/ucb1x00-core.c
11 * to be used on other non-MCP-enabled hardware platforms.
35 * ucb1x00_io_set_dir - set IO direction
54 spin_lock_irqsave(&ucb->io_lock, flags); in ucb1x00_io_set_dir()
55 ucb->io_dir |= out; in ucb1x00_io_set_dir()
56 ucb->io_dir &= ~in; in ucb1x00_io_set_dir()
58 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); in ucb1x00_io_set_dir()
59 spin_unlock_irqrestore(&ucb->io_lock, flags); in ucb1x00_io_set_dir()
63 * ucb1x00_io_write - set or clear IO outputs
70 * The @clear bitfield has priority over the @set bitfield -
82 spin_lock_irqsave(&ucb->io_lock, flags); in ucb1x00_io_write()
83 ucb->io_out |= set; in ucb1x00_io_write()
84 ucb->io_out &= ~clear; in ucb1x00_io_write()
86 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); in ucb1x00_io_write()
87 spin_unlock_irqrestore(&ucb->io_lock, flags); in ucb1x00_io_write()
91 * ucb1x00_io_read - read the current state of the IO pins
112 spin_lock_irqsave(&ucb->io_lock, flags); in ucb1x00_gpio_set()
114 ucb->io_out |= 1 << offset; in ucb1x00_gpio_set()
116 ucb->io_out &= ~(1 << offset); in ucb1x00_gpio_set()
119 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); in ucb1x00_gpio_set()
121 spin_unlock_irqrestore(&ucb->io_lock, flags); in ucb1x00_gpio_set()
141 spin_lock_irqsave(&ucb->io_lock, flags); in ucb1x00_gpio_direction_input()
142 ucb->io_dir &= ~(1 << offset); in ucb1x00_gpio_direction_input()
144 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); in ucb1x00_gpio_direction_input()
146 spin_unlock_irqrestore(&ucb->io_lock, flags); in ucb1x00_gpio_direction_input()
156 unsigned old, mask = 1 << offset; in ucb1x00_gpio_direction_output() local
158 spin_lock_irqsave(&ucb->io_lock, flags); in ucb1x00_gpio_direction_output()
159 old = ucb->io_out; in ucb1x00_gpio_direction_output()
161 ucb->io_out |= mask; in ucb1x00_gpio_direction_output()
163 ucb->io_out &= ~mask; in ucb1x00_gpio_direction_output()
166 if (old != ucb->io_out) in ucb1x00_gpio_direction_output()
167 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); in ucb1x00_gpio_direction_output()
169 if (!(ucb->io_dir & mask)) { in ucb1x00_gpio_direction_output()
170 ucb->io_dir |= mask; in ucb1x00_gpio_direction_output()
171 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); in ucb1x00_gpio_direction_output()
174 spin_unlock_irqrestore(&ucb->io_lock, flags); in ucb1x00_gpio_direction_output()
183 return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO; in ucb1x00_to_irq()
192 * Period between SIB 128-bit frames = 10.7us
196 * ucb1x00_adc_enable - enable the ADC converter
213 mutex_lock(&ucb->adc_mutex); in ucb1x00_adc_enable()
215 ucb->adc_cr |= UCB_ADC_ENA; in ucb1x00_adc_enable()
218 ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); in ucb1x00_adc_enable()
222 * ucb1x00_adc_read - read the specified ADC channel
224 * @adc_channel: ADC channel mask
244 ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel); in ucb1x00_adc_read()
245 ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); in ucb1x00_adc_read()
260 * ucb1x00_adc_disable - disable the ADC converter
267 ucb->adc_cr &= ~UCB_ADC_ENA; in ucb1x00_adc_disable()
268 ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); in ucb1x00_adc_disable()
271 mutex_unlock(&ucb->adc_mutex); in ucb1x00_adc_disable()
278 * Since we need to read an internal register, we must re-enable
294 generic_handle_irq(ucb->irq_base + i); in ucb1x00_irq()
298 static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask) in ucb1x00_irq_update() argument
301 if (ucb->irq_ris_enbl & mask) in ucb1x00_irq_update()
302 ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & in ucb1x00_irq_update()
303 ucb->irq_mask); in ucb1x00_irq_update()
304 if (ucb->irq_fal_enbl & mask) in ucb1x00_irq_update()
305 ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & in ucb1x00_irq_update()
306 ucb->irq_mask); in ucb1x00_irq_update()
317 unsigned mask = 1 << (data->irq - ucb->irq_base); in ucb1x00_irq_mask() local
319 raw_spin_lock(&ucb->irq_lock); in ucb1x00_irq_mask()
320 ucb->irq_mask &= ~mask; in ucb1x00_irq_mask()
321 ucb1x00_irq_update(ucb, mask); in ucb1x00_irq_mask()
322 raw_spin_unlock(&ucb->irq_lock); in ucb1x00_irq_mask()
328 unsigned mask = 1 << (data->irq - ucb->irq_base); in ucb1x00_irq_unmask() local
330 raw_spin_lock(&ucb->irq_lock); in ucb1x00_irq_unmask()
331 ucb->irq_mask |= mask; in ucb1x00_irq_unmask()
332 ucb1x00_irq_update(ucb, mask); in ucb1x00_irq_unmask()
333 raw_spin_unlock(&ucb->irq_lock); in ucb1x00_irq_unmask()
339 unsigned mask = 1 << (data->irq - ucb->irq_base); in ucb1x00_irq_set_type() local
341 raw_spin_lock(&ucb->irq_lock); in ucb1x00_irq_set_type()
343 ucb->irq_ris_enbl |= mask; in ucb1x00_irq_set_type()
345 ucb->irq_ris_enbl &= ~mask; in ucb1x00_irq_set_type()
348 ucb->irq_fal_enbl |= mask; in ucb1x00_irq_set_type()
350 ucb->irq_fal_enbl &= ~mask; in ucb1x00_irq_set_type()
351 if (ucb->irq_mask & mask) { in ucb1x00_irq_set_type()
352 ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & in ucb1x00_irq_set_type()
353 ucb->irq_mask); in ucb1x00_irq_set_type()
354 ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & in ucb1x00_irq_set_type()
355 ucb->irq_mask); in ucb1x00_irq_set_type()
357 raw_spin_unlock(&ucb->irq_lock); in ucb1x00_irq_set_type()
365 struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data; in ucb1x00_irq_set_wake()
366 unsigned mask = 1 << (data->irq - ucb->irq_base); in ucb1x00_irq_set_wake() local
368 if (!pdata || !pdata->can_wakeup) in ucb1x00_irq_set_wake()
369 return -EINVAL; in ucb1x00_irq_set_wake()
371 raw_spin_lock(&ucb->irq_lock); in ucb1x00_irq_set_wake()
373 ucb->irq_wake |= mask; in ucb1x00_irq_set_wake()
375 ucb->irq_wake &= ~mask; in ucb1x00_irq_set_wake()
376 raw_spin_unlock(&ucb->irq_lock); in ucb1x00_irq_set_wake()
397 return -ENOMEM; in ucb1x00_add_dev()
399 dev->ucb = ucb; in ucb1x00_add_dev()
400 dev->drv = drv; in ucb1x00_add_dev()
402 ret = drv->add(dev); in ucb1x00_add_dev()
408 list_add_tail(&dev->dev_node, &ucb->devs); in ucb1x00_add_dev()
409 list_add_tail(&dev->drv_node, &drv->devs); in ucb1x00_add_dev()
416 dev->drv->remove(dev); in ucb1x00_remove_dev()
417 list_del(&dev->dev_node); in ucb1x00_remove_dev()
418 list_del(&dev->drv_node); in ucb1x00_remove_dev()
424 * hard-coded machine dependencies. For reference, the expected
443 unsigned long mask; in ucb1x00_detect_irq() local
445 mask = probe_irq_on(); in ucb1x00_detect_irq()
478 return probe_irq_off(mask); in ucb1x00_detect_irq()
494 struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; in ucb1x00_probe()
498 int ret = -ENODEV; in ucb1x00_probe()
500 /* Tell the platform to deassert the UCB1x00 reset */ in ucb1x00_probe()
501 if (pdata && pdata->reset) in ucb1x00_probe()
502 pdata->reset(UCB_RST_PROBE); in ucb1x00_probe()
514 ret = -ENOMEM; in ucb1x00_probe()
518 device_initialize(&ucb->dev); in ucb1x00_probe()
519 ucb->dev.class = &ucb1x00_class; in ucb1x00_probe()
520 ucb->dev.parent = &mcp->attached_device; in ucb1x00_probe()
521 dev_set_name(&ucb->dev, "ucb1x00"); in ucb1x00_probe()
523 raw_spin_lock_init(&ucb->irq_lock); in ucb1x00_probe()
524 spin_lock_init(&ucb->io_lock); in ucb1x00_probe()
525 mutex_init(&ucb->adc_mutex); in ucb1x00_probe()
527 ucb->id = id; in ucb1x00_probe()
528 ucb->mcp = mcp; in ucb1x00_probe()
530 ret = device_add(&ucb->dev); in ucb1x00_probe()
535 ucb->irq = ucb1x00_detect_irq(ucb); in ucb1x00_probe()
537 if (!ucb->irq) { in ucb1x00_probe()
538 dev_err(&ucb->dev, "IRQ probe failed\n"); in ucb1x00_probe()
539 ret = -ENODEV; in ucb1x00_probe()
543 ucb->gpio.base = -1; in ucb1x00_probe()
544 irq_base = pdata ? pdata->irq_base : 0; in ucb1x00_probe()
545 ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1); in ucb1x00_probe()
546 if (ucb->irq_base < 0) { in ucb1x00_probe()
547 dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n", in ucb1x00_probe()
548 ucb->irq_base); in ucb1x00_probe()
549 ret = ucb->irq_base; in ucb1x00_probe()
554 unsigned irq = ucb->irq_base + i; in ucb1x00_probe()
561 irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING); in ucb1x00_probe()
562 irq_set_chained_handler_and_data(ucb->irq, ucb1x00_irq, ucb); in ucb1x00_probe()
564 if (pdata && pdata->gpio_base) { in ucb1x00_probe()
565 ucb->gpio.label = dev_name(&ucb->dev); in ucb1x00_probe()
566 ucb->gpio.parent = &ucb->dev; in ucb1x00_probe()
567 ucb->gpio.owner = THIS_MODULE; in ucb1x00_probe()
568 ucb->gpio.base = pdata->gpio_base; in ucb1x00_probe()
569 ucb->gpio.ngpio = 10; in ucb1x00_probe()
570 ucb->gpio.set = ucb1x00_gpio_set; in ucb1x00_probe()
571 ucb->gpio.get = ucb1x00_gpio_get; in ucb1x00_probe()
572 ucb->gpio.direction_input = ucb1x00_gpio_direction_input; in ucb1x00_probe()
573 ucb->gpio.direction_output = ucb1x00_gpio_direction_output; in ucb1x00_probe()
574 ucb->gpio.to_irq = ucb1x00_to_irq; in ucb1x00_probe()
575 ret = gpiochip_add_data(&ucb->gpio, ucb); in ucb1x00_probe()
579 dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); in ucb1x00_probe()
584 device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup); in ucb1x00_probe()
586 INIT_LIST_HEAD(&ucb->devs); in ucb1x00_probe()
588 list_add_tail(&ucb->node, &ucb1x00_devices); in ucb1x00_probe()
597 irq_set_chained_handler(ucb->irq, NULL); in ucb1x00_probe()
599 if (ucb->irq_base > 0) in ucb1x00_probe()
600 irq_free_descs(ucb->irq_base, 16); in ucb1x00_probe()
602 device_del(&ucb->dev); in ucb1x00_probe()
604 put_device(&ucb->dev); in ucb1x00_probe()
606 if (pdata && pdata->reset) in ucb1x00_probe()
607 pdata->reset(UCB_RST_PROBE_FAIL); in ucb1x00_probe()
613 struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; in ucb1x00_remove()
618 list_del(&ucb->node); in ucb1x00_remove()
619 list_for_each_safe(l, n, &ucb->devs) { in ucb1x00_remove()
625 if (ucb->gpio.base != -1) in ucb1x00_remove()
626 gpiochip_remove(&ucb->gpio); in ucb1x00_remove()
628 irq_set_chained_handler(ucb->irq, NULL); in ucb1x00_remove()
629 irq_free_descs(ucb->irq_base, 16); in ucb1x00_remove()
630 device_unregister(&ucb->dev); in ucb1x00_remove()
632 if (pdata && pdata->reset) in ucb1x00_remove()
633 pdata->reset(UCB_RST_REMOVE); in ucb1x00_remove()
640 INIT_LIST_HEAD(&drv->devs); in ucb1x00_register_driver()
642 list_add_tail(&drv->node, &ucb1x00_drivers); in ucb1x00_register_driver()
655 list_del(&drv->node); in ucb1x00_unregister_driver()
656 list_for_each_safe(l, n, &drv->devs) { in ucb1x00_unregister_driver()
670 list_for_each_entry(udev, &ucb->devs, dev_node) { in ucb1x00_suspend()
671 if (udev->drv->suspend) in ucb1x00_suspend()
672 udev->drv->suspend(udev); in ucb1x00_suspend()
676 if (ucb->irq_wake) { in ucb1x00_suspend()
679 raw_spin_lock_irqsave(&ucb->irq_lock, flags); in ucb1x00_suspend()
681 ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & in ucb1x00_suspend()
682 ucb->irq_wake); in ucb1x00_suspend()
683 ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & in ucb1x00_suspend()
684 ucb->irq_wake); in ucb1x00_suspend()
686 raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); in ucb1x00_suspend()
688 enable_irq_wake(ucb->irq); in ucb1x00_suspend()
689 } else if (pdata && pdata->reset) in ucb1x00_suspend()
690 pdata->reset(UCB_RST_SUSPEND); in ucb1x00_suspend()
701 if (!ucb->irq_wake && pdata && pdata->reset) in ucb1x00_resume()
702 pdata->reset(UCB_RST_RESUME); in ucb1x00_resume()
705 ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); in ucb1x00_resume()
706 ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); in ucb1x00_resume()
708 if (ucb->irq_wake) { in ucb1x00_resume()
711 raw_spin_lock_irqsave(&ucb->irq_lock, flags); in ucb1x00_resume()
712 ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl & in ucb1x00_resume()
713 ucb->irq_mask); in ucb1x00_resume()
714 ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl & in ucb1x00_resume()
715 ucb->irq_mask); in ucb1x00_resume()
716 raw_spin_unlock_irqrestore(&ucb->irq_lock, flags); in ucb1x00_resume()
718 disable_irq_wake(ucb->irq); in ucb1x00_resume()
723 list_for_each_entry(udev, &ucb->devs, dev_node) { in ucb1x00_resume()
724 if (udev->drv->resume) in ucb1x00_resume()
725 udev->drv->resume(udev); in ucb1x00_resume()