diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 12:58:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 12:58:10 -0400 |
| commit | 76c97e6c754885a3168becfa4a6aa47c7e8ea6a6 (patch) | |
| tree | c6a333a7f302fb648282243dd93783bb5c47517c /drivers | |
| parent | 8da8533dfb0929c5ea5d9fdf60ea6d3ffa02127d (diff) | |
| parent | 829917cd7246204d6c5f066c40b66d2b62d0930d (diff) | |
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon fixes from Guenter Roeck:
- Fix timing problems in applesmc driver
- Improve device removal in jc42 driver
- Fix build warning in acp_power_meter driver
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: (applesmc) Decode and act on read/write status codes
hwmon: (jc42) Don't reset hysteresis on device removal
hwmon: (jc42) Simplify hysteresis mask
hwmon: (acpi_power_meter) Fix build warning
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/hwmon/acpi_power_meter.c | 4 | ||||
| -rw-r--r-- | drivers/hwmon/applesmc.c | 70 | ||||
| -rw-r--r-- | drivers/hwmon/jc42.c | 26 |
3 files changed, 66 insertions, 34 deletions
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 563c02904ddf..23ab3c496b05 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c | |||
| @@ -927,6 +927,8 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type) | |||
| 927 | return 0; | 927 | return 0; |
| 928 | } | 928 | } |
| 929 | 929 | ||
| 930 | #ifdef CONFIG_PM_SLEEP | ||
| 931 | |||
| 930 | static int acpi_power_meter_resume(struct device *dev) | 932 | static int acpi_power_meter_resume(struct device *dev) |
| 931 | { | 933 | { |
| 932 | struct acpi_power_meter_resource *resource; | 934 | struct acpi_power_meter_resource *resource; |
| @@ -944,6 +946,8 @@ static int acpi_power_meter_resume(struct device *dev) | |||
| 944 | return 0; | 946 | return 0; |
| 945 | } | 947 | } |
| 946 | 948 | ||
| 949 | #endif /* CONFIG_PM_SLEEP */ | ||
| 950 | |||
| 947 | static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume); | 951 | static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume); |
| 948 | 952 | ||
| 949 | static struct acpi_driver acpi_power_meter_driver = { | 953 | static struct acpi_driver acpi_power_meter_driver = { |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 4d937a18fadb..282708860517 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -55,9 +55,9 @@ | |||
| 55 | 55 | ||
| 56 | /* wait up to 32 ms for a status change. */ | 56 | /* wait up to 32 ms for a status change. */ |
| 57 | #define APPLESMC_MIN_WAIT 0x0010 | 57 | #define APPLESMC_MIN_WAIT 0x0010 |
| 58 | #define APPLESMC_RETRY_WAIT 0x0100 | ||
| 58 | #define APPLESMC_MAX_WAIT 0x8000 | 59 | #define APPLESMC_MAX_WAIT 0x8000 |
| 59 | 60 | ||
| 60 | #define APPLESMC_STATUS_MASK 0x0f | ||
| 61 | #define APPLESMC_READ_CMD 0x10 | 61 | #define APPLESMC_READ_CMD 0x10 |
| 62 | #define APPLESMC_WRITE_CMD 0x11 | 62 | #define APPLESMC_WRITE_CMD 0x11 |
| 63 | #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 | 63 | #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 |
| @@ -162,51 +162,68 @@ static unsigned int key_at_index; | |||
| 162 | static struct workqueue_struct *applesmc_led_wq; | 162 | static struct workqueue_struct *applesmc_led_wq; |
| 163 | 163 | ||
| 164 | /* | 164 | /* |
| 165 | * __wait_status - Wait up to 32ms for the status port to get a certain value | 165 | * wait_read - Wait for a byte to appear on SMC port. Callers must |
| 166 | * (masked with 0x0f), returning zero if the value is obtained. Callers must | ||
| 167 | * hold applesmc_lock. | 166 | * hold applesmc_lock. |
| 168 | */ | 167 | */ |
| 169 | static int __wait_status(u8 val) | 168 | static int wait_read(void) |
| 170 | { | 169 | { |
| 170 | u8 status; | ||
| 171 | int us; | 171 | int us; |
| 172 | |||
| 173 | val = val & APPLESMC_STATUS_MASK; | ||
| 174 | |||
| 175 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { | 172 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { |
| 176 | udelay(us); | 173 | udelay(us); |
| 177 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) | 174 | status = inb(APPLESMC_CMD_PORT); |
| 175 | /* read: wait for smc to settle */ | ||
| 176 | if (status & 0x01) | ||
| 178 | return 0; | 177 | return 0; |
| 179 | } | 178 | } |
| 180 | 179 | ||
| 180 | pr_warn("wait_read() fail: 0x%02x\n", status); | ||
| 181 | return -EIO; | 181 | return -EIO; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | /* | 184 | /* |
| 185 | * special treatment of command port - on newer macbooks, it seems necessary | 185 | * send_byte - Write to SMC port, retrying when necessary. Callers |
| 186 | * to resend the command byte before polling the status again. Callers must | 186 | * must hold applesmc_lock. |
| 187 | * hold applesmc_lock. | ||
| 188 | */ | 187 | */ |
| 189 | static int send_command(u8 cmd) | 188 | static int send_byte(u8 cmd, u16 port) |
| 190 | { | 189 | { |
| 190 | u8 status; | ||
| 191 | int us; | 191 | int us; |
| 192 | |||
| 193 | outb(cmd, port); | ||
| 192 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { | 194 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { |
| 193 | outb(cmd, APPLESMC_CMD_PORT); | ||
| 194 | udelay(us); | 195 | udelay(us); |
| 195 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) | 196 | status = inb(APPLESMC_CMD_PORT); |
| 197 | /* write: wait for smc to settle */ | ||
| 198 | if (status & 0x02) | ||
| 199 | continue; | ||
| 200 | /* ready: cmd accepted, return */ | ||
| 201 | if (status & 0x04) | ||
| 196 | return 0; | 202 | return 0; |
| 203 | /* timeout: give up */ | ||
| 204 | if (us << 1 == APPLESMC_MAX_WAIT) | ||
| 205 | break; | ||
| 206 | /* busy: long wait and resend */ | ||
| 207 | udelay(APPLESMC_RETRY_WAIT); | ||
| 208 | outb(cmd, port); | ||
| 197 | } | 209 | } |
| 210 | |||
| 211 | pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status); | ||
| 198 | return -EIO; | 212 | return -EIO; |
| 199 | } | 213 | } |
| 200 | 214 | ||
| 215 | static int send_command(u8 cmd) | ||
| 216 | { | ||
| 217 | return send_byte(cmd, APPLESMC_CMD_PORT); | ||
| 218 | } | ||
| 219 | |||
| 201 | static int send_argument(const char *key) | 220 | static int send_argument(const char *key) |
| 202 | { | 221 | { |
| 203 | int i; | 222 | int i; |
| 204 | 223 | ||
| 205 | for (i = 0; i < 4; i++) { | 224 | for (i = 0; i < 4; i++) |
| 206 | outb(key[i], APPLESMC_DATA_PORT); | 225 | if (send_byte(key[i], APPLESMC_DATA_PORT)) |
| 207 | if (__wait_status(0x04)) | ||
| 208 | return -EIO; | 226 | return -EIO; |
| 209 | } | ||
| 210 | return 0; | 227 | return 0; |
| 211 | } | 228 | } |
| 212 | 229 | ||
| @@ -219,11 +236,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | |||
| 219 | return -EIO; | 236 | return -EIO; |
| 220 | } | 237 | } |
| 221 | 238 | ||
| 222 | outb(len, APPLESMC_DATA_PORT); | 239 | if (send_byte(len, APPLESMC_DATA_PORT)) { |
| 240 | pr_warn("%.4s: read len fail\n", key); | ||
| 241 | return -EIO; | ||
| 242 | } | ||
| 223 | 243 | ||
| 224 | for (i = 0; i < len; i++) { | 244 | for (i = 0; i < len; i++) { |
| 225 | if (__wait_status(0x05)) { | 245 | if (wait_read()) { |
| 226 | pr_warn("%.4s: read data fail\n", key); | 246 | pr_warn("%.4s: read data[%d] fail\n", key, i); |
| 227 | return -EIO; | 247 | return -EIO; |
| 228 | } | 248 | } |
| 229 | buffer[i] = inb(APPLESMC_DATA_PORT); | 249 | buffer[i] = inb(APPLESMC_DATA_PORT); |
| @@ -241,14 +261,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) | |||
| 241 | return -EIO; | 261 | return -EIO; |
| 242 | } | 262 | } |
| 243 | 263 | ||
| 244 | outb(len, APPLESMC_DATA_PORT); | 264 | if (send_byte(len, APPLESMC_DATA_PORT)) { |
| 265 | pr_warn("%.4s: write len fail\n", key); | ||
| 266 | return -EIO; | ||
| 267 | } | ||
| 245 | 268 | ||
| 246 | for (i = 0; i < len; i++) { | 269 | for (i = 0; i < len; i++) { |
| 247 | if (__wait_status(0x04)) { | 270 | if (send_byte(buffer[i], APPLESMC_DATA_PORT)) { |
| 248 | pr_warn("%s: write data fail\n", key); | 271 | pr_warn("%s: write data fail\n", key); |
| 249 | return -EIO; | 272 | return -EIO; |
| 250 | } | 273 | } |
| 251 | outb(buffer[i], APPLESMC_DATA_PORT); | ||
| 252 | } | 274 | } |
| 253 | 275 | ||
| 254 | return 0; | 276 | return 0; |
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index e72ba5d2a824..e21e43c13156 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c | |||
| @@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = { | |||
| 57 | #define JC42_CFG_EVENT_LOCK (1 << 7) | 57 | #define JC42_CFG_EVENT_LOCK (1 << 7) |
| 58 | #define JC42_CFG_SHUTDOWN (1 << 8) | 58 | #define JC42_CFG_SHUTDOWN (1 << 8) |
| 59 | #define JC42_CFG_HYST_SHIFT 9 | 59 | #define JC42_CFG_HYST_SHIFT 9 |
| 60 | #define JC42_CFG_HYST_MASK 0x03 | 60 | #define JC42_CFG_HYST_MASK (0x03 << 9) |
| 61 | 61 | ||
| 62 | /* Capabilities */ | 62 | /* Capabilities */ |
| 63 | #define JC42_CAP_RANGE (1 << 2) | 63 | #define JC42_CAP_RANGE (1 << 2) |
| @@ -287,8 +287,8 @@ static ssize_t show_temp_crit_hyst(struct device *dev, | |||
| 287 | return PTR_ERR(data); | 287 | return PTR_ERR(data); |
| 288 | 288 | ||
| 289 | temp = jc42_temp_from_reg(data->temp_crit); | 289 | temp = jc42_temp_from_reg(data->temp_crit); |
| 290 | hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) | 290 | hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) |
| 291 | & JC42_CFG_HYST_MASK]; | 291 | >> JC42_CFG_HYST_SHIFT]; |
| 292 | return sprintf(buf, "%d\n", temp - hyst); | 292 | return sprintf(buf, "%d\n", temp - hyst); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| @@ -302,8 +302,8 @@ static ssize_t show_temp_max_hyst(struct device *dev, | |||
| 302 | return PTR_ERR(data); | 302 | return PTR_ERR(data); |
| 303 | 303 | ||
| 304 | temp = jc42_temp_from_reg(data->temp_max); | 304 | temp = jc42_temp_from_reg(data->temp_max); |
| 305 | hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) | 305 | hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) |
| 306 | & JC42_CFG_HYST_MASK]; | 306 | >> JC42_CFG_HYST_SHIFT]; |
| 307 | return sprintf(buf, "%d\n", temp - hyst); | 307 | return sprintf(buf, "%d\n", temp - hyst); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| @@ -362,8 +362,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev, | |||
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | mutex_lock(&data->update_lock); | 364 | mutex_lock(&data->update_lock); |
| 365 | data->config = (data->config | 365 | data->config = (data->config & ~JC42_CFG_HYST_MASK) |
| 366 | & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT)) | ||
| 367 | | (hyst << JC42_CFG_HYST_SHIFT); | 366 | | (hyst << JC42_CFG_HYST_SHIFT); |
| 368 | err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, | 367 | err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, |
| 369 | data->config); | 368 | data->config); |
| @@ -535,9 +534,16 @@ static int jc42_remove(struct i2c_client *client) | |||
| 535 | struct jc42_data *data = i2c_get_clientdata(client); | 534 | struct jc42_data *data = i2c_get_clientdata(client); |
| 536 | hwmon_device_unregister(data->hwmon_dev); | 535 | hwmon_device_unregister(data->hwmon_dev); |
| 537 | sysfs_remove_group(&client->dev.kobj, &jc42_group); | 536 | sysfs_remove_group(&client->dev.kobj, &jc42_group); |
| 538 | if (data->config != data->orig_config) | 537 | |
| 539 | i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, | 538 | /* Restore original configuration except hysteresis */ |
| 540 | data->orig_config); | 539 | if ((data->config & ~JC42_CFG_HYST_MASK) != |
| 540 | (data->orig_config & ~JC42_CFG_HYST_MASK)) { | ||
| 541 | int config; | ||
| 542 | |||
| 543 | config = (data->orig_config & ~JC42_CFG_HYST_MASK) | ||
| 544 | | (data->config & JC42_CFG_HYST_MASK); | ||
| 545 | i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); | ||
| 546 | } | ||
| 541 | return 0; | 547 | return 0; |
| 542 | } | 548 | } |
| 543 | 549 | ||
