2 * Copyright (C) 2016 Socionext Inc.
3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/clk-provider.h>
17 #include <linux/device.h>
18 #include <linux/regmap.h>
20 #include "clk-uniphier.h"
22 struct uniphier_clk_gate
{
24 struct regmap
*regmap
;
29 #define to_uniphier_clk_gate(_hw) \
30 container_of(_hw, struct uniphier_clk_gate, hw)
32 static int uniphier_clk_gate_endisable(struct clk_hw
*hw
, int enable
)
34 struct uniphier_clk_gate
*gate
= to_uniphier_clk_gate(hw
);
36 return regmap_write_bits(gate
->regmap
, gate
->reg
, BIT(gate
->bit
),
37 enable
? BIT(gate
->bit
) : 0);
40 static int uniphier_clk_gate_enable(struct clk_hw
*hw
)
42 return uniphier_clk_gate_endisable(hw
, 1);
45 static void uniphier_clk_gate_disable(struct clk_hw
*hw
)
47 if (uniphier_clk_gate_endisable(hw
, 0) < 0)
48 pr_warn("failed to disable clk\n");
51 static int uniphier_clk_gate_is_enabled(struct clk_hw
*hw
)
53 struct uniphier_clk_gate
*gate
= to_uniphier_clk_gate(hw
);
56 if (regmap_read(gate
->regmap
, gate
->reg
, &val
) < 0)
57 pr_warn("is_enabled() may return wrong result\n");
59 return !!(val
& BIT(gate
->bit
));
62 static const struct clk_ops uniphier_clk_gate_ops
= {
63 .enable
= uniphier_clk_gate_enable
,
64 .disable
= uniphier_clk_gate_disable
,
65 .is_enabled
= uniphier_clk_gate_is_enabled
,
68 struct clk_hw
*uniphier_clk_register_gate(struct device
*dev
,
69 struct regmap
*regmap
,
71 const struct uniphier_clk_gate_data
*data
)
73 struct uniphier_clk_gate
*gate
;
74 struct clk_init_data init
;
77 gate
= devm_kzalloc(dev
, sizeof(*gate
), GFP_KERNEL
);
79 return ERR_PTR(-ENOMEM
);
82 init
.ops
= &uniphier_clk_gate_ops
;
83 init
.flags
= data
->parent_name
? CLK_SET_RATE_PARENT
: 0;
84 init
.parent_names
= data
->parent_name
? &data
->parent_name
: NULL
;
85 init
.num_parents
= data
->parent_name
? 1 : 0;
87 gate
->regmap
= regmap
;
88 gate
->reg
= data
->reg
;
89 gate
->bit
= data
->bit
;
90 gate
->hw
.init
= &init
;
92 ret
= devm_clk_hw_register(dev
, &gate
->hw
);