diff options
author | Jayachandran C. <jchandra@FreeBSD.org> | 2010-12-12 06:00:26 +0000 |
---|---|---|
committer | Jayachandran C. <jchandra@FreeBSD.org> | 2010-12-12 06:00:26 +0000 |
commit | 3ba09158c8d4129cca45251bdc054b0dbb4ce873 (patch) | |
tree | dd84b36f1b1e1311a69c456e773d4ea661129d6e /sys | |
parent | 9f5a68a00248e5608c353c138c39f32d797d99dc (diff) | |
download | src-3ba09158c8d4129cca45251bdc054b0dbb4ce873.tar.gz src-3ba09158c8d4129cca45251bdc054b0dbb4ce873.zip |
I2C drivers for XLR/XLS processors.
- Major update to xlr_i2c.c: do multi-byte ops correctly, remove unnecessary
code, add mutex to protect bus operations, style(9) fixes.
- Drivers for I2C devices on XLR/XLS engineering boards, ds1374u RTC, max6657
temparature sensor and at24co2n EEPROM.
Submitted by: Sreekanth M. S. (kanthms at netlogicmicro com)
Notes
Notes:
svn path=/head/; revision=216390
Diffstat (limited to 'sys')
-rw-r--r-- | sys/mips/conf/XLR | 14 | ||||
-rw-r--r-- | sys/mips/rmi/board.c | 21 | ||||
-rw-r--r-- | sys/mips/rmi/board.h | 8 | ||||
-rw-r--r-- | sys/mips/rmi/dev/iic/at24co2n.c | 145 | ||||
-rw-r--r-- | sys/mips/rmi/dev/iic/ds1374u.c | 162 | ||||
-rw-r--r-- | sys/mips/rmi/dev/iic/max6657.c | 162 | ||||
-rw-r--r-- | sys/mips/rmi/files.xlr | 6 | ||||
-rw-r--r-- | sys/mips/rmi/iodi.c | 1 | ||||
-rw-r--r-- | sys/mips/rmi/xlr_i2c.c | 455 |
9 files changed, 711 insertions, 263 deletions
diff --git a/sys/mips/conf/XLR b/sys/mips/conf/XLR index 3df81c48b965..28b1c91ba1ba 100644 --- a/sys/mips/conf/XLR +++ b/sys/mips/conf/XLR @@ -143,13 +143,13 @@ device umass # Disks/Mass storage - Requires scbus and da #i2c # Not yet -#device ic -#device iic -#device iicbb -#device iicbus -#device xlr_rtc -#device xlr_temperature -#device xlr_eeprom +device ic +device iic +device iicbb +device iicbus +device ds1374u # RTC on XLR boards +device max6657 # Temparature sensor on XLR boards +device at24co2n # EEPROM on XLR boards #crypto # Not yet diff --git a/sys/mips/rmi/board.c b/sys/mips/rmi/board.c index 4c49dacc5cee..7572a699713c 100644 --- a/sys/mips/rmi/board.c +++ b/sys/mips/rmi/board.c @@ -42,6 +42,11 @@ __FBSDID("$FreeBSD$"); #include <mips/rmi/board.h> #include <mips/rmi/pic.h> +#define XLR_I2C_RTC_ADDR 0xd0 +#define XLR_I2C_EEPROM_ADDR 0xa0 +#define XLR_I2C_TEMPSENSOR_ADDR 0x98 +#define XLR_I2C_ATX8_TEMPSENSOR_ADDR 0x9a + struct stn_cc *xlr_core_cc_configs[] = { &cc_table_cpu_0, &cc_table_cpu_1, &cc_table_cpu_2, &cc_table_cpu_3, &cc_table_cpu_4, &cc_table_cpu_5, &cc_table_cpu_6, &cc_table_cpu_7}; @@ -231,6 +236,7 @@ xls_board_specific_overrides(struct xlr_board_info* board) { struct xlr_gmac_block_t *blk0, *blk1; int i; + struct xlr_i2c_dev_t* iic_blk; blk0 = &board->gmac_block[0]; blk1 = &board->gmac_block[1]; @@ -283,7 +289,11 @@ xls_board_specific_overrides(struct xlr_board_info* board) break; case RMI_XLR_BOARD_ARIZONA_VIII: - if (blk1->enabled) { + iic_blk = &xlr_board_info.xlr_i2c_device[I2C_THERMAL]; + if (iic_blk->enabled) { + iic_blk->addr = XLR_I2C_ATX8_TEMPSENSOR_ADDR; + } + if (blk1->enabled) { /* There is just one Octal PHY on the board and it is * connected to the MII interface for NA Quad 0. */ for (i = 0; i < 4; i++) { @@ -358,6 +368,7 @@ int xlr_board_info_setup() { struct xlr_gmac_block_t *blk0, *blk1, *blk2; + struct xlr_i2c_dev_t* iic_blk; int i; /* This setup code is long'ish because the same base driver @@ -412,6 +423,14 @@ xlr_board_info_setup() blk0 = &xlr_board_info.gmac_block[0]; blk1 = &xlr_board_info.gmac_block[1]; blk2 = &xlr_board_info.gmac_block[2]; + + iic_blk = xlr_board_info.xlr_i2c_device; + iic_blk[I2C_RTC].enabled = 1; + iic_blk[I2C_RTC].addr = XLR_I2C_RTC_ADDR; + iic_blk[I2C_THERMAL].enabled = 1; + iic_blk[I2C_THERMAL].addr = XLR_I2C_TEMPSENSOR_ADDR; + iic_blk[I2C_EEPROM].enabled = 1; + iic_blk[I2C_EEPROM].addr = XLR_I2C_EEPROM_ADDR; if (xlr_is_xls()) { xlr_board_info.is_xls = 1; diff --git a/sys/mips/rmi/board.h b/sys/mips/rmi/board.h index 35ce7e17492f..7d664fe8e542 100644 --- a/sys/mips/rmi/board.h +++ b/sys/mips/rmi/board.h @@ -195,6 +195,7 @@ xlr_is_xls_b0(void) /* all our knowledge of chip and board that cannot be detected run-time goes here */ enum gmac_block_types { XLR_GMAC, XLR_XGMAC, XLR_SPI4}; enum gmac_port_types { XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII, XLR_XGMII, XLR_XAUI }; +enum i2c_dev_types { I2C_RTC, I2C_THERMAL, I2C_EEPROM }; struct xlr_board_info { int is_xls; @@ -207,6 +208,13 @@ struct xlr_board_info { struct bucket_size *bucket_sizes; /* pointer to Core station bucket */ int *msgmap; /* mapping of message station to devices */ int gmacports; /* number of gmac ports on the board */ + struct xlr_i2c_dev_t { + uint32_t addr; + unsigned int enabled; /* mask of devs enabled */ + int type; + int unit; + char *dev_name; + } xlr_i2c_device[3]; struct xlr_gmac_block_t { /* refers to the set of GMACs controlled by a network accelarator */ int type; /* see enum gmac_block_types */ diff --git a/sys/mips/rmi/dev/iic/at24co2n.c b/sys/mips/rmi/dev/iic/at24co2n.c new file mode 100644 index 000000000000..fe9c1c4ddf9c --- /dev/null +++ b/sys/mips/rmi/dev/iic/at24co2n.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2003-2009 RMI Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of RMI Corporation, nor the names of its contributors, + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * RMI_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +/* + * reading eeprom for the mac address . + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/frame.h> +#include <machine/resource.h> + +#include <dev/iicbus/iiconf.h> +#include <dev/iicbus/iicbus.h> + +#include "iicbus_if.h" + +#define AT24CO_EEPROM_ETH_MACADDR 0x20 + +struct at24co2n_softc { + uint32_t sc_addr; + device_t sc_dev; + struct mtx sc_mtx; + uint8_t sc_mac_addr[6]; +}; + +static void at24co2n_read_mac(struct at24co2n_softc *); + +static int +at24co2n_probe(device_t dev) +{ + device_set_desc(dev, "AT24Co2N-10SE-2.7 EEPROM for mac address"); + return (0); +} + +static int +at24co2n_mac_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct at24co2n_softc *sc = arg1; + char buf[24]; + int len; + uint8_t *p; + + at24co2n_read_mac(sc); + p = sc->sc_mac_addr; + len = snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + p[0], p[1], p[2], p[3], p[4], p[5]); + return SYSCTL_OUT(req, buf, len); +} + + +static int +at24co2n_attach(device_t dev) +{ + struct at24co2n_softc *sc = device_get_softc(dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); + struct sysctl_oid *tree = device_get_sysctl_tree(dev); + + if(sc == NULL) { + printf("at24co2n_attach device_get_softc failed\n"); + return (0); + } + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev); + + mtx_init(&sc->sc_mtx, "eeprom", "eeprom", MTX_DEF); + + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "eeprom-mac", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + at24co2n_mac_sysctl, "A", "mac address"); + + return (0); +} + +static void +at24co2n_read_mac(struct at24co2n_softc *sc) +{ + uint8_t addr = AT24CO_EEPROM_ETH_MACADDR; + struct iic_msg msgs[2] = { + { sc->sc_addr, IIC_M_WR, 1, &addr }, + { sc->sc_addr, IIC_M_RD, 6, sc->sc_mac_addr}, + }; + + mtx_lock(&sc->sc_mtx); + iicbus_transfer(sc->sc_dev, msgs, 2); + mtx_unlock(&sc->sc_mtx); +} + +static device_method_t at24co2n_methods[] = { + DEVMETHOD(device_probe, at24co2n_probe), + DEVMETHOD(device_attach, at24co2n_attach), + + {0, 0}, +}; + +static driver_t at24co2n_driver = { + "at24co2n", + at24co2n_methods, + sizeof(struct at24co2n_softc), +}; +static devclass_t at24co2n_devclass; + +DRIVER_MODULE(at24co2n, iicbus, at24co2n_driver, at24co2n_devclass, 0, 0); +MODULE_VERSION(at24co2n, 1); +MODULE_DEPEND(at24co2n, iicbus, 1, 1, 1); diff --git a/sys/mips/rmi/dev/iic/ds1374u.c b/sys/mips/rmi/dev/iic/ds1374u.c new file mode 100644 index 000000000000..f47e9666bf18 --- /dev/null +++ b/sys/mips/rmi/dev/iic/ds1374u.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2003-2009 RMI Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of RMI Corporation, nor the names of its contributors, + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * RMI_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +/* + * RTC chip sitting on the I2C bus. + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/clock.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/rman.h> + +#include <mips/include/bus.h> +#include <mips/include/cpu.h> +#include <mips/include/cpufunc.h> +#include <mips/include/frame.h> +#include <mips/include/resource.h> + +#include <dev/iicbus/iiconf.h> +#include <dev/iicbus/iicbus.h> + +#include "iicbus_if.h" +#include "clock_if.h" + +#define DS1374_RTC_COUNTER 0 /* counter (bytes 0-3) */ + +struct ds1374u_softc { + uint32_t sc_addr; + device_t sc_dev; +}; + +static int +ds1374u_probe(device_t dev) +{ + device_set_desc(dev, "DS1374U-33 RTC"); + return (0); +} + +static int +ds1374u_attach(device_t dev) +{ + struct ds1374u_softc *sc = device_get_softc(dev); + + if(sc==NULL) { + printf("ds1374u_attach device_get_softc failed\n"); + return (0); + } + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev); + + clock_register(dev, 1000); + return (0); +} + + +static int +ds1374u_write(device_t dev, int reg, uint8_t val) +{ + uint8_t data[2]; + struct ds1374u_softc *sc = device_get_softc(dev); + struct iic_msg msgs[1] = { + { sc->sc_addr, IIC_M_WR, 2, data }, + }; + + data[0] = reg; + data[1] = val; + if (iicbus_transfer(dev, msgs, 1) == 0) + return (0); + else + return (-1); +} + +static int +ds1374u_settime(device_t dev, struct timespec *ts) +{ + int i; + int temp = 0; + + for (i = 0; i < 4; i++) { + temp = (ts->tv_sec >> (8*i)) & 0xff; + if (ds1374u_write(dev, DS1374_RTC_COUNTER+i, temp)!=0) + return (-1); + } + return 0; +} + +static int +ds1374u_gettime(device_t dev, struct timespec *ts) +{ + struct ds1374u_softc *sc = device_get_softc(dev); + uint8_t addr[1] = { DS1374_RTC_COUNTER }; + uint8_t secs[4]; + struct iic_msg msgs[2] = { + { sc->sc_addr, IIC_M_WR, 1, addr }, + { sc->sc_addr, IIC_M_RD, 4, secs }, + }; + int error; + + error = iicbus_transfer(dev, msgs, 2); + if (error == 0) { + /* counter has seconds since epoch */ + ts->tv_sec = (secs[3] << 24) | (secs[2] << 16) + | (secs[1] << 8) | (secs[0] << 0); + ts->tv_nsec = 0; + } + return error; + return 0; +} + +static device_method_t ds1374u_methods[] = { + DEVMETHOD(device_probe, ds1374u_probe), + DEVMETHOD(device_attach, ds1374u_attach), + + DEVMETHOD(clock_gettime, ds1374u_gettime), + DEVMETHOD(clock_settime, ds1374u_settime), + + {0, 0}, +}; + +static driver_t ds1374u_driver = { + "ds1374u", + ds1374u_methods, + sizeof(struct ds1374u_softc), +}; +static devclass_t ds1374u_devclass; + +DRIVER_MODULE(ds1374u, iicbus, ds1374u_driver, ds1374u_devclass, 0, 0); +MODULE_VERSION(ds1374u, 1); +MODULE_DEPEND(ds1374u, iicbus, 1, 1, 1); diff --git a/sys/mips/rmi/dev/iic/max6657.c b/sys/mips/rmi/dev/iic/max6657.c new file mode 100644 index 000000000000..81912653ed22 --- /dev/null +++ b/sys/mips/rmi/dev/iic/max6657.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2003-2009 RMI Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of RMI Corporation, nor the names of its contributors, + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * RMI_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +/* + * temperature sensor chip sitting on the I2C bus. + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/frame.h> +#include <machine/resource.h> + +#include <dev/iicbus/iiconf.h> +#include <dev/iicbus/iicbus.h> + +#include <mips/rmi/board.h> +#include <mips/rmi/rmi_boot_info.h> +#include "iicbus_if.h" + +#define MAX6657_EXT_TEMP 1 + +struct max6657_softc { + uint32_t sc_addr; + device_t sc_dev; + struct mtx sc_mtx; + int sc_curtemp; + int sc_lastupdate; /* in ticks */ +}; + +static void max6657_update(struct max6657_softc *); +static int max6657_read(device_t dev, uint32_t addr, int reg) ; + +static int +max6657_probe(device_t dev) +{ + device_set_desc(dev, "MAX6657MSA Temperature Sensor"); + return (0); +} + +static int +max6657_sysctl_temp(SYSCTL_HANDLER_ARGS) +{ + struct max6657_softc *sc = arg1; + int temp; + + max6657_update(sc); + temp = sc->sc_curtemp ; + return sysctl_handle_int(oidp, &temp, 0, req); +} + +static int +max6657_attach(device_t dev) +{ + struct max6657_softc *sc = device_get_softc(dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); + struct sysctl_oid *tree = device_get_sysctl_tree(dev); + + if(sc==NULL) { + printf("max6657_attach device_get_softc failed\n"); + return (0); + } + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev); + mtx_init(&sc->sc_mtx, "max6657", "max6657", MTX_DEF); + + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "temp", CTLTYPE_INT | CTLFLAG_RD, sc, 0, + max6657_sysctl_temp, "I", "operating temperature"); + + device_printf(dev, "Chip temperature {%d} Degree Celsius\n", + max6657_read(sc->sc_dev, sc->sc_addr, MAX6657_EXT_TEMP)); + + return (0); +} + +static int +max6657_read(device_t dev, uint32_t slave_addr, int reg) +{ + uint8_t addr = reg; + uint8_t data[1]; + struct iic_msg msgs[2] = { + { slave_addr, IIC_M_WR, 1, &addr }, + { slave_addr, IIC_M_RD, 1, data }, + }; + + return iicbus_transfer(dev, msgs, 2) != 0 ? -1 : data[0]; +} + + +static void +max6657_update(struct max6657_softc *sc) +{ + int v; + + mtx_lock(&sc->sc_mtx); + /* NB: no point in updating any faster than the chip */ + if (ticks - sc->sc_lastupdate > hz) { + v = max6657_read(sc->sc_dev, sc->sc_addr, MAX6657_EXT_TEMP); + if (v >= 0) + sc->sc_curtemp = v; + sc->sc_lastupdate = ticks; + } + mtx_unlock(&sc->sc_mtx); +} + +static device_method_t max6657_methods[] = { + DEVMETHOD(device_probe, max6657_probe), + DEVMETHOD(device_attach, max6657_attach), + + {0, 0}, +}; + +static driver_t max6657_driver = { + "max6657", + max6657_methods, + sizeof(struct max6657_softc), +}; +static devclass_t max6657_devclass; + +DRIVER_MODULE(max6657, iicbus, max6657_driver, max6657_devclass, 0, 0); +MODULE_VERSION(max6657, 1); +MODULE_DEPEND(max6657, iicbus, 1, 1, 1); diff --git a/sys/mips/rmi/files.xlr b/sys/mips/rmi/files.xlr index e96fc43789fe..0827ca7ce84b 100644 --- a/sys/mips/rmi/files.xlr +++ b/sys/mips/rmi/files.xlr @@ -22,6 +22,6 @@ mips/rmi/dev/sec/rmisec.c optional rmisec mips/rmi/dev/sec/rmilib.c optional rmisec mips/rmi/dev/xlr/rge.c optional rge mips/rmi/dev/nlge/if_nlge.c optional nlge -dev/iicbus/xlr_rtc.c optional xlr_rtc -dev/iicbus/xlr_temperature.c optional xlr_temperature -dev/iicbus/xlr_eeprom.c optional xlr_eeprom +mips/rmi/dev/iic/ds1374u.c optional ds1374u +mips/rmi/dev/iic/max6657.c optional max6657 +mips/rmi/dev/iic/at24co2n.c optional at24co2n diff --git a/sys/mips/rmi/iodi.c b/sys/mips/rmi/iodi.c index 60b7915d1bc8..3c09984a749f 100644 --- a/sys/mips/rmi/iodi.c +++ b/sys/mips/rmi/iodi.c @@ -212,6 +212,7 @@ iodi_attach(device_t dev) */ device_add_child(dev, "uart", 0); device_add_child(dev, "xlr_i2c", 0); + device_add_child(dev, "xlr_i2c", 1); device_add_child(dev, "pcib", 0); device_add_child(dev, "rmisec", -1); diff --git a/sys/mips/rmi/xlr_i2c.c b/sys/mips/rmi/xlr_i2c.c index abd9439e2e8c..eca41226cd80 100644 --- a/sys/mips/rmi/xlr_i2c.c +++ b/sys/mips/rmi/xlr_i2c.c @@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/module.h> +#include <sys/mutex.h> #include <sys/bus.h> #include <sys/rman.h> @@ -46,44 +48,42 @@ __FBSDID("$FreeBSD$"); #include <dev/iicbus/iiconf.h> #include <dev/iicbus/iicbus.h> +#include <mips/rmi/board.h> #include <mips/rmi/iomap.h> #include <mips/include/resource.h> #include "iicbus_if.h" -#define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev)) - -#define I2C_PALM_CFG 0x00 -#define I2C_PALM_CLKDIV 0x01 -#define I2C_PALM_DEVADDR 0x02 -#define I2C_PALM_ADDR 0x03 -#define I2C_PALM_DATAOUT 0x04 -#define I2C_PALM_DATAIN 0x05 -#define I2C_PALM_STATUS 0x06 -#define I2C_PALM_STARTXFR 0x07 -#define I2C_PALM_BYTECNT 0x08 -#define I2C_PALM_HDSTATIM 0x09 - -/* TEST Values!! Change as required */ -#define I2C_PALM_CFG_DEF 0x000000F8 /* 8-Bit Addr + POR Values */ -#define I2C_PALM_CLKDIV_DEF 0x14A //0x00000052 -#define I2C_PALM_HDSTATIM_DEF 0x107 //0x00000000 - -#define I2C_PALM_STARTXFR_RD 0x00000001 -#define I2C_PALM_STARTXFR_WR 0x00000000 - - -#define PHOENIX_IO_I2C_0_OFFSET 0x16000 -#define PHOENIX_IO_I2C_1_OFFSET 0x17000 - -#define ARIZONA_I2c_BUS 1 - -int bus = 1; - - -uint8_t current_slave; -uint8_t read_address; -static xlr_reg_t *iobase_i2c_regs; +/* XLR I2C REGISTERS */ +#define XLR_I2C_CFG 0x00 +#define XLR_I2C_CLKDIV 0x01 +#define XLR_I2C_DEVADDR 0x02 +#define XLR_I2C_ADDR 0x03 +#define XLR_I2C_DATAOUT 0x04 +#define XLR_I2C_DATAIN 0x05 +#define XLR_I2C_STATUS 0x06 +#define XLR_I2C_STARTXFR 0x07 +#define XLR_I2C_BYTECNT 0x08 +#define XLR_I2C_HDSTATIM 0x09 + +/* XLR I2C REGISTERS FLAGS */ +#define XLR_I2C_BUS_BUSY 0x01 +#define XLR_I2C_SDOEMPTY 0x02 +#define XLR_I2C_RXRDY 0x04 +#define XLR_I2C_ACK_ERR 0x08 +#define XLR_I2C_ARB_STARTERR 0x30 + +/* Register Programming Values!! Change as required */ +#define XLR_I2C_CFG_ADDR 0xF8 /* 8-Bit dev Addr + POR Values */ +#define XLR_I2C_CFG_NOADDR 0xFA /* 8-Bit reg Addr + POR Values : No dev addr */ +#define XLR_I2C_STARTXFR_ND 0x02 /* No data , only addr */ +#define XLR_I2C_STARTXFR_RD 0x01 /* Read */ +#define XLR_I2C_STARTXFR_WR 0x00 /* Write */ +#define XLR_I2C_CLKDIV_DEF 0x14A /* 0x00000052 */ +#define XLR_I2C_HDSTATIM_DEF 0x107 /* 0x00000000 */ + +#define MAXTIME 0x10000 +#define ARIZONA_I2C_BUS 1 static devclass_t xlr_i2c_devclass; @@ -97,206 +97,61 @@ static int xlr_i2c_detach(device_t); static int xlr_i2c_start(device_t dev, u_char slave, int timeout); static int xlr_i2c_stop(device_t dev); static int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay); -static int xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout); - +static int xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout); +static int xlr_i2c_callback(device_t dev, int index, caddr_t data); +static int xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout); +static int xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs); struct xlr_i2c_softc { - device_t dev; /* Myself */ + device_t dev; /* Self */ struct resource *mem_res; /* Memory resource */ volatile int flags; -#define RXRDY 4 -#define TXRDY 0x10 int sc_started; - int twi_addr; + uint8_t i2cdev_addr; + xlr_reg_t *iobase_i2c_regs; device_t iicbus; + struct mtx sc_mtx; }; - -#define MDELAY(a){ \ - unsigned long local_loop = 0xfffff; \ - while(local_loop--); \ -}\ - -static void -get_i2c_base(void) +static void +set_i2c_base(device_t dev) { - if (bus == 0) - iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_0_OFFSET); + struct xlr_i2c_softc *sc; + + sc = device_get_softc(dev); + if (device_get_unit(dev) == 0) + sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_0_OFFSET); else - iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_1_OFFSET); - return; + sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_1_OFFSET); } static void -palm_write(int reg, int value) +xlr_i2c_dev_write(device_t dev, int reg, int value) { - get_i2c_base(); - xlr_write_reg(iobase_i2c_regs, reg, value); + struct xlr_i2c_softc *sc; + + sc = device_get_softc(dev); + xlr_write_reg(sc->iobase_i2c_regs, reg, value); return; } static int -palm_read(int reg) +xlr_i2c_dev_read(device_t dev, int reg) { uint32_t val; + struct xlr_i2c_softc *sc; - get_i2c_base(); - val = xlr_read_reg(iobase_i2c_regs, reg); + sc = device_get_softc(dev); + val = xlr_read_reg(sc->iobase_i2c_regs, reg); return ((int)val); } -static int -palm_addr_only(uint8_t addr, uint8_t offset) -{ - volatile uint32_t regVal = 0x00; - - palm_write(I2C_PALM_ADDR, offset); - palm_write(I2C_PALM_DEVADDR, addr); - palm_write(I2C_PALM_CFG, 0xfa); - palm_write(I2C_PALM_STARTXFR, 0x02); - regVal = palm_read(I2C_PALM_STATUS); - if (regVal & 0x0008) { - printf("palm_addr_only: ACKERR. Aborting...\n"); - return -1; - } - return 0; -} - - -static int -palm_rx(uint8_t addr, uint8_t offset, uint8_t len, - uint8_t * buf) -{ - volatile uint32_t regVal = 0x00, ctr = 0x00; - int timeOut, numBytes = 0x00; - - palm_write(I2C_PALM_CFG, 0xfa); - palm_write(I2C_PALM_BYTECNT, len); - palm_write(I2C_PALM_DEVADDR, addr); - //DEVADDR = 0x4c, 0x68 - MDELAY(1); - - for (numBytes = 0x00; numBytes < len; numBytes++) { - palm_write(I2C_PALM_ADDR, offset + numBytes); -//I2C_PALM_ADDR:offset - MDELAY(1); - if (!ctr) { - /* Trigger a READ Transaction */ - palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD); - ctr++; - } - /* Error Conditions [Begin] */ - regVal = palm_read(I2C_PALM_STATUS); - MDELAY(1); - if (regVal & 0x0008) { - printf("palm_rx: ACKERR. Aborting...\n"); - return -1; - } - timeOut = 10; - while ((regVal & 0x0030) && timeOut--) { - palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD); - regVal = palm_read(I2C_PALM_STATUS); - } - if (timeOut == 0x00) { - printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n"); - return -1; - } - timeOut = 10; - /* Do we have valid data from the device yet..? */ - regVal &= 0x0004; - while (!regVal && timeOut--) { - regVal = palm_read(I2C_PALM_STATUS) & 0x0004; - } - if (timeOut == 0x00) { - printf("palm_rx: TimedOut Waiting for Valid Data\n"); - return -1; - } - /* Error Conditions [End] */ - /* Read the data */ - buf[numBytes] = (uint8_t) palm_read(I2C_PALM_DATAIN); - } - return 0; -} - - - -static int -wait_for_idle(void) -{ - int timeOut = 0x1000; - volatile uint32_t regVal = 0x00; - - regVal = palm_read(I2C_PALM_STATUS) & 0x0001; - while (regVal && timeOut--) { - regVal = palm_read(I2C_PALM_STATUS) & 0x0001; - } - if (timeOut == 0x00) - return -1; /* Timed Out */ - else - return 0; -} - - -static int -palm_tx(uint8_t addr, uint8_t offset, uint8_t * buf, uint8_t len) -{ - volatile uint32_t regVal = 0x00; - int timeOut, ctr = 0x00, numBytes = len; - - for (ctr = 0x00; ctr < len; ctr++) { - if (wait_for_idle() < 0) { - printf("TimedOut on Waiting for I2C Bus Idle.\n"); - return -EIO; - } - palm_write(I2C_PALM_CFG, 0xF8); - palm_write(I2C_PALM_BYTECNT, 0x00); - palm_write(I2C_PALM_DEVADDR, addr); - //0x4c, 0x68 - palm_write(I2C_PALM_ADDR, offset + numBytes - 1); - //offset - palm_write(I2C_PALM_DATAOUT, buf[ctr]); - palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR); - MDELAY(1); - - regVal = palm_read(I2C_PALM_STATUS); - MDELAY(1); - if (regVal & 0x0008) { - printf("palm_tx: ACKERR. Aborting...\n"); - return -1; - } - timeOut = 0x1000; - while (!(regVal & 0x0002) && timeOut) { - regVal = palm_read(I2C_PALM_STATUS); - timeOut--; - } - if (timeOut == 0x00) { - printf("palm_tx: [TimeOut] SDOEMPTY Not Set\n"); - return -1; - } - timeOut = 1000; - while ((regVal & 0x0030) && timeOut) { - palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR); - regVal = palm_read(I2C_PALM_STATUS); - timeOut--; - } - if (timeOut == 0x00) { - printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n"); - return -1; - } - numBytes--; - } - return 0; -} - - - - static int xlr_i2c_probe(device_t dev) { - device_set_desc(dev, "I2C bus controller"); + device_set_desc(dev, "XLR/XLS I2C bus controller"); return (0); } @@ -309,17 +164,40 @@ xlr_i2c_probe(device_t dev) static int xlr_i2c_attach(device_t dev) { - struct xlr_i2c_softc *sc; int rid; + struct xlr_i2c_softc *sc; + device_t tmpd; + + if(device_get_unit(dev)!=ARIZONA_I2C_BUS) { + device_printf(dev, "unused iicbus instance\n"); + return 0; + } sc = device_get_softc(dev); - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); + set_i2c_base(dev); + + mtx_init(&sc->sc_mtx, "xlr_i2c", "xlr_i2c", MTX_DEF); + + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { printf("not able to allocate the bus resource\n"); } - if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) + if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) { printf("could not allocate iicbus instance\n"); + return -1; + } + if(xlr_board_info.xlr_i2c_device[I2C_RTC].enabled == 1) { + tmpd = device_add_child(sc->iicbus, "ds1374u", 0); + device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_RTC]); + } + if(xlr_board_info.xlr_i2c_device[I2C_THERMAL].enabled == 1) { + tmpd = device_add_child(sc->iicbus, "max6657", 0); + device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_THERMAL]); + } + if(xlr_board_info.xlr_i2c_device[I2C_EEPROM].enabled == 1) { + tmpd = device_add_child(sc->iicbus, "at24co2n", 0); + device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_EEPROM]); + } bus_generic_attach(dev); @@ -334,19 +212,6 @@ xlr_i2c_detach(device_t dev) return (0); } -/* -static int -xlr_i2c_add_child(device_t dev, int order, const char *name, int unit) -{ - printf("********* %s ******** \n", __FUNCTION__); - device_add_child_ordered(dev, order, name, unit); - - bus_generic_attach(dev); - - return (0); -} -*/ - static int xlr_i2c_start(device_t dev, u_char slave, int timeout) { @@ -354,9 +219,9 @@ xlr_i2c_start(device_t dev, u_char slave, int timeout) struct xlr_i2c_softc *sc; sc = device_get_softc(dev); + mtx_lock(&sc->sc_mtx); sc->sc_started = 1; - - current_slave = (slave >> 1); + sc->i2cdev_addr = (slave >> 1); return error; } @@ -365,7 +230,10 @@ static int xlr_i2c_stop(device_t dev) { int error = 0; + struct xlr_i2c_softc *sc; + sc = device_get_softc(dev); + mtx_unlock(&sc->sc_mtx); return error; } @@ -374,51 +242,106 @@ static int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay) { - int error = 0; + volatile uint32_t i2c_status = 0; + int pos=0; + int timeout = 0; + + xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR); + xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len); + +retry: + xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD); + + timeout = 0; + while(1) { + if(timeout++ > MAXTIME) + return -1; - if (palm_addr_only(current_slave, read_address) == -1) { - printf("I2C ADDRONLY Phase Fail.\n"); - return -1; - } - if (palm_rx(current_slave, read_address, len, buf) == -1) { - printf("I2C Read Fail.\n"); - return -1; - } - *read = len; - return error; + i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS); + if (i2c_status & XLR_I2C_RXRDY) + buf[pos++] = (uint8_t) xlr_i2c_dev_read(dev, XLR_I2C_DATAIN); -} + /* ACKERR -- bail */ + if (i2c_status & XLR_I2C_ACK_ERR) + return -1; /* ACK_ERROR */ + + /* LOST ARB or STARTERR -- repeat */ + if (i2c_status & XLR_I2C_ARB_STARTERR) + goto retry; + + /* Wait for busy bit to go away */ + if (i2c_status & XLR_I2C_BUS_BUSY) + continue; + if (pos == len) + break; + } + *read = pos; + return 0; + +} static int -xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */ ) +xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */ ) { + volatile uint32_t i2c_status = 0x00; + uint8_t devaddr, addr; + struct xlr_i2c_softc *sc; + int pos; - int error = 0; - uint8_t write_address; + sc = device_get_softc(dev); - if (len == 1) { - /* address for the next read */ - read_address = buf[0]; - return error; + /* the first byte of write is addr (of register in device) */ + addr = buf[0]; + devaddr = sc->i2cdev_addr; + xlr_i2c_dev_write(dev, XLR_I2C_ADDR, addr); + xlr_i2c_dev_write(dev, XLR_I2C_DEVADDR, devaddr); + xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_ADDR); + xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len - 1); + +retry: + pos = 1; + if (len == 1) /* there is no data only address */ + xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_ND); + else { + xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_WR); + xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]); } - if (len < 2) - return (-1); - write_address = buf[0]; + while (1) { + i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS); + + /* sdo empty send next byte */ + if (i2c_status & XLR_I2C_SDOEMPTY) { + pos++; + xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]); + } - /* - * for write operation, buf[0] contains the register offset and - * buf[1] onwards contains the value - */ - palm_tx(current_slave, write_address, &buf[1], len - 1); + /* LOST ARB or STARTERR -- repeat */ + if (i2c_status & XLR_I2C_ARB_STARTERR) + goto retry; - return error; + /* ACKERR -- bail */ + if (i2c_status & XLR_I2C_ACK_ERR) { + printf("ACK ERR : exiting\n "); + return -1; + } + + /* busy try again */ + if (i2c_status & XLR_I2C_BUS_BUSY) + continue; + if (pos >= len) + break;; + } + *sent = len - 1; + return 0; } + + static int -xlr_i2c_callback(device_t dev, int index, caddr_t *data) +xlr_i2c_callback(device_t dev, int index, caddr_t data) { return 0; } @@ -429,6 +352,32 @@ xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout) return 0; } +/* + * I2C bus transfer for RMI boards and devices. + * Generic version of iicbus_transfer that calls the appropriate + * routines to accomplish this. See note above about acceptable + * buffer addresses. + */ +int +xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) +{ + int i, error, lenread, lenwrote; + u_char addr; + + addr = msgs[0].slave | LSB; + error = xlr_i2c_start(bus, addr, 0); + for (i = 0, error = 0; i < nmsgs && error == 0; i++) { + if (msgs[i].flags & IIC_M_RD) { + error = xlr_i2c_read((bus), msgs[i].buf, msgs[i].len, &lenread, IIC_LAST_READ, 0); + } + else { + error = xlr_i2c_write((bus), msgs[i].buf, msgs[i].len, &lenwrote, 0); + } + } + error = xlr_i2c_stop(bus); + return (error); +} + static device_method_t xlr_i2c_methods[] = { /* device interface */ @@ -443,6 +392,7 @@ static device_method_t xlr_i2c_methods[] = { DEVMETHOD(iicbus_stop, xlr_i2c_stop), DEVMETHOD(iicbus_write, xlr_i2c_write), DEVMETHOD(iicbus_read, xlr_i2c_read), + DEVMETHOD(iicbus_transfer, xlr_i2c_transfer), {0, 0} }; @@ -453,3 +403,4 @@ static driver_t xlr_i2c_driver = { }; DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0); +DRIVER_MODULE(iicbus, xlr_i2c, iicbus_driver, iicbus_devclass, 0, 0); |