A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
2

Configure Feed

Select the types of activity you want to include in your feed.

rockboxd / utils / regtools / qeditor / std_analysers.cpp
50 kB 1394 lines
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2014 by Amaury Pouly 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20#include "std_analysers.h" 21#include <QDebug> 22 23/** 24 * AnalyserEx 25 */ 26 27AnalyserEx::AnalyserEx(const soc_desc::soc_ref_t& soc, IoBackend *backend) 28 :Analyser(soc, backend), m_helper(backend, soc) 29{ 30} 31 32bool AnalyserEx::ReadRegister(const QString& path, soc_word_t& val) 33{ 34 return m_helper.ReadRegister(m_helper.ParsePath(path), val); 35} 36 37bool AnalyserEx::ReadRegisterOld(const QString& dev, const QString& reg, soc_word_t& val) 38{ 39 return ReadRegister(dev + "." + reg, val); 40} 41 42bool AnalyserEx::ReadField(const QString& path, const QString& field, soc_word_t& val) 43{ 44 return m_helper.ReadRegisterField(m_helper.ParsePath(path), field, val); 45} 46 47bool AnalyserEx::ReadFieldOld(const QString& dev, const QString& reg, 48 const QString& field, soc_word_t& val) 49{ 50 return ReadField(dev + "." + reg, field, val); 51} 52 53/** 54 * Clock analyser 55 */ 56 57ClockAnalyser::ClockAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) 58 :AnalyserEx(soc, backend) 59{ 60 m_group = new QGroupBox("Clock Analyser"); 61 QVBoxLayout *layout = new QVBoxLayout; 62 m_group->setLayout(layout); 63 m_tree_widget = new QTreeWidget; 64 layout->addWidget(m_tree_widget); 65 66 m_tree_widget->setColumnCount(2); 67 QStringList list; 68 list << "Name" << "Frequency"; 69 m_tree_widget->setHeaderLabels(list); 70 71 FillTree(); 72} 73 74ClockAnalyser::~ClockAnalyser() 75{ 76 delete m_group; 77} 78 79QWidget *ClockAnalyser::GetWidget() 80{ 81 return m_group; 82} 83 84bool ClockAnalyser::SupportSoc(const QString& soc_name) 85{ 86 return soc_name == "imx233" 87 || soc_name == "rk27xx" 88 || soc_name == "atj213x" 89 || soc_name == "jz4760b" 90 || soc_name == "stmp3700"; 91} 92 93QString ClockAnalyser::GetFreq(unsigned freq) 94{ 95 if(freq >= 1000000) 96 { 97 if((freq % 1000000) == 0) 98 return QString().sprintf("%d MHz", freq / 1000000); 99 else 100 return QString().sprintf("%.3f MHz", freq / 1000000.0); 101 } 102 if(freq >= 1000) 103 { 104 if((freq % 1000) == 0) 105 return QString().sprintf("%d KHz", freq / 1000); 106 else 107 return QString().sprintf("%.3f KHz", freq / 1000.0); 108 } 109 return QString().sprintf("%d Hz", freq); 110} 111 112QTreeWidgetItem *ClockAnalyser::AddClock(QTreeWidgetItem *parent, const QString& name, 113 int freq, int mul, int div) 114{ 115 if(freq == FROM_PARENT) 116 { 117 int64_t f = GetClockFreq(parent); 118 f *= mul; 119 f /= div; 120 freq = f; 121 } 122 QTreeWidgetItem *item = new QTreeWidgetItem(parent, QStringList() << name 123 << (freq == INVALID ? "<invalid>" : freq == 0 ? "<disabled>" : GetFreq(freq))); 124 item->setData(1, Qt::UserRole, freq); 125 if(freq == DISABLED || freq == INVALID || (parent && parent->isDisabled())) 126 item->setDisabled(true); 127 if(!parent) 128 m_tree_widget->addTopLevelItem(item); 129 return item; 130} 131 132int ClockAnalyser::GetClockFreq(QTreeWidgetItem *item) 133{ 134 return item->data(1, Qt::UserRole).toInt(); 135} 136 137void ClockAnalyser::FillTree() 138{ 139 m_tree_widget->clear(); 140 if(m_soc.get()->name == "imx233") FillTreeIMX233(); 141 if(m_soc.get()->name == "stmp3700") FillTreeIMX233(); 142 else if(m_soc.get()->name == "rk27xx") FillTreeRK27XX(); 143 else if(m_soc.get()->name == "atj213x") FillTreeATJ213X(); 144 else if(m_soc.get()->name == "jz4760b") FillTreeJZ4760B(); 145 m_tree_widget->expandAll(); 146 m_tree_widget->resizeColumnToContents(0); 147} 148 149void ClockAnalyser::FillTreeJZ4760B() 150{ 151 AddClock(0, "RTCLK", 32768); 152 // assume EXCLK is 12MHz, we have no way to knowing for sure but this is the 153 // recommended value anyway 154 QTreeWidgetItem *exclk = AddClock(0, "EXCLK", 12000000); 155 // PLL0 156 soc_word_t pllm, plln, pllod, pllbypass; 157 QTreeWidgetItem *pll0 = 0; 158 if(ReadFieldOld("CPM", "PLLCTRL0", "FEED_DIV", pllm) && 159 ReadFieldOld("CPM", "PLLCTRL0", "IN_DIV", plln) && 160 ReadFieldOld("CPM", "PLLCTRL0", "OUT_DIV", pllod) && 161 ReadFieldOld("CPM", "PLLCTRL0", "BYPASS", pllbypass)) 162 { 163 pll0 = AddClock(exclk, "PLL0", FROM_PARENT, pllbypass ? 1 : 2 * pllm, 164 pllbypass ? 1 : plln * (1 << pllod)); 165 } 166 else 167 pll0 = AddClock(exclk, "PLL0", INVALID); 168 // PLL1 169 soc_word_t plldiv, src_sel; 170 QTreeWidgetItem *pll1 = 0; 171 if(ReadFieldOld("CPM", "PLLCTRL1", "FEED_DIV", pllm) && 172 ReadFieldOld("CPM", "PLLCTRL1", "IN_DIV", plln) && 173 ReadFieldOld("CPM", "PLLCTRL1", "OUT_DIV", pllod) && 174 ReadFieldOld("CPM", "PLLCTRL1", "SRC_SEL", src_sel) && 175 ReadFieldOld("CPM", "PLLCTRL1", "PLL0_DIV", plldiv)) 176 { 177 pll1 = AddClock(src_sel ? pll0 : exclk, "PLL1", FROM_PARENT, 2 * pllm, 178 plln * (1 << pllod) * (src_sel ? plldiv : 1)); 179 } 180 else 181 pll1 = AddClock(exclk, "PLL1", INVALID); 182 // system clocks 183 const int NR_SYSCLK = 6; 184 const char *sysclk[NR_SYSCLK] = { "CCLK", "SCLK", "PCLK", "HCLK", "H2CLK", "MCLK"}; 185 for(int i = 0; i < NR_SYSCLK; i++) 186 { 187 soc_word_t div = 0; 188 std::string field = std::string(sysclk[i]) + "_DIV"; 189 if(ReadFieldOld("CPM", "SYSCLK", field.c_str(), div)) 190 { 191 switch(div) 192 { 193 case 0: div = 1; break; 194 case 1: div = 2; break; 195 case 2: div = 3; break; 196 case 3: div = 4; break; 197 case 4: div = 6; break; 198 case 5: div = 8; break; 199 default: div = 0; break; 200 } 201 } 202 if(div != 0) 203 AddClock(pll0, sysclk[i], FROM_PARENT, 1, div); 204 else 205 AddClock(pll0, sysclk[i], INVALID); 206 } 207 // common to msc, i2s, lcd, uhc, otg, ssi, pcm, gpu, gps 208 soc_word_t pll_div; 209 if(ReadFieldOld("CPM", "SYSCLK", "PLL_DIV", pll_div)) 210 pll_div = pll_div ? 1 : 2; 211 else 212 pll_div = 1; // error 213 // lcd 214 soc_word_t pll_sel, div; 215 if(ReadFieldOld("CPM", "LCDCLK", "DIV", div) && 216 ReadFieldOld("CPM", "LCDCLK", "PLL_SEL", pll_sel)) 217 { 218 AddClock(pll_sel ? pll1 : pll0, "LCDCLK", 219 FROM_PARENT, 1, pll_div * (div + 1)); 220 } 221 else 222 AddClock(exclk, "LCDCLK", INVALID); 223} 224 225void ClockAnalyser::FillTreeATJ213X() 226{ 227 soc_word_t pllbypass, pllclk, en, coreclks, tmp0, tmp1, tmp2, tmp3; 228 229 // system oscillators 32.768k and 24M 230 QTreeWidgetItem *losc_clk = AddClock(0, "losc clk", 32768); 231 QTreeWidgetItem *hosc_clk = AddClock(0, "hosc clk", 24000000); 232 233 // core pll 234 QTreeWidgetItem *corepll = 0; 235 if(ReadFieldOld("CMU", "COREPLL", "CPEN", en) && 236 ReadFieldOld("CMU", "COREPLL", "CPBY", pllbypass) && 237 ReadFieldOld("CMU", "COREPLL", "CPCK", pllclk)) 238 { 239 corepll = AddClock(hosc_clk, "core pll", en ? FROM_PARENT : DISABLED, 240 pllbypass ? 1 : pllclk, pllbypass ? 1 : 4); 241 } 242 else 243 { 244 corepll = AddClock(hosc_clk, "core pll", INVALID); 245 } 246 247 // dsp pll 248 QTreeWidgetItem *dsppll = 0; 249 if(ReadFieldOld("CMU", "DSPPLL", "DPEN", en) && 250 ReadFieldOld("CMU", "DSPPLL", "DPCK", pllclk)) 251 { 252 dsppll = AddClock(hosc_clk, "dsp pll", en ? FROM_PARENT : DISABLED, 253 pllbypass ? 1 : pllclk, pllbypass ? 1 : 4); 254 } 255 else 256 { 257 dsppll = AddClock(hosc_clk, "dsp pll", INVALID); 258 } 259 260 // audio pll 261 QTreeWidgetItem *adcpll = 0; 262 QTreeWidgetItem *dacpll = 0; 263 if(ReadFieldOld("CMU", "AUDIOPLL", "APEN", en) && 264 ReadFieldOld("CMU", "AUDIOPLL", "ADCCLK", tmp0) && 265 ReadFieldOld("CMU", "AUDIOPLL", "DACCLK", tmp1)) 266 { 267 if(en) 268 { 269 adcpll = AddClock(hosc_clk, "audio adc pll", tmp0 ? 22579200 : 24576000); 270 dacpll = AddClock(hosc_clk, "audio dac pll", tmp1 ? 22579200 : 24576000); 271 } 272 else 273 { 274 adcpll = AddClock(hosc_clk, "audio adc pll", DISABLED); 275 dacpll = AddClock(hosc_clk, "audio dac pll", DISABLED); 276 } 277 } 278 else 279 { 280 adcpll = AddClock(hosc_clk, "audio adc pll", INVALID); 281 dacpll = AddClock(hosc_clk, "audio dac pll", INVALID); 282 } 283 284 // audio clocks 285 QTreeWidgetItem *adcclk = 0; 286 QTreeWidgetItem *dacclk = 0; 287 if(ReadFieldOld("CMU", "AUDIOPLL", "ADCCLK", tmp0) && 288 ReadFieldOld("CMU", "AUDIOPLL", "DACCLK", tmp1)) 289 { 290 adcclk = AddClock(adcpll, "audio adc clk", FROM_PARENT, 1, tmp0+1); 291 dacclk = AddClock(dacpll, "audio dac clk", FROM_PARENT, 1, tmp1+1); 292 } 293 else 294 { 295 adcclk = AddClock(adcpll, "audio adc clk", INVALID); 296 dacclk = AddClock(adcpll, "audio dac clk", INVALID); 297 } 298 299 // cpu clock 300 QTreeWidgetItem *cpuclk = 0; 301 if(ReadFieldOld("CMU", "BUSCLK", "CORECLKS", coreclks) && 302 ReadFieldOld("CMU", "BUSCLK", "CCLKDIV", tmp0)) 303 { 304 if(coreclks == 0) 305 cpuclk = AddClock(losc_clk, "cpu clk", FROM_PARENT, 1, tmp0+1); 306 else if(coreclks == 1) 307 cpuclk = AddClock(hosc_clk, "cpu clk", FROM_PARENT, 1, tmp0+1); 308 else if(coreclks == 2) 309 cpuclk = AddClock(corepll, "cpu clk", FROM_PARENT, 1, tmp0+1); 310 else 311 cpuclk = AddClock(corepll, "cpu clk", INVALID); 312 } 313 else 314 { 315 cpuclk = AddClock(corepll, "cpu clk", INVALID); 316 } 317 318 // system clock 319 QTreeWidgetItem *sysclk = 0; 320 if(ReadFieldOld("CMU", "BUSCLK", "SCLKDIV", tmp0)) 321 sysclk = AddClock(cpuclk, "system clk", FROM_PARENT, 1, tmp0+1); 322 else 323 sysclk = AddClock(cpuclk, "system clk", INVALID); 324 325 // peripherial clk 326 QTreeWidgetItem *pclk = 0; 327 if(ReadFieldOld("CMU", "BUSCLK", "PCLKDIV", tmp0)) 328 pclk = AddClock(sysclk, "peripherial clk", FROM_PARENT, 1, tmp0 ? tmp0+1 : 2); 329 else 330 pclk = AddClock(sysclk, "peripherial clk", INVALID); 331 332 // sdram clk 333 QTreeWidgetItem *sdrclk = 0; 334 if(ReadFieldOld("CMU", "DEVCLKEN", "SDRC", en) && 335 ReadFieldOld("CMU", "DEVCLKEN", "SDRM", tmp0) && 336 ReadFieldOld("SDR", "EN", "EN", tmp1) && 337 ReadFieldOld("CMU", "SDRCLK", "SDRDIV", tmp2)) 338 { 339 en &= tmp0 & tmp1; 340 sdrclk = AddClock(sysclk, "sdram clk", en ? FROM_PARENT: DISABLED, 1, tmp2+1); 341 } 342 else 343 sdrclk = AddClock(sysclk, "sdram clk", INVALID); 344 345 // nand clk 346 QTreeWidgetItem *nandclk = 0; 347 if(ReadFieldOld("CMU", "DEVCLKEN", "NAND", en) && 348 ReadFieldOld("CMU", "NANDCLK", "NANDDIV", tmp0)) 349 nandclk = AddClock(corepll, "nand clk", en ? FROM_PARENT : DISABLED, 1, tmp0+1); 350 else 351 nandclk = AddClock(corepll, "nand clk", INVALID); 352 353 // sd clk 354 QTreeWidgetItem *sdclk = 0; 355 if(ReadFieldOld("CMU", "DEVCLKEN", "SD", tmp0) && 356 ReadFieldOld("CMU", "SDCLK", "CKEN" , tmp1) && 357 ReadFieldOld("CMU", "SDCLK", "D128" , tmp2) && 358 ReadFieldOld("CMU", "SDCLK", "SDDIV" , tmp3)) 359 { 360 en = tmp0 & tmp1; 361 sdclk = AddClock(corepll, "sd clk", en ? FROM_PARENT : DISABLED, 362 1, tmp2 ? 128*(tmp3+1) : (tmp3)); 363 } 364 else 365 sdclk = AddClock(corepll, "sd clk", INVALID); 366 367 // mha clk 368 QTreeWidgetItem *mhaclk = 0; 369 if(ReadFieldOld("CMU", "DEVCLKEN", "MHA", en) && 370 ReadFieldOld("CMU", "MHACLK", "MHADIV", tmp1)) 371 mhaclk = AddClock(corepll, "mha clk", en ? FROM_PARENT : DISABLED, 372 1, tmp1+1); 373 else 374 mhaclk = AddClock(corepll, "mha clk", INVALID); 375 376 // mca clk 377 QTreeWidgetItem *mcaclk = 0; 378 if(ReadFieldOld("CMU", "DEVCLKEN", "MCA", en) && 379 ReadFieldOld("CMU", "MCACLK", "MCADIV", tmp1)) 380 mcaclk = AddClock(corepll, "mca clk", en ? FROM_PARENT : DISABLED, 381 1, tmp1+1); 382 else 383 mcaclk = AddClock(corepll, "mca clk", INVALID); 384 385 // backlight pwm 386 QTreeWidgetItem *pwmclk = 0; 387 if(ReadFieldOld("CMU", "FMCLK", "BCKE", en) && 388 ReadFieldOld("CMU", "FMCLK", "BCKS", tmp1) && 389 ReadFieldOld("CMU", "FMCLK", "BCKCON", tmp2)) 390 { 391 if(tmp1) 392 { 393 // HOSC/8 input clk 394 pwmclk = AddClock(hosc_clk, "pwm clk", en ? FROM_PARENT : DISABLED, 395 1, 3*(tmp2+1)); 396 } 397 else 398 { 399 // LOSC input clk 400 pwmclk = AddClock(losc_clk, "pwm clk", en ? FROM_PARENT : DISABLED, 401 1, tmp2+1); 402 } 403 } 404 else 405 pwmclk = AddClock(losc_clk, "pwm clk", INVALID); 406 407 // i2c clk 408 QTreeWidgetItem *i2c1clk = 0; 409 QTreeWidgetItem *i2c2clk = 0; 410 if(ReadFieldOld("CMU", "DEVCLKEN", "I2C", en) && 411 ReadFieldOld("I2C1", "CTL", "EN", tmp0) && 412 ReadFieldOld("I2C1", "CLKDIV", "CLKDIV", tmp1)) 413 { 414 en &= tmp0; 415 i2c1clk = AddClock(pclk, "i2c1 clk", en ? FROM_PARENT : DISABLED, 416 1, 16*(tmp1+1)); 417 } 418 else 419 { 420 i2c1clk = AddClock(pclk, "i2c1 clk", INVALID); 421 } 422 423 if(ReadFieldOld("CMU", "DEVCLKEN", "I2C", en) && 424 ReadFieldOld("I2C2", "CTL", "EN", tmp0) && 425 ReadFieldOld("I2C2", "CLKDIV", "CLKDIV", tmp1)) 426 { 427 en &= tmp0; 428 i2c2clk = AddClock(pclk, "i2c2 clk", en ? FROM_PARENT : DISABLED, 429 1, 16*(tmp1+1)); 430 } 431 else 432 { 433 i2c2clk = AddClock(pclk, "i2c2 clk", INVALID); 434 } 435 436 Q_UNUSED(dsppll); 437 Q_UNUSED(adcclk); 438 Q_UNUSED(dacclk); 439 Q_UNUSED(sdrclk); 440 Q_UNUSED(nandclk); 441 Q_UNUSED(sdclk); 442 Q_UNUSED(mhaclk); 443 Q_UNUSED(mcaclk); 444 Q_UNUSED(pwmclk); 445 Q_UNUSED(i2c1clk); 446 Q_UNUSED(i2c2clk); 447} 448 449void ClockAnalyser::FillTreeRK27XX() 450{ 451 soc_word_t value, value2, value3, value4; 452 soc_word_t bypass, clkr, clkf, clkod, pll_off; 453 454 QTreeWidgetItem *xtal_clk = AddClock(0, "xtal clk", 24000000); 455 456 // F = (Fref*F)/R/OD = (Fref*F)/R/OD 457 QTreeWidgetItem *arm_pll = 0; 458 if(ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_BYPASS", bypass) && 459 ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKR", clkr) && 460 ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKF", clkf) && 461 ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKOD", clkod) && 462 ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_POWERDOWN", pll_off)) 463 { 464 arm_pll = AddClock(xtal_clk, "arm pll", pll_off ? DISABLED : FROM_PARENT, 465 bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); 466 } 467 else 468 { 469 arm_pll = AddClock(xtal_clk, "arm pll", INVALID); 470 } 471 472 QTreeWidgetItem *arm_clk = 0; 473 QTreeWidgetItem *hclk = 0; 474 QTreeWidgetItem *pclk = 0; 475 if(ReadFieldOld("SCU", "DIVCON1", "ARM_SLOW_MODE", value) && 476 ReadFieldOld("SCU", "DIVCON1", "ARM_CLK_DIV", value2) && 477 ReadFieldOld("SCU", "DIVCON1", "PCLK_CLK_DIV", value3)) 478 { 479 arm_clk = AddClock(value ? xtal_clk : arm_pll, "arm clk", FROM_PARENT, 1, value2 ? 2 : 1); 480 hclk = AddClock(arm_clk, "hclk", FROM_PARENT, 1, value2 ? 1 : 2); 481 pclk = AddClock(hclk, "pclk", FROM_PARENT, 1, (1<<value3)); 482 } 483 else 484 { 485 arm_clk = AddClock(xtal_clk, "arm_clk", INVALID); 486 hclk = AddClock(xtal_clk, "hclk", INVALID); 487 pclk = AddClock(xtal_clk, "pclk", INVALID); 488 } 489 490 QTreeWidgetItem *dsp_pll = 0; 491 if(ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_BYPASS", bypass) && 492 ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKR", clkr) && 493 ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKF", clkf) && 494 ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKOD", clkod) && 495 ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_POWERDOWN", pll_off)) 496 { 497 dsp_pll = AddClock(xtal_clk, "dsp pll", pll_off ? DISABLED : FROM_PARENT, 498 bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); 499 } 500 else 501 { 502 dsp_pll = AddClock(xtal_clk, "dsp_pll", INVALID); 503 } 504 505 QTreeWidgetItem *dsp_clk = AddClock(dsp_pll, "dsp clk", FROM_PARENT); 506 507 QTreeWidgetItem *codec_pll = 0; 508 if(ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_BYPASS", bypass) && 509 ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKR", clkr) && 510 ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKF", clkf) && 511 ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKOD", clkod) && 512 ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_POWERDOWN", pll_off)) 513 { 514 codec_pll = AddClock(xtal_clk, "codec pll", pll_off ? DISABLED : FROM_PARENT, 515 bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); 516 } 517 else 518 { 519 codec_pll = AddClock(xtal_clk, "codec_pll", INVALID); 520 } 521 522 QTreeWidgetItem *codec_clk = 0; 523 if(ReadFieldOld("SCU", "DIVCON1", "CODEC_CLK_SRC", value) && 524 ReadFieldOld("SCU", "DIVCON1", "CODEC_CLK_DIV", value2)) 525 { 526 codec_clk = AddClock(value ? xtal_clk : codec_pll, "codec clk", FROM_PARENT, 1, value ? 1 : (value2 + 1)); 527 } 528 else 529 { 530 codec_clk = AddClock(xtal_clk, "codec_clk", INVALID); 531 } 532 533 QTreeWidgetItem *lsadc_clk = 0; 534 if(ReadFieldOld("SCU", "DIVCON1", "LSADC_CLK_DIV", value)) 535 { 536 lsadc_clk = AddClock(pclk, "lsadc clk", FROM_PARENT, 1, (value+1)); 537 } 538 else 539 { 540 lsadc_clk = AddClock(xtal_clk, "lsadc clk", INVALID); 541 } 542 543 QTreeWidgetItem *lcdc_clk = 0; 544 if(ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK", value) && 545 ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK_DIV", value2) && 546 ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK_DIV_SRC", value3)) 547 { 548 if(value) 549 { 550 lcdc_clk = AddClock(xtal_clk, "lcdc clk", FROM_PARENT); 551 } 552 else 553 { 554 if(value3 == 0) 555 lcdc_clk = AddClock(arm_pll, "lcdc clk", FROM_PARENT, 1, value2+1); 556 else if(value3 == 1) 557 lcdc_clk = AddClock(dsp_pll, "lcdc clk", FROM_PARENT, 1, value2+1); 558 else 559 lcdc_clk = AddClock(codec_pll, "lcdc clk", FROM_PARENT, 1, value2+1); 560 } 561 } 562 else 563 { 564 lcdc_clk = AddClock(xtal_clk, "lcdc clk", INVALID); 565 } 566 567 QTreeWidgetItem *pwm0_clk = 0; 568 if(ReadFieldOld("PWM0", "LRC", "TR", value) && 569 ReadFieldOld("PWM0", "CTRL", "PRESCALE", value3) && 570 ReadFieldOld("PWM0", "CTRL", "PWM_EN", value4)) 571 { 572 pwm0_clk = AddClock(pclk, "pwm0 clk", value4 ? FROM_PARENT : DISABLED, 1, 2*value*(1<<value3)); 573 } 574 else 575 { 576 pwm0_clk = AddClock(xtal_clk, "pwm0 clk", INVALID); 577 } 578 579 QTreeWidgetItem *pwm1_clk = 0; 580 if(ReadFieldOld("PWM1", "LRC", "TR", value) && 581 ReadFieldOld("PWM1", "CTRL", "PRESCALE", value3) && 582 ReadFieldOld("PWM1", "CTRL", "PWM_EN", value4)) 583 { 584 pwm1_clk = AddClock(pclk, "pwm1 clk", value4 ? FROM_PARENT : DISABLED, 1, 2*value*(1<<value3)); 585 } 586 else 587 { 588 pwm1_clk = AddClock(xtal_clk, "pwm1 clk", INVALID); 589 } 590 591 QTreeWidgetItem *pwm2_clk = 0; 592 if(ReadFieldOld("PWM2", "LRC", "TR", value) && 593 ReadFieldOld("PWM2", "CTRL", "PRESCALE", value3) && 594 ReadFieldOld("PWM2", "CTRL", "PWM_EN", value4)) 595 { 596 pwm2_clk = AddClock(pclk, "pwm2 clk", value4 ? FROM_PARENT : DISABLED, 1, 2*value*(1<<value3)); 597 } 598 else 599 { 600 pwm2_clk = AddClock(xtal_clk, "pwm2 clk", INVALID); 601 } 602 603 QTreeWidgetItem *pwm3_clk = 0; 604 if(ReadFieldOld("PWM3", "LRC", "TR", value) && 605 ReadFieldOld("PWM3", "CTRL", "PRESCALE", value3) && 606 ReadFieldOld("PWM3", "CTRL", "PWM_EN", value4)) 607 { 608 pwm3_clk = AddClock(pclk, "pwm3", value4 ? FROM_PARENT : DISABLED, 1, 2*value*(1<<value3)); 609 } 610 else 611 { 612 pwm3_clk = AddClock(xtal_clk, "pwm3 clk", INVALID); 613 } 614 615 QTreeWidgetItem *sdmmc_clk = 0; 616 if(ReadFieldOld("SD", "CTRL", "DIVIDER", value)) 617 { 618 sdmmc_clk = AddClock(pclk, "sd clk", FROM_PARENT, 1, value+1); 619 } 620 else 621 { 622 sdmmc_clk = AddClock(xtal_clk, "sd clk", INVALID); 623 } 624 625 Q_UNUSED(dsp_clk); 626 Q_UNUSED(codec_clk); 627 Q_UNUSED(lsadc_clk); 628 Q_UNUSED(lcdc_clk); 629 Q_UNUSED(pwm0_clk); 630 Q_UNUSED(pwm1_clk); 631 Q_UNUSED(pwm2_clk); 632 Q_UNUSED(pwm3_clk); 633 Q_UNUSED(sdmmc_clk); 634} 635 636void ClockAnalyser::FillTreeIMX233() 637{ 638 /* work for stmp3700 and imx233 */ 639 soc_word_t value, value2, value3; 640 641 QTreeWidgetItem *ring_osc = 0; 642 if(ReadFieldOld("POWER", "MINPWR", "ENABLE_OSC", value)) 643 ring_osc = AddClock(0, "ring_clk24m", value ? 24000000 : DISABLED); 644 else 645 ring_osc = AddClock(0, "ring_clk24m", INVALID); 646 QTreeWidgetItem *xtal_osc = 0; 647 if(ReadFieldOld("POWER", "MINPWR", "PWD_XTAL24", value)) 648 xtal_osc = AddClock(0, "xtal_clk24m", value ? DISABLED : 24000000); 649 else 650 xtal_osc = AddClock(0, "xtal_clk24m", INVALID); 651 QTreeWidgetItem *ref_xtal = 0; 652 if(ReadFieldOld("POWER", "MINPWR", "SELECT_OSC", value)) 653 ref_xtal = AddClock(value ? ring_osc : xtal_osc, "ref_xtal", FROM_PARENT); 654 else 655 ref_xtal = AddClock(0, "ref_xtal", INVALID); 656 657 QTreeWidgetItem *ref_pll = 0; 658 if(ReadFieldOld("CLKCTRL", "PLLCTRL0", "POWER", value)) 659 ref_pll = AddClock(ref_xtal, "ref_pll", FROM_PARENT, 20); 660 else 661 ref_pll = AddClock(0, "ref_pll", INVALID); 662 663 QTreeWidgetItem *ref_io = 0; 664 if(ReadFieldOld("CLKCTRL", "FRAC", "CLKGATEIO", value) && 665 ReadFieldOld("CLKCTRL", "FRAC", "IOFRAC", value2)) 666 ref_io = AddClock(ref_pll, "ref_io", value ? DISABLED : FROM_PARENT, 18, value2); 667 else 668 ref_io = AddClock(ref_pll, "ref_io", INVALID); 669 670 QTreeWidgetItem *ref_pix = 0; 671 if(ReadFieldOld("CLKCTRL", "FRAC", "CLKGATEPIX", value) && 672 ReadFieldOld("CLKCTRL", "FRAC", "PIXFRAC", value2)) 673 ref_pix = AddClock(ref_pll, "ref_pix", value ? DISABLED : FROM_PARENT, 18, value2); 674 else 675 ref_pix = AddClock(ref_pll, "ref_pix", INVALID); 676 677 QTreeWidgetItem *ref_emi = 0; 678 if(ReadFieldOld("CLKCTRL", "FRAC", "CLKGATEEMI", value) && 679 ReadFieldOld("CLKCTRL", "FRAC", "EMIFRAC", value2)) 680 ref_emi = AddClock(ref_pll, "ref_emi", value ? DISABLED : FROM_PARENT, 18, value2); 681 else 682 ref_emi = AddClock(ref_pll, "ref_emi", INVALID); 683 684 QTreeWidgetItem *ref_cpu = 0; 685 if(ReadFieldOld("CLKCTRL", "FRAC", "CLKGATECPU", value) && 686 ReadFieldOld("CLKCTRL", "FRAC", "CPUFRAC", value2)) 687 ref_cpu = AddClock(ref_pll, "ref_cpu", value ? DISABLED : FROM_PARENT, 18, value2); 688 else 689 ref_cpu = AddClock(ref_pll, "ref_cpu", INVALID); 690 691 QTreeWidgetItem *clk_p = 0; 692 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_CPU", value)) 693 { 694 if(!value) 695 { 696 if(ReadFieldOld("CLKCTRL", "CPU", "DIV_CPU", value2)) 697 clk_p = AddClock(ref_cpu, "clk_p", FROM_PARENT, 1, value2); 698 else 699 clk_p = AddClock(ref_cpu, "clk_p", INVALID); 700 } 701 else 702 { 703 if(ReadFieldOld("CLKCTRL", "CPU", "DIV_XTAL_FRAC_EN", value) && 704 ReadFieldOld("CLKCTRL", "CPU", "DIV_XTAL", value2)) 705 clk_p = AddClock(ref_xtal, "clk_p", FROM_PARENT, value ? 1024 : 1, value2); 706 else 707 clk_p = AddClock(ref_xtal, "clk_p", INVALID); 708 } 709 } 710 else 711 clk_p = AddClock(ref_xtal, "clk_p", INVALID); 712 713 QTreeWidgetItem *clk_h = 0; 714 if(ReadFieldOld("CLKCTRL", "HBUS", "DIV_FRAC_EN", value) && 715 ReadFieldOld("CLKCTRL", "HBUS", "DIV", value2)) 716 clk_h = AddClock(clk_p, "clk_h", FROM_PARENT, value ? 32 : 1, value2); 717 else 718 clk_h = AddClock(clk_p, "clk_h", INVALID); 719 720 QTreeWidgetItem *clk_x = 0; 721 if(ReadFieldOld("CLKCTRL", "XBUS", "DIV", value)) 722 clk_x = AddClock(ref_xtal, "clk_x", FROM_PARENT, 1, value); 723 else 724 clk_x = AddClock(ref_xtal, "clk_x", INVALID); 725 726 if(ReadFieldOld("CLKCTRL", "XTAL", "UART_CLK_GATE", value)) 727 AddClock(ref_xtal, "clk_uart", value ? DISABLED : FROM_PARENT); 728 else 729 AddClock(ref_xtal, "clk_uart", INVALID); 730 731 if(ReadFieldOld("CLKCTRL", "XTAL", "FILT_CLK24M_GATE", value)) 732 AddClock(ref_xtal, "clk_filt24m", value ? DISABLED : FROM_PARENT); 733 else 734 AddClock(ref_xtal, "clk_filt24m", INVALID); 735 736 if(ReadFieldOld("CLKCTRL", "XTAL", "PWM_CLK24M_GATE", value)) 737 AddClock(ref_xtal, "clk_pwm24m", value ? DISABLED : FROM_PARENT); 738 else 739 AddClock(ref_xtal, "clk_pwm24m", INVALID); 740 741 if(ReadFieldOld("CLKCTRL", "XTAL", "DRI_CLK24M_GATE", value)) 742 AddClock(ref_xtal, "clk_dri24m", value ? DISABLED : FROM_PARENT); 743 else 744 AddClock(ref_xtal, "clk_dri24m", INVALID); 745 746 if(ReadFieldOld("CLKCTRL", "XTAL", "DIGCTRL_CLK1M_GATE", value)) 747 AddClock(ref_xtal, "clk_1m", value ? DISABLED : FROM_PARENT, 1, 24); 748 else 749 AddClock(ref_xtal, "clk_1m", INVALID); 750 751 QTreeWidgetItem *clk_32k = 0; 752 if(ReadFieldOld("CLKCTRL", "XTAL", "TIMROT_CLK32K_GATE", value)) 753 clk_32k = AddClock(ref_xtal, "clk_32k", value ? DISABLED : FROM_PARENT, 1, 750); 754 else 755 clk_32k = AddClock(ref_xtal, "clk_32k", INVALID); 756 757 AddClock(clk_32k, "clk_adc", FROM_PARENT, 1, 16); 758 759 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_PIX", value) && 760 ReadFieldOld("CLKCTRL", "PIX", "DIV", value2)) 761 AddClock(value ? ref_xtal : ref_pix, "clk_pix", FROM_PARENT, 1, value2); 762 else 763 AddClock(ref_xtal, "clk_p", INVALID); 764 765 QTreeWidgetItem *clk_ssp = 0; 766 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_SSP", value) && 767 ReadFieldOld("CLKCTRL", "SSP", "DIV", value2) && 768 ReadFieldOld("CLKCTRL", "SSP", "CLKGATE", value3)) 769 clk_ssp = AddClock(value ? ref_xtal : ref_io, "clk_ssp", value3 ? DISABLED : FROM_PARENT, 1, value2); 770 else 771 clk_ssp = AddClock(ref_xtal, "clk_ssp", INVALID); 772 773 if(ReadFieldOld("SSP[1]", "TIMING", "CLOCK_DIVIDE", value) && 774 ReadFieldOld("SSP[1]", "TIMING", "CLOCK_RATE", value2) && 775 ReadFieldOld("SSP[1]", "CTRL0", "CLKGATE", value3)) 776 AddClock(clk_ssp, "clk_ssp1", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2)); 777 else 778 AddClock(clk_ssp, "clk_ssp1", INVALID); 779 780 if(ReadFieldOld("SSP[2]", "TIMING", "CLOCK_DIVIDE", value) && 781 ReadFieldOld("SSP[2]", "TIMING", "CLOCK_RATE", value2) && 782 ReadFieldOld("SSP[2]", "CTRL0", "CLKGATE", value3)) 783 AddClock(clk_ssp, "clk_ssp2", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2)); 784 else 785 AddClock(clk_ssp, "clk_ssp2", INVALID); 786 787 QTreeWidgetItem *clk_gpmi = 0; 788 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_GPMI", value) && 789 ReadFieldOld("CLKCTRL", "GPMI", "DIV", value2) && 790 ReadFieldOld("CLKCTRL", "GPMI", "CLKGATE", value3)) 791 clk_gpmi = AddClock(value ? ref_xtal : ref_io, "clk_gpmi", value3 ? DISABLED : FROM_PARENT, 1, value2); 792 else 793 clk_gpmi = AddClock(ref_xtal, "clk_p", INVALID); 794 795 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value)) 796 { 797 if(!value) 798 { 799 if(ReadFieldOld("CLKCTRL", "EMI", "DIV_EMI", value2) && 800 ReadFieldOld("CLKCTRL", "EMI", "CLKGATE", value3)) 801 AddClock(ref_emi, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2); 802 else 803 AddClock(ref_emi, "clk_emi", INVALID); 804 } 805 else 806 { 807 if(ReadFieldOld("CLKCTRL", "EMI", "DIV_XTAL", value2) && 808 ReadFieldOld("CLKCTRL", "EMI", "CLKGATE", value3)) 809 AddClock(ref_xtal, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2); 810 else 811 AddClock(ref_xtal, "clk_emi", INVALID); 812 } 813 } 814 else 815 clk_p = AddClock(ref_xtal, "clk_emi", INVALID); 816 817 QTreeWidgetItem *ref_vid = AddClock(ref_pll, "clk_vid", FROM_PARENT); 818 819 if(ReadFieldOld("CLKCTRL", "TV", "CLK_TV108M_GATE", value) && 820 ReadFieldOld("CLKCTRL", "TV", "CLK_TV_GATE", value2)) 821 { 822 QTreeWidgetItem *clk_tv108m = AddClock(ref_vid, "clk_tv108m", value ? DISABLED : FROM_PARENT, 1, 4); 823 AddClock(clk_tv108m, "clk_tv54m", value2 ? DISABLED : FROM_PARENT, 1, 2); 824 AddClock(clk_tv108m, "clk_tv27m", value2 ? DISABLED : FROM_PARENT, 1, 4); 825 } 826 827 if(ReadFieldOld("CLKCTRL", "PLLCTRL0", "EN_USB_CLKS", value)) 828 AddClock(ref_pll, "utmi_clk480m", value ? FROM_PARENT : DISABLED); 829 else 830 AddClock(ref_pll, "utmi_clk480m", INVALID); 831 832 QTreeWidgetItem *xtal_clk32k = 0; 833 if(ReadFieldOld("RTC", "PERSISTENT0", "XTAL32_FREQ", value) && 834 ReadFieldOld("RTC", "PERSISTENT0", "XTAL32KHZ_PWRUP", value2)) 835 xtal_clk32k = AddClock(0, "xtal_clk32k", value2 == 0 ? DISABLED : value ? 32000 : 32768); 836 else 837 xtal_clk32k = AddClock(0, "xtal_clk32k", INVALID); 838 839 if(ReadFieldOld("RTC", "PERSISTENT0", "CLOCKSOURCE", value)) 840 AddClock(value ? xtal_clk32k : ref_xtal, "clk_rtc32k", FROM_PARENT, 1, value ? 1 : 768); 841 else 842 AddClock(ref_xtal, "clk_rtc32k", INVALID); 843 844 Q_UNUSED(clk_x); 845 Q_UNUSED(clk_gpmi); 846 Q_UNUSED(clk_h); 847} 848 849static TmplAnalyserFactory< ClockAnalyser > g_clock_factory(true, "Clock Analyser"); 850 851/** 852 * EMI analyser 853 */ 854EmiAnalyser::EmiAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) 855 :AnalyserEx(soc, backend) 856{ 857 m_display_mode = DisplayCycles; 858 m_group = new QGroupBox("EMI Analyser"); 859 QVBoxLayout *layout = new QVBoxLayout; 860 m_group->setLayout(layout); 861 m_panel = new QToolBox; 862 m_display_selector = new QComboBox; 863 m_display_selector->addItem("Cycles", DisplayCycles); 864 m_display_selector->addItem("Raw Hexadecimal", DisplayRawHex); 865 m_display_selector->addItem("Time", DisplayTime); 866 QHBoxLayout *line_layout = new QHBoxLayout; 867 line_layout->addWidget(new QLabel("Display Mode:")); 868 line_layout->addWidget(m_display_selector); 869 m_emi_freq_label = new QLineEdit; 870 m_emi_freq_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 871 m_emi_freq_label->setReadOnly(true); 872 m_emi_size_label = new QLineEdit; 873 m_emi_size_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 874 m_emi_size_label->setReadOnly(true); 875 line_layout->addStretch(); 876 line_layout->addWidget(new QLabel("Size:")); 877 line_layout->addWidget(m_emi_size_label); 878 line_layout->addWidget(new QLabel("MiB")); 879 line_layout->addStretch(); 880 line_layout->addWidget(new QLabel("Frequency:")); 881 line_layout->addWidget(m_emi_freq_label); 882 line_layout->addWidget(new QLabel("MHz")); 883 line_layout->addStretch(); 884 layout->addLayout(line_layout); 885 layout->addWidget(m_panel); 886 887 connect(m_display_selector, SIGNAL(currentIndexChanged(int)), this, 888 SLOT(OnChangeDisplayMode(int))); 889 890 FillTable(); 891} 892 893EmiAnalyser::~EmiAnalyser() 894{ 895 delete m_group; 896} 897 898QWidget *EmiAnalyser::GetWidget() 899{ 900 return m_group; 901} 902 903bool EmiAnalyser::SupportSoc(const QString& soc_name) 904{ 905 return soc_name == "imx233" || soc_name == "stmp3700"; 906} 907 908void EmiAnalyser::OnChangeDisplayMode(int index) 909{ 910 if(index == -1) 911 return; 912 m_display_mode = (DisplayMode)m_display_selector->itemData(index).toInt(); 913 int idx = m_panel->currentIndex(); 914 FillTable(); 915 m_panel->setCurrentIndex(idx); 916} 917 918void EmiAnalyser::NewGroup(const QString& name) 919{ 920 QTableWidget *table = new QTableWidget; 921 table->setColumnCount(3); 922 table->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); 923 table->setHorizontalHeaderItem(1, new QTableWidgetItem("Value")); 924 table->setHorizontalHeaderItem(2, new QTableWidgetItem("Comment")); 925 table->verticalHeader()->setVisible(false); 926 table->horizontalHeader()->setStretchLastSection(true); 927 m_panel->addItem(table, name); 928} 929 930void EmiAnalyser::AddLine(const QString& name, int value, const QString& unit, const QString& comment) 931{ 932 QTableWidget *table = dynamic_cast< QTableWidget* >(m_panel->widget(m_panel->count() - 1)); 933 int row = table->rowCount(); 934 table->setRowCount(row + 1); 935 table->setItem(row, 0, new QTableWidgetItem(name)); 936 QString val; 937 if(value == INVALID) 938 val = "<invalid>"; 939 else if(value == NONE) 940 val = unit; 941 else if(m_display_mode == DisplayRawHex && unit.size() == 0) 942 val = QString("0x%1").arg(value, 0, 16); 943 else 944 val = QString("%1%2").arg(value).arg(unit); 945 table->setItem(row, 1, new QTableWidgetItem(val)); 946 table->item(row, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 947 table->setItem(row, 2, new QTableWidgetItem(comment)); 948 table->resizeColumnToContents(0); 949 table->resizeColumnToContents(1); 950} 951 952void EmiAnalyser::AddCycleLine(const QString& name, unsigned raw_val, float val, 953 int digits, const QString& comment) 954{ 955 if(m_display_mode == DisplayCycles) 956 { 957 QString str; 958 if(digits == 0) 959 str = QString("%1").arg((int)val); 960 else 961 str = QString("%1").arg(val, 0, 'f', digits); 962 str += " cycles"; 963 AddLine(name, NONE, str, comment); 964 } 965 else if(m_display_mode == DisplayRawHex) 966 { 967 QString str = QString("0x%1").arg(raw_val, 0, 16); 968 AddLine(name, NONE, str, comment); 969 } 970 else if(m_display_mode == DisplayTime && m_emi_freq != 0) 971 { 972 float cycle_time_ns = 1000000000.0 / m_emi_freq; 973 val *= cycle_time_ns; 974 QString str; 975 if(val >= 1000) 976 str = QString::fromWCharArray(L"%1 µs").arg(val / 1000.0, 0, 'f', 2); 977 else 978 str = QString("%1 ns").arg(val, 0, 'f', 2); 979 AddLine(name, NONE, str, comment); 980 } 981 else 982 AddLine(name, raw_val, " cycles", comment); 983} 984 985void EmiAnalyser::FillTable() 986{ 987 while(m_panel->count() > 0) 988 m_panel->removeItem(0); 989 soc_word_t value; 990 991 m_emi_freq = 0; 992 if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value)) 993 { 994 bool ret; 995 if(value) 996 { 997 m_emi_freq = 24000000; 998 ret = ReadFieldOld("CLKCTRL", "EMI", "DIV_XTAL", value); 999 } 1000 else 1001 { 1002 m_emi_freq = 480000000; 1003 if(ReadFieldOld("CLKCTRL", "FRAC", "EMIFRAC", value)) 1004 m_emi_freq = 18 * (int64_t)m_emi_freq / value; 1005 else 1006 m_emi_freq = 0; 1007 ret = ReadFieldOld("CLKCTRL", "EMI", "DIV_EMI", value); 1008 } 1009 if(ret) 1010 m_emi_freq /= value; 1011 else 1012 m_emi_freq = 0; 1013 } 1014 1015 m_emi_freq_label->setText(QString().sprintf("%.3f", m_emi_freq / 1000000.0)); 1016 1017 soc_word_t rows, columns, cs_map; 1018 if(ReadFieldOld("DRAM", "CTL14", "CS_MAP", cs_map) && 1019 ReadFieldOld("DRAM", "CTL10", "ADDR_PINS", rows) && 1020 ReadFieldOld("DRAM", "CTL11", "COLUMN_SIZE", columns)) 1021 { 1022 rows = 13 - rows; 1023 columns = 12 - columns; 1024 soc_word_t banks = 4; 1025 soc_word_t chips = __builtin_popcount(cs_map); 1026 unsigned long size = 2 * (1 << (rows + columns)) * chips * banks; 1027 m_emi_size_label->setText(QString().sprintf("%lu", (unsigned long)size / 1024 / 1024)); 1028 } 1029 else 1030 m_emi_size_label->setText("<invalid>"); 1031 1032 NewGroup("Control Parameters"); 1033 if(ReadFieldOld("EMI", "CTRL", "PORT_PRIORITY_ORDER", value)) 1034 { 1035 QStringList ports; 1036 ports << "AXI0" << "AHB1" << "AHB2" << "AHB3"; 1037 QString order; 1038 order += ports[value / 6]; 1039 ports.erase(ports.begin() + value / 6); 1040 int ord[6][3] = { {0, 1, 2}, {2, 0, 1}, {1, 2, 0}, {2, 1, 0}, {1, 0, 2}, {0, 2, 1} }; 1041 for(int i = 0; i < 3; i++) 1042 order += ", " + ports[ord[value % 6][i]]; 1043 AddLine("Port Priority Order", value, "", order); 1044 } 1045 1046 if(ReadFieldOld("EMI", "CTRL", "MEM_WIDTH", value)) 1047 AddLine("Memory Width", value ? 16 : 8, "-bit"); 1048 1049 if(ReadFieldOld("DRAM", "CTL03", "AP", value)) 1050 AddLine("Auto Pre-Charge", NONE, value ? "Yes" : "No"); 1051 1052 bool bypass_mode = false; 1053 if(ReadFieldOld("DRAM", "CTL04", "DLL_BYPASS_MODE", value)) 1054 { 1055 bypass_mode = value == 1; 1056 AddLine("DLL Bypass Mode", NONE, value ? "Yes" : "No"); 1057 } 1058 1059 if(ReadFieldOld("DRAM", "CTL05", "EN_LOWPOWER_MODE", value)) 1060 AddLine("Low Power Mode", NONE, value ? "Enabled" : "Disabled"); 1061 1062 if(ReadFieldOld("DRAM", "CTL08", "SREFRESH", value)) 1063 AddLine("Self Refresh", NONE, value ? "Yes" : "No"); 1064 1065 if(ReadFieldOld("DRAM", "CTL08", "SDR_MODE", value)) 1066 AddLine("Mode", NONE, value ? "SDR" : "DDR"); 1067 1068 if(ReadFieldOld("DRAM", "CTL10", "ADDR_PINS", value)) 1069 AddLine("Address Pins", 13 - value, ""); 1070 1071 if(ReadFieldOld("DRAM", "CTL11", "COLUMN_SIZE", value)) 1072 AddLine("Column Size", 12 - value, "-bit"); 1073 1074 if(ReadFieldOld("DRAM", "CTL11", "CASLAT", value)) 1075 AddLine("Encoded CAS", value, "", "Memory device dependent"); 1076 1077 if(ReadFieldOld("DRAM", "CTL14", "CS_MAP", value)) 1078 { 1079 QString v; 1080 for(int i = 0; i < 4; i++) 1081 if(value & (1 << i)) 1082 { 1083 if(v.size() != 0) 1084 v += " "; 1085 v += QString("%1").arg(i); 1086 } 1087 AddLine("Chip Select Pins", NONE, v, ""); 1088 } 1089 1090 if(ReadFieldOld("DRAM", "CTL37", "TREF_ENABLE", value)) 1091 AddLine("Refresh Commands", NONE, value ? "Enabled" : "Disabled", "Issue self-refresh every TREF cycles"); 1092 1093 NewGroup("Frequency Parameters"); 1094 1095 if(ReadFieldOld("DRAM", "CTL13", "CASLAT_LIN_GATE", value)) 1096 { 1097 if(value >= 3 && value <= 10 && value != 9) 1098 { 1099 float v = (value / 2) + 0.5 * (value % 2); 1100 AddCycleLine("CAS Gate", value, v, 1, ""); 1101 } 1102 else 1103 AddLine("CAS Gate", NONE, "Reserved", "Reserved value"); 1104 } 1105 if(ReadFieldOld("DRAM", "CTL13", "CASLAT_LIN", value)) 1106 { 1107 if(value >= 3 && value <= 10 && value != 9) 1108 { 1109 float v = (value / 2) + 0.5 * (value % 2); 1110 AddCycleLine("CAS Latency", value, v, 1, ""); 1111 } 1112 else 1113 AddLine("CAS Latency", NONE, "Reserved", "Reserved value"); 1114 } 1115 1116 if(ReadFieldOld("DRAM", "CTL12", "TCKE", value)) 1117 AddCycleLine("tCKE", value, value, 0, "Minimum CKE pulse width"); 1118 1119 if(ReadFieldOld("DRAM", "CTL15", "TDAL", value)) 1120 AddCycleLine("tDAL", value, value, 0, "Auto pre-charge write recovery time"); 1121 1122 if(ReadFieldOld("DRAM", "CTL31", "TDLL", value)) 1123 AddCycleLine("tDLL", value, value, 0, "DLL lock time"); 1124 1125 if(ReadFieldOld("DRAM", "CTL10", "TEMRS", value)) 1126 AddCycleLine("tEMRS", value, value, 0, "Extended mode parameter set time"); 1127 1128 if(ReadFieldOld("DRAM", "CTL34", "TINIT", value)) 1129 AddCycleLine("tINIT", value, value, 0, "Initialisation time"); 1130 1131 if(ReadFieldOld("DRAM", "CTL16", "TMRD", value)) 1132 AddCycleLine("tMRD", value, value, 0, "Mode register set command time"); 1133 1134 if(ReadFieldOld("DRAM", "CTL40", "TPDEX", value)) 1135 AddCycleLine("tPDEX", value, value, 0, "Power down exit time"); 1136 1137 if(ReadFieldOld("DRAM", "CTL32", "TRAS_MAX", value)) 1138 AddCycleLine("tRAS Max", value, value, 0, "Maximum row activate time"); 1139 1140 if(ReadFieldOld("DRAM", "CTL20", "TRAS_MIN", value)) 1141 AddCycleLine("tRAS Min", value, value, 0, "Minimum row activate time"); 1142 1143 if(ReadFieldOld("DRAM", "CTL17", "TRC", value)) 1144 AddCycleLine("tRC", value, value, 0, "Activate to activate delay (same bank)"); 1145 1146 if(ReadFieldOld("DRAM", "CTL20", "TRCD_INT", value)) 1147 AddCycleLine("tRCD", value, value, 0, "RAS to CAS"); 1148 1149 if(ReadFieldOld("DRAM", "CTL26", "TREF", value)) 1150 AddCycleLine("tREF", value, value, 0, "Refresh to refresh time"); 1151 1152 if(ReadFieldOld("DRAM", "CTL21", "TRFC", value)) 1153 AddCycleLine("tRFC", value, value, 0, "Refresh command time"); 1154 1155 if(ReadFieldOld("DRAM", "CTL15", "TRP", value)) 1156 AddCycleLine("tRP", value, value, 0, "Pre-charge command time"); 1157 1158 if(ReadFieldOld("DRAM", "CTL12", "TRRD", value)) 1159 AddCycleLine("tRRD", value, value, 0, "Activate to activate delay (different banks)"); 1160 1161 if(ReadFieldOld("DRAM", "CTL12", "TWR_INT", value)) 1162 AddCycleLine("tWR", value, value, 0, "Write recovery time"); 1163 1164 if(ReadFieldOld("DRAM", "CTL13", "TWTR", value)) 1165 AddCycleLine("tWTR", value, value, 0, "Write to read delay"); 1166 1167 if(ReadFieldOld("DRAM", "CTL32", "TXSNR", value)) 1168 AddCycleLine("tXSNR", value, value, 0, ""); 1169 1170 if(ReadFieldOld("DRAM", "CTL33", "TXSR", value)) 1171 AddCycleLine("tXSR", value, value, 0, "Self-refresh exit time"); 1172 1173 NewGroup("DLL Parameters"); 1174 1175 if(bypass_mode) 1176 { 1177 if(ReadFieldOld("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) 1178 AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle (bypass mode)"); 1179 1180 if(ReadFieldOld("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) 1181 AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle (bypass mode)"); 1182 1183 if(ReadFieldOld("DRAM", "CTL19", "DQS_OUT_SHIFT_BYPASS", value)) 1184 AddLine("DQS Out Delay", value, "", "(bypass mode)"); 1185 1186 if(ReadFieldOld("DRAM", "CTL20", "WR_DQS_SHIFT_BYPASS", value)) 1187 AddLine("DQS Write Delay", value, "", "(bypass mode)"); 1188 } 1189 else 1190 { 1191 if(ReadFieldOld("DRAM", "CTL17", "DLL_START_POINT", value)) 1192 AddLine("DLL Start Point", value, "", "Initial delay count"); 1193 1194 if(ReadFieldOld("DRAM", "CTL17", "DLL_INCREMENT", value)) 1195 AddLine("DLL Increment", value, "", "Delay increment"); 1196 1197 if(ReadFieldOld("DRAM", "CTL18", "DLL_DQS_DELAY_0", value)) 1198 AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle"); 1199 1200 if(ReadFieldOld("DRAM", "CTL18", "DLL_DQS_DELAY_1", value)) 1201 AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle"); 1202 1203 if(ReadFieldOld("DRAM", "CTL19", "DQS_OUT_SHIFT", value)) 1204 AddLine("DQS Out Delay", value, "", ""); 1205 1206 if(ReadFieldOld("DRAM", "CTL20", "WR_DQS_SHIFT", value)) 1207 AddLine("DQS Write Delay", value, "", ""); 1208 } 1209 1210} 1211 1212static TmplAnalyserFactory< EmiAnalyser > g_emi_factory(true, "EMI Analyser"); 1213 1214/** 1215 * Pin analyser 1216 */ 1217 1218namespace pin_desc 1219{ 1220#include "../../imxtools/misc/map.h" 1221} 1222 1223PinAnalyser::PinAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) 1224 :AnalyserEx(soc, backend) 1225{ 1226 m_group = new QGroupBox("Pin Analyser"); 1227 QVBoxLayout *layout = new QVBoxLayout; 1228 m_group->setLayout(layout); 1229 QLabel *label = new QLabel("Package:"); 1230 m_package_edit = new QLineEdit; 1231 m_package_edit->setReadOnly(true); 1232 m_package_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1233 QHBoxLayout *hlayout = new QHBoxLayout; 1234 hlayout->addStretch(); 1235 hlayout->addWidget(label); 1236 hlayout->addWidget(m_package_edit); 1237 hlayout->addStretch(); 1238 layout->addLayout(hlayout); 1239 m_panel = new QToolBox; 1240 layout->addWidget(m_panel); 1241 1242 FillList(); 1243} 1244 1245PinAnalyser::~PinAnalyser() 1246{ 1247 delete m_group; 1248} 1249 1250QWidget *PinAnalyser::GetWidget() 1251{ 1252 return m_group; 1253} 1254 1255bool PinAnalyser::SupportSoc(const QString& soc_name) 1256{ 1257 return soc_name == "imx233" || soc_name == "stmp3700"; 1258} 1259 1260void PinAnalyser::FillList() 1261{ 1262 soc_word_t value; 1263 1264 while(m_panel->count() > 0) 1265 m_panel->removeItem(0); 1266 1267 const char *package_type[8] = 1268 { 1269 "bga169", "bga100", "lqfp100", "lqfp128", 0, 0, 0, 0 1270 }; 1271 1272 if(!ReadFieldOld("DIGCTL", "STATUS", "PACKAGE_TYPE", value)) 1273 { 1274 m_package_edit->setText("<read error>"); 1275 return; 1276 } 1277 if(value >= 8 || package_type[value] == NULL) 1278 { 1279 m_package_edit->setText("<unknown package>"); 1280 return; 1281 } 1282 const char *package = package_type[value]; 1283 m_package_edit->setText(package); 1284 pin_desc::bank_map_t *map = NULL; 1285 for(size_t i = 0; i < sizeof(pin_desc::socs) / sizeof(pin_desc::socs[0]); i++) 1286 if(QString(pin_desc::socs[i].soc) == m_io_backend->GetSocName() && 1287 QString(pin_desc::socs[i].ver) == package) 1288 map = pin_desc::socs[i].map; 1289 if(map == NULL) 1290 { 1291 m_package_edit->setText(QString("%1 (no map available)").arg(package)); 1292 return; 1293 } 1294 1295 QMap< unsigned, QColor > color_map; 1296 color_map[PIN_GROUP_EMI] = QColor(255, 255, 64); 1297 color_map[PIN_GROUP_GPIO] = QColor(171, 214, 230); 1298 color_map[PIN_GROUP_I2C] = QColor(191, 191, 255); 1299 color_map[PIN_GROUP_JTAG] = QColor(238, 75, 21); 1300 color_map[PIN_GROUP_PWM] = QColor(255, 236, 179); 1301 color_map[PIN_GROUP_SPDIF] = QColor(174, 235, 63); 1302 color_map[PIN_GROUP_TIMROT] = QColor(255, 112, 237); 1303 color_map[PIN_GROUP_AUART] = QColor(94, 255, 128); 1304 color_map[PIN_GROUP_ETM] = QColor(168, 53, 14); 1305 color_map[PIN_GROUP_GPMI] = QColor(255, 211, 147); 1306 color_map[PIN_GROUP_IrDA] = QColor(64, 97, 255); 1307 color_map[PIN_GROUP_LCD] = QColor(124, 255, 255); 1308 color_map[PIN_GROUP_SAIF] = QColor(255, 158, 158); 1309 color_map[PIN_GROUP_SSP] = QColor(222, 128, 255); 1310 color_map[PIN_GROUP_DUART] = QColor(192, 191, 191); 1311 color_map[PIN_GROUP_USB] = QColor(0, 255, 0); 1312 color_map[PIN_GROUP_NONE] = QColor(255, 255, 255); 1313 1314 for(int bank = 0; bank < 4; bank++) 1315 { 1316 QTableWidget *table = new QTableWidget; 1317 table->setColumnCount(7); 1318 table->setHorizontalHeaderItem(0, new QTableWidgetItem("Pin")); 1319 table->setHorizontalHeaderItem(1, new QTableWidgetItem("Function")); 1320 table->setHorizontalHeaderItem(2, new QTableWidgetItem("Direction")); 1321 table->setHorizontalHeaderItem(3, new QTableWidgetItem("Drive")); 1322 table->setHorizontalHeaderItem(4, new QTableWidgetItem("Voltage")); 1323 table->setHorizontalHeaderItem(5, new QTableWidgetItem("Pull")); 1324 table->setHorizontalHeaderItem(6, new QTableWidgetItem("Value")); 1325 table->verticalHeader()->setVisible(false); 1326 table->horizontalHeader()->setStretchLastSection(true); 1327 m_panel->addItem(table, QString("Bank %1").arg(bank)); 1328 uint32_t muxsel[2], drive[4], pull, in, out, oe; 1329 bool error = false; 1330 for(int i = 0; i < 2; i++) 1331 if(!ReadRegisterOld("PINCTRL", QString("MUXSELn[%1]").arg(bank * 2 + i), muxsel[i])) 1332 error = true; 1333 /* don't make an error for those since some do not exist */ 1334 for(int i = 0; i < 4; i++) 1335 if(!ReadRegisterOld("PINCTRL", QString("DRIVEn[%1]").arg(bank * 4 + i), drive[i])) 1336 drive[i] = 0; 1337 if(error) 1338 continue; 1339 if(!ReadRegisterOld("PINCTRL", QString("PULLn[%1]").arg(bank), pull)) 1340 pull = 0; 1341 if(!ReadRegisterOld("PINCTRL", QString("DINn[%1]").arg(bank), in)) 1342 in = 0; 1343 if(!ReadRegisterOld("PINCTRL", QString("DOUTn[%1]").arg(bank), out)) 1344 out = 0; 1345 if(!ReadRegisterOld("PINCTRL", QString("DOEn[%1]").arg(bank), oe)) 1346 oe = 0; 1347 1348 for(int pin = 0; pin < 32; pin++) 1349 { 1350 /* skip all-reserved pins */ 1351 bool all_dis = true; 1352 for(int fn = 0; fn < 4; fn++) 1353 if(map[bank].pins[pin].function[fn].name != NULL) 1354 all_dis = false; 1355 if(all_dis) 1356 continue; 1357 /* add line */ 1358 int row = table->rowCount(); 1359 table->setRowCount(row + 1); 1360 /* name */ 1361 table->setItem(row, 0, new QTableWidgetItem(QString("B%1P%2") 1362 .arg(bank).arg(pin, 2, 10, QChar('0')))); 1363 table->item(row, 0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1364 /* function */ 1365 int fn = (muxsel[pin / 16] >> ((pin % 16) * 2)) & 3; 1366 table->setItem(row, 1, new QTableWidgetItem(QString(map[bank].pins[pin].function[fn].name))); 1367 table->item(row, 1)->setBackground(QBrush(color_map[map[bank].pins[pin].function[fn].group])); 1368 table->item(row, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1369 /* direction */ 1370 table->setItem(row, 2, new QTableWidgetItem(fn != 3 ? "" : (oe & (1 << pin)) ? "Output" : "Input")); 1371 table->item(row, 2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1372 /* drive */ 1373 int drv = (drive[pin / 8] >> ((pin % 8) * 4)) & 3; 1374 const char *strength[4] = {"4 mA", "8 mA", "12 mA", "16 mA"}; 1375 table->setItem(row, 3, new QTableWidgetItem(QString(strength[drv]))); 1376 table->item(row, 3)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1377 /* voltage */ 1378 int volt = (drive[pin / 8] >> (((pin % 8) * 4) + 2)) & 1; 1379 if(m_io_backend->GetSocName() == "imx233") 1380 volt = 1; /* cannot change voltage on imx233 */ 1381 const char *voltage[2] = {"1.8 V", "3.3 V"}; 1382 table->setItem(row, 4, new QTableWidgetItem(QString(voltage[volt]))); 1383 table->item(row, 4)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1384 /* pull */ 1385 table->setItem(row, 5, new QTableWidgetItem(QString("%1").arg((pull >> pin) & 1))); 1386 table->item(row, 5)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1387 /* input */ 1388 table->setItem(row, 6, new QTableWidgetItem(QString("%1").arg((in >> pin) & 1))); 1389 table->item(row, 6)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 1390 } 1391 } 1392} 1393 1394static TmplAnalyserFactory< PinAnalyser > g_pin_factory(true, "Pin Analyser");