qidong.liu 1 день назад
Родитель
Сommit
db5b2014ad
1 измененных файлов с 189 добавлено и 17 удалено
  1. 189 17
      ssegment.c

+ 189 - 17
ssegment.c

@@ -11,6 +11,8 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
+#include <linux/delay.h>
+
 #include <linux/io.h>
 #include "gpioregs.h"
 
@@ -43,6 +45,152 @@ struct ssegment_dev
 static struct ssegment_dev *dev = NULL;
 
 
+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;
+}
+
+#if 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;
+}
+#endif
+
+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;
+}
+
 unsigned int readl_cust(unsigned int addr)
 {
     unsigned int val;
@@ -70,40 +218,62 @@ static void delay_work_func(struct work_struct *work)
     static unsigned int flag = 0;
     if(dev->size != 0)
     {
-        // outb(dev->buffer[0], PORT_80);
-        if((dev->buffer[1] & 0x02))
-        {
-            val = readl_cust(SSEGMENT_POINT);
-            val = val | 0x01;
-            ret = writel_cust(SSEGMENT_POINT, val);
-        }
-        else
-        {
-            val = readl_cust(SSEGMENT_POINT);
-            val = val & 0xFFFFFFFE;
-            ret = writel_cust(SSEGMENT_POINT, val);
-        }
-
         if((dev->buffer[1] & 0x80))
         {
+            // blink
             flag++;
             if(flag % 2 == 1)
             {
-                display_value = dev->buffer[0];
+                // blink on
+                if((dev->buffer[1] & 0x02))
+                {
+                    val = readl_cust(SSEGMENT_POINT);
+                    val = val | 0x01;
+                    ret = writel_cust(SSEGMENT_POINT, val);
+                }
+                else
+                {
+                    val = readl_cust(SSEGMENT_POINT);
+                    val = val & 0xFFFFFFFE;
+                    ret = writel_cust(SSEGMENT_POINT, val);
+                }
+                display_value = dev->buffer[0];                
+                outb(display_value, PORT_80);
+                oem_ec_write_ram(1, 0x06, 0);
             }
             else
             {
+                // blink off
                 display_value = 0;
+                // off point
+                val = readl_cust(SSEGMENT_POINT);
+                val = val & 0xFFFFFFFE;
+                ret = writel_cust(SSEGMENT_POINT, val);
+
+                // off segment
+                oem_ec_write_ram(1, 0x06, 1);
             }
-            schedule_delayed_work(&dev->delay_work1, msecs_to_jiffies(1000));
+            schedule_delayed_work(&dev->delay_work1, msecs_to_jiffies(500));
         }
         else
         {
+            if((dev->buffer[1] & 0x02))
+            {
+                val = readl_cust(SSEGMENT_POINT);
+                val = val | 0x01;
+                ret = writel_cust(SSEGMENT_POINT, val);
+            }
+            else
+            {
+                val = readl_cust(SSEGMENT_POINT);
+                val = val & 0xFFFFFFFE;
+                ret = writel_cust(SSEGMENT_POINT, val);
+            }
             flag = 0;
             display_value = dev->buffer[0];
+            outb(display_value, PORT_80);
         }
 
-        outb(display_value, PORT_80);
     }
     
     printk(KERN_INFO "delay_work_func\n");
@@ -265,6 +435,8 @@ int ssegment_init(void)
         goto fail_buffer;
     }
 
+    dev->buffer[0] = inb(PORT_80);
+
     mutex_init(&dev->lock);
 
     INIT_DELAYED_WORK(&dev->delay_work1, delay_work_func);