123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- /*
- * (C) Copyright 2013
- * Viktar Palstsiuk, Promwad, viktar.palstsiuk@promwad.com
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- /*
- * 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 int 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, ®, &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)
- {
- unsigned char reg = SX151X_REG_DATA;
- unsigned char mask;
- int ret;
- sx151x_find_cfg(gpio, ®, &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 */
|