Initial support for the DS4510, a CPU supervisor with integrated EEPROM, SRAM, and 4 programmable non-volatile GPIO pins. The CONFIG_DS4510 define enables support for the device while the CONFIG_CMD_DS4510 define enables the ds4510 command.
Signed-off-by: Peter Tyser <[EMAIL PROTECTED]> --- README | 2 + drivers/gpio/Makefile | 1 + drivers/gpio/ds4510.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++ include/gpio/ds4510.h | 75 +++++++++++ 4 files changed, 422 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/ds4510.c create mode 100644 include/gpio/ds4510.h diff --git a/README b/README index 73bed41..2c0a19f 100644 --- a/README +++ b/README @@ -572,6 +572,7 @@ The following options need to be configured: CONFIG_CMD_DHCP * DHCP support CONFIG_CMD_DIAG * Diagnostics CONFIG_CMD_DOC * Disk-On-Chip Support + CONFIG_CMD_DS4510 * ds4510 I2C gpio/memory commands CONFIG_CMD_DTT * Digital Therm and Thermostat CONFIG_CMD_ECHO echo arguments CONFIG_CMD_EEPROM * EEPROM read/write support @@ -681,6 +682,7 @@ The following options need to be configured: - GPIO Support: CONFIG_PCA953X - use NXP's PCA953X series I2C GPIO + CONFIG_DS4510 - use Maxim's DS4510 I2C GPIO/eeprom Note that if the GPIO device uses I2C, then the I2C interface must also be configured. See I2C Support, below. diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dd618ed..11f0903 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libgpio.a COBJS-$(CONFIG_PCA953X) += pca953x.o +COBJS-$(CONFIG_DS4510) += ds4510.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/gpio/ds4510.c b/drivers/gpio/ds4510.c new file mode 100644 index 0000000..8b9a836 --- /dev/null +++ b/drivers/gpio/ds4510.c @@ -0,0 +1,344 @@ +/* + * Copyright 2008 Extreme Engineering Solutions, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + * + * 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 DS4510, a CPU supervisor with integrated EEPROM, SRAM, + * and 4 programmable non-volatile GPIO pins. + */ + +#include <common.h> +#include <i2c.h> +#include <command.h> +#include <gpio/ds4510.h> + +/* + * Write to DS4510, taking page boundaries into account + */ +int ds4510_mem_write(uint8_t chip, int offset, uint8_t *buf, int count) +{ + int wrlen; + int i = 0; + + do { + wrlen = DS4510_EEPROM_PAGE_SIZE - + DS4510_EEPROM_PAGE_OFFSET(offset); + if (count < wrlen) + wrlen = count; + i2c_write(chip, offset, 1, &buf[i], wrlen); + + /* This delay isn't needed for SRAM writes but shouldn't delay + * things too much, so do it unconditionally for simplicity */ + udelay(DS4510_EEPROM_PAGE_WRITE_DELAY_MS * 1000); + count -= wrlen; + offset += wrlen; + i += wrlen; + } while (count > 0); + + return 0; +} + +/* + * General read from DS4510 + */ +int ds4510_mem_read(uint8_t chip, int offset, uint8_t *buf, int count) +{ + return i2c_read(chip, offset, 1, buf, count); +} + +/* + * Write SEE bit in config register. + * nv = 0 - Writes to SEEPROM registers behave like EEPROM + * nv = 1 - Writes to SEEPROM registers behave like SRAM + */ +int ds4510_see_write(uint8_t chip, uint8_t nv) +{ + uint8_t data; + + if (i2c_read(chip, DS4510_CFG, 1, &data, 1)) + return -1; + + if (nv) /* Treat SEEPROM bits as EEPROM */ + data &= ~DS4510_CFG_SEE; + else /* Treat SEEPROM bits as SRAM */ + data |= DS4510_CFG_SEE; + + return ds4510_mem_write(chip, DS4510_CFG, &data, 1); +} + +/* + * Write de-assertion of reset signal delay + */ +int ds4510_rstdelay_write(uint8_t chip, uint8_t delay) +{ + uint8_t data; + + if (i2c_read(chip, DS4510_RSTDELAY, 1, &data, 1)) + return -1; + + data &= ~DS4510_RSTDELAY_MASK; + data |= delay & DS4510_RSTDELAY_MASK; + + return ds4510_mem_write(chip, DS4510_RSTDELAY, &data, 1); +} + +/* + * Write pullup characteristics of IO pins + */ +int ds4510_pullup_write(uint8_t chip, uint8_t val) +{ + val &= DS4510_IO_MASK; + + return ds4510_mem_write(chip, DS4510_PULLUP, (uint8_t *)&val, 1); +} + +/* + * Read pullup characteristics of IO pins + */ +int ds4510_pullup_read(uint8_t chip) +{ + uint8_t val; + + if (i2c_read(chip, DS4510_PULLUP, 1, &val, 1)) + return -1; + + return val & DS4510_IO_MASK; +} + +/* + * Write drive level of IO pins + */ +int ds4510_gpio_write(uint8_t chip, uint8_t val) +{ + uint8_t data; + int i; + + for (i = 0; i < DS4510_NUM_IO; i++) { + i2c_read(chip, DS4510_IO0 - i, 1, &data, 1); + + if (val & (0x1 << i)) + data |= 0x1; + else + data &= ~0x1; + + ds4510_mem_write(chip, DS4510_IO0 - i, &data, 1); + } + + return 0; +} + +/* + * Read drive level of IO pins + */ +int ds4510_gpio_read(uint8_t chip) +{ + uint8_t data; + int val = 0; + int i; + + for (i = 0; i < DS4510_NUM_IO; i++) { + i2c_read(chip, DS4510_IO0 - i, 1, &data, 1); + + if (data & 1) + val |= (1 << i); + } + + return val; +} + +/* + * Read physical level of IO pins + */ +int ds4510_gpio_read_val(uint8_t chip) +{ + uint8_t val; + + if (i2c_read(chip, DS4510_IO_STATUS, 1, &val, 1)) + return -1; + + return val & DS4510_IO_MASK; +} + +#if defined(CONFIG_CMD_DS4510) +/* + * Display DS4510 information + */ +static int ds4510_info(uint8_t chip) +{ + int i; + int tmp; + uint8_t data; + + printf("DS4510 @ 0x%x:\n\n", chip); + + i2c_read(chip, DS4510_RSTDELAY, 1, &data, 1); + printf("rstdelay = 0x%x\n\n", data & DS4510_RSTDELAY_MASK); + + i2c_read(chip, DS4510_CFG, 1, &data, 1); + printf("config = 0x%x\n", data); + printf(" /ready = %d\n", data & DS4510_CFG_READY ? 1 : 0); + printf(" trip pt = %d\n", data & DS4510_CFG_TRIP_POINT ? 1 : 0); + printf(" rst sts = %d\n", data & DS4510_CFG_RESET ? 1 : 0); + printf(" /see = %d\n", data & DS4510_CFG_SEE ? 1 : 0); + printf(" swrst = %d\n\n", data & DS4510_CFG_SWRST ? 1 : 0); + + printf("gpio pins: 3210\n"); + printf("---------------\n"); + printf("pullup "); + + tmp = ds4510_pullup_read(chip); + for (i = DS4510_NUM_IO - 1; i >= 0; i--) + printf("%d", (tmp & (1 << i)) ? 1 : 0); + printf("\n"); + + printf("driven "); + tmp = ds4510_gpio_read(chip); + for (i = DS4510_NUM_IO - 1; i >= 0; i--) + printf("%d", (tmp & (1 << i)) ? 1 : 0); + printf("\n"); + + printf("read "); + tmp = ds4510_gpio_read_val(chip); + for (i = DS4510_NUM_IO - 1; i >= 0; i--) + printf("%d", (tmp & (1 << i)) ? 1 : 0); + printf("\n"); + + return 0; +} + +int do_ds4510(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr; + ulong pin; + ulong val; + ulong off; + ulong cnt; + int end; + uint8_t chip; + int tmp; + int (*rw_func)(uint8_t, int, uint8_t *, int); + + chip = (uint8_t)simple_strtoul(argv[1], NULL, 16); + + if (i2c_probe(chip)) { + printf("I2C device 0x%02x not found\n", chip); + return -1; + } + + switch (argc) { + case 3: + if (strcmp(argv[2], "info") == 0) + return ds4510_info(chip); + break; + case 4: + val = simple_strtoul(argv[3], NULL, 16); + + if (strcmp(argv[2], "nv") == 0) + return ds4510_see_write(chip, val); + else if (strcmp(argv[2], "rstdelay") == 0) + return ds4510_rstdelay_write(chip, val); + else if (strcmp(argv[2], "input") == 0) + return (ds4510_gpio_read_val(chip) & (1 << val)) != 0; + break; + case 5: + pin = simple_strtoul(argv[3], NULL, 16); + val = simple_strtoul(argv[4], NULL, 16); + + if (pin >= DS4510_NUM_IO) + break; + + if (strcmp(argv[2], "output") == 0) { + tmp = ds4510_gpio_read(chip); + if (val) + tmp |= (1 << pin); + else + tmp &= ~(1 << pin); + return ds4510_gpio_write(chip, tmp); + } else if (strcmp(argv[2], "pullup") == 0) { + tmp = ds4510_pullup_read(chip); + if (val) + tmp |= (1 << pin); + else + tmp &= ~(1 << pin); + return ds4510_pullup_write(chip, tmp); + } + break; + case 7: + addr = simple_strtoul(argv[4], NULL, 16); + off = simple_strtoul(argv[5], NULL, 16); + cnt = simple_strtoul(argv[6], NULL, 16); + + if (strcmp(argv[3], "read") == 0) + rw_func = ds4510_mem_read; + else if (strcmp(argv[3], "write") == 0) + rw_func = ds4510_mem_write; + else + break; + + if (strcmp(argv[2], "eeprom") == 0) { + end = DS4510_EEPROM + DS4510_EEPROM_SIZE; + off += DS4510_EEPROM; + } else if (strcmp(argv[2], "seeprom") == 0) { + end = DS4510_SEEPROM + DS4510_SEEPROM_SIZE; + off += DS4510_SEEPROM; + } else if (strcmp(argv[2], "sram") == 0) { + end = DS4510_SRAM + DS4510_SRAM_SIZE; + off += DS4510_SRAM; + } else { + break; + } + + if ((off + cnt) > end) { + printf("ERROR: invalid len\n"); + return -1; + } + + return rw_func(chip, off, (uint8_t *)addr, cnt); + default: + break; + } + + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + ds4510, 7, 2, do_ds4510, + "ds4510 - ds4510 eeprom/seeprom/sram/gpio access\n", + "chip info\n" + " - display ds4510 info\n" + "ds4510 chip nv 0|1\n" + " - make gpio and seeprom writes volatile/non-volatile\n" + "ds4510 chip rstdelay 0-3\n" + " - set reset output delay\n" + "ds4510 chip output pin 0|1\n" + " - set pin low or high-Z\n" + "ds4510 chip input pin\n" + " - read value of pin\n" + "ds4510 chip pullup pin 0|1\n" + " - disable/enable pullup on specified pin\n" + "ds4510 chip eeprom read addr off cnt\n" + "ds4510 chip eeprom write addr off cnt\n" + " - read/write 'cnt' bytes at EEPROM offset 'off'\n" + "ds4510 chip seeprom read addr off cnt\n" + "ds4510 chip seeprom write addr off cnt\n" + " - read/write 'cnt' bytes at SRAM-shadowed EEPROM offset 'off'\n" + "ds4510 chip sram read addr off cnt\n" + "ds4510 chip sram write addr off cnt\n" + " - read/write 'cnt' bytes at SRAM offset 'off'\n" +); +#endif /* CONFIG_CMD_DS4510 */ diff --git a/include/gpio/ds4510.h b/include/gpio/ds4510.h new file mode 100644 index 0000000..40480af --- /dev/null +++ b/include/gpio/ds4510.h @@ -0,0 +1,75 @@ +/* + * Copyright 2008 Extreme Engineering Solutions, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + * + * 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 __DS4510_H_ +#define __DS4510_H_ + +/* General defines */ +#define DS4510_NUM_IO 0x04 +#define DS4510_IO_MASK ((1 << DS4510_NUM_IO) - 1) +#define DS4510_EEPROM_PAGE_WRITE_DELAY_MS 20 + +/* EEPROM from 0x00 - 0x39 */ +#define DS4510_EEPROM 0x00 +#define DS4510_EEPROM_SIZE 0x40 +#define DS4510_EEPROM_PAGE_SIZE 0x08 +#define DS4510_EEPROM_PAGE_OFFSET(x) ((x) & (DS4510_EEPROM_PAGE_SIZE - 1)) + +/* SEEPROM from 0xf0 - 0xf7 */ +#define DS4510_SEEPROM 0xf0 +#define DS4510_SEEPROM_SIZE 0x08 + +/* Registers overlapping SEEPROM from 0xf0 - 0xf7 */ +#define DS4510_PULLUP 0xF0 +#define DS4510_PULLUP_DIS 0x00 +#define DS4510_PULLUP_EN 0x01 +#define DS4510_RSTDELAY 0xF1 +#define DS4510_RSTDELAY_MASK 0x03 +#define DS4510_RSTDELAY_125 0x00 +#define DS4510_RSTDELAY_250 0x01 +#define DS4510_RSTDELAY_500 0x02 +#define DS4510_RSTDELAY_1000 0x03 +#define DS4510_IO3 0xF4 +#define DS4510_IO2 0xF5 +#define DS4510_IO1 0xF6 +#define DS4510_IO0 0xF7 + +/* Status configuration registers from 0xf8 - 0xf9*/ +#define DS4510_IO_STATUS 0xF8 +#define DS4510_CFG 0xF9 +#define DS4510_CFG_READY 0x80 +#define DS4510_CFG_TRIP_POINT 0x40 +#define DS4510_CFG_RESET 0x20 +#define DS4510_CFG_SEE 0x10 +#define DS4510_CFG_SWRST 0x08 + +/* SRAM from 0xfa - 0xff */ +#define DS4510_SRAM 0xfa +#define DS4510_SRAM_SIZE 0x06 + +int ds4510_mem_write(uint8_t chip, int offset, uint8_t *buf, int count); +int ds4510_mem_read(uint8_t chip, int offset, uint8_t *buf, int count); +int ds4510_see_write(uint8_t chip, uint8_t nv); +int ds4510_rstdelay_write(uint8_t chip, uint8_t delay); +int ds4510_pullup_write(uint8_t chip, uint8_t val); +int ds4510_pullup_read(uint8_t chip); +int ds4510_gpio_write(uint8_t chip, uint8_t val); +int ds4510_gpio_read(uint8_t chip); +int ds4510_gpio_read_val(uint8_t chip); + +#endif /* __DS4510_H_ */ -- 1.6.0.2.GIT _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot