Commit 88fa34df9f2cbfe326cfbdf5e6470d7d682f0221
Committed by
Tom Rini
1 parent
6110503f8f
Exists in
smarc_8mq_lf_v2020.04
and in
11 other branches
stm32mp1: clk: add LDTC and DSI clock support
This patch add clk_enable/clk_disable/clk_get_rate support for - DSI_PX - LTDC_PX - DSI_K (only get rate) These clocks are needed for LTDC and DSI drivers with latest device tree. Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Showing 1 changed file with 93 additions and 3 deletions Side-by-side Diff
drivers/clk/clk_stm32mp1.c
... | ... | @@ -98,6 +98,7 @@ |
98 | 98 | #define RCC_QSPICKSELR 0x900 |
99 | 99 | #define RCC_FMCCKSELR 0x904 |
100 | 100 | #define RCC_USBCKSELR 0x91C |
101 | +#define RCC_DSICKSELR 0x924 | |
101 | 102 | #define RCC_MP_APB1ENSETR 0xA00 |
102 | 103 | #define RCC_MP_APB2ENSETR 0XA08 |
103 | 104 | #define RCC_MP_APB3ENSETR 0xA10 |
... | ... | @@ -267,6 +268,7 @@ |
267 | 268 | _CK_PER, |
268 | 269 | _CK_MPU, |
269 | 270 | _CK_MCU, |
271 | + _DSI_PHY, | |
270 | 272 | _PARENT_NB, |
271 | 273 | _UNKNOWN_ID = 0xff, |
272 | 274 | }; |
... | ... | @@ -287,6 +289,7 @@ |
287 | 289 | _USBPHY_SEL, |
288 | 290 | _USBO_SEL, |
289 | 291 | _STGEN_SEL, |
292 | + _DSI_SEL, | |
290 | 293 | _PARENT_SEL_NB, |
291 | 294 | _UNKNOWN_SEL = 0xff, |
292 | 295 | }; |
... | ... | @@ -512,6 +515,9 @@ |
512 | 515 | |
513 | 516 | STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3), |
514 | 517 | |
518 | + STM32MP1_CLK_SET_CLR_F(RCC_MP_APB4ENSETR, 0, LTDC_PX, _PLL4_Q), | |
519 | + STM32MP1_CLK_SET_CLR_F(RCC_MP_APB4ENSETR, 4, DSI_PX, _PLL4_Q), | |
520 | + STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 4, DSI_K, _DSI_SEL), | |
515 | 521 | STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), |
516 | 522 | STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), |
517 | 523 | STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), |
... | ... | @@ -569,6 +575,7 @@ |
569 | 575 | static const u8 usbphy_parents[] = {_HSE_KER, _PLL4_R, _HSE_KER_DIV2}; |
570 | 576 | static const u8 usbo_parents[] = {_PLL4_R, _USB_PHY_48}; |
571 | 577 | static const u8 stgen_parents[] = {_HSI_KER, _HSE_KER}; |
578 | +static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P}; | |
572 | 579 | |
573 | 580 | static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { |
574 | 581 | STM32MP1_CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents), |
... | ... | @@ -591,6 +598,7 @@ |
591 | 598 | STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), |
592 | 599 | STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), |
593 | 600 | STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), |
601 | + STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents), | |
594 | 602 | }; |
595 | 603 | |
596 | 604 | #ifdef STM32MP1_CLOCK_TREE_INIT |
... | ... | @@ -682,7 +690,8 @@ |
682 | 690 | [_CK_PER] = "CK_PER", |
683 | 691 | [_CK_MPU] = "CK_MPU", |
684 | 692 | [_CK_MCU] = "CK_MCU", |
685 | - [_USB_PHY_48] = "USB_PHY_48" | |
693 | + [_USB_PHY_48] = "USB_PHY_48", | |
694 | + [_DSI_PHY] = "DSI_PHY_PLL", | |
686 | 695 | }; |
687 | 696 | |
688 | 697 | static const char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { |
... | ... | @@ -700,7 +709,8 @@ |
700 | 709 | [_FMC_SEL] = "FMC", |
701 | 710 | [_USBPHY_SEL] = "USBPHY", |
702 | 711 | [_USBO_SEL] = "USBO", |
703 | - [_STGEN_SEL] = "STGEN" | |
712 | + [_STGEN_SEL] = "STGEN", | |
713 | + [_DSI_SEL] = "DSI", | |
704 | 714 | }; |
705 | 715 | #endif |
706 | 716 | |
707 | 717 | |
... | ... | @@ -1060,7 +1070,22 @@ |
1060 | 1070 | case _USB_PHY_48: |
1061 | 1071 | clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48); |
1062 | 1072 | break; |
1073 | + case _DSI_PHY: | |
1074 | + { | |
1075 | + struct clk clk; | |
1076 | + struct udevice *dev = NULL; | |
1063 | 1077 | |
1078 | + if (!uclass_get_device_by_name(UCLASS_CLK, "ck_dsi_phy", | |
1079 | + &dev)) { | |
1080 | + if (clk_request(dev, &clk)) { | |
1081 | + pr_err("ck_dsi_phy request"); | |
1082 | + } else { | |
1083 | + clk.id = 0; | |
1084 | + clock = clk_get_rate(&clk); | |
1085 | + } | |
1086 | + } | |
1087 | + break; | |
1088 | + } | |
1064 | 1089 | default: |
1065 | 1090 | break; |
1066 | 1091 | } |
... | ... | @@ -1723,6 +1748,70 @@ |
1723 | 1748 | } |
1724 | 1749 | #endif /* STM32MP1_CLOCK_TREE_INIT */ |
1725 | 1750 | |
1751 | +static int pll_set_output_rate(struct udevice *dev, | |
1752 | + int pll_id, | |
1753 | + int div_id, | |
1754 | + unsigned long clk_rate) | |
1755 | +{ | |
1756 | + struct stm32mp1_clk_priv *priv = dev_get_priv(dev); | |
1757 | + const struct stm32mp1_clk_pll *pll = priv->data->pll; | |
1758 | + u32 pllxcr = priv->base + pll[pll_id].pllxcr; | |
1759 | + int div; | |
1760 | + ulong fvco; | |
1761 | + | |
1762 | + if (div_id > _DIV_NB) | |
1763 | + return -EINVAL; | |
1764 | + | |
1765 | + fvco = pll_get_fvco(priv, pll_id); | |
1766 | + | |
1767 | + if (fvco <= clk_rate) | |
1768 | + div = 1; | |
1769 | + else | |
1770 | + div = DIV_ROUND_UP(fvco, clk_rate); | |
1771 | + | |
1772 | + if (div > 128) | |
1773 | + div = 128; | |
1774 | + | |
1775 | + debug("fvco = %ld, clk_rate = %ld, div=%d\n", fvco, clk_rate, div); | |
1776 | + /* stop the requested output */ | |
1777 | + clrbits_le32(pllxcr, 0x1 << div_id << RCC_PLLNCR_DIVEN_SHIFT); | |
1778 | + /* change divider */ | |
1779 | + clrsetbits_le32(priv->base + pll[pll_id].pllxcfgr2, | |
1780 | + RCC_PLLNCFGR2_DIVX_MASK << RCC_PLLNCFGR2_SHIFT(div_id), | |
1781 | + (div - 1) << RCC_PLLNCFGR2_SHIFT(div_id)); | |
1782 | + /* start the requested output */ | |
1783 | + setbits_le32(pllxcr, 0x1 << div_id << RCC_PLLNCR_DIVEN_SHIFT); | |
1784 | + | |
1785 | + return 0; | |
1786 | +} | |
1787 | + | |
1788 | +static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate) | |
1789 | +{ | |
1790 | + struct stm32mp1_clk_priv *priv = dev_get_priv(clk->dev); | |
1791 | + int p; | |
1792 | + | |
1793 | + switch (clk->id) { | |
1794 | + case LTDC_PX: | |
1795 | + case DSI_PX: | |
1796 | + break; | |
1797 | + default: | |
1798 | + pr_err("not supported"); | |
1799 | + return -EINVAL; | |
1800 | + } | |
1801 | + | |
1802 | + p = stm32mp1_clk_get_parent(priv, clk->id); | |
1803 | + if (p < 0) | |
1804 | + return -EINVAL; | |
1805 | + | |
1806 | + switch (p) { | |
1807 | + case _PLL4_Q: | |
1808 | + /* for LTDC_PX and DSI_PX case */ | |
1809 | + return pll_set_output_rate(clk->dev, _PLL4, _DIV_Q, clk_rate); | |
1810 | + } | |
1811 | + | |
1812 | + return -EINVAL; | |
1813 | +} | |
1814 | + | |
1726 | 1815 | static void stm32mp1_osc_clk_init(const char *name, |
1727 | 1816 | struct stm32mp1_clk_priv *priv, |
1728 | 1817 | int index) |
... | ... | @@ -1790,6 +1879,7 @@ |
1790 | 1879 | .enable = stm32mp1_clk_enable, |
1791 | 1880 | .disable = stm32mp1_clk_disable, |
1792 | 1881 | .get_rate = stm32mp1_clk_get_rate, |
1882 | + .set_rate = stm32mp1_clk_set_rate, | |
1793 | 1883 | }; |
1794 | 1884 | |
1795 | 1885 | U_BOOT_DRIVER(stm32mp1_clock) = { |