diff options
Diffstat (limited to 'drivers/net/phy/mdio-bitbang.c')
-rw-r--r-- | drivers/net/phy/mdio-bitbang.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index 19e70d7e27ab..65391891d8c4 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c | |||
@@ -22,8 +22,13 @@ | |||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | 24 | ||
25 | #define MDIO_READ 1 | 25 | #define MDIO_READ 2 |
26 | #define MDIO_WRITE 0 | 26 | #define MDIO_WRITE 1 |
27 | |||
28 | #define MDIO_C45 (1<<15) | ||
29 | #define MDIO_C45_ADDR (MDIO_C45 | 0) | ||
30 | #define MDIO_C45_READ (MDIO_C45 | 3) | ||
31 | #define MDIO_C45_WRITE (MDIO_C45 | 1) | ||
27 | 32 | ||
28 | #define MDIO_SETUP_TIME 10 | 33 | #define MDIO_SETUP_TIME 10 |
29 | #define MDIO_HOLD_TIME 10 | 34 | #define MDIO_HOLD_TIME 10 |
@@ -89,7 +94,7 @@ static u16 mdiobb_get_num(struct mdiobb_ctrl *ctrl, int bits) | |||
89 | /* Utility to send the preamble, address, and | 94 | /* Utility to send the preamble, address, and |
90 | * register (common to read and write). | 95 | * register (common to read and write). |
91 | */ | 96 | */ |
92 | static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int read, u8 phy, u8 reg) | 97 | static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int op, u8 phy, u8 reg) |
93 | { | 98 | { |
94 | const struct mdiobb_ops *ops = ctrl->ops; | 99 | const struct mdiobb_ops *ops = ctrl->ops; |
95 | int i; | 100 | int i; |
@@ -108,23 +113,56 @@ static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int read, u8 phy, u8 reg) | |||
108 | for (i = 0; i < 32; i++) | 113 | for (i = 0; i < 32; i++) |
109 | mdiobb_send_bit(ctrl, 1); | 114 | mdiobb_send_bit(ctrl, 1); |
110 | 115 | ||
111 | /* send the start bit (01) and the read opcode (10) or write (10) */ | 116 | /* send the start bit (01) and the read opcode (10) or write (10). |
117 | Clause 45 operation uses 00 for the start and 11, 10 for | ||
118 | read/write */ | ||
112 | mdiobb_send_bit(ctrl, 0); | 119 | mdiobb_send_bit(ctrl, 0); |
113 | mdiobb_send_bit(ctrl, 1); | 120 | if (op & MDIO_C45) |
114 | mdiobb_send_bit(ctrl, read); | 121 | mdiobb_send_bit(ctrl, 0); |
115 | mdiobb_send_bit(ctrl, !read); | 122 | else |
123 | mdiobb_send_bit(ctrl, 1); | ||
124 | mdiobb_send_bit(ctrl, (op >> 1) & 1); | ||
125 | mdiobb_send_bit(ctrl, (op >> 0) & 1); | ||
116 | 126 | ||
117 | mdiobb_send_num(ctrl, phy, 5); | 127 | mdiobb_send_num(ctrl, phy, 5); |
118 | mdiobb_send_num(ctrl, reg, 5); | 128 | mdiobb_send_num(ctrl, reg, 5); |
119 | } | 129 | } |
120 | 130 | ||
131 | /* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the | ||
132 | lower 16 bits of the 21 bit address. This transfer is done identically to a | ||
133 | MDIO_WRITE except for a different code. To enable clause 45 mode or | ||
134 | MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices | ||
135 | can exist on the same bus. Normal devices should ignore the MDIO_ADDR | ||
136 | phase. */ | ||
137 | static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr) | ||
138 | { | ||
139 | unsigned int dev_addr = (addr >> 16) & 0x1F; | ||
140 | unsigned int reg = addr & 0xFFFF; | ||
141 | mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr); | ||
142 | |||
143 | /* send the turnaround (10) */ | ||
144 | mdiobb_send_bit(ctrl, 1); | ||
145 | mdiobb_send_bit(ctrl, 0); | ||
146 | |||
147 | mdiobb_send_num(ctrl, reg, 16); | ||
148 | |||
149 | ctrl->ops->set_mdio_dir(ctrl, 0); | ||
150 | mdiobb_get_bit(ctrl); | ||
151 | |||
152 | return dev_addr; | ||
153 | } | ||
121 | 154 | ||
122 | static int mdiobb_read(struct mii_bus *bus, int phy, int reg) | 155 | static int mdiobb_read(struct mii_bus *bus, int phy, int reg) |
123 | { | 156 | { |
124 | struct mdiobb_ctrl *ctrl = bus->priv; | 157 | struct mdiobb_ctrl *ctrl = bus->priv; |
125 | int ret, i; | 158 | int ret, i; |
126 | 159 | ||
127 | mdiobb_cmd(ctrl, MDIO_READ, phy, reg); | 160 | if (reg & MII_ADDR_C45) { |
161 | reg = mdiobb_cmd_addr(ctrl, phy, reg); | ||
162 | mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); | ||
163 | } else | ||
164 | mdiobb_cmd(ctrl, MDIO_READ, phy, reg); | ||
165 | |||
128 | ctrl->ops->set_mdio_dir(ctrl, 0); | 166 | ctrl->ops->set_mdio_dir(ctrl, 0); |
129 | 167 | ||
130 | /* check the turnaround bit: the PHY should be driving it to zero */ | 168 | /* check the turnaround bit: the PHY should be driving it to zero */ |
@@ -147,7 +185,11 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) | |||
147 | { | 185 | { |
148 | struct mdiobb_ctrl *ctrl = bus->priv; | 186 | struct mdiobb_ctrl *ctrl = bus->priv; |
149 | 187 | ||
150 | mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); | 188 | if (reg & MII_ADDR_C45) { |
189 | reg = mdiobb_cmd_addr(ctrl, phy, reg); | ||
190 | mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); | ||
191 | } else | ||
192 | mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); | ||
151 | 193 | ||
152 | /* send the turnaround (10) */ | 194 | /* send the turnaround (10) */ |
153 | mdiobb_send_bit(ctrl, 1); | 195 | mdiobb_send_bit(ctrl, 1); |