020-gateworks_i2c_pld.patch 9.4 KB

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