0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/phy.h>
0010
0011 #define TI_DP83848C_PHY_ID 0x20005ca0
0012 #define TI_DP83620_PHY_ID 0x20005ce0
0013 #define NS_DP83848C_PHY_ID 0x20005c90
0014 #define TLK10X_PHY_ID 0x2000a210
0015
0016
0017 #define DP83848_MICR 0x11
0018 #define DP83848_MISR 0x12
0019
0020
0021 #define DP83848_MICR_INT_OE BIT(0)
0022 #define DP83848_MICR_INTEN BIT(1)
0023
0024
0025 #define DP83848_MISR_RHF_INT_EN BIT(0)
0026 #define DP83848_MISR_FHF_INT_EN BIT(1)
0027 #define DP83848_MISR_ANC_INT_EN BIT(2)
0028 #define DP83848_MISR_DUP_INT_EN BIT(3)
0029 #define DP83848_MISR_SPD_INT_EN BIT(4)
0030 #define DP83848_MISR_LINK_INT_EN BIT(5)
0031 #define DP83848_MISR_ED_INT_EN BIT(6)
0032 #define DP83848_MISR_LQM_INT_EN BIT(7)
0033
0034 #define DP83848_INT_EN_MASK \
0035 (DP83848_MISR_ANC_INT_EN | \
0036 DP83848_MISR_DUP_INT_EN | \
0037 DP83848_MISR_SPD_INT_EN | \
0038 DP83848_MISR_LINK_INT_EN)
0039
0040 #define DP83848_MISR_RHF_INT BIT(8)
0041 #define DP83848_MISR_FHF_INT BIT(9)
0042 #define DP83848_MISR_ANC_INT BIT(10)
0043 #define DP83848_MISR_DUP_INT BIT(11)
0044 #define DP83848_MISR_SPD_INT BIT(12)
0045 #define DP83848_MISR_LINK_INT BIT(13)
0046 #define DP83848_MISR_ED_INT BIT(14)
0047
0048 #define DP83848_INT_MASK \
0049 (DP83848_MISR_ANC_INT | \
0050 DP83848_MISR_DUP_INT | \
0051 DP83848_MISR_SPD_INT | \
0052 DP83848_MISR_LINK_INT)
0053
0054 static int dp83848_ack_interrupt(struct phy_device *phydev)
0055 {
0056 int err = phy_read(phydev, DP83848_MISR);
0057
0058 return err < 0 ? err : 0;
0059 }
0060
0061 static int dp83848_config_intr(struct phy_device *phydev)
0062 {
0063 int control, ret;
0064
0065 control = phy_read(phydev, DP83848_MICR);
0066 if (control < 0)
0067 return control;
0068
0069 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0070 ret = dp83848_ack_interrupt(phydev);
0071 if (ret)
0072 return ret;
0073
0074 control |= DP83848_MICR_INT_OE;
0075 control |= DP83848_MICR_INTEN;
0076
0077 ret = phy_write(phydev, DP83848_MISR, DP83848_INT_EN_MASK);
0078 if (ret < 0)
0079 return ret;
0080
0081 ret = phy_write(phydev, DP83848_MICR, control);
0082 } else {
0083 control &= ~DP83848_MICR_INTEN;
0084 ret = phy_write(phydev, DP83848_MICR, control);
0085 if (ret)
0086 return ret;
0087
0088 ret = dp83848_ack_interrupt(phydev);
0089 }
0090
0091 return ret;
0092 }
0093
0094 static irqreturn_t dp83848_handle_interrupt(struct phy_device *phydev)
0095 {
0096 int irq_status;
0097
0098 irq_status = phy_read(phydev, DP83848_MISR);
0099 if (irq_status < 0) {
0100 phy_error(phydev);
0101 return IRQ_NONE;
0102 }
0103
0104 if (!(irq_status & DP83848_INT_MASK))
0105 return IRQ_NONE;
0106
0107 phy_trigger_machine(phydev);
0108
0109 return IRQ_HANDLED;
0110 }
0111
0112 static int dp83848_config_init(struct phy_device *phydev)
0113 {
0114 int val;
0115
0116
0117
0118
0119 val = phy_read(phydev, MII_BMCR);
0120 if (!(val & BMCR_ANENABLE))
0121 phydev->autoneg = AUTONEG_DISABLE;
0122
0123 return 0;
0124 }
0125
0126 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
0127 { TI_DP83848C_PHY_ID, 0xfffffff0 },
0128 { NS_DP83848C_PHY_ID, 0xfffffff0 },
0129 { TI_DP83620_PHY_ID, 0xfffffff0 },
0130 { TLK10X_PHY_ID, 0xfffffff0 },
0131 { }
0132 };
0133 MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
0134
0135 #define DP83848_PHY_DRIVER(_id, _name, _config_init) \
0136 { \
0137 .phy_id = _id, \
0138 .phy_id_mask = 0xfffffff0, \
0139 .name = _name, \
0140 \
0141 \
0142 .soft_reset = genphy_soft_reset, \
0143 .config_init = _config_init, \
0144 .suspend = genphy_suspend, \
0145 .resume = genphy_resume, \
0146 \
0147 \
0148 .config_intr = dp83848_config_intr, \
0149 .handle_interrupt = dp83848_handle_interrupt, \
0150 }
0151
0152 static struct phy_driver dp83848_driver[] = {
0153 DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY",
0154 NULL),
0155 DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY",
0156 NULL),
0157 DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY",
0158 dp83848_config_init),
0159 DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY",
0160 NULL),
0161 };
0162 module_phy_driver(dp83848_driver);
0163
0164 MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
0165 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
0166 MODULE_LICENSE("GPL v2");