mediatek: mt7622: add Linux 5.10 support
[openwrt/staging/rmilecki.git] / target / linux / mediatek / files-5.10 / drivers / net / phy / rtk / rtl8367c / smi.c
1 /*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * Unless you and Realtek execute a separate written software license
6 * agreement governing use of this software, this software is licensed
7 * to you under the terms of the GNU General Public License version 2,
8 * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
9 *
10 * Purpose : RTL8367C switch low-level function for access register
11 * Feature : SMI related functions
12 *
13 */
14
15
16 #include <rtk_types.h>
17 #include <smi.h>
18 #include "rtk_error.h"
19
20
21 #if defined(MDC_MDIO_OPERATION)
22 /*******************************************************************************/
23 /* MDC/MDIO porting */
24 /*******************************************************************************/
25 /* define the PHY ID currently used */
26 /* carlos */
27 #if 0
28 #define MDC_MDIO_PHY_ID 0 /* PHY ID 0 or 29 */
29 #else
30 #define MDC_MDIO_PHY_ID 29 /* PHY ID 0 or 29 */
31 #endif
32
33 /* MDC/MDIO, redefine/implement the following Macro */ /*carlos*/
34 #if 0
35 #define MDC_MDIO_WRITE(preamableLength, phyID, regID, data)
36 #define MDC_MDIO_READ(preamableLength, phyID, regID, pData)
37 #else
38 #define u32 unsigned int
39 extern u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data);
40 extern u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data);
41
42 #define MDC_MDIO_WRITE(preamableLength, phyID, regID, data) mii_mgr_write(phyID, regID, data)
43 #define MDC_MDIO_READ(preamableLength, phyID, regID, pData) mii_mgr_read(phyID, regID, pData)
44 #endif
45
46
47
48
49
50 #elif defined(SPI_OPERATION)
51 /*******************************************************************************/
52 /* SPI porting */
53 /*******************************************************************************/
54 /* SPI, redefine/implement the following Macro */
55 #define SPI_WRITE(data, length)
56 #define SPI_READ(pData, length)
57
58
59
60
61
62 #else
63 /*******************************************************************************/
64 /* I2C porting */
65 /*******************************************************************************/
66 /* Define the GPIO ID for SCK & SDA */
67 rtk_uint32 smi_SCK = 1; /* GPIO used for SMI Clock Generation */
68 rtk_uint32 smi_SDA = 2; /* GPIO used for SMI Data signal */
69
70 /* I2C, redefine/implement the following Macro */
71 #define GPIO_DIRECTION_SET(gpioID, direction)
72 #define GPIO_DATA_SET(gpioID, data)
73 #define GPIO_DATA_GET(gpioID, pData)
74
75
76
77
78
79 #endif
80
81 static void rtlglue_drvMutexLock(void)
82 {
83 /* It is empty currently. Implement this function if Lock/Unlock function is needed */
84 return;
85 }
86
87 static void rtlglue_drvMutexUnlock(void)
88 {
89 /* It is empty currently. Implement this function if Lock/Unlock function is needed */
90 return;
91 }
92
93
94
95 #if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION)
96 /* No local function in MDC/MDIO & SPI mode */
97 #else
98 static void _smi_start(void)
99 {
100
101 /* change GPIO pin to Output only */
102 GPIO_DIRECTION_SET(smi_SCK, GPIO_DIR_OUT);
103 GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_OUT);
104
105 /* Initial state: SCK: 0, SDA: 1 */
106 GPIO_DATA_SET(smi_SCK, 0);
107 GPIO_DATA_SET(smi_SDA, 1);
108 CLK_DURATION(DELAY);
109
110 /* CLK 1: 0 -> 1, 1 -> 0 */
111 GPIO_DATA_SET(smi_SCK, 1);
112 CLK_DURATION(DELAY);
113 GPIO_DATA_SET(smi_SCK, 0);
114 CLK_DURATION(DELAY);
115
116 /* CLK 2: */
117 GPIO_DATA_SET(smi_SCK, 1);
118 CLK_DURATION(DELAY);
119 GPIO_DATA_SET(smi_SDA, 0);
120 CLK_DURATION(DELAY);
121 GPIO_DATA_SET(smi_SCK, 0);
122 CLK_DURATION(DELAY);
123 GPIO_DATA_SET(smi_SDA, 1);
124
125 }
126
127
128
129 static void _smi_writeBit(rtk_uint16 signal, rtk_uint32 bitLen)
130 {
131 for( ; bitLen > 0; bitLen--)
132 {
133 CLK_DURATION(DELAY);
134
135 /* prepare data */
136 if ( signal & (1<<(bitLen-1)) )
137 {
138 GPIO_DATA_SET(smi_SDA, 1);
139 }
140 else
141 {
142 GPIO_DATA_SET(smi_SDA, 0);
143 }
144 CLK_DURATION(DELAY);
145
146 /* clocking */
147 GPIO_DATA_SET(smi_SCK, 1);
148 CLK_DURATION(DELAY);
149 GPIO_DATA_SET(smi_SCK, 0);
150 }
151 }
152
153
154
155 static void _smi_readBit(rtk_uint32 bitLen, rtk_uint32 *rData)
156 {
157 rtk_uint32 u = 0;
158
159 /* change GPIO pin to Input only */
160 GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_IN);
161
162 for (*rData = 0; bitLen > 0; bitLen--)
163 {
164 CLK_DURATION(DELAY);
165
166 /* clocking */
167 GPIO_DATA_SET(smi_SCK, 1);
168 CLK_DURATION(DELAY);
169 GPIO_DATA_GET(smi_SDA, &u);
170 GPIO_DATA_SET(smi_SCK, 0);
171
172 *rData |= (u << (bitLen - 1));
173 }
174
175 /* change GPIO pin to Output only */
176 GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_OUT);
177 }
178
179
180
181 static void _smi_stop(void)
182 {
183
184 CLK_DURATION(DELAY);
185 GPIO_DATA_SET(smi_SDA, 0);
186 GPIO_DATA_SET(smi_SCK, 1);
187 CLK_DURATION(DELAY);
188 GPIO_DATA_SET(smi_SDA, 1);
189 CLK_DURATION(DELAY);
190 GPIO_DATA_SET(smi_SCK, 1);
191 CLK_DURATION(DELAY);
192 GPIO_DATA_SET(smi_SCK, 0);
193 CLK_DURATION(DELAY);
194 GPIO_DATA_SET(smi_SCK, 1);
195
196 /* add a click */
197 CLK_DURATION(DELAY);
198 GPIO_DATA_SET(smi_SCK, 0);
199 CLK_DURATION(DELAY);
200 GPIO_DATA_SET(smi_SCK, 1);
201
202
203 /* change GPIO pin to Input only */
204 GPIO_DIRECTION_SET(smi_SDA, GPIO_DIR_IN);
205 GPIO_DIRECTION_SET(smi_SCK, GPIO_DIR_IN);
206 }
207
208 #endif /* End of #if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION) */
209
210 rtk_int32 smi_read(rtk_uint32 mAddrs, rtk_uint32 *rData)
211 {
212 #if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
213 rtk_uint32 rawData=0, ACK;
214 rtk_uint8 con;
215 rtk_uint32 ret = RT_ERR_OK;
216 #endif
217
218 if(mAddrs > 0xFFFF)
219 return RT_ERR_INPUT;
220
221 if(rData == NULL)
222 return RT_ERR_NULL_POINTER;
223
224 #if defined(MDC_MDIO_OPERATION)
225
226 /* Lock */
227 rtlglue_drvMutexLock();
228
229 /* Write address control code to register 31 */
230 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);
231
232 /* Write address to register 23 */
233 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_ADDRESS_REG, mAddrs);
234
235 /* Write read control code to register 21 */
236 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP);
237
238 /* Read data from register 25 */
239 MDC_MDIO_READ(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_DATA_READ_REG, rData);
240
241 /* Unlock */
242 rtlglue_drvMutexUnlock();
243
244 return RT_ERR_OK;
245
246 #elif defined(SPI_OPERATION)
247
248 /* Lock */
249 rtlglue_drvMutexLock();
250
251 /* Write 8 bits READ OP_CODE */
252 SPI_WRITE(SPI_READ_OP, SPI_READ_OP_LEN);
253
254 /* Write 16 bits register address */
255 SPI_WRITE(mAddrs, SPI_REG_LEN);
256
257 /* Read 16 bits data */
258 SPI_READ(rData, SPI_DATA_LEN);
259
260 /* Unlock */
261 rtlglue_drvMutexUnlock();
262
263 return RT_ERR_OK;
264
265 #else
266
267 /*Disable CPU interrupt to ensure that the SMI operation is atomic.
268 The API is based on RTL865X, rewrite the API if porting to other platform.*/
269 rtlglue_drvMutexLock();
270
271 _smi_start(); /* Start SMI */
272
273 _smi_writeBit(0x0b, 4); /* CTRL code: 4'b1011 for RTL8370 */
274
275 _smi_writeBit(0x4, 3); /* CTRL code: 3'b100 */
276
277 _smi_writeBit(0x1, 1); /* 1: issue READ command */
278
279 con = 0;
280 do {
281 con++;
282 _smi_readBit(1, &ACK); /* ACK for issuing READ command*/
283 } while ((ACK != 0) && (con < ack_timer));
284
285 if (ACK != 0) ret = RT_ERR_FAILED;
286
287 _smi_writeBit((mAddrs&0xff), 8); /* Set reg_addr[7:0] */
288
289 con = 0;
290 do {
291 con++;
292 _smi_readBit(1, &ACK); /* ACK for setting reg_addr[7:0] */
293 } while ((ACK != 0) && (con < ack_timer));
294
295 if (ACK != 0) ret = RT_ERR_FAILED;
296
297 _smi_writeBit((mAddrs>>8), 8); /* Set reg_addr[15:8] */
298
299 con = 0;
300 do {
301 con++;
302 _smi_readBit(1, &ACK); /* ACK by RTL8369 */
303 } while ((ACK != 0) && (con < ack_timer));
304 if (ACK != 0) ret = RT_ERR_FAILED;
305
306 _smi_readBit(8, &rawData); /* Read DATA [7:0] */
307 *rData = rawData&0xff;
308
309 _smi_writeBit(0x00, 1); /* ACK by CPU */
310
311 _smi_readBit(8, &rawData); /* Read DATA [15: 8] */
312
313 _smi_writeBit(0x01, 1); /* ACK by CPU */
314 *rData |= (rawData<<8);
315
316 _smi_stop();
317
318 rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
319
320 return ret;
321 #endif /* end of #if defined(MDC_MDIO_OPERATION) */
322 }
323
324
325
326 rtk_int32 smi_write(rtk_uint32 mAddrs, rtk_uint32 rData)
327 {
328 #if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
329 rtk_int8 con;
330 rtk_uint32 ACK;
331 rtk_uint32 ret = RT_ERR_OK;
332 #endif
333
334 if(mAddrs > 0xFFFF)
335 return RT_ERR_INPUT;
336
337 if(rData > 0xFFFF)
338 return RT_ERR_INPUT;
339
340 #if defined(MDC_MDIO_OPERATION)
341
342 /* Lock */
343 rtlglue_drvMutexLock();
344
345 /* Write address control code to register 31 */
346 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);
347
348 /* Write address to register 23 */
349 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_ADDRESS_REG, mAddrs);
350
351 /* Write data to register 24 */
352 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_DATA_WRITE_REG, rData);
353
354 /* Write data control code to register 21 */
355 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN, MDC_MDIO_PHY_ID, MDC_MDIO_CTRL1_REG, MDC_MDIO_WRITE_OP);
356
357 /* Unlock */
358 rtlglue_drvMutexUnlock();
359
360 return RT_ERR_OK;
361
362 #elif defined(SPI_OPERATION)
363
364 /* Lock */
365 rtlglue_drvMutexLock();
366
367 /* Write 8 bits WRITE OP_CODE */
368 SPI_WRITE(SPI_WRITE_OP, SPI_WRITE_OP_LEN);
369
370 /* Write 16 bits register address */
371 SPI_WRITE(mAddrs, SPI_REG_LEN);
372
373 /* Write 16 bits data */
374 SPI_WRITE(rData, SPI_DATA_LEN);
375
376 /* Unlock */
377 rtlglue_drvMutexUnlock();
378
379 return RT_ERR_OK;
380 #else
381
382 /*Disable CPU interrupt to ensure that the SMI operation is atomic.
383 The API is based on RTL865X, rewrite the API if porting to other platform.*/
384 rtlglue_drvMutexLock();
385
386 _smi_start(); /* Start SMI */
387
388 _smi_writeBit(0x0b, 4); /* CTRL code: 4'b1011 for RTL8370*/
389
390 _smi_writeBit(0x4, 3); /* CTRL code: 3'b100 */
391
392 _smi_writeBit(0x0, 1); /* 0: issue WRITE command */
393
394 con = 0;
395 do {
396 con++;
397 _smi_readBit(1, &ACK); /* ACK for issuing WRITE command*/
398 } while ((ACK != 0) && (con < ack_timer));
399 if (ACK != 0) ret = RT_ERR_FAILED;
400
401 _smi_writeBit((mAddrs&0xff), 8); /* Set reg_addr[7:0] */
402
403 con = 0;
404 do {
405 con++;
406 _smi_readBit(1, &ACK); /* ACK for setting reg_addr[7:0] */
407 } while ((ACK != 0) && (con < ack_timer));
408 if (ACK != 0) ret = RT_ERR_FAILED;
409
410 _smi_writeBit((mAddrs>>8), 8); /* Set reg_addr[15:8] */
411
412 con = 0;
413 do {
414 con++;
415 _smi_readBit(1, &ACK); /* ACK for setting reg_addr[15:8] */
416 } while ((ACK != 0) && (con < ack_timer));
417 if (ACK != 0) ret = RT_ERR_FAILED;
418
419 _smi_writeBit(rData&0xff, 8); /* Write Data [7:0] out */
420
421 con = 0;
422 do {
423 con++;
424 _smi_readBit(1, &ACK); /* ACK for writting data [7:0] */
425 } while ((ACK != 0) && (con < ack_timer));
426 if (ACK != 0) ret = RT_ERR_FAILED;
427
428 _smi_writeBit(rData>>8, 8); /* Write Data [15:8] out */
429
430 con = 0;
431 do {
432 con++;
433 _smi_readBit(1, &ACK); /* ACK for writting data [15:8] */
434 } while ((ACK != 0) && (con < ack_timer));
435 if (ACK != 0) ret = RT_ERR_FAILED;
436
437 _smi_stop();
438
439 rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
440
441 return ret;
442 #endif /* end of #if defined(MDC_MDIO_OPERATION) */
443 }
444