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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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 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; }
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; }
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; }
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 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; }
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; }
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; }
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; }