ARM: OMAP2+: gpmc: handle additional timings
authorAfzal Mohammed <afzal@ti.com>
Mon, 28 May 2012 12:21:37 +0000 (17:51 +0530)
committerAfzal Mohammed <afzal@ti.com>
Fri, 9 Nov 2012 12:37:11 +0000 (18:07 +0530)
Configure busturnaround, cycle2cycledelay, waitmonitoringtime,
clkactivationtime in gpmc_cs_set_timings(). This is done so
that boards can configure these parameters of gpmc in Kernel
instead of relying on bootloader. Also configure bool type
timings like extradelay.

This needed change to the existing users that were configuring
clk activation time and extra delay by directly writing to
registers. Thanks to Tony for making me aware of users of clk
activation and being kind enough to test the modified one.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/gpmc.h
arch/arm/mach-omap2/usb-tusb6010.c

index d102183ed9a5b21289b61678b9f4b49746d68c31..2060088372949b2405023c2147efe4fae3b87a42 100644 (file)
@@ -181,10 +181,8 @@ omap2_onenand_calc_sync_timings(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;
-       u32 reg;
        int div, fclk_offset_ns, gpmc_clk_ns;
        int ticks_cez;
-       int cs = cfg->cs;
 
        if (cfg->flags & ONENAND_SYNC_READ)
                onenand_flags = ONENAND_FLAG_SYNCREAD;
@@ -254,27 +252,10 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        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;
        }
 
        t.sync_clk = min_gpmc_clk_period;
@@ -297,6 +278,8 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
                     ticks_cez);
 
+       t.clk_activation = fclk_offset_ns;
+
        /* Write */
        if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
                t.adv_wr_off = t.adv_rd_off;
@@ -338,7 +321,6 @@ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
                          (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
                          (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
                          (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-                         GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
                          GPMC_CONFIG1_PAGE_LEN(2) |
                          (cpu_is_omap34xx() ? 0 :
                                (GPMC_CONFIG1_WAIT_READ_MON |
index bf6117c32f4bc0302522d0ea6f54b83d7c171ea3..5619d1b486684cb62011e52fd6ea5a58577271aa 100644 (file)
 #define GPMC_ECC_CTRL_ECCREG8          0x008
 #define GPMC_ECC_CTRL_ECCREG9          0x009
 
+#define        GPMC_CONFIG2_CSEXTRADELAY               BIT(7)
+#define        GPMC_CONFIG3_ADVEXTRADELAY              BIT(7)
+#define        GPMC_CONFIG4_OEEXTRADELAY               BIT(7)
+#define        GPMC_CONFIG4_WEEXTRADELAY               BIT(23)
+#define        GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN        BIT(6)
+#define        GPMC_CONFIG6_CYCLE2CYCLESAMECSEN        BIT(7)
+
 #define GPMC_CS0_OFFSET                0x60
 #define GPMC_CS_SIZE           0x30
 #define        GPMC_BCH_SIZE           0x10
@@ -223,6 +230,39 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
        return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, reg);
+       if (value)
+               l |= mask;
+       else
+               l &= ~mask;
+       gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+                          GPMC_CONFIG1_TIME_PARA_GRAN,
+                          p->time_para_granularity);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+                          GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+                          GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+                          GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+                          GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+                          GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+                          p->cycle2cyclesamecsen);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+                          GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+                          p->cycle2cyclediffcsen);
+}
+
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
                               int time, const char *name)
@@ -316,6 +356,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
        GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
+       GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
+       GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
+       GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
+
        if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
                GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
        if (gpmc_capability & GPMC_HAS_WR_ACCESS)
@@ -335,6 +381,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
                gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
        }
 
+       gpmc_cs_bool_timings(cs, &t->bool_timings);
+
        return 0;
 }
 
index 79f4dfc2adb3cec5d6f40af94796bc8558492a99..e08a51a7a76ad95448c29ab8c99065be5b8e301f 100644 (file)
 #define GPMC_IRQ_COUNT_EVENT           0x02
 
 
+/* bool type time settings */
+struct gpmc_bool_timings {
+       bool cycle2cyclediffcsen;
+       bool cycle2cyclesamecsen;
+       bool we_extra_delay;
+       bool oe_extra_delay;
+       bool adv_extra_delay;
+       bool cs_extra_delay;
+       bool time_para_granularity;
+};
+
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
  * (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -106,9 +117,17 @@ struct gpmc_timings {
        u16 rd_cycle;           /* Total read cycle time */
        u16 wr_cycle;           /* Total write cycle time */
 
+       u16 bus_turnaround;
+       u16 cycle2cycle_delay;
+
+       u16 wait_monitoring;
+       u16 clk_activation;
+
        /* The following are only on OMAP3430 */
        u16 wr_access;          /* WRACCESSTIME */
        u16 wr_data_mux_bus;    /* WRDATAONADMUXBUS */
+
+       struct gpmc_bool_timings bool_timings;
 };
 
 extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
index a8795ff19e6deb6f415ee01b584fb0047e40e27b..5be96c6e14166a08141c83e03485af423948e6eb 100644 (file)
@@ -175,6 +175,8 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
        tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
        t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
+       t.clk_activation = gpmc_ticks_to_ns(1);
+
        return gpmc_cs_set_timings(sync_cs, &t);
 }
 
@@ -284,7 +286,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
                        | GPMC_CONFIG1_READTYPE_SYNC
                        | GPMC_CONFIG1_WRITEMULTIPLE_SUPP
                        | GPMC_CONFIG1_WRITETYPE_SYNC
-                       | GPMC_CONFIG1_CLKACTIVATIONTIME(1)
                        | GPMC_CONFIG1_PAGE_LEN(2)
                        | GPMC_CONFIG1_WAIT_READ_MON
                        | GPMC_CONFIG1_WAIT_WRITE_MON