3333#define CTRL_IO_ADDRESS_4B BIT(13) /* AST2400 SPI only */
3434#define CTRL_IO_DUMMY_SET (dummy ) \
3535 (((((dummy) >> 2) & 0x1) << 14) | (((dummy) & 0x3) << 6))
36+ #define CTRL_FREQ_SEL_SHIFT 8
37+ #define CTRL_FREQ_SEL_MASK GENMASK(11, CTRL_FREQ_SEL_SHIFT)
3638#define CTRL_CE_STOP_ACTIVE BIT(2)
3739#define CTRL_IO_MODE_CMD_MASK GENMASK(1, 0)
3840#define CTRL_IO_MODE_NORMAL 0x0
4547/* CEx Address Decoding Range Register */
4648#define CE0_SEGMENT_ADDR_REG 0x30
4749
50+ /* CEx Read timing compensation register */
51+ #define CE0_TIMING_COMPENSATION_REG 0x94
52+
4853enum aspeed_spi_ctl_reg_value {
4954 ASPEED_SPI_BASE ,
5055 ASPEED_SPI_READ ,
@@ -70,10 +75,15 @@ struct aspeed_spi_data {
7075 bool hastype ;
7176 u32 mode_bits ;
7277 u32 we0 ;
78+ u32 timing ;
79+ u32 hclk_mask ;
80+ u32 hdiv_max ;
7381
7482 u32 (* segment_start )(struct aspeed_spi * aspi , u32 reg );
7583 u32 (* segment_end )(struct aspeed_spi * aspi , u32 reg );
7684 u32 (* segment_reg )(struct aspeed_spi * aspi , u32 start , u32 end );
85+ int (* calibrate )(struct aspeed_spi_chip * chip , u32 hdiv ,
86+ const u8 * golden_buf , u8 * test_buf );
7787};
7888
7989#define ASPEED_SPI_MAX_NUM_CS 5
@@ -525,6 +535,8 @@ static int aspeed_spi_chip_adjust_window(struct aspeed_spi_chip *chip,
525535 return 0 ;
526536}
527537
538+ static int aspeed_spi_do_calibration (struct aspeed_spi_chip * chip );
539+
528540static int aspeed_spi_dirmap_create (struct spi_mem_dirmap_desc * desc )
529541{
530542 struct aspeed_spi * aspi = spi_controller_get_devdata (desc -> mem -> spi -> master );
@@ -573,6 +585,8 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
573585 chip -> ctl_val [ASPEED_SPI_READ ] = ctl_val ;
574586 writel (chip -> ctl_val [ASPEED_SPI_READ ], chip -> ctl );
575587
588+ ret = aspeed_spi_do_calibration (chip );
589+
576590 dev_info (aspi -> dev , "CE%d read buswidth:%d [0x%08x]\n" ,
577591 chip -> cs , op -> data .buswidth , chip -> ctl_val [ASPEED_SPI_READ ]);
578592
@@ -825,6 +839,249 @@ static u32 aspeed_spi_segment_ast2600_reg(struct aspeed_spi *aspi,
825839 ((end - 1 ) & AST2600_SEG_ADDR_MASK );
826840}
827841
842+ /*
843+ * Read timing compensation sequences
844+ */
845+
846+ #define CALIBRATE_BUF_SIZE SZ_16K
847+
848+ static bool aspeed_spi_check_reads (struct aspeed_spi_chip * chip ,
849+ const u8 * golden_buf , u8 * test_buf )
850+ {
851+ int i ;
852+
853+ for (i = 0 ; i < 10 ; i ++ ) {
854+ memcpy_fromio (test_buf , chip -> ahb_base , CALIBRATE_BUF_SIZE );
855+ if (memcmp (test_buf , golden_buf , CALIBRATE_BUF_SIZE ) != 0 ) {
856+ #if defined(VERBOSE_DEBUG )
857+ print_hex_dump_bytes (DEVICE_NAME " fail: " , DUMP_PREFIX_NONE ,
858+ test_buf , 0x100 );
859+ #endif
860+ return false;
861+ }
862+ }
863+ return true;
864+ }
865+
866+ #define FREAD_TPASS (i ) (((i) / 2) | (((i) & 1) ? 0 : 8))
867+
868+ /*
869+ * The timing register is shared by all devices. Only update for CE0.
870+ */
871+ static int aspeed_spi_calibrate (struct aspeed_spi_chip * chip , u32 hdiv ,
872+ const u8 * golden_buf , u8 * test_buf )
873+ {
874+ struct aspeed_spi * aspi = chip -> aspi ;
875+ const struct aspeed_spi_data * data = aspi -> data ;
876+ int i ;
877+ int good_pass = -1 , pass_count = 0 ;
878+ u32 shift = (hdiv - 1 ) << 2 ;
879+ u32 mask = ~(0xfu << shift );
880+ u32 fread_timing_val = 0 ;
881+
882+ /* Try HCLK delay 0..5, each one with/without delay and look for a
883+ * good pair.
884+ */
885+ for (i = 0 ; i < 12 ; i ++ ) {
886+ bool pass ;
887+
888+ if (chip -> cs == 0 ) {
889+ fread_timing_val &= mask ;
890+ fread_timing_val |= FREAD_TPASS (i ) << shift ;
891+ writel (fread_timing_val , aspi -> regs + data -> timing );
892+ }
893+ pass = aspeed_spi_check_reads (chip , golden_buf , test_buf );
894+ dev_dbg (aspi -> dev ,
895+ " * [%08x] %d HCLK delay, %dns DI delay : %s" ,
896+ fread_timing_val , i / 2 , (i & 1 ) ? 0 : 4 ,
897+ pass ? "PASS" : "FAIL" );
898+ if (pass ) {
899+ pass_count ++ ;
900+ if (pass_count == 3 ) {
901+ good_pass = i - 1 ;
902+ break ;
903+ }
904+ } else {
905+ pass_count = 0 ;
906+ }
907+ }
908+
909+ /* No good setting for this frequency */
910+ if (good_pass < 0 )
911+ return -1 ;
912+
913+ /* We have at least one pass of margin, let's use first pass */
914+ if (chip -> cs == 0 ) {
915+ fread_timing_val &= mask ;
916+ fread_timing_val |= FREAD_TPASS (good_pass ) << shift ;
917+ writel (fread_timing_val , aspi -> regs + data -> timing );
918+ }
919+ dev_dbg (aspi -> dev , " * -> good is pass %d [0x%08x]" ,
920+ good_pass , fread_timing_val );
921+ return 0 ;
922+ }
923+
924+ static bool aspeed_spi_check_calib_data (const u8 * test_buf , u32 size )
925+ {
926+ const u32 * tb32 = (const u32 * )test_buf ;
927+ u32 i , cnt = 0 ;
928+
929+ /* We check if we have enough words that are neither all 0
930+ * nor all 1's so the calibration can be considered valid.
931+ *
932+ * I use an arbitrary threshold for now of 64
933+ */
934+ size >>= 2 ;
935+ for (i = 0 ; i < size ; i ++ ) {
936+ if (tb32 [i ] != 0 && tb32 [i ] != 0xffffffff )
937+ cnt ++ ;
938+ }
939+ return cnt >= 64 ;
940+ }
941+
942+ static const u32 aspeed_spi_hclk_divs [] = {
943+ 0xf , /* HCLK */
944+ 0x7 , /* HCLK/2 */
945+ 0xe , /* HCLK/3 */
946+ 0x6 , /* HCLK/4 */
947+ 0xd , /* HCLK/5 */
948+ };
949+
950+ #define ASPEED_SPI_HCLK_DIV (i ) \
951+ (aspeed_spi_hclk_divs[(i) - 1] << CTRL_FREQ_SEL_SHIFT)
952+
953+ static int aspeed_spi_do_calibration (struct aspeed_spi_chip * chip )
954+ {
955+ struct aspeed_spi * aspi = chip -> aspi ;
956+ const struct aspeed_spi_data * data = aspi -> data ;
957+ u32 ahb_freq = aspi -> clk_freq ;
958+ u32 max_freq = chip -> clk_freq ;
959+ u32 ctl_val ;
960+ u8 * golden_buf = NULL ;
961+ u8 * test_buf = NULL ;
962+ int i , rc , best_div = -1 ;
963+
964+ dev_dbg (aspi -> dev , "calculate timing compensation - AHB freq: %d MHz" ,
965+ ahb_freq / 1000000 );
966+
967+ /*
968+ * use the related low frequency to get check calibration data
969+ * and get golden data.
970+ */
971+ ctl_val = chip -> ctl_val [ASPEED_SPI_READ ] & data -> hclk_mask ;
972+ writel (ctl_val , chip -> ctl );
973+
974+ test_buf = kzalloc (CALIBRATE_BUF_SIZE * 2 , GFP_KERNEL );
975+ if (!test_buf )
976+ return - ENOMEM ;
977+
978+ golden_buf = test_buf + CALIBRATE_BUF_SIZE ;
979+
980+ memcpy_fromio (golden_buf , chip -> ahb_base , CALIBRATE_BUF_SIZE );
981+ if (!aspeed_spi_check_calib_data (golden_buf , CALIBRATE_BUF_SIZE )) {
982+ dev_info (aspi -> dev , "Calibration area too uniform, using low speed" );
983+ goto no_calib ;
984+ }
985+
986+ #if defined(VERBOSE_DEBUG )
987+ print_hex_dump_bytes (DEVICE_NAME " good: " , DUMP_PREFIX_NONE ,
988+ golden_buf , 0x100 );
989+ #endif
990+
991+ /* Now we iterate the HCLK dividers until we find our breaking point */
992+ for (i = ARRAY_SIZE (aspeed_spi_hclk_divs ); i > data -> hdiv_max - 1 ; i -- ) {
993+ u32 tv , freq ;
994+
995+ freq = ahb_freq / i ;
996+ if (freq > max_freq )
997+ continue ;
998+
999+ /* Set the timing */
1000+ tv = chip -> ctl_val [ASPEED_SPI_READ ] | ASPEED_SPI_HCLK_DIV (i );
1001+ writel (tv , chip -> ctl );
1002+ dev_dbg (aspi -> dev , "Trying HCLK/%d [%08x] ..." , i , tv );
1003+ rc = data -> calibrate (chip , i , golden_buf , test_buf );
1004+ if (rc == 0 )
1005+ best_div = i ;
1006+ }
1007+
1008+ /* Nothing found ? */
1009+ if (best_div < 0 ) {
1010+ dev_warn (aspi -> dev , "No good frequency, using dumb slow" );
1011+ } else {
1012+ dev_dbg (aspi -> dev , "Found good read timings at HCLK/%d" , best_div );
1013+
1014+ /* Record the freq */
1015+ for (i = 0 ; i < ASPEED_SPI_MAX ; i ++ )
1016+ chip -> ctl_val [i ] = (chip -> ctl_val [i ] & data -> hclk_mask ) |
1017+ ASPEED_SPI_HCLK_DIV (best_div );
1018+ }
1019+
1020+ no_calib :
1021+ writel (chip -> ctl_val [ASPEED_SPI_READ ], chip -> ctl );
1022+ kfree (test_buf );
1023+ return 0 ;
1024+ }
1025+
1026+ #define TIMING_DELAY_DI BIT(3)
1027+ #define TIMING_DELAY_HCYCLE_MAX 5
1028+ #define TIMING_REG_AST2600 (chip ) \
1029+ ((chip)->aspi->regs + (chip)->aspi->data->timing + \
1030+ (chip)->cs * 4)
1031+
1032+ static int aspeed_spi_ast2600_calibrate (struct aspeed_spi_chip * chip , u32 hdiv ,
1033+ const u8 * golden_buf , u8 * test_buf )
1034+ {
1035+ struct aspeed_spi * aspi = chip -> aspi ;
1036+ int hcycle ;
1037+ u32 shift = (hdiv - 2 ) << 3 ;
1038+ u32 mask = ~(0xfu << shift );
1039+ u32 fread_timing_val = 0 ;
1040+
1041+ for (hcycle = 0 ; hcycle <= TIMING_DELAY_HCYCLE_MAX ; hcycle ++ ) {
1042+ int delay_ns ;
1043+ bool pass = false;
1044+
1045+ fread_timing_val &= mask ;
1046+ fread_timing_val |= hcycle << shift ;
1047+
1048+ /* no DI input delay first */
1049+ writel (fread_timing_val , TIMING_REG_AST2600 (chip ));
1050+ pass = aspeed_spi_check_reads (chip , golden_buf , test_buf );
1051+ dev_dbg (aspi -> dev ,
1052+ " * [%08x] %d HCLK delay, DI delay none : %s" ,
1053+ fread_timing_val , hcycle , pass ? "PASS" : "FAIL" );
1054+ if (pass )
1055+ return 0 ;
1056+
1057+ /* Add DI input delays */
1058+ fread_timing_val &= mask ;
1059+ fread_timing_val |= (TIMING_DELAY_DI | hcycle ) << shift ;
1060+
1061+ for (delay_ns = 0 ; delay_ns < 0x10 ; delay_ns ++ ) {
1062+ fread_timing_val &= ~(0xf << (4 + shift ));
1063+ fread_timing_val |= delay_ns << (4 + shift );
1064+
1065+ writel (fread_timing_val , TIMING_REG_AST2600 (chip ));
1066+ pass = aspeed_spi_check_reads (chip , golden_buf , test_buf );
1067+ dev_dbg (aspi -> dev ,
1068+ " * [%08x] %d HCLK delay, DI delay %d.%dns : %s" ,
1069+ fread_timing_val , hcycle , (delay_ns + 1 ) / 2 ,
1070+ (delay_ns + 1 ) & 1 ? 5 : 5 , pass ? "PASS" : "FAIL" );
1071+ /*
1072+ * TODO: This is optimistic. We should look
1073+ * for a working interval and save the middle
1074+ * value in the read timing register.
1075+ */
1076+ if (pass )
1077+ return 0 ;
1078+ }
1079+ }
1080+
1081+ /* No good setting for this frequency */
1082+ return -1 ;
1083+ }
1084+
8281085/*
8291086 * Platform definitions
8301087 */
@@ -833,6 +1090,10 @@ static const struct aspeed_spi_data ast2400_fmc_data = {
8331090 .hastype = true,
8341091 .we0 = 16 ,
8351092 .ctl0 = CE0_CTRL_REG ,
1093+ .timing = CE0_TIMING_COMPENSATION_REG ,
1094+ .hclk_mask = 0xfffff0ff ,
1095+ .hdiv_max = 1 ,
1096+ .calibrate = aspeed_spi_calibrate ,
8361097 .segment_start = aspeed_spi_segment_start ,
8371098 .segment_end = aspeed_spi_segment_end ,
8381099 .segment_reg = aspeed_spi_segment_reg ,
@@ -843,6 +1104,10 @@ static const struct aspeed_spi_data ast2400_spi_data = {
8431104 .hastype = false,
8441105 .we0 = 0 ,
8451106 .ctl0 = 0x04 ,
1107+ .timing = 0x14 ,
1108+ .hclk_mask = 0xfffff0ff ,
1109+ .hdiv_max = 1 ,
1110+ .calibrate = aspeed_spi_calibrate ,
8461111 /* No segment registers */
8471112};
8481113
@@ -851,6 +1116,10 @@ static const struct aspeed_spi_data ast2500_fmc_data = {
8511116 .hastype = true,
8521117 .we0 = 16 ,
8531118 .ctl0 = CE0_CTRL_REG ,
1119+ .timing = CE0_TIMING_COMPENSATION_REG ,
1120+ .hclk_mask = 0xffffd0ff ,
1121+ .hdiv_max = 1 ,
1122+ .calibrate = aspeed_spi_calibrate ,
8541123 .segment_start = aspeed_spi_segment_start ,
8551124 .segment_end = aspeed_spi_segment_end ,
8561125 .segment_reg = aspeed_spi_segment_reg ,
@@ -861,6 +1130,10 @@ static const struct aspeed_spi_data ast2500_spi_data = {
8611130 .hastype = false,
8621131 .we0 = 16 ,
8631132 .ctl0 = CE0_CTRL_REG ,
1133+ .timing = CE0_TIMING_COMPENSATION_REG ,
1134+ .hclk_mask = 0xffffd0ff ,
1135+ .hdiv_max = 1 ,
1136+ .calibrate = aspeed_spi_calibrate ,
8641137 .segment_start = aspeed_spi_segment_start ,
8651138 .segment_end = aspeed_spi_segment_end ,
8661139 .segment_reg = aspeed_spi_segment_reg ,
@@ -872,6 +1145,10 @@ static const struct aspeed_spi_data ast2600_fmc_data = {
8721145 .mode_bits = SPI_RX_QUAD | SPI_RX_QUAD ,
8731146 .we0 = 16 ,
8741147 .ctl0 = CE0_CTRL_REG ,
1148+ .timing = CE0_TIMING_COMPENSATION_REG ,
1149+ .hclk_mask = 0xf0fff0ff ,
1150+ .hdiv_max = 2 ,
1151+ .calibrate = aspeed_spi_ast2600_calibrate ,
8751152 .segment_start = aspeed_spi_segment_ast2600_start ,
8761153 .segment_end = aspeed_spi_segment_ast2600_end ,
8771154 .segment_reg = aspeed_spi_segment_ast2600_reg ,
@@ -883,6 +1160,10 @@ static const struct aspeed_spi_data ast2600_spi_data = {
8831160 .mode_bits = SPI_RX_QUAD | SPI_RX_QUAD ,
8841161 .we0 = 16 ,
8851162 .ctl0 = CE0_CTRL_REG ,
1163+ .timing = CE0_TIMING_COMPENSATION_REG ,
1164+ .hclk_mask = 0xf0fff0ff ,
1165+ .hdiv_max = 2 ,
1166+ .calibrate = aspeed_spi_ast2600_calibrate ,
8861167 .segment_start = aspeed_spi_segment_ast2600_start ,
8871168 .segment_end = aspeed_spi_segment_ast2600_end ,
8881169 .segment_reg = aspeed_spi_segment_ast2600_reg ,
0 commit comments