--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "rtl838x-spi.h"
+#include <asm/mach-rtl838x/mach-rtl83xx.h>
+
+extern struct rtl83xx_soc_info soc_info;
+
+struct rtl838x_nor {
+ struct spi_nor nor;
+ struct device *dev;
+ volatile void __iomem *base;
+ bool fourByteMode;
+ u32 chipSize;
+ uint32_t flags;
+ uint32_t io_status;
+};
+
+static uint32_t spi_prep(struct rtl838x_nor *rtl838x_nor)
+{
+ /* Needed because of MMU constraints */
+ SPI_WAIT_READY;
+ spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1
+ spi_w32w(0, SFCSR); //activate CS0,CS1
+ spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1
+
+ return (CS0 & rtl838x_nor->flags) ? (SPI_eCS0 & SPI_LEN_INIT)
+ : ((SPI_eCS1 & SPI_LEN_INIT) | SFCSR_CHIP_SEL);
+}
+
+static uint32_t rtl838x_nor_get_SR(struct rtl838x_nor *rtl838x_nor)
+{
+ uint32_t sfcsr, sfdr;
+
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = (SPINOR_OP_RDSR)<<24;
+
+ pr_debug("%s: rdid,sfcsr_val = %.8x,SFDR = %.8x\n", __func__, sfcsr, sfdr);
+ pr_debug("rdid,sfcsr = %.8x\n", sfcsr | SPI_LEN4);
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+ spi_w32_mask(0, SPI_LEN4, SFCSR);
+ SPI_WAIT_READY;
+
+ return spi_r32(SFDR);
+}
+
+static void spi_write_disable(struct rtl838x_nor *rtl838x_nor)
+{
+ uint32_t sfcsr, sfdr;
+
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = (SPINOR_OP_WRDI) << 24;
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+ pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr);
+
+ spi_prep(rtl838x_nor);
+}
+
+static void spi_write_enable(struct rtl838x_nor *rtl838x_nor)
+{
+ uint32_t sfcsr, sfdr;
+
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = (SPINOR_OP_WREN) << 24;
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+ pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr);
+
+ spi_prep(rtl838x_nor);
+}
+
+static void spi_4b_set(struct rtl838x_nor *rtl838x_nor, bool enable)
+{
+ uint32_t sfcsr, sfdr;
+
+ sfcsr = spi_prep(rtl838x_nor);
+ if (enable)
+ sfdr = (SPINOR_OP_EN4B) << 24;
+ else
+ sfdr = (SPINOR_OP_EX4B) << 24;
+
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+ pr_debug("%s: sfcsr_val = %.8x,SFDR = %.8x", __func__, sfcsr, sfdr);
+
+ spi_prep(rtl838x_nor);
+}
+
+static int rtl838x_get_addr_mode(struct rtl838x_nor *rtl838x_nor)
+{
+ int res = 3;
+ u32 reg;
+
+ sw_w32(0x3, RTL838X_INT_RW_CTRL);
+ if (!sw_r32(RTL838X_EXT_VERSION)) {
+ if (sw_r32(RTL838X_STRAP_DBG) & (1 << 29))
+ res = 4;
+ } else {
+ reg = sw_r32(RTL838X_PLL_CML_CTRL);
+ if ((reg & (1 << 30)) && (reg & (1 << 31)))
+ res = 4;
+ if ((!(reg & (1 << 30)))
+ && sw_r32(RTL838X_STRAP_DBG) & (1 << 29))
+ res = 4;
+ }
+ sw_w32(0x0, RTL838X_INT_RW_CTRL);
+ return res;
+}
+
+static int rtl8390_get_addr_mode(struct rtl838x_nor *rtl838x_nor)
+{
+ if (spi_r32(RTL8390_SOC_SPI_MMIO_CONF) & (1 << 9))
+ return 4;
+ return 3;
+}
+
+ssize_t rtl838x_do_read(struct rtl838x_nor *rtl838x_nor, loff_t from,
+ size_t length, u_char *buffer, uint8_t command)
+{
+ uint32_t sfcsr, sfdr;
+ uint32_t len = length;
+
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = command << 24;
+
+ /* Perform SPINOR_OP_READ: 1 byte command & 3 byte addr*/
+ sfcsr |= SPI_LEN4;
+ sfdr |= from;
+
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+
+ /* Read Data, 4 bytes at a time */
+ while (length >= 4) {
+ SPI_WAIT_READY;
+ *((uint32_t *) buffer) = spi_r32(SFDR);
+ buffer += 4;
+ length -= 4;
+ }
+
+ /* The rest needs to be read 1 byte a time */
+ sfcsr &= SPI_LEN_INIT|SPI_LEN1;
+ SPI_WAIT_READY;
+ spi_w32w(sfcsr, SFCSR);
+ while (length > 0) {
+ SPI_WAIT_READY;
+ *(buffer) = spi_r32(SFDR) >> 24;
+ buffer++;
+ length--;
+ }
+ return len;
+}
+
+/*
+ * Do fast read in 3 or 4 Byte addressing mode
+ */
+static ssize_t rtl838x_do_4bf_read(struct rtl838x_nor *rtl838x_nor, loff_t from,
+ size_t length, u_char *buffer, uint8_t command)
+{
+ int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2;
+ int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8;
+ uint32_t sfcsr;
+ uint32_t len = length;
+
+ pr_debug("Fast read from %llx, len %x, shift %d\n",
+ from, sfcsr_addr_len, sfdr_addr_shift);
+ sfcsr = spi_prep(rtl838x_nor);
+
+ /* Send read command */
+ spi_w32w(sfcsr | SPI_LEN1, SFCSR);
+ spi_w32w(command << 24, SFDR);
+
+ /* Send address */
+ spi_w32w(sfcsr | (sfcsr_addr_len << 28), SFCSR);
+ spi_w32w(from << sfdr_addr_shift, SFDR);
+
+ /* Dummy cycles */
+ spi_w32w(sfcsr | SPI_LEN1, SFCSR);
+ spi_w32w(0, SFDR);
+
+ /* Start reading */
+ spi_w32w(sfcsr | SPI_LEN4, SFCSR);
+
+ /* Read Data, 4 bytes at a time */
+ while (length >= 4) {
+ SPI_WAIT_READY;
+ *((uint32_t *) buffer) = spi_r32(SFDR);
+ buffer += 4;
+ length -= 4;
+ }
+
+ /* The rest needs to be read 1 byte a time */
+ sfcsr &= SPI_LEN_INIT|SPI_LEN1;
+ SPI_WAIT_READY;
+ spi_w32w(sfcsr, SFCSR);
+ while (length > 0) {
+ SPI_WAIT_READY;
+ *(buffer) = spi_r32(SFDR) >> 24;
+ buffer++;
+ length--;
+ }
+ return len;
+
+}
+
+/*
+ * Do write (Page Programming) in 3 or 4 Byte addressing mode
+ */
+static ssize_t rtl838x_do_4b_write(struct rtl838x_nor *rtl838x_nor, loff_t to,
+ size_t length, const u_char *buffer,
+ uint8_t command)
+{
+ int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2;
+ int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8;
+ uint32_t sfcsr;
+ uint32_t len = length;
+
+ pr_debug("Write to %llx, len %x, shift %d\n",
+ to, sfcsr_addr_len, sfdr_addr_shift);
+ sfcsr = spi_prep(rtl838x_nor);
+
+ /* Send write command, command IO-width is 1 (bit 25/26) */
+ spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR);
+ spi_w32w(command << 24, SFDR);
+
+ /* Send address */
+ spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR);
+ spi_w32w(to << sfdr_addr_shift, SFDR);
+
+ /* Write Data, 1 byte at a time, if we are not 4-byte aligned */
+ if (((long)buffer) % 4) {
+ spi_w32w(sfcsr | SPI_LEN1, SFCSR);
+ while (length > 0 && (((long)buffer) % 4)) {
+ SPI_WAIT_READY;
+ spi_w32(*(buffer) << 24, SFDR);
+ buffer += 1;
+ length -= 1;
+ }
+ }
+
+ /* Now we can write 4 bytes at a time */
+ SPI_WAIT_READY;
+ spi_w32w(sfcsr | SPI_LEN4, SFCSR);
+ while (length >= 4) {
+ SPI_WAIT_READY;
+ spi_w32(*((uint32_t *)buffer), SFDR);
+ buffer += 4;
+ length -= 4;
+ }
+
+ /* Final bytes might need to be written 1 byte at a time, again */
+ SPI_WAIT_READY;
+ spi_w32w(sfcsr | SPI_LEN1, SFCSR);
+ while (length > 0) {
+ SPI_WAIT_READY;
+ spi_w32(*(buffer) << 24, SFDR);
+ buffer++;
+ length--;
+ }
+ return len;
+}
+
+static ssize_t rtl838x_nor_write(struct spi_nor *nor, loff_t to, size_t len,
+ const u_char *buffer)
+{
+ int ret = 0;
+ uint32_t offset = 0;
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+ size_t l = len;
+ uint8_t cmd = SPINOR_OP_PP;
+
+ /* Do write in 4-byte mode on large Macronix chips */
+ if (rtl838x_nor->fourByteMode) {
+ cmd = SPINOR_OP_PP_4B;
+ spi_4b_set(rtl838x_nor, true);
+ }
+
+ pr_debug("In %s %8x to: %llx\n", __func__,
+ (unsigned int) rtl838x_nor, to);
+
+ while (l >= SPI_MAX_TRANSFER_SIZE) {
+ while
+ (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP);
+ do {
+ spi_write_enable(rtl838x_nor);
+ } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL));
+ ret = rtl838x_do_4b_write(rtl838x_nor, to + offset,
+ SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd);
+ l -= SPI_MAX_TRANSFER_SIZE;
+ offset += SPI_MAX_TRANSFER_SIZE;
+ }
+
+ if (l > 0) {
+ while
+ (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP);
+ do {
+ spi_write_enable(rtl838x_nor);
+ } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL));
+ ret = rtl838x_do_4b_write(rtl838x_nor, to+offset,
+ len, buffer+offset, cmd);
+ }
+
+ return len;
+}
+
+static ssize_t rtl838x_nor_read(struct spi_nor *nor, loff_t from,
+ size_t length, u_char *buffer)
+{
+ uint32_t offset = 0;
+ uint8_t cmd = SPINOR_OP_READ_FAST;
+ size_t l = length;
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+
+ /* Do fast read in 3, or 4-byte mode on large Macronix chips */
+ if (rtl838x_nor->fourByteMode) {
+ cmd = SPINOR_OP_READ_FAST_4B;
+ spi_4b_set(rtl838x_nor, true);
+ }
+
+ /* TODO: do timeout and return error */
+ pr_debug("Waiting for pending writes\n");
+ while
+ (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP);
+ do {
+ spi_write_enable(rtl838x_nor);
+ } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL));
+
+ pr_debug("cmd is %d\n", cmd);
+ pr_debug("%s: addr %.8llx to addr %.8x, cmd %.8x, size %d\n", __func__,
+ from, (u32)buffer, (u32)cmd, length);
+
+ while (l >= SPI_MAX_TRANSFER_SIZE) {
+ rtl838x_do_4bf_read(rtl838x_nor, from + offset,
+ SPI_MAX_TRANSFER_SIZE, buffer+offset, cmd);
+ l -= SPI_MAX_TRANSFER_SIZE;
+ offset += SPI_MAX_TRANSFER_SIZE;
+ }
+
+ if (l > 0)
+ rtl838x_do_4bf_read(rtl838x_nor, from + offset, l, buffer+offset, cmd);
+
+ return length;
+}
+
+static int rtl838x_erase(struct spi_nor *nor, loff_t offs)
+{
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+ int sfcsr_addr_len = rtl838x_nor->fourByteMode ? 0x3 : 0x2;
+ int sfdr_addr_shift = rtl838x_nor->fourByteMode ? 0 : 8;
+ uint32_t sfcsr;
+ uint8_t cmd = SPINOR_OP_SE;
+
+ pr_debug("Erasing sector at %llx\n", offs);
+
+ /* Do erase in 4-byte mode on large Macronix chips */
+ if (rtl838x_nor->fourByteMode) {
+ cmd = SPINOR_OP_SE_4B;
+ spi_4b_set(rtl838x_nor, true);
+ }
+ /* TODO: do timeout and return error */
+ while
+ (rtl838x_nor_get_SR(rtl838x_nor) & SPI_WIP);
+ do {
+ spi_write_enable(rtl838x_nor);
+ } while (!(rtl838x_nor_get_SR(rtl838x_nor) & SPI_WEL));
+
+ sfcsr = spi_prep(rtl838x_nor);
+
+ /* Send erase command, command IO-width is 1 (bit 25/26) */
+ spi_w32w(sfcsr | SPI_LEN1 | (0 << 25), SFCSR);
+ spi_w32w(cmd << 24, SFDR);
+
+ /* Send address */
+ spi_w32w(sfcsr | (sfcsr_addr_len << 28) | (0 << 25), SFCSR);
+ spi_w32w(offs << sfdr_addr_shift, SFDR);
+
+ return 0;
+}
+
+static int rtl838x_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+ int length = len;
+ u8 *buffer = buf;
+ uint32_t sfcsr, sfdr;
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+
+ pr_debug("In %s: opcode %x, len %x\n", __func__, opcode, len);
+
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = opcode << 24;
+
+ sfcsr |= SPI_LEN1;
+
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+
+ while (length > 0) {
+ SPI_WAIT_READY;
+ *(buffer) = spi_r32(SFDR) >> 24;
+ buffer++;
+ length--;
+ }
+
+ return len;
+}
+
+static int rtl838x_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+ uint32_t sfcsr, sfdr;
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+
+ pr_debug("In %s, opcode %x, len %x\n", __func__, opcode, len);
+ sfcsr = spi_prep(rtl838x_nor);
+ sfdr = opcode << 24;
+
+ if (len == 1) { /* SPINOR_OP_WRSR */
+ sfdr |= buf[0];
+ sfcsr |= SPI_LEN2;
+ }
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+ return 0;
+}
+
+static int spi_enter_sio(struct spi_nor *nor)
+{
+ uint32_t sfcsr, sfcr2, sfdr;
+ uint32_t ret = 0, reg = 0, size_bits;
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+
+ pr_debug("In %s\n", __func__);
+ rtl838x_nor->io_status = 0;
+ sfdr = SPI_C_RSTQIO << 24;
+ sfcsr = spi_prep(rtl838x_nor);
+
+ reg = spi_r32(SFCR2);
+ pr_debug("SFCR2: %x, size %x, rdopt: %x\n", reg, SFCR2_GETSIZE(reg),
+ (reg & SFCR2_RDOPT));
+ size_bits = rtl838x_nor->fourByteMode ? SFCR2_SIZE(0x6) : SFCR2_SIZE(0x7);
+
+ sfcr2 = SFCR2_HOLD_TILL_SFDR2 | size_bits
+ | (reg & SFCR2_RDOPT) | SFCR2_CMDIO(0)
+ | SFCR2_ADDRIO(0) | SFCR2_DUMMYCYCLE(4)
+ | SFCR2_DATAIO(0) | SFCR2_SFCMD(SPINOR_OP_READ_FAST);
+ pr_debug("SFCR2: %x, size %x\n", reg, SFCR2_GETSIZE(reg));
+
+ SPI_WAIT_READY;
+ spi_w32w(sfcr2, SFCR2);
+ spi_w32w(sfcsr, SFCSR);
+ spi_w32w(sfdr, SFDR);
+
+ spi_w32_mask(SFCR2_HOLD_TILL_SFDR2, 0, SFCR2);
+ rtl838x_nor->io_status &= ~IOSTATUS_CIO_MASK;
+ rtl838x_nor->io_status |= CIO1;
+
+ spi_prep(rtl838x_nor);
+
+ return ret;
+}
+
+int rtl838x_spi_nor_scan(struct spi_nor *nor, const char *name)
+{
+ static const struct spi_nor_hwcaps hwcaps = {
+ .mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_PP
+ | SNOR_HWCAPS_READ_FAST
+ };
+
+ struct rtl838x_nor *rtl838x_nor = nor->priv;
+
+ pr_debug("In %s\n", __func__);
+
+ spi_w32_mask(0, SFCR_EnableWBO, SFCR);
+ spi_w32_mask(0, SFCR_EnableRBO, SFCR);
+
+ rtl838x_nor->flags = CS0 | R_MODE;
+
+ spi_nor_scan(nor, NULL, &hwcaps);
+ pr_debug("------------- Got size: %llx\n", nor->mtd.size);
+
+ return 0;
+}
+
+int rtl838x_nor_init(struct rtl838x_nor *rtl838x_nor,
+ struct device_node *flash_node)
+{
+ int ret;
+ struct spi_nor *nor;
+
+ pr_info("%s called\n", __func__);
+ nor = &rtl838x_nor->nor;
+ nor->dev = rtl838x_nor->dev;
+ nor->priv = rtl838x_nor;
+ spi_nor_set_flash_node(nor, flash_node);
+
+ nor->read_reg = rtl838x_nor_read_reg;
+ nor->write_reg = rtl838x_nor_write_reg;
+ nor->read = rtl838x_nor_read;
+ nor->write = rtl838x_nor_write;
+ nor->erase = rtl838x_erase;
+ nor->mtd.name = "rtl838x_nor";
+ nor->erase_opcode = rtl838x_nor->fourByteMode ? SPINOR_OP_SE_4B
+ : SPINOR_OP_SE;
+ /* initialized with NULL */
+ ret = rtl838x_spi_nor_scan(nor, NULL);
+ if (ret)
+ return ret;
+
+ spi_enter_sio(nor);
+ spi_write_disable(rtl838x_nor);
+
+ ret = mtd_device_parse_register(&nor->mtd, NULL, NULL, NULL, 0);
+ return ret;
+}
+
+static int rtl838x_nor_drv_probe(struct platform_device *pdev)
+{
+ struct device_node *flash_np;
+ struct resource *res;
+ int ret;
+ struct rtl838x_nor *rtl838x_nor;
+ int addrMode;
+
+ pr_info("Initializing rtl838x_nor_driver\n");
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No DT found\n");
+ return -EINVAL;
+ }
+
+ rtl838x_nor = devm_kzalloc(&pdev->dev, sizeof(*rtl838x_nor), GFP_KERNEL);
+ if (!rtl838x_nor)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, rtl838x_nor);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtl838x_nor->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR((void *)rtl838x_nor->base))
+ return PTR_ERR((void *)rtl838x_nor->base);
+
+ pr_info("SPI resource base is %08x\n", (u32)rtl838x_nor->base);
+ rtl838x_nor->dev = &pdev->dev;
+
+ /* only support one attached flash */
+ flash_np = of_get_next_available_child(pdev->dev.of_node, NULL);
+ if (!flash_np) {
+ dev_err(&pdev->dev, "no SPI flash device to configure\n");
+ ret = -ENODEV;
+ goto nor_free;
+ }
+
+ /* Get the 3/4 byte address mode as configure by bootloader */
+ if (soc_info.family == RTL8390_FAMILY_ID)
+ addrMode = rtl8390_get_addr_mode(rtl838x_nor);
+ else
+ addrMode = rtl838x_get_addr_mode(rtl838x_nor);
+ pr_info("Address mode is %d bytes\n", addrMode);
+ if (addrMode == 4)
+ rtl838x_nor->fourByteMode = true;
+
+ ret = rtl838x_nor_init(rtl838x_nor, flash_np);
+
+nor_free:
+ return ret;
+}
+
+static int rtl838x_nor_drv_remove(struct platform_device *pdev)
+{
+/* struct rtl8xx_nor *rtl838x_nor = platform_get_drvdata(pdev); */
+ return 0;
+}
+
+static const struct of_device_id rtl838x_nor_of_ids[] = {
+ { .compatible = "realtek,rtl838x-nor"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtl838x_nor_of_ids);
+
+static struct platform_driver rtl838x_nor_driver = {
+ .probe = rtl838x_nor_drv_probe,
+ .remove = rtl838x_nor_drv_remove,
+ .driver = {
+ .name = "rtl838x-nor",
+ .pm = NULL,
+ .of_match_table = rtl838x_nor_of_ids,
+ },
+};
+
+module_platform_driver(rtl838x_nor_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("RTL838x SPI NOR Flash Driver");
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2009 Realtek Semiconductor Corp.
+ *
+ * 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 3 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.
+ *
+ */
+
+#ifndef _RTL838X_SPI_H
+#define _RTL838X_SPI_H
+
+
+/*
+ * Register access macros
+ */
+
+#define spi_r32(reg) __raw_readl(rtl838x_nor->base + reg)
+#define spi_w32(val, reg) __raw_writel(val, rtl838x_nor->base + reg)
+#define spi_w32_mask(clear, set, reg) \
+ spi_w32((spi_r32(reg) & ~(clear)) | (set), reg)
+
+#define SPI_WAIT_READY do { \
+ } while (!(spi_r32(SFCSR) & SFCSR_SPI_RDY))
+
+#define spi_w32w(val, reg) do { \
+ __raw_writel(val, rtl838x_nor->base + reg); \
+ SPI_WAIT_READY; \
+ } while (0)
+
+#define SFCR (0x00) /*SPI Flash Configuration Register*/
+ #define SFCR_CLK_DIV(val) ((val)<<29)
+ #define SFCR_EnableRBO (1<<28)
+ #define SFCR_EnableWBO (1<<27)
+ #define SFCR_SPI_TCS(val) ((val)<<23) /*4 bit, 1111 */
+
+#define SFCR2 (0x04) /*For memory mapped I/O */
+ #define SFCR2_SFCMD(val) ((val)<<24) /*8 bit, 1111_1111 */
+ #define SFCR2_SIZE(val) ((val)<<21) /*3 bit, 111 */
+ #define SFCR2_RDOPT (1<<20)
+ #define SFCR2_CMDIO(val) ((val)<<18) /*2 bit, 11 */
+ #define SFCR2_ADDRIO(val) ((val)<<16) /*2 bit, 11 */
+ #define SFCR2_DUMMYCYCLE(val) ((val)<<13) /*3 bit, 111 */
+ #define SFCR2_DATAIO(val) ((val)<<11) /*2 bit, 11 */
+ #define SFCR2_HOLD_TILL_SFDR2 (1<<10)
+ #define SFCR2_GETSIZE(x) (((x)&0x00E00000)>>21)
+
+#define SFCSR (0x08) /*SPI Flash Control&Status Register*/
+ #define SFCSR_SPI_CSB0 (1<<31)
+ #define SFCSR_SPI_CSB1 (1<<30)
+ #define SFCSR_LEN(val) ((val)<<28) /*2 bits*/
+ #define SFCSR_SPI_RDY (1<<27)
+ #define SFCSR_IO_WIDTH(val) ((val)<<25) /*2 bits*/
+ #define SFCSR_CHIP_SEL (1<<24)
+ #define SFCSR_CMD_BYTE(val) ((val)<<16) /*8 bit, 1111_1111 */
+
+#define SFDR (0x0C) /*SPI Flash Data Register*/
+#define SFDR2 (0x10) /*SPI Flash Data Register - for post SPI bootup setting*/
+ #define SPI_CS_INIT (SFCSR_SPI_CSB0 | SFCSR_SPI_CSB1 | SPI_LEN1)
+ #define SPI_CS0 SFCSR_SPI_CSB0
+ #define SPI_CS1 SFCSR_SPI_CSB1
+ #define SPI_eCS0 ((SFCSR_SPI_CSB1)) /*and SFCSR to active CS0*/
+ #define SPI_eCS1 ((SFCSR_SPI_CSB0)) /*and SFCSR to active CS1*/
+
+ #define SPI_WIP (1) /* Write In Progress */
+ #define SPI_WEL (1<<1) /* Write Enable Latch*/
+ #define SPI_SST_QIO_WIP (1<<7) /* SST QIO Flash Write In Progress */
+ #define SPI_LEN_INIT 0xCFFFFFFF /* and SFCSR to init */
+ #define SPI_LEN4 0x30000000 /* or SFCSR to set */
+ #define SPI_LEN3 0x20000000 /* or SFCSR to set */
+ #define SPI_LEN2 0x10000000 /* or SFCSR to set */
+ #define SPI_LEN1 0x00000000 /* or SFCSR to set */
+ #define SPI_SETLEN(val) do { \
+ SPI_REG(SFCSR) &= 0xCFFFFFFF; \
+ SPI_REG(SFCSR) |= (val-1)<<28; \
+ } while (0)
+/*
+ * SPI interface control
+ */
+#define RTL8390_SOC_SPI_MMIO_CONF (0x04)
+
+#define IOSTATUS_CIO_MASK (0x00000038)
+
+/* Chip select: bits 4-7*/
+#define CS0 (1<<4)
+#define R_MODE 0x04
+
+/* io_status */
+#define IO1 (1<<0)
+#define IO2 (1<<1)
+#define CIO1 (1<<3)
+#define CIO2 (1<<4)
+#define CMD_IO1 (1<<6)
+#define W_ADDR_IO1 ((1)<<12)
+#define R_ADDR_IO2 ((2)<<9)
+#define R_DATA_IO2 ((2)<<15)
+#define W_DATA_IO1 ((1)<<18)
+
+/* Commands */
+#define SPI_C_RSTQIO 0xFF
+
+#define SPI_MAX_TRANSFER_SIZE 256
+
+#endif /* _RTL838X_SPI_H */
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/spi-nor.h>
-
-#include "rtl83xx-spiflash.h"
-
-
-extern struct rtl83xx_soc_info soc_info;
-
-static int rtl83xx_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
-static int rtl83xx_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
-
-
-static inline u32 rtl83xx_read(struct rtl83xx_nor *rtnor, u32 reg, bool wait)
-{
- if (wait)
- while (!(__raw_readl(rtnor->base + RTL83XX_SPI_SFCSR) & RTL83XX_SPI_SFCSR_RDY))
- ;
- return __raw_readl(rtnor->base + reg);
-}
-
-static inline void rtl83xx_write(struct rtl83xx_nor *rtnor, u32 reg, u32 value, bool wait)
-{
- if (wait)
- while (!(__raw_readl(rtnor->base + RTL83XX_SPI_SFCSR) & RTL83XX_SPI_SFCSR_RDY))
- ;
- __raw_writel(value, rtnor->base + reg);
-}
-
-/*
- * Deactivate both chip selects and return base SFCSR register settings: correct
- * CS, data length 1, IO width 1.
- */
-static uint32_t spi_prep(struct rtl83xx_nor *rtnor)
-{
- uint32_t init, ret;
-
- /* Deactivate CS0 and CS1 first */
- init = (RTL83XX_SPI_SFCSR_CSB0 | RTL83XX_SPI_SFCSR_CSB1) & RTL83XX_SPI_SFCSR_LEN_MASK;
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, init, true);
-
- /* CS bitfield is active low, so reversed logic */
- if (rtnor->cs == 0)
- ret = RTL83XX_SPI_SFCSR_LEN1 | RTL83XX_SPI_SFCSR_CSB1;
- else
- ret = RTL83XX_SPI_SFCSR_LEN1 | RTL83XX_SPI_SFCSR_CSB0 | RTL83XX_SPI_SFCSR_CS;
-
- return ret;
-}
-
-static int rtl83xx_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- uint32_t sfcsr;
-
- sfcsr = spi_prep(rtnor);
- sfcsr &= RTL83XX_SPI_SFCSR_LEN_MASK | RTL83XX_SPI_SFCSR_LEN1;
-
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, opcode << 24, true);
-
- while (len > 0) {
- *(buf) = rtl83xx_read(rtnor, RTL83XX_SPI_SFDR, true) >> 24;
- buf++;
- len--;
- }
-
- return 0;
-}
-
-static int rtl83xx_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
- int len)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- uint32_t sfcsr, sfdr, len_bits;
-
- sfcsr = spi_prep(rtnor);
- sfdr = opcode << 24;
-
- if (len == 0) {
- len_bits = RTL83XX_SPI_SFCSR_LEN1;
- } else if (len == 1) {
- sfdr |= buf[0] << 16;
- len_bits = RTL83XX_SPI_SFCSR_LEN2;
- } else if (len == 2) {
- sfdr |= buf[0] << 16;
- sfdr |= buf[1] << 8;
- len_bits = RTL83XX_SPI_SFCSR_LEN3;
- } else {
- return -EINVAL;
- }
- sfcsr |= len_bits;
-
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, sfdr, true);
-
- return 0;
-}
-
-static ssize_t rtl83xx_nor_read(struct spi_nor *nor, loff_t from, size_t len,
- u_char *buf)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- uint32_t sfcsr;
- ssize_t ret = 0;
- int sfcsr_addrlen_bits, i;
-
- if (rtnor->nor.addr_width == 4) {
- sfcsr_addrlen_bits = 0x03;
- } else {
- sfcsr_addrlen_bits = 0x02;
- from <<= 8;
- }
-
- sfcsr = spi_prep(rtnor);
- sfcsr &= RTL83XX_SPI_SFCSR_LEN_MASK;
-
- /* Send read command */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN1, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, rtnor->nor.read_opcode << 24, false);
-
- /* Send address */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | (sfcsr_addrlen_bits << 28), true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, from, false);
-
- /* Dummy cycles */
- for (i = 0; i < nor->read_dummy / 8; i++) {
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, 0, false);
- }
-
- /* Read 4 bytes at a time */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN4, true);
- while (len >= 4){
- *((uint32_t*) buf) = rtl83xx_read(rtnor, RTL83XX_SPI_SFDR, false);
- buf += 4;
- len -= 4;
- ret += 4;
- }
-
- /* Read remainder 1 byte at a time */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN1, true);
- while (len > 0) {
- *(buf) = rtl83xx_read(rtnor, RTL83XX_SPI_SFDR, false) >> 24;
- buf++;
- len--;
- ret++;
- }
-
- return ret;
-}
-
-static ssize_t rtl83xx_nor_write(struct spi_nor *nor, loff_t to, size_t len,
- const u_char *buf)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- uint32_t sfcsr;
- ssize_t ret = 0;
- int sfcsr_addrlen_bits;
-
- if (rtnor->nor.addr_width == 4) {
- sfcsr_addrlen_bits = 0x03;
- } else {
- sfcsr_addrlen_bits = 0x02;
- to <<= 8;
- }
-
- sfcsr = spi_prep(rtnor);
- sfcsr &= RTL83XX_SPI_SFCSR_LEN_MASK;
-
- /* Send write command */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN1, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, nor->program_opcode << 24, false);
-
- /* Send address */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | (sfcsr_addrlen_bits << 28), true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, to, false);
-
- /* Write 4 bytes at a time */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN4, true);
- while (len >= 4) {
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, *((uint32_t*)buf), true);
- buf += 4;
- len -= 4;
- ret += 4;
- }
-
- /* Write remainder 1 byte at a time */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN1, true);
- while (len > 0) {
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, *buf << 24, true);
- buf++;
- len--;
- ret++;
- }
-
- return ret;
-}
-
-static int rtl83xx_erase(struct spi_nor *nor, loff_t offset)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- uint32_t sfcsr;
- int sfcsr_addrlen_bits;
-
- if (rtnor->nor.addr_width == 4) {
- sfcsr_addrlen_bits = 0x03;
- } else {
- sfcsr_addrlen_bits = 0x02;
- offset <<= 8;
- }
-
- sfcsr = spi_prep(rtnor);
-
- /* Send erase command */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | RTL83XX_SPI_SFCSR_LEN1, true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, nor->erase_opcode << 24, false);
-
- /* Send address */
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCSR, sfcsr | (sfcsr_addrlen_bits << 28), true);
- rtl83xx_write(rtnor, RTL83XX_SPI_SFDR, offset, false);
-
- return 0;
-}
-
-static int rtl83xx_spi_nor_scan(struct spi_nor *nor)
-{
- struct rtl83xx_nor *rtnor = nor->priv;
- static const struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST | SNOR_HWCAPS_PP
- };
- u32 sfcr;
- int ret;
-
- /* Turn on big-endian byte ordering */
- sfcr = rtl83xx_read(rtnor, RTL83XX_SPI_SFCR, true);
- sfcr |= RTL83XX_SPI_SFCR_RBO | RTL83XX_SPI_SFCR_WBO;
- rtl83xx_write(rtnor, RTL83XX_SPI_SFCR, sfcr, true);
-
- ret = spi_nor_scan(nor, NULL, &hwcaps);
-
- return ret;
-}
-
-static int rtl83xx_nor_init(struct rtl83xx_nor *rtnor,
- struct device_node *flash_node)
-{
- struct spi_nor *nor;
- int ret;
-
- nor = &rtnor->nor;
- nor->priv = rtnor;
- spi_nor_set_flash_node(nor, flash_node);
- nor->read_reg = rtl83xx_nor_read_reg,
- nor->write_reg = rtl83xx_nor_write_reg,
- nor->read = rtl83xx_nor_read,
- nor->write = rtl83xx_nor_write,
- nor->erase = rtl83xx_erase,
- nor->mtd.name = "rtl83xx-spiflash";
-
- ret = rtl83xx_spi_nor_scan(nor);
- if (ret)
- return ret;
- pr_info("SPI flash address width is %d bytes\n", nor->addr_width);
-
- ret = mtd_device_parse_register(&nor->mtd, NULL, NULL, NULL, 0);
-
- return ret;
-}
-
-static uint32_t spi_prep(struct rtl838x_nor *rtl838x_nor)
-{
- /* Needed because of MMU constraints */
- SPI_WAIT_READY;
- spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1
- spi_w32w(0, SFCSR); //activate CS0,CS1
- spi_w32w(SPI_CS_INIT, SFCSR); //deactivate CS0, CS1
-
- return (CS0 & rtl838x_nor->flags) ? (SPI_eCS0 & SPI_LEN_INIT)
- : ((SPI_eCS1 & SPI_LEN_INIT) | SFCSR_CHIP_SEL);
-}
-
-static int rtl83xx_nor_drv_probe(struct platform_device *pdev)
-{
- struct device_node *flash_np;
- struct resource *res;
- struct rtl83xx_nor *rtnor;
- int ret;
-
- if (!pdev->dev.of_node) {
- dev_err(&pdev->dev, "No DT found\n");
- return -EINVAL;
- }
-
- rtnor = devm_kzalloc(&pdev->dev, sizeof(*rtnor), GFP_KERNEL);
- if (!rtnor)
- return -ENOMEM;
- platform_set_drvdata(pdev, rtnor);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rtnor->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(rtnor->base))
- return PTR_ERR(rtnor->base);
-
- rtnor->nor.dev = &pdev->dev;
-
- /* Only support one attached flash */
- flash_np = of_get_next_available_child(pdev->dev.of_node, NULL);
- if (!flash_np) {
- dev_err(&pdev->dev, "no SPI flash device to configure\n");
- return -ENODEV;
- }
-
- /* Optional chip select, defaults to 0 */
- ret = of_property_read_u32(flash_np, "reg", &rtnor->cs);
- if (ret)
- rtnor->cs = 0;
-
- ret = rtl83xx_nor_init(rtnor, flash_np);
-
- return ret;
-}
-
-static int rtl83xx_nor_drv_remove(struct platform_device *pdev)
-{
- struct rtl83xx_nor *rtnor;
-
- rtnor = platform_get_drvdata(pdev);
- mtd_device_unregister(&rtnor->nor.mtd);
-
- return 0;
-}
-
-static const struct of_device_id rtl83xx_nor_of_ids[] = {
- { .compatible = "realtek,rtl83xx-spiflash"},
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, rtl83xx_nor_of_ids);
-
-static struct platform_driver rtl83xx_nor_driver = {
- .probe = rtl83xx_nor_drv_probe,
- .remove = rtl83xx_nor_drv_remove,
- .driver = {
- .name = "rtl83xx-spiflash",
- .pm = NULL,
- .of_match_table = rtl83xx_nor_of_ids,
- },
-};
-
-module_platform_driver(rtl83xx_nor_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("RTL83xx SPI NOR Flash Driver");