Commit 88fa34df9f2cbfe326cfbdf5e6470d7d682f0221

Authored by Patrick Delaunay
Committed by Tom Rini
1 parent 6110503f8f

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) = {