static int iTCO_wdt_probe()

in iTCO_wdt.c [461:597]


static int iTCO_wdt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct itco_wdt_platform_data *pdata = dev_get_platdata(dev);
	struct iTCO_wdt_private *p;
	unsigned long val32;
	int ret;

	if (!pdata)
		return -ENODEV;

	p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	spin_lock_init(&p->io_lock);

	p->tco_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_TCO);
	if (!p->tco_res)
		return -ENODEV;

	p->iTCO_version = pdata->version;
	p->pci_dev = to_pci_dev(dev->parent);

	p->smi_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_SMI);
	if (p->smi_res) {
		/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
		if (!devm_request_region(dev, p->smi_res->start,
					 resource_size(p->smi_res),
					 pdev->name)) {
			dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n",
			       (u64)SMI_EN(p));
			return -EBUSY;
		}
	} else if (iTCO_vendorsupport ||
		   turn_SMI_watchdog_clear_off >= p->iTCO_version) {
		dev_err(dev, "SMI I/O resource is missing\n");
		return -ENODEV;
	}

	iTCO_wdt_no_reboot_bit_setup(p, pdev, pdata);

	/*
	 * Get the Memory-Mapped GCS or PMC register, we need it for the
	 * NO_REBOOT flag (TCO v2 and v3).
	 */
	if (p->iTCO_version >= 2 && p->iTCO_version < 6 &&
	    !pdata->no_reboot_use_pmc) {
		p->gcs_pmc = devm_platform_ioremap_resource(pdev, ICH_RES_MEM_GCS_PMC);
		if (IS_ERR(p->gcs_pmc))
			return PTR_ERR(p->gcs_pmc);
	}

	/* Check chipset's NO_REBOOT bit */
	if (p->update_no_reboot_bit(p->no_reboot_priv, false) &&
	    iTCO_vendor_check_noreboot_on()) {
		dev_info(dev, "unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
		return -ENODEV;	/* Cannot reset NO_REBOOT bit */
	}

	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
	p->update_no_reboot_bit(p->no_reboot_priv, true);

	if (turn_SMI_watchdog_clear_off >= p->iTCO_version) {
		/*
		 * Bit 13: TCO_EN -> 0
		 * Disables TCO logic generating an SMI#
		 */
		val32 = inl(SMI_EN(p));
		val32 &= 0xffffdfff;	/* Turn off SMI clearing watchdog */
		outl(val32, SMI_EN(p));
	}

	if (!devm_request_region(dev, p->tco_res->start,
				 resource_size(p->tco_res),
				 pdev->name)) {
		dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n",
		       (u64)TCOBASE(p));
		return -EBUSY;
	}

	dev_info(dev, "Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
		pdata->name, pdata->version, (u64)TCOBASE(p));

	/* Clear out the (probably old) status */
	switch (p->iTCO_version) {
	case 6:
	case 5:
	case 4:
		outw(0x0008, TCO1_STS(p)); /* Clear the Time Out Status bit */
		outw(0x0002, TCO2_STS(p)); /* Clear SECOND_TO_STS bit */
		break;
	case 3:
		outl(0x20008, TCO1_STS(p));
		break;
	case 2:
	case 1:
	default:
		outw(0x0008, TCO1_STS(p)); /* Clear the Time Out Status bit */
		outw(0x0002, TCO2_STS(p)); /* Clear SECOND_TO_STS bit */
		outw(0x0004, TCO2_STS(p)); /* Clear BOOT_STS bit */
		break;
	}

	p->wddev.info = &ident,
	p->wddev.ops = &iTCO_wdt_ops,
	p->wddev.bootstatus = 0;
	p->wddev.timeout = WATCHDOG_TIMEOUT;
	watchdog_set_nowayout(&p->wddev, nowayout);
	p->wddev.parent = dev;

	watchdog_set_drvdata(&p->wddev, p);
	platform_set_drvdata(pdev, p);

	iTCO_wdt_set_running(p);

	/* Check that the heartbeat value is within it's range;
	   if not reset to the default */
	if (iTCO_wdt_set_timeout(&p->wddev, heartbeat)) {
		iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT);
		dev_info(dev, "timeout value out of range, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	watchdog_stop_on_reboot(&p->wddev);
	watchdog_stop_on_unregister(&p->wddev);
	ret = devm_watchdog_register_device(dev, &p->wddev);
	if (ret != 0) {
		dev_err(dev, "cannot register watchdog device (err=%d)\n", ret);
		return ret;
	}

	dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n",
		heartbeat, nowayout);

	return 0;
}