/* 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);