All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tero Kristo <kristo@kernel.org>
To: u-boot@lists.denx.de
Subject: [PATCHv4 13/26] clk: add support for TI K3 SoC clocks
Date: Tue, 11 May 2021 11:30:51 +0300	[thread overview]
Message-ID: <20210511083104.10868-14-kristo@kernel.org> (raw)
In-Reply-To: <20210511083104.10868-1-kristo@kernel.org>

From: Tero Kristo <t-kristo@ti.com>

Add driver to support TI K3 generation SoC clocks. This driver registers
the clocks provided via platform data, and adds support for controlling
the clocks via DT handles.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tero Kristo <kristo@kernel.org>
---
 drivers/clk/ti/Kconfig  |  12 ++
 drivers/clk/ti/Makefile |   1 +
 drivers/clk/ti/clk-k3.c | 374 ++++++++++++++++++++++++++++++++++++++++
 include/k3-clk.h        | 162 +++++++++++++++++
 4 files changed, 549 insertions(+)
 create mode 100644 drivers/clk/ti/clk-k3.c

diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig
index a8ec4f541a..fbcdefd889 100644
--- a/drivers/clk/ti/Kconfig
+++ b/drivers/clk/ti/Kconfig
@@ -53,3 +53,15 @@ config SPL_CLK_K3_PLL
 	depends on CLK && LIB_RATIONAL && SPL
 	help
 	  Enables PLL clock support for K3 SoC family of devices.
+
+config CLK_K3
+	bool "Clock support for K3 SoC family of devices"
+	depends on CLK
+	help
+	  Enables the clock translation layer from DT to device clocks.
+
+config SPL_CLK_K3
+	bool "Clock support for K3 SoC family of devices"
+	depends on CLK && SPL
+	help
+	  Enables the clock translation layer from DT to device clocks.
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 47839213e5..07aa9a53e0 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_CLK_TI_GATE) += clk-gate.o
 obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o
 obj-$(CONFIG_CLK_TI_SCI) += clk-sci.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_K3_PLL) += clk-k3-pll.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_K3) += clk-k3.o
