All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masahiro Yamada <yamada.masahiro@socionext.com>
To: linux-clk@vger.kernel.org
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@codeaurora.org>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 2/3] clk: uniphier: add CPU-gear change (cpufreq) support
Date: Thu, 24 Nov 2016 14:57:40 +0900	[thread overview]
Message-ID: <1479967061-25975-2-git-send-email-yamada.masahiro@socionext.com> (raw)
In-Reply-To: <1479967061-25975-1-git-send-email-yamada.masahiro@socionext.com>

Core support code for CPU frequency changes, which will be used by
the generic cpufreq driver.

The register view is different from the generic clk-mux; it has
a separate status register, and an update bit to load the register
setting.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2: None

 drivers/clk/uniphier/Makefile               |   3 +
 drivers/clk/uniphier/clk-uniphier-core.c    |   3 +
 drivers/clk/uniphier/clk-uniphier-cpugear.c | 115 ++++++++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier.h         |  17 +++-
 4 files changed, 136 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-cpugear.c

diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index f27b3603..665d1d6 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -1,8 +1,11 @@
 obj-y	+= clk-uniphier-core.o
+
+obj-y	+= clk-uniphier-cpugear.o
 obj-y	+= clk-uniphier-fixed-factor.o
 obj-y	+= clk-uniphier-fixed-rate.o
 obj-y	+= clk-uniphier-gate.o
 obj-y	+= clk-uniphier-mux.o
+
 obj-y	+= clk-uniphier-sys.o
 obj-y	+= clk-uniphier-mio.o
 obj-y	+= clk-uniphier-peri.o
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index 726a10a..b6c02f5 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -27,6 +27,9 @@ static struct clk_hw *uniphier_clk_register(struct device *dev,
 					const struct uniphier_clk_data *data)
 {
 	switch (data->type) {
+	case UNIPHIER_CLK_TYPE_CPUGEAR:
+		return uniphier_clk_register_cpugear(dev, regmap, data->name,
+						     &data->cpugear);
 	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
 		return uniphier_clk_register_fixed_factor(dev, data->name,
 							  &data->factor);
diff --git a/drivers/clk/uniphier/clk-uniphier-cpugear.c b/drivers/clk/uniphier/clk-uniphier-cpugear.c
new file mode 100644
index 0000000..9bff26e
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-cpugear.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.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.
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_CLK_CPUGEAR_STAT	0	/* status */
+#define UNIPHIER_CLK_CPUGEAR_SET	4	/* set */
+#define UNIPHIER_CLK_CPUGEAR_UPD	8	/* update */
+#define   UNIPHIER_CLK_CPUGEAR_UPD_BIT	BIT(0)
+
+struct uniphier_clk_cpugear {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
+#define to_uniphier_clk_cpugear(_hw) \
+			container_of(_hw, struct uniphier_clk_cpugear, hw)
+
+static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				gear->mask, index);
+	if (ret)
+		return ret;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT);
+	if (ret)
+		return ret;
+
+	return regmap_read_poll_timeout(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
+				val, !(val & UNIPHIER_CLK_CPUGEAR_UPD_BIT),
+				0, 1);
+}
+
+static u8 uniphier_clk_cpugear_get_parent(struct clk_hw *hw)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(gear->regmap,
+			  gear->regbase + UNIPHIER_CLK_CPUGEAR_STAT, &val);
+	if (ret)
+		return ret;
+
+	val &= gear->mask;
+
+	return val < num_parents ? val : -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_cpugear_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = uniphier_clk_cpugear_set_parent,
+	.get_parent = uniphier_clk_cpugear_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					 struct regmap *regmap,
+					 const char *name,
+				const struct uniphier_clk_cpugear_data *data)
+{
+	struct uniphier_clk_cpugear *gear;
+	struct clk_init_data init;
+	int ret;
+
+	gear = devm_kzalloc(dev, sizeof(*gear), GFP_KERNEL);
+	if (!gear)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &uniphier_clk_cpugear_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = data->parent_names;
+	init.num_parents = data->num_parents,
+
+	gear->regmap = regmap;
+	gear->regbase = data->regbase;
+	gear->mask = data->mask;
+	gear->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &gear->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &gear->hw;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 4eb4f6d..62816f8 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -20,15 +20,24 @@ struct clk_hw;
 struct device;
 struct regmap;
 
-#define UNIPHIER_CLK_MUX_MAX_PARENTS	8
+#define UNIPHIER_CLK_CPUGEAR_MAX_PARENTS	16
+#define UNIPHIER_CLK_MUX_MAX_PARENTS		8
 
 enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_CPUGEAR,
 	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
 	UNIPHIER_CLK_TYPE_FIXED_RATE,
 	UNIPHIER_CLK_TYPE_GATE,
 	UNIPHIER_CLK_TYPE_MUX,
 };
 
