mfd: rkx110_x120: cru: fix to get a avialble pll rate

In some case, the pll rate will be change to get a target
rate for it's child. we want set the pll rate closest to
the max pll rate. However, It's not all the rate can get
a set of legal paramters to config the pll. So when this
case happen, we try a lower rate as the target pll rate.

Change-Id: I45abec2114f74634904cf3c34655d8df331d171b
Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
This commit is contained in:
Zhang Yubing
2023-12-06 11:17:27 +08:00
committed by Tao Huang
parent 801e11b222
commit eaa1941ab7
4 changed files with 64 additions and 24 deletions

View File

@@ -263,6 +263,7 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax = 0;
HAL_Status ret = HAL_OK;
int i;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN ||
clockName == RKX110_CLK_D_DSI_1_PATTERN_GEN) {
@@ -326,12 +327,21 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -304,6 +304,7 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax = 0;
HAL_Status ret = HAL_OK;
int i;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN) {
clockName = RKX111_CPS_DCLK_D_DSI_0_REC;
@@ -371,12 +372,21 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -252,6 +252,7 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax;
HAL_Status ret = HAL_OK;
int i;
switch (clockName) {
case RKX120_CPS_PLL_TXPLL:
@@ -298,12 +299,21 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */

View File

@@ -263,6 +263,7 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
uint32_t pll;
uint8_t overMax;
HAL_Status ret = HAL_OK;
int i;
switch (clockName) {
case RKX120_CPS_PLL_TXPLL:
@@ -309,12 +310,21 @@ static HAL_Status RKX12x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
pRate = (_MHZ(1200) / rate) * rate;
}
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX12x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */