Commit 65b07ecf authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'renesas-clk-for-v6.3-tag2' of...

Merge tag 'renesas-clk-for-v6.3-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-renesas

Pull more Renesas clk driver updates from Geert Uytterhoeven:

 - Add support for USB host/device configuration on RZ/N1
 - Add PLL2 programming support, and CAN-FD clocks on R-Car V4H
 - Miscellaneous fixes and improvements

* tag 'renesas-clk-for-v6.3-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers:
  clk: renesas: r8a779g0: Add CAN-FD clocks
  clk: renesas: r8a779g0: Tidy up DMAC name on SYS-DMAC
  clk: renesas: r8a779a0: Tidy up DMAC name on SYS-DMAC
  clk: renesas: r8a779g0: Add custom clock for PLL2
  clk: renesas: cpg-mssr: Remove superfluous check in resume code
  clk: renesas: r9a06g032: Handle h2mode setting based on USBF presence
parents ce45dff1 bd176e46
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -176,8 +176,8 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
	DEF_MOD("scif3",	704,	R8A779A0_CLK_S1D8),
	DEF_MOD("scif4",	705,	R8A779A0_CLK_S1D8),
	DEF_MOD("sdhi0",	706,	R8A779A0_CLK_SD0),
	DEF_MOD("sydm1",	709,	R8A779A0_CLK_S1D2),
	DEF_MOD("sydm2",	710,	R8A779A0_CLK_S1D2),
	DEF_MOD("sys-dmac1",	709,	R8A779A0_CLK_S1D2),
	DEF_MOD("sys-dmac2",	710,	R8A779A0_CLK_S1D2),
	DEF_MOD("tmu0",		713,	R8A779A0_CLK_CL16MCK),
	DEF_MOD("tmu1",		714,	R8A779A0_CLK_S1D4),
	DEF_MOD("tmu2",		715,	R8A779A0_CLK_S1D4),
+11 −9
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
	/* Internal Core Clocks */
	DEF_BASE(".main", CLK_MAIN,	CLK_TYPE_GEN4_MAIN,     CLK_EXTAL),
	DEF_BASE(".pll1", CLK_PLL1,	CLK_TYPE_GEN4_PLL1,     CLK_MAIN),
	DEF_BASE(".pll2", CLK_PLL2,	CLK_TYPE_GEN4_PLL2, CLK_MAIN),
	DEF_BASE(".pll2", CLK_PLL2,	CLK_TYPE_GEN4_PLL2_VAR, CLK_MAIN),
	DEF_BASE(".pll3", CLK_PLL3,	CLK_TYPE_GEN4_PLL3,     CLK_MAIN),
	DEF_BASE(".pll4", CLK_PLL4,	CLK_TYPE_GEN4_PLL4,     CLK_MAIN),
	DEF_BASE(".pll5", CLK_PLL5,	CLK_TYPE_GEN4_PLL5,     CLK_MAIN),
@@ -145,6 +145,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
	DEF_FIXED("viobusd2",	R8A779G0_CLK_VIOBUSD2,	CLK_VIO,	2, 1),
	DEF_FIXED("vcbus",	R8A779G0_CLK_VCBUS,	CLK_VC,		1, 1),
	DEF_FIXED("vcbusd2",	R8A779G0_CLK_VCBUSD2,	CLK_VC,		2, 1),
	DEF_DIV6P1("canfd",     R8A779G0_CLK_CANFD,	CLK_PLL5_DIV4,	0x878),
	DEF_FIXED("dsiref",	R8A779G0_CLK_DSIREF,	CLK_PLL5_DIV4,	48, 1),
	DEF_DIV6P1("dsiext",	R8A779G0_CLK_DSIEXT,	CLK_PLL5_DIV4,	0x884),

@@ -163,6 +164,7 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
	DEF_MOD("avb0",		211,	R8A779G0_CLK_S0D4_HSC),
	DEF_MOD("avb1",		212,	R8A779G0_CLK_S0D4_HSC),
	DEF_MOD("avb2",		213,	R8A779G0_CLK_S0D4_HSC),
	DEF_MOD("canfd0",	328,	R8A779G0_CLK_SASYNCPERD2),
	DEF_MOD("dis0",		411,	R8A779G0_CLK_VIOBUSD2),
	DEF_MOD("dsitxlink0",	415,	R8A779G0_CLK_VIOBUSD2),
	DEF_MOD("dsitxlink1",	416,	R8A779G0_CLK_VIOBUSD2),
@@ -192,8 +194,8 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
	DEF_MOD("scif3",	704,	R8A779G0_CLK_SASYNCPERD4),
	DEF_MOD("scif4",	705,	R8A779G0_CLK_SASYNCPERD4),
	DEF_MOD("sdhi",		706,	R8A779G0_CLK_SD0),
	DEF_MOD("sydm0",	709,	R8A779G0_CLK_S0D6_PER),
	DEF_MOD("sydm1",	710,	R8A779G0_CLK_S0D6_PER),
	DEF_MOD("sys-dmac0",	709,	R8A779G0_CLK_S0D6_PER),
	DEF_MOD("sys-dmac1",	710,	R8A779G0_CLK_S0D6_PER),
	DEF_MOD("tmu0",		713,	R8A779G0_CLK_SASYNCRT),
	DEF_MOD("tmu1",		714,	R8A779G0_CLK_SASYNCPERD2),
	DEF_MOD("tmu2",		715,	R8A779G0_CLK_SASYNCPERD2),
+28 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/spinlock.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>

#define R9A06G032_SYSCTRL_USB    0x00
#define R9A06G032_SYSCTRL_USB_H2MODE  (1<<1)
#define R9A06G032_SYSCTRL_DMAMUX 0xA0

struct r9a06g032_gate {
@@ -918,6 +920,29 @@ static void r9a06g032_clocks_del_clk_provider(void *data)
	of_clk_del_provider(data);
}

static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks)
{
	struct device_node *usbf_np = NULL;
	u32 usb;

	while ((usbf_np = of_find_compatible_node(usbf_np, NULL,
						  "renesas,rzn1-usbf"))) {
		if (of_device_is_available(usbf_np))
			break;
	}

	usb = readl(clocks->reg + R9A06G032_SYSCTRL_USB);
	if (usbf_np) {
		/* 1 host and 1 device mode */
		usb &= ~R9A06G032_SYSCTRL_USB_H2MODE;
		of_node_put(usbf_np);
	} else {
		/* 2 hosts mode */
		usb |= R9A06G032_SYSCTRL_USB_H2MODE;
	}
	writel(usb, clocks->reg + R9A06G032_SYSCTRL_USB);
}

static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
@@ -947,6 +972,9 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
	clocks->reg = of_iomap(np, 0);
	if (WARN_ON(!clocks->reg))
		return -ENOMEM;

	r9a06g032_init_h2mode(clocks);

	for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) {
		const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i];
		const char *parent_name = d->source ?
+156 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>

#include "renesas-cpg-mssr.h"
@@ -27,6 +28,152 @@ static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initdata;
static unsigned int cpg_clk_extalr __initdata;
static u32 cpg_mode __initdata;

#define CPG_PLLECR		0x0820	/* PLL Enable Control Register */

#define CPG_PLLECR_PLLST(n)	BIT(8 + ((n) < 3 ? (n) - 1 : \
					 (n) > 3 ? (n) + 1 : n)) /* PLLn Circuit Status */

#define CPG_PLL1CR0		0x830	/* PLLn Control Registers */
#define CPG_PLL1CR1		0x8b0
#define CPG_PLL2CR0		0x834
#define CPG_PLL2CR1		0x8b8
#define CPG_PLL3CR0		0x83c
#define CPG_PLL3CR1		0x8c0
#define CPG_PLL4CR0		0x844
#define CPG_PLL4CR1		0x8c8
#define CPG_PLL6CR0		0x84c
#define CPG_PLL6CR1		0x8d8

#define CPG_PLLxCR0_KICK	BIT(31)
#define CPG_PLLxCR0_NI		GENMASK(27, 20)	/* Integer mult. factor */
#define CPG_PLLxCR0_SSMODE	GENMASK(18, 16)	/* PLL mode */
#define CPG_PLLxCR0_SSMODE_FM	BIT(18)	/* Fractional Multiplication */
#define CPG_PLLxCR0_SSMODE_DITH	BIT(17) /* Frequency Dithering */
#define CPG_PLLxCR0_SSMODE_CENT	BIT(16)	/* Center (vs. Down) Spread Dithering */
#define CPG_PLLxCR0_SSFREQ	GENMASK(14, 8)	/* SSCG Modulation Frequency */
#define CPG_PLLxCR0_SSDEPT	GENMASK(6, 0)	/* SSCG Modulation Depth */

#define SSMODE_FM		BIT(2)	/* Fractional Multiplication */
#define SSMODE_DITHER		BIT(1)	/* Frequency Dithering */
#define SSMODE_CENTER		BIT(0)	/* Center (vs. Down) Spread Dithering */

/* PLL Clocks */
struct cpg_pll_clk {
	struct clk_hw hw;
	void __iomem *pllcr0_reg;
	void __iomem *pllecr_reg;
	u32 pllecr_pllst_mask;
};

#define to_pll_clk(_hw)   container_of(_hw, struct cpg_pll_clk, hw)

static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw,
					     unsigned long parent_rate)
{
	struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
	unsigned int mult;

	mult = FIELD_GET(CPG_PLLxCR0_NI, readl(pll_clk->pllcr0_reg)) + 1;

	return parent_rate * mult * 2;
}

static int cpg_pll_clk_determine_rate(struct clk_hw *hw,
				      struct clk_rate_request *req)
{
	unsigned int min_mult, max_mult, mult;
	unsigned long prate;

	prate = req->best_parent_rate * 2;
	min_mult = max(div64_ul(req->min_rate, prate), 1ULL);
	max_mult = min(div64_ul(req->max_rate, prate), 256ULL);
	if (max_mult < min_mult)
		return -EINVAL;

	mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate);
	mult = clamp(mult, min_mult, max_mult);

	req->rate = prate * mult;
	return 0;
}

static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
{
	struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
	unsigned int mult;
	u32 val;

	mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * 2);
	mult = clamp(mult, 1U, 256U);

	if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK)
		return -EBUSY;

	cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI,
		       FIELD_PREP(CPG_PLLxCR0_NI, mult - 1));

	/*
	 * Set KICK bit in PLLxCR0 to update hardware setting and wait for
	 * clock change completion.
	 */
	cpg_reg_modify(pll_clk->pllcr0_reg, 0, CPG_PLLxCR0_KICK);

	/*
	 * Note: There is no HW information about the worst case latency.
	 *
	 * Using experimental measurements, it seems that no more than
	 * ~45 µs are needed, independently of the CPU rate.
	 * Since this value might be dependent on external xtal rate, pll
	 * rate or even the other emulation clocks rate, use 1000 as a
	 * "super" safe value.
	 */
	return readl_poll_timeout(pll_clk->pllecr_reg, val,
				  val & pll_clk->pllecr_pllst_mask, 0, 1000);
}

static const struct clk_ops cpg_pll_clk_ops = {
	.recalc_rate = cpg_pll_clk_recalc_rate,
	.determine_rate = cpg_pll_clk_determine_rate,
	.set_rate = cpg_pll_clk_set_rate,
};

static struct clk * __init cpg_pll_clk_register(const char *name,
						const char *parent_name,
						void __iomem *base,
						unsigned int cr0_offset,
						unsigned int cr1_offset,
						unsigned int index)

{
	struct cpg_pll_clk *pll_clk;
	struct clk_init_data init = {};
	struct clk *clk;

	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
	if (!pll_clk)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &cpg_pll_clk_ops;
	init.parent_names = &parent_name;
	init.num_parents = 1;

	pll_clk->hw.init = &init;
	pll_clk->pllcr0_reg = base + cr0_offset;
	pll_clk->pllecr_reg = base + CPG_PLLECR;
	pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index);

	/* Disable Fractional Multiplication and Frequency Dithering */
	writel(0, base + cr1_offset);
	cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_SSMODE, 0);

	clk = clk_register(NULL, &pll_clk->hw);
	if (IS_ERR(clk))
		kfree(pll_clk);

	return clk;
}
/*
 * Z0 Clock & Z1 Clock
 */
@@ -205,6 +352,15 @@ struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev,
		div = cpg_pll_config->pll1_div;
		break;

	case CLK_TYPE_GEN4_PLL2_VAR:
		/*
		 * PLL2 is implemented as a custom clock, to change the
		 * multiplier when cpufreq changes between normal and boost
		 * modes.
		 */
		return cpg_pll_clk_register(core->name, __clk_get_name(parent),
					    base, CPG_PLL2CR0, CPG_PLL2CR1, 2);

	case CLK_TYPE_GEN4_PLL2:
		mult = cpg_pll_config->pll2_mult;
		div = cpg_pll_config->pll2_div;
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ enum rcar_gen4_clk_types {
	CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM,
	CLK_TYPE_GEN4_PLL1,
	CLK_TYPE_GEN4_PLL2,
	CLK_TYPE_GEN4_PLL2_VAR,
	CLK_TYPE_GEN4_PLL2X_3X,	/* r8a779a0 only */
	CLK_TYPE_GEN4_PLL3,
	CLK_TYPE_GEN4_PLL4,
Loading