X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fhwmon%2Fvt1211.c;h=7dfcc8dd316dcadceb4362b13aaf877f9e0e7d79;hb=96de0e252cedffad61b3cb5e05662c591898e69a;hp=25cc56003d7aeb325277483c53915488540210fc;hpb=946b92437e550d6ed80213bf54a1f383e141aede;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 25cc56003d7a..7dfcc8dd316d 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -31,6 +31,7 @@ #include #include #include +#include #include static int uch_config = -1; @@ -107,7 +108,7 @@ static const u8 bitalarmfan[] = {6, 7}; struct vt1211_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -178,9 +179,10 @@ struct vt1211_data { * Super-I/O constants and functions * --------------------------------------------------------------------- */ -/* Configuration & data index port registers */ -#define SIO_REG_CIP 0x2e -#define SIO_REG_DIP 0x2f +/* Configuration index port registers + * The vt1211 can live at 2 different addresses so we need to probe both */ +#define SIO_REG_CIP1 0x2e +#define SIO_REG_CIP2 0x4e /* Configuration registers */ #define SIO_VT1211_LDN 0x07 /* logical device number */ @@ -193,33 +195,33 @@ struct vt1211_data { /* VT1211 logical device numbers */ #define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ -static inline void superio_outb(int reg, int val) +static inline void superio_outb(int sio_cip, int reg, int val) { - outb(reg, SIO_REG_CIP); - outb(val, SIO_REG_DIP); + outb(reg, sio_cip); + outb(val, sio_cip + 1); } -static inline int superio_inb(int reg) +static inline int superio_inb(int sio_cip, int reg) { - outb(reg, SIO_REG_CIP); - return inb(SIO_REG_DIP); + outb(reg, sio_cip); + return inb(sio_cip + 1); } -static inline void superio_select(int ldn) +static inline void superio_select(int sio_cip, int ldn) { - outb(SIO_VT1211_LDN, SIO_REG_CIP); - outb(ldn, SIO_REG_DIP); + outb(SIO_VT1211_LDN, sio_cip); + outb(ldn, sio_cip + 1); } -static inline void superio_enter(void) +static inline void superio_enter(int sio_cip) { - outb(0x87, SIO_REG_CIP); - outb(0x87, SIO_REG_CIP); + outb(0x87, sio_cip); + outb(0x87, sio_cip); } -static inline void superio_exit(void) +static inline void superio_exit(int sio_cip) { - outb(0xaa, SIO_REG_CIP); + outb(0xaa, sio_cip); } /* --------------------------------------------------------------------- @@ -793,7 +795,7 @@ static ssize_t set_pwm_auto_point_pwm(struct device *dev, if ((val < 0) || (val > 255)) { dev_err(dev, "pwm value %ld is out of range. " - "Choose a value between 0 and 255." , val); + "Choose a value between 0 and 255.\n" , val); return -EINVAL; } @@ -1129,6 +1131,12 @@ static int __devinit vt1211_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { + err = -EBUSY; + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, (unsigned long)res->end); + goto EXIT_KFREE; + } data->addr = res->start; data->name = DRVNAME; mutex_init(&data->update_lock); @@ -1183,9 +1191,9 @@ static int __devinit vt1211_probe(struct platform_device *pdev) } /* Register device */ - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); dev_err(dev, "Class registration failed (%d)\n", err); goto EXIT_DEV_REMOVE_SILENT; } @@ -1196,6 +1204,8 @@ EXIT_DEV_REMOVE: dev_err(dev, "Sysfs interface creation failed (%d)\n", err); EXIT_DEV_REMOVE_SILENT: vt1211_remove_sysfs(pdev); + release_region(res->start, res->end - res->start + 1); +EXIT_KFREE: platform_set_drvdata(pdev, NULL); kfree(data); EXIT: @@ -1205,12 +1215,16 @@ EXIT: static int __devexit vt1211_remove(struct platform_device *pdev) { struct vt1211_data *data = platform_get_drvdata(pdev); + struct resource *res; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); vt1211_remove_sysfs(pdev); platform_set_drvdata(pdev, NULL); kfree(data); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, res->end - res->start + 1); + return 0; } @@ -1263,26 +1277,26 @@ EXIT: return err; } -static int __init vt1211_find(unsigned short *address) +static int __init vt1211_find(int sio_cip, unsigned short *address) { int err = -ENODEV; - superio_enter(); + superio_enter(sio_cip); - if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) { + if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) { goto EXIT; } - superio_select(SIO_VT1211_LDN_HWMON); + superio_select(sio_cip, SIO_VT1211_LDN_HWMON); - if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) { + if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) { printk(KERN_WARNING DRVNAME ": HW monitor is disabled, " "skipping\n"); goto EXIT; } - *address = ((superio_inb(SIO_VT1211_BADDR) << 8) | - (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00; + *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) | + (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00; if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address is not set, " "skipping\n"); @@ -1291,10 +1305,11 @@ static int __init vt1211_find(unsigned short *address) err = 0; printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, " - "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV)); + "revision %u\n", *address, + superio_inb(sio_cip, SIO_VT1211_DEVREV)); EXIT: - superio_exit(); + superio_exit(sio_cip); return err; } @@ -1303,8 +1318,8 @@ static int __init vt1211_init(void) int err; unsigned short address = 0; - err = vt1211_find(&address); - if (err) { + if ((err = vt1211_find(SIO_REG_CIP1, &address)) && + (err = vt1211_find(SIO_REG_CIP2, &address))) { goto EXIT; }