[PATCH v4 4/7] mtd: spi-nor: core: add configuration register 2 read & write support

2020-05-29 Thread Mason Yang
Configuration register 2 is to set the device operation condition like
STR or DTR mode at address offset 0 and DQS mode at address offset 0x200.

Each device has various address offset for it's specific operatoin
setting.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c | 78 ++
 drivers/mtd/spi-nor/core.h |  2 ++
 2 files changed, 80 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 3799417..fed6236 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -269,6 +269,84 @@ int spi_nor_write_disable(struct spi_nor *nor)
 }
 
 /**
+ * spi_nor_read_cr2() - Read the Configuration Register 2.
+ * @nor:   pointer to 'struct spi_nor'.
+ * @addr:  offset address to read.
+ * @cr2:   pointer to a DMA-able buffer where the value of the
+ *  Configuration Register 2  will be written.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2)
+{
+   int ret;
+   u8 cmd = nor->params->rd_reg_cmd;
+
+   if (nor->spimem) {
+   struct spi_mem_op op =
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cmd, 1),
+  SPI_MEM_OP_ADDR(4, addr, 1),
+  SPI_MEM_OP_DUMMY(4, 1),
+  SPI_MEM_OP_DATA_IN(1, cr2, 1));
+
+   spi_nor_spimem_setup_op(nor, , nor->reg_proto);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   } else {
+   if (spi_nor_protocol_is_dtr(nor->reg_proto))
+   ret = -ENOTSUPP;
+   else
+   ret = nor->controller_ops->read_reg(nor, cmd, cr2, 1);
+   }
+
+   if (ret)
+   dev_dbg(nor->dev, "error %d reading CR2\n", ret);
+
+   return ret;
+}
+
+/**
+ * spi_nor_write_cr2() - Write the Configuration Register 2.
+ * @nor:   pointer to 'struct spi_nor'.
+ * @addr:  offset address to write.
+ * @cr2:   pointer to a DMA-able buffer where the value of the
+ *  Configuratin Register 2 will be read.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2)
+{
+   int ret;
+   u8 cmd = nor->params->wr_reg_cmd;
+
+   ret = spi_nor_write_enable(nor);
+   if (ret)
+   return ret;
+
+   if (nor->spimem) {
+   struct spi_mem_op op =
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cmd, 1),
+  SPI_MEM_OP_ADDR(4, addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1, cr2, 1));
+
+   spi_nor_spimem_setup_op(nor, , nor->reg_proto);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   } else {
+   if (spi_nor_protocol_is_dtr(nor->reg_proto))
+   ret = -ENOTSUPP;
+   else
+   ret = nor->controller_ops->write_reg(nor, cmd, cr2, 1);
+   }
+
+   if (ret)
+   dev_dbg(nor->dev, "error %d write CFG Reg 2\n", ret);
+
+   return ret;
+}
+
+/**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:   pointer to 'struct spi_nor'.
  * @sr:pointer to a DMA-able buffer where the value of the
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 8de7f53..0eb07ca 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -434,6 +434,8 @@ struct spi_nor_manufacturer {
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
+int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
+int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
 int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable);
 int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
 int spi_nor_wait_till_ready(struct spi_nor *nor);
-- 
1.9.1



[PATCH v4 6/7] spi: mxic: patch for octal DTR mode support

2020-05-29 Thread Mason Yang
Driver patch for octal 8D-8D-8D mode support.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 98 +-
 1 file changed, 66 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 69491f3..a9b3817 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -280,10 +280,55 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
   mxic->regs + HC_CFG);
 }
 
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+{
+   u32 cfg =  OP_CMD_BYTES(op->cmd.nbytes) |
+  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
+  (op->cmd.dtr ? OP_CMD_DDR : 0);
+
+   if (op->addr.nbytes)
+   cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
+  OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) |
+  (op->addr.dtr ? OP_ADDR_DDR : 0);
+
+   if (op->dummy.nbytes)
+   cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
+
+   if (op->data.nbytes) {
+   cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) |
+ (op->data.dtr ? OP_DATA_DDR : 0);
+   if (op->data.dir == SPI_MEM_DATA_IN)
+   cfg |= OP_READ;
+   }
+
+   return cfg;
+}
+
+static void mxic_spi_set_hc_cfg(struct spi_device *spi, u32 flags)
+{
+   struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
+   int nio = 1;
+
+   if (spi->mode & (SPI_RX_OCTAL | SPI_TX_OCTAL))
+   nio = 8;
+   else if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
+   nio = 4;
+   else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
+   nio = 2;
+
+   writel(flags | HC_CFG_NIO(nio) |
+  HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
+  HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1),
+  mxic->regs + HC_CFG);
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
  void *rxbuf, unsigned int len)
 {
unsigned int pos = 0;
+   bool dtr_enabled;
+
+   dtr_enabled = (readl(mxic->regs + SS_CTRL(0)) & OP_DATA_DDR);
 
while (pos < len) {
unsigned int nbytes = len - pos;
@@ -302,6 +347,9 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
if (ret)
return ret;
 
+   if (dtr_enabled && len & 0x1)
+   nbytes++;
+
writel(data, mxic->regs + TXD(nbytes % 4));
 
if (rxbuf) {
@@ -319,6 +367,8 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
 
data = readl(mxic->regs + RXD);
data >>= (8 * (4 - nbytes));
+   if (dtr_enabled && len & 0x1)
+   nbytes++;
memcpy(rxbuf + pos, , nbytes);
WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
} else {
@@ -335,8 +385,8 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
 static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 const struct spi_mem_op *op)
 {
-   if (op->data.buswidth > 4 || op->addr.buswidth > 4 ||
-   op->dummy.buswidth > 4 || op->cmd.buswidth > 4)
+   if (op->data.buswidth > 8 || op->addr.buswidth > 8 ||
+   op->dummy.buswidth > 8 || op->cmd.buswidth > 8)
return false;
 
if (op->data.nbytes && op->dummy.nbytes &&
@@ -346,6 +396,9 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
if (op->addr.nbytes > 7)
return false;
 
+   if (op->cmd.buswidth == 8 && op->cmd.nbytes == 2)
+   return true;
+
return spi_mem_default_supports_op(mem, op);
 }
 
@@ -353,47 +406,27 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op)
 {
struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
-   int nio = 1, i, ret;
-   u32 ss_ctrl;
-   u8 addr[8];
+   int i, ret;
+   u8 addr[8], cmd[2];
 
ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
if (ret)
return ret;
 
-   if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
-   nio = 4;
-   else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
-   nio = 2;
+   mxic_spi_set_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN);
 
-   writel(HC_CFG_NIO(nio) |
-  HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
-  HC_CFG_SLV_ACT(mem->spi->

[PATCH v4 2/7] mtd: spi-nor: sfdp: parse xSPI Profile 1.0 table

2020-05-29 Thread Mason Yang
JESD251, xSPI profile 1.0 table supports octal DTR mode.
Extract information like the fast read opcode, dummy cycles for various
frequencies, the number of dummy cycles needed for a Read Status
Register command, the number of address bytes needed for a Read
Status Register command, read volatile register command and write
volatile register command.

According to BFPT 20th DWORD of octal maximum speed, driver get it's
specific dummy cycles from profile 1.0 table and then could update
it to device by their fixup hooks.

Since driver get octal DTR read opcode and then set read settings,
expose spi_nor_set_read_settings() in core.h.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c |   2 +-
 drivers/mtd/spi-nor/core.h |  16 +++
 drivers/mtd/spi-nor/sfdp.c | 106 +
 3 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 1ab4386..3799417 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2204,7 +2204,7 @@ static int spi_nor_check(struct spi_nor *nor)
return 0;
 }
 
-static void
+void
 spi_nor_set_read_settings(struct spi_nor_read_command *read,
  u8 num_mode_clocks,
  u8 num_wait_states,
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7a36b22..a33f807 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -191,6 +191,12 @@ struct spi_nor_locking_ops {
  * @size:  the flash memory density in bytes.
  * @page_size: the page size of the SPI NOR flash memory.
  * @octal_max_speed:   maximum operation speed of device in octal mode.
+ * @rdsr_dummy:dummy cycles needed for Read Status Register 
command.
+ * @rdsr_addr_nbytes:  dummy address bytes needed for Read Status Register
+ * command.
+ * @rd_reg_cmd:read volatile register command for xSPI device.
+ * @wr_reg_cmd:write volatile register command for xSPI device.
+ * @dummy_cycles:  dummy cycles used for various frequencies
  * @hwcaps:describes the read and page program hardware
  * capabilities.
  * @reads: read capabilities ordered by priority: the higher index
@@ -214,6 +220,11 @@ struct spi_nor_flash_parameter {
u64 size;
u32 page_size;
u16 octal_max_speed;
+   u8  rdsr_dummy;
+   u8  rdsr_addr_nbytes;
+   u8  rd_reg_cmd;
+   u8  wr_reg_cmd;
+   u8  dummy_cycles;
 
struct spi_nor_hwcaps   hwcaps;
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
@@ -420,6 +431,11 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, 
size_t len,
 
 int spi_nor_hwcaps_read2cmd(u32 hwcaps);
 u8 spi_nor_convert_3to4_read(u8 opcode);
+void spi_nor_set_read_settings(struct spi_nor_read_command *read,
+  u8 num_mode_clocks,
+  u8 num_wait_states,
+  u8 opcode,
+  enum spi_nor_protocol proto);
 void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
 enum spi_nor_protocol proto);
 
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 4d13f66..27a4de4 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -20,6 +20,7 @@
 #define SFDP_BFPT_ID   0xff00  /* Basic Flash Parameter Table */
 #define SFDP_SECTOR_MAP_ID 0xff81  /* Sector Map Table */
 #define SFDP_4BAIT_ID  0xff84  /* 4-byte Address Instruction Table */
+#define SFDP_PROFILE1_ID   0xff05  /* xSPI Profile 1.0 table. */
 
 #define SFDP_SIGNATURE 0x50444653U
 #define SFDP_JESD216_MAJOR 1
@@ -27,6 +28,27 @@
 #define SFDP_JESD216A_MINOR5
 #define SFDP_JESD216B_MINOR6
 
+/* xSPI Profile 1.0 table (from JESD216D.01). */
+#define XSPI_PF1_DWORD1_RD_CMD  GENMASK(15, 8)
+#define XSPI_PF1_DWORD1_RDSR_ADDR_BYTES BIT(29)
+#define XSPI_PF1_DWORD1_RDSR_DUMMY_CYCLES   BIT(28)
+#define XSPI_PF1_DWORD2_RD_REG_CMD  GENMASK(31, 24)
+#define XSPI_PF1_DWORD2_WR_REG_CMD  GENMASK(15, 8)
+#define XSPI_PF1_DUMMY_CYCLES_DEFAULT  20
+#define XSPI_DWORD(x)   ((x) - 1)
+#define XSPI_DWORD_MAX  5
+
+struct sfdp_xspi {
+   u32 dwords[XSPI_DWORD_MAX];
+};
+
+struct xspi_dummy_cycles {
+   u16 speed_hz;   /* Speed MHz */
+   u8 dwords;  /* Dwords index */
+   u32 mask;   /* Mask */
+   u8 shift;   /* Bit shift */
+};
+
 /* Basic Flash Parameter Table 20th DWORD, Max operation speed of device */
 struct octal_max_speed {
u8 idx

[PATCH v4 7/7] mtd: spi-nor: macronix: Add Octal 8D-8D-8D supports for Macronix mx25uw51245g

2020-05-29 Thread Mason Yang
Macronix mx25uw51245g is a SPI NOR that supports 1-1-1/8-8-8 mode.

Correct the dummy cycles to device for various frequencies
after xSPI profile 1.0 table parsed.

Enable mx25uw51245g to Octal DTR mode by executing the command sequences
to change to octal DTR mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/macronix.c | 55 ++
 1 file changed, 55 insertions(+)

diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 96735d8..6c9a24c 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -8,6 +8,57 @@
 
 #include "core.h"
 
+#define MXIC_CR2_DUMMY_SET_ADDR 0x300
+
+/* Fixup the dummy cycles to device and setup octa_dtr_enable() */
+static void mx25uw51245g_post_sfdp_fixups(struct spi_nor *nor)
+{
+   struct spi_nor_flash_parameter *params = nor->params;
+   int ret;
+   u8 rdc, wdc;
+
+   ret = spi_nor_read_cr2(nor, MXIC_CR2_DUMMY_SET_ADDR, );
+   if (ret)
+   return;
+
+   /* Refer to dummy cycle and frequency table(MHz) */
+   switch (params->dummy_cycles) {
+   case 10:/* 10 dummy cycles for 104 MHz */
+   wdc = 5;
+   break;
+   case 12:/* 12 dummy cycles for 133 MHz */
+   wdc = 4;
+   break;
+   case 16:/* 16 dummy cycles for 166 MHz */
+   wdc = 2;
+   break;
+   case 18:/* 18 dummy cycles for 173 MHz */
+   wdc = 1;
+   break;
+   case 20:/* 20 dummy cycles for 200 MHz */
+   default:
+   wdc = 0;
+   }
+
+   if (rdc != wdc)
+   spi_nor_write_cr2(nor, MXIC_CR2_DUMMY_SET_ADDR, );
+
+   if (params->cmd_seq[0].len) {
+   params->octal_dtr_enable = spi_nor_cmd_seq_octal_dtr;
+   params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+   params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
+   } else {
+   params->octal_dtr_enable = NULL;
+   params->hwcaps.mask &= ~SNOR_HWCAPS_READ_8_8_8_DTR;
+   params->hwcaps.mask &= ~SNOR_HWCAPS_PP_8_8_8_DTR;
+   }
+}
+
+static struct spi_nor_fixups mx25uw51245g_fixups = {
+   .post_sfdp = mx25uw51245g_post_sfdp_fixups,
+};
+
 static int
 mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -84,6 +135,10 @@
  SPI_NOR_QUAD_READ) },
{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
  SPI_NOR_QUAD_READ) },
+   { "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_4B_OPCODES |
+ SPI_NOR_OCTAL_DTR_READ)
+ .fixups = _fixups },
 };
 
 static void macronix_default_init(struct spi_nor *nor)
-- 
1.9.1



[PATCH v4 5/7] mtd: spi-nor: core: execute command sequences to change octal DTR mode

2020-05-29 Thread Mason Yang
Execute command sequences to change octal DTR mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c | 71 ++
 drivers/mtd/spi-nor/core.h |  1 +
 2 files changed, 72 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index fed6236..c8cd0c6 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -347,6 +347,77 @@ int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 
*cr2)
 }
 
 /**
+ * spi_nor_cmd_seq_octal_dtr() - command sequences to change to octal DTR mode
+ * @nor:   pointer to 'struct spi_nor'.
+ * @enable:enable Octal DTR.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_cmd_seq_octal_dtr(struct spi_nor *nor, bool enable)
+{
+   struct spi_nor_flash_parameter *p = nor->params;
+   struct cmd_seq_octal_dtr *cs = p->cmd_seq;
+   int i, ret;
+   struct spi_mem_op op;
+
+   if (!nor->spimem || !p->cmd_seq[0].len)
+   return -ENOTSUPP;
+
+   if (!enable)
+   return 0;
+
+   for (i = 0; i < CMD_SEQ_NUM; i++) {
+   switch (p->cmd_seq[i].len) {
+   case 1:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_NO_ADDR,
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_NO_DATA);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   case 3:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_ADDR(1, cs[i].addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1,
+  [i].data, 1));
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   case 6:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_ADDR(4, cs[i].addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1,
+  [i].data, 1));
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   default:
+   dev_err(nor->dev,
+   "Error %d sequences to Octal DTR\n",
+   p->cmd_seq[i].len);
+   break;
+   }
+   }
+
+   return ret;
+}
+
+/**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:   pointer to 'struct spi_nor'.
  * @sr:pointer to a DMA-able buffer where the value of the
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 0eb07ca..e4cf20a 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -436,6 +436,7 @@ struct spi_nor_manufacturer {
 int spi_nor_write_disable(struct spi_nor *nor);
 int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
 int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
+int spi_nor_cmd_seq_octal_dtr(struct spi_nor *nor, bool enable);
 int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable);
 int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
 int spi_nor_wait_till_ready(struct spi_nor *nor);
-- 
1.9.1



[PATCH v4 0/7] mtd: spi-nor: add xSPI Octal DTR support

2020-05-29 Thread Mason Yang
Hello,

JESD216C has defined specification for Octal 8S-8S-8S and 8D-8D-8D.
Based on JEDEC216C Basic Flash Parameter Table (BFPT) driver extract
DWORD-18: command and command extension type.
DWORD-20: Maximum operation speed of device in Octal mode.

xSPI profile 1.0 table:
DWORD-1: Read Fast command, the number of dummy cycles and address nbytes
 for Read Status Register command.
DWORD-2: Read/Write volatile Register command for CFG Reg2.
DWORD-4 and DWORD-5: dummy cycles used for various frequencies based on
maximum speed of device from BFPT 20th DWORD.

Ccommand sequences to change to octal DTR mode:
The length of each command sequence is 8 per byte for single SPI mode and
patching driver to parse and execute these sequences for octal DTR mode.

By Vignesh's comments, this patches set is dependency on Pratyush's
[1][2][5][7][8] and [10][12].

Tested on Macronix's Zynq PicoZed board with Macronix's SPI controller
(spi-mxic.c) driver patched on mx25uw51245g Octal flash.

[1] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-2-p.ya...@ti.com/
[2] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-3-p.ya...@ti.com/
[5] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-6-p.ya...@ti.com/
[7] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-8-p.ya...@ti.com/
[8] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-9-p.ya...@ti.com/
[10] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-11-p.ya...@ti.com/
[12] 
https://patchwork.ozlabs.org/project/linux-mtd/patch/20200525091544.17270-13-p.ya...@ti.com/

Summary of change log
v4:
Removed Pratyush's patches set part.

v3:
Add support command sequences to change octal DTR mode and based on
part of Pratyush's patches set.

v2: 
Parse BFPT & xSPI table for Octal 8D-8D-8D mode parameters and enable Octal
mode in spi_nor_late_init_params().
Using Macros in spi_nor_spimem_read_data, spi_nor_spimem_write_data and
so on by Vignesh comments.

v1:
Without parsing BFPT & xSPI profile 1.0 table and enter Octal 8D-8D-8D
mode directly in spi_nor_fixups hooks.


thnaks for your time and review.
best regards,
Mason

Mason Yang (7):
  mtd: spi-nor: sfdp: get octal mode maximum speed from BFPT
  mtd: spi-nor: sfdp: parse xSPI Profile 1.0 table
  mtd: spi-nor: sfdp: parse command sequences to change octal DTR mode
  mtd: spi-nor: core: add configuration register 2 read & write support
  mtd: spi-nor: core: execute command sequences to change octal DTR mode
  spi: mxic: patch for octal DTR mode support
  mtd: spi-nor: macronix: Add Octal 8D-8D-8D supports for Macronix
mx25uw51245g

 drivers/mtd/spi-nor/core.c | 151 -
 drivers/mtd/spi-nor/core.h |  41 +++
 drivers/mtd/spi-nor/macronix.c |  55 +
 drivers/mtd/spi-nor/sfdp.c | 246 +
 drivers/mtd/spi-nor/sfdp.h |   4 +
 drivers/spi/spi-mxic.c |  98 ++--
 6 files changed, 562 insertions(+), 33 deletions(-)

-- 
1.9.1



[PATCH v4 3/7] mtd: spi-nor: sfdp: parse command sequences to change octal DTR mode

2020-05-29 Thread Mason Yang
A set of simple command sequences is provided which can be executed
directly by the host controller to enable octal DTR mode.

Each command sequence is 8 per byte for single SPI mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.h |  20 +
 drivers/mtd/spi-nor/sfdp.c | 104 +
 2 files changed, 124 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index a33f807..8de7f53 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -183,6 +183,23 @@ struct spi_nor_locking_ops {
 };
 
 /**
+ * struct cmd_seq_octal_dtr - command sequences to change to octal DTR mode
+ * Each command sequence is 8 per byte for single SPI mode.
+ * @len:   commmand length of each command sequence.
+ * @opcode:command code.
+ * @addr:  address offset to device.
+ * @data:  data write to device.
+ */
+struct cmd_seq_octal_dtr {
+   u8 len;
+   u8 opcode;
+   u32 addr;
+   u8 data;
+};
+
+#define CMD_SEQ_NUM4
+
+/**
  * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
  * Includes legacy flash parameters and settings that can be overwritten
  * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
@@ -205,6 +222,7 @@ struct spi_nor_locking_ops {
  *  higher index in the array, the higher priority.
  * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
  *  Table.
+ * @cmd_seq:   command sequence to change to octal DTR mode.
  * @quad_enable:   enables SPI NOR quad mode.
  * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
  * @convert_addr:  converts an absolute address into something the flash
@@ -232,6 +250,8 @@ struct spi_nor_flash_parameter {
 
struct spi_nor_erase_maperase_map;
 
+   struct cmd_seq_octal_dtrcmd_seq[CMD_SEQ_NUM];
+
int (*quad_enable)(struct spi_nor *nor);
int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 27a4de4..ef19290 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -21,6 +21,7 @@
 #define SFDP_SECTOR_MAP_ID 0xff81  /* Sector Map Table */
 #define SFDP_4BAIT_ID  0xff84  /* 4-byte Address Instruction Table */
 #define SFDP_PROFILE1_ID   0xff05  /* xSPI Profile 1.0 table. */
+#define SFDP_CMD_TO_8DTR_ID0xff0a  /* Command Sequences to Octal DTR */
 
 #define SFDP_SIGNATURE 0x50444653U
 #define SFDP_JESD216_MAJOR 1
@@ -49,6 +50,19 @@ struct xspi_dummy_cycles {
u8 shift;   /* Bit shift */
 };
 
