clk: uniphier: rework UniPhier clk driver
The initial design of the UniPhier clk driver for U-Boot was not very nice. Here is a re-work to sync it with Linux's clk and reset drivers, maximizing the code reuse from Linux's clk data. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
		
							parent
							
								
									f666a65824
								
							
						
					
					
						commit
						805dc44cc8
					
				| 
						 | 
					@ -1,13 +1,10 @@
 | 
				
			||||||
config CLK_UNIPHIER
 | 
					config CLK_UNIPHIER
 | 
				
			||||||
	bool
 | 
						bool "Clock driver for UniPhier SoCs"
 | 
				
			||||||
 | 
						depends on ARCH_UNIPHIER
 | 
				
			||||||
	select CLK
 | 
						select CLK
 | 
				
			||||||
	select SPL_CLK
 | 
						select SPL_CLK
 | 
				
			||||||
 | 
					 | 
				
			||||||
menu "Clock drivers for UniPhier SoCs"
 | 
					 | 
				
			||||||
	depends on CLK_UNIPHIER
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config CLK_UNIPHIER_MIO
 | 
					 | 
				
			||||||
	bool "Clock driver for UniPhier Media I/O block"
 | 
					 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
endmenu
 | 
						  Support for clock controllers on UniPhier SoCs.
 | 
				
			||||||
 | 
						  Say Y if you want to control clocks provided by System Control
 | 
				
			||||||
 | 
						  block, Media I/O block, Peripheral Block.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,2 @@
 | 
				
			||||||
obj-y					+= clk-uniphier-core.o
 | 
					obj-y	+= clk-uniphier-core.o
 | 
				
			||||||
 | 
					obj-y	+= clk-uniphier-mio.o
 | 
				
			||||||
obj-$(CONFIG_CLK_UNIPHIER_MIO)		+= clk-uniphier-mio.o
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,11 +6,11 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <common.h>
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <clk-uclass.h>
 | 
				
			||||||
 | 
					#include <dm/device.h>
 | 
				
			||||||
#include <linux/bitops.h>
 | 
					#include <linux/bitops.h>
 | 
				
			||||||
#include <linux/io.h>
 | 
					#include <linux/io.h>
 | 
				
			||||||
#include <linux/sizes.h>
 | 
					#include <linux/sizes.h>
 | 
				
			||||||
#include <clk-uclass.h>
 | 
					 | 
				
			||||||
