diff mbox series

[v2,4/9] drivers: Add fu540 board driver

Message ID 20200519192340.16624-5-jagan@amarulasolutions.com
State New
Headers show
Series riscv: sifive/fu540: Booting from SPI | expand

Commit Message

Jagan Teki May 19, 2020, 7:23 p.m. UTC
Add fu540 board driver, which is used to get runtime
boot mode of fu540 boards.

Cc: Mario Six <mario.six at gdsys.cc>
Cc: Tom Rini <trini at konsulko.com>
Cc: Simon Glass <sjg at chromium.org>
Cc: Jean-Jacques Hiblot <jjhiblot at ti.com>
Signed-off-by: Jagan Teki <jagan at amarulasolutions.com>
---
Changes for v2:
- new patch

 drivers/board/Kconfig  |  8 ++++
 drivers/board/Makefile |  1 +
 drivers/board/fu540.c  | 86 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 95 insertions(+)
 create mode 100644 drivers/board/fu540.c
diff mbox series

Patch

diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
index 254f657049..306ee76bbd 100644
--- a/drivers/board/Kconfig
+++ b/drivers/board/Kconfig
@@ -12,6 +12,14 @@  config SPL_BOARD
 	depends on SPL_DM
 	bool "Enable board driver support in SPL"
 
+config BOARD_FU540
+	bool "Enable board driver for the FU540 boards"
+	depends on RISCV
+	select SPL_BOARD
+	help
+	  Support querying board information for the fu540 boards, like
+	  get soc mode select, get SPL boot device and etc.
+
 config BOARD_GAZERBEAM
 	bool "Enable board driver for the Gazerbeam board"
 	help
diff --git a/drivers/board/Makefile b/drivers/board/Makefile
index cc16361755..e924472779 100644
--- a/drivers/board/Makefile
+++ b/drivers/board/Makefile
@@ -3,5 +3,6 @@ 
 # (C) Copyright 2017
 # Mario Six,  Guntermann & Drunck GmbH, mario.six at gdsys.cc
 obj-y += board-uclass.o
+obj-$(CONFIG_BOARD_FU540) += fu540.o
 obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o
 obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o
diff --git a/drivers/board/fu540.c b/drivers/board/fu540.c
new file mode 100644
index 0000000000..68d356df6b
--- /dev/null
+++ b/drivers/board/fu540.c
@@ -0,0 +1,86 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Amarula Solutions(India)
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <board.h>
+#include <spl.h>
+#include <asm/io.h>
+
+#define MODE_SELECT_QSPI	0x6
+#define MODE_SELECT_SD		0xb
+#define MODE_SELECT_MASK	GENMASK(3, 0)
+
+struct fu540_board {
+	void __iomem *regs;
+};
+
+static int fu540_get_boot_device(struct udevice *dev)
+{
+	struct fu540_board *priv = dev_get_priv(dev);
+	u8 boot_device = BOOT_DEVICE_MMC1;
+	u32 reg;
+
+	reg = readl(priv->regs);
+	switch (reg & MODE_SELECT_MASK) {
+	case MODE_SELECT_QSPI:
+		boot_device = BOOT_DEVICE_SPI;
+		break;
+	case MODE_SELECT_SD:
+		boot_device = BOOT_DEVICE_MMC1;
+		break;
+	default:
+		dev_err(dev,
+			"Unsupported boot device 0x%x but trying MMC1\n",
+			boot_device);
+		break;
+	}
+
+	return boot_device;
+}
+
+static int fu540_board_get_int(struct udevice *dev, int id, int *val)
+{
+	switch (id) {
+	case BOARD_SPL_BOOT_DEVICE:
+		*val = fu540_get_boot_device(dev);
+		break;
+	default:
+		dev_err(dev, "%s: Integer value %d unknown\n", dev->name, id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct board_ops fu540_board_ops = {
+	.get_int = fu540_board_get_int,
+};
+
+static int fu540_board_probe(struct udevice *dev)
+{
+	struct fu540_board *priv = dev_get_priv(dev);
+
+	priv->regs = (void __iomem *)dev_read_addr(dev);
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	return 0;
+}
+
+static const struct udevice_id fu540_board_ids[] = {
+	{ .compatible = "sifive,fu540-modeselect", },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(fu540_board) = {
+	.id		= UCLASS_BOARD,
+	.name		= "fu540_board",
+	.of_match	= fu540_board_ids,
+	.ops		= &fu540_board_ops,
+	.priv_auto_alloc_size = sizeof(struct fu540_board),
+	.probe		= fu540_board_probe,
+};