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