Browse Source

linux-kernel: Remove the 4.19 kernel

The 4.19 kernel doesn't work with openSBI or the new defconfig, so
remove it.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Alistair Francis 5 years ago
parent
commit
8c8e8eabc9

+ 0 - 42
recipes-kernel/linux/files/freedom-u540/0001-risc-v-Fix-issue-ignoring-CONFIG_CMDLINE_OVERRIDE.patch

@@ -1,42 +0,0 @@
-From dc58ccb30dd1152a2483f4a3d4e2476a7f0d54cf Mon Sep 17 00:00:00 2001
-From: Moritz Fischer <mdf@kernel.org>
-Date: Sat, 7 Apr 2018 22:01:54 +0000
-Subject: [PATCH] risc-v: Fix issue ignoring CONFIG_CMDLINE_OVERRIDE
-
-Fix issue with ignoring CONFIG_CMDLINE_OVERRIDE.
-
-Upstream-status: Inapporopriate [Not correct fix]
-Signed-off-by: Moritz Fischer <mdf@kernel.org>
----
- arch/riscv/kernel/setup.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
-index a1d585387f60..727caa5f5f42 100644
---- a/arch/riscv/kernel/setup.c
-+++ b/arch/riscv/kernel/setup.c
-@@ -39,6 +39,8 @@
- #include <asm/tlbflush.h>
- #include <asm/thread_info.h>
- 
-+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
-+
- #ifdef CONFIG_EARLY_PRINTK
- static void sbi_console_write(struct console *co, const char *buf,
- 			      unsigned int n)
-@@ -222,7 +224,12 @@ void __init setup_arch(char **cmdline_p)
-                register_console(early_console);
-        }
- #endif
-+
-+#if defined(CONFIG_CMDLINE_OVERRIDE)
-+	*cmdline_p = default_command_line;
-+#else
- 	*cmdline_p = boot_command_line;
-+#endif
- 
- 	parse_early_param();
- 
--- 
-2.14.3
-

+ 0 - 512
recipes-kernel/linux/files/freedom-u540/0001-spi-sifive-support-SiFive-SPI-controller-in-Quad-Mod.patch

@@ -1,512 +0,0 @@
-From f169ce2434ae12ada36877fbf21db5d26fde9496 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Mon, 5 Feb 2018 17:42:32 -0800
-Subject: [PATCH 01/11] spi-sifive: support SiFive SPI controller in Quad-Mode
-
-Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
----
- .../devicetree/bindings/spi/spi-sifive.txt         |  29 ++
- drivers/spi/Kconfig                                |   7 +
- drivers/spi/Makefile                               |   1 +
- drivers/spi/spi-sifive.c                           | 423 +++++++++++++++++++++
- 4 files changed, 460 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/spi/spi-sifive.txt
- create mode 100644 drivers/spi/spi-sifive.c
-
-diff --git a/Documentation/devicetree/bindings/spi/spi-sifive.txt b/Documentation/devicetree/bindings/spi/spi-sifive.txt
-new file mode 100644
-index 00000000..94554324
---- /dev/null
-+++ b/Documentation/devicetree/bindings/spi/spi-sifive.txt
-@@ -0,0 +1,29 @@
-+SiFive SPI controller Device Tree Bindings
-+-------------------------------------------------
-+
-+Required properties:
-+- compatible		: Should be "sifive,spi0"
-+- reg			: Physical base address and size of SPI registers map
-+			  A second (optional) range can indicate memory mapped flash
-+- interrupts		: Must contain one entry
-+- interrupt-parent	: Must be core interrupt controller
-+- clocks		: Must reference the frequency given to the controller
-+- #address-cells	: Must be '1', indicating which CS to use
-+- #size-cells		: Must be '0'
-+
-+Optional properties:
-+- sifive,buffer-size	: Depth of hardware queues; defaults to 8
-+- sifive,bits-per-word	: Maximum bits per word; defaults to 8
-+
-+Example:
-+	spi: spi@10040000 {
-+		compatible = "sifive,spi0";
-+		reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>;
-+		interrupt-parent = <&plic>;
-+		interrupts = <51>;
-+		clocks = <&tlclk>;
-+		#address-cells = <1>;
-+		#size-cells = <0>;
-+		sifive,buffer-size = <8>;
-+		sifive,bits-per-word = <8>;
-+	};
-diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
-index 671d0783..b3aa058c 100644
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -749,6 +749,13 @@ config SPI_ZYNQMP_GQSPI
- 	help
- 	  Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
- 
-+config SPI_SIFIVE
-+        tristate "SiFive SPI controller"
-+        depends on HAS_IOMEM
-+	select SPI_BITBANG
-+        help
-+          This exposes the SPI controller IP from SiFive.
-+
- #
- # Add new SPI master controllers in alphabetical order above this line
- #
-diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
-index a90d5597..e22ffa78 100644
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -107,6 +107,7 @@ obj-$(CONFIG_SPI_XILINX)		+= spi-xilinx.o
- obj-$(CONFIG_SPI_XLP)			+= spi-xlp.o
- obj-$(CONFIG_SPI_XTENSA_XTFPGA)		+= spi-xtensa-xtfpga.o
- obj-$(CONFIG_SPI_ZYNQMP_GQSPI)		+= spi-zynqmp-gqspi.o
-+obj-$(CONFIG_SPI_SIFIVE)		+= spi-sifive.o
- 
- # SPI slave protocol handlers
- obj-$(CONFIG_SPI_SLAVE_TIME)		+= spi-slave-time.o
-diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
-new file mode 100644
-index 00000000..208566a9
---- /dev/null
-+++ b/drivers/spi/spi-sifive.c
-@@ -0,0 +1,423 @@
-+/*
-+ * SiFive SPI controller driver (master mode only)
-+ *
-+ * Author: SiFive, Inc.
-+ *	sifive@sifive.com
-+ *
-+ * 2018 (c) SiFive Software, Inc.
-+
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/module.h>
-+#include <linux/interrupt.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/spi/spi.h>
-+#include <linux/io.h>
-+#include <linux/log2.h>
-+
-+#define SIFIVE_SPI_MAX_CS	32
-+
-+#define SIFIVE_SPI_NAME "sifive_spi"
-+
-+#define SIFIVE_SPI_DEFAULT_DEPTH 8
-+#define SIFIVE_SPI_DEFAULT_BITS	8
-+
-+#define XSPI_SCDR_OFFSET	0x000	/* Serial Clock Divisor Register */
-+#define XSPI_SCD_SCALE_MASK	0xFFF
-+
-+#define XSPI_SCMR_OFFSET        0x004   /* Serial Clock Mode Register */
-+#define XSPI_SCM_CPHA		1
-+#define XSPI_SCM_CPOL		2
-+#define XSPI_SCM_MODE_MASK     (XSPI_SCM_CPHA | XSPI_SCM_CPOL)
-+
-+#define XSPI_CSIDR_OFFSET       0x010
-+#define XSPI_CSDR_OFFSET        0x014
-+#define XSPI_CSMR_OFFSET        0x018
-+#define XSPI_CSM_MODE_AUTO      0
-+#define XSPI_CSM_MODE_HOLD      2
-+#define XSPI_CSM_MODE_OFF       3
-+
-+#define XSPI_DC0R_OFFSET        0x028
-+#define XSPI_CS_TO_SCK_MASK     0xFF
-+#define XSPI_SCK_TO_CS_MASK     (0xFF << 16)
-+#define XSPI_DC1R_OFFSET        0x02C
-+#define XSPI_MIN_CS_IATIME_MASK 0xFF
-+#define XSPI_MAX_IF_DELAY_MASK  (0xFF << 16)
-+
-+#define XSPI_FFR_OFFSET         0x040
-+#define XSPI_FF_SINGLE          0
-+#define XSPI_FF_DUAL            1
-+#define XSPI_FF_QUAD            2
-+#define XSPI_FF_SPI_MASK        0x3
-+#define XSPI_FF_LSB_FIRST       4
-+#define XSPI_FF_TX_DIR          8
-+#define XSPI_FF_BPF_MASK        (0xFF << 16)
-+
-+#define XSPI_TXDR_OFFSET	0x048	/* Data Transmit Register */
-+#define XSPI_TXD_FIFO_FULL      (8U << 28)
-+#define XSPI_RXDR_OFFSET	0x04C	/* Data Receive Register */
-+#define XSPI_RXD_FIFO_EMPTY     (8U << 28)
-+#define XSPI_DATA_MASK          0xFF
-+#define XSPI_DATA_SHIFT         8
-+
-+#define XSPI_TXWMR_OFFSET       0x050   /* TX FIFO Watermark Register */
-+#define XSPI_RXWMR_OFFSET       0x054   /* RX FIFO Watermark Register */
-+
-+#define XSPI_FCTRL_OFFSET	0x60
-+
-+#define XSPI_IPR_OFFSET		0x074	/* Interrupt Pendings Register */
-+#define XSPI_IER_OFFSET		0x070	/* Interrupt Enable Register */
-+#define XSPI_TXWM_INTR          0x1
-+#define XSPI_RXWM_INTR          0x2
-+
-+struct sifive_spi {
-+	void __iomem	*regs;		/* virt. address of the control registers */
-+	struct clk	*clk;		/* bus clock */
-+	int		irq;		/* watermark irq */
-+	int 		buffer_size;	/* buffer size in words */
-+	u32		cs_inactive;	/* Level of the CS pins when inactive*/
-+	struct completion done;		/* Wake-up from interrupt */
-+};
-+
-+static void sifive_spi_write(struct sifive_spi *spi, int offset, u32 value)
-+{
-+	iowrite32(value, spi->regs + offset);
-+}
-+
-+static u32 sifive_spi_read(struct sifive_spi *spi, int offset)
-+{
-+	return ioread32(spi->regs + offset);
-+}
-+
-+static void sifive_spi_init(struct sifive_spi *spi)
-+{
-+	/* Watermark interrupts are disabled by default */
-+	sifive_spi_write(spi, XSPI_IER_OFFSET, 0);
-+
-+	/* Default watermark FIFO threshold values */
-+	sifive_spi_write(spi, XSPI_TXWMR_OFFSET, 1);
-+	sifive_spi_write(spi, XSPI_RXWMR_OFFSET, 0);
-+
-+	/* Set CS/SCK Delays and Inactive Time to defaults */
-+
-+	/* Exit specialized memory-mapped SPI flash mode */
-+	sifive_spi_write(spi, XSPI_FCTRL_OFFSET, 0);
-+}
-+
-+static void sifive_spi_prep_device(struct sifive_spi *spi, struct spi_device *device)
-+{
-+	u32 cr;
-+
-+	/* Update the chip select polarity */
-+	if (device->mode & SPI_CS_HIGH)
-+		spi->cs_inactive &= ~BIT(device->chip_select);
-+	else
-+		spi->cs_inactive |= BIT(device->chip_select);
-+	sifive_spi_write(spi, XSPI_CSDR_OFFSET, spi->cs_inactive);
-+
-+	/* Select the correct device */
-+	sifive_spi_write(spi, XSPI_CSIDR_OFFSET, device->chip_select);
-+
-+	/* Switch clock mode bits */
-+	cr = sifive_spi_read(spi, XSPI_SCMR_OFFSET) & ~XSPI_SCM_MODE_MASK;
-+	if (device->mode & SPI_CPHA)
-+		cr |= XSPI_SCM_CPHA;
-+	if (device->mode & SPI_CPOL)
-+		cr |= XSPI_SCM_CPOL;
-+	sifive_spi_write(spi, XSPI_SCMR_OFFSET, cr);
-+}
-+
-+static int sifive_spi_prep_transfer(struct sifive_spi *spi, struct spi_device *device, struct spi_transfer *t)
-+{
-+	u32 hz, scale, cr;
-+	int mode;
-+
-+	/* Calculate and program the clock rate */
-+	hz = t->speed_hz ? t->speed_hz : device->max_speed_hz;
-+	scale = (DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, hz) - 1) & XSPI_SCD_SCALE_MASK;
-+	sifive_spi_write(spi, XSPI_SCDR_OFFSET, scale);
-+
-+	/* Modify the SPI protocol mode */
-+	cr = sifive_spi_read(spi, XSPI_FFR_OFFSET);
-+
-+	/* LSB first? */
-+	cr &= ~XSPI_FF_LSB_FIRST;
-+	if (device->mode & SPI_LSB_FIRST)
-+		cr |= XSPI_FF_LSB_FIRST;
-+
-+	/* SINGLE/DUAL/QUAD? */
-+	mode = max((int)t->rx_nbits, (int)t->tx_nbits);
-+	cr &= ~XSPI_FF_SPI_MASK;
-+	switch (mode) {
-+		case SPI_NBITS_QUAD: cr |= XSPI_FF_QUAD;   break;
-+		case SPI_NBITS_DUAL: cr |= XSPI_FF_DUAL;   break;
-+		default:             cr |= XSPI_FF_SINGLE; break;
-+	}
-+
-+	/* SPI direction */
-+	cr &= ~XSPI_FF_TX_DIR;
-+	if (!t->rx_buf)
-+		cr |= XSPI_FF_TX_DIR;
-+
-+	sifive_spi_write(spi, XSPI_FFR_OFFSET, cr);
-+
-+	/* We will want to poll if the time we need to wait is less than the context switching time.
-+	 * Let's call that threshold 5us. The operation will take:
-+	 *    (8/mode) * buffer_size / hz <= 5 * 10^-6
-+	 *    1600000 * buffer_size <= hz * mode
-+	 */
-+	return 1600000 * spi->buffer_size <= hz * mode;
-+}
-+
-+static void sifive_spi_tx(struct sifive_spi *spi, const u8* tx_ptr)
-+{
-+	BUG_ON((sifive_spi_read(spi, XSPI_TXDR_OFFSET) & XSPI_TXD_FIFO_FULL) != 0);
-+	sifive_spi_write(spi, XSPI_TXDR_OFFSET, *tx_ptr & XSPI_DATA_MASK);
-+}
-+
-+static void sifive_spi_rx(struct sifive_spi *spi, u8* rx_ptr)
-+{
-+        u32 data = sifive_spi_read(spi, XSPI_RXDR_OFFSET);
-+        BUG_ON((data & XSPI_RXD_FIFO_EMPTY) != 0);
-+        *rx_ptr = data & XSPI_DATA_MASK;
-+}
-+
-+static void sifive_spi_wait(struct sifive_spi *spi, int bit, int poll)
-+{
-+	if (poll) {
-+		u32 cr;
-+		do cr = sifive_spi_read(spi, XSPI_IPR_OFFSET);
-+		while (!(cr & bit));
-+	} else {
-+		reinit_completion(&spi->done);
-+		sifive_spi_write(spi, XSPI_IER_OFFSET, bit);
-+		wait_for_completion(&spi->done);
-+	}
-+}
-+
-+static void sifive_spi_execute(struct sifive_spi *spi, struct spi_transfer *t, int poll)
-+{
-+	int remaining_words = t->len;
-+	const u8* tx_ptr = t->tx_buf;
-+	u8* rx_ptr = t->rx_buf;
-+
-+	while (remaining_words) {
-+		int n_words, tx_words, rx_words;
-+		n_words = min(remaining_words, spi->buffer_size);
-+
-+		/* Enqueue n_words for transmission */
-+		for (tx_words = 0; tx_words < n_words; ++tx_words)
-+			sifive_spi_tx(spi, tx_ptr++);
-+
-+		if (rx_ptr) {
-+			/* Wait for transmission + reception to complete */
-+			sifive_spi_write(spi, XSPI_RXWMR_OFFSET, n_words-1);
-+			sifive_spi_wait(spi, XSPI_RXWM_INTR, poll);
-+
-+			/* Read out all the data from the RX FIFO */
-+			for (rx_words = 0; rx_words < n_words; ++rx_words)
-+				sifive_spi_rx(spi, rx_ptr++);
-+		} else {
-+			/* Wait for transmission to complete */
-+			sifive_spi_wait(spi, XSPI_TXWM_INTR, poll);
-+		}
-+
-+		remaining_words -= n_words;
-+	}
-+}
-+
-+static int sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, struct spi_transfer *t)
-+{
-+	struct sifive_spi *spi = spi_master_get_devdata(master);
-+	int poll;
-+
-+	sifive_spi_prep_device(spi, device);
-+	poll = sifive_spi_prep_transfer(spi, device, t);
-+	sifive_spi_execute(spi, t, poll);
-+
-+	return 0;
-+}
-+
-+static void sifive_spi_set_cs(struct spi_device *device, bool is_high)
-+{
-+	struct sifive_spi *spi = spi_master_get_devdata(device->master);
-+
-+	/* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */
-+	if (device->mode & SPI_CS_HIGH)
-+		is_high = !is_high;
-+
-+	sifive_spi_write(spi, XSPI_CSMR_OFFSET, is_high ? XSPI_CSM_MODE_AUTO : XSPI_CSM_MODE_HOLD);
-+}
-+
-+static irqreturn_t sifive_spi_irq(int irq, void *dev_id)
-+{
-+	struct sifive_spi *spi = dev_id;
-+	u32 ip;
-+
-+	ip = sifive_spi_read(spi, XSPI_IPR_OFFSET) & (XSPI_TXWM_INTR | XSPI_RXWM_INTR);
-+	if (ip != 0) {
-+		/* Disable interrupts until next transfer */
-+		sifive_spi_write(spi, XSPI_IER_OFFSET, 0);
-+		complete(&spi->done);
-+		return IRQ_HANDLED;
-+	}
-+
-+	return IRQ_NONE;
-+}
-+
-+static int sifive_spi_probe(struct platform_device *pdev)
-+{
-+	struct sifive_spi *spi;
-+	struct resource *res;
-+	int ret, num_cs;
-+	u32 cs_bits, buffer_size, bits_per_word;
-+	struct spi_master *master;
-+
-+	master = spi_alloc_master(&pdev->dev, sizeof(struct sifive_spi));
-+	if (!master) {
-+		dev_err(&pdev->dev, "out of memory\n");
-+		return -ENOMEM;
-+	}
-+
-+	spi = spi_master_get_devdata(master);
-+	init_completion(&spi->done);
-+	platform_set_drvdata(pdev, master);
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	spi->regs = devm_ioremap_resource(&pdev->dev, res);
-+	if (IS_ERR(spi->regs)) {
-+		dev_err(&pdev->dev, "Unable to map IO resources\n");
-+		ret = PTR_ERR(spi->regs);
-+		goto put_master;
-+	}
-+
-+	spi->clk = devm_clk_get(&pdev->dev, NULL);
-+	if (IS_ERR(spi->clk)) {
-+		dev_err(&pdev->dev, "Unable to find bus clock\n");
-+		ret = PTR_ERR(spi->clk);
-+		goto put_master;
-+	}
-+
-+	spi->irq = platform_get_irq(pdev, 0);
-+	if (spi->irq < 0) {
-+		dev_err(&pdev->dev, "Unable to find interrupt\n");
-+		ret = spi->irq;
-+		goto put_master;
-+	}
-+
-+	/* Optional parameters */
-+	ret = of_property_read_u32(pdev->dev.of_node, "sifive,buffer-size", &buffer_size);
-+	if (ret < 0)
-+		spi->buffer_size = SIFIVE_SPI_DEFAULT_DEPTH;
-+	else
-+		spi->buffer_size = buffer_size;
-+
-+	ret = of_property_read_u32(pdev->dev.of_node, "sifive,bits-per-word", &bits_per_word);
-+	if (ret < 0)
-+		bits_per_word = SIFIVE_SPI_DEFAULT_BITS;
-+
-+	/* Spin up the bus clock before hitting registers */
-+	ret = clk_prepare_enable(spi->clk);
-+	if (ret) {
-+		dev_err(&pdev->dev, "Unable to enable bus clock\n");
-+		goto put_master;
-+	}
-+
-+	/* probe the number of CS lines */
-+	spi->cs_inactive = sifive_spi_read(spi, XSPI_CSDR_OFFSET);
-+	sifive_spi_write(spi, XSPI_CSDR_OFFSET, 0xffffffffU);
-+	cs_bits = sifive_spi_read(spi, XSPI_CSDR_OFFSET);
-+	sifive_spi_write(spi, XSPI_CSDR_OFFSET, spi->cs_inactive);
-+	if (!cs_bits) {
-+		dev_err(&pdev->dev, "Could not auto probe CS lines\n");
-+		ret = -EINVAL;
-+		goto put_master;
-+	}
-+
-+	num_cs = ilog2(cs_bits) + 1;
-+	if (num_cs > SIFIVE_SPI_MAX_CS) {
-+		dev_err(&pdev->dev, "Invalid number of spi slaves\n");
-+		ret = -EINVAL;
-+		goto put_master;
-+	}
-+
-+	/* Define our master */
-+	master->bus_num = pdev->id;
-+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH |
-+	                    SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD;
-+	master->flags = SPI_CONTROLLER_MUST_TX | SPI_MASTER_GPIO_SS;
-+	master->dev.of_node = pdev->dev.of_node;
-+	master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
-+	master->num_chipselect = num_cs;
-+	master->transfer_one = sifive_spi_transfer_one;
-+	master->set_cs = sifive_spi_set_cs;
-+
-+	/* If mmc_spi sees a dma_mask, it starts using dma mapped buffers.
-+	 * Probably it should rely on the SPI core auto mapping instead.
-+	 */
-+	pdev->dev.dma_mask = 0;
-+
-+	/* Configure the SPI master hardware */
-+	sifive_spi_init(spi);
-+
-+	/* Register for SPI Interrupt */
-+	ret = devm_request_irq(&pdev->dev, spi->irq, sifive_spi_irq, 0,
-+				dev_name(&pdev->dev), spi);
-+	if (ret) {
-+		dev_err(&pdev->dev, "Unable to bind to interrupt\n");
-+		goto put_master;
-+	}
-+
-+	dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n",
-+		spi->irq, master->num_chipselect);
-+
-+	ret = devm_spi_register_master(&pdev->dev, master);
-+	if (ret < 0) {
-+		dev_err(&pdev->dev, "spi_register_master failed\n");
-+		goto put_master;
-+	}
-+
-+	return 0;
-+
-+put_master:
-+	spi_master_put(master);
-+
-+	return ret;
-+}
-+
-+static int sifive_spi_remove(struct platform_device *pdev)
-+{
-+	struct spi_master *master = platform_get_drvdata(pdev);
-+	struct sifive_spi *spi = spi_master_get_devdata(master);
-+
-+	/* Disable all the interrupts just in case */
-+	sifive_spi_write(spi, XSPI_IER_OFFSET, 0);
-+	spi_master_put(master);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id sifive_spi_of_match[] = {
-+	{ .compatible = "sifive,spi0", },
-+	{}
-+};
-+MODULE_DEVICE_TABLE(of, sifive_spi_of_match);
-+
-+static struct platform_driver sifive_spi_driver = {
-+	.probe = sifive_spi_probe,
-+	.remove = sifive_spi_remove,
-+	.driver = {
-+		.name = SIFIVE_SPI_NAME,
-+		.of_match_table = sifive_spi_of_match,
-+	},
-+};
-+module_platform_driver(sifive_spi_driver);
-+
-+MODULE_AUTHOR("SiFive, Inc. <sifive@sifive.com>");
-+MODULE_DESCRIPTION("SiFive SPI driver");
-+MODULE_LICENSE("GPL");
--- 
-2.7.4
-

+ 0 - 113
recipes-kernel/linux/files/freedom-u540/0002-spi-nor-add-support-for-is25wp-32-64-128-256.patch

@@ -1,113 +0,0 @@
-From dc4e19c27fceaf46ec61da8130bddb43ce940764 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Mon, 5 Feb 2018 17:44:19 -0800
-Subject: [PATCH 02/11] spi-nor: add support for is25wp{32,64,128,256}
-
-Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 47 ++++++++++++++++++++++++++++++++++++++++++-
- include/linux/mtd/spi-nor.h   |  2 ++
- 2 files changed, 48 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
-index f028277f..d39a7261 100644
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1072,6 +1072,9 @@ static const struct flash_info spi_nor_ids[] = {
- 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- 	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
- 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-+	{ "is25wp256d", INFO(0x9d7019, 0, 32 * 1024, 1024,
-+	                SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES)
-+	},
- 
- 	/* Macronix */
- 	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
-@@ -1515,6 +1518,45 @@ static int macronix_quad_enable(struct spi_nor *nor)
- 	return 0;
- }
- 
-+/**
-+ * issi_unlock() - clear BP[0123] write-protection.
-+ * @nor:	pointer to a 'struct spi_nor'
-+ *
-+ * Bits [2345] of the Status Register are BP[0123].
-+ * ISSI chips use a different block protection scheme than other chips.
-+ * Just disable the write-protect unilaterally.
-+ *
-+ * Return: 0 on success, -errno otherwise.
-+ */
-+static int issi_unlock(struct spi_nor *nor)
-+{
-+	int ret, val;
-+	u8 mask = SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3;
-+
-+	val = read_sr(nor);
-+	if (val < 0)
-+		return val;
-+	if (!(val & mask))
-+		return 0;
-+
-+	write_enable(nor);
-+
-+	write_sr(nor, val & ~mask);
-+
-+	ret = spi_nor_wait_till_ready(nor);
-+	if (ret)
-+		return ret;
-+
-+	ret = read_sr(nor);
-+	if (ret > 0 && !(ret & mask)) {
-+		dev_info(nor->dev, "ISSI Block Protection Bits cleared\n");
-+		return 0;
-+	} else {
-+		dev_err(nor->dev, "ISSI Block Protection Bits not cleared\n");
-+		return -EINVAL;
-+	}
-+}
-+
- /*
-  * Write status Register and configuration register with 2 bytes
-  * The first byte will be written to the status register, while the
-@@ -2747,6 +2789,9 @@ static int spi_nor_init(struct spi_nor *nor)
- 		spi_nor_wait_till_ready(nor);
- 	}
- 
-+	if (JEDEC_MFR(nor->info) == SNOR_MFR_ISSI)
-+		issi_unlock(nor);
-+
- 	if (nor->quad_enable) {
- 		err = nor->quad_enable(nor);
- 		if (err) {
-@@ -2940,7 +2985,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
- 	if (ret)
- 		return ret;
- 
--	if (nor->addr_width) {
-+	if (nor->addr_width && JEDEC_MFR(info) != SNOR_MFR_ISSI) {
- 		/* already configured from SFDP */
- 	} else if (info->addr_width) {
- 		nor->addr_width = info->addr_width;
-diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
-index c922e97f..1a3d07cf 100644
---- a/include/linux/mtd/spi-nor.h
-+++ b/include/linux/mtd/spi-nor.h
-@@ -23,6 +23,7 @@
- #define SNOR_MFR_ATMEL		CFI_MFR_ATMEL
- #define SNOR_MFR_GIGADEVICE	0xc8
- #define SNOR_MFR_INTEL		CFI_MFR_INTEL
-+#define SNOR_MFR_ISSI		0x9d
- #define SNOR_MFR_MICRON		CFI_MFR_ST /* ST Micro <--> Micron */
- #define SNOR_MFR_MACRONIX	CFI_MFR_MACRONIX
- #define SNOR_MFR_SPANSION	CFI_MFR_AMD
-@@ -121,6 +122,7 @@
- #define SR_BP0			BIT(2)	/* Block protect 0 */
- #define SR_BP1			BIT(3)	/* Block protect 1 */
- #define SR_BP2			BIT(4)	/* Block protect 2 */
-+#define SR_BP3			BIT(5)  /* Block protect 3 (on ISSI chips) */
- #define SR_TB			BIT(5)	/* Top/Bottom protect */
- #define SR_SRWD			BIT(7)	/* SR write protect */
- /* Spansion/Cypress specific status bits */
--- 
-2.7.4
-

+ 0 - 1131
recipes-kernel/linux/files/freedom-u540/0003-serial-sifive-initial-driver-from-Paul-Walmsley.patch

@@ -1,1131 +0,0 @@
-From 58f76c1c8221f6ce247bd8a6f39ab0a59422b2f2 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Fri, 16 Mar 2018 11:34:26 -0700
-Subject: [PATCH 03/11] serial/sifive: initial driver from Paul Walmsley
-
----
- drivers/tty/serial/Kconfig       |   23 +
- drivers/tty/serial/Makefile      |    1 +
- drivers/tty/serial/sifive.c      | 1051 ++++++++++++++++++++++++++++++++++++++
- include/uapi/linux/serial_core.h |    3 +
- 4 files changed, 1078 insertions(+)
- create mode 100644 drivers/tty/serial/sifive.c
-
-diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
-index df8bd0c7..94a6de4b 100644
---- a/drivers/tty/serial/Kconfig
-+++ b/drivers/tty/serial/Kconfig
-@@ -1060,6 +1060,29 @@ config SERIAL_OMAP_CONSOLE
- 	  your boot loader about how to pass options to the kernel at
- 	  boot time.)
- 
-+config SERIAL_SIFIVE
-+	tristate "SiFive UART support"
-+	depends on OF
-+	select SERIAL_CORE
-+	help
-+	  If you have a SiFive Freedom U500 or similar SoC, enable this to
-+	  support the SiFive UART.
-+
-+config SERIAL_SIFIVE_CONSOLE
-+	bool "Console on SiFive UART"
-+	depends on SERIAL_SIFIVE=y
-+	select SERIAL_CORE_CONSOLE
-+	help
-+	  Select this option if you would like to use a SiFive UART as the
-+	  system console.
-+
-+	  Even if you say Y here, the currently visible virtual console
-+	  (/dev/tty0) will still be used as the system console by default, but
-+	  you can alter that using a kernel command line option such as
-+	  "console=ttySIx". (Try "man bootparam" or see the documentation of
-+	  your boot loader about how to pass options to the kernel at
-+	  boot time.)
-+
- config SERIAL_LANTIQ
- 	bool "Lantiq serial driver"
- 	depends on LANTIQ
-diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
-index daac6756..7e906d3c 100644
---- a/drivers/tty/serial/Makefile
-+++ b/drivers/tty/serial/Makefile
-@@ -89,6 +89,7 @@ obj-$(CONFIG_SERIAL_MVEBU_UART)	+= mvebu-uart.o
- obj-$(CONFIG_SERIAL_PIC32)	+= pic32_uart.o
- obj-$(CONFIG_SERIAL_MPS2_UART)	+= mps2-uart.o
- obj-$(CONFIG_SERIAL_OWL)	+= owl-uart.o
-+obj-$(CONFIG_SERIAL_SIFIVE)	+= sifive.o
- 
- # GPIOLIB helpers for modem control lines
- obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
-diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
-new file mode 100644
-index 00000000..588fb31c
---- /dev/null
-+++ b/drivers/tty/serial/sifive.c
-@@ -0,0 +1,1051 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * SiFive UART driver
-+ * Copyright (C) 2018 Paul Walmsley <paul@pwsan.com>
-+ *
-+ * Based partially on drivers/tty/serial/pxa.c, drivers/pwm/pwm-sifive.c,
-+ * and drivers/tty/serial/omap-serial.c
-+ *
-+ * See Chapter 19 "Universal Asynchronous Receiver/Transmitter (UART)" of
-+ * SiFive FE310-G000 v2p3.
-+ *
-+ * The SiFive UART design is not 8250-compatible.  The following common
-+ * features are not supported:
-+ * - Word lengths other than 8 bits
-+ * - Break handling
-+ * - Parity
-+ * - Flow control
-+ * - Modem signals (DSR, RI, etc.)
-+ * On the other hand, the design is free from the baggage of the classical 8250
-+ * programming model.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/* XXX Magic SYSRQ support - is it possible to implement? */
-+/* XXX ignore_status_mask */
-+/* XXX Ensure operations are spinlocked that need to be spinlocked */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+#include <linux/serial_reg.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/serial_core.h>
-+#include <linux/irq.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+
-+/*
-+ * Register offsets
-+ */
-+
-+/* TXDATA */
-+#define SIFIVE_SERIAL_TXDATA_OFFS		0x0
-+#define SIFIVE_SERIAL_TXDATA_FULL_SHIFT		31
-+#define SIFIVE_SERIAL_TXDATA_FULL_MASK		(1 << SIFIVE_SERIAL_TXDATA_FULL_SHIFT)
-+#define SIFIVE_SERIAL_TXDATA_DATA_SHIFT		0
-+#define SIFIVE_SERIAL_TXDATA_DATA_MASK		(0xff << SIFIVE_SERIAL_TXDATA_DATA_SHIFT)
-+
-+/* RXDATA */
-+#define SIFIVE_SERIAL_RXDATA_OFFS		0x4
-+#define SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT	31
-+#define SIFIVE_SERIAL_RXDATA_EMPTY_MASK		(1 << SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT)
-+#define SIFIVE_SERIAL_RXDATA_DATA_SHIFT		0
-+#define SIFIVE_SERIAL_RXDATA_DATA_MASK		(0xff << SIFIVE_SERIAL_RXDATA_DATA_SHIFT)
-+
-+/* TXCTRL */
-+#define SIFIVE_SERIAL_TXCTRL_OFFS		0x8
-+#define SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT	16
-+#define SIFIVE_SERIAL_TXCTRL_TXCNT_MASK		(0x7 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT)
-+#define SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT	1
-+#define SIFIVE_SERIAL_TXCTRL_NSTOP_MASK		(1 << SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT)
-+#define SIFIVE_SERIAL_TXCTRL_TXEN_SHIFT		0
-+#define SIFIVE_SERIAL_TXCTRL_TXEN_MASK		(1 << SIFIVE_SERIAL_TXCTRL_TXEN_SHIFT)
-+
-+/* RXCTRL */
-+#define SIFIVE_SERIAL_RXCTRL_OFFS		0xC
-+#define SIFIVE_SERIAL_RXCTRL_RXCNT_SHIFT	16
-+#define SIFIVE_SERIAL_RXCTRL_RXCNT_MASK		(0x7 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT)
-+#define SIFIVE_SERIAL_RXCTRL_RXEN_SHIFT		0
-+#define SIFIVE_SERIAL_RXCTRL_RXEN_MASK		(1 << SIFIVE_SERIAL_RXCTRL_RXEN_SHIFT)
-+
-+/* IE */
-+#define SIFIVE_SERIAL_IE_OFFS			0x10
-+#define SIFIVE_SERIAL_IE_RXWM_SHIFT		1
-+#define SIFIVE_SERIAL_IE_RXWM_MASK		(1 << SIFIVE_SERIAL_IE_RXWM_SHIFT)
-+#define SIFIVE_SERIAL_IE_TXWM_SHIFT		0
-+#define SIFIVE_SERIAL_IE_TXWM_MASK		(1 << SIFIVE_SERIAL_IE_TXWM_SHIFT)
-+
-+/* IP */
-+#define SIFIVE_SERIAL_IP_OFFS			0x14
-+#define SIFIVE_SERIAL_IP_RXWM_SHIFT		1
-+#define SIFIVE_SERIAL_IP_RXWM_MASK		(1 << SIFIVE_SERIAL_IP_RXWM_SHIFT)
-+#define SIFIVE_SERIAL_IP_TXWM_SHIFT		0
-+#define SIFIVE_SERIAL_IP_TXWM_MASK		(1 << SIFIVE_SERIAL_IP_TXWM_SHIFT)
-+
-+/* DIV */
-+#define SIFIVE_SERIAL_DIV_OFFS			0x18
-+#define SIFIVE_SERIAL_DIV_DIV_SHIFT		0
-+#define SIFIVE_SERIAL_DIV_DIV_MASK		(0xffff << SIFIVE_SERIAL_IP_DIV_SHIFT)
-+
-+/*
-+ * Config macros
-+ */
-+
-+/* SIFIVE_SERIAL_MAX_PORTS: maximum number of UARTs possible on a device */
-+/* XXX Move to Kconfig? */
-+#define SIFIVE_SERIAL_MAX_PORTS			10
-+
-+/* SIFIVE_SERIAL_NAME: our driver's name that we pass to the operating system */
-+#define SIFIVE_SERIAL_NAME			"sifive-serial"
-+
-+/* SIFIVE_TTY_PREFIX: tty name prefix for SiFive serial ports */
-+#define SIFIVE_TTY_PREFIX			"ttySI"
-+
-+/*
-+ *
-+ */
-+
-+/**
-+ * sifive_serial_port - driver-specific data extension to struct uart_port
-+ * @port: struct uart_port embedded in this struct
-+ * @dev: struct device *
-+ * @ier: shadowed copy of the interrupt enable register
-+ * @clkin_rate: input clock to the UART IP block.
-+ * @bit_rate: UART serial line rate (e.g., 115200 bps)
-+ * @clk_notifier: clock rate change notifier for upstream clock changes
-+ */
-+struct sifive_serial_port {
-+	struct uart_port	port;
-+	struct device		*dev;
-+	unsigned char		ier;
-+	unsigned long		clkin_rate;
-+	unsigned long		bit_rate;
-+	struct clk		*clk;
-+	struct notifier_block	clk_notifier;
-+};
-+
-+/*
-+ * Structure container-of macros
-+ */
-+
-+#define port_to_sifive_serial_port(p) (container_of((p), \
-+						    struct sifive_serial_port, \
-+						    port))
-+
-+#define notifier_to_sifive_serial_port(nb) (container_of((nb), \
-+							 struct sifive_serial_port, \
-+							 clk_notifier))
-+
-+/*
-+ * Forward declarations
-+ */
-+static void sifive_serial_stop_tx(struct uart_port *port);
-+
-+/*
-+ * Internal functions
-+ */
-+
-+/**
-+ * sifive_serial_early_write() - write to a UART register (early)
-+ * @port: pointer to a struct uart_port record
-+ * @offs: register address offset from the IP block base address
-+ * @v: value to write to the register
-+ *
-+ * Given a pointer @port to a struct uart_port record, write the value @v to the
-+ * IP block register address offset @offs.  This function is intended for early
-+ * console use.
-+ */
-+static void sifive_serial_early_write(struct uart_port *port, u16 offs, u32 v)
-+{
-+	writel(v, port->membase + offs);
-+}
-+
-+/**
-+ * sifive_serial_early_read() - read from a UART register (early)
-+ * @port: pointer to a struct uart_port record
-+ * @offs: register address offset from the IP block base address
-+ *
-+ * Given a pointer @port to a struct uart_port record, read the contents of the
-+ * IP block register located at offset @offs from the IP block base and return
-+ * it.  This function is intended for early console use.
-+ *
-+ * Returns: the register value read from the UART.
-+ */
-+static u32 sifive_serial_early_read(struct uart_port *port, u16 offs)
-+{
-+	return readl(port->membase + offs);
-+}
-+
-+/**
-+ * sifive_serial_write() - write to a UART register
-+ * @ssp: pointer to a struct sifive_serial_port record
-+ * @offs: register address offset from the IP block base address
-+ * @v: value to write to the register
-+ *
-+ * Write the value @v to the IP block register located at offset @offs from the
-+ * IP block base, given a pointer @ssp to a struct sifive_serial_port record.
-+ */
-+static void sifive_serial_write(struct sifive_serial_port *ssp, u16 offs, u32 v)
-+{
-+	sifive_serial_early_write(&ssp->port, offs, v);
-+}
-+
-+/**
-+ * sifive_serial_read() - read from a UART register
-+ * @ssp: pointer to a struct sifive_serial_port record
-+ * @offs: register address offset from the IP block base address
-+ *
-+ * Read the contents of the IP block register located at offset @offs from the
-+ * IP block base, given a pointer @ssp to a struct sifive_serial_port record.
-+ *
-+ * Returns: the value of the UART register
-+ */
-+static u32 sifive_serial_read(struct sifive_serial_port *ssp, u16 offs)
-+{
-+	return sifive_serial_early_read(&ssp->port, offs);
-+}
-+
-+/**
-+ * sifive_serial_is_txfifo_full() - is the TXFIFO full?
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Read the transmit FIFO "full" bit, returning a non-zero value if the
-+ * TX FIFO is full, or zero if space remains.  Intended to be used to prevent
-+ * writes to the TX FIFO when it's full.
-+ *
-+ * Returns: SIFIVE_SERIAL_TXDATA_FULL_MASK (non-zero) if the transmit FIFO
-+ * is full, or 0 if space remains.
-+ */
-+static int sifive_serial_is_txfifo_full(struct sifive_serial_port *ssp)
-+{
-+	return sifive_serial_read(ssp, SIFIVE_SERIAL_TXDATA_OFFS) &
-+		SIFIVE_SERIAL_TXDATA_FULL_MASK;
-+}
-+
-+/**
-+ * sifive_serial_transmit_char() - enqueue a byte to transmit onto the TX FIFO
-+ * @ssp: pointer to a struct sifive_serial_port
-+ * @ch: character to transmit
-+ *
-+ * Enqueue a byte @ch onto the transmit FIFO, given a pointer @ssp to the
-+ * struct sifive_serial_port * to transmit on.  Caller should first check to
-+ * ensure that the TXFIFO has space; see sifive_serial_is_txfifo_full().
-+ */
-+static void sifive_serial_transmit_char(struct sifive_serial_port *ssp, int ch)
-+{
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_TXDATA_OFFS, ch);
-+}
-+
-+/**
-+ * sifive_serial_transmit_chars() - enqueue multiple bytes onto the TX FIFO
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Transfer up to a TX FIFO size's worth of characters from the Linux serial
-+ * transmit buffer to the SiFive UART TX FIFO.
-+ */
-+static void sifive_serial_transmit_chars(struct sifive_serial_port *ssp)
-+{
-+	struct circ_buf *xmit = &ssp->port.state->xmit;
-+	int count;
-+
-+	if (ssp->port.x_char) {
-+		sifive_serial_transmit_char(ssp, ssp->port.x_char);
-+		ssp->port.icount.tx++;
-+		ssp->port.x_char = 0;
-+		return;
-+	}
-+	if (uart_circ_empty(xmit) || uart_tx_stopped(&ssp->port)) {
-+		sifive_serial_stop_tx(&ssp->port);
-+		return;
-+	}
-+	count = ssp->port.fifosize;
-+	do {
-+		sifive_serial_transmit_char(ssp, xmit->buf[xmit->tail]);
-+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+		ssp->port.icount.tx++;
-+		if (uart_circ_empty(xmit))
-+			break;
-+	} while (--count > 0);
-+
-+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+		uart_write_wakeup(&ssp->port);
-+
-+	if (uart_circ_empty(xmit))
-+		sifive_serial_stop_tx(&ssp->port);
-+}
-+
-+/**
-+ * sifive_serial_enable_txwm() - enable transmit watermark interrupts
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Enable interrupt generation when the transmit FIFO watermark is reached
-+ * on the UART referred to by @ssp.
-+ */
-+static void sifive_serial_enable_txwm(struct sifive_serial_port *ssp)
-+{
-+	if (ssp->ier & SIFIVE_SERIAL_IE_TXWM_MASK)
-+		return;
-+
-+	ssp->ier |= SIFIVE_SERIAL_IE_TXWM_MASK;
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, ssp->ier);
-+}
-+
-+/**
-+ * sifive_serial_enable_rxwm() - enable receive watermark interrupts
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Enable interrupt generation when the receive FIFO watermark is reached
-+ * on the UART referred to by @ssp.
-+ */
-+static void sifive_serial_enable_rxwm(struct sifive_serial_port *ssp)
-+{
-+	if (ssp->ier & SIFIVE_SERIAL_IE_RXWM_MASK)
-+		return;
-+
-+	ssp->ier |= SIFIVE_SERIAL_IE_RXWM_MASK;
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, ssp->ier);
-+}
-+
-+/**
-+ * sifive_serial_disable_txwm() - disable transmit watermark interrupts
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Disable interrupt generation when the transmit FIFO watermark is reached
-+ * on the UART referred to by @ssp.
-+ */
-+static void sifive_serial_disable_txwm(struct sifive_serial_port *ssp)
-+{
-+	if (!(ssp->ier & SIFIVE_SERIAL_IE_TXWM_MASK))
-+		return;
-+
-+	ssp->ier &= ~SIFIVE_SERIAL_IE_TXWM_MASK;
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, ssp->ier);
-+}
-+
-+/**
-+ * sifive_serial_disable_rxwm() - disable receive watermark interrupts
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Disable interrupt generation when the receive FIFO watermark is reached
-+ * on the UART referred to by @ssp.
-+ */
-+static void sifive_serial_disable_rxwm(struct sifive_serial_port *ssp)
-+{
-+	if (!(ssp->ier & SIFIVE_SERIAL_IE_RXWM_MASK))
-+		return;
-+
-+	ssp->ier &= ~SIFIVE_SERIAL_IE_RXWM_MASK;
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, ssp->ier);
-+}
-+
-+/**
-+ * sifive_serial_receive_char() - receive a byte from the UART
-+ * @ssp: pointer to a struct sifive_serial_port
-+ * @is_empty: char pointer to return whether the RX FIFO is empty
-+ *
-+ * Try to read a byte from the SiFive UART RX FIFO, referenced by
-+ * @ssp, and to return it.  Also returns the RX FIFO empty bit in
-+ * the char pointed to by @ch.  The caller must pass the byte back to the
-+ * Linux serial layer if needed.
-+ *
-+ * Returns: the byte read from the UART RX FIFO.
-+ */
-+static char sifive_serial_receive_char(struct sifive_serial_port *ssp,
-+				       char *is_empty)
-+{
-+	u32 v;
-+	u8 ch;
-+
-+	v = sifive_serial_read(ssp, SIFIVE_SERIAL_RXDATA_OFFS);
-+
-+	if (!is_empty)
-+		WARN_ON(1);
-+	else
-+		*is_empty = (v & SIFIVE_SERIAL_RXDATA_EMPTY_MASK) >>
-+			SIFIVE_SERIAL_RXDATA_EMPTY_SHIFT;
-+
-+	ch = (v & SIFIVE_SERIAL_RXDATA_DATA_MASK) >>
-+		SIFIVE_SERIAL_RXDATA_DATA_SHIFT;
-+
-+	return ch;
-+}
-+
-+/**
-+ * sifive_serial_receive_chars() - receive multiple bytes from the UART
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Receive up to an RX FIFO's worth of bytes from the SiFive UART referred
-+ * to by @ssp and pass them up to the Linux serial layer.
-+ */
-+static void sifive_serial_receive_chars(struct sifive_serial_port *ssp)
-+{
-+	unsigned char ch;
-+	char is_empty;
-+	int c;
-+
-+	for (c = ssp->port.fifosize; c > 0; --c) {
-+		ch = sifive_serial_receive_char(ssp, &is_empty);
-+		if (is_empty) break;
-+
-+		ssp->port.icount.rx++;
-+		uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
-+	}
-+}
-+
-+/**
-+ * sifive_serial_update_div() - calculate the divisor setting by the line rate
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Calculate the appropriate value of the clock divisor for the UART
-+ * referred to by @ssp and the target line rate referred to by @bps, and
-+ * return it.
-+ */
-+static void sifive_serial_update_div(struct sifive_serial_port *ssp)
-+{
-+	u16 div = DIV_ROUND_UP(ssp->clkin_rate, ssp->bit_rate) - 1;
-+	/* XXX check for div out of spec */
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_DIV_OFFS, div);
-+}
-+
-+/**
-+ * sifive_serial_update_bit_rate() - set the UART "baud rate"
-+ * @ssp: pointer to a struct sifive_serial_port
-+ * @rate: new target bit rate
-+ *
-+ * Calculate the UART divisor value for the target bit rate @rate for the
-+ * SiFive UART described by @ssp and program it into the UART.  There may
-+ * be some error between the target bit rate and the actual bit rate implemented
-+ * by the UART due to clock ratio granularity.
-+ */
-+static void sifive_serial_update_bit_rate(struct sifive_serial_port *ssp,
-+					  unsigned int rate)
-+{
-+	if (ssp->bit_rate == rate)
-+		return;
-+
-+	ssp->bit_rate = rate;
-+	sifive_serial_update_div(ssp);
-+}
-+
-+/**
-+ * sifive_serial_set_stop_bits() - set the number of stop bits
-+ * @ssp: pointer to a struct sifive_serial_port
-+ * @nstop: 1 or 2 (stop bits)
-+ *
-+ * Program the SiFive UART referred to by @ssp to use @nstop stop bits.
-+ */
-+static void sifive_serial_set_stop_bits(struct sifive_serial_port *ssp,
-+					char nstop)
-+{
-+	u32 v;
-+
-+	if (nstop < 1 || nstop > 2) {
-+		WARN_ON(1);
-+		return;
-+	}
-+
-+	v = sifive_serial_read(ssp, SIFIVE_SERIAL_TXCTRL_OFFS);
-+	v &= ~SIFIVE_SERIAL_TXCTRL_NSTOP_MASK;
-+	v |= (nstop-1) << SIFIVE_SERIAL_TXCTRL_NSTOP_SHIFT;
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_TXCTRL_OFFS, v);
-+}
-+
-+/**
-+ * sifive_serial_wait_for_xmitr() - wait for an empty slot on the TX FIFO
-+ * @ssp: pointer to a struct sifive_serial_port
-+ *
-+ * Delay while the UART TX FIFO referred to by @ssp is marked as full.
-+ *
-+ * XXX Probably should use a timeout/bailout.
-+ */
-+static inline void sifive_serial_wait_for_xmitr(struct sifive_serial_port *ssp)
-+{
-+	while (sifive_serial_is_txfifo_full(ssp))
-+		udelay(1); /* XXX Should vary by bps rate */
-+}
-+
-+/*
-+ * Linux serial API functions
-+ */
-+
-+static void sifive_serial_stop_tx(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_disable_txwm(ssp);
-+}
-+
-+static void sifive_serial_stop_rx(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_disable_rxwm(ssp);
-+}
-+
-+static void sifive_serial_start_tx(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_enable_txwm(ssp);
-+}
-+
-+static irqreturn_t sifive_serial_irq(int irq, void *dev_id)
-+{
-+	struct sifive_serial_port *ssp = dev_id;
-+	irqreturn_t r = IRQ_NONE;
-+	int c = ssp->port.fifosize;
-+	u32 ip;
-+
-+	spin_lock(&ssp->port.lock);
-+
-+	do {
-+		ip = sifive_serial_read(ssp, SIFIVE_SERIAL_IP_OFFS);
-+		if (!ip)
-+			break;
-+
-+		r = IRQ_HANDLED;
-+
-+		if (ip & SIFIVE_SERIAL_IP_RXWM_MASK)
-+			sifive_serial_receive_chars(ssp);
-+		if (ip & SIFIVE_SERIAL_IP_TXWM_MASK)
-+			sifive_serial_transmit_chars(ssp);
-+	} while (c--);
-+
-+	spin_unlock(&ssp->port.lock);
-+
-+	tty_flip_buffer_push(&ssp->port.state->port);
-+
-+	return r;
-+}
-+
-+static unsigned int sifive_serial_tx_empty(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	return !sifive_serial_is_txfifo_full(ssp);
-+}
-+
-+static unsigned int sifive_serial_get_mctrl(struct uart_port *port)
-+{
-+	return 0; /* XXX -EINVAL? */
-+}
-+
-+static void sifive_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+	// dev_err(port->dev, "set_mctrl not supported\n");
-+}
-+
-+static void sifive_serial_break_ctl(struct uart_port *port, int break_state)
-+{
-+	dev_err(port->dev, "sending break not supported\n");
-+}
-+
-+static int sifive_serial_startup(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_enable_rxwm(ssp);
-+
-+	return 0;
-+}
-+
-+static void sifive_serial_shutdown(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_disable_rxwm(ssp);
-+	sifive_serial_disable_txwm(ssp);
-+}
-+
-+/**
-+ * sifive_serial_clk_notifier() - clock post-rate-change notifier
-+ * @nb: pointer to the struct notifier_block, from the notifier code
-+ * @event: event mask from the notifier code
-+ * @data: pointer to the struct clk_notifier_data from the notifier code
-+ *
-+ * On the H5U SoC, the UART IP block is derived from the CPU clock source
-+ * after a synchronous divide-by-two divider, so any CPU clock rate change
-+ * requires the UART baud rate to be updated.  This presumably could corrupt any
-+ * serial word currently being transmitted or received.  It would probably
-+ * be better to stop receives and transmits, then complete the baud rate
-+ * change, then re-enable them.
-+ */
-+static int sifive_serial_clk_notifier(struct notifier_block *nb,
-+				      unsigned long event, void *data)
-+{
-+	struct clk_notifier_data *cnd = data;
-+	struct sifive_serial_port *ssp = notifier_to_sifive_serial_port(nb);
-+
-+	if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {
-+		ssp->clkin_rate = cnd->new_rate;
-+		sifive_serial_update_div(ssp);
-+	}
-+
-+	return NOTIFY_OK;
-+}
-+
-+static void sifive_serial_set_termios(struct uart_port *port,
-+				      struct ktermios *termios,
-+				      struct ktermios *old)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+	int rate;
-+	char nstop;
-+
-+	if ((termios->c_cflag & CSIZE) != CS8) {
-+		dev_err(ssp->port.dev, "only 8-bit words supported\n");
-+		return;
-+	}
-+
-+	/* Set number of stop bits */
-+	nstop = (termios->c_cflag & CSTOPB) ? 2 : 1;
-+	sifive_serial_set_stop_bits(ssp, nstop);
-+
-+	/* Set line rate */
-+	rate = uart_get_baud_rate(port, termios, old, 0, ssp->clkin_rate / 16);
-+	sifive_serial_update_bit_rate(ssp, rate);
-+
-+	/* XXX Enable FIFOs with watermark 1 */
-+
-+#if 0
-+	spin_lock_irqsave(&ssp->port.lock, flags);
-+#endif
-+
-+	/*
-+	 * Update the per-port timeout.
-+	 */
-+	uart_update_timeout(port, termios->c_cflag, rate);
-+
-+	/* XXX */
-+	ssp->port.read_status_mask = 0;
-+	if (termios->c_iflag & INPCK) {
-+		dev_err(ssp->port.dev, "INPCK flag not supported\n");
-+		return;
-+	}
-+	if (termios->c_iflag & (BRKINT | PARMRK)) {
-+		dev_err(ssp->port.dev, "BRKINT/PARMRK flag not supported\n");
-+		return;
-+	}
-+
-+#if 0
-+	/*
-+	 * ignore all characters if CREAD is not set
-+	 */
-+	if ((termios->c_cflag & CREAD) == 0)
-+		ssp->port.ignore_status_mask |= UART_LSR_DR;
-+#endif
-+
-+	/* XXX enable interrupts */
-+}
-+
-+static void sifive_serial_release_port(struct uart_port *port)
-+{
-+}
-+
-+static int sifive_serial_request_port(struct uart_port *port)
-+{
-+	return 0;
-+}
-+
-+static void sifive_serial_config_port(struct uart_port *port, int flags)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	ssp->port.type = PORT_SIFIVE_H5U;
-+}
-+
-+static int sifive_serial_verify_port(struct uart_port *port,
-+				     struct serial_struct *ser)
-+{
-+	return -EINVAL;
-+}
-+
-+static const char *sifive_serial_type(struct uart_port *port)
-+{
-+	return port->type == PORT_SIFIVE_H5U ? SIFIVE_SERIAL_NAME : NULL;
-+}
-+
-+/*
-+ * Polling support
-+ */
-+
-+#ifdef CONFIG_CONSOLE_POLL
-+
-+static void sifive_serial_poll_put_char(struct uart_port *port,
-+					unsigned char ch)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_wait_for_xmitr(ssp);
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_TXDATA_OFFS, ch);
-+}
-+
-+static int sifive_serial_poll_get_char(struct uart_port *port)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+	char is_empty, ch;
-+
-+	ch = sifive_serial_receive_char(ssp, &is_empty);
-+	if (is_empty)
-+		return NO_POLL_CHAR;
-+
-+	return ch;
-+}
-+
-+#endif /* CONFIG_CONSOLE_POLL */
-+
-+/*
-+ * Earlyconsole support
-+ */
-+
-+#ifdef CONFIG_SERIAL_EARLYCON
-+static void early_sifive_serial_putc(struct uart_port *port, int c)
-+{
-+	while (sifive_serial_early_read(port, SIFIVE_SERIAL_TXDATA_OFFS) &
-+	       SIFIVE_SERIAL_TXDATA_FULL_MASK)
-+		cpu_relax();
-+
-+	sifive_serial_early_write(port, SIFIVE_SERIAL_TXDATA_OFFS, c);
-+}
-+
-+void early_sifive_serial_write(struct console *console, const char *s,
-+			       unsigned int count)
-+{
-+	struct earlycon_device *device = console->data;
-+	struct uart_port *port = &device->port;
-+
-+	uart_console_write(port, s, count, early_sifive_serial_putc);
-+}
-+
-+static int __init early_sifive_serial_setup(struct earlycon_device *device,
-+					    const char *options)
-+{
-+	struct uart_port *port = &device->port;
-+
-+	if (!(port->membase || port->iobase))
-+		return -ENODEV;
-+
-+	device->con->write = early_sifive_serial_write;
-+	return 0;
-+}
-+
-+OF_EARLYCON_DECLARE(sifive, "sifive,freedom-uart", early_sifive_serial_setup);
-+#endif /* CONFIG_SERIAL_EARLYCON */
-+
-+/*
-+ * Linux console interface
-+ */
-+
-+#ifdef CONFIG_SERIAL_SIFIVE_CONSOLE
-+
-+static struct sifive_serial_port *sifive_serial_console_ports[SIFIVE_SERIAL_MAX_PORTS];
-+
-+static void sifive_serial_console_putchar(struct uart_port *port, int ch)
-+{
-+	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port);
-+
-+	sifive_serial_wait_for_xmitr(ssp);
-+	sifive_serial_transmit_char(ssp, ch);
-+}
-+
-+static void sifive_serial_console_write(struct console *co, const char *s,
-+					unsigned int count)
-+{
-+	struct sifive_serial_port *ssp = sifive_serial_console_ports[co->index];
-+	unsigned long flags;
-+	unsigned int ier;
-+	int locked = 1;
-+
-+	if (!ssp) return;
-+
-+	local_irq_save(flags);
-+	if (ssp->port.sysrq)
-+		locked = 0;
-+	else if (oops_in_progress)
-+		locked = spin_trylock(&ssp->port.lock);
-+	else
-+		spin_lock(&ssp->port.lock);
-+
-+	ier = sifive_serial_read(ssp, SIFIVE_SERIAL_IE_OFFS);
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, 0);
-+
-+	uart_console_write(&ssp->port, s, count, sifive_serial_console_putchar);
-+
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_IE_OFFS, ier);
-+
-+	if (locked)
-+		spin_unlock(&ssp->port.lock);
-+	local_irq_restore(flags);
-+}
-+
-+static int __init sifive_serial_console_setup(struct console *co, char *options)
-+{
-+	struct sifive_serial_port *ssp;
-+	int baud = 115200;
-+	int bits = 8;
-+	int parity = 'n';
-+	int flow = 'n';
-+
-+	ssp = sifive_serial_console_ports[co->index];
-+	if (!ssp)
-+		return -ENODEV;
-+
-+	if (options)
-+		uart_parse_options(options, &baud, &parity, &bits, &flow);
-+
-+	return uart_set_options(&ssp->port, co, baud, parity, bits, flow);
-+}
-+
-+static struct uart_driver sifive_serial_uart_driver;
-+
-+static struct console sifive_serial_console = {
-+	.name		= SIFIVE_TTY_PREFIX,
-+	.write		= sifive_serial_console_write,
-+	.device		= uart_console_device,
-+	.setup		= sifive_serial_console_setup,
-+	.flags		= CON_PRINTBUFFER,
-+	.index		= -1,
-+	.data		= &sifive_serial_uart_driver,
-+};
-+
-+static void sifive_serial_add_console_port(struct sifive_serial_port *ssp)
-+{
-+	sifive_serial_console_ports[ssp->port.line] = ssp;
-+}
-+
-+static void sifive_serial_remove_console_port(struct sifive_serial_port *ssp)
-+{
-+	sifive_serial_console_ports[ssp->port.line] = 0;
-+}
-+
-+#define SIFIVE_SERIAL_CONSOLE	(&sifive_serial_console)
-+
-+#else
-+
-+#define SIFIVE_SERIAL_CONSOLE	NULL
-+
-+static inline void sifive_serial_add_console_port(struct sifive_serial_port *ssp)
-+{}
-+static void sifive_serial_remove_console_port(struct sifive_serial_port *ssp)
-+{}
-+
-+#endif
-+
-+static const struct uart_ops sifive_serial_uops = {
-+	.tx_empty	= sifive_serial_tx_empty,
-+	.set_mctrl	= sifive_serial_set_mctrl,
-+	.get_mctrl	= sifive_serial_get_mctrl,
-+	.stop_tx	= sifive_serial_stop_tx,
-+	.start_tx	= sifive_serial_start_tx,
-+	.stop_rx	= sifive_serial_stop_rx,
-+	.break_ctl	= sifive_serial_break_ctl,
-+	.startup	= sifive_serial_startup,
-+	.shutdown	= sifive_serial_shutdown,
-+	.set_termios	= sifive_serial_set_termios,
-+	.type		= sifive_serial_type,
-+	.release_port	= sifive_serial_release_port,
-+	.request_port	= sifive_serial_request_port,
-+	.config_port	= sifive_serial_config_port,
-+	.verify_port	= sifive_serial_verify_port,
-+#ifdef CONFIG_CONSOLE_POLL
-+	.poll_put_char  = sifive_serial_poll_put_char,
-+	.poll_get_char  = sifive_serial_poll_get_char,
-+#endif
-+};
-+
-+static struct uart_driver sifive_serial_uart_driver = {
-+	.owner		= THIS_MODULE,
-+	.driver_name	= SIFIVE_SERIAL_NAME,
-+	.dev_name	= "ttySI",
-+	.nr		= SIFIVE_SERIAL_MAX_PORTS,
-+	.cons		= SIFIVE_SERIAL_CONSOLE,
-+};
-+
-+static int sifive_serial_probe(struct platform_device *pdev)
-+{
-+	struct sifive_serial_port *ssp;
-+	struct resource *mem;
-+	struct clk *clk;
-+	void __iomem *base;
-+	int irq, id, r;
-+
-+	irq = platform_get_irq(pdev, 0);
-+	if (irq < 0) {
-+		dev_err(&pdev->dev, "could not acquire interrupt\n");
-+		return -EPROBE_DEFER;
-+	}
-+
-+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	base = devm_ioremap_resource(&pdev->dev, mem);
-+	if (IS_ERR(base)) {
-+		dev_err(&pdev->dev, "could not acquire device memory\n");
-+		return PTR_ERR(base);
-+	}
-+
-+	clk = devm_clk_get(&pdev->dev, NULL);
-+	if (IS_ERR(clk)) {
-+		dev_err(&pdev->dev, "unable to find controller clock\n");
-+		return PTR_ERR(clk);
-+	}
-+
-+	id = of_alias_get_id(pdev->dev.of_node, "serial");
-+	if (id < 0) {
-+		dev_err(&pdev->dev, "missing aliases entry\n");
-+		return id;
-+	}
-+
-+#ifdef CONFIG_SERIAL_SIFIVE_CONSOLE
-+	if (id > SIFIVE_SERIAL_MAX_PORTS) {
-+		dev_err(&pdev->dev, "too many UARTs (%d)\n", id);
-+		return -EINVAL;
-+	}
-+#endif
-+
-+	ssp = devm_kzalloc(&pdev->dev, sizeof(*ssp), GFP_KERNEL);
-+	if (!ssp)
-+		return -ENOMEM;
-+
-+	ssp->port.dev = &pdev->dev;
-+	ssp->port.type = PORT_SIFIVE_H5U;
-+	ssp->port.iotype = UPIO_MEM;
-+	ssp->port.irq = irq;
-+	ssp->port.fifosize = 8;
-+	ssp->port.ops = &sifive_serial_uops;
-+	ssp->port.line = id;
-+	ssp->port.mapbase = mem->start;
-+	ssp->port.membase = base;
-+	ssp->dev = &pdev->dev;
-+	ssp->clk = clk;
-+	ssp->clk_notifier.notifier_call = sifive_serial_clk_notifier;
-+
-+	r = clk_notifier_register(ssp->clk, &ssp->clk_notifier);
-+	if (r) {
-+		dev_err(&pdev->dev, "could not register clock notifier: %d\n",
-+			r);
-+		goto probe_out1;
-+	}
-+
-+	/* Setup clock divider */
-+	ssp->clkin_rate = clk_get_rate(ssp->clk);
-+	ssp->bit_rate = 115200;
-+	sifive_serial_update_div(ssp);
-+
-+	platform_set_drvdata(pdev, ssp);
-+
-+	/* Enable transmits and set the watermark level to 1 */
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_TXCTRL_OFFS,
-+			    (1 << SIFIVE_SERIAL_TXCTRL_TXCNT_SHIFT) |
-+			    SIFIVE_SERIAL_TXCTRL_TXEN_MASK);
-+
-+	/* Enable receives and set the watermark level to 0 */
-+	sifive_serial_write(ssp, SIFIVE_SERIAL_RXCTRL_OFFS,
-+			    (0 << SIFIVE_SERIAL_RXCTRL_RXCNT_SHIFT) |
-+			    SIFIVE_SERIAL_RXCTRL_RXEN_MASK);
-+
-+	r = request_irq(ssp->port.irq, sifive_serial_irq, ssp->port.irqflags,
-+			dev_name(&pdev->dev), ssp);
-+	if (r) {
-+		dev_err(&pdev->dev, "could not attach interrupt: %d\n", r);
-+		goto probe_out2;
-+	}
-+
-+	r = uart_add_one_port(&sifive_serial_uart_driver, &ssp->port);
-+	if (r != 0) {
-+		dev_err(&pdev->dev, "could not add uart: %d\n", r);
-+		goto probe_out3;
-+	}
-+
-+	sifive_serial_add_console_port(ssp);
-+
-+	return 0;
-+
-+probe_out3:
-+	free_irq(ssp->port.irq, ssp);
-+probe_out2:
-+	clk_notifier_unregister(ssp->clk, &ssp->clk_notifier);
-+probe_out1:
-+	return r;
-+}
-+
-+static int sifive_serial_remove(struct platform_device *dev)
-+{
-+	struct sifive_serial_port *ssp = platform_get_drvdata(dev);
-+
-+	sifive_serial_remove_console_port(ssp);
-+	uart_remove_one_port(&sifive_serial_uart_driver, &ssp->port);
-+	free_irq(ssp->port.irq, ssp);
-+	clk_notifier_unregister(ssp->clk, &ssp->clk_notifier);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id sifive_serial_of_match[] = {
-+	{ .compatible = "sifive,uart0" },
-+	{},
-+};
-+MODULE_DEVICE_TABLE(of, sifive_serial_match);
-+
-+static struct platform_driver sifive_serial_platform_driver = {
-+	.probe		= sifive_serial_probe,
-+	.remove		= sifive_serial_remove,
-+	.driver		= {
-+		.name	= SIFIVE_SERIAL_NAME,
-+		.of_match_table = of_match_ptr(sifive_serial_of_match),
-+	},
-+};
-+
-+static int __init sifive_serial_init(void)
-+{
-+	struct tty_driver *tty_drv;
-+	int r;
-+
-+	r = uart_register_driver(&sifive_serial_uart_driver);
-+	if (r) goto init_out1;
-+
-+	tty_drv = sifive_serial_uart_driver.tty_driver;
-+	if (!tty_drv) goto init_out2;
-+
-+	/* change default terminal settings for SiFive uarts */
-+	tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
-+	tty_drv->init_termios.c_ispeed = 115200;
-+	tty_drv->init_termios.c_ospeed = 115200;
-+
-+	r = platform_driver_register(&sifive_serial_platform_driver);
-+	if (r) goto init_out2;
-+
-+	return 0;
-+
-+init_out2:
-+	uart_unregister_driver(&sifive_serial_uart_driver);
-+init_out1:
-+	return r;
-+}
-+
-+static void __exit sifive_serial_exit(void)
-+{
-+	platform_driver_unregister(&sifive_serial_platform_driver);
-+	uart_unregister_driver(&sifive_serial_uart_driver);
-+}
-+
-+module_init(sifive_serial_init);
-+module_exit(sifive_serial_exit);
-+
-+MODULE_DESCRIPTION("SiFive UART serial driver");
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Paul Walmsley <paul@pwsan.com>");
-diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
-index dce5f9da..86973c38 100644
---- a/include/uapi/linux/serial_core.h
-+++ b/include/uapi/linux/serial_core.h
-@@ -281,4 +281,7 @@
- /* MediaTek BTIF */
- #define PORT_MTK_BTIF	117
- 
-+/* SiFive UART */
-+#define PORT_SIFIVE_H5U	118
-+
- #endif /* _UAPILINUX_SERIAL_CORE_H */
--- 
-2.7.4
-

+ 0 - 235
recipes-kernel/linux/files/freedom-u540/0004-gemgxl-mgmt-implement-clock-switch-for-GEM-tx_clk.patch

@@ -1,235 +0,0 @@
-From c61e4295c2b2e29bbfe4af4795e2ca862c5de8e3 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Tue, 6 Feb 2018 11:03:07 -0800
-Subject: [PATCH 04/11] gemgxl-mgmt: implement clock switch for GEM tx_clk
-
-Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
----
- .../bindings/clock/sifive,gemgxl-mgmt.txt          |  26 +++++
- drivers/clk/Kconfig                                |   1 +
- drivers/clk/Makefile                               |   1 +
- drivers/clk/sifive/Kconfig                         |   9 ++
- drivers/clk/sifive/Makefile                        |   2 +
- drivers/clk/sifive/gemgxl-mgmt.c                   | 129 +++++++++++++++++++++
- 6 files changed, 168 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/clock/sifive,gemgxl-mgmt.txt
- create mode 100644 drivers/clk/sifive/Kconfig
- create mode 100644 drivers/clk/sifive/Makefile
- create mode 100644 drivers/clk/sifive/gemgxl-mgmt.c
-
-diff --git a/Documentation/devicetree/bindings/clock/sifive,gemgxl-mgmt.txt b/Documentation/devicetree/bindings/clock/sifive,gemgxl-mgmt.txt
-new file mode 100644
-index 00000000..349489e3
---- /dev/null
-+++ b/Documentation/devicetree/bindings/clock/sifive,gemgxl-mgmt.txt
-@@ -0,0 +1,26 @@
-+TX clock switch for GEMGXL in U540 SoCs
-+
-+This binding uses the common clock binding:
-+    Documentation/devicetree/bindings/clock/clock-bindings.txt
-+
-+The U54 includes a clock mux to control the ethernet TX frequenecy. It
-+switches between the local TX clock (125MHz) and PHY TX clocks. This is
-+necessary to toggle between 1Gb and 100/10Mb speeds.
-+
-+Required properties:
-+- compatible:	Should be "sifive,cadencegemgxlmgmt0"
-+- #clock-cells:	Should be <0>
-+- reg:		Specifies base physical address and size of the registers
-+
-+Example:
-+
-+	mgmt: cadence-gemgxl-mgmt@100a00000 {
-+		compatible = "sifive,cadencegemgxlmgmt0";
-+		#clock-cells = <0>;
-+		reg = <0x0 0x100a0000 0x0 0x1000>;
-+	};
-+
-+	ethernet@10090000 {
-+		...
-+		clocks = <&mgmt>; /* TX clock */
-+	};
-diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
-index 292056bb..d4cca333 100644
---- a/drivers/clk/Kconfig
-+++ b/drivers/clk/Kconfig
-@@ -299,5 +299,6 @@ source "drivers/clk/sunxi-ng/Kconfig"
- source "drivers/clk/tegra/Kconfig"
- source "drivers/clk/ti/Kconfig"
- source "drivers/clk/uniphier/Kconfig"
-+source "drivers/clk/sifive/Kconfig"
- 
- endmenu
-diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
-index a84c5573..858bdb9b 100644
---- a/drivers/clk/Makefile
-+++ b/drivers/clk/Makefile
-@@ -90,6 +90,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
- obj-y					+= renesas/
- obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
- obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
-+obj-y					+= sifive/
- obj-$(CONFIG_ARCH_SIRF)			+= sirf/
- obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
- obj-$(CONFIG_PLAT_SPEAR)		+= spear/
-diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
-new file mode 100644
-index 00000000..284bffb1
---- /dev/null
-+++ b/drivers/clk/sifive/Kconfig
-@@ -0,0 +1,9 @@
-+config CLK_U54_PRCI
-+	bool "PRCI driver for U54 SoCs"
-+	---help---
-+	  Supports Power Reset Clock interface found in U540 SoCs
-+
-+config CLK_GEMGXL_MGMT
-+	bool "TX clock switch for GEMGXL in U540 SoCs"
-+	---help---
-+	  Supports clock muxing between 10/100Mbit and 1Gbit TX clock on U540 SoCs
-diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
-new file mode 100644
-index 00000000..7784d2ee
---- /dev/null
-+++ b/drivers/clk/sifive/Makefile
-@@ -0,0 +1,2 @@
-+obj-$(CONFIG_CLK_U54_PRCI)	+= u54-prci.o
-+obj-$(CONFIG_CLK_GEMGXL_MGMT)	+= gemgxl-mgmt.o
-diff --git a/drivers/clk/sifive/gemgxl-mgmt.c b/drivers/clk/sifive/gemgxl-mgmt.c
-new file mode 100644
-index 00000000..00b07580
---- /dev/null
-+++ b/drivers/clk/sifive/gemgxl-mgmt.c
-@@ -0,0 +1,129 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * Copyright (C) 2018 SiFive, Inc.
-+ */
-+
-+#include <linux/clkdev.h>
-+#include <linux/clk-provider.h>
-+#include <linux/err.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+
-+struct sifive_gemgxl_mgmt {
-+	void __iomem *reg;
-+	unsigned long rate;
-+	struct clk_hw hw;
-+};
-+
-+#define to_sifive_gemgxl_mgmt(mgmt) container_of(mgmt, struct sifive_gemgxl_mgmt, hw)
-+
-+static unsigned long sifive_gemgxl_mgmt_recalc_rate(struct clk_hw *hw,
-+				      unsigned long parent_rate)
-+{
-+	struct sifive_gemgxl_mgmt *mgmt = to_sifive_gemgxl_mgmt(hw);
-+	return mgmt->rate;
-+}
-+
-+static long sifive_gemgxl_mgmt_round_rate(struct clk_hw *hw, unsigned long rate,
-+		unsigned long *parent_rate)
-+{
-+	if (WARN_ON(rate < 2500000)) {
-+		return 2500000;
-+	} else if (rate == 2500000) {
-+		return 2500000;
-+	} else if (WARN_ON(rate < 13750000)) {
-+		return 2500000;
-+	} else if (WARN_ON(rate < 25000000)) {
-+		return 25000000;
-+	} else if (rate == 25000000) {
-+		return 25000000;
-+	} else if (WARN_ON(rate < 75000000)) {
-+		return 25000000;
-+	} else if (WARN_ON(rate < 125000000)) {
-+		return 125000000;
-+	} else if (rate == 125000000) {
-+		return 125000000;
-+	} else {
-+		WARN_ON(rate > 125000000);
-+		return 125000000;
-+	}
-+}
-+
-+static int sifive_gemgxl_mgmt_set_rate(struct clk_hw *hw, unsigned long rate,
-+		unsigned long parent_rate)
-+{
-+	struct sifive_gemgxl_mgmt *mgmt = to_sifive_gemgxl_mgmt(hw);
-+	rate = sifive_gemgxl_mgmt_round_rate(hw, rate, &parent_rate);
-+	iowrite32(rate != 125000000, mgmt->reg);
-+	mgmt->rate = rate;
-+	return 0;
-+}
-+
-+static const struct clk_ops sifive_gemgxl_mgmt_ops = {
-+	.recalc_rate = sifive_gemgxl_mgmt_recalc_rate,
-+	.round_rate = sifive_gemgxl_mgmt_round_rate,
-+	.set_rate = sifive_gemgxl_mgmt_set_rate,
-+};
-+
-+static int sifive_gemgxl_mgmt_probe(struct platform_device *pdev)
-+{
-+	struct clk_init_data init;
-+	struct sifive_gemgxl_mgmt *mgmt;
-+	struct resource *res;
-+	struct clk *clk;
-+
-+	mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
-+	if (!mgmt)
-+		return -ENOMEM;
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	mgmt->reg = devm_ioremap_resource(&pdev->dev, res);
-+	if (IS_ERR(mgmt->reg))
-+		return PTR_ERR(mgmt->reg);
-+
-+	init.name = pdev->dev.of_node->name;
-+	init.ops = &sifive_gemgxl_mgmt_ops;
-+	init.flags = 0;
-+	init.num_parents = 0;
-+
-+	mgmt->rate = 0;
-+	mgmt->hw.init = &init;
-+
-+	clk = clk_register(NULL, &mgmt->hw);
-+	if (IS_ERR(clk))
-+		return PTR_ERR(clk);
-+
-+	of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
-+
-+	dev_info(&pdev->dev, "Registered clock switch '%s'\n", init.name);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id sifive_gemgxl_mgmt_of_match[] = {
-+	{ .compatible = "sifive,cadencegemgxlmgmt0", },
-+	{}
-+};
-+
-+static struct platform_driver sifive_gemgxl_mgmt_driver = {
-+	.driver	= {
-+		.name = "sifive-gemgxl-mgmt",
-+		.of_match_table = sifive_gemgxl_mgmt_of_match,
-+	},
-+	.probe = sifive_gemgxl_mgmt_probe,
-+};
-+
-+static int __init sifive_gemgxl_mgmt_init(void)
-+{
-+	return platform_driver_register(&sifive_gemgxl_mgmt_driver);
-+}
-+core_initcall(sifive_gemgxl_mgmt_init);
--- 
-2.7.4
-

+ 0 - 63
recipes-kernel/linux/files/freedom-u540/0005-u54-prci-driver-for-core-U54-clocks.patch

@@ -1,63 +0,0 @@
-From b7bd34686a9341a7d1cde3fc0b607706b3a82b40 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Tue, 13 Feb 2018 19:39:41 -0800
-Subject: [PATCH 05/11] u54-prci: driver for core U54 clocks
-
----
- .../devicetree/bindings/clock/sifive,u54-prci.txt  | 44 ++++++++++++++++++++++
- 1 file changed, 44 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/clock/sifive,u54-prci.txt
-
-diff --git a/Documentation/devicetree/bindings/clock/sifive,u54-prci.txt b/Documentation/devicetree/bindings/clock/sifive,u54-prci.txt
-new file mode 100644
-index 00000000..88682c5e
---- /dev/null
-+++ b/Documentation/devicetree/bindings/clock/sifive,u54-prci.txt
-@@ -0,0 +1,44 @@
-+SiFive U54 SoC clocks
-+
-+This binding uses the common clock binding:
-+    Documentation/devicetree/bindings/clock/clock-bindings.txt
-+
-+The U54 PRCI controller generates clocks for the U54 SoC. There is
-+a core PLL that sets the processor frequency and PLLs for ethernet
-+and DDR. It takes an input clock from the board, typically an oscillator
-+or crystal.
-+
-+Required properties:
-+- compatible:	Should be "sifive,aloeprci0"
-+- #clock-cells:	Should be <1>
-+- reg:		Specifies base physical address and size of the registers
-+- clocks:	phandles to the parent clock used as input
-+
-+Example:
-+
-+	refclk: refclk {
-+		#clock-cells = <0>;
-+		compatible = "fixed-clock";
-+		clock-frequency = <33333333>;
-+		clock-output-names = "xtal";
-+	};
-+
-+	u54: prci@10000000 {
-+		compatible = "sifive,aloeprci0";
-+		reg = <0x0 0x10000000 0x0 0x1000>;
-+		clocks = <&refclk>;
-+		#clock-cells = <1>;
-+	};
-+
-+	tlclk: tlclk {
-+		compatible = "fixed-factor-clock";
-+		clocks = <&u54 0>; /* Core frequency */
-+		#clock-cells = <0>;
-+		clock-div = <2>;
-+		clock-mult = <1>;
-+	};
-+
-+	ethernet@10090000 {
-+		...
-+		clocks = <&prci 1>; /* TX clock */
-+	};
--- 
-2.7.4
-

+ 0 - 333
recipes-kernel/linux/files/freedom-u540/0006-u54-prci-driver-for-core-U54-clocks.patch

@@ -1,333 +0,0 @@
-From ca0f9319165164a75216957bf93e33fd18548d21 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Tue, 13 Feb 2018 19:39:41 -0800
-Subject: [PATCH 06/11] u54-prci: driver for core U54 clocks
-
----
- drivers/clk/sifive/u54-prci.c | 314 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 314 insertions(+)
- create mode 100644 drivers/clk/sifive/u54-prci.c
-
-diff --git a/drivers/clk/sifive/u54-prci.c b/drivers/clk/sifive/u54-prci.c
-new file mode 100644
-index 00000000..edc4b781
---- /dev/null
-+++ b/drivers/clk/sifive/u54-prci.c
-@@ -0,0 +1,314 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * Copyright (C) 2018 SiFive, Inc.
-+ */
-+
-+#include <linux/clkdev.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+#include <linux/log2.h>
-+
-+#define CORE_CLOCK 0
-+#define GEMTX_CLOCK 1
-+#define PRCI_CLOCKS 2
-+
-+#define MIN_REF 7000000UL
-+#define MAX_REF 200000000UL
-+#define MAX_PARENT 600000000UL
-+#define MAX_VCO 4800000000UL
-+#define MAX_DIV 64
-+#define MAX_R 64UL
-+
-+#define PLL_LOCK 0x80000000U
-+#define NAME_LEN 40
-+
-+struct sifive_u54_prci_driver;
-+
-+struct sifive_u54_prci_pll {
-+	struct clk_hw hw;
-+	struct sifive_u54_prci_driver *driver;
-+	char name[NAME_LEN];
-+	u32 freq;
-+	u32 glcm;
-+};
-+
-+struct sifive_u54_prci_driver {
-+	struct clk_onecell_data table;
-+	struct clk *clks[PRCI_CLOCKS];
-+	struct sifive_u54_prci_pll plls[PRCI_CLOCKS];
-+	void __iomem *reg;
-+};
-+
-+#define to_sifive_u54_prci_pll(hw) container_of(hw, struct sifive_u54_prci_pll, hw)
-+
-+struct sifive_u54_pll_cfg {
-+	unsigned long r, f, q, a;
-+};
-+
-+static struct sifive_u54_pll_cfg sifive_u54_pll_cfg(u32 reg)
-+{
-+	struct sifive_u54_pll_cfg cfg;
-+	cfg.r = (reg >>  0) & 0x3f;
-+	cfg.f = (reg >>  6) & 0x1ff;
-+	cfg.q = (reg >> 15) & 0x7;
-+	cfg.a = (reg >> 18) & 0x7;
-+	return cfg;
-+}
-+
-+static u32 sifive_u54_pll_reg(struct sifive_u54_pll_cfg cfg)
-+{
-+	u32 reg = 0;
-+	reg |= (cfg.r & 0x3f)  << 0;
-+	reg |= (cfg.f & 0x1ff) << 6;
-+	reg |= (cfg.q & 0x7)   << 15;
-+	reg |= (cfg.a & 0x7)   << 18;
-+	reg |= 1<<25; // internal feedback
-+	return reg;
-+}
-+
-+static unsigned long sifive_u54_pll_rate(struct sifive_u54_pll_cfg cfg, unsigned long parent)
-+{
-+	return (parent*2*(cfg.f+1) / (cfg.r+1)) >> cfg.q;
-+}
-+
-+static struct sifive_u54_pll_cfg sifive_u54_pll_configure(unsigned long target, unsigned long parent)
-+{
-+	struct sifive_u54_pll_cfg cfg;
-+	unsigned long scale, ratio, best_delta, filter;
-+	u32 max_r, best_r, best_f, r;
-+
-+	/* Confirm input frequency is within bounds */
-+	if (WARN_ON(parent > MAX_PARENT)) { parent = MAX_PARENT; }
-+	if (WARN_ON(parent < MIN_REF))    { parent = MIN_REF; }
-+
-+	/* Calculate the Q shift and target VCO */
-+	scale = MAX_VCO / target;
-+	if (scale <= 1) {
-+		cfg.q = 1;
-+		target = MAX_VCO;
-+	} else if (scale > MAX_DIV) {
-+		cfg.q = ilog2(MAX_DIV);
-+		target = MAX_VCO/2;
-+	} else {
-+		cfg.q = ilog2(scale);
-+		target = target << cfg.q;
-+	}
-+
-+	/* Precalcualte the target ratio */
-+	ratio = (target << 20) / parent;
-+
-+	/* Placeholder values */
-+	best_r = 0;
-+	best_f = 0;
-+	best_delta = MAX_VCO;
-+
-+	/* Consider all values for R which land within [MIN_REF, MAX_REF]; prefer smaller R */
-+	max_r = min(MAX_R, parent / MIN_REF);
-+	for (r = DIV_ROUND_UP(parent, MAX_REF); r <= max_r; ++r) {
-+		/* What is the best F we can pick in this case? */
-+		u32 f = (ratio*r + (1<<20)) >> 21;
-+		unsigned long ref = parent / r;
-+		unsigned long vco = ref * f * 2;
-+		unsigned long delta;
-+
-+		/* Ensure rounding didn't take us out of range */
-+		if (vco > target) --f;
-+		if (vco < MAX_VCO/2) ++f;
-+		vco = ref * f * 2;
-+
-+		delta = abs(target - vco);
-+		if (delta < best_delta) {
-+			best_delta = delta;
-+			best_r = r;
-+			best_f = f;
-+		}
-+	}
-+
-+	cfg.r = best_r - 1;
-+	cfg.f = best_f - 1;
-+
-+	/* Pick the best PLL jitter filter */
-+	filter = parent / best_r;
-+	BUG_ON(filter < 7000000);
-+	if (filter < 11000000) {
-+		cfg.a = 1;
-+	} else if (filter < 18000000) {
-+		cfg.a = 2;
-+	} else if (filter < 30000000) {
-+		cfg.a = 3;
-+	} else if (filter < 50000000) {
-+		cfg.a = 4;
-+	} else if (filter < 80000000) {
-+		cfg.a = 5;
-+	} else if (filter < 130000000) {
-+		cfg.a = 6;
-+	} else {
-+		BUG_ON (filter > 200000000);
-+		cfg.a = 7;
-+	}
-+
-+	return cfg;
-+}
-+
-+static unsigned long sifive_u54_prci_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
-+{
-+	struct sifive_u54_prci_pll *pll = to_sifive_u54_prci_pll(hw);
-+	struct sifive_u54_prci_driver *driver = pll->driver;
-+
-+	u32 reg = ioread32(driver->reg + pll->freq);
-+	struct sifive_u54_pll_cfg cfg = sifive_u54_pll_cfg(reg);
-+
-+	return sifive_u54_pll_rate(cfg, parent_rate);
-+}
-+
-+static long sifive_u54_prci_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate)
-+{
-+	struct sifive_u54_pll_cfg cfg = sifive_u54_pll_configure(rate, *parent_rate);
-+	return sifive_u54_pll_rate(cfg, *parent_rate);
-+}
-+
-+static int sifive_u54_prci_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
-+{
-+	struct sifive_u54_prci_pll *pll = to_sifive_u54_prci_pll(hw);
-+	struct sifive_u54_prci_driver *driver = pll->driver;
-+
-+	struct sifive_u54_pll_cfg cfg = sifive_u54_pll_configure(rate, parent_rate);
-+	u32 reg = sifive_u54_pll_reg(cfg);
-+
-+	/* Switch to reg clock and reconfigure PLL */
-+	iowrite32(1, driver->reg + pll->glcm);
-+	iowrite32(reg, driver->reg + pll->freq);
-+
-+	/* Wait for lock and switch back to PLL */
-+	while (!(ioread32(driver->reg + pll->freq) & PLL_LOCK));
-+	iowrite32(0, driver->reg + pll->glcm);
-+
-+	return 0;
-+}
-+
-+static const struct clk_ops sifive_u54_prci_ops_rw = {
-+	.recalc_rate = sifive_u54_prci_recalc_rate,
-+	.round_rate = sifive_u54_prci_round_rate,
-+	.set_rate = sifive_u54_prci_set_rate,
-+};
-+
-+static const struct clk_ops sifive_u54_prci_ops_ro = {
-+	.recalc_rate = sifive_u54_prci_recalc_rate,
-+};
-+
-+static ssize_t sifive_u54_pll_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+	struct sifive_u54_prci_driver *driver = dev_get_drvdata(dev);
-+	return sprintf(buf, "%ld", clk_get_rate(driver->clks[0]));
-+}
-+
-+static ssize_t sifive_u54_pll_rate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-+{
-+	struct sifive_u54_prci_driver *driver = dev_get_drvdata(dev);
-+	unsigned long rate;
-+	char *endp;
-+
-+	rate = simple_strtoul(buf, &endp, 0);
-+	if (*endp != 0 && *endp != '\n')
-+		return -EINVAL;
-+
-+	clk_set_rate(driver->clks[0], rate);
-+	return count;
-+}
-+
-+static DEVICE_ATTR(rate, 0644, sifive_u54_pll_show, sifive_u54_pll_rate_store);
-+
-+static int sifive_u54_prci_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct clk_init_data init;
-+	struct sifive_u54_prci_driver *driver;
-+	struct resource *res;
-+	const char *parent;
-+	int i;
-+
-+	parent = of_clk_get_parent_name(dev->of_node, 0);
-+	if (!parent) {
-+		dev_err(dev, "No OF parent clocks found\n");
-+		return -EINVAL;
-+	}
-+
-+	driver = devm_kzalloc(dev, sizeof(*driver), GFP_KERNEL);
-+	if (!driver) {
-+		dev_err(dev, "Out of memory\n");
-+		return -ENOMEM;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	driver->reg = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(driver->reg))
-+		return PTR_ERR(driver->reg);
-+
-+	/* Link the data structure */
-+	driver->table.clk_num = PRCI_CLOCKS;
-+	driver->table.clks = &driver->clks[0];
-+	dev_set_drvdata(dev, driver);
-+
-+	/* Describe the clocks */
-+	snprintf(driver->plls[CORE_CLOCK].name, NAME_LEN, "%s.core", dev->of_node->name);
-+	driver->plls[CORE_CLOCK].freq = 0x4;
-+	driver->plls[CORE_CLOCK].glcm = 0x24;
-+	snprintf(driver->plls[GEMTX_CLOCK].name, NAME_LEN, "%s.gemtx", dev->of_node->name);
-+	driver->plls[GEMTX_CLOCK].freq = 0x1c;
-+	driver->plls[GEMTX_CLOCK].glcm = 0; /* None; cannot be set_rate */
-+
-+	/* Export the clocks */
-+	for (i = 0; i < PRCI_CLOCKS; ++i) {
-+		init.name = &driver->plls[i].name[0];
-+		init.ops = driver->plls[i].glcm ? &sifive_u54_prci_ops_rw : &sifive_u54_prci_ops_ro;
-+		init.num_parents = 1;
-+		init.parent_names = &parent;
-+		init.flags = 0;
-+
-+		driver->plls[i].driver = driver;
-+		driver->plls[i].hw.init = &init;
-+
-+		driver->clks[i] = devm_clk_register(dev, &driver->plls[i].hw);
-+		if (IS_ERR(driver->clks[i])) {
-+			dev_err(dev, "Failed to register clock %d, %ld\n", i, PTR_ERR(driver->clks[i]));
-+			return PTR_ERR(driver->clks[i]);
-+		}
-+	}
-+
-+	of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &driver->table);
-+	device_create_file(dev, &dev_attr_rate);
-+	dev_info(dev, "Registered U54 core clocks\n");
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id sifive_u54_prci_of_match[] = {
-+	{ .compatible = "sifive,aloeprci0", },
-+	{}
-+};
-+
-+static struct platform_driver sifive_u54_prci_driver = {
-+	.driver	= {
-+		.name = "sifive-u54-prci",
-+		.of_match_table = sifive_u54_prci_of_match,
-+	},
-+	.probe = sifive_u54_prci_probe,
-+};
-+
-+static int __init sifive_u54_prci_init(void)
-+{
-+	return platform_driver_register(&sifive_u54_prci_driver);
-+}
-+core_initcall(sifive_u54_prci_init);
--- 
-2.7.4
-

+ 0 - 409
recipes-kernel/linux/files/freedom-u540/0007-gpio-sifive-support-GPIO-on-SiFive-SoCs.patch

@@ -1,409 +0,0 @@
-From 28447771a2dddf9c083e1eefa5848d03e83496c7 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Wed, 21 Feb 2018 15:43:02 -0800
-Subject: [PATCH 07/11] gpio-sifive: support GPIO on SiFive SoCs
-
----
- .../devicetree/bindings/gpio/gpio-sifive.txt       |  28 ++
- drivers/gpio/Kconfig                               |   7 +
- drivers/gpio/Makefile                              |   1 +
- drivers/gpio/gpio-sifive.c                         | 322 +++++++++++++++++++++
- 4 files changed, 358 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/gpio/gpio-sifive.txt
- create mode 100644 drivers/gpio/gpio-sifive.c
-
-diff --git a/Documentation/devicetree/bindings/gpio/gpio-sifive.txt b/Documentation/devicetree/bindings/gpio/gpio-sifive.txt
-new file mode 100644
-index 00000000..bf41eed8
---- /dev/null
-+++ b/Documentation/devicetree/bindings/gpio/gpio-sifive.txt
-@@ -0,0 +1,28 @@
-+SiFive GPIO controller bindings
-+
-+Required properties:
-+- compatible:
-+  - "sifive,gpio0"
-+- reg: Physical base address and length of the controller's registers.
-+- #gpio-cells : Should be 2
-+  - The first cell is the gpio offset number.
-+  - The second cell indicates the polarity of the GPIO
-+- gpio-controller : Marks the device node as a GPIO controller.
-+- interrupt-controller: Mark the device node as an interrupt controller
-+- #interrupt-cells : Should be 2.
-+  - The first cell is the GPIO offset number within the GPIO controller.
-+  - The second cell is the edge/level to use for interrupt generation.
-+- interrupts: Specify the interrupts, one per GPIO
-+
-+Example:
-+
-+gpio: gpio@10060000 {
-+	compatible = "sifive,gpio0";
-+	interrupt-parent = <&plic>;
-+	interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>;
-+	reg = <0x0 0x10060000 0x0 0x1000>;
-+	gpio-controller;
-+	#gpio-cells = <2>;
-+	interrupt-controller;
-+	#interrupt-cells = <2>;
-+};
-diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
-index 4f52c3a8..7755f49e 100644
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -439,6 +439,13 @@ config GPIO_REG
- 	  A 32-bit single register GPIO fixed in/out implementation.  This
- 	  can be used to represent any register as a set of GPIO signals.
- 
-+config GPIO_SIFIVE
-+	bool "SiFive GPIO support"
-+	depends on OF_GPIO
-+	select GPIOLIB_IRQCHIP
-+	help
-+	  Say yes here to support the GPIO device on SiFive SoCs.
-+
- config GPIO_SPEAR_SPICS
- 	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
- 	depends on PLAT_SPEAR
-diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
-index c256aff6..244a3696 100644
---- a/drivers/gpio/Makefile
-+++ b/drivers/gpio/Makefile
-@@ -111,6 +111,7 @@ obj-$(CONFIG_GPIO_REG)		+= gpio-reg.o
- obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
- obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
- obj-$(CONFIG_GPIO_SCH311X)	+= gpio-sch311x.o
-+obj-$(CONFIG_GPIO_SIFIVE)	+= gpio-sifive.o
- obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o
- obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-spear-spics.o
- obj-$(CONFIG_GPIO_SPRD)		+= gpio-sprd.o
-diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
-new file mode 100644
-index 00000000..6482ebbc
---- /dev/null
-+++ b/drivers/gpio/gpio-sifive.c
-@@ -0,0 +1,322 @@
-+/*
-+ * SiFive GPIO driver
-+ *
-+ * Copyright (C) 2018 SiFive, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/bitops.h>
-+#include <linux/device.h>
-+#include <linux/errno.h>
-+#include <linux/of_irq.h>
-+#include <linux/gpio/driver.h>
-+#include <linux/irqchip/chained_irq.h>
-+#include <linux/init.h>
-+#include <linux/of.h>
-+#include <linux/pinctrl/consumer.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+
-+#define GPIO_INPUT_VAL	0x00
-+#define GPIO_INPUT_EN	0x04
-+#define GPIO_OUTPUT_EN	0x08
-+#define GPIO_OUTPUT_VAL	0x0C
-+#define GPIO_RISE_IE	0x18
-+#define GPIO_RISE_IP	0x1C
-+#define GPIO_FALL_IE	0x20
-+#define GPIO_FALL_IP	0x24
-+#define GPIO_HIGH_IE	0x28
-+#define GPIO_HIGH_IP	0x2C
-+#define GPIO_LOW_IE	0x30
-+#define GPIO_LOW_IP	0x34
-+#define GPIO_OUTPUT_XOR	0x40
-+
-+#define MAX_GPIO	32
-+
-+struct sifive_gpio {
-+	raw_spinlock_t		lock;
-+	void __iomem		*base;
-+	struct gpio_chip	gc;
-+	unsigned long		enabled;
-+	unsigned		trigger[MAX_GPIO];
-+	unsigned int		irq_parent[MAX_GPIO];
-+	struct sifive_gpio	*self_ptr[MAX_GPIO];
-+};
-+
-+static void sifive_assign_bit(void __iomem *ptr, int offset, int value)
-+{
-+	// It's frustrating that we are not allowed to use the device atomics
-+	// which are GUARANTEED to be supported by this device on RISC-V
-+	u32 bit = BIT(offset), old = ioread32(ptr);
-+	if (value)
-+		iowrite32(old | bit, ptr);
-+	else
-+		iowrite32(old & ~bit, ptr);
-+}
-+
-+static int sifive_direction_input(struct gpio_chip *gc, unsigned offset)
-+{
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	unsigned long flags;
-+
-+	if (offset >= gc->ngpio)
-+		return -EINVAL;
-+
-+	raw_spin_lock_irqsave(&chip->lock, flags);
-+	sifive_assign_bit(chip->base + GPIO_OUTPUT_EN, offset, 0);
-+	sifive_assign_bit(chip->base + GPIO_INPUT_EN,  offset, 1);
-+	raw_spin_unlock_irqrestore(&chip->lock, flags);
-+
-+	return 0;
-+}
-+
-+static int sifive_direction_output(struct gpio_chip *gc, unsigned offset, int value)
-+{
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	unsigned long flags;
-+
-+	if (offset >= gc->ngpio)
-+		return -EINVAL;
-+
-+	raw_spin_lock_irqsave(&chip->lock, flags);
-+	sifive_assign_bit(chip->base + GPIO_INPUT_EN,   offset, 0);
-+	sifive_assign_bit(chip->base + GPIO_OUTPUT_VAL, offset, value);
-+	sifive_assign_bit(chip->base + GPIO_OUTPUT_EN,  offset, 1);
-+	raw_spin_unlock_irqrestore(&chip->lock, flags);
-+
-+	return 0;
-+}
-+
-+static int sifive_get_direction(struct gpio_chip *gc, unsigned offset)
-+{
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+
-+	if (offset >= gc->ngpio)
-+		return -EINVAL;
-+
-+	return !(ioread32(chip->base + GPIO_OUTPUT_EN) & BIT(offset));
-+}
-+
-+static int sifive_get_value(struct gpio_chip *gc, unsigned offset)
-+{
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+
-+	if (offset >= gc->ngpio)
-+		return -EINVAL;
-+
-+	return !!(ioread32(chip->base + GPIO_INPUT_VAL) & BIT(offset));
-+}
-+
-+static void sifive_set_value(struct gpio_chip *gc, unsigned offset, int value)
-+{
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	unsigned long flags;
-+
-+	if (offset >= gc->ngpio)
-+		return;
-+
-+	raw_spin_lock_irqsave(&chip->lock, flags);
-+	sifive_assign_bit(chip->base + GPIO_OUTPUT_VAL, offset, value);
-+	raw_spin_unlock_irqrestore(&chip->lock, flags);
-+}
-+
-+static void sifive_set_ie(struct sifive_gpio *chip, int offset)
-+{
-+	unsigned long flags;
-+	unsigned trigger;
-+
-+	raw_spin_lock_irqsave(&chip->lock, flags);
-+	trigger = (chip->enabled & BIT(offset)) ? chip->trigger[offset] : 0;
-+	sifive_assign_bit(chip->base + GPIO_RISE_IE, offset, trigger & IRQ_TYPE_EDGE_RISING);
-+	sifive_assign_bit(chip->base + GPIO_FALL_IE, offset, trigger & IRQ_TYPE_EDGE_FALLING);
-+	sifive_assign_bit(chip->base + GPIO_HIGH_IE, offset, trigger & IRQ_TYPE_LEVEL_HIGH);
-+	sifive_assign_bit(chip->base + GPIO_LOW_IE,  offset, trigger & IRQ_TYPE_LEVEL_LOW);
-+	raw_spin_unlock_irqrestore(&chip->lock, flags);
-+}
-+
-+static int sifive_irq_set_type(struct irq_data *d, unsigned trigger)
-+{
-+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	int offset = irqd_to_hwirq(d);
-+
-+	if (offset < 0 || offset >= gc->ngpio)
-+		return -EINVAL;
-+
-+	chip->trigger[offset] = trigger;
-+	sifive_set_ie(chip, offset);
-+	return 0;
-+}
-+
-+/* chained_irq_{enter,exit} already mask the parent */
-+static void sifive_irq_mask(struct irq_data *d) { }
-+static void sifive_irq_unmask(struct irq_data *d) { }
-+
-+static void sifive_irq_enable(struct irq_data *d)
-+{
-+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	int offset = irqd_to_hwirq(d) % MAX_GPIO; // must not fail
-+	u32 bit = BIT(offset);
-+
-+	/* Switch to input */
-+	sifive_direction_input(gc, offset);
-+
-+	/* Clear any sticky pending interrupts */
-+	iowrite32(bit, chip->base + GPIO_RISE_IP);
-+	iowrite32(bit, chip->base + GPIO_FALL_IP);
-+	iowrite32(bit, chip->base + GPIO_HIGH_IP);
-+	iowrite32(bit, chip->base + GPIO_LOW_IP);
-+
-+	/* Enable interrupts */
-+	assign_bit(offset, &chip->enabled, 1);
-+	sifive_set_ie(chip, offset);
-+}
-+
-+static void sifive_irq_disable(struct irq_data *d)
-+{
-+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-+	struct sifive_gpio *chip = gpiochip_get_data(gc);
-+	int offset = irqd_to_hwirq(d) % MAX_GPIO; // must not fail
-+
-+	assign_bit(offset, &chip->enabled, 0);
-+	sifive_set_ie(chip, offset);
-+}
-+
-+static struct irq_chip sifive_irqchip = {
-+	.name		= "sifive-gpio",
-+	.irq_set_type	= sifive_irq_set_type,
-+	.irq_mask	= sifive_irq_mask,
-+	.irq_unmask	= sifive_irq_unmask,
-+	.irq_enable	= sifive_irq_enable,
-+	.irq_disable	= sifive_irq_disable,
-+};
-+
-+static void sifive_irq_handler(struct irq_desc *desc)
-+{
-+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
-+	struct sifive_gpio **self_ptr = irq_desc_get_handler_data(desc);
-+	struct sifive_gpio *chip = *self_ptr;
-+	int offset = self_ptr - &chip->self_ptr[0];
-+	u32 bit = BIT(offset);
-+
-+	chained_irq_enter(irqchip, desc);
-+
-+	/* Re-arm the edge triggers so don't miss the next one */
-+	iowrite32(bit, chip->base + GPIO_RISE_IP);
-+	iowrite32(bit, chip->base + GPIO_FALL_IP);
-+
-+	generic_handle_irq(irq_find_mapping(chip->gc.irq.domain, offset));
-+
-+	/* Re-arm the level triggers after handling to prevent spurious refire */
-+	iowrite32(bit, chip->base + GPIO_HIGH_IP);
-+	iowrite32(bit, chip->base + GPIO_LOW_IP);
-+
-+	chained_irq_exit(irqchip, desc);
-+}
-+
-+static int sifive_gpio_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct device_node *node = pdev->dev.of_node;
-+	struct sifive_gpio *chip;
-+	struct resource *res;
-+	int gpio, irq, ret, ngpio;
-+
-+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
-+	if (!chip) {
-+		dev_err(dev, "out of memory\n");
-+		return -ENOMEM;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	chip->base = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(chip->base)) {
-+		dev_err(dev, "failed to allocate device memory\n");
-+		return PTR_ERR(chip->base);
-+	}
-+
-+	ngpio = of_irq_count(node);
-+	if (ngpio >= MAX_GPIO) {
-+		dev_err(dev, "too many interrupts\n");
-+		return -EINVAL;
-+	}
-+
-+	raw_spin_lock_init(&chip->lock);
-+	chip->gc.direction_input = sifive_direction_input;
-+	chip->gc.direction_output = sifive_direction_output;
-+	chip->gc.get_direction = sifive_get_direction;
-+	chip->gc.get = sifive_get_value;
-+	chip->gc.set = sifive_set_value;
-+	chip->gc.base = -1;
-+	chip->gc.ngpio = ngpio;
-+	chip->gc.label = dev_name(dev);
-+	chip->gc.parent = dev;
-+	chip->gc.owner = THIS_MODULE;
-+
-+	ret = gpiochip_add_data(&chip->gc, chip);
-+	if (ret)
-+		return ret;
-+
-+	/* Disable all GPIO interrupts before enabling parent interrupts */
-+	iowrite32(0, chip->base + GPIO_RISE_IE);
-+	iowrite32(0, chip->base + GPIO_FALL_IE);
-+	iowrite32(0, chip->base + GPIO_HIGH_IE);
-+	iowrite32(0, chip->base + GPIO_LOW_IE);
-+	chip->enabled = 0;
-+
-+	ret = gpiochip_irqchip_add(&chip->gc, &sifive_irqchip, 0, handle_simple_irq, IRQ_TYPE_NONE);
-+	if (ret) {
-+		dev_err(dev, "could not add irqchip\n");
-+		gpiochip_remove(&chip->gc);
-+		return ret;
-+	}
-+
-+	chip->gc.irq.num_parents = ngpio;
-+	chip->gc.irq.parents = &chip->irq_parent[0];
-+	chip->gc.irq.map = &chip->irq_parent[0];
-+
-+	for (gpio = 0; gpio < ngpio; ++gpio) {
-+		irq = platform_get_irq(pdev, gpio);
-+		if (irq < 0) {
-+			dev_err(dev, "invalid IRQ\n");
-+			gpiochip_remove(&chip->gc);
-+			return -ENODEV;
-+		}
-+
-+		chip->irq_parent[gpio] = irq;
-+		chip->self_ptr[gpio] = chip;
-+		chip->trigger[gpio] = IRQ_TYPE_LEVEL_HIGH;
-+	}
-+
-+	for (gpio = 0; gpio < ngpio; ++gpio) {
-+		irq = chip->irq_parent[gpio];
-+		irq_set_chained_handler_and_data(irq, sifive_irq_handler, &chip->self_ptr[gpio]);
-+		irq_set_parent(irq_find_mapping(chip->gc.irq.domain, gpio), irq);
-+	}
-+
-+	platform_set_drvdata(pdev, chip);
-+	dev_info(dev, "SiFive GPIO chip registered %d GPIOs\n", ngpio);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id sifive_gpio_match[] = {
-+	{
-+		.compatible = "sifive,gpio0",
-+	},
-+	{ },
-+};
-+
-+static struct platform_driver sifive_gpio_driver = {
-+	.probe		= sifive_gpio_probe,
-+	.driver = {
-+		.name	= "sifive_gpio",
-+		.of_match_table = of_match_ptr(sifive_gpio_match),
-+	},
-+};
-+builtin_platform_driver(sifive_gpio_driver)
--- 
-2.7.4
-

+ 0 - 342
recipes-kernel/linux/files/freedom-u540/0008-pwm-sifive-add-a-driver-for-SiFive-SoC-PWM.patch

@@ -1,342 +0,0 @@
-From e6655fae27290b94c082069da779851dcce40f00 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Fri, 2 Mar 2018 14:53:51 -0800
-Subject: [PATCH 08/11] pwm-sifive: add a driver for SiFive SoC PWM
-
----
- .../devicetree/bindings/pwm/pwm-sifive.txt         |  28 +++
- drivers/pwm/Kconfig                                |  10 +
- drivers/pwm/Makefile                               |   1 +
- drivers/pwm/pwm-sifive.c                           | 252 +++++++++++++++++++++
- 4 files changed, 291 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sifive.txt
- create mode 100644 drivers/pwm/pwm-sifive.c
-
-diff --git a/Documentation/devicetree/bindings/pwm/pwm-sifive.txt b/Documentation/devicetree/bindings/pwm/pwm-sifive.txt
-new file mode 100644
-index 00000000..7cea20db
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pwm/pwm-sifive.txt
-@@ -0,0 +1,28 @@
-+SiFive PWM controller
-+
-+Unlike most other PWM controllers, the SiFive PWM controller currently only
-+supports one period for all channels in the PWM. This is set globally in DTS.
-+The period also has significant restrictions on the values it can achieve,
-+which the driver rounds to the nearest achievable frequency.
-+
-+Required properties:
-+- compatible: should be "sifive,pwm0"
-+- reg: physical base address and length of the controller's registers
-+- clocks: The frequency the controller runs at
-+- #pwm-cells: Should be 2.
-+  The first cell is the PWM channel number
-+  The second cell is the PWM polarity
-+- sifive,approx-period: the driver will get as close to this period as it can
-+- interrupts: one interrupt per PWM channel (currently unused in the driver)
-+
-+Examples:
-+
-+pwm:  pwm@10020000 {
-+	compatible = "sifive,pwm0";
-+	reg = <0x0 0x10020000 0x0 0x1000>;
-+	clocks = <&tlclk>;
-+	interrupt-parent = <&plic>;
-+	interrupts = <42 43 44 45>;
-+	#pwm-cells = <2>;
-+	sifive,approx-period = <1000000>;
-+};
-diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
-index 504d2527..dd12144d 100644
---- a/drivers/pwm/Kconfig
-+++ b/drivers/pwm/Kconfig
-@@ -378,6 +378,16 @@ config PWM_SAMSUNG
- 	  To compile this driver as a module, choose M here: the module
- 	  will be called pwm-samsung.
- 
-+config PWM_SIFIVE
-+	tristate "SiFive PWM support"
-+	depends on OF
-+	depends on COMMON_CLK
-+	help
-+	  Generic PWM framework driver for SiFive SoCs.
-+
-+	  To compile this driver as a module, choose M here: the module
-+	  will be called pwm-sifive.
-+
- config PWM_SPEAR
- 	tristate "STMicroelectronics SPEAr PWM support"
- 	depends on PLAT_SPEAR
-diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
-index 9c676a0d..30089ca6 100644
---- a/drivers/pwm/Makefile
-+++ b/drivers/pwm/Makefile
-@@ -37,6 +37,7 @@ obj-$(CONFIG_PWM_RCAR)		+= pwm-rcar.o
- obj-$(CONFIG_PWM_RENESAS_TPU)	+= pwm-renesas-tpu.o
- obj-$(CONFIG_PWM_ROCKCHIP)	+= pwm-rockchip.o
- obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
-+obj-$(CONFIG_PWM_SIFIVE)	+= pwm-sifive.o
- obj-$(CONFIG_PWM_SPEAR)		+= pwm-spear.o
- obj-$(CONFIG_PWM_STI)		+= pwm-sti.o
- obj-$(CONFIG_PWM_STM32)		+= pwm-stm32.o
-diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
-new file mode 100644
-index 00000000..93bc0844
---- /dev/null
-+++ b/drivers/pwm/pwm-sifive.c
-@@ -0,0 +1,252 @@
-+/*
-+ * Copyright (C) 2018 SiFive, Inc
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2, as published by
-+ * the Free Software Foundation.
-+ */
-+
-+#include <dt-bindings/pwm/pwm.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pwm.h>
-+#include <linux/slab.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+
-+#define MAX_PWM			4
-+
-+/* Register offsets */
-+#define REG_PWMCFG		0x0
-+#define REG_PWMCOUNT		0x8
-+#define REG_PWMS		0x10
-+#define	REG_PWMCMP0		0x20
-+
-+/* PWMCFG fields */
-+#define BIT_PWM_SCALE		0
-+#define BIT_PWM_STICKY		8
-+#define BIT_PWM_ZERO_ZMP	9
-+#define BIT_PWM_DEGLITCH	10
-+#define BIT_PWM_EN_ALWAYS	12
-+#define BIT_PWM_EN_ONCE		13
-+#define BIT_PWM0_CENTER		16
-+#define BIT_PWM0_GANG		24
-+#define BIT_PWM0_IP		28
-+
-+#define SIZE_PWMCMP		4
-+#define MASK_PWM_SCALE		0xf
-+
-+struct sifive_pwm_device {
-+	struct pwm_chip		chip;
-+	struct notifier_block	notifier;
-+	struct clk		*clk;
-+	void __iomem		*regs;
-+	int 			irq;
-+	unsigned int		approx_period;
-+	unsigned int		real_period;
-+};
-+
-+static inline struct sifive_pwm_device *chip_to_sifive(struct pwm_chip *c)
-+{
-+	return container_of(c, struct sifive_pwm_device, chip);
-+}
-+
-+static inline struct sifive_pwm_device *notifier_to_sifive(struct notifier_block *nb)
-+{
-+	return container_of(nb, struct sifive_pwm_device, notifier);
-+}
-+
-+static int sifive_pwm_apply(struct pwm_chip *chip, struct pwm_device *dev, struct pwm_state *state)
-+{
-+	struct sifive_pwm_device *pwm = chip_to_sifive(chip);
-+	unsigned int duty_cycle;
-+	u32 frac;
-+
-+	duty_cycle = state->duty_cycle;
-+	if (!state->enabled) duty_cycle = 0;
-+	if (state->polarity == PWM_POLARITY_NORMAL) duty_cycle = state->period - duty_cycle;
-+
-+	frac = ((u64)duty_cycle << 16) / state->period;
-+	frac = min(frac, 0xFFFFU);
-+
-+	iowrite32(frac, pwm->regs + REG_PWMCMP0 + (dev->hwpwm * SIZE_PWMCMP));
-+
-+	if (state->enabled) {
-+		state->period = pwm->real_period;
-+		state->duty_cycle = ((u64)frac * pwm->real_period) >> 16;
-+		if (state->polarity == PWM_POLARITY_NORMAL)
-+			state->duty_cycle = state->period - state->duty_cycle;
-+	}
-+
-+	return 0;
-+}
-+
-+static void sifive_pwm_get_state(struct pwm_chip *chip, struct pwm_device *dev, struct pwm_state *state)
-+{
-+	struct sifive_pwm_device *pwm = chip_to_sifive(chip);
-+	unsigned long duty;
-+
-+	duty = ioread32(pwm->regs + REG_PWMCMP0 + (dev->hwpwm * SIZE_PWMCMP));
-+
-+	state->period     = pwm->real_period;
-+	state->duty_cycle = ((u64)duty * pwm->real_period) >> 16;
-+	state->polarity   = PWM_POLARITY_INVERSED;
-+	state->enabled    = duty > 0;
-+}
-+
-+static const struct pwm_ops sifive_pwm_ops = {
-+	.get_state	= sifive_pwm_get_state,
-+	.apply		= sifive_pwm_apply,
-+	.owner		= THIS_MODULE,
-+};
-+
-+static struct pwm_device *sifive_pwm_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
-+{
-+	struct sifive_pwm_device *pwm = chip_to_sifive(chip);
-+	struct pwm_device *dev;
-+
-+	if (args->args[0] >= chip->npwm)
-+		return ERR_PTR(-EINVAL);
-+
-+	dev = pwm_request_from_chip(chip, args->args[0], NULL);
-+	if (IS_ERR(dev))
-+		return dev;
-+
-+	/* The period cannot be changed on a per-PWM basis */
-+	dev->args.period   = pwm->real_period;
-+	dev->args.polarity = PWM_POLARITY_NORMAL;
-+	if (args->args[1] & PWM_POLARITY_INVERTED)
-+		dev->args.polarity = PWM_POLARITY_INVERSED;
-+
-+	return dev;
-+}
-+
-+static void sifive_pwm_update_clock(struct sifive_pwm_device *pwm, unsigned long rate)
-+{
-+	/* (1 << (16+scale)) * 10^9/rate = real_period */
-+	unsigned long scalePow = (pwm->approx_period * (u64)rate) / 1000000000;
-+	int scale = ilog2(scalePow) - 16;
-+
-+	scale = clamp(scale, 0, 0xf);
-+	iowrite32((1 << BIT_PWM_EN_ALWAYS) | (scale << BIT_PWM_SCALE), pwm->regs + REG_PWMCFG);
-+
-+	pwm->real_period = (1000000000ULL << (16 + scale)) / rate;
-+}
-+
-+static int sifive_pwm_clock_notifier(struct notifier_block *nb, unsigned long event, void *data)
-+{
-+	struct clk_notifier_data *ndata = data;
-+	struct sifive_pwm_device *pwm = notifier_to_sifive(nb);
-+
-+	if (event == POST_RATE_CHANGE)
-+		sifive_pwm_update_clock(pwm, ndata->new_rate);
-+
-+	return NOTIFY_OK;
-+}
-+
-+static int sifive_pwm_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct device_node *node = pdev->dev.of_node;
-+	struct sifive_pwm_device *pwm;
-+	struct pwm_chip *chip;
-+	struct resource *res;
-+	int ret;
-+
-+	pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
-+	if (!pwm) {
-+		dev_err(dev, "Out of memory\n");
-+		return -ENOMEM;
-+	}
-+
-+	chip = &pwm->chip;
-+	chip->dev = dev;
-+	chip->ops = &sifive_pwm_ops;
-+	chip->of_xlate = sifive_pwm_xlate;
-+	chip->of_pwm_n_cells = 2;
-+	chip->base = -1;
-+
-+	ret = of_property_read_u32(node, "sifive,npwm", &chip->npwm);
-+	if (ret < 0 || chip->npwm > MAX_PWM) chip->npwm = MAX_PWM;
-+
-+	ret = of_property_read_u32(node, "sifive,approx-period", &pwm->approx_period);
-+	if (ret < 0) {
-+		dev_err(dev, "Unable to read sifive,approx-period from DTS\n");
-+		return -ENOENT;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	pwm->regs = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pwm->regs)) {
-+		dev_err(dev, "Unable to map IO resources\n");
-+		return PTR_ERR(pwm->regs);
-+	}
-+
-+	pwm->clk = devm_clk_get(dev, NULL);
-+	if (IS_ERR(pwm->clk)) {
-+		dev_err(dev, "Unable to find controller clock\n");
-+		return PTR_ERR(pwm->clk);
-+	}
-+
-+	pwm->irq = platform_get_irq(pdev, 0);
-+	if (pwm->irq < 0) {
-+		dev_err(dev, "Unable to find interrupt\n");
-+		return pwm->irq;
-+	}
-+
-+	/* Watch for changes to underlying clock frequency */
-+	pwm->notifier.notifier_call = sifive_pwm_clock_notifier;
-+	clk_notifier_register(pwm->clk, &pwm->notifier);
-+
-+	/* Initialize PWM config */
-+	sifive_pwm_update_clock(pwm, clk_get_rate(pwm->clk));
-+
-+	/* No interrupt handler needed yet */
-+/*
-+	ret = devm_request_irq(dev, pwm->irq, sifive_pwm_irq, 0, dev_name(dev), pwm);
-+	if (ret) {
-+		dev_err(dev, "Unable to bind interrupt\n");
-+		return ret;
-+	}
-+*/
-+
-+	ret = pwmchip_add(chip);
-+	if (ret < 0) {
-+		dev_err(dev, "cannot register PWM: %d\n", ret);
-+		clk_notifier_unregister(pwm->clk, &pwm->notifier);
-+		return ret;
-+	}
-+
-+	platform_set_drvdata(pdev, pwm);
-+	dev_info(dev, "SiFive PWM chip registered %d PWMs\n", chip->npwm);
-+
-+	return 0;
-+}
-+
-+static int sifive_pwm_remove(struct platform_device *dev)
-+{
-+	struct sifive_pwm_device *pwm = platform_get_drvdata(dev);
-+	struct pwm_chip *chip = &pwm->chip;
-+
-+	clk_notifier_unregister(pwm->clk, &pwm->notifier);
-+	return pwmchip_remove(chip);
-+}
-+
-+static const struct of_device_id sifive_pwm_of_match[] = {
-+	{ .compatible = "sifive,pwm0" },
-+	{},
-+};
-+MODULE_DEVICE_TABLE(of, sifive_pwm_of_match);
-+
-+static struct platform_driver sifive_pwm_driver = {
-+	.probe = sifive_pwm_probe,
-+	.remove = sifive_pwm_remove,
-+	.driver = {
-+		.name = "pwm-sifivem",
-+		.of_match_table = of_match_ptr(sifive_pwm_of_match),
-+	},
-+};
-+module_platform_driver(sifive_pwm_driver);
-+
-+MODULE_DESCRIPTION("SiFive PWM driver");
-+MODULE_LICENSE("GPL v2");
--- 
-2.7.4
-

+ 0 - 39
recipes-kernel/linux/files/freedom-u540/0009-RISC-V-Networking-fix-Hack.patch

@@ -1,39 +0,0 @@
-From aa230e7dc2ab01db5b630f427e57297ffc25c884 Mon Sep 17 00:00:00 2001
-From: Atish Patra <atish.patra@wdc.com>
-Date: Fri, 7 Sep 2018 10:22:27 -0700
-Subject: [PATCH 09/11] RISC-V: Networking fix Hack
-
-It looks like that kernel driver now supports reseting the
-signal one additional time. As it had been  already reset
-twice in FSBL, PHY gets into incorrect state causing below error.
-
-----------------------------------------------------------------------
-macb 10090000.ethernet (unnamed net_device) (uninitialized): Could not attach to PHY
-macb: probe of 10090000.ethernet failed with error -110
-----------------------------------------------------------------------
-
-This patch is just a temporary fix until we have a fix a FSBL.
-It is just a **HACK** and **NOT TO BE MERGED** into mainline.
-
-Signed-off-by: Atish Patra <atish.patra@wdc.com>
----
- drivers/net/phy/mdio_bus.c | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
-index 98f4b1f7..02c31f83 100644
---- a/drivers/net/phy/mdio_bus.c
-+++ b/drivers/net/phy/mdio_bus.c
-@@ -64,9 +64,6 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
- 
- 	mdiodev->reset = gpiod;
- 
--	/* Assert the reset signal again */
--	mdio_device_reset(mdiodev, 1);
--
- 	return 0;
- }
- 
--- 
-2.7.4
-

+ 0 - 804
recipes-kernel/linux/files/freedom-u540/0010-pcie-microsemi-added-support-for-the-Vera-board-root.patch

@@ -1,804 +0,0 @@
-From 1fd6c8fbc07bec3c18771738ce4b2aad3ed228f2 Mon Sep 17 00:00:00 2001
-From: "Wesley W. Terpstra" <wesley@sifive.com>
-Date: Wed, 25 Apr 2018 12:10:15 -0700
-Subject: [PATCH 10/11] pcie-microsemi: added support for the Vera-board root
- complex
-
----
- drivers/pci/controller/Kconfig          |   6 +
- drivers/pci/controller/Makefile         |   1 +
- drivers/pci/controller/pcie-microsemi.c | 754 ++++++++++++++++++++++++++++++++
- 3 files changed, 761 insertions(+)
- create mode 100644 drivers/pci/controller/pcie-microsemi.c
-
-diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
-index 028b2874..4458c119 100644
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -278,5 +278,11 @@ config VMD
- 	  To compile this driver as a module, choose M here: the
- 	  module will be called vmd.
- 
-+config PCIE_MICROSEMI
-+	bool "Microsemi AXI PCIe host bridge support"
-+	depends on OF || COMPILE_TEST
-+	help
-+	  Say 'Y' here if you want kernel to support the Microsemi AXI PCIe
-+	  Host Bridge driver.
- source "drivers/pci/controller/dwc/Kconfig"
- endmenu
-diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
-index d56a5074..c3b76ff2 100644
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
- obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
-+obj-$(CONFIG_PCIE_MICROSEMI) += pcie-microsemi.o
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y				+= dwc/
-diff --git a/drivers/pci/controller/pcie-microsemi.c b/drivers/pci/controller/pcie-microsemi.c
-new file mode 100644
-index 00000000..9e2abca2
---- /dev/null
-+++ b/drivers/pci/controller/pcie-microsemi.c
-@@ -0,0 +1,754 @@
-+/*
-+ * PCIe host controller driver for Microsemi AXI PCIe Bridge
-+ *
-+ * Copyright (c) 2018 - Microsemi.
-+ * Author: Badal Nilawar <badal.nilawar@microsemi.com>
-+ *
-+ * Based on the Xilinx, Altera PCIe driver
-+ *
-+ *
-+ * This program is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation, either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/msi.h>
-+#include <linux/of_address.h>
-+#include <linux/of_pci.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_irq.h>
-+#include <linux/pci.h>
-+#include <linux/platform_device.h>
-+#include "../pci.h"
-+
-+/* ECAM definitions */
-+#define ECAM_BUS_NUM_SHIFT		20
-+#define ECAM_DEV_NUM_SHIFT		12
-+
-+/* Number of MSI IRQs */
-+#define MICROSEMI_NUM_MSI_IRQS		32
-+
-+/* PCIe Bridge Phy and Controller Phy offsets */
-+#define PCIE0_BRIDGE_PHY_ADDR_OFFSET			0x03004000u
-+#define PCIE0_CRTL_PHY_ADDR_OFFSET			0x03006000u
-+
-+#define PCIE0_BRIDGE_ADDR		0x03004000u
-+#define PCIE0_CRTL_ADDR			0x03006000u
-+
-+#define PCIE1_BRIDGE_ADDR		0x00008000u
-+#define PCIE1_CRTL_ADDR			0x0000A000u
-+
-+/* PCIe LTSSM State reg */
-+#define LTSSM_STATE		0x5c
-+
-+/* PCIe LTSSM L0 state */
-+#define LTSSM_L0_STATE		0x10
-+
-+/* PCIe Controller Phy Regs */
-+#define SEC_ERROR_INT		0x28
-+#define SEC_ERROR_INT_MASK	0x2c
-+#define DED_ERROR_INT		0x30
-+#define DED_ERROR_INT_MASK	0x34
-+#define ECC_CONTROL		0x38
-+#define PCIE_EVENT_INT		0x14c
-+
-+/* PCIe Bridge Phy Regs */
-+#define IMASK_LOCAL		0x180
-+#define ISTATUS_LOCAL		0x184
-+#define IMASK_HOST		0x188
-+#define ISTATUS_HOST		0x18c
-+#define	ISTATUS_MSI		0x194
-+#define	PCIE_PCI_IDS_DW1	0x9c
-+
-+/* PCIe AXI slave table init defines */
-+#define ATR0_AXI4_SLV0_SRCADDR_PARAM	0x800u
-+#define ATR0_AXI4_SLV0_SRC_ADDR		0x804u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB	0x808u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW	0x80cu
-+#define ATR0_AXI4_SLV0_TRSL_PARAM	0x810u
-+
-+#define ATR1_AXI4_SLV0_SRCADDR_PARAM	0x820u
-+#define ATR1_AXI4_SLV0_SRC_ADDR		0x824u
-+#define ATR1_AXI4_SLV0_TRSL_ADDR_LSB	0x828u
-+#define ATR1_AXI4_SLV0_TRSL_ADDR_UDW	0x82cu
-+#define ATR1_AXI4_SLV0_TRSL_PARAM	0x830u
-+
-+/* PCIe Master table init defines */
-+#define ATR0_PCIE_WIN0_SRCADDR_PARAM	0x600u
-+
-+/* Translated ID */
-+#define  PCIE_TX_RX_INTERFACE		0x00000000u
-+#define  PCIE_CONFIG_INTERFACE		0x00000001u
-+
-+/* PCIe Config space MSI capability structure */
-+#define PCIE_ENABLE_MSI			0x10000000u
-+
-+/* MSI definitions */
-+#define MSI_MSG_ADDR			0x190u
-+#define MSI_ENABLE			(0x01u << 16)
-+#define MSI_ENABLE_MULTI		(MICROSEMI_NUM_MSI_IRQS << 20)
-+
-+/* MSI Capability Structure  */
-+#define MSI_CAP_CTRL			0xE0u
-+#define MSI_MSG_ADDR_OFFSET		0xE4u
-+#define MSI_MSG_UPPER_ADDR_OFFEST	0xE8u
-+#define MSI_MSG_DATA			0xF0u
-+
-+
-+
-+/******************************************************************************/
-+/*Enable PCIe local*/
-+#define PCIE_LOCAL_INT_ENABLE		0xF000000u
-+
-+/******************************************************************************/
-+/* Clear PCIe interrupt events */
-+#define PCIE_EVENT_INT_DATA		0x00070007u
-+#define PCIE_ECC_DISABLE	        0x0F000000u
-+#define PCIE_SEC_ERROR_INT_CLEAR	0x0000FFFFu
-+#define PCIE_DED_ERROR_INT_CLEAR	0x0000FFFFu
-+#define PCIE_ISTATUS_CLEAR		0xFFFFFFFFu
-+#define PCIE_CLEAR			0x00000000u
-+#define PCIE_SET			0x00000001u
-+
-+#define ROOT_PORT_ENABLE		0x00000001u
-+
-+#define NULL_POINTER			0x00000000u
-+
-+/*****************************************************************************/
-+/* PCIe Controller 0 */
-+#define PF_PCIE_CTRL_0                 0u
-+/* PCIe Controller 1 */
-+#define PF_PCIE_CTRL_1                 1u
-+
-+/* It indicates that the ATR table is enabled */
-+#define PF_PCIE_ATR_TABLE_ENABLE       1u
-+/* It indicates that the the ATR table is disabled */
-+#define PF_PCIE_ATR_TABLE_DISABLE      0u
-+
-+
-+/**
-+ * struct microsemi_pcie_port - PCIe port information
-+ * @reg_base: IO Mapped Register Base
-+ * @irq: Interrupt number
-+ * @root_busno: Root Bus number
-+ * @dev: Device pointer
-+ * @msi_domain: MSI IRQ domain pointer
-+ * @leg_domain: Legacy IRQ domain pointer
-+ * @resources: Bus Resources
-+ */
-+struct microsemi_pcie_port {
-+	struct platform_device	*pdev;
-+	void __iomem *reg_base;
-+	void __iomem *reg_base_apb;
-+	void __iomem *reg_bridge_apb;
-+	void __iomem *reg_ctrl_apb;
-+	u32 irq;
-+	u8 root_busno;
-+	struct device *dev;
-+	struct irq_domain *msi_domain;
-+	struct irq_domain *leg_domain;
-+	struct list_head resources;
-+};
-+
-+static DECLARE_BITMAP(msi_irq_in_use, MICROSEMI_NUM_MSI_IRQS);
-+
-+static inline u32 pcie_read(struct microsemi_pcie_port *port, u32 reg)
-+{
-+	return readl(port->reg_base + reg);
-+}
-+
-+static inline void pcie_write(struct microsemi_pcie_port *port,
-+				u32 val, u32 reg)
-+{
-+	writel(val, port->reg_base + reg);
-+}
-+
-+static inline bool microsemi_pcie_link_up(struct microsemi_pcie_port *port)
-+{
-+	return (readl(port->reg_ctrl_apb + LTSSM_STATE)
-+		& LTSSM_L0_STATE) ? 1 : 0;
-+}
-+
-+/**
-+ * microsemi_pcie_valid_device - Check if a valid device is present on bus
-+ * @bus: PCI Bus structure
-+ * @devfn: device/function
-+ *
-+ * Return: 'true' on success and 'false' if invalid device is found
-+ */
-+static bool microsemi_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
-+{
-+	struct microsemi_pcie_port *port = bus->sysdata;
-+
-+	/* Check if link is up when trying to access downstream ports */
-+	if (bus->number != port->root_busno)
-+		if (!microsemi_pcie_link_up(port))
-+			return false;
-+
-+	/* Only one device down on each root port */
-+	if (bus->number == port->root_busno && devfn > 0)
-+		return false;
-+
-+	return true;
-+}
-+
-+/**
-+ * microsemi_pcie_map_bus - Get configuration base
-+ * @bus: PCI Bus structure
-+ * @devfn: Device/function
-+ * @where: Offset from base
-+ *
-+ * Return: Base address of the configuration space needed to be
-+ *	   accessed.
-+ */
-+static void __iomem *microsemi_pcie_map_bus(struct pci_bus *bus,
-+					 unsigned int devfn, int where)
-+{
-+	struct microsemi_pcie_port *port = bus->sysdata;
-+	int relbus;
-+
-+
-+	if (!microsemi_pcie_valid_device(bus, devfn))
-+		return NULL;
-+
-+	relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |
-+		 (devfn << ECAM_DEV_NUM_SHIFT);
-+
-+
-+	return port->reg_base + relbus + where;
-+}
-+
-+/* PCIe operations */
-+static struct pci_ops microsemi_pcie_ops = {
-+	.map_bus = microsemi_pcie_map_bus,
-+	.read	= pci_generic_config_read,
-+	.write	= pci_generic_config_write,
-+};
-+
-+/* MSI functions */
-+
-+/**
-+ * microsemi_pcie_destroy_msi - Free MSI number
-+ * @irq: IRQ to be freed
-+ */
-+static void microsemi_pcie_destroy_msi(unsigned int irq)
-+{
-+	struct msi_desc *msi;
-+	struct microsemi_pcie_port *port;
-+	struct irq_data *d = irq_get_irq_data(irq);
-+	irq_hw_number_t hwirq = irqd_to_hwirq(d);
-+
-+	if (!test_bit(hwirq, msi_irq_in_use)) {
-+		msi = irq_get_msi_desc(irq);
-+		port = msi_desc_to_pci_sysdata(msi);
-+		dev_err(port->dev, "Trying to free unused MSI#%d\n", irq);
-+	} else {
-+		clear_bit(hwirq, msi_irq_in_use);
-+	}
-+}
-+
-+/**
-+ * microsemi_pcie_assign_msi - Allocate MSI number
-+ *
-+ * Return: A valid IRQ on success and error value on failure.
-+ */
-+static int microsemi_pcie_assign_msi(void)
-+{
-+	int pos;
-+
-+	pos = find_first_zero_bit(msi_irq_in_use, MICROSEMI_NUM_MSI_IRQS);
-+	if (pos < MICROSEMI_NUM_MSI_IRQS)
-+		set_bit(pos, msi_irq_in_use);
-+	else
-+		return -ENOSPC;
-+
-+	return pos;
-+}
-+
-+/**
-+ * microsemi_msi_teardown_irq - Destroy the MSI
-+ * @chip: MSI Chip descriptor
-+ * @irq: MSI IRQ to destroy
-+ */
-+static void microsemi_msi_teardown_irq(struct msi_controller *chip,
-+				    unsigned int irq)
-+{
-+	microsemi_pcie_destroy_msi(irq);
-+	irq_dispose_mapping(irq);
-+}
-+
-+/**
-+ * microsemi_pcie_msi_setup_irq - Setup MSI request
-+ * @chip: MSI chip pointer
-+ * @pdev: PCIe device pointer
-+ * @desc: MSI descriptor pointer
-+ *
-+ * Return: '0' on success and error value on failure
-+ */
-+static int microsemi_pcie_msi_setup_irq(struct msi_controller *chip,
-+				     struct pci_dev *pdev,
-+				     struct msi_desc *desc)
-+{
-+	struct microsemi_pcie_port *port = pdev->bus->sysdata;
-+	unsigned int irq;
-+	int hwirq;
-+	struct msi_msg msg;
-+
-+	hwirq = microsemi_pcie_assign_msi();
-+	if (hwirq < 0)
-+		return hwirq;
-+
-+	irq = irq_create_mapping(port->msi_domain, hwirq);
-+	if (!irq)
-+		return -EINVAL;
-+
-+	irq_set_msi_desc(irq, desc);
-+
-+	msg.address_hi = 0;
-+	msg.address_lo = MSI_MSG_ADDR;
-+	msg.data = hwirq;
-+
-+	pci_write_msi_msg(irq, &msg);
-+
-+	return 0;
-+}
-+
-+/* MSI Chip Descriptor */
-+static struct msi_controller microsemi_pcie_msi_chip = {
-+	.setup_irq = microsemi_pcie_msi_setup_irq,
-+	.teardown_irq = microsemi_msi_teardown_irq,
-+};
-+
-+/* HW Interrupt Chip Descriptor */
-+static struct irq_chip microsemi_msi_irq_chip = {
-+	.name = "Microsemi PCIe MSI",
-+	.irq_enable = pci_msi_unmask_irq,
-+	.irq_disable = pci_msi_mask_irq,
-+	.irq_mask = pci_msi_mask_irq,
-+	.irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+/**
-+ * microsemi_pcie_msi_map - Set the handler for the MSI and mark IRQ as valid
-+ * @domain: IRQ domain
-+ * @irq: Virtual IRQ number
-+ * @hwirq: HW interrupt number
-+ *
-+ * Return: Always returns 0.
-+ */
-+static int microsemi_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
-+			       irq_hw_number_t hwirq)
-+{
-+	irq_set_chip_and_handler(irq,
-+				&microsemi_msi_irq_chip, handle_simple_irq);
-+	irq_set_chip_data(irq, domain->host_data);
-+
-+	return 0;
-+}
-+
-+/* IRQ Domain operations */
-+static const struct irq_domain_ops msi_domain_ops = {
-+	.map = microsemi_pcie_msi_map,
-+};
-+
-+/**
-+ * microsemi_pcie_enable_msi - Enable MSI support
-+ * @port: PCIe port information
-+ */
-+static void microsemi_pcie_enable_msi(struct microsemi_pcie_port *port)
-+{
-+	u32 cap_ctrl;
-+
-+	cap_ctrl = pcie_read(port, MSI_CAP_CTRL);
-+
-+	pcie_write(port, cap_ctrl | MSI_ENABLE_MULTI | MSI_ENABLE, MSI_CAP_CTRL);
-+	pcie_write(port, MSI_MSG_ADDR, MSI_MSG_ADDR_OFFSET);
-+}
-+
-+/* INTx Functions */
-+
-+/**
-+ * microsemi_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
-+ * @domain: IRQ domain
-+ * @irq: Virtual IRQ number
-+ * @hwirq: HW interrupt number
-+ *
-+ * Return: Always returns 0.
-+ */
-+static int microsemi_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
-+				irq_hw_number_t hwirq)
-+{
-+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
-+	irq_set_chip_data(irq, domain->host_data);
-+
-+	return 0;
-+}
-+
-+/* INTx IRQ Domain operations */
-+static const struct irq_domain_ops intx_domain_ops = {
-+	.map = microsemi_pcie_intx_map,
-+	.xlate = pci_irqd_intx_xlate,
-+};
-+
-+/* PCIe HW Functions */
-+
-+/**
-+ * microsemi_pcie_intr_handler - Interrupt Service Handler
-+ * @irq: IRQ number
-+ * @data: PCIe port information
-+ *
-+ * Return: IRQ_HANDLED on success and IRQ_NONE on failure
-+ */
-+static irqreturn_t microsemi_pcie_intr_handler(int irq, void *data)
-+{
-+	struct microsemi_pcie_port *port = (struct microsemi_pcie_port *)data;
-+	struct device *dev = port->dev;
-+	unsigned long status;
-+	unsigned long msi;
-+	u32 bit;
-+	u32 virq;
-+
-+
-+	status = readl(port->reg_bridge_apb + ISTATUS_LOCAL);
-+
-+	status = (status >> 24) & 0x0f;
-+	for_each_set_bit(bit, &status, PCI_NUM_INTX) {
-+		/* clear interrupts */
-+		writel(1 << (bit+24),
-+			port->reg_bridge_apb + ISTATUS_LOCAL);
-+
-+		virq = irq_find_mapping(port->leg_domain, bit);
-+
-+		if (virq)
-+			generic_handle_irq(virq);
-+		else
-+			dev_err(dev, "unexpected IRQ, INT%d\n", bit);
-+	}
-+
-+	status = readl(port->reg_bridge_apb + ISTATUS_LOCAL);
-+	if ((status & 0x10000000) == 0x10000000) {
-+		writel((1 << 28), port->reg_bridge_apb + ISTATUS_LOCAL);
-+		msi = readl(port->reg_bridge_apb + ISTATUS_MSI);
-+		for_each_set_bit(bit, &msi, MICROSEMI_NUM_MSI_IRQS) {
-+		/* clear interrupts */
-+			writel((1 << bit),
-+				port->reg_bridge_apb + ISTATUS_MSI);
-+			virq = irq_find_mapping(port->msi_domain, bit);
-+			if (virq)
-+				generic_handle_irq(virq);
-+			else
-+				dev_err(dev, "unexpected IRQ, INT%d\n", bit);
-+		}
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+/**
-+ * microsemi_pcie_init_irq_domain - Initialize IRQ domain
-+ * @port: PCIe port information
-+ *
-+ * Return: '0' on success and error value on failure
-+ */
-+static int microsemi_pcie_init_irq_domain(struct microsemi_pcie_port *port)
-+{
-+	struct device *dev = port->dev;
-+	struct device_node *node = dev->of_node;
-+	struct device_node *pcie_intc_node;
-+
-+	/* Setup INTx */
-+	pcie_intc_node = of_get_next_child(node, NULL);
-+	if (!pcie_intc_node) {
-+		dev_err(dev, "No PCIe Intc node found\n");
-+		return -ENODEV;
-+	}
-+	dev_info(dev, "Intc node foundi %s\n", pcie_intc_node->name);
-+
-+	port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
-+						 &intx_domain_ops,
-+						 port);
-+	if (!port->leg_domain) {
-+		dev_err(dev, "Failed to get a INTx IRQ domain\n");
-+		return -ENODEV;
-+	}
-+
-+	/* Setup MSI */
-+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
-+		port->msi_domain = irq_domain_add_linear(node,
-+						MICROSEMI_NUM_MSI_IRQS,
-+						&msi_domain_ops,
-+						&microsemi_pcie_msi_chip);
-+		if (!port->msi_domain) {
-+			dev_err(dev, "Failed to get a MSI IRQ domain\n");
-+			return -ENODEV;
-+		}
-+		microsemi_pcie_enable_msi(port);
-+	}
-+	return 0;
-+}
-+
-+/**
-+ * microsemi_pcie_init_port - Parse Device tree, Initialize hardware
-+ * @port: PCIe port information
-+ *
-+ * Return: '0' on success and error value on failure
-+ */
-+static int microsemi_pcie_init_port(struct microsemi_pcie_port *port)
-+{
-+	struct device *dev = port->dev;
-+	struct device_node *node = dev->of_node;
-+	struct of_pci_range_parser parser;
-+	struct of_pci_range range;
-+	struct resource regs;
-+	struct resource regs1;
-+	resource_size_t size;
-+	u32 bit, pf_bridge_id = 1;
-+	const char *type;
-+	int err;
-+
-+	type = of_get_property(node, "device_type", NULL);
-+	if (!type || strcmp(type, "pci")) {
-+		dev_err(dev, "invalid \"device_type\" %s\n", type);
-+		return -EINVAL;
-+	}
-+
-+	err = of_address_to_resource(node, 0, &regs);
-+	if (err) {
-+		dev_err(dev, "missing \"reg\" property\n");
-+		return err;
-+	}
-+
-+	port->reg_base = devm_pci_remap_cfg_resource(dev, &regs);
-+	if (IS_ERR(port->reg_base))
-+		return PTR_ERR(port->reg_base);
-+
-+
-+	err = of_address_to_resource(node, 1, &regs1);
-+	if (err) {
-+		dev_err(dev, "missing \"reg\" property\n");
-+		return err;
-+	}
-+
-+
-+	port->reg_base_apb = devm_ioremap_resource(dev, &regs1);
-+	if (IS_ERR(port->reg_base_apb))
-+		return PTR_ERR(port->reg_base_apb);
-+
-+	if (pf_bridge_id == 0) {
-+		port->reg_bridge_apb =  port->reg_base_apb + PCIE0_BRIDGE_ADDR;
-+		port->reg_ctrl_apb = port->reg_base_apb + PCIE0_CRTL_ADDR;
-+	} else {
-+		port->reg_bridge_apb =  port->reg_base_apb + PCIE1_BRIDGE_ADDR;
-+		port->reg_ctrl_apb = port->reg_base_apb + PCIE1_CRTL_ADDR;
-+	}
-+
-+	port->irq = irq_of_parse_and_map(node, 0);
-+
-+	err = devm_request_irq(dev, port->irq, microsemi_pcie_intr_handler,
-+			       IRQF_SHARED | IRQF_NO_THREAD,
-+			       "microsemi-pcie", port);
-+	if (err) {
-+		dev_err(dev, "unable to request irq %d\n", port->irq);
-+		return err;
-+	}
-+
-+
-+	/* Clear and Disable interrupts */
-+
-+	writel(0x0f000000, port->reg_ctrl_apb + ECC_CONTROL);
-+	writel(0x00070007, port->reg_ctrl_apb + PCIE_EVENT_INT);
-+	writel(0x0000ffff, port->reg_ctrl_apb + SEC_ERROR_INT);
-+	writel(0x0000ffff, port->reg_ctrl_apb + SEC_ERROR_INT_MASK);
-+	writel(0x0000ffff, port->reg_ctrl_apb + DED_ERROR_INT);
-+	writel(0x0000ffff, port->reg_ctrl_apb + DED_ERROR_INT_MASK);
-+
-+	writel(0x00000000, port->reg_bridge_apb + IMASK_LOCAL);
-+	writel(0xffffffff, port->reg_bridge_apb + ISTATUS_LOCAL);
-+	writel(0x00000000, port->reg_bridge_apb + IMASK_HOST);
-+	writel(0xffffffff, port->reg_bridge_apb + ISTATUS_HOST);
-+
-+	dev_info(dev, "interrupt disabled\n");
-+
-+	/* Configure Address Translation Table 0 for pcie config space */
-+
-+	writel(PCIE_CONFIG_INTERFACE,
-+		port->reg_bridge_apb + ATR0_AXI4_SLV0_TRSL_PARAM);
-+
-+	size = resource_size(&regs);
-+
-+	bit = find_first_bit((const unsigned long *)&size, 64) - 1;
-+
-+	writel((u32)regs.start | bit << 1 | 0x01,
-+		port->reg_bridge_apb + ATR0_AXI4_SLV0_SRCADDR_PARAM);
-+
-+//	writel((u32)(regs.start >> 32),
-+//		port->reg_bridge_apb + ATR0_AXI4_SLV0_SRC_ADDR);
-+
-+	writel((u32)regs.start,
-+		port->reg_bridge_apb + ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
-+
-+//	writel((u32)(regs.start >> 32),
-+//		port->reg_bridge_apb + ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
-+
-+
-+	if (of_pci_range_parser_init(&parser, node)) {
-+		dev_err(dev, "missing \"ranges\" property\n");
-+		return -EINVAL;
-+	}
-+
-+
-+	for_each_of_pci_range(&parser, &range) {
-+		switch (range.flags & IORESOURCE_TYPE_BITS) {
-+		case IORESOURCE_MEM:
-+
-+		size = range.size;
-+		bit = find_first_bit((const unsigned long *)&size, 64) - 1;
-+
-+		/* Configure Address Translation Table 1 for pcie mem space */
-+
-+		writel(PCIE_TX_RX_INTERFACE,
-+			port->reg_bridge_apb + ATR1_AXI4_SLV0_TRSL_PARAM);
-+
-+		writel((u32)range.cpu_addr | bit << 1 | 0x01,
-+			port->reg_bridge_apb + ATR1_AXI4_SLV0_SRCADDR_PARAM);
-+
-+//		writel((u32)(range.cpu_addr >> 32),
-+//			port->reg_bridge_apb + ATR1_AXI4_SLV0_SRC_ADDR);
-+
-+		writel((u32)range.pci_addr,
-+			port->reg_bridge_apb + ATR1_AXI4_SLV0_TRSL_ADDR_LSB);
-+
-+//		writel((u32)(range.pci_addr >> 32),
-+//			port->reg_bridge_apb + ATR1_AXI4_SLV0_TRSL_ADDR_UDW);
-+
-+		break;
-+		}
-+
-+	}
-+
-+
-+	writel(readl(port->reg_bridge_apb + ATR0_PCIE_WIN0_SRCADDR_PARAM)
-+		| 0x3E,
-+		port->reg_bridge_apb + ATR0_PCIE_WIN0_SRCADDR_PARAM);
-+
-+	writel(0, port->reg_bridge_apb + 0x604);
-+
-+	writel((readl(port->reg_bridge_apb + PCIE_PCI_IDS_DW1) & 0xffff)
-+		| (PCI_CLASS_BRIDGE_PCI << 16),
-+		port->reg_bridge_apb + PCIE_PCI_IDS_DW1);
-+
-+	pcie_write(port, 0x00ff0100, 0x18);
-+
-+	/* Enable interrupts */
-+	writel(PCIE_ENABLE_MSI | PCIE_LOCAL_INT_ENABLE,
-+		port->reg_bridge_apb + IMASK_LOCAL);
-+
-+
-+	return 0;
-+}
-+
-+/**
-+ * microsemi_pcie_probe - Probe function
-+ * @pdev: Platform device pointer
-+ *
-+ * Return: '0' on success and error value on failure
-+ */
-+static int microsemi_pcie_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct microsemi_pcie_port *port;
-+	struct pci_bus *bus, *child;
-+	struct pci_host_bridge *bridge;
-+	int err;
-+	resource_size_t iobase = 0;
-+	LIST_HEAD(res);
-+
-+	pr_err("%s In \n", __func__);
-+	if (!dev->of_node)
-+		return -ENODEV;
-+
-+	bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
-+	if (!bridge)
-+		return -ENODEV;
-+
-+	port = pci_host_bridge_priv(bridge);
-+
-+	port->dev = dev;
-+	port->pdev = pdev;
-+
-+	err = microsemi_pcie_init_port(port);
-+	if (err) {
-+		dev_err(dev, "Pcie port initialization failed\n");
-+		return err;
-+	}
-+
-+
-+	err = microsemi_pcie_init_irq_domain(port);
-+	if (err) {
-+		dev_err(dev, "Failed creating IRQ Domain\n");
-+		return err;
-+	}
-+
-+	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
-+					       &iobase);
-+	if (err) {
-+		dev_err(dev, "Getting bridge resources failed\n");
-+		return err;
-+	}
-+
-+	err = devm_request_pci_bus_resources(dev, &res);
-+	if (err)
-+		goto error;
-+
-+
-+	list_splice_init(&res, &bridge->windows);
-+	bridge->dev.parent = dev;
-+	bridge->sysdata = port;
-+	bridge->busnr = 0;
-+	bridge->ops = &microsemi_pcie_ops;
-+	bridge->map_irq = of_irq_parse_and_map_pci;
-+	bridge->swizzle_irq = pci_common_swizzle;
-+
-+#ifdef CONFIG_PCI_MSI
-+	microsemi_pcie_msi_chip.dev = dev;
-+	bridge->msi = &microsemi_pcie_msi_chip;
-+#endif
-+	err = pci_scan_root_bus_bridge(bridge);
-+	dev_info(dev, "pci_scan_root_bus_bridge done\n");
-+	if (err < 0)
-+		goto error;
-+
-+	bus = bridge->bus;
-+
-+	pci_assign_unassigned_bus_resources(bus);
-+	list_for_each_entry(child, &bus->children, node)
-+		pcie_bus_configure_settings(child);
-+	pci_bus_add_devices(bus);
-+
-+	return 0;
-+
-+error:
-+	pci_free_resource_list(&res);
-+	return err;
-+}
-+
-+static const struct of_device_id microsemi_pcie_of_match[] = {
-+	{ .compatible = "ms-pf,axi-pcie-host", },
-+	{}
-+};
-+
-+static struct platform_driver microsemi_pcie_driver = {
-+	.driver = {
-+		.name = "microsemi-pcie",
-+		.of_match_table = microsemi_pcie_of_match,
-+		.suppress_bind_attrs = true,
-+	},
-+	.probe = microsemi_pcie_probe,
-+};
-+builtin_platform_driver(microsemi_pcie_driver);
--- 
-2.7.4
-

+ 0 - 31
recipes-kernel/linux/linux-riscv_4.19.bb

@@ -1,31 +0,0 @@
-require recipes-kernel/linux/linux-riscv-common.inc
-
-LINUX_VERSION ?= "4.19"
-
-BRANCH = "riscv-linux-4.19"
-SRCREV = "998246b5d00db61bb6449aa81a1df145e5aadf6b"
-
-SRC_URI = " \
-    git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux.git;branch=${BRANCH} \
-    file://pci.cfg \
-"
-
-# qemu uses in-tree defconfig
-# freedom-u540 uses out-of-tree defconfig
-SRC_URI_append_freedom-u540 = " file://defconfig"
-
-SRC_URI_append_qemuriscv32 = " file://32bit.cfg"
-
-SRC_URI_append_freedom-u540 = " \
-                                file://0001-risc-v-Fix-issue-ignoring-CONFIG_CMDLINE_OVERRIDE.patch \
-                                file://0001-spi-sifive-support-SiFive-SPI-controller-in-Quad-Mod.patch \
-                                file://0002-spi-nor-add-support-for-is25wp-32-64-128-256.patch \
-                                file://0003-serial-sifive-initial-driver-from-Paul-Walmsley.patch \
-                                file://0004-gemgxl-mgmt-implement-clock-switch-for-GEM-tx_clk.patch \
-                                file://0005-u54-prci-driver-for-core-U54-clocks.patch \
-                                file://0006-u54-prci-driver-for-core-U54-clocks.patch \
-                                file://0008-pwm-sifive-add-a-driver-for-SiFive-SoC-PWM.patch \
-                                file://0007-gpio-sifive-support-GPIO-on-SiFive-SoCs.patch \
-                                file://0009-RISC-V-Networking-fix-Hack.patch \
-                                file://0010-pcie-microsemi-added-support-for-the-Vera-board-root.patch \
-                              "