Beispiel #1
0
static int f7188x_gpio_direction_out(struct gpio_chip *chip,
				     unsigned offset, int value)
{
	int err;
	struct f7188x_gpio_bank *bank =
		container_of(chip, struct f7188x_gpio_bank, chip);
	struct f7188x_sio *sio = bank->data->sio;
	u8 dir, data_out;

	err = superio_enter(sio->addr);
	if (err)
		return err;
	superio_select(sio->addr, SIO_LD_GPIO);

	data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
	if (value)
		data_out |= (1 << offset);
	else
		data_out &= ~(1 << offset);
	superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);

	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
	dir |= (1 << offset);
	superio_outb(sio->addr, gpio_dir(bank->regbase), dir);

	superio_exit(sio->addr);

	return 0;
}
Beispiel #2
0
static int __init smsc47b397_find(unsigned short *addr)
{
	u8 id, rev;

	superio_enter();
	id = superio_inb(SUPERIO_REG_DEVID);

	if ((id != 0x6f) && (id != 0x81)) {
		superio_exit();
		return -ENODEV;
	}

	rev = superio_inb(SUPERIO_REG_DEVREV);

	superio_select(SUPERIO_REG_LD8);
	*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
		 |  superio_inb(SUPERIO_REG_BASE_LSB);

	printk(KERN_INFO "smsc47b397: found SMSC %s "
		"(base address 0x%04x, revision %u)\n",
		id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);

	superio_exit();
	return 0;
}
Beispiel #3
0
static int __init smsc47m1_find(unsigned short *addr,
				struct smsc47m1_sio_data *sio_data)
{
	u8 val;

	superio_enter();
	val = superio_inb(SUPERIO_REG_DEVID);

	/*
	 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
	 * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control.
	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
	 * can do much more besides (device id 0x60).
	 * The LPC47M997 is undocumented, but seems to be compatible with
	 * the LPC47M192, and has the same device id.
	 * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
	 * supports a 3rd fan, and the pin configuration registers are
	 * unfortunately different.
	 */
	switch (val) {
	case 0x51:
		pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
		sio_data->type = smsc47m1;
		break;
	case 0x59:
		pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
		sio_data->type = smsc47m1;
		break;
	case 0x5F:
		pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
		sio_data->type = smsc47m1;
		break;
	case 0x60:
		pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
		sio_data->type = smsc47m1;
		break;
	case 0x6B:
		pr_info(DRVNAME ": Found SMSC LPC47M292\n");
		sio_data->type = smsc47m2;
		break;
	default:
		superio_exit();
		return -ENODEV;
	}

	superio_select();
	*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
	      |  superio_inb(SUPERIO_REG_BASE + 1);
	val = superio_inb(SUPERIO_REG_ACT);
	if (*addr == 0 || (val & 0x01) == 0) {
		pr_info(DRVNAME ": Device is disabled, will not use\n");
		superio_exit();
		return -ENODEV;
	}

