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_mux
{
24 struct regmap
*regmap
;
26 const unsigned int *masks
;
27 const unsigned int *vals
;
30 #define to_uniphier_clk_mux(_hw) container_of(_hw, struct uniphier_clk_mux, hw)
32 static int uniphier_clk_mux_set_parent(struct clk_hw
*hw
, u8 index
)
34 struct uniphier_clk_mux
*mux
= to_uniphier_clk_mux(hw
);
36 return regmap_write_bits(mux
->regmap
, mux
->reg
, mux
->masks
[index
],
40 static u8
uniphier_clk_mux_get_parent(struct clk_hw
*hw
)
42 struct uniphier_clk_mux
*mux
= to_uniphier_clk_mux(hw
);
43 int num_parents
= clk_hw_get_num_parents(hw
);
48 ret
= regmap_read(mux
->regmap
, mux
->reg
, &val
);
52 for (i
= 0; i
< num_parents
; i
++)
53 if ((mux
->masks
[i
] & val
) == mux
->vals
[i
])
59 static const struct clk_ops uniphier_clk_mux_ops
= {
60 .determine_rate
= __clk_mux_determine_rate
,
61 .set_parent
= uniphier_clk_mux_set_parent
,
62 .get_parent
= uniphier_clk_mux_get_parent
,
65 struct clk_hw
*uniphier_clk_register_mux(struct device
*dev
,
66 struct regmap
*regmap
,
68 const struct uniphier_clk_mux_data
*data
)
70 struct uniphier_clk_mux
*mux
;
71 struct clk_init_data init
;
74 mux
= devm_kzalloc(dev
, sizeof(*mux
), GFP_KERNEL
);
76 return ERR_PTR(-ENOMEM
);
79 init
.ops
= &uniphier_clk_mux_ops
;
80 init
.flags
= CLK_SET_RATE_PARENT
;
81 init
.parent_names
= data
->parent_names
;
82 init
.num_parents
= data
->num_parents
,
86 mux
->masks
= data
->masks
;
87 mux
->vals
= data
->vals
;
90 ret
= devm_clk_hw_register(dev
, &mux
->hw
);