2 * Driver for Hifn HIPP-I/II chipset
3 * Copyright (c) 2006 Michael Richardson <mcr@xelerance.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 * Effort sponsored by Hifn Inc.
33 * Driver for various Hifn encryption processors.
35 #include <linux/version.h>
36 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
37 #include <generated/autoconf.h>
39 #include <linux/autoconf.h>
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>
59 #include <cryptodev.h>
61 #include "hifnHIPPreg.h"
62 #include "hifnHIPPvar.h"
65 #define DPRINTF(a...) if (hipp_debug) { \
67 device_get_nameunit(sc->sc_dev) : "hifn"); \
74 typedef int bus_size_t
;
77 pci_get_revid(struct pci_dev
*dev
)
80 pci_read_config_byte(dev
, PCI_REVISION_ID
, &rid
);
84 #define debug hipp_debug
86 module_param(hipp_debug
, int, 0644);
87 MODULE_PARM_DESC(hipp_debug
, "Enable debug");
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");
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
);
98 static irqreturn_t
hipp_intr(int irq
, void *arg
, struct pt_regs
*regs
);
101 static int hipp_num_chips
= 0;
102 static struct hipp_softc
*hipp_chip_idx
[HIPP_MAX_CHIPS
];
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);
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
),
115 static __inline u_int32_t
116 READ_REG(struct hipp_softc
*sc
, unsigned int barno
, bus_size_t reg
)
118 u_int32_t v
= readl(sc
->sc_bar
[barno
] + reg
);
119 //sc->sc_bar0_lastreg = (bus_size_t) -1;
123 WRITE_REG(struct hipp_softc
*sc
, unsigned int barno
, bus_size_t reg
, u_int32_t val
)
125 writel(val
, sc
->sc_bar
[barno
] + reg
);
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)
134 hipp_newsession(device_t dev
, u_int32_t
*sidp
, struct cryptoini
*cri
)
140 hipp_freesession(device_t dev
, u_int64_t tid
)
146 hipp_process(device_t dev
, struct cryptop
*crp
, int hint
)
152 hipp_partname(struct hipp_softc
*sc
, char buf
[128], size_t blen
)
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";
166 snprintf(buf
, blen
, "VID=%02x,PID=%02x",
167 pci_get_vendor(sc
->sc_pcidev
),
168 pci_get_device(sc
->sc_pcidev
));
171 strncat(buf
, n
, blen
);
176 struct hipp_fs_entry
{
177 struct attribute attr
;
183 cryptoid_show(struct device
*dev
,
184 struct device_attribute
*attr
,
187 struct hipp_softc
*sc
;
189 sc
= pci_get_drvdata(to_pci_dev (dev
));
190 return sprintf (buf
, "%d\n", sc
->sc_cid
);
193 struct device_attribute hipp_dev_cryptoid
= __ATTR_RO(cryptoid
);
196 * Attach an interface that successfully probed.
199 hipp_probe(struct pci_dev
*dev
, const struct pci_device_id
*ent
)
201 struct hipp_softc
*sc
= NULL
;
209 DPRINTF("%s()\n", __FUNCTION__
);
211 if (pci_enable_device(dev
) < 0)
214 #ifdef CONFIG_HAVE_PCI_SET_MWI
215 if (pci_set_mwi(dev
))
220 printk("hifn: found device with no IRQ assigned. check BIOS settings!");
221 pci_disable_device(dev
);
225 sc
= (struct hipp_softc
*) kmalloc(sizeof(*sc
), GFP_KERNEL
);
228 memset(sc
, 0, sizeof(*sc
));
230 softc_device_init(sc
, "hifn-hipp", hipp_num_chips
, hipp_methods
);
235 sc
->sc_num
= hipp_num_chips
++;
237 if (sc
->sc_num
< HIPP_MAX_CHIPS
)
238 hipp_chip_idx
[sc
->sc_num
] = sc
;
240 pci_set_drvdata(sc
->sc_pcidev
, sc
);
242 spin_lock_init(&sc
->sc_mtx
);
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.
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
);
262 //hipp_reset_board(sc, 0);
263 pci_set_master(sc
->sc_pcidev
);
266 * Arrange the interrupt line.
268 rc
= request_irq(dev
->irq
, hipp_intr
, IRQF_SHARED
, "hifn", sc
);
270 device_printf(sc
->sc_dev
, "could not map interrupt: %d\n", rc
);
273 sc
->sc_irq
= dev
->irq
;
275 rev
= READ_REG_1(sc
, HIPP_1_REVID
) & 0xffff;
279 device_printf(sc
->sc_dev
, "%s, rev %u",
280 hipp_partname(sc
, b
, sizeof(b
)), rev
);
284 if (sc
->sc_flags
& HIFN_IS_7956
)
285 printf(", pll=0x%x<%s clk, %ux mult>",
287 sc
->sc_pllconfig
& HIFN_PLL_REF_SEL
? "ext" : "pci",
288 2 + 2*((sc
->sc_pllconfig
& HIFN_PLL_ND
) >> 11));
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");
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
);
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
);
310 #if 0 /* no code here yet ?? */
311 crypto_register(sc
->sc_cid
, CRYPTO_3DES_CBC
, 0, 0);
318 crypto_unregister_all(sc
->sc_cid
);
319 if (sc
->sc_irq
!= -1)
320 free_irq(sc
->sc_irq
, sc
);
324 /* Turn off DMA polling */
325 WRITE_REG_1(sc
, HIFN_1_DMA_CNFG
, HIFN_DMACNFG_MSTRESET
|
326 HIFN_DMACNFG_DMARESET
| HIFN_DMACNFG_MODE
);
328 pci_free_consistent(sc
->sc_pcidev
,
330 sc
->sc_dma
, sc
->sc_dma_physaddr
);
338 * Detach an interface that successfully probed.
341 hipp_remove(struct pci_dev
*dev
)
343 struct hipp_softc
*sc
= pci_get_drvdata(dev
);
344 unsigned long l_flags
;
346 DPRINTF("%s()\n", __FUNCTION__
);
348 /* disable interrupts */
352 WRITE_REG_1(sc
, HIFN_1_DMA_IER
, 0);
355 /*XXX other resources */
356 del_timer_sync(&sc
->sc_tickto
);
358 /* Turn off DMA polling */
359 WRITE_REG_1(sc
, HIFN_1_DMA_CNFG
, HIFN_DMACNFG_MSTRESET
|
360 HIFN_DMACNFG_DMARESET
| HIFN_DMACNFG_MODE
);
363 crypto_unregister_all(sc
->sc_cid
);
365 free_irq(sc
->sc_irq
, sc
);
368 pci_free_consistent(sc
->sc_pcidev
, sizeof(*sc
->sc_dma
),
369 sc
->sc_dma
, sc
->sc_dma_physaddr
);
373 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
374 static irqreturn_t
hipp_intr(int irq
, void *arg
)
376 static irqreturn_t
hipp_intr(int irq
, void *arg
, struct pt_regs
*regs
)
379 struct hipp_softc
*sc
= arg
;
381 sc
= sc
; /* shut up compiler */
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, },
393 MODULE_DEVICE_TABLE(pci
, hipp_pci_tbl
);
395 static struct pci_driver hipp_driver
= {
397 .id_table
= hipp_pci_tbl
,
399 .remove
= hipp_remove
,
400 /* add PM stuff here one day */
403 static int __init
hipp_init (void)
405 struct hipp_softc
*sc
= NULL
;
408 DPRINTF("%s(%p)\n", __FUNCTION__
, hipp_init
);
410 rc
= pci_register_driver(&hipp_driver
);
411 pci_register_driver_compat(&hipp_driver
, rc
);
416 static void __exit
hipp_exit (void)
418 pci_unregister_driver(&hipp_driver
);
421 module_init(hipp_init
);
422 module_exit(hipp_exit
);
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");