+struct uniphier_clk_cpugear_data {
+	const char *parent_names[UNIPHIER_CLK_CPUGEAR_MAX_PARENTS];
+	unsigned int num_parents;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
 struct uniphier_clk_fixed_factor_data {
 	const char *parent_name;
 	unsigned int mult;
@@ -58,6 +67,7 @@ struct uniphier_clk_data {
 	enum uniphier_clk_type type;
 	int idx;
 	union {
+		struct uniphier_clk_cpugear_data cpugear;
 		struct uniphier_clk_fixed_factor_data factor;
 		struct uniphier_clk_fixed_rate_data rate;
 		struct uniphier_clk_gate_data gate;
@@ -90,7 +100,10 @@ struct uniphier_clk_data {
 		},						\
 	}
 
-
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					     struct regmap *regmap,
+					     const char *name,
+				const struct uniphier_clk_cpugear_data *data);
 struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
 						  const char *name,
 			const struct uniphier_clk_fixed_factor_data *data);
-- 
2.7.4

WARNING: multiple messages have this Message-ID (diff)
From: yamada.masahiro@socionext.com (Masahiro Yamada)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 2/3] clk: uniphier: add CPU-gear change (cpufreq) support
Date: Thu, 24 Nov 2016 14:57:40 +0900	[thread overview]
Message-ID: <1479967061-25975-2-git-send-email-yamada.masahiro@socionext.com> (raw)
In-Reply-To: <1479967061-25975-1-git-send-email-yamada.masahiro@socionext.com>

Core support code for CPU frequency changes, which will be used by
the generic cpufreq driver.

The register view is different from the generic clk-mux; it has
a separate status register, and an update bit to load the register
setting.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2: None

 drivers/clk/uniphier/Makefile               |   3 +
 drivers/clk/uniphier/clk-uniphier-core.c    |   3 +
 drivers/clk/uniphier/clk-uniphier-cpugear.c | 115 ++++++++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier.h         |  17 +++-
 4 files changed, 136 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-cpugear.c

diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index f27b3603..665d1d6 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -1,8 +1,11 @@
 obj-y	+= clk-uniphier-core.o
+
+obj-y	+= clk-uniphier-cpugear.o
 obj-y	+= clk-uniphier-fixed-factor.o
 obj-y	+= clk-uniphier-fixed-rate.o
 obj-y	+= clk-uniphier-gate.o
 obj-y	+= clk-uniphier-mux.o
+
 obj-y	+= clk-uniphier-sys.o
 obj-y	+= clk-uniphier-mio.o
 obj-y	+= clk-uniphier-peri.o
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index 726a10a..b6c02f5 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -27,6 +27,9 @@ static struct clk_hw *uniphier_clk_register(struct device *dev,
 					const struct uniphier_clk_data *data)
 {
 	switch (data->type) {
+	case UNIPHIER_CLK_TYPE_CPUGEAR:
+		return uniphier_clk_register_cpugear(dev, regmap, data->name,
+						     &data->cpugear);
 	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
 		return uniphier_clk_register_fixed_factor(dev, data->name,
 							  &data->factor);
diff --git a/drivers/clk/uniphier/clk-uniphier-cpugear.c b/drivers/clk/uniphier/clk-uniphier-cpugear.c
new file mode 100644
index 0000000..9bff26e
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-cpugear.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.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.
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_CLK_CPUGEAR_STAT	0	/* status */
+#define UNIPHIER_CLK_CPUGEAR_SET	4	/* set */
+#define UNIPHIER_CLK_CPUGEAR_UPD	8	/* update */
+#define   UNIPHIER_CLK_CPUGEAR_UPD_BIT	BIT(0)
+
+struct uniphier_clk_cpugear {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
+#define to_uniphier_clk_cpugear(_hw) \
+			container_of(_hw, struct uniphier_clk_cpugear, hw)
+
+static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				gear->mask, index);
+	if (ret)
+		return ret;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT);
+	if (ret)
+		return ret;
+
+	return regmap_read_poll_timeout(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
+				val, !(val & UNIPHIER_CLK_CPUGEAR_UPD_BIT),
+				0, 1);
+}
+
+static u8 uniphier_clk_cpugear_get_parent(struct clk_hw *hw)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(gear->regmap,
+			  gear->regbase + UNIPHIER_CLK_CPUGEAR_STAT, &val);
+	if (ret)
+		return ret;
+
+	val &= gear->mask;
+
+	return val < num_parents ? val : -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_cpugear_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = uniphier_clk_cpugear_set_parent,
+	.get_parent = uniphier_clk_cpugear_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					 struct regmap *regmap,
+					 const char *name,
+				const struct uniphier_clk_cpugear_data *data)
+{
+	struct uniphier_clk_cpugear *gear;
+	struct clk_init_data init;
+	int ret;
+
+	gear = devm_kzalloc(dev, sizeof(*gear), GFP_KERNEL);
+	if (!gear)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &uniphier_clk_cpugear_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = data->parent_names;
+	init.num_parents = data->num_parents,
+
+	gear->regmap = regmap;
+	gear->regbase = data->regbase;
+	gear->mask = data->mask;
+	gear->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &gear->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &gear->hw;
+}
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 4eb4f6d..62816f8 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -20,15 +20,24 @@ struct clk_hw;
 struct device;
 struct regmap;
 
-#define UNIPHIER_CLK_MUX_MAX_PARENTS	8
+#define UNIPHIER_CLK_CPUGEAR_MAX_PARENTS	16
+#define UNIPHIER_CLK_MUX_MAX_PARENTS		8
 
 enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_CPUGEAR,
 	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
 	UNIPHIER_CLK_TYPE_FIXED_RATE,
 	UNIPHIER_CLK_TYPE_GATE,
 	UNIPHIER_CLK_TYPE_MUX,
 };
 
+struct uniphier_clk_cpugear_data {
+	const char *parent_names[UNIPHIER_CLK_CPUGEAR_MAX_PARENTS];
+	unsigned int num_parents;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
 struct uniphier_clk_fixed_factor_data {
 	const char *parent_name;
 	unsigned int mult;
@@ -58,6 +67,7 @@ struct uniphier_clk_data {
 	enum uniphier_clk_type type;
 	int idx;
 	union {
+		struct uniphier_clk_cpugear_data cpugear;
 		struct uniphier_clk_fixed_factor_data factor;
 		struct uniphier_clk_fixed_rate_data rate;
 		struct uniphier_clk_gate_data gate;
@@ -90,7 +100,10 @@ struct uniphier_clk_data {
 		},						\
 	}
 
-
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					     struct regmap *regmap,
+					     const char *name,
+				const struct uniphier_clk_cpugear_data *data);
 struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
 						  const char *name,
 			const struct uniphier_clk_fixed_factor_data *data);
-- 
2.7.4

  reply	other threads:[~2016-11-24  6:01 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-24  5:57 [PATCH v2 1/3] clk: uniphier: remove unneeded member name for union Masahiro Yamada
2016-11-24  5:57 ` Masahiro Yamada
2016-11-24  5:57 ` Masahiro Yamada [this message]
2016-11-24  5:57   ` [PATCH v2 2/3] clk: uniphier: add CPU-gear change (cpufreq) support Masahiro Yamada
2016-11-29 21:12   ` Stephen Boyd
2016-11-29 21:12     ` Stephen Boyd
2016-11-24  5:57 ` [PATCH v2 3/3] clk: uniphier: add cpufreq data for LD11, LD20 SoCs Masahiro Yamada
2016-11-24  5:57   ` Masahiro Yamada
2016-11-29 21:12   ` Stephen Boyd
2016-11-29 21:12     ` Stephen Boyd
2016-11-29 21:12 ` [PATCH v2 1/3] clk: uniphier: remove unneeded member name for union Stephen Boyd
2016-11-29 21:12   ` Stephen Boyd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1479967061-25975-2-git-send-email-yamada.masahiro@socionext.com \
    --to=yamada.masahiro@socionext.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=sboyd@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.