mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 13:23:35 -04:00
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
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -66,13 +66,13 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* 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(".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),
|
||||
DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN),
|
||||
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_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),
|
||||
DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN),
|
||||
|
||||
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
|
||||
DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1),
|
||||
@@ -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),
|
||||
|
||||
@@ -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 ?
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -943,9 +943,8 @@ static int cpg_mssr_resume_noirq(struct device *dev)
|
||||
}
|
||||
|
||||
if (!i)
|
||||
dev_warn(dev, "Failed to enable %s%u[0x%x]\n",
|
||||
priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
|
||||
"STB" : "SMSTP", reg, oldval & mask);
|
||||
dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg,
|
||||
oldval & mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user