+#define CMD_TO_8DTR_LENGENMASK(31, 24)
+#define CMD_TO_8DTR_OPCODE GENMASK(23, 16)
+#define CMD_TO_8DTR_1_ADDR GENMASK(15, 8)
+#define CMD_TO_8DTR_1_ADDR_DATAGENMASK(7, 0)
+#define CMD_TO_8DTR_4_ADDR_MSB GENMASK(15, 0)
+#define CMD_TO_8DTR_4_ADDR_LSB GENMASK(31, 16)
+#define CMD_TO_8DTR_4_ADDR_DATAGENMASK(15, 8)
+#define CMD_TO_8DTR_SIZE_MAX   8
+
+struct sfdp_cmd_to_8dtr {
+   u32 dwords[CMD_TO_8DTR_SIZE_MAX];
+};
+
 /* Basic Flash Parameter Table 20th DWORD, Max operation speed of device */
 struct octal_max_speed {
u8 idx; /* Bits value */
@@ -1219,6 +1233,91 @@ static int spi_nor_parse_profile1(struct spi_nor *nor,
 }
 
 /**
+ * spi_nor_parse_cmd_to_8dtr() - parse the command sequence to octal DTR
+ * @nor:   pointer to a 'struct spi_nor'
+ * @param_header:  command sequence to octal DTR parameter table header.
+ * @params:pointer to the 'struct spi_nor_flash_parameter' to be.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_cmd_to_8dtr(struct spi_nor *nor,
+const struct sfdp_parameter_header *header,
+struct spi_nor_flash_parameter *params)
+{
+   struct sfdp_cmd_to_8dtr cmd_seq;
+   u32 i, j, addr;
+   size_t len;
+   int ret;
+
+   if (header->major != SFDP_JESD216_MAJOR ||
+   header->length < CMD_TO_8DTR_SIZE_MAX)
+   return -EINVAL;
+
+   len = min_t(size_t, sizeof(cmd_seq),
+   header->length * sizeof(u32));
+
+   memset(_seq, 0, sizeof(cmd_seq));
+
+   addr = SFDP_PARAM_HEADER_PTP(header);
+   ret = spi_nor_read_sfdp(nor, addr, len, _seq);
+   if (ret)
+   goto out;
+
+   /* Fix endianness of the Command Sequences to octal DTR. */
+   le32_to_cpu_array(cmd_seq.dwords, CMD_TO_8DTR_SIZE_MAX);
+
+   memset(params->cmd_seq, 0, sizeof(params->cmd_seq[CMD_SEQ_NUM]));
+
+   for (i = 0, j = 0;
+i < CMD_SEQ_NUM && j < CMD_TO_8DTR_SIZE_MAX; i++, j += 2) {
+   params->cmd_seq

[PATCH v4 1/7] mtd: spi-nor: sfdp: get octal mode maximum speed from BFPT

2020-05-29 Thread Mason Yang
Get maximum operation speed of device in octal mode from
BFPT 20th DWORD.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.h |  2 ++
 drivers/mtd/spi-nor/sfdp.c | 36 
 drivers/mtd/spi-nor/sfdp.h |  4 
 3 files changed, 42 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 6f2f6b2..7a36b22 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -190,6 +190,7 @@ struct spi_nor_locking_ops {
  *
  * @size:  the flash memory density in bytes.
  * @page_size: the page size of the SPI NOR flash memory.
+ * @octal_max_speed:   maximum operation speed of device in octal mode.
  * @hwcaps:describes the read and page program hardware
  * capabilities.
  * @reads: read capabilities ordered by priority: the higher index
@@ -212,6 +213,7 @@ struct spi_nor_locking_ops {
 struct spi_nor_flash_parameter {
u64 size;
u32 page_size;
+   u16 octal_max_speed;
 
struct spi_nor_hwcaps   hwcaps;
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index f6038d3..4d13f66 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2014, Freescale Semiconductor, Inc.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -26,6 +27,12 @@
 #define SFDP_JESD216A_MINOR5
 #define SFDP_JESD216B_MINOR6
 
+/* Basic Flash Parameter Table 20th DWORD, Max operation speed of device */
+struct octal_max_speed {
+   u8 idx; /* Bits value */
+   u16 hz; /* MHz */
+};
+
 struct sfdp_header {
u32 signature; /* Ox50444653U <=> "SFDP" */
u8  minor;
@@ -440,6 +447,22 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
u32 addr;
u16 half;
u8 erase_mask;
+   static const struct octal_max_speed max_hz[] = {
+   /* Bits value, MHz */
+   { 0x0c, 400 },
+   { 0x0b, 333 },
+   { 0x0a, 266 },
+   { 0x09, 250 },
+   { 0x08, 200 },
+   { 0x07, 166 },
+   { 0x06, 133 },
+   { 0x05, 100 },
+   { 0x04,  80 },
+   { 0x03,  66 },
+   { 0x02,  50 },
+   { 0x01,  33 },
+   };
+   u8 idx;
 
/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
@@ -604,6 +627,19 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EINVAL;
}
 
+   /* Octal mode max speed */
+   idx = max(FIELD_GET(BFPT_DWORD20_OCTAL_DTR_MAX_SPEED,
+   bfpt.dwords[BFPT_DWORD(20)]),
+ FIELD_GET(BFPT_DWORD20_OCTAL_STR_MAX_SPEED,
+   bfpt.dwords[BFPT_DWORD(20)]));
+
+   for (i = 0; i < ARRAY_SIZE(max_hz); i++) {
+   if (max_hz[i].idx == idx) {
+   params->octal_max_speed = max_hz[i].hz;
+   break;
+   }
+   }
+
return spi_nor_post_bfpt_fixups(nor, bfpt_header, , params);
 }
 
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index e0a8ded..8ae6d9a 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -83,6 +83,10 @@ struct sfdp_bfpt {
 #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD(0x4UL << 20)
 #define BFPT_DWORD15_QER_SR2_BIT1  (0x5UL << 20) /* Spansion */
 
+#define BFPT_DWORD20_OCTAL_MAX_SPEED_MASK   GENMASK(31, 16)
+#define BFPT_DWORD20_OCTAL_DTR_MAX_SPEEDGENMASK(31, 28)
+#define BFPT_DWORD20_OCTAL_STR_MAX_SPEEDGENMASK(19, 16)
+
 struct sfdp_parameter_header {
u8  id_lsb;
u8  minor;
-- 
1.9.1



[PATCH v3 14/14] mtd: spi-nor: macronix: Add Octal 8D-8D-8D supports for Macronix mx25uw51245g

2020-05-28 Thread Mason Yang
Macronix mx25uw51245g is a SPI NOR that supports 1-1-1/8-8-8 mode.

Correct the dummy cycles to device for various frequencies
after xSPI profile 1.0 table parsed.

Enable mx25uw51245g to Octal DTR mode by executing the command sequences
to change to octal DTR mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/macronix.c | 55 ++
 1 file changed, 55 insertions(+)

diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 96735d8..6c9a24c 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -8,6 +8,57 @@
 
 #include "core.h"
 
+#define MXIC_CR2_DUMMY_SET_ADDR 0x300
+
+/* Fixup the dummy cycles to device and setup octa_dtr_enable() */
+static void mx25uw51245g_post_sfdp_fixups(struct spi_nor *nor)
+{
+   struct spi_nor_flash_parameter *params = nor->params;
+   int ret;
+   u8 rdc, wdc;
+
+   ret = spi_nor_read_cr2(nor, MXIC_CR2_DUMMY_SET_ADDR, );
+   if (ret)
+   return;
+
+   /* Refer to dummy cycle and frequency table(MHz) */
+   switch (params->dummy_cycles) {
+   case 10:/* 10 dummy cycles for 104 MHz */
+   wdc = 5;
+   break;
+   case 12:/* 12 dummy cycles for 133 MHz */
+   wdc = 4;
+   break;
+   case 16:/* 16 dummy cycles for 166 MHz */
+   wdc = 2;
+   break;
+   case 18:/* 18 dummy cycles for 173 MHz */
+   wdc = 1;
+   break;
+   case 20:/* 20 dummy cycles for 200 MHz */
+   default:
+   wdc = 0;
+   }
+
+   if (rdc != wdc)
+   spi_nor_write_cr2(nor, MXIC_CR2_DUMMY_SET_ADDR, );
+
+   if (params->cmd_seq[0].len) {
+   params->octal_dtr_enable = spi_nor_cmd_seq_octal_dtr;
+   params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+   params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
+   } else {
+   params->octal_dtr_enable = NULL;
+   params->hwcaps.mask &= ~SNOR_HWCAPS_READ_8_8_8_DTR;
+   params->hwcaps.mask &= ~SNOR_HWCAPS_PP_8_8_8_DTR;
+   }
+}
+
+static struct spi_nor_fixups mx25uw51245g_fixups = {
+   .post_sfdp = mx25uw51245g_post_sfdp_fixups,
+};
+
 static int
 mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -84,6 +135,10 @@
  SPI_NOR_QUAD_READ) },
{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
  SPI_NOR_QUAD_READ) },
+   { "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_4B_OPCODES |
+ SPI_NOR_OCTAL_DTR_READ)
+ .fixups = _fixups },
 };
 
 static void macronix_default_init(struct spi_nor *nor)
-- 
1.9.1



[PATCH v3 13/14] mtd: spi-nor: core: execute command sequences to change octal DTR mode

2020-05-28 Thread Mason Yang
Execute command sequences to change octal DTR mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c | 71 ++
 drivers/mtd/spi-nor/core.h |  3 ++
 2 files changed, 74 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index a353830..caac58cd 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -425,6 +425,77 @@ int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 
*cr2)
 }
 
 /**
+ * spi_nor_cmd_seq_octal_dtr() - command sequences to change to octal DTR mode
+ * @nor:   pointer to 'struct spi_nor'.
+ * @enable:enable Octal DTR.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_cmd_seq_octal_dtr(struct spi_nor *nor, bool enable)
+{
+   struct spi_nor_flash_parameter *p = nor->params;
+   struct cmd_seq_octal_dtr *cs = p->cmd_seq;
+   int i, ret;
+   struct spi_mem_op op;
+
+   if (!nor->spimem || !p->cmd_seq[0].len)
+   return -ENOTSUPP;
+
+   if (!enable)
+   return 0;
+
+   for (i = 0; i < CMD_SEQ_OCTAL_DTR_DWORD_LEN; i++) {
+   switch (p->cmd_seq[i].len) {
+   case 1:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_NO_ADDR,
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_NO_DATA);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   case 3:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_ADDR(1, cs[i].addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1,
+  [i].data, 1));
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   case 6:
+   op = (struct spi_mem_op)
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cs[i].opcode, 1),
+  SPI_MEM_OP_ADDR(4, cs[i].addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1,
+  [i].data, 1));
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   if (ret)
+   return ret;
+   break;
+
+   default:
+   dev_err(nor->dev,
+   "Error %d sequences to Octal DTR\n",
+   p->cmd_seq[i].len);
+   break;
+   }
+   }
+
+   return ret;
+}
+
+/**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:   pointer to 'struct spi_nor'.
  * @sr:pointer to a DMA-able buffer where the value of the
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 9b0e0ba..b47bc44d 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -199,6 +199,8 @@ struct cmd_seq_octal_dtr {
u8 data;
 };
 
+#define CMD_SEQ_OCTAL_DTR_DWORD_LEN4
+
 /**
  * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
  * Includes legacy flash parameters and settings that can be overwritten
@@ -442,6 +444,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
 int spi_nor_write_disable(struct spi_nor *nor);
 int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
 int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
+int spi_nor_cmd_seq_octal_dtr(struct spi_nor *nor, bool enable);
 int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable);
 int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
 int spi_nor_wait_till_ready(struct spi_nor *nor);
-- 
1.9.1



[PATCH v3 12/14] spi: mxic: patch for octal DTR mode support

2020-05-28 Thread Mason Yang
Driver patch for octal 8D-8D-8D mode support.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 101 +
 1 file changed, 69 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 69491f3..c83c8c2 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -280,10 +280,58 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
   mxic->regs + HC_CFG);
 }
 
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+{
+   u32 cfg =  OP_CMD_BYTES(op->cmd.nbytes) |
+  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
+  (op->cmd.dtr ? OP_CMD_DDR : 0);
+
+   if (op->addr.nbytes)
+   cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
+  OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) |
+  (op->addr.dtr ? OP_ADDR_DDR : 0);
+
+   if (op->dummy.nbytes)
+   cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
+
+   if (op->data.nbytes) {
+   cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) |
+ (op->data.dtr ? OP_DATA_DDR : 0);
+   if (op->data.dir == SPI_MEM_DATA_IN) {
+   cfg |= OP_READ;
+   if (op->data.dtr == OP_DATA_DDR)
+   cfg |= OP_DQS_EN;
+   }
+   }
+
+   return cfg;
+}
+
+static void mxic_spi_set_hc_cfg(struct spi_device *spi, u32 flags)
+{
+   struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
+   int nio = 1;
+
+   if (spi->mode & (SPI_RX_OCTAL | SPI_TX_OCTAL))
+   nio = 8;
+   else if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
+   nio = 4;
+   else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
+   nio = 2;
+
+   writel(flags | HC_CFG_NIO(nio) |
+  HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
+  HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1),
+  mxic->regs + HC_CFG);
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
  void *rxbuf, unsigned int len)
 {
unsigned int pos = 0;
+   bool dtr_enabled;
+
+   dtr_enabled = (readl(mxic->regs + SS_CTRL(0)) & OP_DATA_DDR);
 
while (pos < len) {
unsigned int nbytes = len - pos;
@@ -302,6 +350,9 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
if (ret)
return ret;
 
+   if (dtr_enabled && len & 0x1)
+   nbytes++;
+
writel(data, mxic->regs + TXD(nbytes % 4));
 
if (rxbuf) {
@@ -319,6 +370,8 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
 
data = readl(mxic->regs + RXD);
data >>= (8 * (4 - nbytes));
+   if (dtr_enabled && len & 0x1)
+   nbytes++;
memcpy(rxbuf + pos, , nbytes);
WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
} else {
@@ -335,8 +388,8 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const 
void *txbuf,
 static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 const struct spi_mem_op *op)
 {
-   if (op->data.buswidth > 4 || op->addr.buswidth > 4 ||
-   op->dummy.buswidth > 4 || op->cmd.buswidth > 4)
+   if (op->data.buswidth > 8 || op->addr.buswidth > 8 ||
+   op->dummy.buswidth > 8 || op->cmd.buswidth > 8)
return false;
 
if (op->data.nbytes && op->dummy.nbytes &&
@@ -346,6 +399,9 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
if (op->addr.nbytes > 7)
return false;
 
+   if (op->cmd.buswidth == 8 && op->cmd.nbytes == 2)
+   return true;
+
return spi_mem_default_supports_op(mem, op);
 }
 
@@ -353,47 +409,27 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op)
 {
struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
-   int nio = 1, i, ret;
-   u32 ss_ctrl;
-   u8 addr[8];
+   int i, ret;
+   u8 addr[8], cmd[2];
 
ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
if (ret)
return ret;
 
-   if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
-   nio = 4;
-   else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
-   nio = 2;
+   mxic_spi_set_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN);
 
-   writel(HC_CFG_NIO(nio) |
-  

[PATCH v3 10/14] mtd: spi-nor: core: use dummy cycle and address width info from SFDP

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

The xSPI Profile 1.0 table specifies how many dummy cycles and address
bytes are needed for the Read Status Register command in octal DTR mode.
Use that information to send the correct Read SR command.

Signed-off-by: Pratyush Yadav 
---
 drivers/mtd/spi-nor/core.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 117d117..cbfdf544 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -435,6 +435,8 @@ int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 
*cr2)
 static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
 {
int ret;
+   u8 addr_bytes = nor->params->rdsr_addr_nbytes;
+   u8 dummy = nor->params->rdsr_dummy;
 
if (nor->spimem) {
struct spi_mem_op op =
@@ -443,10 +445,19 @@ static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
   SPI_MEM_OP_NO_DUMMY,
   SPI_MEM_OP_DATA_IN(1, sr, 1));
 
+   if (spi_nor_protocol_is_dtr(nor->reg_proto)) {
+   op.addr.nbytes = addr_bytes;
+   op.addr.val = 0;
+   op.dummy.nbytes = dummy;
+   }
+
ret = spi_mem_exec_op(nor->spimem, );
} else {
-   ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR,
-   sr, 1);
+   if (spi_nor_protocol_is_dtr(nor->reg_proto))
+   ret = -ENOTSUPP;
+   else
+   ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR,
+   sr, 1);
}
 
if (ret)
@@ -466,6 +477,8 @@ static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
 static int spi_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
 {
int ret;
+   u8 addr_bytes = nor->params->rdsr_addr_nbytes;
+   u8 dummy = nor->params->rdsr_dummy;
 
if (nor->spimem) {
struct spi_mem_op op =
@@ -474,6 +487,12 @@ static int spi_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
   SPI_MEM_OP_NO_DUMMY,
   SPI_MEM_OP_DATA_IN(1, fsr, 1));
 
+   if (spi_nor_protocol_is_dtr(nor->reg_proto)) {
+   op.addr.nbytes = addr_bytes;
+   op.addr.val = 0;
+   op.dummy.nbytes = dummy;
+   }
+
spi_nor_spimem_setup_op(nor, , nor->reg_proto);
 
ret = spi_mem_exec_op(nor->spimem, );
-- 
1.9.1



[PATCH v3 11/14] mtd: spi-nor: core: enable octal DTR mode when possible

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

Allow flashes to specify a hook to enable octal DTR mode. Use this hook
whenever possible to get optimal transfer speeds.

Signed-off-by: Pratyush Yadav 
---
 drivers/mtd/spi-nor/core.c | 35 +++
 drivers/mtd/spi-nor/core.h |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index cbfdf544..a353830 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3162,6 +3162,35 @@ static int spi_nor_init_params(struct spi_nor *nor)
return 0;
 }
 
+/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
+ * @nor: pointer to a 'struct spi_nor'
+ * @enable:  whether to enable or disable Octal DTR
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+   int ret;
+
+   if (!nor->params->octal_dtr_enable)
+   return 0;
+
+   if (!(nor->read_proto == SNOR_PROTO_8_8_8_DTR &&
+ nor->write_proto == SNOR_PROTO_8_8_8_DTR))
+   return 0;
+
+   ret = nor->params->octal_dtr_enable(nor, enable);
+   if (ret)
+   return ret;
+
+   if (enable)
+   nor->reg_proto = SNOR_PROTO_8_8_8_DTR;
+   else
+   nor->reg_proto = SNOR_PROTO_1_1_1;
+
+   return 0;
+}
+
 /**
  * spi_nor_quad_enable() - enable Quad I/O if needed.
  * @nor:pointer to a 'struct spi_nor'
@@ -3201,6 +3230,12 @@ static int spi_nor_init(struct spi_nor *nor)
 {
int err;
 
+   err = spi_nor_octal_dtr_enable(nor, true);
+   if (err) {
+   dev_dbg(nor->dev, "octal mode not supported\n");
+   return err;
+   }
+
err = spi_nor_quad_enable(nor);
if (err) {
dev_dbg(nor->dev, "quad mode not supported\n");
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 91bc69a..9b0e0ba 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -223,6 +223,7 @@ struct cmd_seq_octal_dtr {
  * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
  *  Table.
  * @cmd_seq:   command sequence to change to octal DTR mode.
+ * @octal_dtr_enable:  enables SPI NOR octal DTR mode.
  * @quad_enable:   enables SPI NOR quad mode.
  * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
  * @convert_addr:  converts an absolute address into something the flash
@@ -252,6 +253,7 @@ struct spi_nor_flash_parameter {
 
struct cmd_seq_octal_dtrcmd_seq[4];
 
+   int (*octal_dtr_enable)(struct spi_nor *nor, bool enable);
int (*quad_enable)(struct spi_nor *nor);
int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
-- 
1.9.1



[PATCH v3 08/14] mtd: spi-nor: sfdp: parse command sequences to change octal DTR mode

2020-05-28 Thread Mason Yang
A set of simple command sequences is provided which can be executed
directly by the host controller to enable octal DTR mode.

Each command sequence is 8 per byte for single SPI mode.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.h |  18 
 drivers/mtd/spi-nor/sfdp.c | 103 +
 2 files changed, 121 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 837f5e9..101726c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -185,6 +185,21 @@ struct spi_nor_locking_ops {
 };
 
 /**
+ * struct cmd_seq_octal_dtr - command sequences to change to octal DTR mode
+ * Each command sequence is 8 per byte for single SPI mode.
+ * @len:   commmand length of each command sequence.
+ * @opcode:command code.
+ * @addr:  address offset to device.
+ * @data:  data write to device.
+ */
+struct cmd_seq_octal_dtr {
+   u8 len;
+   u8 opcode;
+   u32 addr;
+   u8 data;
+};
+
+/**
  * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
  * Includes legacy flash parameters and settings that can be overwritten
  * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
@@ -207,6 +222,7 @@ struct spi_nor_locking_ops {
  *  higher index in the array, the higher priority.
  * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
  *  Table.
+ * @cmd_seq:   command sequence to change to octal DTR mode.
  * @quad_enable:   enables SPI NOR quad mode.
  * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
  * @convert_addr:  converts an absolute address into something the flash
@@ -234,6 +250,8 @@ struct spi_nor_flash_parameter {
 
struct spi_nor_erase_maperase_map;
 
+   struct cmd_seq_octal_dtrcmd_seq[4];
+
int (*quad_enable)(struct spi_nor *nor);
int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 550422b..fb5f9f3 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -21,6 +21,7 @@
 #define SFDP_SECTOR_MAP_ID 0xff81  /* Sector Map Table */
 #define SFDP_4BAIT_ID  0xff84  /* 4-byte Address Instruction Table */
 #define SFDP_PROFILE1_ID   0xff05  /* xSPI Profile 1.0 table. */
+#define SFDP_CMD_TO_8DTR_ID0xff0a  /* Command Sequence to Octal DDR */
 
 #define SFDP_SIGNATURE 0x50444653U
 #define SFDP_JESD216_MAJOR 1
@@ -55,6 +56,19 @@ struct octal_max_speed {
u16 hz; /* MHz */
 };
 
+#define CMD_TO_8DTR_LENGENMASK(31, 24)
+#define CMD_TO_8DTR_OPCODE GENMASK(23, 16)
+#define CMD_TO_8DTR_1_ADDR GENMASK(15, 8)
+#define CMD_TO_8DTR_1_ADDR_DATAGENMASK(7, 0)
+#define CMD_TO_8DTR_4_ADDR_MSB GENMASK(15, 0)
+#define CMD_TO_8DTR_4_ADDR_LSB GENMASK(31, 16)
+#define CMD_TO_8DTR_4_ADDR_DATAGENMASK(15, 8)
+#define CMD_TO_8DTR_SIZE_MAX   8
+
+struct sfdp_cmd_to_8dtr {
+   u32 dwords[CMD_TO_8DTR_SIZE_MAX];
+};
+
 struct sfdp_header {
u32 signature; /* Ox50444653U <=> "SFDP" */
u8  minor;
@@ -1248,6 +1262,90 @@ static int spi_nor_parse_profile1(struct spi_nor *nor,
 }
 
 /**
+ * spi_nor_parse_cmd_to_8dtr() - parse the command sequence to octal DTR
+ * @nor:   pointer to a 'struct spi_nor'
+ * @param_header:  command sequence to octal DTR parameter table header.
+ * @params:pointer to the 'struct spi_nor_flash_parameter' to be.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_cmd_to_8dtr(struct spi_nor *nor,
+const struct sfdp_parameter_header *header,
+struct spi_nor_flash_parameter *params)
+{
+   struct sfdp_cmd_to_8dtr cmd_seq;
+   u32 i, j, addr;
+   size_t len;
+   int ret;
+
+   if (header->major != SFDP_JESD216_MAJOR ||
+   header->length < CMD_TO_8DTR_SIZE_MAX)
+   return -EINVAL;
+
+   len = min_t(size_t, sizeof(cmd_seq),
+   header->length * sizeof(u32));
+
+   memset(_seq, 0, sizeof(cmd_seq));
+
+   addr = SFDP_PARAM_HEADER_PTP(header);
+   ret = spi_nor_read_sfdp(nor, addr, len, _seq);
+   if (ret)
+   goto out;
+
+   /* Fix endianness of the Command Sequences to octal DTR. */
+   le32_to_cpu_array(cmd_seq.dwords, CMD_TO_8DTR_SIZE_MAX);
+
+   memset(params->cmd_seq, 0, sizeof(params->cmd_seq[4]));
+
+   for (i = 0, j = 0; i < 4 && j < 8; i++, j += 2) {
+   params->cmd_seq[i].len = FIELD_GET(CMD_TO_8DTR_LEN,
+  cmd_seq.dwor

[PATCH v3 09/14] mtd: spi-nor: core: add configuration register 2 read & write support

2020-05-28 Thread Mason Yang
Configuration register 2 is to set the device operation condition like
STR or DTR mode at address offset 0 and DQS mode at address offset 0x200.

Each device has various address offset for it's specific operatoin
setting.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c | 78 ++
 drivers/mtd/spi-nor/core.h |  2 ++
 2 files changed, 80 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 642e3c0..117d117 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -347,6 +347,84 @@ int spi_nor_write_disable(struct spi_nor *nor)
 }
 
 /**
+ * spi_nor_read_cr2() - Read the Configuration Register 2.
+ * @nor:   pointer to 'struct spi_nor'.
+ * @addr:  offset address to read.
+ * @cr2:   pointer to a DMA-able buffer where the value of the
+ *  Configuration Register 2  will be written.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2)
+{
+   int ret;
+   u8 cmd = nor->params->rd_reg_cmd;
+
+   if (nor->spimem) {
+   struct spi_mem_op op =
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cmd, 1),
+  SPI_MEM_OP_ADDR(4, addr, 1),
+  SPI_MEM_OP_DUMMY(4, 1),
+  SPI_MEM_OP_DATA_IN(1, cr2, 1));
+
+   spi_nor_spimem_setup_op(nor, , nor->reg_proto);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   } else {
+   if (spi_nor_protocol_is_dtr(nor->reg_proto))
+   ret = -ENOTSUPP;
+   else
+   ret = nor->controller_ops->read_reg(nor, cmd, cr2, 1);
+   }
+
+   if (ret)
+   dev_dbg(nor->dev, "error %d reading CR2\n", ret);
+
+   return ret;
+}
+
+/**
+ * spi_nor_write_cr2() - Write the Configuration Register 2.
+ * @nor:   pointer to 'struct spi_nor'.
+ * @addr:  offset address to write.
+ * @cr2:   pointer to a DMA-able buffer where the value of the
+ *  Configuratin Register 2 will be read.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2)
+{
+   int ret;
+   u8 cmd = nor->params->wr_reg_cmd;
+
+   ret = spi_nor_write_enable(nor);
+   if (ret)
+   return ret;
+
+   if (nor->spimem) {
+   struct spi_mem_op op =
+   SPI_MEM_OP(SPI_MEM_OP_CMD(cmd, 1),
+  SPI_MEM_OP_ADDR(4, addr, 1),
+  SPI_MEM_OP_NO_DUMMY,
+  SPI_MEM_OP_DATA_OUT(1, cr2, 1));
+
+   spi_nor_spimem_setup_op(nor, , nor->reg_proto);
+
+   ret = spi_mem_exec_op(nor->spimem, );
+   } else {
+   if (spi_nor_protocol_is_dtr(nor->reg_proto))
+   ret = -ENOTSUPP;
+   else
+   ret = nor->controller_ops->write_reg(nor, cmd, cr2, 1);
+   }
+
+   if (ret)
+   dev_dbg(nor->dev, "error %d write CFG Reg 2\n", ret);
+
+   return ret;
+}
+
+/**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:   pointer to 'struct spi_nor'.
  * @sr:pointer to a DMA-able buffer where the value of the
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 101726c..91bc69a 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -438,6 +438,8 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
 const enum spi_nor_protocol proto);
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
+int spi_nor_read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
+int spi_nor_write_cr2(struct spi_nor *nor, u32 addr, u8 *cr2);
 int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable);
 int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
 int spi_nor_wait_till_ready(struct spi_nor *nor);
-- 
1.9.1



[PATCH v3 04/14] mtd: spi-nor: sfdp: prepare BFPT parsing for JESD216 rev D

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

JESD216 rev D makes BFPT 20 DWORDs. Update the BFPT size define to
reflect that.

The check for rev A or later compared the BFPT header length with the
maximum BFPT length, BFPT_DWORD_MAX. Since BFPT_DWORD_MAX was 16, and so
was the BFPT length for both rev A and B, this check worked fine. But
now, since BFPT_DWORD_MAX is 20, it means this check will also stop BFPT
parsing for rev A or B, since their length is 16.

So, instead check for BFPT_DWORD_MAX_JESD216 to stop BFPT parsing for
the first JESD216 version, and check for BFPT_DWORD_MAX_JESD216B for the
next two versions.

Signed-off-by: Pratyush Yadav 
---
 drivers/mtd/spi-nor/sfdp.c | 7 ++-
 drivers/mtd/spi-nor/sfdp.h | 5 +++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index f917631..c289395 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -548,7 +548,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
  SNOR_ERASE_TYPE_MASK;
 
/* Stop here if not JESD216 rev A or later. */
-   if (bfpt_header->length < BFPT_DWORD_MAX)
+   if (bfpt_header->length == BFPT_DWORD_MAX_JESD216)
return spi_nor_post_bfpt_fixups(nor, bfpt_header, ,
params);
 
@@ -604,6 +604,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EINVAL;
}
 
+   /* Stop here if JESD216 rev B. */
+   if (bfpt_header->length == BFPT_DWORD_MAX_JESD216B)
+   return spi_nor_post_bfpt_fixups(nor, bfpt_header, ,
+   params);
+
return spi_nor_post_bfpt_fixups(nor, bfpt_header, , params);
 }
 
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index e0a8ded..f8198af 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -10,11 +10,11 @@
 /* Basic Flash Parameter Table */
 
 /*
- * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
+ * JESD216 rev D defines a Basic Flash Parameter Table of 20 DWORDs.
  * They are indexed from 1 but C arrays are indexed from 0.
  */
 #define BFPT_DWORD(i)  ((i) - 1)
-#define BFPT_DWORD_MAX 16
+#define BFPT_DWORD_MAX 20
 
 struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
@@ -22,6 +22,7 @@ struct sfdp_bfpt {
 
 /* The first version of JESD216 defined only 9 DWORDs. */
 #define BFPT_DWORD_MAX_JESD216 9
+#define BFPT_DWORD_MAX_JESD216B16
 
 /* 1st DWORD. */
 #define BFPT_DWORD1_FAST_READ_1_1_2BIT(16)
-- 
1.9.1



[PATCH v3 05/14] mtd: spi-nor: sfdp: get command opcode extension type from BFPT

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

Some devices in DTR mode expect an extra command byte called the
extension. The extension can either be same as the opcode, bitwise
inverse of the opcode, or another additional byte forming a 16-byte
opcode. Get the extension type from the BFPT. For now, only flashes with
"repeat" and "inverse" extensions are supported.

Signed-off-by: Pratyush Yadav 
---
 drivers/mtd/spi-nor/sfdp.c | 17 +
 drivers/mtd/spi-nor/sfdp.h |  6 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index c289395..3685a3a 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -608,6 +608,23 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
if (bfpt_header->length == BFPT_DWORD_MAX_JESD216B)
return spi_nor_post_bfpt_fixups(nor, bfpt_header, ,
params);
+   /* 8D-8D-8D command extension. */
+   switch (bfpt.dwords[BFPT_DWORD(18)] & BFPT_DWORD18_CMD_EXT_MASK) {
+   case BFPT_DWORD18_CMD_EXT_REP:
+   nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+   break;
+
+   case BFPT_DWORD18_CMD_EXT_INV:
+   nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
+   break;
+
+   case BFPT_DWORD18_CMD_EXT_RES:
+   return -EINVAL;
+
+   case BFPT_DWORD18_CMD_EXT_16B:
+   dev_err(nor->dev, "16-bit opcodes not supported\n");
+   return -ENOTSUPP;
+   }
 
return spi_nor_post_bfpt_fixups(nor, bfpt_header, , params);
 }
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index f8198af..e15e307 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -84,6 +84,12 @@ struct sfdp_bfpt {
 #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD(0x4UL << 20)
 #define BFPT_DWORD15_QER_SR2_BIT1  (0x5UL << 20) /* Spansion */
 
+#define BFPT_DWORD18_CMD_EXT_MASK  GENMASK(30, 29)
+#define BFPT_DWORD18_CMD_EXT_REP   (0x0UL << 29) /* Repeat */
+#define BFPT_DWORD18_CMD_EXT_INV   (0x1UL << 29) /* Invert */
+#define BFPT_DWORD18_CMD_EXT_RES   (0x2UL << 29) /* Reserved */
+#define BFPT_DWORD18_CMD_EXT_16B   (0x3UL << 29) /* 16-bit opcode 
*/
+
 struct sfdp_parameter_header {
u8  id_lsb;
u8  minor;
-- 
1.9.1



[PATCH v3 02/14] spi: spi-mem: allow specifying a command's extension

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

In xSPI mode, flashes expect 2-byte opcodes. The second byte is called
the "command extension". There can be 3 types of extensions in xSPI:
repeat, invert, and hex. When the extension type is "repeat", the same
opcode is sent twice. When it is "invert", the second byte is the
inverse of the opcode. When it is "hex" an additional opcode byte based
is sent with the command whose value can be anything.

So, make opcode a 16-bit value and add a 'nbytes', similar to how
multiple address widths are handled.

Some places use sizeof(op->cmd.opcode). Replace them with op->cmd.nbytes

The spi-mxic and spi-zynq-qspi drivers directly use op->cmd.opcode as a
buffer. Now that opcode is a 2-byte field, this can result in different
behaviour depending on if the machine is little endian or big endian.
Extract the opcode in a local 1-byte variable and use that as the buffer
instead. Both these drivers would reject multi-byte opcodes in their
supports_op() hook anyway, so we only need to worry about single-byte
opcodes for now.

The above two changes are put in this commit to keep the series
bisectable.

Signed-off-by: Pratyush Yadav 
---
 drivers/spi/spi-mem.c   | 13 +++--
 drivers/spi/spi-mtk-nor.c   |  4 ++--
 drivers/spi/spi-zynq-qspi.c | 11 ++-
 include/linux/spi/spi-mem.h |  6 +-
 4 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index d8905e0..a0366ff 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -157,6 +157,9 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
 
+   if (op->cmd.nbytes != 1)
+   return false;
+
return true;
 }
 EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
@@ -171,7 +174,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth)
 
 static int spi_mem_check_op(const struct spi_mem_op *op)
 {
-   if (!op->cmd.buswidth)
+   if (!op->cmd.buswidth || !op->cmd.nbytes)
return -EINVAL;
 
if ((op->addr.nbytes && !op->addr.buswidth) ||
@@ -307,8 +310,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct 
spi_mem_op *op)
return ret;
}
 
-   tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
-op->dummy.nbytes;
+   tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
 
