Re: [PATCH RFC v3 2/2] memory: pl353: Add driver for arm pl353 static memory controller

2014-07-03 Thread Arnd Bergmann
On Friday 27 June 2014 08:32:42 Punnaiah Choudary Kalluri wrote:

> +/**
> + * struct pl353_smc_data - Private smc driver structure
> + * @devclk:  Pointer to the peripheral clock
> + * @aperclk: Pointer to the APER clock
> + */
> +struct pl353_smc_data {
> + struct clk  *memclk;
> + struct clk  *aclk;
> +};
> +
> +/* SMC virtual register base */
> +static void __iomem *pl353_smc_base;

Drivers should not assume that there is only a single instance of the
hardware in the system. Please remove this global variable and
change the code to pass around a pointer to a structure containing
it.

> +/**
> + * pl353_smc_set_buswidth - Set memory buswidth
> + * @bw:  Memory buswidth (8 | 16)
> + * Return: 0 on success or negative errno.
> + */
> +int pl353_smc_set_buswidth(unsigned int bw)
> +{
> +
> + if (bw != PL353_SMC_MEM_WIDTH_8  && bw != PL353_SMC_MEM_WIDTH_16)
> + return -EINVAL;
> +
> + writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS);
> + writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
> +PL353_SMC_DIRECT_CMD_OFFS);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth);

Why is this an exported interface? Wouldn't that setting just be
determined from DT when the device is probed?

> +/**
> + * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit
> + * Return: the raw_int_status1 bit from the memc_status register
> + */
> +int pl353_smc_get_nand_int_status_raw(void)
> +{
> + u32 reg;
> +
> + reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS);
> + reg >>= PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT;
> + reg &= 1;
> +
> + return reg;
> +}
> +EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw);
> +
> +/**
> + * pl353_smc_clr_nand_int - Clear NAND interrupt
> + */
> +void pl353_smc_clr_nand_int(void)
> +{
> + writel(PL353_SMC_CFG_CLR_INT_CLR_1,
> + pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
> +}
> +EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int);

Why aren't these just part of the NAND driver?

> + pl353_smc_set_cycles(t_rc, t_wc, t_rea, t_wp, t_clr, t_ar, t_rr);
> + writel(PL353_SMC_CFG_CLR_INT_CLR_1,
> + pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
> + writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
> +PL353_SMC_DIRECT_CMD_OFFS);
> + /* Wait till the ECC operation is complete */
> + do {
> + if (pl353_smc_ecc_is_busy_noirq())
> + cpu_relax();
> + else
> + break;
> + } while (!time_after_eq(jiffies, timeout));

This blocks the CPU for up to a second (the timeout value). Since you are
not in atomic context, you can instead sleep here, e.g. using msleep(1)
or some other appropriate timeout.

What is the expected average duration of the loop?

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH RFC v3 2/2] memory: pl353: Add driver for arm pl353 static memory controller

2014-07-03 Thread Arnd Bergmann
On Friday 27 June 2014 08:32:42 Punnaiah Choudary Kalluri wrote:

 +/**
 + * struct pl353_smc_data - Private smc driver structure
 + * @devclk:  Pointer to the peripheral clock
 + * @aperclk: Pointer to the APER clock
 + */
 +struct pl353_smc_data {
 + struct clk  *memclk;
 + struct clk  *aclk;
 +};
 +
 +/* SMC virtual register base */
 +static void __iomem *pl353_smc_base;

Drivers should not assume that there is only a single instance of the
hardware in the system. Please remove this global variable and
change the code to pass around a pointer to a structure containing
it.

 +/**
 + * pl353_smc_set_buswidth - Set memory buswidth
 + * @bw:  Memory buswidth (8 | 16)
 + * Return: 0 on success or negative errno.
 + */
 +int pl353_smc_set_buswidth(unsigned int bw)
 +{
 +
 + if (bw != PL353_SMC_MEM_WIDTH_8   bw != PL353_SMC_MEM_WIDTH_16)
 + return -EINVAL;
 +
 + writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS);
 + writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
 +PL353_SMC_DIRECT_CMD_OFFS);
 +
 + return 0;
 +}
 +EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth);

Why is this an exported interface? Wouldn't that setting just be
determined from DT when the device is probed?

 +/**
 + * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit
 + * Return: the raw_int_status1 bit from the memc_status register
 + */
 +int pl353_smc_get_nand_int_status_raw(void)
 +{
 + u32 reg;
 +
 + reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS);
 + reg = PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT;
 + reg = 1;
 +
 + return reg;
 +}
 +EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw);
 +
 +/**
 + * pl353_smc_clr_nand_int - Clear NAND interrupt
 + */
 +void pl353_smc_clr_nand_int(void)
 +{
 + writel(PL353_SMC_CFG_CLR_INT_CLR_1,
 + pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
 +}
 +EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int);

