summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorYe.Li <B37916@freescale.com>2014-01-13 16:27:39 +0800
committerMax Krummenacher <max.krummenacher@toradex.com>2016-03-09 14:42:01 +0100
commit3be7a01cf43437e4d405f21c143c2a60f2d90a2f (patch)
treed3bef08410df6bc4715051f90da05ae3ba9e0c24 /drivers
parent6d10f71152be50ac275204eab774f4c4dcac7242 (diff)
ENGR00315499-18 driver:MAX7310: Add GPIO expander driver for MAX7310
Implement simple functionalities for MAX7310 GPIO input and output. Because MAX7310 is a off-chip device and need to co-exist with on-chip GPIO, new APIs are added specifically for expander device. CONFIG_MAX7310_IOEXP is used to enable the MAX7310 driver. The I2C related configurations also need to set together. Signed-off-by: Ye.Li <B37916@freescale.com> Signed-off-by: Nitin Garg <nitin.garg@freescale.com> (cherry picked from commit e3b699dab2c92268799b56c28c6a8fcda4f6110b) Signed-off-by: Peng Fan <Peng.Fan@freescale.com> Conflicts: drivers/gpio/Makefile
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/max7310_ioexp.c167
2 files changed, 168 insertions, 0 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 62c73042b7..1072a46f6f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -42,4 +42,5 @@ obj-$(CONFIG_TCA642X) += tca642x.o
oby-$(CONFIG_SX151X) += sx151x.o
obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o
obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o
+obj-$(CONFIG_MAX7310_IOEXP) += max7310_ioexp.o
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
diff --git a/drivers/gpio/max7310_ioexp.c b/drivers/gpio/max7310_ioexp.c
new file mode 100644
index 0000000000..34c494f753
--- /dev/null
+++ b/drivers/gpio/max7310_ioexp.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+#include <gpio_exp.h>
+
+#define MAX7310_REG_INPUT_PORT 0x00
+#define MAX7310_REG_OUTPUT_PORT 0x01
+#define MAX7310_REG_POLARITY 0x02
+#define MAX7310_REG_CONFIGURATION 0x03
+#define MAX7310_REG_TIMEOUT 0x04
+
+enum max7310_gpio_direction {
+ MAX7310_GPIO_DIRECTION_IN,
+ MAX7310_GPIO_DIRECTION_OUT,
+};
+
+struct max7310_config_struct {
+ int i2c_slave_addr;
+ int i2c_bus_id;
+};
+
+static struct max7310_config_struct max7310_configs[CONFIG_IOEXP_DEVICES_NUM];
+
+
+static int max7310_gpio_direction(unsigned int gpio,
+ enum max7310_gpio_direction direction)
+{
+ unsigned int dev = IOEXP_GPIO_TO_DEVICE(gpio);
+ unsigned int pin = IOEXP_GPIO_TO_PIN(gpio);
+ unsigned char value, val2, val3;
+ unsigned char chip;
+
+ if (dev >= CONFIG_IOEXP_DEVICES_NUM)
+ return -EPERM;
+
+ chip = max7310_configs[dev].i2c_slave_addr;
+
+ i2c_set_bus_num(max7310_configs[dev].i2c_bus_id);
+ if (i2c_probe(chip))
+ return -ENXIO;
+
+ i2c_read(chip, MAX7310_REG_CONFIGURATION, 1, &value, 1);
+
+ switch (direction) {
+ case MAX7310_GPIO_DIRECTION_OUT:
+ value &= ~(1 << pin);
+ i2c_write(chip, MAX7310_REG_CONFIGURATION, 1, &value, 1);
+ break;
+ case MAX7310_GPIO_DIRECTION_IN:
+
+ i2c_read(chip, MAX7310_REG_POLARITY, 1, &val2, 1);
+ i2c_read(chip, MAX7310_REG_OUTPUT_PORT, 1, &val3, 1);
+
+ value |= (1 << pin);
+ val2 &= ~(1 << pin);
+ val3 &= ~(1 << pin);
+
+ i2c_write(chip, MAX7310_REG_POLARITY, 1, &val2, 1);
+ i2c_write(chip, MAX7310_REG_CONFIGURATION, 1, &value, 1);
+ i2c_write(chip, MAX7310_REG_OUTPUT_PORT, 1, &val3, 1);
+
+ break;
+ }
+
+ return 0;
+}
+
+static int max7310_gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int dev = IOEXP_GPIO_TO_DEVICE(gpio);
+ unsigned int pin = IOEXP_GPIO_TO_PIN(gpio);
+ unsigned char reg_val;
+ unsigned char chip;
+
+ if (dev >= CONFIG_IOEXP_DEVICES_NUM)
+ return -EPERM;
+
+ chip = max7310_configs[dev].i2c_slave_addr;
+
+ i2c_set_bus_num(max7310_configs[dev].i2c_bus_id);
+ if (i2c_probe(chip))
+ return -ENXIO;
+
+ i2c_read(chip, MAX7310_REG_OUTPUT_PORT, 1, &reg_val, 1);
+
+ if (value)
+ reg_val |= 1 << pin;
+ else
+ reg_val &= ~(1 << pin);
+
+ i2c_write(chip, MAX7310_REG_OUTPUT_PORT, 1, &reg_val, 1);
+
+ return 0;
+}
+
+static int max7310_gpio_get_value(unsigned gpio)
+{
+ unsigned int dev = IOEXP_GPIO_TO_DEVICE(gpio);
+ unsigned int pin = IOEXP_GPIO_TO_PIN(gpio);
+ unsigned char reg_val;
+ unsigned char chip;
+
+ if (dev >= CONFIG_IOEXP_DEVICES_NUM)
+ return -EPERM;
+
+ chip = max7310_configs[dev].i2c_slave_addr;
+
+ i2c_set_bus_num(max7310_configs[dev].i2c_bus_id);
+ if (i2c_probe(chip))
+ return -ENXIO;
+
+ i2c_read(chip, MAX7310_REG_INPUT_PORT, 1, &reg_val, 1);
+
+ reg_val = (reg_val >> pin) & 0x01;
+
+ return reg_val;
+}
+
+int gpio_exp_direction_input(unsigned gpio)
+{
+ int ret = max7310_gpio_direction(gpio, MAX7310_GPIO_DIRECTION_IN);
+
+ if (ret < 0)
+ return ret;
+
+ return max7310_gpio_get_value(gpio);
+}
+
+int gpio_exp_direction_output(unsigned gpio, int value)
+{
+ int ret = max7310_gpio_direction(gpio, MAX7310_GPIO_DIRECTION_OUT);
+
+ if (ret < 0)
+ return ret;
+
+ return max7310_gpio_set_value(gpio, value);
+}
+
+int gpio_exp_setup_port(int port, int i2c_bus_id, int i2c_slave_addr)
+{
+ if (port > CONFIG_IOEXP_DEVICES_NUM || port <= 0)
+ return -EPERM;
+
+ max7310_configs[port-1].i2c_bus_id = i2c_bus_id;
+ max7310_configs[port-1].i2c_slave_addr = i2c_slave_addr;
+
+ return 0;
+}