/*
 * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
@@ -323,7 +325,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct 
spi_mem_op *op)
 
tmpbuf[0] = op->cmd.opcode;
xfers[xferpos].tx_buf = tmpbuf;
-   xfers[xferpos].len = sizeof(op->cmd.opcode);
+   xfers[xferpos].len = op->cmd.nbytes;
xfers[xferpos].tx_nbits = op->cmd.buswidth;
spi_message_add_tail([xferpos], );
xferpos++;
@@ -425,8 +427,7 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct 
spi_mem_op *op)
return ctlr->mem_ops->adjust_op_size(mem, op);
 
if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) {
-   len = sizeof(op->cmd.opcode) + op->addr.nbytes +
- op->dummy.nbytes;
+   len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
 
if (len > spi_max_transfer_size(mem->spi))
return -EINVAL;
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index c15a991..d1f4cfc 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -195,7 +195,7 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, 
struct spi_mem_op *op)
}
}
 
-   len = MTK_NOR_PRG_MAX_SIZE - sizeof(op->cmd.opcode) - op->addr.nbytes -
+   len = MTK_NOR_PRG_MAX_SIZE - op->cmd.nbytes - op->addr.nbytes -
  op->dummy.nbytes;
if (op->data.nbytes > len)
op->data.nbytes = len;
@@ -219,7 +219,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
   (op->dummy.buswidth == 0) &&
   (op->data.buswidth == 1);
}
-   len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+   len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
if ((len > MTK_NOR_PRG_MAX_SIZE) ||
((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE)))
return false;
diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c
index 1764115..bbf3d90 100644
--- a/drivers/spi/spi-zynq-qspi.c
+++ b/drivers/spi/spi-zynq-qspi.c
@@ -527,20 +527,21 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
int err = 0, i;
u8 *tmpbuf;
+   u8 opcode = op->cmd.opcode;
 
dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
-   op->cmd.opcode, op->cmd.buswidth, 

[PATCH v3 01/14] spi: spi-mem: allow specifying whether an op is DTR or not

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

Each phase is given a separate 'dtr' field so mixed protocols like
4S-4D-4D can be supported.

Signed-off-by: Pratyush Yadav 
---
 drivers/spi/spi-mem.c   | 3 +++
 include/linux/spi/spi-mem.h | 8 
 2 files changed, 11 insertions(+)

diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index adaa0c4..d8905e0 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -154,6 +154,9 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
   op->data.dir == SPI_MEM_DATA_OUT))
return false;
 
+   if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
+   return false;
+
return true;
 }
 EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
index af9ff2f..e3dcb95 100644
--- a/include/linux/spi/spi-mem.h
+++ b/include/linux/spi/spi-mem.h
@@ -71,9 +71,11 @@ enum spi_mem_data_dir {
  * struct spi_mem_op - describes a SPI memory operation
  * @cmd.buswidth: number of IO lines used to transmit the command
  * @cmd.opcode: operation opcode
+ * @cmd.dtr: whether the command opcode should be sent in DTR mode or not
  * @addr.nbytes: number of address bytes to send. Can be zero if the operation
  *  does not need to send an address
  * @addr.buswidth: number of IO lines used to transmit the address cycles
+ * @addr.dtr: whether the address should be sent in DTR mode or not
  * @addr.val: address value. This value is always sent MSB first on the bus.
  *   Note that only @addr.nbytes are taken into account in this
  *   address value, so users should make sure the value fits in the
@@ -81,7 +83,9 @@ enum spi_mem_data_dir {
  * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can
  *   be zero if the operation does not require dummy bytes
  * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
+ * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not
  * @data.buswidth: number of IO lanes used to send/receive the data
+ * @data.dtr: whether the data should be sent in DTR mode or not
  * @data.dir: direction of the transfer
  * @data.nbytes: number of data bytes to send/receive. Can be zero if the
  *  operation does not involve transferring data
@@ -91,22 +95,26 @@ enum spi_mem_data_dir {
 struct spi_mem_op {
struct {
u8 buswidth;
+   u8 dtr : 1;
u8 opcode;
} cmd;
 
struct {
u8 nbytes;
u8 buswidth;
+   u8 dtr : 1;
u64 val;
} addr;
 
struct {
u8 nbytes;
u8 buswidth;
+   u8 dtr : 1;
} dummy;
 
struct {
u8 buswidth;
+   u8 dtr : 1;
enum spi_mem_data_dir dir;
unsigned int nbytes;
union {
-- 
1.9.1



[PATCH v3 03/14] mtd: spi-nor: add support for DTR protocol

2020-05-28 Thread Mason Yang
From: Pratyush Yadav 

Double Transfer Rate (DTR) is SPI protocol in which data is transferred
on each clock edge as opposed to on each clock cycle. Make
framework-level changes to allow supporting flashes in DTR mode.

Right now, mixed DTR modes are not supported. So, for example a mode
like 4S-4D-4D will not work. All phases need to be either DTR or STR.

Signed-off-by: Pratyush Yadav 
---
 drivers/mtd/spi-nor/core.c  | 305 +++-
 drivers/mtd/spi-nor/core.h  |   6 +
 drivers/mtd/spi-nor/sfdp.c  |   9 +-
 include/linux/mtd/spi-nor.h |  51 ++--
 4 files changed, 295 insertions(+), 76 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 1ab4386..388e695 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -41,6 +41,76 @@
 #define SPI_NOR_MAX_ADDR_WIDTH 4
 
 /**
+ * spi_nor_get_cmd_ext() - Get the command opcode extension based on the
+ *extension type.
+ * @nor:   pointer to a 'struct spi_nor'
+ * @op:pointer to the 'struct spi_mem_op' whose 
properties
+ * need to be initialized.
+ *
+ * Right now, only "repeat" and "invert" are supported.
+ *
+ * Return: The opcode extension.
+ */
+static u8 spi_nor_get_cmd_ext(const struct spi_nor *nor,
+ const struct spi_mem_op *op)
+{
+   switch (nor->cmd_ext_type) {
+   case SPI_NOR_EXT_INVERT:
+   return ~op->cmd.opcode;
+
+   case SPI_NOR_EXT_REPEAT:
+   return op->cmd.opcode;
+
+   default:
+   dev_err(nor->dev, "Unknown command extension type\n");
+   return 0;
+   }
+}
+
+/**
+ * spi_nor_spimem_setup_op() - Set up common properties of a spi-mem op.
+ * @nor:   pointer to a 'struct spi_nor'
+ * @op:pointer to the 'struct spi_mem_op' whose 
properties
+ * need to be initialized.
+ * @proto: the protocol from which the properties need to be set.
+ */
+void spi_nor_spimem_setup_op(const struct spi_nor *nor,
+struct spi_mem_op *op,
+const enum spi_nor_protocol proto)
+{
+   u8 ext;
+
+   op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(proto);
+
+   if (op->addr.nbytes)
+   op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
+
+   if (op->dummy.nbytes)
+   op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
+
+   if (op->data.nbytes)
+   op->data.buswidth = spi_nor_get_protocol_data_nbits(proto);
+
+   if (spi_nor_protocol_is_dtr(proto)) {
+   /*
+* spi-mem supports mixed DTR modes, but right now we can only
+* have all phases either DTR or STR. IOW, spi-mem can have
+* something like 4S-4D-4D, but spi-nor can't. So, set all 4
+* phases to either DTR or STR.
+*/
+   op->cmd.dtr = op->addr.dtr = op->dummy.dtr
+  = op->data.dtr = true;
+
+   /* 2 bytes per clock cycle in DTR mode. */
+   op->dummy.nbytes *= 2;
+
+   ext = spi_nor_get_cmd_ext(nor, op);
+   op->cmd.opcode = (op->cmd.opcode << 8) | ext;
+   op->cmd.nbytes = 2;
+   }
+}
+
+/**
  * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data
  *   transfer
  * @nor:pointer to 'struct spi_nor'
@@ -104,14 +174,12 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor 
*nor, loff_t from,
ssize_t nbytes;
int error;
 
-   /* get transfer protocols. */
-   op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
-   op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
-   op.dummy.buswidth = op.addr.buswidth;
-   op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
+   spi_nor_spimem_setup_op(nor, , nor->read_proto);
 
/* convert the dummy cycles to the number of bytes */
op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
+   if (spi_nor_protocol_is_dtr(nor->read_proto))
+   op.dummy.nbytes *= 2;
 
usebouncebuf = spi_nor_spimem_bounce(nor, );
 
@@ -169,13 +237,11 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor 
*nor, loff_t to,
ssize_t nbytes;
int error;
 
-   op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
-   op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
-   op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
-
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
op.addr.nbytes = 0;
 
+   spi_nor_spimem_setup_op(nor, , nor->write_proto);
+
if (spi_nor_spimem_bounce(nor, ))
memcpy(nor->bouncebuf, buf, 

[PATCH v3 06/14] mtd: spi-nor: sfdp: get octal mode maximum speed from BFPT

2020-05-28 Thread Mason Yang
Get maximum operation speed of device in octal mode from
BFPT 20th DWORD.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.h |  2 ++
 drivers/mtd/spi-nor/sfdp.c | 36 
 drivers/mtd/spi-nor/sfdp.h |  4 
 3 files changed, 42 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index de1e391..f644ed1 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -192,6 +192,7 @@ struct spi_nor_locking_ops {
  *
  * @size:  the flash memory density in bytes.
  * @page_size: the page size of the SPI NOR flash memory.
+ * @octal_max_speed:   maximum operation speed of device in octal mode.
  * @hwcaps:describes the read and page program hardware
  * capabilities.
  * @reads: read capabilities ordered by priority: the higher index
@@ -214,6 +215,7 @@ struct spi_nor_locking_ops {
 struct spi_nor_flash_parameter {
u64 size;
u32 page_size;
+   u16 octal_max_speed;
 
struct spi_nor_hwcaps   hwcaps;
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 3685a3a..d7ef47a 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2014, Freescale Semiconductor, Inc.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -26,6 +27,12 @@
 #define SFDP_JESD216A_MINOR5
 #define SFDP_JESD216B_MINOR6
 
+/* Basic Flash Parameter Table 20th DWORD, Max operation speed of device */
+struct octal_max_speed {
+   u8 idx; /* Bits value */
+   u16 hz; /* MHz */
+};
+
 struct sfdp_header {
u32 signature; /* Ox50444653U <=> "SFDP" */
u8  minor;
@@ -440,6 +447,22 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
u32 addr;
u16 half;
u8 erase_mask;
+   static const struct octal_max_speed max_hz[] = {
+   /* Bits value, MHz */
+   { 0x0c, 400 },
+   { 0x0b, 333 },
+   { 0x0a, 266 },
+   { 0x09, 250 },
+   { 0x08, 200 },
+   { 0x07, 166 },
+   { 0x06, 133 },
+   { 0x05, 100 },
+   { 0x04,  80 },
+   { 0x03,  66 },
+   { 0x02,  50 },
+   { 0x01,  33 },
+   };
+   u8 idx;
 
/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
@@ -626,6 +649,19 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -ENOTSUPP;
}
 
+   /* Octal mode max speed */
+   idx = max(FIELD_GET(BFPT_DWORD20_OCTAL_DTR_MAX_SPEED,
+   bfpt.dwords[BFPT_DWORD(20)]),
+ FIELD_GET(BFPT_DWORD20_OCTAL_STR_MAX_SPEED,
+   bfpt.dwords[BFPT_DWORD(20)]));
+
+   for (i = 0; i < ARRAY_SIZE(max_hz); i++) {
+   if (max_hz[i].idx == idx) {
+   params->octal_max_speed = max_hz[i].hz;
+   break;
+   }
+   }
+
return spi_nor_post_bfpt_fixups(nor, bfpt_header, , params);
 }
 
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
index e15e307..d8ee681 100644
--- a/drivers/mtd/spi-nor/sfdp.h
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -90,6 +90,10 @@ struct sfdp_bfpt {
 #define BFPT_DWORD18_CMD_EXT_RES   (0x2UL << 29) /* Reserved */
 #define BFPT_DWORD18_CMD_EXT_16B   (0x3UL << 29) /* 16-bit opcode 
*/
 
+#define BFPT_DWORD20_OCTAL_MAX_SPEED_MASK   GENMASK(31, 16)
+#define BFPT_DWORD20_OCTAL_DTR_MAX_SPEEDGENMASK(31, 28)
+#define BFPT_DWORD20_OCTAL_STR_MAX_SPEEDGENMASK(19, 16)
+
 struct sfdp_parameter_header {
u8  id_lsb;
u8  minor;
-- 
1.9.1



[PATCH v3 00/14] mtd: spi-nor: add xSPI Octal DTR support

2020-05-28 Thread Mason Yang
Hello,

JESD216C has defined specification for Octal 8S-8S-8S and 8D-8D-8D.
Based on JEDEC216C Basic Flash Parameter Table (BFPT) driver extract
DWORD-18: command and command extension type.
DWORD-20: Maximum operation speed of device in Octal mode.

xSPI profile 1.0 table:
DWORD-1: Read Fast command, the number of dummy cycles and address nbytes
 for Read Status Register command.
DWORD-2: Read/Write volatile Register command for CFG Reg2.
DWORD-4 and DWORD-5: dummy cycles used for various frequencies based on
maximum speed of device from BFPT 20th DWORD.

Ccommand sequences to change to octal DTR mode:
The length of each command sequence is 8 per byte for single SPI mode and
patching driver to parse and execute these sequences for octal DTR mode.

By Vignesh's comments to patch these drivers based on Pratyush's patches
set [1].

This series adds support for Macronix mx25uw51245g works in octal DTR mode.

Tested on Macronix's Zynq PicoZed board with Macronix's SPI controller
(spi-mxic.c) driver patched on mx25uw51245g Octal flash.


[1] 
https://patchwork.ozlabs.org/project/linux-mtd/cover/20200525091544.17270-1-p.ya...@ti.com/


Summary of change log
v3:
Add support command sequences to change octal DTR mode and based on
part of Pratyush's patches set.

v2: 
Parse BFPT & xSPI table for Octal 8D-8D-8D mode parameters and enable Octal
mode in spi_nor_late_init_params().
Using Macros in spi_nor_spimem_read_data, spi_nor_spimem_write_data and
so on by Vignesh comments.

v1:
Without parsing BFPT & xSPI profile 1.0 table and enter Octal 8D-8D-8D
mode directly in spi_nor_fixups hooks.


thnaks for your time and review.
best regards,
Mason

--
Mason Yang (7):
  mtd: spi-nor: sfdp: get octal mode maximum speed from BFPT
  mtd: spi-nor: sfdp: parse xSPI Profile 1.0 table
  mtd: spi-nor: sfdp: parse command sequences to change octal DTR mode
  mtd: spi-nor: core: add configuration register 2 read & write support
  spi: mxic: patch for octal DTR mode support
  mtd: spi-nor: core: execute command sequences to change octal DTR mode
  mtd: spi-nor: macronix: Add Octal 8D-8D-8D supports for Macronix
mx25uw51245g

Pratyush Yadav (7):
  spi: spi-mem: allow specifying whether an op is DTR or not
  spi: spi-mem: allow specifying a command's extension
  mtd: spi-nor: add support for DTR protocol
  mtd: spi-nor: sfdp: prepare BFPT parsing for JESD216 rev D
  mtd: spi-nor: sfdp: get command opcode extension type from BFPT
  mtd: spi-nor: core: use dummy cycle and address width info from SFDP
  mtd: spi-nor: core: enable octal DTR mode when possible

 drivers/mtd/spi-nor/core.c | 514 +++--
 drivers/mtd/spi-nor/core.h |  49 
 drivers/mtd/spi-nor/macronix.c |  55 +
 drivers/mtd/spi-nor/sfdp.c | 278 +-
 drivers/mtd/spi-nor/sfdp.h |  15 +-
 drivers/spi/spi-mem.c  |  16 +-
 drivers/spi/spi-mtk-nor.c  |   4 +-
 drivers/spi/spi-mxic.c | 101 +---
 drivers/spi/spi-zynq-qspi.c|  11 +-
 include/linux/mtd/spi-nor.h|  51 ++--
 include/linux/spi/spi-mem.h|  14 +-
 11 files changed, 980 insertions(+), 128 deletions(-)

-- 
1.9.1



[PATCH v3 07/14] mtd: spi-nor: sfdp: parse xSPI Profile 1.0 table

2020-05-28 Thread Mason Yang
JESD251, xSPI profile 1.0 table supports octal DTR mode.
Extract information like the fast read opcode, dummy cycles for various
frequencies, the number of dummy cycles needed for a Read Status
Register command, the number of address bytes needed for a Read
Status Register command, read volatile register command and write
volatile register command.

According to BFPT 20th DWORD of octal maximum speed, driver get it's
specific dummy cycles from profile 1.0 table and then could update
it to device by their fixup hooks.

Since driver get octal DTR read opcode and then set read settings,
expose spi_nor_set_read_settings() in core.h.

Signed-off-by: Mason Yang 
---
 drivers/mtd/spi-nor/core.c |   2 +-
 drivers/mtd/spi-nor/core.h |  16 +++
 drivers/mtd/spi-nor/sfdp.c | 106 +
 3 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 388e695..642e3c0 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2355,7 +2355,7 @@ static int spi_nor_check(struct spi_nor *nor)
return 0;
 }
 
-static void
+void
 spi_nor_set_read_settings(struct spi_nor_read_command *read,
  u8 num_mode_clocks,
  u8 num_wait_states,
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index f644ed1..837f5e9 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -193,6 +193,12 @@ struct spi_nor_locking_ops {
  * @size:  the flash memory density in bytes.
  * @page_size: the page size of the SPI NOR flash memory.
  * @octal_max_speed:   maximum operation speed of device in octal mode.
+ * @rdsr_dummy:dummy cycles needed for Read Status Register 
command.
+ * @rdsr_addr_nbytes:  dummy address bytes needed for Read Status Register
+ * command.
+ * @rd_reg_cmd:read volatile register command for xSPI device.
+ * @wr_reg_cmd:write volatile register command for xSPI device.
+ * @dummy_cycles:  dummy cycles used for various frequencies.
  * @hwcaps:describes the read and page program hardware
  * capabilities.
  * @reads: read capabilities ordered by priority: the higher index
@@ -216,6 +222,11 @@ struct spi_nor_flash_parameter {
u64 size;
u32 page_size;
u16 octal_max_speed;
+   u8  rdsr_dummy;
+   u8  rdsr_addr_nbytes;
+   u8  rd_reg_cmd;
+   u8  wr_reg_cmd;
+   u8  dummy_cycles;
 
struct spi_nor_hwcaps   hwcaps;
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
@@ -426,6 +437,11 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, 
size_t len,
 
 int spi_nor_hwcaps_read2cmd(u32 hwcaps);
 u8 spi_nor_convert_3to4_read(u8 opcode);
+void spi_nor_set_read_settings(struct spi_nor_read_command *read,
+  u8 num_mode_clocks,
+  u8 num_wait_states,
+  u8 opcode,
+  enum spi_nor_protocol proto);
 void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
 enum spi_nor_protocol proto);
 
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index d7ef47a..550422b 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -20,6 +20,7 @@
 #define SFDP_BFPT_ID   0xff00  /* Basic Flash Parameter Table */
 #define SFDP_SECTOR_MAP_ID 0xff81  /* Sector Map Table */
 #define SFDP_4BAIT_ID  0xff84  /* 4-byte Address Instruction Table */
+#define SFDP_PROFILE1_ID   0xff05  /* xSPI Profile 1.0 table. */
 
 #define SFDP_SIGNATURE 0x50444653U
 #define SFDP_JESD216_MAJOR 1
@@ -27,6 +28,27 @@
 #define SFDP_JESD216A_MINOR5
 #define SFDP_JESD216B_MINOR6
 
+/* xSPI Profile 1.0 table (from JESD216D.01). */
+#define XSPI_PF1_DWORD1_RD_CMD  GENMASK(15, 8)
+#define XSPI_PF1_DWORD1_RDSR_ADDR_BYTES BIT(29)
+#define XSPI_PF1_DWORD1_RDSR_DUMMY_CYCLES   BIT(28)
+#define XSPI_PF1_DWORD2_RD_REG_CMD  GENMASK(31, 24)
+#define XSPI_PF1_DWORD2_WR_REG_CMD  GENMASK(15, 8)
+#define XSPI_PF1_DUMMY_CYCLES_DEFAULT  20
+#define XSPI_DWORD(x)   ((x) - 1)
+#define XSPI_DWORD_MAX  5
+
+struct sfdp_xspi {
+   u32 dwords[XSPI_DWORD_MAX];
+};
+
+struct xspi_dummy_cycles {
+   u16 speed_hz;   /* Speed MHz */
+   u8 dwords;  /* Dwords index */
+   u32 mask;   /* Mask */
+   u8 shift;   /* Bit shift */
+};
+
 /* Basic Flash Parameter Table 20th DWORD, Max operation speed of device */
 struct octal_max_speed {
u8 idx

[PATCH RFC 2/3] mtd: rawnand: Add support Macronix Block Protection function

2019-09-18 Thread Mason Yang
Macronix AC series support using SET/GET_FEATURES to change
Block Protection and Unprotection.

MTD default _lock/_unlock function replacement by manufacturer
postponed initialization.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 80 +---
 1 file changed, 75 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 58511ae..991c636 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -11,6 +11,10 @@
 #define MACRONIX_READ_RETRY_BIT BIT(0)
 #define MACRONIX_NUM_READ_RETRY_MODES 6
 
+#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0
+#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38
+#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0
+
 struct nand_onfi_vendor_macronix {
u8 reserved;
u8 reliability_func;
@@ -57,10 +61,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
  * the timings unlike what is declared in the parameter page. Unflag
  * this feature to avoid unnecessary downturns.
  */
-static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
-{
-   unsigned int i;
-   static const char * const broken_get_timings[] = {
+static const char * const broken_get_timings[] = {
"MX30LF1G18AC",
"MX30LF1G28AC",
"MX30LF2G18AC",
@@ -75,7 +76,11 @@ static void macronix_nand_fix_broken_get_timings(struct 
nand_chip *chip)
"MX30UF4G18AC",
"MX30UF4G16AC",
"MX30UF4G28AC",
-   };
+};
+
+static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
+{
+   unsigned int i;
 
if (!chip->parameters.supports_set_get_features)
return;
@@ -105,6 +110,71 @@ static int macronix_nand_init(struct nand_chip *chip)
return 0;
 }
 
+static int mxic_nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+   int ret;
+
+   feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("%s all blocks failed\n", __func__);
+
+   return ret;
+}
+
+static int mxic_nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+   int ret;
+
+   feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("%s all blocks failed\n", __func__);
+
+   return ret;
+}
+
+/*
+ * Macronix AC series support using SET/GET_FEATURES to change
+ * Block Protection and Unprotection.
+ *
+ * MTD call-back function replacement by manufacturer postponed
+ * initialization.
+ */
+static void macronix_nand_post_init(struct nand_chip *chip)
+{
+   unsigned int i, blockprotected = 0;
+   struct mtd_info *mtd = nand_to_mtd(chip);
+
+   for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) {
+   if (!strcmp(broken_get_timings[i], chip->parameters.model)) {
+   blockprotected = 1;
+   break;
+   }
+   }
+
+   if (blockprotected && chip->parameters.supports_set_get_features) {
+   bitmap_set(chip->parameters.set_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
+   bitmap_set(chip->parameters.get_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
+
+   mtd->_lock = mxic_nand_lock;
+   mtd->_unlock = mxic_nand_unlock;
+   }
+}
+
 const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
.init = macronix_nand_init,
+   .post_init = macronix_nand_post_init,
 };
-- 
1.9.1



[PATCH RFC 3/3] mtd: rawnand: Add support Macronix power down mode

2019-09-18 Thread Mason Yang
Macronix AD series support using power down command to
enter a minimum power consumption state.

MTD default _suspend/_resume function replacement by
manufacturer postponed initialization.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 78 +++-
 1 file changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 991c636..99a7b2e 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -15,6 +15,8 @@
 #define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38
 #define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0
 
+#define NAND_CMD_POWER_DOWN 0xB9
+
 struct nand_onfi_vendor_macronix {
u8 reserved;
u8 reliability_func;
@@ -78,6 +80,12 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
"MX30UF4G28AC",
 };
 
+static const char * const nand_power_down[] = {
+   "MX30LF1G28AD",
+   "MX30LF2G28AD",
+   "MX30LF4G28AD",
+};
+
 static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
 {
unsigned int i;
@@ -144,8 +152,64 @@ static int mxic_nand_unlock(struct mtd_info *mtd, loff_t 
ofs, uint64_t len)
return ret;
 }
 
+int nand_power_down_op(struct nand_chip *chip)
+{
+   int ret;
+
+   if (nand_has_exec_op(chip)) {
+   struct nand_op_instr instrs[] = {
+   NAND_OP_CMD(NAND_CMD_POWER_DOWN, 0),
+   };
+
+   struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
+
+   ret = nand_exec_op(chip, );
+   if (ret)
+   return ret;
+
+   } else {
+   chip->legacy.cmdfunc(chip, NAND_CMD_POWER_DOWN, -1, -1);
+   }
+
+   return 0;
+}
+
+static int mxic_nand_suspend(struct mtd_info *mtd)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+
+   mutex_lock(>lock);
+
+   nand_select_target(chip, 0);
+   nand_power_down_op(chip);
+   nand_deselect_target(chip);
+
+   chip->suspend = 1;
+   mutex_unlock(>lock);
+
+   return 0;
+}
+
+static void mxic_nand_resume(struct mtd_info *mtd)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+
+   mutex_lock(>lock);
+   // toggle #CS pin to resume NAND device
+   nand_select_target(chip, 0);
+   ndelay(20);
+   nand_deselect_target(chip);
+
+   if (chip->suspend)
+   chip->suspended = 0;
+   else
+   pr_err("%s call for a chip which is not in suspended state\n",
+  __func__);
+   mutex_unlock(>lock);
+}
+
 /*
- * Macronix AC series support using SET/GET_FEATURES to change
+ * Macronix AC and AD series support using SET/GET_FEATURES to change
  * Block Protection and Unprotection.
  *
  * MTD call-back function replacement by manufacturer postponed
@@ -163,6 +227,18 @@ static void macronix_nand_post_init(struct nand_chip *chip)
}
}
 
+   for (i = 0; i < ARRAY_SIZE(nand_power_down); i++) {
+   if (!strcmp(nand_power_down[i], chip->parameters.model)) {
+   blockprotected = 1;
+   break;
+   }
+   }
+
+   if (i < ARRAY_SIZE(nand_power_down)) {
+   mtd->_suspend = mxic_nand_suspend;
+   mtd->_resume = mxic_nand_resume;
+   }
+
if (blockprotected && chip->parameters.supports_set_get_features) {
bitmap_set(chip->parameters.set_feature_list,
   ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
-- 
1.9.1



[PATCH RFC 1/3] mtd: rawnand: Add support manufacturer postponed initialization

2019-09-18 Thread Mason Yang
Manufacturer postponed initialization is for MTD default call-back
function replacement for vendor soecific operation, i.e.,
_lock/_unlock, _suspend/_resume and so on.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/internals.h |  4 
 drivers/mtd/nand/raw/nand_base.c | 19 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index cba6fe7..505dd46 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -42,6 +42,9 @@
  *  is here to let vendor specific code release those resources.
  * @fixup_onfi_param_page: apply vendor specific fixups to the ONFI parameter
  *page. This is called after the checksum is verified.
+ * @post_init: postponed initialization is for MTD default call-back function
+ *replacement for vendor specific operation i.e., _lock/_unlock,
+ *_suspend/_resume and so on.
  */
 struct nand_manufacturer_ops {
void (*detect)(struct nand_chip *chip);
@@ -49,6 +52,7 @@ struct nand_manufacturer_ops {
void (*cleanup)(struct nand_chip *chip);
void (*fixup_onfi_param_page)(struct nand_chip *chip,
  struct nand_onfi_params *p);
+   void (*post_init)(struct nand_chip *chip);
 };
 
 /**
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 91f046d..7835b81 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4619,6 +4619,21 @@ static int nand_manufacturer_init(struct nand_chip *chip)
 }
 
 /*
+ * Manufacturer postponed initialization. This function is called for all NANDs
+ * whose MTD default call-back function replacement is needed.
+ * Manufacturer drivers should put all their specific postponed initialization
+ * code in their ->post_init() hook.
+ */
+static void nand_manufacturer_post_init(struct nand_chip *chip)
+{
+   if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops ||
+   !chip->manufacturer.desc->ops->post_init)
+   return;
+
+   return chip->manufacturer.desc->ops->post_init(chip);
+}
+
+/*
  * Manufacturer cleanup. This function is called for all NANDs including
  * ONFI and JEDEC compliant ones.
  * Manufacturer drivers should put all their specific cleanup code in their
@@ -5812,6 +5827,10 @@ static int nand_scan_tail(struct nand_chip *chip)
goto err_nanddev_cleanup;
}
 
+   nand_select_target(chip, 0);
+   nand_manufacturer_post_init(chip);
+   nand_deselect_target(chip);
+
/* Check, if we should skip the bad block table scan */
if (chip->options & NAND_SKIP_BBTSCAN)
return 0;
-- 
1.9.1



[PATCH v3] mtd: rawnand: Add support for Macronix NAND randomizer

2019-09-05 Thread Mason Yang
Macronix NANDs support randomizer operation for user data scrambled,
which can be enabled with a SET_FEATURE.

User data written to the NAND device without randomizer is still readable
after randomizer function enabled.
The penalty of randomizer are subpage accesses prohibited and more time
period is needed in program operation and entering deep power-down mode.
i.e., tPROG 300us to 340us(randomizer enabled)

For more high-reliability concern, if subpage write not available with
hardware ECC and then to enable randomizer is recommended by default.
Driver checks byte 167 of Vendor Blocks in ONFI parameter page table
to see if this high-reliability function is supported. By adding a new
specific DT property in children nodes to enable randomizer function.
i.e.,

nand: nand-controller@unit-address {

nand@0 {
reg = <0>;
mxic,enable-randomizer-otp;
};
};

--
changelog
v3:
To enable randomizer by specific DT property in children nodes,
mxic,enable-randomizer-otp;

v2:
To enable randomizer by checking chip options NAND_NO_SUBPAGE_WRITE

v1:
To enable randomizer by sys-fs

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 64 
 1 file changed, 64 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 58511ae..d5df09a 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -11,6 +11,13 @@
 #define MACRONIX_READ_RETRY_BIT BIT(0)
 #define MACRONIX_NUM_READ_RETRY_MODES 6
 
+#define MACRONIX_RANDOMIZER_BIT BIT(1)
+#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
+#define MACRONIX_RANDOMIZER_ENPGM BIT(0)
+#define MACRONIX_RANDOMIZER_RANDEN BIT(1)
+#define MACRONIX_RANDOMIZER_RANDOPT BIT(2)
+#define MACRONIX_RANDOMIZER_MODE_EXIT ~MACRONIX_RANDOMIZER_ENPGM
+
 struct nand_onfi_vendor_macronix {
u8 reserved;
u8 reliability_func;
@@ -29,15 +36,72 @@ static int macronix_nand_setup_read_retry(struct nand_chip 
*chip, int mode)
return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
 }
 
+static void macronix_nand_randomizer_check_enable(struct nand_chip *chip)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+   int ret;
+
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (feature[0]) {
+   pr_info("Macronix NAND randomizer enabled:0x%x\n", feature[0]);
+   return;
+   }
+
+   feature[0] = MACRONIX_RANDOMIZER_ENPGM | MACRONIX_RANDOMIZER_RANDEN |
+MACRONIX_RANDOMIZER_RANDOPT;
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (ret)
+   goto err;
+
+   feature[0] = 0x0;
+   ret = nand_prog_page_op(chip, 0, 0, feature, 1);
+   if (ret)
+   goto err;
+
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (ret)
+   goto err;
+
+   feature[0] &= MACRONIX_RANDOMIZER_MODE_EXIT;
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (ret)
+   goto err;
+
+   pr_info("Macronix NAND randomizer enable ok\n");
+   return;
+err:
+   pr_err("Macronix NAND randomizer enable failed\n");
+}
+
 static void macronix_nand_onfi_init(struct nand_chip *chip)
 {
struct nand_parameters *p = >parameters;
struct nand_onfi_vendor_macronix *mxic;
+   struct device_node *dn = nand_get_flash_node(chip);
+   int rand_otp = 0;
 
if (!p->onfi)
return;
 
+   if (of_find_property(dn, "mxic,enable-randomizer-otp", NULL))
+   rand_otp = 1;
+
mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
+   if (rand_otp && chip->options & NAND_NO_SUBPAGE_WRITE &&
+   mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) {
+   if (p->supports_set_get_features) {
+   bitmap_set(p->set_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
+   bitmap_set(p->get_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
+   macronix_nand_randomizer_check_enable(chip);
+   }
+   }
+
if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
return;
 
-- 
1.9.1



[PATCH] Add support for Macronix NAND randomizer

2019-08-19 Thread Mason Yang
Macronix NANDs support randomizer operation for user data scrambled,
which can be enabled with a SET_FEATURE.

User data written to the NAND device without randomizer is still readable
after randomizer function enabled.
The penalty of randomizer are NOP = 1 instead of NOP = 4 and more time period
is needed in program operation and entering deep power-down mode.
i.e., tPROG 300us to 340us(randomizer enabled)

If subpage write not available with hardware ECC, for example,
NAND chip options NAND_NO_SUBPAGE_WRITE be set in driver and
randomizer function is recommended for high-reliability.
Driver checks byte 167 of Vendor Blocks in ONFI parameter page table
to see if this high-reliability function is supported.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 54 
 1 file changed, 54 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 58511ae..b8b5bcb 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -11,6 +11,13 @@
 #define MACRONIX_READ_RETRY_BIT BIT(0)
 #define MACRONIX_NUM_READ_RETRY_MODES 6
 
+#define MACRONIX_RANDOMIZER_BIT BIT(1)
+#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
+#define MACRONIX_RANDOMIZER_ENPGM BIT(0)
+#define MACRONIX_RANDOMIZER_RANDEN BIT(1)
+#define MACRONIX_RANDOMIZER_RANDOPT BIT(2)
+#define MACRONIX_RANDOMIZER_MODE_EXIT 0
+
 struct nand_onfi_vendor_macronix {
u8 reserved;
u8 reliability_func;
@@ -29,6 +36,42 @@ static int macronix_nand_setup_read_retry(struct nand_chip 
*chip, int mode)
return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
 }
 
+static void macronix_nand_randomizer_check_enable(struct nand_chip *chip)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+   int ret;
+
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (feature[0]) {
+   pr_info("Macronix NAND randomizer enabled:0x%x\n", feature[0]);
+   return;
+   }
+
+   feature[0] = MACRONIX_RANDOMIZER_ENPGM | MACRONIX_RANDOMIZER_RANDEN |
+MACRONIX_RANDOMIZER_RANDOPT;
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (ret)
+   goto err;
+
+   feature[0] = 0x0;
+   ret = nand_prog_page_op(chip, 0, 0, feature, 1);
+   if (ret)
+   goto err;
+
+   feature[0] = MACRONIX_RANDOMIZER_MODE_EXIT;
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   if (ret)
+   goto err;
+
+   pr_info("Macronix NAND randomizer enable ok\n");
+   return;
+err:
+   pr_err("Macronix NAND randomizer enable failed\n");
+}
+
 static void macronix_nand_onfi_init(struct nand_chip *chip)
 {
struct nand_parameters *p = >parameters;
@@ -38,6 +81,17 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
return;
 
mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
+   if (chip->options & NAND_NO_SUBPAGE_WRITE &&
+   mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) {
+   if (p->supports_set_get_features) {
+   bitmap_set(p->set_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
+   bitmap_set(p->get_feature_list,
+  ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
+   macronix_nand_randomizer_check_enable(chip);
+   }
+   }
+
if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
return;
 
-- 
1.9.1



[PATCH v7 0/2] Add Macronix raw NAND controller driver

2019-08-19 Thread Mason Yang
Hello,

v7 patch including:
1. compatible rename to "mxic,multi-itfc-v009-nand-controller"
2. using interrupts instead of polling RY/#BS pin
3. removed sdr timing setup in mxic_nfc_hw_init().
4. And other patches based on Boris comments.

v6 patch including:
1. compatible rename to "mxicy,multi-itfc-v009-nand-morph"
2. remove xxx_clk to xxx in DTS and driver.
3. patch mxic_nfc_data_xfer()

v5 patch including:
1. compatible rename to "macronix,nand-controller"
2. handle three clock in one
3. other minor patches

v4 patch back to only raw NAND controller driver instead of MFD,
raw NAND and SPI driver. This is based on MFD maintainer, Lee Jones
comments:
MFD is for registering child devices of chips which offer genuine
cross-subsystem functionality.
It is not designed for mode selecting, or as a place to shove shared code 
just because a better location doesn't appear to exist. 

v3 patch is to rename the title of SPI controller driver.
"Patch Macronix SPI controller driver according to MX25F0A MFD driver"

v2s patches is to support Macronix MX25F0A MFD driver 
for raw nand and spi controller which is separated 
form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason

Mason Yang (2):
  mtd: rawnand: Add Macronix raw NAND controller driver
  dt-bindings: mtd: Document Macronix raw NAND controller bindings

 .../devicetree/bindings/mtd/mxic-nand.txt  |  36 ++
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 584 +
 4 files changed, 627 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

-- 
1.9.1



[PATCH v7 2/2] dt-bindings: mtd: Document Macronix raw NAND controller bindings

2019-08-19 Thread Mason Yang
Document the bindings used by the Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mtd/mxic-nand.txt  | 36 ++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt

diff --git a/Documentation/devicetree/bindings/mtd/mxic-nand.txt 
b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
new file mode 100644
index 000..46c5529
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
@@ -0,0 +1,36 @@
+Macronix Raw NAND Controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be "mxic,multi-itfc-v009-nand-controller"
+- reg: should contain 1 entry for the registers
+- #address-cells: should be set to 1
+- #size-cells: should be set to 0
+- interrupts: interrupt line connected to this raw NAND controller
+- clock-names: should contain "ps", "send" and "send_dly"
+- clocks: should contain 3 phandles for the "ps", "send" and
+"send_dly" clocks
+
+Children nodes:
+- children nodes represent the available NAND chips.
+
+See Documentation/devicetree/bindings/mtd/nand-controller.yaml
+for more details on generic bindings.
+
+Example:
+
+   nand: nand-controller@43c3 {
+   compatible = "mxic,multi-itfc-v009-nand-controller";
+   reg = <0x43c3 0x1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   interrupts = ;
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send", "send_dly", "ps";
+
+   nand@0 {
+   reg = <0>;
+   nand-ecc-mode = "soft";
+   nand-ecc-algo = "bch";
+   };
+   };
-- 
1.9.1



[PATCH v7 1/2] mtd: rawnand: Add Macronix raw NAND controller driver

2019-08-19 Thread Mason Yang
Add a driver for Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 584 +++
 3 files changed, 591 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5a711d8..9cff36a 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -407,6 +407,12 @@ config MTD_NAND_MTK
  Enables support for NAND controller on MTK SoCs.
  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
 
+config MTD_NAND_MXIC
+   tristate "Macronix raw NAND controller"
+   depends on HAS_IOMEM || COMPILE_TEST
+   help
+ This selects the Macronix raw NAND controller driver.
+
 config MTD_NAND_TEGRA
tristate "NVIDIA Tegra NAND controller"
depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index efaf5cd..9b43fbf 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= 
hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..b493edb
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,584 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Macronix International Co., Ltd.
+ *
+ * Author:
+ * Mason Yang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+#define HC_CFG 0x0
+#define HC_CFG_IF_CFG(x)   ((x) << 27)
+#define HC_CFG_DUAL_SLAVE  BIT(31)
+#define HC_CFG_INDIVIDUAL  BIT(30)
+#define HC_CFG_NIO(x)  (((x) / 4) << 27)
+#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
+#define HC_CFG_TYPE_SPI_NOR0
+#define HC_CFG_TYPE_SPI_NAND   1
+#define HC_CFG_TYPE_SPI_RAM2
+#define HC_CFG_TYPE_RAW_NAND   3
+#define HC_CFG_SLV_ACT(x)  ((x) << 21)
+#define HC_CFG_CLK_PH_EN   BIT(20)
+#define HC_CFG_CLK_POL_INV BIT(19)
+#define HC_CFG_BIG_ENDIAN  BIT(18)
+#define HC_CFG_DATA_PASS   BIT(17)
+#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
+#define HC_CFG_MAN_START_ENBIT(3)
+#define HC_CFG_MAN_START   BIT(2)
+#define HC_CFG_MAN_CS_EN   BIT(1)
+#define HC_CFG_MAN_CS_ASSERT   BIT(0)
+
+#define INT_STS0x4
+#define INT_STS_EN 0x8
+#define INT_SIG_EN 0xc
+#define INT_STS_ALLGENMASK(31, 0)
+#define INT_RDY_PINBIT(26)
+#define INT_RDY_SR BIT(25)
+#define INT_LNR_SUSP   BIT(24)
+#define INT_ECC_ERRBIT(17)
+#define INT_CRC_ERRBIT(16)
+#define INT_LWR_DISBIT(12)
+#define INT_LRD_DISBIT(11)
+#define INT_SDMA_INT   BIT(10)
+#define INT_DMA_FINISH BIT(9)
+#define INT_RX_NOT_FULLBIT(3)
+#define INT_RX_NOT_EMPTY   BIT(2)
+#define INT_TX_NOT_FULLBIT(1)
+#define INT_TX_EMPTY   BIT(0)
+
+#define HC_EN  0x10
+#define HC_EN_BIT  BIT(0)
+
+#define TXD(x) (0x14 + ((x) * 4))
+#define RXD0x24
+
+#define SS_CTRL(s) (0x30 + ((s) * 4))
+#define LRD_CFG0x44
+#define LWR_CFG0x80
+#define RWW_CFG0x70
+#define OP_READBIT(23)
+#define OP_DUMMY_CYC(x)((x) << 17)
+#define OP_ADDR_BYTES(x)   ((x) << 14)
+#define OP_CMD_BYTES(x)(((x) - 1) << 13)
+#define OP_OCTA_CRC_EN BIT(12)
+#define OP_DQS_EN  BIT(11)
+#define OP_ENHC_EN BIT(10)
+#define OP_PREAMBLE_EN BIT(9)
+#define OP_DATA_DDRBIT(8)
+#define OP_DATA_BUSW(x)((x) << 6)
+#define OP_ADDR_DDRBIT(5)
+#define OP_ADDR_BUSW(x)((x) << 3)
+#define OP_CMD_DDR BIT(2)
+#define OP_CMD_BUSW(x) (x)
+#define OP_BUSW_1  0
+#define OP_BUSW_2  1
+#define OP_BUSW_4  2
+#define OP_BUSW_8  3
+
+#define OCTA_CRC   0x38
+#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
+#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
+#define

[PATCH v17 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-08-05 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 45 ++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..d4344c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,45 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77980-rpc"  (R-Car V3H)
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of RPC-IF registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain the clock phandle/specifier pair for the module clock.
+- clock-names: should contain "rpc"
+- power-domains: should contain the power domain phandle/secifier pair.
+- resets: should contain the reset controller phandle/specifier pair.
+- #address-cells: should be 1
+- #size-cells: should be 0
+- flash: should be represented by a subnode of the RPC-IF node,
+its "compatible" property contains "jedec,spi-nor" if SPI is used.
+
+Example:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
+   };
+   };
-- 
1.9.1



[PATCH v17 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-08-05 Thread Mason Yang
Hi Mark,

v17 patch including:
1) patch adding rpc_spi_hw_init() after reset_control_rest()
2) v14 dt-binding file has reviewed by Rob Herring.

v16 patch including:
1) fixed typo and spi-tx/rx-bus-width in DTS.
2) v14 dt-binding file has reviewed by Rob Herring.

v15 patch including:
1) A typo in dt-bindings and add flash subnode description
2) v14 dt-binding file has reviewed by Rob Herring.

v14 patch including:
1) Patch RPC-IF back to SPI mode only instead of MFD & SPI 
   by MFD maintainer, Lee Jones comments.
2) Patch pm_runtime control in spi transfer.

v13 patch including:
1) rename mfd to ddata for SPI driver.
2) Patch RPC-IF devicetree for SPI and HyperFlash.

v12 patch including:
1) add back "wbuf" in dts example.
2) RPC-IF replace rpc-if in dts.

v11 patch including:
1) Patch mfd include header file.
2) mfd coding style.
3) add back wbuf description in dts.

v10 patch including:
1) Address range for > 64M byte flash.
2) Removed dirmap_write due to WBUF 256 bytes transfer issue.
3) Dummy bytes setting according to spi-nor.c layer.

v9 patch is for RPC MFD driver and RPC SPI driver.

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  45 ++
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 756 +
 4 files changed, 808 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v17 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-08-05 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 756 ++
 3 files changed, 763 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3a1d8f1..88e28de 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -571,6 +571,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 63dcab5..d858e4c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..52537b7
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,756 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAV(c)   (((c) & 0xf) << 16)
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) <

[PATCH v6 0/2] Add Macronix raw NAND controller driver

2019-07-31 Thread Mason Yang
Hi,

v6 patch including:
1. compatible rename to "mxicy,multi-itfc-v009-nand-morph"
2. remove xxx_clk to xxx in DTS and driver.
3. patch mxic_nfc_data_xfer()

v5 patch including:
1. compatible rename to "macronix,nand-controller"
2. handle three clock in one
3. other minor patches

v4 patch back to only raw NAND controller driver instead of MFD,
raw NAND and SPI driver. This is based on MFD maintainer, Lee Jones
comments:
MFD is for registering child devices of chips which offer genuine
cross-subsystem functionality.
It is not designed for mode selecting, or as a place to shove shared code 
just because a better location doesn't appear to exist. 

v3 patch is to rename the title of SPI controller driver.
"Patch Macronix SPI controller driver according to MX25F0A MFD driver"

v2s patches is to support Macronix MX25F0A MFD driver 
for raw nand and spi controller which is separated 
form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason


Mason Yang (2):
  mtd: rawnand: Add Macronix raw NAND controller driver
  dt-bindings: mtd: Document Macronix raw NAND controller bindings

 .../devicetree/bindings/mtd/mxic-nand.txt  |  19 +
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 554 +
 4 files changed, 580 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

-- 
1.9.1



[PATCH v6 1/2] mtd: rawnand: Add Macronix raw NAND controller driver

2019-07-31 Thread Mason Yang
Add a driver for Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 554 +++
 3 files changed, 561 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5a711d8..9cff36a 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -407,6 +407,12 @@ config MTD_NAND_MTK
  Enables support for NAND controller on MTK SoCs.
  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
 
+config MTD_NAND_MXIC
+   tristate "Macronix raw NAND controller"
+   depends on HAS_IOMEM || COMPILE_TEST
+   help
+ This selects the Macronix raw NAND controller driver.
+
 config MTD_NAND_TEGRA
tristate "NVIDIA Tegra NAND controller"
depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index efaf5cd..9b43fbf 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= 
hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..56e816d
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Macronix International Co., Ltd.
+ *
+ * Author:
+ * Mason Yang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+#define HC_CFG 0x0
+#define HC_CFG_IF_CFG(x)   ((x) << 27)
+#define HC_CFG_DUAL_SLAVE  BIT(31)
+#define HC_CFG_INDIVIDUAL  BIT(30)
+#define HC_CFG_NIO(x)  (((x) / 4) << 27)
+#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
+#define HC_CFG_TYPE_SPI_NOR0
+#define HC_CFG_TYPE_SPI_NAND   1
+#define HC_CFG_TYPE_SPI_RAM2
+#define HC_CFG_TYPE_RAW_NAND   3
+#define HC_CFG_SLV_ACT(x)  ((x) << 21)
+#define HC_CFG_CLK_PH_EN   BIT(20)
+#define HC_CFG_CLK_POL_INV BIT(19)
+#define HC_CFG_BIG_ENDIAN  BIT(18)
+#define HC_CFG_DATA_PASS   BIT(17)
+#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
+#define HC_CFG_MAN_START_ENBIT(3)
+#define HC_CFG_MAN_START   BIT(2)
+#define HC_CFG_MAN_CS_EN   BIT(1)
+#define HC_CFG_MAN_CS_ASSERT   BIT(0)
+
+#define INT_STS0x4
+#define INT_STS_EN 0x8
+#define INT_SIG_EN 0xc
+#define INT_STS_ALLGENMASK(31, 0)
+#define INT_RDY_PINBIT(26)
+#define INT_RDY_SR BIT(25)
+#define INT_LNR_SUSP   BIT(24)
+#define INT_ECC_ERRBIT(17)
+#define INT_CRC_ERRBIT(16)
+#define INT_LWR_DISBIT(12)
+#define INT_LRD_DISBIT(11)
+#define INT_SDMA_INT   BIT(10)
+#define INT_DMA_FINISH BIT(9)
+#define INT_RX_NOT_FULLBIT(3)
+#define INT_RX_NOT_EMPTY   BIT(2)
+#define INT_TX_NOT_FULLBIT(1)
+#define INT_TX_EMPTY   BIT(0)
+
+#define HC_EN  0x10
+#define HC_EN_BIT  BIT(0)
+
+#define TXD(x) (0x14 + ((x) * 4))
+#define RXD0x24
+
+#define SS_CTRL(s) (0x30 + ((s) * 4))
+#define LRD_CFG0x44
+#define LWR_CFG0x80
+#define RWW_CFG0x70
+#define OP_READBIT(23)
+#define OP_DUMMY_CYC(x)((x) << 17)
+#define OP_ADDR_BYTES(x)   ((x) << 14)
+#define OP_CMD_BYTES(x)(((x) - 1) << 13)
+#define OP_OCTA_CRC_EN BIT(12)
+#define OP_DQS_EN  BIT(11)
+#define OP_ENHC_EN BIT(10)
+#define OP_PREAMBLE_EN BIT(9)
+#define OP_DATA_DDRBIT(8)
+#define OP_DATA_BUSW(x)((x) << 6)
+#define OP_ADDR_DDRBIT(5)
+#define OP_ADDR_BUSW(x)((x) << 3)
+#define OP_CMD_DDR BIT(2)
+#define OP_CMD_BUSW(x) (x)
+#define OP_BUSW_1  0
+#define OP_BUSW_2  1
+#define OP_BUSW_4  2
+#define OP_BUSW_8  3
+
+#define OCTA_CRC   0x38
+#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
+#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
+#define OCTA_CRC_OUT

[PATCH v6 2/2] dt-bindings: mtd: Document Macronix raw NAND controller bindings

2019-07-31 Thread Mason Yang
Document the bindings used by the Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 Documentation/devicetree/bindings/mtd/mxic-nand.txt | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt

diff --git a/Documentation/devicetree/bindings/mtd/mxic-nand.txt 
b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
new file mode 100644
index 000..de37d60
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
@@ -0,0 +1,19 @@
+Macronix Raw NAND Controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be "mxicy,multi-itfc-v009-nand-morph"
+- reg: should contain 1 entry for the registers
+- interrupts: interrupt line connected to this raw NAND controller
+- clock-names: should contain "ps", "send" and "send_dly"
+- clocks: should contain 3 phandles for the "ps", "send" and
+"send_dly" clocks
+
+Example:
+
+   nand: nand-controller@43c3 {
+   compatible = "mxicy,multi-itfc-v009-nand-morph";
+   reg = <0x43c3 0x1>;
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send", "send_dly", "ps";
+   };
-- 
1.9.1



[PATCH v16 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-07-30 Thread Mason Yang
Hi Mark,

v16 patch including:
1) fixed typo and spi-tx/rx-bus-width in DTS.
2) v14 dt-binding file has reviewed by Rob Herring.

v15 patch including:
1) A typo in dt-bindings and add flash subnode description
2) v14 dt-binding file has reviewed by Rob Herring.

v14 patch including:
1) Patch RPC-IF back to SPI mode only instead of MFD & SPI 
   by MFD maintainer, Lee Jones comments.
2) Patch pm_runtime control in spi transfer.

v13 patch including:
1) rename mfd to ddata for SPI driver.
2) Patch RPC-IF devicetree for SPI and HyperFlash.

v12 patch including:
1) add back "wbuf" in dts example.
2) RPC-IF replace rpc-if in dts.

v11 patch including:
1) Patch mfd include header file.
2) mfd coding style.
3) add back wbuf description in dts.

v10 patch including:
1) Address range for > 64M byte flash.
2) Removed dirmap_write due to WBUF 256 bytes transfer issue.
3) Dummy bytes setting according to spi-nor.c layer.

v9 patch is for RPC MFD driver and RPC SPI driver.

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  45 ++
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 754 +
 4 files changed, 806 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v16 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-07-30 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 45 ++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..d4344c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,45 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77980-rpc"  (R-Car V3H)
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of RPC-IF registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain the clock phandle/specifier pair for the module clock.
+- clock-names: should contain "rpc"
+- power-domains: should contain the power domain phandle/secifier pair.
+- resets: should contain the reset controller phandle/specifier pair.
+- #address-cells: should be 1
+- #size-cells: should be 0
+- flash: should be represented by a subnode of the RPC-IF node,
+its "compatible" property contains "jedec,spi-nor" if SPI is used.
+
+Example:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
+   };
+   };
-- 
1.9.1



[PATCH v16 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-07-30 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 754 ++
 3 files changed, 761 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3a1d8f1..88e28de 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -571,6 +571,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 63dcab5..d858e4c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..648d14e
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,754 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAV(c)   (((c) & 0xf) << 16)
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) <

[PATCH v15 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-07-25 Thread Mason Yang
Dcument the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 46 ++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..d929850
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,46 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77980-rpc"  (R-Car V3H)
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of RPC-IF registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain the clock phandle/specifier pair for the module clock.
+- clock-names: should contain "rpc"
+- power-domains: should contain the power domain phandle/secifier pair.
+- resets: should contain the reset controller phandle/specifier pair.
+- #address-cells: should be 1
+- #size-cells: should be 0
+- flash: should be represented by a subnode of the RPC-IF node,
+which "compatible" property contains "jedec,spi-nor", it presents
+SPI is used.
+
+Example:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v15 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-07-25 Thread Mason Yang
Hi Mark,

v15 patch including:
1) A typo in dt-bindings and add flash subnode description
2) v14 dt-binding file has reviewed by Rob Herring.

v14 patch including:
1) Patch RPC-IF back to SPI mode only instead of MFD & SPI 
   by MFD maintainer, Lee Jones comments.
2) Patch pm_runtime control in spi transfer.

v13 patch including:
1) rename mfd to ddata for SPI driver.
2) Patch RPC-IF devicetree for SPI and HyperFlash.

v12 patch including:
1) add back "wbuf" in dts example.
2) RPC-IF replace rpc-if in dts.

v11 patch including:
1) Patch mfd include header file.
2) mfd coding style.
3) add back wbuf description in dts.

v10 patch including:
1) Address range for > 64M byte flash.
2) Removed dirmap_write due to WBUF 256 bytes transfer issue.
3) Dummy bytes setting according to spi-nor.c layer.

v9 patch is for RPC MFD driver and RPC SPI driver.

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  46 ++
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 754 +
 4 files changed, 807 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v15 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-07-25 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 754 ++
 3 files changed, 761 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3a1d8f1..88e28de 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -571,6 +571,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 63dcab5..d858e4c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..648d14e
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,754 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAV(c)   (((c) & 0xf) << 16)
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) <

[PATCH v5 1/2] mtd: rawnand: Add Macronix raw NAND controller

2019-07-03 Thread Mason Yang
Add a driver for Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 557 +++
 3 files changed, 564 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5a711d8..9cff36a 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -407,6 +407,12 @@ config MTD_NAND_MTK
  Enables support for NAND controller on MTK SoCs.
  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
 
+config MTD_NAND_MXIC
+   tristate "Macronix raw NAND controller"
+   depends on HAS_IOMEM || COMPILE_TEST
+   help
+ This selects the Macronix raw NAND controller driver.
+
 config MTD_NAND_TEGRA
