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