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