예제 #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;
}
예제 #2
0
static void wdt_stop(void)
{
	unsigned long flags;

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

	superio_select(GPIO);
	superio_outb(0x00, WDTCTRL);
	superio_outb(WDT_TOV1, WDTCFG);
	superio_outb(0x00, WDTVALMSB);
	superio_outb(0x00, WDTVALLSB);

	superio_exit();
	spin_unlock_irqrestore(&spinlock, flags);
}
static void select_pin(unsigned iminor)
{
	/* select GPIO port/pin from device minor number */
	device_select(SIO_GPIO_UNIT);
	superio_outb(SIO_GPIO_PIN_SELECT,
		     ((iminor << 1) & 0xF0) | (iminor & 0x7));
}
예제 #4
0
static void select_pin(unsigned iminor)
{
	
	device_select(SIO_GPIO_UNIT);
	superio_outb(SIO_GPIO_PIN_SELECT,
		     ((iminor << 1) & 0xF0) | (iminor & 0x7));
}
예제 #5
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;
}
예제 #6
0
/*
 * The Nuvoton NCT6102D starts per default after reset with both,
 * the internal watchdog and the internal legacy UART enabled. This
 * code provides a function to disable the watchdog.
 */
int nct6102d_wdt_disable(void)
{
	superio_enter();
	/* Select logical device for WDT */
	superio_select(NCT6102D_LD_WDT);
	superio_outb(NCT6102D_WDT_TIMEOUT, 0x00);
	superio_exit();

	return 0;
}
예제 #7
0
static void wdt_start(void)
{
	unsigned long flags;

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

	superio_select(GPIO);
	if (test_bit(WDTS_USE_GP, &wdt_status))
		superio_outb(WDT_GAMEPORT, WDTCTRL);
	else
		superio_outb(WDT_CIRINT, WDTCTRL);
	if (!testmode)
		superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG);
	else
		superio_outb(WDT_TOV1, WDTCFG);
	superio_outb(timeout>>8, WDTVALMSB);
	superio_outb(timeout, WDTVALLSB);

	superio_exit();
	spin_unlock_irqrestore(&spinlock, flags);
}
예제 #8
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;
}
예제 #9
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;
}
예제 #10
0
파일: w83627hf_wdt.c 프로젝트: 7799/linux
static int wdt_set_time(unsigned int timeout)
{
	int ret;

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

	superio_select(W83627HF_LD_WDT);
	superio_outb(cr_wdt_timeout, timeout);
	superio_exit();

	return 0;
}
예제 #11
0
static int wdt_set_timeout(int t)
{
	unsigned long flags;

	if (t < 1 || t > 65535)
		return -EINVAL;

	timeout = t;

	spin_lock_irqsave(&spinlock, flags);
	if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
		superio_enter();

		superio_select(GPIO);
		superio_outb(t>>8, WDTVALMSB);
		superio_outb(t, WDTVALLSB);

		superio_exit();
	}
예제 #12
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;
}
예제 #13
0
파일: gpio-f7188x.c 프로젝트: 020gzh/linux
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;
}
예제 #14
0
파일: gpio-f7188x.c 프로젝트: 020gzh/linux
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);
}
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;
}
예제 #16
0
static void qnap_timer(unsigned long data)
{
	int tmp;
	unsigned long flags;

        struct input_dev *qnap_input = (struct input_dev *) data;

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

	tmp = inb(gpio_base_address);

	input_report_key(qnap_input, KEY_ARCHIVE, (tmp & 0x40) >> 6 ); /* USB Copy Button */
	input_report_key(qnap_input, KEY_RESTART, (tmp & 0x80) >> 7 ); /* RESET Button */
	input_sync(qnap_input);

	superio_outb(GPIO_SMI_STATUS_REG, tmp | 0xc0);

	superio_exit();
	spin_unlock_irqrestore(&spinlock, flags);
}
예제 #17
0
파일: w83627hf_wdt.c 프로젝트: 7799/linux
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;
}
static void device_select(unsigned devldn)
{
	superio_outb(SIO_UNIT_SEL, devldn);
	selected_device = devldn;
}
예제 #19
0
static void superio_select(int ld)
{
	superio_outb(NCT_LD_SELECT_REG, ld);
}
예제 #20
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;
}
예제 #21
0
파일: w83627hf_wdt.c 프로젝트: 7799/linux
static void superio_select(int ld)
{
	superio_outb(0x07, ld);
}