tristate "NVIDIA Tegra NAND controller"
depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index efaf5cd..9b43fbf 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= 
hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..2c27228
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,557 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Macronix International Co., Ltd.
+ *
+ * Author:
+ * Mason Yang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+#define HC_CFG 0x0
+#define HC_CFG_IF_CFG(x)   ((x) << 27)
+#define HC_CFG_DUAL_SLAVE  BIT(31)
+#define HC_CFG_INDIVIDUAL  BIT(30)
+#define HC_CFG_NIO(x)  (((x) / 4) << 27)
+#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
+#define HC_CFG_TYPE_SPI_NOR0
+#define HC_CFG_TYPE_SPI_NAND   1
+#define HC_CFG_TYPE_SPI_RAM2
+#define HC_CFG_TYPE_RAW_NAND   3
+#define HC_CFG_SLV_ACT(x)  ((x) << 21)
+#define HC_CFG_CLK_PH_EN   BIT(20)
+#define HC_CFG_CLK_POL_INV BIT(19)
+#define HC_CFG_BIG_ENDIAN  BIT(18)
+#define HC_CFG_DATA_PASS   BIT(17)
+#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
+#define HC_CFG_MAN_START_ENBIT(3)
+#define HC_CFG_MAN_START   BIT(2)
+#define HC_CFG_MAN_CS_EN   BIT(1)
+#define HC_CFG_MAN_CS_ASSERT   BIT(0)
+
+#define INT_STS0x4
+#define INT_STS_EN 0x8
+#define INT_SIG_EN 0xc
+#define INT_STS_ALLGENMASK(31, 0)
+#define INT_RDY_PINBIT(26)
+#define INT_RDY_SR BIT(25)
+#define INT_LNR_SUSP   BIT(24)
+#define INT_ECC_ERRBIT(17)
+#define INT_CRC_ERRBIT(16)
+#define INT_LWR_DISBIT(12)
+#define INT_LRD_DISBIT(11)
+#define INT_SDMA_INT   BIT(10)
+#define INT_DMA_FINISH BIT(9)
+#define INT_RX_NOT_FULLBIT(3)
+#define INT_RX_NOT_EMPTY   BIT(2)
+#define INT_TX_NOT_FULLBIT(1)
+#define INT_TX_EMPTY   BIT(0)
+
+#define HC_EN  0x10
+#define HC_EN_BIT  BIT(0)
+
+#define TXD(x) (0x14 + ((x) * 4))
+#define RXD0x24
+
+#define SS_CTRL(s) (0x30 + ((s) * 4))
+#define LRD_CFG0x44
+#define LWR_CFG0x80
+#define RWW_CFG0x70
+#define OP_READBIT(23)
+#define OP_DUMMY_CYC(x)((x) << 17)
+#define OP_ADDR_BYTES(x)   ((x) << 14)
+#define OP_CMD_BYTES(x)(((x) - 1) << 13)
+#define OP_OCTA_CRC_EN BIT(12)
+#define OP_DQS_EN  BIT(11)
+#define OP_ENHC_EN BIT(10)
+#define OP_PREAMBLE_EN BIT(9)
+#define OP_DATA_DDRBIT(8)
+#define OP_DATA_BUSW(x)((x) << 6)
+#define OP_ADDR_DDRBIT(5)
+#define OP_ADDR_BUSW(x)((x) << 3)
+#define OP_CMD_DDR BIT(2)
+#define OP_CMD_BUSW(x) (x)
+#define OP_BUSW_1  0
+#define OP_BUSW_2  1
+#define OP_BUSW_4  2
+#define OP_BUSW_8  3
+
+#define OCTA_CRC   0x38
+#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
+#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
+#define OCTA_CRC_OUT

[PATCH v5 0/2] Add Macronix raw NAND controller driver

2019-07-03 Thread Mason Yang
Hi,

v5 patch including:
1. compatible rename to "macronix,nand-controller"
2. handle three clock in one
3. other minor patches

v4 patch back to only raw NAND controller driver instead of MFD,
raw NAND and SPI driver. This is based on MFD maintainer, Lee Jones
comments:
MFD is for registering child devices of chips which offer genuine
cross-subsystem functionality.
It is not designed for mode selecting, or as a place to shove shared code 
just because a better location doesn't appear to exist. 

v3 patch is to rename the title of SPI controller driver.
"Patch Macronix SPI controller driver according to MX25F0A MFD driver"

v2s patches is to support Macronix MX25F0A MFD driver 
for raw nand and spi controller which is separated 
form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason


Mason Yang (2):
  mtd: rawnand: Add Macronix raw NAND controller
  dt-bindings: mtd: Document Macronix raw NAND controller bindings

 .../devicetree/bindings/mtd/mxic-nand.txt  |  20 +
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 557 +
 4 files changed, 584 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

-- 
1.9.1



[PATCH v5 2/2] dt-bindings: mtd: Document Macronix raw NAND controller bindings

2019-07-03 Thread Mason Yang
Document the bindings used by the Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 Documentation/devicetree/bindings/mtd/mxic-nand.txt | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt

diff --git a/Documentation/devicetree/bindings/mtd/mxic-nand.txt 
b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
new file mode 100644
index 000..ddd7660
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
@@ -0,0 +1,20 @@
+Macronix Raw NAND Controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be "macronix,nand-controller"
+- reg: should contain 1 entrie for the registers
+- interrupts: interrupt line connected to this raw NAND controller
+- clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
+- clocks: should contain 3 phandles for the "ps_clk", "send_clk" and
+"send_dly_clk" clocks
+
+Example:
+
+   nand: mxic-nfc@43c3 {
+   compatible = "macronix,nand-controller";
+   reg = <0x43c3 0x1>;
+   reg-names = "regs";
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send_clk", "send_dly_clk", "ps_clk";
+   };
-- 
1.9.1



[PATCH v4 1/2] mtd: rawnand: Add Macronix Raw NAND controller

2019-06-24 Thread Mason Yang
Add a driver for Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 551 +++
 3 files changed, 558 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 5a711d8..9cff36a 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -407,6 +407,12 @@ config MTD_NAND_MTK
  Enables support for NAND controller on MTK SoCs.
  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
 
+config MTD_NAND_MXIC
+   tristate "Macronix raw NAND controller"
+   depends on HAS_IOMEM || COMPILE_TEST
+   help
+ This selects the Macronix raw NAND controller driver.
+
 config MTD_NAND_TEGRA
tristate "NVIDIA Tegra NAND controller"
depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index efaf5cd..9b43fbf 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= 
hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)   += meson_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..14c0b3b
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Macronix International Co., Ltd.
+ *
+ * Author:
+ * Mason Yang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+#define HC_CFG 0x0
+#define HC_CFG_IF_CFG(x)   ((x) << 27)
+#define HC_CFG_DUAL_SLAVE  BIT(31)
+#define HC_CFG_INDIVIDUAL  BIT(30)
+#define HC_CFG_NIO(x)  (((x) / 4) << 27)
+#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
+#define HC_CFG_TYPE_SPI_NOR0
+#define HC_CFG_TYPE_SPI_NAND   1
+#define HC_CFG_TYPE_SPI_RAM2
+#define HC_CFG_TYPE_RAW_NAND   3
+#define HC_CFG_SLV_ACT(x)  ((x) << 21)
+#define HC_CFG_CLK_PH_EN   BIT(20)
+#define HC_CFG_CLK_POL_INV BIT(19)
+#define HC_CFG_BIG_ENDIAN  BIT(18)
+#define HC_CFG_DATA_PASS   BIT(17)
+#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
+#define HC_CFG_MAN_START_ENBIT(3)
+#define HC_CFG_MAN_START   BIT(2)
+#define HC_CFG_MAN_CS_EN   BIT(1)
+#define HC_CFG_MAN_CS_ASSERT   BIT(0)
+
+#define INT_STS0x4
+#define INT_STS_EN 0x8
+#define INT_SIG_EN 0xc
+#define INT_STS_ALLGENMASK(31, 0)
+#define INT_RDY_PINBIT(26)
+#define INT_RDY_SR BIT(25)
+#define INT_LNR_SUSP   BIT(24)
+#define INT_ECC_ERRBIT(17)
+#define INT_CRC_ERRBIT(16)
+#define INT_LWR_DISBIT(12)
+#define INT_LRD_DISBIT(11)
+#define INT_SDMA_INT   BIT(10)
+#define INT_DMA_FINISH BIT(9)
+#define INT_RX_NOT_FULLBIT(3)
+#define INT_RX_NOT_EMPTY   BIT(2)
+#define INT_TX_NOT_FULLBIT(1)
+#define INT_TX_EMPTY   BIT(0)
+
+#define HC_EN  0x10
+#define HC_EN_BIT  BIT(0)
+
+#define TXD(x) (0x14 + ((x) * 4))
+#define RXD0x24
+
+#define SS_CTRL(s) (0x30 + ((s) * 4))
+#define LRD_CFG0x44
+#define LWR_CFG0x80
+#define RWW_CFG0x70
+#define OP_READBIT(23)
+#define OP_DUMMY_CYC(x)((x) << 17)
+#define OP_ADDR_BYTES(x)   ((x) << 14)
+#define OP_CMD_BYTES(x)(((x) - 1) << 13)
+#define OP_OCTA_CRC_EN BIT(12)
+#define OP_DQS_EN  BIT(11)
+#define OP_ENHC_EN BIT(10)
+#define OP_PREAMBLE_EN BIT(9)
+#define OP_DATA_DDRBIT(8)
+#define OP_DATA_BUSW(x)((x) << 6)
+#define OP_ADDR_DDRBIT(5)
+#define OP_ADDR_BUSW(x)((x) << 3)
+#define OP_CMD_DDR BIT(2)
+#define OP_CMD_BUSW(x) (x)
+#define OP_BUSW_1  0
+#define OP_BUSW_2  1
+#define OP_BUSW_4  2
+#define OP_BUSW_8  3
+
+#define OCTA_CRC   0x38
+#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
+#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
+#define OCTA_CRC_OUT

[PATCH v4 2/2] dt-bindings: mtd: Document Macronix raw NAND controller bindings

2019-06-24 Thread Mason Yang
Document the bindings used by the Macronix raw NAND controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mtd/mxic-nand.txt  | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt

diff --git a/Documentation/devicetree/bindings/mtd/mxic-nand.txt 
b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
new file mode 100644
index 000..3d198e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxic-nand.txt
@@ -0,0 +1,26 @@
+Macronix Raw NAND Controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be "mxic,raw-nand-ctlr"
+- reg: should contain 1 entrie for the registers
+- reg-names: should contain "regs"
+- interrupts: interrupt line connected to this NAND controller
+- clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
+- clocks: should contain 3 entries for the "ps_clk", "send_clk" and
+"send_dly_clk" clocks
+
+Example:
+
+   nand: mxic-nfc@43c3 {
+   compatible = "mxic,raw-nand-ctlr";
+   reg = <0x43c3 0x1>;
+   reg-names = "regs";
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send_clk", "send_dly_clk", "ps_clk";
+
+   nand-ecc-mode = "soft";
+   nand-ecc-algo = "bch";
+   nand-ecc-step-size = <512>;
+   nand-ecc-strength = <8>;
+   };
-- 
1.9.1



[PATCH v4 0/2] Add Macronix Raw NAND controller driver

2019-06-24 Thread Mason Yang
Hi,

v4 patch back to only raw NAND controller driver instead of MFD,
raw NAND and SPI driver. This is based on MFD maintainer, Lee Jones
comments:
MFD is for registering child devices of chips which offer genuine
cross-subsystem functionality.
It is not designed for mode selecting, or as a place to shove shared code 
just because a better location doesn't appear to exist. 

v3 patch is to rename the title of SPI controller driver.
"Patch Macronix SPI controller driver according to MX25F0A MFD driver"

v2s patches is to support Macronix MX25F0A MFD driver 
for raw nand and spi controller which is separated 
form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason


Mason Yang (2):
  mtd: rawnand: Add Macronix Raw NAND controller
  dt-bindings: mtd: Document Macronix raw NAND controller bindings

 .../devicetree/bindings/mtd/mxic-nand.txt  |  26 +
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 551 +
 4 files changed, 584 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic-nand.txt
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

-- 
1.9.1



[PATCH v14 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-06-20 Thread Mason Yang
Hi Mark,

V14 patch including:
1) Patch RPC-IF back to SPI mode only instead of MFD & SPI 
   by MFD maintainer, Lee Jones comments.
2) Patch pm_runtime control in spi transfer.

v13 patch including:
1) rename mfd to ddata for SPI driver.
2) Patch RPC-IF devicetree for SPI and HyperFlash.

v12 patch including:
1) add back "wbuf" in dts example.
2) RPC-IF replace rpc-if in dts.

v11 patch including:
1) Patch mfd include header file.
2) mfd coding style.
3) add back wbuf description in dts.

v10 patch including:
1) Address range for > 64M byte flash.
2) Removed dirmap_write due to WBUF 256 bytes transfer issue.
3) Dummy bytes setting according to spi-nor.c layer.

v9 patch is for RPC MFD driver and RPC SPI driver.

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  43 ++
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 760 +
 4 files changed, 810 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v14 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-06-20 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 760 ++
 3 files changed, 767 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 30a4028..68a808b 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -571,6 +571,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f2f78d0..2a6e052 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..e0fe7b0
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,760 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAV(c)   (((c) & 0xf) << 16)
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) <

[PATCH v14 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-06-20 Thread Mason Yang
Dcument the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..e8edf99
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,43 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+-
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77980-rpc"  (R-Car V3H)
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of RPC-IF registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain the clock phandle/specifier pair for the module clock.
+- clock-names: should contain "rpc"
+- power-domain: should contain the power domain phandle/secifier pair.
+- resets: should contain the reset controller phandle/specifier pair.
+- #address-cells: should be 1
+- #size-cells: should be 0
+
+Example:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v3] mtd: rawnand: Add Macronix NAND read retry support

2019-06-02 Thread Mason Yang
Add support for Macronix NAND read retry.

Macronix NANDs support specific read operation for data recovery,
which can be enabled with a SET_FEATURE.
Driver checks byte 167 of Vendor Blocks in ONFI parameter page table
to see if this high-reliability function is supported.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 45 
 1 file changed, 45 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index fad57c3..58511ae 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -8,6 +8,50 @@
 
 #include "internals.h"
 
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_NUM_READ_RETRY_MODES 6
+
+struct nand_onfi_vendor_macronix {
+   u8 reserved;
+   u8 reliability_func;
+} __packed;
+
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+
+   if (!chip->parameters.supports_set_get_features ||
+   !test_bit(ONFI_FEATURE_ADDR_READ_RETRY,
+ chip->parameters.set_feature_list))
+   return -ENOTSUPP;
+
+   feature[0] = mode;
+   return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+}
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+   struct nand_parameters *p = >parameters;
+   struct nand_onfi_vendor_macronix *mxic;
+
+   if (!p->onfi)
+   return;
+
+   mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
+   if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
+   return;
+
+   chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES;
+   chip->setup_read_retry = macronix_nand_setup_read_retry;
+
+   if (p->supports_set_get_features) {
+   bitmap_set(p->set_feature_list,
+  ONFI_FEATURE_ADDR_READ_RETRY, 1);
+   bitmap_set(p->get_feature_list,
+  ONFI_FEATURE_ADDR_READ_RETRY, 1);
+   }
+}
+
 /*
  * Macronix AC series does not support using SET/GET_FEATURES to change
  * the timings unlike what is declared in the parameter page. Unflag
@@ -56,6 +100,7 @@ static int macronix_nand_init(struct nand_chip *chip)
chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
macronix_nand_fix_broken_get_timings(chip);
+   macronix_nand_onfi_init(chip);
 
return 0;
 }
-- 
1.9.1



[PATCH v13 0/3] mfd: Add Renesas R-Car Gen3 RPC-IF MFD & SPI driver

2019-05-21 Thread Mason Yang
Hi,

v13 patch including:
1) rename mfd to ddata for SPI driver.
2) Patch RPC-IF devicetree for SPI and HyperFlash.

v12 patch including:
1) add back "wbuf" in dts example.
2) RPC-IF replace rpc-if in dts.

v11 patch including:
1) Patch mfd include header file.
2) mfd coding style.
3) add back wbuf description in dts.

v10 patch including:
1) Address range for > 64M byte flash.
2) Removed dirmap_write due to WBUF 256 bytes transfer issue.
3) Dummy bytes setting according to spi-nor.c layer.

v9 patch is for RPC MFD driver and RPC SPI driver.

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason

Mason Yang (3):
  mfd: Add Renesas R-Car Gen3 RPC-IF MFD driver
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: mfd: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/mfd/renesas-rpc-if.txt |  65 +++
 drivers/mfd/Kconfig|   9 +
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/renesas-rpc.c  | 125 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 573 +
 include/linux/mfd/renesas-rpc.h| 141 +
 8 files changed, 921 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/renesas-rpc-if.txt
 create mode 100644 drivers/mfd/renesas-rpc.c
 create mode 100644 drivers/spi/spi-renesas-rpc.c
 create mode 100644 include/linux/mfd/renesas-rpc.h

-- 
1.9.1



[PATCH v13 1/3] mfd: Add Renesas R-Car Gen3 RPC-IF MFD driver

2019-05-21 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF MFD

Signed-off-by: Mason Yang 
---
 drivers/mfd/Kconfig |   9 +++
 drivers/mfd/Makefile|   1 +
 drivers/mfd/renesas-rpc.c   | 125 +++
 include/linux/mfd/renesas-rpc.h | 141 
 4 files changed, 276 insertions(+)
 create mode 100644 drivers/mfd/renesas-rpc.c
 create mode 100644 include/linux/mfd/renesas-rpc.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 294d956..cdbde79 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1002,6 +1002,15 @@ config MFD_RDC321X
  southbridge which provides access to GPIOs and Watchdog using the
  southbridge PCI device configuration space.
 
+config MFD_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF controller driver"
+   select MFD_CORE
+   depends on ARCH_RENESAS
+   help
+ This supports Renesas R-Car Gen3 RPC-IF controller which provides
+ either SPI host or HyperFlash.
+ You have to select individual components under the corresponding menu.
+
 config MFD_RT5033
tristate "Richtek RT5033 Power Management IC"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 52b1a90..459eb2f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -184,6 +184,7 @@ obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO)  += 
intel_quark_i2c_gpio.o
 obj-$(CONFIG_LPC_SCH)  += lpc_sch.o
 obj-$(CONFIG_LPC_ICH)  += lpc_ich.o
 obj-$(CONFIG_MFD_RDC321X)  += rdc321x-southbridge.o
+obj-$(CONFIG_MFD_RENESAS_RPC)  += renesas-rpc.o
 obj-$(CONFIG_MFD_JANZ_CMODIO)  += janz-cmodio.o
 obj-$(CONFIG_MFD_JZ4740_ADC)   += jz4740-adc.o
 obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o
diff --git a/drivers/mfd/renesas-rpc.c b/drivers/mfd/renesas-rpc.c
new file mode 100644
index 000..c80c8d1
--- /dev/null
+++ b/drivers/mfd/renesas-rpc.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF MFD driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static const struct mfd_cell rpc_hf_ctlr = {
+   .name = "rpc-hf",
+};
+
+static const struct mfd_cell rpc_spi_ctlr = {
+   .name = "rpc-spi",
+};
+
+static const struct regmap_range rpc_mfd_volatile_ranges[] = {
+   regmap_reg_range(RPC_SMRDR0, RPC_SMRDR1),
+   regmap_reg_range(RPC_SMWDR0, RPC_SMWDR1),
+   regmap_reg_range(RPC_CMNSR, RPC_CMNSR),
+};
+
+static const struct regmap_access_table rpc_mfd_volatile_table = {
+   .yes_ranges = rpc_mfd_volatile_ranges,
+   .n_yes_ranges   = ARRAY_SIZE(rpc_mfd_volatile_ranges),
+};
+
+static const struct regmap_config rpc_mfd_regmap_config = {
+   .reg_bits = 32,
+   .val_bits = 32,
+   .reg_stride = 4,
+   .fast_io = true,
+   .max_register = RPC_PHYOFFSET2,
+   .volatile_table = _mfd_volatile_table,
+};
+
+static int rpc_mfd_probe(struct platform_device *pdev)
+{
+   struct device_node *flash;
+   const struct mfd_cell *cell;
+   struct resource *res;
+   struct rpc_mfd *rpc;
+   void __iomem *base;
+
+   flash = of_get_next_child(pdev->dev.of_node, NULL);
+   if (!flash) {
+   dev_warn(>dev, "no flash node found\n");
+   return -ENODEV;
+   }
+
+   if (of_device_is_compatible(flash, "jedec,spi-nor")) {
+   cell = _spi_ctlr;
+   } else if (of_device_is_compatible(flash, "cfi-flash")) {
+   cell = _hf_ctlr;
+   } else {
+   dev_warn(>dev, "unknown flash type\n");
+   return -ENODEV;
+   }
+
+   rpc = devm_kzalloc(>dev, sizeof(*rpc), GFP_KERNEL);
+   if (!rpc)
+   return -ENOMEM;
+
+   rpc->clk_rpc = devm_clk_get(>dev, "rpc");
+   if (IS_ERR(rpc->clk_rpc))
+   return PTR_ERR(rpc->clk_rpc);
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   rpc->regmap = devm_regmap_init_mmio(>dev, base,
+   _mfd_regmap_config);
+   if (IS_ERR(rpc->regmap)) {
+   dev_err(>dev,
+   "failed to init regmap for rpc-mfd, error %ld\n",
+   PTR_ERR(rpc->regmap));
+   return PTR_ERR(rpc->regmap);
+   }
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
+   rpc->dirmap = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(rpc->dirmap))
+   rpc->dirmap = NULL;
+
+  

[PATCH v13 2/3] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-05-21 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 573 ++
 3 files changed, 580 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 0fba8f4..229f6d7 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -570,6 +570,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f2f78d0..2a6e052 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..86931cf
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,573 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct rpc_spi {
+   struct rpc_mfd *ddata;
+   u32 cur_speed_hz;
+   u32 cmd;
+   u32 addr;
+   u32 dummy;
+   u32 smcr;
+   u32 smenr;
+   u32 xferlen;
+   u32 totalxferlen;
+   enum spi_mem_data_dir xfer_dir;
+};
+
+static int rpc_spi_set_freq(struct rpc_spi *rpc, unsigned long freq)
+{
+   int ret;
+
+   if (rpc->cur_speed_hz == freq)
+   return 0;
+
+   ret = clk_set_rate(rpc->ddata->clk_rpc, freq);
+   if (ret)
+   return ret;
+
+   rpc->cur_speed_hz = freq;
+   return ret;
+}
+
+static void rpc_spi_hw_init(struct rpc_spi *rpc)
+{
+   //
+   // NOTE: The 0x260 are undocumented bits, but they must be set.
+   //   RPC_PHYCNT_STRTIM is strobe timing adjustment bit,
+   //   0x0 : the delay is biggest,
+   //   0x1 : the delay is 2nd biggest,
+   //   On H3 ES1.x, the value should be 0, while on others,
+   //   the value should be 6.
+   //
+   regmap_write(rpc->ddata->regmap, RPC_PHYCNT, RPC_PHYCNT_CAL |
+ RPC_PHYCNT_STRTIM(6) | 0x260);
+
+   //
+   // NOTE: The 0x1511144 are undocumented bits, but they must be set
+   //   for RPC_PHYOFFSET1.
+   //   The 0x31 are undocumented bits, but they must be set
+   //   for RPC_PHYOFFSET2.
+   //
+   regmap_write(rpc->ddata->regmap, RPC_PHYOFFSET1,
+RPC_PHYOFFSET1_DDRTMG(3) | 0x1511144);
+   regmap_write(rpc->ddata->regmap, RPC_PHYOFFSET2, 0x31 |
+RPC_PHYOFFSET2_OCTTMG(4));
+   regmap_write(rpc->ddata->regmap, RPC_SSLDR, RPC_SSLDR_SPNDL(7) |
+RPC_SSLDR_SLNDL(7) | RPC_SSLDR_SCKDL(7));
+   regmap_write(rpc->ddata->regmap, RPC_CMNCR, RPC_CMNCR_MD |
+RPC_CMNCR_SFDE | RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
+RPC_CMNCR_BSZ(0));
+}
+
+static int wait_msg_xfer_end(struct rpc_spi *rpc)
+{
+   u32 sts;
+
+   return regmap_read_poll_timeout(rpc->ddata->regmap, RPC_CMNSR, sts,
+   sts & RPC_CMNSR_TEND, 0, USEC_PER_SEC);
+}
+
+static u8 rpc_bits_set(u32 nbytes)
+{
+   nbytes = clamp(nbytes, 1U, 4U);
+
+   return GENMASK(3, 4 - nbytes);
+}
+
+static int rpc_spi_io_xfer(struct rpc_spi *rpc,
+  const void *tx_buf, void *rx_buf)
+{
+   u32 smenr, smcr, data, pos = 0;
+   int ret;
+
+   regmap_update_bits(rpc->ddata->regmap, RPC_CMNCR, RPC_CMNCR_MD,
+  RPC_CMNCR_MD);
+   regmap_write(rpc->ddata->regmap, RPC_SMDRENR, 0);
+   regmap_write(rpc->ddata->regmap, RPC_SMCMR, rpc->cmd);
+   regmap_write(rpc->ddata->regmap, RPC_SMDMCR, rpc->dummy);
+   re

[PATCH v13 3/3] dt-bindings: mfd: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-05-21 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mfd/renesas-rpc-if.txt | 65 ++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/renesas-rpc-if.txt

diff --git a/Documentation/devicetree/bindings/mfd/renesas-rpc-if.txt 
b/Documentation/devicetree/bindings/mfd/renesas-rpc-if.txt
new file mode 100644
index 000..20ec85b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/renesas-rpc-if.txt
@@ -0,0 +1,65 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+-
+
+RPC-IF supports both SPI NOR and HyperFlash (CFI-compliant flash)
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for RPC-IF registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain 1 entries for the module's clock
+- clock-names: should contain "rpc"
+- power-domains: should contain system-controller(sysc) for power-domain-cell
+- resets: should contain clock pulse generator(cpg) for reset-cell,
+ power-domain-cell and clock-cell
+- #address-cells: should be 1
+- #size-cells: should be 0
+
+Example:
+- SPI mode:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
+
+- HF mode:
+   rpc: spi@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "cypress,hyperflash", "cfi-flash";
+   reg = <0>;
+   };
+   };
-- 
1.9.1



[PATCH v2] mtd: rawnand: Add Macronix NAND read retry support

2019-05-17 Thread Mason Yang
Add support for Macronix NAND read retry.

Macronix NANDs support specific read operation for data recovery,
which can be enabled/disabled with a SET/GET_FEATURE.
Driver checks byte 167 of Vendor Blocks in ONFI parameter page table
to see if this high-reliability function is supported.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 57 
 1 file changed, 57 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index e287e71..1a4dc92 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -17,6 +17,62 @@
 
 #include "internals.h"
 
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_READ_RETRY_MODE 6
+
+struct nand_onfi_vendor_macronix {
+   u8 reserved[1];
+   u8 reliability_func;
+} __packed;
+
+/*
+ * Macronix NANDs support using SET/GET_FEATURES to enter/exit read retry mode
+ */
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+   int ret, feature_addr = ONFI_FEATURE_ADDR_READ_RETRY;
+
+   if (chip->parameters.supports_set_get_features &&
+   test_bit(feature_addr, chip->parameters.set_feature_list) &&
+   test_bit(feature_addr, chip->parameters.get_feature_list)) {
+   feature[0] = mode;
+   ret =  nand_set_features(chip, feature_addr, feature);
+   if (ret)
+   pr_err("Failed to set read retry moded:%d\n", mode);
+
+   ret =  nand_get_features(chip, feature_addr, feature);
+   if (ret || feature[0] != mode)
+   pr_err("Failed to verify read retry moded:%d(%d)\n",
+  mode, feature[0]);
+   }
+
+   return ret;
+}
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+   struct nand_parameters *p = >parameters;
+   struct nand_onfi_vendor_macronix *mxic;
+
+   if (!p->onfi)
+   return;
+
+   mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
+   if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
+   return;
+
+   chip->read_retries = MACRONIX_READ_RETRY_MODE;
+   chip->setup_read_retry = macronix_nand_setup_read_retry;
+
+   if (p->supports_set_get_features) {
+   bitmap_set(p->set_feature_list,
+  ONFI_FEATURE_ADDR_READ_RETRY, 1);
+   bitmap_set(p->get_feature_list,
+  ONFI_FEATURE_ADDR_READ_RETRY, 1);
+   }
+}
+
 /*
  * Macronix AC series does not support using SET/GET_FEATURES to change
  * the timings unlike what is declared in the parameter page. Unflag
@@ -65,6 +121,7 @@ static int macronix_nand_init(struct nand_chip *chip)
chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
macronix_nand_fix_broken_get_timings(chip);
+   macronix_nand_onfi_init(chip);
 
return 0;
 }
-- 
1.9.1



[PATCH v1] mtd: rawnand: Add Macronix NAND read retry support

2019-05-10 Thread Mason Yang
Add a driver for Macronix NAND read retry.

Macronix NAND supports specfical read for data recovery and enabled
it by Set Feature.
Driver check byte 167 of Vendor Blocks in ONFI parameter page table
to see if this high reliability function is support or not.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 52 
 1 file changed, 52 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 47d8cda..5cd1e5f 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -17,6 +17,57 @@
 
 #include "internals.h"
 
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_READ_RETRY_MODE 5
+
+struct nand_onfi_vendor_macronix {
+   u8 reserved[1];
+   u8 reliability_func;
+} __packed;
+
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   if (mode > MACRONIX_READ_RETRY_MODE)
+   mode = MACRONIX_READ_RETRY_MODE;
+
+   feature[0] = mode;
+   ret =  nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+   if (ret)
+   pr_err("set feature failed to read retry moded:%d\n", mode);
+
+   ret =  nand_get_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+   if (ret || feature[0] != mode)
+   pr_err("get feature failed to read retry moded:%d(%d)\n",
+  mode, feature[0]);
+
+   return ret;
+}
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+   struct nand_parameters *p = >parameters;
+
+   if (p->onfi) {
+   struct nand_onfi_vendor_macronix *mxic =
+   (void *)p->onfi->vendor;
+
+   if (mxic->reliability_func & MACRONIX_READ_RETRY_BIT) {
+   chip->read_retries = MACRONIX_READ_RETRY_MODE + 1;
+   chip->setup_read_retry =
+macronix_nand_setup_read_retry;
+   if (p->supports_set_get_features) {
+   set_bit(ONFI_FEATURE_ADDR_READ_RETRY,
+   p->set_feature_list);
+   set_bit(ONFI_FEATURE_ADDR_READ_RETRY,
+   p->get_feature_list);
+   }
+   }
+   }
+}
+
 /*
  * Macronix AC series does not support using SET/GET_FEATURES to change
  * the timings unlike what is declared in the parameter page. Unflag
@@ -65,6 +116,7 @@ static int macronix_nand_init(struct nand_chip *chip)
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 
macronix_nand_fix_broken_get_timings(chip);
+   macronix_nand_onfi_init(chip);
 
return 0;
 }
-- 
1.9.1



[PATCH v3 3/4] spi: Patch Macronix SPI controller driver according to MX25F0A MFD driver

2019-04-15 Thread Mason Yang
Patch Macronix MX25F0A SPI controller driver according to it's MFD driver.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 275 +
 1 file changed, 49 insertions(+), 226 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index e41ae6e..f98f8e0 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -9,168 +9,13 @@
 //
 
 #include 
-#include 
-#include 
-#include 
-#include 
+#include 
 #include 
 #include 
 #include 
 
-#define HC_CFG 0x0
-#define HC_CFG_IF_CFG(x)   ((x) << 27)
-#define HC_CFG_DUAL_SLAVE  BIT(31)
-#define HC_CFG_INDIVIDUAL  BIT(30)
-#define HC_CFG_NIO(x)  (((x) / 4) << 27)
-#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
-#define HC_CFG_TYPE_SPI_NOR0
-#define HC_CFG_TYPE_SPI_NAND   1
-#define HC_CFG_TYPE_SPI_RAM2
-#define HC_CFG_TYPE_RAW_NAND   3
-#define HC_CFG_SLV_ACT(x)  ((x) << 21)
-#define HC_CFG_CLK_PH_EN   BIT(20)
-#define HC_CFG_CLK_POL_INV BIT(19)
-#define HC_CFG_BIG_ENDIAN  BIT(18)
-#define HC_CFG_DATA_PASS   BIT(17)
-#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
-#define HC_CFG_MAN_START_ENBIT(3)
-#define HC_CFG_MAN_START   BIT(2)
-#define HC_CFG_MAN_CS_EN   BIT(1)
-#define HC_CFG_MAN_CS_ASSERT   BIT(0)
-
-#define INT_STS0x4
-#define INT_STS_EN 0x8
-#define INT_SIG_EN 0xc
-#define INT_STS_ALLGENMASK(31, 0)
-#define INT_RDY_PINBIT(26)
-#define INT_RDY_SR BIT(25)
-#define INT_LNR_SUSP   BIT(24)
-#define INT_ECC_ERRBIT(17)
-#define INT_CRC_ERRBIT(16)
-#define INT_LWR_DISBIT(12)
-#define INT_LRD_DISBIT(11)
-#define INT_SDMA_INT   BIT(10)
-#define INT_DMA_FINISH BIT(9)
-#define INT_RX_NOT_FULLBIT(3)
-#define INT_RX_NOT_EMPTY   BIT(2)
-#define INT_TX_NOT_FULLBIT(1)
-#define INT_TX_EMPTY   BIT(0)
-
-#define HC_EN  0x10
-#define HC_EN_BIT  BIT(0)
-
-#define TXD(x) (0x14 + ((x) * 4))
-#define RXD0x24
-
-#define SS_CTRL(s) (0x30 + ((s) * 4))
-#define LRD_CFG0x44
-#define LWR_CFG0x80
-#define RWW_CFG0x70
-#define OP_READBIT(23)
-#define OP_DUMMY_CYC(x)((x) << 17)
-#define OP_ADDR_BYTES(x)   ((x) << 14)
-#define OP_CMD_BYTES(x)(((x) - 1) << 13)
-#define OP_OCTA_CRC_EN BIT(12)
-#define OP_DQS_EN  BIT(11)
-#define OP_ENHC_EN BIT(10)
-#define OP_PREAMBLE_EN BIT(9)
-#define OP_DATA_DDRBIT(8)
-#define OP_DATA_BUSW(x)((x) << 6)
-#define OP_ADDR_DDRBIT(5)
-#define OP_ADDR_BUSW(x)((x) << 3)
-#define OP_CMD_DDR BIT(2)
-#define OP_CMD_BUSW(x) (x)
-#define OP_BUSW_1  0
-#define OP_BUSW_2  1
-#define OP_BUSW_4  2
-#define OP_BUSW_8  3
-
-#define OCTA_CRC   0x38
-#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
-#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
-#define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16))
-
-#define ONFI_DIN_CNT(s)(0x3c + (s))
-
-#define LRD_CTRL   0x48
-#define RWW_CTRL   0x74
-#define LWR_CTRL   0x84
-#define LMODE_EN   BIT(31)
-#define LMODE_SLV_ACT(x)   ((x) << 21)
-#define LMODE_CMD1(x)  ((x) << 8)
-#define LMODE_CMD0(x)  (x)
-
-#define LRD_ADDR   0x4c
-#define LWR_ADDR   0x88
-#define LRD_RANGE  0x50
-#define LWR_RANGE  0x8c
-
-#define AXI_SLV_ADDR   0x54
-
-#define DMAC_RD_CFG0x58
-#define DMAC_WR_CFG0x94
-#define DMAC_CFG_PERIPH_EN BIT(31)
-#define DMAC_CFG_ALLFLUSH_EN   BIT(30)
-#define DMAC_CFG_LASTFLUSH_EN  BIT(29)
-#define DMAC_CFG_QE(x) (((x) + 1) << 16)
-#define DMAC_CFG_BURST_LEN(x)  (((x) + 1) << 12)
-#define DMAC_CFG_BURST_SZ(x)   ((x) << 8)
-#define DMAC_CFG_DIR_READ  BIT(1)
-#define DMAC_CFG_START BIT(0)
-
-#define DMAC_RD_CNT0x5c
-#define DMAC_WR_CNT0x98
-
-#define SDMA_ADDR  0x60
-
-#define DMAM_CFG   0x64
-#define DMAM_CFG_START BIT(31)
-#define DMAM_CFG_CONT  BIT(30)
-#define DMAM_CFG_SDMA_GAP(x)   (fls((x) / 8192) << 2)
-#define DMAM_CFG_DIR_READ  BIT(1)
-#define DMAM_CFG_ENBIT(0)
-
-#define DMAM_CNT   0x68
-
-#define LNR_TIMER_TH   0x6c
-
-#define RDM_CFG0   0x78
-#define RDM_CFG0_POLY(x)   (x)
-
-#define RDM_CFG1   0x7c
-#define RDM_CFG1_RDM_ENBIT(31)
-#define RD

[PATCH v3 0/4] Add Macronix MX25F0A MFD driver for raw nand and spi

2019-04-15 Thread Mason Yang
Hi,

v3 patch is to rename the title of SPI controller driver.
"Patch Macronix SPI controller driver according to MX25F0A MFD driver"

v2s patches is to support Macronix MX25F0A MFD driver 
for raw nand and spi controller which is separated 
form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason

Mason Yang (4):
  mfd: Add Macronix MX25F0A MFD controller driver
  mtd: rawnand: Add Macronix MX25F0A NAND controller
  spi: Patch Macronix SPI controller driver according to MX25F0A MFD
driver
  dt-bindings: mfd: Document Macronix MX25F0A controller bindings

 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   |  51 
 drivers/mfd/Kconfig|   9 +
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/mxic-mx25f0a.c |  84 ++
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 294 +
 drivers/spi/spi-mxic.c | 275 ---
 include/linux/mfd/mxic-mx25f0a.h   | 175 
 9 files changed, 670 insertions(+), 226 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

-- 
1.9.1



[PATCH v3 1/4] mfd: Add Macronix MX25F0A MFD controller driver

2019-04-15 Thread Mason Yang
Add a driver for Macronix MX25F0A multifunction device controller.

Signed-off-by: Mason Yang 
---
 drivers/mfd/Kconfig  |   9 ++
 drivers/mfd/Makefile |   1 +
 drivers/mfd/mxic-mx25f0a.c   |  84 +++
 include/linux/mfd/mxic-mx25f0a.h | 175 +++
 4 files changed, 269 insertions(+)
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 26ad646..7e99e93 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -823,6 +823,15 @@ config MFD_MAX8998
  additional drivers must be enabled in order to use the functionality
  of the device.
 
+config MFD_MXIC_MX25F0A
+   tristate "Macronix mx25f0a multifunction device support"
+   select MFD_CORE
+   help
+ This supports for Macronix mx25f0a multifunction device controller
+ for raw nand or spi. You have to select individual components like
+ raw nand controller or spi host controller under the corresponding
+ menus.
+
 config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b4569ed7..dcfe8fd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -163,6 +163,7 @@ max8925-objs:= max8925-core.o 
max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)  += max8925.o
 obj-$(CONFIG_MFD_MAX8997)  += max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)  += max8998.o max8998-irq.o
+obj-$(CONFIG_MFD_MXIC_MX25F0A) += mxic-mx25f0a.o
 
 pcf50633-objs  := pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
diff --git a/drivers/mfd/mxic-mx25f0a.c b/drivers/mfd/mxic-mx25f0a.c
new file mode 100644
index 000..a884d97
--- /dev/null
+++ b/drivers/mfd/mxic-mx25f0a.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+
+static const struct mfd_cell mx25f0a_nand_ctlr = {
+   .name = "mxic-nand-ctlr",
+   .of_compatible = "mxicy,mx25f0a-nand-ctlr",
+};
+
+static const struct mfd_cell mx25f0a_spi_ctlr = {
+   .name = "mxic-spi",
+   .of_compatible = "mxicy,mx25f0a-spi",
+};
+
+static int mx25f0a_mfd_probe(struct platform_device *pdev)
+{
+   const struct mfd_cell *cell;
+   struct mx25f0a_mfd *mxic;
+   struct resource *res;
+   int ret;
+
+   ret = of_device_is_compatible(pdev->dev.of_node->child,
+ "jedec,spi-nor");
+   if (ret)
+   cell = _spi_ctlr;
+   else
+   cell = _nand_ctlr;
+
+   mxic = devm_kzalloc(>dev, sizeof(*mxic), GFP_KERNEL);
+   if (!mxic)
+   return -ENOMEM;
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   mxic->regs = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(mxic->regs))
+   return PTR_ERR(mxic->regs);
+
+   if (cell == _spi_ctlr) {
+   mxic->ps_clk = devm_clk_get(>dev, "ps_clk");
+   if (IS_ERR(mxic->ps_clk))
+   return PTR_ERR(mxic->ps_clk);
+
+   mxic->send_clk = devm_clk_get(>dev, "send_clk");
+   if (IS_ERR(mxic->send_clk))
+   return PTR_ERR(mxic->send_clk);
+
+   mxic->send_dly_clk = devm_clk_get(>dev, "send_dly_clk");
+   if (IS_ERR(mxic->send_dly_clk))
+   return PTR_ERR(mxic->send_dly_clk);
+   }
+
+   platform_set_drvdata(pdev, mxic);
+
+   ret = devm_mfd_add_devices(>dev, -1, cell, 1, NULL, 0, NULL);
+
+   return ret;
+}
+
+static const struct of_device_id mx25f0a_mfd_of_match[] = {
+   { .compatible = "mxic,mx25f0a", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, mx25f0a_mfd_of_match);
+
+static struct platform_driver mx25f0a_mfd_driver = {
+   .probe  = mx25f0a_mfd_probe,
+   .driver = {
+   .name = "mx25f0a-mfd",
+   .of_match_table = mx25f0a_mfd_of_match,
+   },
+};
+module_platform_driver(mx25f0a_mfd_driver);
+
+MODULE_AUTHOR("Mason Yang ");
+MODULE_DESCRIPTION("MX25F0A controller MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mxic-mx25f0a.h b/include/linux/mfd/mxic-mx25f0a.h
new file mode 100644
index 000..cb7bf19
--- /dev/null
+++ b/include/linux/mfd/mxic-mx25f0a.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Author:
+// Mason Yang 
+//
+
+#ifndef __MFD_MXIC_MX25F0A_H
+#define __MFD_MXIC_MX25F0A_H
+
+#i

[PATCH v3 2/4] mtd: rawnand: Add Macronix MX25F0A NAND controller

2019-04-15 Thread Mason Yang
Add a driver for Macronix MX25F0A NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 294 +++
 3 files changed, 301 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625..e0329cc 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -522,6 +522,12 @@ config MTD_NAND_QCOM
  Enables support for NAND flash chips on SoCs containing the EBI2 NAND
  controller. This controller is found on IPQ806x SoC.
 
+config MTD_NAND_MXIC
+   tristate "Macronix MX25F0A NAND controller"
+   depends on HAS_IOMEM
+   help
+ This selects the Macronix MX25F0A NAND controller driver.
+
 config MTD_NAND_MTK
tristate "Support for NAND controller on MTK SoCs"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f..c8a6790 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI)  += sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..689fae2
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Authors:
+// Mason Yang 
+// zhengxunli 
+//
+
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+struct mxic_nand_ctlr {
+   struct mx25f0a_mfd *mfd;
+   struct nand_controller base;
+   struct nand_chip nand;
+};
+
+static void mxic_host_init(struct mxic_nand_ctlr *mxic)
+{
+   writel(DATA_STROB_EDO_EN, mxic->mfd->regs + DATA_STROB);
+   writel(INT_STS_ALL, mxic->mfd->regs + INT_STS_EN);
+   writel(0x0, mxic->mfd->regs + ONFI_DIN_CNT(0));
+   writel(HC_CFG_NIO(8) | HC_CFG_SLV_ACT(0) | HC_CFG_IDLE_SIO_LVL(1) |
+  HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) | HC_CFG_MAN_CS_EN,
+  mxic->mfd->regs + HC_CFG);
+   writel(0x0, mxic->mfd->regs + HC_EN);
+}
+
+static int  mxic_nand_wait_ready(struct nand_chip *chip)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+   u32 sts;
+
+   return readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+ sts & INT_RDY_PIN, 0, USEC_PER_SEC);
+}
+
+static void mxic_nand_select_chip(struct nand_chip *chip, int chipnr)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+
+   switch (chipnr) {
+   case 0:
+   case 1:
+   writel(HC_EN_BIT, mxic->mfd->regs + HC_EN);
+   writel(HC_CFG_MAN_CS_ASSERT | readl(mxic->mfd->regs + HC_CFG),
+  mxic->mfd->regs + HC_CFG);
+   break;
+
+   case -1:
+   writel(~HC_CFG_MAN_CS_ASSERT & readl(mxic->mfd->regs + HC_CFG),
+  mxic->mfd->regs + HC_CFG);
+   writel(0, mxic->mfd->regs + HC_EN);
+   break;
+
+   default:
+   break;
+   }
+}
+
+static int mxic_nand_data_xfer(struct mxic_nand_ctlr *mxic, const void *txbuf,
+  void *rxbuf, unsigned int len)
+{
+   unsigned int pos = 0;
+
+   while (pos < len) {
+   unsigned int nbytes = len - pos;
+   u32 data = 0x;
+   u32 sts;
+   int ret;
+
+   if (nbytes > 4)
+   nbytes = 4;
+
+   if (txbuf)
+   memcpy(, txbuf + pos, nbytes);
+
+   ret = readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+   writel(data, mxic->mfd->regs + TXD(nbytes % 4));
+
+   if (rxbuf) {
+   ret = readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0,
+USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+

[PATCH v3 4/4] dt-bindings: mfd: Document Macronix MX25F0A controller bindings

2019-04-15 Thread Mason Yang
Document the bindings used by the Macronix MX25F0A MFD controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   | 51 ++
 1 file changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt

diff --git a/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt 
b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
new file mode 100644
index 000..7f3e0f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
@@ -0,0 +1,51 @@
+Macronix MX25F0A MultiFunction Device Tree Bindings
+
+
+MX25F0A is a MultiFunction Device with SPI and raw NAND, which
+supports either spi host controller or raw nand controller.
+
+Required properties:
+- compatible: should be "mxic,mx25f0a"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area in SPI mode.
+- reg-names: should contain "regs" and "dirmap"
+- interrupts: interrupt line connected to this MFD controller
+- SPI controller driver:
+   - clock-names: should contain "ps_clk", "send_clk" and
+  "send_dly_clk"
+   - clocks: should contain 3 entries for the "ps_clk", "send_clk"
+ and "send_dly_clk" clocks
+
+- Raw nand controller driver.
+   - nand-ecc-mode = "soft";
+   - nand-ecc-algo = "bch";
+
+Example:
+
+   mxic: mx25f0a@43c3 {
+   compatible = "mxic,mx25f0a";
+   reg = <0x43c3 0x1>, <0xa000 0x400>;
+   reg-names = "regs", "dirmap";
+
+   /* spi */
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send_clk", "send_dly_clk", "ps_clk";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <2500>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
+   };
+
+   /* nand */
+   nand-ecc-mode = "soft";
+   nand-ecc-algo = "bch";
+   nand-ecc-step-size = <512>;
+   nand-ecc-strength = <8>;
+   };
-- 
1.9.1



[PATCH] mtd: rawnand: Add Macronix NAND read retry and randomizer support