#include <dm/device.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "clk-uniphier.h"
 | 
					#include "clk-uniphier.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,14 +18,116 @@
 | 
				
			||||||
 * struct uniphier_clk_priv - private data for UniPhier clock driver
 | 
					 * struct uniphier_clk_priv - private data for UniPhier clock driver
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @base: base address of the clock provider
 | 
					 * @base: base address of the clock provider
 | 
				
			||||||
 * @socdata: SoC specific data
 | 
					 * @data: SoC specific data
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct uniphier_clk_priv {
 | 
					struct uniphier_clk_priv {
 | 
				
			||||||
	void __iomem *base;
 | 
						void __iomem *base;
 | 
				
			||||||
	const struct uniphier_clk_soc_data *socdata;
 | 
						const struct uniphier_clk_data *data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uniphier_clk_probe(struct udevice *dev)
 | 
					static int uniphier_clk_enable(struct clk *clk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
				
			||||||
 | 
						unsigned long id = clk->id;
 | 
				
			||||||
 | 
						const struct uniphier_clk_gate_data *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (p = priv->data->gate; p->id != UNIPHIER_CLK_ID_END; p++) {
 | 
				
			||||||
 | 
							u32 val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (p->id != id)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							val = readl(priv->base + p->reg);
 | 
				
			||||||
 | 
							val |= BIT(p->bit);
 | 
				
			||||||
 | 
							writel(val, priv->base + p->reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_err(priv->dev, "clk_id=%lu was not handled\n", id);
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct uniphier_clk_mux_data *
 | 
				
			||||||
 | 
					uniphier_clk_get_mux_data(struct uniphier_clk_priv *priv, unsigned long id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct uniphier_clk_mux_data *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (p = priv->data->mux; p->id != UNIPHIER_CLK_ID_END; p++) {
 | 
				
			||||||
 | 
							if (p->id == id)
 | 
				
			||||||
 | 
								return p;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ulong uniphier_clk_get_rate(struct clk *clk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
				
			||||||
 | 
						const struct uniphier_clk_mux_data *mux;
 | 
				
			||||||
 | 
						u32 val;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mux = uniphier_clk_get_mux_data(priv, clk->id);
 | 
				
			||||||
 | 
						if (!mux)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mux->nr_muxs)		/* fixed-rate */
 | 
				
			||||||
 | 
							return mux->rates[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = readl(priv->base + mux->reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < mux->nr_muxs; i++)
 | 
				
			||||||
 | 
							if ((mux->masks[i] & val) == mux->vals[i])
 | 
				
			||||||
 | 
								return mux->rates[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
				
			||||||
 | 
						const struct uniphier_clk_mux_data *mux;
 | 
				
			||||||
 | 
						u32 val;
 | 
				
			||||||
 | 
						int i, best_rate_id = -1;
 | 
				
			||||||
 | 
						ulong best_rate = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mux = uniphier_clk_get_mux_data(priv, clk->id);
 | 
				
			||||||
 | 
						if (!mux)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mux->nr_muxs)		/* fixed-rate */
 | 
				
			||||||
 | 
							return mux->rates[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* first, decide the best match rate */
 | 
				
			||||||
 | 
						for (i = 0; i < mux->nr_muxs; i++) {
 | 
				
			||||||
 | 
							if (mux->rates[i] > best_rate && mux->rates[i] <= rate) {
 | 
				
			||||||
 | 
								best_rate = mux->rates[i];
 | 
				
			||||||
 | 
								best_rate_id = i;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (best_rate_id < 0)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = readl(priv->base + mux->reg);
 | 
				
			||||||
 | 
						val &= ~mux->masks[best_rate_id];
 | 
				
			||||||
 | 
						val |= mux->vals[best_rate_id];
 | 
				
			||||||
 | 
						writel(val, priv->base + mux->reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						debug("%s: requested rate = %lu, set rate = %lu\n", __func__,
 | 
				
			||||||
 | 
						      rate, best_rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return best_rate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct clk_ops uniphier_clk_ops = {
 | 
				
			||||||
 | 
						.enable = uniphier_clk_enable,
 | 
				
			||||||
 | 
						.get_rate = uniphier_clk_get_rate,
 | 
				
			||||||
 | 
						.set_rate = uniphier_clk_set_rate,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uniphier_clk_probe(struct udevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct uniphier_clk_priv *priv = dev_get_priv(dev);
 | 
						struct uniphier_clk_priv *priv = dev_get_priv(dev);
 | 
				
			||||||
	fdt_addr_t addr;
 | 
						fdt_addr_t addr;
 | 
				
			||||||
| 
						 | 
					@ -38,125 +140,11 @@ int uniphier_clk_probe(struct udevice *dev)
 | 
				
			||||||
	if (!priv->base)
 | 
						if (!priv->base)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	priv->socdata = (void *)dev_get_driver_data(dev);
 | 
						priv->data = (void *)dev_get_driver_data(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int uniphier_clk_enable(struct clk *clk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	const struct uniphier_clk_gate_data *gate = priv->socdata->gate;
 | 
					 | 
				
			||||||
	unsigned int nr_gate = priv->socdata->nr_gate;
 | 
					 | 
				
			||||||
	void __iomem *reg;
 | 
					 | 
				
			||||||
	u32 mask, data, tmp;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < nr_gate; i++) {
 | 
					 | 
				
			||||||
		if (gate[i].index != clk->id)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		reg = priv->base + gate[i].reg;
 | 
					 | 
				
			||||||
		mask = gate[i].mask;
 | 
					 | 
				
			||||||
		data = gate[i].data & mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		tmp = readl(reg);
 | 
					 | 
				
			||||||
		tmp &= ~mask;
 | 
					 | 
				
			||||||
		tmp |= data & mask;
 | 
					 | 
				
			||||||
		debug("%s: %p: %08x\n", __func__, reg, tmp);
 | 
					 | 
				
			||||||
		writel(tmp, reg);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static ulong uniphier_clk_get_rate(struct clk *clk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	const struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
 | 
					 | 
				
			||||||
	unsigned int nr_rdata = priv->socdata->nr_rate;
 | 
					 | 
				
			||||||
	void __iomem *reg;
 | 
					 | 
				
			||||||
	u32 mask, data;
 | 
					 | 
				
			||||||
	ulong matched_rate = 0;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < nr_rdata; i++) {
 | 
					 | 
				
			||||||
		if (rdata[i].index != clk->id)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
 | 
					 | 
				
			||||||
			return rdata[i].rate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		reg = priv->base + rdata[i].reg;
 | 
					 | 
				
			||||||
		mask = rdata[i].mask;
 | 
					 | 
				
			||||||
		data = rdata[i].data & mask;
 | 
					 | 
				
			||||||
		if ((readl(reg) & mask) == data) {
 | 
					 | 
				
			||||||
			if (matched_rate && rdata[i].rate != matched_rate) {
 | 
					 | 
				
			||||||
				printf("failed to get clk rate for insane register values\n");
 | 
					 | 
				
			||||||
				return -EINVAL;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			matched_rate = rdata[i].rate;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debug("%s: rate = %lu\n", __func__, matched_rate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return matched_rate;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
 | 
					 | 
				
			||||||
	const struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
 | 
					 | 
				
			||||||
	unsigned int nr_rdata = priv->socdata->nr_rate;
 | 
					 | 
				
			||||||
	void __iomem *reg;
 | 
					 | 
				
			||||||
	u32 mask, data, tmp;
 | 
					 | 
				
			||||||
	ulong best_rate = 0;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* first, decide the best match rate */
 | 
					 | 
				
			||||||
	for (i = 0; i < nr_rdata; i++) {
 | 
					 | 
				
			||||||
		if (rdata[i].index != clk->id)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (rdata[i].rate > best_rate && rdata[i].rate <= rate)
 | 
					 | 
				
			||||||
			best_rate = rdata[i].rate;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!best_rate)
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debug("%s: requested rate = %lu, set rate = %lu\n", __func__,
 | 
					 | 
				
			||||||
	      rate, best_rate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* second, really set registers */
 | 
					 | 
				
			||||||
	for (i = 0; i < nr_rdata; i++) {
 | 
					 | 
				
			||||||
		if (rdata[i].index != clk->id || rdata[i].rate != best_rate)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		reg = priv->base + rdata[i].reg;
 | 
					 | 
				
			||||||
		mask = rdata[i].mask;
 | 
					 | 
				
			||||||
		data = rdata[i].data & mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		tmp = readl(reg);
 | 
					 | 
				
			||||||
		tmp &= ~mask;
 | 
					 | 
				
			||||||
		tmp |= data;
 | 
					 | 
				
			||||||
		debug("%s: %p: %08x\n", __func__, reg, tmp);
 | 
					 | 
				
			||||||
		writel(tmp, reg);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return best_rate;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const struct clk_ops uniphier_clk_ops = {
 | 
					 | 
				
			||||||
	.enable = uniphier_clk_enable,
 | 
					 | 
				
			||||||
	.get_rate = uniphier_clk_get_rate,
 | 
					 | 
				
			||||||
	.set_rate = uniphier_clk_set_rate,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct udevice_id uniphier_clk_match[] = {
 | 
					static const struct udevice_id uniphier_clk_match[] = {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		.compatible = "socionext,uniphier-sld3-mio-clock",
 | 
							.compatible = "socionext,uniphier-sld3-mio-clock",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,136 +5,81 @@
 | 
				
			||||||
 * SPDX-License-Identifier:	GPL-2.0+
 | 
					 * SPDX-License-Identifier:	GPL-2.0+
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <dm/device.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "clk-uniphier.h"
 | 
					#include "clk-uniphier.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNIPHIER_MIO_CLK_GATE_SD(ch, idx)	\
 | 
					#define UNIPHIER_MIO_CLK_SD_GATE(id, ch)				\
 | 
				
			||||||
	{					\
 | 
						UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 8)
 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x20 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00000100,		\
 | 
					 | 
				
			||||||
		.data = 0x00000100,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x110 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00000001,		\
 | 
					 | 
				
			||||||
		.data = 0x00000001,		\
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNIPHIER_MIO_CLK_RATE_SD(ch, idx)	\
 | 
					#define UNIPHIER_MIO_CLK_USB2(id, ch)					\
 | 
				
			||||||
	{					\
 | 
						UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 28)
 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00000000,		\
 | 
					 | 
				
			||||||
		.rate = 44444444,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00010000,		\
 | 
					 | 
				
			||||||
		.rate = 33333333,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00020000,		\
 | 
					 | 
				
			||||||
		.rate = 50000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00020000,		\
 | 
					 | 
				
			||||||
		.rate = 66666666,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00001000,		\
 | 
					 | 
				
			||||||
		.rate = 100000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00001100,		\
 | 
					 | 
				
			||||||
		.rate = 40000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00001200,		\
 | 
					 | 
				
			||||||
		.rate = 25000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x30 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00031300,		\
 | 
					 | 
				
			||||||
		.data = 0x00001300,		\
 | 
					 | 
				
			||||||
		.rate = 22222222,		\
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNIPHIER_MIO_CLK_GATE_USB(ch, idx)	\
 | 
					#define UNIPHIER_MIO_CLK_USB2_PHY(id, ch)				\
 | 
				
			||||||
	{					\
 | 
						UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 29)
 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x20 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x30000000,		\
 | 
					 | 
				
			||||||
		.data = 0x30000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x110 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x01000000,		\
 | 
					 | 
				
			||||||
		.data = 0x01000000,		\
 | 
					 | 
				
			||||||
	},					\
 | 
					 | 
				
			||||||
	{					\
 | 
					 | 
				
			||||||
		.index = (idx),			\
 | 
					 | 
				
			||||||
		.reg = 0x114 + 0x200 * (ch),	\
 | 
					 | 
				
			||||||
		.mask = 0x00000001,		\
 | 
					 | 
				
			||||||
		.data = 0x00000001,		\
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNIPHIER_MIO_CLK_GATE_DMAC(idx)		\
 | 
					#define UNIPHIER_MIO_CLK_DMAC(id)					\
 | 
				
			||||||
	{					\
 | 
						UNIPHIER_CLK_GATE((id), 0x20, 25)
 | 
				
			||||||
		.index = (idx),			\
 | 
					
 | 
				
			||||||
		.reg = 0x20,			\
 | 
					#define UNIPHIER_MIO_CLK_SD_MUX(_id, ch)				\
 | 
				
			||||||
		.mask = 0x02000000,		\
 | 
						{								\
 | 
				
			||||||
		.data = 0x02000000,		\
 | 
							.id = (_id),						\
 | 
				
			||||||
	},					\
 | 
							.nr_muxs = 8,						\
 | 
				
			||||||
	{					\
 | 
							.reg = 0x30 + 0x200 * (ch),				\
 | 
				
			||||||
		.index = (idx),			\
 | 
							.masks = {						\
 | 
				
			||||||
		.reg = 0x110,			\
 | 
								0x00031000,					\
 | 
				
			||||||
		.mask = 0x00020000,		\
 | 
								0x00031000,					\
 | 
				
			||||||
		.data = 0x00020000,		\
 | 
								0x00031000,					\
 | 
				
			||||||
 | 
								0x00031000,					\
 | 
				
			||||||
 | 
								0x00001300,					\
 | 
				
			||||||
 | 
								0x00001300,					\
 | 
				
			||||||
 | 
								0x00001300,					\
 | 
				
			||||||
 | 
								0x00001300,					\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
 | 
							.vals = {						\
 | 
				
			||||||
 | 
								0x00000000,					\
 | 
				
			||||||
 | 
								0x00010000,					\
 | 
				
			||||||
 | 
								0x00020000,					\
 | 
				
			||||||
 | 
								0x00030000,					\
 | 
				
			||||||
 | 
								0x00001000,					\
 | 
				
			||||||
 | 
								0x00001100,					\
 | 
				
			||||||
 | 
								0x00001200,					\
 | 
				
			||||||
 | 
								0x00001300,					\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
 | 
							.rates = {						\
 | 
				
			||||||
 | 
								44444444,					\
 | 
				
			||||||
 | 
								33333333,					\
 | 
				
			||||||
 | 
								50000000,					\
 | 
				
			||||||
 | 
								66666666,					\
 | 
				
			||||||
 | 
								100000000,					\
 | 
				
			||||||
 | 
								40000000,					\
 | 
				
			||||||
 | 
								25000000,					\
 | 
				
			||||||
 | 
								22222222,					\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
 | 
					static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_SD(0, 0),
 | 
						UNIPHIER_MIO_CLK_SD_GATE(0, 0),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_SD(1, 1),
 | 
						UNIPHIER_MIO_CLK_SD_GATE(1, 1),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_SD(2, 2),		/* for PH1-Pro4 only */
 | 
						UNIPHIER_MIO_CLK_SD_GATE(2, 2),		/* for PH1-Pro4 only */
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_USB(0, 3),
 | 
						UNIPHIER_MIO_CLK_DMAC(7),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_USB(1, 4),
 | 
						UNIPHIER_MIO_CLK_USB2(8, 0),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_USB(2, 5),
 | 
						UNIPHIER_MIO_CLK_USB2(9, 1),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_DMAC(6),
 | 
						UNIPHIER_MIO_CLK_USB2(10, 2),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_GATE_USB(3, 7),	/* for PH1-sLD3 only */
 | 
						UNIPHIER_MIO_CLK_USB2(11, 3),		/* for PH1-sLD3 only */
 | 
				
			||||||
 | 
						UNIPHIER_MIO_CLK_USB2_PHY(12, 0),
 | 
				
			||||||
 | 
						UNIPHIER_MIO_CLK_USB2_PHY(13, 1),
 | 
				
			||||||
 | 
						UNIPHIER_MIO_CLK_USB2_PHY(14, 2),
 | 
				
			||||||
 | 
						UNIPHIER_MIO_CLK_USB2_PHY(15, 3),	/* for PH1-sLD3 only */
 | 
				
			||||||
 | 
						UNIPHIER_CLK_END
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = {
 | 
					static const struct uniphier_clk_mux_data uniphier_mio_clk_mux[] = {
 | 
				
			||||||
	UNIPHIER_MIO_CLK_RATE_SD(0, 0),
 | 
						UNIPHIER_MIO_CLK_SD_MUX(0, 0),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_RATE_SD(1, 1),
 | 
						UNIPHIER_MIO_CLK_SD_MUX(1, 1),
 | 
				
			||||||
	UNIPHIER_MIO_CLK_RATE_SD(2, 2),		/* for PH1-Pro4 only */
 | 
						UNIPHIER_MIO_CLK_SD_MUX(2, 2),		/* for PH1-Pro4 only */
 | 
				
			||||||
 | 
						UNIPHIER_CLK_END
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct uniphier_clk_soc_data uniphier_mio_clk_data = {
 | 
					const struct uniphier_clk_data uniphier_mio_clk_data = {
 | 
				
			||||||
	.gate = uniphier_mio_clk_gate,
 | 
						.gate = uniphier_mio_clk_gate,
 | 
				
			||||||
	.nr_gate = ARRAY_SIZE(uniphier_mio_clk_gate),
 | 
						.mux = uniphier_mio_clk_mux,
 | 
				
			||||||
	.rate = uniphier_mio_clk_rate,
 | 
					 | 
				
			||||||
	.nr_rate = ARRAY_SIZE(uniphier_mio_clk_rate),
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,36 +10,46 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/kernel.h>
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNIPHIER_CLK_MAX_NR_MUXS	8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct uniphier_clk_gate_data {
 | 
					struct uniphier_clk_gate_data {
 | 
				
			||||||
	int index;
 | 
						unsigned int id;
 | 
				
			||||||
	unsigned int reg;
 | 
						unsigned int reg;
 | 
				
			||||||
	u32 mask;
 | 
						unsigned int bit;
 | 
				
			||||||
	u32 data;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct uniphier_clk_rate_data {
 | 
					struct uniphier_clk_mux_data {
 | 
				
			||||||
	int index;
 | 
						unsigned int id;
 | 
				
			||||||
 | 
						unsigned int nr_muxs;
 | 
				
			||||||
	unsigned int reg;
 | 
						unsigned int reg;
 | 
				
			||||||
#define UNIPHIER_CLK_RATE_IS_FIXED		UINT_MAX
 | 
						unsigned int masks[UNIPHIER_CLK_MAX_NR_MUXS];
 | 
				
			||||||
	u32 mask;
 | 
						unsigned int vals[UNIPHIER_CLK_MAX_NR_MUXS];
 | 
				
			||||||
	u32 data;
 | 
						unsigned long rates[UNIPHIER_CLK_MAX_NR_MUXS];
 | 
				
			||||||
	unsigned long rate;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct uniphier_clk_soc_data {
 | 
					struct uniphier_clk_data {
 | 
				
			||||||
	const struct uniphier_clk_gate_data *gate;
 | 
						const struct uniphier_clk_gate_data *gate;
 | 
				
			||||||
	unsigned int nr_gate;
 | 
						const struct uniphier_clk_mux_data *mux;
 | 
				
			||||||
	const struct uniphier_clk_rate_data *rate;
 | 
					 | 
				
			||||||
	unsigned int nr_rate;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNIPHIER_CLK_FIXED_RATE(i, f)			\
 | 
					#define UNIPHIER_CLK_ID_END		(unsigned int)(-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNIPHIER_CLK_END				\
 | 
				
			||||||
 | 
						{ .id = UNIPHIER_CLK_ID_END }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNIPHIER_CLK_GATE(_id, _reg, _bit)		\
 | 
				
			||||||
	{						\
 | 
						{						\
 | 
				
			||||||
		.index = i,				\
 | 
							.id = (_id),				\
 | 
				
			||||||
		.reg = UNIPHIER_CLK_RATE_IS_FIXED,	\
 | 
							.reg = (_reg),				\
 | 
				
			||||||
		.rate = f,				\
 | 
							.bit = (_bit),				\
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const struct uniphier_clk_soc_data uniphier_mio_clk_data;
 | 
					#define UNIPHIER_CLK_FIXED_RATE(_id, _rate)		\
 | 
				
			||||||
 | 
						{						\
 | 
				
			||||||
 | 
							.id = (_id),				\
 | 
				
			||||||
 | 
							.rates = {(_reg),},			\
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct uniphier_clk_data uniphier_mio_clk_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __CLK_UNIPHIER_H__ */
 | 
					#endif /* __CLK_UNIPHIER_H__ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue