Advertisement
Guest User

Untitled

a guest
Mar 7th, 2013
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 7.22 KB | None | 0 0
  1. commit 2fd0b48b17aa4d1cdff10b05b741f0304f52d549
  2. Author: Pantelis Antoniou <panto@antoniou-consulting.com>
  3. Date:   Tue Mar 5 19:45:36 2013 +0200
  4.  
  5.     grove-i2c: Add rudimentary grove i2c motor control driver.
  6.    
  7.     Simple solenoid handling using grove i2c.
  8.    
  9.     Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
  10.  
  11. diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
  12. index a0f75af..3c0cbf6 100644
  13. --- a/drivers/misc/Kconfig
  14. +++ b/drivers/misc/Kconfig
  15. @@ -505,6 +505,12 @@ config GPEVT
  16.     help
  17.       Simply amazing!
  18.  
  19. +config GROVE_I2C
  20. +   tristate "Support Grove I2C Motor Driver"
  21. +   depends on OF && I2C
  22. +   help
  23. +     Say Y here to support a minimal Grove I2C Motor Driver
  24. +
  25.  source "drivers/misc/c2port/Kconfig"
  26.  source "drivers/misc/eeprom/Kconfig"
  27.  source "drivers/misc/cb710/Kconfig"
  28. diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
  29. index f063b90..72aef82 100644
  30. --- a/drivers/misc/Makefile
  31. +++ b/drivers/misc/Makefile
  32. @@ -50,4 +50,5 @@ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
  33.  obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
  34.  obj-$(CONFIG_INTEL_MEI)        += mei/
  35.  obj-$(CONFIG_GPEVT)        += gpevt.o
  36. +obj-$(CONFIG_GROVE_I2C)        += grove-i2c.o
  37.  obj-y              += cape/
  38. diff --git a/drivers/misc/grove-i2c.c b/drivers/misc/grove-i2c.c
  39. new file mode 100644
  40. index 0000000..8932616
  41. --- /dev/null
  42. +++ b/drivers/misc/grove-i2c.c
  43. @@ -0,0 +1,239 @@
  44. +/*
  45. + *  grove-i2c.c - I2C driver module for the Grove motor drivers
  46. + *
  47. + *  Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
  48. + *
  49. + *  This program is free software; you can redistribute it and/or modify
  50. + *  it under the terms of the GNU General Public License as published by
  51. + *  the Free Software Foundation; either version 2 of the License, or
  52. + *  (at your option) any later version.
  53. + *
  54. + *  This program is distributed in the hope that it will be useful,
  55. + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  56. + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  57. + *  GNU General Public License for more details.
  58. + *
  59. + *  You should have received a copy of the GNU General Public License
  60. + *  along with this program; if not, write to the Free Software
  61. + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  62. + */
  63. +
  64. +#include <linux/module.h>
  65. +#include <linux/init.h>
  66. +#include <linux/slab.h>
  67. +#include <linux/i2c.h>
  68. +#include <linux/mutex.h>
  69. +
  70. +struct grove_data {
  71. +   struct i2c_client *client;
  72. +   struct mutex lock;
  73. +
  74. +   int state[2];
  75. +#define GS_NONE            0
  76. +#define GS_SOLENOID_FORWARD    1
  77. +#define GS_SOLENOID_BACKWARD   2
  78. +
  79. +};
  80. +
  81. +static void grove_send_word(struct grove_data *data, u8 cmd, u16 val)
  82. +{
  83. +   struct i2c_client *client = data->client;
  84. +
  85. +   i2c_smbus_write_word_data(data->client, cmd, val);
  86. +}
  87. +
  88. +static int grove_set_state(struct grove_data *data, unsigned int which,
  89. +       int state)
  90. +{
  91. +   static const u8 motor_addr[2] = { 0xa1, 0xa5 };
  92. +
  93. +   if (which > 1)
  94. +       return -EINVAL;
  95. +
  96. +   switch (state) {
  97. +
  98. +       case GS_NONE:
  99. +           /* nothing */
  100. +           break;
  101. +
  102. +       case GS_SOLENOID_FORWARD:
  103. +           grove_send_word(data, motor_addr[which], 0xff01);
  104. +           break;
  105. +
  106. +       case GS_SOLENOID_BACKWARD:
  107. +           grove_send_word(data, motor_addr[which], 0x0000);
  108. +           break;
  109. +
  110. +       default:
  111. +           /* unknown state */
  112. +           return -EINVAL;
  113. +   }
  114. +
  115. +   data->state[which] = state;
  116. +
  117. +   return 0;
  118. +}
  119. +
  120. +static ssize_t grove_show_state(struct device *dev,
  121. +       struct device_attribute *attr, char *buf, unsigned int which)
  122. +{
  123. +   struct grove_data *data = i2c_get_clientdata(to_i2c_client(dev));
  124. +
  125. +   if (which > 1)
  126. +       return -EINVAL;
  127. +
  128. +   return sprintf(buf, "%u\n", data->state[which]);
  129. +}
  130. +
  131. +static ssize_t grove_store_state(struct device *dev,
  132. +       struct device_attribute *attr, const char *buf, size_t count,
  133. +       unsigned int which)
  134. +{
  135. +   struct i2c_client *client = to_i2c_client(dev);
  136. +   struct grove_data *data = i2c_get_clientdata(client);
  137. +   unsigned long val = simple_strtoul(buf, NULL, 10);
  138. +   int ret;
  139. +
  140. +   if (which > 1)
  141. +       return -EINVAL;
  142. +
  143. +   if (val < 0 || val > 2)
  144. +       return -EINVAL;
  145. +
  146. +   mutex_lock(&data->lock);
  147. +   ret = grove_set_state(data, which, val);
  148. +   mutex_unlock(&data->lock);
  149. +
  150. +   if (ret < 0)
  151. +       return ret;
  152. +
  153. +   return count;
  154. +}
  155. +
  156. +static ssize_t grove_show_stateA(struct device *dev,
  157. +       struct device_attribute *attr, char *buf)
  158. +{
  159. +   return grove_show_state(dev, attr, buf, 0);
  160. +}
  161. +
  162. +static ssize_t grove_store_stateA(struct device *dev,
  163. +       struct device_attribute *attr, const char *buf, size_t count)
  164. +{
  165. +   return grove_store_state(dev, attr, buf, count, 0);
  166. +}
  167. +
  168. +static DEVICE_ATTR(stateA, S_IWUSR | S_IRUGO,
  169. +          grove_show_stateA, grove_store_stateA);
  170. +
  171. +static ssize_t grove_show_stateB(struct device *dev,
  172. +       struct device_attribute *attr, char *buf)
  173. +{
  174. +   return grove_show_state(dev, attr, buf, 1);
  175. +}
  176. +
  177. +static ssize_t grove_store_stateB(struct device *dev,
  178. +       struct device_attribute *attr, const char *buf, size_t count)
  179. +{
  180. +   return grove_store_state(dev, attr, buf, count, 1);
  181. +}
  182. +
  183. +
  184. +static DEVICE_ATTR(stateB, S_IWUSR | S_IRUGO,
  185. +          grove_show_stateB, grove_store_stateB);
  186. +
  187. +static struct attribute *grove_attributes[] = {
  188. +   &dev_attr_stateA.attr,
  189. +   &dev_attr_stateB.attr,
  190. +   NULL
  191. +};
  192. +
  193. +static const struct attribute_group grove_attr_group = {
  194. +   .attrs = grove_attributes,
  195. +};
  196. +
  197. +static int grove_init_client(struct i2c_client *client)
  198. +{
  199. +   struct grove_data *data = i2c_get_clientdata(client);
  200. +
  201. +   data->state[0] = GS_NONE;
  202. +   data->state[1] = GS_NONE;
  203. +
  204. +   return 0;
  205. +}
  206. +
  207. +static int grove_probe(struct i2c_client *client,
  208. +                  const struct i2c_device_id *id)
  209. +{
  210. +   struct device *dev = &client->dev;
  211. +   struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
  212. +   struct grove_data *data;
  213. +   int err = 0;
  214. +
  215. +   if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
  216. +                       | I2C_FUNC_SMBUS_READ_BYTE_DATA))
  217. +       return -EIO;
  218. +
  219. +   data = devm_kzalloc(dev, sizeof(struct grove_data), GFP_KERNEL);
  220. +   if (!data)
  221. +       return -ENOMEM;
  222. +
  223. +   data->client = client;
  224. +   i2c_set_clientdata(client, data);
  225. +
  226. +   mutex_init(&data->lock);
  227. +
  228. +   /* Initialize the TSL2550 chip */
  229. +   err = grove_init_client(client);
  230. +   if (err) {
  231. +       dev_err(dev, "failed to init client\n");
  232. +       goto exit_kfree;
  233. +   }
  234. +
  235. +   /* Register sysfs hooks */
  236. +   err = sysfs_create_group(&client->dev.kobj, &grove_attr_group);
  237. +   if (err) {
  238. +       dev_err(dev, "failed to create sysfs group\n");
  239. +       goto exit_kfree;
  240. +   }
  241. +
  242. +   dev_info(dev, "Initialized OK\n");
  243. +
  244. +   return 0;
  245. +
  246. +exit_kfree:
  247. +   devm_kfree(dev, data);
  248. +   return err;
  249. +}
  250. +
  251. +static int grove_remove(struct i2c_client *client)
  252. +{
  253. +   struct grove_data *data = i2c_get_clientdata(client);
  254. +
  255. +   sysfs_remove_group(&client->dev.kobj, &grove_attr_group);
  256. +
  257. +   devm_kfree(&client->dev, data);
  258. +
  259. +   return 0;
  260. +}
  261. +
  262. +static const struct i2c_device_id grove_id[] = {
  263. +   { "grove", 0 },
  264. +   { }
  265. +};
  266. +MODULE_DEVICE_TABLE(i2c, grove_id);
  267. +
  268. +static struct i2c_driver grove_driver = {
  269. +   .driver = {
  270. +       .name   = "grove-i2c",
  271. +       .owner  = THIS_MODULE,
  272. +   },
  273. +   .probe  = grove_probe,
  274. +   .remove = grove_remove,
  275. +   .id_table = grove_id,
  276. +};
  277. +
  278. +module_i2c_driver(grove_driver);
  279. +
  280. +MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
  281. +MODULE_DESCRIPTION("Grove I2C Motor control driver");
  282. +MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement