X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fhwmon%2Fit87.c;h=62afc63708a5c85dec58aae278b2f2047c476e3e;hb=ec09150303479aff2bbe5ca5fcb714336b973074;hp=323ef06719c160537942a002b5495a79159c2b28;hpb=ccaa36f73544163ef6e15eb29a620130755f6001;p=powerpc.git diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 323ef06719..62afc63708 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -3,7 +3,7 @@ monitoring. Supports: IT8705F Super I/O chip w/LPC interface - IT8712F Super I/O chip w/LPC interface & SMBus + IT8712F Super I/O chip w/LPC interface IT8716F Super I/O chip w/LPC interface IT8718F Super I/O chip w/LPC interface Sis950 A clone of the IT8705F @@ -41,12 +41,8 @@ #include -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; static unsigned short isa_address; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718); +enum chips { it87, it8712, it8716, it8718 }; #define REG 0x2e /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ @@ -162,8 +158,6 @@ static u8 vid_value; #define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2) #define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2) -#define IT87_REG_I2C_ADDR 0x48 - #define IT87_REG_VIN_ENABLE 0x50 #define IT87_REG_TEMP_ENABLE 0x51 @@ -208,15 +202,23 @@ static int DIV_TO_REG(int val) } #define DIV_FROM_REG(val) (1 << (val)) +static const unsigned int pwm_freq[8] = { + 48000000 / 128, + 24000000 / 128, + 12000000 / 128, + 8000000 / 128, + 6000000 / 128, + 3000000 / 128, + 1500000 / 128, + 750000 / 128, +}; -/* For each registered IT87, we need to keep some data in memory. That - data is pointed to by it87_list[NR]->data. The structure itself is - dynamically allocated, at the same time when a new it87 client is - allocated. */ + +/* For each registered chip, we need to keep some data in memory. + The structure is dynamically allocated. */ struct it87_data { struct i2c_client client; struct class_device *class_dev; - struct mutex lock; enum chips type; struct mutex update_lock; @@ -238,37 +240,27 @@ struct it87_data { u8 vrm; u32 alarms; /* Register encoding, combined */ u8 fan_main_ctrl; /* Register value */ + u8 fan_ctl; /* Register value */ u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ }; -static int it87_attach_adapter(struct i2c_adapter *adapter); -static int it87_isa_attach_adapter(struct i2c_adapter *adapter); -static int it87_detect(struct i2c_adapter *adapter, int address, int kind); +static int it87_detect(struct i2c_adapter *adapter); static int it87_detach_client(struct i2c_client *client); static int it87_read_value(struct i2c_client *client, u8 reg); -static int it87_write_value(struct i2c_client *client, u8 reg, u8 value); +static void it87_write_value(struct i2c_client *client, u8 reg, u8 value); static struct it87_data *it87_update_device(struct device *dev); static int it87_check_pwm(struct i2c_client *client); static void it87_init_client(struct i2c_client *client, struct it87_data *data); -static struct i2c_driver it87_driver = { - .driver = { - .name = "it87", - }, - .id = I2C_DRIVERID_IT87, - .attach_adapter = it87_attach_adapter, - .detach_client = it87_detach_client, -}; - static struct i2c_driver it87_isa_driver = { .driver = { .owner = THIS_MODULE, .name = "it87-isa", }, - .attach_adapter = it87_isa_attach_adapter, + .attach_adapter = it87_detect, .detach_client = it87_detach_client, }; @@ -536,6 +528,14 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); } +static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct it87_data *data = it87_update_device(dev); + int index = (data->fan_ctl >> 4) & 0x07; + + return sprintf(buf, "%u\n", pwm_freq[index]); +} static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -545,9 +545,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); + u8 reg; mutex_lock(&data->update_lock); + reg = it87_read_value(client, IT87_REG_FAN_DIV); switch (nr) { case 0: data->fan_div[nr] = reg & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; @@ -656,6 +657,28 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, mutex_unlock(&data->update_lock); return count; } +static ssize_t set_pwm_freq(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + int i; + + /* Search for the nearest available frequency */ + for (i = 0; i < 7; i++) { + if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) + break; + } + + mutex_lock(&data->update_lock); + data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; + data->fan_ctl |= i << 4; + it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); + mutex_unlock(&data->update_lock); + + return count; +} #define show_fan_offset(offset) \ static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ @@ -673,7 +696,10 @@ show_fan_offset(3); static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ show_pwm_enable, set_pwm_enable, offset - 1); \ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, offset - 1); + show_pwm, set_pwm, offset - 1); \ +static DEVICE_ATTR(pwm##offset##_freq, \ + (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ + show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); show_pwm_offset(1); show_pwm_offset(2); @@ -850,22 +876,6 @@ static const struct attribute_group it87_group_opt = { .attrs = it87_attributes_opt, }; -/* This function is called when: - * it87_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and it87_driver is still present) */ -static int it87_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, it87_detect); -} - -static int it87_isa_attach_adapter(struct i2c_adapter *adapter) -{ - return it87_detect(adapter, isa_address, -1); -} - /* SuperIO detection - will change isa_address if a chip is found */ static int __init it87_find(unsigned short *address) { @@ -916,29 +926,20 @@ exit: } /* This function is called by i2c_probe */ -static int it87_detect(struct i2c_adapter *adapter, int address, int kind) +static int it87_detect(struct i2c_adapter *adapter) { - int i; struct i2c_client *new_client; struct it87_data *data; int err = 0; - const char *name = ""; - int is_isa = i2c_is_isa_adapter(adapter); + const char *name; int enable_pwm_interface; - if (!is_isa && - !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto ERROR0; - /* Reserve the ISA region */ - if (is_isa) - if (!request_region(address, IT87_EXTENT, - it87_isa_driver.driver.name)) - goto ERROR0; - - /* For now, we presume we have a valid client. We create the - client structure, even though we cannot fill it completely yet. - But it allows us to access it87_{read,write}_value. */ + if (!request_region(isa_address, IT87_EXTENT, + it87_isa_driver.driver.name)){ + err = -EBUSY; + goto ERROR0; + } if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) { err = -ENOMEM; @@ -946,80 +947,45 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) } new_client = &data->client; - if (is_isa) - mutex_init(&data->lock); i2c_set_clientdata(new_client, data); - new_client->addr = address; + new_client->addr = isa_address; new_client->adapter = adapter; - new_client->driver = is_isa ? &it87_isa_driver : &it87_driver; - new_client->flags = 0; + new_client->driver = &it87_isa_driver; /* Now, we do the remaining detection. */ - - if (kind < 0) { - if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80) - || (!is_isa - && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) { - err = -ENODEV; - goto ERROR2; - } + if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80) + || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) { + err = -ENODEV; + goto ERROR2; } /* Determine the chip type. */ - if (kind <= 0) { - i = it87_read_value(new_client, IT87_REG_CHIPID); - if (i == 0x90) { - kind = it87; - if (is_isa) { - switch (chip_type) { - case IT8712F_DEVID: - kind = it8712; - break; - case IT8716F_DEVID: - kind = it8716; - break; - case IT8718F_DEVID: - kind = it8718; - break; - } - } - } - else { - if (kind == 0) - dev_info(&adapter->dev, - "Ignoring 'force' parameter for unknown chip at " - "adapter %d, address 0x%02x\n", - i2c_adapter_id(adapter), address); - err = -ENODEV; - goto ERROR2; - } - } - - if (kind == it87) { - name = "it87"; - } else if (kind == it8712) { + switch (chip_type) { + case IT8712F_DEVID: + data->type = it8712; name = "it8712"; - } else if (kind == it8716) { + break; + case IT8716F_DEVID: + data->type = it8716; name = "it8716"; - } else if (kind == it8718) { + break; + case IT8718F_DEVID: + data->type = it8718; name = "it8718"; + break; + default: + data->type = it87; + name = "it87"; } /* Fill in the remaining client fields and put it into the global list */ strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) goto ERROR2; - if (!is_isa) - dev_info(&new_client->dev, "The I2C interface to IT87xxF " - "hardware monitoring chips is deprecated. Please " - "report if you still rely on it.\n"); - /* Check PWM configuration */ enable_pwm_interface = it87_check_pwm(new_client); @@ -1097,7 +1063,13 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr)) || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_pwm3.dev_attr))) + &sensor_dev_attr_pwm3.dev_attr)) + || (err = device_create_file(&new_client->dev, + &dev_attr_pwm1_freq)) + || (err = device_create_file(&new_client->dev, + &dev_attr_pwm2_freq)) + || (err = device_create_file(&new_client->dev, + &dev_attr_pwm3_freq))) goto ERROR4; } @@ -1129,8 +1101,7 @@ ERROR3: ERROR2: kfree(data); ERROR1: - if (is_isa) - release_region(address, IT87_EXTENT); + release_region(isa_address, IT87_EXTENT); ERROR0: return err; } @@ -1147,50 +1118,28 @@ static int it87_detach_client(struct i2c_client *client) if ((err = i2c_detach_client(client))) return err; - if(i2c_is_isa_client(client)) - release_region(client->addr, IT87_EXTENT); + release_region(client->addr, IT87_EXTENT); kfree(data); return 0; } -/* The SMBus locks itself, but ISA access must be locked explicitly! - We don't want to lock the whole ISA bus, so we lock each client - separately. +/* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */ static int it87_read_value(struct i2c_client *client, u8 reg) { - struct it87_data *data = i2c_get_clientdata(client); - - int res; - if (i2c_is_isa_client(client)) { - mutex_lock(&data->lock); - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - res = inb_p(client->addr + IT87_DATA_REG_OFFSET); - mutex_unlock(&data->lock); - return res; - } else - return i2c_smbus_read_byte_data(client, reg); + outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); + return inb_p(client->addr + IT87_DATA_REG_OFFSET); } -/* The SMBus locks itself, but ISA access muse be locked explicitly! - We don't want to lock the whole ISA bus, so we lock each client - separately. +/* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */ -static int it87_write_value(struct i2c_client *client, u8 reg, u8 value) +static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) { - struct it87_data *data = i2c_get_clientdata(client); - - if (i2c_is_isa_client(client)) { - mutex_lock(&data->lock); - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - outb_p(value, client->addr + IT87_DATA_REG_OFFSET); - mutex_unlock(&data->lock); - return 0; - } else - return i2c_smbus_write_byte_data(client, reg, value); + outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); + outb_p(value, client->addr + IT87_DATA_REG_OFFSET); } /* Return 1 if and only if the PWM interface is safe to use */ @@ -1404,6 +1353,7 @@ static struct it87_data *it87_update_device(struct device *dev) (it87_read_value(client, IT87_REG_ALARM2) << 8) | (it87_read_value(client, IT87_REG_ALARM3) << 16); data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); + data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); /* The 8705 does not have VID capability */ @@ -1426,26 +1376,14 @@ static int __init sm_it87_init(void) { int res; - res = i2c_add_driver(&it87_driver); - if (res) + if ((res = it87_find(&isa_address))) return res; - - if (!it87_find(&isa_address)) { - res = i2c_isa_add_driver(&it87_isa_driver); - if (res) { - i2c_del_driver(&it87_driver); - return res; - } - } - - return 0; + return i2c_isa_add_driver(&it87_isa_driver); } static void __exit sm_it87_exit(void) { - if (isa_address) - i2c_isa_del_driver(&it87_isa_driver); - i2c_del_driver(&it87_driver); + i2c_isa_del_driver(&it87_isa_driver); }