diff --git a/drivers/clk/ti/clk-k3.c b/drivers/clk/ti/clk-k3.c
new file mode 100644
index 0000000000..ec262d5c21
--- /dev/null
+++ b/drivers/clk/ti/clk-k3.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments K3 clock driver
+ *
+ * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ *	Tero Kristo <t-kristo@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <soc.h>
+#include <clk-uclass.h>
+#include "k3-clk.h"
+
+#define PLL_MIN_FREQ	800000000
+#define PLL_MAX_FREQ	3200000000UL
+#define PLL_MAX_DIV	127
+
+/**
+ * struct clk_map - mapping from dev/clk id tuples towards physical clocks
+ * @dev_id: device ID for the clock
+ * @clk_id: clock ID for the clock
+ * @clk: pointer to the registered clock entry for the mapping
+ */
+struct clk_map {
+	u16 dev_id;
+	u32 clk_id;
+	struct clk *clk;
+};
+
+/**
+ * struct ti_clk_data - clock controller information structure
+ * @map: mapping from dev/clk id tuples to physical clock entries
+ * @size: number of entries in the map
+ */
+struct ti_clk_data {
+	struct clk_map *map;
+	int size;
+};
+
+static ulong osc_freq;
+
+static void clk_add_map(struct ti_clk_data *data, struct clk *clk,
+			u32 dev_id, u32 clk_id)
+{
+	struct clk_map *map;
+
+	debug("%s: added clk=%p, data=%p, dev=%d, clk=%d\n", __func__,
+	      clk, data, dev_id, clk_id);
+	if (!clk)
+		return;
+
+	map = data->map + data->size++;
+
+	map->dev_id = dev_id;
+	map->clk_id = clk_id;
+	map->clk = clk;
+}
+
+static const struct soc_attr ti_k3_soc_clk_data[] = {
+#ifdef CONFIG_SOC_K3_J721E
+	{
+		.family = "J721E",
+		.data = &j721e_clk_platdata,
+	},
+	{
+		.family = "J7200",
+		.data = &j7200_clk_platdata,
+	},
+#endif
+	{ /* sentinel */ }
+};
+
+static int ti_clk_probe(struct udevice *dev)
+{
+	struct ti_clk_data *data = dev_get_priv(dev);
+	struct clk *clk;
+	const char *name;
+	const struct clk_data *ti_clk_data;
+	int i, j;
+	const struct soc_attr *soc_match_data;
+	const struct ti_k3_clk_platdata *pdata;
+
+	debug("%s(dev=%p)\n", __func__, dev);
+
+	soc_match_data = soc_device_match(ti_k3_soc_clk_data);
+	if (!soc_match_data)
+		return -ENODEV;
+
+	pdata = (const struct ti_k3_clk_platdata *)soc_match_data->data;
+
+	data->map = kcalloc(pdata->soc_dev_clk_data_cnt, sizeof(*data->map),
+			    GFP_KERNEL);
+	data->size = 0;
+
+	for (i = 0; i < pdata->clk_list_cnt; i++) {
+		ti_clk_data = &pdata->clk_list[i];
+
+		switch (ti_clk_data->type) {
+		case CLK_TYPE_FIXED_RATE:
+			name = ti_clk_data->clk.fixed_rate.name;
+			clk = clk_register_fixed_rate(NULL,
+						      name,
+						      ti_clk_data->clk.fixed_rate.rate);
+			break;
+		case CLK_TYPE_DIV:
+			name = ti_clk_data->clk.div.name;
+			clk = clk_register_divider(NULL, name,
+						   ti_clk_data->clk.div.parent,
+						   ti_clk_data->clk.div.flags,
+						   map_physmem(ti_clk_data->clk.div.reg, 0, MAP_NOCACHE),
+						   ti_clk_data->clk.div.shift,
+						   ti_clk_data->clk.div.width,
+						   0);
+			break;
+		case CLK_TYPE_MUX:
+			name = ti_clk_data->clk.mux.name;
+			clk = clk_register_mux(NULL, name,
+					       ti_clk_data->clk.mux.parents,
+					       ti_clk_data->clk.mux.num_parents,
+					       ti_clk_data->clk.mux.flags,
+					       map_physmem(ti_clk_data->clk.mux.reg, 0, MAP_NOCACHE),
+					       ti_clk_data->clk.mux.shift,
+					       ti_clk_data->clk.mux.width,
+					       0);
+			break;
+		case CLK_TYPE_PLL:
+			name = ti_clk_data->clk.pll.name;
+			clk = clk_register_ti_pll(name,
+						  ti_clk_data->clk.pll.parent,
+						  map_physmem(ti_clk_data->clk.pll.reg, 0, MAP_NOCACHE));
+
+			if (!osc_freq)
+				osc_freq = clk_get_rate(clk_get_parent(clk));
+			break;
+		default:
+			name = NULL;
+			clk = NULL;
+			printf("WARNING: %s has encountered unknown clk type %d\n",
+			       __func__, ti_clk_data->type);
+		}
+
+		if (clk && ti_clk_data->default_freq)
+			clk_set_rate(clk, ti_clk_data->default_freq);
+
+		if (clk && name) {
+			for (j = 0; j < pdata->soc_dev_clk_data_cnt; j++) {
+				if (!strcmp(name, pdata->soc_dev_clk_data[j].clk_name)) {
+					clk_add_map(data, clk, pdata->soc_dev_clk_data[j].dev_id,
+						    pdata->soc_dev_clk_data[j].clk_id);
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int _clk_cmp(u32 dev_id, u32 clk_id, const struct clk_map *map)
+{
+	if (map->dev_id == dev_id && map->clk_id == clk_id)
+		return 0;
+	if (map->dev_id > dev_id ||
+	    (map->dev_id == dev_id && map->clk_id > clk_id))
+		return -1;
+	return 1;
+}
+
+static int bsearch(u32 dev_id, u32 clk_id, struct clk_map *map, int num)
+{
+	int result;
+	int idx;
+
+	for (idx = 0; idx < num; idx++) {
+		result = _clk_cmp(dev_id, clk_id, &map[idx]);
+
+		if (result == 0)
+			return idx;
+	}
+
+	return -ENOENT;
+}
+
+static int ti_clk_of_xlate(struct clk *clk,
+			   struct ofnode_phandle_args *args)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	int idx;
+
+	debug("%s(clk=%p, args_count=%d [0]=%d [1]=%d)\n", __func__, clk,
+	      args->args_count, args->args[0], args->args[1]);
+
+	if (args->args_count != 2) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (!data->size)
+		return -EPROBE_DEFER;
+
+	idx = bsearch(args->args[0], args->args[1], data->map, data->size);
+	if (idx < 0)
+		return idx;
+
+	clk->id = idx;
+
+	return 0;
+}
+
+static ulong ti_clk_get_rate(struct clk *clk)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	struct clk *clkp = data->map[clk->id].clk;
+
+	return clk_get_rate(clkp);
+}
+
+static ulong ti_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	struct clk *clkp = data->map[clk->id].clk;
+	int div = 1;
+	ulong child_rate;
+	const struct clk_ops *ops;
+	ulong new_rate, rem;
+	ulong diff, new_diff;
+
+	/*
+	 * We must propagate rate change to parent if current clock type
+	 * does not allow setting it.
+	 */
+	while (clkp) {
+		ops = clkp->dev->driver->ops;
+		if (ops->set_rate)
+			break;
+
+		/*
+		 * Store child rate so we can calculate the clock rate
+		 * that must be passed to parent
+		 */
+		child_rate = clk_get_rate(clkp);
+		clkp = clk_get_parent(clkp);
+		if (clkp) {
+			debug("%s: propagating rate change to parent %s, rate=%u.\n",
+			      __func__, clkp->dev->name, (u32)rate / div);
+			div *= clk_get_rate(clkp) / child_rate;
+		}
+	}
+
+	if (!clkp)
+		return -ENOSYS;
+
+	child_rate = clk_get_rate(clkp);
+
+	new_rate = clk_set_rate(clkp, rate / div);
+
+	diff = abs(new_rate - rate / div);
+
+	debug("%s: clk=%s, div=%d, rate=%u, new_rate=%u, diff=%u\n", __func__,
+	      clkp->dev->name, div, (u32)rate, (u32)new_rate, (u32)diff);
+
+	/*
+	 * If the new rate differs by 50% of the target,
+	 * modify parent. This handles typical cases where we have a hsdiv
+	 * following directly a PLL
+	 */
+
+	if (diff > rate / div / 2) {
+		ulong pll_tgt;
+		int pll_div = 0;
+
+		clk = clkp;
+
+		debug("%s: propagating rate change to parent, rate=%u.\n",
+		      __func__, (u32)rate / div);
+
+		clkp = clk_get_parent(clkp);
+
+		if (rate > osc_freq) {
+			if (rate > PLL_MAX_FREQ / 2 && rate < PLL_MAX_FREQ) {
+				pll_tgt = rate;
+				pll_div = 1;
+			} else {
+				for (pll_div = 2; pll_div < PLL_MAX_DIV; pll_div++) {
+					pll_tgt = rate / div * pll_div;
+					if (pll_tgt >= PLL_MIN_FREQ && pll_tgt <= PLL_MAX_FREQ)
+						break;
+				}
+			}
+		} else {
+			pll_tgt = osc_freq;
+			pll_div = rate / div / osc_freq;
+		}
+
+		debug("%s: pll_tgt=%u, rate=%u, div=%u\n", __func__,
+		      (u32)pll_tgt, (u32)rate, pll_div);
+
+		clk_set_rate(clkp, pll_tgt);
+
+		return clk_set_rate(clk, rate / div) * div;
+	}
+
+	/*
+	 * If the new rate differs by@least 5% of the target,
+	 * we must check for rounding error in a divider, so try
+	 * set rate with rate + (parent_freq % rate).
+	 */
+
+	if (diff > rate / div / 20) {
+		u64 parent_freq = clk_get_parent_rate(clkp);
+
+		rem = parent_freq % rate;
+		new_rate = clk_set_rate(clkp, (rate / div) + rem);
+		new_diff = abs(new_rate - rate / div);
+
+		if (new_diff > diff) {
+			new_rate = clk_set_rate(clkp, rate / div);
+		} else {
+			debug("%s: Using better rate %lu that gives diff %lu\n",
+			      __func__, new_rate, new_diff);
+		}
+	}
+
+	return new_rate;
+}
+
+static int ti_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	struct clk *clkp = data->map[clk->id].clk;
+	struct clk *parentp = data->map[parent->id].clk;
+
+	return clk_set_parent(clkp, parentp);
+}
+
+static int ti_clk_enable(struct clk *clk)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	struct clk *clkp = data->map[clk->id].clk;
+
+	return clk_enable(clkp);
+}
+
+static int ti_clk_disable(struct clk *clk)
+{
+	struct ti_clk_data *data = dev_get_priv(clk->dev);
+	struct clk *clkp = data->map[clk->id].clk;
+
+	return clk_disable(clkp);
+}
+
+static const struct udevice_id ti_clk_of_match[] = {
+	{ .compatible = "ti,k2g-sci-clk" },
+	{ /* sentinel */ },
+};
+
+static const struct clk_ops ti_clk_ops = {
+	.of_xlate = ti_clk_of_xlate,
+	.set_rate = ti_clk_set_rate,
+	.get_rate = ti_clk_get_rate,
+	.enable = ti_clk_enable,
+	.disable = ti_clk_disable,
+	.set_parent = ti_clk_set_parent,
+};
+
+U_BOOT_DRIVER(ti_clk) = {
+	.name = "ti-clk",
+	.id = UCLASS_CLK,
+	.of_match = ti_clk_of_match,
+	.probe = ti_clk_probe,
+	.priv_auto = sizeof(struct ti_clk_data),
+	.ops = &ti_clk_ops,
+};
diff --git a/include/k3-clk.h b/include/k3-clk.h
index fc84378d03..36f0ddf7cc 100644
--- a/include/k3-clk.h
+++ b/include/k3-clk.h
@@ -7,7 +7,169 @@
 #ifndef __K3_CLK_H__
 #define __K3_CLK_H__
 
