diff options
author | Afzal Mohammed <afzal@ti.com> | 2012-05-28 16:21:37 +0400 |
---|---|---|
committer | Afzal Mohammed <afzal@ti.com> | 2012-11-09 16:37:11 +0400 |
commit | 559d94b00c4dca74b060bae1feeb81cac38628a6 (patch) | |
tree | b5294c16ac82c6ecac29b288f29555da20e690e4 /arch/arm/mach-omap2/gpmc.c | |
parent | a1bfdc6020c2ac52fbadca11cc99c7c63b310d37 (diff) | |
download | linux-559d94b00c4dca74b060bae1feeb81cac38628a6.tar.xz |
ARM: OMAP2+: gpmc: handle additional timings
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>
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index bf6117c32f4b..5619d1b48668 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -74,6 +74,13 @@ #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; } |