Lines Matching +full:pmureg +full:- +full:phandle
1 // SPDX-License-Identifier: GPL-2.0-or-later
29 #include <linux/soc/samsung/exynos-pmu.h>
80 * DOC: Quirk flags for different Samsung watchdog IP-cores
85 * differences in both watchdog and PMU IP-cores should be accounted for. Quirk
92 * write-only, writing any values to this register clears the interrupt, but
149 * struct s3c2410_wdt_variant - Per-variant config data
151 * @disable_reg: Offset in pmureg for the register that disables the watchdog
153 * @mask_reset_reg: Offset in pmureg for the register that masks the watchdog
158 * @rst_stat_reg: Offset in pmureg for the register that has the reset status.
161 * @cnt_en_reg: Offset in pmureg for the register that enables WDT counter.
190 struct regmap *pmureg; member
307 { .compatible = "google,gs101-wdt",
309 { .compatible = "samsung,s3c2410-wdt",
311 { .compatible = "samsung,s3c6410-wdt",
313 { .compatible = "samsung,exynos5250-wdt",
315 { .compatible = "samsung,exynos5420-wdt",
317 { .compatible = "samsung,exynos7-wdt",
319 { .compatible = "samsung,exynos850-wdt",
321 { .compatible = "samsung,exynosautov9-wdt",
330 .name = "s3c2410-wdt",
341 return clk_get_rate(wdt->src_clk ? wdt->src_clk : wdt->bus_clk); in s3c2410wdt_get_freq()
354 const u32 mask_val = BIT(wdt->drv_data->mask_bit); in s3c2410wdt_disable_wdt_reset()
358 ret = regmap_update_bits(wdt->pmureg, wdt->drv_data->disable_reg, in s3c2410wdt_disable_wdt_reset()
361 dev_err(wdt->dev, "failed to update reg(%d)\n", ret); in s3c2410wdt_disable_wdt_reset()
368 const u32 mask_val = BIT(wdt->drv_data->mask_bit); in s3c2410wdt_mask_wdt_reset()
369 const bool val_inv = wdt->drv_data->mask_reset_inv; in s3c2410wdt_mask_wdt_reset()
373 ret = regmap_update_bits(wdt->pmureg, wdt->drv_data->mask_reset_reg, in s3c2410wdt_mask_wdt_reset()
376 dev_err(wdt->dev, "failed to update reg(%d)\n", ret); in s3c2410wdt_mask_wdt_reset()
383 const u32 mask_val = BIT(wdt->drv_data->cnt_en_bit); in s3c2410wdt_enable_counter()
387 ret = regmap_update_bits(wdt->pmureg, wdt->drv_data->cnt_en_reg, in s3c2410wdt_enable_counter()
390 dev_err(wdt->dev, "failed to update reg(%d)\n", ret); in s3c2410wdt_enable_counter()
399 if (wdt->drv_data->quirks & QUIRK_HAS_PMU_AUTO_DISABLE) { in s3c2410wdt_enable()
405 if (wdt->drv_data->quirks & QUIRK_HAS_PMU_MASK_RESET) { in s3c2410wdt_enable()
411 if (wdt->drv_data->quirks & QUIRK_HAS_PMU_CNT_EN) { in s3c2410wdt_enable()
425 if (!(wdt->drv_data->quirks & QUIRK_HAS_DBGACK_BIT)) in s3c2410wdt_mask_dbgack()
428 wtcon = readl(wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_mask_dbgack()
430 writel(wtcon, wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_mask_dbgack()
438 spin_lock_irqsave(&wdt->lock, flags); in s3c2410wdt_keepalive()
439 writel(wdt->count, wdt->reg_base + S3C2410_WTCNT); in s3c2410wdt_keepalive()
440 spin_unlock_irqrestore(&wdt->lock, flags); in s3c2410wdt_keepalive()
449 wtcon = readl(wdt->reg_base + S3C2410_WTCON); in __s3c2410wdt_stop()
451 writel(wtcon, wdt->reg_base + S3C2410_WTCON); in __s3c2410wdt_stop()
459 spin_lock_irqsave(&wdt->lock, flags); in s3c2410wdt_stop()
461 spin_unlock_irqrestore(&wdt->lock, flags); in s3c2410wdt_stop()
472 spin_lock_irqsave(&wdt->lock, flags); in s3c2410wdt_start()
476 wtcon = readl(wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_start()
487 dev_dbg(wdt->dev, "Starting watchdog: count=0x%08x, wtcon=%08lx\n", in s3c2410wdt_start()
488 wdt->count, wtcon); in s3c2410wdt_start()
490 writel(wdt->count, wdt->reg_base + S3C2410_WTDAT); in s3c2410wdt_start()
491 writel(wdt->count, wdt->reg_base + S3C2410_WTCNT); in s3c2410wdt_start()
492 writel(wtcon, wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_start()
493 spin_unlock_irqrestore(&wdt->lock, flags); in s3c2410wdt_start()
508 return -EINVAL; in s3c2410wdt_set_heartbeat()
513 dev_dbg(wdt->dev, "Heartbeat: count=%d, timeout=%d, freq=%lu\n", in s3c2410wdt_set_heartbeat()
525 dev_err(wdt->dev, "timeout %d too big\n", timeout); in s3c2410wdt_set_heartbeat()
526 return -EINVAL; in s3c2410wdt_set_heartbeat()
530 dev_dbg(wdt->dev, "Heartbeat: timeout=%d, divisor=%d, count=%d (%08x)\n", in s3c2410wdt_set_heartbeat()
534 wdt->count = count; in s3c2410wdt_set_heartbeat()
536 /* update the pre-scaler */ in s3c2410wdt_set_heartbeat()
537 wtcon = readl(wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_set_heartbeat()
539 wtcon |= S3C2410_WTCON_PRESCALE(divisor-1); in s3c2410wdt_set_heartbeat()
541 writel(count, wdt->reg_base + S3C2410_WTDAT); in s3c2410wdt_set_heartbeat()
542 writel(wtcon, wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_set_heartbeat()
544 wdd->timeout = (count * divisor) / freq; in s3c2410wdt_set_heartbeat()
553 void __iomem *wdt_base = wdt->reg_base; in s3c2410wdt_restart()
602 dev_info(wdt->dev, "watchdog timer expired (irq)\n"); in s3c2410wdt_irq()
604 s3c2410wdt_keepalive(&wdt->wdt_device); in s3c2410wdt_irq()
606 if (wdt->drv_data->quirks & QUIRK_HAS_WTCLRINT_REG) in s3c2410wdt_irq()
607 writel(0x1, wdt->reg_base + S3C2410_WTCLRINT); in s3c2410wdt_irq()
617 if (!(wdt->drv_data->quirks & QUIRK_HAS_PMU_RST_STAT)) in s3c2410wdt_get_bootstatus()
620 ret = regmap_read(wdt->pmureg, wdt->drv_data->rst_stat_reg, &rst_stat); in s3c2410wdt_get_bootstatus()
622 dev_warn(wdt->dev, "Couldn't get RST_STAT register\n"); in s3c2410wdt_get_bootstatus()
623 else if (rst_stat & BIT(wdt->drv_data->rst_stat_bit)) in s3c2410wdt_get_bootstatus()
633 struct device *dev = &pdev->dev; in s3c2410_get_wdt_drv_data()
639 platform_get_device_id(pdev)->driver_data; in s3c2410_get_wdt_drv_data()
650 err = of_property_read_u32(dev->of_node, in s3c2410_get_wdt_drv_data()
651 "samsung,cluster-index", &index); in s3c2410_get_wdt_drv_data()
653 return dev_err_probe(dev, -EINVAL, "failed to get cluster index\n"); in s3c2410_get_wdt_drv_data()
667 return dev_err_probe(dev, -EINVAL, "wrong cluster index: %u\n", index); in s3c2410_get_wdt_drv_data()
672 wdt->drv_data = variant; in s3c2410_get_wdt_drv_data()
683 struct device *dev = &pdev->dev; in s3c2410wdt_probe()
691 return -ENOMEM; in s3c2410wdt_probe()
693 wdt->dev = dev; in s3c2410wdt_probe()
694 spin_lock_init(&wdt->lock); in s3c2410wdt_probe()
695 wdt->wdt_device = s3c2410_wdd; in s3c2410wdt_probe()
701 if (wdt->drv_data->quirks & QUIRKS_HAVE_PMUREG) { in s3c2410wdt_probe()
702 wdt->pmureg = exynos_get_pmu_regmap_by_phandle(dev->of_node, in s3c2410wdt_probe()
703 "samsung,syscon-phandle"); in s3c2410wdt_probe()
704 if (IS_ERR(wdt->pmureg)) in s3c2410wdt_probe()
705 return dev_err_probe(dev, PTR_ERR(wdt->pmureg), in s3c2410wdt_probe()
714 wdt->reg_base = devm_platform_ioremap_resource(pdev, 0); in s3c2410wdt_probe()
715 if (IS_ERR(wdt->reg_base)) in s3c2410wdt_probe()
716 return PTR_ERR(wdt->reg_base); in s3c2410wdt_probe()
718 wdt->bus_clk = devm_clk_get_enabled(dev, "watchdog"); in s3c2410wdt_probe()
719 if (IS_ERR(wdt->bus_clk)) in s3c2410wdt_probe()
720 return dev_err_probe(dev, PTR_ERR(wdt->bus_clk), "failed to get bus clock\n"); in s3c2410wdt_probe()
723 * "watchdog_src" clock is optional; if it's not present -- just skip it in s3c2410wdt_probe()
726 wdt->src_clk = devm_clk_get_optional_enabled(dev, "watchdog_src"); in s3c2410wdt_probe()
727 if (IS_ERR(wdt->src_clk)) in s3c2410wdt_probe()
728 return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n"); in s3c2410wdt_probe()
730 wdt->wdt_device.min_timeout = 1; in s3c2410wdt_probe()
731 wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt); in s3c2410wdt_probe()
733 watchdog_set_drvdata(&wdt->wdt_device, wdt); in s3c2410wdt_probe()
738 watchdog_init_timeout(&wdt->wdt_device, tmr_margin, dev); in s3c2410wdt_probe()
739 ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device, in s3c2410wdt_probe()
740 wdt->wdt_device.timeout); in s3c2410wdt_probe()
742 ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device, in s3c2410wdt_probe()
752 pdev->name, pdev); in s3c2410wdt_probe()
756 watchdog_set_nowayout(&wdt->wdt_device, nowayout); in s3c2410wdt_probe()
757 watchdog_set_restart_priority(&wdt->wdt_device, 128); in s3c2410wdt_probe()
759 wdt->wdt_device.bootstatus = s3c2410wdt_get_bootstatus(wdt); in s3c2410wdt_probe()
760 wdt->wdt_device.parent = dev; in s3c2410wdt_probe()
765 * If "tmr_atboot" param is non-zero, start the watchdog right now. Also in s3c2410wdt_probe()
773 s3c2410wdt_start(&wdt->wdt_device); in s3c2410wdt_probe()
774 set_bit(WDOG_HW_RUNNING, &wdt->wdt_device.status); in s3c2410wdt_probe()
776 s3c2410wdt_stop(&wdt->wdt_device); in s3c2410wdt_probe()
779 ret = devm_watchdog_register_device(dev, &wdt->wdt_device); in s3c2410wdt_probe()
795 wtcon = readl(wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_probe()
810 s3c2410wdt_stop(&wdt->wdt_device); in s3c2410wdt_shutdown()
819 wdt->wtcon_save = readl(wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_suspend()
820 wdt->wtdat_save = readl(wdt->reg_base + S3C2410_WTDAT); in s3c2410wdt_suspend()
827 s3c2410wdt_stop(&wdt->wdt_device); in s3c2410wdt_suspend()
838 writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTDAT); in s3c2410wdt_resume()
839 writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTCNT);/* Reset count */ in s3c2410wdt_resume()
840 writel(wdt->wtcon_save, wdt->reg_base + S3C2410_WTCON); in s3c2410wdt_resume()
847 (wdt->wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); in s3c2410wdt_resume()
860 .name = "s3c2410-wdt",