From: "Klaus H. Sorensen"
Some SoCs in the mpc83xx family, e.g. mpc8309, have a dedicated spi
chip select, SPISEL_BOOT, that is used by the boot code to boot from
flash.
This chip select will typically be used to select a SPI boot
flash. The SPISEL_BOOT signal is controlled by a single bit in the
SPI_CS register.
Implement a gpio driver for the spi chip select register. This allows a
spi driver capable of using gpios as chip select, to bind a chip select
to SPISEL_BOOT.
It may be a little odd to do this as a GPIO driver, since the signal
is neither GP or I, but it is quite convenient to present it to the
spi driver that way. The alternative it to teach mpc8xxx_spi to handle
the SPISEL_BOOT signal itself (that is how it's done in the linux
kernel, see commit 69b921acae8a)
Signed-off-by: Klaus H. Sorensen
Signed-off-by: Rasmus Villemoes
---
.../gpio/fsl,mpc83xx-spisel-boot.txt | 22 +++
drivers/gpio/Kconfig | 8 +
drivers/gpio/Makefile | 1 +
drivers/gpio/mpc83xx_spisel_boot.c| 148 ++
4 files changed, 179 insertions(+)
create mode 100644 doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
create mode 100644 drivers/gpio/mpc83xx_spisel_boot.c
diff --git a/doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
b/doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
new file mode 100644
index 00..52d8bb0a5c
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
@@ -0,0 +1,22 @@
+MPC83xx SPISEL_BOOT gpio controller
+
+Provide access to MPC83xx SPISEL_BOOT signal as a gpio to allow it to be
+easily bound as a SPI controller chip select.
+
+The SPISEL_BOOT signal is always an output.
+
+Required properties:
+
+- compatible: must be "fsl,mpc83xx-spisel-boot" or "fsl,mpc8309-spisel-boot".
+- reg: must point to the SPI_CS register in the SoC register map.
+- ngpios: number of gpios provided by driver, normally 1.
+
+Example:
+
+ spisel_boot: spisel_boot@14c {
+ compatible = "fsl,mpc8309-spisel-boot";
+ reg = <0x14c 0x04>;
+ #gpio-cells = <2>;
+ device_type = "gpio";
+ ngpios = <1>;
+ };
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c1ad5d64a3..73fdb8cb3b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -383,6 +383,14 @@ config MPC8XXX_GPIO
value setting, the open-drain feature, which can configure individual
GPIOs to work as open-drain outputs, is supported.
+config MPC83XX_SPISEL_BOOT
+ bool "Freescale MPC83XX SPISEL_BOOT driver"
+ depends on DM_GPIO && ARCH_MPC830X
+ help
+ GPIO driver to set/clear dedicated SPISEL_BOOT output on MPC83XX.
+
+ This pin is typically used as spi chip select to a spi nor flash.
+
config MT7621_GPIO
bool "MediaTek MT7621 GPIO driver"
depends on DM_GPIO && SOC_MT7628
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ccc49e2eb0..bbeec30431 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o
obj-$(CONFIG_ALTERA_PIO) += altera_pio.o
obj-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
obj-$(CONFIG_MPC8XXX_GPIO) += mpc8xxx_gpio.o
+obj-$(CONFIG_MPC83XX_SPISEL_BOOT) += mpc83xx_spisel_boot.o
obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
obj-$(CONFIG_OMAP_GPIO)+= omap_gpio.o
obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
diff --git a/drivers/gpio/mpc83xx_spisel_boot.c
b/drivers/gpio/mpc83xx_spisel_boot.c
new file mode 100644
index 00..c7b08404d9
--- /dev/null
+++ b/drivers/gpio/mpc83xx_spisel_boot.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 DEIF A/S
+ *
+ * GPIO driver to set/clear SPISEL_BOOT pin on mpc83xx.
+ */
+
+#include
+#include
+#include
+#include
+
+struct mpc83xx_spisel_boot {
+ u32 __iomem *spi_cs;
+ ulong addr;
+ uint gpio_count;
+ ulong type;
+};
+
+static u32 gpio_mask(uint gpio)
+{
+ return (1U << (31 - (gpio)));
+}
+
+static int mpc83xx_spisel_boot_direction_input(struct udevice *dev, uint gpio)
+{
+ return -EINVAL;
+}
+
+static int mpc83xx_spisel_boot_set_value(struct udevice *dev, uint gpio, int
value)
+{
+ struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
+
+ debug("%s: gpio=%d, value=%u, gpio_mask=0x%08x\n", __func__,
+ gpio, value, gpio_mask(gpio));
+
+ if (value)
+ setbits_be32(data->spi_cs, gpio_mask(gpio));
+ else
+ clrbits_be32(data->spi_cs, gpio_mask(gpio));
+
+ return 0;
+}
+
+static int mpc83xx_spisel_boot_direction_output(struct udevice *dev, uint
gpio, int value)
+{
+ return 0;
+}
+
+static int mpc83xx_spisel_boot_get_value(struct udevice *dev, uint gpio)
+{
+ struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
+
+ return