[23/43] mtd: ts72xx_nand: add platform helper

Message ID 20230424123522.18302-24-nikita.shubin@maquefel.me
State New
Headers
Series ep93xx device tree conversion |

Commit Message

Nikita Shubin April 24, 2023, 12:34 p.m. UTC
  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
  

Patch

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 170f1185ddc4..08f88c34ce53 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -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
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 917cdfb815b9..b1d5cec84519 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -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
diff --git a/drivers/mtd/nand/raw/ts72xx_nand.c b/drivers/mtd/nand/raw/ts72xx_nand.c
new file mode 100644
index 000000000000..1c1c06c6e71a
--- /dev/null
+++ b/drivers/mtd/nand/raw/ts72xx_nand.c
@@ -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);