1 /*
2 * Copyright (c) 2024 Microchip Technology Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/net/mdio.h>
8 #include <zephyr/net/phy.h>
9 #include <errno.h>
10
11 /* Open Alliance TC14 (10BASE-T1S) PLCA registers */
12 #define MDIO_OATC14_PLCA_IDVER 0xca00 /* PLCA ID and version */
13 #define MDIO_OATC14_PLCA_CTRL0 0xca01 /* PLCA Control register 0 */
14 #define MDIO_OATC14_PLCA_CTRL1 0xca02 /* PLCA Control register 1 */
15 #define MDIO_OATC14_PLCA_STATUS 0xca03 /* PLCA Status register */
16 #define MDIO_OATC14_PLCA_TOTMR 0xca04 /* PLCA TO Timer register */
17 #define MDIO_OATC14_PLCA_BURST 0xca05 /* PLCA BURST mode register */
18
19 /* Open Alliance TC14 PLCA IDVER register */
20 #define MDIO_OATC14_PLCA_IDM GENMASK(15, 8) /* PLCA MAP ID */
21 #define MDIO_OATC14_PLCA_VER GENMASK(7, 0) /* PLCA MAP version */
22
23 /* Open Alliance TC14 PLCA CTRL0 register */
24 #define MDIO_OATC14_PLCA_EN BIT(15) /* PLCA enable */
25 #define MDIO_OATC14_PLCA_RST BIT(14) /* PLCA reset */
26
27 /* Open Alliance TC14 PLCA CTRL1 register */
28 #define MDIO_OATC14_PLCA_NCNT GENMASK(15, 8) /* PLCA node count */
29 #define MDIO_OATC14_PLCA_ID GENMASK(7, 0) /* PLCA local node ID */
30
31 /* Open Alliance TC14 PLCA STATUS register */
32 #define MDIO_OATC14_PLCA_PST BIT(15) /* PLCA status indication */
33
34 /* Open Alliance TC14 PLCA TOTMR register */
35 #define MDIO_OATC14_PLCA_TOT GENMASK(7, 0)
36
37 /* Open Alliance TC14 PLCA BURST register */
38 #define MDIO_OATC14_PLCA_MAXBC GENMASK(15, 8)
39 #define MDIO_OATC14_PLCA_BTMR GENMASK(7, 0)
40
41 /* Version Identifiers */
42 #define OATC14_IDM 0x0a00
43
genphy_set_plca_cfg(const struct device * dev,struct phy_plca_cfg * plca_cfg)44 int genphy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
45 {
46 uint16_t val;
47 int ret;
48
49 /* Disable plca before doing the configuration */
50 ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0, 0x0);
51 if (ret) {
52 return ret;
53 }
54
55 if (!plca_cfg->enable) {
56 /* As the PLCA is disabled above, just return */
57 return 0;
58 }
59
60 val = (plca_cfg->node_count << 8) | plca_cfg->node_id;
61 ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL1, val);
62 if (ret) {
63 return ret;
64 }
65
66 val = (plca_cfg->burst_count << 8) | plca_cfg->burst_timer;
67 ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_BURST, val);
68 if (ret) {
69 return ret;
70 }
71
72 ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_TOTMR,
73 plca_cfg->to_timer);
74 if (ret) {
75 return ret;
76 }
77
78 /* Enable plca after doing all the configuration */
79 return phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0,
80 MDIO_OATC14_PLCA_EN);
81 }
82
genphy_get_plca_cfg(const struct device * dev,struct phy_plca_cfg * plca_cfg)83 int genphy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
84 {
85 uint16_t val;
86 int ret;
87
88 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_IDVER, &val);
89 if (ret) {
90 return ret;
91 }
92
93 if ((val & MDIO_OATC14_PLCA_IDM) != OATC14_IDM) {
94 return -ENODEV;
95 }
96
97 plca_cfg->version = ret & ~MDIO_OATC14_PLCA_IDM;
98
99 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0, &val);
100 if (ret) {
101 return ret;
102 }
103
104 plca_cfg->enable = !!(val & MDIO_OATC14_PLCA_EN);
105
106 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL1, &val);
107 if (ret) {
108 return ret;
109 }
110
111 plca_cfg->node_id = val & MDIO_OATC14_PLCA_ID;
112 plca_cfg->node_count = (val & MDIO_OATC14_PLCA_NCNT) >> 8;
113
114 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_BURST, &val);
115 if (ret) {
116 return ret;
117 }
118
119 plca_cfg->burst_timer = val & MDIO_OATC14_PLCA_BTMR;
120 plca_cfg->burst_count = (val & MDIO_OATC14_PLCA_MAXBC) >> 8;
121
122 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_TOTMR, &val);
123 if (ret) {
124 return ret;
125 }
126
127 plca_cfg->to_timer = val & MDIO_OATC14_PLCA_TOT;
128
129 return 0;
130 }
131
genphy_get_plca_sts(const struct device * dev,bool * plca_sts)132 int genphy_get_plca_sts(const struct device *dev, bool *plca_sts)
133 {
134 uint16_t val;
135 int ret;
136
137 ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_STATUS, &val);
138 if (ret) {
139 return ret;
140 }
141
142 *plca_sts = !!(val & MDIO_OATC14_PLCA_PST);
143
144 return 0;
145 }
146