Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76c97e6c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 8da8533d 829917cd
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -927,6 +927,8 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type)
	return 0;
}

#ifdef CONFIG_PM_SLEEP

static int acpi_power_meter_resume(struct device *dev)
{
	struct acpi_power_meter_resource *resource;
@@ -944,6 +946,8 @@ static int acpi_power_meter_resume(struct device *dev)
	return 0;
}

#endif /* CONFIG_PM_SLEEP */

static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);

static struct acpi_driver acpi_power_meter_driver = {
+46 −24
Original line number Diff line number Diff line
@@ -55,9 +55,9 @@

/* wait up to 32 ms for a status change. */
#define APPLESMC_MIN_WAIT	0x0010
#define APPLESMC_RETRY_WAIT	0x0100
#define APPLESMC_MAX_WAIT	0x8000

#define APPLESMC_STATUS_MASK	0x0f
#define APPLESMC_READ_CMD	0x10
#define APPLESMC_WRITE_CMD	0x11
#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;

/*
 * __wait_status - Wait up to 32ms for the status port to get a certain value
 * (masked with 0x0f), returning zero if the value is obtained.  Callers must
 * wait_read - Wait for a byte to appear on SMC port. Callers must
 * hold applesmc_lock.
 */
static int __wait_status(u8 val)
static int wait_read(void)
{
	u8 status;
	int us;

	val = val & APPLESMC_STATUS_MASK;

	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
		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;
	}

	pr_warn("wait_read() fail: 0x%02x\n", status);
	return -EIO;
}

/*
 * special treatment of command port - on newer macbooks, it seems necessary
 * to resend the command byte before polling the status again. Callers must
 * hold applesmc_lock.
 * send_byte - Write to SMC port, retrying when necessary. Callers
 * must hold applesmc_lock.
 */
static int send_command(u8 cmd)
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) {
		outb(cmd, APPLESMC_CMD_PORT);
		udelay(us);
		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
		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)
{
	return send_byte(cmd, APPLESMC_CMD_PORT);
}

static int send_argument(const char *key)
{
	int i;

	for (i = 0; i < 4; i++) {
		outb(key[i], APPLESMC_DATA_PORT);
		if (__wait_status(0x04))
	for (i = 0; i < 4; i++)
		if (send_byte(key[i], APPLESMC_DATA_PORT))
			return -EIO;
	}
	return 0;
}

@@ -219,11 +236,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
		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++) {
		if (__wait_status(0x05)) {
			pr_warn("%.4s: read data fail\n", key);
		if (wait_read()) {
			pr_warn("%.4s: read data[%d] fail\n", key, i);
			return -EIO;
		}
		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;
	}

	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++) {
		if (__wait_status(0x04)) {
		if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
			pr_warn("%s: write data fail\n", key);
			return -EIO;
		}
		outb(buffer[i], APPLESMC_DATA_PORT);
	}

	return 0;
+16 −10
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = {
#define JC42_CFG_EVENT_LOCK	(1 << 7)
#define JC42_CFG_SHUTDOWN	(1 << 8)
#define JC42_CFG_HYST_SHIFT	9
#define JC42_CFG_HYST_MASK	0x03
#define JC42_CFG_HYST_MASK	(0x03 << 9)

/* Capabilities */
#define JC42_CAP_RANGE		(1 << 2)
@@ -287,8 +287,8 @@ static ssize_t show_temp_crit_hyst(struct device *dev,
		return PTR_ERR(data);

	temp = jc42_temp_from_reg(data->temp_crit);
	hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
			       & JC42_CFG_HYST_MASK];
	hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
			       >> JC42_CFG_HYST_SHIFT];
	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);

	temp = jc42_temp_from_reg(data->temp_max);
	hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
			       & JC42_CFG_HYST_MASK];
	hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
			       >> JC42_CFG_HYST_SHIFT];
	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);
	data->config = (data->config
			& ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
	data->config = (data->config & ~JC42_CFG_HYST_MASK)
	  | (hyst << JC42_CFG_HYST_SHIFT);
	err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
					   data->config);
@@ -535,9 +534,16 @@ static int jc42_remove(struct i2c_client *client)
	struct jc42_data *data = i2c_get_clientdata(client);
	hwmon_device_unregister(data->hwmon_dev);
	sysfs_remove_group(&client->dev.kobj, &jc42_group);
	if (data->config != data->orig_config)
		i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
					     data->orig_config);

	/* Restore original configuration except hysteresis */
	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;
}