2019-04-08 Thread Mason Yang
Add a driver for Macronix NAND read retry and randomizer.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 169 +++
 1 file changed, 169 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 47d8cda..a19caa4 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -17,6 +17,174 @@
 
 #include "internals.h"
 
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_RANDOMIZER_BIT BIT(1)
+#define MACRONIX_READ_RETRY_MODE 5
+
+#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
+
+struct nand_onfi_vendor_macronix {
+   u8 reserved[1];
+   u8 reliability_func;
+} __packed;
+
+struct nand_chip *mxic_sysfs;
+
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   if (mode > MACRONIX_READ_RETRY_MODE)
+   mode = MACRONIX_READ_RETRY_MODE;
+
+   feature[0] = mode;
+   ret =  nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+   if (ret)
+   pr_err("failed to enter read retry moded:%d\n", mode);
+
+   if (mode == 0)
+   ret =  nand_get_features(chip, ONFI_FEATURE_ADDR_READ_RETRY,
+feature);
+   if (ret)
+   pr_err("failed to exits read retry moded:%d\n", mode);
+
+   return ret;
+}
+
+static ssize_t mxic_nand_rand_type_show(struct kobject *kobj,
+   struct kobj_attribute *attr, char *buf)
+{
+   struct nand_chip *chip = mxic_sysfs;
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   nand_select_target(chip, 0);
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("failed to check mxic nand device randomizer\n");
+
+   return sprintf(buf, "MXIC NAND device randomizer %s(0x%x)\n",
+  feature[0] & MACRONIX_RANDOMIZER_BIT ?
+  "enable" : "disable", feature[0]);
+}
+
+static ssize_t mxic_nand_rand_type_store(struct kobject *kobj,
+struct kobj_attribute *attr,
+const char *buf, size_t count)
+{
+   struct nand_chip *chip = mxic_sysfs;
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   unsigned int rand_layout;
+   int ret;
+
+   nand_select_target(chip, 0);
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+
+   if (feature[0]) {
+   pr_err("Randomizer is enabled 0x%x\n", feature[0]);
+   goto err_out;
+   }
+
+   ret = kstrtouint(buf, 0, _layout);
+   if (ret)
+   goto err_out;
+
+   if (rand_layout > 7) {
+   pr_err("Error parameter value:0x%x\n", rand_layout);
+   goto err_out;
+   }
+
+   feature[0] = rand_layout & 0x07;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret) {
+   pr_err("device randomizer set feature failed\n");
+   goto err_out;
+   }
+
+   feature[0] = 0x0;
+   nand_select_target(chip, 0);
+   ret = nand_prog_page_op(chip, 0, 0, feature, 1);
+   nand_deselect_target(chip);
+   if (ret) {
+   pr_err("Prog device randomizer failed\n");
+   goto err_out;
+   }
+
+   feature[0] = 0x0;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("failed to exits prog device randomizer\n");
+
+err_out:
+   return count;
+}
+
+static const struct kobj_attribute sysfs_mxic_nand =
+   __ATTR(nand_random, S_IRUGO | S_IWUSR,
+  mxic_nand_rand_type_show,
+  mxic_nand_rand_type_store);
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+   struct nand_parameters *p = >parameters;
+   struct kobject *kobj;
+   int ret;
+
+   mxic_sysfs = chip;
+   if (p->onfi) {
+   struct nand_onfi_vendor_macronix *mxic =
+   (void *)p->onfi->vendor;
+
+   if (mxic->reliability_func & MACRONIX_READ_RETRY_BIT) {
+   chip->read_retries = MACRONIX_READ_RETRY_MODE + 1;
+   chip->setup_read_retry =
+

[PATCH v2 2/4] mtd: rawnand: Add Macronix MX25F0A NAND controller driver

2019-04-08 Thread Mason Yang
Add a driver for Macronix MX25F0A NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 294 +++
 3 files changed, 301 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625..e0329cc 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -522,6 +522,12 @@ config MTD_NAND_QCOM
  Enables support for NAND flash chips on SoCs containing the EBI2 NAND
  controller. This controller is found on IPQ806x SoC.
 
+config MTD_NAND_MXIC
+   tristate "Macronix MX25F0A NAND controller"
+   depends on HAS_IOMEM
+   help
+ This selects the Macronix MX25F0A NAND controller driver.
+
 config MTD_NAND_MTK
tristate "Support for NAND controller on MTK SoCs"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f..c8a6790 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI)  += sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..689fae2
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Authors:
+// Mason Yang 
+// zhengxunli 
+//
+
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+struct mxic_nand_ctlr {
+   struct mx25f0a_mfd *mfd;
+   struct nand_controller base;
+   struct nand_chip nand;
+};
+
+static void mxic_host_init(struct mxic_nand_ctlr *mxic)
+{
+   writel(DATA_STROB_EDO_EN, mxic->mfd->regs + DATA_STROB);
+   writel(INT_STS_ALL, mxic->mfd->regs + INT_STS_EN);
+   writel(0x0, mxic->mfd->regs + ONFI_DIN_CNT(0));
+   writel(HC_CFG_NIO(8) | HC_CFG_SLV_ACT(0) | HC_CFG_IDLE_SIO_LVL(1) |
+  HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) | HC_CFG_MAN_CS_EN,
+  mxic->mfd->regs + HC_CFG);
+   writel(0x0, mxic->mfd->regs + HC_EN);
+}
+
+static int  mxic_nand_wait_ready(struct nand_chip *chip)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+   u32 sts;
+
+   return readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+ sts & INT_RDY_PIN, 0, USEC_PER_SEC);
+}
+
+static void mxic_nand_select_chip(struct nand_chip *chip, int chipnr)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+
+   switch (chipnr) {
+   case 0:
+   case 1:
+   writel(HC_EN_BIT, mxic->mfd->regs + HC_EN);
+   writel(HC_CFG_MAN_CS_ASSERT | readl(mxic->mfd->regs + HC_CFG),
+  mxic->mfd->regs + HC_CFG);
+   break;
+
+   case -1:
+   writel(~HC_CFG_MAN_CS_ASSERT & readl(mxic->mfd->regs + HC_CFG),
+  mxic->mfd->regs + HC_CFG);
+   writel(0, mxic->mfd->regs + HC_EN);
+   break;
+
+   default:
+   break;
+   }
+}
+
+static int mxic_nand_data_xfer(struct mxic_nand_ctlr *mxic, const void *txbuf,
+  void *rxbuf, unsigned int len)
+{
+   unsigned int pos = 0;
+
+   while (pos < len) {
+   unsigned int nbytes = len - pos;
+   u32 data = 0x;
+   u32 sts;
+   int ret;
+
+   if (nbytes > 4)
+   nbytes = 4;
+
+   if (txbuf)
+   memcpy(, txbuf + pos, nbytes);
+
+   ret = readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+   writel(data, mxic->mfd->regs + TXD(nbytes % 4));
+
+   if (rxbuf) {
+   ret = readl_poll_timeout(mxic->mfd->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0,
+USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+

[PATCH v2 3/4] spi: Add MFD for Macronix MX25F0A SPI controller driver

2019-04-08 Thread Mason Yang
Add a MFD driver for Macronix MX25F0A SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 275 +
 1 file changed, 49 insertions(+), 226 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index e41ae6e..f98f8e0 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -9,168 +9,13 @@
 //
 
 #include 
-#include 
-#include 
-#include 
-#include 
+#include 
 #include 
 #include 
 #include 
 
-#define HC_CFG 0x0
-#define HC_CFG_IF_CFG(x)   ((x) << 27)
-#define HC_CFG_DUAL_SLAVE  BIT(31)
-#define HC_CFG_INDIVIDUAL  BIT(30)
-#define HC_CFG_NIO(x)  (((x) / 4) << 27)
-#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
-#define HC_CFG_TYPE_SPI_NOR0
-#define HC_CFG_TYPE_SPI_NAND   1
-#define HC_CFG_TYPE_SPI_RAM2
-#define HC_CFG_TYPE_RAW_NAND   3
-#define HC_CFG_SLV_ACT(x)  ((x) << 21)
-#define HC_CFG_CLK_PH_EN   BIT(20)
-#define HC_CFG_CLK_POL_INV BIT(19)
-#define HC_CFG_BIG_ENDIAN  BIT(18)
-#define HC_CFG_DATA_PASS   BIT(17)
-#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
-#define HC_CFG_MAN_START_ENBIT(3)
-#define HC_CFG_MAN_START   BIT(2)
-#define HC_CFG_MAN_CS_EN   BIT(1)
-#define HC_CFG_MAN_CS_ASSERT   BIT(0)
-
-#define INT_STS0x4
-#define INT_STS_EN 0x8
-#define INT_SIG_EN 0xc
-#define INT_STS_ALLGENMASK(31, 0)
-#define INT_RDY_PINBIT(26)
-#define INT_RDY_SR BIT(25)
-#define INT_LNR_SUSP   BIT(24)
-#define INT_ECC_ERRBIT(17)
-#define INT_CRC_ERRBIT(16)
-#define INT_LWR_DISBIT(12)
-#define INT_LRD_DISBIT(11)
-#define INT_SDMA_INT   BIT(10)
-#define INT_DMA_FINISH BIT(9)
-#define INT_RX_NOT_FULLBIT(3)
-#define INT_RX_NOT_EMPTY   BIT(2)
-#define INT_TX_NOT_FULLBIT(1)
-#define INT_TX_EMPTY   BIT(0)
-
-#define HC_EN  0x10
-#define HC_EN_BIT  BIT(0)
-
-#define TXD(x) (0x14 + ((x) * 4))
-#define RXD0x24
-
-#define SS_CTRL(s) (0x30 + ((s) * 4))
-#define LRD_CFG0x44
-#define LWR_CFG0x80
-#define RWW_CFG0x70
-#define OP_READBIT(23)
-#define OP_DUMMY_CYC(x)((x) << 17)
-#define OP_ADDR_BYTES(x)   ((x) << 14)
-#define OP_CMD_BYTES(x)(((x) - 1) << 13)
-#define OP_OCTA_CRC_EN BIT(12)
-#define OP_DQS_EN  BIT(11)
-#define OP_ENHC_EN BIT(10)
-#define OP_PREAMBLE_EN BIT(9)
-#define OP_DATA_DDRBIT(8)
-#define OP_DATA_BUSW(x)((x) << 6)
-#define OP_ADDR_DDRBIT(5)
-#define OP_ADDR_BUSW(x)((x) << 3)
-#define OP_CMD_DDR BIT(2)
-#define OP_CMD_BUSW(x) (x)
-#define OP_BUSW_1  0
-#define OP_BUSW_2  1
-#define OP_BUSW_4  2
-#define OP_BUSW_8  3
-
-#define OCTA_CRC   0x38
-#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
-#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
-#define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16))
-
-#define ONFI_DIN_CNT(s)(0x3c + (s))
-
-#define LRD_CTRL   0x48
-#define RWW_CTRL   0x74
-#define LWR_CTRL   0x84
-#define LMODE_EN   BIT(31)
-#define LMODE_SLV_ACT(x)   ((x) << 21)
-#define LMODE_CMD1(x)  ((x) << 8)
-#define LMODE_CMD0(x)  (x)
-
-#define LRD_ADDR   0x4c
-#define LWR_ADDR   0x88
-#define LRD_RANGE  0x50
-#define LWR_RANGE  0x8c
-
-#define AXI_SLV_ADDR   0x54
-
-#define DMAC_RD_CFG0x58
-#define DMAC_WR_CFG0x94
-#define DMAC_CFG_PERIPH_EN BIT(31)
-#define DMAC_CFG_ALLFLUSH_EN   BIT(30)
-#define DMAC_CFG_LASTFLUSH_EN  BIT(29)
-#define DMAC_CFG_QE(x) (((x) + 1) << 16)
-#define DMAC_CFG_BURST_LEN(x)  (((x) + 1) << 12)
-#define DMAC_CFG_BURST_SZ(x)   ((x) << 8)
-#define DMAC_CFG_DIR_READ  BIT(1)
-#define DMAC_CFG_START BIT(0)
-
-#define DMAC_RD_CNT0x5c
-#define DMAC_WR_CNT0x98
-
-#define SDMA_ADDR  0x60
-
-#define DMAM_CFG   0x64
-#define DMAM_CFG_START BIT(31)
-#define DMAM_CFG_CONT  BIT(30)
-#define DMAM_CFG_SDMA_GAP(x)   (fls((x) / 8192) << 2)
-#define DMAM_CFG_DIR_READ  BIT(1)
-#define DMAM_CFG_ENBIT(0)
-
-#define DMAM_CNT   0x68
-
-#define LNR_TIMER_TH   0x6c
-
-#define RDM_CFG0   0x78
-#define RDM_CFG0_POLY(x)   (x)
-
-#define RDM_CFG1   0x7c
-#define RDM_CFG1_RDM_ENBIT(31)
-#define RDM_CFG1_SEED(x)   (

[PATCH v2 0/4] Add Macronix MX25F0A MFD driver for raw nand and spi

2019-04-08 Thread Mason Yang
Hi,

This patches support Macronix MX25F0A MFD driver for raw nand and spi
controller which is separated form previous patchset:

https://patchwork.kernel.org/patch/10874679/

thanks for your review.

best regards,
Mason

Mason Yang (4):
  mfd: Add Macronix MX25F0A MFD controller driver
  mtd: rawnand: Add Macronix MX25F0A NAND controller driver
  spi: Add MFD for Macronix MX25F0A SPI controller driver
  dt-bindings: mfd: Document Macronix MX25F0A controller bindings

 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   |  51 
 drivers/mfd/Kconfig|   9 +
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/mxic-mx25f0a.c |  84 ++
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 294 +
 drivers/spi/spi-mxic.c | 275 ---
 include/linux/mfd/mxic-mx25f0a.h   | 175 
 9 files changed, 670 insertions(+), 226 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

-- 
1.9.1



[PATCH v2 4/4] dt-bindings: mfd: Document Macronix MX25F0A controller bindings

2019-04-08 Thread Mason Yang
Document the bindings used by the Macronix MX25F0A MFD controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   | 51 ++
 1 file changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt

diff --git a/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt 
b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
new file mode 100644
index 000..7f3e0f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
@@ -0,0 +1,51 @@
+Macronix MX25F0A MultiFunction Device Tree Bindings
+
+
+MX25F0A is a MultiFunction Device with SPI and raw NAND, which
+supports either spi host controller or raw nand controller.
+
+Required properties:
+- compatible: should be "mxic,mx25f0a"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area in SPI mode.
+- reg-names: should contain "regs" and "dirmap"
+- interrupts: interrupt line connected to this MFD controller
+- SPI controller driver:
+   - clock-names: should contain "ps_clk", "send_clk" and
+  "send_dly_clk"
+   - clocks: should contain 3 entries for the "ps_clk", "send_clk"
+ and "send_dly_clk" clocks
+
+- Raw nand controller driver.
+   - nand-ecc-mode = "soft";
+   - nand-ecc-algo = "bch";
+
+Example:
+
+   mxic: mx25f0a@43c3 {
+   compatible = "mxic,mx25f0a";
+   reg = <0x43c3 0x1>, <0xa000 0x400>;
+   reg-names = "regs", "dirmap";
+
+   /* spi */
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send_clk", "send_dly_clk", "ps_clk";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <2500>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
+   };
+
+   /* nand */
+   nand-ecc-mode = "soft";
+   nand-ecc-algo = "bch";
+   nand-ecc-step-size = <512>;
+   nand-ecc-strength = <8>;
+   };
-- 
1.9.1



[PATCH v2 1/4] mfd: Add Macronix MX25F0A MFD controller driver

2019-04-08 Thread Mason Yang
Add a driver for Macronix MX25F0A multifunction device controller.

Signed-off-by: Mason Yang 
---
 drivers/mfd/Kconfig  |   9 ++
 drivers/mfd/Makefile |   1 +
 drivers/mfd/mxic-mx25f0a.c   |  84 +++
 include/linux/mfd/mxic-mx25f0a.h | 175 +++
 4 files changed, 269 insertions(+)
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 26ad646..7e99e93 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -823,6 +823,15 @@ config MFD_MAX8998
  additional drivers must be enabled in order to use the functionality
  of the device.
 
+config MFD_MXIC_MX25F0A
+   tristate "Macronix mx25f0a multifunction device support"
+   select MFD_CORE
+   help
+ This supports for Macronix mx25f0a multifunction device controller
+ for raw nand or spi. You have to select individual components like
+ raw nand controller or spi host controller under the corresponding
+ menus.
+
 config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b4569ed7..dcfe8fd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -163,6 +163,7 @@ max8925-objs:= max8925-core.o 
max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)  += max8925.o
 obj-$(CONFIG_MFD_MAX8997)  += max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)  += max8998.o max8998-irq.o
+obj-$(CONFIG_MFD_MXIC_MX25F0A) += mxic-mx25f0a.o
 
 pcf50633-objs  := pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
diff --git a/drivers/mfd/mxic-mx25f0a.c b/drivers/mfd/mxic-mx25f0a.c
new file mode 100644
index 000..a884d97
--- /dev/null
+++ b/drivers/mfd/mxic-mx25f0a.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+
+static const struct mfd_cell mx25f0a_nand_ctlr = {
+   .name = "mxic-nand-ctlr",
+   .of_compatible = "mxicy,mx25f0a-nand-ctlr",
+};
+
+static const struct mfd_cell mx25f0a_spi_ctlr = {
+   .name = "mxic-spi",
+   .of_compatible = "mxicy,mx25f0a-spi",
+};
+
+static int mx25f0a_mfd_probe(struct platform_device *pdev)
+{
+   const struct mfd_cell *cell;
+   struct mx25f0a_mfd *mxic;
+   struct resource *res;
+   int ret;
+
+   ret = of_device_is_compatible(pdev->dev.of_node->child,
+ "jedec,spi-nor");
+   if (ret)
+   cell = _spi_ctlr;
+   else
+   cell = _nand_ctlr;
+
+   mxic = devm_kzalloc(>dev, sizeof(*mxic), GFP_KERNEL);
+   if (!mxic)
+   return -ENOMEM;
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   mxic->regs = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(mxic->regs))
+   return PTR_ERR(mxic->regs);
+
+   if (cell == _spi_ctlr) {
+   mxic->ps_clk = devm_clk_get(>dev, "ps_clk");
+   if (IS_ERR(mxic->ps_clk))
+   return PTR_ERR(mxic->ps_clk);
+
+   mxic->send_clk = devm_clk_get(>dev, "send_clk");
+   if (IS_ERR(mxic->send_clk))
+   return PTR_ERR(mxic->send_clk);
+
+   mxic->send_dly_clk = devm_clk_get(>dev, "send_dly_clk");
+   if (IS_ERR(mxic->send_dly_clk))
+   return PTR_ERR(mxic->send_dly_clk);
+   }
+
+   platform_set_drvdata(pdev, mxic);
+
+   ret = devm_mfd_add_devices(>dev, -1, cell, 1, NULL, 0, NULL);
+
+   return ret;
+}
+
+static const struct of_device_id mx25f0a_mfd_of_match[] = {
+   { .compatible = "mxic,mx25f0a", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, mx25f0a_mfd_of_match);
+
+static struct platform_driver mx25f0a_mfd_driver = {
+   .probe  = mx25f0a_mfd_probe,
+   .driver = {
+   .name = "mx25f0a-mfd",
+   .of_match_table = mx25f0a_mfd_of_match,
+   },
+};
+module_platform_driver(mx25f0a_mfd_driver);
+
+MODULE_AUTHOR("Mason Yang ");
+MODULE_DESCRIPTION("MX25F0A controller MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mxic-mx25f0a.h b/include/linux/mfd/mxic-mx25f0a.h
new file mode 100644
index 000..cb7bf19
--- /dev/null
+++ b/include/linux/mfd/mxic-mx25f0a.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Author:
+// Mason Yang 
+//
+
+#ifndef __MFD_MXIC_MX25F0A_H
+#define __MFD_MXIC_MX25F0A_H
+
+#i

[PATCH 4/7] dt-bindings: mfd: Document Macronix MX25F0A controller bindings

2019-03-28 Thread Mason Yang
Document the bindings used by the Macronix MX25F0A MFD controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   | 66 ++
 1 file changed, 66 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt

diff --git a/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt 
b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
new file mode 100644
index 000..53b4839
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
@@ -0,0 +1,66 @@
+Macronix MX25F0A Multi-Function Device Tree Bindings
+
+
+MX25F0A is a MultiFunction Device with SPI and raw NAND, which
+supports either spi host controller or raw nand controller.
+
+Required properties:
+- compatible: should be "mxic,mx25f0a-mfd"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area in SPI mode.
+- reg-names: should contain "regs" and "dirmap"
+- interrupts: interrupt line connected to this MFD controller
+
+Required nodes:
+ - spi :
+   Node for configuring the SPI controller driver.
+   Required properties:
+   - compatible = "mxicy,mx25f0a-spi";
+   - clock-names: should contain "ps_clk", "send_clk" and
+  "send_dly_clk"
+   - clocks: should contain 3 entries for the "ps_clk", "send_clk"
+ and "send_dly_clk" clocks
+
+- nand :
+   Node for configuring the raw nand controller driver.
+   Required properties:
+   - compatible = "mxicy,mx25f0a-nand-ctlr";
+   - nand-ecc-mode = "soft";
+   - nand-ecc-algo = "bch";
+
+Example:
+
+   mxic: mx25f0a-mfd@43c3 {
+   compatible = "mxic,mx25f0a-mfd";
+   reg = <0x43c3 0x1>, <0xa000 0x400>;
+   reg-names = "regs", "dirmap";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   /* either spi or nand */
+   spi {
+   compatible = "mxicy,mx25f0a-spi";
+   clocks = < 0>, < 1>, < 15>;
+   clock-names = "send_clk", "send_dly_clk", "ps_clk";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <2500>;
+   spi-tx-bus-width = <4>;
+   spi-rx-bus-width = <4>;
+   };
+   };
+
+   nand {
+   compatible = "mxicy,mx25f0a-nand-ctlr";
+   nand-ecc-mode = "soft";
+   nand-ecc-algo = "bch";
+   nand-ecc-step-size = <512>;
+   nand-ecc-strength = <8>;
+   };
+   };
-- 
1.9.1



[PATCH 7/7] mtd: rawnand: Add Macronix NAND block protection driver

2019-03-28 Thread Mason Yang
Add a driver for Macronix NAND block protection function.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/mxic_nand.c |  3 +++
 drivers/mtd/nand/raw/nand_macronix.c | 47 
 include/linux/mfd/mxic-mx25f0a.h |  3 +++
 3 files changed, 53 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
index 03886b2..9307ca2 100644
--- a/drivers/mtd/nand/raw/mxic_nand.c
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -262,6 +262,9 @@ static int mx25f0a_nand_probe(struct platform_device *pdev)
if (err)
goto fail;
 
+   mtd->_lock = mxic_nand_lock;
+   mtd->_unlock = mxic_nand_unlock;
+
err = mtd_device_register(mtd, NULL, 0);
if (err)
goto fail;
diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index a19caa4..db63350 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -21,8 +21,12 @@
 #define MACRONIX_RANDOMIZER_BIT BIT(1)
 #define MACRONIX_READ_RETRY_MODE 5
 
+#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0
 #define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
 
+#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38
+#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0
+
 struct nand_onfi_vendor_macronix {
u8 reserved[1];
u8 reliability_func;
@@ -146,6 +150,13 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
struct nand_onfi_vendor_macronix *mxic =
(void *)p->onfi->vendor;
 
+   if (p->supports_set_get_features) {
+   set_bit(ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   p->get_feature_list);
+   set_bit(ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   p->set_feature_list);
+   }
+
if (mxic->reliability_func & MACRONIX_READ_RETRY_BIT) {
chip->read_retries = MACRONIX_READ_RETRY_MODE + 1;
chip->setup_read_retry =
@@ -241,3 +252,39 @@ static int macronix_nand_init(struct nand_chip *chip)
 const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
.init = macronix_nand_init,
 };
+
+int mxic_nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("Lock MXIC NAND all blocks failed, err:%d\n", ret);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(mxic_nand_lock);
+
+int mxic_nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+   struct nand_chip *chip = mtd_to_nand(mtd);
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("Unlock MXIC NAND all blocks failed, err:%d\n", ret);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(mxic_nand_unlock);
diff --git a/include/linux/mfd/mxic-mx25f0a.h b/include/linux/mfd/mxic-mx25f0a.h
index 5a8cfc7..cfce992 100644
--- a/include/linux/mfd/mxic-mx25f0a.h
+++ b/include/linux/mfd/mxic-mx25f0a.h
@@ -170,4 +170,7 @@ struct mx25f0a_mfd {
void __iomem *dirmap;
 };
 
+int mxic_nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+int mxic_nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+
 #endif // __MFD_MXIC_MX25F0A_H
-- 
1.9.1



[PATCH 0/7] Add Macronix MX25F0A MFD driver and NAND function

2019-03-28 Thread Mason Yang
Hi,

These patches support
1. Add Macronix MX25F0A MFD driver for SPI and raw NAND controller.
2. Add direct mapping read mode for SPI host controller.
3. Macronix NAND device read retry and randomizer function.
4. Macronix NAND device block protection function.

thanks for your review.

best regards,
Mason


Mason Yang (7):
  mfd: Add Macronix MX25F0A MFD controller driver
  mtd: rawnand: Add Macronix MX25F0A NAND controller driver
  spi: Patch Macronix MX25F0A SPI controller driver
  dt-bindings: mfd: Document Macronix MX25F0A controller bindings
  spi: Add direct mapping mode for Macronix SPI controller
  mtd: rawnand: Add Macronix NAND read retry and randomizer support
  mtd: rawnand: Add Macronix NAND block protection driver

 .../devicetree/bindings/mfd/mxic-mx25f0a.txt   |  66 +
 drivers/mfd/Kconfig|   9 +
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/mxic-mx25f0a.c |  90 ++
 drivers/mtd/nand/raw/Kconfig   |   6 +
 drivers/mtd/nand/raw/Makefile  |   1 +
 drivers/mtd/nand/raw/mxic_nand.c   | 306 +
 drivers/mtd/nand/raw/nand_macronix.c   | 216 +++
 drivers/spi/spi-mxic.c | 288 +++
 include/linux/mfd/mxic-mx25f0a.h   | 176 
 10 files changed, 974 insertions(+), 185 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/mxic-mx25f0a.txt
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

-- 
1.9.1



[PATCH 6/7] mtd: rawnand: Add Macronix NAND read retry and randomizer support

2019-03-28 Thread Mason Yang
Add a driver for Macronix NAND read retry and randomizer.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/nand_macronix.c | 169 +++
 1 file changed, 169 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_macronix.c 
b/drivers/mtd/nand/raw/nand_macronix.c
index 47d8cda..a19caa4 100644
--- a/drivers/mtd/nand/raw/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
@@ -17,6 +17,174 @@
 
 #include "internals.h"
 
+#define MACRONIX_READ_RETRY_BIT BIT(0)
+#define MACRONIX_RANDOMIZER_BIT BIT(1)
+#define MACRONIX_READ_RETRY_MODE 5
+
+#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
+
+struct nand_onfi_vendor_macronix {
+   u8 reserved[1];
+   u8 reliability_func;
+} __packed;
+
+struct nand_chip *mxic_sysfs;
+
+static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
+{
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   if (mode > MACRONIX_READ_RETRY_MODE)
+   mode = MACRONIX_READ_RETRY_MODE;
+
+   feature[0] = mode;
+   ret =  nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
+   if (ret)
+   pr_err("failed to enter read retry moded:%d\n", mode);
+
+   if (mode == 0)
+   ret =  nand_get_features(chip, ONFI_FEATURE_ADDR_READ_RETRY,
+feature);
+   if (ret)
+   pr_err("failed to exits read retry moded:%d\n", mode);
+
+   return ret;
+}
+
+static ssize_t mxic_nand_rand_type_show(struct kobject *kobj,
+   struct kobj_attribute *attr, char *buf)
+{
+   struct nand_chip *chip = mxic_sysfs;
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   int ret;
+
+   nand_select_target(chip, 0);
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("failed to check mxic nand device randomizer\n");
+
+   return sprintf(buf, "MXIC NAND device randomizer %s(0x%x)\n",
+  feature[0] & MACRONIX_RANDOMIZER_BIT ?
+  "enable" : "disable", feature[0]);
+}
+
+static ssize_t mxic_nand_rand_type_store(struct kobject *kobj,
+struct kobj_attribute *attr,
+const char *buf, size_t count)
+{
+   struct nand_chip *chip = mxic_sysfs;
+   u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {0};
+   unsigned int rand_layout;
+   int ret;
+
+   nand_select_target(chip, 0);
+   ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+
+   if (feature[0]) {
+   pr_err("Randomizer is enabled 0x%x\n", feature[0]);
+   goto err_out;
+   }
+
+   ret = kstrtouint(buf, 0, _layout);
+   if (ret)
+   goto err_out;
+
+   if (rand_layout > 7) {
+   pr_err("Error parameter value:0x%x\n", rand_layout);
+   goto err_out;
+   }
+
+   feature[0] = rand_layout & 0x07;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret) {
+   pr_err("device randomizer set feature failed\n");
+   goto err_out;
+   }
+
+   feature[0] = 0x0;
+   nand_select_target(chip, 0);
+   ret = nand_prog_page_op(chip, 0, 0, feature, 1);
+   nand_deselect_target(chip);
+   if (ret) {
+   pr_err("Prog device randomizer failed\n");
+   goto err_out;
+   }
+
+   feature[0] = 0x0;
+   nand_select_target(chip, 0);
+   ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
+   feature);
+   nand_deselect_target(chip);
+   if (ret)
+   pr_err("failed to exits prog device randomizer\n");
+
+err_out:
+   return count;
+}
+
+static const struct kobj_attribute sysfs_mxic_nand =
+   __ATTR(nand_random, S_IRUGO | S_IWUSR,
+  mxic_nand_rand_type_show,
+  mxic_nand_rand_type_store);
+
+static void macronix_nand_onfi_init(struct nand_chip *chip)
+{
+   struct nand_parameters *p = >parameters;
+   struct kobject *kobj;
+   int ret;
+
+   mxic_sysfs = chip;
+   if (p->onfi) {
+   struct nand_onfi_vendor_macronix *mxic =
+   (void *)p->onfi->vendor;
+
+   if (mxic->reliability_func & MACRONIX_READ_RETRY_BIT) {
+   chip->read_retries = MACRONIX_READ_RETRY_MODE + 1;
+   chip->setup_read_retry =
+

[PATCH 3/7] spi: Patch Macronix MX25F0A SPI controller driver

2019-03-28 Thread Mason Yang
Patch a MFD driver for Macronix MX25F0A SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 159 +
 1 file changed, 3 insertions(+), 156 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index e41ae6e..fbebf89 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -9,163 +9,11 @@
 //
 
 #include 
-#include 
-#include 
-#include 
-#include 
+#include 
 #include 
 #include 
 #include 
 
-#define HC_CFG 0x0
-#define HC_CFG_IF_CFG(x)   ((x) << 27)
-#define HC_CFG_DUAL_SLAVE  BIT(31)
-#define HC_CFG_INDIVIDUAL  BIT(30)
-#define HC_CFG_NIO(x)  (((x) / 4) << 27)
-#define HC_CFG_TYPE(s, t)  ((t) << (23 + ((s) * 2)))
-#define HC_CFG_TYPE_SPI_NOR0
-#define HC_CFG_TYPE_SPI_NAND   1
-#define HC_CFG_TYPE_SPI_RAM2
-#define HC_CFG_TYPE_RAW_NAND   3
-#define HC_CFG_SLV_ACT(x)  ((x) << 21)
-#define HC_CFG_CLK_PH_EN   BIT(20)
-#define HC_CFG_CLK_POL_INV BIT(19)
-#define HC_CFG_BIG_ENDIAN  BIT(18)
-#define HC_CFG_DATA_PASS   BIT(17)
-#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
-#define HC_CFG_MAN_START_ENBIT(3)
-#define HC_CFG_MAN_START   BIT(2)
-#define HC_CFG_MAN_CS_EN   BIT(1)
-#define HC_CFG_MAN_CS_ASSERT   BIT(0)
-
-#define INT_STS0x4
-#define INT_STS_EN 0x8
-#define INT_SIG_EN 0xc
-#define INT_STS_ALLGENMASK(31, 0)
-#define INT_RDY_PINBIT(26)
-#define INT_RDY_SR BIT(25)
-#define INT_LNR_SUSP   BIT(24)
-#define INT_ECC_ERRBIT(17)
-#define INT_CRC_ERRBIT(16)
-#define INT_LWR_DISBIT(12)
-#define INT_LRD_DISBIT(11)
-#define INT_SDMA_INT   BIT(10)
-#define INT_DMA_FINISH BIT(9)
-#define INT_RX_NOT_FULLBIT(3)
-#define INT_RX_NOT_EMPTY   BIT(2)
-#define INT_TX_NOT_FULLBIT(1)
-#define INT_TX_EMPTY   BIT(0)
-
-#define HC_EN  0x10
-#define HC_EN_BIT  BIT(0)
-
-#define TXD(x) (0x14 + ((x) * 4))
-#define RXD0x24
-
-#define SS_CTRL(s) (0x30 + ((s) * 4))
-#define LRD_CFG0x44
-#define LWR_CFG0x80
-#define RWW_CFG0x70
-#define OP_READBIT(23)
-#define OP_DUMMY_CYC(x)((x) << 17)
-#define OP_ADDR_BYTES(x)   ((x) << 14)
-#define OP_CMD_BYTES(x)(((x) - 1) << 13)
-#define OP_OCTA_CRC_EN BIT(12)
-#define OP_DQS_EN  BIT(11)
-#define OP_ENHC_EN BIT(10)
-#define OP_PREAMBLE_EN BIT(9)
-#define OP_DATA_DDRBIT(8)
-#define OP_DATA_BUSW(x)((x) << 6)
-#define OP_ADDR_DDRBIT(5)
-#define OP_ADDR_BUSW(x)((x) << 3)
-#define OP_CMD_DDR BIT(2)
-#define OP_CMD_BUSW(x) (x)
-#define OP_BUSW_1  0
-#define OP_BUSW_2  1
-#define OP_BUSW_4  2
-#define OP_BUSW_8  3
-
-#define OCTA_CRC   0x38
-#define OCTA_CRC_IN_EN(s)  BIT(3 + ((s) * 16))
-#define OCTA_CRC_CHUNK(s, x)   ((fls((x) / 32)) << (1 + ((s) * 16)))
-#define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16))
-
-#define ONFI_DIN_CNT(s)(0x3c + (s))
-
-#define LRD_CTRL   0x48
-#define RWW_CTRL   0x74
-#define LWR_CTRL   0x84
-#define LMODE_EN   BIT(31)
-#define LMODE_SLV_ACT(x)   ((x) << 21)
-#define LMODE_CMD1(x)  ((x) << 8)
-#define LMODE_CMD0(x)  (x)
-
-#define LRD_ADDR   0x4c
-#define LWR_ADDR   0x88
-#define LRD_RANGE  0x50
-#define LWR_RANGE  0x8c
-
-#define AXI_SLV_ADDR   0x54
-
-#define DMAC_RD_CFG0x58
-#define DMAC_WR_CFG0x94
-#define DMAC_CFG_PERIPH_EN BIT(31)
-#define DMAC_CFG_ALLFLUSH_EN   BIT(30)
-#define DMAC_CFG_LASTFLUSH_EN  BIT(29)
-#define DMAC_CFG_QE(x) (((x) + 1) << 16)
-#define DMAC_CFG_BURST_LEN(x)  (((x) + 1) << 12)
-#define DMAC_CFG_BURST_SZ(x)   ((x) << 8)
-#define DMAC_CFG_DIR_READ  BIT(1)
-#define DMAC_CFG_START BIT(0)
-
-#define DMAC_RD_CNT0x5c
-#define DMAC_WR_CNT0x98
-
-#define SDMA_ADDR  0x60
-
-#define DMAM_CFG   0x64
-#define DMAM_CFG_START BIT(31)
-#define DMAM_CFG_CONT  BIT(30)
-#define DMAM_CFG_SDMA_GAP(x)   (fls((x) / 8192) << 2)
-#define DMAM_CFG_DIR_READ  BIT(1)
-#define DMAM_CFG_ENBIT(0)
-
-#define DMAM_CNT   0x68
-
-#define LNR_TIMER_TH   0x6c
-
-#define RDM_CFG0   0x78
-#define RDM_CFG0_POLY(x)   (x)
-
-#define RDM_CFG1   0x7c
-#define RDM_CFG1_RDM_ENBIT(31)
-#define RDM_CFG1_SEED(

[PATCH 5/7] spi: Add direct mapping mode for Macronix SPI controller

2019-03-28 Thread Mason Yang
Add direct mapping read mode for Macronix SPI controller driver.

Signed-off-by: Mason Yang 
---
 drivers/spi/spi-mxic.c | 129 ++---
 1 file changed, 100 insertions(+), 29 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index fbebf89..9f5ff2b 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -19,6 +19,7 @@ struct mxic_spi {
struct clk *send_clk;
struct clk *send_dly_clk;
void __iomem *regs;
+   void __iomem *dirmap;
u32 cur_speed_hz;
 };
 
@@ -128,6 +129,42 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
   mxic->regs + HC_CFG);
 }
 
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+{
+   u32 cfg = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
+
+   if (op->addr.nbytes)
+   cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
+  OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
+
+   if (op->dummy.nbytes)
+   cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
+
+   if (op->data.nbytes) {
+   cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
+   if (op->data.dir == SPI_MEM_DATA_IN)
+   cfg |= OP_READ;
+   }
+
+   return cfg;
+}
+
+static void mxic_spi_set_hc_cfg(struct spi_device *spi, u32 flags)
+{
+   struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
+   int nio = 1;
+
+   if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
+   nio = 4;
+   else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
+   nio = 2;
+
+   writel(flags | HC_CFG_NIO(nio) |
+  HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
+  HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1),
+  mxic->regs + HC_CFG);
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
  void *rxbuf, unsigned int len)
 {
@@ -201,43 +238,18 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op)
 {
struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
-   int nio = 1, i, ret;
-   u32 ss_ctrl;
+   int i, ret;
u8 addr[8];
 
ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
if (ret)
return ret;
 
-   if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
-   nio = 4;
-   else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
-   nio = 2;
+   mxic_spi_set_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN);
 
-   writel(HC_CFG_NIO(nio) |
-  HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
-  HC_CFG_SLV_ACT(mem->spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1) |
-  HC_CFG_MAN_CS_EN,
-  mxic->regs + HC_CFG);
writel(HC_EN_BIT, mxic->regs + HC_EN);
-
-   ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
-
-   if (op->addr.nbytes)
-   ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) |
-  OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
-
-   if (op->dummy.nbytes)
-   ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes);
-
-   if (op->data.nbytes) {
-   ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
-   if (op->data.dir == SPI_MEM_DATA_IN)
-   ss_ctrl |= OP_READ;
-   }
-
-   writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select));
-
+   writel(mxic_spi_mem_prep_op_cfg(op),
+  mxic->regs + SS_CTRL(mem->spi->chip_select));
writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
   mxic->regs + HC_CFG);
 
@@ -271,9 +283,64 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
return ret;
 }
 
