Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: mdio: mdio-bitbang: Separate C22 and C45 transactions

The bitbbanging bus driver can perform both C22 and C45 transfers.
Create separate functions for each and register the C45 versions using
the new driver API calls.

The SH Ethernet driver places wrappers around these functions. In
order to not break boards which might be using C45, add similar
wrappers for C45 operations.

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Andrew Lunn and committed by
Jakub Kicinski
002dd3de ce30fa56

+130 -40
+31 -6
drivers/net/ethernet/renesas/sh_eth.c
··· 3044 3044 return 0; 3045 3045 } 3046 3046 3047 - static int sh_mdiobb_read(struct mii_bus *bus, int phy, int reg) 3047 + static int sh_mdiobb_read_c22(struct mii_bus *bus, int phy, int reg) 3048 3048 { 3049 3049 int res; 3050 3050 3051 3051 pm_runtime_get_sync(bus->parent); 3052 - res = mdiobb_read(bus, phy, reg); 3052 + res = mdiobb_read_c22(bus, phy, reg); 3053 3053 pm_runtime_put(bus->parent); 3054 3054 3055 3055 return res; 3056 3056 } 3057 3057 3058 - static int sh_mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) 3058 + static int sh_mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val) 3059 3059 { 3060 3060 int res; 3061 3061 3062 3062 pm_runtime_get_sync(bus->parent); 3063 - res = mdiobb_write(bus, phy, reg, val); 3063 + res = mdiobb_write_c22(bus, phy, reg, val); 3064 + pm_runtime_put(bus->parent); 3065 + 3066 + return res; 3067 + } 3068 + 3069 + static int sh_mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg) 3070 + { 3071 + int res; 3072 + 3073 + pm_runtime_get_sync(bus->parent); 3074 + res = mdiobb_read_c45(bus, phy, devad, reg); 3075 + pm_runtime_put(bus->parent); 3076 + 3077 + return res; 3078 + } 3079 + 3080 + static int sh_mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, 3081 + int reg, u16 val) 3082 + { 3083 + int res; 3084 + 3085 + pm_runtime_get_sync(bus->parent); 3086 + res = mdiobb_write_c45(bus, phy, devad, reg, val); 3064 3087 pm_runtime_put(bus->parent); 3065 3088 3066 3089 return res; ··· 3114 3091 return -ENOMEM; 3115 3092 3116 3093 /* Wrap accessors with Runtime PM-aware ops */ 3117 - mdp->mii_bus->read = sh_mdiobb_read; 3118 - mdp->mii_bus->write = sh_mdiobb_write; 3094 + mdp->mii_bus->read = sh_mdiobb_read_c22; 3095 + mdp->mii_bus->write = sh_mdiobb_write_c22; 3096 + mdp->mii_bus->read_c45 = sh_mdiobb_read_c45; 3097 + mdp->mii_bus->write_c45 = sh_mdiobb_write_c45; 3119 3098 3120 3099 /* Hook up MII support for ethtool */ 3121 3100 mdp->mii_bus->name = "sh_mii";
+43 -7
drivers/net/ethernet/ti/davinci_mdio.c
··· 225 225 return test_bit(MDIO_PIN, &reg); 226 226 } 227 227 228 - static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg) 228 + static int davinci_mdiobb_read_c22(struct mii_bus *bus, int phy, int reg) 229 229 { 230 230 int ret; 231 231 ··· 233 233 if (ret < 0) 234 234 return ret; 235 235 236 - ret = mdiobb_read(bus, phy, reg); 236 + ret = mdiobb_read_c22(bus, phy, reg); 237 237 238 238 pm_runtime_mark_last_busy(bus->parent); 239 239 pm_runtime_put_autosuspend(bus->parent); ··· 241 241 return ret; 242 242 } 243 243 244 - static int davinci_mdiobb_write(struct mii_bus *bus, int phy, int reg, 245 - u16 val) 244 + static int davinci_mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, 245 + u16 val) 246 246 { 247 247 int ret; 248 248 ··· 250 250 if (ret < 0) 251 251 return ret; 252 252 253 - ret = mdiobb_write(bus, phy, reg, val); 253 + ret = mdiobb_write_c22(bus, phy, reg, val); 254 + 255 + pm_runtime_mark_last_busy(bus->parent); 256 + pm_runtime_put_autosuspend(bus->parent); 257 + 258 + return ret; 259 + } 260 + 261 + static int davinci_mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, 262 + int reg) 263 + { 264 + int ret; 265 + 266 + ret = pm_runtime_resume_and_get(bus->parent); 267 + if (ret < 0) 268 + return ret; 269 + 270 + ret = mdiobb_read_c45(bus, phy, devad, reg); 271 + 272 + pm_runtime_mark_last_busy(bus->parent); 273 + pm_runtime_put_autosuspend(bus->parent); 274 + 275 + return ret; 276 + } 277 + 278 + static int davinci_mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, 279 + int reg, u16 val) 280 + { 281 + int ret; 282 + 283 + ret = pm_runtime_resume_and_get(bus->parent); 284 + if (ret < 0) 285 + return ret; 286 + 287 + ret = mdiobb_write_c45(bus, phy, devad, reg, val); 254 288 255 289 pm_runtime_mark_last_busy(bus->parent); 256 290 pm_runtime_put_autosuspend(bus->parent); ··· 607 573 data->bus->name = dev_name(dev); 608 574 609 575 if (data->manual_mode) { 610 - data->bus->read = davinci_mdiobb_read; 611 - data->bus->write = davinci_mdiobb_write; 576 + data->bus->read = davinci_mdiobb_read_c22; 577 + data->bus->write = davinci_mdiobb_write_c22; 578 + data->bus->read_c45 = davinci_mdiobb_read_c45; 579 + data->bus->write_c45 = davinci_mdiobb_write_c45; 612 580 data->bus->reset = davinci_mdiobb_reset; 613 581 614 582 dev_info(dev, "Configuring MDIO in manual mode\n");
+52 -25
drivers/net/mdio/mdio-bitbang.c
··· 127 127 128 128 /* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the 129 129 lower 16 bits of the 21 bit address. This transfer is done identically to a 130 - MDIO_WRITE except for a different code. To enable clause 45 mode or 131 - MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices 132 - can exist on the same bus. Normal devices should ignore the MDIO_ADDR 130 + MDIO_WRITE except for a different code. Theoretically clause 45 and normal 131 + devices can exist on the same bus. Normal devices should ignore the MDIO_ADDR 133 132 phase. */ 134 - static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr) 133 + static void mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, int dev_addr, 134 + int reg) 135 135 { 136 - unsigned int dev_addr = (addr >> 16) & 0x1F; 137 - unsigned int reg = addr & 0xFFFF; 138 136 mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr); 139 137 140 138 /* send the turnaround (10) */ ··· 143 145 144 146 ctrl->ops->set_mdio_dir(ctrl, 0); 145 147 mdiobb_get_bit(ctrl); 146 - 147 - return dev_addr; 148 148 } 149 149 150 - int mdiobb_read(struct mii_bus *bus, int phy, int reg) 150 + static int mdiobb_read_common(struct mii_bus *bus, int phy) 151 151 { 152 152 struct mdiobb_ctrl *ctrl = bus->priv; 153 153 int ret, i; 154 - 155 - if (reg & MII_ADDR_C45) { 156 - reg = mdiobb_cmd_addr(ctrl, phy, reg); 157 - mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); 158 - } else 159 - mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); 160 154 161 155 ctrl->ops->set_mdio_dir(ctrl, 0); 162 156 ··· 170 180 mdiobb_get_bit(ctrl); 171 181 return ret; 172 182 } 173 - EXPORT_SYMBOL(mdiobb_read); 174 183 175 - int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) 184 + int mdiobb_read_c22(struct mii_bus *bus, int phy, int reg) 176 185 { 177 186 struct mdiobb_ctrl *ctrl = bus->priv; 178 187 179 - if (reg & MII_ADDR_C45) { 180 - reg = mdiobb_cmd_addr(ctrl, phy, reg); 181 - mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); 182 - } else 183 - mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); 188 + mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); 189 + 190 + return mdiobb_read_common(bus, phy); 191 + } 192 + EXPORT_SYMBOL(mdiobb_read_c22); 193 + 194 + int mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg) 195 + { 196 + struct mdiobb_ctrl *ctrl = bus->priv; 197 + 198 + mdiobb_cmd_addr(ctrl, phy, devad, reg); 199 + mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); 200 + 201 + return mdiobb_read_common(bus, phy); 202 + } 203 + EXPORT_SYMBOL(mdiobb_read_c45); 204 + 205 + static int mdiobb_write_common(struct mii_bus *bus, u16 val) 206 + { 207 + struct mdiobb_ctrl *ctrl = bus->priv; 184 208 185 209 /* send the turnaround (10) */ 186 210 mdiobb_send_bit(ctrl, 1); ··· 206 202 mdiobb_get_bit(ctrl); 207 203 return 0; 208 204 } 209 - EXPORT_SYMBOL(mdiobb_write); 205 + 206 + int mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val) 207 + { 208 + struct mdiobb_ctrl *ctrl = bus->priv; 209 + 210 + mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); 211 + 212 + return mdiobb_write_common(bus, val); 213 + } 214 + EXPORT_SYMBOL(mdiobb_write_c22); 215 + 216 + int mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, int reg, u16 val) 217 + { 218 + struct mdiobb_ctrl *ctrl = bus->priv; 219 + 220 + mdiobb_cmd_addr(ctrl, phy, devad, reg); 221 + mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); 222 + 223 + return mdiobb_write_common(bus, val); 224 + } 225 + EXPORT_SYMBOL(mdiobb_write_c45); 210 226 211 227 struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) 212 228 { ··· 238 214 239 215 __module_get(ctrl->ops->owner); 240 216 241 - bus->read = mdiobb_read; 242 - bus->write = mdiobb_write; 217 + bus->read = mdiobb_read_c22; 218 + bus->write = mdiobb_write_c22; 219 + bus->read_c45 = mdiobb_read_c45; 220 + bus->write_c45 = mdiobb_write_c45; 221 + 243 222 bus->priv = ctrl; 244 223 if (!ctrl->override_op_c22) { 245 224 ctrl->op_c22_read = MDIO_READ;
+4 -2
include/linux/mdio-bitbang.h
··· 38 38 u8 op_c22_write; 39 39 }; 40 40 41 - int mdiobb_read(struct mii_bus *bus, int phy, int reg); 42 - int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val); 41 + int mdiobb_read_c22(struct mii_bus *bus, int phy, int reg); 42 + int mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val); 43 + int mdiobb_read_c45(struct mii_bus *bus, int devad, int phy, int reg); 44 + int mdiobb_write_c45(struct mii_bus *bus, int devad, int phy, int reg, u16 val); 43 45 44 46 /* The returned bus is not yet registered with the phy layer. */ 45 47 struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl);