020-gateworks_i2c_pld.patch 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. --- a/drivers/gpio/Kconfig
  2. +++ b/drivers/gpio/Kconfig
  3. @@ -696,6 +696,14 @@ config GPIO_SX150X
  4. 8 bits: sx1508q
  5. 16 bits: sx1509q
  6. +config GPIO_GW_I2C_PLD
  7. + tristate "Gateworks I2C PLD GPIO Expander"
  8. + depends on I2C
  9. + help
  10. + Say yes here to provide access to the Gateworks I2C PLD GPIO
  11. + Expander. This is used at least on the GW2358-4.
  12. +
  13. +
  14. endmenu
  15. menu "MFD GPIO expanders"
  16. --- a/drivers/gpio/Makefile
  17. +++ b/drivers/gpio/Makefile
  18. @@ -40,6 +40,7 @@ obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etrax
  19. obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
  20. obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
  21. obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
  22. +obj-$(CONFIG_GPIO_GW_I2C_PLD) += gw_i2c_pld.o
  23. obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
  24. obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
  25. obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
  26. --- /dev/null
  27. +++ b/drivers/gpio/gw_i2c_pld.c
  28. @@ -0,0 +1,371 @@
  29. +/*
  30. + * Gateworks I2C PLD GPIO expander
  31. + *
  32. + * Copyright (C) 2009 Gateworks Corporation
  33. + *
  34. + * This program is free software; you can redistribute it and/or modify
  35. + * it under the terms of the GNU General Public License as published by
  36. + * the Free Software Foundation; either version 2 of the License, or
  37. + * (at your option) any later version.
  38. + *
  39. + * This program is distributed in the hope that it will be useful,
  40. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  41. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  42. + * GNU General Public License for more details.
  43. + *
  44. + * You should have received a copy of the GNU General Public License
  45. + * along with this program; if not, write to the Free Software
  46. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47. + */
  48. +
  49. +#include <linux/kernel.h>
  50. +#include <linux/slab.h>
  51. +#include <linux/hardirq.h>
  52. +#include <linux/i2c.h>
  53. +#include <linux/i2c/gw_i2c_pld.h>
  54. +#include <linux/module.h>
  55. +#include <linux/export.h>
  56. +#include <asm/gpio.h>
  57. +#include <mach/hardware.h>
  58. +
  59. +static const struct i2c_device_id gw_i2c_pld_id[] = {
  60. + { "gw_i2c_pld", 8 },
  61. + { }
  62. +};
  63. +MODULE_DEVICE_TABLE(i2c, gw_i2c_pld_id);
  64. +
  65. +/*
  66. + * The Gateworks I2C PLD chip only expose one read and one
  67. + * write register. Writing a "one" bit (to match the reset state) lets
  68. + * that pin be used as an input. It is an open-drain model.
  69. + */
  70. +
  71. +struct gw_i2c_pld {
  72. + struct gpio_chip chip;
  73. + struct i2c_client *client;
  74. + unsigned out; /* software latch */
  75. +};
  76. +
  77. +/*-------------------------------------------------------------------------*/
  78. +
  79. +/*
  80. + * The Gateworks I2C PLD chip does not properly send the acknowledge bit
  81. + * thus we cannot use standard i2c_smbus functions. We have recreated
  82. + * our own here, but we still use the rt_mutex_lock to lock the i2c_bus
  83. + * as the device still exists on the I2C bus.
  84. +*/
  85. +
  86. +#define PLD_SCL_GPIO 6
  87. +#define PLD_SDA_GPIO 7
  88. +
  89. +#define SCL_LO() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_LOW)
  90. +#define SCL_HI() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_HIGH)
  91. +#define SCL_EN() gpio_line_config(PLD_SCL_GPIO, IXP4XX_GPIO_OUT)
  92. +#define SDA_LO() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_LOW)
  93. +#define SDA_HI() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_HIGH)
  94. +#define SDA_EN() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_OUT)
  95. +#define SDA_DIS() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_IN)
  96. +#define SDA_IN(x) gpio_line_get(PLD_SDA_GPIO, &x);
  97. +
  98. +static int i2c_pld_write_byte(int address, int byte)
  99. +{
  100. + int i;
  101. +
  102. + address = (address << 1) & ~0x1;
  103. +
  104. + SDA_HI();
  105. + SDA_EN();
  106. + SCL_EN();
  107. + SCL_HI();
  108. + SDA_LO();
  109. + SCL_LO();
  110. +
  111. + for (i = 7; i >= 0; i--)
  112. + {
  113. + if (address & (1 << i))
  114. + SDA_HI();
  115. + else
  116. + SDA_LO();
  117. +
  118. + SCL_HI();
  119. + SCL_LO();
  120. + }
  121. +
  122. + SDA_DIS();
  123. + SCL_HI();
  124. + SDA_IN(i);
  125. + SCL_LO();
  126. + SDA_EN();
  127. +
  128. + for (i = 7; i >= 0; i--)
  129. + {
  130. + if (byte & (1 << i))
  131. + SDA_HI();
  132. + else
  133. + SDA_LO();
  134. + SCL_HI();
  135. + SCL_LO();
  136. + }
  137. +
  138. + SDA_DIS();
  139. + SCL_HI();
  140. + SDA_IN(i);
  141. + SCL_LO();
  142. +
  143. + SDA_HI();
  144. + SDA_EN();
  145. +
  146. + SDA_LO();
  147. + SCL_HI();
  148. + SDA_HI();
  149. + SCL_LO();
  150. + SCL_HI();
  151. +
  152. + return 0;
  153. +}
  154. +
  155. +static unsigned int i2c_pld_read_byte(int address)
  156. +{
  157. + int i = 0, byte = 0;
  158. + int bit;
  159. +
  160. + address = (address << 1) | 0x1;
  161. +
  162. + SDA_HI();
  163. + SDA_EN();
  164. + SCL_EN();
  165. + SCL_HI();
  166. + SDA_LO();
  167. + SCL_LO();
  168. +
  169. + for (i = 7; i >= 0; i--)
  170. + {
  171. + if (address & (1 << i))
  172. + SDA_HI();
  173. + else
  174. + SDA_LO();
  175. +
  176. + SCL_HI();
  177. + SCL_LO();
  178. + }
  179. +
  180. + SDA_DIS();
  181. + SCL_HI();
  182. + SDA_IN(i);
  183. + SCL_LO();
  184. + SDA_EN();
  185. +
  186. + SDA_DIS();
  187. + for (i = 7; i >= 0; i--)
  188. + {
  189. + SCL_HI();
  190. + SDA_IN(bit);
  191. + byte |= bit << i;
  192. + SCL_LO();
  193. + }
  194. +
  195. + SDA_LO();
  196. + SCL_HI();
  197. + SDA_HI();
  198. + SCL_LO();
  199. + SCL_HI();
  200. +
  201. + return byte;
  202. +}
  203. +
  204. +
  205. +static int gw_i2c_pld_input8(struct gpio_chip *chip, unsigned offset)
  206. +{
  207. + int ret;
  208. + struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
  209. + struct i2c_adapter *adap = gpio->client->adapter;
  210. +
  211. + if (in_atomic() || irqs_disabled()) {
  212. + ret = rt_mutex_trylock(&adap->bus_lock);
  213. + if (!ret)
  214. + /* I2C activity is ongoing. */
  215. + return -EAGAIN;
  216. + } else {
  217. + rt_mutex_lock(&adap->bus_lock);
  218. + }
  219. +
  220. + gpio->out |= (1 << offset);
  221. +
  222. + ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
  223. +
  224. + rt_mutex_unlock(&adap->bus_lock);
  225. +
  226. + return ret;
  227. +}
  228. +
  229. +static int gw_i2c_pld_get8(struct gpio_chip *chip, unsigned offset)
  230. +{
  231. + int ret;
  232. + s32 value;
  233. + struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
  234. + struct i2c_adapter *adap = gpio->client->adapter;
  235. +
  236. + if (in_atomic() || irqs_disabled()) {
  237. + ret = rt_mutex_trylock(&adap->bus_lock);
  238. + if (!ret)
  239. + /* I2C activity is ongoing. */
  240. + return -EAGAIN;
  241. + } else {
  242. + rt_mutex_lock(&adap->bus_lock);
  243. + }
  244. +
  245. + value = i2c_pld_read_byte(gpio->client->addr);
  246. +
  247. + rt_mutex_unlock(&adap->bus_lock);
  248. +
  249. + return (value < 0) ? 0 : (value & (1 << offset));
  250. +}
  251. +
  252. +static int gw_i2c_pld_output8(struct gpio_chip *chip, unsigned offset, int value)
  253. +{
  254. + int ret;
  255. +
  256. + struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
  257. + struct i2c_adapter *adap = gpio->client->adapter;
  258. +
  259. + unsigned bit = 1 << offset;
  260. +
  261. + if (in_atomic() || irqs_disabled()) {
  262. + ret = rt_mutex_trylock(&adap->bus_lock);
  263. + if (!ret)
  264. + /* I2C activity is ongoing. */
  265. + return -EAGAIN;
  266. + } else {
  267. + rt_mutex_lock(&adap->bus_lock);
  268. + }
  269. +
  270. +
  271. + if (value)
  272. + gpio->out |= bit;
  273. + else
  274. + gpio->out &= ~bit;
  275. +
  276. + ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
  277. +
  278. + rt_mutex_unlock(&adap->bus_lock);
  279. +
  280. + return ret;
  281. +}
  282. +
  283. +static void gw_i2c_pld_set8(struct gpio_chip *chip, unsigned offset, int value)
  284. +{
  285. + gw_i2c_pld_output8(chip, offset, value);
  286. +}
  287. +
  288. +/*-------------------------------------------------------------------------*/
  289. +
  290. +static int gw_i2c_pld_probe(struct i2c_client *client,
  291. + const struct i2c_device_id *id)
  292. +{
  293. + struct gw_i2c_pld_platform_data *pdata;
  294. + struct gw_i2c_pld *gpio;
  295. + int status;
  296. +
  297. + pdata = client->dev.platform_data;
  298. + if (!pdata)
  299. + return -ENODEV;
  300. +
  301. + /* Allocate, initialize, and register this gpio_chip. */
  302. + gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
  303. + if (!gpio)
  304. + return -ENOMEM;
  305. +
  306. + gpio->chip.base = pdata->gpio_base;
  307. + gpio->chip.can_sleep = 1;
  308. + gpio->chip.dev = &client->dev;
  309. + gpio->chip.owner = THIS_MODULE;
  310. +
  311. + gpio->chip.ngpio = pdata->nr_gpio;
  312. + gpio->chip.direction_input = gw_i2c_pld_input8;
  313. + gpio->chip.get = gw_i2c_pld_get8;
  314. + gpio->chip.direction_output = gw_i2c_pld_output8;
  315. + gpio->chip.set = gw_i2c_pld_set8;
  316. +
  317. + gpio->chip.label = client->name;
  318. +
  319. + gpio->client = client;
  320. + i2c_set_clientdata(client, gpio);
  321. +
  322. + gpio->out = 0xFF;
  323. +
  324. + status = gpiochip_add(&gpio->chip);
  325. + if (status < 0)
  326. + goto fail;
  327. +
  328. + dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
  329. + gpio->chip.base,
  330. + gpio->chip.base + gpio->chip.ngpio - 1,
  331. + client->name,
  332. + client->irq ? " (irq ignored)" : "");
  333. +
  334. + /* Let platform code set up the GPIOs and their users.
  335. + * Now is the first time anyone could use them.
  336. + */
  337. + if (pdata->setup) {
  338. + status = pdata->setup(client,
  339. + gpio->chip.base, gpio->chip.ngpio,
  340. + pdata->context);
  341. + if (status < 0)
  342. + dev_warn(&client->dev, "setup --> %d\n", status);
  343. + }
  344. +
  345. + return 0;
  346. +
  347. +fail:
  348. + dev_dbg(&client->dev, "probe error %d for '%s'\n",
  349. + status, client->name);
  350. + kfree(gpio);
  351. + return status;
  352. +}
  353. +
  354. +static int gw_i2c_pld_remove(struct i2c_client *client)
  355. +{
  356. + struct gw_i2c_pld_platform_data *pdata = client->dev.platform_data;
  357. + struct gw_i2c_pld *gpio = i2c_get_clientdata(client);
  358. + int status = 0;
  359. +
  360. + if (pdata->teardown) {
  361. + status = pdata->teardown(client,
  362. + gpio->chip.base, gpio->chip.ngpio,
  363. + pdata->context);
  364. + if (status < 0) {
  365. + dev_err(&client->dev, "%s --> %d\n",
  366. + "teardown", status);
  367. + return status;
  368. + }
  369. + }
  370. +
  371. + gpiochip_remove(&gpio->chip);
  372. + kfree(gpio);
  373. + return 0;
  374. +}
  375. +
  376. +static struct i2c_driver gw_i2c_pld_driver = {
  377. + .driver = {
  378. + .name = "gw_i2c_pld",
  379. + .owner = THIS_MODULE,
  380. + },
  381. + .probe = gw_i2c_pld_probe,
  382. + .remove = gw_i2c_pld_remove,
  383. + .id_table = gw_i2c_pld_id,
  384. +};
  385. +
  386. +static int __init gw_i2c_pld_init(void)
  387. +{
  388. + return i2c_add_driver(&gw_i2c_pld_driver);
  389. +}
  390. +module_init(gw_i2c_pld_init);
  391. +
  392. +static void __exit gw_i2c_pld_exit(void)
  393. +{
  394. + i2c_del_driver(&gw_i2c_pld_driver);
  395. +}
  396. +module_exit(gw_i2c_pld_exit);
  397. +
  398. +MODULE_LICENSE("GPL");
  399. +MODULE_AUTHOR("Chris Lang");
  400. --- /dev/null
  401. +++ b/include/linux/i2c/gw_i2c_pld.h
  402. @@ -0,0 +1,20 @@
  403. +#ifndef __LINUX_GW_I2C_PLD_H
  404. +#define __LINUX_GW_I2C_PLD_H
  405. +
  406. +/**
  407. + * The Gateworks I2C PLD Implements an additional 8 bits of GPIO through the PLD
  408. + */
  409. +
  410. +struct gw_i2c_pld_platform_data {
  411. + unsigned gpio_base;
  412. + unsigned nr_gpio;
  413. + int (*setup)(struct i2c_client *client,
  414. + int gpio, unsigned ngpio,
  415. + void *context);
  416. + int (*teardown)(struct i2c_client *client,
  417. + int gpio, unsigned ngpio,
  418. + void *context);
  419. + void *context;
  420. +};
  421. +
  422. +#endif /* __LINUX_GW_I2C_PLD_H */