NetXen: Adding new device ids.
[linux-2.6] / drivers / net / ibm_emac / ibm_emac_tah.c
1 /*
2  * drivers/net/ibm_emac/ibm_emac_tah.c
3  *
4  * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
5  *
6  * Copyright 2004 MontaVista Software, Inc.
7  * Matt Porter <mporter@kernel.crashing.org>
8  *
9  * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.net>
10  *
11  * This program is free software; you can redistribute  it and/or modify it
12  * under  the terms of  the GNU General  Public License as published by the
13  * Free Software Foundation;  either version 2 of the  License, or (at your
14  * option) any later version.
15  */
16 #include <asm/io.h>
17
18 #include "ibm_emac_core.h"
19
20 static int __init tah_init(struct ocp_device *ocpdev)
21 {
22         struct tah_regs *p;
23
24         if (ocp_get_drvdata(ocpdev)) {
25                 printk(KERN_ERR "tah%d: already in use!\n", ocpdev->def->index);
26                 return -EBUSY;
27         }
28
29         /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
30         p = (struct tah_regs *)ioremap(ocpdev->def->paddr, sizeof(*p));
31         if (!p) {
32                 printk(KERN_ERR "tah%d: could not ioremap device registers!\n",
33                        ocpdev->def->index);
34                 return -ENOMEM;
35         }
36         ocp_set_drvdata(ocpdev, p);
37         __tah_reset(ocpdev);
38
39         return 0;
40 }
41
42 int __init tah_attach(void *emac)
43 {
44         struct ocp_enet_private *dev = emac;
45         struct ocp_func_emac_data *emacdata = dev->def->additions;
46
47         /* Check if we need to attach to a TAH */
48         if (emacdata->tah_idx >= 0) {
49                 dev->tah_dev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
50                                                emacdata->tah_idx);
51                 if (!dev->tah_dev) {
52                         printk(KERN_ERR "emac%d: unknown tah%d!\n",
53                                dev->def->index, emacdata->tah_idx);
54                         return -ENODEV;
55                 }
56                 if (tah_init(dev->tah_dev)) {
57                         printk(KERN_ERR
58                                "emac%d: tah%d initialization failed!\n",
59                                dev->def->index, emacdata->tah_idx);
60                         return -ENODEV;
61                 }
62         }
63         return 0;
64 }
65
66 void __exit __tah_fini(struct ocp_device *ocpdev)
67 {
68         struct tah_regs *p = ocp_get_drvdata(ocpdev);
69         BUG_ON(!p);
70         ocp_set_drvdata(ocpdev, NULL);
71         iounmap((void *)p);
72 }
73
74 void __tah_reset(struct ocp_device *ocpdev)
75 {
76         struct tah_regs *p = ocp_get_drvdata(ocpdev);
77         int n;
78
79         /* Reset TAH */
80         out_be32(&p->mr, TAH_MR_SR);
81         n = 100;
82         while ((in_be32(&p->mr) & TAH_MR_SR) && n)
83                 --n;
84
85         if (unlikely(!n))
86                 printk(KERN_ERR "tah%d: reset timeout\n", ocpdev->def->index);
87
88         /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
89         out_be32(&p->mr,
90                  TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
91                  TAH_MR_DIG);
92 }
93
94 int __tah_get_regs_len(struct ocp_device *ocpdev)
95 {
96         return sizeof(struct emac_ethtool_regs_subhdr) +
97             sizeof(struct tah_regs);
98 }
99
100 void *tah_dump_regs(struct ocp_device *ocpdev, void *buf)
101 {
102         struct tah_regs *dev = ocp_get_drvdata(ocpdev);
103         struct emac_ethtool_regs_subhdr *hdr = buf;
104         struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
105
106         hdr->version = 0;
107         hdr->index = ocpdev->def->index;
108         memcpy_fromio(regs, dev, sizeof(struct tah_regs));
109         return regs + 1;
110 }