Lines Matching +full:first +full:- +full:data +full:- +full:gpios
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:
28 * The GPIO "subchip" supports 18 GPIOs which can be configured as
35 * There are also two LED pins used sometimes as output-only GPIOs.
50 /* Mask for GPIO registers when aggregated into a 32-bit integer */
64 /*----------------------------------------------------------------------*/
69 static inline int gpio_twl4030_write(u8 address, u8 data) in gpio_twl4030_write() argument
71 return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address); in gpio_twl4030_write()
74 /*----------------------------------------------------------------------*/
99 /*----------------------------------------------------------------------*/
106 u8 data; in gpio_twl4030_read() local
109 ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address); in gpio_twl4030_read()
110 return (ret < 0) ? ret : data; in gpio_twl4030_read()
113 /*----------------------------------------------------------------------*/
203 /*----------------------------------------------------------------------*/
210 mutex_lock(&priv->mutex); in twl_request()
212 /* Support the two LED outputs as output-only GPIOs. */ in twl_request()
218 offset -= TWL4030_GPIO_MAX; in twl_request()
224 /* initialize PWM to always-drive */ in twl_request()
225 /* Configure PWM OFF register first */ in twl_request()
235 /* init LED to not-driven (high) */ in twl_request()
250 /* on first use, turn GPIO module "on" */ in twl_request()
251 if (!priv->usage_count) { in twl_request()
255 /* optionally have the first two GPIOs switch vMMC1 in twl_request()
258 pdata = dev_get_platdata(chip->parent); in twl_request()
260 value |= pdata->mmc_cd & 0x03; in twl_request()
267 priv->usage_count |= BIT(offset); in twl_request()
269 mutex_unlock(&priv->mutex); in twl_request()
277 mutex_lock(&priv->mutex); in twl_free()
279 twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); in twl_free()
283 priv->usage_count &= ~BIT(offset); in twl_free()
286 if (!priv->usage_count) in twl_free()
290 mutex_unlock(&priv->mutex); in twl_free()
298 mutex_lock(&priv->mutex); in twl_direction_in()
302 ret = -EINVAL; /* LED outputs can't be set as input */ in twl_direction_in()
305 priv->direction &= ~BIT(offset); in twl_direction_in()
307 mutex_unlock(&priv->mutex); in twl_direction_in()
318 mutex_lock(&priv->mutex); in twl_get()
319 if (!(priv->usage_count & BIT(offset))) { in twl_get()
320 ret = -EPERM; in twl_get()
324 if (priv->direction & BIT(offset)) in twl_get()
325 status = priv->out_state & BIT(offset); in twl_get()
331 mutex_unlock(&priv->mutex); in twl_get()
339 mutex_lock(&priv->mutex); in twl_set()
343 twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); in twl_set()
346 priv->out_state |= BIT(offset); in twl_set()
348 priv->out_state &= ~BIT(offset); in twl_set()
350 mutex_unlock(&priv->mutex); in twl_set()
358 mutex_lock(&priv->mutex); in twl_direction_out()
362 mutex_unlock(&priv->mutex); in twl_direction_out()
368 * LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output in twl_direction_out()
371 priv->direction |= BIT(offset); in twl_direction_out()
372 mutex_unlock(&priv->mutex); in twl_direction_out()
384 * LED GPIOs >= TWL4030_GPIO_MAX are always output in twl_get_direction()
388 mutex_lock(&priv->mutex); in twl_get_direction()
392 mutex_unlock(&priv->mutex); in twl_get_direction()
396 mutex_unlock(&priv->mutex); in twl_get_direction()
405 return (priv->irq_base && (offset < TWL4030_GPIO_MAX)) in twl_to_irq()
406 ? (priv->irq_base + offset) in twl_to_irq()
407 : -EINVAL; in twl_to_irq()
424 /*----------------------------------------------------------------------*/
432 * We should have data that's specific to this board. in gpio_twl4030_pulls()
482 omap_twl_info->use_leds = of_property_read_bool(dev->of_node, in of_gpio_twl4030()
483 "ti,use-leds"); in of_gpio_twl4030()
485 of_property_read_u32(dev->of_node, "ti,debounce", in of_gpio_twl4030()
486 &omap_twl_info->debounce); in of_gpio_twl4030()
487 of_property_read_u32(dev->of_node, "ti,mmc-cd", in of_gpio_twl4030()
488 (u32 *)&omap_twl_info->mmc_cd); in of_gpio_twl4030()
489 of_property_read_u32(dev->of_node, "ti,pullups", in of_gpio_twl4030()
490 &omap_twl_info->pullups); in of_gpio_twl4030()
491 of_property_read_u32(dev->of_node, "ti,pulldowns", in of_gpio_twl4030()
492 &omap_twl_info->pulldowns); in of_gpio_twl4030()
499 struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); in gpio_twl4030_probe()
500 struct device_node *node = pdev->dev.of_node; in gpio_twl4030_probe()
504 priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv), in gpio_twl4030_probe()
507 return -ENOMEM; in gpio_twl4030_probe()
511 dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); in gpio_twl4030_probe()
515 irq_base = devm_irq_alloc_descs(&pdev->dev, -1, in gpio_twl4030_probe()
518 dev_err(&pdev->dev, "Failed to alloc irq_descs\n"); in gpio_twl4030_probe()
525 ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); in gpio_twl4030_probe()
529 priv->irq_base = irq_base; in gpio_twl4030_probe()
532 priv->gpio_chip = template_chip; in gpio_twl4030_probe()
533 priv->gpio_chip.base = -1; in gpio_twl4030_probe()
534 priv->gpio_chip.ngpio = TWL4030_GPIO_MAX; in gpio_twl4030_probe()
535 priv->gpio_chip.parent = &pdev->dev; in gpio_twl4030_probe()
537 mutex_init(&priv->mutex); in gpio_twl4030_probe()
540 pdata = of_gpio_twl4030(&pdev->dev, pdata); in gpio_twl4030_probe()
543 dev_err(&pdev->dev, "Platform data is missing\n"); in gpio_twl4030_probe()
544 return -ENXIO; in gpio_twl4030_probe()
549 * and pulldowns correctly ... default for non-ULPI pins is in gpio_twl4030_probe()
553 ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns); in gpio_twl4030_probe()
555 dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n", in gpio_twl4030_probe()
556 pdata->pullups, pdata->pulldowns, ret); in gpio_twl4030_probe()
558 ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd); in gpio_twl4030_probe()
560 dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n", in gpio_twl4030_probe()
561 pdata->debounce, pdata->mmc_cd, ret); in gpio_twl4030_probe()
567 if (pdata->use_leds) in gpio_twl4030_probe()
568 priv->gpio_chip.ngpio += 2; in gpio_twl4030_probe()
570 ret = gpiochip_add_data(&priv->gpio_chip, priv); in gpio_twl4030_probe()
572 dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); in gpio_twl4030_probe()
573 priv->gpio_chip.ngpio = 0; in gpio_twl4030_probe()
580 if (pdata->setup) { in gpio_twl4030_probe()
583 status = pdata->setup(&pdev->dev, priv->gpio_chip.base, in gpio_twl4030_probe()
586 dev_dbg(&pdev->dev, "setup --> %d\n", status); in gpio_twl4030_probe()
596 struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); in gpio_twl4030_remove()
600 if (pdata && pdata->teardown) { in gpio_twl4030_remove()
601 status = pdata->teardown(&pdev->dev, priv->gpio_chip.base, in gpio_twl4030_remove()
604 dev_dbg(&pdev->dev, "teardown --> %d\n", status); in gpio_twl4030_remove()
609 gpiochip_remove(&priv->gpio_chip); in gpio_twl4030_remove()
616 return -EIO; in gpio_twl4030_remove()
620 { .compatible = "ti,twl4030-gpio", },
625 /* Note: this hardware lives inside an I2C-based multi-function device. */