Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/drivers/clk/imx/clk-gate2.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Copyright (C) 2019 DENX Software Engineering
4
 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
5
 *
6
 * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
7
 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License version 2 as
11
 * published by the Free Software Foundation.
12
 *
13
 * Gated clock implementation
14
 *
15
 */
16
17
#include <asm/io.h>
18
#include <malloc.h>
19
#include <clk-uclass.h>
20
#include <dm/device.h>
21
#include <dm/devres.h>
22
#include <linux/bug.h>
23
#include <linux/clk-provider.h>
24
#include <clk.h>
25
#include "clk.h"
26
#include <linux/err.h>
27
28
0
#define UBOOT_DM_CLK_IMX_GATE2 "imx_clk_gate2"
29
30
struct clk_gate2 {
31
  struct clk clk;
32
  void __iomem  *reg;
33
  u8    bit_idx;
34
  u8    cgr_val;
35
  u8    flags;
36
  unsigned int  *share_count;
37
};
38
39
0
#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk)
40
41
static int clk_gate2_enable(struct clk *clk)
42
0
{
43
0
  struct clk_gate2 *gate = to_clk_gate2(clk);
44
0
  u32 reg;
45
46
0
  if (gate->share_count && (*gate->share_count)++ > 0)
47
0
    return 0;
48
49
0
  reg = readl(gate->reg);
50
0
  reg &= ~(3 << gate->bit_idx);
51
0
  reg |= gate->cgr_val << gate->bit_idx;
52
0
  writel(reg, gate->reg);
53
54
0
  return 0;
55
0
}
56
57
static int clk_gate2_disable(struct clk *clk)
58
0
{
59
0
  struct clk_gate2 *gate = to_clk_gate2(clk);
60
0
  u32 reg;
61
62
0
  if (gate->share_count) {
63
0
    if (WARN_ON(*gate->share_count == 0))
64
0
      return 0;
65
0
    else if (--(*gate->share_count) > 0)
66
0
      return 0;
67
0
  }
68
69
0
  reg = readl(gate->reg);
70
0
  reg &= ~(3 << gate->bit_idx);
71
0
  writel(reg, gate->reg);
72
73
0
  return 0;
74
0
}
75
76
static ulong clk_gate2_set_rate(struct clk *clk, ulong rate)
77
0
{
78
0
  struct clk *parent = clk_get_parent(clk);
79
80
0
  if (parent)
81
0
    return clk_set_rate(parent, rate);
82
83
0
  return -ENODEV;
84
0
}
85
86
static const struct clk_ops clk_gate2_ops = {
87
  .set_rate = clk_gate2_set_rate,
88
  .enable = clk_gate2_enable,
89
  .disable = clk_gate2_disable,
90
  .get_rate = clk_generic_get_rate,
91
};
92
93
struct clk *clk_register_gate2(struct udevice *dev, const char *name,
94
    const char *parent_name, unsigned long flags,
95
    void __iomem *reg, u8 bit_idx, u8 cgr_val,
96
    u8 clk_gate2_flags, unsigned int *share_count)
97
0
{
98
0
  struct clk_gate2 *gate;
99
0
  struct clk *clk;
100
0
  int ret;
101
102
0
  gate = kzalloc(sizeof(*gate), GFP_KERNEL);
103
0
  if (!gate)
104
0
    return ERR_PTR(-ENOMEM);
105
106
0
  gate->reg = reg;
107
0
  gate->bit_idx = bit_idx;
108
0
  gate->cgr_val = cgr_val;
109
0
  gate->flags = clk_gate2_flags;
110
0
  gate->share_count = share_count;
111
112
0
  clk = &gate->clk;
113
114
0
  ret = clk_register(clk, UBOOT_DM_CLK_IMX_GATE2, name,
115
0
    clk_resolve_parent_clk(dev, parent_name));
116
0
  if (ret) {
117
0
    kfree(gate);
118
0
    return ERR_PTR(ret);
119
0
  }
120
121
0
  return clk;
122
0
}
123
124
U_BOOT_DRIVER(clk_gate2) = {
125
  .name = UBOOT_DM_CLK_IMX_GATE2,
126
  .id = UCLASS_CLK,
127
  .ops  = &clk_gate2_ops,
128
  .flags = DM_FLAG_PRE_RELOC,
129
};