/* this driver doesn't aim at the peak continuous sample rate */
#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
-struct ts_event {
+struct ads7846_buf {
+ u8 cmd;
/*
- * For portability, we can't read 12 bit values using SPI (which
- * would make the controller deliver them as native byte order u16
- * with msbs zeroed). Instead, we read them as two 8-bit values,
- * *** WHICH NEED BYTESWAPPING *** and range adjustment.
+ * This union is a temporary hack. The driver does an in-place
+ * endianness conversion. This will be cleaned up in the next
+ * patch.
*/
- u16 x;
- u16 y;
- u16 z1, z2;
- bool ignore;
- u8 x_buf[3];
- u8 y_buf[3];
+ union {
+ __be16 data_be16;
+ u16 data;
+ };
+} __packed;
+
+
+struct ts_event {
+ bool ignore;
+ struct ads7846_buf x;
+ struct ads7846_buf y;
+ struct ads7846_buf z1;
+ struct ads7846_buf z2;
};
/*
* systems where main memory is not DMA-coherent (most non-x86 boards).
*/
struct ads7846_packet {
- u8 read_x, read_y, read_z1, read_z2, pwrdown;
- u16 dummy; /* for the pwrdown read */
- struct ts_event tc;
- /* for ads7845 with mpc5121 psc spi we use 3-byte buffers */
- u8 read_x_cmd[3], read_y_cmd[3], pwrdown_cmd[3];
+ struct ts_event tc;
+ struct ads7846_buf read_x_cmd;
+ struct ads7846_buf read_y_cmd;
+ struct ads7846_buf read_z1_cmd;
+ struct ads7846_buf read_z2_cmd;
+ struct ads7846_buf pwrdown_cmd;
};
struct ads7846 {
int value;
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+ struct ads7846_buf *buf = t->rx_buf;
- if (ts->model == 7845) {
- value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
- } else {
- /*
- * adjust: on-wire is a must-ignore bit, a BE12 value, then
- * padding; built from two 8 bit values written msb-first.
- */
- value = be16_to_cpup((__be16 *)t->rx_buf);
- }
+ value = be16_to_cpup(&buf->data_be16);
/* enforce ADC output is 12 bits width */
return (value >> 3) & 0xfff;
{
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+ struct ads7846_buf *buf = t->rx_buf;
- *(u16 *)t->rx_buf = val;
+ buf->data = val;
}
static void ads7846_read_state(struct ads7846 *ts)
* from on-the-wire format as part of debouncing to get stable
* readings.
*/
+ x = packet->tc.x.data;
+ y = packet->tc.y.data;
if (ts->model == 7845) {
- x = *(u16 *)packet->tc.x_buf;
- y = *(u16 *)packet->tc.y_buf;
z1 = 0;
z2 = 0;
} else {
- x = packet->tc.x;
- y = packet->tc.y;
- z1 = packet->tc.z1;
- z2 = packet->tc.z2;
+ z1 = packet->tc.z1.data;
+ z2 = packet->tc.z2.data;
}
/* range filtering */
spi_message_init(m);
m->context = ts;
- if (ts->model == 7845) {
- packet->read_y_cmd[0] = READ_Y(vref);
- packet->read_y_cmd[1] = 0;
- packet->read_y_cmd[2] = 0;
- x->tx_buf = &packet->read_y_cmd[0];
- x->rx_buf = &packet->tc.y_buf[0];
- x->len = 3;
- spi_message_add_tail(x, m);
- } else {
- /* y- still on; turn on only y+ (and ADC) */
- packet->read_y = READ_Y(vref);
- x->tx_buf = &packet->read_y;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
- x->rx_buf = &packet->tc.y;
- x->len = 2;
- spi_message_add_tail(x, m);
- }
+ packet->read_y_cmd.cmd = READ_Y(vref);
+ x->tx_buf = &packet->read_y_cmd;
+ x->rx_buf = &packet->tc.y;
+ x->len = 3;
+ spi_message_add_tail(x, m);
/*
* The first sample after switching drivers can be low quality;
if (pdata->settle_delay_usecs) {
x->delay.value = pdata->settle_delay_usecs;
x->delay.unit = SPI_DELAY_UNIT_USECS;
-
x++;
- x->tx_buf = &packet->read_y;
- x->len = 1;
- spi_message_add_tail(x, m);
- x++;
+ x->tx_buf = &packet->read_y_cmd;
x->rx_buf = &packet->tc.y;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
}
spi_message_init(m);
m->context = ts;
- if (ts->model == 7845) {
- x++;
- packet->read_x_cmd[0] = READ_X(vref);
- packet->read_x_cmd[1] = 0;
- packet->read_x_cmd[2] = 0;
- x->tx_buf = &packet->read_x_cmd[0];
- x->rx_buf = &packet->tc.x_buf[0];
- x->len = 3;
- spi_message_add_tail(x, m);
- } else {
- /* turn y- off, x+ on, then leave in lowpower */
- x++;
- packet->read_x = READ_X(vref);
- x->tx_buf = &packet->read_x;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
- x->rx_buf = &packet->tc.x;
- x->len = 2;
- spi_message_add_tail(x, m);
- }
+ /* turn y- off, x+ on, then leave in lowpower */
+ x++;
+ packet->read_x_cmd.cmd = READ_X(vref);
+ x->tx_buf = &packet->read_x_cmd;
+ x->rx_buf = &packet->tc.x;
+ x->len = 3;
+ spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
if (pdata->settle_delay_usecs) {
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
- x->tx_buf = &packet->read_x;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
+ x->tx_buf = &packet->read_x_cmd;
x->rx_buf = &packet->tc.x;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
}
m->context = ts;
x++;
- packet->read_z1 = READ_Z1(vref);
- x->tx_buf = &packet->read_z1;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
+ packet->read_z1_cmd.cmd = READ_Z1(vref);
+ x->tx_buf = &packet->read_z1_cmd;
x->rx_buf = &packet->tc.z1;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
- x->tx_buf = &packet->read_z1;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
+ x->tx_buf = &packet->read_z1_cmd;
x->rx_buf = &packet->tc.z1;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
}
m->context = ts;
x++;
- packet->read_z2 = READ_Z2(vref);
- x->tx_buf = &packet->read_z2;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
+ packet->read_z2_cmd.cmd = READ_Z2(vref);
+ x->tx_buf = &packet->read_z2_cmd;
x->rx_buf = &packet->tc.z2;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
- x->tx_buf = &packet->read_z2;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
+ x->tx_buf = &packet->read_z2_cmd;
x->rx_buf = &packet->tc.z2;
- x->len = 2;
+ x->len = 3;
spi_message_add_tail(x, m);
}
}
spi_message_init(m);
m->context = ts;
- if (ts->model == 7845) {
- x++;
- packet->pwrdown_cmd[0] = PWRDOWN;
- packet->pwrdown_cmd[1] = 0;
- packet->pwrdown_cmd[2] = 0;
- x->tx_buf = &packet->pwrdown_cmd[0];
- x->len = 3;
- } else {
- x++;
- packet->pwrdown = PWRDOWN;
- x->tx_buf = &packet->pwrdown;
- x->len = 1;
- spi_message_add_tail(x, m);
-
- x++;
- x->rx_buf = &packet->dummy;
- x->len = 2;
- }
+ x++;
+ packet->pwrdown_cmd.cmd = PWRDOWN;
+ x->tx_buf = &packet->pwrdown_cmd;
+ x->len = 3;
CS_CHANGE(*x);
spi_message_add_tail(x, m);