@@ -376,14 +376,9 @@ static void __init of_omap2_apll_setup(struct device_node *node)
}
clk_hw->fixed_rate = val;
- if (of_property_read_u32(node, "ti,bit-shift", &val)) {
- pr_err("%pOFn missing bit-shift\n", node);
- goto cleanup;
- }
-
- clk_hw->enable_bit = val;
- ad->enable_mask = 0x3 << val;
- ad->autoidle_mask = 0x3 << val;
+ clk_hw->enable_bit = ti_clk_get_legacy_bit_shift(node);
+ ad->enable_mask = 0x3 << clk_hw->enable_bit;
+ ad->autoidle_mask = 0x3 << clk_hw->enable_bit;
if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
pr_err("%pOFn missing idlest-shift\n", node);
@@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/list.h>
+#include <linux/minmax.h>
#include <linux/regmap.h>
#include <linux/string_helpers.h>
#include <linux/memblock.h>
@@ -307,8 +308,9 @@ int __init ti_clk_retry_init(struct device_node *node, void *user,
int ti_clk_get_reg_addr(struct device_node *node, int index,
struct clk_omap_reg *reg)
{
- u32 val;
- int i;
+ u32 clksel_addr, val;
+ bool is_clksel = false;
+ int i, err;
for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
if (clocks_node_ptr[i] == node->parent)
@@ -324,21 +326,62 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
reg->index = i;
- if (of_property_read_u32_index(node, "reg", index, &val)) {
- if (of_property_read_u32_index(node->parent, "reg",
- index, &val)) {
- pr_err("%pOFn or parent must have reg[%d]!\n",
- node, index);
+ if (of_device_is_compatible(node->parent, "ti,clksel")) {
+ err = of_property_read_u32_index(node->parent, "reg", index, &clksel_addr);
+ if (err) {
+ pr_err("%pOFn parent clksel must have reg[%d]!\n", node, index);
return -EINVAL;
}
+ is_clksel = true;
}
+ err = of_property_read_u32_index(node, "reg", index, &val);
+ if (err && is_clksel) {
+ /* Legacy clksel with no reg and a possible ti,bit-shift property */
+ reg->offset = clksel_addr;
+ reg->bit = ti_clk_get_legacy_bit_shift(node);
+ reg->ptr = NULL;
+
+ return 0;
+ }
+
+ /* Updated clksel clock with a proper reg property */
+ if (is_clksel) {
+ reg->offset = clksel_addr;
+ reg->bit = val;
+ reg->ptr = NULL;
+ return 0;
+ }
+
+ /* Other clocks that may or may not have ti,bit-shift property */
reg->offset = val;
+ reg->bit = ti_clk_get_legacy_bit_shift(node);
reg->ptr = NULL;
return 0;
}
+/**
+ * ti_clk_get_legacy_bit_shift - get bit shift for a clock register
+ * @node: device node for the clock
+ *
+ * Gets the clock register bit shift using the legacy ti,bit-shift
+ * property. Only needed for legacy clock, and can be eventually
+ * dropped once all the composite clocks use a clksel node with a
+ * proper reg property.
+ */
+int ti_clk_get_legacy_bit_shift(struct device_node *node)
+{
+ int err;
+ u32 val;
+
+ err = of_property_read_u32(node, "ti,bit-shift", &val);
+ if (!err && in_range(val, 0, 32))
+ return val;
+
+ return 0;
+}
+
void ti_clk_latch(struct clk_omap_reg *reg, s8 shift)
{
u32 latch;
@@ -216,6 +216,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
int ti_clk_get_reg_addr(struct device_node *node, int index,
struct clk_omap_reg *reg);
+int ti_clk_get_legacy_bit_shift(struct device_node *node);
void ti_dt_clocks_register(struct ti_dt_clk *oclks);
int ti_clk_retry_init(struct device_node *node, void *user,
ti_of_clk_init_cb_t func);
@@ -477,10 +477,7 @@ static int __init ti_clk_divider_populate(struct device_node *node,
if (ret)
return ret;
- if (!of_property_read_u32(node, "ti,bit-shift", &val))
- div->shift = val;
- else
- div->shift = 0;
+ div->shift = div->reg.bit;
if (!of_property_read_u32(node, "ti,latch-bit", &val))
div->latch = val;
@@ -132,7 +132,6 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
struct clk_omap_reg reg;
const char *name;
u8 enable_bit = 0;
- u32 val;
u32 flags = 0;
u8 clk_gate_flags = 0;
@@ -140,8 +139,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
if (ti_clk_get_reg_addr(node, 0, ®))
return;
- if (!of_property_read_u32(node, "ti,bit-shift", &val))
- enable_bit = val;
+ enable_bit = reg.bit;
}
if (of_clk_get_parent_count(node) != 1) {
@@ -170,7 +168,6 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
const struct clk_hw_omap_ops *hw_ops)
{
struct clk_hw_omap *gate;
- u32 val = 0;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
@@ -179,9 +176,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg))
goto cleanup;
- of_property_read_u32(node, "ti,bit-shift", &val);
-
- gate->enable_bit = val;
+ gate->enable_bit = gate->enable_reg.bit;
gate->ops = hw_ops;
if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
@@ -66,13 +66,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
struct clk_omap_reg reg;
u8 enable_bit = 0;
const char *name;
- u32 val;
if (ti_clk_get_reg_addr(node, 0, ®))
return;
- if (!of_property_read_u32(node, "ti,bit-shift", &val))
- enable_bit = val;
+ enable_bit = reg.bit;
parent_name = of_clk_get_parent_name(node, 0);
if (!parent_name) {
@@ -189,7 +189,7 @@ static void of_mux_clk_setup(struct device_node *node)
if (ti_clk_get_reg_addr(node, 0, ®))
goto cleanup;
- of_property_read_u32(node, "ti,bit-shift", &shift);
+ shift = reg.bit;
of_property_read_u32(node, "ti,latch-bit", &latch);
@@ -252,7 +252,6 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
{
struct clk_omap_mux *mux;
unsigned int num_parents;
- u32 val;
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -261,8 +260,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
if (ti_clk_get_reg_addr(node, 0, &mux->reg))
goto cleanup;
- if (!of_property_read_u32(node, "ti,bit-shift", &val))
- mux->shift = val;
+ mux->shift = mux->reg.bit;
if (of_property_read_bool(node, "ti,index-starts-at-one"))
mux->flags |= CLK_MUX_INDEX_ONE;
@@ -13,11 +13,14 @@
/**
* struct clk_omap_reg - OMAP register declaration
* @offset: offset from the master IP module base address
+ * @bit: register bit offset
* @index: index of the master IP module
+ * @flags: flags
*/
struct clk_omap_reg {
void __iomem *ptr;
u16 offset;
+ u8 bit;
u8 index;
u8 flags;
};
Because of legacy reasons, the TI clksel composite clocks can have overlapping reg properties, and use a custom ti,bit-shift property. For the clksel clocks we can start using of the standard reg property instead of the custom ti,bit-shift property. To do this, let's add a ti_clk_get_legacy_bit_shift() helper, and make ti_clk_get_reg_addr() populate the clock bit offset. This makes it possible to update the devicetree files to use the reg property one clock at a time. Signed-off-by: Tony Lindgren <tony@atomide.com> --- drivers/clk/ti/apll.c | 11 ++------ drivers/clk/ti/clk.c | 57 +++++++++++++++++++++++++++++++++----- drivers/clk/ti/clock.h | 1 + drivers/clk/ti/divider.c | 5 +--- drivers/clk/ti/gate.c | 9 ++---- drivers/clk/ti/interface.c | 4 +-- drivers/clk/ti/mux.c | 6 ++-- include/linux/clk/ti.h | 3 ++ 8 files changed, 63 insertions(+), 33 deletions(-)