1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
7 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/platform_device.h>
12 #include <linux/sched.h>
17 struct dss_video_pll
{
22 void __iomem
*clkctrl_base
;
25 #define REG_MOD(reg, val, start, end) \
26 writel_relaxed(FLD_MOD(readl_relaxed(reg), val, start, end), reg)
28 static void dss_dpll_enable_scp_clk(struct dss_video_pll
*vpll
)
30 REG_MOD(vpll
->clkctrl_base
, 1, 14, 14); /* CIO_CLK_ICG */
33 static void dss_dpll_disable_scp_clk(struct dss_video_pll
*vpll
)
35 REG_MOD(vpll
->clkctrl_base
, 0, 14, 14); /* CIO_CLK_ICG */
38 static void dss_dpll_power_enable(struct dss_video_pll
*vpll
)
40 REG_MOD(vpll
->clkctrl_base
, 2, 31, 30); /* PLL_POWER_ON_ALL */
43 * DRA7x PLL CTRL's PLL_PWR_STATUS seems to always return 0,
44 * so we have to use fixed delay here.
49 static void dss_dpll_power_disable(struct dss_video_pll
*vpll
)
51 REG_MOD(vpll
->clkctrl_base
, 0, 31, 30); /* PLL_POWER_OFF */
54 static int dss_video_pll_enable(struct dss_pll
*pll
)
56 struct dss_video_pll
*vpll
= container_of(pll
, struct dss_video_pll
, pll
);
59 r
= dss_runtime_get(pll
->dss
);
63 dss_ctrl_pll_enable(pll
, true);
65 dss_dpll_enable_scp_clk(vpll
);
67 r
= dss_pll_wait_reset_done(pll
);
71 dss_dpll_power_enable(vpll
);
76 dss_dpll_disable_scp_clk(vpll
);
77 dss_ctrl_pll_enable(pll
, false);
78 dss_runtime_put(pll
->dss
);
83 static void dss_video_pll_disable(struct dss_pll
*pll
)
85 struct dss_video_pll
*vpll
= container_of(pll
, struct dss_video_pll
, pll
);
87 dss_dpll_power_disable(vpll
);
89 dss_dpll_disable_scp_clk(vpll
);
91 dss_ctrl_pll_enable(pll
, false);
93 dss_runtime_put(pll
->dss
);
96 static const struct dss_pll_ops dss_pll_ops
= {
97 .enable
= dss_video_pll_enable
,
98 .disable
= dss_video_pll_disable
,
99 .set_config
= dss_pll_write_config_type_a
,
102 static const struct dss_pll_hw dss_dra7_video_pll_hw
= {
103 .type
= DSS_PLL_TYPE_A
,
105 .n_max
= (1 << 8) - 1,
106 .m_max
= (1 << 12) - 1,
107 .mX_max
= (1 << 5) - 1,
110 .clkdco_max
= 1800000000,
132 struct dss_pll
*dss_video_pll_init(struct dss_device
*dss
,
133 struct platform_device
*pdev
, int id
,
134 struct regulator
*regulator
)
136 const char * const reg_name
[] = { "pll1", "pll2" };
137 const char * const clkctrl_name
[] = { "pll1_clkctrl", "pll2_clkctrl" };
138 const char * const clkin_name
[] = { "video1_clk", "video2_clk" };
140 struct resource
*res
;
141 struct dss_video_pll
*vpll
;
142 void __iomem
*pll_base
, *clkctrl_base
;
149 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, reg_name
[id
]);
150 pll_base
= devm_ioremap_resource(&pdev
->dev
, res
);
151 if (IS_ERR(pll_base
))
152 return ERR_CAST(pll_base
);
156 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
158 clkctrl_base
= devm_ioremap_resource(&pdev
->dev
, res
);
159 if (IS_ERR(clkctrl_base
))
160 return ERR_CAST(clkctrl_base
);
164 clk
= devm_clk_get(&pdev
->dev
, clkin_name
[id
]);
166 DSSERR("can't get video pll clkin\n");
167 return ERR_CAST(clk
);
170 vpll
= devm_kzalloc(&pdev
->dev
, sizeof(*vpll
), GFP_KERNEL
);
172 return ERR_PTR(-ENOMEM
);
174 vpll
->dev
= &pdev
->dev
;
175 vpll
->clkctrl_base
= clkctrl_base
;
179 pll
->name
= id
== 0 ? "video0" : "video1";
180 pll
->id
= id
== 0 ? DSS_PLL_VIDEO1
: DSS_PLL_VIDEO2
;
182 pll
->regulator
= regulator
;
183 pll
->base
= pll_base
;
184 pll
->hw
= &dss_dra7_video_pll_hw
;
185 pll
->ops
= &dss_pll_ops
;
187 r
= dss_pll_register(dss
, pll
);
194 void dss_video_pll_uninit(struct dss_pll
*pll
)
196 dss_pll_unregister(pll
);