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