Why aren't these just part of the NAND driver?

 + pl353_smc_set_cycles(t_rc, t_wc, t_rea, t_wp, t_clr, t_ar, t_rr);
 + writel(PL353_SMC_CFG_CLR_INT_CLR_1,
 + pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
 + writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
 +PL353_SMC_DIRECT_CMD_OFFS);
 + /* Wait till the ECC operation is complete */
 + do {
 + if (pl353_smc_ecc_is_busy_noirq())
 + cpu_relax();
 + else
 + break;
 + } while (!time_after_eq(jiffies, timeout));

This blocks the CPU for up to a second (the timeout value). Since you are
not in atomic context, you can instead sleep here, e.g. using msleep(1)
or some other appropriate timeout.

What is the expected average duration of the loop?

Arnd
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RFC v3 2/2] memory: pl353: Add driver for arm pl353 static memory controller

2014-06-26 Thread Punnaiah Choudary Kalluri
Add driver for arm pl353 static memory controller. This controller is
used in xilinx zynq soc for interfacing the nand and nor/sram memory
devices.

Signed-off-by: Punnaiah Choudary Kalluri 
---
Changes in v2:
 - Since now the timing parameters are in nano seconds, added logic to convert
   them to the cycles
---
 drivers/memory/Kconfig   |6 +
 drivers/memory/Makefile  |1 +
 drivers/memory/pl353-smc.c   |  569 ++
 include/linux/memory/pl353-smc.h |   34 +++
 4 files changed, 610 insertions(+), 0 deletions(-)
 create mode 100644 drivers/memory/pl353-smc.c
 create mode 100644 include/linux/memory/pl353-smc.h

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c59e9c9..58c29a2 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -65,4 +65,10 @@ config FSL_IFC
bool
depends on FSL_SOC
 
+config PL353_SMC
+   bool "ARM PL353 Static Memory Controller(SMC) driver"
+   default y
+   depends on ARM
+   help
+ This driver is for the ARM PL353 Static Memory Controller(SMC) module.
 endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 71160a2..5040977 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)   += tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)   += tegra30-mc.o
