Skip to content

Commit

Permalink
clk: bcm281xx: don't use unnamed structs or unions
Browse files Browse the repository at this point in the history
The Broadcom Kona clock code, as originally written, made use of
unnamed union and struct fields.  This is a feature present in C11,
and is a GNU extension otherwise.  It worked very well for me.

Unfortunately, Russell King reported that this feature was not
supported in a build environment he used, which meant attempting
to build this code failed spectacularly.

Add names to these unnamed fields, and update the code accordingly.

Reported-by: Russell King <linux@arm.linux.org.uk>
Tested-by: Markus Mayer <markus.mayer@linaro.org>
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
  • Loading branch information
Alex Elder authored and Mike Turquette committed Apr 30, 2014
1 parent d1db0ee commit e813d49
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 61 deletions.
33 changes: 17 additions & 16 deletions drivers/clk/bcm/clk-kona-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ LIST_HEAD(ccu_list); /* The list of set up CCUs */

static bool clk_requires_trigger(struct kona_clk *bcm_clk)
{
struct peri_clk_data *peri = bcm_clk->peri;
struct peri_clk_data *peri = bcm_clk->u.peri;
struct bcm_clk_sel *sel;
struct bcm_clk_div *div;

Expand Down Expand Up @@ -63,7 +63,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
u32 limit;

BUG_ON(bcm_clk->type != bcm_clk_peri);
peri = bcm_clk->peri;
peri = bcm_clk->u.peri;
name = bcm_clk->name;
range = bcm_clk->ccu->range;

Expand All @@ -81,19 +81,19 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)

div = &peri->div;
if (divider_exists(div)) {
if (div->offset > limit) {
if (div->u.s.offset > limit) {
pr_err("%s: bad divider offset for %s (%u > %u)\n",
__func__, name, div->offset, limit);
__func__, name, div->u.s.offset, limit);
return false;
}
}

div = &peri->pre_div;
if (divider_exists(div)) {
if (div->offset > limit) {
if (div->u.s.offset > limit) {
pr_err("%s: bad pre-divider offset for %s "
"(%u > %u)\n",
__func__, name, div->offset, limit);
__func__, name, div->u.s.offset, limit);
return false;
}
}
Expand Down Expand Up @@ -249,21 +249,22 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
{
if (divider_is_fixed(div)) {
/* Any fixed divider value but 0 is OK */
if (div->fixed == 0) {
if (div->u.fixed == 0) {
pr_err("%s: bad %s fixed value 0 for %s\n", __func__,
field_name, clock_name);
return false;
}
return true;
}
if (!bitfield_valid(div->shift, div->width, field_name, clock_name))
if (!bitfield_valid(div->u.s.shift, div->u.s.width,
field_name, clock_name))
return false;

if (divider_has_fraction(div))
if (div->frac_width > div->width) {
if (div->u.s.frac_width > div->u.s.width) {
pr_warn("%s: bad %s fraction width for %s (%u > %u)\n",
__func__, field_name, clock_name,
div->frac_width, div->width);
div->u.s.frac_width, div->u.s.width);
return false;
}

Expand All @@ -278,7 +279,7 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
*/
static bool kona_dividers_valid(struct kona_clk *bcm_clk)
{
struct peri_clk_data *peri = bcm_clk->peri;
struct peri_clk_data *peri = bcm_clk->u.peri;
struct bcm_clk_div *div;
struct bcm_clk_div *pre_div;
u32 limit;
Expand All @@ -295,7 +296,7 @@ static bool kona_dividers_valid(struct kona_clk *bcm_clk)

limit = BITS_PER_BYTE * sizeof(u32);

return div->frac_width + pre_div->frac_width <= limit;
return div->u.s.frac_width + pre_div->u.s.frac_width <= limit;
}


Expand Down Expand Up @@ -328,7 +329,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
if (!peri_clk_data_offsets_valid(bcm_clk))
return false;

peri = bcm_clk->peri;
peri = bcm_clk->u.peri;
name = bcm_clk->name;
gate = &peri->gate;
if (gate_exists(gate) && !gate_valid(gate, "gate", name))
Expand Down Expand Up @@ -588,12 +589,12 @@ static void bcm_clk_teardown(struct kona_clk *bcm_clk)
{
switch (bcm_clk->type) {
case bcm_clk_peri:
peri_clk_teardown(bcm_clk->data, &bcm_clk->init_data);
peri_clk_teardown(bcm_clk->u.data, &bcm_clk->init_data);
break;
default:
break;
}
bcm_clk->data = NULL;
bcm_clk->u.data = NULL;
bcm_clk->type = bcm_clk_none;
}

Expand Down Expand Up @@ -644,7 +645,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name,
break;
}
bcm_clk->type = type;
bcm_clk->data = data;
bcm_clk->u.data = data;

/* Make sure everything makes sense before we set it up */
if (!kona_clk_valid(bcm_clk)) {
Expand Down
64 changes: 33 additions & 31 deletions drivers/clk/bcm/clk-kona.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ u64 do_div_round_closest(u64 dividend, unsigned long divisor)
/* Convert a divider into the scaled divisor value it represents. */
static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
{
return (u64)reg_div + ((u64)1 << div->frac_width);
return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
}

/*
Expand All @@ -77,7 +77,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
BUG_ON(billionths >= BILLION);

combined = (u64)div_value * BILLION + billionths;
combined <<= div->frac_width;
combined <<= div->u.s.frac_width;

return do_div_round_closest(combined, BILLION);
}
Expand All @@ -87,7 +87,7 @@ static inline u64
scaled_div_min(struct bcm_clk_div *div)
{
if (divider_is_fixed(div))
return (u64)div->fixed;
return (u64)div->u.fixed;

return scaled_div_value(div, 0);
}
Expand All @@ -98,9 +98,9 @@ u64 scaled_div_max(struct bcm_clk_div *div)
u32 reg_div;

if (divider_is_fixed(div))
return (u64)div->fixed;
return (u64)div->u.fixed;

reg_div = ((u32)1 << div->width) - 1;
reg_div = ((u32)1 << div->u.s.width) - 1;

return scaled_div_value(div, reg_div);
}
Expand All @@ -115,7 +115,7 @@ divider(struct bcm_clk_div *div, u64 scaled_div)
BUG_ON(scaled_div < scaled_div_min(div));
BUG_ON(scaled_div > scaled_div_max(div));

return (u32)(scaled_div - ((u64)1 << div->frac_width));
return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width));
}

/* Return a rate scaled for use when dividing by a scaled divisor. */
Expand All @@ -125,7 +125,7 @@ scale_rate(struct bcm_clk_div *div, u32 rate)
if (divider_is_fixed(div))
return (u64)rate;

return (u64)rate << div->frac_width;
return (u64)rate << div->u.s.frac_width;
}

/* CCU access */
Expand Down Expand Up @@ -398,14 +398,14 @@ static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div)
u32 reg_div;

