lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <daa7571b0731e203b5a86e484da8083fd034601e.1735232354.git.tjakobi@math.uni-bielefeld.de>
Date: Thu, 26 Dec 2024 18:00:16 +0100
From: tjakobi@...h.uni-bielefeld.de
To: Derek John Clark <derekjohn.clark@...il.com>,
	Joaquín Ignacio Aramendía <samsagax@...il.com>,
	Jean Delvare <jdelvare@...e.com>,
	Guenter Roeck <linux@...ck-us.net>
Cc: Tobias Jakobi <tjakobi@...h.uni-bielefeld.de>,
	linux-hwmon@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH 1/4] hwmon: (oxp-sensors) Separate logic from device-specific data

From: Tobias Jakobi <tjakobi@...h.uni-bielefeld.de>

We currently have large switch-statements in all functions that
write to EC registers, even though the bulk of the supported
devices functions more or less the same.

Factor the device-specific data out into a struct oxp_config. This
only leaves logic in the corresponding functions and should make
adding future devices much easier and less error-prone.

Also introduce struct oxp_data which is going to be used in a
later commit to cache device state.

Signed-off-by: Tobias Jakobi <tjakobi@...h.uni-bielefeld.de>
---
 drivers/hwmon/oxp-sensors.c | 517 +++++++++++++++---------------------
 1 file changed, 215 insertions(+), 302 deletions(-)

diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c
index 83730d931824..fbd1463d1494 100644
--- a/drivers/hwmon/oxp-sensors.c
+++ b/drivers/hwmon/oxp-sensors.c
@@ -42,27 +42,6 @@ static bool unlock_global_acpi_lock(void)
 	return ACPI_SUCCESS(acpi_release_global_lock(oxp_mutex));
 }
 
-enum oxp_board {
-	aok_zoe_a1 = 1,
-	aya_neo_2,
-	aya_neo_air,
-	aya_neo_air_1s,
-	aya_neo_air_plus_mendo,
-	aya_neo_air_pro,
-	aya_neo_flip,
-	aya_neo_geek,
-	aya_neo_kun,
-	orange_pi_neo,
-	oxp_2,
-	oxp_fly,
-	oxp_mini_amd,
-	oxp_mini_amd_a07,
-	oxp_mini_amd_pro,
-	oxp_x1,
-};
-
-static enum oxp_board board;
-
 /* Fan reading and PWM */
 #define OXP_SENSOR_FAN_REG             0x76 /* Fan reading is 2 registers long */
 #define OXP_2_SENSOR_FAN_REG           0x58 /* Fan reading is 2 registers long */
@@ -89,125 +68,212 @@ static enum oxp_board board;
 
 #define OXP_TURBO_RETURN_VAL           0x00 /* Common return val */
 
