]> Pileus Git - ~andy/linux/blobdiff - arch/arm/mach-omap2/gpmc-onenand.c
Merge tag 'at91-fixes' of git://github.com/at91linux/linux-at91 into next/fixes-non...
[~andy/linux] / arch / arm / mach-omap2 / gpmc-onenand.c
index fadd87435cd02e8396ef7fea8ed16a5eabf8e116..64b5a83469822ad53693c2ae8ffdd3b227fa2a7b 100644 (file)
@@ -47,11 +47,23 @@ static struct platform_device gpmc_onenand_device = {
        .resource       = &gpmc_onenand_resource,
 };
 
-static struct gpmc_timings omap2_onenand_calc_async_timings(void)
+static struct gpmc_settings onenand_async = {
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+};
+
+static struct gpmc_settings onenand_sync = {
+       .burst_read     = true,
+       .burst_wrap     = true,
+       .burst_len      = GPMC_BURST_16,
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+       .wait_pin       = 0,
+};
+
+static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
 {
        struct gpmc_device_timings dev_t;
-       struct gpmc_timings t;
-
        const int t_cer = 15;
        const int t_avdp = 12;
        const int t_aavdh = 7;
@@ -64,7 +76,6 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
        dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
        dev_t.t_avdp_w = dev_t.t_avdp_r;
        dev_t.t_aavdh = t_aavdh * 1000;
@@ -76,19 +87,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
        dev_t.t_wpl = t_wpl * 1000;
        dev_t.t_wph = t_wph * 1000;
 
-       gpmc_calc_timings(&t, &dev_t);
-
-       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);
-
-       return gpmc_cs_set_timings(cs, t);
+       gpmc_calc_timings(t, &onenand_async, &dev_t);
 }
 
 static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
@@ -158,12 +157,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
        return freq;
 }
 
-static struct gpmc_timings
-omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
-                               int freq)
+static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+                                           unsigned int flags,
+                                           int freq)
 {
        struct gpmc_device_timings dev_t;
-       struct gpmc_timings t;
        const int t_cer  = 15;
        const int t_avdp = 12;
        const int t_cez  = 20; /* max of t_cez, t_oez */
@@ -172,9 +170,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
        int div, gpmc_clk_ns;
 
-       if (cfg->flags & ONENAND_SYNC_READ)
+       if (flags & ONENAND_SYNC_READ)
                onenand_flags = ONENAND_FLAG_SYNCREAD;
-       else if (cfg->flags & ONENAND_SYNC_READWRITE)
+       else if (flags & ONENAND_SYNC_READWRITE)
                onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
 
        switch (freq) {
@@ -239,10 +237,11 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        /* Set synchronous read timings */
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
-       dev_t.sync_read = true;
+       if (onenand_flags & ONENAND_FLAG_SYNCREAD)
+               onenand_sync.sync_read = true;
        if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
-               dev_t.sync_write = true;
+               onenand_sync.sync_write = true;
+               onenand_sync.burst_write = true;
        } else {
                dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
                dev_t.t_wpl = t_wpl * 1000;
@@ -265,32 +264,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        dev_t.cyc_aavdh_oe = 1;
        dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
 
-       gpmc_calc_timings(&t, &dev_t);
-
-       return t;
-}
-
-static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
-{
-       unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
-       unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
-
-       /* Configure GPMC for synchronous read */
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-                         GPMC_CONFIG1_WRAPBURST_SUPP |
-                         GPMC_CONFIG1_READMULTIPLE_SUPP |
-                         (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-                         (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-                         (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-                         GPMC_CONFIG1_PAGE_LEN(2) |
-                         (cpu_is_omap34xx() ? 0 :
-                               (GPMC_CONFIG1_WAIT_READ_MON |
-                                GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-                         GPMC_CONFIG1_DEVICESIZE_16 |
-                         GPMC_CONFIG1_DEVICETYPE_NOR |
-                         GPMC_CONFIG1_MUXADDDATA);
-
-       return gpmc_cs_set_timings(cs, t);
+       gpmc_calc_timings(t, &onenand_sync, &dev_t);
 }
 
 static int omap2_onenand_setup_async(void __iomem *onenand_base)
@@ -298,12 +272,20 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
        struct gpmc_timings t;
        int ret;
 
+       if (gpmc_onenand_data->of_node)
+               gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+                                     &onenand_async);
+
        omap2_onenand_set_async_mode(onenand_base);
 
-       t = omap2_onenand_calc_async_timings();
+       omap2_onenand_calc_async_timings(&t);
+
+       ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
+       if (ret < 0)
+               return ret;
 
-       ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       if (ret < 0)
                return ret;
 
        omap2_onenand_set_async_mode(onenand_base);
@@ -322,10 +304,26 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
                set_onenand_cfg(onenand_base);
        }
 
-       t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
+       if (gpmc_onenand_data->of_node) {
+               gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+                                     &onenand_sync);
+       } else {
+               /*
+                * FIXME: Appears to be legacy code from initial ONENAND commit.
+                * Unclear what boards this is for and if this can be removed.
+                */
+               if (!cpu_is_omap34xx())
+                       onenand_sync.wait_on_read = true;
+       }
+
+       omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
 
-       ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
+       if (ret < 0)
+               return ret;
+
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       if (ret < 0)
                return ret;
 
        set_onenand_cfg(onenand_base);
@@ -359,6 +357,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
        int err;
+       struct device *dev = &gpmc_onenand_device.dev;
 
        gpmc_onenand_data = _onenand_data;
        gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
@@ -366,7 +365,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 
        if (cpu_is_omap24xx() &&
                        (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
-               printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
+               dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
                gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
                gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
        }
@@ -379,7 +378,8 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
        err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
                                (unsigned long *)&gpmc_onenand_resource.start);
        if (err < 0) {
-               pr_err("%s: Cannot request GPMC CS\n", __func__);
+               dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
+                       gpmc_onenand_data->cs, err);
                return;
        }
 
@@ -387,7 +387,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
                                                        ONENAND_IO_SIZE - 1;
 
        if (platform_device_register(&gpmc_onenand_device) < 0) {
-               pr_err("%s: Unable to register OneNAND device\n", __func__);
+               dev_err(dev, "Unable to register OneNAND device\n");
                gpmc_cs_free(gpmc_onenand_data->cs);
                return;
        }