linux/drivers/net/dsa/realtek-smi-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Realtek Simple Management Interface (SMI) driver
   3 * It can be discussed how "simple" this interface is.
   4 *
   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.
   9 *
  10 * ASICs we intend to support with this driver:
  11 *
  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
  20 *
  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>
  26 */
  27
  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>
  33#include <linux/of.h>
  34#include <linux/of_device.h>
  35#include <linux/of_mdio.h>
  36#include <linux/delay.h>
  37#include <linux/gpio/consumer.h>
  38#include <linux/platform_device.h>
  39#include <linux/regmap.h>
  40#include <linux/bitops.h>
  41#include <linux/if_bridge.h>
  42
  43#include "realtek-smi-core.h"
  44
  45#define REALTEK_SMI_ACK_RETRY_COUNT             5
  46#define REALTEK_SMI_HW_STOP_DELAY               25      /* msecs */
  47#define REALTEK_SMI_HW_START_DELAY              100     /* msecs */
  48
  49static inline void realtek_smi_clk_delay(struct realtek_smi *smi)
  50{
  51        ndelay(smi->clk_delay);
  52}
  53
  54static void realtek_smi_start(struct realtek_smi *smi)
  55{
  56        /* Set GPIO pins to output mode, with initial state:
  57         * SCK = 0, SDA = 1
  58         */
  59        gpiod_direction_output(smi->mdc, 0);
  60        gpiod_direction_output(smi->mdio, 1);
  61        realtek_smi_clk_delay(smi);
  62
  63        /* CLK 1: 0 -> 1, 1 -> 0 */
  64        gpiod_set_value(smi->mdc, 1);
  65        realtek_smi_clk_delay(smi);
  66        gpiod_set_value(smi->mdc, 0);
  67        realtek_smi_clk_delay(smi);
  68
  69        /* CLK 2: */
  70        gpiod_set_value(smi->mdc, 1);
  71        realtek_smi_clk_delay(smi);
  72        gpiod_set_value(smi->mdio, 0);
  73        realtek_smi_clk_delay(smi);
  74        gpiod_set_value(smi->mdc, 0);
  75        realtek_smi_clk_delay(smi);
  76        gpiod_set_value(smi->mdio, 1);
  77}
  78
  79static void realtek_smi_stop(struct realtek_smi *smi)
  80{
  81        realtek_smi_clk_delay(smi);
  82        gpiod_set_value(smi->mdio, 0);
  83        gpiod_set_value(smi->mdc, 1);
  84        realtek_smi_clk_delay(smi);
  85        gpiod_set_value(smi->mdio, 1);
  86        realtek_smi_clk_delay(smi);
  87        gpiod_set_value(smi->mdc, 1);
  88        realtek_smi_clk_delay(smi);
  89        gpiod_set_value(smi->mdc, 0);
  90        realtek_smi_clk_delay(smi);
  91        gpiod_set_value(smi->mdc, 1);
  92
  93        /* Add a click */
  94        realtek_smi_clk_delay(smi);
  95        gpiod_set_value(smi->mdc, 0);
  96        realtek_smi_clk_delay(smi);
  97        gpiod_set_value(smi->mdc, 1);
  98
  99        /* Set GPIO pins to input mode */
 100        gpiod_direction_input(smi->mdio);
 101        gpiod_direction_input(smi->mdc);
 102}
 103
 104static void realtek_smi_write_bits(struct realtek_smi *smi, u32 data, u32 len)
 105{
 106        for (; len > 0; len--) {
 107                realtek_smi_clk_delay(smi);
 108
 109                /* Prepare data */
 110                gpiod_set_value(smi->mdio, !!(data & (1 << (len - 1))));
 111                realtek_smi_clk_delay(smi);
 112
 113                /* Clocking */
 114                gpiod_set_value(smi->mdc, 1);
 115                realtek_smi_clk_delay(smi);
 116                gpiod_set_value(smi->mdc, 0);
 117        }
 118}
 119
 120static void realtek_smi_read_bits(struct realtek_smi *smi, u32 len, u32 *data)
 121{
 122        gpiod_direction_input(smi->mdio);
 123
 124        for (*data = 0; len > 0; len--) {
 125                u32 u;
 126
 127                realtek_smi_clk_delay(smi);
 128
 129                /* Clocking */
 130                gpiod_set_value(smi->mdc, 1);
 131                realtek_smi_clk_delay(smi);
 132                u = !!gpiod_get_value(smi->mdio);
 133                gpiod_set_value(smi->mdc, 0);
 134
 135                *data |= (u << (len - 1));
 136        }
 137
 138        gpiod_direction_output(smi->mdio, 0);
 139}
 140
 141static int realtek_smi_wait_for_ack(struct realtek_smi *smi)
 142{
 143        int retry_cnt;
 144
 145        retry_cnt = 0;
 146        do {
 147                u32 ack;
 148
 149                realtek_smi_read_bits(smi, 1, &ack);
 150                if (ack == 0)
 151                        break;
 152
 153                if (++retry_cnt > REALTEK_SMI_ACK_RETRY_COUNT) {
 154                        dev_err(smi->dev, "ACK timeout\n");
 155                        return -ETIMEDOUT;
 156                }
 157        } while (1);
 158
 159        return 0;
 160}
 161
 162static int realtek_smi_write_byte(struct realtek_smi *smi, u8 data)
 163{
 164        realtek_smi_write_bits(smi, data, 8);
 165        return realtek_smi_wait_for_ack(smi);
 166}
 167
 168static int realtek_smi_write_byte_noack(struct realtek_smi *smi, u8 data)
 169{
 170        realtek_smi_write_bits(smi, data, 8);
 171        return 0;
 172}
 173
 174static int realtek_smi_read_byte0(struct realtek_smi *smi, u8 *data)
 175{
 176        u32 t;
 177
 178        /* Read data */
 179        realtek_smi_read_bits(smi, 8, &t);
 180        *data = (t & 0xff);
 181
 182        /* Send an ACK */
 183        realtek_smi_write_bits(smi, 0x00, 1);
 184
 185        return 0;
 186}
 187
 188static int realtek_smi_read_byte1(struct realtek_smi *smi, u8 *data)
 189{
 190        u32 t;
 191
 192        /* Read data */
 193        realtek_smi_read_bits(smi, 8, &t);
 194        *data = (t & 0xff);
 195
 196        /* Send an ACK */
 197        realtek_smi_write_bits(smi, 0x01, 1);
 198
 199        return 0;
 200}
 201
 202static int realtek_smi_read_reg(struct realtek_smi *smi, u32 addr, u32 *data)
 203{
 204        unsigned long flags;
 205        u8 lo = 0;
 206        u8 hi = 0;
 207        int ret;
 208
 209        spin_lock_irqsave(&smi->lock, flags);
 210
 211        realtek_smi_start(smi);
 212
 213        /* Send READ command */
 214        ret = realtek_smi_write_byte(smi, smi->cmd_read);
 215        if (ret)
 216                goto out;
 217
 218        /* Set ADDR[7:0] */
 219        ret = realtek_smi_write_byte(smi, addr & 0xff);
 220        if (ret)
 221                goto out;
 222
 223        /* Set ADDR[15:8] */
 224        ret = realtek_smi_write_byte(smi, addr >> 8);
 225        if (ret)
 226                goto out;
 227
 228        /* Read DATA[7:0] */
 229        realtek_smi_read_byte0(smi, &lo);
 230        /* Read DATA[15:8] */
 231        realtek_smi_read_byte1(smi, &hi);
 232
 233        *data = ((u32)lo) | (((u32)hi) << 8);
 234
 235        ret = 0;
 236
 237 out:
 238        realtek_smi_stop(smi);
 239        spin_unlock_irqrestore(&smi->lock, flags);
 240
 241        return ret;
 242}
 243
 244static int realtek_smi_write_reg(struct realtek_smi *smi,
 245                                 u32 addr, u32 data, bool ack)
 246{
 247        unsigned long flags;
 248        int ret;
 249
 250        spin_lock_irqsave(&smi->lock, flags);
 251
 252        realtek_smi_start(smi);
 253
 254        /* Send WRITE command */
 255        ret = realtek_smi_write_byte(smi, smi->cmd_write);
 256        if (ret)
 257                goto out;
 258
 259        /* Set ADDR[7:0] */
 260        ret = realtek_smi_write_byte(smi, addr & 0xff);
 261        if (ret)
 262                goto out;
 263
 264        /* Set ADDR[15:8] */
 265        ret = realtek_smi_write_byte(smi, addr >> 8);
 266        if (ret)
 267                goto out;
 268
 269        /* Write DATA[7:0] */
 270        ret = realtek_smi_write_byte(smi, data & 0xff);
 271        if (ret)
 272                goto out;
 273
 274        /* Write DATA[15:8] */
 275        if (ack)
 276                ret = realtek_smi_write_byte(smi, data >> 8);
 277        else
 278                ret = realtek_smi_write_byte_noack(smi, data >> 8);
 279        if (ret)
 280                goto out;
 281
 282        ret = 0;
 283
 284 out:
 285        realtek_smi_stop(smi);
 286        spin_unlock_irqrestore(&smi->lock, flags);
 287
 288        return ret;
 289}
 290
 291/* There is one single case when we need to use this accessor and that
 292 * is when issueing soft reset. Since the device reset as soon as we write
 293 * that bit, no ACK will come back for natural reasons.
 294 */
 295int realtek_smi_write_reg_noack(struct realtek_smi *smi, u32 addr,
 296                                u32 data)
 297{
 298        return realtek_smi_write_reg(smi, addr, data, false);
 299}
 300EXPORT_SYMBOL_GPL(realtek_smi_write_reg_noack);
 301
 302/* Regmap accessors */
 303
 304static int realtek_smi_write(void *ctx, u32 reg, u32 val)
 305{
 306        struct realtek_smi *smi = ctx;
 307
 308        return realtek_smi_write_reg(smi, reg, val, true);
 309}
 310
 311static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
 312{
 313        struct realtek_smi *smi = ctx;
 314
 315        return realtek_smi_read_reg(smi, reg, val);
 316}
 317
 318static const struct regmap_config realtek_smi_mdio_regmap_config = {
 319        .reg_bits = 10, /* A4..A0 R4..R0 */
 320        .val_bits = 16,
 321        .reg_stride = 1,
 322        /* PHY regs are at 0x8000 */
 323        .max_register = 0xffff,
 324        .reg_format_endian = REGMAP_ENDIAN_BIG,
 325        .reg_read = realtek_smi_read,
 326        .reg_write = realtek_smi_write,
 327        .cache_type = REGCACHE_NONE,
 328};
 329
 330static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
 331{
 332        struct realtek_smi *smi = bus->priv;
 333
 334        return smi->ops->phy_read(smi, addr, regnum);
 335}
 336
 337static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
 338                                  u16 val)
 339{
 340        struct realtek_smi *smi = bus->priv;
 341
 342        return smi->ops->phy_write(smi, addr, regnum, val);
 343}
 344
 345int realtek_smi_setup_mdio(struct realtek_smi *smi)
 346{
 347        struct device_node *mdio_np;
 348        int ret;
 349
 350        mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
 351        if (!mdio_np) {
 352                dev_err(smi->dev, "no MDIO bus node\n");
 353                return -ENODEV;
 354        }
 355
 356        smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
 357        if (!smi->slave_mii_bus) {
 358                ret = -ENOMEM;
 359                goto err_put_node;
 360        }
 361        smi->slave_mii_bus->priv = smi;
 362        smi->slave_mii_bus->name = "SMI slave MII";
 363        smi->slave_mii_bus->read = realtek_smi_mdio_read;
 364        smi->slave_mii_bus->write = realtek_smi_mdio_write;
 365        snprintf(smi->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
 366                 smi->ds->index);
 367        smi->slave_mii_bus->dev.of_node = mdio_np;
 368        smi->slave_mii_bus->parent = smi->dev;
 369        smi->ds->slave_mii_bus = smi->slave_mii_bus;
 370
 371        ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np);
 372        if (ret) {
 373                dev_err(smi->dev, "unable to register MDIO bus %s\n",
 374                        smi->slave_mii_bus->id);
 375                goto err_put_node;
 376        }
 377
 378        return 0;
 379
 380err_put_node:
 381        of_node_put(mdio_np);
 382
 383        return ret;
 384}
 385
 386static int realtek_smi_probe(struct platform_device *pdev)
 387{
 388        const struct realtek_smi_variant *var;
 389        struct device *dev = &pdev->dev;
 390        struct realtek_smi *smi;
 391        struct device_node *np;
 392        int ret;
 393
 394        var = of_device_get_match_data(dev);
 395        np = dev->of_node;
 396
 397        smi = devm_kzalloc(dev, sizeof(*smi) + var->chip_data_sz, GFP_KERNEL);
 398        if (!smi)
 399                return -ENOMEM;
 400        smi->chip_data = (void *)smi + sizeof(*smi);
 401        smi->map = devm_regmap_init(dev, NULL, smi,
 402                                    &realtek_smi_mdio_regmap_config);
 403        if (IS_ERR(smi->map)) {
 404                ret = PTR_ERR(smi->map);
 405                dev_err(dev, "regmap init failed: %d\n", ret);
 406                return ret;
 407        }
 408
 409        /* Link forward and backward */
 410        smi->dev = dev;
 411        smi->clk_delay = var->clk_delay;
 412        smi->cmd_read = var->cmd_read;
 413        smi->cmd_write = var->cmd_write;
 414        smi->ops = var->ops;
 415
 416        dev_set_drvdata(dev, smi);
 417        spin_lock_init(&smi->lock);
 418
 419        /* TODO: if power is software controlled, set up any regulators here */
 420
 421        /* Assert then deassert RESET */
 422        smi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 423        if (IS_ERR(smi->reset)) {
 424                dev_err(dev, "failed to get RESET GPIO\n");
 425                return PTR_ERR(smi->reset);
 426        }
 427        msleep(REALTEK_SMI_HW_STOP_DELAY);
 428        gpiod_set_value(smi->reset, 0);
 429        msleep(REALTEK_SMI_HW_START_DELAY);
 430        dev_info(dev, "deasserted RESET\n");
 431
 432        /* Fetch MDIO pins */
 433        smi->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
 434        if (IS_ERR(smi->mdc))
 435                return PTR_ERR(smi->mdc);
 436        smi->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
 437        if (IS_ERR(smi->mdio))
 438                return PTR_ERR(smi->mdio);
 439
 440        smi->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
 441
 442        ret = smi->ops->detect(smi);
 443        if (ret) {
 444                dev_err(dev, "unable to detect switch\n");
 445                return ret;
 446        }
 447
 448        smi->ds = devm_kzalloc(dev, sizeof(*smi->ds), GFP_KERNEL);
 449        if (!smi->ds)
 450                return -ENOMEM;
 451
 452        smi->ds->dev = dev;
 453        smi->ds->num_ports = smi->num_ports;
 454        smi->ds->priv = smi;
 455
 456        smi->ds->ops = var->ds_ops;
 457        ret = dsa_register_switch(smi->ds);
 458        if (ret) {
 459                dev_err(dev, "unable to register switch ret = %d\n", ret);
 460                return ret;
 461        }
 462        return 0;
 463}
 464
 465static int realtek_smi_remove(struct platform_device *pdev)
 466{
 467        struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
 468
 469        dsa_unregister_switch(smi->ds);
 470        if (smi->slave_mii_bus)
 471                of_node_put(smi->slave_mii_bus->dev.of_node);
 472        gpiod_set_value(smi->reset, 1);
 473
 474        return 0;
 475}
 476
 477static const struct of_device_id realtek_smi_of_match[] = {
 478        {
 479                .compatible = "realtek,rtl8366rb",
 480                .data = &rtl8366rb_variant,
 481        },
 482        {
 483                /* FIXME: add support for RTL8366S and more */
 484                .compatible = "realtek,rtl8366s",
 485                .data = NULL,
 486        },
 487        { /* sentinel */ },
 488};
 489MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
 490
 491static struct platform_driver realtek_smi_driver = {
 492        .driver = {
 493                .name = "realtek-smi",
 494                .of_match_table = of_match_ptr(realtek_smi_of_match),
 495        },
 496        .probe  = realtek_smi_probe,
 497        .remove = realtek_smi_remove,
 498};
 499module_platform_driver(realtek_smi_driver);
 500
 501MODULE_LICENSE("GPL");
 502