Lines Matching +full:twl4030 +full:- +full:gpio
1 // SPDX-License-Identifier: GPL-2.0+
3 * Access to GPIOs on TWL4030/TPS659x0 chips
5 * Copyright (C) 2006-2007 Texas Instruments, Inc.
8 * Code re-arranged and cleaned up by:
20 #include <linux/gpio/machine.h>
21 #include <linux/gpio/driver.h>
22 #include <linux/gpio/consumer.h>
30 * The GPIO "subchip" supports 18 GPIOs which can be configured as
32 * GPIO can trigger interrupts on either or both edges.
34 * GPIO interrupts can be fed to either of two IRQ lines; this is
37 * There are also two LED pins used sometimes as output-only GPIOs.
52 /* Mask for GPIO registers when aggregated into a 32-bit integer */
66 /*----------------------------------------------------------------------*/
69 * To configure TWL4030 GPIO module registers
76 /*----------------------------------------------------------------------*/
101 /*----------------------------------------------------------------------*/
104 * To read a TWL4030 GPIO module register
115 /*----------------------------------------------------------------------*/
139 static int twl4030_set_gpio_direction(int gpio, int is_input) in twl4030_set_gpio_direction() argument
141 u8 d_bnk = gpio >> 3; in twl4030_set_gpio_direction()
142 u8 d_msk = BIT(gpio & 0x7); in twl4030_set_gpio_direction()
159 static int twl4030_get_gpio_direction(int gpio) in twl4030_get_gpio_direction() argument
161 u8 d_bnk = gpio >> 3; in twl4030_get_gpio_direction()
162 u8 d_msk = BIT(gpio & 0x7); in twl4030_get_gpio_direction()
176 static int twl4030_set_gpio_dataout(int gpio, int enable) in twl4030_set_gpio_dataout() argument
178 u8 d_bnk = gpio >> 3; in twl4030_set_gpio_dataout()
179 u8 d_msk = BIT(gpio & 0x7); in twl4030_set_gpio_dataout()
190 static int twl4030_get_gpio_datain(int gpio) in twl4030_get_gpio_datain() argument
192 u8 d_bnk = gpio >> 3; in twl4030_get_gpio_datain()
193 u8 d_off = gpio & 0x7; in twl4030_get_gpio_datain()
205 /*----------------------------------------------------------------------*/
212 mutex_lock(&priv->mutex); in twl_request()
214 /* Support the two LED outputs as output-only GPIOs. */ in twl_request()
220 offset -= TWL4030_GPIO_MAX; in twl_request()
226 /* initialize PWM to always-drive */ in twl_request()
237 /* init LED to not-driven (high) */ in twl_request()
252 /* on first use, turn GPIO module "on" */ in twl_request()
253 if (!priv->usage_count) { in twl_request()
260 pdata = dev_get_platdata(chip->parent); in twl_request()
262 value |= pdata->mmc_cd & 0x03; in twl_request()
269 priv->usage_count |= BIT(offset); in twl_request()
271 mutex_unlock(&priv->mutex); in twl_request()
279 mutex_lock(&priv->mutex); in twl_free()
281 WARN_ON_ONCE(twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1)); in twl_free()
285 priv->usage_count &= ~BIT(offset); in twl_free()
287 /* on last use, switch off GPIO module */ in twl_free()
288 if (!priv->usage_count) in twl_free()
292 mutex_unlock(&priv->mutex); in twl_free()
300 mutex_lock(&priv->mutex); in twl_direction_in()
304 ret = -EINVAL; /* LED outputs can't be set as input */ in twl_direction_in()
307 priv->direction &= ~BIT(offset); in twl_direction_in()
309 mutex_unlock(&priv->mutex); in twl_direction_in()
320 mutex_lock(&priv->mutex); in twl_get()
321 if (!(priv->usage_count & BIT(offset))) { in twl_get()
322 ret = -EPERM; in twl_get()
326 if (priv->direction & BIT(offset)) in twl_get()
327 status = priv->out_state & BIT(offset); in twl_get()
333 mutex_unlock(&priv->mutex); in twl_get()
342 mutex_lock(&priv->mutex); in twl_set()
346 ret = twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); in twl_set()
349 priv->out_state |= BIT(offset); in twl_set()
351 priv->out_state &= ~BIT(offset); in twl_set()
353 mutex_unlock(&priv->mutex); in twl_set()
363 mutex_lock(&priv->mutex); in twl_direction_out()
367 mutex_unlock(&priv->mutex); in twl_direction_out()
376 priv->direction |= BIT(offset); in twl_direction_out()
377 mutex_unlock(&priv->mutex); in twl_direction_out()
391 mutex_lock(&priv->mutex); in twl_get_direction()
395 mutex_unlock(&priv->mutex); in twl_get_direction()
399 mutex_unlock(&priv->mutex); in twl_get_direction()
408 return (priv->irq_base && (offset < TWL4030_GPIO_MAX)) in twl_to_irq()
409 ? (priv->irq_base + offset) in twl_to_irq()
410 : -EINVAL; in twl_to_irq()
414 .label = "twl4030",
427 /*----------------------------------------------------------------------*/
479 omap_twl_info->use_leds = of_property_read_bool(dev->of_node, in of_gpio_twl4030()
480 "ti,use-leds"); in of_gpio_twl4030()
482 of_property_read_u32(dev->of_node, "ti,debounce", in of_gpio_twl4030()
483 &omap_twl_info->debounce); in of_gpio_twl4030()
484 of_property_read_u32(dev->of_node, "ti,mmc-cd", in of_gpio_twl4030()
485 (u32 *)&omap_twl_info->mmc_cd); in of_gpio_twl4030()
486 of_property_read_u32(dev->of_node, "ti,pullups", in of_gpio_twl4030()
487 &omap_twl_info->pullups); in of_gpio_twl4030()
488 of_property_read_u32(dev->of_node, "ti,pulldowns", in of_gpio_twl4030()
489 &omap_twl_info->pulldowns); in of_gpio_twl4030()
509 priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv), in gpio_twl4030_probe()
512 return -ENOMEM; in gpio_twl4030_probe()
516 dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); in gpio_twl4030_probe()
520 irq_base = devm_irq_alloc_descs(&pdev->dev, -1, in gpio_twl4030_probe()
523 dev_err(&pdev->dev, "Failed to alloc irq_descs\n"); in gpio_twl4030_probe()
527 irq_domain_create_legacy(dev_fwnode(&pdev->dev), TWL4030_GPIO_MAX, irq_base, 0, in gpio_twl4030_probe()
530 ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); in gpio_twl4030_probe()
534 priv->irq_base = irq_base; in gpio_twl4030_probe()
537 priv->gpio_chip = template_chip; in gpio_twl4030_probe()
538 priv->gpio_chip.base = -1; in gpio_twl4030_probe()
539 priv->gpio_chip.ngpio = TWL4030_GPIO_MAX; in gpio_twl4030_probe()
540 priv->gpio_chip.parent = &pdev->dev; in gpio_twl4030_probe()
542 mutex_init(&priv->mutex); in gpio_twl4030_probe()
544 pdata = of_gpio_twl4030(&pdev->dev); in gpio_twl4030_probe()
546 dev_err(&pdev->dev, "Platform data is missing\n"); in gpio_twl4030_probe()
547 return -ENXIO; in gpio_twl4030_probe()
552 * and pulldowns correctly ... default for non-ULPI pins is in gpio_twl4030_probe()
556 ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); in gpio_twl4030_probe()
558 dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", in gpio_twl4030_probe()
559 pdata->pullups, pdata->pulldowns, ret); in gpio_twl4030_probe()
561 ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd); in gpio_twl4030_probe()
563 dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n", in gpio_twl4030_probe()
564 pdata->debounce, pdata->mmc_cd, ret); in gpio_twl4030_probe()
570 if (pdata->use_leds) in gpio_twl4030_probe()
571 priv->gpio_chip.ngpio += 2; in gpio_twl4030_probe()
573 ret = devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, priv); in gpio_twl4030_probe()
575 dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); in gpio_twl4030_probe()
576 priv->gpio_chip.ngpio = 0; in gpio_twl4030_probe()
582 * GPIO. in gpio_twl4030_probe()
585 of_machine_is_compatible("compulab,omap3-sbc-t3730")) { in gpio_twl4030_probe()
588 d = gpiochip_request_own_desc(&priv->gpio_chip, in gpio_twl4030_probe()
593 return dev_err_probe(&pdev->dev, PTR_ERR(d), in gpio_twl4030_probe()
594 "unable to hog wlan pwr GPIO\n"); in gpio_twl4030_probe()
598 ret = devm_add_action_or_reset(&pdev->dev, gpio_twl4030_power_off_action, d); in gpio_twl4030_probe()
600 return dev_err_probe(&pdev->dev, ret, in gpio_twl4030_probe()
609 { .compatible = "ti,twl4030-gpio", },
614 /* Note: this hardware lives inside an I2C-based multi-function device. */
638 MODULE_DESCRIPTION("GPIO interface for TWL4030");