2 * Copyright (C) 2013 Realtek Semiconductor Corp.
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
10 * Purpose : RTL8367C switch low-level function for access register
11 * Feature : SMI related functions
16 #include <rtk_types.h>
18 #include "rtk_error.h"
21 #if defined(MDC_MDIO_OPERATION)
22 /*******************************************************************************/
23 /* MDC/MDIO porting */
24 /*******************************************************************************/
25 /* define the PHY ID currently used */
28 #define MDC_MDIO_PHY_ID 0 /* PHY ID 0 or 29 */
30 #define MDC_MDIO_PHY_ID 29 /* PHY ID 0 or 29 */
33 /* MDC/MDIO, redefine/implement the following Macro */ /*carlos*/
35 #define MDC_MDIO_WRITE(preamableLength, phyID, regID, data)
36 #define MDC_MDIO_READ(preamableLength, phyID, regID, pData)
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
);
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)
50 #elif defined(SPI_OPERATION)
51 /*******************************************************************************/
53 /*******************************************************************************/
54 /* SPI, redefine/implement the following Macro */
55 #define SPI_WRITE(data, length)
56 #define SPI_READ(pData, length)
63 /*******************************************************************************/
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 */
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)
81 static void rtlglue_drvMutexLock(void)
83 /* It is empty currently. Implement this function if Lock/Unlock function is needed */
87 static void rtlglue_drvMutexUnlock(void)
89 /* It is empty currently. Implement this function if Lock/Unlock function is needed */
95 #if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION)
96 /* No local function in MDC/MDIO & SPI mode */
98 static void _smi_start(void)
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
);
105 /* Initial state: SCK: 0, SDA: 1 */
106 GPIO_DATA_SET(smi_SCK
, 0);
107 GPIO_DATA_SET(smi_SDA
, 1);
110 /* CLK 1: 0 -> 1, 1 -> 0 */
111 GPIO_DATA_SET(smi_SCK
, 1);
113 GPIO_DATA_SET(smi_SCK
, 0);
117 GPIO_DATA_SET(smi_SCK
, 1);
119 GPIO_DATA_SET(smi_SDA
, 0);
121 GPIO_DATA_SET(smi_SCK
, 0);
123 GPIO_DATA_SET(smi_SDA
, 1);
129 static void _smi_writeBit(rtk_uint16 signal
, rtk_uint32 bitLen
)
131 for( ; bitLen
> 0; bitLen
--)
136 if ( signal
& (1<<(bitLen
-1)) )
138 GPIO_DATA_SET(smi_SDA
, 1);
142 GPIO_DATA_SET(smi_SDA
, 0);
147 GPIO_DATA_SET(smi_SCK
, 1);
149 GPIO_DATA_SET(smi_SCK
, 0);
155 static void _smi_readBit(rtk_uint32 bitLen
, rtk_uint32
*rData
)
159 /* change GPIO pin to Input only */
160 GPIO_DIRECTION_SET(smi_SDA
, GPIO_DIR_IN
);
162 for (*rData
= 0; bitLen
> 0; bitLen
--)
167 GPIO_DATA_SET(smi_SCK
, 1);
169 GPIO_DATA_GET(smi_SDA
, &u
);
170 GPIO_DATA_SET(smi_SCK
, 0);
172 *rData
|= (u
<< (bitLen
- 1));
175 /* change GPIO pin to Output only */
176 GPIO_DIRECTION_SET(smi_SDA
, GPIO_DIR_OUT
);
181 static void _smi_stop(void)
185 GPIO_DATA_SET(smi_SDA
, 0);
186 GPIO_DATA_SET(smi_SCK
, 1);
188 GPIO_DATA_SET(smi_SDA
, 1);
190 GPIO_DATA_SET(smi_SCK
, 1);
192 GPIO_DATA_SET(smi_SCK
, 0);
194 GPIO_DATA_SET(smi_SCK
, 1);
198 GPIO_DATA_SET(smi_SCK
, 0);
200 GPIO_DATA_SET(smi_SCK
, 1);
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
);
208 #endif /* End of #if defined(MDC_MDIO_OPERATION) || defined(SPI_OPERATION) */
210 rtk_int32
smi_read(rtk_uint32 mAddrs
, rtk_uint32
*rData
)
212 #if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
213 rtk_uint32 rawData
=0, ACK
;
215 rtk_uint32 ret
= RT_ERR_OK
;
222 return RT_ERR_NULL_POINTER
;
224 #if defined(MDC_MDIO_OPERATION)
227 rtlglue_drvMutexLock();
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
);
232 /* Write address to register 23 */
233 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN
, MDC_MDIO_PHY_ID
, MDC_MDIO_ADDRESS_REG
, mAddrs
);
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
);
238 /* Read data from register 25 */
239 MDC_MDIO_READ(MDC_MDIO_PREAMBLE_LEN
, MDC_MDIO_PHY_ID
, MDC_MDIO_DATA_READ_REG
, rData
);
242 rtlglue_drvMutexUnlock();
246 #elif defined(SPI_OPERATION)
249 rtlglue_drvMutexLock();
251 /* Write 8 bits READ OP_CODE */
252 SPI_WRITE(SPI_READ_OP
, SPI_READ_OP_LEN
);
254 /* Write 16 bits register address */
255 SPI_WRITE(mAddrs
, SPI_REG_LEN
);
257 /* Read 16 bits data */
258 SPI_READ(rData
, SPI_DATA_LEN
);
261 rtlglue_drvMutexUnlock();
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();
271 _smi_start(); /* Start SMI */
273 _smi_writeBit(0x0b, 4); /* CTRL code: 4'b1011 for RTL8370 */
275 _smi_writeBit(0x4, 3); /* CTRL code: 3'b100 */
277 _smi_writeBit(0x1, 1); /* 1: issue READ command */
282 _smi_readBit(1, &ACK
); /* ACK for issuing READ command*/
283 } while ((ACK
!= 0) && (con
< ack_timer
));
285 if (ACK
!= 0) ret
= RT_ERR_FAILED
;
287 _smi_writeBit((mAddrs
&0xff), 8); /* Set reg_addr[7:0] */
292 _smi_readBit(1, &ACK
); /* ACK for setting reg_addr[7:0] */
293 } while ((ACK
!= 0) && (con
< ack_timer
));
295 if (ACK
!= 0) ret
= RT_ERR_FAILED
;
297 _smi_writeBit((mAddrs
>>8), 8); /* Set reg_addr[15:8] */
302 _smi_readBit(1, &ACK
); /* ACK by RTL8369 */
303 } while ((ACK
!= 0) && (con
< ack_timer
));
304 if (ACK
!= 0) ret
= RT_ERR_FAILED
;
306 _smi_readBit(8, &rawData
); /* Read DATA [7:0] */
307 *rData
= rawData
&0xff;
309 _smi_writeBit(0x00, 1); /* ACK by CPU */
311 _smi_readBit(8, &rawData
); /* Read DATA [15: 8] */
313 _smi_writeBit(0x01, 1); /* ACK by CPU */
314 *rData
|= (rawData
<<8);
318 rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
321 #endif /* end of #if defined(MDC_MDIO_OPERATION) */
326 rtk_int32
smi_write(rtk_uint32 mAddrs
, rtk_uint32 rData
)
328 #if (!defined(MDC_MDIO_OPERATION) && !defined(SPI_OPERATION))
331 rtk_uint32 ret
= RT_ERR_OK
;
340 #if defined(MDC_MDIO_OPERATION)
343 rtlglue_drvMutexLock();
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
);
348 /* Write address to register 23 */
349 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN
, MDC_MDIO_PHY_ID
, MDC_MDIO_ADDRESS_REG
, mAddrs
);
351 /* Write data to register 24 */
352 MDC_MDIO_WRITE(MDC_MDIO_PREAMBLE_LEN
, MDC_MDIO_PHY_ID
, MDC_MDIO_DATA_WRITE_REG
, rData
);
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
);
358 rtlglue_drvMutexUnlock();
362 #elif defined(SPI_OPERATION)
365 rtlglue_drvMutexLock();
367 /* Write 8 bits WRITE OP_CODE */
368 SPI_WRITE(SPI_WRITE_OP
, SPI_WRITE_OP_LEN
);
370 /* Write 16 bits register address */
371 SPI_WRITE(mAddrs
, SPI_REG_LEN
);
373 /* Write 16 bits data */
374 SPI_WRITE(rData
, SPI_DATA_LEN
);
377 rtlglue_drvMutexUnlock();
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();
386 _smi_start(); /* Start SMI */
388 _smi_writeBit(0x0b, 4); /* CTRL code: 4'b1011 for RTL8370*/
390 _smi_writeBit(0x4, 3); /* CTRL code: 3'b100 */
392 _smi_writeBit(0x0, 1); /* 0: issue WRITE command */
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
;
401 _smi_writeBit((mAddrs
&0xff), 8); /* Set reg_addr[7:0] */
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
;
410 _smi_writeBit((mAddrs
>>8), 8); /* Set reg_addr[15:8] */
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
;
419 _smi_writeBit(rData
&0xff, 8); /* Write Data [7:0] out */
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
;
428 _smi_writeBit(rData
>>8, 8); /* Write Data [15:8] out */
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
;
439 rtlglue_drvMutexUnlock();/*enable CPU interrupt*/
442 #endif /* end of #if defined(MDC_MDIO_OPERATION) */