This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / net / ibm_emac / ibm_emac_rgmii.c
1 /*
2  * drivers/net/ibm_emac/ibm_emac_rgmii.c
3  *
4  * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
5  *
6  * Copyright (c) 2004, 2005 Zultys Technologies.
7  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
8  *
9  * Based on original work by
10  *      Matt Porter <mporter@kernel.crashing.org>
11  *      Copyright 2004 MontaVista Software, Inc.
12  * 
13  * This program is free software; you can redistribute  it and/or modify it
14  * under  the terms of  the GNU General  Public License as published by the
15  * Free Software Foundation;  either version 2 of the  License, or (at your
16  * option) any later version.
17  *
18  */
19 #include <linux/config.h>
20 #include <linux/kernel.h>
21 #include <linux/ethtool.h>
22 #include <asm/io.h>
23
24 #include "ibm_emac_core.h"
25 #include "ibm_emac_debug.h"
26
27 /* RGMIIx_FER */
28 #define RGMII_FER_MASK(idx)     (0x7 << ((idx) * 4))
29 #define RGMII_FER_RTBI(idx)     (0x4 << ((idx) * 4))
30 #define RGMII_FER_RGMII(idx)    (0x5 << ((idx) * 4))
31 #define RGMII_FER_TBI(idx)      (0x6 << ((idx) * 4))
32 #define RGMII_FER_GMII(idx)     (0x7 << ((idx) * 4))
33
34 /* RGMIIx_SSR */
35 #define RGMII_SSR_MASK(idx)     (0x7 << ((idx) * 8))
36 #define RGMII_SSR_100(idx)      (0x2 << ((idx) * 8))
37 #define RGMII_SSR_1000(idx)     (0x4 << ((idx) * 8))
38
39 /* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
40 static inline int rgmii_valid_mode(int phy_mode)
41 {
42         return  phy_mode == PHY_MODE_GMII ||
43                 phy_mode == PHY_MODE_RGMII ||
44                 phy_mode == PHY_MODE_TBI ||
45                 phy_mode == PHY_MODE_RTBI;
46 }
47
48 static inline const char *rgmii_mode_name(int mode)
49 {
50         switch (mode) {
51         case PHY_MODE_RGMII:
52                 return "RGMII";
53         case PHY_MODE_TBI:
54                 return "TBI";
55         case PHY_MODE_GMII:
56                 return "GMII";
57         case PHY_MODE_RTBI:
58                 return "RTBI";
59         default:
60                 BUG();
61         }
62 }
63
64 static inline u32 rgmii_mode_mask(int mode, int input)
65 {
66         switch (mode) {
67         case PHY_MODE_RGMII:
68                 return RGMII_FER_RGMII(input);
69         case PHY_MODE_TBI:
70                 return RGMII_FER_TBI(input);
71         case PHY_MODE_GMII:
72                 return RGMII_FER_GMII(input);
73         case PHY_MODE_RTBI:
74                 return RGMII_FER_RTBI(input);
75         default:
76                 BUG();
77         }
78 }
79
80 static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode)
81 {
82         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
83         struct rgmii_regs *p;
84
85         RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode);
86
87         if (!dev) {
88                 dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
89                 if (!dev) {
90                         printk(KERN_ERR
91                                "rgmii%d: couldn't allocate device structure!\n",
92                                ocpdev->def->index);
93                         return -ENOMEM;
94                 }
95
96                 p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr,
97                                                  sizeof(struct rgmii_regs));
98                 if (!p) {
99                         printk(KERN_ERR
100                                "rgmii%d: could not ioremap device registers!\n",
101                                ocpdev->def->index);
102                         kfree(dev);
103                         return -ENOMEM;
104                 }
105
106                 dev->base = p;
107                 ocp_set_drvdata(ocpdev, dev);
108
109                 /* Disable all inputs by default */
110                 out_be32(&p->fer, 0);
111         } else
112                 p = dev->base;
113
114         /* Enable this input */
115         out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));
116
117         printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
118                ocpdev->def->index, input, rgmii_mode_name(mode));
119
120         ++dev->users;
121         return 0;
122 }
123
124 int __init rgmii_attach(void *emac)
125 {
126         struct ocp_enet_private *dev = emac;
127         struct ocp_func_emac_data *emacdata = dev->def->additions;
128
129         /* Check if we need to attach to a RGMII */
130         if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) {
131                 dev->rgmii_input = emacdata->rgmii_mux;
132                 dev->rgmii_dev =
133                     ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII,
134                                     emacdata->rgmii_idx);
135                 if (!dev->rgmii_dev) {
136                         printk(KERN_ERR "emac%d: unknown rgmii%d!\n",
137                                dev->def->index, emacdata->rgmii_idx);
138                         return -ENODEV;
139                 }
140                 if (rgmii_init
141                     (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) {
142                         printk(KERN_ERR
143                                "emac%d: rgmii%d initialization failed!\n",
144                                dev->def->index, emacdata->rgmii_idx);
145                         return -ENODEV;
146                 }
147         }
148         return 0;
149 }
150
151 void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
152 {
153         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
154         u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input);
155
156         RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
157
158         if (speed == SPEED_1000)
159                 ssr |= RGMII_SSR_1000(input);
160         else if (speed == SPEED_100)
161                 ssr |= RGMII_SSR_100(input);
162
163         out_be32(&dev->base->ssr, ssr);
164 }
165
166 void __exit __rgmii_fini(struct ocp_device *ocpdev, int input)
167 {
168         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
169         BUG_ON(!dev || dev->users == 0);
170
171         RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
172
173         /* Disable this input */
174         out_be32(&dev->base->fer,
175                  in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input));
176
177         if (!--dev->users) {
178                 /* Free everything if this is the last user */
179                 ocp_set_drvdata(ocpdev, NULL);
180                 iounmap((void *)dev->base);
181                 kfree(dev);
182         }
183 }
184
185 int __rgmii_get_regs_len(struct ocp_device *ocpdev)
186 {
187         return sizeof(struct emac_ethtool_regs_subhdr) +
188             sizeof(struct rgmii_regs);
189 }
190
191 void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf)
192 {
193         struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
194         struct emac_ethtool_regs_subhdr *hdr = buf;
195         struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
196
197         hdr->version = 0;
198         hdr->index = ocpdev->def->index;
199         memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));
200         return regs + 1;
201 }