X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fgpio%2Fda8xx_gpio.c;h=507f8b18c21694543ac6502644c2b9c254280b1c;hb=41575d8e4c334df148c4cdd7c40cc825dc0fcaa1;hp=76648d27d426bc9e644378312e010d10629e329d;hpb=412665b46134f93464c09405e02f08ac9c62526d;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index 76648d2..507f8b1 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -1,28 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * GPIO driver for TI DaVinci DA8xx SOCs. * * (C) Copyright 2011 Guralp Systems Ltd. * Laurence Withers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA */ #include +#include +#include +#include #include #include +#include + +#include "da8xx_gpio.h" + +#if !CONFIG_IS_ENABLED(DM_GPIO) #include #include @@ -317,7 +311,7 @@ static const struct pinmux_config gpio_pinmux[] = { #define davinci_configure_pin_mux(a, b) #endif /* CONFIG_SOC_DA8XX */ -int gpio_request(unsigned gpio, const char *label) +int gpio_request(unsigned int gpio, const char *label) { if (gpio >= MAX_NUM_GPIOS) return -1; @@ -334,7 +328,7 @@ int gpio_request(unsigned gpio, const char *label) return 0; } -int gpio_free(unsigned gpio) +int gpio_free(unsigned int gpio) { if (gpio >= MAX_NUM_GPIOS) return -1; @@ -347,42 +341,23 @@ int gpio_free(unsigned gpio) /* Do not configure as input or change pin mux here */ return 0; } +#endif -int gpio_direction_input(unsigned gpio) +static int _gpio_direction_input(struct davinci_gpio *bank, unsigned int gpio) { - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); return 0; } -int gpio_direction_output(unsigned gpio, int value) -{ - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); - clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); - gpio_set_value(gpio, value); - return 0; -} - -int gpio_get_value(unsigned gpio) +static int _gpio_get_value(struct davinci_gpio *bank, unsigned int gpio) { - struct davinci_gpio *bank; unsigned int ip; - - bank = GPIO_BANK(gpio); ip = in_le32(&bank->in_data) & (1U << GPIO_BIT(gpio)); return ip ? 1 : 0; } -int gpio_set_value(unsigned gpio, int value) +static int _gpio_set_value(struct davinci_gpio *bank, unsigned int gpio, int value) { - struct davinci_gpio *bank; - - bank = GPIO_BANK(gpio); - if (value) bank->set_data = 1U << GPIO_BIT(gpio); else @@ -391,14 +366,29 @@ int gpio_set_value(unsigned gpio, int value) return 0; } +static int _gpio_get_dir(struct davinci_gpio *bank, unsigned int gpio) +{ + return in_le32(&bank->dir) & (1U << GPIO_BIT(gpio)); +} + +static int _gpio_direction_output(struct davinci_gpio *bank, unsigned int gpio, + int value) +{ + clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); + _gpio_set_value(bank, gpio, value); + return 0; +} + +#if !CONFIG_IS_ENABLED(DM_GPIO) + void gpio_info(void) { - unsigned gpio, dir, val; + unsigned int gpio, dir, val; struct davinci_gpio *bank; for (gpio = 0; gpio < MAX_NUM_GPIOS; ++gpio) { bank = GPIO_BANK(gpio); - dir = in_le32(&bank->dir) & (1U << GPIO_BIT(gpio)); + dir = _gpio_get_dir(bank, gpio); val = gpio_get_value(gpio); printf("% 4d: %s: %d [%c] %s\n", @@ -407,3 +397,172 @@ void gpio_info(void) gpio_registry[gpio].name); } } + +int gpio_direction_input(unsigned int gpio) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_direction_input(bank, gpio); +} + +int gpio_direction_output(unsigned int gpio, int value) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_direction_output(bank, gpio, value); +} + +int gpio_get_value(unsigned int gpio) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_get_value(bank, gpio); +} + +int gpio_set_value(unsigned int gpio, int value) +{ + struct davinci_gpio *bank; + + bank = GPIO_BANK(gpio); + return _gpio_set_value(bank, gpio, value); +} + +#else /* DM_GPIO */ + +static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio_bank *bank = dev_get_priv(dev); + unsigned long addr; + + /* + * The device tree is not broken into banks but the infrastructure is + * expecting it this way, so we'll first include the 0x10 offset, then + * calculate the bank manually based on the offset. + * Casting 'addr' as Unsigned long is needed to make the math work. + */ + addr = ((unsigned long)(struct davinci_gpio *)bank->base) + + 0x10 + (0x28 * (offset >> 5)); + return (struct davinci_gpio *)addr; +} + +static int davinci_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + /* + * Fetch the address based on GPIO, but only pass the masked low 32-bits + */ + _gpio_direction_input(base, (offset & 0x1f)); + return 0; +} + +static int davinci_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + _gpio_direction_output(base, (offset & 0x1f), value); + return 0; +} + +static int davinci_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + return _gpio_get_value(base, (offset & 0x1f)); +} + +static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + _gpio_set_value(base, (offset & 0x1f), value); + + return 0; +} + +static int davinci_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + unsigned int dir; + struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); + + dir = _gpio_get_dir(base, offset); + + if (dir) + return GPIOF_INPUT; + + return GPIOF_OUTPUT; +} + +static int davinci_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + desc->offset = args->args[0]; + + if (args->args[1] & GPIO_ACTIVE_LOW) + desc->flags = GPIOD_ACTIVE_LOW; + else + desc->flags = 0; + return 0; +} + +static const struct dm_gpio_ops gpio_davinci_ops = { + .direction_input = davinci_gpio_direction_input, + .direction_output = davinci_gpio_direction_output, + .get_value = davinci_gpio_get_value, + .set_value = davinci_gpio_set_value, + .get_function = davinci_gpio_get_function, + .xlate = davinci_gpio_xlate, +}; + +static int davinci_gpio_probe(struct udevice *dev) +{ + struct davinci_gpio_bank *bank = dev_get_priv(dev); + struct davinci_gpio_platdata *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + const void *fdt = gd->fdt_blob; + int node = dev_of_offset(dev); + + uc_priv->bank_name = plat->port_name; + uc_priv->gpio_count = fdtdec_get_int(fdt, node, "ti,ngpio", -1); + bank->base = (struct davinci_gpio *)plat->base; + return 0; +} + +static const struct udevice_id davinci_gpio_ids[] = { + { .compatible = "ti,dm6441-gpio" }, + { .compatible = "ti,k2g-gpio" }, + { .compatible = "ti,keystone-gpio" }, + { } +}; + +static int davinci_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct davinci_gpio_platdata *plat = dev_get_platdata(dev); + fdt_addr_t addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = addr; + return 0; +} + +U_BOOT_DRIVER(ti_dm6441_gpio) = { + .name = "ti_dm6441_gpio", + .id = UCLASS_GPIO, + .ops = &gpio_davinci_ops, + .ofdata_to_platdata = of_match_ptr(davinci_gpio_ofdata_to_platdata), + .of_match = davinci_gpio_ids, + .bind = dm_scan_fdt_dev, + .platdata_auto = sizeof(struct davinci_gpio_platdata), + .probe = davinci_gpio_probe, + .priv_auto = sizeof(struct davinci_gpio_bank), +}; + +#endif