max8925-i2c.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * I2C driver for Maxim MAX8925
  3. *
  4. * Copyright (C) 2009 Marvell International Ltd.
  5. * Haojian Zhuang <haojian.zhuang@marvell.com>
  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 version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/i2c.h>
  15. #include <linux/mfd/max8925.h>
  16. static inline int max8925_read_device(struct i2c_client *i2c,
  17. int reg, int bytes, void *dest)
  18. {
  19. unsigned char data;
  20. unsigned char *buf;
  21. int ret;
  22. buf = kzalloc(bytes + 1, GFP_KERNEL);
  23. if (!buf)
  24. return -ENOMEM;
  25. data = (unsigned char)reg;
  26. ret = i2c_master_send(i2c, &data, 1);
  27. if (ret < 0)
  28. return ret;
  29. ret = i2c_master_recv(i2c, buf, bytes + 1);
  30. if (ret < 0)
  31. return ret;
  32. memcpy(dest, buf, bytes);
  33. return 0;
  34. }
  35. static inline int max8925_write_device(struct i2c_client *i2c,
  36. int reg, int bytes, void *src)
  37. {
  38. unsigned char buf[bytes + 1];
  39. int ret;
  40. buf[0] = (unsigned char)reg;
  41. memcpy(&buf[1], src, bytes);
  42. ret = i2c_master_send(i2c, buf, bytes + 1);
  43. if (ret < 0)
  44. return ret;
  45. return 0;
  46. }
  47. int max8925_reg_read(struct i2c_client *i2c, int reg)
  48. {
  49. struct max8925_chip *chip = i2c_get_clientdata(i2c);
  50. unsigned char data;
  51. int ret;
  52. mutex_lock(&chip->io_lock);
  53. ret = max8925_read_device(i2c, reg, 1, &data);
  54. mutex_unlock(&chip->io_lock);
  55. if (ret < 0)
  56. return ret;
  57. else
  58. return (int)data;
  59. }
  60. EXPORT_SYMBOL(max8925_reg_read);
  61. int max8925_reg_write(struct i2c_client *i2c, int reg,
  62. unsigned char data)
  63. {
  64. struct max8925_chip *chip = i2c_get_clientdata(i2c);
  65. int ret;
  66. mutex_lock(&chip->io_lock);
  67. ret = max8925_write_device(i2c, reg, 1, &data);
  68. mutex_unlock(&chip->io_lock);
  69. return ret;
  70. }
  71. EXPORT_SYMBOL(max8925_reg_write);
  72. int max8925_bulk_read(struct i2c_client *i2c, int reg,
  73. int count, unsigned char *buf)
  74. {
  75. struct max8925_chip *chip = i2c_get_clientdata(i2c);
  76. int ret;
  77. mutex_lock(&chip->io_lock);
  78. ret = max8925_read_device(i2c, reg, count, buf);
  79. mutex_unlock(&chip->io_lock);
  80. return ret;
  81. }
  82. EXPORT_SYMBOL(max8925_bulk_read);
  83. int max8925_bulk_write(struct i2c_client *i2c, int reg,
  84. int count, unsigned char *buf)
  85. {
  86. struct max8925_chip *chip = i2c_get_clientdata(i2c);
  87. int ret;
  88. mutex_lock(&chip->io_lock);
  89. ret = max8925_write_device(i2c, reg, count, buf);
  90. mutex_unlock(&chip->io_lock);
  91. return ret;
  92. }
  93. EXPORT_SYMBOL(max8925_bulk_write);
  94. int max8925_set_bits(struct i2c_client *i2c, int reg,
  95. unsigned char mask, unsigned char data)
  96. {
  97. struct max8925_chip *chip = i2c_get_clientdata(i2c);
  98. unsigned char value;
  99. int ret;
  100. mutex_lock(&chip->io_lock);
  101. ret = max8925_read_device(i2c, reg, 1, &value);
  102. if (ret < 0)
  103. goto out;
  104. value &= ~mask;
  105. value |= data;
  106. ret = max8925_write_device(i2c, reg, 1, &value);
  107. out:
  108. mutex_unlock(&chip->io_lock);
  109. return ret;
  110. }
  111. EXPORT_SYMBOL(max8925_set_bits);
  112. static const struct i2c_device_id max8925_id_table[] = {
  113. { "max8925", 0 },
  114. {}
  115. };
  116. MODULE_DEVICE_TABLE(i2c, max8925_id_table);
  117. static int __devinit max8925_probe(struct i2c_client *client,
  118. const struct i2c_device_id *id)
  119. {
  120. struct max8925_platform_data *pdata = client->dev.platform_data;
  121. struct max8925_chip *chip;
  122. if (!pdata) {
  123. pr_info("%s: platform data is missing\n", __func__);
  124. return -EINVAL;
  125. }
  126. if ((pdata->chip_id <= MAX8925_INVALID)
  127. || (pdata->chip_id >= MAX8925_MAX)) {
  128. pr_info("#%s: wrong chip identification\n", __func__);
  129. return -EINVAL;
  130. }
  131. chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
  132. if (chip == NULL)
  133. return -ENOMEM;
  134. chip->i2c = client;
  135. chip->chip_id = pdata->chip_id;
  136. i2c_set_clientdata(client, chip);
  137. chip->dev = &client->dev;
  138. mutex_init(&chip->io_lock);
  139. dev_set_drvdata(chip->dev, chip);
  140. max8925_device_init(chip, pdata);
  141. return 0;
  142. }
  143. static int __devexit max8925_remove(struct i2c_client *client)
  144. {
  145. struct max8925_chip *chip = i2c_get_clientdata(client);
  146. max8925_device_exit(chip);
  147. i2c_set_clientdata(client, NULL);
  148. kfree(chip);
  149. return 0;
  150. }
  151. static struct i2c_driver max8925_driver = {
  152. .driver = {
  153. .name = "max8925",
  154. .owner = THIS_MODULE,
  155. },
  156. .probe = max8925_probe,
  157. .remove = __devexit_p(max8925_remove),
  158. .id_table = max8925_id_table,
  159. };
  160. static int __init max8925_i2c_init(void)
  161. {
  162. int ret;
  163. ret = i2c_add_driver(&max8925_driver);
  164. if (ret != 0)
  165. pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
  166. return ret;
  167. }
  168. subsys_initcall(max8925_i2c_init);
  169. static void __exit max8925_i2c_exit(void)
  170. {
  171. i2c_del_driver(&max8925_driver);
  172. }
  173. module_exit(max8925_i2c_exit);
  174. MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
  175. MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
  176. MODULE_LICENSE("GPL");