コード例 #1
0
static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	int new_options, retval = -EINVAL;
	int new_heartbeat;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT |
					WDIOF_KEEPALIVEPING |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		DRV_NAME,
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		if (get_user(new_options, p))
			return -EFAULT;

		if (new_options & WDIOS_DISABLECARD) {
			iTCO_wdt_stop();
			retval = 0;
		}
		if (new_options & WDIOS_ENABLECARD) {
			iTCO_wdt_keepalive();
			iTCO_wdt_start();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		iTCO_wdt_keepalive();
		return 0;

	case WDIOC_SETTIMEOUT:
	{
		if (get_user(new_heartbeat, p))
			return -EFAULT;
		if (iTCO_wdt_set_heartbeat(new_heartbeat))
			return -EINVAL;
		iTCO_wdt_keepalive();
		/* Fall */
	}
	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, p);
	case WDIOC_GETTIMELEFT:
	{
		int time_left;
		if (iTCO_wdt_get_timeleft(&time_left))
			return -EINVAL;
		return put_user(time_left, p);
	}
	default:
		return -ENOTTY;
	}
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations iTCO_wdt_fops = {
	.owner =		THIS_MODULE,
	.llseek =		no_llseek,
	.write =		iTCO_wdt_write,
	.unlocked_ioctl =	iTCO_wdt_ioctl,
	.open =			iTCO_wdt_open,
	.release =		iTCO_wdt_release,
};

static struct miscdevice iTCO_wdt_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&iTCO_wdt_fops,
};

/*
 *	Reboot notifier
 */

static int TCO_reboot_notifier(struct notifier_block *this,
			   unsigned long code,
			   void *another_unused)
{
	if (code == SYS_HALT || code == SYS_POWER_OFF) {
		iTCO_wdt_set_reset_type(TCO_POLICY_HALT);
	}

	iTCO_wdt_last_kick(5);

#ifdef CONFIG_DEBUG_FS
	if (iTCO_wdt_private.panic_reboot_notifier) {
		BUG();
	}
#endif

	return NOTIFY_DONE;
}

static irqreturn_t tco_irq_handler(int irq, void *arg)
{
	unsigned long val32;

	pr_warn("[SHTDWN] %s, WATCHDOG TIMEOUT HANDLER!\n", __func__);

	/* reduce the timeout to the minimum, but sufficient for tracing */
	iTCO_wdt_set_heartbeat(15);
	iTCO_wdt_keepalive();

	trigger_all_cpu_backtrace();
	panic("Kernel Watchdog");

	/* This code should not be reached */

	return IRQ_HANDLED;
}

/*
 *	Init & exit routines
 */

static int iTCO_wdt_init(struct pci_dev *pdev,
		const struct pci_device_id *ent, struct platform_device *dev)
{
	int ret;
	u32 base_address;
	unsigned long val32;

	/*
	 *      Find the ACPI/PM base I/O address which is the base
	 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
	 *      ACPIBASE is bits [15:7] from 0x40-0x43
	 */
	pci_read_config_dword(pdev, 0x40, &base_address);
	base_address &= 0x0000ff80;
	if (base_address == 0x00000000) {
		/* Something's wrong here, ACPIBASE has to be set */
		pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n");
		return -ENODEV;
	}
	iTCO_wdt_private.iTCO_version =
			iTCO_chipset_info[ent->driver_data].iTCO_version;
	iTCO_wdt_private.ACPIBASE = base_address;
	iTCO_wdt_private.pdev = pdev;

	pci_read_config_dword(pdev, 0x44, &pmc_base_address);
	pmc_base_address &= 0xFFFFFE00;

	/*
	 * Disable watchdog on command-line demand
	 */
	if (strstr(saved_command_line, "disable_kernel_watchdog=1")) {
		pr_warn("disable_kernel_watchdog=1 watchdog will not be started\n");
		iTCO_wdt_private.enable = false;
		/* Set the NO_REBOOT bit to prevent later reboots */
		iTCO_wdt_set_NO_REBOOT_bit();
		/* Ensure Wdt is well stopped in case started by IAFW */
		iTCO_wdt_stop();
	} else {
		iTCO_wdt_private.enable = true;
		/* Check chipset's NO_REBOOT bit */
		if (iTCO_wdt_unset_NO_REBOOT_bit()) {
			pr_err("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
			ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
			goto out;
		}
	}

	/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
	if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
		pr_err("I/O address 0x%04lx already in use, device disabled\n",
		       SMI_EN);
		ret = -EIO;
		goto out;
	}
	if (!request_region(SMI_STS, 4,	"iTCO_wdt")) {
		pr_err("I/O address 0x%04lx already in use, device disabled\n",
				SMI_STS);
		ret = -EIO;
		goto unreg_smi_sts;
	}

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

	/* The TCO I/O registers reside in a 32-byte range pointed to
	   by the TCOBASE value */
	if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
		pr_err("I/O address 0x%04lx already in use, device disabled\n",
		       TCOBASE);
		ret = -EIO;
		goto unreg_smi_en;
	}

	pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
		iTCO_chipset_info[ent->driver_data].name,
		iTCO_chipset_info[ent->driver_data].iTCO_version,
		TCOBASE);

	/* Check that the heartbeat value is within it's range;
	   if not reset to the default */
	if (iTCO_wdt_set_heartbeat(heartbeat)) {
		iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
		pr_info("timeout value out of range, using %d\n", heartbeat);
	}

	ret = misc_register(&iTCO_wdt_miscdev);
	if (ret != 0) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       WATCHDOG_MINOR, ret);
		goto unreg_region;
	}

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

	/* Reset OS policy */
	iTCO_wdt_set_reset_type(TCO_POLICY_NORM);

	ret = acpi_register_gsi(NULL, TCO_WARNING_IRQ,
				ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH);
	if (ret < 0) {
		pr_err("failed to configure TCO warning IRQ %d\n", TCO_WARNING_IRQ);
		goto misc_unreg;
	}
	ret = request_irq(TCO_WARNING_IRQ, tco_irq_handler, 0, "tco_watchdog", NULL);
	if (ret < 0) {
		pr_err("failed to request TCO warning IRQ %d\n", TCO_WARNING_IRQ);
		goto gsi_unreg;
	}

	/* Clear old TCO timeout status */
	val32 = TCO_TIMEOUT_BIT | SECOND_TO_STS_BIT;
	outl(val32, TCO1_STS);
	/* Clear the SMI status */
	outl(TCO_STS_BIT, SMI_STS);

	/* Enable SMI for TCO */
	val32 = inl(SMI_EN);
	val32 |= TCO_EN_BIT;
	outl(val32, SMI_EN);
	/* then ensure that PMC is ready to handle next SMI */
	val32 |= EOS_BIT;
	outl(val32, SMI_EN);

	reboot_notifier.notifier_call = TCO_reboot_notifier;
	reboot_notifier.priority = 1;
	ret = register_reboot_notifier(&reboot_notifier);
	if (ret)
		/* We continue as reboot notifier is not critical for
			 * watchdog */
		pr_err("cannot register reboot notifier %d\n", ret);

	return 0;

gsi_unreg:
	acpi_unregister_gsi(TCO_WARNING_IRQ);
misc_unreg:
	misc_deregister(&iTCO_wdt_miscdev);
unreg_region:
	release_region(TCOBASE, 0x20);
unreg_smi_sts:
	release_region(SMI_STS, 4);
unreg_smi_en:
	release_region(SMI_EN, 4);
out:
	iTCO_wdt_private.ACPIBASE = 0;
	return ret;
}
コード例 #2
0
static void install_reboot_notifier(void)
{
    register_reboot_notifier(&reboot_boot_globals_nb);
}
コード例 #3
0
ファイル: sc1200wdt.c プロジェクト: 274914765/C
static int __init sc1200wdt_init(void)
{
    int ret;

    printk("%s\n", banner);

    sema_init(&open_sem, 1);

#if defined CONFIG_PNP
    if (isapnp) {
        ret = pnp_register_driver(&scl200wdt_pnp_driver);
        if (ret)
            goto out_clean;
    }
#endif

    if (io == -1) {
        printk(KERN_ERR PFX "io parameter must be specified\n");
        ret = -EINVAL;
        goto out_pnp;
    }

#if defined CONFIG_PNP
    /* now that the user has specified an IO port and we haven't detected
     * any devices, disable pnp support */
    isapnp = 0;
    pnp_unregister_driver(&scl200wdt_pnp_driver);
#endif

    if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
        printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
        ret = -EBUSY;
        goto out_pnp;
    }

    ret = sc1200wdt_probe();
    if (ret)
        goto out_io;

    ret = register_reboot_notifier(&sc1200wdt_notifier);
    if (ret) {
        printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret);
        goto out_io;
    }

    ret = misc_register(&sc1200wdt_miscdev);
    if (ret) {
        printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
        goto out_rbt;
    }

    /* ret = 0 */

out_clean:
    return ret;

out_rbt:
    unregister_reboot_notifier(&sc1200wdt_notifier);

out_io:
    release_region(io, io_len);

out_pnp:
#if defined CONFIG_PNP
    if (isapnp)
        pnp_unregister_driver(&scl200wdt_pnp_driver);
#endif
    goto out_clean;
}
コード例 #4
0
static int ali_ioctl(struct inode *inode, struct file *file,
			  unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident = {
		.options =		WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"ALi M1535 WatchDog Timer",
	};

	switch (cmd) {
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident,
				sizeof (ident)) ? -EFAULT : 0;

		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);

		case WDIOC_KEEPALIVE:
			ali_keepalive();
			return 0;

		case WDIOC_SETOPTIONS:
		{
			int new_options, retval = -EINVAL;

			if (get_user (new_options, p))
				return -EFAULT;

			if (new_options & WDIOS_DISABLECARD) {
				ali_stop();
				retval = 0;
			}

			if (new_options & WDIOS_ENABLECARD) {
				ali_start();
				retval = 0;
			}

			return retval;
		}

		case WDIOC_SETTIMEOUT:
		{
			int new_timeout;

			if (get_user(new_timeout, p))
				return -EFAULT;

			if (ali_settimer(new_timeout))
			    return -EINVAL;

			ali_keepalive();
			/* Fall */
		}

		case WDIOC_GETTIMEOUT:
			return put_user(timeout, p);

		default:
			return -ENOIOCTLCMD;
	}
}

/*
 *	ali_open	-	handle open of ali watchdog
 *	@inode: inode from VFS
 *	@file: file from VFS
 *
 *	Open the ALi watchdog device. Ensure only one person opens it
 *	at a time. Also start the watchdog running.
 */

static int ali_open(struct inode *inode, struct file *file)
{
	/* /dev/watchdog can only be opened once */
	if (test_and_set_bit(0, &ali_is_open))
		return -EBUSY;

	/* Activate */
	ali_start();
	return nonseekable_open(inode, file);
}

/*
 *	ali_release	-	close an ALi watchdog
 *	@inode: inode from VFS
 *	@file: file from VFS
 *
 *	Close the ALi watchdog device. Actual shutdown of the timer
 *	only occurs if the magic sequence has been set.
 */

static int ali_release(struct inode *inode, struct file *file)
{
	/*
	 *      Shut off the timer.
	 */
	if (ali_expect_release == 42) {
		ali_stop();
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		ali_keepalive();
	}
	clear_bit(0, &ali_is_open);
	ali_expect_release = 0;
	return 0;
}

/*
 *	ali_notify_sys	-	System down notifier
 *
 *	Notifier for system down
 */


static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
{
	if (code==SYS_DOWN || code==SYS_HALT) {
		/* Turn the WDT off */
		ali_stop();
	}

	return NOTIFY_DONE;
}

/*
 *	Data for PCI driver interface
 *
 *	This data only exists for exporting the supported
 *	PCI ids via MODULE_DEVICE_TABLE.  We do not actually
 *	register a pci_driver, because someone else might one day
 *	want to register another driver on the same PCI id.
 */

