uboot/drivers/gpio/max7320_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * max7320 I2C GPIO EXPANDER DRIVER
   4 *
   5 * Copyright (C) 2021 Hannes Schmelzer <oe5hpm@oevsv.at>
   6 * B&R Industrial Automation GmbH - http://www.br-automation.com
   7 *
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <i2c.h>
  13#include <asm-generic/gpio.h>
  14#include <linux/bitops.h>
  15
  16struct max7320_chip {
  17        u32 outreg;
  18};
  19
  20static int max7320_direction_output(struct udevice *dev,
  21                                    unsigned int offset, int value)
  22{
  23        struct max7320_chip *plat = dev_get_plat(dev);
  24        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  25        struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
  26
  27        int ret;
  28
  29        if (value)
  30                plat->outreg |= BIT(offset);
  31        else
  32                plat->outreg &= ~BIT(offset);
  33
  34        ret = dm_i2c_write(dev,
  35                           plat->outreg & 0xff,
  36                           (uint8_t *)&plat->outreg + 1,
  37                           uc_priv->gpio_count > 8 ? 1 : 0);
  38        if (ret)
  39                printf("%s i2c write failed to addr %x\n", __func__,
  40                       chip->chip_addr);
  41
  42        return ret;
  43}
  44
  45static int max7320_get_value(struct udevice *dev, unsigned int offset)
  46{
  47        struct max7320_chip *plat = dev_get_plat(dev);
  48
  49        return (plat->outreg >> offset) & 0x1;
  50}
  51
  52static int max7320_set_value(struct udevice *dev, unsigned int offset,
  53                             int value)
  54{
  55        return max7320_direction_output(dev, offset, value);
  56}
  57
  58static int max7320_get_function(struct udevice *dev, unsigned int offset)
  59{
  60        return GPIOF_OUTPUT;
  61}
  62
  63static int max7320_ofdata_plat(struct udevice *dev)
  64{
  65        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  66
  67        uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", 8);
  68        if (uc_priv->gpio_count > 16) {
  69                printf("%s: max7320 doesn't support more than 16 gpios!",
  70                       __func__);
  71                return -EINVAL;
  72        }
  73
  74        uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
  75                                         "gpio-bank-name", NULL);
  76        if (!uc_priv->bank_name)
  77                uc_priv->bank_name = fdt_get_name(gd->fdt_blob,
  78                                                  dev_of_offset(dev), NULL);
  79
  80        return 0;
  81}
  82
  83static int max7320_gpio_probe(struct udevice  *dev)
  84{
  85        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  86
  87        debug("%s GPIO controller with %d gpios probed\n",
  88              uc_priv->bank_name, uc_priv->gpio_count);
  89
  90        return 0;
  91}
  92
  93static const struct dm_gpio_ops max7320_gpio_ops = {
  94        .direction_output       = max7320_direction_output,
  95        .set_value              = max7320_set_value,
  96        .get_value              = max7320_get_value,
  97        .get_function           = max7320_get_function,
  98};
  99
 100static const struct udevice_id max7320_gpio_ids[] = {
 101        { .compatible = "maxim,max7320" },
 102        { }
 103};
 104
 105U_BOOT_DRIVER(gpio_max7320) = {
 106        .name           = "gpio_max7320",
 107        .id             = UCLASS_GPIO,
 108        .ops            = &max7320_gpio_ops,
 109        .of_match       = max7320_gpio_ids,
 110        .of_to_plat     = max7320_ofdata_plat,
 111        .probe          = max7320_gpio_probe,
 112        .plat_auto      = sizeof(struct max7320_chip),
 113};
 114