* [PATCH 02/14] ARM: clk: sunxi: Add driver for the H3 THS clock
[not found] <20160623192104.18720-1-megous@megous.com>
@ 2016-06-23 19:20 ` megous
2016-06-23 19:21 ` [PATCH 11/14] ARM: sun8i: clk: Add clk-factor rate application method megous
1 sibling, 0 replies; 3+ messages in thread
From: megous @ 2016-06-23 19:20 UTC (permalink / raw)
To: dev
Cc: linux-arm-kernel, Josef Gajdusek, Michael Turquette, Stephen Boyd,
Rob Herring, Mark Rutland, Maxime Ripard, Chen-Yu Tsai,
Emilio López, open list:COMMON CLK FRAMEWORK,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
From: Josef Gajdusek <atx@atx.name>
This patch adds a driver for the THS clock which is present on the
Allwinner H3.
Signed-off-by: Josef Gajdusek <atx@atx.name>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
drivers/clk/sunxi/Makefile | 1 +
drivers/clk/sunxi/clk-h3-ths.c | 98 +++++++++++++++++++++++
3 files changed, 100 insertions(+)
create mode 100644 drivers/clk/sunxi/clk-h3-ths.c
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8f7619d..5faae05 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -87,6 +87,7 @@ Required properties:
"allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
"allwinner,sun4i-a10-ve-clk" - for the Video Engine clock
"allwinner,sun6i-a31-display-clk" - for the display clocks
+ "allwinner,sun8i-h3-ths-clk" - for THS on H3
Required properties for all clocks:
- reg : shall be the control register address for the clock.
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 39d2044..8e245e3 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -9,6 +9,7 @@ obj-y += clk-a10-mod1.o
obj-y += clk-a10-pll2.o
obj-y += clk-a10-ve.o
obj-y += clk-a20-gmac.o
+obj-y += clk-h3-ths.o
obj-y += clk-mod0.o
obj-y += clk-simple-gates.o
obj-y += clk-sun4i-display.o
diff --git a/drivers/clk/sunxi/clk-h3-ths.c b/drivers/clk/sunxi/clk-h3-ths.c
new file mode 100644
index 0000000..c1d6d32
--- /dev/null
+++ b/drivers/clk/sunxi/clk-h3-ths.c
@@ -0,0 +1,98 @@
+/*
+ * sun8i THS clock driver
+ *
+ * Copyright (C) 2015 Josef Gajdusek
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define SUN8I_H3_THS_CLK_ENABLE 31
+#define SUN8I_H3_THS_CLK_DIVIDER_SHIFT 0
+#define SUN8I_H3_THS_CLK_DIVIDER_WIDTH 2
+
+static DEFINE_SPINLOCK(sun8i_h3_ths_clk_lock);
+
+static const struct clk_div_table sun8i_h3_ths_clk_table[] __initconst = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 6 },
+ { } /* sentinel */
+};
+
+static void __init sun8i_h3_ths_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ struct clk_gate *gate;
+ struct clk_divider *div;
+ const char *parent;
+ const char *clk_name = node->name;
+ void __iomem *reg;
+ int err;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+
+ if (IS_ERR(reg))
+ return;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ goto err_unmap;
+
+ div = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!div)
+ goto err_gate_free;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ parent = of_clk_get_parent_name(node, 0);
+
+ gate->reg = reg;
+ gate->bit_idx = SUN8I_H3_THS_CLK_ENABLE;
+ gate->lock = &sun8i_h3_ths_clk_lock;
+
+ div->reg = reg;
+ div->shift = SUN8I_H3_THS_CLK_DIVIDER_SHIFT;
+ div->width = SUN8I_H3_THS_CLK_DIVIDER_WIDTH;
+ div->table = sun8i_h3_ths_clk_table;
+ div->lock = &sun8i_h3_ths_clk_lock;
+
+ clk = clk_register_composite(NULL, clk_name, &parent, 1,
+ NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops,
+ CLK_SET_RATE_PARENT);
+
+ if (IS_ERR(clk))
+ goto err_div_free;
+
+ err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ if (err)
+ goto err_unregister_clk;
+
+ return;
+
+err_unregister_clk:
+ clk_unregister(clk);
+err_gate_free:
+ kfree(gate);
+err_div_free:
+ kfree(div);
+err_unmap:
+ iounmap(reg);
+}
+
+CLK_OF_DECLARE(sun8i_h3_ths_clk, "allwinner,sun8i-h3-ths-clk",
+ sun8i_h3_ths_clk_setup);
--
2.9.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 11/14] ARM: sun8i: clk: Add clk-factor rate application method
[not found] <20160623192104.18720-1-megous@megous.com>
2016-06-23 19:20 ` [PATCH 02/14] ARM: clk: sunxi: Add driver for the H3 THS clock megous
@ 2016-06-23 19:21 ` megous
2016-06-24 2:53 ` [linux-sunxi] " Julian Calaby
1 sibling, 1 reply; 3+ messages in thread
From: megous @ 2016-06-23 19:21 UTC (permalink / raw)
To: dev
Cc: linux-arm-kernel, Ondrej Jirman, Rob Herring, Mark Rutland,
Russell King, Maxime Ripard, Chen-Yu Tsai, Emilio López,
Michael Turquette, Stephen Boyd,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, open list:COMMON CLK FRAMEWORK
From: Ondrej Jirman <megous@megous.com>
PLL1 on H3 requires special factors application algorithm,
when the rate is changed. This algorithm was extracted
from the arisc code that handles frequency scaling
in the BSP kernel.
This commit adds optional apply function to
struct factors_data, that can implement non-trivial
factors application method, when necessary.
Also struct clk_factors_config is extended with position
of the PLL lock flag.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 2 +-
drivers/clk/sunxi/clk-factors.c | 34 +++++++++----------
drivers/clk/sunxi/clk-factors.h | 12 +++++++
drivers/clk/sunxi/clk-sunxi.c | 72 +++++++++++++++++++++++++++++++++++++++--
4 files changed, 98 insertions(+), 22 deletions(-)
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 8d86f57..58a49db 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -114,7 +114,7 @@
pll1: clk@01c20000 {
#clock-cells = <0>;
- compatible = "allwinner,sun8i-a23-pll1-clk";
+ compatible = "allwinner,sun8i-h3-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
clock-output-names = "pll1";
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index ddefe96..7c165db 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -34,13 +34,6 @@
#define FACTORS_MAX_PARENTS 5
-#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
-#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
-#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
-
-#define FACTOR_SET(bit, len, reg, val) \
- (((reg) & CLRMASK(len, bit)) | (val << (bit)))
-
static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -150,20 +143,24 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
if (factors->lock)
spin_lock_irqsave(factors->lock, flags);
- /* Fetch the register value */
- reg = readl(factors->reg);
+ if (factors->apply) {
+ factors->apply(factors, &req);
+ } else {
+ /* Fetch the register value */
+ reg = readl(factors->reg);
- /* Set up the new factors - macros do not do anything if width is 0 */
- reg = FACTOR_SET(config->nshift, config->nwidth, reg, req.n);
- reg = FACTOR_SET(config->kshift, config->kwidth, reg, req.k);
- reg = FACTOR_SET(config->mshift, config->mwidth, reg, req.m);
- reg = FACTOR_SET(config->pshift, config->pwidth, reg, req.p);
+ /* Set up the new factors - macros do not do anything if width is 0 */
+ reg = FACTOR_SET(config->nshift, config->nwidth, reg, req.n);
+ reg = FACTOR_SET(config->kshift, config->kwidth, reg, req.k);
+ reg = FACTOR_SET(config->mshift, config->mwidth, reg, req.m);
+ reg = FACTOR_SET(config->pshift, config->pwidth, reg, req.p);
- /* Apply them now */
- writel(reg, factors->reg);
+ /* Apply them now */
+ writel(reg, factors->reg);
- /* delay 500us so pll stabilizes */
- __delay((rate >> 20) * 500 / 2);
+ /* delay 500us so pll stabilizes */
+ __delay((rate >> 20) * 500 / 2);
+ }
if (factors->lock)
spin_unlock_irqrestore(factors->lock, flags);
@@ -213,6 +210,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
factors->config = data->table;
factors->get_factors = data->getter;
factors->recalc = data->recalc;
+ factors->apply = data->apply;
factors->lock = lock;
/* Add a gate if this factor clock can be gated */
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 1e63c5b..661a45a 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -6,6 +6,13 @@
#define SUNXI_FACTORS_NOT_APPLICABLE (0)
+#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
+#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
+#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
+
+#define FACTOR_SET(bit, len, reg, val) \
+ (((reg) & CLRMASK(len, bit)) | (val << (bit)))
+
struct clk_factors_config {
u8 nshift;
u8 nwidth;
@@ -16,6 +23,7 @@ struct clk_factors_config {
u8 pshift;
u8 pwidth;
u8 n_start;
+ u8 lock;
};
struct factors_request {
@@ -28,6 +36,8 @@ struct factors_request {
u8 p;
};
+struct clk_factors;
+
struct factors_data {
int enable;
int mux;
@@ -35,6 +45,7 @@ struct factors_data {
const struct clk_factors_config *table;
void (*getter)(struct factors_request *req);
void (*recalc)(struct factors_request *req);
+ void (*apply)(struct clk_factors *factors, struct factors_request *req);
const char *name;
};
@@ -44,6 +55,7 @@ struct clk_factors {
const struct clk_factors_config *config;
void (*get_factors)(struct factors_request *req);
void (*recalc)(struct factors_request *req);
+ void (*apply)(struct clk_factors *factors, struct factors_request *req);
spinlock_t *lock;
/* for cleanup */
struct clk_mux *mux;
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 838b22a..e4bb908 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/log2.h>
+#include <linux/delay.h>
#include "clk-factors.h"
@@ -200,6 +201,56 @@ static void sun8i_a23_get_pll1_factors(struct factors_request *req)
}
/**
+ * sun8i_h3_apply_pll1_factors() - applies n, k, m, p factors to the
+ * register using an algorithm that tries to reserve the PLL lock
+ */
+
+static void sun8i_h3_apply_pll1_factors(struct clk_factors *factors, struct factors_request *req)
+{
+ const struct clk_factors_config *config = factors->config;
+ u32 reg;
+
+ /* Fetch the register value */
+ reg = readl(factors->reg);
+
+ if (FACTOR_GET(config->pshift, config->pwidth, reg) < req->p) {
+ reg = FACTOR_SET(config->pshift, config->pwidth, reg, req->p);
+
+ writel(reg, factors->reg);
+ __delay(2000);
+ }
+
+ if (FACTOR_GET(config->mshift, config->mwidth, reg) < req->m) {
+ reg = FACTOR_SET(config->mshift, config->mwidth, reg, req->m);
+
+ writel(reg, factors->reg);
+ __delay(2000);
+ }
+
+ reg = FACTOR_SET(config->nshift, config->nwidth, reg, req->n);
+ reg = FACTOR_SET(config->kshift, config->kwidth, reg, req->k);
+
+ writel(reg, factors->reg);
+ __delay(20);
+
+ while (!(readl(factors->reg) & (1 << config->lock)));
+
+ if (FACTOR_GET(config->mshift, config->mwidth, reg) > req->m) {
+ reg = FACTOR_SET(config->mshift, config->mwidth, reg, req->m);
+
+ writel(reg, factors->reg);
+ __delay(2000);
+ }
+
+ if (FACTOR_GET(config->pshift, config->pwidth, reg) > req->p) {
+ reg = FACTOR_SET(config->pshift, config->pwidth, reg, req->p);
+
+ writel(reg, factors->reg);
+ __delay(2000);
+ }
+}
+
+/**
* sun4i_get_pll5_factors() - calculates n, k factors for PLL5
* PLL5 rate is calculated as follows
* rate = parent_rate * n * (k + 1)
@@ -451,6 +502,7 @@ static const struct clk_factors_config sun8i_a23_pll1_config = {
.pshift = 16,
.pwidth = 2,
.n_start = 1,
+ .lock = 28
};
static const struct clk_factors_config sun4i_pll5_config = {
@@ -513,6 +565,13 @@ static const struct factors_data sun8i_a23_pll1_data __initconst = {
.getter = sun8i_a23_get_pll1_factors,
};
+static const struct factors_data sun8i_h3_pll1_data __initconst = {
+ .enable = 31,
+ .table = &sun8i_a23_pll1_config,
+ .getter = sun8i_a23_get_pll1_factors,
+ .apply = sun8i_h3_apply_pll1_factors,
+};
+
static const struct factors_data sun7i_a20_pll4_data __initconst = {
.enable = 31,
.table = &sun4i_pll5_config,
@@ -590,12 +649,19 @@ static void __init sun6i_pll1_clk_setup(struct device_node *node)
CLK_OF_DECLARE(sun6i_pll1, "allwinner,sun6i-a31-pll1-clk",
sun6i_pll1_clk_setup);
-static void __init sun8i_pll1_clk_setup(struct device_node *node)
+static void __init sun8i_a23_pll1_clk_setup(struct device_node *node)
{
sunxi_factors_clk_setup(node, &sun8i_a23_pll1_data);
}
-CLK_OF_DECLARE(sun8i_pll1, "allwinner,sun8i-a23-pll1-clk",
- sun8i_pll1_clk_setup);
+CLK_OF_DECLARE(sun8i_a23_pll1, "allwinner,sun8i-a23-pll1-clk",
+ sun8i_a23_pll1_clk_setup);
+
+static void __init sun8i_h3_pll1_clk_setup(struct device_node *node)
+{
+ sunxi_factors_clk_setup(node, &sun8i_h3_pll1_data);
+}
+CLK_OF_DECLARE(sun8i_h3_pll1, "allwinner,sun8i-h3-pll1-clk",
+ sun8i_h3_pll1_clk_setup);
static void __init sun7i_pll4_clk_setup(struct device_node *node)
{
--
2.9.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [linux-sunxi] [PATCH 11/14] ARM: sun8i: clk: Add clk-factor rate application method
2016-06-23 19:21 ` [PATCH 11/14] ARM: sun8i: clk: Add clk-factor rate application method megous
@ 2016-06-24 2:53 ` Julian Calaby
0 siblings, 0 replies; 3+ messages in thread
From: Julian Calaby @ 2016-06-24 2:53 UTC (permalink / raw)
To: megous
Cc: Linux Sunxi, Mailing List, Arm, Rob Herring, Mark Rutland,
Russell King, Maxime Ripard, Chen-Yu Tsai, Emilio López,
Michael Turquette, Stephen Boyd,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list, open list:COMMON CLK FRAMEWORK
Hi Ondrej,
On Fri, Jun 24, 2016 at 5:21 AM, <megous@megous.com> wrote:
> From: Ondrej Jirman <megous@megous.com>
>
> PLL1 on H3 requires special factors application algorithm,
> when the rate is changed. This algorithm was extracted
> from the arisc code that handles frequency scaling
> in the BSP kernel.
>
> This commit adds optional apply function to
> struct factors_data, that can implement non-trivial
> factors application method, when necessary.
>
> Also struct clk_factors_config is extended with position
> of the PLL lock flag.
>
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> ---
> arch/arm/boot/dts/sun8i-h3.dtsi | 2 +-
> drivers/clk/sunxi/clk-factors.c | 34 +++++++++----------
> drivers/clk/sunxi/clk-factors.h | 12 +++++++
> drivers/clk/sunxi/clk-sunxi.c | 72 +++++++++++++++++++++++++++++++++++++++--
> 4 files changed, 98 insertions(+), 22 deletions(-)
Shouldn't the .dtsi changes be in a separate patch?
Thanks,
--
Julian Calaby
Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-06-24 2:53 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20160623192104.18720-1-megous@megous.com>
2016-06-23 19:20 ` [PATCH 02/14] ARM: clk: sunxi: Add driver for the H3 THS clock megous
2016-06-23 19:21 ` [PATCH 11/14] ARM: sun8i: clk: Add clk-factor rate application method megous
2016-06-24 2:53 ` [linux-sunxi] " Julian Calaby
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox