Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d6ddb08 authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: clkfwk: Support variable size accesses for MSTP clocks.



The bulk of the MSTP users require 32-bit access, but this isn't the case
for some of the SH-2A parts, so add in some basic infrastructure to let
the CPU define its required access size in preparation.

Requested-by: default avatarPhil Edworthy <phil.edworthy@renesas.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent a9e1e53b
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
 *
 *  Copyright (C) 2010  Magnus Damm
 *  Copyright (C) 2010 - 2012  Paul Mundt
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
@@ -13,26 +14,41 @@
#include <linux/io.h>
#include <linux/sh_clk.h>

static int sh_clk_mstp32_enable(struct clk *clk)
static int sh_clk_mstp_enable(struct clk *clk)
{
	if (clk->flags & CLK_ENABLE_REG_8BIT)
		iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit),
			 clk->mapped_reg);
	else if (clk->flags & CLK_ENABLE_REG_16BIT)
		iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit),
			  clk->mapped_reg);
	else
		iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
			  clk->mapped_reg);

	return 0;
}

static void sh_clk_mstp32_disable(struct clk *clk)
static void sh_clk_mstp_disable(struct clk *clk)
{
	if (clk->flags & CLK_ENABLE_REG_8BIT)
		iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit),
			 clk->mapped_reg);
	else if (clk->flags & CLK_ENABLE_REG_16BIT)
		iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit),
			  clk->mapped_reg);
	else
		iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
			  clk->mapped_reg);
}

static struct sh_clk_ops sh_clk_mstp32_clk_ops = {
	.enable		= sh_clk_mstp32_enable,
	.disable	= sh_clk_mstp32_disable,
static struct sh_clk_ops sh_clk_mstp_clk_ops = {
	.enable		= sh_clk_mstp_enable,
	.disable	= sh_clk_mstp_disable,
	.recalc		= followparent_recalc,
};

int __init sh_clk_mstp32_register(struct clk *clks, int nr)
int __init sh_clk_mstp_register(struct clk *clks, int nr)
{
	struct clk *clkp;
	int ret = 0;
@@ -40,7 +56,7 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr)

	for (k = 0; !ret && (k < nr); k++) {
		clkp = clks + k;
		clkp->ops = &sh_clk_mstp32_clk_ops;
		clkp->ops = &sh_clk_mstp_clk_ops;
		ret |= clk_register(clkp);
	}

+31 −3
Original line number Diff line number Diff line
@@ -59,7 +59,15 @@ struct clk {
	unsigned int		nr_freqs;
};

#define CLK_ENABLE_ON_INIT	(1 << 0)
#define CLK_ENABLE_ON_INIT	BIT(0)

#define CLK_ENABLE_REG_32BIT	BIT(1)	/* default access size */
#define CLK_ENABLE_REG_16BIT	BIT(2)
#define CLK_ENABLE_REG_8BIT	BIT(3)

#define CLK_ENABLE_REG_MASK	(CLK_ENABLE_REG_32BIT | \
				 CLK_ENABLE_REG_16BIT | \
				 CLK_ENABLE_REG_8BIT)

/* drivers/sh/clk.c */
unsigned long followparent_recalc(struct clk *);
@@ -102,7 +110,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
		      unsigned long *best_freq, unsigned long *parent_freq,
		      unsigned int div_min, unsigned int div_max);

#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags)	\
#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags)		\
{									\
	.parent		= _parent,					\
	.enable_reg	= (void __iomem *)_enable_reg,			\
@@ -110,7 +118,27 @@ long clk_round_parent(struct clk *clk, unsigned long target,
	.flags		= _flags,					\
}

int sh_clk_mstp32_register(struct clk *clks, int nr);
#define SH_CLK_MSTP32(_p, _r, _b, _f)					\
	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT)

#define SH_CLK_MSTP16(_p, _r, _b, _f)					\
	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT)

#define SH_CLK_MSTP8(_p, _r, _b, _f)					\
	SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT)

int sh_clk_mstp_register(struct clk *clks, int nr);

/*
 * MSTP registration never really cared about access size, despite the
 * original enable/disable pairs assuming a 32-bit access. Clocks are
 * responsible for defining their access sizes either directly or via the
 * clock definition wrappers.
 */
static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
{
	return sh_clk_mstp_register(clks, nr);
}

#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags)	\
{								\