[U-Boot] [PATCH] Add support for SX151x SPI GPIO Expanders

Viktar Palstsiuk viktar.palstsiuk at promwad.com
Wed Oct 30 11:55:33 CET 2013


Signed-off-by: Viktar Palstsiuk <viktar.palstsiuk at promwad.com>
---
 drivers/gpio/Makefile |   1 +
 drivers/gpio/sx151x.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/sx151x.h      |  30 ++++++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/gpio/sx151x.c
 create mode 100644 include/sx151x.h

diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 71ddb00..9f13342 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_S3C2440_GPIO)	+= s3c2440_gpio.o
 COBJS-$(CONFIG_XILINX_GPIO)	+= xilinx_gpio.o
 COBJS-$(CONFIG_ADI_GPIO2)	+= adi_gpio2.o
 COBJS-$(CONFIG_TCA642X)		+= tca642x.o
+COBJS-$(CONFIG_SX151X)		+= sx151x.o
 
 COBJS	:= $(COBJS-y)
 SRCS 	:= $(COBJS:.o=.c)
diff --git a/drivers/gpio/sx151x.c b/drivers/gpio/sx151x.c
new file mode 100644
index 0000000..06a5758
--- /dev/null
+++ b/drivers/gpio/sx151x.c
@@ -0,0 +1,255 @@
+/*
+ * (C) Copyright 2013
+ * Viktar Palstsiuk, Promwad, viktar.palstsiuk at promwad.com
+ *
+ * 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
+ */
+
+/*
+ * Driver for Semtech SX151x SPI GPIO Expanders
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <sx151x.h>
+
+#ifndef CONFIG_SX151X_SPI_BUS
+#define CONFIG_SX151X_SPI_BUS 0
+#endif
+
+/*
+ * The SX151x registers
+ */
+
+#ifdef CONFIG_SX151X_GPIO_COUNT_8
+/* 8bit: SX1511 */
+#define SX151X_REG_DIR		0x07
+#define SX151X_REG_DATA		0x08
+#else
+/* 16bit: SX1512 */
+#define SX151X_REG_DIR		0x0F
+#define SX151X_REG_DATA		0x11
+#endif
+#define SX151X_REG_RESET	0x7D
+
+static int sx151x_spi_write(int chip, unsigned char reg, unsigned char val)
+{
+	struct spi_slave *slave;
+	unsigned char buf[2];
+	int ret;
+
+	slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
+				SPI_MODE_0);
+	if (!slave)
+		return 0;
+
+	spi_claim_bus(slave);
+
+	buf[0] = reg;
+	buf[1] = val;
+
+	ret = spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+	if (ret < 0)
+		printf("spi%d.%d write fail: can't write %02x to %02x: %d\n",
+			CONFIG_SX151X_SPI_BUS, chip, val, reg, ret);
+	else
+		printf("spi%d.%d write 0x%02x to register 0x%02x\n",
+		       CONFIG_SX151X_SPI_BUS, chip, val, reg);
+	spi_release_bus(slave);
+	spi_free_slave(slave);
+
+	return ret;
+}
+
+static int sx151x_spi_read(int chip, unsigned char reg)
+{
+	struct spi_slave *slave;
+	int ret;
+
+	slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
+				SPI_MODE_0);
+	if (!slave)
+		return 0;
+
+	spi_claim_bus(slave);
+
+	ret = spi_w8r8(slave, reg | 0x80);
+	if (ret < 0)
+		printf("spi%d.%d read fail: can't read %02x: %d\n",
+			CONFIG_SX151X_SPI_BUS, chip, reg, ret);
+	else
+		printf("spi%d.%d read register 0x%02x: 0x%02x\n",
+		       CONFIG_SX151X_SPI_BUS, chip, reg, ret);
+
+	spi_release_bus(slave);
+	spi_free_slave(slave);
+
+	return ret;
+}
+
+static inline void sx151x_find_cfg(int gpio, unsigned char *reg, unsigned char *mask)
+{
+	*reg   -= gpio / 8;
+	*mask   = 1 << (gpio % 8);
+}
+
+static s32 sx151x_write_cfg(int chip, unsigned char gpio, unsigned char reg, int val)
+{
+	unsigned char  mask;
+	unsigned char  data;
+	int ret;
+
+	sx151x_find_cfg(gpio, &reg, &mask);
+	ret = sx151x_spi_read(chip, reg);
+	if (ret < 0)
+		return ret;
+	else
+		data = ret;
+	data &= ~mask;
+	data |= (val << (gpio % 8)) & mask;
+	return sx151x_spi_write(chip, reg, data);
+}
+
+int sx151x_get_value(int chip, int gpio)
+{
+	u8  reg = SX151X_REG_DATA;
+	u8  mask;
+	s32 ret;
+
+	sx151x_find_cfg(gpio, &reg, &mask);
+	ret = sx151x_spi_read(chip, reg);
+	if (ret >= 0)
+		ret = (ret & mask) != 0 ? 1 : 0;
+
+	return ret;
+}
+
+int sx151x_set_value(int chip, int gpio, int val)
+{
+	return sx151x_write_cfg(chip, gpio, SX151X_REG_DATA, (val ? 1 : 0));
+}
+
+int sx151x_direction_input(int chip, int gpio)
+{
+	return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 1);
+}
+
+int sx151x_direction_output(int chip, int gpio)
+{
+	return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 0);
+}
+
+int sx151x_reset(int chip)
+{
+	int err;
+
+	err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x12);
+	if (err < 0)
+		return err;
+
+	err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x34);
+	return err;
+}
+
+#ifdef CONFIG_CMD_SX151X
+
+int do_sx151x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret = CMD_RET_USAGE, chip = 0, gpio = 0, val = 0;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	/* arg2 used as chip number */
+	chip = simple_strtoul(argv[2], NULL, 10);
+
+	if (strcmp(argv[1], "reset") == 0) {
+		ret = sx151x_reset(chip);
+		if (!ret) {
+			printf("Device at spi%d.%d was reset\n",
+			       CONFIG_SX151X_SPI_BUS, chip);
+		}
+		return ret;
+	}
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+
+	/* arg3 used as gpio number */
+	gpio = simple_strtoul(argv[3], NULL, 10);
+
+	if (strcmp(argv[1], "get") == 0) {
+		ret = sx151x_get_value(chip, gpio);
+		if (ret < 0)
+			printf("Failed to get value at spi%d.%d gpio %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio);
+		else {
+			printf("Value at spi%d.%d gpio %d is %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio, ret);
+			ret = 0;
+		}
+		return ret;
+	}
+
+	if (argc < 5)
+		return CMD_RET_USAGE;
+
+	/* arg4 used as value or direction */
+	val = simple_strtoul(argv[4], NULL, 10);
+
+	if (strcmp(argv[1], "set") == 0) {
+		ret = sx151x_set_value(chip, gpio, val);
+		if (ret < 0)
+			printf("Failed to set value at spi%d.%d gpio %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio);
+		else
+			printf("New value at spi%d.%d gpio %d is %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio, val);
+		return ret;
+	} else if (strcmp(argv[1], "dir") == 0) {
+		if (val == 0)
+			ret = sx151x_direction_output(chip, gpio);
+		else
+			ret = sx151x_direction_input(chip, gpio);
+
+		if (ret < 0)
+			printf("Failed to set direction of spi%d.%d gpio %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio);
+		else
+			printf("New direction of spi%d.%d gpio %d is %d\n",
+			       CONFIG_SX151X_SPI_BUS, chip, gpio, val);
+		return ret;
+	}
+
+	printf("Please see usage\n");
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	sx151x,	5,	1,	do_sx151x,
+	"sx151x gpio access",
+	"dir chip gpio 0|1\n"
+	"	- set gpio direction (0 for output, 1 for input)\n"
+	"sx151x get chip gpio\n"
+	"	- get gpio value\n"
+	"sx151x set chip gpio 0|1\n"
+	"	- set gpio value\n"
+	"sx151x reset chip\n"
+	"	- reset chip"
+);
+
+#endif /* CONFIG_CMD_SX151X */
diff --git a/include/sx151x.h b/include/sx151x.h
new file mode 100644
index 0000000..603f468
--- /dev/null
+++ b/include/sx151x.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2013
+ * Viktar Palstsiuk, Promwad, viktar.palstsiuk at promwad.com
+ *
+ * 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
+ */
+
+#ifndef __SX151X_H_
+#define __SX151X_H_
+
+int sx151x_get_value(int chip, int gpio);
+int sx151x_set_value(int chip, int gpio, int val);
+int sx151x_direction_input(int chip, int gpio);
+int sx151x_direction_output(int chip, int gpio);
+int sx151x_reset(int chip);
+
+#endif /* __SX151X_H_ */
-- 
1.8.4.rc3



More information about the U-Boot mailing list