2121#define WDTSR 0x04 /* WDT Status Register RW, 16 */
2222#define WDTRCR 0x06 /* WDT Reset Control Register RW, 8 */
2323
24+ /* This register is only available on RZ/T2H and RZ/N2H SoCs */
25+ #define WDTDCR 0x00 /* WDT Debug Control Register RW, 32 */
26+
2427#define WDTCR_TOPS_1024 0x00
28+ #define WDTCR_TOPS_4096 0x01
2529#define WDTCR_TOPS_16384 0x03
2630
2731#define WDTCR_CKS_CLK_1 0x00
32+ #define WDTCR_CKS_CLK_4 0x10
2833#define WDTCR_CKS_CLK_256 0x50
34+ #define WDTCR_CKS_CLK_8192 0x80
2935
3036#define WDTCR_RPES_0 0x300
3137#define WDTCR_RPES_75 0x000
3541
3642#define WDTRCR_RSTIRQS BIT(7)
3743
44+ #define WDTDCR_WDTSTOPCTRL BIT(0)
45+
3846#define WDT_DEFAULT_TIMEOUT 60U
3947
4048static bool nowayout = WATCHDOG_NOWAYOUT ;
@@ -54,10 +62,12 @@ struct rzv2h_of_data {
5462 u8 tops ;
5563 u16 timeout_cycles ;
5664 enum rzv2h_wdt_count_source count_source ;
65+ bool wdtdcr ;
5766};
5867
5968struct rzv2h_wdt_priv {
6069 void __iomem * base ;
70+ void __iomem * wdtdcr ;
6171 struct clk * pclk ;
6272 struct clk * oscclk ;
6373 struct reset_control * rstc ;
@@ -79,6 +89,20 @@ static int rzv2h_wdt_ping(struct watchdog_device *wdev)
7989 return 0 ;
8090}
8191
92+ static void rzt2h_wdt_wdtdcr_count_stop (struct rzv2h_wdt_priv * priv )
93+ {
94+ u32 reg = readl (priv -> wdtdcr + WDTDCR );
95+
96+ writel (reg | WDTDCR_WDTSTOPCTRL , priv -> wdtdcr + WDTDCR );
97+ }
98+
99+ static void rzt2h_wdt_wdtdcr_count_start (struct rzv2h_wdt_priv * priv )
100+ {
101+ u32 reg = readl (priv -> wdtdcr + WDTDCR );
102+
103+ writel (reg & ~WDTDCR_WDTSTOPCTRL , priv -> wdtdcr + WDTDCR );
104+ }
105+
82106static void rzv2h_wdt_setup (struct watchdog_device * wdev , u16 wdtcr )
83107{
84108 struct rzv2h_wdt_priv * priv = watchdog_get_drvdata (wdev );
@@ -114,14 +138,21 @@ static int rzv2h_wdt_start(struct watchdog_device *wdev)
114138
115139 /*
116140 * WDTCR
117- * - CKS[7:4] - Clock Division Ratio Select - 0101b: oscclk/256
141+ * - CKS[7:4] - Clock Division Ratio Select
142+ * - 0101b: oscclk/256 for RZ/V2H(P)
143+ * - 1000b: pclkl/8192 for RZ/T2H
118144 * - RPSS[13:12] - Window Start Position Select - 11b: 100%
119145 * - RPES[9:8] - Window End Position Select - 11b: 0%
120- * - TOPS[1:0] - Timeout Period Select - 11b: 16384 cycles (3FFFh)
146+ * - TOPS[1:0] - Timeout Period Select
147+ * - 11b: 16384 cycles (3FFFh) for RZ/V2H(P)
148+ * - 01b: 4096 cycles (0FFFh) for RZ/T2H
121149 */
122150 rzv2h_wdt_setup (wdev , of_data -> cks_max | WDTCR_RPSS_100 |
123151 WDTCR_RPES_0 | of_data -> tops );
124152
153+ if (priv -> of_data -> wdtdcr )
154+ rzt2h_wdt_wdtdcr_count_start (priv );
155+
125156 /*
126157 * Down counting starts after writing the sequence 00h -> FFh to the
127158 * WDTRR register. Hence, call the ping operation after loading the counter.
@@ -140,6 +171,9 @@ static int rzv2h_wdt_stop(struct watchdog_device *wdev)
140171 if (ret )
141172 return ret ;
142173
174+ if (priv -> of_data -> wdtdcr )
175+ rzt2h_wdt_wdtdcr_count_stop (priv );
176+
143177 ret = pm_runtime_put (wdev -> parent );
144178 if (ret < 0 )
145179 return ret ;
@@ -192,14 +226,19 @@ static int rzv2h_wdt_restart(struct watchdog_device *wdev,
192226
193227 /*
194228 * WDTCR
195- * - CKS[7:4] - Clock Division Ratio Select - 0000b: oscclk/1
229+ * - CKS[7:4] - Clock Division Ratio Select
230+ * - 0000b: oscclk/1 for RZ/V2H(P)
231+ * - 0100b: pclkl/4 for RZ/T2H
196232 * - RPSS[13:12] - Window Start Position Select - 00b: 25%
197233 * - RPES[9:8] - Window End Position Select - 00b: 75%
198234 * - TOPS[1:0] - Timeout Period Select - 00b: 1024 cycles (03FFh)
199235 */
200236 rzv2h_wdt_setup (wdev , priv -> of_data -> cks_min | WDTCR_RPSS_25 |
201237 WDTCR_RPES_75 | WDTCR_TOPS_1024 );
202238
239+ if (priv -> of_data -> wdtdcr )
240+ rzt2h_wdt_wdtdcr_count_start (priv );
241+
203242 rzv2h_wdt_ping (wdev );
204243
205244 /* wait for underflow to trigger... */
@@ -216,6 +255,28 @@ static const struct watchdog_ops rzv2h_wdt_ops = {
216255 .restart = rzv2h_wdt_restart ,
217256};
218257
258+ static int rzt2h_wdt_wdtdcr_init (struct platform_device * pdev ,
259+ struct rzv2h_wdt_priv * priv )
260+ {
261+ int ret ;
262+
263+ priv -> wdtdcr = devm_platform_ioremap_resource (pdev , 1 );
264+ if (IS_ERR (priv -> wdtdcr ))
265+ return PTR_ERR (priv -> wdtdcr );
266+
267+ ret = pm_runtime_resume_and_get (& pdev -> dev );
268+ if (ret )
269+ return ret ;
270+
271+ rzt2h_wdt_wdtdcr_count_stop (priv );
272+
273+ ret = pm_runtime_put (& pdev -> dev );
274+ if (ret < 0 )
275+ return ret ;
276+
277+ return 0 ;
278+ }
279+
219280static int rzv2h_wdt_probe (struct platform_device * pdev )
220281{
221282 struct device * dev = & pdev -> dev ;
@@ -265,6 +326,12 @@ static int rzv2h_wdt_probe(struct platform_device *pdev)
265326 if (ret )
266327 return ret ;
267328
329+ if (priv -> of_data -> wdtdcr ) {
330+ ret = rzt2h_wdt_wdtdcr_init (pdev , priv );
331+ if (ret )
332+ return dev_err_probe (dev , ret , "WDTDCR init failed\n" );
333+ }
334+
268335 priv -> wdev .min_timeout = 1 ;
269336 priv -> wdev .timeout = WDT_DEFAULT_TIMEOUT ;
270337 priv -> wdev .info = & rzv2h_wdt_ident ;
@@ -281,6 +348,16 @@ static int rzv2h_wdt_probe(struct platform_device *pdev)
281348 return devm_watchdog_register_device (dev , & priv -> wdev );
282349}
283350
351+ static const struct rzv2h_of_data rzt2h_wdt_of_data = {
352+ .cks_min = WDTCR_CKS_CLK_4 ,
353+ .cks_max = WDTCR_CKS_CLK_8192 ,
354+ .cks_div = 8192 ,
355+ .tops = WDTCR_TOPS_4096 ,
356+ .timeout_cycles = 4096 ,
357+ .count_source = COUNT_SOURCE_PCLK ,
358+ .wdtdcr = true,
359+ };
360+
284361static const struct rzv2h_of_data rzv2h_wdt_of_data = {
285362 .cks_min = WDTCR_CKS_CLK_1 ,
286363 .cks_max = WDTCR_CKS_CLK_256 ,
@@ -292,6 +369,7 @@ static const struct rzv2h_of_data rzv2h_wdt_of_data = {
292369
293370static const struct of_device_id rzv2h_wdt_ids [] = {
294371 { .compatible = "renesas,r9a09g057-wdt" , .data = & rzv2h_wdt_of_data },
372+ { .compatible = "renesas,r9a09g077-wdt" , .data = & rzt2h_wdt_of_data },
295373 { /* sentinel */ }
296374};
297375MODULE_DEVICE_TABLE (of , rzv2h_wdt_ids );
0 commit comments