Skip to content

Commit 0c15963

Browse files
committed
Merge tag 'renesas-clk-for-v6.13-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 RTC power domain and Battery Backup Function (VBATTB) clock support for the Renesas RZ/G3S SoC - Add the devm_clk_hw_register_gate_parent_hw() helper * tag 'renesas-clk-for-v6.13-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers: clk: renesas: vbattb: Add VBATTB clock driver clk: Add devm_clk_hw_register_gate_parent_hw() clk: renesas: rzg2l: Fix FOUTPOSTDIV clk dt-bindings: clock: renesas,r9a08g045-vbattb: Document VBATTB clk: renesas: r9a08g045: Add power domain for RTC clk: renesas: r9a08g045: Mark the watchdog and always-on PM domains as IRQ safe clk: renesas: rzg2l-cpg: Use GENPD_FLAG_* flags instead of local ones clk: renesas: rzg2l-cpg: Move PM domain power on in rzg2l_cpg_pd_setup() dt-bindings: clock: r9a08g045-cpg: Add power domain ID for RTC
2 parents 31ba299 + 3b42450 commit 0c15963

File tree

10 files changed

+380
-63
lines changed

10 files changed

+380
-63
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/clock/renesas,r9a08g045-vbattb.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Renesas Battery Backup Function (VBATTB)
8+
9+
description:
10+
Renesas VBATTB is an always on powered module (backed by battery) which
11+
controls the RTC clock (VBATTCLK), tamper detection logic and a small
12+
general usage memory (128B).
13+
14+
maintainers:
15+
- Claudiu Beznea <[email protected]>
16+
17+
properties:
18+
compatible:
19+
const: renesas,r9a08g045-vbattb
20+
21+
reg:
22+
maxItems: 1
23+
24+
interrupts:
25+
items:
26+
- description: tamper detector interrupt
27+
28+
clocks:
29+
items:
30+
- description: VBATTB module clock
31+
- description: RTC input clock (crystal or external clock device)
32+
33+
clock-names:
34+
items:
35+
- const: bclk
36+
- const: rtx
37+
38+
'#clock-cells':
39+
const: 1
40+
41+
power-domains:
42+
maxItems: 1
43+
44+
resets:
45+
items:
46+
- description: VBATTB module reset
47+
48+
quartz-load-femtofarads:
49+
description: load capacitance of the on board crystal
50+
enum: [ 4000, 7000, 9000, 12500 ]
51+
default: 4000
52+
53+
required:
54+
- compatible
55+
- reg
56+
- interrupts
57+
- clocks
58+
- clock-names
59+
- '#clock-cells'
60+
- power-domains
61+
- resets
62+
63+
additionalProperties: false
64+
65+
examples:
66+
- |
67+
#include <dt-bindings/clock/r9a08g045-cpg.h>
68+
#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
69+
#include <dt-bindings/interrupt-controller/arm-gic.h>
70+
#include <dt-bindings/interrupt-controller/irq.h>
71+
72+
clock-controller@1005c000 {
73+
compatible = "renesas,r9a08g045-vbattb";
74+
reg = <0x1005c000 0x1000>;
75+
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
76+
clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattb_xtal>;
77+
clock-names = "bclk", "rtx";
78+
assigned-clocks = <&vbattb VBATTB_MUX>;
79+
assigned-clock-parents = <&vbattb VBATTB_XC>;
80+
#clock-cells = <1>;
81+
power-domains = <&cpg>;
82+
resets = <&cpg R9A08G045_VBAT_BRESETN>;
83+
quartz-load-femtofarads = <12500>;
84+
};

drivers/clk/renesas/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ config CLK_RZV2H
237237
bool "RZ/V2H(P) family clock support" if COMPILE_TEST
238238
select RESET_CONTROLLER
239239

240+
config CLK_RENESAS_VBATTB
241+
tristate "Renesas VBATTB clock controller"
242+
depends on ARCH_RZG2L || COMPILE_TEST
243+
select RESET_CONTROLLER
244+
240245
# Generic
241246
config CLK_RENESAS_CPG_MSSR
242247
bool "CPG/MSSR clock support" if COMPILE_TEST

drivers/clk/renesas/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ obj-$(CONFIG_CLK_RZV2H) += rzv2h-cpg.o
5353
obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o
5454
obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o
5555
obj-$(CONFIG_CLK_RENESAS_DIV6) += clk-div6.o
56+
obj-$(CONFIG_CLK_RENESAS_VBATTB) += clk-vbattb.o

drivers/clk/renesas/clk-vbattb.c

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* VBATTB clock driver
4+
*
5+
* Copyright (C) 2024 Renesas Electronics Corp.
6+
*/
7+
8+
#include <linux/cleanup.h>
9+
#include <linux/clk-provider.h>
10+
#include <linux/device.h>
11+
#include <linux/io.h>
12+
#include <linux/mod_devicetable.h>
13+
#include <linux/of.h>
14+
#include <linux/platform_device.h>
15+
#include <linux/pm_runtime.h>
16+
#include <linux/reset.h>
17+
18+
#include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
19+
20+
#define VBATTB_BKSCCR 0x1c
21+
#define VBATTB_BKSCCR_SOSEL 6
22+
#define VBATTB_SOSCCR2 0x24
23+
#define VBATTB_SOSCCR2_SOSTP2 0
24+
#define VBATTB_XOSCCR 0x30
25+
#define VBATTB_XOSCCR_OUTEN 16
26+
#define VBATTB_XOSCCR_XSEL GENMASK(1, 0)
27+
#define VBATTB_XOSCCR_XSEL_4_PF 0x0
28+
#define VBATTB_XOSCCR_XSEL_7_PF 0x1
29+
#define VBATTB_XOSCCR_XSEL_9_PF 0x2
30+
#define VBATTB_XOSCCR_XSEL_12_5_PF 0x3
31+
32+
/**
33+
* struct vbattb_clk - VBATTB clock data structure
34+
* @base: base address
35+
* @lock: lock
36+
*/
37+
struct vbattb_clk {
38+
void __iomem *base;
39+
spinlock_t lock;
40+
};
41+
42+
static int vbattb_clk_validate_load_capacitance(u32 *reg_lc, u32 of_lc)
43+
{
44+
switch (of_lc) {
45+
case 4000:
46+
*reg_lc = VBATTB_XOSCCR_XSEL_4_PF;
47+
break;
48+
case 7000:
49+
*reg_lc = VBATTB_XOSCCR_XSEL_7_PF;
50+
break;
51+
case 9000:
52+
*reg_lc = VBATTB_XOSCCR_XSEL_9_PF;
53+
break;
54+
case 12500:
55+
*reg_lc = VBATTB_XOSCCR_XSEL_12_5_PF;
56+
break;
57+
default:
58+
return -EINVAL;
59+
}
60+
61+
return 0;
62+
}
63+
64+
static void vbattb_clk_action(void *data)
65+
{
66+
struct device *dev = data;
67+
struct reset_control *rstc = dev_get_drvdata(dev);
68+
int ret;
69+
70+
ret = reset_control_assert(rstc);
71+
if (ret)
72+
dev_err(dev, "Failed to de-assert reset!");
73+
74+
ret = pm_runtime_put_sync(dev);
75+
if (ret < 0)
76+
dev_err(dev, "Failed to runtime suspend!");
77+
78+
of_clk_del_provider(dev->of_node);
79+
}
80+
81+
static int vbattb_clk_probe(struct platform_device *pdev)
82+
{
83+
struct device_node *np = pdev->dev.of_node;
84+
struct clk_parent_data parent_data = {};
85+
struct clk_hw_onecell_data *clk_data;
86+
const struct clk_hw *parent_hws[2];
87+
struct device *dev = &pdev->dev;
88+
struct reset_control *rstc;
89+
struct vbattb_clk *vbclk;
90+
u32 of_lc, reg_lc;
91+
struct clk_hw *hw;
92+
/* 4 clocks are exported: VBATTB_XC, VBATTB_XBYP, VBATTB_MUX, VBATTB_VBATTCLK. */
93+
u8 num_clks = 4;
94+
int ret;
95+
96+
/* Default to 4pF as this is not needed if external clock device is connected. */
97+
of_lc = 4000;
98+
of_property_read_u32(np, "quartz-load-femtofarads", &of_lc);
99+
100+
ret = vbattb_clk_validate_load_capacitance(&reg_lc, of_lc);
101+
if (ret)
102+
return ret;
103+
104+
vbclk = devm_kzalloc(dev, sizeof(*vbclk), GFP_KERNEL);
105+
if (!vbclk)
106+
return -ENOMEM;
107+
108+
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, num_clks), GFP_KERNEL);
109+
if (!clk_data)
110+
return -ENOMEM;
111+
clk_data->num = num_clks;
112+
113+
vbclk->base = devm_platform_ioremap_resource(pdev, 0);
114+
if (IS_ERR(vbclk->base))
115+
return PTR_ERR(vbclk->base);
116+
117+
ret = devm_pm_runtime_enable(dev);
118+
if (ret)
119+
return ret;
120+
121+
rstc = devm_reset_control_get_shared(dev, NULL);
122+
if (IS_ERR(rstc))
123+
return PTR_ERR(rstc);
124+
125+
ret = pm_runtime_resume_and_get(dev);
126+
if (ret)
127+
return ret;
128+
129+
ret = reset_control_deassert(rstc);
130+
if (ret) {
131+
pm_runtime_put_sync(dev);
132+
return ret;
133+
}
134+
135+
dev_set_drvdata(dev, rstc);
136+
ret = devm_add_action_or_reset(dev, vbattb_clk_action, dev);
137+
if (ret)
138+
return ret;
139+
140+
spin_lock_init(&vbclk->lock);
141+
142+
parent_data.fw_name = "rtx";
143+
hw = devm_clk_hw_register_gate_parent_data(dev, "xc", &parent_data, 0,
144+
vbclk->base + VBATTB_SOSCCR2,
145+
VBATTB_SOSCCR2_SOSTP2,
146+
CLK_GATE_SET_TO_DISABLE, &vbclk->lock);
147+
if (IS_ERR(hw))
148+
return PTR_ERR(hw);
149+
clk_data->hws[VBATTB_XC] = hw;
150+
151+
hw = devm_clk_hw_register_fixed_factor_fwname(dev, np, "xbyp", "rtx", 0, 1, 1);
152+
if (IS_ERR(hw))
153+
return PTR_ERR(hw);
154+
clk_data->hws[VBATTB_XBYP] = hw;
155+
156+
parent_hws[0] = clk_data->hws[VBATTB_XC];
157+
parent_hws[1] = clk_data->hws[VBATTB_XBYP];
158+
hw = devm_clk_hw_register_mux_parent_hws(dev, "mux", parent_hws, 2, 0,
159+
vbclk->base + VBATTB_BKSCCR,
160+
VBATTB_BKSCCR_SOSEL,
161+
1, 0, &vbclk->lock);
162+
if (IS_ERR(hw))
163+
return PTR_ERR(hw);
164+
clk_data->hws[VBATTB_MUX] = hw;
165+
166+
/* Set load capacitance before registering the VBATTCLK clock. */
167+
scoped_guard(spinlock, &vbclk->lock) {
168+
u32 val = readl_relaxed(vbclk->base + VBATTB_XOSCCR);
169+
170+
val &= ~VBATTB_XOSCCR_XSEL;
171+
val |= reg_lc;
172+
writel_relaxed(val, vbclk->base + VBATTB_XOSCCR);
173+
}
174+
175+
/* This feeds the RTC counter clock and it needs to stay on. */
176+
hw = devm_clk_hw_register_gate_parent_hw(dev, "vbattclk", hw, CLK_IS_CRITICAL,
177+
vbclk->base + VBATTB_XOSCCR,
178+
VBATTB_XOSCCR_OUTEN, 0,
179+
&vbclk->lock);
180+
181+
if (IS_ERR(hw))
182+
return PTR_ERR(hw);
183+
clk_data->hws[VBATTB_VBATTCLK] = hw;
184+
185+
return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
186+
}
187+
188+
static const struct of_device_id vbattb_clk_match[] = {
189+
{ .compatible = "renesas,r9a08g045-vbattb" },
190+
{ /* sentinel */ }
191+
};
192+
MODULE_DEVICE_TABLE(of, vbattb_clk_match);
193+
194+
static struct platform_driver vbattb_clk_driver = {
195+
.driver = {
196+
.name = "renesas-vbattb-clk",
197+
.of_match_table = vbattb_clk_match,
198+
},
199+
.probe = vbattb_clk_probe,
200+
};
201+
module_platform_driver(vbattb_clk_driver);
202+
203+
MODULE_DESCRIPTION("Renesas VBATTB Clock Driver");
204+
MODULE_AUTHOR("Claudiu Beznea <[email protected]>");
205+
MODULE_LICENSE("GPL");

drivers/clk/renesas/r9a08g045-cpg.c

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/device.h>
1010
#include <linux/init.h>
1111
#include <linux/kernel.h>
12+
#include <linux/pm_domain.h>
1213

1314
#include <dt-bindings/clock/r9a08g045-cpg.h>
1415

@@ -266,61 +267,50 @@ static const struct rzg2l_cpg_pm_domain_init_data r9a08g045_pm_domains[] = {
266267
/* Keep always-on domain on the first position for proper domains registration. */
267268
DEF_PD("always-on", R9A08G045_PD_ALWAYS_ON,
268269
DEF_REG_CONF(0, 0),
269-
RZG2L_PD_F_ALWAYS_ON),
270+
GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
270271
DEF_PD("gic", R9A08G045_PD_GIC,
271272
DEF_REG_CONF(CPG_BUS_ACPU_MSTOP, BIT(3)),
272-
RZG2L_PD_F_ALWAYS_ON),
273+
GENPD_FLAG_ALWAYS_ON),
273274
DEF_PD("ia55", R9A08G045_PD_IA55,
274275
DEF_REG_CONF(CPG_BUS_PERI_CPU_MSTOP, BIT(13)),
275-
RZG2L_PD_F_ALWAYS_ON),
276+
GENPD_FLAG_ALWAYS_ON),
276277
DEF_PD("dmac", R9A08G045_PD_DMAC,
277278
DEF_REG_CONF(CPG_BUS_REG1_MSTOP, GENMASK(3, 0)),
278-
RZG2L_PD_F_ALWAYS_ON),
279+
GENPD_FLAG_ALWAYS_ON),
279280
DEF_PD("wdt0", R9A08G045_PD_WDT0,
280281
DEF_REG_CONF(CPG_BUS_REG0_MSTOP, BIT(0)),
281-
RZG2L_PD_F_NONE),
282+
GENPD_FLAG_IRQ_SAFE),
282283
DEF_PD("sdhi0", R9A08G045_PD_SDHI0,
283-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(0)),
284-
RZG2L_PD_F_NONE),
284+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(0)), 0),
285285
DEF_PD("sdhi1", R9A08G045_PD_SDHI1,
286-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(1)),
287-
RZG2L_PD_F_NONE),
286+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(1)), 0),
288287
DEF_PD("sdhi2", R9A08G045_PD_SDHI2,
289-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)),
290-
RZG2L_PD_F_NONE),
288+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)), 0),
291289
DEF_PD("usb0", R9A08G045_PD_USB0,
292-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, GENMASK(6, 5)),
293-
RZG2L_PD_F_NONE),
290+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, GENMASK(6, 5)), 0),
294291
DEF_PD("usb1", R9A08G045_PD_USB1,
295-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(7)),
296-
RZG2L_PD_F_NONE),
292+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(7)), 0),
297293
DEF_PD("usb-phy", R9A08G045_PD_USB_PHY,
298-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(4)),
299-
RZG2L_PD_F_NONE),
294+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(4)), 0),
300295
DEF_PD("eth0", R9A08G045_PD_ETHER0,
301-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)),
302-
RZG2L_PD_F_NONE),
296+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)), 0),
303297
DEF_PD("eth1", R9A08G045_PD_ETHER1,
304-
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(3)),
305-
RZG2L_PD_F_NONE),
298+
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(3)), 0),
306299
DEF_PD("i2c0", R9A08G045_PD_I2C0,
307-
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(10)),
308-
RZG2L_PD_F_NONE),
300+
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(10)), 0),
309301
DEF_PD("i2c1", R9A08G045_PD_I2C1,
310-
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(11)),
311-
RZG2L_PD_F_NONE),
302+
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(11)), 0),
312303
DEF_PD("i2c2", R9A08G045_PD_I2C2,
313-
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(12)),
314-
RZG2L_PD_F_NONE),
304+
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(12)), 0),
315305
DEF_PD("i2c3", R9A08G045_PD_I2C3,
316-
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(13)),
317-
RZG2L_PD_F_NONE),
306+
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(13)), 0),
318307
DEF_PD("scif0", R9A08G045_PD_SCIF0,
319-
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(1)),
320-
RZG2L_PD_F_NONE),
308+
DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(1)), 0),
321309
DEF_PD("vbat", R9A08G045_PD_VBAT,
322310
DEF_REG_CONF(CPG_BUS_MCPU3_MSTOP, BIT(8)),
323-
RZG2L_PD_F_ALWAYS_ON),
311+
GENPD_FLAG_ALWAYS_ON),
312+
DEF_PD("rtc", R9A08G045_PD_RTC,
313+
DEF_REG_CONF(CPG_BUS_MCPU3_MSTOP, BIT(7)), 0),
324314
};
325315

326316
const struct rzg2l_cpg_info r9a08g045_cpg_info = {

0 commit comments

Comments
 (0)