+static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+   struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+
+   if (!mxic->dirmap)
+   return -ENOTSUPP;
+
+/*
+ * TODO: overcome this limitation by moving LWR/LRD_ADDR during a
+ * read/write operation.
+ */
+   if (desc->info.offset + desc->info.length > U32_MAX)
+   return -ENOTSUPP;
+
+   if (!mxic_spi_mem_supports_op(desc->mem, >info.op_tmpl))
+   return -ENOTSUPP;
+
+   if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT)
+   return -ENOTSUPP;
+
+   return 0;
+}
+
+static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
+   u64 offs, size_t len, void *buf)
+{
+   struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+   int ret;
+   u32 sts;
+
+

[PATCH 1/7] mfd: Add Macronix MX25F0A MFD controller driver

2019-03-28 Thread Mason Yang
Add a driver for Macronix MX25F0A multifunction device controller.

Signed-off-by: Mason Yang 
---
 drivers/mfd/Kconfig  |   9 ++
 drivers/mfd/Makefile |   1 +
 drivers/mfd/mxic-mx25f0a.c   |  90 
 include/linux/mfd/mxic-mx25f0a.h | 173 +++
 4 files changed, 273 insertions(+)
 create mode 100644 drivers/mfd/mxic-mx25f0a.c
 create mode 100644 include/linux/mfd/mxic-mx25f0a.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0ce2d8d..68aaf2a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -823,6 +823,15 @@ config MFD_MAX8998
  additional drivers must be enabled in order to use the functionality
  of the device.
 
+config MFD_MXIC_MX25F0A
+   tristate "Macronix mx25f0a multifunction device support"
+   select MFD_CORE
+   help
+ This supports for Macronix mx25f0a multifunction device controller
+ for raw nand or spi. You have to select individual components like
+ raw nand controller or spi host controller under the corresponding
+ menus.
+
 config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b4569ed7..dcfe8fd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -163,6 +163,7 @@ max8925-objs:= max8925-core.o 
max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)  += max8925.o
 obj-$(CONFIG_MFD_MAX8997)  += max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)  += max8998.o max8998-irq.o
+obj-$(CONFIG_MFD_MXIC_MX25F0A) += mxic-mx25f0a.o
 
 pcf50633-objs  := pcf50633-core.o pcf50633-irq.o
 obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
diff --git a/drivers/mfd/mxic-mx25f0a.c b/drivers/mfd/mxic-mx25f0a.c
new file mode 100644
index 000..04b1173
--- /dev/null
+++ b/drivers/mfd/mxic-mx25f0a.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Author:
+// Mason Yang 
+//
+
+#include 
+#include 
+
+static const struct mfd_cell mx25f0a_nand_ctlr = {
+   .name = "mxic-nand-ctlr",
+   .of_compatible = "mxicy,mx25f0a-nand-ctlr",
+};
+
+static const struct mfd_cell mx25f0a_spi_ctlr = {
+   .name = "mxic-spi",
+   .of_compatible = "mxicy,mx25f0a-spi",
+};
+
+static int mx25f0a_mfd_probe(struct platform_device *pdev)
+{
+   struct device_node *ctlr;
+   const struct mfd_cell *cell;
+   struct mx25f0a_mfd *mxic;
+   struct resource *res;
+   int ret;
+
+   ctlr = of_get_next_child(pdev->dev.of_node, NULL);
+   if (!ctlr) {
+   dev_warn(>dev, "no spi/nand ctlr node found\n");
+   return -ENODEV;
+   }
+
+   ret = of_device_is_compatible(ctlr, "mxicy,mx25f0a-nand-ctlr");
+   if (ret) {
+   cell = _nand_ctlr;
+   } else {
+   ret = of_device_is_compatible(ctlr, "mxicy,mx25f0a-spi");
+   if (ret) {
+   cell = _spi_ctlr;
+   } else {
+   dev_warn(>dev, "no any spi/nand device found\n");
+   return -ENODEV;
+   }
+   }
+
+   mxic = devm_kzalloc(>dev, sizeof(*mxic), GFP_KERNEL);
+   if (!mxic)
+   return -ENOMEM;
+
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   mxic->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(mxic->base))
+   return PTR_ERR(mxic->base);
+
+   if (cell == _spi_ctlr) {
+   res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+  "dirmap");
+   mxic->dirmap = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(mxic->dirmap))
+   mxic->dirmap = NULL;
+   }
+
+   platform_set_drvdata(pdev, mxic);
+
+   ret = devm_mfd_add_devices(>dev, -1, cell, 1, NULL, 0, NULL);
+
+   return ret;
+}
+
+static const struct of_device_id mx25f0a_mfd_of_match[] = {
+   { .compatible = "mxic,mx25f0a-mfd", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, mx25f0a_mfd_of_match);
+
+static struct platform_driver mx25f0a_mfd_driver = {
+   .probe  = mx25f0a_mfd_probe,
+   .driver = {
+       .name = "mx25f0a-mfd",
+   .of_match_table = mx25f0a_mfd_of_match,
+   },
+};
+module_platform_driver(mx25f0a_mfd_driver);
+
+MODULE_AUTHOR("Mason Yang ");
+MODULE_DESCRIPTION("MX25F0A controller MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mxic-mx25f0a.h b/include/linux/mfd/mxic-mx25f0a.h
new file mode 100644
index 000..5a8cfc7
--- /dev/null
+++ b/include/linux/mfd/mxic-mx25f0a.h
@@ -0,0

[PATCH 2/7] mtd: rawnand: Add Macronix MX25F0A NAND controller driver

2019-03-28 Thread Mason Yang
Add a driver for Macronix MX25F0A NAND controller.

Signed-off-by: Mason Yang 
---
 drivers/mtd/nand/raw/Kconfig |   6 +
 drivers/mtd/nand/raw/Makefile|   1 +
 drivers/mtd/nand/raw/mxic_nand.c | 303 +++
 3 files changed, 310 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/mxic_nand.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index e604625..e0329cc 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -522,6 +522,12 @@ config MTD_NAND_QCOM
  Enables support for NAND flash chips on SoCs containing the EBI2 NAND
  controller. This controller is found on IPQ806x SoC.
 
+config MTD_NAND_MXIC
+   tristate "Macronix MX25F0A NAND controller"
+   depends on HAS_IOMEM
+   help
+ This selects the Macronix MX25F0A NAND controller driver.
+
 config MTD_NAND_MTK
tristate "Support for NAND controller on MTK SoCs"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 5a5a72f..c8a6790 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI)  += sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o
+obj-$(CONFIG_MTD_NAND_MXIC)+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)   += tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)  += stm32_fmc2_nand.o
diff --git a/drivers/mtd/nand/raw/mxic_nand.c b/drivers/mtd/nand/raw/mxic_nand.c
new file mode 100644
index 000..03886b2
--- /dev/null
+++ b/drivers/mtd/nand/raw/mxic_nand.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Macronix International Co., Ltd.
+//
+// Authors:
+// Mason Yang 
+// zhengxunli 
+//
+
+#include 
+#include 
+#include 
+
+#include "internals.h"
+
+struct mxic_nand_ctlr {
+   struct nand_controller base;
+   struct nand_chip nand;
+   void __iomem *regs;
+};
+
+static void mxic_host_init(struct mxic_nand_ctlr *mxic)
+{
+   writel(DATA_STROB_EDO_EN, mxic->regs + DATA_STROB);
+   writel(INT_STS_ALL, mxic->regs + INT_STS_EN);
+   writel(0x0, mxic->regs + ONFI_DIN_CNT(0));
+   writel(HC_CFG_NIO(8) | HC_CFG_SLV_ACT(0) | HC_CFG_IDLE_SIO_LVL(1) |
+  HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) | HC_CFG_MAN_CS_EN,
+  mxic->regs + HC_CFG);
+   writel(0x0, mxic->regs + HC_EN);
+}
+
+static int  mxic_nand_wait_ready(struct nand_chip *chip)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+   u32 sts;
+
+   return readl_poll_timeout(mxic->regs + INT_STS, sts,
+ sts & INT_RDY_PIN, 0, USEC_PER_SEC);
+}
+
+static void mxic_nand_select_chip(struct nand_chip *chip, int chipnr)
+{
+   struct mxic_nand_ctlr *mxic = nand_get_controller_data(chip);
+
+   switch (chipnr) {
+   case 0:
+   case 1:
+   writel(HC_EN_BIT, mxic->regs + HC_EN);
+   writel(HC_CFG_MAN_CS_ASSERT | readl(mxic->regs + HC_CFG),
+  mxic->regs + HC_CFG);
+   break;
+
+   case -1:
+   writel(~HC_CFG_MAN_CS_ASSERT & readl(mxic->regs + HC_CFG),
+  mxic->regs + HC_CFG);
+   writel(0, mxic->regs + HC_EN);
+   break;
+
+   default:
+   break;
+   }
+}
+
+static int mxic_nand_data_xfer(struct mxic_nand_ctlr *mxic, const void *txbuf,
+  void *rxbuf, unsigned int len)
+{
+   unsigned int pos = 0;
+
+   while (pos < len) {
+   unsigned int nbytes = len - pos;
+   u32 data = 0x;
+   u32 sts;
+   int ret;
+
+   if (nbytes > 4)
+   nbytes = 4;
+
+   if (txbuf)
+   memcpy(, txbuf + pos, nbytes);
+
+   ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+   writel(data, mxic->regs + TXD(nbytes % 4));
+
+   if (rxbuf) {
+   ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+sts & INT_TX_EMPTY, 0,
+USEC_PER_SEC);
+   if (ret)
+   return ret;
+
+   ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+sts & INT_RX_NOT_E

[PATCH v8 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-01-27 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 804 ++
 3 files changed, 811 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9f89cb1..6ad1782 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -544,6 +544,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f296270..9150732 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..ea12017
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,804 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  // R/W
+#defin

[PATCH v8 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-01-27 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 40 ++
 1 file changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..7dff7e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,40 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback.
+   supported SoC-specific values are:
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of rpc-if registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain 1 entries for the module's clock
+- clock-names: should contain "rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v8 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-01-27 Thread Mason Yang
Hi Mark,

v8 patch including:
1) Supported SoC-specific values in DTS.
2) Rename device node name as flash.

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason

Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  40 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 804 +
 4 files changed, 851 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v7 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-01-22 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 46 ++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..305bd10
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,46 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+
+
+Required properties:
+- compatible: should be an SoC-specific compatible value, followed by
+   "renesas,rcar-gen3-rpc" as a fallback, i.e.,
+   "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc".
+   "renesas,r8a7795-rpc"   (R-Car H3)
+   "renesas,r8a7796-rpc"   (R-Car M3-W)
+   "renesas,r8a77965-rpc"  (R-Car M3-N)
+   "renesas,r8a77970-rpc"  (R-Car V3M)
+   "renesas,r8a77980-rpc"  (R-Car V3H)
+   "renesas,r8a77990-rpc"  (R-Car E3)
+   "renesas,r8a77995-rpc"  (R-Car D3)
+- reg: should contain three register areas:
+   first for the base address of rpc-if registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clocks: should contain 1 entries for the module's clock
+- clock-names: should contain "rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,r8a77995-rpc", "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x200>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", "wbuf";
+   clocks = < CPG_MOD 917>;
+   clock-names = "rpc";
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v7 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-01-22 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 805 ++
 3 files changed, 812 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9f89cb1..6ad1782 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -544,6 +544,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f296270..9150732 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..0127f25
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,805 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_DRDB(o)  (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  // R/W
+#defin

[PATCH v7 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-01-22 Thread Mason Yang
Hi Mark,

v7 patch is according to Geert and Sergei's comments:
1) Add all R-Car Gen3 model in dts.
2) patch rpc-if child node search.
3) minror coding style.

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code.
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc."
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits().
3) C++ style comment.

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match().
2) Drop unused RPC registers.
3) Use ilog2() instead of fls().
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned().
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM.
3) add RPC module software reset,
4) add regmap.
5) other coding style and so on.

thanks for your review.

best regards,
Mason

Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  46 ++
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 805 +
 4 files changed, 858 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v6 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller bindings

2019-01-17 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 37 ++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..9b5001e
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,37 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+--
+
+Required properties:
+- compatible: should be "renesas,rcar-gen3-rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain three register areas:
+   first for the base address of rpc-if registers,
+   second for the direct mapping read mode and
+   third for the write buffer area.
+- reg-names: should contain "regs", "dirmap" and "wbuf"
+- clock-names: should contain "rpc"
+- clocks: should contain 1 entries for the module's clock
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,rcar-gen3-rpc";
+   reg = <0 0xee20 0 0x7fff>, <0 0x0800 0 0x400>,
+ <0 0xee208000 0 0x100>;
+   reg-names = "regs", "dirmap", ";
+   clocks = < CPG_MOD 917>;
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   clock-names = "rpc";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v6 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-01-17 Thread Mason Yang
Hi Mark,

v6 patch is accroding to Geert, Marek and Sergei's comments:
1) spi_controller for new code. 
2) "renesas,rcar-gen3-rpc" instead of "renesas,r8a77995-rpc".
3) patch external address read mode w/o u64 readq().
4) patch dts for write buffer & drop "renesas,rpc-mode".
5) coding style and so on.

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits()
3) C++ style comment

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match()
2) Drop unused RPC registers
3) Use ilog2() instead of fls()
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned()
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM,
3) add RPC module software reset,
4) add regmap,
5) other coding style and so on.

thanks for your review.

best regards,
Mason

Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC-IF controller
bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  37 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 800 +
 4 files changed, 844 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v6 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-01-17 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
Signed-off-by: Sergei Shtylyov 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 800 ++
 3 files changed, 807 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9f89cb1..6ad1782 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -544,6 +544,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC-IF controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f296270..9150732 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..692c760
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,800 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  // R/W
+#defin

[PATCH v5 0/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI driver

2019-01-07 Thread Mason Yang
Hi Mark,

This Renesas R-Car Gen3 RPC-IF SPI driver is based on Boris's new
spi-mem direct mapping read/write mode [1][2].

v5 patch is accroding to Sergei's comments:
1) Read 6 bytes ID from Sergei's patch.
2) regmap_update_bits()
3) C++ style comment

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match()
2) Drop unused RPC registers
3) Use ilog2() instead of fls()
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned()
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM, 
3) add RPC module software reset, 
4) add regmap,
5) other coding style and so on.

thanks for your review.

best regards,
Mason

[1] https://patchwork.kernel.org/patch/10670753
[2] https://patchwork.kernel.org/patch/10670747


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver
  dt-bindings: spi: Document Renesas R-Car RPC-IF controller bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  37 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 787 +
 4 files changed, 831 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v5 2/2] dt-bindings: spi: Document Renesas R-Car RPC-IF controller bindings

2019-01-07 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC-IF controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 37 ++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..5f96532
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,37 @@
+Renesas R-Car Gen3 RPC-IF controller Device Tree Bindings
+--
+
+Required properties:
+- compatible: should be "renesas,r8a77995-rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area
+- reg-names: should contain "regs" and "dirmap"
+- clock-names: should contain "rpc"
+- clocks: should contain 1 entries for the module's clock
+- renesas,rpc-mode: should contain "spi" for rpc spi mode or
+  "hyperflash" for rpc hyperflash mode.
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,r8a77995-rpc";
+   reg = <0 0xee20 0 0x8100>, <0 0x0800 0 0x400>;
+   reg-names = "regs", "dirmap";
+   clocks = < CPG_MOD 917>;
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   clock-names = "rpc";
+   renesas,rpc-mode = "spi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v5 1/2] spi: Add Renesas R-Car Gen3 RPC-IF SPI controller driver

2019-01-07 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC-IF SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 787 ++
 3 files changed, 794 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9f89cb1..81b4e04 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -544,6 +544,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC_IF
+   tristate "Renesas R-Car Gen3 RPC-IF SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC-IF.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index f296270..3f2b2f9 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC_IF)   += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..1e57eb1
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,787 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC-IF SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  // R/W
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) // undocumented bit but must be set
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14) // undocumented bit
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12) // undocumented bit
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  // R/W
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  // R/W
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  // R/W
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  // R/W
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  // R/W
+
+#define RPC_DRENR  0x001C  // R/W
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  // R/W
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  // R/W
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  // R/W
+#define RPC_SMOP

[PATCH v4 0/2] spi: Add Renesas R-Car Gen3 RPC SPI driver

2018-12-23 Thread Mason Yang
Hi Mark,

This Renesas R-Car Gen3 RPC SPI driver is based on Boris's new
spi-mem direct mapping read/write mode [1][2].

v4 patch is according to Sergei's comments including:
1) Drop soc_device_match()
2) Drop unused RPC registers
3) Use ilog2() instead of fls()
4) Patch read 6 bytes ID w/ one command.
5) Coding style and so on.

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned()
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.

v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM, 
3) add RPC module software reset, 
4) add regmap,
5) other coding style and so on.

thanks for your review.

best regards,
Mason

[1] https://patchwork.kernel.org/patch/10670753
[2] https://patchwork.kernel.org/patch/10670747


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC SPI controller driver
  dt-bindings: spi: Document Renesas R-Car Gen3 RPC controller bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  37 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 788 +
 4 files changed, 832 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v4 2/2] dt-bindings: spi: Document Renesas R-Car Gen3 RPC controller bindings

2018-12-23 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 37 ++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..ba863d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,37 @@
+Renesas R-Car Gen3 RPC controller Device Tree Bindings
+--
+
+Required properties:
+- compatible: should be "renesas,r8a77995-rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area
+- reg-names: should contain "regs" and "dirmap"
+- clock-names: should contain "rpc"
+- clocks: should contain 1 entries for the module's clock
+- renesas,rpc-mode: should contain "spi" for rpc spi mode or
+  "hyperflash" for rpc hyerflash mode.
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,r8a77995-rpc";
+   reg = <0 0xee20 0 0x8100>, <0 0x0800 0 0x400>;
+   reg-names = "regs", "dirmap";
+   clocks = < CPG_MOD 917>;
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   clock-names = "rpc";
+   renesas,rpc-mode = "spi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v4 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver

2018-12-23 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 788 ++
 3 files changed, 795 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c9..54b40f8 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -528,6 +528,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205..5d5c523 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..6dd739a
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,788 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  /* R/W */
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24) /* undocumented bit but must be set */
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  /* R/W */
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) v) - 1) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  /* R/W */
+#define RPC_DREAR_EAC(c)   (((c) & 0x7) << 0)
+
+#define RPC_DROPR  0x0018  /* R/W */
+
+#define RPC_DRENR  0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  /* R/W */
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  /* R/W */
+#define RPC_SMOPR  0x002C  /* R/W *

[PATCH v3 2/2] dt-binding: spi: Document Renesas R-Car Gen3 RPC controller bindings

2018-12-07 Thread Mason Yang
Document the bindings used by the Renesas R-Car Gen3 RPC controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 38 ++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..a191f70
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,38 @@
+Renesas R-Car Gen3 RPC controller Device Tree Bindings
+--
+
+Required properties:
+- compatible: should be "renesas,r8a77995-rpc"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area
+- reg-names: should contain "rpc_regs" and "dirmap"
+- interrupts: interrupt line connected to the RPC controller
+- clock-names: should contain "clk_rpc"
+- clocks: should contain 1 entries for the module's clock
+- rpc-mode: should contain "rpc-spi-flash" for rpc spi mode or
+  "rpc-hyperflash" for rpc hyerflash mode.
+
+Example:
+
+   rpc: rpc@ee20 {
+   compatible = "renesas,r8a77995-rpc";
+   reg = <0 0xee20 0 0x8100>, <0 0x0800 0 0x400>;
+   reg-names = "rpc_regs", "dirmap";
+   clocks = < CPG_MOD 917>;
+   power-domains = < R8A77995_PD_ALWAYS_ON>;
+   resets = < 917>;
+   clock-names = "clk_rpc";
+   rpc-mode = "rpc-spi-flash";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH v3 0/2] spi: Add Renesas R-Car Gen3 RPC SPI driver

2018-12-07 Thread Mason Yang
Hi Mark,

This Renesas R-Car Gen3 RPC SPI driver is based on Boris's new
spi-mem direct mapping read/write mode [1][2].

v3 patch is according to Marek and Geert's comments including:
1) soc_device_mach() to set up RPC_PHYCNT_STRTIM.
2) get_unaligned()
3) rpc-mode for rpi-spi-flash or rpc-hyperflash.
4) coding style and so on.


v2 patch including:
1) remove RPC clock enable/dis-able control,
2) patch run time PM, 
3) add RPC module software reset, 
4) add regmap,
5) other coding style and so on.

thanks for your review.

best regards,
Mason

[1] https://patchwork.kernel.org/patch/10670753
[2] https://patchwork.kernel.org/patch/10670747


Mason Yang (2):
  spi: Add Renesas R-Car Gen3 RPC SPI controller driver
  dt-binding: spi: Document Renesas R-Car Gen3 RPC controller bindings

 .../devicetree/bindings/spi/spi-renesas-rpc.txt|  38 +
 drivers/spi/Kconfig|   6 +
 drivers/spi/Makefile   |   1 +
 drivers/spi/spi-renesas-rpc.c  | 776 +
 4 files changed, 821 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
 create mode 100644 drivers/spi/spi-renesas-rpc.c

-- 
1.9.1



[PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver

2018-12-07 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 776 ++
 3 files changed, 783 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c9..54b40f8 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -528,6 +528,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC SPI controller"
+   depends on ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205..5d5c523 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..cec5669
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,776 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RPC_CMNCR  0x  /* R/W */
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24)
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_CPHATBIT(6)
+#define RPC_CMNCR_CPHARBIT(5)
+#define RPC_CMNCR_SSLP BIT(4)
+#define RPC_CMNCR_CPOL BIT(3)
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  /* R/W */
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  /* R/W */
+#define RPC_DREAR_EAC  BIT(0)
+
+#define RPC_DROPR  0x0018  /* R/W */
+
+#define RPC_DRENR  0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  /* R/W */
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) <

[PATCH v2 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver

2018-12-03 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 808 ++
 3 files changed, 815 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c9..8f826fe 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -528,6 +528,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC SPI controller"
+   depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205..5d5c523 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..ac9094e
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,808 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RPC_CMNCR  0x  /* R/W */
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24)
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_CPHATBIT(6)
+#define RPC_CMNCR_CPHARBIT(5)
+#define RPC_CMNCR_SSLP BIT(4)
+#define RPC_CMNCR_CPOL BIT(3)
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  /* R/W */
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  /* R/W */
+#define RPC_DREAR_EAC  BIT(0)
+
+#define RPC_DROPR  0x0018  /* R/W */
+
+#define RPC_DRENR  0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  /* R/W */
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SM

[PATCH v2 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver

2018-12-03 Thread Mason Yang
Add a driver for Renesas R-Car Gen3 RPC SPI controller.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 808 ++
 3 files changed, 815 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c9..8f826fe 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -528,6 +528,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car Gen3 RPC SPI controller"
+   depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car Gen3 RPC.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205..5d5c523 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..ac9094e
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,808 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car Gen3 RPC SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RPC_CMNCR  0x  /* R/W */
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24)
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_CPHATBIT(6)
+#define RPC_CMNCR_CPHARBIT(5)
+#define RPC_CMNCR_SSLP BIT(4)
+#define RPC_CMNCR_CPOL BIT(3)
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  /* R/W */
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  /* R/W */
+#define RPC_DREAR_EAC  BIT(0)
+
+#define RPC_DROPR  0x0018  /* R/W */
+
+#define RPC_DRENR  0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  /* R/W */
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SM

[PATCH 2/2] dt-binding: spi: Document Renesas R-Car RPC controller bindings

2018-11-19 Thread Mason Yang
Document the bindings used by the Renesas R-Car D3 RPC controller.

Signed-off-by: Mason Yang 
---
 .../devicetree/bindings/spi/spi-renesas-rpc.txt| 33 ++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt

diff --git a/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt 
b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
new file mode 100644
index 000..8286cc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-renesas-rpc.txt
@@ -0,0 +1,33 @@
+Renesas R-Car D3 RPC controller Device Tree Bindings
+
+
+Required properties:
+- compatible: should be "renesas,rpc-r8a77995"
+- #address-cells: should be 1
+- #size-cells: should be 0
+- reg: should contain 2 entries, one for the registers and one for the direct
+   mapping area
+- reg-names: should contain "rpc_regs" and "dirmap"
+- interrupts: interrupt line connected to the RPC SPI controller
+- clock-names: should contain "clk_rpc"
+- clocks: should contain 1 entries for the CPG Module 917 clocks
+
+Example:
+
+   rpc: spi@ee20 {
+   compatible = "renesas,rpc-r8a77995";
+   reg = <0 0xee20 0 0x8100>, <0 0x0800 0 0x400>;
+   reg-names = "rpc_regs", "dirmap";
+   clocks = < CPG_MOD 917>;
+   clock-names = "clk_rpc";
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   flash@0 {
+   compatible = "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <4000>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   };
+   };
-- 
1.9.1



[PATCH 1/2] spi: Add Renesas R-Car RPC SPI controller driver

2018-11-19 Thread Mason Yang
Add a driver for Renesas R-Car D3 RPC SPI controller driver.

Signed-off-by: Mason Yang 
---
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-renesas-rpc.c | 750 ++
 3 files changed, 757 insertions(+)
 create mode 100644 drivers/spi/spi-renesas-rpc.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c9..093006a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -528,6 +528,12 @@ config SPI_RSPI
help
  SPI driver for Renesas RSPI and QSPI blocks.
 
+config SPI_RENESAS_RPC
+   tristate "Renesas R-Car D3 RPC SPI controller"
+   depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
+   help
+ SPI driver for Renesas R-Car D3 RPC.
+
 config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205..5d5c523 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
 obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
 obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o
 obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RENESAS_RPC)  += spi-renesas-rpc.o
 obj-$(CONFIG_SPI_S3C24XX)  += spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y   := spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c
new file mode 100644
index 000..00b9d8f
--- /dev/null
+++ b/drivers/spi/spi-renesas-rpc.c
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp.
+// Copyright (C) 2018 Macronix International Co., Ltd.
+//
+// R-Car D3 RPC SPI/QSPI/Octa driver
+//
+// Authors:
+// Mason Yang 
+//
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RPC_CMNCR  0x  /* R/W */
+#define RPC_CMNCR_MD   BIT(31)
+#define RPC_CMNCR_SFDE BIT(24)
+#define RPC_CMNCR_MOIIO3(val)  (((val) & 0x3) << 22)
+#define RPC_CMNCR_MOIIO2(val)  (((val) & 0x3) << 20)
+#define RPC_CMNCR_MOIIO1(val)  (((val) & 0x3) << 18)
+#define RPC_CMNCR_MOIIO0(val)  (((val) & 0x3) << 16)
+#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
+RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
+#define RPC_CMNCR_IO3FV(val)   (((val) & 0x3) << 14)
+#define RPC_CMNCR_IO2FV(val)   (((val) & 0x3) << 12)
+#define RPC_CMNCR_IO0FV(val)   (((val) & 0x3) << 8)
+#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
+RPC_CMNCR_IO3FV(3))
+#define RPC_CMNCR_CPHATBIT(6)
+#define RPC_CMNCR_CPHARBIT(5)
+#define RPC_CMNCR_SSLP BIT(4)
+#define RPC_CMNCR_CPOL BIT(3)
+#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
+
+#define RPC_SSLDR  0x0004  /* R/W */
+#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
+#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
+#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
+
+#define RPC_DRCR   0x000C  /* R/W */
+#define RPC_DRCR_SSLN  BIT(24)
+#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
+#define RPC_DRCR_RCF   BIT(9)
+#define RPC_DRCR_RBE   BIT(8)
+#define RPC_DRCR_SSLE  BIT(0)
+
+#define RPC_DRCMR  0x0010  /* R/W */
+#define RPC_DRCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_DRCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_DREAR  0x0014  /* R/W */
+#define RPC_DREAR_EAC  BIT(0)
+
+#define RPC_DROPR  0x0018  /* R/W */
+
+#define RPC_DRENR  0x001C  /* R/W */
+#define RPC_DRENR_CDB(o)   (u32)o) & 0x3) << 30))
+#define RPC_DRENR_OCDB(o)  (((o) & 0x3) << 28)
+#define RPC_DRENR_ADB(o)   (((o) & 0x3) << 24)
+#define RPC_DRENR_OPDB(o)  (((o) & 0x3) << 20)
+#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
+#define RPC_DRENR_DME  BIT(15)
+#define RPC_DRENR_CDE  BIT(14)
+#define RPC_DRENR_OCDE BIT(12)
+#define RPC_DRENR_ADE(v)   (((v) & 0xF) << 8)
+#define RPC_DRENR_OPDE(v)  (((v) & 0xF) << 4)
+
+#define RPC_SMCR   0x0020  /* R/W */
+#define RPC_SMCR_SSLKP BIT(8)
+#define RPC_SMCR_SPIRE BIT(2)
+#define RPC_SMCR_SPIWE BIT(1)
+#define RPC_SMCR_SPIE  BIT(0)
+
+#define RPC_SMCMR  0x0024  /* R/W */
+#define RPC_SMCMR_CMD(c)   (((c) & 0xFF) << 16)
+#define RPC_SMCMR_OCMD(c)  (((c) & 0xFF) << 0)
+
+#define RPC_SMADR  0x0028  /* 

  1   2   >