X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fgpio%2Fomap_gpio.c;h=cd960dc013f0f128be8d625aab83996e3863eb65;hb=42c91c10c52a3f3512ad5c5e906bc118349bbff5;hp=fc89f2a42b12b0c8690a80e52d5842b5902e9e0a;hpb=6e2fbdea1b26d75314d87c380a36b0015bf824cf;p=oweals%2Fu-boot.git diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index fc89f2a42b..cd960dc013 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -2,20 +2,7 @@ * Copyright (c) 2009 Wind River Systems, Inc. * Tom Rix * - * 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 + * SPDX-License-Identifier: GPL-2.0 * * This work is derived from the linux 2.6.27 kernel source * To fetch, use the kernel repository @@ -30,45 +17,39 @@ * * Copyright (C) 2003-2005 Nokia Corporation * Written by Juha Yrjölä - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include +#include +#include #include #include #include +#include + +DECLARE_GLOBAL_DATA_PTR; #define OMAP_GPIO_DIR_OUT 0 #define OMAP_GPIO_DIR_IN 1 -static inline const struct gpio_bank *get_gpio_bank(int gpio) -{ - return &omap_gpio_bank[gpio >> 5]; -} +#ifdef CONFIG_DM_GPIO + +#define GPIO_PER_BANK 32 + +struct gpio_bank { + /* TODO(sjg@chromium.org): Can we use a struct here? */ + void *base; /* address of registers in physical memory */ +}; + +#endif static inline int get_gpio_index(int gpio) { return gpio & 0x1f; } -static inline int gpio_valid(int gpio) -{ - if (gpio < 0) - return -1; - if (gpio < 192) - return 0; - return -1; -} - -static int check_gpio(int gpio) +int gpio_is_valid(int gpio) { - if (gpio_valid(gpio) < 0) { - printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); - return -1; - } - return 0; + return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); } static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, @@ -77,13 +58,8 @@ static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, void *reg = bank->base; u32 l; - switch (bank->method) { - case METHOD_GPIO_24XX: - reg += OMAP_GPIO_OE; - break; - default: - return; - } + reg += OMAP_GPIO_OE; + l = __raw_readl(reg); if (is_input) l |= 1 << gpio; @@ -101,13 +77,7 @@ static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) void *reg = bank->base; u32 v; - switch (bank->method) { - case METHOD_GPIO_24XX: - reg += OMAP_GPIO_OE; - break; - default: - return -1; - } + reg += OMAP_GPIO_OE; v = __raw_readl(reg); @@ -123,20 +93,49 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, void *reg = bank->base; u32 l = 0; - switch (bank->method) { - case METHOD_GPIO_24XX: - if (enable) - reg += OMAP_GPIO_SETDATAOUT; - else - reg += OMAP_GPIO_CLEARDATAOUT; - l = 1 << gpio; + if (enable) + reg += OMAP_GPIO_SETDATAOUT; + else + reg += OMAP_GPIO_CLEARDATAOUT; + + l = 1 << gpio; + __raw_writel(l, reg); +} + +static int _get_gpio_value(const struct gpio_bank *bank, int gpio) +{ + void *reg = bank->base; + int input; + + input = _get_gpio_direction(bank, gpio); + switch (input) { + case OMAP_GPIO_DIR_IN: + reg += OMAP_GPIO_DATAIN; + break; + case OMAP_GPIO_DIR_OUT: + reg += OMAP_GPIO_DATAOUT; break; default: - printf("omap3-gpio unknown bank method %s %d\n", - __FILE__, __LINE__); - return; + return -1; } - __raw_writel(l, reg); + + return (__raw_readl(reg) & (1 << gpio)) != 0; +} + +#ifndef CONFIG_DM_GPIO + +static inline const struct gpio_bank *get_gpio_bank(int gpio) +{ + return &omap_gpio_bank[gpio >> 5]; +} + +static int check_gpio(int gpio) +{ + if (!gpio_is_valid(gpio)) { + printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); + return -1; + } + return 0; } /** @@ -160,32 +159,12 @@ int gpio_set_value(unsigned gpio, int value) int gpio_get_value(unsigned gpio) { const struct gpio_bank *bank; - void *reg; - int input; if (check_gpio(gpio) < 0) return -1; bank = get_gpio_bank(gpio); - reg = bank->base; - switch (bank->method) { - case METHOD_GPIO_24XX: - input = _get_gpio_direction(bank, get_gpio_index(gpio)); - switch (input) { - case OMAP_GPIO_DIR_IN: - reg += OMAP_GPIO_DATAIN; - break; - case OMAP_GPIO_DIR_OUT: - reg += OMAP_GPIO_DATAOUT; - break; - default: - return -1; - } - break; - default: - return -1; - } - return (__raw_readl(reg) - & (1 << get_gpio_index(gpio))) != 0; + + return _get_gpio_value(bank, get_gpio_index(gpio)); } /** @@ -241,3 +220,127 @@ int gpio_free(unsigned gpio) { return 0; } + +#else /* new driver model interface CONFIG_DM_GPIO */ + +/* set GPIO pin 'gpio' as an input */ +static int omap_gpio_direction_input(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + /* Configure GPIO direction as input. */ + _set_gpio_direction(bank, offset, 1); + + return 0; +} + +/* set GPIO pin 'gpio' as an output, with polarity 'value' */ +static int omap_gpio_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + _set_gpio_dataout(bank, offset, value); + _set_gpio_direction(bank, offset, 0); + + return 0; +} + +/* read GPIO IN value of pin 'gpio' */ +static int omap_gpio_get_value(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + return _get_gpio_value(bank, offset); +} + +/* write GPIO OUT value to pin 'gpio' */ +static int omap_gpio_set_value(struct udevice *dev, unsigned offset, + int value) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + _set_gpio_dataout(bank, offset, value); + + return 0; +} + +static int omap_gpio_get_function(struct udevice *dev, unsigned offset) +{ + struct gpio_bank *bank = dev_get_priv(dev); + + /* GPIOF_FUNC is not implemented yet */ + if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops gpio_omap_ops = { + .direction_input = omap_gpio_direction_input, + .direction_output = omap_gpio_direction_output, + .get_value = omap_gpio_get_value, + .set_value = omap_gpio_set_value, + .get_function = omap_gpio_get_function, +}; + +static int omap_gpio_probe(struct udevice *dev) +{ + struct gpio_bank *bank = dev_get_priv(dev); + struct omap_gpio_platdata *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->bank_name = plat->port_name; + uc_priv->gpio_count = GPIO_PER_BANK; + bank->base = (void *)plat->base; + + return 0; +} + +static int omap_gpio_bind(struct udevice *dev) +{ + struct omap_gpio_platdata *plat = dev->platdata; + fdt_addr_t base_addr; + + if (plat) + return 0; + + base_addr = dev_get_addr(dev); + if (base_addr == FDT_ADDR_T_NONE) + return -ENODEV; + + /* + * TODO: + * When every board is converted to driver model and DT is + * supported, this can be done by auto-alloc feature, but + * not using calloc to alloc memory for platdata. + */ + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->base = base_addr; + plat->port_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL); + dev->platdata = plat; + + return 0; +} + +static const struct udevice_id omap_gpio_ids[] = { + { .compatible = "ti,omap3-gpio" }, + { .compatible = "ti,omap4-gpio" }, + { .compatible = "ti,am4372-gpio" }, + { } +}; + +U_BOOT_DRIVER(gpio_omap) = { + .name = "gpio_omap", + .id = UCLASS_GPIO, + .ops = &gpio_omap_ops, + .of_match = omap_gpio_ids, + .bind = omap_gpio_bind, + .probe = omap_gpio_probe, + .priv_auto_alloc_size = sizeof(struct gpio_bank), +}; + +#endif /* CONFIG_DM_GPIO */