| From foo@baz Thu May 24 11:23:00 CEST 2018 |
| From: Shawn Lin <shawn.lin@rock-chips.com> |
| Date: Mon, 5 Mar 2018 11:25:58 +0800 |
| Subject: clk: rockchip: Prevent calculating mmc phase if clock rate is zero |
| |
| From: Shawn Lin <shawn.lin@rock-chips.com> |
| |
| [ Upstream commit 4bf59902b50012b1dddeeaa23b217d9c4956cdda ] |
| |
| The MMC sample and drv clock for rockchip platforms are derived from |
| the bus clock output to the MMC/SDIO card. So it should never happens |
| that the clk rate is zero given it should inherits the clock rate from |
| its parent. If something goes wrong and makes the clock rate to be zero, |
| the calculation would be wrong but may still make the mmc tuning process |
| work luckily. However it makes people harder to debug when the following |
| data transfer is unstable. |
| |
| Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> |
| Signed-off-by: Heiko Stuebner <heiko@sntech.de> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/clk/rockchip/clk-mmc-phase.c | 23 +++++++++++++++++++++++ |
| 1 file changed, 23 insertions(+) |
| |
| --- a/drivers/clk/rockchip/clk-mmc-phase.c |
| +++ b/drivers/clk/rockchip/clk-mmc-phase.c |
| @@ -58,6 +58,12 @@ static int rockchip_mmc_get_phase(struct |
| u16 degrees; |
| u32 delay_num = 0; |
| |
| + /* See the comment for rockchip_mmc_set_phase below */ |
| + if (!rate) { |
| + pr_err("%s: invalid clk rate\n", __func__); |
| + return -EINVAL; |
| + } |
| + |
| raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift); |
| |
| degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; |
| @@ -84,6 +90,23 @@ static int rockchip_mmc_set_phase(struct |
| u32 raw_value; |
| u32 delay; |
| |
| + /* |
| + * The below calculation is based on the output clock from |
| + * MMC host to the card, which expects the phase clock inherits |
| + * the clock rate from its parent, namely the output clock |
| + * provider of MMC host. However, things may go wrong if |
| + * (1) It is orphan. |
| + * (2) It is assigned to the wrong parent. |
| + * |
| + * This check help debug the case (1), which seems to be the |
| + * most likely problem we often face and which makes it difficult |
| + * for people to debug unstable mmc tuning results. |
| + */ |
| + if (!rate) { |
| + pr_err("%s: invalid clk rate\n", __func__); |
| + return -EINVAL; |
| + } |
| + |
| nineties = degrees / 90; |
| remainder = (degrees % 90); |
| |