1 // SPDX-License-Identifier: GPL-2.0+
2 /* Realtek Simple Management Interface (SMI) driver
3 * It can be discussed how "simple" this interface is.
5 * The SMI protocol piggy-backs the MDIO MDC and MDIO signals levels
6 * but the protocol is not MDIO at all. Instead it is a Realtek
7 * pecularity that need to bit-bang the lines in a special way to
8 * communicate with the switch.
10 * ASICs we intend to support with this driver:
12 * RTL8366 - The original version, apparently
13 * RTL8369 - Similar enough to have the same datsheet as RTL8366
14 * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite
15 * different register layout from the other two
16 * RTL8366S - Is this "RTL8366 super"?
17 * RTL8367 - Has an OpenWRT driver as well
18 * RTL8368S - Seems to be an alternative name for RTL8366RB
19 * RTL8370 - Also uses SMI
21 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
22 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
23 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
24 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
25 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/device.h>
31 #include <linux/spinlock.h>
32 #include <linux/skbuff.h>
34 #include <linux/delay.h>
35 #include <linux/gpio/consumer.h>
36 #include <linux/platform_device.h>
37 #include <linux/regmap.h>
38 #include <linux/bitops.h>
39 #include <linux/if_bridge.h>
42 #include "realtek-smi.h"
45 #define REALTEK_SMI_ACK_RETRY_COUNT 5
47 static inline void realtek_smi_clk_delay(struct realtek_priv
*priv
)
49 ndelay(priv
->variant
->clk_delay
);
52 static void realtek_smi_start(struct realtek_priv
*priv
)
54 /* Set GPIO pins to output mode, with initial state:
57 gpiod_direction_output(priv
->mdc
, 0);
58 gpiod_direction_output(priv
->mdio
, 1);
59 realtek_smi_clk_delay(priv
);
61 /* CLK 1: 0 -> 1, 1 -> 0 */
62 gpiod_set_value(priv
->mdc
, 1);
63 realtek_smi_clk_delay(priv
);
64 gpiod_set_value(priv
->mdc
, 0);
65 realtek_smi_clk_delay(priv
);
68 gpiod_set_value(priv
->mdc
, 1);
69 realtek_smi_clk_delay(priv
);
70 gpiod_set_value(priv
->mdio
, 0);
71 realtek_smi_clk_delay(priv
);
72 gpiod_set_value(priv
->mdc
, 0);
73 realtek_smi_clk_delay(priv
);
74 gpiod_set_value(priv
->mdio
, 1);
77 static void realtek_smi_stop(struct realtek_priv
*priv
)
79 realtek_smi_clk_delay(priv
);
80 gpiod_set_value(priv
->mdio
, 0);
81 gpiod_set_value(priv
->mdc
, 1);
82 realtek_smi_clk_delay(priv
);
83 gpiod_set_value(priv
->mdio
, 1);
84 realtek_smi_clk_delay(priv
);
85 gpiod_set_value(priv
->mdc
, 1);
86 realtek_smi_clk_delay(priv
);
87 gpiod_set_value(priv
->mdc
, 0);
88 realtek_smi_clk_delay(priv
);
89 gpiod_set_value(priv
->mdc
, 1);
92 realtek_smi_clk_delay(priv
);
93 gpiod_set_value(priv
->mdc
, 0);
94 realtek_smi_clk_delay(priv
);
95 gpiod_set_value(priv
->mdc
, 1);
97 /* Set GPIO pins to input mode */
98 gpiod_direction_input(priv
->mdio
);
99 gpiod_direction_input(priv
->mdc
);
102 static void realtek_smi_write_bits(struct realtek_priv
*priv
, u32 data
, u32 len
)
104 for (; len
> 0; len
--) {
105 realtek_smi_clk_delay(priv
);
108 gpiod_set_value(priv
->mdio
, !!(data
& (1 << (len
- 1))));
109 realtek_smi_clk_delay(priv
);
112 gpiod_set_value(priv
->mdc
, 1);
113 realtek_smi_clk_delay(priv
);
114 gpiod_set_value(priv
->mdc
, 0);
118 static void realtek_smi_read_bits(struct realtek_priv
*priv
, u32 len
, u32
*data
)
120 gpiod_direction_input(priv
->mdio
);
122 for (*data
= 0; len
> 0; len
--) {
125 realtek_smi_clk_delay(priv
);
128 gpiod_set_value(priv
->mdc
, 1);
129 realtek_smi_clk_delay(priv
);
130 u
= !!gpiod_get_value(priv
->mdio
);
131 gpiod_set_value(priv
->mdc
, 0);
133 *data
|= (u
<< (len
- 1));
136 gpiod_direction_output(priv
->mdio
, 0);
139 static int realtek_smi_wait_for_ack(struct realtek_priv
*priv
)
147 realtek_smi_read_bits(priv
, 1, &ack
);
151 if (++retry_cnt
> REALTEK_SMI_ACK_RETRY_COUNT
) {
152 dev_err(priv
->dev
, "ACK timeout\n");
160 static int realtek_smi_write_byte(struct realtek_priv
*priv
, u8 data
)
162 realtek_smi_write_bits(priv
, data
, 8);
163 return realtek_smi_wait_for_ack(priv
);
166 static int realtek_smi_write_byte_noack(struct realtek_priv
*priv
, u8 data
)
168 realtek_smi_write_bits(priv
, data
, 8);
172 static int realtek_smi_read_byte0(struct realtek_priv
*priv
, u8
*data
)
177 realtek_smi_read_bits(priv
, 8, &t
);
181 realtek_smi_write_bits(priv
, 0x00, 1);
186 static int realtek_smi_read_byte1(struct realtek_priv
*priv
, u8
*data
)
191 realtek_smi_read_bits(priv
, 8, &t
);
195 realtek_smi_write_bits(priv
, 0x01, 1);
200 static int realtek_smi_read_reg(struct realtek_priv
*priv
, u32 addr
, u32
*data
)
207 spin_lock_irqsave(&priv
->lock
, flags
);
209 realtek_smi_start(priv
);
211 /* Send READ command */
212 ret
= realtek_smi_write_byte(priv
, priv
->variant
->cmd_read
);
217 ret
= realtek_smi_write_byte(priv
, addr
& 0xff);
222 ret
= realtek_smi_write_byte(priv
, addr
>> 8);
227 realtek_smi_read_byte0(priv
, &lo
);
228 /* Read DATA[15:8] */
229 realtek_smi_read_byte1(priv
, &hi
);
231 *data
= ((u32
)lo
) | (((u32
)hi
) << 8);
236 realtek_smi_stop(priv
);
237 spin_unlock_irqrestore(&priv
->lock
, flags
);
242 static int realtek_smi_write_reg(struct realtek_priv
*priv
,
243 u32 addr
, u32 data
, bool ack
)
248 spin_lock_irqsave(&priv
->lock
, flags
);
250 realtek_smi_start(priv
);
252 /* Send WRITE command */
253 ret
= realtek_smi_write_byte(priv
, priv
->variant
->cmd_write
);
258 ret
= realtek_smi_write_byte(priv
, addr
& 0xff);
263 ret
= realtek_smi_write_byte(priv
, addr
>> 8);
267 /* Write DATA[7:0] */
268 ret
= realtek_smi_write_byte(priv
, data
& 0xff);
272 /* Write DATA[15:8] */
274 ret
= realtek_smi_write_byte(priv
, data
>> 8);
276 ret
= realtek_smi_write_byte_noack(priv
, data
>> 8);
283 realtek_smi_stop(priv
);
284 spin_unlock_irqrestore(&priv
->lock
, flags
);
289 /* There is one single case when we need to use this accessor and that
290 * is when issueing soft reset. Since the device reset as soon as we write
291 * that bit, no ACK will come back for natural reasons.
293 static int realtek_smi_write_reg_noack(void *ctx
, u32 reg
, u32 val
)
295 return realtek_smi_write_reg(ctx
, reg
, val
, false);
298 /* Regmap accessors */
300 static int realtek_smi_write(void *ctx
, u32 reg
, u32 val
)
302 struct realtek_priv
*priv
= ctx
;
304 return realtek_smi_write_reg(priv
, reg
, val
, true);
307 static int realtek_smi_read(void *ctx
, u32 reg
, u32
*val
)
309 struct realtek_priv
*priv
= ctx
;
311 return realtek_smi_read_reg(priv
, reg
, val
);
314 static const struct realtek_interface_info realtek_smi_info
= {
315 .reg_read
= realtek_smi_read
,
316 .reg_write
= realtek_smi_write
,
320 * realtek_smi_probe() - Probe a platform device for an SMI-connected switch
321 * @pdev: platform_device to probe on.
323 * This function should be used as the .probe in a platform_driver. After
324 * calling the common probe function for both interfaces, it initializes the
325 * values specific for SMI-connected devices. Finally, it calls a common
326 * function to register the DSA switch.
328 * Context: Can sleep. Takes and releases priv->map_lock.
329 * Return: Returns 0 on success, a negative error on failure.
331 int realtek_smi_probe(struct platform_device
*pdev
)
333 struct device
*dev
= &pdev
->dev
;
334 struct realtek_priv
*priv
;
337 priv
= rtl83xx_probe(dev
, &realtek_smi_info
);
339 return PTR_ERR(priv
);
341 /* Fetch MDIO pins */
342 priv
->mdc
= devm_gpiod_get_optional(dev
, "mdc", GPIOD_OUT_LOW
);
343 if (IS_ERR(priv
->mdc
)) {
344 rtl83xx_remove(priv
);
345 return PTR_ERR(priv
->mdc
);
348 priv
->mdio
= devm_gpiod_get_optional(dev
, "mdio", GPIOD_OUT_LOW
);
349 if (IS_ERR(priv
->mdio
)) {
350 rtl83xx_remove(priv
);
351 return PTR_ERR(priv
->mdio
);
354 priv
->write_reg_noack
= realtek_smi_write_reg_noack
;
356 ret
= rtl83xx_register_switch(priv
);
358 rtl83xx_remove(priv
);
364 EXPORT_SYMBOL_NS_GPL(realtek_smi_probe
, "REALTEK_DSA");
367 * realtek_smi_remove() - Remove the driver of a SMI-connected switch
368 * @pdev: platform_device to be removed.
370 * This function should be used as the .remove in a platform_driver. First
371 * it unregisters the DSA switch and then it calls the common remove function.
373 * Context: Can sleep.
376 void realtek_smi_remove(struct platform_device
*pdev
)
378 struct realtek_priv
*priv
= platform_get_drvdata(pdev
);
383 rtl83xx_unregister_switch(priv
);
385 rtl83xx_remove(priv
);
387 EXPORT_SYMBOL_NS_GPL(realtek_smi_remove
, "REALTEK_DSA");
390 * realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
391 * @pdev: platform_device shutting down.
393 * This function should be used as the .shutdown in a platform_driver. It calls
394 * the common shutdown function.
396 * Context: Can sleep.
399 void realtek_smi_shutdown(struct platform_device
*pdev
)
401 struct realtek_priv
*priv
= platform_get_drvdata(pdev
);
406 rtl83xx_shutdown(priv
);
408 EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown
, "REALTEK_DSA");