hifnHIPP.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*-
  2. * Driver for Hifn HIPP-I/II chipset
  3. * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. * Effort sponsored by Hifn Inc.
  29. *
  30. */
  31. /*
  32. * Driver for various Hifn encryption processors.
  33. */
  34. #include <linux/version.h>
  35. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
  36. #include <linux/config.h>
  37. #endif
  38. #include <linux/module.h>
  39. #include <linux/init.h>
  40. #include <linux/list.h>
  41. #include <linux/slab.h>
  42. #include <linux/wait.h>
  43. #include <linux/sched.h>
  44. #include <linux/pci.h>
  45. #include <linux/delay.h>
  46. #include <linux/interrupt.h>
  47. #include <linux/spinlock.h>
  48. #include <linux/random.h>
  49. #include <linux/skbuff.h>
  50. #include <linux/uio.h>
  51. #include <linux/sysfs.h>
  52. #include <linux/miscdevice.h>
  53. #include <asm/io.h>
  54. #include <cryptodev.h>
  55. #include "hifnHIPPreg.h"
  56. #include "hifnHIPPvar.h"
  57. #if 1
  58. #define DPRINTF(a...) if (hipp_debug) { \
  59. printk("%s: ", sc ? \
  60. device_get_nameunit(sc->sc_dev) : "hifn"); \
  61. printk(a); \
  62. } else
  63. #else
  64. #define DPRINTF(a...)
  65. #endif
  66. typedef int bus_size_t;
  67. static inline int
  68. pci_get_revid(struct pci_dev *dev)
  69. {
  70. u8 rid = 0;
  71. pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
  72. return rid;
  73. }
  74. #define debug hipp_debug
  75. int hipp_debug = 0;
  76. module_param(hipp_debug, int, 0644);
  77. MODULE_PARM_DESC(hipp_debug, "Enable debug");
  78. int hipp_maxbatch = 1;
  79. module_param(hipp_maxbatch, int, 0644);
  80. MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
  81. static int hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
  82. static void hipp_remove(struct pci_dev *dev);
  83. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
  84. static irqreturn_t hipp_intr(int irq, void *arg);
  85. #else
  86. static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
  87. #endif
  88. static int hipp_num_chips = 0;
  89. static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
  90. static int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
  91. static int hipp_freesession(device_t, u_int64_t);
  92. static int hipp_process(device_t, struct cryptop *, int);
  93. static device_method_t hipp_methods = {
  94. /* crypto device methods */
  95. DEVMETHOD(cryptodev_newsession, hipp_newsession),
  96. DEVMETHOD(cryptodev_freesession,hipp_freesession),
  97. DEVMETHOD(cryptodev_process, hipp_process),
  98. };
  99. static __inline u_int32_t
  100. READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
  101. {
  102. u_int32_t v = readl(sc->sc_bar[barno] + reg);
  103. //sc->sc_bar0_lastreg = (bus_size_t) -1;
  104. return (v);
  105. }
  106. static __inline void
  107. WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
  108. {
  109. writel(val, sc->sc_bar[barno] + reg);
  110. }
  111. #define READ_REG_0(sc, reg) READ_REG(sc, 0, reg)
  112. #define WRITE_REG_0(sc, reg, val) WRITE_REG(sc,0, reg, val)
  113. #define READ_REG_1(sc, reg) READ_REG(sc, 1, reg)
  114. #define WRITE_REG_1(sc, reg, val) WRITE_REG(sc,1, reg, val)
  115. static int
  116. hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
  117. {
  118. return EINVAL;
  119. }
  120. static int
  121. hipp_freesession(device_t dev, u_int64_t tid)
  122. {
  123. return EINVAL;
  124. }
  125. static int
  126. hipp_process(device_t dev, struct cryptop *crp, int hint)
  127. {
  128. return EINVAL;
  129. }
  130. static const char*
  131. hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
  132. {
  133. char *n = NULL;
  134. switch (pci_get_vendor(sc->sc_pcidev)) {
  135. case PCI_VENDOR_HIFN:
  136. switch (pci_get_device(sc->sc_pcidev)) {
  137. case PCI_PRODUCT_HIFN_7855: n = "Hifn 7855";
  138. case PCI_PRODUCT_HIFN_8155: n = "Hifn 8155";
  139. case PCI_PRODUCT_HIFN_6500: n = "Hifn 6500";
  140. }
  141. }
  142. if(n==NULL) {
  143. snprintf(buf, blen, "VID=%02x,PID=%02x",
  144. pci_get_vendor(sc->sc_pcidev),
  145. pci_get_device(sc->sc_pcidev));
  146. } else {
  147. buf[0]='\0';
  148. strncat(buf, n, blen);
  149. }
  150. return buf;
  151. }
  152. struct hipp_fs_entry {
  153. struct attribute attr;
  154. /* other stuff */
  155. };
  156. static ssize_t
  157. cryptoid_show(struct device *dev,
  158. struct device_attribute *attr,
  159. char *buf)
  160. {
  161. struct hipp_softc *sc;
  162. sc = pci_get_drvdata(to_pci_dev (dev));
  163. return sprintf (buf, "%d\n", sc->sc_cid);
  164. }
  165. struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
  166. /*
  167. * Attach an interface that successfully probed.
  168. */
  169. static int
  170. hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
  171. {
  172. struct hipp_softc *sc = NULL;
  173. int i;
  174. //char rbase;
  175. //u_int16_t ena;
  176. int rev;
  177. //int rseg;
  178. int rc;
  179. DPRINTF("%s()\n", __FUNCTION__);
  180. if (pci_enable_device(dev) < 0)
  181. return(-ENODEV);
  182. if (pci_set_mwi(dev))
  183. return(-ENODEV);
  184. if (!dev->irq) {
  185. printk("hifn: found device with no IRQ assigned. check BIOS settings!");
  186. pci_disable_device(dev);
  187. return(-ENODEV);
  188. }
  189. sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
  190. if (!sc)
  191. return(-ENOMEM);
  192. memset(sc, 0, sizeof(*sc));
  193. softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
  194. sc->sc_pcidev = dev;
  195. sc->sc_irq = -1;
  196. sc->sc_cid = -1;
  197. sc->sc_num = hipp_num_chips++;
  198. if (sc->sc_num < HIPP_MAX_CHIPS)
  199. hipp_chip_idx[sc->sc_num] = sc;
  200. pci_set_drvdata(sc->sc_pcidev, sc);
  201. spin_lock_init(&sc->sc_mtx);
  202. /*
  203. * Setup PCI resources.
  204. * The READ_REG_0, WRITE_REG_0, READ_REG_1,
  205. * and WRITE_REG_1 macros throughout the driver are used
  206. * to permit better debugging.
  207. */
  208. for(i=0; i<4; i++) {
  209. unsigned long mem_start, mem_len;
  210. mem_start = pci_resource_start(sc->sc_pcidev, i);
  211. mem_len = pci_resource_len(sc->sc_pcidev, i);
  212. sc->sc_barphy[i] = (caddr_t)mem_start;
  213. sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
  214. if (!sc->sc_bar[i]) {
  215. device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
  216. goto fail;
  217. }
  218. }
  219. //hipp_reset_board(sc, 0);
  220. pci_set_master(sc->sc_pcidev);
  221. /*
  222. * Arrange the interrupt line.
  223. */
  224. rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
  225. if (rc) {
  226. device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
  227. goto fail;
  228. }
  229. sc->sc_irq = dev->irq;
  230. rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
  231. {
  232. char b[32];
  233. device_printf(sc->sc_dev, "%s, rev %u",
  234. hipp_partname(sc, b, sizeof(b)), rev);
  235. }
  236. #if 0
  237. if (sc->sc_flags & HIFN_IS_7956)
  238. printf(", pll=0x%x<%s clk, %ux mult>",
  239. sc->sc_pllconfig,
  240. sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
  241. 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
  242. #endif
  243. printf("\n");
  244. sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
  245. if (sc->sc_cid < 0) {
  246. device_printf(sc->sc_dev, "could not get crypto driver id\n");
  247. goto fail;
  248. }
  249. #if 0 /* cannot work with a non-GPL module */
  250. /* make a sysfs entry to let the world know what entry we got */
  251. sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
  252. #endif
  253. #if 0
  254. init_timer(&sc->sc_tickto);
  255. sc->sc_tickto.function = hifn_tick;
  256. sc->sc_tickto.data = (unsigned long) sc->sc_num;
  257. mod_timer(&sc->sc_tickto, jiffies + HZ);
  258. #endif
  259. #if 0 /* no code here yet ?? */
  260. crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
  261. #endif
  262. return (0);
  263. fail:
  264. if (sc->sc_cid >= 0)
  265. crypto_unregister_all(sc->sc_cid);
  266. if (sc->sc_irq != -1)
  267. free_irq(sc->sc_irq, sc);
  268. #if 0
  269. if (sc->sc_dma) {
  270. /* Turn off DMA polling */
  271. WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  272. HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  273. pci_free_consistent(sc->sc_pcidev,
  274. sizeof(*sc->sc_dma),
  275. sc->sc_dma, sc->sc_dma_physaddr);
  276. }
  277. #endif
  278. kfree(sc);
  279. return (-ENXIO);
  280. }
  281. /*
  282. * Detach an interface that successfully probed.
  283. */
  284. static void
  285. hipp_remove(struct pci_dev *dev)
  286. {
  287. struct hipp_softc *sc = pci_get_drvdata(dev);
  288. unsigned long l_flags;
  289. DPRINTF("%s()\n", __FUNCTION__);
  290. /* disable interrupts */
  291. HIPP_LOCK(sc);
  292. #if 0
  293. WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
  294. HIFN_UNLOCK(sc);
  295. /*XXX other resources */
  296. del_timer_sync(&sc->sc_tickto);
  297. /* Turn off DMA polling */
  298. WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
  299. HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
  300. #endif
  301. crypto_unregister_all(sc->sc_cid);
  302. free_irq(sc->sc_irq, sc);
  303. #if 0
  304. pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
  305. sc->sc_dma, sc->sc_dma_physaddr);
  306. #endif
  307. }
  308. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
  309. static irqreturn_t hipp_intr(int irq, void *arg)
  310. #else
  311. static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
  312. #endif
  313. {
  314. struct hipp_softc *sc = arg;
  315. sc = sc; /* shut up compiler */
  316. return IRQ_HANDLED;
  317. }
  318. static struct pci_device_id hipp_pci_tbl[] = {
  319. { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
  320. PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
  321. { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
  322. PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
  323. { 0 }, /* terminating entry */
  324. };
  325. MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
  326. static struct pci_driver hipp_driver = {
  327. .name = "hipp",
  328. .id_table = hipp_pci_tbl,
  329. .probe = hipp_probe,
  330. .remove = hipp_remove,
  331. /* add PM stuff here one day */
  332. };
  333. static int __init hipp_init (void)
  334. {
  335. struct hipp_softc *sc = NULL;
  336. int rc;
  337. DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
  338. rc = pci_register_driver(&hipp_driver);
  339. pci_register_driver_compat(&hipp_driver, rc);
  340. return rc;
  341. }
  342. static void __exit hipp_exit (void)
  343. {
  344. pci_unregister_driver(&hipp_driver);
  345. }
  346. module_init(hipp_init);
  347. module_exit(hipp_exit);
  348. MODULE_LICENSE("Dual BSD/GPL");
  349. MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
  350. MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");