|
@@ -188,3 +188,153 @@ static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
|
|
writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL);
|
|
|
}
|
|
|
|
|
|
+ if (cmd != NAND_CMD_NONE)
|
|
|
+ writeb(cmd, this->IO_ADDR_W);
|
|
|
+}
|
|
|
+
|
|
|
+static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
|
|
|
+{
|
|
|
+ return readb(TS_NAND_CTRL) & 0x20;
|
|
|
+}
|
|
|
+
|
|
|
+static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
|
|
|
+ const uint8_t *buf, int len)
|
|
|
+{
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ void __iomem *io_base = chip->IO_ADDR_W;
|
|
|
+ unsigned long off = ((unsigned long)buf & 3);
|
|
|
+ int sz;
|
|
|
+
|
|
|
+ if (off) {
|
|
|
+ sz = min_t(int, 4 - off, len);
|
|
|
+ writesb(io_base, buf, sz);
|
|
|
+ buf += sz;
|
|
|
+ len -= sz;
|
|
|
+ }
|
|
|
+
|
|
|
+ sz = len >> 2;
|
|
|
+ if (sz) {
|
|
|
+ u32 *buf32 = (u32 *)buf;
|
|
|
+ writesl(io_base, buf32, sz);
|
|
|
+ buf += sz << 2;
|
|
|
+ len -= sz << 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len)
|
|
|
+ writesb(io_base, buf, len);
|
|
|
+}
|
|
|
+
|
|
|
+static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
|
|
|
+ uint8_t *buf, int len)
|
|
|
+{
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ void __iomem *io_base = chip->IO_ADDR_R;
|
|
|
+ unsigned long off = ((unsigned long)buf & 3);
|
|
|
+ int sz;
|
|
|
+
|
|
|
+ if (off) {
|
|
|
+ sz = min_t(int, 4 - off, len);
|
|
|
+ readsb(io_base, buf, sz);
|
|
|
+ buf += sz;
|
|
|
+ len -= sz;
|
|
|
+ }
|
|
|
+
|
|
|
+ sz = len >> 2;
|
|
|
+ if (sz) {
|
|
|
+ u32 *buf32 = (u32 *)buf;
|
|
|
+ readsl(io_base, buf32, sz);
|
|
|
+ buf += sz << 2;
|
|
|
+ len -= sz << 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len)
|
|
|
+ readsb(io_base, buf, len);
|
|
|
+}
|
|
|
+
|
|
|
+static struct mtd_partition ts78xx_ts_nand_parts[] = {
|
|
|
+ {
|
|
|
+ .name = "mbr",
|
|
|
+ .offset = 0,
|
|
|
+ .size = SZ_128K,
|
|
|
+ .mask_flags = MTD_WRITEABLE,
|
|
|
+ }, {
|
|
|
+ .name = "kernel",
|
|
|
+ .offset = MTDPART_OFS_APPEND,
|
|
|
+ .size = SZ_4M,
|
|
|
+ }, {
|
|
|
+ .name = "initrd",
|
|
|
+ .offset = MTDPART_OFS_APPEND,
|
|
|
+ .size = SZ_4M,
|
|
|
+ }, {
|
|
|
+ .name = "rootfs",
|
|
|
+ .offset = MTDPART_OFS_APPEND,
|
|
|
+ .size = MTDPART_SIZ_FULL,
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+static struct platform_nand_data ts78xx_ts_nand_data = {
|
|
|
+ .chip = {
|
|
|
+ .nr_chips = 1,
|
|
|
+ .partitions = ts78xx_ts_nand_parts,
|
|
|
+ .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts),
|
|
|
+ .chip_delay = 15,
|
|
|
+ .bbt_options = NAND_BBT_USE_FLASH,
|
|
|
+ },
|
|
|
+ .ctrl = {
|
|
|
+ /*
|
|
|
+ * The HW ECC offloading functions, used to give about a 9%
|
|
|
+ * performance increase for 'dd if=/dev/mtdblockX' and 5% for
|
|
|
+ * nanddump. This all however was changed by git commit
|
|
|
+ * 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,
|
|
|
+ .write_buf = ts78xx_ts_nand_write_buf,
|
|
|
+ .read_buf = ts78xx_ts_nand_read_buf,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static struct resource ts78xx_ts_nand_resources
|
|
|
+ = DEFINE_RES_MEM(TS_NAND_DATA, 4);
|
|
|
+
|
|
|
+static struct platform_device ts78xx_ts_nand_device = {
|
|
|
+ .name = "gen_nand",
|
|
|
+ .id = -1,
|
|
|
+ .dev = {
|
|
|
+ .platform_data = &ts78xx_ts_nand_data,
|
|
|
+ },
|
|
|
+ .resource = &ts78xx_ts_nand_resources,
|
|
|
+ .num_resources = 1,
|
|
|
+};
|
|
|
+
|
|
|
+static int ts78xx_ts_nand_load(void)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (ts78xx_fpga.supports.ts_nand.init == 0) {
|
|
|
+ rc = platform_device_register(&ts78xx_ts_nand_device);
|
|
|
+ if (!rc)
|
|
|
+ ts78xx_fpga.supports.ts_nand.init = 1;
|
|
|
+ } else
|
|
|
+ rc = platform_device_add(&ts78xx_ts_nand_device);
|
|
|
+
|
|
|
+ if (rc)
|
|
|
+ pr_info("NAND could not be registered: %d\n", rc);
|
|
|
+ return rc;
|
|
|
+};
|
|
|
+
|
|
|
+static void ts78xx_ts_nand_unload(void)
|
|
|
+{
|
|
|
+ platform_device_del(&ts78xx_ts_nand_device);
|
|
|
+}
|
|
|
+
|
|
|
+/*****************************************************************************
|
|
|
+ * HW RNG
|
|
|
+ ****************************************************************************/
|
|
|
+#define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044)
|
|
|
+
|
|
|
+static struct resource ts78xx_ts_rng_resource
|
|
|
+ = DEFINE_RES_MEM(TS_RNG_DATA, 4);
|
|
|
+
|
|
|
+static struct timeriomem_rng_data ts78xx_ts_rng_data = {
|