static int orion_wdt_get_regs(struct platform_device *pdev, struct orion_watchdog *dev) { struct device_node *node = pdev->dev.of_node; struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!dev->reg) return -ENOMEM; /* Each supported compatible has some RSTOUT register quirk */ if (of_device_is_compatible(node, "marvell,orion-wdt")) { dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & INTERNAL_REGS_MASK); if (!dev->rstout) return -ENODEV; } else if (of_device_is_compatible(node, "marvell,armada-370-wdt") || of_device_is_compatible(node, "marvell,armada-xp-wdt")) { /* Dedicated RSTOUT register, can be requested. */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dev->rstout = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->rstout)) return PTR_ERR(dev->rstout); } else if (of_device_is_compatible(node, "marvell,armada-375-wdt") || of_device_is_compatible(node, "marvell,armada-380-wdt")) { /* Dedicated RSTOUT register, can be requested. */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dev->rstout = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->rstout)) return PTR_ERR(dev->rstout); res = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!res) return -ENODEV; dev->rstout_mask = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!dev->rstout_mask) return -ENOMEM; } else { return -ENODEV; } return 0; }
static int orion_wdt_probe(struct platform_device *pdev) { struct orion_watchdog *dev; const struct of_device_id *match; unsigned int wdt_max_duration; /* (seconds) */ struct resource *res; int ret, irq; dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog), GFP_KERNEL); if (!dev) return -ENOMEM; match = of_match_device(orion_wdt_of_match_table, &pdev->dev); if (!match) /* Default legacy match */ match = &orion_wdt_of_match_table[0]; dev->wdt.info = &orion_wdt_info; dev->wdt.ops = &orion_wdt_ops; dev->wdt.min_timeout = 1; dev->data = match->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!dev->reg) return -ENOMEM; dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & INTERNAL_REGS_MASK); if (!dev->rstout) return -ENODEV; ret = dev->data->clock_init(pdev, dev); if (ret) { dev_err(&pdev->dev, "cannot initialize clock\n"); return ret; } wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; dev->wdt.timeout = wdt_max_duration; dev->wdt.max_timeout = wdt_max_duration; watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); platform_set_drvdata(pdev, &dev->wdt); watchdog_set_drvdata(&dev->wdt, dev); /* * Let's make sure the watchdog is fully stopped, unless it's * explicitly enabled. This may be the case if the module was * removed and re-insterted, or if the bootloader explicitly * set a running watchdog before booting the kernel. */ if (!orion_wdt_enabled(dev)) orion_wdt_stop(&dev->wdt); /* Request the IRQ only after the watchdog is disabled */ irq = platform_get_irq(pdev, 0); if (irq > 0) { /* * Not all supported platforms specify an interrupt for the * watchdog, so let's make it optional. */ ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0, pdev->name, dev); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); goto disable_clk; } } watchdog_set_nowayout(&dev->wdt, nowayout); ret = watchdog_register_device(&dev->wdt); if (ret) goto disable_clk; pr_info("Initial timeout %d sec%s\n", dev->wdt.timeout, nowayout ? ", nowayout" : ""); return 0; disable_clk: clk_disable_unprepare(dev->clk); clk_put(dev->clk); return ret; }