diff options
author | Tony Lindgren <tony@atomide.com> | 2014-11-03 20:45:01 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-11-03 20:45:01 -0500 |
commit | 35ac051e019431ccdfdaa9d71e08123870770de2 (patch) | |
tree | 7481403cae9a4c39c10229d0b9bacdeb78565940 | |
parent | 9ed7a776eb50de2284dd053c719f2f6481af9027 (diff) |
ARM: OMAP2+: Show bootloader GPMC timings to allow configuring the .dts file
As we still have some devices with GPMC timings missing from the
.dts files, let's make it a bit easier to use the bootloader
values and print them out.
Note that we now need to move the parsing of the device tree provided
configuration a bit earlier so we can use that for checking if anything
was configured.
Acked-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 144 |
1 files changed, 141 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 2c5f3485e44c..eee7065a5020 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -292,6 +292,129 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) | |||
292 | } | 292 | } |
293 | 293 | ||
294 | #ifdef DEBUG | 294 | #ifdef DEBUG |
295 | static int get_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | ||
296 | bool raw, bool noval, int shift, | ||
297 | const char *name) | ||
298 | { | ||
299 | u32 l; | ||
300 | int nr_bits, max_value, mask; | ||
301 | |||
302 | l = gpmc_cs_read_reg(cs, reg); | ||
303 | nr_bits = end_bit - st_bit + 1; | ||
304 | max_value = (1 << nr_bits) - 1; | ||
305 | mask = max_value << st_bit; | ||
306 | l = (l & mask) >> st_bit; | ||
307 | if (shift) | ||
308 | l = (shift << l); | ||
309 | if (noval && (l == 0)) | ||
310 | return 0; | ||
311 | if (!raw) { | ||
312 | unsigned int time_ns_min, time_ns, time_ns_max; | ||
313 | |||
314 | time_ns_min = gpmc_ticks_to_ns(l ? l - 1 : 0); | ||
315 | time_ns = gpmc_ticks_to_ns(l); | ||
316 | time_ns_max = gpmc_ticks_to_ns(l + 1 > max_value ? | ||
317 | max_value : l + 1); | ||
318 | pr_info("gpmc,%s = <%u> (%u - %u ns, %i ticks)\n", | ||
319 | name, time_ns, time_ns_min, time_ns_max, l); | ||
320 | } else { | ||
321 | pr_info("gpmc,%s = <%u>\n", name, l); | ||
322 | } | ||
323 | |||
324 | return l; | ||
325 | } | ||
326 | |||
327 | #define GPMC_PRINT_CONFIG(cs, config) \ | ||
328 | pr_info("cs%i %s: 0x%08x\n", cs, #config, \ | ||
329 | gpmc_cs_read_reg(cs, config)) | ||
330 | #define GPMC_GET_RAW(reg, st, end, field) \ | ||
331 | get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 0, 0, field) | ||
332 | #define GPMC_GET_RAW_BOOL(reg, st, end, field) \ | ||
333 | get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, 0, field) | ||
334 | #define GPMC_GET_RAW_SHIFT(reg, st, end, shift, field) \ | ||
335 | get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, (shift), field) | ||
336 | #define GPMC_GET_TICKS(reg, st, end, field) \ | ||
337 | get_gpmc_timing_reg(cs, (reg), (st), (end), 0, 0, 0, field) | ||
338 | |||
339 | static void gpmc_show_regs(int cs, const char *desc) | ||
340 | { | ||
341 | pr_info("gpmc cs%i %s:\n", cs, desc); | ||
342 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG1); | ||
343 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG2); | ||
344 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG3); | ||
345 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG4); | ||
346 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG5); | ||
347 | GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG6); | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Note that gpmc,wait-pin handing wrongly assumes bit 8 is available, | ||
352 | * see commit c9fb809. | ||
353 | */ | ||
354 | static void gpmc_cs_show_timings(int cs, const char *desc) | ||
355 | { | ||
356 | gpmc_show_regs(cs, desc); | ||
357 | |||
358 | pr_info("gpmc cs%i access configuration:\n", cs); | ||
359 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 4, 4, "time-para-granularity"); | ||
360 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 8, 9, "mux-add-data"); | ||
361 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 12, 13, "device-width"); | ||
362 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin"); | ||
363 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write"); | ||
364 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read"); | ||
365 | GPMC_GET_RAW_SHIFT(GPMC_CS_CONFIG1, 23, 24, 4, "burst-length"); | ||
366 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write"); | ||
367 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write"); | ||
368 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read"); | ||
369 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 30, 30, "burst-read"); | ||
370 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 31, 31, "burst-wrap"); | ||
371 | |||
372 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG2, 7, 7, "cs-extra-delay"); | ||
373 | |||
374 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG3, 7, 7, "adv-extra-delay"); | ||
375 | |||
376 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 23, 23, "we-extra-delay"); | ||
377 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 7, 7, "oe-extra-delay"); | ||
378 | |||
379 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6, 7, 7, "cycle2cycle-samecsen"); | ||
380 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6, 6, 6, "cycle2cycle-diffcsen"); | ||
381 | |||
382 | pr_info("gpmc cs%i timings configuration:\n", cs); | ||
383 | GPMC_GET_TICKS(GPMC_CS_CONFIG2, 0, 3, "cs-on-ns"); | ||
384 | GPMC_GET_TICKS(GPMC_CS_CONFIG2, 8, 12, "cs-rd-off-ns"); | ||
385 | GPMC_GET_TICKS(GPMC_CS_CONFIG2, 16, 20, "cs-wr-off-ns"); | ||
386 | |||
387 | GPMC_GET_TICKS(GPMC_CS_CONFIG3, 0, 3, "adv-on-ns"); | ||
388 | GPMC_GET_TICKS(GPMC_CS_CONFIG3, 8, 12, "adv-rd-off-ns"); | ||
389 | GPMC_GET_TICKS(GPMC_CS_CONFIG3, 16, 20, "adv-wr-off-ns"); | ||
390 | |||
391 | GPMC_GET_TICKS(GPMC_CS_CONFIG4, 0, 3, "oe-on-ns"); | ||
392 | GPMC_GET_TICKS(GPMC_CS_CONFIG4, 8, 12, "oe-off-ns"); | ||
393 | GPMC_GET_TICKS(GPMC_CS_CONFIG4, 16, 19, "we-on-ns"); | ||
394 | GPMC_GET_TICKS(GPMC_CS_CONFIG4, 24, 28, "we-off-ns"); | ||
395 | |||
396 | GPMC_GET_TICKS(GPMC_CS_CONFIG5, 0, 4, "rd-cycle-ns"); | ||
397 | GPMC_GET_TICKS(GPMC_CS_CONFIG5, 8, 12, "wr-cycle-ns"); | ||
398 | GPMC_GET_TICKS(GPMC_CS_CONFIG5, 16, 20, "access-ns"); | ||
399 | |||
400 | GPMC_GET_TICKS(GPMC_CS_CONFIG5, 24, 27, "page-burst-access-ns"); | ||
401 | |||
402 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns"); | ||
403 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns"); | ||
404 | |||
405 | GPMC_GET_TICKS(GPMC_CS_CONFIG1, 18, 19, "wait-monitoring-ns"); | ||
406 | GPMC_GET_TICKS(GPMC_CS_CONFIG1, 25, 26, "clk-activation-ns"); | ||
407 | |||
408 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns"); | ||
409 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns"); | ||
410 | } | ||
411 | #else | ||
412 | static inline void gpmc_cs_show_timings(int cs, const char *desc) | ||
413 | { | ||
414 | } | ||
415 | #endif | ||
416 | |||
417 | #ifdef DEBUG | ||
295 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | 418 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, |
296 | int time, const char *name) | 419 | int time, const char *name) |
297 | #else | 420 | #else |
@@ -361,6 +484,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
361 | int div; | 484 | int div; |
362 | u32 l; | 485 | u32 l; |
363 | 486 | ||
487 | gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings"); | ||
364 | div = gpmc_calc_divider(t->sync_clk); | 488 | div = gpmc_calc_divider(t->sync_clk); |
365 | if (div < 0) | 489 | if (div < 0) |
366 | return div; | 490 | return div; |
@@ -410,6 +534,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
410 | } | 534 | } |
411 | 535 | ||
412 | gpmc_cs_bool_timings(cs, &t->bool_timings); | 536 | gpmc_cs_bool_timings(cs, &t->bool_timings); |
537 | gpmc_cs_show_timings(cs, "after gpmc_cs_set_timings"); | ||
413 | 538 | ||
414 | return 0; | 539 | return 0; |
415 | } | 540 | } |
@@ -1571,6 +1696,22 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1571 | } | 1696 | } |
1572 | gpmc_cs_set_name(cs, child->name); | 1697 | gpmc_cs_set_name(cs, child->name); |
1573 | 1698 | ||
1699 | gpmc_read_settings_dt(child, &gpmc_s); | ||
1700 | gpmc_read_timings_dt(child, &gpmc_t); | ||
1701 | |||
1702 | /* | ||
1703 | * For some GPMC devices we still need to rely on the bootloader | ||
1704 | * timings because the devices can be connected via FPGA. | ||
1705 | * REVISIT: Add timing support from slls644g.pdf. | ||
1706 | */ | ||
1707 | if (!gpmc_t.cs_rd_off) { | ||
1708 | WARN(1, "enable GPMC debug to configure .dts timings for CS%i\n", | ||
1709 | cs); | ||
1710 | gpmc_cs_show_timings(cs, | ||
1711 | "please add GPMC bootloader timings to .dts"); | ||
1712 | goto no_timings; | ||
1713 | } | ||
1714 | |||
1574 | /* | 1715 | /* |
1575 | * For some GPMC devices we still need to rely on the bootloader | 1716 | * For some GPMC devices we still need to rely on the bootloader |
1576 | * timings because the devices can be connected via FPGA. So far | 1717 | * timings because the devices can be connected via FPGA. So far |
@@ -1602,8 +1743,6 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1602 | goto err; | 1743 | goto err; |
1603 | } | 1744 | } |
1604 | 1745 | ||
1605 | gpmc_read_settings_dt(child, &gpmc_s); | ||
1606 | |||
1607 | ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); | 1746 | ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); |
1608 | if (ret < 0) | 1747 | if (ret < 0) |
1609 | goto err; | 1748 | goto err; |
@@ -1612,7 +1751,6 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1612 | if (ret < 0) | 1751 | if (ret < 0) |
1613 | goto err; | 1752 | goto err; |
1614 | 1753 | ||
1615 | gpmc_read_timings_dt(child, &gpmc_t); | ||
1616 | gpmc_cs_set_timings(cs, &gpmc_t); | 1754 | gpmc_cs_set_timings(cs, &gpmc_t); |
1617 | 1755 | ||
1618 | no_timings: | 1756 | no_timings: |