]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/phy/dp83848.c
Merge remote-tracking branch 'sound-current/for-linus'
[karo-tx-linux.git] / drivers / net / phy / dp83848.c
1 /*
2  * Driver for the Texas Instruments DP83848 PHY
3  *
4  * Copyright (C) 2015 Texas Instruments Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/module.h>
17 #include <linux/phy.h>
18
19 #define DP83848_PHY_ID                  0x20005c90
20
21 /* Registers */
22 #define DP83848_MICR                    0x11
23 #define DP83848_MISR                    0x12
24
25 /* MICR Register Fields */
26 #define DP83848_MICR_INT_OE             BIT(0) /* Interrupt Output Enable */
27 #define DP83848_MICR_INTEN              BIT(1) /* Interrupt Enable */
28
29 /* MISR Register Fields */
30 #define DP83848_MISR_RHF_INT_EN         BIT(0) /* Receive Error Counter */
31 #define DP83848_MISR_FHF_INT_EN         BIT(1) /* False Carrier Counter */
32 #define DP83848_MISR_ANC_INT_EN         BIT(2) /* Auto-negotiation complete */
33 #define DP83848_MISR_DUP_INT_EN         BIT(3) /* Duplex Status */
34 #define DP83848_MISR_SPD_INT_EN         BIT(4) /* Speed status */
35 #define DP83848_MISR_LINK_INT_EN        BIT(5) /* Link status */
36 #define DP83848_MISR_ED_INT_EN          BIT(6) /* Energy detect */
37 #define DP83848_MISR_LQM_INT_EN         BIT(7) /* Link Quality Monitor */
38
39 static int dp83848_ack_interrupt(struct phy_device *phydev)
40 {
41         int err = phy_read(phydev, DP83848_MISR);
42
43         return err < 0 ? err : 0;
44 }
45
46 static int dp83848_config_intr(struct phy_device *phydev)
47 {
48         int err;
49
50         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
51                 err = phy_write(phydev, DP83848_MICR,
52                                 DP83848_MICR_INT_OE |
53                                 DP83848_MICR_INTEN);
54                 if (err < 0)
55                         return err;
56
57                 return phy_write(phydev, DP83848_MISR,
58                                  DP83848_MISR_ANC_INT_EN |
59                                  DP83848_MISR_DUP_INT_EN |
60                                  DP83848_MISR_SPD_INT_EN |
61                                  DP83848_MISR_LINK_INT_EN);
62         }
63
64         return phy_write(phydev, DP83848_MICR, 0x0);
65 }
66
67 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
68         { DP83848_PHY_ID, 0xfffffff0 },
69         { }
70 };
71 MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
72
73 static struct phy_driver dp83848_driver[] = {
74         {
75                 .phy_id         = DP83848_PHY_ID,
76                 .phy_id_mask    = 0xfffffff0,
77                 .name           = "TI DP83848",
78                 .features       = PHY_BASIC_FEATURES,
79                 .flags          = PHY_HAS_INTERRUPT,
80
81                 .soft_reset     = genphy_soft_reset,
82                 .config_init    = genphy_config_init,
83                 .suspend        = genphy_suspend,
84                 .resume         = genphy_resume,
85                 .config_aneg    = genphy_config_aneg,
86                 .read_status    = genphy_read_status,
87
88                 /* IRQ related */
89                 .ack_interrupt  = dp83848_ack_interrupt,
90                 .config_intr    = dp83848_config_intr,
91
92                 .driver         = { .owner = THIS_MODULE, },
93         },
94 };
95 module_phy_driver(dp83848_driver);
96
97 MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
98 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com");
99 MODULE_LICENSE("GPL");