@@ -191,6 +191,75 @@ static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
return readb(TS_NAND_CTRL) & 0x20;
}
+/*
+ * FPGA will handle 8/16/32bit reads and writes
+ */
+static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
+ uint8_t *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (len % 2) {
+ *buf++ = readb(this->IO_ADDR_R);
+ len--;
+ }
+ if (len % 4 == 2) {
+ uint16_t *t = (uint16_t *) buf;
+ *t = readw(this->IO_ADDR_R);
+ buf += 2;
+ len -= 2;
+ }
+
+ while (len > 3) {
+ uint32_t *t = (uint32_t *) buf;
+ *t = readl(this->IO_ADDR_R);
+ buf += 4;
+ len -= 4;
+ }
+
+ if (len % 4 == 2) {
+ uint16_t *t = (uint16_t *) buf;
+ *t = readw(this->IO_ADDR_R);
+ buf += 2;
+ len -= 2;
+ }
+ if (len)
+ *buf = readb(this->IO_ADDR_R);
+}
+
+static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
+ const uint8_t *buf, int len)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (len % 2) {
+ writeb(*buf++, this->IO_ADDR_W);
+ len--;
+ }
+ if (len % 4 == 2) {
+ uint16_t *t = (uint16_t *) buf;
+ writew(*t, this->IO_ADDR_W);
+ buf += 2;
+ len -= 2;
+ }
+
+ while (len > 3) {
+ uint32_t *t = (uint32_t *) buf;
+ writel(*t, this->IO_ADDR_W);
+ buf += 4;
+ len -= 4;
+ }
+
+ if (len % 4 == 2) {
+ uint16_t *t = (uint16_t *) buf;
+ writew(*t, this->IO_ADDR_W);
+ buf += 2;
+ len -= 2;
+ }
+ if (len)
+ writeb(*buf, this->IO_ADDR_W);
+}
+
const char *ts_nand_part_probes[] = { "cmdlinepart", NULL };
static struct mtd_partition ts78xx_ts_nand_parts[] = {
@@ -230,8 +299,10 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
* e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is
* no performance advantage to be had so we no longer bother
*/
- .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl,
.dev_ready = ts78xx_ts_nand_dev_ready,
+ .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl,
+ .read_buf = ts78xx_ts_nand_read_buf,
+ .write_buf = ts78xx_ts_nand_write_buf,
},
};
@@ -61,6 +61,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
data->chip.dev_ready = pdata->ctrl.dev_ready;
data->chip.select_chip = pdata->ctrl.select_chip;
+ data->chip.write_buf = pdata->ctrl.write_buf;
+ data->chip.read_buf = pdata->ctrl.read_buf;
data->chip.chip_delay = pdata->chip.chip_delay;
data->chip.options |= pdata->chip.options;
@@ -584,6 +584,8 @@ struct platform_nand_chip {
* @select_chip: platform specific chip select function
* @cmd_ctrl: platform specific function for controlling
* ALE/CLE/nCE. Also used to write command and address
+ * @write_buf: platform specific function for write buffer
+ * @read_buf: platform specific function for read buffer
* @priv: private data to transport driver specific settings
*
* All fields are optional and depend on the hardware driver requirements
@@ -594,6 +596,10 @@ struct platform_nand_ctrl {
void (*select_chip)(struct mtd_info *mtd, int chip);
void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
unsigned int ctrl);
+ void (*write_buf)(struct mtd_info *mtd,
+ const uint8_t *buf, int len);
+ void (*read_buf)(struct mtd_info *mtd,
+ uint8_t *buf, int len);
void *priv;
};