static struct pci_device_id ali_pci_tbl[] = {
	{ PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
	{ 0, },
};
MODULE_DEVICE_TABLE(pci, ali_pci_tbl);

/*
 *	ali_find_watchdog	-	find a 1535 and 7101
 *
 *	Scans the PCI hardware for a 1535 series bridge and matching 7101
 *	watchdog device. This may be overtight but it is better to be safe
 */

static int __init ali_find_watchdog(void)
{
	struct pci_dev *pdev;
	u32 wdog;

	/* Check for a 1535 series bridge */
	pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
	if(pdev == NULL)
		return -ENODEV;

	/* Check for the a 7101 PMU */
	pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
	if(pdev == NULL)
		return -ENODEV;

	if(pci_enable_device(pdev))
		return -EIO;

	ali_pci = pdev;

	/*
	 *	Initialize the timer bits
	 */
	pci_read_config_dword(pdev, 0xCC, &wdog);

	wdog &= ~0x3F;		/* Timer bits */
	wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24));	/* Issued events */
	wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9));	/* No monitor bits */

	pci_write_config_dword(pdev, 0xCC, wdog);

	return 0;
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations ali_fops = {
	.owner =	THIS_MODULE,
	.llseek =	no_llseek,
	.write =	ali_write,
	.ioctl =	ali_ioctl,
	.open =		ali_open,
	.release =	ali_release,
};

static struct miscdevice ali_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&ali_fops,
};

static struct notifier_block ali_notifier = {
	.notifier_call =	ali_notify_sys,
};

/*
 *	watchdog_init	-	module initialiser
 *
 *	Scan for a suitable watchdog and if so initialize it. Return an error
 *	if we cannot, the error causes the module to unload
 */

static int __init watchdog_init(void)
{
	int ret;

	spin_lock_init(&ali_lock);

	/* Check whether or not the hardware watchdog is there */
	if (ali_find_watchdog() != 0) {
		return -ENODEV;
	}

	/* Check that the timeout value is within it's range ; if not reset to the default */
	if (timeout < 1 || timeout >= 18000) {
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n",
			timeout);
	}

	/* Calculate the watchdog's timeout */
	ali_settimer(timeout);

	ret = misc_register(&ali_miscdev);
	if (ret != 0) {
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		goto out;
	}

	ret = register_reboot_notifier(&ali_notifier);
	if (ret != 0) {
		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		goto unreg_miscdev;
	}

	printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

out:
	return ret;
unreg_miscdev:
	misc_deregister(&ali_miscdev);
	goto out;
}

/*
 *	watchdog_exit	-	module de-initialiser
 *
 *	Called while unloading a successfully installed watchdog module.
 */

static void __exit watchdog_exit(void)
{
	/* Stop the timer before we leave */
	ali_stop();

	/* Deregister */
	unregister_reboot_notifier(&ali_notifier);
	misc_deregister(&ali_miscdev);
}
コード例 #5
0
static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_timeout;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
							| WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "W83697HF WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			wdt_disable();
			retval = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			wdt_enable();
			retval = 0;
		}

		return retval;
	}

	case WDIOC_KEEPALIVE:
		wdt_ping();
		break;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, p))
			return -EFAULT;
		if (wdt_set_heartbeat(new_timeout))
			return -EINVAL;
		wdt_ping();
		

	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);

	default:
		return -ENOTTY;
	}
	return 0;
}

static int wdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wdt_is_open))
		return -EBUSY;

	wdt_enable();
	return nonseekable_open(inode, file);
}

static int wdt_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42)
		wdt_disable();
	else {
		pr_crit("Unexpected close, not stopping watchdog!\n");
		wdt_ping();
	}
	expect_close = 0;
	clear_bit(0, &wdt_is_open);
	return 0;
}


static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_disable();	

	return NOTIFY_DONE;
}


static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wdt_write,
	.unlocked_ioctl	= wdt_ioctl,
	.open		= wdt_open,
	.release	= wdt_close,
};

static struct miscdevice wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &wdt_fops,
};


static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static int w83697hf_check_wdt(void)
{
	if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
		pr_err("I/O address 0x%x already in use\n", wdt_io);
		return -EIO;
	}

	pr_debug("Looking for watchdog at address 0x%x\n", wdt_io);
	w83697hf_unlock();
	if (w83697hf_get_reg(0x20) == 0x60) {
		pr_info("watchdog found at address 0x%x\n", wdt_io);
		w83697hf_lock();
		return 0;
	}
	
	w83697hf_lock();

	pr_info("watchdog not found at address 0x%x\n", wdt_io);
	release_region(wdt_io, 2);
	return -EIO;
}

static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 };

static int __init wdt_init(void)
{
	int ret, i, found = 0;

	pr_info("WDT driver for W83697HF/HG initializing\n");

	if (wdt_io == 0) {
		
		for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) {
			wdt_io = w83697hf_ioports[i];
			if (!w83697hf_check_wdt())
				found++;
		}
	} else {
		if (!w83697hf_check_wdt())
			found++;
	}

	if (!found) {
		pr_err("No W83697HF/HG could be found\n");
		ret = -EIO;
		goto out;
	}

	w83697hf_init();
	if (early_disable) {
		if (wdt_running())
			pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
		wdt_disable();
	}

	if (wdt_set_heartbeat(timeout)) {
		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	ret = register_reboot_notifier(&wdt_notifier);
	if (ret != 0) {
		pr_err("cannot register reboot notifier (err=%d)\n", ret);
		goto unreg_regions;
	}

	ret = misc_register(&wdt_miscdev);
	if (ret != 0) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       WATCHDOG_MINOR, ret);
		goto unreg_reboot;
	}

	pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

out:
	return ret;
unreg_reboot:
	unregister_reboot_notifier(&wdt_notifier);
unreg_regions:
	release_region(wdt_io, 2);
	goto out;
}

static void __exit wdt_exit(void)
{
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	release_region(wdt_io, 2);
}
コード例 #6
0
ファイル: nvdumper.c プロジェクト: Beta1440/Sublime-N9
static int __init nvdumper_init(void)
{
	int ret, dirty;

#ifdef CONFIG_TEGRA_USE_NCT
	union nct_item_type *item;
#endif

	if (!nvdumper_reserved) {
		pr_info("nvdumper: not configured\n");
		return -ENOTSUPP;
	}
	nvdumper_ptr = ioremap_nocache(nvdumper_reserved,
			NVDUMPER_RESERVED_SIZE);
	if (!nvdumper_ptr) {
		pr_info("nvdumper: failed to ioremap memory at 0x%08lx\n",
				nvdumper_reserved);
		return -EIO;
	}
	ret = register_reboot_notifier(&nvdumper_reboot_notifier);
	if (ret)
		goto err_out1;

	ret = nvdumper_regdump_init();
	if (ret)
		goto err_out2;

	nvdumper_dbg_footprint_init();

	dirty = get_dirty_state();
	switch (dirty) {
	case 0:
		pr_info("nvdumper: last reboot was clean\n");
		break;
	case 1:
		pr_info("nvdumper: last reboot was dirty\n");
		break;
	default:
		pr_info("nvdumper: last reboot was unknown\n");
		break;
	}
#ifdef CONFIG_TEGRA_USE_NCT
	item = kzalloc(sizeof(*item), GFP_KERNEL);
	if (!item) {
		pr_err("failed to allocate memory\n");
		goto err_out3;
	}

	ret = tegra_nct_read_item(NCT_ID_RAMDUMP, item);
	if (ret < 0) {
		pr_err("%s: NCT read failure\n", __func__);
		kfree(item);
		goto err_out3;
	}

	pr_info("%s: RAMDUMP flag(%d) from NCT\n",
			__func__, item->ramdump.flag);
	if (item->ramdump.flag == 1)
		set_dirty_state(1);
	else
		set_dirty_state(0);

	kfree(item);

	return 0;

err_out3:

#else
	set_dirty_state(1);
	return 0;
#endif

err_out2:
	unregister_reboot_notifier(&nvdumper_reboot_notifier);
err_out1:
	iounmap(nvdumper_ptr);

	return ret;

}
コード例 #7
0
ファイル: eurotechwdt.c プロジェクト: b3rnik/dsl-n55u-bender
static int eurwdt_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
{
    void __user *argp = (void __user *)arg;
    int __user *p = argp;
    static struct watchdog_info ident = {
        .options	  = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
        .firmware_version = 1,
        .identity	  = "WDT Eurotech CPU-1220/1410",
    };

    int time;
    int options, retval = -EINVAL;

    switch(cmd) {
    default:
        return -ENOTTY;

    case WDIOC_GETSUPPORT:
        return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;

    case WDIOC_GETSTATUS:
    case WDIOC_GETBOOTSTATUS:
        return put_user(0, p);

    case WDIOC_KEEPALIVE:
        eurwdt_ping();
        return 0;

    case WDIOC_SETTIMEOUT:
        if (copy_from_user(&time, p, sizeof(int)))
            return -EFAULT;

        /* Sanity check */
        if (time < 0 || time > 255)
            return -EINVAL;

        eurwdt_timeout = time;
        eurwdt_set_timeout(time);
    /* Fall */

    case WDIOC_GETTIMEOUT:
        return put_user(eurwdt_timeout, p);

    case WDIOC_SETOPTIONS:
        if (get_user(options, p))
            return -EFAULT;
        if (options & WDIOS_DISABLECARD) {
            eurwdt_disable_timer();
            retval = 0;
        }
        if (options & WDIOS_ENABLECARD) {
            eurwdt_activate_timer();
            eurwdt_ping();
            retval = 0;
        }
        return retval;
    }
}

/**
 * eurwdt_open:
 * @inode: inode of device
 * @file: file handle to device
 *
 * The misc device has been opened. The watchdog device is single
 * open and on opening we load the counter.
 */

static int eurwdt_open(struct inode *inode, struct file *file)
{
    if (test_and_set_bit(0, &eurwdt_is_open))
        return -EBUSY;
    eurwdt_timeout = WDT_TIMEOUT;	/* initial timeout */
    /* Activate the WDT */
    eurwdt_activate_timer();
    return nonseekable_open(inode, file);
}

/**
 * eurwdt_release:
 * @inode: inode to board
 * @file: file handle to board
 *
 * The watchdog has a configurable API. There is a religious dispute
 * between people who want their watchdog to be able to shut down and
 * those who want to be sure if the watchdog manager dies the machine
 * reboots. In the former case we disable the counters, in the latter
 * case you have to open it again very soon.
 */

static int eurwdt_release(struct inode *inode, struct file *file)
{
    if (eur_expect_close == 42) {
        eurwdt_disable_timer();
    } else {
        printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
        eurwdt_ping();
    }
    clear_bit(0, &eurwdt_is_open);
    eur_expect_close = 0;
    return 0;
}

/**
 * eurwdt_notify_sys:
 * @this: our notifier block
 * @code: the event being reported
 * @unused: unused
 *
 * Our notifier is called on system shutdowns. We want to turn the card
 * off at reboot otherwise the machine will reboot again during memory
 * test or worse yet during the following fsck. This would suck, in fact
 * trust me - if it happens it does suck.
 */

static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
                             void *unused)
{
    if (code == SYS_DOWN || code == SYS_HALT) {
        /* Turn the card off */
        eurwdt_disable_timer();
    }

    return NOTIFY_DONE;
}

/*
 * Kernel Interfaces
 */


static const struct file_operations eurwdt_fops = {
    .owner	= THIS_MODULE,
    .llseek	= no_llseek,
    .write	= eurwdt_write,
    .ioctl	= eurwdt_ioctl,
    .open	= eurwdt_open,
    .release	= eurwdt_release,
};

static struct miscdevice eurwdt_miscdev = {
    .minor	= WATCHDOG_MINOR,
    .name	= "watchdog",
    .fops	= &eurwdt_fops,
};

/*
 * The WDT card needs to learn about soft shutdowns in order to
 * turn the timebomb registers off.
 */

static struct notifier_block eurwdt_notifier = {
    .notifier_call = eurwdt_notify_sys,
};

/**
 * cleanup_module:
 *
 * Unload the watchdog. You cannot do this with any file handles open.
 * If your watchdog is set to continue ticking on close and you unload
 * it, well it keeps ticking. We won't get the interrupt but the board
 * will not touch PC memory so all is fine. You just have to load a new
 * module in 60 seconds or reboot.
 */

static void __exit eurwdt_exit(void)
{
    eurwdt_lock_chip();

    misc_deregister(&eurwdt_miscdev);

    unregister_reboot_notifier(&eurwdt_notifier);
    release_region(io, 2);
    free_irq(irq, NULL);
}

