1 #include <common.h> 2 #include <command.h> 3 #include <string.h> 4 #include <asm/io.h> 5 6 #define AST_SCU (0x1e6e2000) 7 #if defined(CONFIG_ASPEED_AST2500) 8 #define AST_SCU_SYSRST_CTRL (AST_SCU + 0x04) 9 #elif defined(CONFIG_ASPEED_AST2600) 10 #define AST_SCU_SYSRST_CLR2 (AST_SCU + 0x54) 11 #endif 12 13 #define AST_PECI (0x1e78b000) 14 #define AST_PECI_CTRL (AST_PECI + 0x00) 15 #define AST_PECI_TIMING (AST_PECI + 0x04) 16 #define AST_PECI_CMD (AST_PECI + 0x08) 17 #define AST_PECI_RW_LEN (AST_PECI + 0x0C) 18 #define AST_PECI_EXP_FCS (AST_PECI + 0x10) 19 #define AST_PECI_CAP_FCS (AST_PECI + 0x14) 20 #define AST_PECI_INT_CTRL (AST_PECI + 0x18) 21 #define AST_PECI_INT_STAT (AST_PECI + 0x1C) 22 #define AST_PECI_WR_DATA0 (AST_PECI + 0x20) 23 #define AST_PECI_WR_DATA1 (AST_PECI + 0x24) 24 #define AST_PECI_WR_DATA2 (AST_PECI + 0x28) 25 #define AST_PECI_WR_DATA3 (AST_PECI + 0x2C) 26 #define AST_PECI_RD_DATA0 (AST_PECI + 0x30) 27 #define AST_PECI_RD_DATA1 (AST_PECI + 0x34) 28 #define AST_PECI_RD_DATA2 (AST_PECI + 0x38) 29 #define AST_PECI_RD_DATA3 (AST_PECI + 0x3C) 30 #define AST_PECI_WR_DATA4 (AST_PECI + 0x40) 31 #define AST_PECI_WR_DATA5 (AST_PECI + 0x44) 32 #define AST_PECI_WR_DATA6 (AST_PECI + 0x48) 33 #define AST_PECI_WR_DATA7 (AST_PECI + 0x4C) 34 #define AST_PECI_RD_DATA4 (AST_PECI + 0x50) 35 #define AST_PECI_RD_DATA5 (AST_PECI + 0x54) 36 #define AST_PECI_RD_DATA6 (AST_PECI + 0x58) 37 #define AST_PECI_RD_DATA7 (AST_PECI + 0x5C) 38 39 #ifdef CONFIG_ASPEED_AST2500 40 static void ast2500_peci_init(void) 41 { 42 unsigned int val; 43 static bool is_init = false; 44 45 /* init once only */ 46 if (is_init) 47 return; 48 49 /* release PECI reset */ 50 val = readl(AST_SCU_SYSRST_CTRL); 51 val &= ~(0x1 << 10); 52 writel(val, AST_SCU_SYSRST_CTRL); 53 54 /* 55 * 1. disable PECI 56 * 2. set source clock to 24Mhz oscillator 57 * 3. set clock divider to 8 58 */ 59 writel(0x80301, AST_PECI_CTRL); 60 61 /* set negotiate timing */ 62 writel(0x4040, AST_PECI_TIMING); 63 64 /* enable interrupt */ 65 writel(0x1f, AST_PECI_INT_CTRL); 66 67 /* enable PECI */ 68 writel(0x80311, AST_PECI_CTRL); 69 70 is_init = true; 71 } 72 #endif 73 74 #ifdef CONFIG_ASPEED_AST2600 75 static void ast2600_peci_init(void) 76 { 77 static bool is_init = false; 78 79 /* init once only */ 80 if (is_init) 81 return; 82 83 /* release PECI reset */ 84 writel(0x10, AST_SCU_SYSRST_CLR2); 85 86 /* 87 * 1. disable PECI 88 * 2. set source clock to HCLK 89 * 3. set clock divider to 2 90 * 4. set 32-byte mode 91 */ 92 writel(0x80901, AST_PECI_CTRL); 93 94 /* set negotiate timing */ 95 writel(0x0303, AST_PECI_TIMING); 96 97 /* enable interrupt */ 98 writel(0x1f, AST_PECI_INT_CTRL); 99 100 /* enable PECI */ 101 writel(0x80911, AST_PECI_CTRL); 102 103 is_init = true; 104 } 105 #endif 106 107 static void ast_peci_init(void) 108 { 109 #if defined(CONFIG_ASPEED_AST2500) 110 return ast2500_peci_init(); 111 #elif defined(CONFIG_ASPEED_AST2600) 112 return ast2600_peci_init(); 113 #endif 114 } 115 116 static int do_ast_peci_ping(unsigned long client_addr) 117 { 118 unsigned int rec_wfcs; 119 unsigned int exp_wfcs; 120 121 unsigned long val; 122 unsigned long retry = 10; 123 124 ast_peci_init(); 125 126 /* make PECI no operation */ 127 writel(0x0, AST_PECI_CMD); 128 129 /* set client address */ 130 writel((client_addr & 0xff), AST_PECI_RW_LEN); 131 132 /* clear interrupt status */ 133 writel(0x1f, AST_PECI_INT_STAT); 134 135 /* fire PECI command */ 136 writel(0x1, AST_PECI_CMD); 137 138 /* wait PECI done for 10 seconds */ 139 printf("Waiting PECI ... "); 140 while (retry) { 141 val = readl(AST_PECI_INT_STAT); 142 if (val & 0x1) 143 break; 144 printf("Retry ... "); 145 udelay(1000000); 146 --retry; 147 } 148 149 if (retry == 0) { 150 printf("Timeout\n"); 151 goto ping_clean_and_exit; 152 } 153 printf("Done\n"); 154 155 /* compare the expected WFCS and the captured one */ 156 exp_wfcs = readl(AST_PECI_EXP_FCS) & 0xFF; 157 rec_wfcs = readl(AST_PECI_CAP_FCS) & 0xFF; 158 if (exp_wfcs != rec_wfcs) 159 printf("Mismatched WFCS: %02x, expected %02x\n", rec_wfcs, exp_wfcs); 160 else 161 printf("Ping: ACK\n"); 162 163 ping_clean_and_exit: 164 writel(0x1f, AST_PECI_INT_STAT); 165 writel(0x0, AST_PECI_CMD); 166 167 return 0; 168 } 169 170 static int do_ast_peci_getdib(unsigned long client_addr) 171 { 172 unsigned char dib[8]; 173 174 unsigned long val; 175 unsigned long retry = 10; 176 177 unsigned int rec_wfcs; 178 unsigned int exp_wfcs; 179 180 unsigned int rec_rfcs; 181 unsigned int exp_rfcs; 182 183 ast_peci_init(); 184 185 memset(dib, 0, sizeof(dib)); 186 187 /* make PECI no operation */ 188 writel(0x0, AST_PECI_CMD); 189 190 /* prepare GetDIB command code 0xF7 */ 191 writel(0xf7, AST_PECI_WR_DATA0); 192 writel(0x00, AST_PECI_WR_DATA1); 193 writel(0x00, AST_PECI_WR_DATA2); 194 writel(0x00, AST_PECI_WR_DATA3); 195 writel(0x00, AST_PECI_WR_DATA4); 196 writel(0x00, AST_PECI_WR_DATA5); 197 writel(0x00, AST_PECI_WR_DATA6); 198 writel(0x00, AST_PECI_WR_DATA7); 199 200 /* 201 * 1. set read length to 8 bytes 202 * 2. set write length to 1 bytes 203 * 3. set client address 204 */ 205 writel((0x80100 | (client_addr & 0xff)), AST_PECI_RW_LEN); 206 207 /* clear interrupt status */ 208 writel(0x1f, AST_PECI_INT_STAT); 209 210 /* fire PECI command */ 211 writel(0x1, AST_PECI_CMD); 212 213 /* wait PECI done for 10 seconds */ 214 printf("Waiting PECI ... "); 215 while (retry) { 216 val = readl(AST_PECI_INT_STAT); 217 if (val & 0x1) 218 break; 219 printf("Retry ... "); 220 udelay(1000000); 221 --retry; 222 } 223 224 if (retry == 0) { 225 printf("Timeout\n"); 226 goto getdib_clean_and_exit; 227 } 228 printf("Done\n"); 229 230 /* compare the expected WFCS and the captured one */ 231 exp_wfcs = readl(AST_PECI_EXP_FCS) & 0xFF; 232 rec_wfcs = readl(AST_PECI_CAP_FCS) & 0xFF; 233 if (exp_wfcs != rec_wfcs) { 234 printf("Mismatched WFCS: %02x, expected %02x\n", 235 rec_wfcs, exp_wfcs); 236 goto getdib_clean_and_exit; 237 } 238 239 /* compare the expected RFCS and the captured one */ 240 exp_rfcs = readl(AST_PECI_EXP_FCS) & 0xFF0000; 241 rec_rfcs = readl(AST_PECI_CAP_FCS) & 0xFF0000; 242 if (exp_rfcs != rec_rfcs) { 243 printf("Mismatched RFCS: %02x, expected %02x\n", 244 rec_rfcs, exp_rfcs); 245 goto getdib_clean_and_exit; 246 } 247 248 *((unsigned int*)dib) = readl(AST_PECI_RD_DATA0); 249 *((unsigned int*)(dib + 4)) = readl(AST_PECI_RD_DATA1); 250 251 printf("DIB: %02x %02x %02x %02x %02x %02x %02x %02x\n", 252 dib[0], dib[1], dib[2], dib[3], 253 dib[4], dib[5], dib[6], dib[7]); 254 255 getdib_clean_and_exit: 256 writel(0x1f, AST_PECI_INT_STAT); 257 writel(0x0, AST_PECI_CMD); 258 259 return 0; 260 } 261 262 static int do_ast_peci(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 263 { 264 char *peci_cmd; 265 unsigned long client_addr; 266 267 if (argc < 3) 268 return CMD_RET_USAGE; 269 270 peci_cmd = argv[1]; 271 client_addr = strtoul(argv[2], 0, 0); 272 273 if (client_addr > 0xFF) { 274 printf("Invalid client address: %lu\n", client_addr); 275 return CMD_RET_USAGE; 276 } 277 278 if (!strcmp(peci_cmd, "ping")) 279 return do_ast_peci_ping(client_addr); 280 281 if (!strcmp(peci_cmd, "getdib")) 282 return do_ast_peci_getdib(client_addr); 283 284 return CMD_RET_USAGE; 285 } 286 287 U_BOOT_CMD(peci, 3, 0, do_ast_peci, 288 "ASPEED PECI general bus command test program", 289 "ping <client_addr> - Ping to check if the device at the targeted address can respond\n" 290 "peci getdib <client_addr> - Get 8-byte Device Information Bytes\n" 291 ); 292