Root/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
74typedef int bus_size_t;
75
76static inline int
77pci_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
85int hipp_debug = 0;
86module_param(hipp_debug, int, 0644);
87MODULE_PARM_DESC(hipp_debug, "Enable debug");
88
89int hipp_maxbatch = 1;
90module_param(hipp_maxbatch, int, 0644);
91MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
92
93static int hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
94static void hipp_remove(struct pci_dev *dev);
95#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
96static irqreturn_t hipp_intr(int irq, void *arg);
97#else
98static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
99#endif
100
101static int hipp_num_chips = 0;
102static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
103
104static int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
105static int hipp_freesession(device_t, u_int64_t);
106static int hipp_process(device_t, struct cryptop *, int);
107
108static 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
115static __inline u_int32_t
116READ_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}
122static __inline void
123WRITE_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
133static int
134hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
135{
136    return EINVAL;
137}
138
139static int
140hipp_freesession(device_t dev, u_int64_t tid)
141{
142    return EINVAL;
143}
144
145static int
146hipp_process(device_t dev, struct cryptop *crp, int hint)
147{
148    return EINVAL;
149}
150
151static const char*
152hipp_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
176struct hipp_fs_entry {
177    struct attribute attr;
178    /* other stuff */
179};
180
181
182static ssize_t
183cryptoid_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
193struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
194
195/*
196 * Attach an interface that successfully probed.
197 */
198static int
199hipp_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
316fail:
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 */
340static void
341hipp_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)
374static irqreturn_t hipp_intr(int irq, void *arg)
375#else
376static 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
386static 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};
393MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
394
395static 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
403static 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
416static void __exit hipp_exit (void)
417{
418    pci_unregister_driver(&hipp_driver);
419}
420
421module_init(hipp_init);
422module_exit(hipp_exit);
423
424MODULE_LICENSE("BSD");
425MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
426MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");
427

Archive Download this file



interactive