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)
This commit is contained in:
parent
9daf74d4c8
commit
d381cdd7a8
@ -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
|
||||
|
@ -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,6 +289,10 @@ xls_board_specific_overrides(struct xlr_board_info* board)
|
||||
break;
|
||||
|
||||
case RMI_XLR_BOARD_ARIZONA_VIII:
|
||||
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. */
|
||||
@ -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
|
||||
@ -413,6 +424,14 @@ xlr_board_info_setup()
|
||||
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;
|
||||
xlr_board_info.nr_cpus = 8;
|
||||
|
@ -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 */
|
||||
|
145
sys/mips/rmi/dev/iic/at24co2n.c
Normal file
145
sys/mips/rmi/dev/iic/at24co2n.c
Normal file
@ -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);
|
162
sys/mips/rmi/dev/iic/ds1374u.c
Normal file
162
sys/mips/rmi/dev/iic/ds1374u.c
Normal file
@ -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);
|
162
sys/mips/rmi/dev/iic/max6657.c
Normal file
162
sys/mips/rmi/dev/iic/max6657.c
Normal file
@ -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);
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
/* 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
|
||||
|
||||
#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
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
/* 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 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;
|
||||
#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)
|
||||
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;
|
||||
|
||||
if (palm_addr_only(current_slave, read_address) == -1) {
|
||||
printf("I2C ADDRONLY Phase Fail.\n");
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
if (palm_rx(current_slave, read_address, len, buf) == -1) {
|
||||
printf("I2C Read Fail.\n");
|
||||
return -1;
|
||||
}
|
||||
*read = len;
|
||||
return error;
|
||||
*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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
/* sdo empty send next byte */
|
||||
if (i2c_status & XLR_I2C_SDOEMPTY) {
|
||||
pos++;
|
||||
xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]);
|
||||
}
|
||||
|
||||
return error;
|
||||
/* LOST ARB or STARTERR -- repeat */
|
||||
if (i2c_status & XLR_I2C_ARB_STARTERR)
|
||||
goto retry;
|
||||
|
||||
/* 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);
|
||||
|
Loading…
Reference in New Issue
Block a user