Reorganize gpmc-onenand initialization so that changes
required for gpmc driver migration can be made smooth.

Ensuring sync read/write are disabled in onenand cannot
be expected to work properly unless GPMC is setup, this
has been removed.

Refactor set_async_mode & set_sync_mode functions to
separate out timing calculation & actual configuration
(GPMC & OneNAND side).

Thanks to Jon for his suggestions.

Signed-off-by: Afzal Mohammed <af...@ti.com>
---

v4:
Reorganize set_sync/async functions in a better way
v3:
Refactor set_sync/async functions to separate out timing and
 configurations
v2:
Move ensuring that async mode in OneNAND has been setup from
 set_sync to setup function, improve commit message

 arch/arm/mach-omap2/gpmc-onenand.c |  153 +++++++++++++++++++-----------------
 1 file changed, 83 insertions(+), 70 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c 
b/arch/arm/mach-omap2/gpmc-onenand.c
index 8863e0a..878182b 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <asm/mach/flash.h>
 
@@ -25,6 +26,7 @@
 
 #define        ONENAND_IO_SIZE SZ_128K
 
+static int hf, vhf, sync_read, sync_write, latency;
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
 static struct resource gpmc_onenand_resource = {
@@ -38,11 +40,9 @@ static struct platform_device gpmc_onenand_device = {
        .resource       = &gpmc_onenand_resource,
 };
 
-static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
+static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 {
        struct gpmc_timings t;
-       u32 reg;
-       int err;
 
        const int t_cer = 15;
        const int t_avdp = 12;
@@ -55,11 +55,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem 
*onenand_base)
        const int t_wpl = 40;
        const int t_wph = 30;
 
-       /* Ensure sync read and sync write are disabled */
-       reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
-       reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
-       writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
-
        memset(&t, 0, sizeof(t));
        t.sync_clk = 0;
        t.cs_on = 0;
@@ -86,25 +81,30 @@ static int omap2_onenand_set_async_mode(int cs, void 
__iomem *onenand_base)
        t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
        t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 
+       return t;
+}
+
+static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+{
        /* Configure GPMC for asynchronous read */
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
                          GPMC_CONFIG1_DEVICESIZE_16 |
                          GPMC_CONFIG1_MUXADDDATA);
 
-       err = gpmc_cs_set_timings(cs, &t);
-       if (err)
-               return err;
+       return gpmc_cs_set_timings(cs, t);
+}
+
+static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
+{
+       u32 reg;
 
        /* Ensure sync read and sync write are disabled */
        reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
        reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
        writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
-
-       return 0;
 }
 
-static void set_onenand_cfg(void __iomem *onenand_base, int latency,
-                               int sync_read, int sync_write, int hf, int vhf)
+static void set_onenand_cfg(void __iomem *onenand_base)
 {
        u32 reg;
 
@@ -172,9 +172,9 @@ static int omap2_onenand_get_freq(struct 
omap_onenand_platform_data *cfg,
        return freq;
 }
 
-static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
-                                       void __iomem *onenand_base,
-                                       int *freq_ptr)
+static struct gpmc_timings
+omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+                                               int freq, bool clk_dep)
 {
        struct gpmc_timings t;
        const int t_cer  = 15;
@@ -184,28 +184,15 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
        const int t_wpl  = 40;
        const int t_wph  = 30;
        int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
-       int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
-       int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
-       int err, ticks_cez;
-       int cs = cfg->cs, freq = *freq_ptr;
-       u32 reg;
-       bool clk_dep = false;
+       int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns;
+       int ticks_cez;
+       int cs = cfg->cs;
 
        if (cfg->flags & ONENAND_SYNC_READ) {
                sync_read = 1;
        } else if (cfg->flags & ONENAND_SYNC_READWRITE) {
                sync_read = 1;
                sync_write = 1;
-       } else
-               return omap2_onenand_set_async_mode(cs, onenand_base);
-
-       if (!freq) {
-               /* Very first call freq is not known */
-               err = omap2_onenand_set_async_mode(cs, onenand_base);
-               if (err)
-                       return err;
-               freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
-               first_time = 1;
        }
 
        switch (freq) {
@@ -279,36 +266,16 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
                }
        }
 
-       if (first_time)
-               set_onenand_cfg(onenand_base, latency,
-                                       sync_read, sync_write, hf, vhf);
+       /* Set synchronous read timings */
+       memset(&t, 0, sizeof(t));
 
        if (div == 1) {
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-               reg |= (1 << 7);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-               reg |= (1 << 7);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-               reg |= (1 << 7);
-               reg |= (1 << 23);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
-       } else {
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-               reg &= ~(1 << 7);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-               reg &= ~(1 << 7);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-               reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-               reg &= ~(1 << 7);
-               reg &= ~(1 << 23);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+               t.bool_timings.cs_extra_delay = true;
+               t.bool_timings.adv_extra_delay = true;
+               t.bool_timings.oe_extra_delay = true;
+               t.bool_timings.we_extra_delay = true;
        }
 
-       /* Set synchronous read timings */
-       memset(&t, 0, sizeof(t));
        t.sync_clk = min_gpmc_clk_period;
        t.cs_on = 0;
        t.adv_on = 0;
@@ -357,6 +324,11 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
                }
        }
 
+       return t;
+}
+
+static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+{
        /* Configure GPMC for synchronous read */
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
                          GPMC_CONFIG1_WRAPBURST_SUPP |
@@ -372,11 +344,45 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
                          GPMC_CONFIG1_DEVICETYPE_NOR |
                          GPMC_CONFIG1_MUXADDDATA);
 
-       err = gpmc_cs_set_timings(cs, &t);
-       if (err)
-               return err;
+       return gpmc_cs_set_timings(cs, t);
+}
+
+static int omap2_onenand_setup_async(void __iomem *onenand_base)
+{
+       struct gpmc_timings t;
+       int ret;
 
-       set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
+       t = omap2_onenand_calc_async_timings();
+
+       ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       omap2_onenand_set_async_mode(onenand_base);
+
+       return 0;
+}
+
+static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+{
+       int ret, freq = *freq_ptr;
+       struct gpmc_timings t;
+       bool clk_dep = false;
+
+       if (!freq) {
+               /* Very first call freq is not known */
+               freq = omap2_onenand_get_freq(gpmc_onenand_data,
+                                               onenand_base, &clk_dep);
+               set_onenand_cfg(onenand_base);
+       }
+
+       t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq, clk_dep);
+
+       ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       set_onenand_cfg(onenand_base);
 
        *freq_ptr = freq;
 
@@ -386,15 +392,22 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
        struct device *dev = &gpmc_onenand_device.dev;
+       unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
+       int ret;
 
-       /* Set sync timings in GPMC */
-       if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
-                       freq_ptr) < 0) {
-               dev_err(dev, "Unable to set synchronous mode\n");
-               return -EINVAL;
+       ret = omap2_onenand_setup_async(onenand_base);
+       if (ret) {
+               dev_err(dev, "unable to set to async mode\n");
+               return ret;
        }
 
-       return 0;
+       if (!(gpmc_onenand_data->flags & l))
+               return 0;
+
+       ret = omap2_onenand_setup_sync(onenand_base, freq_ptr);
+       if (ret)
+               dev_err(dev, "unable to set to sync mode\n");
+       return ret;
 }
 
 void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
-- 
1.7.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to