Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Basic KB3310B Embedded Controller support for the YeeLoong 2F netbook
0004  *
0005  *  Copyright (C) 2008 Lemote Inc.
0006  *  Author: liujl <liujl@lemote.com>, 2008-04-20
0007  */
0008 
0009 #include <linux/io.h>
0010 #include <linux/export.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/delay.h>
0013 
0014 #include "ec_kb3310b.h"
0015 
0016 static DEFINE_SPINLOCK(index_access_lock);
0017 static DEFINE_SPINLOCK(port_access_lock);
0018 
0019 unsigned char ec_read(unsigned short addr)
0020 {
0021     unsigned char value;
0022     unsigned long flags;
0023 
0024     spin_lock_irqsave(&index_access_lock, flags);
0025     outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
0026     outb((addr & 0x00ff), EC_IO_PORT_LOW);
0027     value = inb(EC_IO_PORT_DATA);
0028     spin_unlock_irqrestore(&index_access_lock, flags);
0029 
0030     return value;
0031 }
0032 EXPORT_SYMBOL_GPL(ec_read);
0033 
0034 void ec_write(unsigned short addr, unsigned char val)
0035 {
0036     unsigned long flags;
0037 
0038     spin_lock_irqsave(&index_access_lock, flags);
0039     outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
0040     outb((addr & 0x00ff), EC_IO_PORT_LOW);
0041     outb(val, EC_IO_PORT_DATA);
0042     /*  flush the write action */
0043     inb(EC_IO_PORT_DATA);
0044     spin_unlock_irqrestore(&index_access_lock, flags);
0045 }
0046 EXPORT_SYMBOL_GPL(ec_write);
0047 
0048 /*
0049  * This function is used for EC command writes and corresponding status queries.
0050  */
0051 int ec_query_seq(unsigned char cmd)
0052 {
0053     int timeout;
0054     unsigned char status;
0055     unsigned long flags;
0056     int ret = 0;
0057 
0058     spin_lock_irqsave(&port_access_lock, flags);
0059 
0060     /* make chip goto reset mode */
0061     udelay(EC_REG_DELAY);
0062     outb(cmd, EC_CMD_PORT);
0063     udelay(EC_REG_DELAY);
0064 
0065     /* check if the command is received by ec */
0066     timeout = EC_CMD_TIMEOUT;
0067     status = inb(EC_STS_PORT);
0068     while (timeout-- && (status & (1 << 1))) {
0069         status = inb(EC_STS_PORT);
0070         udelay(EC_REG_DELAY);
0071     }
0072 
0073     spin_unlock_irqrestore(&port_access_lock, flags);
0074 
0075     if (timeout <= 0) {
0076         printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
0077         ret = -EINVAL;
0078     } else
0079         printk(KERN_INFO
0080                "(%x/%d)ec issued command %d status : 0x%x\n",
0081                timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
0082 
0083     return ret;
0084 }
0085 EXPORT_SYMBOL_GPL(ec_query_seq);
0086 
0087 /*
0088  * Send query command to EC to get the proper event number
0089  */
0090 int ec_query_event_num(void)
0091 {
0092     return ec_query_seq(CMD_GET_EVENT_NUM);
0093 }
0094 EXPORT_SYMBOL(ec_query_event_num);
0095 
0096 /*
0097  * Get event number from EC
0098  *
0099  * NOTE: This routine must follow the query_event_num function in the
0100  * interrupt.
0101  */
0102 int ec_get_event_num(void)
0103 {
0104     int timeout = 100;
0105     unsigned char value;
0106     unsigned char status;
0107 
0108     udelay(EC_REG_DELAY);
0109     status = inb(EC_STS_PORT);
0110     udelay(EC_REG_DELAY);
0111     while (timeout-- && !(status & (1 << 0))) {
0112         status = inb(EC_STS_PORT);
0113         udelay(EC_REG_DELAY);
0114     }
0115     if (timeout <= 0) {
0116         pr_info("%s: get event number timeout.\n", __func__);
0117 
0118         return -EINVAL;
0119     }
0120     value = inb(EC_DAT_PORT);
0121     udelay(EC_REG_DELAY);
0122 
0123     return value;
0124 }
0125 EXPORT_SYMBOL(ec_get_event_num);