ec_kb3310b.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. #include <linux/module.h>
  13. #include <linux/spinlock.h>
  14. #include <linux/delay.h>
  15. #include "ec_kb3310b.h"
  16. static DEFINE_SPINLOCK(index_access_lock);
  17. static DEFINE_SPINLOCK(port_access_lock);
  18. unsigned char ec_read(unsigned short addr)
  19. {
  20. unsigned char value;
  21. unsigned long flags;
  22. spin_lock_irqsave(&index_access_lock, flags);
  23. outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
  24. outb((addr & 0x00ff), EC_IO_PORT_LOW);
  25. value = inb(EC_IO_PORT_DATA);
  26. spin_unlock_irqrestore(&index_access_lock, flags);
  27. return value;
  28. }
  29. EXPORT_SYMBOL_GPL(ec_read);
  30. void ec_write(unsigned short addr, unsigned char val)
  31. {
  32. unsigned long flags;
  33. spin_lock_irqsave(&index_access_lock, flags);
  34. outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
  35. outb((addr & 0x00ff), EC_IO_PORT_LOW);
  36. outb(val, EC_IO_PORT_DATA);
  37. /* flush the write action */
  38. inb(EC_IO_PORT_DATA);
  39. spin_unlock_irqrestore(&index_access_lock, flags);
  40. }
  41. EXPORT_SYMBOL_GPL(ec_write);
  42. /*
  43. * This function is used for EC command writes and corresponding status queries.
  44. */
  45. int ec_query_seq(unsigned char cmd)
  46. {
  47. int timeout;
  48. unsigned char status;
  49. unsigned long flags;
  50. int ret = 0;
  51. spin_lock_irqsave(&port_access_lock, flags);
  52. /* make chip goto reset mode */
  53. udelay(EC_REG_DELAY);
  54. outb(cmd, EC_CMD_PORT);
  55. udelay(EC_REG_DELAY);
  56. /* check if the command is received by ec */
  57. timeout = EC_CMD_TIMEOUT;
  58. status = inb(EC_STS_PORT);
  59. while (timeout-- && (status & (1 << 1))) {
  60. status = inb(EC_STS_PORT);
  61. udelay(EC_REG_DELAY);
  62. }
  63. spin_unlock_irqrestore(&port_access_lock, flags);
  64. if (timeout <= 0) {
  65. printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
  66. ret = -EINVAL;
  67. } else
  68. printk(KERN_INFO
  69. "(%x/%d)ec issued command %d status : 0x%x\n",
  70. timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
  71. return ret;
  72. }
  73. EXPORT_SYMBOL_GPL(ec_query_seq);
  74. /*
  75. * Send query command to EC to get the proper event number
  76. */
  77. int ec_query_event_num(void)
  78. {
  79. return ec_query_seq(CMD_GET_EVENT_NUM);
  80. }
  81. EXPORT_SYMBOL(ec_query_event_num);
  82. /*
  83. * Get event number from EC
  84. *
  85. * NOTE: This routine must follow the query_event_num function in the
  86. * interrupt.
  87. */
  88. int ec_get_event_num(void)
  89. {
  90. int timeout = 100;
  91. unsigned char value;
  92. unsigned char status;
  93. udelay(EC_REG_DELAY);
  94. status = inb(EC_STS_PORT);
  95. udelay(EC_REG_DELAY);
  96. while (timeout-- && !(status & (1 << 0))) {
  97. status = inb(EC_STS_PORT);
  98. udelay(EC_REG_DELAY);
  99. }
  100. if (timeout <= 0) {
  101. pr_info("%s: get event number timeout.\n", __func__);
  102. return -EINVAL;
  103. }
  104. value = inb(EC_DAT_PORT);
  105. udelay(EC_REG_DELAY);
  106. return value;
  107. }
  108. EXPORT_SYMBOL(ec_get_event_num);