📄 prcm_34xx.c
字号:
"FCLK Mask : 0x%x " "ICLK Mask : 0x%x\n", domainid, fclk_mask, iclk_mask) ; return PRCM_FAIL; } /* * Are initiators in standby? * Are all devices idle? * * (Not needed for NEON) */ if (domainid != DOM_NEON) { prcm_get_initiators_not_standby(domainid, &init_mask); prcm_get_devices_not_idle(domainid, &dev_mask); if (init_mask || dev_mask) { printk (KERN_INFO "prcm_set_clock_domain_state : " "Pre-condition not met. " "Domain : 0x%x " "Init Mask : 0x%x " "Idle Mask : 0x%x\n", domainid, init_mask, dev_mask) ; return PRCM_FAIL; } } } } /* Program Clkstctrl register */ new_val = *addr & ~valid; new_val = new_val | new_state; *addr = new_val; /* NEON has no CLKSTST register */ if ((check_state == PRCM_TRUE) && (domainid != DOM_NEON)) { /* Wait for the Clock domain to transition to the new state */ if (new_state == PRCM_SWSUP_WKUP) return prcm_check_clock_domain_status(domainid, PRCM_ENABLE); if (new_state == PRCM_SWSUP_SLEEP) return prcm_check_clock_domain_status(domainid, PRCM_DISABLE); } return PRCM_PASS;}/*========================================================================*//*===================GET POWER DOMAIN STATE===============================*//*= This function returns the current state of a power domain. If the =*//*= power domain is in the middle of a state transition, it waits for the=*//*= transition to complete. =*//*========================================================================*/int prcm_get_power_domain_state(u32 domainid, u8 *result){ volatile u32 *addr; u32 valid, loop_cnt = 0, retries_cnt = 0; int ret; if ((domainid == DOM_CORE1) || (domainid == DOM_CORE2)) { printk (KERN_INFO "prcm_get_power_domain_state : " "Not supported for DOM_CORE1/DOM_CORE2\n") ; return PRCM_FAIL; } addr = get_addr(domainid, REG_PWSTST); valid = get_val_bits(domainid, REG_PWSTST); if (!addr) return PRCM_FAIL; while (*addr & PWSTST_INTRANS_MASK) { ret = loop_wait(&loop_cnt, &retries_cnt, 100); if (ret != PRCM_PASS) { printk (KERN_INFO "prcm_get_power_domain_state : " "Loop count exceeded. " "(domain 0x%x)\n", domainid) ; return ret; } } *result = (u8) (*addr & PWSTST_PWST_MASK); return PRCM_PASS;}/*========================================================================*//*===============GET PREVIOUS POWER DOMAIN STATE==========================*//*= This function returns the previous state of a power domain. =*//*========================================================================*/int prcm_get_pre_power_domain_state(u32 domainid, u8 *result){ volatile u32 *addr; u32 valid; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_PREPWSTST); valid = get_val_bits(domainid, REG_PREPWSTST); if (!addr) return PRCM_FAIL; *result = (u8) *addr & PWSTST_PWST_MASK; return PRCM_PASS;}/*============================================================================*//*======================== POWER DOMAIN STATUS ===============================*//*============================================================================*//* This function waits for the power domain to transition to the desired state*//* It polls on the power domain state and times out after a wait of ~500 micro*//* secs. It returns PRCM_PASS id the power domain transitions to the desired *//* state within the timeout period, else return PRCM_FAIL *//*============================================================================*/static int prcm_check_power_domain_status(u32 domainid, u8 desired_state){ u8 curr_state; int ret; u32 loop_cnt = 0, retries_cnt = 0; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; if ( (domainid == DOM_CORE1) || (domainid == DOM_CORE2) || (domainid == DOM_MPU)) { printk(KERN_INFO "prcm_check_power_domain_status: " "Not supported for DOM_CORE1/DOM_CORE2/DOM_MPU\n") ; return PRCM_FAIL; } if (prcm_get_power_domain_state(domainid, &curr_state)) return PRCM_FAIL; while (curr_state != desired_state) { ret = prcm_get_power_domain_state(domainid, &curr_state); if (ret != PRCM_PASS) return ret; ret = loop_wait(&loop_cnt, &retries_cnt, 100); if (ret != PRCM_PASS) { printk (KERN_INFO "prcm_check_power_domain_status : " "Loop count exceeded. " "(domain 0x%x)\n", domainid) ; return ret; } } return PRCM_PASS;}/*============================================================================*//*======================== SET POWER DOMAIN STATE ============================*//*============================================================================*//* This function sets the power domain state to the 'new_state' specified. If *//* mode is 'PRCM_AUTO', the clock domain is programmed in Hardware supervised *//* mode and the function waits for the power domain to transition to the *//* desired state. If mode is 'PRCM_FORCE' the clock domain is programmed in *//* software supervised mode and the function does not wait for the power *//* domain transition to happen. *//*============================================================================*/int prcm_set_power_domain_state(u32 domainid, u8 new_state, u8 mode){ volatile u32 *addr; volatile u32 *rstst_addr; u32 new_val; int ret = PRCM_PASS; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; if ( (domainid == DOM_CORE1) || (domainid == DOM_CORE2)) { printk(KERN_INFO "prcm_set_power_domain_state: " "Not supported for DOM_CORE1/DOM_CORE2\n") ; return PRCM_FAIL; } addr = get_addr(domainid, REG_PWSTCTRL); if (!addr) return PRCM_FAIL; rstst_addr = get_addr(domainid, REG_RSTST); if (new_state == PRCM_ON) { if (rstst_addr != 0) *rstst_addr |= DOM_WKUP_RST; } if (mode == PRCM_AUTO) { /* Set the power domain state to new_state */ new_val = *addr & ~PWSTST_PWST_MASK; new_val = new_val | new_state; *addr = new_val; ret = prcm_set_clock_domain_state(domainid, PRCM_HWSUP_AUTO, PRCM_FALSE); } else if (mode == PRCM_FORCE) { if (domainid == DOM_MPU) return PRCM_FAIL; /*No force mode for MPU */ new_val = *addr & ~PWSTST_PWST_MASK; new_val = new_val | new_state; *addr = new_val; if ( (new_state == PRCM_OFF) || (new_state == PRCM_RET)) { ret = prcm_set_clock_domain_state(domainid, PRCM_SWSUP_SLEEP, PRCM_TRUE); } else { ret = prcm_set_clock_domain_state(domainid, PRCM_SWSUP_WKUP, PRCM_FALSE); } if (ret == PRCM_PASS) { /* Wait for the power domain transition to complete */ ret = prcm_check_power_domain_status(domainid, new_state); } } return ret;}/*============================================================================*//*======================== DEVICES NOT IDLE =================================*//*============================================================================*//*= This function returns a mask of devices that are not idle in the =*//*= specified domain. It reads the CM_IDLEST_<DOMAIN> register to generate =*//*= the mask. Each Bit in the mask which is set to 1, specifies the =*//*= corresponding device is not idle. The function returns PRCM_FAIL if the =*//*= specified device does not have a corresponding IDLEST register. =*//*============================================================================*/int prcm_get_devices_not_idle(u32 domainid, u32 *result){ u32 valid; volatile u32 *addr; *result = 0x0; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_IDLEST); valid = get_val_bits(domainid, REG_IDLEST); if (!addr) return PRCM_FAIL; *result = (~(*addr & valid) & valid); return PRCM_PASS;}/*============================================================================*//*======================== INITIATORS NOT STANDBY ===========================*//*============================================================================*//*= This function returns a mask of initiators that are not in standby mode. =*//*= Each bit in the mask which is set to 1, specifies that the Standby is not=*//*= asserted for the corresponding initiator. The function returns PRCM_FAIL =*//*= if the specified device does not have a corresponding IDLEST register. =*//*============================================================================*/int prcm_get_initiators_not_standby(u32 domainid, u32 *result){ u32 valid; volatile u32 *addr; *result = 0x0; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_IDLEST); valid = get_val_bits(domainid, REG_IDLEST); if (!addr) return PRCM_FAIL; if (prcm_get_devices_not_idle(domainid, result) != PRCM_PASS) return PRCM_FAIL; switch (domainid) { case DOM_IVA2: *result &= IVA2_IMASK; break; case DOM_MPU: *result &= MPU_IMASK; break; case DOM_CORE1: *result &= CORE1_IMASK; break; case DOM_CORE2: *result &= CORE2_IMASK; break; case DOM_SGX: *result &= SGX_IMASK; break; case DOM_USBHOST: *result &= USBHOST_IMASK; break; case DOM_WKUP: *result &= WKUP_IMASK; break; case DOM_DSS: *result &= DSS_IMASK; break; case DOM_CAM: *result &= CAM_IMASK; break; case DOM_PER: *result &= PER_IMASK; break; case DOM_NEON: *result &= NEON_IMASK; break; default: break; } return PRCM_PASS;}/*============================================================================*//*======================== GET DOMAIN INTERFACE CLKS ========================*//*============================================================================*//*= This function returns the CM_ICLKEN_<domain> register value in result for=*//*= the specified domain. The function returns PRCM_FAIL if the ICLKEN =*//*= register is not available for the specified domain, else returns =*//*= PRCM_PASS. =*//*============================================================================*/int prcm_get_domain_interface_clocks(u32 domainid, u32 *result){ u32 valid; volatile u32 *addr; *result = 0x0; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_ICLKEN); valid = get_val_bits(domainid, REG_ICLKEN); if (!addr) return PRCM_FAIL; *result = *addr & valid; return PRCM_PASS;}/*============================================================================*//*======================== GET DOMAIN FUNCTIONAL CLKS =======================*//*============================================================================*//*= This function returns the CM_FCLKEN_<domain> register in the result for =*//*= the specified domain. The function returns PRCM_FAIL if the FCLKEN =*//* register is not available for the specified domain, else returns =*//*= PRCM_PASS. =*//*============================================================================*/int prcm_get_domain_functional_clocks(u32 domainid, u32 *result){ u32 valid; volatile u32 *addr; *result = 0x0; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_FCLKEN); valid = get_val_bits(domainid, REG_FCLKEN); if (!addr) return PRCM_FAIL; *result = *addr & valid; return PRCM_PASS;}/*============================================================================*//*======================== SET DOMAIN INTERFACE CLKS ========================*//*============================================================================*//*= This function sets CM_ICLKEN_<domain> register for the specified domain =*//*= with the mask specified in setmask. The function returns PRCM_FAIL if the=*//*= ICLKEN register is not available for the specified domain, else returns =*//*= PRCM_PASS. =*//*============================================================================*/int prcm_set_domain_interface_clocks(u32 domainid, u32 setmask){ u32 valid; volatile u32 *addr; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_ICLKEN); valid = get_val_bits(domainid, REG_ICLKEN); if (!addr) return PRCM_FAIL; *addr = setmask & valid; return PRCM_PASS;}/*============================================================================*//*======================== SET DOMAIN FUNCTIONAL CLKS =======================*//*============================================================================*//*= This function sets CM_FCLKEN_<domain> register for the specified domain =*//*= with the mask specified in setmask. The function returns PRCM_FAIL if the=*//*= FCLKEN register is not available for the specified domain, else returns =*//*= PRCM_PASS. =*//*============================================================================*/int prcm_set_domain_functional_clocks(u32 domainid, u32 setmask){ u32 valid; volatile u32 *addr; if (domainid > PRCM_NUM_DOMAINS) return PRCM_FAIL; addr = get_addr(domainid, REG_FCLKEN); valid = get_val_bits(domainid, REG_FCLKEN); if (!addr) return PRCM_FAIL; *addr = setmask & valid; return PRCM_PASS;}/*============================================================================*//*======================== GET OSC RATE =====================================*//*============================================================================*//*= This function returns the Current System clock speed in KHz. Fetches =*//*= values from PRM_CLKSEL[2:0]. Ranges from 12,13,19.2,26,38.4 MHz =*//*============================================================================*/int prcm_get_crystal_rate(void){ u32 osc_clkspeed; osc_clkspeed = PRM_CLKSEL & 0x
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -