All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Add support for more MSM8916 clocks
@ 2015-06-05 12:40 Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops Georgi Djakov
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

This patchset adds support for the iommu, gpu and audio clocks on
the MSM8916 platforms.

Changes since v1:
* Added a set of ops for read-only RCGs and RCGs with shared branches.

Patchset based on clk-next.

Georgi Djakov (5):
  clk: qcom: Add support for read-only rcg2 ops
  clk: qcom: Add MSM8916 iommu clocks
  clk: qcom: Add support for RCGs with shared branches
  clk: qcom: Add MSM8916 gpu clocks
  clk: qcom: Add MSM8916 audio clocks

 drivers/clk/qcom/clk-rcg.h                   |    2 +
 drivers/clk/qcom/clk-rcg2.c                  |   71 ++++
 drivers/clk/qcom/gcc-msm8916.c               |  495 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8916.h |   22 ++
 4 files changed, 590 insertions(+)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops
  2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
@ 2015-06-05 12:40 ` Georgi Djakov
  2015-06-06  1:14   ` Stephen Boyd
  2015-06-05 12:40 ` [PATCH v2 2/5] clk: qcom: Add MSM8916 iommu clocks Georgi Djakov
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

Some root clock generators can be controlled by other processors. In this
case modifying them is not recommended. By using the read-only operations,
the child clocks will be able to get information about their parent - like
rate etc.

Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/clk/qcom/clk-rcg.h  |    1 +
 drivers/clk/qcom/clk-rcg2.c |    7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 56028bb31d87..706a55b34b81 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -169,6 +169,7 @@ struct clk_rcg2 {
 #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
 
 extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_ro_ops;
 extern const struct clk_ops clk_edp_pixel_ops;
 extern const struct clk_ops clk_byte_ops;
 extern const struct clk_ops clk_pixel_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index b95d17fbb8d7..cb17fd4b193f 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -301,6 +301,13 @@ const struct clk_ops clk_rcg2_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg2_ops);
 
+const struct clk_ops clk_rcg2_ro_ops = {
+	.is_enabled = clk_rcg2_is_enabled,
+	.get_parent = clk_rcg2_get_parent,
+	.recalc_rate = clk_rcg2_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_ro_ops);
+
 struct frac_entry {
 	int num;
 	int den;

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/5] clk: qcom: Add MSM8916 iommu clocks
  2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops Georgi Djakov
@ 2015-06-05 12:40 ` Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches Georgi Djakov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

Add support for the msm8916 TCU clocks that are needed for IOMMU.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/clk/qcom/gcc-msm8916.c               |   48 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8916.h |    3 ++
 2 files changed, 51 insertions(+)

diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index c66f7bc2ae87..d493e9f3a2eb 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -2358,6 +2358,51 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
 	},
 };
 
+static struct clk_rcg2 bimc_ddr_clk_src = {
+	.cmd_rcgr = 0x32004,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_bimc_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "bimc_ddr_clk_src",
+		.parent_names = gcc_xo_gpll0_bimc,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ro_ops,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_branch gcc_apss_tcu_clk = {
+	.halt_reg = 0x12018,
+	.clkr = {
+		.enable_reg = 0x4500c,
+		.enable_mask = BIT(1),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_apss_tcu_clk",
+			.parent_names = (const char *[]){
+				"bimc_ddr_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gfx_tcu_clk = {
+	.halt_reg = 0x12020,
+	.clkr = {
+		.enable_reg = 0x4500c,
+		.enable_mask = BIT(2),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gfx_tcu_clk",
+			.parent_names = (const char *[]){
+				"bimc_ddr_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_gtcu_ahb_clk = {
 	.halt_reg = 0x12044,
 	.clkr = {
@@ -2701,6 +2746,9 @@ static struct clk_regmap *gcc_msm8916_clocks[] = {
 	[GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
 	[GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
 	[GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
+	[BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr,
+	[GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr,
+	[GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr,
 };
 
 static const struct qcom_reset_map gcc_msm8916_resets[] = {
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h
index e430f644dd6c..53b39293d759 100644
--- a/include/dt-bindings/clock/qcom,gcc-msm8916.h
+++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h
@@ -152,5 +152,8 @@
 #define GCC_VENUS0_AHB_CLK			135
 #define GCC_VENUS0_AXI_CLK			136
 #define GCC_VENUS0_VCODEC0_CLK			137
+#define BIMC_DDR_CLK_SRC			138
+#define GCC_APSS_TCU_CLK			139
+#define GCC_GFX_TCU_CLK				140
 
 #endif

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches
  2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 2/5] clk: qcom: Add MSM8916 iommu clocks Georgi Djakov
@ 2015-06-05 12:40 ` Georgi Djakov
  2015-06-06  1:39   ` Stephen Boyd
  2015-06-05 12:40 ` [PATCH v2 4/5] clk: qcom: Add MSM8916 gpu clocks Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks Georgi Djakov
  4 siblings, 1 reply; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

Some root clock generators may have child branches that are controlled
by different CPUs. These RCGs require special operations.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/clk/qcom/clk-rcg.h  |    1 +
 drivers/clk/qcom/clk-rcg2.c |   64 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 706a55b34b81..c233a8f5e910 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -170,6 +170,7 @@ struct clk_rcg2 {
 
 extern const struct clk_ops clk_rcg2_ops;
 extern const struct clk_ops clk_rcg2_ro_ops;
+extern const struct clk_ops clk_rcg2_shared_ops;
 extern const struct clk_ops clk_edp_pixel_ops;
 extern const struct clk_ops clk_byte_ops;
 extern const struct clk_ops clk_pixel_ops;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index cb17fd4b193f..60563adad21d 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -47,6 +47,8 @@
 #define N_REG			0xc
 #define D_REG			0x10
 
+#define XO_FREQ			19200000
+
 static int clk_rcg2_is_enabled(struct clk_hw *hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -308,6 +310,68 @@ const struct clk_ops clk_rcg2_ro_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg2_ro_ops);
 
+static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const char *name = __clk_get_name(hw->clk);
+	int ret, count;
+	unsigned int cmd = CMD_ROOT_EN;
+
+	/* force enable RCG */
+	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+				 cmd, cmd);
+	if (ret)
+		return ret;
+
+	/* wait for RCG to turn ON */
+	for (count = 500; count > 0; count--) {
+		ret = clk_rcg2_is_enabled(hw);
+		if (ret)
+			break;
+		udelay(1);
+	}
+	if (!count)
+		pr_err("%s: RCG did not turn on\n", name);
+
+	/* set clock rate */
+	ret = __clk_rcg2_set_rate(hw, rate);
+	if (ret)
+		return ret;
+
+	/* clear force enable RCG */
+	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+				 cmd, ~cmd);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int clk_rcg2_shared_enable(struct clk_hw *hw)
+{
+	unsigned long rate = __clk_get_rate(hw->clk);
+
+	return clk_rcg2_shared_set_rate(hw, rate, 0);
+}
+
+static void clk_rcg2_shared_disable(struct clk_hw *hw)
+{
+	/* switch to XO, which is always-on */
+	clk_rcg2_shared_set_rate(hw, XO_FREQ, 0);
+}
+
+const struct clk_ops clk_rcg2_shared_ops = {
+	.enable = clk_rcg2_shared_enable,
+	.disable = clk_rcg2_shared_disable,
+	.get_parent = clk_rcg2_get_parent,
+	.is_enabled = clk_rcg2_is_enabled,
+	.recalc_rate = clk_rcg2_recalc_rate,
+	.determine_rate = clk_rcg2_determine_rate,
+	.set_rate = clk_rcg2_shared_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
+
 struct frac_entry {
 	int num;
 	int den;

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/5] clk: qcom: Add MSM8916 gpu clocks
  2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
                   ` (2 preceding siblings ...)
  2015-06-05 12:40 ` [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches Georgi Djakov
@ 2015-06-05 12:40 ` Georgi Djakov
  2015-06-05 12:40 ` [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks Georgi Djakov
  4 siblings, 0 replies; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

Add support for the msm8916 bimc clocks that are needed for GPU.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/clk/qcom/gcc-msm8916.c               |   59 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8916.h |    3 ++
 2 files changed, 62 insertions(+)

diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index d493e9f3a2eb..9b4a8ebb1eb2 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -1094,6 +1094,28 @@ static struct clk_rcg2 apss_tcu_clk_src = {
 	},
 };
 
+static const struct freq_tbl ftbl_gcc_bimc_gpu_clk[] = {
+	F(100000000, P_GPLL0, 8, 0, 0),
+	F(200000000, P_GPLL0, 4, 0, 0),
+	F(266500000, P_BIMC, 4, 0, 0),
+	F(533000000, P_BIMC, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 bimc_gpu_clk_src = {
+	.cmd_rcgr = 0x31028,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_bimc_map,
+	.freq_tbl = ftbl_gcc_bimc_gpu_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "bimc_gpu_clk_src",
+		.parent_names = gcc_xo_gpll0_bimc,
+		.num_parents = 3,
+		.flags = CLK_GET_RATE_NOCACHE,
+		.ops = &clk_rcg2_shared_ops,
+	},
+};
+
 static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
 	F(80000000, P_GPLL0, 10, 0, 0),
 	{ }
@@ -2420,6 +2442,40 @@ static struct clk_branch gcc_gtcu_ahb_clk = {
 	},
 };
 
+static struct clk_branch gcc_bimc_gfx_clk = {
+	.halt_reg = 0x31024,
+	.clkr = {
+		.enable_reg = 0x31024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_bimc_gfx_clk",
+			.parent_names = (const char *[]){
+				"bimc_gpu_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_bimc_gpu_clk = {
+	.halt_reg = 0x31040,
+	.clkr = {
+		.enable_reg = 0x31040,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_bimc_gpu_clk",
+			.parent_names = (const char *[]){
+				"bimc_gpu_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_jpeg_tbu_clk = {
 	.halt_reg = 0x12034,
 	.clkr = {
@@ -2749,6 +2805,9 @@ static struct clk_regmap *gcc_msm8916_clocks[] = {
 	[BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr,
 	[GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr,
 	[GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr,
+	[BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr,
+	[GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+	[GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
 };
 
 static const struct qcom_reset_map gcc_msm8916_resets[] = {
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h
index 53b39293d759..d54a9715c37e 100644
--- a/include/dt-bindings/clock/qcom,gcc-msm8916.h
+++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h
@@ -155,5 +155,8 @@
 #define BIMC_DDR_CLK_SRC			138
 #define GCC_APSS_TCU_CLK			139
 #define GCC_GFX_TCU_CLK				140
+#define BIMC_GPU_CLK_SRC			141
+#define GCC_BIMC_GFX_CLK			142
+#define GCC_BIMC_GPU_CLK			143
 
 #endif

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks
  2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
                   ` (3 preceding siblings ...)
  2015-06-05 12:40 ` [PATCH v2 4/5] clk: qcom: Add MSM8916 gpu clocks Georgi Djakov
@ 2015-06-05 12:40 ` Georgi Djakov
  2015-06-06  1:41   ` Stephen Boyd
  4 siblings, 1 reply; 9+ messages in thread
From: Georgi Djakov @ 2015-06-05 12:40 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

Add support for the msm8916 audio clocks. This includes core bus,
low-power audio and codec clocks. They are required for audio playback.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/clk/qcom/gcc-msm8916.c               |  388 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8916.h |   16 ++
 2 files changed, 404 insertions(+)

diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index 9b4a8ebb1eb2..2f38fffe1411 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -44,6 +44,9 @@ enum {
 	P_SLEEP_CLK,
 	P_DSI0_PHYPLL_BYTE,
 	P_DSI0_PHYPLL_DSI,
+	P_EXT_PRI_I2S,
+	P_EXT_SEC_I2S,
+	P_EXT_MCLK,
 };
 
 static const struct parent_map gcc_xo_gpll0_map[] = {
@@ -190,6 +193,76 @@ static const char *gcc_xo_gpll0a_gpll1_gpll2[] = {
 	"gpll2_vote",
 };
 
+static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL1, 2 },
+	{ P_SLEEP_CLK, 6 }
+};
+
+static const char *gcc_xo_gpll0_gpll1_sleep[] = {
+	"xo",
+	"gpll0_vote",
+	"gpll1_vote",
+	"sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_epi2s_emclk_sleep_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL1, 1 },
+	{ P_EXT_PRI_I2S, 2 },
+	{ P_EXT_MCLK, 3 },
+	{ P_SLEEP_CLK, 6 }
+};
+
+static const char *gcc_xo_gpll1_epi2s_emclk_sleep[] = {
+	"xo",
+	"gpll1_vote",
+	"ext_pri_i2s",
+	"ext_mclk",
+	"sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_esi2s_emclk_sleep_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL1, 1 },
+	{ P_EXT_SEC_I2S, 2 },
+	{ P_EXT_MCLK, 3 },
+	{ P_SLEEP_CLK, 6 }
+};
+
+static const char *gcc_xo_gpll1_esi2s_emclk_sleep[] = {
+	"xo",
+	"gpll1_vote",
+	"ext_sec_i2s",
+	"ext_mclk",
+	"sleep_clk",
+};
+
+static const struct parent_map gcc_xo_sleep_map[] = {
+	{ P_XO, 0 },
+	{ P_SLEEP_CLK, 6 }
+};
+
+static const char *gcc_xo_sleep[] = {
+	"xo",
+	"sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll1_emclk_sleep_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL1, 1 },
+	{ P_EXT_MCLK, 2 },
+	{ P_SLEEP_CLK, 6 }
+};
+
+static const char *gcc_xo_gpll1_emclk_sleep[] = {
+	"xo",
+	"gpll1_vote",
+	"ext_mclk",
+	"sleep_clk",
+};
+
 #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
 
 static struct clk_pll gpll0 = {
@@ -1134,6 +1207,305 @@ static struct clk_rcg2 usb_hs_system_clk_src = {
 	},
 };
 
+static const struct freq_tbl ftbl_gcc_ultaudio_ahb_clk[] = {
+	F(3200000, P_XO, 6, 0, 0),
+	F(6400000, P_XO, 3, 0, 0),
+	F(9600000, P_XO, 2, 0, 0),
+	F(19200000, P_XO, 1, 0, 0),
+	F(40000000, P_GPLL0, 10, 1, 2),
+	F(66670000, P_GPLL0, 12, 0, 0),
+	F(80000000, P_GPLL0, 10, 0, 0),
+	F(100000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ultaudio_ahbfabric_clk_src = {
+	.cmd_rcgr = 0x1c010,
+	.hid_width = 5,
+	.mnd_width = 8,
+	.parent_map = gcc_xo_gpll0_gpll1_sleep_map,
+	.freq_tbl = ftbl_gcc_ultaudio_ahb_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ultaudio_ahbfabric_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll1_sleep,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_clk = {
+	.halt_reg = 0x1c028,
+	.clkr = {
+		.enable_reg = 0x1c028,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_ahbfabric_ixfabric_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_ahbfabric_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_lpm_clk = {
+	.halt_reg = 0x1c024,
+	.clkr = {
+		.enable_reg = 0x1c024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_ahbfabric_ixfabric_lpm_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_ahbfabric_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ultaudio_lpaif_i2s_clk[] = {
+	F(256000, P_XO, 5, 1, 15),
+	F(512000, P_XO, 5, 2, 15),
+	F(705600, P_GPLL1, 16, 1, 80),
+	F(768000, P_XO, 5, 1, 5),
+	F(800000, P_XO, 5, 5, 24),
+	F(1024000, P_GPLL1, 14, 1, 63),
+	F(1152000, P_XO, 1, 3, 50),
+	F(1411200, P_GPLL1, 16, 1, 40),
+	F(1536000, P_XO, 1, 2, 25),
+	F(1600000, P_XO, 12, 0, 0),
+	F(2048000, P_GPLL1, 9, 1, 49),
+	F(2400000, P_XO, 8, 0, 0),
+	F(2822400, P_GPLL1, 16, 1, 20),
+	F(3072000, P_GPLL1, 14, 1, 21),
+	F(4096000, P_GPLL1, 9, 2, 49),
+	F(4800000, P_XO, 4, 0, 0),
+	F(5644800, P_GPLL1, 16, 1, 10),
+	F(6144000, P_GPLL1, 7, 1, 21),
+	F(8192000, P_GPLL1, 9, 4, 49),
+	F(9600000, P_XO, 2, 0, 0),
+	F(11289600, P_GPLL1, 16, 1, 5),
+	F(12288000, P_GPLL1, 7, 2, 21),
+	{ }
+};
+
+static struct clk_rcg2 ultaudio_lpaif_pri_i2s_clk_src = {
+	.cmd_rcgr = 0x1c054,
+	.hid_width = 5,
+	.mnd_width = 8,
+	.parent_map = gcc_xo_gpll1_epi2s_emclk_sleep_map,
+	.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ultaudio_lpaif_pri_i2s_clk_src",
+		.parent_names = gcc_xo_gpll1_epi2s_emclk_sleep,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_pri_i2s_clk = {
+	.halt_reg = 0x1c068,
+	.clkr = {
+		.enable_reg = 0x1c068,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_lpaif_pri_i2s_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_lpaif_pri_i2s_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_rcg2 ultaudio_lpaif_sec_i2s_clk_src = {
+	.cmd_rcgr = 0x1c06c,
+	.hid_width = 5,
+	.mnd_width = 8,
+	.parent_map = gcc_xo_gpll1_esi2s_emclk_sleep_map,
+	.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ultaudio_lpaif_sec_i2s_clk_src",
+		.parent_names = gcc_xo_gpll1_esi2s_emclk_sleep,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_sec_i2s_clk = {
+	.halt_reg = 0x1c080,
+	.clkr = {
+		.enable_reg = 0x1c080,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_lpaif_sec_i2s_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_lpaif_sec_i2s_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_rcg2 ultaudio_lpaif_aux_i2s_clk_src = {
+	.cmd_rcgr = 0x1c084,
+	.hid_width = 5,
+	.mnd_width = 8,
+	.parent_map = gcc_xo_gpll1_emclk_sleep_map,
+	.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ultaudio_lpaif_aux_i2s_clk_src",
+		.parent_names = gcc_xo_gpll1_emclk_sleep,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_ultaudio_lpaif_aux_i2s_clk = {
+	.halt_reg = 0x1c098,
+	.clkr = {
+		.enable_reg = 0x1c098,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_lpaif_aux_i2s_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_lpaif_aux_i2s_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ultaudio_xo_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ultaudio_xo_clk_src = {
+	.cmd_rcgr = 0x1c034,
+	.hid_width = 5,
+	.parent_map = gcc_xo_sleep_map,
+	.freq_tbl = ftbl_gcc_ultaudio_xo_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "ultaudio_xo_clk_src",
+		.parent_names = gcc_xo_sleep,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_ultaudio_avsync_xo_clk = {
+	.halt_reg = 0x1c04c,
+	.clkr = {
+		.enable_reg = 0x1c04c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_avsync_xo_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_xo_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ultaudio_stc_xo_clk = {
+	.halt_reg = 0x1c050,
+	.clkr = {
+		.enable_reg = 0x1c050,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_stc_xo_clk",
+			.parent_names = (const char *[]){
+				"ultaudio_xo_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_codec_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(11289600, P_EXT_MCLK, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 codec_digcodec_clk_src = {
+	.cmd_rcgr = 0x1c09c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll1_emclk_sleep_map,
+	.freq_tbl = ftbl_codec_clk,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "codec_digcodec_clk_src",
+		.parent_names = gcc_xo_gpll1_emclk_sleep,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_codec_digcodec_clk = {
+	.halt_reg = 0x1c0b0,
+	.clkr = {
+		.enable_reg = 0x1c0b0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_codec_digcodec_clk",
+			.parent_names = (const char *[]){
+				"codec_digcodec_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ultaudio_pcnoc_mport_clk = {
+	.halt_reg = 0x1c000,
+	.clkr = {
+		.enable_reg = 0x1c000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_pcnoc_mport_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_bfdcd_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ultaudio_pcnoc_sway_clk = {
+	.halt_reg = 0x1c004,
+	.clkr = {
+		.enable_reg = 0x1c004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ultaudio_pcnoc_sway_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_bfdcd_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
 	F(100000000, P_GPLL0, 8, 0, 0),
 	F(160000000, P_GPLL0, 5, 0, 0),
@@ -2808,6 +3180,22 @@ static struct clk_regmap *gcc_msm8916_clocks[] = {
 	[BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr,
 	[GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
 	[GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
+	[ULTAUDIO_AHBFABRIC_CLK_SRC] = &ultaudio_ahbfabric_clk_src.clkr,
+	[ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC] = &ultaudio_lpaif_pri_i2s_clk_src.clkr,
+	[ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC] = &ultaudio_lpaif_sec_i2s_clk_src.clkr,
+	[ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC] = &ultaudio_lpaif_aux_i2s_clk_src.clkr,
+	[ULTAUDIO_XO_CLK_SRC] = &ultaudio_xo_clk_src.clkr,
+	[CODEC_DIGCODEC_CLK_SRC] = &codec_digcodec_clk_src.clkr,
+	[GCC_ULTAUDIO_PCNOC_MPORT_CLK] = &gcc_ultaudio_pcnoc_mport_clk.clkr,
+	[GCC_ULTAUDIO_PCNOC_SWAY_CLK] = &gcc_ultaudio_pcnoc_sway_clk.clkr,
+	[GCC_ULTAUDIO_AVSYNC_XO_CLK] = &gcc_ultaudio_avsync_xo_clk.clkr,
+	[GCC_ULTAUDIO_STC_XO_CLK] = &gcc_ultaudio_stc_xo_clk.clkr,
+	[GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK] =	&gcc_ultaudio_ahbfabric_ixfabric_clk.clkr,
+	[GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_lpm_clk.clkr,
+	[GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK] = &gcc_ultaudio_lpaif_pri_i2s_clk.clkr,
+	[GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK] = &gcc_ultaudio_lpaif_sec_i2s_clk.clkr,
+	[GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK] = &gcc_ultaudio_lpaif_aux_i2s_clk.clkr,
+	[GCC_CODEC_DIGCODEC_CLK] = &gcc_codec_digcodec_clk.clkr,
 };
 
 static const struct qcom_reset_map gcc_msm8916_resets[] = {
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h
index d54a9715c37e..694872d887f5 100644
--- a/include/dt-bindings/clock/qcom,gcc-msm8916.h
+++ b/include/dt-bindings/clock/qcom,gcc-msm8916.h
@@ -158,5 +158,21 @@
 #define BIMC_GPU_CLK_SRC			141
 #define GCC_BIMC_GFX_CLK			142
 #define GCC_BIMC_GPU_CLK			143
+#define ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC		144
+#define ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC		145
+#define ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC		146
+#define ULTAUDIO_XO_CLK_SRC			147
+#define ULTAUDIO_AHBFABRIC_CLK_SRC		148
+#define CODEC_DIGCODEC_CLK_SRC			149
+#define GCC_ULTAUDIO_PCNOC_MPORT_CLK		150
+#define GCC_ULTAUDIO_PCNOC_SWAY_CLK		151
+#define GCC_ULTAUDIO_AVSYNC_XO_CLK		152
+#define GCC_ULTAUDIO_STC_XO_CLK			153
+#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK	154
+#define GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK	155
+#define GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK		156
+#define GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK		157
+#define GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK		158
+#define GCC_CODEC_DIGCODEC_CLK			159
 
 #endif

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops
  2015-06-05 12:40 ` [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops Georgi Djakov
@ 2015-06-06  1:14   ` Stephen Boyd
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Boyd @ 2015-06-06  1:14 UTC (permalink / raw)
  To: Georgi Djakov; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

On 06/05, Georgi Djakov wrote:
> Some root clock generators can be controlled by other processors. In this
> case modifying them is not recommended. By using the read-only operations,
> the child clocks will be able to get information about their parent - like
> rate etc.
> 
> Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
> Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>

Do we actually need this? I think I wrote the clk ops for the RCG
to make it skip doing anything if there isn't a frequency table.
So to make a read-only RCG all we need to do is remove the
frequency table? Sorry if I led you down the wrong path.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches
  2015-06-05 12:40 ` [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches Georgi Djakov
@ 2015-06-06  1:39   ` Stephen Boyd
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Boyd @ 2015-06-06  1:39 UTC (permalink / raw)
  To: Georgi Djakov; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

On 06/05, Georgi Djakov wrote:
> diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
> index cb17fd4b193f..60563adad21d 100644
> --- a/drivers/clk/qcom/clk-rcg2.c
> +++ b/drivers/clk/qcom/clk-rcg2.c
> @@ -47,6 +47,8 @@
>  #define N_REG			0xc
>  #define D_REG			0x10
>  
> +#define XO_FREQ			19200000

Hm.. we don't know that XO is always going to be 19.2 MHz.

> +
>  static int clk_rcg2_is_enabled(struct clk_hw *hw)
>  {
>  	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
> @@ -308,6 +310,68 @@ const struct clk_ops clk_rcg2_ro_ops = {
>  };
>  EXPORT_SYMBOL_GPL(clk_rcg2_ro_ops);
>  
> +static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
> +				    unsigned long parent_rate)
> +{
> +	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
> +	const char *name = __clk_get_name(hw->clk);
> +	int ret, count;
> +	unsigned int cmd = CMD_ROOT_EN;
> +
> +	/* force enable RCG */
> +	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
> +				 cmd, cmd);
> +	if (ret)
> +		return ret;
> +
> +	/* wait for RCG to turn ON */
> +	for (count = 500; count > 0; count--) {
> +		ret = clk_rcg2_is_enabled(hw);
> +		if (ret)
> +			break;
> +		udelay(1);
> +	}
> +	if (!count)
> +		pr_err("%s: RCG did not turn on\n", name);
> +
> +	/* set clock rate */
> +	ret = __clk_rcg2_set_rate(hw, rate);
> +	if (ret)
> +		return ret;
> +
> +	/* clear force enable RCG */
> +	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
> +				 cmd, ~cmd);

The last argument could just be 0, save an instruction.

> +	if (ret)
> +		return ret;
> +
> +	return 0;

This function will become more complicated.

> +}
> +
> +static int clk_rcg2_shared_enable(struct clk_hw *hw)
> +{
> +	unsigned long rate = __clk_get_rate(hw->clk);
> +
> +	return clk_rcg2_shared_set_rate(hw, rate, 0);

And we shouldn't configure the clock to be at any rate besides XO
speed while the clock is off because the other processors may not
be requesting enough voltage to support the clock at whatever
rate we've chosen. So we need to make set_rate() into a caching
operation when the clock is disabled in software's view.

> +}
> +
> +static void clk_rcg2_shared_disable(struct clk_hw *hw)
> +{
> +	/* switch to XO, which is always-on */
> +	clk_rcg2_shared_set_rate(hw, XO_FREQ, 0);

Maybe here we should just "know" that the XO frequency is either
the lowest entry in the frequency table or that it's source 0 and
make up some fake frequency struct to pass around.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks
  2015-06-05 12:40 ` [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks Georgi Djakov
@ 2015-06-06  1:41   ` Stephen Boyd
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Boyd @ 2015-06-06  1:41 UTC (permalink / raw)
  To: Georgi Djakov; +Cc: mturquette, linux-clk, linux-kernel, linux-arm-msm

On 06/05, Georgi Djakov wrote:
> @@ -190,6 +193,76 @@ static const char *gcc_xo_gpll0a_gpll1_gpll2[] = {
>  	"gpll2_vote",
>  };
>  
> +static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = {
> +	{ P_XO, 0 },
> +	{ P_GPLL0, 1 },
> +	{ P_GPLL1, 2 },
> +	{ P_SLEEP_CLK, 6 }
> +};
> +
> +static const char *gcc_xo_gpll0_gpll1_sleep[] = {

Please make these new ones const char * const now that we've
fixed that problem in the clk framework


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-06-06  1:41 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-05 12:40 [PATCH v2 0/5] Add support for more MSM8916 clocks Georgi Djakov
2015-06-05 12:40 ` [PATCH v2 1/5] clk: qcom: Add support for read-only rcg2 ops Georgi Djakov
2015-06-06  1:14   ` Stephen Boyd
2015-06-05 12:40 ` [PATCH v2 2/5] clk: qcom: Add MSM8916 iommu clocks Georgi Djakov
2015-06-05 12:40 ` [PATCH v2 3/5] clk: qcom: Add support for RCGs with shared branches Georgi Djakov
2015-06-06  1:39   ` Stephen Boyd
2015-06-05 12:40 ` [PATCH v2 4/5] clk: qcom: Add MSM8916 gpu clocks Georgi Djakov
2015-06-05 12:40 ` [PATCH v2 5/5] clk: qcom: Add MSM8916 audio clocks Georgi Djakov
2015-06-06  1:41   ` Stephen Boyd

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.