2 * Clkout driver for Rockchip RK808
4 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
6 * Author:Chris Zhong <zyw@rock-chips.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 #include <linux/clk-provider.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/platform_device.h>
22 #include <linux/mfd/rk808.h>
23 #include <linux/i2c.h>
27 struct clk_hw clkout1_hw
;
28 struct clk_hw clkout2_hw
;
31 static unsigned long rk808_clkout_recalc_rate(struct clk_hw
*hw
,
32 unsigned long parent_rate
)
37 static int rk808_clkout2_enable(struct clk_hw
*hw
, bool enable
)
39 struct rk808_clkout
*rk808_clkout
= container_of(hw
,
42 struct rk808
*rk808
= rk808_clkout
->rk808
;
44 return regmap_update_bits(rk808
->regmap
, RK808_CLK32OUT_REG
,
45 CLK32KOUT2_EN
, enable
? CLK32KOUT2_EN
: 0);
48 static int rk808_clkout2_prepare(struct clk_hw
*hw
)
50 return rk808_clkout2_enable(hw
, true);
53 static void rk808_clkout2_unprepare(struct clk_hw
*hw
)
55 rk808_clkout2_enable(hw
, false);
58 static int rk808_clkout2_is_prepared(struct clk_hw
*hw
)
60 struct rk808_clkout
*rk808_clkout
= container_of(hw
,
63 struct rk808
*rk808
= rk808_clkout
->rk808
;
66 int ret
= regmap_read(rk808
->regmap
, RK808_CLK32OUT_REG
, &val
);
71 return (val
& CLK32KOUT2_EN
) ? 1 : 0;
74 static const struct clk_ops rk808_clkout1_ops
= {
75 .recalc_rate
= rk808_clkout_recalc_rate
,
78 static const struct clk_ops rk808_clkout2_ops
= {
79 .prepare
= rk808_clkout2_prepare
,
80 .unprepare
= rk808_clkout2_unprepare
,
81 .is_prepared
= rk808_clkout2_is_prepared
,
82 .recalc_rate
= rk808_clkout_recalc_rate
,
85 static struct clk_hw
*
86 of_clk_rk808_get(struct of_phandle_args
*clkspec
, void *data
)
88 struct rk808_clkout
*rk808_clkout
= data
;
89 unsigned int idx
= clkspec
->args
[0];
92 pr_err("%s: invalid index %u\n", __func__
, idx
);
93 return ERR_PTR(-EINVAL
);
96 return idx
? &rk808_clkout
->clkout2_hw
: &rk808_clkout
->clkout1_hw
;
99 static int rk808_clkout_probe(struct platform_device
*pdev
)
101 struct rk808
*rk808
= dev_get_drvdata(pdev
->dev
.parent
);
102 struct i2c_client
*client
= rk808
->i2c
;
103 struct device_node
*node
= client
->dev
.of_node
;
104 struct clk_init_data init
= {};
105 struct rk808_clkout
*rk808_clkout
;
108 rk808_clkout
= devm_kzalloc(&client
->dev
,
109 sizeof(*rk808_clkout
), GFP_KERNEL
);
113 rk808_clkout
->rk808
= rk808
;
115 init
.parent_names
= NULL
;
116 init
.num_parents
= 0;
117 init
.name
= "rk808-clkout1";
118 init
.ops
= &rk808_clkout1_ops
;
119 rk808_clkout
->clkout1_hw
.init
= &init
;
121 /* optional override of the clockname */
122 of_property_read_string_index(node
, "clock-output-names",
125 ret
= devm_clk_hw_register(&client
->dev
, &rk808_clkout
->clkout1_hw
);
129 init
.name
= "rk808-clkout2";
130 init
.ops
= &rk808_clkout2_ops
;
131 rk808_clkout
->clkout2_hw
.init
= &init
;
133 /* optional override of the clockname */
134 of_property_read_string_index(node
, "clock-output-names",
137 ret
= devm_clk_hw_register(&client
->dev
, &rk808_clkout
->clkout2_hw
);
141 return devm_of_clk_add_hw_provider(&pdev
->dev
, of_clk_rk808_get
,
145 static struct platform_driver rk808_clkout_driver
= {
146 .probe
= rk808_clkout_probe
,
148 .name
= "rk808-clkout",
152 module_platform_driver(rk808_clkout_driver
);
154 MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
155 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
156 MODULE_LICENSE("GPL");
157 MODULE_ALIAS("platform:rk808-clkout");