diff options
author | Robert ABEL <rabel@cit-ec.uni-bielefeld.de> | 2015-02-27 10:56:55 -0500 |
---|---|---|
committer | Roger Quadros <rogerq@ti.com> | 2015-03-06 05:55:32 -0500 |
commit | 4b613e9b4bbe94545a588a100e09006d827a7ebe (patch) | |
tree | c948cde4f4ad27625865f3c3cebf0da5309dd2f5 | |
parent | 7f2e8c58ae9e35240e5924c63163c07a506d0d12 (diff) |
ARM OMAP2+ GPMC: fix programming/showing reserved timing parameters
GPMC_CONFIG1_i parameters CLKACTIVATIONTIME and WAITMONITORINGTIME
have reserved values.
Raise an error if calculated timings try to program reserved values.
GPMC_CONFIG1_i ATTACHEDDEVICEPAGELENGTH and DEVICESIZE were already checked
when parsing the DT.
Explicitly comment invalid values on gpmc_cs_show_timings for
-CLKACTIVATIONTIME
-WAITMONITORINGTIME
-DEVICESIZE
-ATTACHEDDEVICEPAGELENGTH
Signed-off-by: Robert ABEL <rabel@cit-ec.uni-bielefeld.de>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
-rw-r--r-- | drivers/memory/omap-gpmc.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 6c076b7c9b6f..c94ea0d68746 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c | |||
@@ -135,7 +135,11 @@ | |||
135 | #define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) | 135 | #define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) |
136 | #define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) | 136 | #define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) |
137 | #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) | 137 | #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) |
138 | /** CLKACTIVATIONTIME Max Ticks */ | ||
139 | #define GPMC_CONFIG1_CLKACTIVATIONTIME_MAX 2 | ||
138 | #define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) | 140 | #define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) |
141 | /** ATTACHEDDEVICEPAGELENGTH Max Value */ | ||
142 | #define GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX 2 | ||
139 | #define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) | 143 | #define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) |
140 | #define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) | 144 | #define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) |
141 | #define GPMC_CONFIG1_WAIT_MON_TIME(val) ((val & 3) << 18) | 145 | #define GPMC_CONFIG1_WAIT_MON_TIME(val) ((val & 3) << 18) |
@@ -144,6 +148,8 @@ | |||
144 | #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) | 148 | #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) |
145 | #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) | 149 | #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) |
146 | #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) | 150 | #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) |
151 | /** DEVICESIZE Max Value */ | ||
152 | #define GPMC_CONFIG1_DEVICESIZE_MAX 1 | ||
147 | #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) | 153 | #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) |
148 | #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) | 154 | #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) |
149 | #define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) | 155 | #define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) |
@@ -404,6 +410,8 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) | |||
404 | * @reg: GPMC_CS_CONFIGn register offset. | 410 | * @reg: GPMC_CS_CONFIGn register offset. |
405 | * @st_bit: Start Bit | 411 | * @st_bit: Start Bit |
406 | * @end_bit: End Bit. Must be >= @st_bit. | 412 | * @end_bit: End Bit. Must be >= @st_bit. |
413 | * @ma:x Maximum parameter value (before optional @shift). | ||
414 | * If 0, maximum is as high as @st_bit and @end_bit allow. | ||
407 | * @name: DTS node name, w/o "gpmc," | 415 | * @name: DTS node name, w/o "gpmc," |
408 | * @cd: Clock Domain of timing parameter. | 416 | * @cd: Clock Domain of timing parameter. |
409 | * @shift: Parameter value left shifts @shift, which is then printed instead of value. | 417 | * @shift: Parameter value left shifts @shift, which is then printed instead of value. |
@@ -411,13 +419,14 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) | |||
411 | * raw format: gpmc,name = <value> | 419 | * raw format: gpmc,name = <value> |
412 | * tick format: gpmc,name = <value> /‍* x ns -- y ns; x ticks *‍/ | 420 | * tick format: gpmc,name = <value> /‍* x ns -- y ns; x ticks *‍/ |
413 | * Where x ns -- y ns result in the same tick value. | 421 | * Where x ns -- y ns result in the same tick value. |
422 | * When @max is exceeded, "invalid" is printed inside comment. | ||
414 | * @noval: Parameter values equal to 0 are not printed. | 423 | * @noval: Parameter values equal to 0 are not printed. |
415 | * @return: Specified timing parameter (after optional @shift). | 424 | * @return: Specified timing parameter (after optional @shift). |
416 | * | 425 | * |
417 | */ | 426 | */ |
418 | static int get_gpmc_timing_reg( | 427 | static int get_gpmc_timing_reg( |
419 | /* timing specifiers */ | 428 | /* timing specifiers */ |
420 | int cs, int reg, int st_bit, int end_bit, | 429 | int cs, int reg, int st_bit, int end_bit, int max, |
421 | const char *name, const enum gpmc_clk_domain cd, | 430 | const char *name, const enum gpmc_clk_domain cd, |
422 | /* value transform */ | 431 | /* value transform */ |
423 | int shift, | 432 | int shift, |
@@ -427,11 +436,15 @@ static int get_gpmc_timing_reg( | |||
427 | u32 l; | 436 | u32 l; |
428 | int nr_bits; | 437 | int nr_bits; |
429 | int mask; | 438 | int mask; |
439 | bool invalid; | ||
430 | 440 | ||
431 | l = gpmc_cs_read_reg(cs, reg); | 441 | l = gpmc_cs_read_reg(cs, reg); |
432 | nr_bits = end_bit - st_bit + 1; | 442 | nr_bits = end_bit - st_bit + 1; |
433 | mask = (1 << nr_bits) - 1; | 443 | mask = (1 << nr_bits) - 1; |
434 | l = (l >> st_bit) & mask; | 444 | l = (l >> st_bit) & mask; |
445 | if (!max) | ||
446 | max = mask; | ||
447 | invalid = l > max; | ||
435 | if (shift) | 448 | if (shift) |
436 | l = (shift << l); | 449 | l = (shift << l); |
437 | if (noval && (l == 0)) | 450 | if (noval && (l == 0)) |
@@ -444,11 +457,13 @@ static int get_gpmc_timing_reg( | |||
444 | if (l) | 457 | if (l) |
445 | time_ns_min = gpmc_clk_ticks_to_ns(l - 1, cs, cd) + 1; | 458 | time_ns_min = gpmc_clk_ticks_to_ns(l - 1, cs, cd) + 1; |
446 | time_ns = gpmc_clk_ticks_to_ns(l, cs, cd); | 459 | time_ns = gpmc_clk_ticks_to_ns(l, cs, cd); |
447 | pr_info("gpmc,%s = <%u> /* %u ns - %u ns; %i ticks */\n", | 460 | pr_info("gpmc,%s = <%u> /* %u ns - %u ns; %i ticks%s*/\n", |
448 | name, time_ns, time_ns_min, time_ns, l); | 461 | name, time_ns, time_ns_min, time_ns, l, |
462 | invalid ? "; invalid " : " "); | ||
449 | } else { | 463 | } else { |
450 | /* raw format */ | 464 | /* raw format */ |
451 | pr_info("gpmc,%s = <%u>\n", name, l); | 465 | pr_info("gpmc,%s = <%u>%s\n", name, l, |
466 | invalid ? " /* invalid */" : ""); | ||
452 | } | 467 | } |
453 | 468 | ||
454 | return l; | 469 | return l; |
@@ -458,15 +473,19 @@ static int get_gpmc_timing_reg( | |||
458 | pr_info("cs%i %s: 0x%08x\n", cs, #config, \ | 473 | pr_info("cs%i %s: 0x%08x\n", cs, #config, \ |
459 | gpmc_cs_read_reg(cs, config)) | 474 | gpmc_cs_read_reg(cs, config)) |
460 | #define GPMC_GET_RAW(reg, st, end, field) \ | 475 | #define GPMC_GET_RAW(reg, st, end, field) \ |
461 | get_gpmc_timing_reg(cs, (reg), (st), (end), field, GPMC_CD_FCLK, 0, 1, 0) | 476 | get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 0) |
477 | #define GPMC_GET_RAW_MAX(reg, st, end, max, field) \ | ||
478 | get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, 0, 1, 0) | ||
462 | #define GPMC_GET_RAW_BOOL(reg, st, end, field) \ | 479 | #define GPMC_GET_RAW_BOOL(reg, st, end, field) \ |
463 | get_gpmc_timing_reg(cs, (reg), (st), (end), field, GPMC_CD_FCLK, 0, 1, 1) | 480 | get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 1) |
464 | #define GPMC_GET_RAW_SHIFT(reg, st, end, shift, field) \ | 481 | #define GPMC_GET_RAW_SHIFT_MAX(reg, st, end, shift, max, field) \ |
465 | get_gpmc_timing_reg(cs, (reg), (st), (end), field, GPMC_CD_FCLK, (shift), 1, 1) | 482 | get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, (shift), 1, 1) |
466 | #define GPMC_GET_TICKS(reg, st, end, field) \ | 483 | #define GPMC_GET_TICKS(reg, st, end, field) \ |
467 | get_gpmc_timing_reg(cs, (reg), (st), (end), field, GPMC_CD_FCLK, 0, 0, 0) | 484 | get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 0, 0) |
468 | #define GPMC_GET_TICKS_CD(reg, st, end, field, cd) \ | 485 | #define GPMC_GET_TICKS_CD(reg, st, end, field, cd) \ |
469 | get_gpmc_timing_reg(cs, (reg), (st), (end), field, (cd), 0, 0, 0) | 486 | get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, (cd), 0, 0, 0) |
487 | #define GPMC_GET_TICKS_CD_MAX(reg, st, end, max, field, cd) \ | ||
488 | get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, (cd), 0, 0, 0) | ||
470 | 489 | ||
471 | static void gpmc_show_regs(int cs, const char *desc) | 490 | static void gpmc_show_regs(int cs, const char *desc) |
472 | { | 491 | { |
@@ -490,11 +509,14 @@ static void gpmc_cs_show_timings(int cs, const char *desc) | |||
490 | pr_info("gpmc cs%i access configuration:\n", cs); | 509 | pr_info("gpmc cs%i access configuration:\n", cs); |
491 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 4, 4, "time-para-granularity"); | 510 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 4, 4, "time-para-granularity"); |
492 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 8, 9, "mux-add-data"); | 511 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 8, 9, "mux-add-data"); |
493 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 12, 13, "device-width"); | 512 | GPMC_GET_RAW_MAX(GPMC_CS_CONFIG1, 12, 13, |
513 | GPMC_CONFIG1_DEVICESIZE_MAX, "device-width"); | ||
494 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin"); | 514 | GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin"); |
495 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write"); | 515 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write"); |
496 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read"); | 516 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read"); |
497 | GPMC_GET_RAW_SHIFT(GPMC_CS_CONFIG1, 23, 24, 4, "burst-length"); | 517 | GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 23, 24, 4, |
518 | GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX, | ||
519 | "burst-length"); | ||
498 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write"); | 520 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write"); |
499 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write"); | 521 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write"); |
500 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read"); | 522 | GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read"); |
@@ -534,8 +556,12 @@ static void gpmc_cs_show_timings(int cs, const char *desc) | |||
534 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns"); | 556 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns"); |
535 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns"); | 557 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns"); |
536 | 558 | ||
537 | GPMC_GET_TICKS_CD(GPMC_CS_CONFIG1, 18, 19, "wait-monitoring-ns", GPMC_CD_CLK); | 559 | GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 18, 19, |
538 | GPMC_GET_TICKS(GPMC_CS_CONFIG1, 25, 26, "clk-activation-ns"); | 560 | GPMC_CONFIG1_WAITMONITORINGTIME_MAX, |
561 | "wait-monitoring-ns", GPMC_CD_CLK); | ||
562 | GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 25, 26, | ||
563 | GPMC_CONFIG1_CLKACTIVATIONTIME_MAX, | ||
564 | "clk-activation-ns", GPMC_CD_FCLK); | ||
539 | 565 | ||
540 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns"); | 566 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns"); |
541 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns"); | 567 | GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns"); |
@@ -555,12 +581,14 @@ static inline void gpmc_cs_show_timings(int cs, const char *desc) | |||
555 | * @reg: GPMC_CS_CONFIGn register offset. | 581 | * @reg: GPMC_CS_CONFIGn register offset. |
556 | * @st_bit: Start Bit | 582 | * @st_bit: Start Bit |
557 | * @end_bit: End Bit. Must be >= @st_bit. | 583 | * @end_bit: End Bit. Must be >= @st_bit. |
584 | * @max: Maximum parameter value. | ||
585 | * If 0, maximum is as high as @st_bit and @end_bit allow. | ||
558 | * @time: Timing parameter in ns. | 586 | * @time: Timing parameter in ns. |
559 | * @cd: Timing parameter clock domain. | 587 | * @cd: Timing parameter clock domain. |
560 | * @name: Timing parameter name. | 588 | * @name: Timing parameter name. |
561 | * @return: 0 on success, -1 on error. | 589 | * @return: 0 on success, -1 on error. |
562 | */ | 590 | */ |
563 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | 591 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max, |
564 | int time, enum gpmc_clk_domain cd, const char *name) | 592 | int time, enum gpmc_clk_domain cd, const char *name) |
565 | { | 593 | { |
566 | u32 l; | 594 | u32 l; |
@@ -573,9 +601,12 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | |||
573 | nr_bits = end_bit - st_bit + 1; | 601 | nr_bits = end_bit - st_bit + 1; |
574 | mask = (1 << nr_bits) - 1; | 602 | mask = (1 << nr_bits) - 1; |
575 | 603 | ||
576 | if (ticks > mask) { | 604 | if (!max) |
605 | max = mask; | ||
606 | |||
607 | if (ticks > max) { | ||
577 | pr_err("%s: GPMC CS%d: %s %d ns, %d ticks > %d ticks\n", | 608 | pr_err("%s: GPMC CS%d: %s %d ns, %d ticks > %d ticks\n", |
578 | __func__, cs, name, time, ticks, mask); | 609 | __func__, cs, name, time, ticks, max); |
579 | 610 | ||
580 | return -1; | 611 | return -1; |
581 | } | 612 | } |
@@ -594,13 +625,13 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | |||
594 | return 0; | 625 | return 0; |
595 | } | 626 | } |
596 | 627 | ||
597 | #define GPMC_SET_ONE_CD(reg, st, end, field, cd) \ | 628 | #define GPMC_SET_ONE_CD_MAX(reg, st, end, max, field, cd) \ |
598 | if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ | 629 | if (set_gpmc_timing_reg(cs, (reg), (st), (end), (max), \ |
599 | t->field, (cd), #field) < 0) \ | 630 | t->field, (cd), #field) < 0) \ |
600 | return -1 | 631 | return -1 |
601 | 632 | ||
602 | #define GPMC_SET_ONE(reg, st, end, field) \ | 633 | #define GPMC_SET_ONE(reg, st, end, field) \ |
603 | GPMC_SET_ONE_CD(reg, st, end, field, GPMC_CD_FCLK) | 634 | GPMC_SET_ONE_CD_MAX(reg, st, end, 0, field, GPMC_CD_FCLK) |
604 | 635 | ||
605 | /** | 636 | /** |
606 | * gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME | 637 | * gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME |
@@ -729,8 +760,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, | |||
729 | l |= (div - 1); | 760 | l |= (div - 1); |
730 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); | 761 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); |
731 | 762 | ||
732 | GPMC_SET_ONE_CD(GPMC_CS_CONFIG1, 18, 19, wait_monitoring, GPMC_CD_CLK); | 763 | GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 18, 19, |
733 | GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); | 764 | GPMC_CONFIG1_WAITMONITORINGTIME_MAX, |
765 | wait_monitoring, GPMC_CD_CLK); | ||
766 | GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 25, 26, | ||
767 | GPMC_CONFIG1_CLKACTIVATIONTIME_MAX, | ||
768 | clk_activation, GPMC_CD_FCLK); | ||
734 | 769 | ||
735 | #ifdef DEBUG | 770 | #ifdef DEBUG |
736 | pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n", | 771 | pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n", |