in rtc-x1205.c [380:491]
static int x1205_validate_client(struct i2c_client *client)
{
int i, xfer;
/* Probe array. We will read the register at the specified
* address and check if the given bits are zero.
*/
static const unsigned char probe_zero_pattern[] = {
/* register, mask */
X1205_REG_SR, 0x18,
X1205_REG_DTR, 0xF8,
X1205_REG_ATR, 0xC0,
X1205_REG_INT, 0x18,
X1205_REG_0, 0xFF,
};
static const struct x1205_limit probe_limits_pattern[] = {
/* register, mask, min, max */
{ X1205_REG_Y2K, 0xFF, 19, 20 },
{ X1205_REG_DW, 0xFF, 0, 6 },
{ X1205_REG_YR, 0xFF, 0, 99 },
{ X1205_REG_MO, 0xFF, 0, 12 },
{ X1205_REG_DT, 0xFF, 0, 31 },
{ X1205_REG_HR, 0x7F, 0, 23 },
{ X1205_REG_MN, 0xFF, 0, 59 },
{ X1205_REG_SC, 0xFF, 0, 59 },
{ X1205_REG_Y2K1, 0xFF, 19, 20 },
{ X1205_REG_Y2K0, 0xFF, 19, 20 },
};
/* check that registers have bits a 0 where expected */
for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
unsigned char buf;
unsigned char addr[2] = { 0, probe_zero_pattern[i] };
struct i2c_msg msgs[2] = {
{
.addr = client->addr,
.len = 2,
.buf = addr
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = &buf
},
};
xfer = i2c_transfer(client->adapter, msgs, 2);
if (xfer != 2) {
dev_err(&client->dev,
"%s: could not read register %x\n",
__func__, probe_zero_pattern[i]);
return -EIO;
}
if ((buf & probe_zero_pattern[i+1]) != 0) {
dev_err(&client->dev,
"%s: register=%02x, zero pattern=%d, value=%x\n",
__func__, probe_zero_pattern[i], i, buf);
return -ENODEV;
}
}
/* check limits (only registers with bcd values) */
for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
unsigned char reg, value;
unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
struct i2c_msg msgs[2] = {
{
.addr = client->addr,
.len = 2,
.buf = addr
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = ®
},
};
xfer = i2c_transfer(client->adapter, msgs, 2);
if (xfer != 2) {
dev_err(&client->dev,
"%s: could not read register %x\n",
__func__, probe_limits_pattern[i].reg);
return -EIO;
}
value = bcd2bin(reg & probe_limits_pattern[i].mask);
if (value > probe_limits_pattern[i].max ||
value < probe_limits_pattern[i].min) {
dev_dbg(&client->dev,
"%s: register=%x, lim pattern=%d, value=%d\n",
__func__, probe_limits_pattern[i].reg,
i, value);
return -ENODEV;
}
}
return 0;
}