i2c-prosavage.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. #ifndef I2C_HW_B_S3VIA
  81. #define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
  82. #endif
  83. /* delays */
  84. #define CYCLE_DELAY 10
  85. #define TIMEOUT (HZ / 2)
  86. /*
  87. * S3/VIA 8365/8375 registers
  88. */
  89. #define VGA_CR_IX 0x3d4
  90. #define VGA_CR_DATA 0x3d5
  91. #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
  92. #define MM_SERIAL1 0xff20
  93. #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
  94. /* based on vt8365 documentation */
  95. #define I2C_ENAB 0x10
  96. #define I2C_SCL_OUT 0x01
  97. #define I2C_SDA_OUT 0x02
  98. #define I2C_SCL_IN 0x04
  99. #define I2C_SDA_IN 0x08
  100. #define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX)
  101. #define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA)
  102. #define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA)
  103. /*
  104. * Serial bus line handling
  105. *
  106. * serial communications register as parameter in private data
  107. *
  108. * TODO: locks with other code sections accessing video registers?
  109. */
  110. static void bit_s3via_setscl(void *bus, int val)
  111. {
  112. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  113. unsigned int r;
  114. SET_CR_IX(p, p->i2c_reg);
  115. r = GET_CR_DATA(p);
  116. r |= I2C_ENAB;
  117. if (val) {
  118. r |= I2C_SCL_OUT;
  119. } else {
  120. r &= ~I2C_SCL_OUT;
  121. }
  122. SET_CR_DATA(p, r);
  123. }
  124. static void bit_s3via_setsda(void *bus, int val)
  125. {
  126. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  127. unsigned int r;
  128. SET_CR_IX(p, p->i2c_reg);
  129. r = GET_CR_DATA(p);
  130. r |= I2C_ENAB;
  131. if (val) {
  132. r |= I2C_SDA_OUT;
  133. } else {
  134. r &= ~I2C_SDA_OUT;
  135. }
  136. SET_CR_DATA(p, r);
  137. }
  138. static int bit_s3via_getscl(void *bus)
  139. {
  140. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  141. SET_CR_IX(p, p->i2c_reg);
  142. return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
  143. }
  144. static int bit_s3via_getsda(void *bus)
  145. {
  146. struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
  147. SET_CR_IX(p, p->i2c_reg);
  148. return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
  149. }
  150. /*
  151. * adapter initialisation
  152. */
  153. static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
  154. {
  155. int ret;
  156. p->adap.owner = THIS_MODULE;
  157. p->adap.id = I2C_HW_B_S3VIA;
  158. p->adap.algo_data = &p->algo;
  159. p->adap.dev.parent = &dev->dev;
  160. p->algo.setsda = bit_s3via_setsda;
  161. p->algo.setscl = bit_s3via_setscl;
  162. p->algo.getsda = bit_s3via_getsda;
  163. p->algo.getscl = bit_s3via_getscl;
  164. p->algo.udelay = CYCLE_DELAY;
  165. p->algo.mdelay = CYCLE_DELAY;
  166. p->algo.timeout = TIMEOUT;
  167. p->algo.data = p;
  168. p->mmvga = mmvga;
  169. p->i2c_reg = i2c_reg;
  170. ret = i2c_bit_add_bus(&p->adap);
  171. if (ret) {
  172. return ret;
  173. }
  174. p->adap_ok = 1;
  175. return 0;
  176. }
  177. /*
  178. * Cleanup stuff
  179. */
  180. static void prosavage_remove(struct pci_dev *dev)
  181. {
  182. struct s_i2c_chip *chip;
  183. int i, ret;
  184. chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
  185. if (!chip) {
  186. return;
  187. }
  188. for (i = MAX_BUSSES - 1; i >= 0; i--) {
  189. if (chip->i2c_bus[i].adap_ok == 0)
  190. continue;
  191. ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
  192. if (ret) {
  193. dev_err(&dev->dev, "%s not removed\n",
  194. chip->i2c_bus[i].adap.name);
  195. }
  196. }
  197. if (chip->mmio) {
  198. iounmap(chip->mmio);
  199. }
  200. kfree(chip);
  201. }
  202. /*
  203. * Detect chip and initialize it
  204. */
  205. static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
  206. {
  207. int ret;
  208. unsigned long base, len;
  209. struct s_i2c_chip *chip;
  210. struct s_i2c_bus *bus;
  211. pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
  212. chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
  213. if (chip == NULL) {
  214. return -ENOMEM;
  215. }
  216. memset(chip, 0, sizeof(struct s_i2c_chip));
  217. base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
  218. len = dev->resource[0].end - base + 1;
  219. chip->mmio = ioremap_nocache(base, len);
  220. if (chip->mmio == NULL) {
  221. dev_err(&dev->dev, "ioremap failed\n");
  222. prosavage_remove(dev);
  223. return -ENODEV;
  224. }
  225. /*
  226. * Chip initialisation
  227. */
  228. /* Unlock Extended IO Space ??? */
  229. /*
  230. * i2c bus registration
  231. */
  232. bus = &chip->i2c_bus[0];
  233. snprintf(bus->adap.name, sizeof(bus->adap.name),
  234. "ProSavage I2C bus at %02x:%02x.%x",
  235. dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  236. ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
  237. if (ret) {
  238. goto err_adap;
  239. }
  240. /*
  241. * ddc bus registration
  242. */
  243. bus = &chip->i2c_bus[1];
  244. snprintf(bus->adap.name, sizeof(bus->adap.name),
  245. "ProSavage DDC bus at %02x:%02x.%x",
  246. dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  247. ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
  248. if (ret) {
  249. goto err_adap;
  250. }
  251. return 0;
  252. err_adap:
  253. dev_err(&dev->dev, "%s failed\n", bus->adap.name);
  254. prosavage_remove(dev);
  255. return ret;
  256. }
  257. /*
  258. * Data for PCI driver interface
  259. */
  260. static struct pci_device_id prosavage_pci_tbl[] = {
  261. { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
  262. { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
  263. { 0, },
  264. };
  265. MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
  266. static struct pci_driver prosavage_driver = {
  267. .name = "prosavage_smbus",
  268. .id_table = prosavage_pci_tbl,
  269. .probe = prosavage_probe,
  270. .remove = prosavage_remove,
  271. };
  272. static int __init i2c_prosavage_init(void)
  273. {
  274. return pci_register_driver(&prosavage_driver);
  275. }
  276. static void __exit i2c_prosavage_exit(void)
  277. {
  278. pci_unregister_driver(&prosavage_driver);
  279. }
  280. MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
  281. MODULE_AUTHOR("Henk Vergonet");
  282. MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
  283. MODULE_LICENSE("GPL");
  284. module_init (i2c_prosavage_init);
  285. module_exit (i2c_prosavage_exit);