>From 932beeb80d022c5bab861ea4d8d78cd82cae0bba Mon Sep 17 00:00:00 2001 From: Alejandro del Rio Date: Mon, 16 Jan 2012 00:32:21 -0800 Subject: [PATCH 1/2] [temporal change] [temporal change] Signed-off-by: Alejandro del Rio --- drivers/hwmon/w83627hf.c | 331 ++++++++++++---------------------------------- 1 files changed, 86 insertions(+), 245 deletions(-) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 374118f..3c29146 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -6,6 +6,8 @@ and Mark Studebaker Ported to 2.6 by Bernhard C. Schrenk Copyright (c) 2007 Jean Delvare + MFD support added by Rodolfo Giometti + Copyright (c) 2010 Rodolfo Giometti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,17 +56,10 @@ #include #include #include +#include #include "lm75.h" -static struct platform_device *pdev; -#define DRVNAME "w83627hf" -enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; - -struct w83627hf_sio_data { - enum chips type; - int sioaddr; -}; static u8 force_i2c = 0x1f; module_param(force_i2c, byte, 0); @@ -75,86 +70,8 @@ static bool init = 1; module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -/* modified from kernel/include/traps.c */ -#define DEV 0x07 /* Register: Logical device select */ - -/* logical device numbers for superio_select (below) */ -#define W83627HF_LD_FDC 0x00 -#define W83627HF_LD_PRT 0x01 -#define W83627HF_LD_UART1 0x02 -#define W83627HF_LD_UART2 0x03 -#define W83627HF_LD_KBC 0x05 -#define W83627HF_LD_CIR 0x06 /* w83627hf only */ -#define W83627HF_LD_GAME 0x07 -#define W83627HF_LD_MIDI 0x07 -#define W83627HF_LD_GPIO1 0x07 -#define W83627HF_LD_GPIO5 0x07 /* w83627thf only */ -#define W83627HF_LD_GPIO2 0x08 -#define W83627HF_LD_GPIO3 0x09 -#define W83627HF_LD_GPIO4 0x09 /* w83627thf only */ -#define W83627HF_LD_ACPI 0x0a -#define W83627HF_LD_HWM 0x0b - -#define DEVID 0x20 /* Register: Device ID */ - -#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */ -#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ -#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ - -#define W83687THF_VID_EN 0x29 /* w83687thf only */ -#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ -#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ - -static inline void -superio_outb(struct w83627hf_sio_data *sio, int reg, int val) -{ - outb(reg, sio->sioaddr); - outb(val, sio->sioaddr + 1); -} - -static inline int -superio_inb(struct w83627hf_sio_data *sio, int reg) -{ - outb(reg, sio->sioaddr); - return inb(sio->sioaddr + 1); -} - -static inline void -superio_select(struct w83627hf_sio_data *sio, int ld) -{ - outb(DEV, sio->sioaddr); - outb(ld, sio->sioaddr + 1); -} - -static inline void -superio_enter(struct w83627hf_sio_data *sio) -{ - outb(0x87, sio->sioaddr); - outb(0x87, sio->sioaddr); -} - -static inline void -superio_exit(struct w83627hf_sio_data *sio) -{ - outb(0xAA, sio->sioaddr); -} - -#define W627_DEVID 0x52 -#define W627THF_DEVID 0x82 -#define W697_DEVID 0x60 -#define W637_DEVID 0x70 -#define W687THF_DEVID 0x85 -#define WINB_ACT_REG 0x30 -#define WINB_BASE_REG 0x60 /* Constants specified below */ -/* Alignment of the base address */ -#define WINB_ALIGNMENT ~7 - /* Offset & size of I/O region we are interested in */ #define WINB_REGION_OFFSET 5 #define WINB_REGION_SIZE 2 @@ -394,7 +311,7 @@ static void w83627hf_init_device(struct platform_device *pdev); static struct platform_driver w83627hf_driver = { .driver = { .owner = THIS_MODULE, - .name = DRVNAME, + .name = DRVNAME "_hwmon", }, .probe = w83627hf_probe, .remove = __devexit_p(w83627hf_remove), @@ -1123,70 +1040,6 @@ show_name(struct device *dev, struct device_attribute *devattr, char *buf) } static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static int __init w83627hf_find(int sioaddr, unsigned short *addr, - struct w83627hf_sio_data *sio_data) -{ - int err = -ENODEV; - u16 val; - - static const __initdata char *names[] = { - "W83627HF", - "W83627THF", - "W83697HF", - "W83637HF", - "W83687THF", - }; - - sio_data->sioaddr = sioaddr; - superio_enter(sio_data); - val = force_id ? force_id : superio_inb(sio_data, DEVID); - switch (val) { - case W627_DEVID: - sio_data->type = w83627hf; - break; - case W627THF_DEVID: - sio_data->type = w83627thf; - break; - case W697_DEVID: - sio_data->type = w83697hf; - break; - case W637_DEVID: - sio_data->type = w83637hf; - break; - case W687THF_DEVID: - sio_data->type = w83687thf; - break; - case 0xff: /* No device at all */ - goto exit; - default: - pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val); - goto exit; - } - - superio_select(sio_data, W83627HF_LD_HWM); - val = (superio_inb(sio_data, WINB_BASE_REG) << 8) | - superio_inb(sio_data, WINB_BASE_REG + 1); - *addr = val & WINB_ALIGNMENT; - if (*addr == 0) { - pr_warn("Base address not set, skipping\n"); - goto exit; - } - - val = superio_inb(sio_data, WINB_ACT_REG); - if (!(val & 0x01)) { - pr_warn("Enabling HWM logical device\n"); - superio_outb(sio_data, WINB_ACT_REG, val | 0x01); - } - - err = 0; - pr_info(DRVNAME ": Found %s chip at %#x\n", - names[sio_data->type], *addr); - - exit: - superio_exit(sio_data); - return err; -} - #define VIN_UNIT_ATTRS(_X_) \ &sensor_dev_attr_in##_X_##_input.dev_attr.attr, \ &sensor_dev_attr_in##_X_##_min.dev_attr.attr, \ @@ -1265,27 +1118,81 @@ static const struct attribute_group w83627hf_group_opt = { .attrs = w83627hf_attributes_opt, }; +static int w83627hf_enable_hwmon(struct w83627hf_sio_data *sio_data) +{ + u16 val; + int ret; + + superio_enter(sio_data); + + superio_select(sio_data, W83627HF_LD_HWM); + + val = (superio_inb(sio_data, 0x60) << 8) | + superio_inb(sio_data, 0x60 + 1); + ret = val & (~7); + pr_info(DRVNAME ": hwmon chip %s at %#x\n", sio_data->name, ret); + + if (ret == 0) { + printk(KERN_WARNING DRVNAME ": Base address not set, " + "skipping\n"); + ret = -EINVAL; + goto exit; + } + + val = superio_inb(sio_data, 0x30); + superio_outb(sio_data, 0x30, val | 0x01); + +exit: + superio_exit(sio_data); + + return ret; +} + +static void w83627hf_disable_hwmon(struct w83627hf_sio_data *sio_data) +{ + u16 val; + + superio_enter(sio_data); + + superio_select(sio_data, W83627HF_LD_HWM); + + val = superio_inb(sio_data, 0x30); + superio_outb(sio_data, 0x30, val & ~0x01); + + superio_exit(sio_data); +} + static int __devinit w83627hf_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct w83627hf_sio_data *sio_data = dev->platform_data; + struct w83627hf_sio_data *sio_data = dev->parent->platform_data; struct w83627hf_data *data; - struct resource *res; int err, i; - static const char *names[] = { - "w83627hf", - "w83627thf", - "w83697hf", - "w83637hf", - "w83687thf", + struct resource res = { + .start = /* address + */ WINB_REGION_OFFSET, + .end = /* address + */ WINB_REGION_OFFSET + + WINB_REGION_SIZE - 1, + .name = DRVNAME "_hwmon", + .flags = IORESOURCE_IO, }; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { + err = w83627hf_enable_hwmon(sio_data); + if (err < 0) + return err; + + /* Before doing our job we should fixup ioport range */ + res.start += err; + res.end += err; + + err = acpi_check_resource_conflict(&res); + if (err) + goto ERROR0; + + if (!request_region(res.start, WINB_REGION_SIZE, DRVNAME "_hwmon")) { dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)(res->start + WINB_REGION_SIZE - 1)); + (unsigned long) res.start, + (unsigned long) (res.start + WINB_REGION_SIZE - 1)); err = -EBUSY; goto ERROR0; } @@ -1294,9 +1201,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) err = -ENOMEM; goto ERROR1; } - data->addr = res->start; + data->addr = res.start; data->type = sio_data->type; - data->name = names[sio_data->type]; + data->name = sio_data->name; mutex_init(&data->lock); mutex_init(&data->update_lock); platform_set_drvdata(pdev, data); @@ -1429,15 +1336,20 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); kfree(data); ERROR1: - release_region(res->start, WINB_REGION_SIZE); + release_region(res.start, WINB_REGION_SIZE); ERROR0: + w83627hf_disable_hwmon(sio_data); return err; } static int __devexit w83627hf_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct w83627hf_sio_data *sio_data = dev->parent->platform_data; struct w83627hf_data *data = platform_get_drvdata(pdev); - struct resource *res; + unsigned int addr = data->addr; + + w83627hf_disable_hwmon(sio_data); hwmon_device_unregister(data->hwmon_dev); @@ -1446,8 +1358,7 @@ static int __devexit w83627hf_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); kfree(data); - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, WINB_REGION_SIZE); + release_region(addr, WINB_REGION_SIZE); return 0; } @@ -1498,7 +1409,8 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) { - struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct w83627hf_sio_data *sio_data = dev->parent->platform_data; int res = 0xff, sel; superio_enter(sio_data); @@ -1529,7 +1441,8 @@ exit: static int __devinit w83687thf_read_vid(struct platform_device *pdev) { - struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct w83627hf_sio_data *sio_data = dev->parent->platform_data; int res = 0xff; superio_enter(sio_data); @@ -1772,92 +1685,20 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) return data; } -static int __init w83627hf_device_add(unsigned short address, - const struct w83627hf_sio_data *sio_data) -{ - struct resource res = { - .start = address + WINB_REGION_OFFSET, - .end = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1, - .name = DRVNAME, - .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; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct w83627hf_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - err = platform_device_add(pdev); - if (err) { - pr_err("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 sensors_w83627hf_init(void) { - int err; - unsigned short address; - struct w83627hf_sio_data sio_data; - - if (w83627hf_find(0x2e, &address, &sio_data) - && w83627hf_find(0x4e, &address, &sio_data)) - return -ENODEV; - - err = platform_driver_register(&w83627hf_driver); - if (err) - goto exit; - - /* Sets global pdev as a side effect */ - err = w83627hf_device_add(address, &sio_data); - if (err) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&w83627hf_driver); -exit: - return err; + return platform_driver_register(&w83627hf_driver); } static void __exit sensors_w83627hf_exit(void) { - platform_device_unregister(pdev); platform_driver_unregister(&w83627hf_driver); } MODULE_AUTHOR("Frodo Looijaard , " "Philip Edelbrock , " "and Mark Studebaker "); -MODULE_DESCRIPTION("W83627HF driver"); +MODULE_DESCRIPTION("W83627HF hwmon driver"); MODULE_LICENSE("GPL"); module_init(sensors_w83627hf_init); -- 1.7.4.1