* [PATCH v2 01/11] clk: at91: rework main clk implementation
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 02/11] clk: at91: update main clk documentation Boris BREZILLON
` (9 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON, Boris BREZILLON
AT91 main clk a clk multiplexer and not a simple fixed rate clk as currently
implemented.
In some SoCs (sam9x5, sama5, sam9g45 families) this multiplexer can
choose among 2 sources: an internal RC oscillator circuit and an oscillator
using an external crystal.
In other Socs (sam9260, rm9200 families) the multiplexer source is
hardcoded to the external crystal oscillator.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
drivers/clk/at91/clk-main.c | 581 ++++++++++++++++++++++++++++++++++++++-----
drivers/clk/at91/pmc.c | 12 +
drivers/clk/at91/pmc.h | 6 +
3 files changed, 536 insertions(+), 63 deletions(-)
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 8e9e8cc..4e8a26a 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -30,99 +30,550 @@
#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
-struct clk_main {
+#define MOR_KEY_MASK (0xff << 16)
+
+struct clk_main_osc {
struct clk_hw hw;
struct at91_pmc *pmc;
- unsigned long rate;
unsigned int irq;
wait_queue_head_t wait;
};
-#define to_clk_main(hw) container_of(hw, struct clk_main, hw)
+#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
+
+struct clk_main_rc_osc {
+ struct clk_hw hw;
+ struct at91_pmc *pmc;
+ unsigned int irq;
+ wait_queue_head_t wait;
+ unsigned long frequency;
+ unsigned long accuracy;
+};
+
+#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
+
+struct clk_rm9200_main {
+ struct clk_hw hw;
+ struct at91_pmc *pmc;
+};
+
+#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
-static irqreturn_t clk_main_irq_handler(int irq, void *dev_id)
+struct clk_sam9x5_main {
+ struct clk_hw hw;
+ struct at91_pmc *pmc;
+ unsigned int irq;
+ wait_queue_head_t wait;
+ u8 parent;
+};
+
+#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
+
+static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id)
{
- struct clk_main *clkmain = (struct clk_main *)dev_id;
+ struct clk_main_osc *osc = dev_id;
- wake_up(&clkmain->wait);
- disable_irq_nosync(clkmain->irq);
+ wake_up(&osc->wait);
+ disable_irq_nosync(osc->irq);
return IRQ_HANDLED;
}
-static int clk_main_prepare(struct clk_hw *hw)
+static int clk_main_osc_prepare(struct clk_hw *hw)
{
- struct clk_main *clkmain = to_clk_main(hw);
- struct at91_pmc *pmc = clkmain->pmc;
- unsigned long halt_time, timeout;
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
u32 tmp;
+ tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+ if (tmp & AT91_PMC_OSCBYPASS)
+ return 0;
+
+ if (!(tmp & AT91_PMC_MOSCEN)) {
+ tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
+ pmc_write(pmc, AT91_CKGR_MOR, tmp);
+ }
+
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
- enable_irq(clkmain->irq);
- wait_event(clkmain->wait,
+ enable_irq(osc->irq);
+ wait_event(osc->wait,
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
}
- if (clkmain->rate)
- return 0;
+ return 0;
+}
+
+static void clk_main_osc_unprepare(struct clk_hw *hw)
+{
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
+ u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+
+ if (tmp & AT91_PMC_OSCBYPASS)
+ return;
+
+ if (!(tmp & AT91_PMC_MOSCEN))
+ return;
+
+ tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
+ pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
+}
+
+static int clk_main_osc_is_prepared(struct clk_hw *hw)
+{
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
+ u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+
+ if (tmp & AT91_PMC_OSCBYPASS)
+ return 1;
+
+ return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) &&
+ (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN));
+}
+
+static const struct clk_ops main_osc_ops = {
+ .prepare = clk_main_osc_prepare,
+ .unprepare = clk_main_osc_unprepare,
+ .is_prepared = clk_main_osc_is_prepared,
+};
+
+static struct clk * __init
+at91_clk_register_main_osc(struct at91_pmc *pmc,
+ unsigned int irq,
+ const char *name,
+ const char *parent_name,
+ bool bypass)
+{
+ int ret;
+ struct clk_main_osc *osc;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!pmc || !irq || !name || !parent_name)
+ return ERR_PTR(-EINVAL);
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &main_osc_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
+
+ osc->hw.init = &init;
+ osc->pmc = pmc;
+ osc->irq = irq;
+
+ init_waitqueue_head(&osc->wait);
+ irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
+ ret = request_irq(osc->irq, clk_main_osc_irq_handler,
+ IRQF_TRIGGER_HIGH, name, osc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (bypass)
+ pmc_write(pmc, AT91_CKGR_MOR,
+ (pmc_read(pmc, AT91_CKGR_MOR) &
+ ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) |
+ AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
+
+ clk = clk_register(NULL, &osc->hw);
+ if (IS_ERR(clk)) {
+ free_irq(irq, osc);
+ kfree(osc);
+ }
+
+ return clk;
+}
+
+void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
+ struct at91_pmc *pmc)
+{
+ struct clk *clk;
+ unsigned int irq;
+ const char *name = np->name;
+ const char *parent_name;
+ bool bypass;
+
+ of_property_read_string(np, "clock-output-names", &name);
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+ parent_name = of_clk_get_parent_name(np, 0);
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq)
+ return;
+
+ clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id)
+{
+ struct clk_main_rc_osc *osc = dev_id;
+
+ wake_up(&osc->wait);
+ disable_irq_nosync(osc->irq);
+
+ return IRQ_HANDLED;
+}
+
+static int clk_main_rc_osc_prepare(struct clk_hw *hw)
+{
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
+ u32 tmp;
+
+ tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+
+ if (!(tmp & AT91_PMC_MOSCRCEN)) {
+ tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY;
+ pmc_write(pmc, AT91_CKGR_MOR, tmp);
+ }
+
+ while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) {
+ enable_irq(osc->irq);
+ wait_event(osc->wait,
+ pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS);
+ }
+
+ return 0;
+}
+
+static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
+{
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
+ u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+
+ if (!(tmp & AT91_PMC_MOSCRCEN))
+ return;
+
+ tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN);
+ pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
+}
+
+static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
+{
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
+ struct at91_pmc *pmc = osc->pmc;
+
+ return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) &&
+ (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN));
+}
+
+static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
+
+ return osc->frequency;
+}
+
+static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
+ unsigned long parent_acc)
+{
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
+
+ return osc->accuracy;
+}
+
+static const struct clk_ops main_rc_osc_ops = {
+ .prepare = clk_main_rc_osc_prepare,
+ .unprepare = clk_main_rc_osc_unprepare,
+ .is_prepared = clk_main_rc_osc_is_prepared,
+ .recalc_rate = clk_main_rc_osc_recalc_rate,
+ .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
+};
+
+static struct clk * __init
+at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
+ unsigned int irq,
+ const char *name,
+ u32 frequency, u32 accuracy)
+{
+ int ret;
+ struct clk_main_rc_osc *osc;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!pmc || !irq || !name || !frequency)
+ return ERR_PTR(-EINVAL);
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &main_osc_ops;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ /*
+ * Internal RC oscillator must be enabled on reset, so
+ * keep it enabled even if unused.
+ */
+ init.flags = CLK_IGNORE_UNUSED;
+
+ osc->hw.init = &init;
+ osc->pmc = pmc;
+ osc->irq = irq;
+ osc->frequency = frequency;
+ osc->accuracy = accuracy;
+
+ init_waitqueue_head(&osc->wait);
+ irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
+ ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler,
+ IRQF_TRIGGER_HIGH, name, osc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ clk = clk_register(NULL, &osc->hw);
+ if (IS_ERR(clk)) {
+ free_irq(irq, osc);
+ kfree(osc);
+ }
+
+ return clk;
+}
+
+void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
+ struct at91_pmc *pmc)
+{
+ struct clk *clk;
+ unsigned int irq;
+ u32 frequency = 0;
+ u32 accuracy = 0;
+ const char *name = np->name;
+
+ of_property_read_string(np, "clock-output-names", &name);
+ of_property_read_u32(np, "clock-frequency", &frequency);
+ of_property_read_u32(np, "clock-accuracy", &accuracy);
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq)
+ return;
+
+ clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency,
+ accuracy);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+
+static int clk_main_probe_frequency(struct at91_pmc *pmc)
+{
+ unsigned long prep_time, timeout;
+ u32 tmp;
timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
do {
- halt_time = jiffies;
+ prep_time = jiffies;
tmp = pmc_read(pmc, AT91_CKGR_MCFR);
if (tmp & AT91_PMC_MAINRDY)
return 0;
usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
- } while (time_before(halt_time, timeout));
+ } while (time_before(prep_time, timeout));
- return 0;
+ return -ETIMEDOUT;
}
-static int clk_main_is_prepared(struct clk_hw *hw)
+static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
+ unsigned long parent_rate)
{
- struct clk_main *clkmain = to_clk_main(hw);
+ u32 tmp;
+
+ if (parent_rate)
+ return parent_rate;
+
+ tmp = pmc_read(pmc, AT91_CKGR_MCFR);
+ if (!(tmp & AT91_PMC_MAINRDY))
+ return 0;
- return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
+ return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
}
-static unsigned long clk_main_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static int clk_rm9200_main_prepare(struct clk_hw *hw)
{
- u32 tmp;
- struct clk_main *clkmain = to_clk_main(hw);
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
+
+ return clk_main_probe_frequency(clkmain->pmc);
+}
+
+static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
+{
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
+
+ return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY);
+}
+
+static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
+
+ return clk_main_recalc_rate(clkmain->pmc, parent_rate);
+}
+
+static const struct clk_ops rm9200_main_ops = {
+ .prepare = clk_rm9200_main_prepare,
+ .is_prepared = clk_rm9200_main_is_prepared,
+ .recalc_rate = clk_rm9200_main_recalc_rate,
+};
+
+static struct clk * __init
+at91_clk_register_rm9200_main(struct at91_pmc *pmc,
+ const char *name,
+ const char *parent_name)
+{
+ struct clk_rm9200_main *clkmain;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!pmc || !name)
+ return ERR_PTR(-EINVAL);
+
+ if (!parent_name)
+ return ERR_PTR(-EINVAL);
+
+ clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
+ if (!clkmain)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &rm9200_main_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
+
+ clkmain->hw.init = &init;
+ clkmain->pmc = pmc;
+
+ clk = clk_register(NULL, &clkmain->hw);
+ if (IS_ERR(clk))
+ kfree(clkmain);
+
+ return clk;
+}
+
+void __init of_at91rm9200_clk_main_setup(struct device_node *np,
+ struct at91_pmc *pmc)
+{
+ struct clk *clk;
+ const char *parent_name;
+ const char *name = np->name;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = at91_clk_register_rm9200_main(pmc, name, parent_name);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id)
+{
+ struct clk_sam9x5_main *clkmain = dev_id;
+
+ wake_up(&clkmain->wait);
+ disable_irq_nosync(clkmain->irq);
+
+ return IRQ_HANDLED;
+}
+
+static int clk_sam9x5_main_prepare(struct clk_hw *hw)
+{
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
struct at91_pmc *pmc = clkmain->pmc;
- if (clkmain->rate)
- return clkmain->rate;
+ while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
+ enable_irq(clkmain->irq);
+ wait_event(clkmain->wait,
+ pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
+ }
+
+ return clk_main_probe_frequency(pmc);
+}
- tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF;
- clkmain->rate = (tmp * parent_rate) / MAINF_DIV;
+static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
+{
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
- return clkmain->rate;
+ return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
}
-static const struct clk_ops main_ops = {
- .prepare = clk_main_prepare,
- .is_prepared = clk_main_is_prepared,
- .recalc_rate = clk_main_recalc_rate,
+static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
+
+ return clk_main_recalc_rate(clkmain->pmc, parent_rate);
+}
+
+static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
+ struct at91_pmc *pmc = clkmain->pmc;
+ u32 tmp;
+
+ if (index > 1)
+ return -EINVAL;
+
+ tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+
+ if (index && !(tmp & AT91_PMC_MOSCSEL))
+ pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
+ else if (!index && (tmp & AT91_PMC_MOSCSEL))
+ pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
+
+ while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
+ enable_irq(clkmain->irq);
+ wait_event(clkmain->wait,
+ pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
+ }
+
+ return 0;
+}
+
+static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
+{
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
+
+ return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN);
+}
+
+static const struct clk_ops sam9x5_main_ops = {
+ .prepare = clk_sam9x5_main_prepare,
+ .is_prepared = clk_sam9x5_main_is_prepared,
+ .recalc_rate = clk_sam9x5_main_recalc_rate,
+ .set_parent = clk_sam9x5_main_set_parent,
+ .get_parent = clk_sam9x5_main_get_parent,
};
static struct clk * __init
-at91_clk_register_main(struct at91_pmc *pmc,
- unsigned int irq,
- const char *name,
- const char *parent_name,
- unsigned long rate)
+at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
+ unsigned int irq,
+ const char *name,
+ const char **parent_names,
+ int num_parents)
{
int ret;
- struct clk_main *clkmain;
+ struct clk_sam9x5_main *clkmain;
struct clk *clk = NULL;
struct clk_init_data init;
if (!pmc || !irq || !name)
return ERR_PTR(-EINVAL);
- if (!rate && !parent_name)
+ if (!parent_names || !num_parents)
return ERR_PTR(-EINVAL);
clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
@@ -130,19 +581,20 @@ at91_clk_register_main(struct at91_pmc *pmc,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.ops = &main_ops;
- init.parent_names = parent_name ? &parent_name : NULL;
- init.num_parents = parent_name ? 1 : 0;
- init.flags = parent_name ? 0 : CLK_IS_ROOT;
+ init.ops = &sam9x5_main_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_PARENT_GATE;
clkmain->hw.init = &init;
- clkmain->rate = rate;
clkmain->pmc = pmc;
clkmain->irq = irq;
+ clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) &
+ AT91_PMC_MOSCEN);
init_waitqueue_head(&clkmain->wait);
irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
- ret = request_irq(clkmain->irq, clk_main_irq_handler,
- IRQF_TRIGGER_HIGH, "clk-main", clkmain);
+ ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler,
+ IRQF_TRIGGER_HIGH, name, clkmain);
if (ret)
return ERR_PTR(ret);
@@ -155,33 +607,36 @@ at91_clk_register_main(struct at91_pmc *pmc,
return clk;
}
-
-
-static void __init
-of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc)
+void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
+ struct at91_pmc *pmc)
{
struct clk *clk;
+ const char *parent_names[2];
+ int num_parents;
unsigned int irq;
- const char *parent_name;
const char *name = np->name;
- u32 rate = 0;
+ int i;
+
+ num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ if (num_parents <= 0 || num_parents > 2)
+ return;
+
+ for (i = 0; i < num_parents; ++i) {
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ if (!parent_names[i])
+ return;
+ }
- parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
- of_property_read_u32(np, "clock-frequency", &rate);
+
irq = irq_of_parse_and_map(np, 0);
if (!irq)
return;
- clk = at91_clk_register_main(pmc, irq, name, parent_name, rate);
+ clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names,
+ num_parents);
if (IS_ERR(clk))
return;
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
-
-void __init of_at91rm9200_clk_main_setup(struct device_node *np,
- struct at91_pmc *pmc)
-{
- of_at91_clk_main_setup(np, pmc);
-}
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 6a61477..dc5fdde 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -231,9 +231,21 @@ out_free_pmc:
static const struct of_device_id pmc_clk_ids[] __initconst = {
/* Main clock */
{
+ .compatible = "atmel,at91rm9200-clk-main-osc",
+ .data = of_at91rm9200_clk_main_osc_setup,
+ },
+ {
+ .compatible = "atmel,at91sam9x5-clk-main-rc-osc",
+ .data = of_at91sam9x5_clk_main_rc_osc_setup,
+ },
+ {
.compatible = "atmel,at91rm9200-clk-main",
.data = of_at91rm9200_clk_main_setup,
},
+ {
+ .compatible = "atmel,at91sam9x5-clk-main",
+ .data = of_at91sam9x5_clk_main_setup,
+ },
/* PLL clocks */
{
.compatible = "atmel,at91rm9200-clk-pll",
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 4413509..42cc7cc 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -58,8 +58,14 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range);
+extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
+ struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
+ struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
+ struct at91_pmc *pmc);
extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
struct at91_pmc *pmc);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 02/11] clk: at91: update main clk documentation
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 01/11] clk: at91: rework main " Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-04-18 12:49 ` Nicolas Ferre
2014-03-24 8:27 ` [PATCH v2 03/11] clk: at91: add slow clks driver Boris BREZILLON
` (8 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, Boris BREZILLON, linux-kernel, linux-arm-kernel,
linux-doc
Update main clk documentation to match main clk implementation rework.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
.../devicetree/bindings/clock/at91-clock.txt | 56 ++++++++++++++++----
1 file changed, 47 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
index cd5e239..9a7025b 100644
--- a/Documentation/devicetree/bindings/clock/at91-clock.txt
+++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
@@ -15,8 +15,13 @@ Required properties:
All at91 specific clocks (clocks defined below) must be child
node of the PMC node.
+ "atmel,at91rm9200-clk-main-osc"
+ "atmel,at91sam9x5-clk-main-rc-osc"
+ at91 main clk sources
+
+ "atmel,at91sam9x5-clk-main"
"atmel,at91rm9200-clk-main":
- at91 main oscillator
+ at91 main clock
"atmel,at91rm9200-clk-master" or
"atmel,at91sam9x5-clk-master":
@@ -85,24 +90,57 @@ For example:
/* put at91 clocks here */
};
+Required properties for main clock oscillator:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<0>".
+- clock-frequency : define the internal RC oscillator frequency.
+
+Optional properties:
+- clock-accuracy : define the internal RC oscillator accuracy.
+
+For example:
+ main_rc_osc: main_rc_osc {
+ compatible = "atmel,at91sam9x5-clk-main-rc-osc";
+ interrupt-parent = <&pmc>;
+ interrupts = <0>;
+ clock-frequency = <12000000>;
+ clock-accuracy = <50000000>;
+ };
+
+Required properties for main clock internal RC oscillator:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<0>".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall encode the main osc source clk sources (see atmel datasheet).
+
+Optional properties:
+- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
+ on XIN.
+
+ clock signal is directly provided on XIN pin.
+
+For example:
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
+ interrupt-parent = <&pmc>;
+ interrupts = <0>;
+ #clock-cells = <0>;
+ clocks = <&main_xtal>;
+ };
+
Required properties for main clock:
- interrupt-parent : must reference the PMC node.
- interrupts : shall be set to "<0>".
- #clock-cells : from common clock binding; shall be set to 0.
-- clocks (optional if clock-frequency is provided) : shall be the slow clock
- phandle. This clock is used to calculate the main clock rate if
- "clock-frequency" is not provided.
-- clock-frequency : the main oscillator frequency.Prefer the use of
- "clock-frequency" over automatic clock rate calculation.
+- clocks : shall encode the main clk sources (see atmel datasheet).
For example:
main: mainck {
- compatible = "atmel,at91rm9200-clk-main";
+ compatible = "atmel,at91sam9x5-clk-main";
interrupt-parent = <&pmc>;
interrupts = <0>;
#clock-cells = <0>;
- clocks = <&ck32k>;
- clock-frequency = <18432000>;
+ clocks = <&main_rc_osc &main_osc>;
};
Required properties for master clock:
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 02/11] clk: at91: update main clk documentation
2014-03-24 8:27 ` [PATCH v2 02/11] clk: at91: update main clk documentation Boris BREZILLON
@ 2014-04-18 12:49 ` Nicolas Ferre
2014-04-18 13:00 ` Boris BREZILLON
0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Ferre @ 2014-04-18 12:49 UTC (permalink / raw)
To: Boris BREZILLON, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
On 24/03/2014 09:27, Boris BREZILLON :
> Update main clk documentation to match main clk implementation rework.
>
> Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
> ---
> .../devicetree/bindings/clock/at91-clock.txt | 56 ++++++++++++++++----
> 1 file changed, 47 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
> index cd5e239..9a7025b 100644
> --- a/Documentation/devicetree/bindings/clock/at91-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
> @@ -15,8 +15,13 @@ Required properties:
> All at91 specific clocks (clocks defined below) must be child
> node of the PMC node.
>
> + "atmel,at91rm9200-clk-main-osc"
> + "atmel,at91sam9x5-clk-main-rc-osc"
> + at91 main clk sources
> +
> + "atmel,at91sam9x5-clk-main"
> "atmel,at91rm9200-clk-main":
> - at91 main oscillator
> + at91 main clock
>
> "atmel,at91rm9200-clk-master" or
> "atmel,at91sam9x5-clk-master":
> @@ -85,24 +90,57 @@ For example:
> /* put at91 clocks here */
> };
>
> +Required properties for main clock oscillator:
> +- interrupt-parent : must reference the PMC node.
> +- interrupts : shall be set to "<0>".
> +- clock-frequency : define the internal RC oscillator frequency.
> +
> +Optional properties:
> +- clock-accuracy : define the internal RC oscillator accuracy.
> +
> +For example:
> + main_rc_osc: main_rc_osc {
> + compatible = "atmel,at91sam9x5-clk-main-rc-osc";
> + interrupt-parent = <&pmc>;
> + interrupts = <0>;
> + clock-frequency = <12000000>;
> + clock-accuracy = <50000000>;
> + };
Don't you swapped this example above with the description below?
> +Required properties for main clock internal RC oscillator:
> +- interrupt-parent : must reference the PMC node.
> +- interrupts : shall be set to "<0>".
> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clocks : shall encode the main osc source clk sources (see atmel datasheet).
> +
> +Optional properties:
> +- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
> + on XIN.
> +
> + clock signal is directly provided on XIN pin.
> +
> +For example:
> + main_osc: main_osc {
> + compatible = "atmel,at91rm9200-clk-main-osc";
> + interrupt-parent = <&pmc>;
> + interrupts = <0>;
> + #clock-cells = <0>;
> + clocks = <&main_xtal>;
> + };
> +
> Required properties for main clock:
> - interrupt-parent : must reference the PMC node.
> - interrupts : shall be set to "<0>".
> - #clock-cells : from common clock binding; shall be set to 0.
> -- clocks (optional if clock-frequency is provided) : shall be the slow clock
> - phandle. This clock is used to calculate the main clock rate if
> - "clock-frequency" is not provided.
> -- clock-frequency : the main oscillator frequency.Prefer the use of
> - "clock-frequency" over automatic clock rate calculation.
> +- clocks : shall encode the main clk sources (see atmel datasheet).
>
> For example:
> main: mainck {
> - compatible = "atmel,at91rm9200-clk-main";
> + compatible = "atmel,at91sam9x5-clk-main";
> interrupt-parent = <&pmc>;
> interrupts = <0>;
> #clock-cells = <0>;
> - clocks = <&ck32k>;
> - clock-frequency = <18432000>;
> + clocks = <&main_rc_osc &main_osc>;
> };
>
> Required properties for master clock:
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 02/11] clk: at91: update main clk documentation
2014-04-18 12:49 ` Nicolas Ferre
@ 2014-04-18 13:00 ` Boris BREZILLON
0 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-04-18 13:00 UTC (permalink / raw)
To: Nicolas Ferre, Boris BREZILLON, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel
On 18/04/2014 14:49, Nicolas Ferre wrote:
> On 24/03/2014 09:27, Boris BREZILLON :
>> Update main clk documentation to match main clk implementation rework.
>>
>> Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
>> ---
>> .../devicetree/bindings/clock/at91-clock.txt | 56 ++++++++++++++++----
>> 1 file changed, 47 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
>> index cd5e239..9a7025b 100644
>> --- a/Documentation/devicetree/bindings/clock/at91-clock.txt
>> +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
>> @@ -15,8 +15,13 @@ Required properties:
>> All at91 specific clocks (clocks defined below) must be child
>> node of the PMC node.
>>
>> + "atmel,at91rm9200-clk-main-osc"
>> + "atmel,at91sam9x5-clk-main-rc-osc"
>> + at91 main clk sources
>> +
>> + "atmel,at91sam9x5-clk-main"
>> "atmel,at91rm9200-clk-main":
>> - at91 main oscillator
>> + at91 main clock
>>
>> "atmel,at91rm9200-clk-master" or
>> "atmel,at91sam9x5-clk-master":
>> @@ -85,24 +90,57 @@ For example:
>> /* put at91 clocks here */
>> };
>>
>> +Required properties for main clock oscillator:
>> +- interrupt-parent : must reference the PMC node.
>> +- interrupts : shall be set to "<0>".
>> +- clock-frequency : define the internal RC oscillator frequency.
>> +
>> +Optional properties:
>> +- clock-accuracy : define the internal RC oscillator accuracy.
>> +
>> +For example:
>> + main_rc_osc: main_rc_osc {
>> + compatible = "atmel,at91sam9x5-clk-main-rc-osc";
>> + interrupt-parent = <&pmc>;
>> + interrupts = <0>;
>> + clock-frequency = <12000000>;
>> + clock-accuracy = <50000000>;
>> + };
> Don't you swapped this example above with the description below?
Actually I only swapped the "Required properties" lines, I'll fix it.
Thanks,
Boris
>
>
>> +Required properties for main clock internal RC oscillator:
>> +- interrupt-parent : must reference the PMC node.
>> +- interrupts : shall be set to "<0>".
>> +- #clock-cells : from common clock binding; shall be set to 0.
>> +- clocks : shall encode the main osc source clk sources (see atmel datasheet).
>> +
>> +Optional properties:
>> +- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
>> + on XIN.
>> +
>> + clock signal is directly provided on XIN pin.
>> +
>> +For example:
>> + main_osc: main_osc {
>> + compatible = "atmel,at91rm9200-clk-main-osc";
>> + interrupt-parent = <&pmc>;
>> + interrupts = <0>;
>> + #clock-cells = <0>;
>> + clocks = <&main_xtal>;
>> + };
>> +
>> Required properties for main clock:
>> - interrupt-parent : must reference the PMC node.
>> - interrupts : shall be set to "<0>".
>> - #clock-cells : from common clock binding; shall be set to 0.
>> -- clocks (optional if clock-frequency is provided) : shall be the slow clock
>> - phandle. This clock is used to calculate the main clock rate if
>> - "clock-frequency" is not provided.
>> -- clock-frequency : the main oscillator frequency.Prefer the use of
>> - "clock-frequency" over automatic clock rate calculation.
>> +- clocks : shall encode the main clk sources (see atmel datasheet).
>>
>> For example:
>> main: mainck {
>> - compatible = "atmel,at91rm9200-clk-main";
>> + compatible = "atmel,at91sam9x5-clk-main";
>> interrupt-parent = <&pmc>;
>> interrupts = <0>;
>> #clock-cells = <0>;
>> - clocks = <&ck32k>;
>> - clock-frequency = <18432000>;
>> + clocks = <&main_rc_osc &main_osc>;
>> };
>>
>> Required properties for master clock:
>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 03/11] clk: at91: add slow clks driver
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 01/11] clk: at91: rework main " Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 02/11] clk: at91: update main clk documentation Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 04/11] clk: at91: add slow clk documentation Boris BREZILLON
` (7 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON, Boris BREZILLON
AT91 slow clk is a clk multiplexer.
In some SoCs (sam9x5, sama5, sam9g45 families) this multiplexer can
choose among 2 sources: an internal RC oscillator circuit and an oscillator
using an external crystal.
In other Socs (sam9260 family) the multiplexer source is hardcoded with
the OSCSEL signal.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
drivers/clk/at91/Makefile | 4 +-
drivers/clk/at91/clk-slow.c | 467 ++++++++++++++++++++++++++++++++++++++++++
drivers/clk/at91/pmc.h | 3 +
drivers/clk/at91/sckc.c | 57 ++++++
drivers/clk/at91/sckc.h | 22 ++
include/linux/clk/at91_pmc.h | 1 +
6 files changed, 552 insertions(+), 2 deletions(-)
create mode 100644 drivers/clk/at91/clk-slow.c
create mode 100644 drivers/clk/at91/sckc.c
create mode 100644 drivers/clk/at91/sckc.h
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 46c1d3d..4998aee 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -2,8 +2,8 @@
# Makefile for at91 specific clk
#
-obj-y += pmc.o
-obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o
+obj-y += pmc.o sckc.o
+obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
obj-y += clk-system.o clk-peripheral.o clk-programmable.o
obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
new file mode 100644
index 0000000..fc2d54c
--- /dev/null
+++ b/drivers/clk/at91/clk-slow.c
@@ -0,0 +1,467 @@
+/*
+ * drivers/clk/at91/clk-slow.c
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include "pmc.h"
+#include "sckc.h"
+
+#define SLOW_CLOCK_FREQ 32768
+#define SLOWCK_SW_CYCLES 5
+#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
+ SLOW_CLOCK_FREQ)
+
+#define AT91_SCKC_CR 0x00
+#define AT91_SCKC_RCEN (1 << 0)
+#define AT91_SCKC_OSC32EN (1 << 1)
+#define AT91_SCKC_OSC32BYP (1 << 2)
+#define AT91_SCKC_OSCSEL (1 << 3)
+
+struct clk_slow_osc {
+ struct clk_hw hw;
+ void __iomem *sckcr;
+ unsigned long startup_usec;
+};
+
+#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
+
+struct clk_slow_rc_osc {
+ struct clk_hw hw;
+ void __iomem *sckcr;
+ unsigned long frequency;
+ unsigned long accuracy;
+ unsigned long startup_usec;
+};
+
+#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
+
+struct clk_sam9260_slow {
+ struct clk_hw hw;
+ struct at91_pmc *pmc;
+};
+
+#define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
+
+struct clk_sam9x5_slow {
+ struct clk_hw hw;
+ void __iomem *sckcr;
+ u8 parent;
+};
+
+#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
+
+
+static int clk_slow_osc_prepare(struct clk_hw *hw)
+{
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
+ void __iomem *sckcr = osc->sckcr;
+ u32 tmp = readl(sckcr);
+
+ if (tmp & AT91_SCKC_OSC32BYP)
+ return 0;
+
+ writel(tmp | AT91_SCKC_OSC32EN, sckcr);
+
+ usleep_range(osc->startup_usec, osc->startup_usec + 1);
+
+ return 0;
+}
+
+static void clk_slow_osc_unprepare(struct clk_hw *hw)
+{
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
+ void __iomem *sckcr = osc->sckcr;
+ u32 tmp = readl(sckcr);
+
+ if (tmp & AT91_SCKC_OSC32BYP)
+ return;
+
+ writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
+}
+
+static int clk_slow_osc_is_prepared(struct clk_hw *hw)
+{
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
+ void __iomem *sckcr = osc->sckcr;
+ u32 tmp = readl(sckcr);
+
+ if (tmp & AT91_SCKC_OSC32BYP)
+ return 1;
+
+ return !!(tmp & AT91_SCKC_OSC32EN);
+}
+
+static const struct clk_ops slow_osc_ops = {
+ .prepare = clk_slow_osc_prepare,
+ .unprepare = clk_slow_osc_unprepare,
+ .is_prepared = clk_slow_osc_is_prepared,
+};
+
+static struct clk * __init
+at91_clk_register_slow_osc(void __iomem *sckcr,
+ const char *name,
+ const char *parent_name,
+ unsigned long startup,
+ bool bypass)
+{
+ struct clk_slow_osc *osc;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!sckcr || !name || !parent_name)
+ return ERR_PTR(-EINVAL);
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &slow_osc_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
+
+ osc->hw.init = &init;
+ osc->sckcr = sckcr;
+ osc->startup_usec = startup;
+
+ if (bypass)
+ writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
+ sckcr);
+
+ clk = clk_register(NULL, &osc->hw);
+ if (IS_ERR(clk))
+ kfree(osc);
+
+ return clk;
+}
+
+void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
+ void __iomem *sckcr)
+{
+ struct clk *clk;
+ const char *parent_name;
+ const char *name = np->name;
+ u32 startup;
+ bool bypass;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ of_property_read_string(np, "clock-output-names", &name);
+ of_property_read_u32(np, "atmel,startup-time-usec", &startup);
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
+ bypass);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+
+ return osc->frequency;
+}
+
+static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
+ unsigned long parent_acc)
+{
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+
+ return osc->accuracy;
+}
+
+static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
+{
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+ void __iomem *sckcr = osc->sckcr;
+
+ writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
+
+ usleep_range(osc->startup_usec, osc->startup_usec + 1);
+
+ return 0;
+}
+
+static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
+{
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+ void __iomem *sckcr = osc->sckcr;
+
+ writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
+}
+
+static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
+{
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+
+ return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
+}
+
+static const struct clk_ops slow_rc_osc_ops = {
+ .prepare = clk_slow_rc_osc_prepare,
+ .unprepare = clk_slow_rc_osc_unprepare,
+ .is_prepared = clk_slow_rc_osc_is_prepared,
+ .recalc_rate = clk_slow_rc_osc_recalc_rate,
+ .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
+};
+
+static struct clk * __init
+at91_clk_register_slow_rc_osc(void __iomem *sckcr,
+ const char *name,
+ unsigned long frequency,
+ unsigned long accuracy,
+ unsigned long startup)
+{
+ struct clk_slow_rc_osc *osc;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!sckcr || !name)
+ return ERR_PTR(-EINVAL);
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &slow_rc_osc_ops;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ init.flags = CLK_IS_ROOT;
+
+ osc->hw.init = &init;
+ osc->sckcr = sckcr;
+ osc->frequency = frequency;
+ osc->accuracy = accuracy;
+ osc->startup_usec = startup;
+
+ clk = clk_register(NULL, &osc->hw);
+ if (IS_ERR(clk))
+ kfree(osc);
+
+ return clk;
+}
+
+void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
+ void __iomem *sckcr)
+{
+ struct clk *clk;
+ u32 frequency = 0;
+ u32 accuracy = 0;
+ u32 startup = 0;
+ const char *name = np->name;
+
+ of_property_read_string(np, "clock-output-names", &name);
+ of_property_read_u32(np, "clock-frequency", &frequency);
+ of_property_read_u32(np, "clock-accuracy", &accuracy);
+ of_property_read_u32(np, "atmel,startup-time-usec", &startup);
+
+ clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
+ startup);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
+ void __iomem *sckcr = slowck->sckcr;
+ u32 tmp;
+
+ if (index > 1)
+ return -EINVAL;
+
+ tmp = readl(sckcr);
+
+ if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
+ (index && (tmp & AT91_SCKC_OSCSEL)))
+ return 0;
+
+ if (index)
+ tmp |= AT91_SCKC_OSCSEL;
+ else
+ tmp &= ~AT91_SCKC_OSCSEL;
+
+ writel(tmp, sckcr);
+
+ usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
+
+ return 0;
+}
+
+static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
+{
+ struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
+
+ return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
+}
+
+static const struct clk_ops sam9x5_slow_ops = {
+ .set_parent = clk_sam9x5_slow_set_parent,
+ .get_parent = clk_sam9x5_slow_get_parent,
+};
+
+static struct clk * __init
+at91_clk_register_sam9x5_slow(void __iomem *sckcr,
+ const char *name,
+ const char **parent_names,
+ int num_parents)
+{
+ struct clk_sam9x5_slow *slowck;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!sckcr || !name || !parent_names || !num_parents)
+ return ERR_PTR(-EINVAL);
+
+ slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
+ if (!slowck)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &sam9x5_slow_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = 0;
+
+ slowck->hw.init = &init;
+ slowck->sckcr = sckcr;
+ slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
+
+ clk = clk_register(NULL, &slowck->hw);
+ if (IS_ERR(clk))
+ kfree(slowck);
+
+ return clk;
+}
+
+void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
+ void __iomem *sckcr)
+{
+ struct clk *clk;
+ const char *parent_names[2];
+ int num_parents;
+ const char *name = np->name;
+ int i;
+
+ num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ if (num_parents <= 0 || num_parents > 2)
+ return;
+
+ for (i = 0; i < num_parents; ++i) {
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ if (!parent_names[i])
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
+ num_parents);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
+{
+ struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
+
+ return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL);
+}
+
+static const struct clk_ops sam9260_slow_ops = {
+ .get_parent = clk_sam9260_slow_get_parent,
+};
+
+static struct clk * __init
+at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
+ const char *name,
+ const char **parent_names,
+ int num_parents)
+{
+ struct clk_sam9260_slow *slowck;
+ struct clk *clk = NULL;
+ struct clk_init_data init;
+
+ if (!pmc || !name)
+ return ERR_PTR(-EINVAL);
+
+ if (!parent_names || !num_parents)
+ return ERR_PTR(-EINVAL);
+
+ slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
+ if (!slowck)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &sam9260_slow_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = 0;
+
+ slowck->hw.init = &init;
+ slowck->pmc = pmc;
+
+ clk = clk_register(NULL, &slowck->hw);
+ if (IS_ERR(clk))
+ kfree(slowck);
+
+ return clk;
+}
+
+void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
+ struct at91_pmc *pmc)
+{
+ struct clk *clk;
+ const char *parent_names[2];
+ int num_parents;
+ const char *name = np->name;
+ int i;
+
+ num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ if (num_parents <= 0 || num_parents > 1)
+ return;
+
+ for (i = 0; i < num_parents; ++i) {
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ if (!parent_names[i])
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = at91_clk_register_sam9260_slow(pmc, name, parent_names,
+ num_parents);
+ if (IS_ERR(clk))
+ return;
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 42cc7cc..6c76259 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -58,6 +58,9 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range);
+extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
+ struct at91_pmc *pmc);
+
extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
struct at91_pmc *pmc);
extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
new file mode 100644
index 0000000..1184d76
--- /dev/null
+++ b/drivers/clk/at91/sckc.c
@@ -0,0 +1,57 @@
+/*
+ * drivers/clk/at91/sckc.c
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "sckc.h"
+
+static const struct of_device_id sckc_clk_ids[] __initconst = {
+ /* Slow clock */
+ {
+ .compatible = "atmel,at91sam9x5-clk-slow-osc",
+ .data = of_at91sam9x5_clk_slow_osc_setup,
+ },
+ {
+ .compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
+ .data = of_at91sam9x5_clk_slow_rc_osc_setup,
+ },
+ {
+ .compatible = "atmel,at91sam9x5-clk-slow",
+ .data = of_at91sam9x5_clk_slow_setup,
+ },
+ { /*sentinel*/ }
+};
+
+static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
+{
+ struct device_node *childnp;
+ void (*clk_setup)(struct device_node *, void __iomem *);
+ const struct of_device_id *clk_id;
+ void __iomem *regbase = of_iomap(np, 0);
+
+ if (!regbase)
+ return;
+
+ for_each_child_of_node(np, childnp) {
+ clk_id = of_match_node(sckc_clk_ids, childnp);
+ if (!clk_id)
+ continue;
+ clk_setup = clk_id->data;
+ clk_setup(childnp, regbase);
+ }
+}
+CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
+ of_at91sam9x5_sckc_setup);
diff --git a/drivers/clk/at91/sckc.h b/drivers/clk/at91/sckc.h
new file mode 100644
index 0000000..836fcf5
--- /dev/null
+++ b/drivers/clk/at91/sckc.h
@@ -0,0 +1,22 @@
+/*
+ * drivers/clk/at91/sckc.h
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __AT91_SCKC_H_
+#define __AT91_SCKC_H_
+
+extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
+ void __iomem *sckcr);
+extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
+ void __iomem *sckcr);
+extern void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
+ void __iomem *sckcr);
+
+#endif /* __AT91_SCKC_H_ */
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index a6911eb..de4268d 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -155,6 +155,7 @@ extern void __iomem *at91_pmc_base;
#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9] */
+#define AT91_PMC_OSCSEL (1 << 7) /* Slow Oscillator Selection [some SAM9] */
#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 04/11] clk: at91: add slow clk documentation
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (2 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 03/11] clk: at91: add slow clks driver Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-04-18 13:09 ` Nicolas Ferre
2014-03-24 8:27 ` [PATCH v2 05/11] ARM: at91/dt: move sama5d3 SoC to the new main/slow clk model Boris BREZILLON
` (6 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Add slow clk, and slow oscillators documentation.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
.../devicetree/bindings/clock/at91-clock.txt | 72 ++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
index 9a7025b..820061c 100644
--- a/Documentation/devicetree/bindings/clock/at91-clock.txt
+++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
@@ -6,6 +6,16 @@ This binding uses the common clock binding[1].
Required properties:
- compatible : shall be one of the following:
+ "atmel,at91sam9x5-sckc":
+ at91 SCKC (Slow Clock Controller)
+ This node contains the slow clock definitions.
+
+ "atmel,at91sam9x5-clk-slow-osc":
+ at91 slow oscillator
+
+ "atmel,at91sam9x5-clk-slow-rc-osc":
+ at91 internal slow RC oscillator
+
"atmel,at91rm9200-pmc" or
"atmel,at91sam9g45-pmc" or
"atmel,at91sam9n12-pmc" or
@@ -15,6 +25,11 @@ Required properties:
All at91 specific clocks (clocks defined below) must be child
node of the PMC node.
+ "atmel,at91sam9x5-clk-slow" (under sckc node)
+ or
+ "atmel,at91sam9260-clk-slow" (under pmc node):
+ at91 slow clk
+
"atmel,at91rm9200-clk-main-osc"
"atmel,at91sam9x5-clk-main-rc-osc"
at91 main clk sources
@@ -59,6 +74,63 @@ Required properties:
"atmel,at91sam9x5-clk-utmi":
at91 utmi clock
+Required properties for SCKC node:
+- reg : defines the IO memory reserved for the SCKC.
+- #size-cells : shall be 0 (reg is used to encode clk id).
+- #address-cells : shall be 1 (reg is used to encode clk id).
+
+
+For example:
+ ckc: sckc@fffffe50 {
+ compatible = "atmel,sama5d3-pmc";
+ reg = <0xfffffe50 0x4>
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ /* put at91 slow clocks here */
+ };
+
+
+Required properties for internal slow RC oscillator:
+- #clock-cells : from common clock binding; shall be set to 0.
+- clock-frequency : define the internal RC oscillator frequency.
+
+Optional properties:
+- clock-accuracy : define the internal RC oscillator accuracy.
+
+For example:
+ slow_rc_osc: slow_rc_osc {
+ compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
+ clock-frequency = <32768>;
+ clock-accuracy = <50000000>;
+ };
+
+Required properties for slow oscillator:
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall encode the main osc source clk sources (see atmel datasheet).
+
+Optional properties:
+- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
+ provided on XIN.
+
+For example:
+ slow_osc: slow_osc {
+ compatible = "atmel,at91rm9200-clk-slow-osc";
+ #clock-cells = <0>;
+ clocks = <&slow_xtal>;
+ };
+
+Required properties for slow clock:
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall encode the slow clk sources (see atmel datasheet).
+
+For example:
+ clk32k: slck {
+ compatible = "atmel,at91sam9x5-clk-slow";
+ #clock-cells = <0>;
+ clocks = <&slow_rc_osc &slow_osc>;
+ };
+
Required properties for PMC node:
- reg : defines the IO memory reserved for the PMC.
- #size-cells : shall be 0 (reg is used to encode clk id).
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 04/11] clk: at91: add slow clk documentation
2014-03-24 8:27 ` [PATCH v2 04/11] clk: at91: add slow clk documentation Boris BREZILLON
@ 2014-04-18 13:09 ` Nicolas Ferre
0 siblings, 0 replies; 16+ messages in thread
From: Nicolas Ferre @ 2014-04-18 13:09 UTC (permalink / raw)
To: Boris BREZILLON, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
On 24/03/2014 09:27, Boris BREZILLON :
> Add slow clk, and slow oscillators documentation.
>
> Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
> ---
> .../devicetree/bindings/clock/at91-clock.txt | 72 ++++++++++++++++++++
> 1 file changed, 72 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
> index 9a7025b..820061c 100644
> --- a/Documentation/devicetree/bindings/clock/at91-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
> @@ -6,6 +6,16 @@ This binding uses the common clock binding[1].
>
> Required properties:
> - compatible : shall be one of the following:
> + "atmel,at91sam9x5-sckc":
> + at91 SCKC (Slow Clock Controller)
> + This node contains the slow clock definitions.
> +
> + "atmel,at91sam9x5-clk-slow-osc":
> + at91 slow oscillator
> +
> + "atmel,at91sam9x5-clk-slow-rc-osc":
> + at91 internal slow RC oscillator
> +
> "atmel,at91rm9200-pmc" or
> "atmel,at91sam9g45-pmc" or
> "atmel,at91sam9n12-pmc" or
> @@ -15,6 +25,11 @@ Required properties:
> All at91 specific clocks (clocks defined below) must be child
> node of the PMC node.
>
> + "atmel,at91sam9x5-clk-slow" (under sckc node)
> + or
> + "atmel,at91sam9260-clk-slow" (under pmc node):
> + at91 slow clk
> +
> "atmel,at91rm9200-clk-main-osc"
> "atmel,at91sam9x5-clk-main-rc-osc"
> at91 main clk sources
> @@ -59,6 +74,63 @@ Required properties:
> "atmel,at91sam9x5-clk-utmi":
> at91 utmi clock
>
> +Required properties for SCKC node:
> +- reg : defines the IO memory reserved for the SCKC.
> +- #size-cells : shall be 0 (reg is used to encode clk id).
> +- #address-cells : shall be 1 (reg is used to encode clk id).
> +
> +
> +For example:
> + ckc: sckc@fffffe50 {
s/ckc/sckc/ ?
> + compatible = "atmel,sama5d3-pmc";
> + reg = <0xfffffe50 0x4>
> + #size-cells = <0>;
> + #address-cells = <1>;
> +
> + /* put at91 slow clocks here */
> + };
> +
> +
> +Required properties for internal slow RC oscillator:
> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clock-frequency : define the internal RC oscillator frequency.
> +
> +Optional properties:
> +- clock-accuracy : define the internal RC oscillator accuracy.
> +
> +For example:
> + slow_rc_osc: slow_rc_osc {
> + compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
> + clock-frequency = <32768>;
> + clock-accuracy = <50000000>;
> + };
> +
> +Required properties for slow oscillator:
> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clocks : shall encode the main osc source clk sources (see atmel datasheet).
> +
> +Optional properties:
> +- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
> + provided on XIN.
> +
> +For example:
> + slow_osc: slow_osc {
> + compatible = "atmel,at91rm9200-clk-slow-osc";
> + #clock-cells = <0>;
> + clocks = <&slow_xtal>;
> + };
> +
> +Required properties for slow clock:
> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clocks : shall encode the slow clk sources (see atmel datasheet).
> +
> +For example:
> + clk32k: slck {
> + compatible = "atmel,at91sam9x5-clk-slow";
> + #clock-cells = <0>;
> + clocks = <&slow_rc_osc &slow_osc>;
> + };
> +
> Required properties for PMC node:
> - reg : defines the IO memory reserved for the PMC.
> - #size-cells : shall be 0 (reg is used to encode clk id).
>
--
Nicolas Ferre
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 05/11] ARM: at91/dt: move sama5d3 SoC to the new main/slow clk model
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (3 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 04/11] clk: at91: add slow clk documentation Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 06/11] ARM: at91/dt: add xtal frequencies to sama5d3xcm boards Boris BREZILLON
` (5 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, Boris BREZILLON, linux-doc, linux-kernel,
Boris BREZILLON, linux-arm-kernel
Replace the old main and clk definitions (fixed rate clk) by the new main and
slow clk subtree definition (ck = mux(rc_osc, osc)).
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
arch/arm/boot/dts/sama5d3.dtsi | 61 ++++++++++++++++++++++++++++++++++++----
1 file changed, 55 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index 3d5faf8..015797d 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -59,6 +59,18 @@
};
clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
adc_op_clk: adc_op_clk{
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -760,18 +772,29 @@
#size-cells = <0>;
#interrupt-cells = <1>;
- clk32k: slck {
- compatible = "fixed-clock";
+ main_rc_osc: main_rc_osc {
+ compatible = "atmel,at91sam9x5-clk-main-rc-osc";
#clock-cells = <0>;
- clock-frequency = <32768>;
+ interrupt-parent = <&pmc>;
+ interrupts = <AT91_PMC_MOSCRCS>;
+ clock-frequency = <12000000>;
+ clock-accuracy = <50000000>;
};
- main: mainck {
- compatible = "atmel,at91rm9200-clk-main";
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
#clock-cells = <0>;
interrupt-parent = <&pmc>;
interrupts = <AT91_PMC_MOSCS>;
- clocks = <&clk32k>;
+ clocks = <&main_xtal>;
+ };
+
+ main: mainck {
+ compatible = "atmel,at91sam9x5-clk-main";
+ #clock-cells = <0>;
+ interrupt-parent = <&pmc>;
+ interrupts = <AT91_PMC_MOSCSELS>;
+ clocks = <&main_rc_osc &main_osc>;
};
plla: pllack {
@@ -1100,6 +1123,32 @@
status = "disabled";
};
+ sckc@fffffe50 {
+ compatible = "atmel,at91sam9x5-sckc";
+ reg = <0xfffffe50 0x4>;
+
+ slow_rc_osc: slow_rc_osc {
+ compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-accuracy = <50000000>;
+ atmel,startup-time-usec = <75>;
+ };
+
+ slow_osc: slow_osc {
+ compatible = "atmel,at91sam9x5-clk-slow-osc";
+ #clock-cells = <0>;
+ clocks = <&slow_xtal>;
+ atmel,startup-time-usec = <1200000>;
+ };
+
+ clk32k: slowck {
+ compatible = "atmel,at91sam9x5-clk-slow";
+ #clock-cells = <0>;
+ clocks = <&slow_rc_osc &slow_osc>;
+ };
+ };
+
rtc@fffffeb0 {
compatible = "atmel,at91rm9200-rtc";
reg = <0xfffffeb0 0x30>;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 06/11] ARM: at91/dt: add xtal frequencies to sama5d3xcm boards
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (4 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 05/11] ARM: at91/dt: move sama5d3 SoC to the new main/slow clk model Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 07/11] ARM: at91/dt: add xtal frequencies to sama5d3 xplained board Boris BREZILLON
` (4 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON, Boris BREZILLON
Define crystal frequencies of sama5d3xcm boards.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
arch/arm/boot/dts/sama5d3xcm.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi
index f55ed07..b320fad 100644
--- a/arch/arm/boot/dts/sama5d3xcm.dtsi
+++ b/arch/arm/boot/dts/sama5d3xcm.dtsi
@@ -18,6 +18,16 @@
reg = <0x20000000 0x20000000>;
};
+ clocks {
+ slow_xtal: slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal: main_xtal {
+ clock-frequency = <12000000>;
+ };
+ };
+
ahb {
apb {
spi0: spi@f0004000 {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 07/11] ARM: at91/dt: add xtal frequencies to sama5d3 xplained board
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (5 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 06/11] ARM: at91/dt: add xtal frequencies to sama5d3xcm boards Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 08/11] ARM: at91/dt: move at91sam9261 SoC to the new main clock model Boris BREZILLON
` (3 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON, Boris BREZILLON
Define crystal properties of sama5d3 xplained board.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
arch/arm/boot/dts/at91-sama5d3_xplained.dts | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index ce13755..df5b707 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -21,6 +21,16 @@
reg = <0x20000000 0x10000000>;
};
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
+ };
+
ahb {
apb {
mmc0: mmc@f0000000 {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 08/11] ARM: at91/dt: move at91sam9261 SoC to the new main clock model
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (6 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 07/11] ARM: at91/dt: add xtal frequencies to sama5d3 xplained board Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 09/11] ARM: at91/dt: define main xtal frequency of the at91sam9261ek board Boris BREZILLON
` (2 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
Acked-by: Jean-Jacques HIBLOT <jjhiblot@traphandler.com>
---
arch/arm/boot/dts/at91sam9261.dtsi | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/at91sam9261.dtsi
index e21dda0..e00fabc 100644
--- a/arch/arm/boot/dts/at91sam9261.dtsi
+++ b/arch/arm/boot/dts/at91sam9261.dtsi
@@ -45,6 +45,14 @@
reg = <0x20000000 0x08000000>;
};
+ clocks {
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -534,7 +542,7 @@
compatible = "atmel,at91rm9200-clk-main";
#clock-cells = <0>;
interrupts-extended = <&pmc AT91_PMC_MOSCS>;
- clocks = <&clk32k>;
+ clocks = <&main_xtal>;
};
plla: pllack {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 09/11] ARM: at91/dt: define main xtal frequency of the at91sam9261ek board
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (7 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 08/11] ARM: at91/dt: move at91sam9261 SoC to the new main clock model Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 10/11] ARM: at91/dt: move at91sam9rl SoC to the new slow/main clock models Boris BREZILLON
2014-03-24 8:27 ` [PATCH v2 11/11] ARM: at91/dt: define sam9rlek crystal frequencies Boris BREZILLON
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Define at91sam9261ek main crystal frequency.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
Acked-by: Jean-Jacques HIBLOT <jjhiblot@traphandler.com>
---
arch/arm/boot/dts/at91sam9261ek.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index 2ce527e..7175986 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -29,6 +29,10 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ main_xtal: main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 10/11] ARM: at91/dt: move at91sam9rl SoC to the new slow/main clock models
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (8 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 09/11] ARM: at91/dt: define main xtal frequency of the at91sam9261ek board Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
[not found] ` <1395649643-9146-11-git-send-email-b.brezillon.dev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-03-24 8:27 ` [PATCH v2 11/11] ARM: at91/dt: define sam9rlek crystal frequencies Boris BREZILLON
10 siblings, 1 reply; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Move at91sam9rl SoC to the new main/slow clock model.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/boot/dts/at91sam9rl.dtsi | 47 +++++++++++++++++++++++++++++++------
1 file changed, 40 insertions(+), 7 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi
index 63e1784..56220d8 100644
--- a/arch/arm/boot/dts/at91sam9rl.dtsi
+++ b/arch/arm/boot/dts/at91sam9rl.dtsi
@@ -48,6 +48,20 @@
reg = <0x20000000 0x04000000>;
};
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -548,17 +562,11 @@
#size-cells = <0>;
#interrupt-cells = <1>;
- clk32k: slck {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
main: mainck {
compatible = "atmel,at91rm9200-clk-main";
#clock-cells = <0>;
interrupts-extended = <&pmc AT91_PMC_MOSCS>;
- clocks = <&clk32k>;
+ clocks = <&main_xtal>;
};
plla: pllack {
@@ -769,6 +777,31 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
status = "disabled";
};
+
+ sckc@fffffd50 {
+ compatible = "atmel,at91sam9x5-sckc";
+
+ slow_osc: slow_osc {
+ compatible = "atmel,at91sam9x5-clk-slow-osc";
+ #clock-cells = <0>;
+ atmel,startup-time-usec = <1200000>;
+ clocks = <&slow_xtal>;
+ };
+
+ slow_rc_osc: slow_rc_osc {
+ compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
+ #clock-cells = <0>;
+ atmel,startup-time-usec = <75>;
+ clock-frequency = <32768>;
+ clock-accuracy = <50000000>;
+ };
+
+ clk32k: slck {
+ compatible = "atmel,at91sam9x5-clk-slow";
+ #clock-cells = <0>;
+ clocks = <&slow_rc_osc &slow_osc>;
+ };
+ };
};
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 11/11] ARM: at91/dt: define sam9rlek crystal frequencies
2014-03-24 8:27 [PATCH v2 00/11] ARM: at91: rework main and slow clk implementation Boris BREZILLON
` (9 preceding siblings ...)
2014-03-24 8:27 ` [PATCH v2 10/11] ARM: at91/dt: move at91sam9rl SoC to the new slow/main clock models Boris BREZILLON
@ 2014-03-24 8:27 ` Boris BREZILLON
10 siblings, 0 replies; 16+ messages in thread
From: Boris BREZILLON @ 2014-03-24 8:27 UTC (permalink / raw)
To: Nicolas Ferre, Mike Turquette, Alexandre Belloni,
Jean-Jacques Hiblot, Jean-Christophe PLAGNIOL-VILLARD
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Define at91sam9rlek crystal frequencies.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
arch/arm/boot/dts/at91sam9rlek.dts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/at91sam9rlek.dts b/arch/arm/boot/dts/at91sam9rlek.dts
index cddb378..85b68b9 100644
--- a/arch/arm/boot/dts/at91sam9rlek.dts
+++ b/arch/arm/boot/dts/at91sam9rlek.dts
@@ -25,6 +25,14 @@
#size-cells = <1>;
ranges;
+ slow_xtal: slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal: main_xtal {
+ clock-frequency = <12000000>;
+ };
+
main_clock: clock {
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 16+ messages in thread