Fix timing problems in applesmc driver
Improve device removal in jc42 driver Fix build warning in acp_power_meter driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQFEikAAoJEMsfJm/On5mBZzMP/jMKhWUn+4p1a17NDj5hpdIF btCrsJvGN2ZyzzwzeB+3ymjDK83//yahH0heQFGhrhnIwFuevPX9wVmfU3roj20u Wpsc/9t1cBL17V0SDQ00lUAOcTRqinT7CHBPGExZLiwWZMNUF+SD/l5QEu64Oqav uFkF/a2yl6MullsOQfEVd2gziNI3GMf0mIXrvhN91qxCvCjBI+bzlIQuHU1nQfJG dX1zDdfKX9uXwtOOa2fTEpk8QXRduBa6v6hvW/jkW0OV6t4sLeM/iPIqH00I/Vq1 SpO08R5dsjqBpCwp8zVKKfQQgRSJfilmJHH3bCTwx6NIPWEYY7ZHUMhrRJUQxGch okj0yVTGbcD8yr46HfauoNFpthp/AY9FFwwGBpObaS24SiUWySKxQS3lR7Wh7gfI tmNpejoU8eVhgtlN4TBPGQhFsiXewCDkuwd9ocoFJ3jvVggN6wP0ioAn7eFYBQJ3 3Glp3ocSvY1VfJw2qJVRmsUroMNin12ORGrVeaprTPobFNN4FqSiPEcqAqitOS5T iFULihzrLz0eXuiQoispvI7gUnI7/NQZF/6L5UGadAX7kfKS9U40XdC5dp+H5FOx GR6RWqIASMAwKK+PHxjAZ0jnDQvFWM85QEZsnLwAT6zmlDgIGjgQsxUqqwOu281S xo8kV9ljhSYFD18q6lzv =nt8q -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
76c97e6c75
|
@ -927,6 +927,8 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
|
||||||
static int acpi_power_meter_resume(struct device *dev)
|
static int acpi_power_meter_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct acpi_power_meter_resource *resource;
|
struct acpi_power_meter_resource *resource;
|
||||||
|
@ -944,6 +946,8 @@ static int acpi_power_meter_resume(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);
|
static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);
|
||||||
|
|
||||||
static struct acpi_driver acpi_power_meter_driver = {
|
static struct acpi_driver acpi_power_meter_driver = {
|
||||||
|
|
|
@ -55,9 +55,9 @@
|
||||||
|
|
||||||
/* wait up to 32 ms for a status change. */
|
/* wait up to 32 ms for a status change. */
|
||||||
#define APPLESMC_MIN_WAIT 0x0010
|
#define APPLESMC_MIN_WAIT 0x0010
|
||||||
|
#define APPLESMC_RETRY_WAIT 0x0100
|
||||||
#define APPLESMC_MAX_WAIT 0x8000
|
#define APPLESMC_MAX_WAIT 0x8000
|
||||||
|
|
||||||
#define APPLESMC_STATUS_MASK 0x0f
|
|
||||||
#define APPLESMC_READ_CMD 0x10
|
#define APPLESMC_READ_CMD 0x10
|
||||||
#define APPLESMC_WRITE_CMD 0x11
|
#define APPLESMC_WRITE_CMD 0x11
|
||||||
#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
|
#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
|
||||||
|
@ -162,51 +162,68 @@ static unsigned int key_at_index;
|
||||||
static struct workqueue_struct *applesmc_led_wq;
|
static struct workqueue_struct *applesmc_led_wq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __wait_status - Wait up to 32ms for the status port to get a certain value
|
* wait_read - Wait for a byte to appear on SMC port. Callers must
|
||||||
* (masked with 0x0f), returning zero if the value is obtained. Callers must
|
|
||||||
* hold applesmc_lock.
|
* hold applesmc_lock.
|
||||||
*/
|
*/
|
||||||
static int __wait_status(u8 val)
|
static int wait_read(void)
|
||||||
{
|
{
|
||||||
|
u8 status;
|
||||||
int us;
|
int us;
|
||||||
|
|
||||||
val = val & APPLESMC_STATUS_MASK;
|
|
||||||
|
|
||||||
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
||||||
udelay(us);
|
udelay(us);
|
||||||
if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val)
|
status = inb(APPLESMC_CMD_PORT);
|
||||||
|
/* read: wait for smc to settle */
|
||||||
|
if (status & 0x01)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pr_warn("wait_read() fail: 0x%02x\n", status);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* special treatment of command port - on newer macbooks, it seems necessary
|
* send_byte - Write to SMC port, retrying when necessary. Callers
|
||||||
* to resend the command byte before polling the status again. Callers must
|
* must hold applesmc_lock.
|
||||||
* hold applesmc_lock.
|
|
||||||
*/
|
*/
|
||||||
|
static int send_byte(u8 cmd, u16 port)
|
||||||
|
{
|
||||||
|
u8 status;
|
||||||
|
int us;
|
||||||
|
|
||||||
|
outb(cmd, port);
|
||||||
|
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
||||||
|
udelay(us);
|
||||||
|
status = inb(APPLESMC_CMD_PORT);
|
||||||
|
/* write: wait for smc to settle */
|
||||||
|
if (status & 0x02)
|
||||||
|
continue;
|
||||||
|
/* ready: cmd accepted, return */
|
||||||
|
if (status & 0x04)
|
||||||
|
return 0;
|
||||||
|
/* timeout: give up */
|
||||||
|
if (us << 1 == APPLESMC_MAX_WAIT)
|
||||||
|
break;
|
||||||
|
/* busy: long wait and resend */
|
||||||
|
udelay(APPLESMC_RETRY_WAIT);
|
||||||
|
outb(cmd, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
static int send_command(u8 cmd)
|
static int send_command(u8 cmd)
|
||||||
{
|
{
|
||||||
int us;
|
return send_byte(cmd, APPLESMC_CMD_PORT);
|
||||||
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
|
||||||
outb(cmd, APPLESMC_CMD_PORT);
|
|
||||||
udelay(us);
|
|
||||||
if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_argument(const char *key)
|
static int send_argument(const char *key)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++)
|
||||||
outb(key[i], APPLESMC_DATA_PORT);
|
if (send_byte(key[i], APPLESMC_DATA_PORT))
|
||||||
if (__wait_status(0x04))
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,11 +236,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
outb(len, APPLESMC_DATA_PORT);
|
if (send_byte(len, APPLESMC_DATA_PORT)) {
|
||||||
|
pr_warn("%.4s: read len fail\n", key);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (__wait_status(0x05)) {
|
if (wait_read()) {
|
||||||
pr_warn("%.4s: read data fail\n", key);
|
pr_warn("%.4s: read data[%d] fail\n", key, i);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
buffer[i] = inb(APPLESMC_DATA_PORT);
|
buffer[i] = inb(APPLESMC_DATA_PORT);
|
||||||
|
@ -241,14 +261,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
outb(len, APPLESMC_DATA_PORT);
|
if (send_byte(len, APPLESMC_DATA_PORT)) {
|
||||||
|
pr_warn("%.4s: write len fail\n", key);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (__wait_status(0x04)) {
|
if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
|
||||||
pr_warn("%s: write data fail\n", key);
|
pr_warn("%s: write data fail\n", key);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
outb(buffer[i], APPLESMC_DATA_PORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = {
|
||||||
#define JC42_CFG_EVENT_LOCK (1 << 7)
|
#define JC42_CFG_EVENT_LOCK (1 << 7)
|
||||||
#define JC42_CFG_SHUTDOWN (1 << 8)
|
#define JC42_CFG_SHUTDOWN (1 << 8)
|
||||||
#define JC42_CFG_HYST_SHIFT 9
|
#define JC42_CFG_HYST_SHIFT 9
|
||||||
#define JC42_CFG_HYST_MASK 0x03
|
#define JC42_CFG_HYST_MASK (0x03 << 9)
|
||||||
|
|
||||||
/* Capabilities */
|
/* Capabilities */
|
||||||
#define JC42_CAP_RANGE (1 << 2)
|
#define JC42_CAP_RANGE (1 << 2)
|
||||||
|
@ -287,8 +287,8 @@ static ssize_t show_temp_crit_hyst(struct device *dev,
|
||||||
return PTR_ERR(data);
|
return PTR_ERR(data);
|
||||||
|
|
||||||
temp = jc42_temp_from_reg(data->temp_crit);
|
temp = jc42_temp_from_reg(data->temp_crit);
|
||||||
hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
|
hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
|
||||||
& JC42_CFG_HYST_MASK];
|
>> JC42_CFG_HYST_SHIFT];
|
||||||
return sprintf(buf, "%d\n", temp - hyst);
|
return sprintf(buf, "%d\n", temp - hyst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,8 +302,8 @@ static ssize_t show_temp_max_hyst(struct device *dev,
|
||||||
return PTR_ERR(data);
|
return PTR_ERR(data);
|
||||||
|
|
||||||
temp = jc42_temp_from_reg(data->temp_max);
|
temp = jc42_temp_from_reg(data->temp_max);
|
||||||
hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
|
hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
|
||||||
& JC42_CFG_HYST_MASK];
|
>> JC42_CFG_HYST_SHIFT];
|
||||||
return sprintf(buf, "%d\n", temp - hyst);
|
return sprintf(buf, "%d\n", temp - hyst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,8 +362,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
data->config = (data->config
|
data->config = (data->config & ~JC42_CFG_HYST_MASK)
|
||||||
& ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
|
|
||||||
| (hyst << JC42_CFG_HYST_SHIFT);
|
| (hyst << JC42_CFG_HYST_SHIFT);
|
||||||
err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
|
err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
|
||||||
data->config);
|
data->config);
|
||||||
|
@ -535,9 +534,16 @@ static int jc42_remove(struct i2c_client *client)
|
||||||
struct jc42_data *data = i2c_get_clientdata(client);
|
struct jc42_data *data = i2c_get_clientdata(client);
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
sysfs_remove_group(&client->dev.kobj, &jc42_group);
|
sysfs_remove_group(&client->dev.kobj, &jc42_group);
|
||||||
if (data->config != data->orig_config)
|
|
||||||
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
|
/* Restore original configuration except hysteresis */
|
||||||
data->orig_config);
|
if ((data->config & ~JC42_CFG_HYST_MASK) !=
|
||||||
|
(data->orig_config & ~JC42_CFG_HYST_MASK)) {
|
||||||
|
int config;
|
||||||
|
|
||||||
|
config = (data->orig_config & ~JC42_CFG_HYST_MASK)
|
||||||
|
| (data->config & JC42_CFG_HYST_MASK);
|
||||||
|
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue