diff options
Diffstat (limited to 'drivers/clk/ti/interface.c')
-rw-r--r-- | drivers/clk/ti/interface.c | 98 |
1 files changed, 74 insertions, 24 deletions
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index 9c3e8c4aaa40..265d91f071c5 100644 --- a/drivers/clk/ti/interface.c +++ b/drivers/clk/ti/interface.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | #include <linux/clk/ti.h> | 22 | #include <linux/clk/ti.h> |
23 | #include "clock.h" | ||
23 | 24 | ||
24 | #undef pr_fmt | 25 | #undef pr_fmt |
25 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 26 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
@@ -31,53 +32,102 @@ static const struct clk_ops ti_interface_clk_ops = { | |||
31 | .is_enabled = &omap2_dflt_clk_is_enabled, | 32 | .is_enabled = &omap2_dflt_clk_is_enabled, |
32 | }; | 33 | }; |
33 | 34 | ||
34 | static void __init _of_ti_interface_clk_setup(struct device_node *node, | 35 | static struct clk *_register_interface(struct device *dev, const char *name, |
35 | const struct clk_hw_omap_ops *ops) | 36 | const char *parent_name, |
37 | void __iomem *reg, u8 bit_idx, | ||
38 | const struct clk_hw_omap_ops *ops) | ||
36 | { | 39 | { |
37 | struct clk *clk; | ||
38 | struct clk_init_data init = { NULL }; | 40 | struct clk_init_data init = { NULL }; |
39 | struct clk_hw_omap *clk_hw; | 41 | struct clk_hw_omap *clk_hw; |
40 | const char *parent_name; | 42 | struct clk *clk; |
41 | u32 val; | ||
42 | 43 | ||
43 | clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); | 44 | clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); |
44 | if (!clk_hw) | 45 | if (!clk_hw) |
45 | return; | 46 | return ERR_PTR(-ENOMEM); |
46 | 47 | ||
47 | clk_hw->hw.init = &init; | 48 | clk_hw->hw.init = &init; |
48 | clk_hw->ops = ops; | 49 | clk_hw->ops = ops; |
49 | clk_hw->flags = MEMMAP_ADDRESSING; | 50 | clk_hw->flags = MEMMAP_ADDRESSING; |
51 | clk_hw->enable_reg = reg; | ||
52 | clk_hw->enable_bit = bit_idx; | ||
50 | 53 | ||
51 | clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0); | 54 | init.name = name; |
52 | if (!clk_hw->enable_reg) | ||
53 | goto cleanup; | ||
54 | |||
55 | if (!of_property_read_u32(node, "ti,bit-shift", &val)) | ||
56 | clk_hw->enable_bit = val; | ||
57 | |||
58 | init.name = node->name; | ||
59 | init.ops = &ti_interface_clk_ops; | 55 | init.ops = &ti_interface_clk_ops; |
60 | init.flags = 0; | 56 | init.flags = 0; |
61 | 57 | ||
62 | parent_name = of_clk_get_parent_name(node, 0); | ||
63 | if (!parent_name) { | ||
64 | pr_err("%s must have a parent\n", node->name); | ||
65 | goto cleanup; | ||
66 | } | ||
67 | |||
68 | init.num_parents = 1; | 58 | init.num_parents = 1; |
69 | init.parent_names = &parent_name; | 59 | init.parent_names = &parent_name; |
70 | 60 | ||
71 | clk = clk_register(NULL, &clk_hw->hw); | 61 | clk = clk_register(NULL, &clk_hw->hw); |
72 | 62 | ||
73 | if (!IS_ERR(clk)) { | 63 | if (IS_ERR(clk)) |
74 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 64 | kfree(clk_hw); |
65 | else | ||
75 | omap2_init_clk_hw_omap_clocks(clk); | 66 | omap2_init_clk_hw_omap_clocks(clk); |
67 | |||
68 | return clk; | ||
69 | } | ||
70 | |||
71 | #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS) | ||
72 | struct clk *ti_clk_register_interface(struct ti_clk *setup) | ||
73 | { | ||
74 | const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait; | ||
75 | u32 reg; | ||
76 | struct clk_omap_reg *reg_setup; | ||
77 | struct ti_clk_gate *gate; | ||
78 | |||
79 | gate = setup->data; | ||
80 | reg_setup = (struct clk_omap_reg *)® | ||
81 | reg_setup->index = gate->module; | ||
82 | reg_setup->offset = gate->reg; | ||
83 | |||
84 | if (gate->flags & CLKF_NO_WAIT) | ||
85 | ops = &clkhwops_iclk; | ||
86 | |||
87 | if (gate->flags & CLKF_HSOTGUSB) | ||
88 | ops = &clkhwops_omap3430es2_iclk_hsotgusb_wait; | ||
89 | |||
90 | if (gate->flags & CLKF_DSS) | ||
91 | ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait; | ||
92 | |||
93 | if (gate->flags & CLKF_SSI) | ||
94 | ops = &clkhwops_omap3430es2_iclk_ssi_wait; | ||
95 | |||
96 | if (gate->flags & CLKF_AM35XX) | ||
97 | ops = &clkhwops_am35xx_ipss_wait; | ||
98 | |||
99 | return _register_interface(NULL, setup->name, gate->parent, | ||
100 | (void __iomem *)reg, gate->bit_shift, ops); | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | static void __init _of_ti_interface_clk_setup(struct device_node *node, | ||
105 | const struct clk_hw_omap_ops *ops) | ||
106 | { | ||
107 | struct clk *clk; | ||
108 | const char *parent_name; | ||
109 | void __iomem *reg; | ||
110 | u8 enable_bit = 0; | ||
111 | u32 val; | ||
112 | |||
113 | reg = ti_clk_get_reg_addr(node, 0); | ||
114 | if (!reg) | ||
115 | return; | ||
116 | |||
117 | if (!of_property_read_u32(node, "ti,bit-shift", &val)) | ||
118 | enable_bit = val; | ||
119 | |||
120 | parent_name = of_clk_get_parent_name(node, 0); | ||
121 | if (!parent_name) { | ||
122 | pr_err("%s must have a parent\n", node->name); | ||
76 | return; | 123 | return; |
77 | } | 124 | } |
78 | 125 | ||
79 | cleanup: | 126 | clk = _register_interface(NULL, node->name, parent_name, reg, |
80 | kfree(clk_hw); | 127 | enable_bit, ops); |
128 | |||
129 | if (!IS_ERR(clk)) | ||
130 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
81 | } | 131 | } |
82 | 132 | ||
83 | static void __init of_ti_interface_clk_setup(struct device_node *node) | 133 | static void __init of_ti_interface_clk_setup(struct device_node *node) |