Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+75 -25
+6 -24
arch/arm/mach-omap2/gpmc-onenand.c
··· 181 181 const int t_wpl = 40; 182 182 const int t_wph = 30; 183 183 int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; 184 - u32 reg; 185 184 int div, fclk_offset_ns, gpmc_clk_ns; 186 185 int ticks_cez; 187 - int cs = cfg->cs; 188 186 189 187 if (cfg->flags & ONENAND_SYNC_READ) 190 188 onenand_flags = ONENAND_FLAG_SYNCREAD; ··· 252 254 memset(&t, 0, sizeof(t)); 253 255 254 256 if (div == 1) { 255 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 256 - reg |= (1 << 7); 257 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 258 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 259 - reg |= (1 << 7); 260 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 261 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 262 - reg |= (1 << 7); 263 - reg |= (1 << 23); 264 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 265 - } else { 266 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); 267 - reg &= ~(1 << 7); 268 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); 269 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); 270 - reg &= ~(1 << 7); 271 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); 272 - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); 273 - reg &= ~(1 << 7); 274 - reg &= ~(1 << 23); 275 - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); 257 + t.bool_timings.cs_extra_delay = true; 258 + t.bool_timings.adv_extra_delay = true; 259 + t.bool_timings.oe_extra_delay = true; 260 + t.bool_timings.we_extra_delay = true; 276 261 } 277 262 278 263 t.sync_clk = min_gpmc_clk_period; ··· 277 296 ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; 278 297 t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + 279 298 ticks_cez); 299 + 300 + t.clk_activation = fclk_offset_ns; 280 301 281 302 /* Write */ 282 303 if (onenand_flags & ONENAND_FLAG_SYNCWRITE) { ··· 321 338 (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | 322 339 (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | 323 340 (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | 324 - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | 325 341 GPMC_CONFIG1_PAGE_LEN(2) | 326 342 (cpu_is_omap34xx() ? 0 : 327 343 (GPMC_CONFIG1_WAIT_READ_MON |
+48
arch/arm/mach-omap2/gpmc.c
··· 74 74 #define GPMC_ECC_CTRL_ECCREG8 0x008 75 75 #define GPMC_ECC_CTRL_ECCREG9 0x009 76 76 77 + #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) 78 + #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) 79 + #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) 80 + #define GPMC_CONFIG4_WEEXTRADELAY BIT(23) 81 + #define GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN BIT(6) 82 + #define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN BIT(7) 83 + 77 84 #define GPMC_CS0_OFFSET 0x60 78 85 #define GPMC_CS_SIZE 0x30 79 86 #define GPMC_BCH_SIZE 0x10 ··· 230 223 return ticks * gpmc_get_fclk_period() / 1000; 231 224 } 232 225 226 + static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) 227 + { 228 + u32 l; 229 + 230 + l = gpmc_cs_read_reg(cs, reg); 231 + if (value) 232 + l |= mask; 233 + else 234 + l &= ~mask; 235 + gpmc_cs_write_reg(cs, reg, l); 236 + } 237 + 238 + static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) 239 + { 240 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, 241 + GPMC_CONFIG1_TIME_PARA_GRAN, 242 + p->time_para_granularity); 243 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2, 244 + GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay); 245 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3, 246 + GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay); 247 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, 248 + GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay); 249 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, 250 + GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay); 251 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, 252 + GPMC_CONFIG6_CYCLE2CYCLESAMECSEN, 253 + p->cycle2cyclesamecsen); 254 + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, 255 + GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN, 256 + p->cycle2cyclediffcsen); 257 + } 258 + 233 259 #ifdef DEBUG 234 260 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, 235 261 int time, const char *name) ··· 356 316 357 317 GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); 358 318 319 + GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); 320 + GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); 321 + 322 + GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); 323 + GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); 324 + 359 325 if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) 360 326 GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); 361 327 if (gpmc_capability & GPMC_HAS_WR_ACCESS) ··· 380 334 l |= (div - 1); 381 335 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); 382 336 } 337 + 338 + gpmc_cs_bool_timings(cs, &t->bool_timings); 383 339 384 340 return 0; 385 341 }
+19
arch/arm/mach-omap2/gpmc.h
··· 74 74 #define GPMC_IRQ_COUNT_EVENT 0x02 75 75 76 76 77 + /* bool type time settings */ 78 + struct gpmc_bool_timings { 79 + bool cycle2cyclediffcsen; 80 + bool cycle2cyclesamecsen; 81 + bool we_extra_delay; 82 + bool oe_extra_delay; 83 + bool adv_extra_delay; 84 + bool cs_extra_delay; 85 + bool time_para_granularity; 86 + }; 87 + 77 88 /* 78 89 * Note that all values in this struct are in nanoseconds except sync_clk 79 90 * (which is in picoseconds), while the register values are in gpmc_fck cycles. ··· 117 106 u16 rd_cycle; /* Total read cycle time */ 118 107 u16 wr_cycle; /* Total write cycle time */ 119 108 109 + u16 bus_turnaround; 110 + u16 cycle2cycle_delay; 111 + 112 + u16 wait_monitoring; 113 + u16 clk_activation; 114 + 120 115 /* The following are only on OMAP3430 */ 121 116 u16 wr_access; /* WRACCESSTIME */ 122 117 u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */ 118 + 119 + struct gpmc_bool_timings bool_timings; 123 120 }; 124 121 125 122 extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+2 -1
arch/arm/mach-omap2/usb-tusb6010.c
··· 175 175 tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */; 176 176 t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); 177 177 178 + t.clk_activation = gpmc_ticks_to_ns(1); 179 + 178 180 return gpmc_cs_set_timings(sync_cs, &t); 179 181 } 180 182 ··· 286 284 | GPMC_CONFIG1_READTYPE_SYNC 287 285 | GPMC_CONFIG1_WRITEMULTIPLE_SUPP 288 286 | GPMC_CONFIG1_WRITETYPE_SYNC 289 - | GPMC_CONFIG1_CLKACTIVATIONTIME(1) 290 287 | GPMC_CONFIG1_PAGE_LEN(2) 291 288 | GPMC_CONFIG1_WAIT_READ_MON 292 289 | GPMC_CONFIG1_WAIT_WRITE_MON