Commit b53a1603 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-ti', 'clk-analog', 'clk-trace', 'clk-at91' and 'clk-silabs' into clk-next

 - Add some trace points for clk_set_rate() "range" functions
 - DVFS support for AT91 clk driver

* clk-ti:
  clk: ti: omap5: Fix reboot DPLL lock failure when using ABE TIMERs
  clk: ti: Fix memleak in ti_fapll_synth_setup

* clk-analog:
  clk: axi-clkgen: move the OF table at the bottom of the file
  clk: axi-clkgen: wrap limits in a struct and keep copy on the state object
  dt-bindings: clock: adi,axi-clkgen: convert old binding to yaml format

* clk-trace:
  clk: Trace clk_set_rate() "range" functions

* clk-at91:
  clk: at91: sam9x60: remove atmel,osc-bypass support
  clk: at91: sama7g5: register cpu clock
  clk: at91: clk-master: re-factor master clock
  clk: at91: sama7g5: do not allow cpu pll to go higher than 1GHz
  clk: at91: sama7g5: decrease lower limit for MCK0 rate
  clk: at91: sama7g5: remove mck0 from parent list of other clocks
  clk: at91: clk-sam9x60-pll: allow runtime changes for pll
  clk: at91: sama7g5: add 5th divisor for mck0 layout and characteristics
  clk: at91: clk-master: add 5th divisor for mck master
  clk: at91: sama7g5: allow SYS and CPU PLLs to be exported and referenced in DT
  dt-bindings: clock: at91: add sama7g5 pll defines
  clk: at91: sama7g5: fix compilation error