/**
 * eurwdt_init:
 *
 * Set up the WDT watchdog board. After grabbing the resources
 * we require we need also to unlock the device.
 * The open() function will actually kick the board off.
 */

static int __init eurwdt_init(void)
{
    int ret;

    ret = misc_register(&eurwdt_miscdev);
    if (ret) {
        printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
               WATCHDOG_MINOR);
        goto out;
    }

    ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
    if(ret) {
        printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
        goto outmisc;
    }

    if (!request_region(io, 2, "eurwdt")) {
        printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
        ret = -EBUSY;
        goto outirq;
    }

    ret = register_reboot_notifier(&eurwdt_notifier);
    if (ret) {
        printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret);
        goto outreg;
    }

    eurwdt_unlock_chip();

    ret = 0;
    printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
           " - timeout event: %s\n",
           io, irq, (!strcmp("int", ev) ? "int" : "reboot"));

out:
    return ret;

outreg:
    release_region(io, 2);

outirq:
    free_irq(irq, NULL);

outmisc:
    misc_deregister(&eurwdt_miscdev);
    goto out;
}
コード例 #8
0
ファイル: gpio_wdt.c プロジェクト: 383530895/linux
static int gpio_wdt_probe(struct platform_device *pdev)
{
	struct gpio_wdt_priv *priv;
	enum of_gpio_flags flags;
	unsigned int hw_margin;
	unsigned long f = 0;
	const char *algo;
	int ret;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
	if (!gpio_is_valid(priv->gpio))
		return priv->gpio;

	priv->active_low = flags & OF_GPIO_ACTIVE_LOW;

	ret = of_property_read_string(pdev->dev.of_node, "hw_algo", &algo);
	if (ret)
		return ret;
	if (!strncmp(algo, "toggle", 6)) {
		priv->hw_algo = HW_ALGO_TOGGLE;
		f = GPIOF_IN;
	} else if (!strncmp(algo, "level", 5)) {
		priv->hw_algo = HW_ALGO_LEVEL;
		f = priv->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
	} else {
		return -EINVAL;
	}

	ret = devm_gpio_request_one(&pdev->dev, priv->gpio, f,
				    dev_name(&pdev->dev));
	if (ret)
		return ret;

	ret = of_property_read_u32(pdev->dev.of_node,
				   "hw_margin_ms", &hw_margin);
	if (ret)
		return ret;
	/* Disallow values lower than 2 and higher than 65535 ms */
	if (hw_margin < 2 || hw_margin > 65535)
		return -EINVAL;

	/* Use safe value (1/2 of real timeout) */
	priv->hw_margin = msecs_to_jiffies(hw_margin / 2);

	watchdog_set_drvdata(&priv->wdd, priv);

	priv->wdd.info		= &gpio_wdt_ident;
	priv->wdd.ops		= &gpio_wdt_ops;
	priv->wdd.min_timeout	= SOFT_TIMEOUT_MIN;
	priv->wdd.max_timeout	= SOFT_TIMEOUT_MAX;

	if (watchdog_init_timeout(&priv->wdd, 0, &pdev->dev) < 0)
		priv->wdd.timeout = SOFT_TIMEOUT_DEF;

	setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd);

	ret = watchdog_register_device(&priv->wdd);
	if (ret)
		return ret;

	priv->notifier.notifier_call = gpio_wdt_notify_sys;
	ret = register_reboot_notifier(&priv->notifier);
	if (ret)
		watchdog_unregister_device(&priv->wdd);

	return ret;
}
コード例 #9
0
/* Init routine */
int __init bcm_reset_utils_init(void)
{
	register_reboot_notifier(&reboot_notifier);

	return 0;
}
コード例 #10
0
static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident = {
		.options =		WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"ALi M1535 WatchDog Timer",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_SETOPTIONS:
	{
		int new_options, retval = -EINVAL;

		if (get_user(new_options, p))
			return -EFAULT;
		if (new_options & WDIOS_DISABLECARD) {
			ali_stop();
			retval = 0;
		}
		if (new_options & WDIOS_ENABLECARD) {
			ali_start();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		ali_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
	{
		int new_timeout;
		if (get_user(new_timeout, p))
			return -EFAULT;
		if (ali_settimer(new_timeout))
			return -EINVAL;
		ali_keepalive();
		
	}
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
}



static int ali_open(struct inode *inode, struct file *file)
{
	
	if (test_and_set_bit(0, &ali_is_open))
		return -EBUSY;

	
	ali_start();
	return nonseekable_open(inode, file);
}



static int ali_release(struct inode *inode, struct file *file)
{
	
	if (ali_expect_release == 42)
		ali_stop();
	else {
		printk(KERN_CRIT PFX
				"Unexpected close, not stopping watchdog!\n");
		ali_keepalive();
	}
	clear_bit(0, &ali_is_open);
	ali_expect_release = 0;
	return 0;
}




static int ali_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		ali_stop();		
	return NOTIFY_DONE;
}



static struct pci_device_id ali_pci_tbl[] = {
	{ PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
	{ PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
	{ 0, },
};
MODULE_DEVICE_TABLE(pci, ali_pci_tbl);



static int __init ali_find_watchdog(void)
{
	struct pci_dev *pdev;
	u32 wdog;

	
	pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
	if (pdev == NULL)
		pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL);
	if (pdev == NULL)
		return -ENODEV;
	pci_dev_put(pdev);

	
	pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
	if (pdev == NULL)
		return -ENODEV;

	if (pci_enable_device(pdev)) {
		pci_dev_put(pdev);
		return -EIO;
	}

	ali_pci = pdev;

	
	pci_read_config_dword(pdev, 0xCC, &wdog);

	
	wdog &= ~0x3F;
	
	wdog &= ~((1 << 27)|(1 << 26)|(1 << 25)|(1 << 24));
	
	wdog &= ~((1 << 16)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9));

	pci_write_config_dword(pdev, 0xCC, wdog);

	return 0;
}



static const struct file_operations ali_fops = {
	.owner 		=	THIS_MODULE,
	.llseek 	=	no_llseek,
	.write		=	ali_write,
	.unlocked_ioctl =	ali_ioctl,
	.open 		=	ali_open,
	.release 	=	ali_release,
};

static struct miscdevice ali_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&ali_fops,
};

static struct notifier_block ali_notifier = {
	.notifier_call =	ali_notify_sys,
};



static int __init watchdog_init(void)
{
	int ret;

	
	if (ali_find_watchdog() != 0)
		return -ENODEV;

	
	if (timeout < 1 || timeout >= 18000) {
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX
		     "timeout value must be 0 < timeout < 18000, using %d\n",
							timeout);
	}

	
	ali_settimer(timeout);

	ret = register_reboot_notifier(&ali_notifier);
	if (ret != 0) {
		printk(KERN_ERR PFX
			"cannot register reboot notifier (err=%d)\n", ret);
		goto out;
	}

	ret = misc_register(&ali_miscdev);
	if (ret != 0) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
						WATCHDOG_MINOR, ret);
		goto unreg_reboot;
	}

	printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

out:
	return ret;
unreg_reboot:
	unregister_reboot_notifier(&ali_notifier);
	goto out;
}



static void __exit watchdog_exit(void)
{
	
	ali_stop();

	
	misc_deregister(&ali_miscdev);
	unregister_reboot_notifier(&ali_notifier);
	pci_dev_put(ali_pci);
}
コード例 #11
0
ファイル: xpc_main.c プロジェクト: 274914765/C
int __init
xpc_init(void)
{
    int ret;
    short partid;
    struct xpc_partition *part;
    struct task_struct *kthread;
    size_t buf_size;

    if (!ia64_platform_is("sn2"))
        return -ENODEV;

    buf_size = max(XPC_RP_VARS_SIZE,
                   XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
    xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
                             GFP_KERNEL,
                             &xpc_remote_copy_buffer_base);
    if (xpc_remote_copy_buffer == NULL)
        return -ENOMEM;

    snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
    snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");

    xpc_sysctl = register_sysctl_table(xpc_sys_dir);

    /*
     * The first few fields of each entry of xpc_partitions[] need to
     * be initialized now so that calls to xpc_connect() and
     * xpc_disconnect() can be made prior to the activation of any remote
     * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
     * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
     * PARTITION HAS BEEN ACTIVATED.
     */
    for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
        part = &xpc_partitions[partid];

        DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));

        part->act_IRQ_rcvd = 0;
        spin_lock_init(&part->act_lock);
        part->act_state = XPC_P_INACTIVE;
        XPC_SET_REASON(part, 0, 0);

        init_timer(&part->disengage_request_timer);
        part->disengage_request_timer.function =
            xpc_timeout_partition_disengage_request;
        part->disengage_request_timer.data = (unsigned long)part;

        part->setup_state = XPC_P_UNSET;
        init_waitqueue_head(&part->teardown_wq);
        atomic_set(&part->references, 0);
    }

    /*
     * Open up protections for IPI operations (and AMO operations on
     * Shub 1.1 systems).
     */
    xpc_allow_IPI_ops();

    /*
     * Interrupts being processed will increment this atomic variable and
     * awaken the heartbeat thread which will process the interrupts.
     */
    atomic_set(&xpc_act_IRQ_rcvd, 0);

    /*
     * This is safe to do before the xpc_hb_checker thread has started
     * because the handler releases a wait queue.  If an interrupt is
     * received before the thread is waiting, it will not go to sleep,
     * but rather immediately process the interrupt.
     */
    ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
                      "xpc hb", NULL);
    if (ret != 0) {
        dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
                "errno=%d\n", -ret);

        xpc_restrict_IPI_ops();

        if (xpc_sysctl)
            unregister_sysctl_table(xpc_sysctl);

        kfree(xpc_remote_copy_buffer_base);
        return -EBUSY;
    }

    /*
     * Fill the partition reserved page with the information needed by
     * other partitions to discover we are alive and establish initial
     * communications.
     */
    xpc_rsvd_page = xpc_rsvd_page_init();
    if (xpc_rsvd_page == NULL) {
        dev_err(xpc_part, "could not setup our reserved page\n");

        free_irq(SGI_XPC_ACTIVATE, NULL);
        xpc_restrict_IPI_ops();

        if (xpc_sysctl)
            unregister_sysctl_table(xpc_sysctl);

        kfree(xpc_remote_copy_buffer_base);
        return -EBUSY;
    }

    /* add ourselves to the reboot_notifier_list */
    ret = register_reboot_notifier(&xpc_reboot_notifier);
    if (ret != 0)
        dev_warn(xpc_part, "can't register reboot notifier\n");

    /* add ourselves to the die_notifier list */
    ret = register_die_notifier(&xpc_die_notifier);
    if (ret != 0)
        dev_warn(xpc_part, "can't register die notifier\n");

    init_timer(&xpc_hb_timer);
    xpc_hb_timer.function = xpc_hb_beater;

    /*
     * The real work-horse behind xpc.  This processes incoming
     * interrupts and monitors remote heartbeats.
     */
    kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME);
    if (IS_ERR(kthread)) {
        dev_err(xpc_part, "failed while forking hb check thread\n");

        /* indicate to others that our reserved page is uninitialized */
        xpc_rsvd_page->vars_pa = 0;

        /* take ourselves off of the reboot_notifier_list */
        (void)unregister_reboot_notifier(&xpc_reboot_notifier);

        /* take ourselves off of the die_notifier list */
        (void)unregister_die_notifier(&xpc_die_notifier);

        del_timer_sync(&xpc_hb_timer);
        free_irq(SGI_XPC_ACTIVATE, NULL);
        xpc_restrict_IPI_ops();

        if (xpc_sysctl)
            unregister_sysctl_table(xpc_sysctl);

        kfree(xpc_remote_copy_buffer_base);
        return -EBUSY;
    }

    /*
     * Startup a thread that will attempt to discover other partitions to
     * activate based on info provided by SAL. This new thread is short
     * lived and will exit once discovery is complete.
     */
    kthread = kthread_run(xpc_initiate_discovery, NULL,
                          XPC_DISCOVERY_THREAD_NAME);
    if (IS_ERR(kthread)) {
        dev_err(xpc_part, "failed while forking discovery thread\n");

        /* mark this new thread as a non-starter */
        complete(&xpc_discovery_exited);

        xpc_do_exit(xpUnloading);
        return -EBUSY;
    }

    /* set the interface to point at XPC's functions */
    xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
                      xpc_initiate_allocate, xpc_initiate_send,
                      xpc_initiate_send_notify, xpc_initiate_received,
                      xpc_initiate_partid_to_nasids);

    return 0;
}
コード例 #12
0
static int pn544_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct pn544_i2c_platform_data *platform_data;
	struct pn544_dev *pn544_dev;

	pr_debug("%s : Probing pn544 driver\n", __func__);

	if (client->dev.of_node)
		platform_data = pn544_of_init(client);
	else
		platform_data = client->dev.platform_data;

	if (!platform_data) {
		pr_err("%s : GPIO has value 0, nfc probe fail.\n", __func__);
		goto err_exit;
	}

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s : i2c_check_functionality I2C_FUNC_I2C failed.\n",
			__func__);
		goto err_exit;
	}

	pn544_dev = kzalloc(sizeof(*pn544_dev), GFP_KERNEL);
	if (pn544_dev == NULL) {
		dev_err(&client->dev,
				"failed to allocate memory for module data\n");
		ret = -ENOMEM;
		goto err_exit;
	}

	ret = pn544_gpio_init(platform_data);
	if (ret) {
		dev_err(&client->dev, "gpio init failed\n");
		goto err_gpio_init;
	}

	pn544_dev->irq_gpio = platform_data->irq_gpio;
	pn544_dev->ven_gpio  = platform_data->ven_gpio;
	pn544_dev->firmware_gpio = platform_data->firmware_gpio;
	pn544_dev->ven_polarity = platform_data->ven_polarity;
	pn544_dev->discharge_delay = platform_data->discharge_delay;
	pn544_dev->client   = client;

	wake_lock_init(&pn544_dev->wakelock, WAKE_LOCK_SUSPEND, "pn544c3");

	/* init mutex and queues */
	init_waitqueue_head(&pn544_dev->read_wq);
	mutex_init(&pn544_dev->read_mutex);
	mutex_init(&pn544_dev->ioctl_mutex);
	spin_lock_init(&pn544_dev->irq_enabled_lock);

	pn544_dev->pn544_device.minor = MISC_DYNAMIC_MINOR;
	pn544_dev->pn544_device.name = "pn544";
	pn544_dev->pn544_device.fops = &pn544_dev_fops;

	ret = misc_register(&pn544_dev->pn544_device);
	if (ret) {
		pr_err("%s : misc_register failed.\n", __FILE__);
		goto err_misc_register;
	}

	pr_debug("%s : PN544 Misc Minor: %d\n",
		__func__, pn544_dev->pn544_device.minor);

	/* Get the device structure */
	pn544_dev->pn544_control_device = pn544_dev->pn544_device.this_device;

	/* Create sysfs device for PN544 control functionality */
	ret = device_create_file(pn544_dev->pn544_control_device,
				&dev_attr_pn544_control_dev);
	if (ret) {
		pr_err("%s : device_create_file failed\n", __FILE__);
		goto err_device_create_file_failed;
	}

	/* request irq.  the irq is set whenever the chip has data available
	 * for reading.  it is cleared when all data has been read.
	 */
	pr_debug("%s : requesting IRQ %d\n", __func__, client->irq);
	pn544_dev->irq_enabled = true;
	ret = request_irq(client->irq, pn544_dev_irq_handler,
			  IRQF_TRIGGER_HIGH, client->name, pn544_dev);
	if (ret) {
		dev_err(&client->dev, "request_irq failed\n");
		goto err_request_irq_failed;
	}
	if (unlikely(irq_set_irq_wake(client->irq, 1)))
		pr_err("%s : unable to make irq %d wakeup\n", __func__,
					client->irq);
	pn544_disable_irq(pn544_dev);
	pn544_dev->reboot_notify.notifier_call = nfc_blk_reboot_notify;
	register_reboot_notifier(&pn544_dev->reboot_notify);
	i2c_set_clientdata(client, pn544_dev);

	return 0;

err_request_irq_failed:
	device_remove_file(pn544_dev->pn544_control_device,
				&dev_attr_pn544_control_dev);
err_device_create_file_failed:
	misc_deregister(&pn544_dev->pn544_device);
err_misc_register:
	mutex_destroy(&pn544_dev->ioctl_mutex);
	mutex_destroy(&pn544_dev->read_mutex);
	pn544_gpio_free(pn544_dev);
	wake_unlock(&pn544_dev->wakelock);
	wake_lock_destroy(&pn544_dev->wakelock);
err_gpio_init:
	kfree(pn544_dev);
err_exit:
	return ret;
}
コード例 #13
0
static long indydog_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	int options, retval = -EINVAL;
	static struct watchdog_info ident = {
		.options		= WDIOF_KEEPALIVEPING |
					  WDIOF_MAGICCLOSE,
		.firmware_version	= 0,
		.identity		= "Hardware Watchdog for SGI IP22",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((struct watchdog_info *)arg,
				 &ident, sizeof(ident)))
			return -EFAULT;
		return 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, (int *)arg);
	case WDIOC_SETOPTIONS:
	{
		if (get_user(options, (int *)arg))
			return -EFAULT;
		if (options & WDIOS_DISABLECARD) {
			indydog_stop();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			indydog_start();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		indydog_ping();
		return 0;
	case WDIOC_GETTIMEOUT:
		return put_user(WATCHDOG_TIMEOUT, (int *)arg);
	default:
		return -ENOTTY;
	}
}

static int indydog_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		indydog_stop();		/* Turn the WDT off */

	return NOTIFY_DONE;
}

static const struct file_operations indydog_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= indydog_write,
	.unlocked_ioctl	= indydog_ioctl,
	.open		= indydog_open,
	.release	= indydog_release,
};

static struct miscdevice indydog_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &indydog_fops,
};

static struct notifier_block indydog_notifier = {
	.notifier_call = indydog_notify_sys,
};

static char banner[] __initdata =
	KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";

static int __init watchdog_init(void)
{
	int ret;

	spin_lock_init(&indydog_lock);

	ret = register_reboot_notifier(&indydog_notifier);
	if (ret) {
		printk(KERN_ERR PFX
			"cannot register reboot notifier (err=%d)\n", ret);
		return ret;
	}

	ret = misc_register(&indydog_miscdev);
	if (ret) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
							WATCHDOG_MINOR, ret);
		unregister_reboot_notifier(&indydog_notifier);
		return ret;
	}

	printk(banner);

	return 0;
}

static void __exit watchdog_exit(void)
{
	misc_deregister(&indydog_miscdev);
	unregister_reboot_notifier(&indydog_notifier);
}
コード例 #14
0
static int
hif_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
	int ret = 0;
	struct hif_usb_softc *sc;
	struct ol_softc *ol_sc;
	struct usb_device *pdev = interface_to_usbdev(interface);
	int vendor_id, product_id;

	pr_info("hif_usb_probe\n");
	usb_get_dev(pdev);
	vendor_id = le16_to_cpu(pdev->descriptor.idVendor);
	product_id = le16_to_cpu(pdev->descriptor.idProduct);

	ret = 0;

	sc = A_MALLOC(sizeof(*sc));
	if (!sc) {
		ret = -ENOMEM;
		goto err_alloc;
	}

	OS_MEMZERO(sc, sizeof(*sc));
	sc->pdev = (void *)pdev;
	sc->dev = &pdev->dev;

	sc->aps_osdev.bdev = pdev;
	sc->aps_osdev.device = &pdev->dev;
	sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_AHB;
	sc->devid = id->idProduct;

	adf_os_spinlock_init(&sc->target_lock);

	ol_sc = A_MALLOC(sizeof(*ol_sc));
	if (!ol_sc)
		goto err_attach;
	OS_MEMZERO(ol_sc, sizeof(*ol_sc));
	ol_sc->sc_osdev = &sc->aps_osdev;
	ol_sc->hif_sc = (void *)sc;
	sc->ol_sc = ol_sc;

	if ((usb_control_msg(pdev, usb_sndctrlpipe(pdev, 0),
			     USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0,
			     HZ)) < 0) {
		pr_info("%s[%d]\n\r", __func__, __LINE__);
	}
	usb_set_interface(pdev, 0, 0);

	if (hif_usb_configure(sc, &ol_sc->hif_hdl, interface))
		goto err_config;

	ol_sc->enableuartprint = 1;
	ol_sc->enablefwlog = 0;
	ol_sc->enablesinglebinary = FALSE;
	ol_sc->max_no_of_peers = 1;

	init_waitqueue_head(&ol_sc->sc_osdev->event_queue);

	ret = hdd_wlan_startup(&pdev->dev, ol_sc);
	if (ret) {
		hif_nointrs(sc);
		if (sc->hif_device != NULL) {
			((HIF_DEVICE_USB *)(sc->hif_device))->sc = NULL;
		}
		athdiag_procfs_remove();
		goto err_config;
	}
	sc->hdd_removed = 0;
	sc->hdd_removed_processing = 0;
	sc->hdd_removed_wait_cnt = 0;

#ifndef REMOVE_PKT_LOG
	if (vos_get_conparam() != VOS_FTM_MODE &&
        !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) {
		/*
		 * pktlog initialization
		 */
		ol_pl_sethandle(&ol_sc->pdev_txrx_handle->pl_dev, ol_sc);

		if (pktlogmod_init(ol_sc))
			pr_err("%s: pktlogmod_init failed\n", __func__);
	}
#endif

#ifdef WLAN_BTAMP_FEATURE
	/* Send WLAN UP indication to Nlink Service */
	send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
#endif

	sc->interface = interface;
	sc->reboot_notifier.notifier_call = hif_usb_reboot;
	register_reboot_notifier(&sc->reboot_notifier);

	usb_sc = sc;
	return 0;

err_config:
	A_FREE(ol_sc);
err_attach:
	ret = -EIO;
	usb_sc = NULL;
	A_FREE(sc);
err_alloc:
	usb_put_dev(pdev);

	return ret;
}
コード例 #15
0
ファイル: sc520_wdt.c プロジェクト: FatSunHYS/OSCourseDesign
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "SC520",
	};

	switch(cmd)
	{
		default:
			return -ENOIOCTLCMD;
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);
		case WDIOC_KEEPALIVE:
			wdt_keepalive();
			return 0;
		case WDIOC_SETOPTIONS:
		{
			int new_options, retval = -EINVAL;

			if(get_user(new_options, p))
				return -EFAULT;

			if(new_options & WDIOS_DISABLECARD) {
				wdt_turnoff();
				retval = 0;
			}

			if(new_options & WDIOS_ENABLECARD) {
				wdt_startup();
				retval = 0;
			}

			return retval;
		}
		case WDIOC_SETTIMEOUT:
		{
			int new_timeout;

			if(get_user(new_timeout, p))
				return -EFAULT;

			if(wdt_set_heartbeat(new_timeout))
				return -EINVAL;

			wdt_keepalive();
			/* Fall through */
		}
		case WDIOC_GETTIMEOUT:
			return put_user(timeout, p);
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.ioctl		= fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wdt_fops,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit sc520_wdt_unload(void)
{
	if (!nowayout)
		wdt_turnoff();

	/* Deregister */
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	iounmap(wdtmrctl);
}

static int __init sc520_wdt_init(void)
{
	int rc = -EBUSY;

	spin_lock_init(&wdt_spinlock);

	init_timer(&timer);
	timer.function = wdt_timer_ping;
	timer.data = 0;

	/* Check that the timeout value is within it's range ; if not reset to the default */
	if (wdt_set_heartbeat(timeout)) {
		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
	if (!wdtmrctl) {
		printk(KERN_ERR PFX "Unable to remap memory\n");
		rc = -ENOMEM;
		goto err_out_region2;
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			rc);
		goto err_out_ioremap;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, rc);
		goto err_out_notifier;
	}

	printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
		timeout,nowayout);

	return 0;

err_out_notifier:
	unregister_reboot_notifier(&wdt_notifier);
err_out_ioremap:
	iounmap(wdtmrctl);
err_out_region2:
	return rc;
}

module_init(sc520_wdt_init);
module_exit(sc520_wdt_unload);