+obj-$(CONFIG_PL353_SMC)+= pl353-smc.o
diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c
new file mode 100644
index 000..02221ba
--- /dev/null
+++ b/drivers/memory/pl353-smc.c
@@ -0,0 +1,569 @@
+/*
+ * ARM PL353 SMC Driver
+ *
+ * Copyright (C) 2012 - 2014 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Currently only a single SMC instance is supported.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Register definitions */
+#define PL353_SMC_MEMC_STATUS_OFFS 0   /* Controller status reg, RO */
+#define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */
+#define PL353_SMC_DIRECT_CMD_OFFS  0x10/* Direct command reg, WO */
+#define PL353_SMC_SET_CYCLES_OFFS  0x14/* Set cycles register, WO */
+#define PL353_SMC_SET_OPMODE_OFFS  0x18/* Set opmode register, WO */
+#define PL353_SMC_ECC_STATUS_OFFS  0x400   /* ECC status register */
+#define PL353_SMC_ECC_MEMCFG_OFFS  0x404   /* ECC mem config reg */
+#define PL353_SMC_ECC_MEMCMD1_OFFS 0x408   /* ECC mem cmd1 reg */
+#define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C   /* ECC mem cmd2 reg */
+#define PL353_SMC_ECC_VALUE0_OFFS  0x418   /* ECC value 0 reg */
+
+/* Controller status register specifc constants */
+#define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT  6
+
+/* Clear configuration register specific constants */
+#define PL353_SMC_CFG_CLR_INT_CLR_10x10
+#define PL353_SMC_CFG_CLR_ECC_INT_DIS_10x40
+#define PL353_SMC_CFG_CLR_INT_DIS_10x2
+#define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \
+PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \
+PL353_SMC_CFG_CLR_INT_DIS_1)
+
+/* Set cycles register specific constants */
+#define PL353_SMC_SET_CYCLES_T0_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T0_SHIFT  0
+#define PL353_SMC_SET_CYCLES_T1_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T1_SHIFT  4
+#define PL353_SMC_SET_CYCLES_T2_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T2_SHIFT  8
+#define PL353_SMC_SET_CYCLES_T3_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T3_SHIFT  11
+#define PL353_SMC_SET_CYCLES_T4_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T4_SHIFT  14
+#define PL353_SMC_SET_CYCLES_T5_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T5_SHIFT  17
+#define PL353_SMC_SET_CYCLES_T6_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T6_SHIFT  20
+
+/* ECC status register specific constants */
+#define PL353_SMC_ECC_STATUS_BUSY  (1 << 6)
+
+/* ECC memory config register specific constants */
+#define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC
+#define PL353_SMC_ECC_MEMCFG_MODE_SHIFT2
+#define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK   0xC
+
+#define PL353_SMC_DC_UPT_NAND_REGS ((4 << 23) |/* CS: NAND chip */ \
+(2 << 21)) /* UpdateRegs operation */
+
+#define PL353_NAND_ECC_CMD1((0x80)   | /* Write command */ \
+(0 << 8) | /* Read 

[PATCH RFC v3 2/2] memory: pl353: Add driver for arm pl353 static memory controller

2014-06-26 Thread Punnaiah Choudary Kalluri
Add driver for arm pl353 static memory controller. This controller is
used in xilinx zynq soc for interfacing the nand and nor/sram memory
devices.

Signed-off-by: Punnaiah Choudary Kalluri punn...@xilinx.com
---
Changes in v2:
 - Since now the timing parameters are in nano seconds, added logic to convert
   them to the cycles
---
 drivers/memory/Kconfig   |6 +
 drivers/memory/Makefile  |1 +
 drivers/memory/pl353-smc.c   |  569 ++
 include/linux/memory/pl353-smc.h |   34 +++
 4 files changed, 610 insertions(+), 0 deletions(-)
 create mode 100644 drivers/memory/pl353-smc.c
 create mode 100644 include/linux/memory/pl353-smc.h

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c59e9c9..58c29a2 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -65,4 +65,10 @@ config FSL_IFC
bool
depends on FSL_SOC
 
+config PL353_SMC
+   bool ARM PL353 Static Memory Controller(SMC) driver
+   default y
+   depends on ARM
+   help
+ This driver is for the ARM PL353 Static Memory Controller(SMC) module.
 endif
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 71160a2..5040977 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)   += tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)   += tegra30-mc.o
+obj-$(CONFIG_PL353_SMC)+= pl353-smc.o
diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c
new file mode 100644
index 000..02221ba
--- /dev/null
+++ b/drivers/memory/pl353-smc.c
@@ -0,0 +1,569 @@
+/*
+ * ARM PL353 SMC Driver
+ *
+ * Copyright (C) 2012 - 2014 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Currently only a single SMC instance is supported.
+ */
+
+#include linux/clk.h
+#include linux/io.h
+#include linux/kernel.h
+#include linux/memory/pl353-smc.h
+#include linux/module.h
+#include linux/of_platform.h
+#include linux/platform_device.h
+#include linux/slab.h
+
+/* Register definitions */
+#define PL353_SMC_MEMC_STATUS_OFFS 0   /* Controller status reg, RO */
+#define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */
+#define PL353_SMC_DIRECT_CMD_OFFS  0x10/* Direct command reg, WO */
+#define PL353_SMC_SET_CYCLES_OFFS  0x14/* Set cycles register, WO */
+#define PL353_SMC_SET_OPMODE_OFFS  0x18/* Set opmode register, WO */
+#define PL353_SMC_ECC_STATUS_OFFS  0x400   /* ECC status register */
+#define PL353_SMC_ECC_MEMCFG_OFFS  0x404   /* ECC mem config reg */
+#define PL353_SMC_ECC_MEMCMD1_OFFS 0x408   /* ECC mem cmd1 reg */
+#define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C   /* ECC mem cmd2 reg */
+#define PL353_SMC_ECC_VALUE0_OFFS  0x418   /* ECC value 0 reg */
+
+/* Controller status register specifc constants */
+#define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT  6
+
+/* Clear configuration register specific constants */
+#define PL353_SMC_CFG_CLR_INT_CLR_10x10
+#define PL353_SMC_CFG_CLR_ECC_INT_DIS_10x40
+#define PL353_SMC_CFG_CLR_INT_DIS_10x2
+#define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \
+PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \
+PL353_SMC_CFG_CLR_INT_DIS_1)
+
+/* Set cycles register specific constants */
+#define PL353_SMC_SET_CYCLES_T0_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T0_SHIFT  0
+#define PL353_SMC_SET_CYCLES_T1_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T1_SHIFT  4
+#define PL353_SMC_SET_CYCLES_T2_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T2_SHIFT  8
+#define PL353_SMC_SET_CYCLES_T3_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T3_SHIFT  11
+#define PL353_SMC_SET_CYCLES_T4_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T4_SHIFT  14
+#define PL353_SMC_SET_CYCLES_T5_MASK   0x7
+#define PL353_SMC_SET_CYCLES_T5_SHIFT  17
+#define PL353_SMC_SET_CYCLES_T6_MASK   0xF
+#define PL353_SMC_SET_CYCLES_T6_SHIFT  20
+
+/* ECC status register specific constants */
+#define PL353_SMC_ECC_STATUS_BUSY  (1  6)
+
+/* ECC memory config register specific constants */
+#define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC
+#define PL353_SMC_ECC_MEMCFG_MODE_SHIFT2
+#define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK   0xC
+
+#define PL353_SMC_DC_UPT_NAND_REGS ((4  23) |/* CS: NAND chip */ \
+(2  21)) /* UpdateRegs