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