+#include <common.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
 #include <linux/clk-provider.h>
+#include <linux/types.h>
+#include <stdint.h>
+
+struct dev_clk {
+	int dev_id;
+	int clk_id;
+	const char *clk_name;
+};
+
+#define DEV_CLK(_dev_id, _clk_id, _clk_name) { .dev_id = _dev_id,		\
+					.clk_id = _clk_id, .clk_name = _clk_name, }
+
+#define CLK_TYPE_MUX		0x01
+#define CLK_TYPE_DIV		0x02
+#define CLK_TYPE_PLL		0x03
+#define CLK_TYPE_HFOSC		0x04
+#define CLK_TYPE_POSTDIV	0x05
+#define CLK_TYPE_MUX_PLLCTRL	0x06
+#define CLK_TYPE_FIXED_RATE	0x07
+
+struct pll_data {
+	u32 reg;
+	const char *name;
+	const char *parent;
+	u32 flags;
+};
+
+struct mux_data {
+	u32 reg;
+	const char *name;
+	const char * const *parents;
+	int num_parents;
+	u32 flags;
+	int shift;
+	int width;
+};
+
+struct div_data {
+	u32 reg;
+	const char *name;
+	const char *parent;
+	u32 flags;
+	int shift;
+	int width;
+};
+
+struct hfosc_data {
+	const char *name;
+	u32 flags;
+};
+
+struct fixed_rate_data {
+	const char *name;
+	u64 rate;
+	u32 flags;
+};
+
+struct postdiv_data {
+	const char *name;
+	const char *parent;
+	int width;
+	u32 flags;
+};
+
+struct mux_pllctrl_data {
+	u32 reg;
+	const char *name;
+	const char * const *parents;
+	int num_parents;
+	u32 flags;
+};
+
+struct clk_data {
+	int type;
+	u32 default_freq;
+	union {
+		struct pll_data pll;
+		struct mux_data mux;
+		struct div_data div;
+		struct hfosc_data hfosc;
+		struct postdiv_data postdiv;
+		struct mux_pllctrl_data mux_pllctrl;
+		struct fixed_rate_data fixed_rate;
+	} clk;
+};
+
+#define CLK_MUX(_name, _parents, _num_parents, _reg, _shift, _width, _flags) \
+	{								\
+		.type = CLK_TYPE_MUX,					\
+		.clk.mux = { .name = _name, .parents = _parents,	\
+		.reg = _reg,						\
+		.num_parents = _num_parents, .shift = _shift,		\
+		.width = _width, .flags = _flags }			\
+	}
+
+#define CLK_DIV(_name, _parent, _reg, _shift, _width, _flags)	\
+	{							\
+		.type = CLK_TYPE_DIV,				\
+		.clk.div = {.name = _name, .parent = _parent, .reg = _reg, .shift = _shift, .width = _width, .flags = _flags } \
+	}
+
+#define CLK_DIV_DEFFREQ(_name, _parent, _reg, _shift, _width, _flags, _freq) \
+	{							\
+		.type = CLK_TYPE_DIV,				\
+		.default_freq = _freq,				\
+		.clk.div = {					\
+			.name = _name, .parent = _parent,	\
+			.reg = _reg, .shift = _shift,		\
+			.width = _width, .flags = _flags }	\
+	}
+
+#define CLK_PLL(_name, _parent, _reg,  _flags)	\
+	{					\
+		.type = CLK_TYPE_PLL,		\
+		.clk.pll = {.name = _name, .parent = _parent, .reg = _reg, .flags = _flags } \
+	}
+
+#define CLK_PLL_DEFFREQ(_name, _parent, _reg, _flags, _freq)	\
+	{							\
+		.type = CLK_TYPE_PLL,				\
+		.default_freq = _freq,				\
+		.clk.pll = { .name = _name, .parent = _parent,	\
+				.reg = _reg, .flags = _flags }	\
+	}
+
+#define CLK_HFOSC(_name, _flags)		\
+	{					\
+		.type = CLK_TYPE_HFOSC,		\
+		.clk.hfosc = { .name = _name, .flags = _flags } \
+	}
+
+#define CLK_FIXED_RATE(_name, _rate, _flags)		\
+	{						\
+		.type = CLK_TYPE_FIXED_RATE,		\
+		.clk.fixed_rate = { .name = _name, .rate = _rate, .flags = _flags } \
+	}
+
+#define CLK_POSTDIV(_name, _parent, _width, _flags)	\
+	{						\
+		.type = CLK_TYPE_POSTDIV,		\
+		.clk.postdiv = {.name = _name, .parent = _parent, .width = _width, .flags = _flags } \
+	}
+
+#define CLK_MUX_PLLCTRL(_name, _parents, _num_parents, _reg, _flags)	\
+	{								\
+		.type = CLK_TYPE_MUX,					\
+		.clk.mux_pllctrl = { .name = _name, .parents = _parents,\
+		.num_parents = _num_parents, .flags = _flags }		\
+	}
+
+struct ti_k3_clk_platdata {
+	const struct clk_data *clk_list;
+	int clk_list_cnt;
+	const struct dev_clk *soc_dev_clk_data;
+	int soc_dev_clk_data_cnt;
+};
+
+extern const struct ti_k3_clk_platdata j721e_clk_platdata;
+extern const struct ti_k3_clk_platdata j7200_clk_platdata;
 
 struct clk *clk_register_ti_pll(const char *name, const char *parent_name,
 				void __iomem *reg);