MODULE_AUTHOR("Scott and Bill Jennings");
MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
コード例 #16
0
static long wdog_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_heartbeat;
	int status;
	int options;
	uint32_t remaining;

	struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT|
					WDIOF_MAGICCLOSE|
					WDIOF_KEEPALIVEPING,
		.firmware_version =	1,
		.identity =		"BCM2708",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		status = wdog_get_status();
		return put_user(status, p);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_KEEPALIVE:
		wdog_ping();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, p))
			return -EFAULT;
		if (wdog_set_heartbeat(new_heartbeat))
			return -EINVAL;
		wdog_ping();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, p);
	case WDIOC_GETTIMELEFT:
		remaining = WDOG_TICKS_TO_SECS(wdog_get_remaining());
		return put_user(remaining, p);
	case WDIOC_SETOPTIONS:
		if (get_user(options, p))
			return -EFAULT;
		if (options & WDIOS_DISABLECARD)
			wdog_stop();
		if (options & WDIOS_ENABLECARD)
			wdog_start(wdog_ticks);
		return 0;
	default:
		return -ENOTTY;
	}
}

/**
 *	@inode: inode of device
 *	@file: file handle to device
 *
 *	The watchdog device has been opened. The watchdog device is single
 *	open and on opening we load the counters.
 */

static int wdog_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wdog_is_open))
		return -EBUSY;
	/*
	 *	Activate
	 */
	wdog_start(wdog_ticks);
	return nonseekable_open(inode, file);
}

/**
 *	@inode: inode to board
 *	@file: file handle to board
 *
 *	The watchdog has a configurable API. There is a religious dispute
 *	between people who want their watchdog to be able to shut down and
 *	those who want to be sure if the watchdog manager dies the machine
 *	reboots. In the former case we disable the counters, in the latter
 *	case you have to open it again very soon.
 */

static int wdog_release(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		wdog_stop();
	} else {
		printk(KERN_CRIT
		 "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
		wdog_ping();
	}
	clear_bit(0, &wdog_is_open);
	expect_close = 0;
	return 0;
}

/**
 *	@this: our notifier block
 *	@code: the event being reported
 *	@unused: unused
 *
 *	Our notifier is called on system shutdowns. Turn the watchdog
 *	off so that it does not fire during the next reboot.
 */

static int wdog_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdog_stop();
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */


static const struct file_operations wdog_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wdog_write,
	.unlocked_ioctl	= wdog_ioctl,
	.open		= wdog_open,
	.release	= wdog_release,
};

static struct miscdevice wdog_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wdog_fops,
};

/*
 *	The WDT card needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdog_notifier = {
	.notifier_call = wdog_notify_sys,
};

/**
 *	cleanup_module:
 *
 *	Unload the watchdog. You cannot do this with any file handles open.
 *	If your watchdog is set to continue ticking on close and you unload
 *	it, well it keeps ticking. We won't get the interrupt but the board
 *	will not touch PC memory so all is fine. You just have to load a new
 *	module in 60 seconds or reboot.
 */

static void __exit wdog_exit(void)
{
	misc_deregister(&wdog_miscdev);
	unregister_reboot_notifier(&wdog_notifier);
}

static int __init wdog_init(void)
{
	int ret;

	/* Check that the heartbeat value is within it's range;
	   if not reset to the default */
	if (wdog_set_heartbeat(heartbeat)) {
		wdog_set_heartbeat(WD_TIMO);
		printk(KERN_INFO "bcm2708_wdog: heartbeat value must be "
			"0 < heartbeat < %d, using %d\n",
				WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),
				WD_TIMO);
	}

	ret = register_reboot_notifier(&wdog_notifier);
	if (ret) {
		printk(KERN_ERR
		      "wdt: cannot register reboot notifier (err=%d)\n", ret);
		goto out_reboot;
	}

	ret = misc_register(&wdog_miscdev);
	if (ret) {
		printk(KERN_ERR
			"wdt: cannot register miscdev on minor=%d (err=%d)\n",
							WATCHDOG_MINOR, ret);
		goto out_misc;
	}

	printk(KERN_INFO "bcm2708 watchdog, heartbeat=%d sec (nowayout=%d)\n",
		heartbeat, nowayout);
	return 0;

out_misc:
	unregister_reboot_notifier(&wdog_notifier);
out_reboot:
	return ret;
}
コード例 #17
0
static long intel_scu_ioctl(struct file *file,
			   unsigned int cmd,
			   unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	u32 __user *p = argp;
	u32 new_margin;


	static const struct watchdog_info ident = {
		.options =          WDIOF_SETTIMEOUT
				    | WDIOF_KEEPALIVEPING,
		.firmware_version = 0,  /* @todo Get from SCU via
						 ipc_get_scu_fw_version()? */
		.identity =         "Intel_SCU IOH Watchdog"  /* len < 32 */
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp,
				    &ident,
				    sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_KEEPALIVE:
		intel_scu_keepalive();

		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, p))
			return -EFAULT;

		if (check_timer_margin(new_margin))
			return -EINVAL;

		if (intel_scu_set_heartbeat(new_margin))
			return -EINVAL;
		return 0;
	case WDIOC_GETTIMEOUT:
		return put_user(watchdog_device.soft_threshold, p);

	default:
		return -ENOTTY;
	}
}

/*
 *      Notifier for system down
 */
static int intel_scu_notify_sys(struct notifier_block *this,
			       unsigned long code,
			       void *another_unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		/* Turn off the watchdog timer. */
		intel_scu_stop();
	return NOTIFY_DONE;
}

/*
 *      Kernel Interfaces
 */
static const struct file_operations intel_scu_fops = {
	.owner          = THIS_MODULE,
	.llseek         = no_llseek,
	.write          = intel_scu_write,
	.unlocked_ioctl = intel_scu_ioctl,
	.open           = intel_scu_open,
	.release        = intel_scu_release,
};

static int __init intel_scu_watchdog_init(void)
{
	int ret;
	u32 __iomem *tmp_addr;

	/*
	 * We don't really need to check this as the SFI timer get will fail
	 * but if we do so we can exit with a clearer reason and no noise.
	 *
	 * If it isn't an intel MID device then it doesn't have this watchdog
	 */
	if (!mrst_identify_cpu())
		return -ENODEV;

	/* Check boot parameters to verify that their initial values */
	/* are in range. */
	/* Check value of timer_set boot parameter */
	if ((timer_set < MIN_TIME_CYCLE) ||
	    (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
		pr_err("Watchdog timer: value of timer_set %x (hex) "
		  "is out of range from %x to %x (hex)\n",
		  timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
		return -EINVAL;
	}

	/* Check value of timer_margin boot parameter */
	if (check_timer_margin(timer_margin))
		return -EINVAL;

	watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);

	if (watchdog_device.timer_tbl_ptr == NULL) {
		pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
		return -ENODEV;
	}
	/* make sure the timer exists */
	if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
		pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
								sfi_mtimer_num);
		return -ENODEV;
	}

	if (watchdog_device.timer_tbl_ptr->irq == 0) {
		pr_debug("Watchdog timer: timer %d invalid irq\n",
							sfi_mtimer_num);
		return -ENODEV;
	}

	tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr,
			20);

	if (tmp_addr == NULL) {
		pr_debug("Watchdog timer: timer unable to ioremap\n");
		return -ENOMEM;
	}

	watchdog_device.timer_load_count_addr = tmp_addr++;
	watchdog_device.timer_current_value_addr = tmp_addr++;
	watchdog_device.timer_control_addr = tmp_addr++;
	watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
	watchdog_device.timer_interrupt_status_addr = tmp_addr++;

	/* Set the default time values in device structure */

	watchdog_device.timer_set = timer_set;
	watchdog_device.threshold =
		timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
	watchdog_device.soft_threshold =
		(watchdog_device.timer_set - timer_margin)
		* watchdog_device.timer_tbl_ptr->freq_hz;


	watchdog_device.intel_scu_notifier.notifier_call =
		intel_scu_notify_sys;

	ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
	if (ret) {
		pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
		goto register_reboot_error;
	}

	watchdog_device.miscdev.minor = WATCHDOG_MINOR;
	watchdog_device.miscdev.name = "watchdog";
	watchdog_device.miscdev.fops = &intel_scu_fops;

	ret = misc_register(&watchdog_device.miscdev);
	if (ret) {
		pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
							WATCHDOG_MINOR, ret);
		goto misc_register_error;
	}

	ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
		watchdog_timer_interrupt,
		IRQF_SHARED, "watchdog",
		&watchdog_device.timer_load_count_addr);
	if (ret) {
		pr_err("Watchdog timer: error requesting irq %d\n", ret);
		goto request_irq_error;
	}
	/* Make sure timer is disabled before returning */
	intel_scu_stop();
	return 0;

/* error cleanup */

request_irq_error:
	misc_deregister(&watchdog_device.miscdev);
misc_register_error:
	unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
register_reboot_error:
	intel_scu_stop();
	iounmap(watchdog_device.timer_load_count_addr);
	return ret;
}
コード例 #18
0
ファイル: battery.c プロジェクト: Av3ng3/Lamobo-D1s
/**
*  @Copyright (C) 	Anyka 2012
*  @brief       		probe battery
*  @author   		Gao wangsheng
*  @email		[email protected]
*  @date        	2012-11-2
*  @param[out]  	void
*  @param[in]   	*dev
*  @return      	fail or not
*/
static int __devinit ak_battery_probe(struct platform_device *dev)
{
	int ret = 0;
	struct ak_bat_mach_info *info;

	info = (struct ak_bat_mach_info *)dev->dev.platform_data;
	if (!info) 
	{
		printk(KERN_ERR "%s:no platform data for battery\n",__func__);
		ret = -EINVAL;
		goto nodata_out;
	}	

	/* initialize hardware */
	mutex_init(&bat_device.bat_lock);
	bat_device.rd_voltage.sample = info->bat_mach_info.voltage_sample;
	bat_device.rd_voltage.design_max = info->bat_mach_info.max_voltage;
	init_timer(&bat_device.timer);
	bat_device.timer.function = bat_charge_full_timer;
	bat_device.timer.data = (unsigned long) &bat_device;
	
	INIT_DELAYED_WORK(&charge_work,bat_charge_work);
	INIT_DELAYED_WORK(&discharge_work,bat_discharge_work);
	INIT_DELAYED_WORK(&voltage_work,bat_voltage_work);
	INIT_DELAYED_WORK(&usbirq_work,bat_usbirq_work);
	INIT_DELAYED_WORK(&pdown_work,bat_pdown_work);
	INIT_DELAYED_WORK(&resume_work,bat_resume_work);
		
	ret = power_supply_register(&dev->dev, &bat_device.bat_ps);
	if (ret != 0)
	{
		goto cancel_out;
	}
	
	ret = power_supply_register(&dev->dev,&bat_device.usb_ps);
	if (ret != 0)
	{
		goto free_bat_ps_out;
	}
	
	ret = power_supply_register(&dev->dev,&bat_device.ac_ps);
	if (ret != 0)
	{
		goto free_usb_ps_out;
	}

	// use for charge full state 
	if (info->full_gpio.pindata.pin >= 0)
	{
		info->gpio_init(&info->full_gpio.pindata);
	}

	if (info->ac_gpio.is_detect_mode == BAT_CHARGE_GPIO_DETECT) {
		INIT_DELAYED_WORK(&acirq_work,bat_acirq_work);
		// use for ac charge in irq
		if (info->ac_gpio.irq >= 0)
		{
			info->gpio_init(&info->ac_gpio.pindata);
			bat_set_int_inverse(info->ac_gpio.pindata.pin);	
			if (request_irq(info->ac_gpio.irq,akbat_ac_irqhandler,0,"ac_charge",&bat_device))
			{
				printk(KERN_ERR "%s:Could not allocate IRQ %d\n", __func__,info->ac_gpio.irq);
				ret = -EIO;
				goto free_ac_ps_out;
			}
		}
	} else if (info->ac_gpio.is_detect_mode == BAT_CHARGE_ADC_DETECT) {
		memset(&ac_detect_nb, 0, sizeof(ac_detect_nb));
		ac_detect_nb.notifier_call = ac_detect_plugin;
		addetect_register_client(&ac_detect_nb);
	}

	// use for usb charge in irq
	if (info->usb_gpio.irq >= 0)
	{
		info->gpio_init(&info->usb_gpio.pindata);
		mdelay(100);
		bat_set_int_inverse(info->usb_gpio.pindata.pin);	
		if (request_irq(info->usb_gpio.irq,akbat_usb_irqhandler,0,"usb_charge",&bat_device))
		{
			printk(KERN_ERR "%s:Could not allocate IRQ %d\n", __func__,info->usb_gpio.irq);
			ret = -EIO;
			goto free_acirq_out;
		}
	}

	ak_bat_update(&bat_device);
	schedule_delayed_work(&voltage_work,UPDATE_VOLTAGE_DELAY);
	register_reboot_notifier(&battery_reboot_nb);
	
	bat_print_battery_info(&bat_device);
	printk("AK Battery initialized\n");
	return ret;
	
free_acirq_out:
	if (info->ac_gpio.irq > 0)
	{
		disable_irq(info->ac_gpio.irq);
		free_irq(info->ac_gpio.irq, dev);
	}
free_ac_ps_out:
	power_supply_unregister(&bat_device.ac_ps);
free_usb_ps_out:
	power_supply_unregister(&bat_device.usb_ps);
free_bat_ps_out:
	power_supply_unregister(&bat_device.bat_ps);
cancel_out:
	del_timer_sync(&bat_device.timer);
	cancel_delayed_work_sync(&charge_work);
	cancel_delayed_work_sync(&discharge_work);
	cancel_delayed_work_sync(&voltage_work);
	cancel_delayed_work_sync(&usbirq_work);
	cancel_delayed_work_sync(&acirq_work);
	cancel_delayed_work_sync(&pdown_work);
	cancel_delayed_work_sync(&resume_work);
	
nodata_out:
	printk(KERN_ERR "###########%s:ERR out##########\n",__func__);
	return ret;
}
コード例 #19
0
ファイル: xpc_main.c プロジェクト: garyvan/openwrt-1.6
int __init
xpc_init(void)
{
	int ret;
	struct task_struct *kthread;

	dev_set_name(xpc_part, "part");
	dev_set_name(xpc_chan, "chan");

	if (is_shub()) {
		/*
		 * The ia64-sn2 architecture supports at most 64 partitions.
		 * And the inability to unregister remote amos restricts us
		 * further to only support exactly 64 partitions on this
		 * architecture, no less.
		 */
		if (xp_max_npartitions != 64) {
			dev_err(xpc_part, "max #of partitions not set to 64\n");
			ret = -EINVAL;
		} else {
			ret = xpc_init_sn2();
		}

	} else if (is_uv()) {
		ret = xpc_init_uv();

	} else {
		ret = -ENODEV;
	}

	if (ret != 0)
		return ret;

	ret = xpc_setup_partitions();
	if (ret != 0) {
		dev_err(xpc_part, "can't get memory for partition structure\n");
		goto out_1;
	}

	xpc_sysctl = register_sysctl_table(xpc_sys_dir);

	/*
	 * Fill the partition reserved page with the information needed by
	 * other partitions to discover we are alive and establish initial
	 * communications.
	 */
	ret = xpc_setup_rsvd_page();
	if (ret != 0) {
		dev_err(xpc_part, "can't setup our reserved page\n");
		goto out_2;
	}

	/* add ourselves to the reboot_notifier_list */
	ret = register_reboot_notifier(&xpc_reboot_notifier);
	if (ret != 0)
		dev_warn(xpc_part, "can't register reboot notifier\n");

	/* add ourselves to the die_notifier list */
	ret = register_die_notifier(&xpc_die_notifier);
	if (ret != 0)
		dev_warn(xpc_part, "can't register die notifier\n");

	/*
	 * The real work-horse behind xpc.  This processes incoming
	 * interrupts and monitors remote heartbeats.
	 */
	kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME);
	if (IS_ERR(kthread)) {
		dev_err(xpc_part, "failed while forking hb check thread\n");
		ret = -EBUSY;
		goto out_3;
	}

	/*
	 * Startup a thread that will attempt to discover other partitions to
	 * activate based on info provided by SAL. This new thread is short
	 * lived and will exit once discovery is complete.
	 */
	kthread = kthread_run(xpc_initiate_discovery, NULL,
			      XPC_DISCOVERY_THREAD_NAME);
	if (IS_ERR(kthread)) {
		dev_err(xpc_part, "failed while forking discovery thread\n");

		/* mark this new thread as a non-starter */
		complete(&xpc_discovery_exited);

		xpc_do_exit(xpUnloading);
		return -EBUSY;
	}

	/* set the interface to point at XPC's functions */
	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
			  xpc_initiate_send, xpc_initiate_send_notify,
			  xpc_initiate_received, xpc_initiate_partid_to_nasids);

	return 0;

	/* initialization was not successful */
out_3:
	xpc_teardown_rsvd_page();

	(void)unregister_die_notifier(&xpc_die_notifier);
	(void)unregister_reboot_notifier(&xpc_reboot_notifier);
out_2:
	if (xpc_sysctl)
		unregister_sysctl_table(xpc_sysctl);

	xpc_teardown_partitions();
out_1:
	if (is_shub())
		xpc_exit_sn2();
	else if (is_uv())
		xpc_exit_uv();
	return ret;
}
コード例 #20
0
static long wafwdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	int new_timeout;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
							WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "Wafer 5823 WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			wafwdt_start();
			retval = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			wafwdt_stop();
			retval = 0;
		}

		return retval;
	}

	case WDIOC_KEEPALIVE:
		wafwdt_ping();
		break;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, p))
			return -EFAULT;
		if ((new_timeout < 1) || (new_timeout > 255))
			return -EINVAL;
		timeout = new_timeout;
		wafwdt_stop();
		wafwdt_start();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);

	default:
		return -ENOTTY;
	}
	return 0;
}

static int wafwdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wafwdt_is_open))
		return -EBUSY;

	/*
	 *      Activate
	 */
	wafwdt_start();
	return nonseekable_open(inode, file);
}

static int wafwdt_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42)
		wafwdt_stop();
	else {
//		printk(KERN_CRIT PFX
;
		wafwdt_ping();
	}
	clear_bit(0, &wafwdt_is_open);
	expect_close = 0;
	return 0;
}

/*
 *	Notifier for system down
 */

static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code,
								void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wafwdt_stop();
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations wafwdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wafwdt_write,
	.unlocked_ioctl	= wafwdt_ioctl,
	.open		= wafwdt_open,
	.release	= wafwdt_close,
};

static struct miscdevice wafwdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wafwdt_fops,
};

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wafwdt_notifier = {
	.notifier_call = wafwdt_notify_sys,
};

static int __init wafwdt_init(void)
{
	int ret;

//	printk(KERN_INFO
;

	if (timeout < 1 || timeout > 255) {
		timeout = WD_TIMO;
//		printk(KERN_INFO PFX
//			"timeout value must be 1 <= x <= 255, using %d\n",
;
	}

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
//			printk(KERN_ERR PFX
//				"I/O address 0x%04x already in use\n",
;
			ret = -EIO;
			goto error;
		}
	}

	if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
//		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
;
		ret = -EIO;
		goto error2;
	}

	ret = register_reboot_notifier(&wafwdt_notifier);
	if (ret != 0) {
//		printk(KERN_ERR PFX
;
		goto error3;
	}

	ret = misc_register(&wafwdt_miscdev);
	if (ret != 0) {
//		printk(KERN_ERR PFX
//			"cannot register miscdev on minor=%d (err=%d)\n",
;
		goto error4;
	}

//	printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
;

	return ret;
error4:
	unregister_reboot_notifier(&wafwdt_notifier);
error3:
	release_region(wdt_start, 1);
error2:
	if (wdt_stop != wdt_start)
		release_region(wdt_stop, 1);
error:
	return ret;
}

static void __exit wafwdt_exit(void)
{
	misc_deregister(&wafwdt_miscdev);
	unregister_reboot_notifier(&wafwdt_notifier);
	if (wdt_stop != wdt_start)
		release_region(wdt_stop, 1);
	release_region(wdt_start, 1);
}
コード例 #21
0
ファイル: sbc_epx_c3.c プロジェクト: CSCLOG/beaglebone
static long epx_c3_ioctl(struct file *file, unsigned int cmd,
						unsigned long arg)
{
	int options, retval = -EINVAL;
	int __user *argp = (void __user *)arg;
	static const struct watchdog_info ident = {
		.options		= WDIOF_KEEPALIVEPING,
		.firmware_version	= 0,
		.identity		= "Winsystems EPX-C3 H/W Watchdog",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		return 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, argp);
	case WDIOC_SETOPTIONS:
		if (get_user(options, argp))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			epx_c3_stop();
			retval = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			epx_c3_start();
			retval = 0;
		}

		return retval;
	case WDIOC_KEEPALIVE:
		epx_c3_pet();
		return 0;
	case WDIOC_GETTIMEOUT:
		return put_user(WATCHDOG_TIMEOUT, argp);
	default:
		return -ENOTTY;
	}
}

static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
				void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		epx_c3_stop();		/* Turn the WDT off */

	return NOTIFY_DONE;
}

static const struct file_operations epx_c3_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= epx_c3_write,
	.unlocked_ioctl	= epx_c3_ioctl,
	.open		= epx_c3_open,
	.release	= epx_c3_release,
};

static struct miscdevice epx_c3_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &epx_c3_fops,
};

static struct notifier_block epx_c3_notifier = {
	.notifier_call = epx_c3_notify_sys,
};

static const char banner[] __initconst = KERN_INFO PFX
	"Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";

static int __init watchdog_init(void)
{
	int ret;

	if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
		return -EBUSY;

	ret = register_reboot_notifier(&epx_c3_notifier);
	if (ret) {
		printk(KERN_ERR PFX "cannot register reboot notifier "
			"(err=%d)\n", ret);
		goto out;
	}

	ret = misc_register(&epx_c3_miscdev);
	if (ret) {
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
			"(err=%d)\n", WATCHDOG_MINOR, ret);
		unregister_reboot_notifier(&epx_c3_notifier);
		goto out;
	}

	printk(banner);

	return 0;

out:
	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
	return ret;
}

static void __exit watchdog_exit(void)
{
	misc_deregister(&epx_c3_miscdev);
	unregister_reboot_notifier(&epx_c3_notifier);
	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
}
コード例 #22
0
ファイル: pnx833x_wdt.c プロジェクト: 020gzh/linux
static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	int options, new_timeout = 0;
	uint32_t timeout, timeout_left = 0;

	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
		.firmware_version = 0,
		.identity = "Hardware Watchdog for PNX833x",
	};

	switch (cmd) {
	default:
		return -ENOTTY;

	case WDIOC_GETSUPPORT:
		if (copy_to_user((struct watchdog_info *)arg,
				 &ident, sizeof(ident)))
			return -EFAULT;
		return 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, (int *)arg);

	case WDIOC_SETOPTIONS:
		if (get_user(options, (int *)arg))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD)
			pnx833x_wdt_stop();

		if (options & WDIOS_ENABLECARD)
			pnx833x_wdt_start();

		return 0;

	case WDIOC_KEEPALIVE:
		pnx833x_wdt_ping();
		return 0;

	case WDIOC_SETTIMEOUT:
	{
		if (get_user(new_timeout, (int *)arg))
			return -EFAULT;

		pnx833x_wdt_timeout = new_timeout;
		PNX833X_REG(PNX833X_CONFIG +
			PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = new_timeout;
		return put_user(new_timeout, (int *)arg);
	}

	case WDIOC_GETTIMEOUT:
		timeout = PNX833X_REG(PNX833X_CONFIG +
					PNX833X_CONFIG_CPU_WATCHDOG_COMPARE);
		return put_user(timeout, (int *)arg);

	case WDIOC_GETTIMELEFT:
		timeout_left = PNX833X_REG(PNX833X_CONFIG +
						PNX833X_CONFIG_CPU_WATCHDOG);
		return put_user(timeout_left, (int *)arg);

	}
}

static int pnx833x_wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		pnx833x_wdt_stop(); /* Turn the WDT off */

	return NOTIFY_DONE;
}

static const struct file_operations pnx833x_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= pnx833x_wdt_write,
	.unlocked_ioctl	= pnx833x_wdt_ioctl,
	.open		= pnx833x_wdt_open,
	.release	= pnx833x_wdt_release,
};