	superio_exit();
	return 0;
}
Beispiel #4
0
static int pc8736x_superio_present(void)
{
    /* try the 2 possible values, read a hardware reg to verify */
    superio_cmd = SIO_BASE1;
    if (superio_inb(SIO_SID) == SIO_SID_VALUE)
        return superio_cmd;

    superio_cmd = SIO_BASE2;
    if (superio_inb(SIO_SID) == SIO_SID_VALUE)
        return superio_cmd;

    return 0;
}
Beispiel #5
0
static int __init nct6683_find(int sioaddr, struct nct6683_sio_data *sio_data)
{
	int addr;
	u16 val;
	int err;

	err = superio_enter(sioaddr);
	if (err)
		return err;

	val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
	       | superio_inb(sioaddr, SIO_REG_DEVID + 1);

	switch (val & SIO_ID_MASK) {
	case SIO_NCT6683_ID:
		sio_data->kind = nct6683;
		break;
	default:
		if (val != 0xffff)
			pr_debug("unsupported chip ID: 0x%04x\n", val);
		goto fail;
	}

	/* We have a known chip, find the HWM I/O address */
	superio_select(sioaddr, NCT6683_LD_HWM);
	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
	addr = val & IOREGION_ALIGNMENT;
	if (addr == 0) {
		pr_err("EC base I/O port unconfigured\n");
		goto fail;
	}

	/* Activate logical device if needed */
	val = superio_inb(sioaddr, SIO_REG_ENABLE);
	if (!(val & 0x01)) {
		pr_warn("Forcibly enabling EC access. Data may be unusable.\n");
		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
	}

	superio_exit(sioaddr);
	pr_info("Found %s or compatible chip at %#x:%#x\n",
		nct6683_chip_names[sio_data->kind], sioaddr, addr);
	sio_data->sioreg = sioaddr;

	return addr;

fail:
	superio_exit(sioaddr);
	return -ENODEV;
}
Beispiel #6
0
static ssize_t
beep_enable_store(struct device *dev, struct device_attribute *attr,
		  const char *buf, size_t count)
{
	struct nct6683_data *data = dev_get_drvdata(dev);
	unsigned long val;
	u8 reg;
	int ret;

	if (kstrtoul(buf, 10, &val) || (val != 0 && val != 1))
		return -EINVAL;

	mutex_lock(&data->update_lock);

	ret = superio_enter(data->sioreg);
	if (ret) {
		count = ret;
		goto error;
	}

	superio_select(data->sioreg, NCT6683_LD_HWM);
	reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP);
	if (val)
		reg |= NCT6683_CR_BEEP_MASK;
	else
		reg &= ~NCT6683_CR_BEEP_MASK;
	superio_outb(data->sioreg, NCT6683_REG_CR_BEEP, reg);
	superio_exit(data->sioreg);
error:
	mutex_unlock(&data->update_lock);
	return count;
}
Beispiel #7
0
static ssize_t
intrusion0_alarm_show(struct device *dev, struct device_attribute *attr,
		      char *buf)
{
	struct nct6683_data *data = dev_get_drvdata(dev);
	int ret;
	u8 reg;

	mutex_lock(&data->update_lock);

	ret = superio_enter(data->sioreg);
	if (ret)
		goto error;
	superio_select(data->sioreg, NCT6683_LD_ACPI);
	reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN);
	superio_exit(data->sioreg);

	mutex_unlock(&data->update_lock);

	return sprintf(buf, "%u\n", !(reg & NCT6683_CR_CASEOPEN_MASK));

