linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add ASRock HDD Saver support
@ 2021-05-03 15:58 Paweł Marciniak
  2021-05-03 17:10 ` Guenter Roeck
  0 siblings, 1 reply; 2+ messages in thread
From: Paweł Marciniak @ 2021-05-03 15:58 UTC (permalink / raw)
  To: linux-hwmon, linux-kernel

Some of the asrock motherboards are equipped with hdd saver technology.
It is implemented via a special power connector on the motherboard and a corresponding custom made power cable with two SATA power ports.
The control is via the gpio10 pin of the nct6791d chip.
When this technology is available the module creates the hddsaver_enable file.
Reading the file returns the current status, while writing turns off or on the power of the SATA connectors.

Supported motheboards:
ASRock Z97 Extreme4 - works 100% tested.
ASRock Z97 Extreme6 - Based on boardview/schematic should works, not tested.
Other ASRock motherboards supporting this technology - status unknown.

Signed-off-by: Paweł Marciniak <sunwire@gmail.com>
---
  drivers/hwmon/nct6775.c | 80 +++++++++++++++++++++++++++++++++++++++++
  1 file changed, 80 insertions(+)

diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 5bd1562..17b70f3 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -110,6 +110,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing forfan RPM signal");
  #define NCT6775_LD_ACPI		0x0a
  #define NCT6775_LD_HWM		0x0b
  #define NCT6775_LD_VID		0x0d
+#define NCT6775_LD_GPIO_DATA		0x08
  #define NCT6775_LD_12		0x12

  #define SIO_REG_LDSEL		0x07	/* Logical device select */
@@ -229,6 +230,7 @@ static const u16 NCT6775_REG_IN[] = {
  #define NCT6775_REG_FANDIV2		0x507

  #define NCT6775_REG_CR_FAN_DEBOUNCE	0xf0
+#define NCT6775_REG_CR_GPIO1_DATA	0xf1

  static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };

@@ -1205,6 +1207,8 @@ struct nct6775_data {
  	u8 vrm;

  	bool have_vid;
+	bool have_hddsaver; /* True if hdd saver is supported */
+	bool hddsaver_status; /* True if enabled */

  	u16 have_temp;
  	u16 have_temp_fixed;
@@ -1987,6 +1991,48 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
  	return count;
  }

+static ssize_t
+show_hddsaver(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+
+	return sprintf(buf, "%s\n", (data->hddsaver_status ? "On" : "Off"));
+}
+
+static ssize_t
+store_hddsaver(struct device *dev, struct device_attribute *attr, const char *buf,
+	       size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	bool val;
+	int err, ret;
+	u8 tmp;
+
+	err = kstrtobool(buf, &val);
+	if (err == -EINVAL)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	ret = superio_enter(data->sioreg);
+	if (ret) {
+		count = ret;
+		goto error;
+	}
+
+	if (val != data->hddsaver_status) {
+		superio_select(data->sioreg, NCT6775_LD_GPIO_DATA); /* Logical Device 8 */
+		tmp = superio_inb(data->sioreg,
+				  NCT6775_REG_CR_GPIO1_DATA); /* GPIO1 date reg */
+		superio_outb(data->sioreg, NCT6775_REG_CR_GPIO1_DATA, tmp ^ (1<<0));
+		data->hddsaver_status = val;
+		pr_info("HDD Saver is %s\n", val ? "On" : "Off");
+	}
+	superio_exit(data->sioreg);
+error:
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
  static ssize_t
  show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
  {
@@ -3455,6 +3501,8 @@ static SENSOR_DEVICE_ATTR(intrusion1_beep, S_IWUSR | S_IRUGO, show_beep,
  			  store_beep, INTRUSION_ALARM_BASE + 1);
  static SENSOR_DEVICE_ATTR(beep_enable, S_IWUSR | S_IRUGO, show_beep,
  			  store_beep, BEEP_ENABLE_BASE);
+static SENSOR_DEVICE_ATTR(hddsaver_enable, S_IWUSR | S_IRUGO, show_hddsaver,
+			  store_hddsaver, 0);

  static umode_t nct6775_other_is_visible(struct kobject *kobj,
  					struct attribute *attr, int index)
@@ -3475,6 +3523,9 @@ static umode_t nct6775_other_is_visible(struct kobject *kobj,
  			return 0;
  	}

+	if (index == 6 && !data->have_hddsaver)
+		return 0;
+
  	return attr->mode;
  }

@@ -3490,6 +3541,7 @@ static struct attribute *nct6775_attributes_other[]= {
  	&sensor_dev_attr_intrusion0_beep.dev_attr.attr,		/* 3 */
  	&sensor_dev_attr_intrusion1_beep.dev_attr.attr,		/* 4 */
  	&sensor_dev_attr_beep_enable.dev_attr.attr,		/* 5 */
+	&sensor_dev_attr_hddsaver_enable.dev_attr.attr,		/* 6 */

  	NULL
  };
@@ -3805,6 +3857,8 @@ static int nct6775_probe(struct platform_device *pdev)
  	struct device *hwmon_dev;
  	int num_attr_groups = 0;

+	const char *board_vendor, *board_name;
+
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
  				 DRVNAME))
@@ -4502,6 +4556,9 @@ static int nct6775_probe(struct platform_device *pdev)
  	/* Initialize the chip */
  	nct6775_init_device(data);

+	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+	board_name = dmi_get_system_info(DMI_BOARD_NAME);
+
  	err = superio_enter(sio_data->sioreg);
  	if (err)
  		return err;
@@ -4518,6 +4575,15 @@ static int nct6775_probe(struct platform_device *pdev)
  	case nct6116:
  	case nct6779:
  	case nct6791:
+		if (board_name && board_vendor &&
+		    !strcmp(board_vendor, "ASRock")) {
+            /* Z97 Extreme6 should also work (the same GPIO10 pin is used) */
+            /* but it needs testing!!! */
+			if (!strcmp(board_name, "Z97 Extreme4") || !strcmp(board_name, "Z97 Extreme6")) {
+                data->have_hddsaver = (cr2a & (1<<6));
+            }
+        }
+        break;
  	case nct6792:
  	case nct6793:
  	case nct6795:
@@ -4527,6 +4593,20 @@ static int nct6775_probe(struct platform_device *pdev)
  		break;
  	}

+	if (data->have_hddsaver) {
+		u8 tmp;
+
+		pr_notice("HDD Saver found\n");
+		superio_select(sio_data->sioreg, NCT6775_LD_GPIO_DATA); /* Logical Device 8 */
+		tmp = superio_inb(sio_data->sioreg, NCT6775_REG_CR_GPIO1_DATA); /* GPIO1 date reg */
+		data->hddsaver_status = tmp & (1<<0); /* check bit0 */
+		if (data->hddsaver_status) {
+			pr_warn("HDD Saver is disabled\n");
+		} else {
+			pr_warn("HDD Saver is enabled\n");
+		}
+	}
+
  	/*
  	 * Read VID value
  	 * We can get the VID input values directly at logical device D 0xe3.
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] Add ASRock HDD Saver support
  2021-05-03 15:58 [PATCH] Add ASRock HDD Saver support Paweł Marciniak
@ 2021-05-03 17:10 ` Guenter Roeck
  0 siblings, 0 replies; 2+ messages in thread
From: Guenter Roeck @ 2021-05-03 17:10 UTC (permalink / raw)
  To: Paweł Marciniak, linux-hwmon, linux-kernel

On 5/3/21 8:58 AM, Paweł Marciniak wrote:
> Some of the asrock motherboards are equipped with hdd saver technology.
> It is implemented via a special power connector on the motherboard and a corresponding custom made power cable with two SATA power ports.
> The control is via the gpio10 pin of the nct6791d chip.
> When this technology is available the module creates the hddsaver_enable file.
> Reading the file returns the current status, while writing turns off or on the power of the SATA connectors.
> 
> Supported motheboards:
> ASRock Z97 Extreme4 - works 100% tested.
> ASRock Z97 Extreme6 - Based on boardview/schematic should works, not tested.
> Other ASRock motherboards supporting this technology - status unknown.
> 
> Signed-off-by: Paweł Marciniak <sunwire@gmail.com>

I don't see what this has to do with hardware monitoring.
I am not going to apply this patch. Feel free to submit
a platform driver to implement such functionality.

Guenter

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-05-03 17:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-03 15:58 [PATCH] Add ASRock HDD Saver support Paweł Marciniak
2021-05-03 17:10 ` Guenter Roeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).