wpce775x.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* Quanta EC driver for the Winbond Embedded Controller
  2. *
  3. * Copyright (C) 2009 Quanta Computer Inc.
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/err.h>
  17. #include <linux/i2c.h>
  18. #include <linux/slab.h>
  19. #define EC_ID_NAME "qci-i2cec"
  20. #define EC_BUFFER_LEN 16
  21. #define EC_CMD_POWER_OFF 0xAC
  22. #define EC_CMD_RESTART 0xAB
  23. static struct i2c_client *g_i2cec_client;
  24. /* General structure to hold the driver data */
  25. struct i2cec_drv_data {
  26. struct i2c_client *i2cec_client;
  27. struct work_struct work;
  28. char ec_data[EC_BUFFER_LEN+1];
  29. };
  30. static int __devinit wpce_probe(struct i2c_client *client,
  31. const struct i2c_device_id *id);
  32. static int __devexit wpce_remove(struct i2c_client *kbd);
  33. #ifdef CONFIG_PM
  34. static int wpce_suspend(struct device *dev)
  35. {
  36. return 0;
  37. }
  38. static int wpce_resume(struct device *dev)
  39. {
  40. return 0;
  41. }
  42. #endif
  43. #ifdef CONFIG_PM
  44. static struct dev_pm_ops wpce_pm_ops = {
  45. .suspend = wpce_suspend,
  46. .resume = wpce_resume,
  47. };
  48. #endif
  49. static const struct i2c_device_id wpce_idtable[] = {
  50. { EC_ID_NAME, 0 },
  51. { }
  52. };
  53. static struct i2c_driver wpce_driver = {
  54. .driver = {
  55. .owner = THIS_MODULE,
  56. .name = EC_ID_NAME,
  57. #ifdef CONFIG_PM
  58. .pm = &wpce_pm_ops,
  59. #endif
  60. },
  61. .probe = wpce_probe,
  62. .remove = __devexit_p(wpce_remove),
  63. .id_table = wpce_idtable,
  64. };
  65. static int __devinit wpce_probe(struct i2c_client *client,
  66. const struct i2c_device_id *id)
  67. {
  68. int err = -ENOMEM;
  69. struct i2cec_drv_data *context = 0;
  70. /* there is no need to call i2c_check_functionality() since it is the
  71. client's job to use the interface (I2C vs SMBUS) appropriate for it. */
  72. client->driver = &wpce_driver;
  73. context = kzalloc(sizeof(struct i2cec_drv_data), GFP_KERNEL);
  74. if (!context)
  75. return err;
  76. context->i2cec_client = client;
  77. g_i2cec_client = client;
  78. i2c_set_clientdata(context->i2cec_client, context);
  79. return 0;
  80. }
  81. static int __devexit wpce_remove(struct i2c_client *dev)
  82. {
  83. struct i2cec_drv_data *context = i2c_get_clientdata(dev);
  84. g_i2cec_client = NULL;
  85. kfree(context);
  86. return 0;
  87. }
  88. static int __init wpce_init(void)
  89. {
  90. return i2c_add_driver(&wpce_driver);
  91. }
  92. static void __exit wpce_exit(void)
  93. {
  94. i2c_del_driver(&wpce_driver);
  95. }
  96. struct i2c_client *wpce_get_i2c_client(void)
  97. {
  98. return g_i2cec_client;
  99. }
  100. EXPORT_SYMBOL_GPL(wpce_get_i2c_client);
  101. void wpce_poweroff(void)
  102. {
  103. if (g_i2cec_client == NULL)
  104. return;
  105. i2c_smbus_write_byte(g_i2cec_client, EC_CMD_POWER_OFF);
  106. }
  107. EXPORT_SYMBOL_GPL(wpce_poweroff);
  108. void wpce_restart(void)
  109. {
  110. if (g_i2cec_client == NULL)
  111. return;
  112. i2c_smbus_write_byte(g_i2cec_client, EC_CMD_RESTART);
  113. }
  114. EXPORT_SYMBOL_GPL(wpce_restart);
  115. int wpce_i2c_transfer(struct i2c_msg *msg)
  116. {
  117. if (g_i2cec_client == NULL)
  118. return -1;
  119. msg->addr = g_i2cec_client->addr;
  120. return i2c_transfer(g_i2cec_client->adapter, msg, 1);
  121. }
  122. EXPORT_SYMBOL_GPL(wpce_i2c_transfer);
  123. int wpce_smbus_write_word_data(u8 command, u16 value)
  124. {
  125. if (g_i2cec_client == NULL)
  126. return -1;
  127. return i2c_smbus_write_word_data(g_i2cec_client, command, value);
  128. }
  129. EXPORT_SYMBOL_GPL(wpce_smbus_write_word_data);
  130. int wpce_smbus_write_byte_data(u8 command, u8 value)
  131. {
  132. if (g_i2cec_client == NULL)
  133. return -1;
  134. return i2c_smbus_write_byte_data(g_i2cec_client, command, value);
  135. }
  136. EXPORT_SYMBOL_GPL(wpce_smbus_write_byte_data);
  137. module_init(wpce_init);
  138. module_exit(wpce_exit);
  139. MODULE_AUTHOR("Quanta Computer Inc.");
  140. MODULE_DESCRIPTION("Quanta Embedded Controller I2C Bridge Driver");
  141. MODULE_LICENSE("GPL v2");