error:
	mutex_unlock(&data->update_lock);
	return ret;
}
Beispiel #8
0
static int pc8736x_superio_present(void)
{
	int id;

	
	superio_cmd = SIO_BASE1;
	id = superio_inb(SIO_SID);
	if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
		return superio_cmd;

	superio_cmd = SIO_BASE2;
	id = superio_inb(SIO_SID);
	if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
		return superio_cmd;

	return 0;
}
static int pc8736x_superio_present(void)
{
	int id;

	/* try the 2 possible values, read a hardware reg to verify */
	superio_cmd = SIO_BASE1;
	id = superio_inb(SIO_SID);
	if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
		return superio_cmd;

	superio_cmd = SIO_BASE2;
	id = superio_inb(SIO_SID);
	if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
		return superio_cmd;

	return 0;
}
Beispiel #10
0
static int __init qnap_gpio_button_init(void)
{
	u16 chip_type;
	u8  chip_rev;
	unsigned long flags;
	int err = -ENODEV;
	int tmp;

	spin_lock_irqsave(&spinlock, flags);
	superio_enter();

	chip_type = superio_inw(SIO_CHIP_ID);
	chip_rev  = superio_inb(SIO_CHIP_REV) & 0x0f;

	if (chip_type != SIO_IT8718_ID)
		goto exit;

	superio_select(SIO_GPIO_LDN);
		
	gpio_base_address = superio_inw(GPIO_ADDR_MSB_REG);

	// GP16 GP17
	tmp = superio_inb(GPIO_SET1_SEL_REG);
	superio_outb(GPIO_SET1_SEL_REG, tmp | 0xc0);	//select GPIO Set1 function
	
	tmp = superio_inb(GPIO_SET1_ENABLE_REG);
	superio_outb(GPIO_SET1_ENABLE_REG, tmp | 0xc0);	//enable simple IO function

	tmp = superio_inb(GPIO_SET1_OUTPUT_EN_REG);
	superio_outb(GPIO_SET1_OUTPUT_EN_REG, tmp & 0x3f); //enable input direction

	superio_outb(GPIO_DBOUNCE_SEL_REG, 0x03); // set De-Bounce

	tmp = superio_inb(GPIO_SMI_STATUS_REG);
	superio_outb(GPIO_SMI_STATUS_REG, tmp | 0xc0); /* reset panel button de-bounce status */

	superio_outb(GPIO_BTN0_MAPPING_REG, 0x4e); /* GP16 = 001110 */
	superio_outb(GPIO_BTN1_MAPPING_REG, 0x4f); /* GP17 = 001111 */

	err = 0;
exit:
	superio_exit();
	spin_unlock_irqrestore(&spinlock, flags);
	return err;
}
Beispiel #11
0
static int __init f71805f_find(int sioaddr, unsigned short *address)
{
    int err = -ENODEV;
    u16 devid;

    superio_enter(sioaddr);

    devid = superio_inw(sioaddr, SIO_REG_MANID);
    if (devid != SIO_FINTEK_ID)
        goto exit;

    devid = superio_inw(sioaddr, SIO_REG_DEVID);
    if (devid != SIO_F71805F_ID) {
        printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
               "skipping\n");
        goto exit;
    }

    superio_select(sioaddr, F71805F_LD_HWM);
    if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
        printk(KERN_WARNING DRVNAME ": Device not activated, "
               "skipping\n");
        goto exit;
    }

    *address = superio_inw(sioaddr, SIO_REG_ADDR);
    if (*address == 0) {
        printk(KERN_WARNING DRVNAME ": Base address not set, "
               "skipping\n");
        goto exit;
    }

    err = 0;
    printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
           *address, superio_inb(sioaddr, SIO_REG_DEVREV));

exit:
    superio_exit(sioaddr);
    return err;
}
Beispiel #12
0
static int __init f7188x_find(int addr, struct f7188x_sio *sio)
{
	int err;
	u16 devid;

	err = superio_enter(addr);
	if (err)
		return err;

	err = -ENODEV;
	devid = superio_inw(addr, SIO_MANID);
	if (devid != SIO_FINTEK_ID) {
		pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr);
		goto err;
	}

	devid = superio_inw(addr, SIO_DEVID);
	switch (devid) {
	case SIO_F71808E_ID:
		sio->type = f71808e;
		break;
	case SIO_F71869_ID:
		sio->type = f71869;
		break;
	case SIO_F71869A_ID:
		sio->type = f71869a;
		break;
	case SIO_F71882_ID:
		sio->type = f71882fg;
		break;
	case SIO_F71889_ID:
		sio->type = f71889f;
		break;
	case SIO_F81866_ID:
		sio->type = f81866;
		break;
	default:
		pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
		goto err;
	}
	sio->addr = addr;
	err = 0;

	pr_info(DRVNAME ": Found %s at %#x, revision %d\n",
		f7188x_names[sio->type],
		(unsigned int) addr,
		(int) superio_inb(addr, SIO_DEVREV));

err:
	superio_exit(addr);
	return err;
}
Beispiel #13
0
static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	int err;
	struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
	struct f7188x_sio *sio = bank->data->sio;
	u8 dir, data;

	err = superio_enter(sio->addr);
	if (err)
		return err;
	superio_select(sio->addr, SIO_LD_GPIO);

	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
	dir = !!(dir & (1 << offset));
	if (dir)
		data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
	else
		data = superio_inb(sio->addr, gpio_data_in(bank->regbase));

	superio_exit(sio->addr);

	return !!(data & 1 << offset);
}
Beispiel #14
0
static unsigned int wdt_get_time(struct watchdog_device *wdog)
{
	unsigned int timeleft;
	int ret;

	ret = superio_enter();
	if (ret)
		return 0;

	superio_select(W83627HF_LD_WDT);
	timeleft = superio_inb(cr_wdt_timeout);
	superio_exit();

	return timeleft;
}
Beispiel #15
0
static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
	int err;
	struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
	struct f7188x_sio *sio = bank->data->sio;
	u8 dir;

	err = superio_enter(sio->addr);
	if (err)
		return err;
	superio_select(sio->addr, SIO_LD_GPIO);

	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
	dir &= ~(1 << offset);
	superio_outb(sio->addr, gpio_dir(bank->regbase), dir);

	superio_exit(sio->addr);

	return 0;
}
static inline u32 pc8736x_gpio_configure_fn(unsigned index, u32 mask, u32 bits,
					    u32 func_slct)
{
	u32 config, new_config;

	mutex_lock(&pc8736x_gpio_config_lock);

	device_select(SIO_GPIO_UNIT);
	select_pin(index);

	/* read current config value */
	config = superio_inb(func_slct);

	/* set new config */
	new_config = (config & mask) | bits;
	superio_outb(func_slct, new_config);

	mutex_unlock(&pc8736x_gpio_config_lock);

	return config;
}
Beispiel #17
0
static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	int err;
	struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
	struct f7188x_sio *sio = bank->data->sio;
	u8 data_out;

	err = superio_enter(sio->addr);
	if (err)
		return;
	superio_select(sio->addr, SIO_LD_GPIO);

	data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
	if (value)
		data_out |= (1 << offset);
	else
		data_out &= ~(1 << offset);
	superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);

	superio_exit(sio->addr);
}
Beispiel #18
0
static ssize_t
intrusion0_alarm_store(struct device *dev, struct device_attribute *attr,
		       const char *buf, size_t count)
{
	struct nct6683_data *data = dev_get_drvdata(dev);
	unsigned long val;
	u8 reg;
	int ret;

	if (kstrtoul(buf, 10, &val) || val != 0)
		return -EINVAL;

	mutex_lock(&data->update_lock);

	/*
	 * Use CR registers to clear caseopen status.
	 * Caseopen is activ low, clear by writing 1 into the register.
	 */

	ret = superio_enter(data->sioreg);
	if (ret) {
		count = ret;
		goto error;
	}

	superio_select(data->sioreg, NCT6683_LD_ACPI);
	reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN);
	reg |= NCT6683_CR_CASEOPEN_MASK;
	superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg);
	reg &= ~NCT6683_CR_CASEOPEN_MASK;
	superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg);
	superio_exit(data->sioreg);

	data->valid = false;	/* Force cache refresh */
error:
	mutex_unlock(&data->update_lock);
	return count;
}
Beispiel #19
0
static int __init smsc47b397_device_add(unsigned short address)
{
	struct resource res = {
		.start	= address,
		.end	= address + SMSC_EXTENT - 1,
		.name	= DRVNAME,
		.flags	= IORESOURCE_IO,
	};
	int err;

	pdev = platform_device_alloc(DRVNAME, address);
	if (!pdev) {
		err = -ENOMEM;
		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
		goto exit;
	}

	err = platform_device_add_resources(pdev, &res, 1);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device resource addition failed "
		       "(%d)\n", err);
		goto exit_device_put;
	}

	err = platform_device_add(pdev);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
		       err);
		goto exit_device_put;
	}

	return 0;

exit_device_put:
	platform_device_put(pdev);
exit:
	return err;
}

static int __init smsc47b397_find(unsigned short *addr)
{
	u8 id, rev;
	char *name;

	superio_enter();
	id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);

	switch(id) {
	case 0x81:
		name = "SCH5307-NS";
		break;
	case 0x6f:
		name = "LPC47B397-NC";
		break;
	case 0x85:
	case 0x8c:
		name = "SCH5317";
		break;
	default:
		superio_exit();
		return -ENODEV;
	}

	rev = superio_inb(SUPERIO_REG_DEVREV);

	superio_select(SUPERIO_REG_LD8);
	*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
		 |  superio_inb(SUPERIO_REG_BASE_LSB);

	printk(KERN_INFO DRVNAME ": found SMSC %s "
		"(base address 0x%04x, revision %u)\n",
		name, *addr, rev);

	superio_exit();
	return 0;
}
int __init pc8736x_gpio_init(void)
{
	int rc;
	dev_t devid;

	pdev = platform_device_alloc(DEVNAME, 0);
	if (!pdev)
		return -ENOMEM;

	rc = platform_device_add(pdev);
	if (rc) {
		rc = -ENODEV;
		goto undo_platform_dev_alloc;
	}
	dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");

	if (!pc8736x_superio_present()) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "no device found\n");
		goto undo_platform_dev_add;
	}
	pc8736x_gpio_ops.dev = &pdev->dev;
        __VERIFIER_assert(pc8736x_gpio_ops.dev == &pdev->dev);

	/* Verify that chip and it's GPIO unit are both enabled.
	   My BIOS does this, so I take minimum action here
	 */
	rc = superio_inb(SIO_CF1);
	if (!(rc & 0x01)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "device not enabled\n");
		goto undo_platform_dev_add;
	}
	device_select(SIO_GPIO_UNIT);
	if (!superio_inb(SIO_UNIT_ACT)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "GPIO unit not enabled\n");
		goto undo_platform_dev_add;
	}

	/* read the GPIO unit base addr that chip responds to */
	pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
			     | superio_inb(SIO_BASE_LADDR));

	if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "GPIO ioport %x busy\n",
			pc8736x_gpio_base);
		goto undo_platform_dev_add;
	}
	dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);

	if (major) {
		devid = MKDEV(major, 0);
		rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME);
	} else {
		rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME);
		major = MAJOR(devid);
	}

	if (rc < 0) {
		dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
		goto undo_request_region;
	}
	if (!major) {
		major = rc;
		dev_dbg(&pdev->dev, "got dynamic major %d\n", major);
	}

	pc8736x_init_shadow();

	/* ignore minor errs, and succeed */
	cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops);
	cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT);

	return 0;

undo_request_region:
	release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
undo_platform_dev_add:
	platform_device_del(pdev);
undo_platform_dev_alloc:
	platform_device_put(pdev);

	return rc;
}
Beispiel #21
0
static int wdt_find(int addr)
{
	u8 val;
	int ret;

	cr_wdt_timeout = W83627HF_WDT_TIMEOUT;
	cr_wdt_control = W83627HF_WDT_CONTROL;
	cr_wdt_csr = W836X7HF_WDT_CSR;

	ret = superio_enter();
	if (ret)
		return ret;
	superio_select(W83627HF_LD_WDT);
	val = superio_inb(0x20);
	switch (val) {
	case W83627HF_ID:
		ret = w83627hf;
		break;
	case W83627S_ID:
		ret = w83627s;
		break;
	case W83697HF_ID:
		ret = w83697hf;
		cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
		cr_wdt_control = W83697HF_WDT_CONTROL;
		break;
	case W83697UG_ID:
		ret = w83697ug;
		cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
		cr_wdt_control = W83697HF_WDT_CONTROL;
		break;
	case W83637HF_ID:
		ret = w83637hf;
		break;
	case W83627THF_ID:
		ret = w83627thf;
		break;
	case W83687THF_ID:
		ret = w83687thf;
		break;
	case W83627EHF_ID:
		ret = w83627ehf;
		break;
	case W83627DHG_ID:
		ret = w83627dhg;
		break;
	case W83627DHG_P_ID:
		ret = w83627dhg_p;
		break;
	case W83627UHG_ID:
		ret = w83627uhg;
		break;
	case W83667HG_ID:
		ret = w83667hg;
		break;
	case W83667HG_B_ID:
		ret = w83667hg_b;
		break;
	case NCT6775_ID:
		ret = nct6775;
		break;
	case NCT6776_ID:
		ret = nct6776;
		break;
	case NCT6779_ID:
		ret = nct6779;
		break;
	case NCT6791_ID:
		ret = nct6791;
		break;
	case NCT6792_ID:
		ret = nct6792;
		break;
	case NCT6793_ID:
		ret = nct6793;
		break;
	case NCT6795_ID:
		ret = nct6795;
		break;
	case NCT6102_ID:
		ret = nct6102;
		cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
		cr_wdt_control = NCT6102D_WDT_CONTROL;
		cr_wdt_csr = NCT6102D_WDT_CSR;
		break;
	case 0xff:
		ret = -ENODEV;
		break;
	default:
		ret = -ENODEV;
		pr_err("Unsupported chip ID: 0x%02x\n", val);
		break;
	}
	superio_exit();
	return ret;
}
Beispiel #22
0
static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
{
	int ret;
	unsigned char t;

	ret = superio_enter();
	if (ret)
		return ret;

	superio_select(W83627HF_LD_WDT);

	/* set CR30 bit 0 to activate GPIO2 */
	t = superio_inb(0x30);
	if (!(t & 0x01))
		superio_outb(0x30, t | 0x01);

	switch (chip) {
	case w83627hf:
	case w83627s:
		t = superio_inb(0x2B) & ~0x10;
		superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
		break;
	case w83697hf:
		/* Set pin 119 to WDTO# mode (= CR29, WDT0) */
		t = superio_inb(0x29) & ~0x60;
		t |= 0x20;
		superio_outb(0x29, t);
		break;
	case w83697ug:
		/* Set pin 118 to WDTO# mode */
		t = superio_inb(0x2b) & ~0x04;
		superio_outb(0x2b, t);
		break;
	case w83627thf:
		t = (superio_inb(0x2B) & ~0x08) | 0x04;
		superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
		break;
	case w83627dhg:
	case w83627dhg_p:
		t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
		superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
		t = superio_inb(cr_wdt_control);
		t |= 0x02;	/* enable the WDTO# output low pulse
				 * to the KBRST# pin */
		superio_outb(cr_wdt_control, t);
		break;
	case w83637hf:
		break;
	case w83687thf:
		t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */
		superio_outb(0x2C, t);
		break;
	case w83627ehf:
	case w83627uhg:
	case w83667hg:
	case w83667hg_b:
	case nct6775:
	case nct6776:
	case nct6779:
		/*
		 * These chips have a fixed WDTO# output pin (W83627UHG),
		 * or support more than one WDTO# output pin.
		 * Don't touch its configuration, and hope the BIOS
		 * does the right thing.
		 */
		t = superio_inb(cr_wdt_control);
		t |= 0x02;	/* enable the WDTO# output low pulse
				 * to the KBRST# pin */
		superio_outb(cr_wdt_control, t);
		break;
	default:
		break;
	}

	t = superio_inb(cr_wdt_timeout);
	if (t != 0) {
		pr_info("Watchdog already running. Resetting timeout to %d sec\n",
			wdog->timeout);
		superio_outb(cr_wdt_timeout, wdog->timeout);
	}

	/* set second mode & disable keyboard turning off watchdog */
	t = superio_inb(cr_wdt_control) & ~0x0C;
	superio_outb(cr_wdt_control, t);

	/* reset trigger, disable keyboard & mouse turning off watchdog */
	t = superio_inb(0xF7) & ~0xD0;
	superio_outb(0xF7, t);

	superio_exit();

	return 0;
}
Beispiel #23
0
static int __init pc8736x_gpio_init(void)
{
	int rc;
	dev_t devid;

	pdev = platform_device_alloc(DEVNAME, 0);
	if (!pdev)
		return -ENOMEM;

	rc = platform_device_add(pdev);
	if (rc) {
		rc = -ENODEV;
		goto undo_platform_dev_alloc;
	}
	dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");

	if (!pc8736x_superio_present()) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "no device found\n");
		goto undo_platform_dev_add;
	}
	pc8736x_gpio_ops.dev = &pdev->dev;

	
	rc = superio_inb(SIO_CF1);
	if (!(rc & 0x01)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "device not enabled\n");
		goto undo_platform_dev_add;
	}
	device_select(SIO_GPIO_UNIT);
	if (!superio_inb(SIO_UNIT_ACT)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "GPIO unit not enabled\n");
		goto undo_platform_dev_add;
	}

	
	pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
			     | superio_inb(SIO_BASE_LADDR));

	if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
		rc = -ENODEV;
		dev_err(&pdev->dev, "GPIO ioport %x busy\n",
			pc8736x_gpio_base);
		goto undo_platform_dev_add;
	}
	dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);

	if (major) {
		devid = MKDEV(major, 0);
		rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME);
	} else {
		rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME);
		major = MAJOR(devid);
	}

	if (rc < 0) {
		dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
		goto undo_request_region;
	}
	if (!major) {
		major = rc;
		dev_dbg(&pdev->dev, "got dynamic major %d\n", major);
	}

	pc8736x_init_shadow();

	
	cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops);
	cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT);

	return 0;

undo_request_region:
	release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
undo_platform_dev_add:
	platform_device_del(pdev);
undo_platform_dev_alloc:
	platform_device_put(pdev);

	return rc;
}
Beispiel #24
0
static int __init pc87427_device_add(unsigned short address)
{
	struct resource res = {
		.start	= address,
		.end	= address + REGION_LENGTH - 1,
		.name	= logdev_str[0],
		.flags	= IORESOURCE_IO,
	};
	int err;

	err = acpi_check_resource_conflict(&res);
	if (err)
		goto exit;

	pdev = platform_device_alloc(DRVNAME, address);
	if (!pdev) {
		err = -ENOMEM;
		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
		goto exit;
	}

	err = platform_device_add_resources(pdev, &res, 1);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device resource addition failed "
		       "(%d)\n", err);
		goto exit_device_put;
	}

	err = platform_device_add(pdev);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
		       err);
		goto exit_device_put;
	}

	return 0;

exit_device_put:
	platform_device_put(pdev);
exit:
	return err;
}

static int __init pc87427_find(int sioaddr, unsigned short *address)
{
	u16 val;
	int i, err = 0;

	/* Identify device */
	val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID);
	if (val != 0xf2) {	/* PC87427 */
		err = -ENODEV;
		goto exit;
	}

	for (i = 0; i < 2; i++) {
		address[i] = 0;
		/* Select logical device */
		superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);

		val = superio_inb(sioaddr, SIOREG_ACT);
		if (!(val & 0x01)) {
			printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
			       "not activated\n", logdev[i]);
			continue;
		}

		val = superio_inb(sioaddr, SIOREG_MAP);
		if (val & 0x01) {
			printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
			       "is memory-mapped, can't use\n", logdev[i]);
			continue;
		}

		val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
		    | superio_inb(sioaddr, SIOREG_IOBASE + 1);
		if (!val) {
			printk(KERN_INFO DRVNAME ": I/O base address not set "
			       "for logical device 0x%02x\n", logdev[i]);
			continue;
		}
		address[i] = val;
	}

exit:
	superio_exit(sioaddr);
	return err;
}
Beispiel #25
0
static int __init f71805f_device_add(unsigned short address)
{
	struct resource res = {
		.start	= address,
		.end	= address + REGION_LENGTH - 1,
		.flags	= IORESOURCE_IO,
	};
	int err;

	pdev = platform_device_alloc(DRVNAME, address);
	if (!pdev) {
		err = -ENOMEM;
		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
		goto exit;
	}

	res.name = pdev->name;
	err = platform_device_add_resources(pdev, &res, 1);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device resource addition failed "
		       "(%d)\n", err);
		goto exit_device_put;
	}

	err = platform_device_add(pdev);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
		       err);
		goto exit_device_put;
	}

	return 0;

