Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[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 <linux/config.h>
17 #include <asm/io.h>
18
19 #include "ibm_emac_core.h"
20
21 static int __init tah_init(struct ocp_device *ocpdev)
22 {
23         struct tah_regs *p;
24
25         if (ocp_get_drvdata(ocpdev)) {
26                 printk(KERN_ERR "tah%d: already in use!\n", ocpdev->def->index);
27                 return -EBUSY;
28         }
29
30         /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
31         p = (struct tah_regs *)ioremap(ocpdev->def->paddr, sizeof(*p));
32         if (!p) {
33                 printk(KERN_ERR "tah%d: could not ioremap device registers!\n",
34                        ocpdev->def->index);
35                 return -ENOMEM;
36         }
37         ocp_set_drvdata(ocpdev, p);
38         __tah_reset(ocpdev);
39
40         return 0;
41 }
42
43 int __init tah_attach(void *emac)
44 {
45         struct ocp_enet_private *dev = emac;
46         struct ocp_func_emac_data *emacdata = dev->def->additions;
47
48         /* Check if we need to attach to a TAH */
49         if (emacdata->tah_idx >= 0) {
50                 dev->tah_dev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
51                                                emacdata->tah_idx);
52                 if (!dev->tah_dev) {
53                         printk(KERN_ERR "emac%d: unknown tah%d!\n",
54                                dev->def->index, emacdata->tah_idx);
55                         return -ENODEV;
56                 }
57                 if (tah_init(dev->tah_dev)) {
58                         printk(KERN_ERR
59                                "emac%d: tah%d initialization failed!\n",
60                                dev->def->index, emacdata->tah_idx);
61                         return -ENODEV;
62                 }
63         }
64         return 0;
65 }
66
67 void __exit __tah_fini(struct ocp_device *ocpdev)
68 {
69         struct tah_regs *p = ocp_get_drvdata(ocpdev);
70         BUG_ON(!p);
71         ocp_set_drvdata(ocpdev, NULL);
72         iounmap((void *)p);
73 }
74
75 void __tah_reset(struct ocp_device *ocpdev)
76 {
77         struct tah_regs *p = ocp_get_drvdata(ocpdev);
78         int n;
79
80         /* Reset TAH */
81         out_be32(&p->mr, TAH_MR_SR);
82         n = 100;
83         while ((in_be32(&p->mr) & TAH_MR_SR) && n)
84                 --n;
85
86         if (unlikely(!n))
87                 printk(KERN_ERR "tah%d: reset timeout\n", ocpdev->def->index);
88
89         /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
90         out_be32(&p->mr,
91                  TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
92                  TAH_MR_DIG);
93 }
94
95 int __tah_get_regs_len(struct ocp_device *ocpdev)
96 {
97         return sizeof(struct emac_ethtool_regs_subhdr) +
98             sizeof(struct tah_regs);
99 }
100
101 void *tah_dump_regs(struct ocp_device *ocpdev, void *buf)
102 {
103         struct tah_regs *dev = ocp_get_drvdata(ocpdev);
104         struct emac_ethtool_regs_subhdr *hdr = buf;
105         struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
106
107         hdr->version = 0;
108         hdr->index = ocpdev->def->index;
109         memcpy_fromio(regs, dev, sizeof(struct tah_regs));
110         return regs + 1;
111 }