drivers/gpio: add support for MAX7320 i2c i/o expander

This commit adds support for the MAX7320 (and clones) gpio expander.

Signed-off-by: Hannes Schmelzer <hannes.schmelzer@br-automation.com>
This commit is contained in:
Hannes Schmelzer 2021-10-01 13:37:57 +02:00 committed by Tom Rini
parent 93b1965322
commit bba76a17bd
4 changed files with 158 additions and 0 deletions

View file

@ -0,0 +1,36 @@
* MAX7320 I/O expanders
The original maxim 7320 i/o expander offers 8 bit push/pull outputs.
There exists some clones which offers 16 bit.
Required Properties:
- compatible: should be one of the following.
- "maxim,max7320"
- reg: I2C slave address.
- gpio-controller: Marks the device node as a gpio controller.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
Optional Properties:
- ngpios: tell the driver how many gpios the device offers.
if the property is omitted, 8bit (original maxim) is assumed.
Please refer to gpio.txt in this directory for details of the common GPIO
bindings used by client devices.
Example: MAX7320 I/O expander node
ledgpio: max7320@5d {
status = "okay";
compatible = "maxim,max7320";
reg = <0x5d>;
#gpio-cells = <2>;
gpio-controller;
ngpios = <16>;
};

View file

@ -183,6 +183,14 @@ config LPC32XX_GPIO
help help
Support for the LPC32XX GPIO driver. Support for the LPC32XX GPIO driver.
config MAX7320_GPIO
bool "MAX7320 I2C GPIO Expander driver"
depends on DM_GPIO && DM_I2C
help
Support for MAX7320 I2C 8/16-bit GPIO expander.
original maxim device has 8 push/pull outputs,
some clones offers 16bit.
config MCP230XX_GPIO config MCP230XX_GPIO
bool "MCP230XX GPIO driver" bool "MCP230XX GPIO driver"
depends on DM depends on DM

View file

@ -68,3 +68,4 @@ obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o
obj-$(CONFIG_NX_GPIO) += nx_gpio.o obj-$(CONFIG_NX_GPIO) += nx_gpio.o
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o

113
drivers/gpio/max7320_gpio.c Normal file
View file

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* max7320 I2C GPIO EXPANDER DRIVER
*
* Copyright (C) 2021 Hannes Schmelzer <oe5hpm@oevsv.at>
* B&R Industrial Automation GmbH - http://www.br-automation.com
*
*/
#include <common.h>
#include <dm.h>
#include <i2c.h>
#include <asm-generic/gpio.h>
#include <linux/bitops.h>
struct max7320_chip {
u32 outreg;
};
static int max7320_direction_output(struct udevice *dev,
unsigned int offset, int value)
{
struct max7320_chip *plat = dev_get_plat(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
int ret;
if (value)
plat->outreg |= BIT(offset);
else
plat->outreg &= ~BIT(offset);
ret = dm_i2c_write(dev,
plat->outreg & 0xff,
(uint8_t *)&plat->outreg + 1,
uc_priv->gpio_count > 8 ? 1 : 0);
if (ret)
printf("%s i2c write failed to addr %x\n", __func__,
chip->chip_addr);
return ret;
}
static int max7320_get_value(struct udevice *dev, unsigned int offset)
{
struct max7320_chip *plat = dev_get_plat(dev);
return (plat->outreg >> offset) & 0x1;
}
static int max7320_set_value(struct udevice *dev, unsigned int offset,
int value)
{
return max7320_direction_output(dev, offset, value);
}
static int max7320_get_function(struct udevice *dev, unsigned int offset)
{
return GPIOF_OUTPUT;
}
static int max7320_ofdata_plat(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", 8);
if (uc_priv->gpio_count > 16) {
printf("%s: max7320 doesn't support more than 16 gpios!",
__func__);
return -EINVAL;
}
uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
"gpio-bank-name", NULL);
if (!uc_priv->bank_name)
uc_priv->bank_name = fdt_get_name(gd->fdt_blob,
dev_of_offset(dev), NULL);
return 0;
}
static int max7320_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
debug("%s GPIO controller with %d gpios probed\n",
uc_priv->bank_name, uc_priv->gpio_count);
return 0;
}
static const struct dm_gpio_ops max7320_gpio_ops = {
.direction_output = max7320_direction_output,
.set_value = max7320_set_value,
.get_value = max7320_get_value,
.get_function = max7320_get_function,
};
static const struct udevice_id max7320_gpio_ids[] = {
{ .compatible = "maxim,max7320" },
{ }
};
U_BOOT_DRIVER(gpio_max7320) = {
.name = "gpio_max7320",
.id = UCLASS_GPIO,
.ops = &max7320_gpio_ops,
.of_match = max7320_gpio_ids,
.of_to_plat = max7320_ofdata_plat,
.probe = max7320_gpio_probe,
.plat_auto = sizeof(struct max7320_chip),
};