* clk-silabs:
  clk: si5351: Wait for bit clear after PLL reset
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/adi,axi-clkgen.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Binding for Analog Devices AXI clkgen pcore clock generator
maintainers:
- Lars-Peter Clausen <lars@metafoo.de>
- Michael Hennerich <michael.hennerich@analog.com>
description: |
The axi_clkgen IP core is a software programmable clock generator,
that can be synthesized on various FPGA platforms.
Link: https://wiki.analog.com/resources/fpga/docs/axi_clkgen
properties:
compatible:
enum:
- adi,axi-clkgen-2.00.a
clocks:
description:
Specifies the reference clock(s) from which the output frequency is
derived. This must either reference one clock if only the first clock
input is connected or two if both clock inputs are connected.
minItems: 1
maxItems: 2
'#clock-cells':
const: 0
reg:
maxItems: 1
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
clock-controller@ff000000 {
compatible = "adi,axi-clkgen-2.00.a";
#clock-cells = <0>;
reg = <0xff000000 0x1000>;
clocks = <&osc 1>;
};
Binding for the axi-clkgen clock generator
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a".
- #clock-cells : from common clock binding; Should always be set to 0.
- reg : Address and length of the axi-clkgen register set.
- clocks : Phandle and clock specifier for the parent clock(s). This must
either reference one clock if only the first clock input is connected or two
if both clock inputs are connected. For the later case the clock connected
to the first input must be specified first.
Optional properties:
- clock-output-names : From common clock binding.
Example:
clock@ff000000 {
compatible = "adi,axi-clkgen";
#clock-cells = <0>;
reg = <0xff000000 0x1000>;
clocks = <&osc 1>;
};
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(rm9200_mck_lock);
struct sck {
char *n;
char *p;
......@@ -137,9 +139,20 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
&rm9200_mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91rm9200_master_layout,
&rm9200_mck_characteristics,
&rm9200_mck_lock, CLK_SET_RATE_GATE,
INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91rm9200_master_layout,
&rm9200_mck_characteristics,
&rm9200_mck_lock, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -181,7 +194,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91rm9200_periphck[i].n,
"masterck",
"masterck_div",
at91rm9200_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
......
......@@ -32,6 +32,8 @@ struct at91sam926x_data {
bool has_slck;
};
static DEFINE_SPINLOCK(at91sam9260_mck_lock);
static const struct clk_master_characteristics sam9260_mck_characteristics = {
.output = { .min = 0, .max = 105000000 },
.divisors = { 1, 2, 4, 0 },
......@@ -218,8 +220,8 @@ static const struct sck at91sam9261_systemck[] = {
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "pck3", .p = "prog3", .id = 11 },
{ .n = "hclk0", .p = "masterck", .id = 16 },
{ .n = "hclk1", .p = "masterck", .id = 17 },
{ .n = "hclk0", .p = "masterck_div", .id = 16 },
{ .n = "hclk1", .p = "masterck_div", .id = 17 },
};
static const struct pck at91sam9261_periphck[] = {
......@@ -413,9 +415,21 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
data->mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91rm9200_master_layout,
data->mck_characteristics,
&at91sam9260_mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91rm9200_master_layout,
data->mck_characteristics,
&at91sam9260_mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -457,7 +471,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
for (i = 0; i < data->num_pck; i++) {
hw = at91_clk_register_peripheral(regmap,
data->pck[i].n,
"masterck",
"masterck_div",
data->pck[i].id);
if (IS_ERR(hw))
goto err_free;
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(at91sam9g45_mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
......@@ -40,10 +42,10 @@ static const struct {
char *p;
u8 id;
} at91sam9g45_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
struct pck {
......@@ -148,9 +150,21 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91rm9200_master_layout,
&mck_characteristics,
&at91sam9g45_mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91rm9200_master_layout,
&mck_characteristics,
&at91sam9g45_mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -166,7 +180,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
char name[6];
......@@ -195,7 +209,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9g45_periphck[i].n,
"masterck",
"masterck_div",
at91sam9g45_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(at91sam9n12_mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
......@@ -54,12 +56,12 @@ static const struct {
char *p;
u8 id;
} at91sam9n12_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
static const struct clk_pcr_layout at91sam9n12_pcr_layout = {
......@@ -175,9 +177,21 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "pllbck";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91sam9x5_master_layout,
&mck_characteristics,
&at91sam9n12_mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91sam9x5_master_layout,
&mck_characteristics,
&at91sam9n12_mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -191,7 +205,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "pllbck";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
char name[6];
......@@ -221,7 +235,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9n12_pcr_layout,
at91sam9n12_periphck[i].n,
"masterck",
"masterck_div",
at91sam9n12_periphck[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(sam9rl_mck_lock);
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
.output = { .min = 0, .max = 94000000 },
.divisors = { 1, 2, 4, 0 },
......@@ -117,9 +119,20 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics,
&sam9rl_mck_lock, CLK_SET_RATE_GATE,
INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91rm9200_master_layout,
&sam9rl_mck_characteristics,
&sam9rl_mck_lock, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -129,7 +142,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
char name[6];
......@@ -158,7 +171,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9rl_periphck[i].n,
"masterck",
"masterck_div",
at91sam9rl_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
......@@ -41,7 +43,7 @@ static const struct {
char *p;
u8 id;
} at91sam9x5_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
......@@ -196,9 +198,19 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -218,7 +230,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
char name[6];
......@@ -245,7 +257,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
}
if (has_lcdck) {
hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
hw = at91_clk_register_system(regmap, "lcdck", "masterck_div", 3);
if (IS_ERR(hw))
goto err_free;
......@@ -256,7 +268,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
at91sam9x5_periphck[i].n,
"masterck",
"masterck_div",
at91sam9x5_periphck[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......@@ -269,7 +281,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
extra_pcks[i].n,
"masterck",
"masterck_div",
extra_pcks[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......
This diff is collapsed.
......@@ -229,6 +229,57 @@ static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
}
static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
struct sam9x60_frac *frac = to_sam9x60_frac(core);
struct regmap *regmap = core->regmap;
unsigned long irqflags;
unsigned int val, cfrac, cmul;
long ret;
ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
if (ret <= 0)
return ret;
spin_lock_irqsave(core->lock, irqflags);
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
core->id);
regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
if (cmul == frac->mul && cfrac == frac->frac)
goto unlock;
regmap_write(regmap, AT91_PMC_PLL_CTRL1,
(frac->mul << core->layout->mul_shift) |
(frac->frac << core->layout->frac_shift));
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
AT91_PMC_PLL_UPDT_UPDATE | core->id);
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
AT91_PMC_PLL_CTRL0_ENLOCK |
AT91_PMC_PLL_CTRL0_ENPLL);
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
AT91_PMC_PLL_UPDT_UPDATE | core->id);
while (!sam9x60_pll_ready(regmap, core->id))
cpu_relax();
unlock:
spin_unlock_irqrestore(core->lock, irqflags);
return ret;
}
static const struct clk_ops sam9x60_frac_pll_ops = {
.prepare = sam9x60_frac_pll_prepare,
.unprepare = sam9x60_frac_pll_unprepare,
......@@ -238,6 +289,15 @@ static const struct clk_ops sam9x60_frac_pll_ops = {
.set_rate = sam9x60_frac_pll_set_rate,
};
static const struct clk_ops sam9x60_frac_pll_ops_chg = {
.prepare = sam9x60_frac_pll_prepare,
.unprepare = sam9x60_frac_pll_unprepare,
.is_prepared = sam9x60_frac_pll_is_prepared,
.recalc_rate = sam9x60_frac_pll_recalc_rate,
.round_rate = sam9x60_frac_pll_round_rate,
.set_rate = sam9x60_frac_pll_set_rate_chg,
};
static int sam9x60_div_pll_prepare(struct clk_hw *hw)
{
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
......@@ -384,6 +444,44 @@ static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
struct sam9x60_div *div = to_sam9x60_div(core);
struct regmap *regmap = core->regmap;
unsigned long irqflags;
unsigned int val, cdiv;
div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
spin_lock_irqsave(core->lock, irqflags);
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
core->id);
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
/* Stop if nothing changed. */
if (cdiv == div->div)
goto unlock;
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
core->layout->div_mask,
(div->div << core->layout->div_shift));
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
AT91_PMC_PLL_UPDT_UPDATE | core->id);
while (!sam9x60_pll_ready(regmap, core->id))
cpu_relax();
unlock:
spin_unlock_irqrestore(core->lock, irqflags);
return 0;
}
static const struct clk_ops sam9x60_div_pll_ops = {
.prepare = sam9x60_div_pll_prepare,
.unprepare = sam9x60_div_pll_unprepare,
......@@ -393,17 +491,26 @@ static const struct clk_ops sam9x60_div_pll_ops = {
.set_rate = sam9x60_div_pll_set_rate,
};
static const struct clk_ops sam9x60_div_pll_ops_chg = {
.prepare = sam9x60_div_pll_prepare,
.unprepare = sam9x60_div_pll_unprepare,
.is_prepared = sam9x60_div_pll_is_prepared,
.recalc_rate = sam9x60_div_pll_recalc_rate,
.round_rate = sam9x60_div_pll_round_rate,
.set_rate = sam9x60_div_pll_set_rate_chg,
};
struct clk_hw * __init
sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
struct clk_hw *parent_hw, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical)
const struct clk_pll_layout *layout, u32 flags)
{
struct sam9x60_frac *frac;
struct clk_hw *hw;
struct clk_init_data init;
unsigned long parent_rate, flags;
unsigned long parent_rate, irqflags;
unsigned int val;
int ret;
......@@ -417,10 +524,12 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
init.name = name;
init.parent_names = &parent_name;
init.num_parents = 1;
init.ops = &sam9x60_frac_pll_ops;
init.flags = CLK_SET_RATE_GATE;
if (critical)
init.flags |= CLK_IS_CRITICAL;
if (flags & CLK_SET_RATE_GATE)
init.ops = &sam9x60_frac_pll_ops;
else
init.ops = &sam9x60_frac_pll_ops_chg;
init.flags = flags;
frac->core.id = id;
frac->core.hw.init = &init;
......@@ -429,7 +538,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
frac->core.regmap = regmap;
frac->core.lock = lock;
spin_lock_irqsave(frac->core.lock, flags);
spin_lock_irqsave(frac->core.lock, irqflags);
if (sam9x60_pll_ready(regmap, id)) {
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
AT91_PMC_PLL_UPDT_ID_MSK, id);
......@@ -457,7 +566,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
goto free;
}
}
spin_unlock_irqrestore(frac->core.lock, flags);
spin_unlock_irqrestore(frac->core.lock, irqflags);
hw = &frac->core.hw;
ret = clk_hw_register(NULL, hw);
......@@ -469,7 +578,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
return hw;
free:
spin_unlock_irqrestore(frac->core.lock, flags);
spin_unlock_irqrestore(frac->core.lock, irqflags);
kfree(frac);
return hw;
}
......@@ -478,12 +587,12 @@ struct clk_hw * __init
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical)
const struct clk_pll_layout *layout, u32 flags)
{
struct sam9x60_div *div;
struct clk_hw *hw;
struct clk_init_data init;
unsigned long flags;
unsigned long irqflags;
unsigned int val;
int ret;
......@@ -497,11 +606,11 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
init.name = name;
init.parent_names = &parent_name;
init.num_parents = 1;
init.ops = &sam9x60_div_pll_ops;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT;
if (critical)
init.flags |= CLK_IS_CRITICAL;
if (flags & CLK_SET_RATE_GATE)
init.ops = &sam9x60_div_pll_ops;
else
init.ops = &sam9x60_div_pll_ops_chg;
init.flags = flags;
div->core.id = id;
div->core.hw.init = &init;
......@@ -510,14 +619,14 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
div->core.regmap = regmap;
div->core.lock = lock;
spin_lock_irqsave(div->core.lock, flags);
spin_lock_irqsave(div->core.lock, irqflags);
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
AT91_PMC_PLL_UPDT_ID_MSK, id);
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
spin_unlock_irqrestore(div->core.lock, flags);
spin_unlock_irqrestore(div->core.lock, irqflags);
hw = &div->core.hw;
ret = clk_hw_register(NULL, hw);
......
......@@ -24,6 +24,8 @@
#define GCK_INDEX_DT_AUDIO_PLL 5
static DEFINE_SPINLOCK(mck_lock);
#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
{
......@@ -388,9 +390,16 @@ of_at91_clk_master_setup(struct device_node *np,
if (IS_ERR(regmap))
return;
hw = at91_clk_register_master(regmap, name, num_parents,
parent_names, layout,
characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
parent_names, layout,
characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto out_free_characteristics;
hw = at91_clk_register_master_div(regmap, name, "masterck_pres",
layout, characteristics,
&mck_lock, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto out_free_characteristics;
......
......@@ -48,7 +48,7 @@ extern const struct clk_master_layout at91sam9x5_master_layout;
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u32 divisors[5];
u8 have_div3_pres;
};
......@@ -155,10 +155,18 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
const char **parent_names, int num_parents);
struct clk_hw * __init
at91_clk_register_master(struct regmap *regmap, const char *name,
int num_parents, const char **parent_names,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics);
at91_clk_register_master_pres(struct regmap *regmap, const char *name,
int num_parents, const char **parent_names,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock, u32 flags, int chg_pid);
struct clk_hw * __init
at91_clk_register_master_div(struct regmap *regmap, const char *name,
const char *parent_names,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics,
spinlock_t *lock, u32 flags);
struct clk_hw * __init
at91_clk_sama7g5_register_master(struct regmap *regmap,
......@@ -190,14 +198,14 @@ struct clk_hw * __init
sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical);
const struct clk_pll_layout *layout, u32 flags);
struct clk_hw * __init
sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
struct clk_hw *parent_hw, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical);
const struct clk_pll_layout *layout, u32 flags);
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name,
......
......@@ -8,6 +8,7 @@
#include "pmc.h"
static DEFINE_SPINLOCK(pmc_pll_lock);
static DEFINE_SPINLOCK(mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 140000000, .max = 200000000 },
......@@ -76,11 +77,11 @@ static const struct {
char *p;
u8 id;
} sam9x60_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "qspick", .p = "masterck", .id = 19 },
{ .n = "qspick", .p = "masterck_div", .id = 19 },
};
static const struct {
......@@ -174,7 +175,6 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
struct regmap *regmap;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "td_slck");
if (i < 0)
......@@ -209,10 +209,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0);
if (IS_ERR(hw))
goto err_free;
main_osc_hw = hw;
......@@ -228,13 +225,24 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
"mainck", sam9x60_pmc->chws[PMC_MAIN],
0, &plla_characteristics,
&pll_frac_layout, true);
&pll_frac_layout,
/*
* This feeds pllack_divck which
* feeds CPU. It should not be
* disabled.
*/
CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
"pllack_fracck", 0, &plla_characteristics,
&pll_div_layout, true);
&pll_div_layout,
/*
* This feeds CPU. It should not
* be disabled.
*/
CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -243,13 +251,16 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
"main_osc", main_osc_hw, 1,
&upll_characteristics,
&pll_frac_layout, false);
&pll_frac_layout, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
"upllck_fracck", 1, &upll_characteristics,
&pll_div_layout, false);
&pll_div_layout,
CLK_SET_RATE_GATE |
CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT);
if (IS_ERR(hw))
goto err_free;
......@@ -258,9 +269,17 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[0] = md_slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack_divck";
hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
&sam9x60_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3,
parent_names, &sam9x60_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres", &sam9x60_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -276,7 +295,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[0] = md_slck_name;
parent_names[1] = td_slck_name;
parent_names[2] = "mainck";
parent_names[3] = "masterck";
parent_names[3] = "masterck_div";
parent_names[4] = "pllack_divck";
parent_names[5] = "upllck_divck";
for (i = 0; i < 2; i++) {
......@@ -308,7 +327,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sam9x60_pcr_layout,
sam9x60_periphck[i].n,
"masterck",
"masterck_div",
sam9x60_periphck[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 124000000, .max = 166000000 },
.divisors = { 1, 2, 4, 3 },
......@@ -40,14 +42,14 @@ static const struct {
char *p;
u8 id;
} sama5d2_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "iscck", .p = "masterck", .id = 18 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "iscck", .p = "masterck_div", .id = 18 },
};
static const struct {
......@@ -235,15 +237,25 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_MCK] = hw;
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
if (IS_ERR(hw))
goto err_free;
......@@ -259,7 +271,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < 3; i++) {
char name[6];
......@@ -290,7 +302,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_periphck[i].n,
"masterck",
"masterck_div",
sama5d2_periphck[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......@@ -317,7 +329,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 166000000 },
.divisors = { 1, 2, 4, 3 },
......@@ -40,14 +42,14 @@ static const struct {
char *p;
u8 id;
} sama5d3_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
};
static const struct {
......@@ -170,9 +172,19 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
......@@ -192,7 +204,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 3; i++) {
char name[6];
......@@ -222,7 +234,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d3_pcr_layout,
sama5d3_periphck[i].n,
"masterck",
"masterck_div",
sama5d3_periphck[i].id,
&sama5d3_periphck[i].r,
INT_MIN);
......
......@@ -7,6 +7,8 @@
#include "pmc.h"
static DEFINE_SPINLOCK(mck_lock);
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 125000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
......@@ -39,14 +41,14 @@ static const struct {
char *p;
u8 id;
} sama5d4_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "ddrck", .p = "masterck_div", .id = 2 },
{ .n = "lcdck", .p = "masterck_div", .id = 3 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
};
static const struct {
......@@ -185,15 +187,25 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
parent_names,
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE, INT_MIN);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_master_div(regmap, "masterck_div",
"masterck_pres",
&at91sam9x5_master_layout,
&mck_characteristics, &mck_lock,
CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->chws[PMC_MCK] = hw;
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
if (IS_ERR(hw))
goto err_free;
......@@ -215,7 +227,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
parent_names[4] = "masterck_div";
for (i = 0; i < 3; i++) {
char name[6];
......@@ -245,7 +257,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d4_pcr_layout,
sama5d4_periphck[i].n,
"masterck",
"masterck_div",
sama5d4_periphck[i].id,
&range, INT_MIN);
if (IS_ERR(hw))
......
This diff is collapsed.
......@@ -46,9 +46,17 @@
#define MMCM_CLK_DIV_DIVIDE BIT(11)
#define MMCM_CLK_DIV_NOCOUNT BIT(12)
struct axi_clkgen_limits {
unsigned int fpfd_min;
unsigned int fpfd_max;
unsigned int fvco_min;
unsigned int fvco_max;
};
struct axi_clkgen {
void __iomem *base;
struct clk_hw clk_hw;
struct axi_clkgen_limits limits;
};
static uint32_t axi_clkgen_lookup_filter(unsigned int m)
......@@ -100,12 +108,15 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m)
return 0x1f1f00fa;
}
static const unsigned int fpfd_min = 10000;
static const unsigned int fpfd_max = 300000;
static const unsigned int fvco_min = 600000;
static const unsigned int fvco_max = 1200000;
static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = {
.fpfd_min = 10000,
.fpfd_max = 300000,
.fvco_min = 600000,
.fvco_max = 1200000,
};
static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
unsigned long fin, unsigned long fout,
unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
{
unsigned long d, d_min, d_max, _d_min, _d_max;
......@@ -122,12 +133,12 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
*best_m = 0;
*best_dout = 0;
d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
d_max = min_t(unsigned long, fin / fpfd_min, 80);
d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1);
d_max = min_t(unsigned long, fin / limits->fpfd_min, 80);
again:
fvco_min_fract = fvco_min << fract_shift;
fvco_max_fract = fvco_max << fract_shift;
fvco_min_fract = limits->fvco_min << fract_shift;
fvco_max_fract = limits->fvco_max << fract_shift;
m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
......@@ -319,6 +330,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
unsigned long rate, unsigned long parent_rate)
{
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
unsigned int d, m, dout;
struct axi_clkgen_div_params params;
uint32_t power = 0;
......@@ -328,7 +340,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
if (parent_rate == 0 || rate == 0)
return -EINVAL;
axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
......@@ -368,10 +380,12 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
unsigned int d, m, dout;
unsigned long long tmp;
axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
......@@ -482,17 +496,9 @@ static const struct clk_ops axi_clkgen_ops = {
.get_parent = axi_clkgen_get_parent,
};
static const struct of_device_id axi_clkgen_ids[] = {
{
.compatible = "adi,axi-clkgen-2.00.a",
},
{ },
};
MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
static int axi_clkgen_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
const struct axi_clkgen_limits *dflt_limits;
struct axi_clkgen *axi_clkgen;
struct clk_init_data init;
const char *parent_names[2];
......@@ -501,11 +507,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
unsigned int i;
int ret;
if (!pdev->dev.of_node)
return -ENODEV;
id = of_match_node(axi_clkgen_ids, pdev->dev.of_node);
if (!id)
dflt_limits = device_get_match_data(&pdev->dev);
if (!dflt_limits)
return -ENODEV;
axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
......@@ -527,6 +530,8 @@ static int axi_clkgen_probe(struct platform_device *pdev)
return -EINVAL;
}
memcpy(&axi_clkgen->limits, dflt_limits, sizeof(axi_clkgen->limits));
clk_name = pdev->dev.of_node->name;
of_property_read_string(pdev->dev.of_node, "clock-output-names",
&clk_name);
......@@ -554,6 +559,15 @@ static int axi_clkgen_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id axi_clkgen_ids[] = {
{
.compatible = "adi,axi-clkgen-2.00.a",
.data = &axi_clkgen_zynq_default_limits,
},
{ }
};
MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
static struct platform_driver axi_clkgen_driver = {
.driver = {
.name = "adi-axi-clkgen",
......
......@@ -902,6 +902,10 @@ static int _si5351_clkout_set_disable_state(
static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
{
u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num);
u8 mask = val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
SI5351_PLL_RESET_A;
unsigned int v;
int err;
switch (val & SI5351_CLK_INPUT_MASK) {
case SI5351_CLK_INPUT_XTAL:
......@@ -909,9 +913,12 @@ static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num
return; /* pll not used, no need to reset */
}
si5351_reg_write(drvdata, SI5351_PLL_RESET,
val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
SI5351_PLL_RESET_A);
si5351_reg_write(drvdata, SI5351_PLL_RESET, mask);
err = regmap_read_poll_timeout(drvdata->regmap, SI5351_PLL_RESET, v,
!(v & mask), 0, 20000);
if (err < 0)
dev_err(&drvdata->client->dev, "Reset bit didn't clear\n");
dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n",
__func__, clk_hw_get_name(&drvdata->clkout[num].hw),
......
......@@ -2314,6 +2314,8 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
if (!clk)
return 0;
trace_clk_set_rate_range(clk->core, min, max);
if (min > max) {
pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
__func__, clk->core->name, clk->dev_id, clk->con_id,
......@@ -2381,6 +2383,8 @@ int clk_set_min_rate(struct clk *clk, unsigned long rate)
if (!clk)
return 0;
trace_clk_set_min_rate(clk->core, rate);
return clk_set_rate_range(clk, rate, clk->max_rate);
}
EXPORT_SYMBOL_GPL(clk_set_min_rate);
......@@ -2397,6 +2401,8 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate)
if (!clk)
return 0;
trace_clk_set_max_rate(clk->core, rate);
return clk_set_rate_range(clk, clk->min_rate, rate);
}
EXPORT_SYMBOL_GPL(clk_set_max_rate);
......
......@@ -605,7 +605,7 @@ static struct ti_dt_clk omap54xx_clks[] = {
int __init omap5xxx_dt_clk_init(void)
{
int rc;
struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
struct clk *abe_dpll_ref, *abe_dpll, *abe_dpll_byp, *sys_32k_ck, *usb_dpll;
ti_dt_clocks_register(omap54xx_clks);
......@@ -616,6 +616,16 @@ int __init omap5xxx_dt_clk_init(void)
abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_clk_mux");
sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
/*
* This must also be set to sys_32k_ck to match or
* the ABE DPLL will not lock on a warm reboot when
* ABE timers are used.
*/
abe_dpll_byp = clk_get_sys(NULL, "abe_dpll_bypass_clk_mux");
if (!rc)
rc = clk_set_parent(abe_dpll_byp, sys_32k_ck);
abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
if (!rc)
rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ);
......
......@@ -498,6 +498,7 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
{
struct clk_init_data *init;
struct fapll_synth *synth;
struct clk *clk = ERR_PTR(-ENOMEM);
init = kzalloc(sizeof(*init), GFP_KERNEL);
if (!init)
......@@ -520,13 +521,19 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
synth->hw.init = init;
synth->clk_pll = pll_clk;
return clk_register(NULL, &synth->hw);
clk = clk_register(NULL, &synth->hw);
if (IS_ERR(clk)) {
pr_err("failed to register clock\n");
goto free;
}
return clk;
free:
kfree(synth);
kfree(init);
return ERR_PTR(-ENOMEM);
return clk;
}
static void __init ti_fapll_setup(struct device_node *node)
......
......@@ -25,6 +25,17 @@
#define PMC_PLLBCK 8
#define PMC_AUDIOPLLCK 9
/* SAMA7G5 */
#define PMC_CPUPLL (PMC_MAIN + 1)
#define PMC_SYSPLL (PMC_MAIN + 2)
#define PMC_DDRPLL (PMC_MAIN + 3)
#define PMC_IMGPLL (PMC_MAIN + 4)
#define PMC_BAUDPLL (PMC_MAIN + 5)
#define PMC_AUDIOPMCPLL (PMC_MAIN + 6)
#define PMC_AUDIOIOPLL (PMC_MAIN + 7)
#define PMC_ETHPLL (PMC_MAIN + 8)
#define PMC_CPU (PMC_MAIN + 9)
#ifndef AT91_PMC_MOSCS
#define AT91_PMC_MOSCS 0 /* MOSCS Flag */
#define AT91_PMC_LOCKA 1 /* PLLA Lock */
......
......@@ -118,6 +118,50 @@ DEFINE_EVENT(clk_rate, clk_set_rate_complete,
TP_ARGS(core, rate)
);
DEFINE_EVENT(clk_rate, clk_set_min_rate,
TP_PROTO(struct clk_core *core, unsigned long rate),
TP_ARGS(core, rate)
);
DEFINE_EVENT(clk_rate, clk_set_max_rate,
TP_PROTO(struct clk_core *core, unsigned long rate),
TP_ARGS(core, rate)
);
DECLARE_EVENT_CLASS(clk_rate_range,
TP_PROTO(struct clk_core *core, unsigned long min, unsigned long max),
TP_ARGS(core, min, max),
TP_STRUCT__entry(
__string( name, core->name )
__field(unsigned long, min )
__field(unsigned long, max )
),
TP_fast_assign(
__assign_str(name, core->name);
__entry->min = min;
__entry->max = max;
),
TP_printk("%s min %lu max %lu", __get_str(name),
(unsigned long)__entry->min,
(unsigned long)__entry->max)
);
DEFINE_EVENT(clk_rate_range, clk_set_rate_range,
TP_PROTO(struct clk_core *core, unsigned long min, unsigned long max),
TP_ARGS(core, min, max)
);
DECLARE_EVENT_CLASS(clk_parent,
TP_PROTO(struct clk_core *core, struct clk_core *parent),
......
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