Parcourir la source

差分sysfs_power功能

liu qidong [url ssh://qidong.liu@10.2.90.253:29418/] il y a 1 mois
Parent
commit
7d2e6d4f40
5 fichiers modifiés avec 289 ajouts et 2 suppressions
  1. 1 1
      Makefile
  2. 1 1
      fan.c
  3. 11 0
      main.c
  4. 269 0
      sysfs_power.c
  5. 7 0
      sysfs_power.h

+ 1 - 1
Makefile

@@ -3,7 +3,7 @@
 MODULE_NAME := opal
 obj-m := opal.o
 
-opal-objs := main.o led.o light_ring.o ssegment.o ec_version.o buzzer.o fan.o writeprotect.o myname.o cash_drawers.o batteryled.o watchdog.o power.o switches.o backlight.o gsensor.o lcd_2x20.o smart_battery.o voltage_sysfs.o led_heartbeat.o
+opal-objs := main.o led.o light_ring.o ssegment.o ec_version.o buzzer.o fan.o writeprotect.o myname.o cash_drawers.o batteryled.o watchdog.o power.o switches.o backlight.o gsensor.o lcd_2x20.o smart_battery.o voltage_sysfs.o led_heartbeat.o sysfs_power.o
 
 PROJECT_NAME := POS
 KERNELDIR := ~/timesys/SDK64Bit-V6_02_00/kernel-source/linux-5.15/

+ 1 - 1
fan.c

@@ -4255,7 +4255,7 @@ static struct attribute *fan_attrs[] = {
     &temp1_input.attr,
     &temp2_input.attr,
     // &power_flag.attr,
-    &ac_power.attr,
+    // &ac_power.attr,
     // &voltage_vcore.attr,
 	&voltage_vbat.attr,
     // &voltage_5v.attr,

+ 11 - 0
main.c

@@ -35,6 +35,7 @@
 #include "smart_battery.h"
 #include "voltage_sysfs.h"
 #include "led_heartbeat.h"
+#include "sysfs_power.h"
 
 struct kobject *vfiec_kobj = NULL;
 struct kobject *hwmon_kobj = NULL;
@@ -176,8 +177,17 @@ static int __init all_driver_init(void)
         goto out_voltage_sysfs;
     }
 
+    ret = sysfs_power_init();
+    if(ret != 0)
+    {
+        printk(KERN_ERR "sysfs_power_init failed\n");
+        goto out_led_heartbeat;
+    }
+
     printk(KERN_INFO "all_driver_init\n");
     return ret;
+out_sysfs_power:
+    sysfs_power_exit();
 out_led_heartbeat:
     led_heartbeat_exit();
 out_voltage_sysfs:
@@ -243,6 +253,7 @@ static void __exit all_driver_exit(void)
     battery_acpi_driver_exit();
     voltage_sysfs_exit();
     led_heartbeat_exit();
+    sysfs_power_exit();
     kobject_put(hwmon_kobj);
     kobject_put(vfiec_kobj);
 }

+ 269 - 0
sysfs_power.c

