Skip to content

Commit cd4eadf

Browse files
Sam ProtsenkoWim Van Sebroeck
authored andcommitted
watchdog: s3c2410: Add Exynos850 support
Exynos850 is a bit different from SoCs already supported in WDT driver: - AUTOMATIC_WDT_RESET_DISABLE register is removed, so its value is always 0; .disable_auto_reset callback is not set for that reason - MASK_WDT_RESET_REQUEST register is replaced with CLUSTERx_NONCPU_IN_EN register; instead of masking (disabling) WDT reset interrupt it's now enabled with the same value; .mask_reset callback is reused for that functionality though - To make WDT functional, WDT counter needs to be enabled in CLUSTERx_NONCPU_OUT register; it's done using .enable_counter callback Also Exynos850 has two CPU clusters, each has its own dedicated WDT instance. Different PMU registers and bits are used for each cluster. So driver data is now modified in probe, adding needed info depending on cluster index passed from device tree. Signed-off-by: Sam Protsenko <[email protected]> Reviewed-by: Krzysztof Kozlowski <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Wim Van Sebroeck <[email protected]>
1 parent 968011a commit cd4eadf

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

drivers/watchdog/s3c2410_wdt.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656
#define EXYNOS5_RST_STAT_REG_OFFSET 0x0404
5757
#define EXYNOS5_WDT_DISABLE_REG_OFFSET 0x0408
5858
#define EXYNOS5_WDT_MASK_RESET_REG_OFFSET 0x040c
59+
#define EXYNOS850_CLUSTER0_NONCPU_OUT 0x1220
60+
#define EXYNOS850_CLUSTER0_NONCPU_INT_EN 0x1244
61+
#define EXYNOS850_CLUSTER1_NONCPU_OUT 0x1620
62+
#define EXYNOS850_CLUSTER1_NONCPU_INT_EN 0x1644
63+
64+
#define EXYNOS850_CLUSTER0_WDTRESET_BIT 24
65+
#define EXYNOS850_CLUSTER1_WDTRESET_BIT 23
5966

6067
/**
6168
* DOC: Quirk flags for different Samsung watchdog IP-cores
@@ -205,6 +212,30 @@ static const struct s3c2410_wdt_variant drv_data_exynos7 = {
205212
QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_AUTO_DISABLE,
206213
};
207214

215+
static const struct s3c2410_wdt_variant drv_data_exynos850_cl0 = {
216+
.mask_reset_reg = EXYNOS850_CLUSTER0_NONCPU_INT_EN,
217+
.mask_bit = 2,
218+
.mask_reset_inv = true,
219+
.rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
220+
.rst_stat_bit = EXYNOS850_CLUSTER0_WDTRESET_BIT,
221+
.cnt_en_reg = EXYNOS850_CLUSTER0_NONCPU_OUT,
222+
.cnt_en_bit = 7,
223+
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | \
224+
QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
225+
};
226+
227+
static const struct s3c2410_wdt_variant drv_data_exynos850_cl1 = {
228+
.mask_reset_reg = EXYNOS850_CLUSTER1_NONCPU_INT_EN,
229+
.mask_bit = 2,
230+
.mask_reset_inv = true,
231+
.rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
232+
.rst_stat_bit = EXYNOS850_CLUSTER1_WDTRESET_BIT,
233+
.cnt_en_reg = EXYNOS850_CLUSTER1_NONCPU_OUT,
234+
.cnt_en_bit = 7,
235+
.quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | \
236+
QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN,
237+
};
238+
208239
static const struct of_device_id s3c2410_wdt_match[] = {
209240
{ .compatible = "samsung,s3c2410-wdt",
210241
.data = &drv_data_s3c2410 },
@@ -216,6 +247,8 @@ static const struct of_device_id s3c2410_wdt_match[] = {
216247
.data = &drv_data_exynos5420 },
217248
{ .compatible = "samsung,exynos7-wdt",
218249
.data = &drv_data_exynos7 },
250+
{ .compatible = "samsung,exynos850-wdt",
251+
.data = &drv_data_exynos850_cl0 },
219252
{},
220253
};
221254
MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
@@ -587,14 +620,40 @@ static inline const struct s3c2410_wdt_variant *
587620
s3c2410_get_wdt_drv_data(struct platform_device *pdev)
588621
{
589622
const struct s3c2410_wdt_variant *variant;
623+
struct device *dev = &pdev->dev;
590624

591-
variant = of_device_get_match_data(&pdev->dev);
625+
variant = of_device_get_match_data(dev);
592626
if (!variant) {
593627
/* Device matched by platform_device_id */
594628
variant = (struct s3c2410_wdt_variant *)
595629
platform_get_device_id(pdev)->driver_data;
596630
}
597631

632+
#ifdef CONFIG_OF
633+
/* Choose Exynos850 driver data w.r.t. cluster index */
634+
if (variant == &drv_data_exynos850_cl0) {
635+
u32 index;
636+
int err;
637+
638+
err = of_property_read_u32(dev->of_node,
639+
"samsung,cluster-index", &index);
640+
if (err) {
641+
dev_err(dev, "failed to get cluster index\n");
642+
return NULL;
643+
}
644+
645+
switch (index) {
646+
case 0:
647+
return &drv_data_exynos850_cl0;
648+
case 1:
649+
return &drv_data_exynos850_cl1;
650+
default:
651+
dev_err(dev, "wrong cluster index: %u\n", index);
652+
return NULL;
653+
}
654+
}
655+
#endif
656+
598657
return variant;
599658
}
600659

@@ -615,6 +674,9 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
615674
wdt->wdt_device = s3c2410_wdd;
616675

617676
wdt->drv_data = s3c2410_get_wdt_drv_data(pdev);
677+
if (!wdt->drv_data)
678+
return -EINVAL;
679+
618680
if (wdt->drv_data->quirks & QUIRKS_HAVE_PMUREG) {
619681
wdt->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
620682
"samsung,syscon-phandle");

0 commit comments

Comments
 (0)