|
|
@@ -0,0 +1,106 @@
|
|
|
+From 6ce402327a6fb714a9f40a0bb59bcbfe383839a5 Mon Sep 17 00:00:00 2001
|
|
|
+From: Christian Marangi <[email protected]>
|
|
|
+Date: Tue, 4 Jun 2024 18:43:43 +0200
|
|
|
+Subject: [PATCH] hwmon: g672: add support for g761
|
|
|
+
|
|
|
+Add support for g761 PWM Fan Controller.
|
|
|
+
|
|
|
+The g761 is a copy of the g763 with the only difference of supporting
|
|
|
+and internal clock. The internal clock is used if no clocks property is
|
|
|
+defined in device node and in such case the required bit is enabled and
|
|
|
+clock handling is skipped.
|
|
|
+
|
|
|
+The internal clock oscillator runs at 31KHz.
|
|
|
+
|
|
|
+Signed-off-by: Christian Marangi <[email protected]>
|
|
|
+Link: https://lore.kernel.org/r/[email protected]
|
|
|
+Signed-off-by: Guenter Roeck <[email protected]>
|
|
|
+---
|
|
|
+ drivers/hwmon/g762.c | 33 ++++++++++++++++++++++++++++++---
|
|
|
+ 1 file changed, 30 insertions(+), 3 deletions(-)
|
|
|
+
|
|
|
+--- a/drivers/hwmon/g762.c
|
|
|
++++ b/drivers/hwmon/g762.c
|
|
|
+@@ -69,6 +69,7 @@ enum g762_regs {
|
|
|
+ #define G762_REG_FAN_CMD1_PWM_POLARITY 0x02 /* PWM polarity */
|
|
|
+ #define G762_REG_FAN_CMD1_PULSE_PER_REV 0x01 /* pulse per fan revolution */
|
|
|
+
|
|
|
++#define G761_REG_FAN_CMD2_FAN_CLOCK 0x20 /* choose internal clock*/
|
|
|
+ #define G762_REG_FAN_CMD2_GEAR_MODE_1 0x08 /* fan gear mode */
|
|
|
+ #define G762_REG_FAN_CMD2_GEAR_MODE_0 0x04
|
|
|
+ #define G762_REG_FAN_CMD2_FAN_STARTV_1 0x02 /* fan startup voltage */
|
|
|
+@@ -115,6 +116,7 @@ enum g762_regs {
|
|
|
+
|
|
|
+ struct g762_data {
|
|
|
+ struct i2c_client *client;
|
|
|
++ bool internal_clock;
|
|
|
+ struct clk *clk;
|
|
|
+
|
|
|
+ /* update mutex */
|
|
|
+@@ -566,6 +568,7 @@ static int do_set_fan_startv(struct devi
|
|
|
+
|
|
|
+ #ifdef CONFIG_OF
|
|
|
+ static const struct of_device_id g762_dt_match[] = {
|
|
|
++ { .compatible = "gmt,g761" },
|
|
|
+ { .compatible = "gmt,g762" },
|
|
|
+ { .compatible = "gmt,g763" },
|
|
|
+ { },
|
|
|
+@@ -597,6 +600,21 @@ static int g762_of_clock_enable(struct i
|
|
|
+ if (!client->dev.of_node)
|
|
|
+ return 0;
|
|
|
+
|
|
|
++ data = i2c_get_clientdata(client);
|
|
|
++
|
|
|
++ /*
|
|
|
++ * Skip CLK detection and handling if we use internal clock.
|
|
|
++ * This is only valid for g761.
|
|
|
++ */
|
|
|
++ data->internal_clock = of_device_is_compatible(client->dev.of_node,
|
|
|
++ "gmt,g761") &&
|
|
|
++ !of_property_present(client->dev.of_node,
|
|
|
++ "clocks");
|
|
|
++ if (data->internal_clock) {
|
|
|
++ do_set_clk_freq(&client->dev, 32768);
|
|
|
++ return 0;
|
|
|
++ }
|
|
|
++
|
|
|
+ clk = of_clk_get(client->dev.of_node, 0);
|
|
|
+ if (IS_ERR(clk)) {
|
|
|
+ dev_err(&client->dev, "failed to get clock\n");
|
|
|
+@@ -616,7 +634,6 @@ static int g762_of_clock_enable(struct i
|
|
|
+ goto clk_unprep;
|
|
|
+ }
|
|
|
+
|
|
|
+- data = i2c_get_clientdata(client);
|
|
|
+ data->clk = clk;
|
|
|
+
|
|
|
+ ret = devm_add_action(&client->dev, g762_of_clock_disable, data);
|
|
|
+@@ -1025,16 +1042,26 @@ ATTRIBUTE_GROUPS(g762);
|
|
|
+ static inline int g762_fan_init(struct device *dev)
|
|
|
+ {
|
|
|
+ struct g762_data *data = g762_update_client(dev);
|
|
|
++ int ret;
|
|
|
+
|
|
|
+ if (IS_ERR(data))
|
|
|
+ return PTR_ERR(data);
|
|
|
+
|
|
|
++ /* internal_clock can only be set with compatible g761 */
|
|
|
++ if (data->internal_clock)
|
|
|
++ data->fan_cmd2 |= G761_REG_FAN_CMD2_FAN_CLOCK;
|
|
|
++
|
|
|
+ data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_FAIL;
|
|
|
+ data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC;
|
|
|
+ data->valid = false;
|
|
|
+
|
|
|
+- return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
|
|
|
+- data->fan_cmd1);
|
|
|
++ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
|
|
|
++ data->fan_cmd1);
|
|
|
++ if (ret)
|
|
|
++ return ret;
|
|
|
++
|
|
|
++ return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
|
|
|
++ data->fan_cmd2);
|
|
|
+ }
|
|
|
+
|
|
|
+ static int g762_probe(struct i2c_client *client)
|