clk: tegra: add locking support to DFLL

Based on part of https://gitlab.com/nvidia/nv-tegra/linux-4.9/-/commit/4f0b1e6e76f7b0ff8d028c66d34da9f37ca39233
This commit is contained in:
tmakin committed 2026-10-06 01:09:56 -05:00
1 parent 9642e53c2c
commit bafa332c10
1 file changed
+25
+25
View File
@@ -359,6 +359,9 @@ struct tegra_dfll {
struct pinctrl_state *pwm_enable_state;
struct pinctrl_state *pwm_disable_state;
u32 reg_init_uV;
/* spinlock protecting register accesses */
spinlock_t lock;
};
#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -1106,6 +1109,7 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
{
int ret;
struct dfll_rate_req req;
unsigned long flags;
if (td->mode == DFLL_UNINITIALIZED) {
dev_err(td->dev, "%s: Cannot set DFLL rate in %s mode\n",
@@ -1121,8 +1125,10 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
td->last_req = req;
if (td->mode == DFLL_CLOSED_LOOP) {
spin_lock_irqsave(&td->lock, flags);
dfll_set_close_loop_config(td, &td->last_req);
dfll_set_frequency_request(td, &td->last_req);
spin_unlock_irqrestore(&td->lock, flags);
}
return 0;
@@ -1141,13 +1147,18 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
*/
static int dfll_disable(struct tegra_dfll *td)
{
unsigned long flags;
if (td->mode != DFLL_OPEN_LOOP) {
dev_err(td->dev, "cannot disable DFLL in %s mode\n",
mode_name[td->mode]);
return -EINVAL;
}
spin_lock_irqsave(&td->lock, flags);
dfll_set_mode(td, DFLL_DISABLED);
spin_unlock_irqrestore(&td->lock, flags);
pm_runtime_put_sync(td->dev);
return 0;
@@ -1211,6 +1222,7 @@ static void dfll_set_open_loop_config(struct tegra_dfll *td)
static int dfll_lock(struct tegra_dfll *td)
{
struct dfll_rate_req *req = &td->last_req;
unsigned long flags;
switch (td->mode) {
case DFLL_CLOSED_LOOP:
@@ -1228,10 +1240,12 @@ static int dfll_lock(struct tegra_dfll *td)
else
dfll_i2c_set_output_enabled(td, true);
spin_lock_irqsave(&td->lock, flags);
dfll_set_mode(td, DFLL_CLOSED_LOOP);
dfll_set_close_loop_config(td, req);
dfll_set_frequency_request(td, req);
dfll_set_force_output_enabled(td, false);
spin_unlock_irqrestore(&td->lock, flags);
return 0;
default:
@@ -1251,14 +1265,19 @@ static int dfll_lock(struct tegra_dfll *td)
*/
static int dfll_unlock(struct tegra_dfll *td)
{
unsigned long flags;
switch (td->mode) {
case DFLL_CLOSED_LOOP:
spin_lock_irqsave(&td->lock, flags);
dfll_set_open_loop_config(td);
dfll_set_mode(td, DFLL_OPEN_LOOP);
if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
dfll_pwm_set_output_enabled(td, false);
else
dfll_i2c_set_output_enabled(td, false);
spin_unlock_irqrestore(&td->lock, flags);
return 0;
case DFLL_OPEN_LOOP:
@@ -1521,8 +1540,10 @@ static int attr_registers_show(struct seq_file *s, void *data)
{
u32 val, offs;
struct tegra_dfll *td = s->private;
unsigned long flags;
seq_puts(s, "CONTROL REGISTERS:\n");
spin_lock_irqsave(&td->lock, flags);
for (offs = 0; offs <= DFLL_MONITOR_DATA; offs += 4) {
if (offs == DFLL_OUTPUT_CFG)
val = dfll_i2c_readl(td, offs);
@@ -1551,6 +1572,8 @@ static int attr_registers_show(struct seq_file *s, void *data)
__raw_readl(td->lut_base + offs));
}
spin_unlock_irqrestore(&td->lock, flags);
return 0;
}
@@ -2292,6 +2315,8 @@ int tegra_dfll_register(struct platform_device *pdev,
if (ret)
return ret;
spin_lock_init(&td->lock);
ret = dfll_register_clk(td);
if (ret) {
dev_err(&pdev->dev, "DFLL clk registration failed\n");