2 * Copyright (c) 2015 Linaro Ltd.
3 * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/clk-provider.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/slab.h>
20 #include "clk-cpumux.h"
22 static inline struct mtk_clk_cpumux
*to_mtk_clk_cpumux(struct clk_hw
*_hw
)
24 return container_of(_hw
, struct mtk_clk_cpumux
, hw
);
27 static u8
clk_cpumux_get_parent(struct clk_hw
*hw
)
29 struct mtk_clk_cpumux
*mux
= to_mtk_clk_cpumux(hw
);
30 int num_parents
= clk_hw_get_num_parents(hw
);
33 regmap_read(mux
->regmap
, mux
->reg
, &val
);
38 if (val
>= num_parents
)
44 static int clk_cpumux_set_parent(struct clk_hw
*hw
, u8 index
)
46 struct mtk_clk_cpumux
*mux
= to_mtk_clk_cpumux(hw
);
49 val
= index
<< mux
->shift
;
50 mask
= mux
->mask
<< mux
->shift
;
52 return regmap_update_bits(mux
->regmap
, mux
->reg
, mask
, val
);
55 static const struct clk_ops clk_cpumux_ops
= {
56 .get_parent
= clk_cpumux_get_parent
,
57 .set_parent
= clk_cpumux_set_parent
,
60 static struct clk __init
*
61 mtk_clk_register_cpumux(const struct mtk_composite
*mux
,
62 struct regmap
*regmap
)
64 struct mtk_clk_cpumux
*cpumux
;
66 struct clk_init_data init
;
68 cpumux
= kzalloc(sizeof(*cpumux
), GFP_KERNEL
);
70 return ERR_PTR(-ENOMEM
);
72 init
.name
= mux
->name
;
73 init
.ops
= &clk_cpumux_ops
;
74 init
.parent_names
= mux
->parent_names
;
75 init
.num_parents
= mux
->num_parents
;
76 init
.flags
= mux
->flags
;
78 cpumux
->reg
= mux
->mux_reg
;
79 cpumux
->shift
= mux
->mux_shift
;
80 cpumux
->mask
= BIT(mux
->mux_width
) - 1;
81 cpumux
->regmap
= regmap
;
82 cpumux
->hw
.init
= &init
;
84 clk
= clk_register(NULL
, &cpumux
->hw
);
91 int __init
mtk_clk_register_cpumuxes(struct device_node
*node
,
92 const struct mtk_composite
*clks
, int num
,
93 struct clk_onecell_data
*clk_data
)
97 struct regmap
*regmap
;
99 regmap
= syscon_node_to_regmap(node
);
100 if (IS_ERR(regmap
)) {
101 pr_err("Cannot find regmap for %s: %ld\n", node
->full_name
,
103 return PTR_ERR(regmap
);
106 for (i
= 0; i
< num
; i
++) {
107 const struct mtk_composite
*mux
= &clks
[i
];
109 clk
= mtk_clk_register_cpumux(mux
, regmap
);
111 pr_err("Failed to register clk %s: %ld\n",
112 mux
->name
, PTR_ERR(clk
));
116 clk_data
->clks
[mux
->id
] = clk
;