static struct miscdevice pnx833x_wdt_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &pnx833x_wdt_fops,
};

static struct notifier_block pnx833x_wdt_notifier = {
	.notifier_call = pnx833x_wdt_notify_sys,
};

static int __init watchdog_init(void)
{
	int ret, cause;

	/* Lets check the reason for the reset.*/
	cause = PNX833X_REG(PNX833X_RESET);
	/*If bit 31 is set then watchdog was cause of reset.*/
	if (cause & 0x80000000) {
		pr_info("The system was previously reset due to the watchdog firing - please investigate...\n");
	}

	ret = register_reboot_notifier(&pnx833x_wdt_notifier);
	if (ret) {
		pr_err("cannot register reboot notifier (err=%d)\n", ret);
		return ret;
	}

	ret = misc_register(&pnx833x_wdt_miscdev);
	if (ret) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       WATCHDOG_MINOR, ret);
		unregister_reboot_notifier(&pnx833x_wdt_notifier);
		return ret;
	}

	pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n");

	if (start_enabled)
		pnx833x_wdt_start();

	return 0;
}

static void __exit watchdog_exit(void)
{
	misc_deregister(&pnx833x_wdt_miscdev);
	unregister_reboot_notifier(&pnx833x_wdt_notifier);
}
コード例 #23
0
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
							| WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "W83877F",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_SETOPTIONS:
	{
		int new_options, retval = -EINVAL;

		if (get_user(new_options, p))
			return -EFAULT;

		if (new_options & WDIOS_DISABLECARD) {
			wdt_turnoff();
			retval = 0;
		}

		if (new_options & WDIOS_ENABLECARD) {
			wdt_startup();
			retval = 0;
		}

		return retval;
	}
	case WDIOC_KEEPALIVE:
		wdt_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
	{
		int new_timeout;

		if (get_user(new_timeout, p))
			return -EFAULT;

		/* arbitrary upper limit */
		if (new_timeout < 1 || new_timeout > 3600)
			return -EINVAL;

		timeout = new_timeout;
		wdt_keepalive();
		/* Fall through */
	}
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.unlocked_ioctl	= fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wdt_fops,
};


static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}


static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit w83877f_wdt_unload(void)
{
	wdt_turnoff();

	/* Deregister */
	misc_deregister(&wdt_miscdev);

	unregister_reboot_notifier(&wdt_notifier);
	release_region(WDT_PING, 1);
	release_region(ENABLE_W83877F_PORT, 2);
}

static int __init w83877f_wdt_init(void)
{
	int rc = -EBUSY;

	if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX
			"timeout value must be 1 <= x <= 3600, using %d\n",
							timeout);
	}

	if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) {
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			ENABLE_W83877F_PORT);
		rc = -EIO;
		goto err_out;
	}

	if (!request_region(WDT_PING, 1, "W8387FF WDT")) {
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			WDT_PING);
		rc = -EIO;
		goto err_out_region1;
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		printk(KERN_ERR PFX
			"cannot register reboot notifier (err=%d)\n", rc);
		goto err_out_region2;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
							wdt_miscdev.minor, rc);
		goto err_out_reboot;
	}

	printk(KERN_INFO PFX
	  "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

err_out_reboot:
	unregister_reboot_notifier(&wdt_notifier);
err_out_region2:
	release_region(WDT_PING, 1);
err_out_region1:
	release_region(ENABLE_W83877F_PORT, 2);
err_out:
	return rc;
}
コード例 #24
0
ファイル: smsc37b787_wdt.c プロジェクト: avagin/linux
static long wb_smsc_wdt_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	int new_timeout;

	union {
		struct watchdog_info __user *ident;
		int __user *i;
	} uarg;

	static const struct watchdog_info ident = {
		.options =		WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"SMsC 37B787 Watchdog",
	};

	uarg.i = (int __user *)arg;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(uarg.ident, &ident, sizeof(ident))
								? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		return put_user(wb_smsc_wdt_status(), uarg.i);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, uarg.i);
	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, uarg.i))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			wb_smsc_wdt_disable();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			wb_smsc_wdt_enable();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		wb_smsc_wdt_reset_timer();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, uarg.i))
			return -EFAULT;
		/* the API states this is given in secs */
		if (unit == UNIT_MINUTE)
			new_timeout /= 60;
		if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
			return -EINVAL;
		timeout = new_timeout;
		wb_smsc_wdt_set_timeout(timeout);
		/* fall through - and return the new timeout... */
	case WDIOC_GETTIMEOUT:
		new_timeout = timeout;
		if (unit == UNIT_MINUTE)
			new_timeout *= 60;
		return put_user(new_timeout, uarg.i);
	default:
		return -ENOTTY;
	}
}

/* -- Notifier funtions -----------------------------------------*/

static int wb_smsc_wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT) {
		/* set timeout to 0, to avoid possible race-condition */
		timeout = 0;
		wb_smsc_wdt_disable();
	}
	return NOTIFY_DONE;
}

/* -- Module's structures ---------------------------------------*/

static const struct file_operations wb_smsc_wdt_fops = {
	.owner	  = THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wb_smsc_wdt_write,
	.unlocked_ioctl	= wb_smsc_wdt_ioctl,
	.open		= wb_smsc_wdt_open,
	.release	= wb_smsc_wdt_release,
};

static struct notifier_block wb_smsc_wdt_notifier = {
	.notifier_call  = wb_smsc_wdt_notify_sys,
};

static struct miscdevice wb_smsc_wdt_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &wb_smsc_wdt_fops,
};

/* -- Module init functions -------------------------------------*/

/* module's "constructor" */

static int __init wb_smsc_wdt_init(void)
{
	int ret;

	pr_info("SMsC 37B787 watchdog component driver "
		VERSION " initialising...\n");

	if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
		pr_err("Unable to register IO port %#x\n", IOPORT);
		ret = -EBUSY;
		goto out_pnp;
	}

	/* set new maximum, if it's too big */
	if (timeout > MAX_TIMEOUT)
		timeout = MAX_TIMEOUT;

	/* init the watchdog timer */
	wb_smsc_wdt_initialize();

	ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
	if (ret) {
		pr_err("Unable to register reboot notifier err = %d\n", ret);
		goto out_io;
	}

	ret = misc_register(&wb_smsc_wdt_miscdev);
	if (ret) {
		pr_err("Unable to register miscdev on minor %d\n",
		       WATCHDOG_MINOR);
		goto out_rbt;
	}

	/* output info */
	pr_info("Timeout set to %d %s\n",
		timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
	pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n",
		nowayout);
out_clean:
	return ret;

out_rbt:
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);

out_io:
	release_region(IOPORT, IOPORT_SIZE);

out_pnp:
	goto out_clean;
}

/* module's "destructor" */

static void __exit wb_smsc_wdt_exit(void)
{
	/* Stop the timer before we leave */
	if (!nowayout) {
		wb_smsc_wdt_shutdown();
		pr_info("Watchdog disabled\n");
	}

	misc_deregister(&wb_smsc_wdt_miscdev);
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);
	release_region(IOPORT, IOPORT_SIZE);

	pr_info("SMsC 37B787 watchdog component driver removed\n");
}

module_init(wb_smsc_wdt_init);
module_exit(wb_smsc_wdt_exit);

MODULE_AUTHOR("Sven Anders <*****@*****.**>");
MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version "
								VERSION ")");
MODULE_LICENSE("GPL");

#ifdef SMSC_SUPPORT_MINUTES
module_param(unit, int, 0);
MODULE_PARM_DESC(unit,
		"set unit to use, 0=seconds or 1=minutes, default is 0");
#endif

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");

module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
		"Watchdog cannot be stopped once started (default="
				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
コード例 #25
0
ファイル: alim7101_wdt.c プロジェクト: CSCLOG/beaglebone
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
							| WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "ALiM7101",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_SETOPTIONS:
	{
		int new_options, retval = -EINVAL;

		if (get_user(new_options, p))
			return -EFAULT;
		if (new_options & WDIOS_DISABLECARD) {
			wdt_turnoff();
			retval = 0;
		}
		if (new_options & WDIOS_ENABLECARD) {
			wdt_startup();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		wdt_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
	{
		int new_timeout;

		if (get_user(new_timeout, p))
			return -EFAULT;
		/* arbitrary upper limit */
		if (new_timeout < 1 || new_timeout > 3600)
			return -EINVAL;
		timeout = new_timeout;
		wdt_keepalive();
		/* Fall through */
	}
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
}

static const struct file_operations wdt_fops = {
	.owner		=	THIS_MODULE,
	.llseek		=	no_llseek,
	.write		=	fop_write,
	.open		=	fop_open,
	.release	=	fop_close,
	.unlocked_ioctl	=	fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor	=	WATCHDOG_MINOR,
	.name	=	"watchdog",
	.fops	=	&wdt_fops,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_turnoff();

	if (code == SYS_RESTART) {
		/*
		 * Cobalt devices have no way of rebooting themselves other
		 * than getting the watchdog to pull reset, so we restart the
		 * watchdog on reboot with no heartbeat
		 */
		wdt_change(WDT_ENABLE);
		printk(KERN_INFO PFX "Watchdog timer is now enabled "
			"with no heartbeat - should reboot in ~1 second.\n");
	}
	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit alim7101_wdt_unload(void)
{
	wdt_turnoff();
	/* Deregister */
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	pci_dev_put(alim7101_pmu);
}

static int __init alim7101_wdt_init(void)
{
	int rc = -EBUSY;
	struct pci_dev *ali1543_south;
	char tmp;

	printk(KERN_INFO PFX "Steve Hill <*****@*****.**>.\n");
	alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
		NULL);
	if (!alim7101_pmu) {
		printk(KERN_INFO PFX
			"ALi M7101 PMU not present - WDT not set\n");
		return -EBUSY;
	}

	/* Set the WDT in the PMU to 1 second */
	pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02);

	ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
		NULL);
	if (!ali1543_south) {
		printk(KERN_INFO PFX
			"ALi 1543 South-Bridge not present - WDT not set\n");
		goto err_out;
	}
	pci_read_config_byte(ali1543_south, 0x5e, &tmp);
	pci_dev_put(ali1543_south);
	if ((tmp & 0x1e) == 0x00) {
		if (!use_gpio) {
			printk(KERN_INFO PFX
				"Detected old alim7101 revision 'a1d'.  "
				"If this is a cobalt board, set the 'use_gpio' "
				"module parameter.\n");
			goto err_out;
		}
		nowayout = 1;
	} else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
		printk(KERN_INFO PFX
			"ALi 1543 South-Bridge does not have the correct "
			"revision number (???1001?) - WDT not set\n");
		goto err_out;
	}

	if (timeout < 1 || timeout > 3600) {
		/* arbitrary upper limit */
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX
			"timeout value must be 1 <= x <= 3600, using %d\n",
								timeout);
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		printk(KERN_ERR PFX
			"cannot register reboot notifier (err=%d)\n", rc);
		goto err_out;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
			wdt_miscdev.minor, rc);
		goto err_out_reboot;
	}

	if (nowayout)
		__module_get(THIS_MODULE);

	printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. "
					"timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);
	return 0;

err_out_reboot:
	unregister_reboot_notifier(&wdt_notifier);
err_out:
	pci_dev_put(alim7101_pmu);
	return rc;
}
コード例 #26
0
ファイル: acquirewdt.c プロジェクト: ivucica/linux
static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	int options, retval = -EINVAL;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident =
	{
		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "Acquire WDT",
	};

	switch(cmd)
	{
	case WDIOC_GETSUPPORT:
	  return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
	  return put_user(0, p);

	case WDIOC_KEEPALIVE:
	  acq_keepalive();
	  return 0;

	case WDIOC_GETTIMEOUT:
	  return put_user(WATCHDOG_HEARTBEAT, p);

	case WDIOC_SETOPTIONS:
	{
	    if (get_user(options, p))
	      return -EFAULT;

	    if (options & WDIOS_DISABLECARD)
	    {
	      acq_stop();
	      retval = 0;
	    }

	    if (options & WDIOS_ENABLECARD)
	    {
	      acq_keepalive();
	      retval = 0;
	    }

	    return retval;
	}

	default:
	  return -ENOTTY;
	}
}

static int acq_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &acq_is_open))
		return -EBUSY;

	if (nowayout)
		__module_get(THIS_MODULE);

	/* Activate */
	acq_keepalive();
	return nonseekable_open(inode, file);
}

static int acq_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		acq_stop();
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		acq_keepalive();
	}
	clear_bit(0, &acq_is_open);
	expect_close = 0;
	return 0;
}

/*
 *	Notifier for system down
 */

static int acq_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT) {
		/* Turn the WDT off */
		acq_stop();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations acq_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= acq_write,
	.ioctl		= acq_ioctl,
	.open		= acq_open,
	.release	= acq_close,
};

static struct miscdevice acq_miscdev=
{
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &acq_fops,
};

/*
 *	The WDT card needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block acq_notifier =
{
	.notifier_call = acq_notify_sys,
};

static int __init acq_init(void)
{
	int ret;

	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
				wdt_stop);
			ret = -EIO;
			goto out;
		}
	}

	if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_start);
		ret = -EIO;
		goto unreg_stop;
	}

	ret = register_reboot_notifier(&acq_notifier);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		goto unreg_regions;
	}

	ret = misc_register(&acq_miscdev);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		goto unreg_reboot;
	}

	printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
		nowayout);

	return 0;

unreg_reboot:
	unregister_reboot_notifier(&acq_notifier);
unreg_regions:
	release_region(wdt_start, 1);
unreg_stop:
	if (wdt_stop != wdt_start)
		release_region(wdt_stop, 1);
out:
	return ret;
}

static void __exit acq_exit(void)
{
	misc_deregister(&acq_miscdev);
	unregister_reboot_notifier(&acq_notifier);
	if(wdt_stop != wdt_start)
		release_region(wdt_stop,1);
	release_region(wdt_start,1);
}
コード例 #27
0
ファイル: sbc60xxwdt.c プロジェクト: ivucica/linux
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident=
	{
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "SBC60xx",
	};

	switch(cmd)
	{
		default:
			return -ENOTTY;
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);
		case WDIOC_KEEPALIVE:
			wdt_keepalive();
			return 0;
		case WDIOC_SETOPTIONS:
		{
			int new_options, retval = -EINVAL;

			if(get_user(new_options, p))
				return -EFAULT;

			if(new_options & WDIOS_DISABLECARD) {
				wdt_turnoff();
				retval = 0;
			}

			if(new_options & WDIOS_ENABLECARD) {
				wdt_startup();
				retval = 0;
			}

			return retval;
		}
		case WDIOC_SETTIMEOUT:
		{
			int new_timeout;

			if(get_user(new_timeout, p))
				return -EFAULT;

			if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
				return -EINVAL;

			timeout = new_timeout;
			wdt_keepalive();
			/* Fall through */
		}
		case WDIOC_GETTIMEOUT:
			return put_user(timeout, p);
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.ioctl		= fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &wdt_fops,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier=
{
	.notifier_call = wdt_notify_sys,
};

static void __exit sbc60xxwdt_unload(void)
{
	wdt_turnoff();

	/* Deregister */
	misc_deregister(&wdt_miscdev);

	unregister_reboot_notifier(&wdt_notifier);
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
		release_region(wdt_stop,1);
	release_region(wdt_start,1);
}

static int __init sbc60xxwdt_init(void)
{
	int rc = -EBUSY;

	if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
	{
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
			timeout);
 	}

	if (!request_region(wdt_start, 1, "SBC 60XX WDT"))
	{
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_start);
		rc = -EIO;
		goto err_out;
	}

	/* We cannot reserve 0x45 - the kernel already has! */
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
	{
		if (!request_region(wdt_stop, 1, "SBC 60XX WDT"))
		{
			printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
				wdt_stop);
			rc = -EIO;
			goto err_out_region1;
		}
	}

	init_timer(&timer);
	timer.function = wdt_timer_ping;
	timer.data = 0;

	rc = misc_register(&wdt_miscdev);
	if (rc)
	{
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			wdt_miscdev.minor, rc);
		goto err_out_region2;
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc)
	{
		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			rc);
		goto err_out_miscdev;
	}

	printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

err_out_miscdev:
	misc_deregister(&wdt_miscdev);
err_out_region2:
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
		release_region(wdt_stop,1);
err_out_region1:
	release_region(wdt_start,1);
err_out:
	return rc;
}
コード例 #28
0
static int exynos5_devfreq_int_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct devfreq_data_int *data;
	struct devfreq_notifier_block *devfreq_nb;
	struct exynos_devfreq_platdata *plat_data;

	data = kzalloc(sizeof(struct devfreq_data_int), GFP_KERNEL);
	if (data == NULL) {
		pr_err("DEVFREQ(INT) : Failed to allocate private data\n");
		ret = -ENOMEM;
		goto err_data;
	}

	exynos5433_devfreq_int_init(data);

	data->initial_freq = exynos5_devfreq_int_profile.initial_freq;

	exynos5_devfreq_int_profile.freq_table = kzalloc(sizeof(int) * data->max_state, GFP_KERNEL);
	if (exynos5_devfreq_int_profile.freq_table == NULL) {
		pr_err("DEVFREQ(INT) : Failed to allocate freq table\n");
		ret = -ENOMEM;
		goto err_freqtable;
	}

	ret = exynos5_init_int_table(&pdev->dev, data);
	if (ret)
		goto err_inittable;

	platform_set_drvdata(pdev, data);
	mutex_init(&data->lock);

	data->target_volt = get_match_volt(ID_INT, DEVFREQ_INITIAL_FREQ);
	data->volt_constraint_isp = 0;
	data->volt_offset = 0;
	int_dev =
	data->dev = &pdev->dev;
	data->vdd_int = regulator_get(NULL, "vdd_int");

	if (IS_ERR_OR_NULL(data->vdd_int)) {
		pr_err("DEVFREQ(INT) : Failed to get regulator\n");
		goto err_inittable;
	}

	data->vdd_int_m = regulator_get(NULL, "vdd_int_m");
	if (IS_ERR(data->vdd_int)) {
		dev_err(data->dev, "DEVFREQ(INT) : failed to get regulator\n");
		goto err_regulator_m;
	}

	data->devfreq = devfreq_add_device(data->dev,
						&exynos5_devfreq_int_profile,
						"simple_ondemand",
						&exynos5_devfreq_int_governor_data);

	devfreq_nb = kzalloc(sizeof(struct devfreq_notifier_block), GFP_KERNEL);
	if (devfreq_nb == NULL) {
		pr_err("DEVFREQ(INT) : Failed to allocate notifier block\n");
		ret = -ENOMEM;
		goto err_nb;
	}

	devfreq_nb->df = data->devfreq;
	devfreq_nb->nb.notifier_call = exynos5_devfreq_int_notifier;

	exynos5433_devfreq_register(&devfreq_int_exynos);
	exynos5433_ppmu_register_notifier(INT, &devfreq_nb->nb);

	plat_data = data->dev->platform_data;

	data->default_qos = plat_data->default_qos;
	data->devfreq->min_freq = plat_data->default_qos;
	data->devfreq->max_freq = devfreq_int_opp_list[0].freq;

	register_reboot_notifier(&exynos5_int_reboot_notifier);

#ifdef CONFIG_EXYNOS_THERMAL
	data->tmu_notifier.notifier_call = exynos5_devfreq_int_tmu_notifier;
	exynos_tmu_add_notifier(&data->tmu_notifier);
#endif
	data->use_dvfs = true;

	return ret;
err_nb:
	devfreq_remove_device(data->devfreq);
	regulator_put(data->vdd_int_m);
err_regulator_m:
	regulator_put(data->vdd_int);
err_inittable:
	kfree(exynos5_devfreq_int_profile.freq_table);
err_freqtable:
	kfree(data);
err_data:
	return ret;
}
コード例 #29
0
static int
wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	  unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_timeout;
	static struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "W83627HF WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
	  if (copy_to_user(argp, &ident, sizeof(ident)))
	    return -EFAULT;
	  break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
	  return put_user(0, p);

	case WDIOC_KEEPALIVE:
	  wdt_ping();
	  break;

	case WDIOC_SETTIMEOUT:
	  if (get_user(new_timeout, p))
		  return -EFAULT;
	  if (wdt_set_heartbeat(new_timeout))
		  return -EINVAL;
	  wdt_ping();
	  /* Fall */

	case WDIOC_GETTIMEOUT:
	  return put_user(timeout, p);

	case WDIOC_SETOPTIONS:
	{
	  int options, retval = -EINVAL;

	  if (get_user(options, p))
	    return -EFAULT;

	  if (options & WDIOS_DISABLECARD) {
	    wdt_disable();
	    retval = 0;
	  }

	  if (options & WDIOS_ENABLECARD) {
	    wdt_ping();
	    retval = 0;
	  }

	  return retval;
	}

	default:
	  return -ENOIOCTLCMD;
	}
	return 0;
}

static int
wdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wdt_is_open))
		return -EBUSY;
	/*
	 *	Activate
	 */

	wdt_ping();
	return nonseekable_open(inode, file);
}

static int
wdt_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		wdt_disable();
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		wdt_ping();
	}
	expect_close = 0;
	clear_bit(0, &wdt_is_open);
	return 0;
}

/*
 *	Notifier for system down
 */

static int
wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT) {
		/* Turn the WDT off */
		wdt_disable();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */

static struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wdt_write,
	.ioctl		= wdt_ioctl,
	.open		= wdt_open,
	.release	= wdt_close,
};

static struct miscdevice wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &wdt_fops,
};

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static int __init
wdt_init(void)
{
	int ret;

	printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n");

	if (wdt_set_heartbeat(timeout)) {
		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_io);
		ret = -EIO;
		goto out;
	}

	w83627hf_init();

	ret = register_reboot_notifier(&wdt_notifier);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		goto unreg_regions;
	}

	ret = misc_register(&wdt_miscdev);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		goto unreg_reboot;
	}

	printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

out:
	return ret;
unreg_reboot:
	unregister_reboot_notifier(&wdt_notifier);
unreg_regions:
	release_region(wdt_io, 1);
	goto out;
}

static void __exit
wdt_exit(void)
{
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	release_region(wdt_io,1);
}
コード例 #30
0
ファイル: softdog.c プロジェクト: 3sOx/asuswrt-merlin
static int softdog_ioctl(struct inode *inode, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_margin;
	static struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT |
					WDIOF_KEEPALIVEPING |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"Software Watchdog",
	};
	switch (cmd) {
		default:
			return -ENOTTY;
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident,
				sizeof(ident)) ? -EFAULT : 0;
		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);
		case WDIOC_KEEPALIVE:
			softdog_keepalive();
			return 0;
		case WDIOC_SETTIMEOUT:
			if (get_user(new_margin, p))
				return -EFAULT;
			if (softdog_set_heartbeat(new_margin))
				return -EINVAL;
			softdog_keepalive();
			/* Fall */
		case WDIOC_GETTIMEOUT:
			return put_user(soft_margin, p);
	}
}

/*
 *	Notifier for system down
 */

static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT) {
		/* Turn the WDT off */
		softdog_stop();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations softdog_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= softdog_write,
	.ioctl		= softdog_ioctl,
	.open		= softdog_open,
	.release	= softdog_release,
};

static struct miscdevice softdog_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &softdog_fops,
};

static struct notifier_block softdog_notifier = {
	.notifier_call	= softdog_notify_sys,
};

static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";

static int __init watchdog_init(void)
{
	int ret;

	/* Check that the soft_margin value is within it's range ; if not reset to the default */
	if (softdog_set_heartbeat(soft_margin)) {
		softdog_set_heartbeat(TIMER_MARGIN);
		printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n",
			TIMER_MARGIN);
	}

	ret = register_reboot_notifier(&softdog_notifier);
	if (ret) {
		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		return ret;
	}

	ret = misc_register(&softdog_miscdev);
	if (ret) {
		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		unregister_reboot_notifier(&softdog_notifier);
		return ret;
	}

	printk(banner, soft_noboot, soft_margin, nowayout);

	return 0;
}

static void __exit watchdog_exit(void)
{
	misc_deregister(&softdog_miscdev);
	unregister_reboot_notifier(&softdog_notifier);
}