ec_kb3310b.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. return;
  41. }
  42. EXPORT_SYMBOL_GPL(ec_write);
  43. /*
  44. * This function is used for EC command writes and corresponding status queries.
  45. */
  46. int ec_query_seq(unsigned char cmd)
  47. {
  48. int timeout;
  49. unsigned char status;
  50. unsigned long flags;
  51. int ret = 0;
  52. spin_lock_irqsave(&port_access_lock, flags);
  53. /* make chip goto reset mode */
  54. udelay(EC_REG_DELAY);
  55. outb(cmd, EC_CMD_PORT);
  56. udelay(EC_REG_DELAY);
  57. /* check if the command is received by ec */
  58. timeout = EC_CMD_TIMEOUT;
  59. status = inb(EC_STS_PORT);
  60. while (timeout-- && (status & (1 << 1))) {
  61. status = inb(EC_STS_PORT);
  62. udelay(EC_REG_DELAY);
  63. }
  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. spin_unlock_irqrestore(&port_access_lock, flags);
  72. return ret;
  73. }
  74. EXPORT_SYMBOL_GPL(ec_query_seq);
  75. /*
  76. * Send query command to EC to get the proper event number
  77. */
  78. int ec_query_event_num(void)
  79. {
  80. return ec_query_seq(CMD_GET_EVENT_NUM);
  81. }
  82. EXPORT_SYMBOL(ec_query_event_num);
  83. /*
  84. * Get event number from EC
  85. *
  86. * NOTE: This routine must follow the query_event_num function in the
  87. * interrupt.
  88. */
  89. int ec_get_event_num(void)
  90. {
  91. int timeout = 100;
  92. unsigned char value;
  93. unsigned char status;
  94. udelay(EC_REG_DELAY);
  95. status = inb(EC_STS_PORT);
  96. udelay(EC_REG_DELAY);
  97. while (timeout-- && !(status & (1 << 0))) {
  98. status = inb(EC_STS_PORT);
  99. udelay(EC_REG_DELAY);
  100. }
  101. if (timeout <= 0) {
  102. pr_info("%s: get event number timeout.\n", __func__);
  103. return -EINVAL;
  104. }
  105. value = inb(EC_DAT_PORT);
  106. udelay(EC_REG_DELAY);
  107. return value;
  108. }
  109. EXPORT_SYMBOL(ec_get_event_num);