2 * Realtek RTL8366 SMI interface driver
4 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/gpio.h>
16 #include <linux/spinlock.h>
18 #include "rtl8366_smi.h"
20 #define RTL8366_SMI_ACK_RETRY_COUNT 5
21 #define RTL8366_SMI_CLK_DELAY 10 /* nsec */
23 static inline void rtl8366_smi_clk_delay(struct rtl8366_smi
*smi
)
25 ndelay(RTL8366_SMI_CLK_DELAY
);
28 static void rtl8366_smi_start(struct rtl8366_smi
*smi
)
30 unsigned int sda
= smi
->gpio_sda
;
31 unsigned int sck
= smi
->gpio_sck
;
34 * Set GPIO pins to output mode, with initial state:
37 gpio_direction_output(sck
, 0);
38 gpio_direction_output(sda
, 1);
39 rtl8366_smi_clk_delay(smi
);
41 /* CLK 1: 0 -> 1, 1 -> 0 */
42 gpio_set_value(sck
, 1);
43 rtl8366_smi_clk_delay(smi
);
44 gpio_set_value(sck
, 0);
45 rtl8366_smi_clk_delay(smi
);
48 gpio_set_value(sck
, 1);
49 rtl8366_smi_clk_delay(smi
);
50 gpio_set_value(sda
, 0);
51 rtl8366_smi_clk_delay(smi
);
52 gpio_set_value(sck
, 0);
53 rtl8366_smi_clk_delay(smi
);
54 gpio_set_value(sda
, 1);
57 static void rtl8366_smi_stop(struct rtl8366_smi
*smi
)
59 unsigned int sda
= smi
->gpio_sda
;
60 unsigned int sck
= smi
->gpio_sck
;
62 rtl8366_smi_clk_delay(smi
);
63 gpio_set_value(sda
, 0);
64 gpio_set_value(sck
, 1);
65 rtl8366_smi_clk_delay(smi
);
66 gpio_set_value(sda
, 1);
67 rtl8366_smi_clk_delay(smi
);
68 gpio_set_value(sck
, 1);
69 rtl8366_smi_clk_delay(smi
);
70 gpio_set_value(sck
, 0);
71 rtl8366_smi_clk_delay(smi
);
72 gpio_set_value(sck
, 1);
75 rtl8366_smi_clk_delay(smi
);
76 gpio_set_value(sck
, 0);
77 rtl8366_smi_clk_delay(smi
);
78 gpio_set_value(sck
, 1);
80 /* set GPIO pins to input mode */
81 gpio_direction_input(sda
);
82 gpio_direction_input(sck
);
85 static void rtl8366_smi_write_bits(struct rtl8366_smi
*smi
, u32 data
, u32 len
)
87 unsigned int sda
= smi
->gpio_sda
;
88 unsigned int sck
= smi
->gpio_sck
;
90 for (; len
> 0; len
--) {
91 rtl8366_smi_clk_delay(smi
);
94 if ( data
& ( 1 << (len
- 1)) )
95 gpio_set_value(sda
, 1);
97 gpio_set_value(sda
, 0);
98 rtl8366_smi_clk_delay(smi
);
101 gpio_set_value(sck
, 1);
102 rtl8366_smi_clk_delay(smi
);
103 gpio_set_value(sck
, 0);
107 static void rtl8366_smi_read_bits(struct rtl8366_smi
*smi
, u32 len
, u32
*data
)
109 unsigned int sda
= smi
->gpio_sda
;
110 unsigned int sck
= smi
->gpio_sck
;
112 gpio_direction_input(sda
);
114 for (*data
= 0; len
> 0; len
--) {
117 rtl8366_smi_clk_delay(smi
);
120 gpio_set_value(sck
, 1);
121 rtl8366_smi_clk_delay(smi
);
122 u
= gpio_get_value(sda
);
123 gpio_set_value(sck
, 0);
125 *data
|= (u
<< (len
- 1));
128 gpio_direction_output(sda
, 0);
131 static int rtl8366_smi_wait_for_ack(struct rtl8366_smi
*smi
)
139 rtl8366_smi_read_bits(smi
, 1, &ack
);
143 if (++retry_cnt
> RTL8366_SMI_ACK_RETRY_COUNT
)
150 static int rtl8366_smi_write_byte(struct rtl8366_smi
*smi
, u8 data
)
152 rtl8366_smi_write_bits(smi
, data
, 8);
153 return rtl8366_smi_wait_for_ack(smi
);
156 static int rtl8366_smi_read_byte0(struct rtl8366_smi
*smi
, u8
*data
)
161 rtl8366_smi_read_bits(smi
, 8, &t
);
165 rtl8366_smi_write_bits(smi
, 0x00, 1);
170 static int rtl8366_smi_read_byte1(struct rtl8366_smi
*smi
, u8
*data
)
175 rtl8366_smi_read_bits(smi
, 8, &t
);
179 rtl8366_smi_write_bits(smi
, 0x01, 1);
184 int rtl8366_smi_read_reg(struct rtl8366_smi
*smi
, u32 addr
, u32
*data
)
191 spin_lock_irqsave(&smi
->lock
, flags
);
193 rtl8366_smi_start(smi
);
195 /* send READ command */
196 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x01);
201 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
206 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
211 rtl8366_smi_read_byte0(smi
, &lo
);
212 /* read DATA[15:8] */
213 rtl8366_smi_read_byte1(smi
, &hi
);
215 *data
= ((u32
) lo
) | (((u32
) hi
) << 8);
220 rtl8366_smi_stop(smi
);
221 spin_unlock_irqrestore(&smi
->lock
, flags
);
225 EXPORT_SYMBOL_GPL(rtl8366_smi_read_reg
);
227 int rtl8366_smi_write_reg(struct rtl8366_smi
*smi
, u32 addr
, u32 data
)
232 spin_lock_irqsave(&smi
->lock
, flags
);
234 rtl8366_smi_start(smi
);
236 /* send WRITE command */
237 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x00);
242 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
247 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
251 /* write DATA[7:0] */
252 ret
= rtl8366_smi_write_byte(smi
, data
& 0xff);
256 /* write DATA[15:8] */
257 ret
= rtl8366_smi_write_byte(smi
, data
>> 8);
264 rtl8366_smi_stop(smi
);
265 spin_unlock_irqrestore(&smi
->lock
, flags
);
269 EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg
);
271 int rtl8366_smi_init(struct rtl8366_smi
*smi
)
278 err
= gpio_request(smi
->gpio_sda
, dev_name(smi
->parent
));
280 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
285 err
= gpio_request(smi
->gpio_sck
, dev_name(smi
->parent
));
287 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
292 spin_lock_init(&smi
->lock
);
294 dev_info(smi
->parent
, "using GPIO pins %u (SDA) and %u (SCK)\n",
295 smi
->gpio_sda
, smi
->gpio_sck
);
300 gpio_free(smi
->gpio_sda
);
304 EXPORT_SYMBOL_GPL(rtl8366_smi_init
);
306 void rtl8366_smi_cleanup(struct rtl8366_smi
*smi
)
308 gpio_free(smi
->gpio_sck
);
309 gpio_free(smi
->gpio_sda
);
311 EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup
);
313 MODULE_DESCRIPTION("Realtek RTL8366 SMI interface driver");
314 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
315 MODULE_LICENSE("GPL v2");