The only purpose of this code to provide platform_nand_data to gen_nand
driver which requires .cmd_ctrl and .dev_ready.
Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
---
Notes:
rfc->v0
Alexander Sverdlin:
- platfrom -> platform
Linus Walleij:
- __raw_read/write[w|l] -> readb/writeb
Arnd Bergmann:
- name match node ts7250 instead of wildcard
drivers/mtd/nand/raw/Kconfig | 8 +++
drivers/mtd/nand/raw/Makefile | 1 +
drivers/mtd/nand/raw/ts72xx_nand.c | 94 ++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+)
create mode 100644 drivers/mtd/nand/raw/ts72xx_nand.c
@@ -456,6 +456,14 @@ config MTD_NAND_RENESAS
Enables support for the NAND controller found on Renesas R-Car
Gen3 and RZ/N1 SoC families.
+config MTD_NAND_TS72XX
+ bool "ts72xx NAND controller"
+ depends on ARCH_EP93XX && HAS_IOMEM
+ select MTD_NAND_PLATFORM
+ help
+ Enables support for NAND controller on ts72xx SBCs.
+ These only set's platform data. The real driver is gen_nand.
+
comment "Misc"
config MTD_SM_COMMON
@@ -23,6 +23,7 @@ omap2_nand-objs := omap2.o
obj-$(CONFIG_MTD_NAND_OMAP2) += omap2_nand.o
obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD) += omap_elm.o
obj-$(CONFIG_MTD_NAND_MARVELL) += marvell_nand.o
+obj-$(CONFIG_MTD_NAND_TS72XX) += ts72xx_nand.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
new file mode 100644
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Technologic Systems TS72xx NAND driver platform code
+ * Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/platnand.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
+#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
+
+static void ts72xx_nand_hwcontrol(struct nand_chip *chip,
+ int cmd, unsigned int ctrl)
+{
+ if (ctrl & NAND_CTRL_CHANGE) {
+ void __iomem *addr = chip->legacy.IO_ADDR_R;
+ unsigned char bits;
+
+ addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
+
+ bits = readb(addr) & ~0x07;
+ bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
+ bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
+ bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
+
+ writeb(bits, addr);
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->legacy.IO_ADDR_W);
+}
+
+static int ts72xx_nand_device_ready(struct nand_chip *chip)
+{
+ void __iomem *addr = chip->legacy.IO_ADDR_R;
+
+ addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
+
+ return !!(readb(addr) & 0x20);
+}
+
+static struct platform_nand_data ts72xx_nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .chip_delay = 15,
+ },
+ .ctrl = {
+ .cmd_ctrl = ts72xx_nand_hwcontrol,
+ .dev_ready = ts72xx_nand_device_ready,
+ },
+};
+
+static int __init ts72xx_nand_setup(void)
+{
+ struct device_node *np;
+ struct platform_device *pdev;
+
+ /* Multiplatform guard, only proceed on ts7250 */
+ if (!of_machine_is_compatible("technologic,ts7250"))
+ return 0;
+
+ np = of_find_compatible_node(NULL, NULL, "technologic,ts7200-nand");
+ if (!np) {
+ pr_err("%s : nand device tree node not found.\n", __func__);
+ return -EINVAL;
+ }
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev) {
+ pr_err("%s : nand device not found.\n", __func__);
+ return -EINVAL;
+ }
+
+ pdev->dev.platform_data = &ts72xx_nand_data;
+ put_device(&pdev->dev);
+ of_node_put(np);
+
+ return 0;
+}
+
+subsys_initcall(ts72xx_nand_setup);