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 gpio_set_value(sda
, !!(data
& ( 1 << (len
- 1))));
95 rtl8366_smi_clk_delay(smi
);
98 gpio_set_value(sck
, 1);
99 rtl8366_smi_clk_delay(smi
);
100 gpio_set_value(sck
, 0);
104 static void rtl8366_smi_read_bits(struct rtl8366_smi
*smi
, u32 len
, u32
*data
)
106 unsigned int sda
= smi
->gpio_sda
;
107 unsigned int sck
= smi
->gpio_sck
;
109 gpio_direction_input(sda
);
111 for (*data
= 0; len
> 0; len
--) {
114 rtl8366_smi_clk_delay(smi
);
117 gpio_set_value(sck
, 1);
118 rtl8366_smi_clk_delay(smi
);
119 u
= !!gpio_get_value(sda
);
120 gpio_set_value(sck
, 0);
122 *data
|= (u
<< (len
- 1));
125 gpio_direction_output(sda
, 0);
128 static int rtl8366_smi_wait_for_ack(struct rtl8366_smi
*smi
)
136 rtl8366_smi_read_bits(smi
, 1, &ack
);
140 if (++retry_cnt
> RTL8366_SMI_ACK_RETRY_COUNT
)
147 static int rtl8366_smi_write_byte(struct rtl8366_smi
*smi
, u8 data
)
149 rtl8366_smi_write_bits(smi
, data
, 8);
150 return rtl8366_smi_wait_for_ack(smi
);
153 static int rtl8366_smi_read_byte0(struct rtl8366_smi
*smi
, u8
*data
)
158 rtl8366_smi_read_bits(smi
, 8, &t
);
162 rtl8366_smi_write_bits(smi
, 0x00, 1);
167 static int rtl8366_smi_read_byte1(struct rtl8366_smi
*smi
, u8
*data
)
172 rtl8366_smi_read_bits(smi
, 8, &t
);
176 rtl8366_smi_write_bits(smi
, 0x01, 1);
181 int rtl8366_smi_read_reg(struct rtl8366_smi
*smi
, u32 addr
, u32
*data
)
188 spin_lock_irqsave(&smi
->lock
, flags
);
190 rtl8366_smi_start(smi
);
192 /* send READ command */
193 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x01);
198 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
203 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
208 rtl8366_smi_read_byte0(smi
, &lo
);
209 /* read DATA[15:8] */
210 rtl8366_smi_read_byte1(smi
, &hi
);
212 *data
= ((u32
) lo
) | (((u32
) hi
) << 8);
217 rtl8366_smi_stop(smi
);
218 spin_unlock_irqrestore(&smi
->lock
, flags
);
222 EXPORT_SYMBOL_GPL(rtl8366_smi_read_reg
);
224 int rtl8366_smi_write_reg(struct rtl8366_smi
*smi
, u32 addr
, u32 data
)
229 spin_lock_irqsave(&smi
->lock
, flags
);
231 rtl8366_smi_start(smi
);
233 /* send WRITE command */
234 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x00);
239 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
244 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
248 /* write DATA[7:0] */
249 ret
= rtl8366_smi_write_byte(smi
, data
& 0xff);
253 /* write DATA[15:8] */
254 ret
= rtl8366_smi_write_byte(smi
, data
>> 8);
261 rtl8366_smi_stop(smi
);
262 spin_unlock_irqrestore(&smi
->lock
, flags
);
266 EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg
);
268 int rtl8366_smi_init(struct rtl8366_smi
*smi
)
275 err
= gpio_request(smi
->gpio_sda
, dev_name(smi
->parent
));
277 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
282 err
= gpio_request(smi
->gpio_sck
, dev_name(smi
->parent
));
284 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
289 spin_lock_init(&smi
->lock
);
291 dev_info(smi
->parent
, "using GPIO pins %u (SDA) and %u (SCK)\n",
292 smi
->gpio_sda
, smi
->gpio_sck
);
297 gpio_free(smi
->gpio_sda
);
301 EXPORT_SYMBOL_GPL(rtl8366_smi_init
);
303 void rtl8366_smi_cleanup(struct rtl8366_smi
*smi
)
305 gpio_free(smi
->gpio_sck
);
306 gpio_free(smi
->gpio_sda
);
308 EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup
);
310 MODULE_DESCRIPTION("Realtek RTL8366 SMI interface driver");
311 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
312 MODULE_LICENSE("GPL v2");