mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									93b1965322
								
							
						
					
					
						commit
						bba76a17bd
					
				
							
								
								
									
										36
									
								
								doc/device-tree-bindings/gpio/gpio-max7320.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								doc/device-tree-bindings/gpio/gpio-max7320.txt
									
									
									
									
									
										Normal 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>;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
@ -183,6 +183,14 @@ config LPC32XX_GPIO
 | 
			
		||||
	help
 | 
			
		||||
	  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
 | 
			
		||||
	bool "MCP230XX GPIO driver"
 | 
			
		||||
	depends on DM
 | 
			
		||||
 | 
			
		||||
@ -68,3 +68,4 @@ obj-$(CONFIG_MSCC_SGPIO)	+= mscc_sgpio.o
 | 
			
		||||
obj-$(CONFIG_NX_GPIO)		+= nx_gpio.o
 | 
			
		||||
obj-$(CONFIG_SIFIVE_GPIO)	+= sifive-gpio.o
 | 
			
		||||
obj-$(CONFIG_NOMADIK_GPIO)	+= nmk_gpio.o
 | 
			
		||||
obj-$(CONFIG_MAX7320_GPIO)	+= max7320_gpio.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								drivers/gpio/max7320_gpio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								drivers/gpio/max7320_gpio.c
									
									
									
									
									
										Normal 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),
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user