]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
94885faf GF |
2 | /* |
3 | * clkgen-mux.c: ST GEN-MUX Clock driver | |
4 | * | |
5 | * Copyright (C) 2014 STMicroelectronics (R&D) Limited | |
6 | * | |
7 | * Authors: Stephen Gallimore <stephen.gallimore@st.com> | |
8 | * Pankaj Dev <pankaj.dev@st.com> | |
94885faf GF |
9 | */ |
10 | ||
11 | #include <linux/slab.h> | |
62e59c4e | 12 | #include <linux/io.h> |
94885faf | 13 | #include <linux/of_address.h> |
d5f728ac | 14 | #include <linux/clk.h> |
94885faf | 15 | #include <linux/clk-provider.h> |
46a57afd | 16 | #include "clkgen.h" |
94885faf | 17 | |
94885faf GF |
18 | static const char ** __init clkgen_mux_get_parents(struct device_node *np, |
19 | int *num_parents) | |
20 | { | |
21 | const char **parents; | |
caeb057c | 22 | unsigned int nparents; |
94885faf | 23 | |
0a65239c | 24 | nparents = of_clk_get_parent_count(np); |
caeb057c | 25 | if (WARN_ON(!nparents)) |
94885faf GF |
26 | return ERR_PTR(-EINVAL); |
27 | ||
86665d28 | 28 | parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL); |
94885faf GF |
29 | if (!parents) |
30 | return ERR_PTR(-ENOMEM); | |
31 | ||
0b4e7f08 | 32 | *num_parents = of_clk_parent_fill(np, parents, nparents); |
94885faf GF |
33 | return parents; |
34 | } | |
35 | ||
44993d38 GF |
36 | struct clkgen_mux_data { |
37 | u32 offset; | |
38 | u8 shift; | |
39 | u8 width; | |
40 | spinlock_t *lock; | |
41 | unsigned long clk_flags; | |
42 | u8 mux_flags; | |
43 | }; | |
44 | ||
13e6f2da GF |
45 | static struct clkgen_mux_data stih407_a9_mux_data = { |
46 | .offset = 0x1a4, | |
3be6d8ce | 47 | .shift = 0, |
13e6f2da | 48 | .width = 2, |
46a57afd | 49 | .lock = &clkgen_a9_lock, |
13e6f2da | 50 | }; |
ab35dc13 | 51 | |
880d54ff GF |
52 | static void __init st_of_clkgen_mux_setup(struct device_node *np, |
53 | struct clkgen_mux_data *data) | |
44993d38 | 54 | { |
44993d38 GF |
55 | struct clk *clk; |
56 | void __iomem *reg; | |
57 | const char **parents; | |
7df404c9 | 58 | int num_parents = 0; |
44993d38 GF |
59 | |
60 | reg = of_iomap(np, 0); | |
61 | if (!reg) { | |
62 | pr_err("%s: Failed to get base address\n", __func__); | |
63 | return; | |
64 | } | |
65 | ||
66 | parents = clkgen_mux_get_parents(np, &num_parents); | |
67 | if (IS_ERR(parents)) { | |
68 | pr_err("%s: Failed to get parents (%ld)\n", | |
69 | __func__, PTR_ERR(parents)); | |
86665d28 | 70 | goto err_parents; |
44993d38 GF |
71 | } |
72 | ||
73 | clk = clk_register_mux(NULL, np->name, parents, num_parents, | |
74 | data->clk_flags | CLK_SET_RATE_PARENT, | |
75 | reg + data->offset, | |
76 | data->shift, data->width, data->mux_flags, | |
77 | data->lock); | |
78 | if (IS_ERR(clk)) | |
79 | goto err; | |
80 | ||
81 | pr_debug("%s: parent %s rate %u\n", | |
82 | __clk_get_name(clk), | |
83 | __clk_get_name(clk_get_parent(clk)), | |
84 | (unsigned int)clk_get_rate(clk)); | |
85 | ||
86665d28 | 86 | kfree(parents); |
44993d38 | 87 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
86665d28 | 88 | return; |
44993d38 GF |
89 | |
90 | err: | |
91 | kfree(parents); | |
86665d28 SB |
92 | err_parents: |
93 | iounmap(reg); | |
44993d38 | 94 | } |
880d54ff GF |
95 | |
96 | static void __init st_of_clkgen_a9_mux_setup(struct device_node *np) | |
97 | { | |
98 | st_of_clkgen_mux_setup(np, &stih407_a9_mux_data); | |
99 | } | |
100 | CLK_OF_DECLARE(clkgen_a9mux, "st,stih407-clkgen-a9-mux", | |
101 | st_of_clkgen_a9_mux_setup); |