diff options
Diffstat (limited to 'drivers/clk/ti/interface.c')
-rw-r--r-- | drivers/clk/ti/interface.c | 96 |
1 files changed, 72 insertions, 24 deletions
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index 9c3e8c4aaa40..d71cd9b5de46 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,100 @@ 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 | struct clk *ti_clk_register_interface(struct ti_clk *setup) | ||
72 | { | ||
73 | const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait; | ||
74 | u32 reg; | ||
75 | struct clk_omap_reg *reg_setup; | ||
76 | struct ti_clk_gate *gate; | ||
77 | |||
78 | gate = setup->data; | ||
79 | reg_setup = (struct clk_omap_reg *)® | ||
80 | reg_setup->index = gate->module; | ||
81 | reg_setup->offset = gate->reg; | ||
82 | |||
83 | if (gate->flags & CLKF_NO_WAIT) | ||
84 | ops = &clkhwops_iclk; | ||
85 | |||
86 | if (gate->flags & CLKF_HSOTGUSB) | ||
87 | ops = &clkhwops_omap3430es2_iclk_hsotgusb_wait; | ||
88 | |||
89 | if (gate->flags & CLKF_DSS) | ||
90 | ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait; | ||
91 | |||
92 | if (gate->flags & CLKF_SSI) | ||
93 | ops = &clkhwops_omap3430es2_iclk_ssi_wait; | ||
94 | |||
95 | if (gate->flags & CLKF_AM35XX) | ||
96 | ops = &clkhwops_am35xx_ipss_wait; | ||
97 | |||
98 | return _register_interface(NULL, setup->name, gate->parent, | ||
99 | (void __iomem *)reg, gate->bit_shift, ops); | ||
100 | } | ||
101 | |||
102 | static void __init _of_ti_interface_clk_setup(struct device_node *node, | ||
103 | const struct clk_hw_omap_ops *ops) | ||
104 | { | ||
105 | struct clk *clk; | ||
106 | const char *parent_name; | ||
107 | void __iomem *reg; | ||
108 | u8 enable_bit = 0; | ||
109 | u32 val; | ||
110 | |||
111 | reg = ti_clk_get_reg_addr(node, 0); | ||
112 | if (!reg) | ||
113 | return; | ||
114 | |||
115 | if (!of_property_read_u32(node, "ti,bit-shift", &val)) | ||
116 | enable_bit = val; | ||
117 | |||
118 | parent_name = of_clk_get_parent_name(node, 0); | ||
119 | if (!parent_name) { | ||
120 | pr_err("%s must have a parent\n", node->name); | ||
76 | return; | 121 | return; |
77 | } | 122 | } |
78 | 123 | ||
79 | cleanup: | 124 | clk = _register_interface(NULL, node->name, parent_name, reg, |
80 | kfree(clk_hw); | 125 | enable_bit, ops); |
126 | |||
127 | if (!IS_ERR(clk)) | ||
128 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
81 | } | 129 | } |
82 | 130 | ||
83 | static void __init of_ti_interface_clk_setup(struct device_node *node) | 131 | static void __init of_ti_interface_clk_setup(struct device_node *node) |