i2c-prosavage.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * kernel/busses/i2c-prosavage.c
  3. *
  4. * i2c bus driver for S3/VIA 8365/8375 graphics processor.
  5. * Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org>
  6. * Based on code written by:
  7. * Frodo Looijaard <frodol@dds.nl>,
  8. * Philip Edelbrock <phil@netroedge.com>,
  9. * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
  10. * Mark D. Studebaker <mdsxyz123@yahoo.com>
  11. * Simon Vogl
  12. * and others
  13. *
  14. * Please read the lm_sensors documentation for details on use.
  15. *
  16. * This program is free software; you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation; either version 2 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29. *
  30. */
  31. /* 18-05-2003 HVE - created
  32. * 14-06-2003 HVE - adapted for lm_sensors2
  33. * 17-06-2003 HVE - linux 2.5.xx compatible
  34. * 18-06-2003 HVE - codingstyle
  35. * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx
  36. * codingstyle, mmio enabled
  37. *
  38. * This driver interfaces to the I2C bus of the VIA north bridge embedded
  39. * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips.
  40. *
  41. * Graphics cores:
  42. * S3/VIA KM266/VT8375 aka ProSavage8
  43. * S3/VIA KM133/VT8365 aka Savage4
  44. *
  45. * Two serial busses are implemented:
  46. * SERIAL1 - I2C serial communications interface
  47. * SERIAL2 - DDC2 monitor communications interface
  48. *
  49. * Tested on a FX41 mainboard, see http://www.shuttle.com
  50. *
  51. *
  52. * TODO:
  53. * - integration with prosavage framebuffer device
  54. * (Additional documentation needed :(
  55. */
  56. #include <linux/module.h>
  57. #include <linux/init.h>
  58. #include <linux/pci.h>
  59. #include <linux/i2c.h>
  60. #include <linux/i2c-algo-bit.h>
  61. #include <asm/io.h>
  62. /*
  63. * driver configuration
  64. */
  65. #define MAX_BUSSES 2
  66. struct s_i2c_bus {
  67. void __iomem *mmvga;
  68. int i2c_reg;
  69. int adap_ok;
  70. struct i2c_adapter adap;
  71. struct i2c_algo_bit_data algo;
  72. };
  73. struct s_i2c_chip {
  74. void __iomem *mmio;
  75. struct s_i2c_bus i2c_bus[MAX_BUSSES];
  76. };
  77. /*
  78. * i2c configuration
  79. */
  80. #define CYCLE_DELAY 10
  81. #define TIMEOUT (HZ / 2)
  82. /*
  83. * S3/VIA 8365/8375 registers
  84. */
  85. #define VGA_CR_IX 0x3d4
  86. #define VGA_CR_DATA 0x3d5
  87. #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
  88. #define MM_SERIAL1 0xff20
  89. #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
  90. /* based on vt8365 documentation */
  91. #define I2C_ENAB 0x10
  92. #define I2C_SCL_OUT 0x01
  93. #define I2C_SDA_OUT 0x02
  94. #define I2C_SCL_IN 0x04
  95. #define I2C_SDA_IN 0x08
  96. #define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX)
  97. #define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA)
  98. #define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA)
  99. /*
  100. * Serial bus line handling
  101. *
  102. * serial communications register as parameter in private data
  103. *
  104. * TODO: locks with other code sections accessing video registers?
  105. */
  106. static void bit_s3via_setscl(void *bus, int val)
  107. {
  108. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  109. unsigned int r;
  110. SET_CR_IX(p, p->i2c_reg);
  111. r = GET_CR_DATA(p);
  112. r |= I2C_ENAB;
  113. if (val) {
  114. r |= I2C_SCL_OUT;
  115. } else {
  116. r &= ~I2C_SCL_OUT;
  117. }
  118. SET_CR_DATA(p, r);
  119. }
  120. static void bit_s3via_setsda(void *bus, int val)
  121. {
  122. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  123. unsigned int r;
  124. SET_CR_IX(p, p->i2c_reg);
  125. r = GET_CR_DATA(p);
  126. r |= I2C_ENAB;
  127. if (val) {
  128. r |= I2C_SDA_OUT;
  129. } else {
  130. r &= ~I2C_SDA_OUT;
  131. }
  132. SET_CR_DATA(p, r);
  133. }
  134. static int bit_s3via_getscl(void *bus)
  135. {
  136. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  137. SET_CR_IX(p, p->i2c_reg);
  138. return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
  139. }
  140. static int bit_s3via_getsda(void *bus)
  141. {
  142. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  143. SET_CR_IX(p, p->i2c_reg);
  144. return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
  145. }
  146. /*
  147. * adapter initialisation
  148. */
  149. static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
  150. {
  151. int ret;
  152. p->adap.owner = THIS_MODULE;
  153. p->adap.id = I2C_HW_B_S3VIA;
  154. p->adap.algo_data = &p->algo;
  155. p->adap.dev.parent = &dev->dev;
  156. p->algo.setsda = bit_s3via_setsda;
  157. p->algo.setscl = bit_s3via_setscl;
  158. p->algo.getsda = bit_s3via_getsda;
  159. p->algo.getscl = bit_s3via_getscl;
  160. p->algo.udelay = CYCLE_DELAY;
  161. p->algo.mdelay = CYCLE_DELAY;
  162. p->algo.timeout = TIMEOUT;
  163. p->algo.data = p;
  164. p->mmvga = mmvga;
  165. p->i2c_reg = i2c_reg;
  166. ret = i2c_bit_add_bus(&p->adap);
  167. if (ret) {
  168. return ret;
  169. }
  170. p->adap_ok = 1;
  171. return 0;
  172. }
  173. /*
  174. * Cleanup stuff
  175. */
  176. static void prosavage_remove(struct pci_dev *dev)
  177. {
  178. struct s_i2c_chip *chip;
  179. int i, ret;
  180. chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
  181. if (!chip) {
  182. return;
  183. }
  184. for (i = MAX_BUSSES - 1; i >= 0; i--) {
  185. if (chip->i2c_bus[i].adap_ok == 0)
  186. continue;
  187. ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
  188. if (ret) {
  189. dev_err(&dev->dev, "%s not removed\n",
  190. chip->i2c_bus[i].adap.name);
  191. }
  192. }
  193. if (chip->mmio) {
  194. iounmap(chip->mmio);
  195. }
  196. kfree(chip);
  197. }
  198. /*
  199. * Detect chip and initialize it
  200. */
  201. static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
  202. {
  203. int ret;
  204. unsigned long base, len;
  205. struct s_i2c_chip *chip;
  206. struct s_i2c_bus *bus;
  207. pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
  208. chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
  209. if (chip == NULL) {
  210. return -ENOMEM;
  211. }
  212. base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
  213. len = dev->resource[0].end - base + 1;
  214. chip->mmio = ioremap_nocache(base, len);
  215. if (chip->mmio == NULL) {
  216. dev_err(&dev->dev, "ioremap failed\n");
  217. prosavage_remove(dev);
  218. return -ENODEV;
  219. }
  220. /*
  221. * Chip initialisation
  222. */
  223. /* Unlock Extended IO Space ??? */
  224. /*
  225. * i2c bus registration
  226. */
  227. bus = &chip->i2c_bus[0];
  228. snprintf(bus->adap.name, sizeof(bus->adap.name),
  229. "ProSavage I2C bus at %02x:%02x.%x",
  230. dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  231. ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
  232. if (ret) {
  233. goto err_adap;
  234. }
  235. /*
  236. * ddc bus registration
  237. */
  238. bus = &chip->i2c_bus[1];
  239. snprintf(bus->adap.name, sizeof(bus->adap.name),
  240. "ProSavage DDC bus at %02x:%02x.%x",
  241. dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  242. ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
  243. if (ret) {
  244. goto err_adap;
  245. }
  246. return 0;
  247. err_adap:
  248. dev_err(&dev->dev, "%s failed\n", bus->adap.name);
  249. prosavage_remove(dev);
  250. return ret;
  251. }
  252. /*
  253. * Data for PCI driver interface
  254. */
  255. static struct pci_device_id prosavage_pci_tbl[] = {
  256. { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
  257. { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
  258. { 0, },
  259. };
  260. MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
  261. static struct pci_driver prosavage_driver = {
  262. .name = "prosavage_smbus",
  263. .id_table = prosavage_pci_tbl,
  264. .probe = prosavage_probe,
  265. .remove = prosavage_remove,
  266. };
  267. static int __init i2c_prosavage_init(void)
  268. {
  269. return pci_register_driver(&prosavage_driver);
  270. }
  271. static void __exit i2c_prosavage_exit(void)
  272. {
  273. pci_unregister_driver(&prosavage_driver);
  274. }
  275. MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
  276. MODULE_AUTHOR("Henk Vergonet");
  277. MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
  278. MODULE_LICENSE("GPL");
  279. module_init (i2c_prosavage_init);
  280. module_exit (i2c_prosavage_exit);