/** Set DPLLs 1,2,3,4,5 to ON (locked) and autoidle. * @param device Register map. * * The idea is to get all DPLLs running and make hw control their power mode, * based on the module requirements (module ICLKs and FCLKs). */ void amdm37x_setup_dpll_on_autoidle(amdm37x_t *device) { assert(device); /* Get SYS_CLK value, it is used as reference clock by all DPLLs, * NFI who sets this or why it is set to specific value. */ const unsigned osc_clk = pio_read_32(&device->prm.clocks->clksel) & CLOCK_CONTROL_PRM_CLKSEL_SYS_CLKIN_MASK; const unsigned clk_reg = pio_read_32(&device->prm.global->clksrc_ctrl); const unsigned base_freq = sys_clk_freq_kHz(osc_clk) / GLOBAL_REG_PRM_CLKSRC_CTRL_SYSCLKDIV_GET(clk_reg); ddf_msg(LVL_NOTE, "Base frequency: %d.%dMhz", base_freq / 1000, base_freq % 1000); /* DPLL1 provides MPU(CPU) clock. * It uses SYS_CLK as reference clock and core clock (DPLL3) as * high frequency bypass (MPU then runs on L3 interconnect freq). * It should be setup by fw or u-boot.*/ mpu_cm_regs_t *mpu = device->cm.mpu; /* Current MPU frequency. */ if (pio_read_32(&mpu->clkstst) & MPU_CM_CLKSTST_CLKACTIVITY_MPU_ACTIVE_FLAG) { if (pio_read_32(&mpu->idlest_pll) & MPU_CM_IDLEST_PLL_ST_MPU_CLK_LOCKED_FLAG) { /* DPLL active and locked */ const uint32_t reg = pio_read_32(&mpu->clksel1_pll); const unsigned multiplier = (reg & MPU_CM_CLKSEL1_PLL_MPU_DPLL_MULT_MASK) >> MPU_CM_CLKSEL1_PLL_MPU_DPLL_MULT_SHIFT; const unsigned divisor = (reg & MPU_CM_CLKSEL1_PLL_MPU_DPLL_DIV_MASK) >> MPU_CM_CLKSEL1_PLL_MPU_DPLL_DIV_SHIFT; const unsigned divisor2 = (pio_read_32(&mpu->clksel2_pll) & MPU_CM_CLKSEL2_PLL_MPU_DPLL_CLKOUT_DIV_MASK); if (multiplier && divisor && divisor2) { /** See AMDM37x TRM p. 300 for the formula */ const unsigned freq = ((base_freq * multiplier) / (divisor + 1)) / divisor2; ddf_msg(LVL_NOTE, "MPU running at %d.%d MHz", freq / 1000, freq % 1000); } else { ddf_msg(LVL_WARN, "Frequency divisor and/or " "multiplier value invalid: %d %d %d", multiplier, divisor, divisor2); } } else { /* DPLL in LP bypass mode */ const unsigned divisor = MPU_CM_CLKSEL1_PLL_MPU_CLK_SRC_VAL( pio_read_32(&mpu->clksel1_pll)); ddf_msg(LVL_NOTE, "MPU DPLL in bypass mode, running at" " CORE CLK / %d MHz", divisor); } } else {
uint32_t hda_reg32_read(uint32_t *r) { return uint32_t_le2host(pio_read_32(r)); }
/** Debug function, checks consistency of memory structures. * * @param[in] arg UHCI structure to use. * @return EOK (should never return) */ int hc_debug_checker(void *arg) { hc_t *instance = arg; assert(instance); #define QH(queue) \ instance->transfers_##queue.queue_head while (1) { const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); const uint16_t sts = pio_read_16(&instance->registers->usbsts); const uint16_t intr = pio_read_16(&instance->registers->usbintr); if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { usb_log_debug2("Command: %X Status: %X Intr: %x\n", cmd, sts, intr); } const uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd) & ~0xfff; if (frame_list != addr_to_phys(instance->frame_list)) { usb_log_debug("Framelist address: %p vs. %p.\n", (void *) frame_list, (void *) addr_to_phys(instance->frame_list)); } int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; uintptr_t expected_pa = instance->frame_list[frnum] & LINK_POINTER_ADDRESS_MASK; uintptr_t real_pa = addr_to_phys(QH(interrupt)); if (expected_pa != real_pa) { usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n", (void *) expected_pa, frnum, (void *) real_pa); } expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK; real_pa = addr_to_phys(QH(control_slow)); if (expected_pa != real_pa) { usb_log_debug("Control Slow QH: %p vs. %p.\n", (void *) expected_pa, (void *) real_pa); } expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK; real_pa = addr_to_phys(QH(control_full)); if (expected_pa != real_pa) { usb_log_debug("Control Full QH: %p vs. %p.\n", (void *) expected_pa, (void *) real_pa); } expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK; real_pa = addr_to_phys(QH(bulk_full)); if (expected_pa != real_pa ) { usb_log_debug("Bulk QH: %p vs. %p.\n", (void *) expected_pa, (void *) real_pa); } async_usleep(UHCI_DEBUGER_TIMEOUT); } return EOK; #undef QH }