1 /*
2  * Copyright (c) 2023 DENX Software Engineering GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef OA_TC6_CFG_H__
7 #define OA_TC6_CFG_H__
8 
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/drivers/spi.h>
14 #include <zephyr/net/net_pkt.h>
15 
16 #define MMS_REG(m, r)        ((((m) & GENMASK(3, 0)) << 16) | ((r) & GENMASK(15, 0)))
17 /* Memory Map Sector (MMS) 0 */
18 #define OA_ID                MMS_REG(0x0, 0x000) /* expect 0x11 */
19 #define OA_PHYID             MMS_REG(0x0, 0x001)
20 #define OA_RESET             MMS_REG(0x0, 0x003)
21 #define OA_RESET_SWRESET     BIT(0)
22 #define OA_CONFIG0           MMS_REG(0x0, 0x004)
23 #define OA_CONFIG0_SYNC      BIT(15)
24 #define OA_CONFIG0_RFA_ZARFE BIT(12)
25 #define OA_CONFIG0_PROTE     BIT(5)
26 #define OA_STATUS0           MMS_REG(0x0, 0x008)
27 #define OA_STATUS0_RESETC    BIT(6)
28 #define OA_STATUS1           MMS_REG(0x0, 0x009)
29 #define OA_BUFSTS            MMS_REG(0x0, 0x00B)
30 #define OA_BUFSTS_TXC        GENMASK(15, 8)
31 #define OA_BUFSTS_RCA        GENMASK(7, 0)
32 #define OA_IMASK0            MMS_REG(0x0, 0x00C)
33 #define OA_IMASK0_TXPEM      BIT(0)
34 #define OA_IMASK0_TXBOEM     BIT(1)
35 #define OA_IMASK0_TXBUEM     BIT(2)
36 #define OA_IMASK0_RXBOEM     BIT(3)
37 #define OA_IMASK0_LOFEM      BIT(4)
38 #define OA_IMASK0_HDREM      BIT(5)
39 #define OA_IMASK1            MMS_REG(0x0, 0x00D)
40 #define OA_IMASK0_UV18M      BIT(19)
41 
42 /* OA Control header */
43 #define OA_CTRL_HDR_DNC  BIT(31)
44 #define OA_CTRL_HDR_HDRB BIT(30)
45 #define OA_CTRL_HDR_WNR  BIT(29)
46 #define OA_CTRL_HDR_AID  BIT(28)
47 #define OA_CTRL_HDR_MMS  GENMASK(27, 24)
48 #define OA_CTRL_HDR_ADDR GENMASK(23, 8)
49 #define OA_CTRL_HDR_LEN  GENMASK(7, 1)
50 #define OA_CTRL_HDR_P    BIT(0)
51 
52 /* OA Data header */
53 #define OA_DATA_HDR_DNC  BIT(31)
54 #define OA_DATA_HDR_SEQ  BIT(30)
55 #define OA_DATA_HDR_NORX BIT(29)
56 #define OA_DATA_HDR_DV   BIT(21)
57 #define OA_DATA_HDR_SV   BIT(20)
58 #define OA_DATA_HDR_SWO  GENMASK(19, 16)
59 #define OA_DATA_HDR_EV   BIT(14)
60 #define OA_DATA_HDR_EBO  GENMASK(13, 8)
61 #define OA_DATA_HDR_P    BIT(0)
62 
63 /* OA Data footer */
64 #define OA_DATA_FTR_EXST BIT(31)
65 #define OA_DATA_FTR_HDRB BIT(30)
66 #define OA_DATA_FTR_SYNC BIT(29)
67 #define OA_DATA_FTR_RCA  GENMASK(28, 24)
68 #define OA_DATA_FTR_DV   BIT(21)
69 #define OA_DATA_FTR_SV   BIT(20)
70 #define OA_DATA_FTR_SWO  GENMASK(19, 16)
71 #define OA_DATA_FTR_FD   BIT(15)
72 #define OA_DATA_FTR_EV   BIT(14)
73 #define OA_DATA_FTR_EBO  GENMASK(13, 8)
74 #define OA_DATA_FTR_TXC  GENMASK(5, 1)
75 #define OA_DATA_FTR_P    BIT(0)
76 
77 #define OA_TC6_HDR_SIZE          4
78 #define OA_TC6_FTR_SIZE          4
79 #define OA_TC6_BUF_ALLOC_TIMEOUT K_MSEC(10)
80 #define OA_TC6_FTR_RCA_MAX       GENMASK(4, 0)
81 #define OA_TC6_FTR_TXC_MAX       GENMASK(4, 0)
82 
83 /* PHY Clause 22 registers base address and mask */
84 #define OA_TC6_PHY_STD_REG_ADDR_BASE 0xFF00
85 #define OA_TC6_PHY_STD_REG_ADDR_MASK 0x1F
86 
87 /* PHY – Clause 45 registers memory map selector (MMS) as per table 6 in the
88  * OPEN Alliance specification.
89  */
90 #define OA_TC6_PHY_C45_PCS_MMS2      2 /* MMD 3 */
91 #define OA_TC6_PHY_C45_PMA_PMD_MMS3  3 /* MMD 1 */
92 #define OA_TC6_PHY_C45_VS_PLCA_MMS4  4 /* MMD 31 */
93 #define OA_TC6_PHY_C45_AUTO_NEG_MMS5 5 /* MMD 7 */
94 
95 /**
96  * @brief OA TC6 data.
97  */
98 struct oa_tc6 {
99 	/** Pointer to SPI device */
100 	const struct spi_dt_spec *spi;
101 
102 	/** OA data payload (chunk) size */
103 	uint8_t cps;
104 
105 	/**
106 	 * Number of available chunks buffers in OA TC6 device to store
107 	 * data for transmission
108 	 */
109 	uint8_t txc;
110 
111 	/** Number of available chunks to read from OA TC6 device */
112 	uint8_t rca;
113 
114 	/** Indication of pending interrupt in OA TC6 device */
115 	bool exst;
116 
117 	/** Indication of OA TC6 device being ready for transmission */
118 	bool sync;
119 
120 	/** Indication of protected control transmission mode */
121 	bool protected;
122 
123 	/** Pointer to network buffer concatenated from received chunk */
124 	struct net_buf *concat_buf;
125 };
126 
127 /**
128  * @brief Calculate parity bit from data
129  *
130  * @param x data to calculate parity
131  *
132  * @return 0 if number of ones is odd, 1 otherwise.
133  */
oa_tc6_get_parity(const uint32_t x)134 static inline bool oa_tc6_get_parity(const uint32_t x)
135 {
136 	uint32_t y;
137 
138 	y = x ^ (x >> 1);
139 	y = y ^ (y >> 2);
140 	y = y ^ (y >> 4);
141 	y = y ^ (y >> 8);
142 	y = y ^ (y >> 16);
143 
144 	return !(y & 1);
145 }
146 
147 /**
148  * @brief Read OA TC6 compliant device single register
149  *
150  * @param tc6 OA TC6 specific data
151  *
152  * @param reg register to read
153 
154  * @param val pointer to variable to store read value
155  *
156  * @return 0 if read was successful, <0 otherwise.
157  */
158 int oa_tc6_reg_read(struct oa_tc6 *tc6, const uint32_t reg, uint32_t *val);
159 
160 /**
161  * @brief Write to OA TC6 compliant device a single register
162  *
163  * @param tc6 OA TC6 specific data
164  *
165  * @param reg register to read
166 
167  * @param val data to send to device
168  *
169  * @return 0 if write was successful, <0 otherwise.
170  */
171 int oa_tc6_reg_write(struct oa_tc6 *tc6, const uint32_t reg, uint32_t val);
172 
173 /**
174  * @brief Enable or disable the protected mode for control transactions
175  *
176  * @param tc6 OA TC6 specific data
177  *
178  * @param prote enable or disable protected control transactions
179  *
180  * @return 0 if operation was successful, <0 otherwise.
181  */
182 int oa_tc6_set_protected_ctrl(struct oa_tc6 *tc6, bool prote);
183 
184 /**
185  * @brief Send OA TC6 data chunks to the device
186  *
187  * @param tc6 OA TC6 specific data
188  *
189  * @param pkt network packet to be send
190  *
191  * @return 0 if data send was successful, <0 otherwise.
192  */
193 int oa_tc6_send_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt);
194 
195 /**
196  * @brief Read data chunks from OA TC6 device
197  *
198  * @param tc6 OA TC6 specific data
199  *
200  * @param pkt network packet to store received data
201  *
202  * @return 0 if read was successful, <0 otherwise.
203  */
204 int oa_tc6_read_chunks(struct oa_tc6 *tc6, struct net_pkt *pkt);
205 
206 /**
207  * @brief Perform SPI transfer of single chunk from/to OA TC6 device
208  *
209  * @param tc6 OA TC6 specific data
210  *
211  * @param buf_rx buffer to store read data
212  *
213  * @param buf_tx buffer with data to send
214  *
215  * @param hdr OA TC6 data transmission header value
216  *
217  * @param ftr poniter to OA TC6 data received footer
218  *
219  * @return 0 if transmission was successful, <0 otherwise.
220  */
221 int oa_tc6_chunk_spi_transfer(struct oa_tc6 *tc6, uint8_t *buf_rx, uint8_t *buf_tx, uint32_t hdr,
222 			      uint32_t *ftr);
223 
224 /**
225  * @brief Read status from OA TC6 device
226  *
227  * @param tc6 OA TC6 specific data
228  *
229  * @param ftr poniter to OA TC6 data received footer
230  *
231  * @return 0 if successful, <0 otherwise.
232  */
233 int oa_tc6_read_status(struct oa_tc6 *tc6, uint32_t *ftr);
234 
235 /**
236  * @brief Read, modify and write control register from OA TC6 device
237  *
238  * @param tc6 OA TC6 specific data
239  *
240  * @param reg register to modify
241  *
242  * @param mask bit mask for modified register
243  *
244  * @param value to be stored in the register
245  *
246  * @return 0 if successful, <0 otherwise.
247  */
248 int oa_tc6_reg_rmw(struct oa_tc6 *tc6, const uint32_t reg, uint32_t mask, uint32_t val);
249 
250 /**
251  * @brief Check the status of OA TC6 device
252  *
253  * @param tc6 OA TC6 specific data
254  *
255  * @return 0 if successful, <0 otherwise.
256  */
257 int oa_tc6_check_status(struct oa_tc6 *tc6);
258 
259 /**
260  * @brief      Read C22 registers using MDIO Bus
261  *
262  * This routine provides an interface to perform a C22 register read on the
263  * MAC-PHY MDIO bus.
264  *
265  * @param[in]  tc6         Pointer to the tc6 structure for the MAC-PHY
266  * @param[in]  prtad       Port address
267  * @param[in]  regad       Register address
268  * @param      data        Pointer to receive read data
269  *
270  * @return 0 if successful, <0 otherwise.
271  */
272 int oa_tc6_mdio_read(struct oa_tc6 *tc6, uint8_t prtad, uint8_t regad, uint16_t *data);
273 
274 /**
275  * @brief      Write C22 registers using MDIO Bus
276  *
277  * This routine provides an interface to perform a C22 register write on the
278  * MAC-PHY MDIO bus.
279  *
280  * @param[in]  tc6         Pointer to the tc6 structure for the MAC-PHY
281  * @param[in]  prtad       Port address
282  * @param[in]  regad       Register address
283  * @param[in]  data        Write data
284  *
285  * @return 0 if successful, <0 otherwise.
286  */
287 int oa_tc6_mdio_write(struct oa_tc6 *tc6, uint8_t prtad, uint8_t regad, uint16_t data);
288 
289 /**
290  * @brief      Read C45 registers using MDIO Bus
291  *
292  * This routine provides an interface to perform a C45 register read on the
293  * MAC-PHY MDIO bus.
294  *
295  * @param[in]  tc6         Pointer to the tc6 structure for the MAC-PHY
296  * @param[in]  prtad       Port address
297  * @param[in]  devad       MMD device address
298  * @param[in]  regad       Register address
299  * @param      data        Pointer to receive read data
300  *
301  * @return 0 if successful, <0 otherwise.
302  */
303 int oa_tc6_mdio_read_c45(struct oa_tc6 *tc6, uint8_t prtad, uint8_t devad, uint16_t regad,
304 			 uint16_t *data);
305 
306 /**
307  * @brief      Write C45 registers using MDIO Bus
308  *
309  * This routine provides an interface to perform a C45 register write on the
310  * MAC-PHY MDIO bus.
311  *
312  * @param[in]  tc6         Pointer to the tc6 structure for the MAC-PHY
313  * @param[in]  prtad       Port address
314  * @param[in]  devad       MMD device address
315  * @param[in]  regad       Register address
316  * @param[in]  data        Write data
317  *
318  * @return 0 if successful, <0 otherwise.
319  */
320 int oa_tc6_mdio_write_c45(struct oa_tc6 *tc6, uint8_t prtad, uint8_t devad, uint16_t regad,
321 			  uint16_t data);
322 #endif /* OA_TC6_CFG_H__ */
323