hc
2023-02-13 e440ec23c5a540cdd3f7464e8779219be6fd3d95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Basic KB3310B Embedded Controller support for the YeeLoong 2F netbook
 *
 *  Copyright (C) 2008 Lemote Inc.
 *  Author: liujl <liujl@lemote.com>, 2008-04-20
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
 
#include <linux/io.h>
#include <linux/export.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
 
#include "ec_kb3310b.h"
 
static DEFINE_SPINLOCK(index_access_lock);
static DEFINE_SPINLOCK(port_access_lock);
 
unsigned char ec_read(unsigned short addr)
{
   unsigned char value;
   unsigned long flags;
 
   spin_lock_irqsave(&index_access_lock, flags);
   outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
   outb((addr & 0x00ff), EC_IO_PORT_LOW);
   value = inb(EC_IO_PORT_DATA);
   spin_unlock_irqrestore(&index_access_lock, flags);
 
   return value;
}
EXPORT_SYMBOL_GPL(ec_read);
 
void ec_write(unsigned short addr, unsigned char val)
{
   unsigned long flags;
 
   spin_lock_irqsave(&index_access_lock, flags);
   outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
   outb((addr & 0x00ff), EC_IO_PORT_LOW);
   outb(val, EC_IO_PORT_DATA);
   /*  flush the write action */
   inb(EC_IO_PORT_DATA);
   spin_unlock_irqrestore(&index_access_lock, flags);
}
EXPORT_SYMBOL_GPL(ec_write);
 
/*
 * This function is used for EC command writes and corresponding status queries.
 */
int ec_query_seq(unsigned char cmd)
{
   int timeout;
   unsigned char status;
   unsigned long flags;
   int ret = 0;
 
   spin_lock_irqsave(&port_access_lock, flags);
 
   /* make chip goto reset mode */
   udelay(EC_REG_DELAY);
   outb(cmd, EC_CMD_PORT);
   udelay(EC_REG_DELAY);
 
   /* check if the command is received by ec */
   timeout = EC_CMD_TIMEOUT;
   status = inb(EC_STS_PORT);
   while (timeout-- && (status & (1 << 1))) {
       status = inb(EC_STS_PORT);
       udelay(EC_REG_DELAY);
   }
 
   spin_unlock_irqrestore(&port_access_lock, flags);
 
   if (timeout <= 0) {
       printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
       ret = -EINVAL;
   } else
       printk(KERN_INFO
              "(%x/%d)ec issued command %d status : 0x%x\n",
              timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
 
   return ret;
}
EXPORT_SYMBOL_GPL(ec_query_seq);
 
/*
 * Send query command to EC to get the proper event number
 */
int ec_query_event_num(void)
{
   return ec_query_seq(CMD_GET_EVENT_NUM);
}
EXPORT_SYMBOL(ec_query_event_num);
 
/*
 * Get event number from EC
 *
 * NOTE: This routine must follow the query_event_num function in the
 * interrupt.
 */
int ec_get_event_num(void)
{
   int timeout = 100;
   unsigned char value;
   unsigned char status;
 
   udelay(EC_REG_DELAY);
   status = inb(EC_STS_PORT);
   udelay(EC_REG_DELAY);
   while (timeout-- && !(status & (1 << 0))) {
       status = inb(EC_STS_PORT);
       udelay(EC_REG_DELAY);
   }
   if (timeout <= 0) {
       pr_info("%s: get event number timeout.\n", __func__);
 
       return -EINVAL;
   }
   value = inb(EC_DAT_PORT);
   udelay(EC_REG_DELAY);
 
   return value;
}
EXPORT_SYMBOL(ec_get_event_num);