Implement a handful of missing smbus protocol functions. Proposed on
tech-kern: http://mail-index.netbsd.org/tech-kern/2006/03/16/0029.html
This commit is contained in:
parent
f02decf866
commit
913f185f8f
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: i2c.c,v 1.5 2005/12/11 12:21:22 christos Exp $ */
|
||||
/* $NetBSD: i2c.c,v 1.6 2006/03/27 23:59:38 jmcneill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wasabi Systems, Inc.
|
||||
|
@ -48,6 +48,7 @@
|
|||
struct iic_softc {
|
||||
struct device sc_dev;
|
||||
i2c_tag_t sc_tag;
|
||||
int sc_type;
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -66,7 +67,8 @@ iic_print(void *aux, const char *pnp)
|
|||
{
|
||||
struct i2c_attach_args *ia = aux;
|
||||
|
||||
aprint_normal(" addr 0x%x", ia->ia_addr);
|
||||
if (ia->ia_addr != (i2c_addr_t)-1)
|
||||
aprint_normal(" addr 0x%x", ia->ia_addr);
|
||||
|
||||
return (UNCONF);
|
||||
}
|
||||
|
@ -81,6 +83,7 @@ iic_search(struct device *parent, struct cfdata *cf,
|
|||
ia.ia_tag = sc->sc_tag;
|
||||
ia.ia_addr = cf->cf_loc[IICCF_ADDR];
|
||||
ia.ia_size = cf->cf_loc[IICCF_SIZE];
|
||||
ia.ia_type = sc->sc_type;
|
||||
|
||||
if (config_match(parent, cf, &ia) > 0)
|
||||
config_attach(parent, cf, &ia, iic_print);
|
||||
|
@ -107,6 +110,7 @@ iic_attach(struct device *parent, struct device *self, void *aux)
|
|||
aprint_normal(": I2C bus\n");
|
||||
|
||||
sc->sc_tag = iba->iba_tag;
|
||||
sc->sc_type = iba->iba_type;
|
||||
|
||||
/*
|
||||
* Attach all i2c devices described in the kernel
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: i2c_exec.c,v 1.4 2005/12/11 12:21:22 christos Exp $ */
|
||||
/* $NetBSD: i2c_exec.c,v 1.5 2006/03/27 23:59:38 jmcneill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wasabi Systems, Inc.
|
||||
|
@ -44,6 +44,9 @@
|
|||
#define _I2C_PRIVATE
|
||||
#include <dev/i2c/i2cvar.h>
|
||||
|
||||
static uint8_t iic_smbus_crc8(uint16_t);
|
||||
static uint8_t iic_smbus_pec(int, uint8_t *, uint8_t *);
|
||||
|
||||
/*
|
||||
* iic_exec:
|
||||
*
|
||||
|
@ -63,6 +66,37 @@ iic_exec(i2c_tag_t tag, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
|
|||
int error;
|
||||
size_t len;
|
||||
|
||||
if ((flags & I2C_F_PEC) && cmdlen > 0 && tag->ic_exec != NULL) {
|
||||
uint8_t data[33]; /* XXX */
|
||||
uint8_t b[3];
|
||||
|
||||
b[0] = addr << 1;
|
||||
b[1] = cmd[0];
|
||||
|
||||
switch (buflen) {
|
||||
case 0:
|
||||
data[0] = iic_smbus_pec(2, b, NULL);
|
||||
buflen++;
|
||||
break;
|
||||
case 1:
|
||||
b[2] = buf[0];
|
||||
data[0] = iic_smbus_pec(3, b, NULL);
|
||||
data[1] = b[2];
|
||||
buflen++;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
memcpy(data, vbuf, sizeof(vbuf));
|
||||
data[sizeof(vbuf)] = iic_smbus_pec(2, b, data);
|
||||
buflen++;
|
||||
break;
|
||||
}
|
||||
|
||||
return ((*tag->ic_exec)(tag->ic_cookie, op, addr, cmd,
|
||||
cmdlen, data, buflen, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Defer to the controller if it provides an exec function. Use
|
||||
* it if it does.
|
||||
|
@ -127,6 +161,24 @@ iic_smbus_write_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
|||
&val, 1, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_write_word:
|
||||
*
|
||||
* Perform an SMBus "write word" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_write_word(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
||||
uint16_t val, int flags)
|
||||
{
|
||||
uint8_t vbuf[2];
|
||||
|
||||
vbuf[0] = val & 0xff;
|
||||
vbuf[1] = (val >> 8) & 0xff;
|
||||
|
||||
return (iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd, 1,
|
||||
vbuf, 2, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_read_byte:
|
||||
*
|
||||
|
@ -141,6 +193,20 @@ iic_smbus_read_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
|||
valp, 1, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_read_word:
|
||||
*
|
||||
* Perform an SMBus "read word" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_read_word(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
||||
uint16_t *valp, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, &cmd, 1,
|
||||
(uint8_t *)valp, 2, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_receive_byte:
|
||||
*
|
||||
|
@ -154,3 +220,110 @@ iic_smbus_receive_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t *valp,
|
|||
return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0,
|
||||
valp, 1, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_send_byte:
|
||||
*
|
||||
* Perform an SMBus "send byte" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_send_byte(i2c_tag_t tag, i2c_addr_t addr, uint8_t val, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, NULL, 0,
|
||||
&val, 1, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_quick_read:
|
||||
*
|
||||
* Perform an SMBus "quick read" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_quick_read(i2c_tag_t tag, i2c_addr_t addr, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, NULL, 0,
|
||||
NULL, 0, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_quick_write:
|
||||
*
|
||||
* Perform an SMBus "quick write" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_quick_write(i2c_tag_t tag, i2c_addr_t addr, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, NULL, 0,
|
||||
NULL, 0, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_block_read:
|
||||
*
|
||||
* Perform an SMBus "block read" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_block_read(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
||||
uint8_t *vbuf, size_t buflen, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, &cmd, 1,
|
||||
vbuf, buflen, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_block_write:
|
||||
*
|
||||
* Perform an SMBus "block write" operation.
|
||||
*/
|
||||
int
|
||||
iic_smbus_block_write(i2c_tag_t tag, i2c_addr_t addr, uint8_t cmd,
|
||||
uint8_t *vbuf, size_t buflen, int flags)
|
||||
{
|
||||
|
||||
return (iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd, 1,
|
||||
vbuf, buflen, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_crc8
|
||||
*
|
||||
* Private helper for calculating packet error checksum
|
||||
*/
|
||||
static uint8_t
|
||||
iic_smbus_crc8(uint16_t data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (data & 0x8000)
|
||||
data = data ^ (0x1070U << 3);
|
||||
data = data << 1;
|
||||
}
|
||||
|
||||
return (uint8_t)(data >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* iic_smbus_pec
|
||||
*
|
||||
* Private function for calculating packet error checking on SMBus
|
||||
* packets.
|
||||
*/
|
||||
static uint8_t
|
||||
iic_smbus_pec(int count, uint8_t *s, uint8_t *r)
|
||||
{
|
||||
int i;
|
||||
uint8_t crc = 0;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
crc = iic_smbus_crc8((crc ^ s[i]) << 8);
|
||||
if (r != NULL)
|
||||
for (i = 0; i <= r[0]; i++)
|
||||
crc = iic_smbus_crc8((crc ^ r[i]) << 8);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: i2cvar.h,v 1.2 2005/12/11 12:21:22 christos Exp $ */
|
||||
/* $NetBSD: i2cvar.h,v 1.3 2006/03/27 23:59:38 jmcneill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wasabi Systems, Inc.
|
||||
|
@ -46,6 +46,7 @@
|
|||
#define I2C_F_LAST 0x02 /* last byte of read */
|
||||
#define I2C_F_STOP 0x04 /* send stop after byte */
|
||||
#define I2C_F_POLL 0x08 /* poll, don't sleep */
|
||||
#define I2C_F_PEC 0x10 /* smbus packet error checking */
|
||||
|
||||
/*
|
||||
* This structure provides the interface between the i2c framework
|
||||
|
@ -89,10 +90,14 @@ typedef struct i2c_controller {
|
|||
int (*ic_write_byte)(void *, uint8_t, int);
|
||||
} *i2c_tag_t;
|
||||
|
||||
/* I2C bus types */
|
||||
#define I2C_TYPE_SMBUS 1
|
||||
|
||||
/* Used to attach the i2c framework to the controller. */
|
||||
struct i2cbus_attach_args {
|
||||
const char *iba_name; /* bus name ("iic") */
|
||||
i2c_tag_t iba_tag; /* the controller */
|
||||
int iba_type; /* bus type */
|
||||
};
|
||||
|
||||
/* Used to attach devices on the i2c bus. */
|
||||
|
@ -100,6 +105,7 @@ struct i2c_attach_args {
|
|||
i2c_tag_t ia_tag; /* our controller */
|
||||
i2c_addr_t ia_addr; /* address of device */
|
||||
int ia_size; /* size (for EEPROMs) */
|
||||
int ia_type; /* bus type */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -137,7 +143,16 @@ int iic_exec(i2c_tag_t, i2c_op_t, i2c_addr_t, const void *,
|
|||
size_t, void *, size_t, int);
|
||||
|
||||
int iic_smbus_write_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t, int);
|
||||
int iic_smbus_write_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t, int);
|
||||
int iic_smbus_read_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, int);
|
||||
int iic_smbus_read_word(i2c_tag_t, i2c_addr_t, uint8_t, uint16_t *, int);
|
||||
int iic_smbus_receive_byte(i2c_tag_t, i2c_addr_t, uint8_t *, int);
|
||||
int iic_smbus_send_byte(i2c_tag_t, i2c_addr_t, uint8_t, int);
|
||||
int iic_smbus_quick_read(i2c_tag_t, i2c_addr_t, int);
|
||||
int iic_smbus_quick_write(i2c_tag_t, i2c_addr_t, int);
|
||||
int iic_smbus_block_read(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *,
|
||||
size_t, int);
|
||||
int iic_smbus_block_write(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *,
|
||||
size_t, int);
|
||||
|
||||
#endif /* _DEV_I2C_I2CVAR_H_ */
|
||||
|
|
Loading…
Reference in New Issue