0551a79a2454663d15407f58a5bbd4153b4fb840
[cascardo/linux.git] / drivers / net / phy / swphy.c
1 /*
2  * Software PHY emulation
3  *
4  * Code taken from fixed_phy.c by Russell King <rmk+kernel@arm.linux.org.uk>
5  *
6  * Author: Vitaly Bordug <vbordug@ru.mvista.com>
7  *         Anton Vorontsov <avorontsov@ru.mvista.com>
8  *
9  * Copyright (c) 2006-2007 MontaVista Software, Inc.
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/export.h>
17 #include <linux/mii.h>
18 #include <linux/phy.h>
19 #include <linux/phy_fixed.h>
20
21 #include "swphy.h"
22
23 /**
24  * swphy_update_regs - update MII register array with fixed phy state
25  * @regs: array of 32 registers to update
26  * @state: fixed phy status
27  *
28  * Update the array of MII registers with the fixed phy link, speed,
29  * duplex and pause mode settings.
30  */
31 int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
32 {
33         u16 bmsr = BMSR_ANEGCAPABLE;
34         u16 bmcr = 0;
35         u16 lpagb = 0;
36         u16 lpa = 0;
37
38         if (state->duplex) {
39                 switch (state->speed) {
40                 case 1000:
41                         bmsr |= BMSR_ESTATEN;
42                         break;
43                 case 100:
44                         bmsr |= BMSR_100FULL;
45                         break;
46                 case 10:
47                         bmsr |= BMSR_10FULL;
48                         break;
49                 default:
50                         break;
51                 }
52         } else {
53                 switch (state->speed) {
54                 case 1000:
55                         bmsr |= BMSR_ESTATEN;
56                         break;
57                 case 100:
58                         bmsr |= BMSR_100HALF;
59                         break;
60                 case 10:
61                         bmsr |= BMSR_10HALF;
62                         break;
63                 default:
64                         break;
65                 }
66         }
67
68         if (state->link) {
69                 bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
70
71                 if (state->duplex) {
72                         bmcr |= BMCR_FULLDPLX;
73
74                         switch (state->speed) {
75                         case 1000:
76                                 bmcr |= BMCR_SPEED1000;
77                                 lpagb |= LPA_1000FULL;
78                                 break;
79                         case 100:
80                                 bmcr |= BMCR_SPEED100;
81                                 lpa |= LPA_100FULL;
82                                 break;
83                         case 10:
84                                 lpa |= LPA_10FULL;
85                                 break;
86                         default:
87                                 pr_warn("swphy: unknown speed\n");
88                                 return -EINVAL;
89                         }
90                 } else {
91                         switch (state->speed) {
92                         case 1000:
93                                 bmcr |= BMCR_SPEED1000;
94                                 lpagb |= LPA_1000HALF;
95                                 break;
96                         case 100:
97                                 bmcr |= BMCR_SPEED100;
98                                 lpa |= LPA_100HALF;
99                                 break;
100                         case 10:
101                                 lpa |= LPA_10HALF;
102                                 break;
103                         default:
104                                 pr_warn("swphy: unknown speed\n");
105                                 return -EINVAL;
106                         }
107                 }
108
109                 if (state->pause)
110                         lpa |= LPA_PAUSE_CAP;
111
112                 if (state->asym_pause)
113                         lpa |= LPA_PAUSE_ASYM;
114         }
115
116         regs[MII_PHYSID1] = 0;
117         regs[MII_PHYSID2] = 0;
118
119         regs[MII_BMSR] = bmsr;
120         regs[MII_BMCR] = bmcr;
121         regs[MII_LPA] = lpa;
122         regs[MII_STAT1000] = lpagb;
123
124         return 0;
125 }
126 EXPORT_SYMBOL_GPL(swphy_update_regs);