cdc23e926f86c6f4c6809018222351041172556a
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / hifn / hifnHIPP.c
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 /*
33  * Driver for various Hifn encryption processors.
34  */
35 #include <linux/version.h>
36 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
37 #include <generated/autoconf.h>
38 #else
39 #include <linux/autoconf.h>
40 #endif
41 #include <linux/module.h>
42 #include <linux/init.h>
43 #include <linux/list.h>
44 #include <linux/slab.h>
45 #include <linux/wait.h>
46 #include <linux/sched.h>
47 #include <linux/pci.h>
48 #include <linux/delay.h>
49 #include <linux/interrupt.h>
50 #include <linux/spinlock.h>
51 #include <linux/random.h>
52 #include <linux/version.h>
53 #include <linux/skbuff.h>
54 #include <linux/uio.h>
55 #include <linux/sysfs.h>
56 #include <linux/miscdevice.h>
57 #include <asm/io.h>
58
59 #include <cryptodev.h>
60
61 #include "hifnHIPPreg.h"
62 #include "hifnHIPPvar.h"
63
64 #if 1
65 #define DPRINTF(a...)   if (hipp_debug) { \
66                                                         printk("%s: ", sc ? \
67                                                                 device_get_nameunit(sc->sc_dev) : "hifn"); \
68                                                         printk(a); \
69                                                 } else
70 #else
71 #define DPRINTF(a...)
72 #endif
73
74 typedef int bus_size_t;
75
76 static inline int
77 pci_get_revid(struct pci_dev *dev)
78 {
79         u8 rid = 0;
80         pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
81         return rid;
82 }
83
84 #define debug hipp_debug
85 int hipp_debug = 0;
86 module_param(hipp_debug, int, 0644);
87 MODULE_PARM_DESC(hipp_debug, "Enable debug");
88
89 int hipp_maxbatch = 1;
90 module_param(hipp_maxbatch, int, 0644);
91 MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
92
93 static  int  hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
94 static  void hipp_remove(struct pci_dev *dev);
95 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
96 static irqreturn_t hipp_intr(int irq, void *arg);
97 #else
98 static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
99 #endif
100
101 static int hipp_num_chips = 0;
102 static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
103
104 static  int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
105 static  int hipp_freesession(device_t, u_int64_t);
106 static  int hipp_process(device_t, struct cryptop *, int);
107
108 static device_method_t hipp_methods = {
109         /* crypto device methods */
110         DEVMETHOD(cryptodev_newsession, hipp_newsession),
111         DEVMETHOD(cryptodev_freesession,hipp_freesession),
112         DEVMETHOD(cryptodev_process,    hipp_process),
113 };
114
115 static __inline u_int32_t
116 READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
117 {
118         u_int32_t v = readl(sc->sc_bar[barno] + reg);
119         //sc->sc_bar0_lastreg = (bus_size_t) -1;
120         return (v);
121 }
122 static __inline void
123 WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
124 {
125         writel(val, sc->sc_bar[barno] + reg);
126 }
127
128 #define READ_REG_0(sc, reg)         READ_REG(sc, 0, reg)
129 #define WRITE_REG_0(sc, reg, val)   WRITE_REG(sc,0, reg, val)
130 #define READ_REG_1(sc, reg)         READ_REG(sc, 1, reg)
131 #define WRITE_REG_1(sc, reg, val)   WRITE_REG(sc,1, reg, val)
132
133 static int
134 hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
135 {
136         return EINVAL;
137 }
138
139 static int
140 hipp_freesession(device_t dev, u_int64_t tid)
141 {
142         return EINVAL;
143 }
144
145 static int
146 hipp_process(device_t dev, struct cryptop *crp, int hint)
147 {
148         return EINVAL;
149 }
150
151 static const char*
152 hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
153 {
154         char *n = NULL;
155
156         switch (pci_get_vendor(sc->sc_pcidev)) {
157         case PCI_VENDOR_HIFN:
158                 switch (pci_get_device(sc->sc_pcidev)) {
159                 case PCI_PRODUCT_HIFN_7855:     n = "Hifn 7855";
160                 case PCI_PRODUCT_HIFN_8155:     n = "Hifn 8155";
161                 case PCI_PRODUCT_HIFN_6500:     n = "Hifn 6500";
162                 }
163         }
164
165         if(n==NULL) {
166                 snprintf(buf, blen, "VID=%02x,PID=%02x",
167                          pci_get_vendor(sc->sc_pcidev),
168                          pci_get_device(sc->sc_pcidev));
169         } else {
170                 buf[0]='\0';
171                 strncat(buf, n, blen);
172         }
173         return buf;
174 }
175
176 struct hipp_fs_entry {
177         struct attribute attr;
178         /* other stuff */
179 };
180
181
182 static ssize_t
183 cryptoid_show(struct device *dev,
184               struct device_attribute *attr,
185               char *buf)                                                
186 {                                                               
187         struct hipp_softc *sc;                                  
188
189         sc = pci_get_drvdata(to_pci_dev (dev));
190         return sprintf (buf, "%d\n", sc->sc_cid);
191 }
192
193 struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
194
195 /*
196  * Attach an interface that successfully probed.
197  */
198 static int
199 hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
200 {
201         struct hipp_softc *sc = NULL;
202         int i;
203         //char rbase;
204         //u_int16_t ena;
205         int rev;
206         //int rseg;
207         int rc;
208
209         DPRINTF("%s()\n", __FUNCTION__);
210
211         if (pci_enable_device(dev) < 0)
212                 return(-ENODEV);
213
214 #ifdef CONFIG_HAVE_PCI_SET_MWI
215         if (pci_set_mwi(dev))
216                 return(-ENODEV);
217 #endif
218
219         if (!dev->irq) {
220                 printk("hifn: found device with no IRQ assigned. check BIOS settings!");
221                 pci_disable_device(dev);
222                 return(-ENODEV);
223         }
224
225         sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
226         if (!sc)
227                 return(-ENOMEM);
228         memset(sc, 0, sizeof(*sc));
229
230         softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
231
232         sc->sc_pcidev = dev;
233         sc->sc_irq = -1;
234         sc->sc_cid = -1;
235         sc->sc_num = hipp_num_chips++;
236
237         if (sc->sc_num < HIPP_MAX_CHIPS)
238                 hipp_chip_idx[sc->sc_num] = sc;
239
240         pci_set_drvdata(sc->sc_pcidev, sc);
241
242         spin_lock_init(&sc->sc_mtx);
243
244         /*
245          * Setup PCI resources.
246          * The READ_REG_0, WRITE_REG_0, READ_REG_1,
247          * and WRITE_REG_1 macros throughout the driver are used
248          * to permit better debugging.
249          */
250         for(i=0; i<4; i++) {
251                 unsigned long mem_start, mem_len;
252                 mem_start = pci_resource_start(sc->sc_pcidev, i);
253                 mem_len   = pci_resource_len(sc->sc_pcidev, i);
254                 sc->sc_barphy[i] = (caddr_t)mem_start;
255                 sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
256                 if (!sc->sc_bar[i]) {
257                         device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
258                         goto fail;
259                 }
260         }
261
262         //hipp_reset_board(sc, 0);
263         pci_set_master(sc->sc_pcidev);
264
265         /*
266          * Arrange the interrupt line.
267          */
268         rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
269         if (rc) {
270                 device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
271                 goto fail;
272         }
273         sc->sc_irq = dev->irq;
274
275         rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
276
277         {
278                 char b[32];
279                 device_printf(sc->sc_dev, "%s, rev %u",
280                               hipp_partname(sc, b, sizeof(b)), rev);
281         }
282
283 #if 0
284         if (sc->sc_flags & HIFN_IS_7956)
285                 printf(", pll=0x%x<%s clk, %ux mult>",
286                         sc->sc_pllconfig,
287                         sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
288                         2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
289 #endif
290         printf("\n");
291
292         sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
293         if (sc->sc_cid < 0) {
294                 device_printf(sc->sc_dev, "could not get crypto driver id\n");
295                 goto fail;
296         }
297
298 #if 0 /* cannot work with a non-GPL module */
299         /* make a sysfs entry to let the world know what entry we got */
300         sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
301 #endif
302
303 #if 0
304         init_timer(&sc->sc_tickto);
305         sc->sc_tickto.function = hifn_tick;
306         sc->sc_tickto.data = (unsigned long) sc->sc_num;
307         mod_timer(&sc->sc_tickto, jiffies + HZ);
308 #endif
309
310 #if 0 /* no code here yet ?? */
311         crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
312 #endif
313
314         return (0);
315
316 fail:
317         if (sc->sc_cid >= 0)
318                 crypto_unregister_all(sc->sc_cid);
319         if (sc->sc_irq != -1)
320                 free_irq(sc->sc_irq, sc);
321         
322 #if 0
323         if (sc->sc_dma) {
324                 /* Turn off DMA polling */
325                 WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
326                             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
327                 
328                 pci_free_consistent(sc->sc_pcidev,
329                                     sizeof(*sc->sc_dma),
330                                     sc->sc_dma, sc->sc_dma_physaddr);
331         }
332 #endif
333         kfree(sc);
334         return (-ENXIO);
335 }
336
337 /*
338  * Detach an interface that successfully probed.
339  */
340 static void
341 hipp_remove(struct pci_dev *dev)
342 {
343         struct hipp_softc *sc = pci_get_drvdata(dev);
344         unsigned long l_flags;
345
346         DPRINTF("%s()\n", __FUNCTION__);
347
348         /* disable interrupts */
349         HIPP_LOCK(sc);
350
351 #if 0
352         WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
353         HIFN_UNLOCK(sc);
354
355         /*XXX other resources */
356         del_timer_sync(&sc->sc_tickto);
357
358         /* Turn off DMA polling */
359         WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
360             HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
361 #endif
362
363         crypto_unregister_all(sc->sc_cid);
364
365         free_irq(sc->sc_irq, sc);
366
367 #if 0
368         pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
369                 sc->sc_dma, sc->sc_dma_physaddr);
370 #endif
371 }
372
373 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
374 static irqreturn_t hipp_intr(int irq, void *arg)
375 #else
376 static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
377 #endif
378 {
379         struct hipp_softc *sc = arg;
380
381         sc = sc; /* shut up compiler */
382
383         return IRQ_HANDLED;
384 }
385
386 static struct pci_device_id hipp_pci_tbl[] = {
387         { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
388           PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
389         { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
390           PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
391         { 0 }
392 };
393 MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
394
395 static struct pci_driver hipp_driver = {
396         .name         = "hipp",
397         .id_table     = hipp_pci_tbl,
398         .probe        = hipp_probe,
399         .remove       = hipp_remove,
400         /* add PM stuff here one day */
401 };
402
403 static int __init hipp_init (void)
404 {
405         struct hipp_softc *sc = NULL;
406         int rc;
407
408         DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
409
410         rc = pci_register_driver(&hipp_driver);
411         pci_register_driver_compat(&hipp_driver, rc);
412
413         return rc;
414 }
415
416 static void __exit hipp_exit (void)
417 {
418         pci_unregister_driver(&hipp_driver);
419 }
420
421 module_init(hipp_init);
422 module_exit(hipp_exit);
423
424 MODULE_LICENSE("BSD");
425 MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
426 MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");