u8 data8, *dst8;
 
        doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
-       cdr = len & 0x3;
+       cdr = len & 0x1;
        len4 = len - cdr;
 
        if (first)
  * @len: the number of bytes to be read (must be a multiple of 4)
  * @buf: the buffer to be filled in (or NULL is forget bytes)
  * @first: 1 if first time read, DOC_READADDRESS should be set
+ * @last_odd: 1 if last read ended up on an odd byte
+ *
+ * Reads bytes from a prepared page. There is a trickery here : if the last read
+ * ended up on an odd offset in the 1024 bytes double page, ie. between the 2
+ * planes, the first byte must be read apart. If a word (16bit) read was used,
+ * the read would return the byte of plane 2 as low *and* high endian, which
+ * will mess the read.
  *
  */
 static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
-                                 int first)
+                                 int first, int last_odd)
 {
-       doc_read_data_area(docg3, buf, len, first);
+       if (last_odd && len > 0) {
+               doc_read_data_area(docg3, buf, 1, first);
+               doc_read_data_area(docg3, buf ? buf + 1 : buf, len - 1, 0);
+       } else {
+               doc_read_data_area(docg3, buf, len, first);
+       }
        doc_delay(docg3, 2);
        return len;
 }
                ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES);
                if (ret < 0)
                        goto err_in_read;
-               ret = doc_read_page_getbytes(docg3, skip, NULL, 1);
+               ret = doc_read_page_getbytes(docg3, skip, NULL, 1, 0);
                if (ret < skip)
                        goto err_in_read;
-               ret = doc_read_page_getbytes(docg3, nbdata, buf, 0);
+               ret = doc_read_page_getbytes(docg3, nbdata, buf, 0, skip % 2);
                if (ret < nbdata)
                        goto err_in_read;
                doc_read_page_getbytes(docg3,
                                       DOC_LAYOUT_PAGE_SIZE - nbdata - skip,
-                                      NULL, 0);
-               ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0);
+                                      NULL, 0, (skip + nbdata) % 2);
+               ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0, 0);
                if (ret < nboob)
                        goto err_in_read;
                doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob,
-                                      NULL, 0);
+                                      NULL, 0, nboob % 2);
 
                doc_get_bch_hw_ecc(docg3, hwecc);
                eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
                                                     DOC_LAYOUT_PAGE_SIZE);
                if (!ret)
                        doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
-                                              buf, 1);
+                                              buf, 1, 0);
                buf += DOC_LAYOUT_PAGE_SIZE;
        }
        doc_read_page_finish(docg3);
        ret = doc_reset_seq(docg3);
        if (!ret)
                ret = doc_read_page_prepare(docg3, block0, block1, page,
-                                           ofs + DOC_LAYOUT_WEAR_OFFSET);
+                                           ofs + DOC_LAYOUT_WEAR_OFFSET, 0);
        if (!ret)
                ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE,
-                                            buf, 1);
+                                            buf, 1, 0);
        doc_read_page_finish(docg3);
 
        if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK))