1 /* 2 * This program is distributed in the hope that it will be useful, 3 * but WITHOUT ANY WARRANTY; without even the implied warranty of 4 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 5 * GNU General Public License for more details. 6 * 7 * You should have received a copy of the GNU General Public License 8 * along with this program; if not, write to the Free Software 9 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 10 */ 11 12 #include <common.h> 13 #include <console.h> 14 #include <bootretry.h> 15 #include <cli.h> 16 #include <command.h> 17 #include <console.h> 18 19 #include <inttypes.h> 20 #include <mapmem.h> 21 #include <asm/io.h> 22 #include <linux/compiler.h> 23 24 #include <common.h> 25 #include <clk-uclass.h> 26 #include <dm.h> 27 #include <asm/io.h> 28 #include <dm/lists.h> 29 #include <asm/arch/scu_ast2600.h> 30 #include <dt-bindings/clock/ast2600-clock.h> 31 32 #include <asm/arch/scu_ast2600.h> 33 #include <dt-bindings/clock/ast2600-clock.h> 34 35 DECLARE_GLOBAL_DATA_PTR; 36 37 /* ------------------------------------------------------------------------- */ 38 unsigned long get_ast2600_pll_rate(struct udevice *scu_dev, unsigned int pll_idx) 39 { 40 struct clk clk; 41 unsigned long ret = 0; 42 43 clk.id = pll_idx; 44 ret = clk_request(scu_dev, &clk); 45 if (ret < 0) { 46 return ret; 47 } 48 49 ret = clk_get_rate(&clk); 50 51 clk_free(&clk); 52 53 return ret; 54 } 55 56 static int cal_ast2600_28nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx) 57 { 58 u32 ulCounter, ulLowLimit, ulHighLimit; 59 u32 ulData; 60 u32 ulErrRate = 2; 61 int i = 0; 62 63 // printf("pll rate : %ld \n", pll_rate); 64 65 ulCounter = (pll_rate/1000) * 512 / 25000 - 1; 66 ulLowLimit = ulCounter * (100 - ulErrRate) / 100; 67 ulHighLimit = ulCounter * (100 + ulErrRate) / 100; 68 writel((ulLowLimit << 16) | ulHighLimit, 0x1e6e2324); 69 // printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit %lx \n", ulCounter, ulLowLimit, ulHighLimit); 70 71 //1. Set SCU320 = 0x30 72 writel(0x30, 0x1e6e2320); 73 //2. Wait until SCU320[29:16] = 0 74 do { 75 ulData = readl(0x1e6e2320); 76 mdelay(1); 77 } while ((ulData & 0x3fff0000) && (i++<1000)); //wait until SCU320[29:16]=0 78 79 if (i>= 1000) 80 { 81 printf("Fre Count Eng No idle %x\n", ulData); 82 return 1; 83 } 84 //3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement 85 writel((pll_idx << 2) | 0x1, 0x1e6e2320); 86 //4. Delay 1ms 87 mdelay(1); 88 //5. Set SCU320[1] = 1 89 writel((pll_idx << 2) | 0x3, 0x1e6e2320); 90 91 //6. Wait until SCU320[6] = 1 92 i = 0; 93 do { 94 ulData = readl(0x1e6e2320); 95 mdelay(1); 96 } while ((!(ulData & 0x40)) && (i++<1000)); 97 98 if (i>= 1000) 99 { 100 printf("PLL Detec No idle %x\n", ulData); 101 return 1; 102 } 103 104 //7. Read SCU320[29:16] and calculate the result frequency using following equation 105 // printf("ulCounter val : %lx \n", (readl(0x1e6e2320) & GENMASK(29, 16)) >> 16); 106 //When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then 107 //OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1) 108 // printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2320) & GENMASK(29, 16)) >> 16) + 1)); 109 110 ulData = readl(0x1e6e2320); 111 112 writel(0x2C, 0x1e6e2320); //disable ring 113 114 if(ulData & 0x80) 115 return 0; 116 else 117 return 1; 118 } 119 120 static int cal_ast2600_13nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx) 121 { 122 u32 ulData; 123 u32 ulCounter, ulLowLimit, ulHighLimit; 124 u32 ulErrRate = 2; 125 int i = 0; 126 127 // printf("pll rate : %ld \n", pll_rate); 128 129 ulCounter = (pll_rate/1000) * 512 / 25000 - 1; 130 ulLowLimit = ulCounter * (100 - ulErrRate) / 100; 131 ulHighLimit = ulCounter * (100 + ulErrRate) / 100; 132 writel((ulHighLimit << 16) | ulLowLimit, 0x1e6e2334); 133 // printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit %lx \n", ulCounter, ulLowLimit, ulHighLimit); 134 135 //1. Set SCU320 = 0x30 136 writel(0x30, 0x1e6e2330); 137 //2. Wait until SCU320[29:16] = 0 138 do { 139 ulData = readl(0x1e6e2330); 140 mdelay(1); 141 } while ((ulData & 0x3fff0000) && (i++<1000)); //wait until SCU320[29:16]=0 142 143 if (i>= 1000) 144 { 145 printf("Fre Count Eng No idle %x\n", ulData); 146 return 1; 147 } 148 //3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement 149 writel((pll_idx << 2) | 0x1, 0x1e6e2330); 150 //4. Delay 1ms 151 mdelay(1); 152 //5. Set SCU320[1] = 1 153 writel((pll_idx << 2) | 0x3, 0x1e6e2330); 154 155 //6. Wait until SCU320[6] = 1 156 i = 0; 157 do { 158 ulData = readl(0x1e6e2330); 159 mdelay(1); 160 } while ((!(ulData & 0x40)) && (i++<1000)); 161 162 if (i>= 1000) 163 { 164 printf("PLL Detec No idle %x\n", ulData); 165 return 1; 166 } 167 168 //7. Read SCU320[29:16] and calculate the result frequency using following equation 169 // printf("ulCounter val : %lx \n", (readl(0x1e6e2330) & GENMASK(29, 16)) >> 16); 170 //When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then 171 //OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1) 172 // printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2330) & GENMASK(29, 16)) >> 16) + 1)); 173 174 ulData = readl(0x1e6e2330); 175 176 writel(0x2C, 0x1e6e2330); //disable ring 177 178 if(ulData & 0x80) 179 return 0; 180 else 181 return 1; 182 } 183 184 185 int do_ast2600_pll_test(struct udevice *scu_dev, unsigned int pll_idx) 186 { 187 int ret = 0; 188 unsigned long pll_rate = 0; 189 190 switch(pll_idx) { 191 case 0: //delay cell 192 printf("Delay Cell : BYPASS \n"); 193 break; 194 case 1: //nand gate 195 printf("NAND Gate : BYPASS \n"); 196 break; 197 case 2: 198 printf("DLY 16 : BYPASS \n"); 199 break; 200 case 3: 201 printf("DLY 32 : BYPASS \n"); 202 break; 203 case 4: 204 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_DPLL); 205 if(cal_ast2600_28nm_pll_rate(pll_rate/2, 4)) { 206 printf("D-PLL : Fail \n"); 207 ret = 1; 208 } else 209 printf("D-PLL : PASS \n"); 210 break; 211 case 5: 212 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_EPLL); 213 if(cal_ast2600_28nm_pll_rate(pll_rate/4, 5)) 214 printf("E-PLL : Fail \n"); 215 else 216 printf("E-PLL : PASS \n"); 217 break; 218 case 6: 219 if(readl(0x1e6ed0c0) & BIT(5)) { 220 switch((readl(0x1e6ed0d0) >> 16) & 0x3) { 221 case 1: //2.5G 125Mhz 222 pll_rate = 125000000; 223 break; 224 case 2: 225 pll_rate = 250000000; 226 break; 227 } 228 if(cal_ast2600_28nm_pll_rate(pll_rate, 6)) 229 printf("XPCLK-EP : Fail \n"); 230 else 231 printf("XPCLK-EP : PASS \n"); 232 } else 233 printf("XPCLK-EP : Fail 0 \n"); 234 break; 235 case 8: 236 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_MPLL); 237 if(cal_ast2600_28nm_pll_rate(pll_rate/2, 8)) { 238 printf("MCLK : Fail \n"); 239 ret = 1; 240 } else 241 printf("MCLK : PASS \n"); 242 break; 243 case 9: 244 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB); 245 if(cal_ast2600_28nm_pll_rate(pll_rate, 9)) { 246 printf("HCLK-28nm : Fail \n"); 247 ret = 1; 248 } else 249 printf("HCLK-28nm : PASS \n"); 250 break; 251 case 16: 252 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APLL); 253 if(cal_ast2600_13nm_pll_rate(pll_rate/8, 0)) { 254 printf("APLL : Fail \n"); 255 ret = 1; 256 } else 257 printf("APLL : PASS \n"); 258 break; 259 case 17: 260 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB); 261 if(cal_ast2600_13nm_pll_rate(pll_rate, 1)) { 262 printf("HCLK-13nm : Fail \n"); 263 ret = 1; 264 } else 265 printf("HCLK-13nm : PASS \n"); 266 break; 267 case 18: 268 pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APB2); 269 if(cal_ast2600_13nm_pll_rate(pll_rate, 2)) 270 printf("PCLK : Fail \n"); 271 else 272 printf("PCLK : PASS \n"); 273 break; 274 } 275 276 return ret; 277 } 278 279 int do_aspeed_full_pll_test(struct udevice *scu_dev) 280 { 281 int i = 0; 282 int ret = 0; 283 for(i = 0; i < 32; i++) { 284 ret += do_ast2600_pll_test(scu_dev, i); 285 } 286 287 printf("**************************************************** \n"); 288 if(ret) 289 printf("PLL Test : Fail \n"); 290 else 291 printf("PLL Test : Pass \n"); 292 printf("**************************************************** \n"); 293 294 return 1; 295 } 296 297 static int 298 do_aspeed_plltest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 299 { 300 struct udevice *scu_dev; 301 char *pll_cmd; 302 unsigned long pll_idx; 303 int ret; 304 305 ret = uclass_get_device_by_driver(UCLASS_CLK, 306 DM_GET_DRIVER(aspeed_scu), &scu_dev); 307 if (ret) 308 return ret; 309 310 if (argc != 2) 311 return CMD_RET_USAGE; 312 313 pll_cmd = argv[1]; 314 315 if (!strcmp(pll_cmd, "full")) 316 ret = do_aspeed_full_pll_test(scu_dev); 317 else { 318 pll_idx = strtoul(argv[1], 0, 0); 319 ret = do_ast2600_pll_test(scu_dev, pll_idx); 320 } 321 322 return ret; 323 } 324 325 U_BOOT_CMD( 326 plltest, 3, 0, do_aspeed_plltest, 327 "ASPEED PLL test", 328 "ping d2 - Ping to check if the device at the targeted address can respond\n" 329 "" 330 ); 331