Commit a7e90924 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of https://git.linaro.org/people/mike.turquette/linux

Pull clock fixes from Mike Turquette:
 "The fixes for the clock framework are all regressions in drivers, plus
  a single fix in one of the basic clock templates.  No fixes to the
  core this time around.

  As with most clock driver fixes these run the gamut from fixing a
  build warning to fixing wrecked memory timings, with a little USB
  tossed in for fun"

* tag 'clk-fixes-for-linus' of https://git.linaro.org/people/mike.turquette/linux:
  clk: pxa: fix pxa27x CCCR bit usage
  clk-divider: Fix READ_ONLY when divider > 1
  clk: qcom: Fix duplicate rbcpr clock name
  clk: at91: usb: fix at91sam9x5 recalc, round and set rate
  clk: at91: usb: fix at91rm9200 round and set rate
parents 5d01410f dcf3d458
...@@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, ...@@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
tmp = pmc_read(pmc, AT91_PMC_USB); tmp = pmc_read(pmc, AT91_PMC_USB);
usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
return parent_rate / (usbdiv + 1);
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
} }
static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate) unsigned long *parent_rate)
{ {
unsigned long div; unsigned long div;
unsigned long bestrate;
unsigned long tmp; if (!rate)
return -EINVAL;
if (rate >= *parent_rate) if (rate >= *parent_rate)
return *parent_rate; return *parent_rate;
div = *parent_rate / rate; div = DIV_ROUND_CLOSEST(*parent_rate, rate);
if (div >= SAM9X5_USB_MAX_DIV) if (div > SAM9X5_USB_MAX_DIV + 1)
return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); div = SAM9X5_USB_MAX_DIV + 1;
bestrate = *parent_rate / div;
tmp = *parent_rate / (div + 1);
if (bestrate - rate > rate - tmp)
bestrate = tmp;
return bestrate; return DIV_ROUND_CLOSEST(*parent_rate, div);
} }
static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
...@@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
u32 tmp; u32 tmp;
struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
struct at91_pmc *pmc = usb->pmc; struct at91_pmc *pmc = usb->pmc;
unsigned long div = parent_rate / rate; unsigned long div;
if (!rate)
return -EINVAL;
if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV) div = DIV_ROUND_CLOSEST(parent_rate, rate);
if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
return -EINVAL; return -EINVAL;
tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV;
...@@ -253,7 +254,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -253,7 +254,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
tmp_parent_rate = rate * usb->divisors[i]; tmp_parent_rate = rate * usb->divisors[i];
tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate); tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
tmprate = tmp_parent_rate / usb->divisors[i]; tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
if (tmprate < rate) if (tmprate < rate)
tmpdiff = rate - tmprate; tmpdiff = rate - tmprate;
else else
...@@ -281,10 +282,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -281,10 +282,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
struct at91_pmc *pmc = usb->pmc; struct at91_pmc *pmc = usb->pmc;
unsigned long div; unsigned long div;
if (!rate || parent_rate % rate) if (!rate)
return -EINVAL; return -EINVAL;
div = parent_rate / rate; div = DIV_ROUND_CLOSEST(parent_rate, rate);
for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
if (usb->divisors[i] == div) { if (usb->divisors[i] == div) {
......
...@@ -263,6 +263,14 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, ...@@ -263,6 +263,14 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (!rate) if (!rate)
rate = 1; rate = 1;
/* if read only, just return current value */
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
bestdiv = readl(divider->reg) >> divider->shift;
bestdiv &= div_mask(divider);
bestdiv = _get_div(divider, bestdiv);
return bestdiv;
}
maxdiv = _get_maxdiv(divider); maxdiv = _get_maxdiv(divider);
if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
...@@ -361,11 +369,6 @@ const struct clk_ops clk_divider_ops = { ...@@ -361,11 +369,6 @@ const struct clk_ops clk_divider_ops = {
}; };
EXPORT_SYMBOL_GPL(clk_divider_ops); EXPORT_SYMBOL_GPL(clk_divider_ops);
const struct clk_ops clk_divider_ro_ops = {
.recalc_rate = clk_divider_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
static struct clk *_register_divider(struct device *dev, const char *name, static struct clk *_register_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
...@@ -391,10 +394,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, ...@@ -391,10 +394,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
} }
init.name = name; init.name = name;
if (clk_divider_flags & CLK_DIVIDER_READ_ONLY) init.ops = &clk_divider_ops;
init.ops = &clk_divider_ro_ops;
else
init.ops = &clk_divider_ops;
init.flags = flags | CLK_IS_BASIC; init.flags = flags | CLK_IS_BASIC;
init.parent_names = (parent_name ? &parent_name: NULL); init.parent_names = (parent_name ? &parent_name: NULL);
init.num_parents = (parent_name ? 1 : 0); init.num_parents = (parent_name ? 1 : 0);
......
...@@ -322,7 +322,7 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw, ...@@ -322,7 +322,7 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
unsigned long ccsr = CCSR; unsigned long ccsr = CCSR;
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
a = cccr & CCCR_A_BIT; a = cccr & (1 << CCCR_A_BIT);
l = ccsr & CCSR_L_MASK; l = ccsr & CCSR_L_MASK;
if (osc_forced || a) if (osc_forced || a)
...@@ -341,7 +341,7 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw) ...@@ -341,7 +341,7 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
unsigned long ccsr = CCSR; unsigned long ccsr = CCSR;
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT); osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
a = cccr & CCCR_A_BIT; a = cccr & (1 << CCCR_A_BIT);
if (osc_forced) if (osc_forced)
return PXA_MEM_13Mhz; return PXA_MEM_13Mhz;
if (a) if (a)
......
...@@ -3122,7 +3122,7 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = { ...@@ -3122,7 +3122,7 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = {
[ESC1_CLK_SRC] = &esc1_clk_src.clkr, [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
[HDMI_CLK_SRC] = &hdmi_clk_src.clkr, [HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
[VSYNC_CLK_SRC] = &vsync_clk_src.clkr, [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
[RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr, [MMSS_RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
[RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr, [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
[MAPLE_CLK_SRC] = &maple_clk_src.clkr, [MAPLE_CLK_SRC] = &maple_clk_src.clkr,
[VDP_CLK_SRC] = &vdp_clk_src.clkr, [VDP_CLK_SRC] = &vdp_clk_src.clkr,
......
...@@ -90,9 +90,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, ...@@ -90,9 +90,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
div->width = div_width; div->width = div_width;
div->lock = lock; div->lock = lock;
div->table = div_table; div->table = div_table;
div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) div_ops = &clk_divider_ops;
? &clk_divider_ro_ops
: &clk_divider_ops;
} }
clk = clk_register_composite(NULL, name, parent_names, num_parents, clk = clk_register_composite(NULL, name, parent_names, num_parents,
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
#define ESC1_CLK_SRC 43 #define ESC1_CLK_SRC 43
#define HDMI_CLK_SRC 44 #define HDMI_CLK_SRC 44
#define VSYNC_CLK_SRC 45 #define VSYNC_CLK_SRC 45
#define RBCPR_CLK_SRC 46 #define MMSS_RBCPR_CLK_SRC 46
#define RBBMTIMER_CLK_SRC 47 #define RBBMTIMER_CLK_SRC 47
#define MAPLE_CLK_SRC 48 #define MAPLE_CLK_SRC 48
#define VDP_CLK_SRC 49 #define VDP_CLK_SRC 49
......
...@@ -352,7 +352,6 @@ struct clk_divider { ...@@ -352,7 +352,6 @@ struct clk_divider {
#define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_READ_ONLY BIT(5)
extern const struct clk_ops clk_divider_ops; extern const struct clk_ops clk_divider_ops;
extern const struct clk_ops clk_divider_ro_ops;
struct clk *clk_register_divider(struct device *dev, const char *name, struct clk *clk_register_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment