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>
17 #include <linux/skbuff.h>
19 #include "rtl8366_smi.h"
21 #define RTL8366_SMI_ACK_RETRY_COUNT 5
22 #define RTL8366_SMI_CLK_DELAY 10 /* nsec */
24 static inline void rtl8366_smi_clk_delay(struct rtl8366_smi
*smi
)
26 ndelay(RTL8366_SMI_CLK_DELAY
);
29 static void rtl8366_smi_start(struct rtl8366_smi
*smi
)
31 unsigned int sda
= smi
->gpio_sda
;
32 unsigned int sck
= smi
->gpio_sck
;
35 * Set GPIO pins to output mode, with initial state:
38 gpio_direction_output(sck
, 0);
39 gpio_direction_output(sda
, 1);
40 rtl8366_smi_clk_delay(smi
);
42 /* CLK 1: 0 -> 1, 1 -> 0 */
43 gpio_set_value(sck
, 1);
44 rtl8366_smi_clk_delay(smi
);
45 gpio_set_value(sck
, 0);
46 rtl8366_smi_clk_delay(smi
);
49 gpio_set_value(sck
, 1);
50 rtl8366_smi_clk_delay(smi
);
51 gpio_set_value(sda
, 0);
52 rtl8366_smi_clk_delay(smi
);
53 gpio_set_value(sck
, 0);
54 rtl8366_smi_clk_delay(smi
);
55 gpio_set_value(sda
, 1);
58 static void rtl8366_smi_stop(struct rtl8366_smi
*smi
)
60 unsigned int sda
= smi
->gpio_sda
;
61 unsigned int sck
= smi
->gpio_sck
;
63 rtl8366_smi_clk_delay(smi
);
64 gpio_set_value(sda
, 0);
65 gpio_set_value(sck
, 1);
66 rtl8366_smi_clk_delay(smi
);
67 gpio_set_value(sda
, 1);
68 rtl8366_smi_clk_delay(smi
);
69 gpio_set_value(sck
, 1);
70 rtl8366_smi_clk_delay(smi
);
71 gpio_set_value(sck
, 0);
72 rtl8366_smi_clk_delay(smi
);
73 gpio_set_value(sck
, 1);
76 rtl8366_smi_clk_delay(smi
);
77 gpio_set_value(sck
, 0);
78 rtl8366_smi_clk_delay(smi
);
79 gpio_set_value(sck
, 1);
81 /* set GPIO pins to input mode */
82 gpio_direction_input(sda
);
83 gpio_direction_input(sck
);
86 static void rtl8366_smi_write_bits(struct rtl8366_smi
*smi
, u32 data
, u32 len
)
88 unsigned int sda
= smi
->gpio_sda
;
89 unsigned int sck
= smi
->gpio_sck
;
91 for (; len
> 0; len
--) {
92 rtl8366_smi_clk_delay(smi
);
95 gpio_set_value(sda
, !!(data
& ( 1 << (len
- 1))));
96 rtl8366_smi_clk_delay(smi
);
99 gpio_set_value(sck
, 1);
100 rtl8366_smi_clk_delay(smi
);
101 gpio_set_value(sck
, 0);
105 static void rtl8366_smi_read_bits(struct rtl8366_smi
*smi
, u32 len
, u32
*data
)
107 unsigned int sda
= smi
->gpio_sda
;
108 unsigned int sck
= smi
->gpio_sck
;
110 gpio_direction_input(sda
);
112 for (*data
= 0; len
> 0; len
--) {
115 rtl8366_smi_clk_delay(smi
);
118 gpio_set_value(sck
, 1);
119 rtl8366_smi_clk_delay(smi
);
120 u
= !!gpio_get_value(sda
);
121 gpio_set_value(sck
, 0);
123 *data
|= (u
<< (len
- 1));
126 gpio_direction_output(sda
, 0);
129 static int rtl8366_smi_wait_for_ack(struct rtl8366_smi
*smi
)
137 rtl8366_smi_read_bits(smi
, 1, &ack
);
141 if (++retry_cnt
> RTL8366_SMI_ACK_RETRY_COUNT
)
148 static int rtl8366_smi_write_byte(struct rtl8366_smi
*smi
, u8 data
)
150 rtl8366_smi_write_bits(smi
, data
, 8);
151 return rtl8366_smi_wait_for_ack(smi
);
154 static int rtl8366_smi_read_byte0(struct rtl8366_smi
*smi
, u8
*data
)
159 rtl8366_smi_read_bits(smi
, 8, &t
);
163 rtl8366_smi_write_bits(smi
, 0x00, 1);
168 static int rtl8366_smi_read_byte1(struct rtl8366_smi
*smi
, u8
*data
)
173 rtl8366_smi_read_bits(smi
, 8, &t
);
177 rtl8366_smi_write_bits(smi
, 0x01, 1);
182 int rtl8366_smi_read_reg(struct rtl8366_smi
*smi
, u32 addr
, u32
*data
)
189 spin_lock_irqsave(&smi
->lock
, flags
);
191 rtl8366_smi_start(smi
);
193 /* send READ command */
194 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x01);
199 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
204 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
209 rtl8366_smi_read_byte0(smi
, &lo
);
210 /* read DATA[15:8] */
211 rtl8366_smi_read_byte1(smi
, &hi
);
213 *data
= ((u32
) lo
) | (((u32
) hi
) << 8);
218 rtl8366_smi_stop(smi
);
219 spin_unlock_irqrestore(&smi
->lock
, flags
);
223 EXPORT_SYMBOL_GPL(rtl8366_smi_read_reg
);
225 int rtl8366_smi_write_reg(struct rtl8366_smi
*smi
, u32 addr
, u32 data
)
230 spin_lock_irqsave(&smi
->lock
, flags
);
232 rtl8366_smi_start(smi
);
234 /* send WRITE command */
235 ret
= rtl8366_smi_write_byte(smi
, 0x0a << 4 | 0x04 << 1 | 0x00);
240 ret
= rtl8366_smi_write_byte(smi
, addr
& 0xff);
245 ret
= rtl8366_smi_write_byte(smi
, addr
>> 8);
249 /* write DATA[7:0] */
250 ret
= rtl8366_smi_write_byte(smi
, data
& 0xff);
254 /* write DATA[15:8] */
255 ret
= rtl8366_smi_write_byte(smi
, data
>> 8);
262 rtl8366_smi_stop(smi
);
263 spin_unlock_irqrestore(&smi
->lock
, flags
);
267 EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg
);
269 int rtl8366_smi_rmwr(struct rtl8366_smi
*smi
, u32 addr
, u32 mask
, u32 data
)
274 err
= rtl8366_smi_read_reg(smi
, addr
, &t
);
278 err
= rtl8366_smi_write_reg(smi
, addr
, (t
& ~mask
) | data
);
282 EXPORT_SYMBOL_GPL(rtl8366_smi_rmwr
);
284 static int rtl8366_smi_mii_init(struct rtl8366_smi
*smi
)
289 smi
->mii_bus
= mdiobus_alloc();
290 if (smi
->mii_bus
== NULL
) {
295 smi
->mii_bus
->priv
= (void *) smi
;
296 smi
->mii_bus
->name
= dev_name(smi
->parent
);
297 smi
->mii_bus
->read
= smi
->ops
->mii_read
;
298 smi
->mii_bus
->write
= smi
->ops
->mii_write
;
299 snprintf(smi
->mii_bus
->id
, MII_BUS_ID_SIZE
, "%s",
300 dev_name(smi
->parent
));
301 smi
->mii_bus
->parent
= smi
->parent
;
302 smi
->mii_bus
->phy_mask
= ~(0x1f);
303 smi
->mii_bus
->irq
= smi
->mii_irq
;
304 for (i
= 0; i
< PHY_MAX_ADDR
; i
++)
305 smi
->mii_irq
[i
] = PHY_POLL
;
307 ret
= mdiobus_register(smi
->mii_bus
);
314 mdiobus_free(smi
->mii_bus
);
319 static void rtl8366_smi_mii_cleanup(struct rtl8366_smi
*smi
)
321 mdiobus_unregister(smi
->mii_bus
);
322 mdiobus_free(smi
->mii_bus
);
325 int rtl8366_smi_init(struct rtl8366_smi
*smi
)
335 err
= gpio_request(smi
->gpio_sda
, dev_name(smi
->parent
));
337 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
342 err
= gpio_request(smi
->gpio_sck
, dev_name(smi
->parent
));
344 dev_err(smi
->parent
, "gpio_request failed for %u, err=%d\n",
349 spin_lock_init(&smi
->lock
);
351 dev_info(smi
->parent
, "using GPIO pins %u (SDA) and %u (SCK)\n",
352 smi
->gpio_sda
, smi
->gpio_sck
);
354 err
= smi
->ops
->detect(smi
);
356 dev_err(smi
->parent
, "chip detection failed, err=%d\n", err
);
360 err
= rtl8366_smi_mii_init(smi
);
367 gpio_free(smi
->gpio_sck
);
369 gpio_free(smi
->gpio_sda
);
373 EXPORT_SYMBOL_GPL(rtl8366_smi_init
);
375 void rtl8366_smi_cleanup(struct rtl8366_smi
*smi
)
377 rtl8366_smi_mii_cleanup(smi
);
378 gpio_free(smi
->gpio_sck
);
379 gpio_free(smi
->gpio_sda
);
381 EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup
);
383 MODULE_DESCRIPTION("Realtek RTL8366 SMI interface driver");
384 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
385 MODULE_LICENSE("GPL v2");