+enum oxp_feature_bits {
+	OXP_FEATURE_SENSOR_FAN,
+	OXP_FEATURE_PWM,
+	OXP_FEATURE_TURBO,
+	OXP_FEATURE_ONLY_AMD,
+};
+
+struct oxp_config {
+	unsigned long features;
+
+	u8 sensor_pwm_enable_reg;
+	u8 sensor_pwm_reg;
+	u8 sensor_pwm_scale[2];
+	u8 sensor_fan_reg;
+
+	u8 turbo_switch_reg;
+	u8 turbo_enable_val;
+};
+
+struct oxp_data {
+	struct device *hwmon_dev;
+	const struct oxp_config *config;
+};
+
+static const struct oxp_config config_oxp = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM),
+
+	.sensor_pwm_enable_reg = OXP_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = OXP_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {0, 100},
+	.sensor_fan_reg = OXP_SENSOR_FAN_REG,
+};
+
+static const struct oxp_config config_mini_amd = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM) | BIT(OXP_FEATURE_ONLY_AMD),
+
+	.sensor_pwm_enable_reg = OXP_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = OXP_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {0, 100},
+	.sensor_fan_reg = OXP_SENSOR_FAN_REG,
+};
+
+static const struct oxp_config config_mini_amd_a07 = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM) | BIT(OXP_FEATURE_TURBO),
+
+	.sensor_pwm_enable_reg = OXP_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = OXP_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {0, 100},
+	.sensor_fan_reg = OXP_SENSOR_FAN_REG,
+
+	.turbo_switch_reg = OXP_MINI_TURBO_SWITCH_REG,
+	.turbo_enable_val = OXP_MINI_TURBO_TAKE_VAL,
+};
+
+static const struct oxp_config config_oxp2_turbo = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM) | BIT(OXP_FEATURE_TURBO),
+
+	.sensor_pwm_enable_reg = OXP_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = OXP_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {0, 184},
+	.sensor_fan_reg = OXP_2_SENSOR_FAN_REG,
+
+	.turbo_switch_reg = OXP_2_TURBO_SWITCH_REG,
+	.turbo_enable_val = OXP_TURBO_TAKE_VAL,
+};
+
+static const struct oxp_config config_orange = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM),
+
+	.sensor_pwm_enable_reg = ORANGEPI_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = ORANGEPI_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {1, 244},
+	.sensor_fan_reg = ORANGEPI_SENSOR_FAN_REG,
+};
+
+static const struct oxp_config config_aok_zoe = {
+	.features = BIT(OXP_FEATURE_SENSOR_FAN) | BIT(OXP_FEATURE_PWM) | BIT(OXP_FEATURE_TURBO),
+
+	.sensor_pwm_enable_reg = OXP_SENSOR_PWM_ENABLE_REG,
+	.sensor_pwm_reg = OXP_SENSOR_PWM_REG,
+	.sensor_pwm_scale = {0, 255},
+	.sensor_fan_reg = OXP_SENSOR_FAN_REG,
+
+	.turbo_switch_reg = OXP_TURBO_SWITCH_REG,
+	.turbo_enable_val = OXP_TURBO_TAKE_VAL,
+};
+
 static const struct dmi_system_id dmi_table[] = {
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 AR07"),
 		},
-		.driver_data = (void *)aok_zoe_a1,
+		.driver_data = (void *)&config_aok_zoe,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 Pro"),
 		},
-		.driver_data = (void *)aok_zoe_a1,
+		.driver_data = (void *)&config_aok_zoe,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_MATCH(DMI_BOARD_NAME, "AYANEO 2"),
 		},
-		.driver_data = (void *)aya_neo_2,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR"),
 		},
-		.driver_data = (void *)aya_neo_air,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR 1S"),
 		},
-		.driver_data = (void *)aya_neo_air_1s,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AB05-Mendocino"),
 		},
-		.driver_data = (void *)aya_neo_air_plus_mendo,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR Pro"),
 		},
-		.driver_data = (void *)aya_neo_air_pro,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_MATCH(DMI_BOARD_NAME, "FLIP"),
 		},
-		.driver_data = (void *)aya_neo_flip,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_MATCH(DMI_BOARD_NAME, "GEEK"),
 		},
-		.driver_data = (void *)aya_neo_geek,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "KUN"),
 		},
-		.driver_data = (void *)aya_neo_kun,
+		.driver_data = (void *)&config_oxp,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "OrangePi"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "NEO-01"),
 		},
-		.driver_data = (void *)orange_pi_neo,
+		.driver_data = (void *)&config_orange,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONE XPLAYER"),
 		},
-		.driver_data = (void *)oxp_mini_amd,
+		.driver_data = (void *)&config_mini_amd,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_MATCH(DMI_BOARD_NAME, "ONEXPLAYER 2"),
 		},
-		.driver_data = (void *)oxp_2,
+		.driver_data = (void *)&config_oxp2_turbo,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER F1"),
 		},
-		.driver_data = (void *)oxp_fly,
+		.driver_data = (void *)&config_aok_zoe,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER mini A07"),
 		},
-		.driver_data = (void *)oxp_mini_amd_a07,
+		.driver_data = (void *)&config_mini_amd_a07,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER Mini Pro"),
 		},
-		.driver_data = (void *)oxp_mini_amd_pro,
+		.driver_data = (void *)&config_aok_zoe,
 	},
 	{
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
 			DMI_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1"),
 		},
-		.driver_data = (void *)oxp_x1,
+		.driver_data = (void *)&config_oxp2_turbo,
 	},
 	{},
 };
@@ -252,83 +318,59 @@ static int write_to_ec(u8 reg, u8 value)
 	return ret;
 }
 
-/* Turbo button toggle functions */
-static int tt_toggle_enable(void)
+/* Rescale a (HW) sensor PWM value to userspace range. */
+static long rescale_sensor_pwm_to_user(const struct oxp_config *config, long val)
 {
-	u8 reg;
-	u8 val;
+	const long range = config->sensor_pwm_scale[1] - config->sensor_pwm_scale[0];
 
-	switch (board) {
-	case oxp_mini_amd_a07:
-		reg = OXP_MINI_TURBO_SWITCH_REG;
-		val = OXP_MINI_TURBO_TAKE_VAL;
-		break;
-	case aok_zoe_a1:
-	case oxp_fly:
-	case oxp_mini_amd_pro:
-		reg = OXP_TURBO_SWITCH_REG;
-		val = OXP_TURBO_TAKE_VAL;
-		break;
-	case oxp_2:
-	case oxp_x1:
-		reg = OXP_2_TURBO_SWITCH_REG;
-		val = OXP_TURBO_TAKE_VAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return write_to_ec(reg, val);
+	if (range == 255)
+		return val;
+
+	return ((val - config->sensor_pwm_scale[0]) * 255) / range;
 }
 
-static int tt_toggle_disable(void)
+/* Rescale a (userspace) sensor PWM value to hw range. */
+static long rescale_sensor_pwm_to_hw(const struct oxp_config *config, long val)
 {
-	u8 reg;
-	u8 val;
+	const long range = config->sensor_pwm_scale[1] - config->sensor_pwm_scale[0];
 
-	switch (board) {
-	case oxp_mini_amd_a07:
-		reg = OXP_MINI_TURBO_SWITCH_REG;
-		val = OXP_TURBO_RETURN_VAL;
-		break;
-	case aok_zoe_a1:
-	case oxp_fly:
-	case oxp_mini_amd_pro:
-		reg = OXP_TURBO_SWITCH_REG;
-		val = OXP_TURBO_RETURN_VAL;
-		break;
-	case oxp_2:
-	case oxp_x1:
-		reg = OXP_2_TURBO_SWITCH_REG;
-		val = OXP_TURBO_RETURN_VAL;
-		break;
-	default:
+	if (range == 255)
+		return val;
+
+	return config->sensor_pwm_scale[0] + (val * range) / 255;
+}
+
+/* Turbo button toggle functions */
+static int tt_toggle_enable(const struct oxp_config *config)
+{
+	if (!test_bit(OXP_FEATURE_TURBO, &config->features))
 		return -EINVAL;
-	}
-	return write_to_ec(reg, val);
+
+	return write_to_ec(config->turbo_switch_reg, config->turbo_enable_val);
+}
+
+static int tt_toggle_disable(const struct oxp_config *config)
+{
+	if (!test_bit(OXP_FEATURE_TURBO, &config->features))
+		return -EINVAL;
+
+	return write_to_ec(config->turbo_switch_reg, OXP_TURBO_RETURN_VAL);
 }
 
 /* Callbacks for turbo toggle attribute */
 static umode_t tt_toggle_is_visible(struct kobject *kobj,
 				    struct attribute *attr, int n)
 {
-	switch (board) {
-	case aok_zoe_a1:
-	case oxp_2:
-	case oxp_fly:
-	case oxp_mini_amd_a07:
-	case oxp_mini_amd_pro:
-	case oxp_x1:
-		return attr->mode;
-	default:
-		break;
-	}
-	return 0;
+	return attr->mode;
 }
 
 static ssize_t tt_toggle_store(struct device *dev,
 			       struct device_attribute *attr, const char *buf,
 			       size_t count)
 {
+	struct oxp_data *data = dev_get_drvdata(dev);
+	const struct oxp_config *config = data->config;
+
 	int rval;
 	bool value;
 
@@ -337,9 +379,9 @@ static ssize_t tt_toggle_store(struct device *dev,
 		return rval;
 
 	if (value) {
-		rval = tt_toggle_enable();
+		rval = tt_toggle_enable(config);
 	} else {
-		rval = tt_toggle_disable();
+		rval = tt_toggle_disable(config);
 	}
 	if (rval)
 		return rval;
@@ -350,28 +392,15 @@ static ssize_t tt_toggle_store(struct device *dev,
 static ssize_t tt_toggle_show(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
+	struct oxp_data *data = dev_get_drvdata(dev);
+	const struct oxp_config *config = data->config;
 	int retval;
-	u8 reg;
 	long val;
 
-	switch (board) {
-	case oxp_mini_amd_a07:
-		reg = OXP_MINI_TURBO_SWITCH_REG;
-		break;
-	case aok_zoe_a1:
-	case oxp_fly:
-	case oxp_mini_amd_pro:
-		reg = OXP_TURBO_SWITCH_REG;
-		break;
-	case oxp_2:
-	case oxp_x1:
-		reg = OXP_2_TURBO_SWITCH_REG;
-		break;
-	default:
+	if (!test_bit(OXP_FEATURE_TURBO, &config->features))
 		return -EINVAL;
-	}
 
-	retval = read_from_ec(reg, 1, &val);
+	retval = read_from_ec(config->turbo_switch_reg, 1, &val);
 	if (retval)
 		return retval;
 
@@ -381,55 +410,20 @@ static ssize_t tt_toggle_show(struct device *dev,
 static DEVICE_ATTR_RW(tt_toggle);
 
 /* PWM enable/disable functions */
-static int oxp_pwm_enable(void)
+static int oxp_pwm_enable(const struct oxp_config *config)
 {
-	switch (board) {
-	case orange_pi_neo:
-		return write_to_ec(ORANGEPI_SENSOR_PWM_ENABLE_REG, PWM_MODE_MANUAL);
-	case aok_zoe_a1:
-	case aya_neo_2:
-	case aya_neo_air:
-	case aya_neo_air_plus_mendo:
-	case aya_neo_air_pro:
-	case aya_neo_flip:
-	case aya_neo_geek:
-	case aya_neo_kun:
-	case oxp_2:
-	case oxp_fly:
-	case oxp_mini_amd:
-	case oxp_mini_amd_a07:
-	case oxp_mini_amd_pro:
-	case oxp_x1:
-		return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_MANUAL);
-	default:
-		return -EINVAL;
-	}
+	if (test_bit(OXP_FEATURE_PWM, &config->features))
+		return write_to_ec(config->sensor_pwm_enable_reg, PWM_MODE_MANUAL);
+
+	return -EINVAL;
 }
 
-static int oxp_pwm_disable(void)
+static int oxp_pwm_disable(const struct oxp_config *config)
 {
-	switch (board) {
-	case orange_pi_neo:
-		return write_to_ec(ORANGEPI_SENSOR_PWM_ENABLE_REG, PWM_MODE_AUTO);
-	case aok_zoe_a1:
-	case aya_neo_2:
-	case aya_neo_air:
-	case aya_neo_air_1s:
-	case aya_neo_air_plus_mendo:
-	case aya_neo_air_pro:
-	case aya_neo_flip:
-	case aya_neo_geek:
-	case aya_neo_kun:
-	case oxp_2:
-	case oxp_fly:
-	case oxp_mini_amd:
-	case oxp_mini_amd_a07:
-	case oxp_mini_amd_pro:
-	case oxp_x1:
-		return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_AUTO);
-	default:
-		return -EINVAL;
-	}
+	if (test_bit(OXP_FEATURE_PWM, &config->features))
+		return write_to_ec(config->sensor_pwm_enable_reg, PWM_MODE_AUTO);
+
+	return -EINVAL;
 }
 
 /* Callbacks for hwmon interface */
@@ -449,108 +443,33 @@ static umode_t oxp_ec_hwmon_is_visible(const void *drvdata,
 static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type,
 			     u32 attr, int channel, long *val)
 {
-	int ret;
+	struct oxp_data *data = dev_get_drvdata(dev);
+	const struct oxp_config *config = data->config;
 
 	switch (type) {
 	case hwmon_fan:
-		switch (attr) {
-		case hwmon_fan_input:
-			switch (board) {
-			case orange_pi_neo:
-				return read_from_ec(ORANGEPI_SENSOR_FAN_REG, 2, val);
-			case oxp_2:
-			case oxp_x1:
-				return read_from_ec(OXP_2_SENSOR_FAN_REG, 2, val);
-			case aok_zoe_a1:
-			case aya_neo_2:
-			case aya_neo_air:
-			case aya_neo_air_1s:
-			case aya_neo_air_plus_mendo:
-			case aya_neo_air_pro:
-			case aya_neo_flip:
-			case aya_neo_geek:
-			case aya_neo_kun:
-			case oxp_fly:
-			case oxp_mini_amd:
-			case oxp_mini_amd_a07:
-			case oxp_mini_amd_pro:
-				return read_from_ec(OXP_SENSOR_FAN_REG, 2, val);
-			default:
-				break;
-			}
-			break;
-		default:
-			break;
-		}
+		if (attr == hwmon_fan_input && test_bit(OXP_FEATURE_SENSOR_FAN, &config->features))
+			return read_from_ec(config->sensor_fan_reg, 2, val);
 		break;
 	case hwmon_pwm:
 		switch (attr) {
 		case hwmon_pwm_input:
-			switch (board) {
-			case orange_pi_neo:
-				ret = read_from_ec(ORANGEPI_SENSOR_PWM_REG, 1, val);
-				if (ret)
-					return ret;
-				/* scale from range [1-244] */
-				*val = ((*val - 1) * 254 / 243) + 1;
-				break;
-			case oxp_2:
-			case oxp_x1:
-				ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val);
-				if (ret)
-					return ret;
-				/* scale from range [0-184] */
-				*val = (*val * 255) / 184;
-				break;
-			case aya_neo_2:
-			case aya_neo_air:
-			case aya_neo_air_1s:
-			case aya_neo_air_plus_mendo:
-			case aya_neo_air_pro:
-			case aya_neo_flip:
-			case aya_neo_geek:
-			case aya_neo_kun:
-			case oxp_mini_amd:
-			case oxp_mini_amd_a07:
-				ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val);
-				if (ret)
-					return ret;
-				/* scale from range [0-100] */
-				*val = (*val * 255) / 100;
-				break;
-			case aok_zoe_a1:
-			case oxp_fly:
-			case oxp_mini_amd_pro:
-			default:
-				ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val);
+			if (test_bit(OXP_FEATURE_PWM, &config->features)) {
+				int ret;
+				long tmp;
+
+				ret = read_from_ec(config->sensor_pwm_reg, 1, &tmp);
 				if (ret)
 					return ret;
-				break;
+
+				*val = rescale_sensor_pwm_to_user(config, tmp);
+
+				return 0;
 			}
-			return 0;
+			break;
 		case hwmon_pwm_enable:
-			switch (board) {
-			case orange_pi_neo:
-				return read_from_ec(ORANGEPI_SENSOR_PWM_ENABLE_REG, 1, val);
-			case aok_zoe_a1:
-			case aya_neo_2:
-			case aya_neo_air:
-			case aya_neo_air_1s:
-			case aya_neo_air_plus_mendo:
-			case aya_neo_air_pro:
-			case aya_neo_flip:
-			case aya_neo_geek:
-			case aya_neo_kun:
-			case oxp_2:
-			case oxp_fly:
-			case oxp_mini_amd:
-			case oxp_mini_amd_a07:
-			case oxp_mini_amd_pro:
-			case oxp_x1:
-				return read_from_ec(OXP_SENSOR_PWM_ENABLE_REG, 1, val);
-			default:
-				break;
-			}
+			if (test_bit(OXP_FEATURE_PWM, &config->features))
+				return read_from_ec(config->sensor_pwm_enable_reg, 1, val);
 			break;
 		default:
 			break;
@@ -559,53 +478,32 @@ static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type,
 	default:
 		break;
 	}
+
 	return -EOPNOTSUPP;
 }
 
 static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type,
 			      u32 attr, int channel, long val)
 {
+	struct oxp_data *data = dev_get_drvdata(dev);
+	const struct oxp_config *config = data->config;
+
 	switch (type) {
 	case hwmon_pwm:
 		switch (attr) {
 		case hwmon_pwm_enable:
 			if (val == 1)
-				return oxp_pwm_enable();
+				return oxp_pwm_enable(config);
 			else if (val == 0)
-				return oxp_pwm_disable();
+				return oxp_pwm_disable(config);
 			return -EINVAL;
 		case hwmon_pwm_input:
 			if (val < 0 || val > 255)
 				return -EINVAL;
-			switch (board) {
-			case orange_pi_neo:
-				/* scale to range [1-244] */
-				val = ((val - 1) * 243 / 254) + 1;
-				return write_to_ec(ORANGEPI_SENSOR_PWM_REG, val);
-			case oxp_2:
-			case oxp_x1:
-				/* scale to range [0-184] */
-				val = (val * 184) / 255;
-				return write_to_ec(OXP_SENSOR_PWM_REG, val);
-			case aya_neo_2:
-			case aya_neo_air:
-			case aya_neo_air_1s:
-			case aya_neo_air_plus_mendo:
-			case aya_neo_air_pro:
-			case aya_neo_flip:
-			case aya_neo_geek:
-			case aya_neo_kun:
-			case oxp_mini_amd:
-			case oxp_mini_amd_a07:
-				/* scale to range [0-100] */
-				val = (val * 100) / 255;
-				return write_to_ec(OXP_SENSOR_PWM_REG, val);
-			case aok_zoe_a1:
-			case oxp_fly:
-			case oxp_mini_amd_pro:
-				return write_to_ec(OXP_SENSOR_PWM_REG, val);
-			default:
-				break;
+			if (test_bit(OXP_FEATURE_PWM, &config->features)) {
+				const long hw_val = rescale_sensor_pwm_to_hw(config, val);
+
+				return write_to_ec(config->sensor_pwm_reg, hw_val);
 			}
 			break;
 		default:
@@ -657,12 +555,43 @@ static const struct hwmon_chip_info oxp_ec_chip_info = {
 static int oxp_platform_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device *hwdev;
+	struct oxp_data *data;
 
-	hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
-						     &oxp_ec_chip_info, NULL);
+	const struct dmi_system_id *dmi_entry;
+	const struct oxp_config *config;
 
-	return PTR_ERR_OR_ZERO(hwdev);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	dmi_entry = dmi_first_match(dmi_table);
+	if (!dmi_entry)
+		return -ENODEV;
+
+	config = dmi_entry->driver_data;
+
+	/*
+	 * Have to check for AMD processor here because DMI strings are the same
+	 * between Intel and AMD boards on older OneXPlayer devices, the only way
+	 * to tell them apart is the CPU. Old Intel boards have an unsupported EC.
+	 */
+	if (test_bit(OXP_FEATURE_ONLY_AMD, &config->features) &&
+	    boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return -ENODEV;
+
+	/* If we lack the turbo feature, don't expose the turbo toggle attribute. */
+	if (!test_bit(OXP_FEATURE_TURBO, &config->features))
+		dev_attr_tt_toggle.attr.mode = 0;
+
+	data->config = config;
+	data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "oxpec", data,
+							       &oxp_ec_chip_info, NULL);
+	if (IS_ERR(data->hwmon_dev))
+		return PTR_ERR(data->hwmon_dev);
+
+	platform_set_drvdata(pdev, data);
+
+	return 0;
 }
 
 static struct platform_driver oxp_platform_driver = {
@@ -677,22 +606,6 @@ static struct platform_device *oxp_platform_device;
 
 static int __init oxp_platform_init(void)
 {
-	const struct dmi_system_id *dmi_entry;
-
-	dmi_entry = dmi_first_match(dmi_table);
-	if (!dmi_entry)
-		return -ENODEV;
-
-	board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
-
-	/*
-	 * Have to check for AMD processor here because DMI strings are the same
-	 * between Intel and AMD boards on older OneXPlayer devices, the only way
-	 * to tell them apart is the CPU. Old Intel boards have an unsupported EC.
-	 */
-	if (board == oxp_mini_amd && boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-		return -ENODEV;
-
 	oxp_platform_device =
 		platform_create_bundle(&oxp_platform_driver,
 				       oxp_platform_probe, NULL, 0, NULL, 0);
-- 
2.45.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