-- 
2.17.1

  parent reply	other threads:[~2021-05-11  8:30 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-11  8:30 [PATCHv4 00/26] J72xx: HSM rearch support series Tero Kristo
2021-05-11  8:30 ` [PATCHv4 01/26] lib: rational: copy the rational fraction lib routines from Linux Tero Kristo
2021-05-11  8:30 ` [PATCHv4 02/26] arm: mach-k3: introduce new config option for sysfw split Tero Kristo
2021-05-11  8:30 ` [PATCHv4 03/26] remoteproc: k3-r5: remove sysfw PM calls if not supported Tero Kristo
2021-05-11  8:30 ` [PATCHv4 04/26] common: fit: Update board_fit_image_post_process() to pass fit and node_offset Tero Kristo
2021-05-11  8:30 ` [PATCHv4 05/26] clk: fixed_rate: add API for directly registering fixed rate clocks Tero Kristo
2021-05-11  8:30 ` [PATCHv4 06/26] clk: fix clock tree dump to properly dump out every registered clock Tero Kristo
2021-05-11  8:30 ` [PATCHv4 07/26] clk: do not attempt to fetch clock pointer with null device Tero Kristo
2021-05-11  8:30 ` [PATCHv4 08/26] clk: add support for setting clk rate from cmdline Tero Kristo
2021-05-11  8:30 ` [PATCHv4 09/26] clk: sci-clk: fix return value of set_rate Tero Kristo
2021-05-11  8:30 ` [PATCHv4 10/26] clk: fix assigned-clocks to pass with deferring provider Tero Kristo
2021-05-11  8:30 ` [PATCHv4 11/26] clk: fix set_rate to clean up cached rates for the hierarchy Tero Kristo
2021-05-11  8:30 ` [PATCHv4 12/26] clk: add support for TI K3 SoC PLL Tero Kristo
2021-05-11  8:30 ` Tero Kristo [this message]
2021-05-11  8:30 ` [PATCHv4 14/26] power: domain: Introduce driver for raw TI K3 PDs Tero Kristo
2021-05-11 22:44   ` Jaehoon Chung
2021-05-11  8:30 ` [PATCHv4 15/26] cmd: ti: pd: Add debug command for K3 power domains Tero Kristo
2021-05-11 22:44   ` Jaehoon Chung
2021-05-11  8:30 ` [PATCHv4 16/26] tools: k3_fit_atf: add DM binary to the FIT image Tero Kristo
2021-05-11  8:30 ` [PATCHv4 17/26] arm: mach-k3: Add platform data for j721e and j7200 Tero Kristo
2021-05-11  8:30 ` [PATCHv4 18/26] arm: mach-k3: add support for detecting firmware images from FIT Tero Kristo
2021-05-11  8:30 ` [PATCHv4 19/26] arm: mach-k3: do board config for PM only if supported Tero Kristo
2021-05-11  8:30 ` [PATCHv4 20/26] arm: mach-k3: common: Drop main r5 start Tero Kristo
2021-05-11  8:30 ` [PATCHv4 21/26] arm: mach-k3: sysfw-loader: pass boardcfg to sciserver Tero Kristo
2021-05-11  8:31 ` [PATCHv4 22/26] arm: mach-k3: j721e_init: Force early probe of clk-k3 driver Tero Kristo
2021-05-11  8:31 ` [PATCHv4 23/26] configs: j721e_evm_r5: Enable raw access power management features Tero Kristo
2021-05-11  8:31 ` [PATCHv4 24/26] configs: j7200_evm_r5: " Tero Kristo
2021-05-11  8:31 ` [PATCHv4 25/26] board: ti: j72xx: README: update build instructions and image formats Tero Kristo
2021-05-11  8:31 ` [PATCHv4 26/26] arm: dts: k3-j72xx: correct MCU timer1 frequency Tero Kristo
2021-06-02 16:26 ` [PATCHv4 00/26] J72xx: HSM rearch support series Lokesh Vutla

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=20210511083104.10868-14-kristo@kernel.org \
    --to=kristo@kernel.org \
    --cc=u-boot@lists.denx.de \
    /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.