exit_device_put:
	platform_device_put(pdev);
exit:
	return err;
}

static int __init f71805f_find(int sioaddr, unsigned short *address)
{
	int err = -ENODEV;
	u16 devid;

	superio_enter(sioaddr);

	devid = superio_inw(sioaddr, SIO_REG_MANID);
	if (devid != SIO_FINTEK_ID)
		goto exit;

	devid = superio_inw(sioaddr, SIO_REG_DEVID);
	if (devid != SIO_F71805F_ID) {
		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
		       "skipping\n");
		goto exit;
	}

	superio_select(sioaddr, F71805F_LD_HWM);
	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
		printk(KERN_WARNING DRVNAME ": Device not activated, "
		       "skipping\n");
		goto exit;
	}

	*address = superio_inw(sioaddr, SIO_REG_ADDR);
	if (*address == 0) {
		printk(KERN_WARNING DRVNAME ": Base address not set, "
		       "skipping\n");
		goto exit;
	}

	err = 0;
	printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
	       *address, superio_inb(sioaddr, SIO_REG_DEVREV));

exit:
	superio_exit(sioaddr);
	return err;
}
Beispiel #26
0
static int __init f71805f_device_add(unsigned short address,
				     const struct f71805f_sio_data *sio_data)
{
	struct resource res = {
		.start	= address,
		.end	= address + REGION_LENGTH - 1,
		.flags	= IORESOURCE_IO,
	};
	int err;

	pdev = platform_device_alloc(DRVNAME, address);
	if (!pdev) {
		err = -ENOMEM;
		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
		goto exit;
	}

	res.name = pdev->name;
	err = acpi_check_resource_conflict(&res);
	if (err)
		goto exit_device_put;

	err = platform_device_add_resources(pdev, &res, 1);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device resource addition failed "
		       "(%d)\n", err);
		goto exit_device_put;
	}

	err = platform_device_add_data(pdev, sio_data,
				       sizeof(struct f71805f_sio_data));
	if (err) {
		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
		goto exit_device_put;
	}

	err = platform_device_add(pdev);
	if (err) {
		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
		       err);
		goto exit_device_put;
	}

	return 0;

exit_device_put:
	platform_device_put(pdev);
exit:
	return err;
}

static int __init f71805f_find(int sioaddr, unsigned short *address,
			       struct f71805f_sio_data *sio_data)
{
	int err = -ENODEV;
	u16 devid;

	static const char *names[] = {
		"F71805F/FG",
		"F71872F/FG or F71806F/FG",
	};

	superio_enter(sioaddr);

	devid = superio_inw(sioaddr, SIO_REG_MANID);
	if (devid != SIO_FINTEK_ID)
		goto exit;

	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
	switch (devid) {
	case SIO_F71805F_ID:
		sio_data->kind = f71805f;
		break;
	case SIO_F71872F_ID:
		sio_data->kind = f71872f;
		sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
		break;
	default:
		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
		       "skipping\n");
		goto exit;
	}

	superio_select(sioaddr, F71805F_LD_HWM);
	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
		printk(KERN_WARNING DRVNAME ": Device not activated, "
		       "skipping\n");
		goto exit;
	}

	*address = superio_inw(sioaddr, SIO_REG_ADDR);
	if (*address == 0) {
		printk(KERN_WARNING DRVNAME ": Base address not set, "
		       "skipping\n");
		goto exit;
	}
	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */

	err = 0;
	printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
	       names[sio_data->kind], *address,
	       superio_inb(sioaddr, SIO_REG_DEVREV));

exit:
	superio_exit(sioaddr);
	return err;
}