ec_kb3310b.c 2.8 KB

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