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;
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;
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;
(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 |
#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
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)
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)
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
}
+ gpmc_cs_bool_timings(cs, &t->bool_timings);
+
return 0;
}
#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.
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);
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);
}
| 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