Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Bitbanged MDIO support.
0004  *
0005  * Author: Scott Wood <scottwood@freescale.com>
0006  * Copyright (c) 2007 Freescale Semiconductor
0007  *
0008  * Based on CPM2 MDIO code which is:
0009  *
0010  * Copyright (c) 2003 Intracom S.A.
0011  *  by Pantelis Antoniou <panto@intracom.gr>
0012  *
0013  * 2005 (c) MontaVista Software, Inc.
0014  * Vitaly Bordug <vbordug@ru.mvista.com>
0015  */
0016 
0017 #include <linux/delay.h>
0018 #include <linux/mdio-bitbang.h>
0019 #include <linux/module.h>
0020 #include <linux/types.h>
0021 
0022 #define MDIO_READ 2
0023 #define MDIO_WRITE 1
0024 
0025 #define MDIO_C45 (1<<15)
0026 #define MDIO_C45_ADDR (MDIO_C45 | 0)
0027 #define MDIO_C45_READ (MDIO_C45 | 3)
0028 #define MDIO_C45_WRITE (MDIO_C45 | 1)
0029 
0030 #define MDIO_SETUP_TIME 10
0031 #define MDIO_HOLD_TIME 10
0032 
0033 /* Minimum MDC period is 400 ns, plus some margin for error.  MDIO_DELAY
0034  * is done twice per period.
0035  */
0036 #define MDIO_DELAY 250
0037 
0038 /* The PHY may take up to 300 ns to produce data, plus some margin
0039  * for error.
0040  */
0041 #define MDIO_READ_DELAY 350
0042 
0043 /* MDIO must already be configured as output. */
0044 static void mdiobb_send_bit(struct mdiobb_ctrl *ctrl, int val)
0045 {
0046     const struct mdiobb_ops *ops = ctrl->ops;
0047 
0048     ops->set_mdio_data(ctrl, val);
0049     ndelay(MDIO_DELAY);
0050     ops->set_mdc(ctrl, 1);
0051     ndelay(MDIO_DELAY);
0052     ops->set_mdc(ctrl, 0);
0053 }
0054 
0055 /* MDIO must already be configured as input. */
0056 static int mdiobb_get_bit(struct mdiobb_ctrl *ctrl)
0057 {
0058     const struct mdiobb_ops *ops = ctrl->ops;
0059 
0060     ndelay(MDIO_DELAY);
0061     ops->set_mdc(ctrl, 1);
0062     ndelay(MDIO_READ_DELAY);
0063     ops->set_mdc(ctrl, 0);
0064 
0065     return ops->get_mdio_data(ctrl);
0066 }
0067 
0068 /* MDIO must already be configured as output. */
0069 static void mdiobb_send_num(struct mdiobb_ctrl *ctrl, u16 val, int bits)
0070 {
0071     int i;
0072 
0073     for (i = bits - 1; i >= 0; i--)
0074         mdiobb_send_bit(ctrl, (val >> i) & 1);
0075 }
0076 
0077 /* MDIO must already be configured as input. */
0078 static u16 mdiobb_get_num(struct mdiobb_ctrl *ctrl, int bits)
0079 {
0080     int i;
0081     u16 ret = 0;
0082 
0083     for (i = bits - 1; i >= 0; i--) {
0084         ret <<= 1;
0085         ret |= mdiobb_get_bit(ctrl);
0086     }
0087 
0088     return ret;
0089 }
0090 
0091 /* Utility to send the preamble, address, and
0092  * register (common to read and write).
0093  */
0094 static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int op, u8 phy, u8 reg)
0095 {
0096     const struct mdiobb_ops *ops = ctrl->ops;
0097     int i;
0098 
0099     ops->set_mdio_dir(ctrl, 1);
0100 
0101     /*
0102      * Send a 32 bit preamble ('1's) with an extra '1' bit for good
0103      * measure.  The IEEE spec says this is a PHY optional
0104      * requirement.  The AMD 79C874 requires one after power up and
0105      * one after a MII communications error.  This means that we are
0106      * doing more preambles than we need, but it is safer and will be
0107      * much more robust.
0108      */
0109 
0110     for (i = 0; i < 32; i++)
0111         mdiobb_send_bit(ctrl, 1);
0112 
0113     /* send the start bit (01) and the read opcode (10) or write (01).
0114        Clause 45 operation uses 00 for the start and 11, 10 for
0115        read/write */
0116     mdiobb_send_bit(ctrl, 0);
0117     if (op & MDIO_C45)
0118         mdiobb_send_bit(ctrl, 0);
0119     else
0120         mdiobb_send_bit(ctrl, 1);
0121     mdiobb_send_bit(ctrl, (op >> 1) & 1);
0122     mdiobb_send_bit(ctrl, (op >> 0) & 1);
0123 
0124     mdiobb_send_num(ctrl, phy, 5);
0125     mdiobb_send_num(ctrl, reg, 5);
0126 }
0127 
0128 /* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the
0129    lower 16 bits of the 21 bit address. This transfer is done identically to a
0130    MDIO_WRITE except for a different code. To enable clause 45 mode or
0131    MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices
0132    can exist on the same bus. Normal devices should ignore the MDIO_ADDR
0133    phase. */
0134 static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)
0135 {
0136     unsigned int dev_addr = (addr >> 16) & 0x1F;
0137     unsigned int reg = addr & 0xFFFF;
0138     mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr);
0139 
0140     /* send the turnaround (10) */
0141     mdiobb_send_bit(ctrl, 1);
0142     mdiobb_send_bit(ctrl, 0);
0143 
0144     mdiobb_send_num(ctrl, reg, 16);
0145 
0146     ctrl->ops->set_mdio_dir(ctrl, 0);
0147     mdiobb_get_bit(ctrl);
0148 
0149     return dev_addr;
0150 }
0151 
0152 int mdiobb_read(struct mii_bus *bus, int phy, int reg)
0153 {
0154     struct mdiobb_ctrl *ctrl = bus->priv;
0155     int ret, i;
0156 
0157     if (reg & MII_ADDR_C45) {
0158         reg = mdiobb_cmd_addr(ctrl, phy, reg);
0159         mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
0160     } else
0161         mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
0162 
0163     ctrl->ops->set_mdio_dir(ctrl, 0);
0164 
0165     /* check the turnaround bit: the PHY should be driving it to zero, if this
0166      * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that
0167      */
0168     if (mdiobb_get_bit(ctrl) != 0 &&
0169         !(bus->phy_ignore_ta_mask & (1 << phy))) {
0170         /* PHY didn't drive TA low -- flush any bits it
0171          * may be trying to send.
0172          */
0173         for (i = 0; i < 32; i++)
0174             mdiobb_get_bit(ctrl);
0175 
0176         return 0xffff;
0177     }
0178 
0179     ret = mdiobb_get_num(ctrl, 16);
0180     mdiobb_get_bit(ctrl);
0181     return ret;
0182 }
0183 EXPORT_SYMBOL(mdiobb_read);
0184 
0185 int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
0186 {
0187     struct mdiobb_ctrl *ctrl = bus->priv;
0188 
0189     if (reg & MII_ADDR_C45) {
0190         reg = mdiobb_cmd_addr(ctrl, phy, reg);
0191         mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
0192     } else
0193         mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
0194 
0195     /* send the turnaround (10) */
0196     mdiobb_send_bit(ctrl, 1);
0197     mdiobb_send_bit(ctrl, 0);
0198 
0199     mdiobb_send_num(ctrl, val, 16);
0200 
0201     ctrl->ops->set_mdio_dir(ctrl, 0);
0202     mdiobb_get_bit(ctrl);
0203     return 0;
0204 }
0205 EXPORT_SYMBOL(mdiobb_write);
0206 
0207 struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
0208 {
0209     struct mii_bus *bus;
0210 
0211     bus = mdiobus_alloc();
0212     if (!bus)
0213         return NULL;
0214 
0215     __module_get(ctrl->ops->owner);
0216 
0217     bus->read = mdiobb_read;
0218     bus->write = mdiobb_write;
0219     bus->priv = ctrl;
0220     if (!ctrl->override_op_c22) {
0221         ctrl->op_c22_read = MDIO_READ;
0222         ctrl->op_c22_write = MDIO_WRITE;
0223     }
0224 
0225     return bus;
0226 }
0227 EXPORT_SYMBOL(alloc_mdio_bitbang);
0228 
0229 void free_mdio_bitbang(struct mii_bus *bus)
0230 {
0231     struct mdiobb_ctrl *ctrl = bus->priv;
0232 
0233     module_put(ctrl->ops->owner);
0234     mdiobus_free(bus);
0235 }
0236 EXPORT_SYMBOL(free_mdio_bitbang);
0237 
0238 MODULE_LICENSE("GPL v2");