if (divider_is_fixed(div))
return (u64)div->fixed;
return (u64)div->u.fixed;

flags = ccu_lock(ccu);
reg_val = __ccu_read(ccu, div->offset);
reg_val = __ccu_read(ccu, div->u.s.offset);
ccu_unlock(ccu, flags);

/* Extract the full divider field from the register value */
reg_div = bitfield_extract(reg_val, div->shift, div->width);
reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width);

/* Return the scaled divisor value it represents */
return scaled_div_value(div, reg_div);
Expand Down Expand Up @@ -433,16 +433,17 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
* state was defined in the device tree, we just find out
* what its current value is rather than updating it.
*/
if (div->scaled_div == BAD_SCALED_DIV_VALUE) {
reg_val = __ccu_read(ccu, div->offset);
reg_div = bitfield_extract(reg_val, div->shift, div->width);
div->scaled_div = scaled_div_value(div, reg_div);
if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) {
reg_val = __ccu_read(ccu, div->u.s.offset);
reg_div = bitfield_extract(reg_val, div->u.s.shift,
div->u.s.width);
div->u.s.scaled_div = scaled_div_value(div, reg_div);

return 0;
}

/* Convert the scaled divisor to the value we need to record */
reg_div = divider(div, div->scaled_div);
reg_div = divider(div, div->u.s.scaled_div);

/* Clock needs to be enabled before changing the rate */
enabled = __is_clk_gate_enabled(ccu, gate);
Expand All @@ -452,9 +453,10 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
}

/* Replace the divider value and record the result */
reg_val = __ccu_read(ccu, div->offset);
reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div);
__ccu_write(ccu, div->offset, reg_val);
reg_val = __ccu_read(ccu, div->u.s.offset);
reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width,
reg_div);
__ccu_write(ccu, div->u.s.offset, reg_val);

/* If the trigger fails we still want to disable the gate */
if (!__clk_trigger(ccu, trig))
Expand Down Expand Up @@ -490,11 +492,11 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,

BUG_ON(divider_is_fixed(div));

previous = div->scaled_div;
previous = div->u.s.scaled_div;
if (previous == scaled_div)
return 0; /* No change */

div->scaled_div = scaled_div;
div->u.s.scaled_div = scaled_div;

flags = ccu_lock(ccu);
__ccu_write_enable(ccu);
Expand All @@ -505,7 +507,7 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
ccu_unlock(ccu, flags);

if (ret)
div->scaled_div = previous; /* Revert the change */
div->u.s.scaled_div = previous; /* Revert the change */

return ret;

Expand Down Expand Up @@ -802,23 +804,23 @@ static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
static int kona_peri_clk_enable(struct clk_hw *hw)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;

return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true);
}

static void kona_peri_clk_disable(struct clk_hw *hw)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;

(void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false);
}

static int kona_peri_clk_is_enabled(struct clk_hw *hw)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;

return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0;
}
Expand All @@ -827,7 +829,7 @@ static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->peri;
struct peri_clk_data *data = bcm_clk->u.peri;

return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div,
parent_rate);
Expand All @@ -837,20 +839,20 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct bcm_clk_div *div = &bcm_clk->peri->div;
struct bcm_clk_div *div = &bcm_clk->u.peri->div;

if (!divider_exists(div))
return __clk_get_rate(hw->clk);

/* Quietly avoid a zero rate */
return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div,
return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
rate ? rate : 1, *parent_rate, NULL);
}

static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->peri;
struct peri_clk_data *data = bcm_clk->u.peri;
struct bcm_clk_sel *sel = &data->sel;
struct bcm_clk_trig *trig;
int ret;
Expand Down Expand Up @@ -884,7 +886,7 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->peri;
struct peri_clk_data *data = bcm_clk->u.peri;
u8 index;

index = selector_read_index(bcm_clk->ccu, &data->sel);
Expand All @@ -897,7 +899,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->peri;
struct peri_clk_data *data = bcm_clk->u.peri;
struct bcm_clk_div *div = &data->div;
u64 scaled_div = 0;
int ret;
Expand Down Expand Up @@ -958,7 +960,7 @@ struct clk_ops kona_peri_clk_ops = {
static bool __peri_clk_init(struct kona_clk *bcm_clk)
{
struct ccu_data *ccu = bcm_clk->ccu;
struct peri_clk_data *peri = bcm_clk->peri;
struct peri_clk_data *peri = bcm_clk->u.peri;
const char *name = bcm_clk->name;
struct bcm_clk_trig *trig;

Expand Down
Loading

0 comments on commit e813d49

Please sign in to comment.