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");