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