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>
---

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 |  134 +++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 65 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c 
b/arch/arm/mach-omap2/gpmc-onenand.c
index 8863e0a..789ca8c9 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,12 +81,21 @@ 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 omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base,
+                                                       struct gpmc_timings *t)
+{
+       u32 reg;
+       int err;
+
        /* 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);
+       err = gpmc_cs_set_timings(cs, t);
        if (err)
                return err;
 
@@ -103,8 +107,7 @@ static int omap2_onenand_set_async_mode(int cs, void 
__iomem *onenand_base)
        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 +175,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 +187,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 +269,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 +327,17 @@ static int omap2_onenand_set_sync_mode(struct 
omap_onenand_platform_data *cfg,
                }
        }
 
+       return t;
+}
+
+static int omap2_onenand_set_sync_mode(int cs, struct gpmc_timings *t,
+                                       void __iomem *onenand_base, int initial)
+{
+       int err;
+
+       if (initial)
+               set_onenand_cfg(onenand_base);
+
        /* Configure GPMC for synchronous read */
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
                          GPMC_CONFIG1_WRAPBURST_SUPP |
@@ -372,13 +353,11 @@ 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);
+       err = gpmc_cs_set_timings(cs, t);
        if (err)
                return err;
 
-       set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
-
-       *freq_ptr = freq;
+       set_onenand_cfg(onenand_base);
 
        return 0;
 }
@@ -386,13 +365,38 @@ 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;
+       struct gpmc_timings t;
+       int ret, first_time = 0, freq = *freq_ptr;
+       unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
+       bool clk_dep = false;
+
+       t = omap2_onenand_calc_async_timings();
+       ret = omap2_onenand_set_async_mode(gpmc_onenand_data->cs,
+                                                       onenand_base, &t);
+       if (IS_ERR_VALUE(ret)) {
+               dev_err(dev, "unable to set to async mode\n");
+               return ret;
+       }
+
+       if (!(gpmc_onenand_data->flags & l))
+               return 0;
+
+       /* setup sync mode */
+       if (!freq) {
+               /* Very first call freq is not known */
+               freq = omap2_onenand_get_freq(gpmc_onenand_data,
+                                               onenand_base, &clk_dep);
+               first_time = 1;
+       }
 
-       /* 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;
+       t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq, clk_dep);
+       ret = omap2_onenand_set_sync_mode(gpmc_onenand_data->cs, &t,
+                                               onenand_base, first_time);
+       if (IS_ERR_VALUE(ret)) {
+               dev_err(dev, "unable to set to sync mode\n");
+               return ret;
        }
+       *freq_ptr = freq;
 
        return 0;
 }
-- 
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