2 * Copyright (C) 2013 Freescale Semiconductor, Inc.
4 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License
6 * Version 2 or later at the following locations:
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
12 #include <linux/clk-provider.h>
13 #include <linux/err.h>
15 #include <linux/slab.h>
19 * struct clk_fixup_mux - imx integer fixup multiplexer clock
20 * @mux: the parent class
21 * @ops: pointer to clk_ops of parent class
22 * @fixup: a hook to fixup the write value
24 * The imx fixup multiplexer clock is a subclass of basic clk_mux
25 * with an addtional fixup hook.
27 struct clk_fixup_mux
{
29 const struct clk_ops
*ops
;
30 void (*fixup
)(u32
*val
);
33 static inline struct clk_fixup_mux
*to_clk_fixup_mux(struct clk_hw
*hw
)
35 struct clk_mux
*mux
= to_clk_mux(hw
);
37 return container_of(mux
, struct clk_fixup_mux
, mux
);
40 static u8
clk_fixup_mux_get_parent(struct clk_hw
*hw
)
42 struct clk_fixup_mux
*fixup_mux
= to_clk_fixup_mux(hw
);
44 return fixup_mux
->ops
->get_parent(&fixup_mux
->mux
.hw
);
47 static int clk_fixup_mux_set_parent(struct clk_hw
*hw
, u8 index
)
49 struct clk_fixup_mux
*fixup_mux
= to_clk_fixup_mux(hw
);
50 struct clk_mux
*mux
= to_clk_mux(hw
);
51 unsigned long flags
= 0;
54 spin_lock_irqsave(mux
->lock
, flags
);
56 val
= readl(mux
->reg
);
57 val
&= ~(mux
->mask
<< mux
->shift
);
58 val
|= index
<< mux
->shift
;
59 fixup_mux
->fixup(&val
);
60 writel(val
, mux
->reg
);
62 spin_unlock_irqrestore(mux
->lock
, flags
);
67 static const struct clk_ops clk_fixup_mux_ops
= {
68 .get_parent
= clk_fixup_mux_get_parent
,
69 .set_parent
= clk_fixup_mux_set_parent
,
72 struct clk
*imx_clk_fixup_mux(const char *name
, void __iomem
*reg
,
73 u8 shift
, u8 width
, const char **parents
,
74 int num_parents
, void (*fixup
)(u32
*val
))
76 struct clk_fixup_mux
*fixup_mux
;
78 struct clk_init_data init
;
81 return ERR_PTR(-EINVAL
);
83 fixup_mux
= kzalloc(sizeof(*fixup_mux
), GFP_KERNEL
);
85 return ERR_PTR(-ENOMEM
);
88 init
.ops
= &clk_fixup_mux_ops
;
89 init
.parent_names
= parents
;
90 init
.num_parents
= num_parents
;
93 fixup_mux
->mux
.reg
= reg
;
94 fixup_mux
->mux
.shift
= shift
;
95 fixup_mux
->mux
.mask
= BIT(width
) - 1;
96 fixup_mux
->mux
.lock
= &imx_ccm_lock
;
97 fixup_mux
->mux
.hw
.init
= &init
;
98 fixup_mux
->ops
= &clk_mux_ops
;
99 fixup_mux
->fixup
= fixup
;
101 clk
= clk_register(NULL
, &fixup_mux
->mux
.hw
);