MCU: add poweroff node
authorNick Xie <nick@khadas.com>
Wed, 26 Jun 2019 03:25:02 +0000 (11:25 +0800)
committerNick Xie <nick@khadas.com>
Wed, 26 Jun 2019 03:25:02 +0000 (11:25 +0800)
Signed-off-by: Nick Xie <nick@khadas.com>
drivers/misc/khadas-mcu.c

index 792be03..95ca930 100644 (file)
@@ -27,6 +27,7 @@
 #define MCU_WOL_REG                            0x21
 #define MCU_FAN_CTRL                   0x88
 #define MCU_USB_PCIE_SWITCH            0x33 /* VIM3 only */
+#define MCU_PWR_OFF_CMD                        0x80
 
 #define KHADAS_FAN_TRIG_TEMP_LEVEL0            50      // 50 degree if not set
 #define KHADAS_FAN_TRIG_TEMP_LEVEL1            60      // 60 degree if not set
@@ -91,6 +92,7 @@ struct mcu_data {
        struct i2c_client *client;
        struct class *wol_class;
        struct class *usb_pcie_switch_class;
+       struct class *mcu_class;
        int wol_enable;
        u8 usb_pcie_switch_mode;
        struct khadas_fan_data fan_data;
@@ -422,6 +424,30 @@ static ssize_t show_usb_pcie_switch_mode(struct class *cls,
        return sprintf(buf, "%d\n", g_mcu_data->usb_pcie_switch_mode);
 }
 
+static ssize_t store_mcu_poweroff(struct class *cls, struct class_attribute *attr,
+                const char *buf, size_t count)
+{
+       int ret;
+       int val;
+       u8 reg;
+
+       if (kstrtoint(buf, 0, &val))
+               return -EINVAL;
+
+       if (1 != val)
+               return -EINVAL;
+
+       reg = (u8)val;
+       ret = mcu_i2c_write_regs(g_mcu_data->client, MCU_PWR_OFF_CMD, &reg, 1);
+       if (ret < 0) {
+               printk("write poweroff cmd error\n");
+
+               return ret;
+       }
+
+       return count;
+}
+
 static struct class_attribute wol_class_attrs[] = {
        __ATTR(enable, 0644, show_wol_enable, store_wol_enable),
 };
@@ -437,6 +463,10 @@ static struct class_attribute usb_pcie_switch_class_attrs[] = {
        __ATTR(mode, 0644, show_usb_pcie_switch_mode, store_usb_pcie_switch_mode),
 };
 
+static struct class_attribute mcu_class_attrs[] = {
+       __ATTR(poweroff, 0644, NULL, store_mcu_poweroff),
+};
+
 static void create_mcu_attrs(void)
 {
        int i;
@@ -447,11 +477,22 @@ static void create_mcu_attrs(void)
                return;
        }
 
+       g_mcu_data->mcu_class = class_create(THIS_MODULE, "mcu");
+       if (IS_ERR(g_mcu_data->mcu_class)) {
+               pr_err("create mcu_class debug class fail\n");
+               return;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wol_class_attrs); i++) {
                if (class_create_file(g_mcu_data->wol_class, &wol_class_attrs[i]))
                        pr_err("create wol attribute %s fail\n", wol_class_attrs[i].attr.name);
        }
 
+       for (i = 0; i < ARRAY_SIZE(mcu_class_attrs); i++) {
+               if (class_create_file(g_mcu_data->mcu_class, &mcu_class_attrs[i]))
+                       pr_err("create mcu attribute %s fail\n", mcu_class_attrs[i].attr.name);
+       }
+
        if (is_mcu_fan_control_available()) {
                g_mcu_data->fan_data.fan_class = class_create(THIS_MODULE, "fan");
                if (IS_ERR(g_mcu_data->fan_data.fan_class)) {