@@ -0,0 +1,269 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "gpioregs.h"
+
+extern struct kobject *hwmon_kobj;
+
+
+/* Helper functions for IO access */
+static uint8_t hwm_read_reg(uint16_t hwm_base, uint8_t reg)
+{
+    outb(reg, hwm_base + HWM_INDEX_OFFSET);
+    return inb(hwm_base + HWM_DATA_OFFSET);
+}
+
+static void hwm_write_reg(uint16_t hwm_base, uint8_t reg, uint8_t val)
+{
+    outb(reg, hwm_base + HWM_INDEX_OFFSET);
+    outb(val, hwm_base + HWM_DATA_OFFSET);
+}
+
+static uint8_t hwm_read_reg_retry(uint16_t hwm_base, uint8_t reg)
+{
+    uint8_t v = hwm_read_reg(hwm_base, reg);
+    if (v == 0xFF) {
+        v = hwm_read_reg(hwm_base, reg);
+    }
+    return v;
+}
+
+static int vin_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
+{
+    int vm = raw * 11;
+    if (r_top_kohm > 0 && r_bottom_kohm > 0) {
+        vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
+    }
+    return vm;
+}
+
+static int ec_raw_to_volt(uint8_t raw, int r_top_kohm, int r_bottom_kohm)
+{
+    int vm = raw * 12; /* EC unit: 10mV */
+    vm = (vm * (r_top_kohm + r_bottom_kohm)) / r_bottom_kohm;
+    return vm ;
+}
+
+
+static int ec_wait_ibf(void)
+{
+    int i = 0;
+    while (inb(EC_CMD_PORT) & EC_IBF) {
+        if (++i > TIMEOUT_LOOPS) {
+            printk("Error: EC IBF Timeout!\n");
+            return -1;
+        }
+        udelay(1);
+    }
+    return 0;
+}
+
+static int ec_wait_obf(void)
+{
+    int i = 0;
+    while (!(inb(EC_CMD_PORT) & EC_OBF)) {
+        if (++i > TIMEOUT_LOOPS) {
+            printk("Error: EC OBF Timeout!\n");
+            return -1;
+        }
+        udelay(1);
+    }
+    return 0;
+}
+
+
+static int wait_ibf(void)
+{
+    int i = 0;
+    while (inb(EC_CMD_PORT) & EC_IBF)
+    {
+        if (++i > TIMEOUT_LOOPS)
+        {
+            return -1;
+        }
+        udelay(1);
+    }
+    return 0;
+}
+
+static int wait_obf(void)
+{
+    int i = 0;
+    while (!(inb(EC_CMD_PORT) & EC_OBF))
+    {
+        if (++i > TIMEOUT_LOOPS)
+        {
+            return -1;
+        }
+        udelay(1);
+    }
+    return 0;
+}
+
+static int ec_read_ram(uint8_t offset, uint8_t *data)
+{
+    if (wait_ibf() < 0)
+        return -1;
+    outb(CMD_READ_RAM, EC_CMD_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(offset, EC_DATA_PORT);
+
+    if (wait_obf() < 0)
+        return -1;
+    *data = inb(EC_DATA_PORT);
+
+    return 0;
+}
+
+static int ec_write_ram(uint8_t offset, uint8_t data)
+{
+    if (wait_ibf() < 0)
+        return -1;
+    outb(CMD_WRITE_RAM, EC_CMD_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(offset, EC_DATA_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(data, EC_DATA_PORT);
+
+    return 0;
+}
+
+static int oem_ec_read_ram(uint8_t page, uint8_t offset, uint8_t *data)
+{
+    unsigned char WEC, REC;
+    switch(page)
+    {
+        case 0:
+        {
+            WEC = 0x96;
+            REC = 0x95;
+            break;
+        }
+        
+        case 1:
+        {
+            WEC = 0x98;
+            REC = 0x97;
+            break;
+        }
+        
+        default:
+        {
+            WEC = 0x81;
+            REC = 0x80;
+            break;
+        }
+    }    
+    if (wait_ibf() < 0)
+        return -1;
+    outb(REC, EC_CMD_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(offset, EC_DATA_PORT);
+
+    if (wait_obf() < 0)
+        return -1;
+    *data = inb(EC_DATA_PORT);
+
+    return 0;
+}
+
+static int oem_ec_write_ram(uint8_t page, uint8_t offset, uint8_t data)
+{
+    unsigned char WEC, REC;
+    switch(page)
+    {
+        case 0:
+        {
+            WEC = 0x96;
+            REC = 0x95;
+            break;
+        }
+        
+        case 1:
+        {
+            WEC = 0x98;
+            REC = 0x97;
+            break;
+        }
+        
+        default:
+        {
+            WEC = 0x81;
+            REC = 0x80;
+            break;
+        }
+    }
+    if (wait_ibf() < 0)
+        return -1;
+    outb(WEC, EC_CMD_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(offset, EC_DATA_PORT);
+
+    if (wait_ibf() < 0)
+        return -1;
+    outb(data, EC_DATA_PORT);
+
+    return 0;
+}
+
+
+
+static ssize_t ac_power_show(struct kobject *kobj, struct kobj_attribute *attr,
+                         char *buf)
+{
+    int ac_power_flag = 0;
+    uint8_t val = 0x00;
+    if (oem_ec_read_ram(2, 0x36, &val) < 0)
+        return -1;
+    ac_power_flag = (val  & 0x03) ? 1 : 0;
+
+	return sprintf(buf, "%d", ac_power_flag);
+}
+
+static ssize_t ac_power_store(struct kobject *kobj, struct kobj_attribute *attr,
+                                 const char *buf, size_t count)
+{
+    return -EINVAL;
+}
+
+
+static struct kobj_attribute ac_power =
+    __ATTR(ac_power, 0644, ac_power_show, ac_power_store);
+
+static struct attribute *sysfs_power_attrs[] = {
+    &ac_power.attr,
+    NULL,
+};
+
+static struct attribute_group sysfs_power_attr_group = {
+    .attrs = sysfs_power_attrs,
+};
+
+int sysfs_power_init(void)
+{
+    int ret = 0;
+
+    ret = sysfs_create_group(hwmon_kobj, &sysfs_power_attr_group);
+
+    return ret;
+}
+
+void sysfs_power_exit(void)
+{
+    sysfs_remove_group(hwmon_kobj, &sysfs_power_attr_group);
+}

+ 7 - 0
sysfs_power.h

@@ -0,0 +1,7 @@
+#ifndef __SYSFS_POWER_H__
+#define __SYSFS_POWER_H__
+
+int sysfs_power_init(void);
+void sysfs_power_exit(void);
+
+#endif