root/drivers/net/phy/spi_ks8995.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_chip_id
  2. get_chip_rev
  3. create_spi_cmd
  4. ks8995_read
  5. ks8995_write
  6. ks8995_read_reg
  7. ks8995_write_reg
  8. ks8995_stop
  9. ks8995_start
  10. ks8995_reset
  11. ks8995_registers_read
  12. ks8995_registers_write
  13. ks8995_get_revision
  14. ks8995_parse_dt
  15. ks8995_probe
  16. ks8995_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches
   4  *
   5  * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
   6  *
   7  * This file was based on: drivers/spi/at25.c
   8  *     Copyright (C) 2006 David Brownell
   9  */
  10 
  11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12 
  13 #include <linux/types.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/delay.h>
  17 #include <linux/device.h>
  18 #include <linux/gpio/consumer.h>
  19 #include <linux/of.h>
  20 #include <linux/of_gpio.h>
  21 
  22 #include <linux/spi/spi.h>
  23 
  24 #define DRV_VERSION             "0.1.1"
  25 #define DRV_DESC                "Micrel KS8995 Ethernet switch SPI driver"
  26 
  27 /* ------------------------------------------------------------------------ */
  28 
  29 #define KS8995_REG_ID0          0x00    /* Chip ID0 */
  30 #define KS8995_REG_ID1          0x01    /* Chip ID1 */
  31 
  32 #define KS8995_REG_GC0          0x02    /* Global Control 0 */
  33 #define KS8995_REG_GC1          0x03    /* Global Control 1 */
  34 #define KS8995_REG_GC2          0x04    /* Global Control 2 */
  35 #define KS8995_REG_GC3          0x05    /* Global Control 3 */
  36 #define KS8995_REG_GC4          0x06    /* Global Control 4 */
  37 #define KS8995_REG_GC5          0x07    /* Global Control 5 */
  38 #define KS8995_REG_GC6          0x08    /* Global Control 6 */
  39 #define KS8995_REG_GC7          0x09    /* Global Control 7 */
  40 #define KS8995_REG_GC8          0x0a    /* Global Control 8 */
  41 #define KS8995_REG_GC9          0x0b    /* Global Control 9 */
  42 
  43 #define KS8995_REG_PC(p, r)     ((0x10 * p) + r)         /* Port Control */
  44 #define KS8995_REG_PS(p, r)     ((0x10 * p) + r + 0xe)  /* Port Status */
  45 
  46 #define KS8995_REG_TPC0         0x60    /* TOS Priority Control 0 */
  47 #define KS8995_REG_TPC1         0x61    /* TOS Priority Control 1 */
  48 #define KS8995_REG_TPC2         0x62    /* TOS Priority Control 2 */
  49 #define KS8995_REG_TPC3         0x63    /* TOS Priority Control 3 */
  50 #define KS8995_REG_TPC4         0x64    /* TOS Priority Control 4 */
  51 #define KS8995_REG_TPC5         0x65    /* TOS Priority Control 5 */
  52 #define KS8995_REG_TPC6         0x66    /* TOS Priority Control 6 */
  53 #define KS8995_REG_TPC7         0x67    /* TOS Priority Control 7 */
  54 
  55 #define KS8995_REG_MAC0         0x68    /* MAC address 0 */
  56 #define KS8995_REG_MAC1         0x69    /* MAC address 1 */
  57 #define KS8995_REG_MAC2         0x6a    /* MAC address 2 */
  58 #define KS8995_REG_MAC3         0x6b    /* MAC address 3 */
  59 #define KS8995_REG_MAC4         0x6c    /* MAC address 4 */
  60 #define KS8995_REG_MAC5         0x6d    /* MAC address 5 */
  61 
  62 #define KS8995_REG_IAC0         0x6e    /* Indirect Access Control 0 */
  63 #define KS8995_REG_IAC1         0x6f    /* Indirect Access Control 0 */
  64 #define KS8995_REG_IAD7         0x70    /* Indirect Access Data 7 */
  65 #define KS8995_REG_IAD6         0x71    /* Indirect Access Data 6 */
  66 #define KS8995_REG_IAD5         0x72    /* Indirect Access Data 5 */
  67 #define KS8995_REG_IAD4         0x73    /* Indirect Access Data 4 */
  68 #define KS8995_REG_IAD3         0x74    /* Indirect Access Data 3 */
  69 #define KS8995_REG_IAD2         0x75    /* Indirect Access Data 2 */
  70 #define KS8995_REG_IAD1         0x76    /* Indirect Access Data 1 */
  71 #define KS8995_REG_IAD0         0x77    /* Indirect Access Data 0 */
  72 
  73 #define KSZ8864_REG_ID1         0xfe    /* Chip ID in bit 7 */
  74 
  75 #define KS8995_REGS_SIZE        0x80
  76 #define KSZ8864_REGS_SIZE       0x100
  77 #define KSZ8795_REGS_SIZE       0x100
  78 
  79 #define ID1_CHIPID_M            0xf
  80 #define ID1_CHIPID_S            4
  81 #define ID1_REVISION_M          0x7
  82 #define ID1_REVISION_S          1
  83 #define ID1_START_SW            1       /* start the switch */
  84 
  85 #define FAMILY_KS8995           0x95
  86 #define FAMILY_KSZ8795          0x87
  87 #define CHIPID_M                0
  88 #define KS8995_CHIP_ID          0x00
  89 #define KSZ8864_CHIP_ID         0x01
  90 #define KSZ8795_CHIP_ID         0x09
  91 
  92 #define KS8995_CMD_WRITE        0x02U
  93 #define KS8995_CMD_READ         0x03U
  94 
  95 #define KS8995_RESET_DELAY      10 /* usec */
  96 
  97 enum ks8995_chip_variant {
  98         ks8995,
  99         ksz8864,
 100         ksz8795,
 101         max_variant
 102 };
 103 
 104 struct ks8995_chip_params {
 105         char *name;
 106         int family_id;
 107         int chip_id;
 108         int regs_size;
 109         int addr_width;
 110         int addr_shift;
 111 };
 112 
 113 static const struct ks8995_chip_params ks8995_chip[] = {
 114         [ks8995] = {
 115                 .name = "KS8995MA",
 116                 .family_id = FAMILY_KS8995,
 117                 .chip_id = KS8995_CHIP_ID,
 118                 .regs_size = KS8995_REGS_SIZE,
 119                 .addr_width = 8,
 120                 .addr_shift = 0,
 121         },
 122         [ksz8864] = {
 123                 .name = "KSZ8864RMN",
 124                 .family_id = FAMILY_KS8995,
 125                 .chip_id = KSZ8864_CHIP_ID,
 126                 .regs_size = KSZ8864_REGS_SIZE,
 127                 .addr_width = 8,
 128                 .addr_shift = 0,
 129         },
 130         [ksz8795] = {
 131                 .name = "KSZ8795CLX",
 132                 .family_id = FAMILY_KSZ8795,
 133                 .chip_id = KSZ8795_CHIP_ID,
 134                 .regs_size = KSZ8795_REGS_SIZE,
 135                 .addr_width = 12,
 136                 .addr_shift = 1,
 137         },
 138 };
 139 
 140 struct ks8995_pdata {
 141         int reset_gpio;
 142         enum of_gpio_flags reset_gpio_flags;
 143 };
 144 
 145 struct ks8995_switch {
 146         struct spi_device       *spi;
 147         struct mutex            lock;
 148         struct ks8995_pdata     *pdata;
 149         struct bin_attribute    regs_attr;
 150         const struct ks8995_chip_params *chip;
 151         int                     revision_id;
 152 };
 153 
 154 static const struct spi_device_id ks8995_id[] = {
 155         {"ks8995", ks8995},
 156         {"ksz8864", ksz8864},
 157         {"ksz8795", ksz8795},
 158         { }
 159 };
 160 MODULE_DEVICE_TABLE(spi, ks8995_id);
 161 
 162 static const struct of_device_id ks8895_spi_of_match[] = {
 163         { .compatible = "micrel,ks8995" },
 164         { .compatible = "micrel,ksz8864" },
 165         { .compatible = "micrel,ksz8795" },
 166         { },
 167  };
 168 MODULE_DEVICE_TABLE(of, ks8895_spi_of_match);
 169 
 170 static inline u8 get_chip_id(u8 val)
 171 {
 172         return (val >> ID1_CHIPID_S) & ID1_CHIPID_M;
 173 }
 174 
 175 static inline u8 get_chip_rev(u8 val)
 176 {
 177         return (val >> ID1_REVISION_S) & ID1_REVISION_M;
 178 }
 179 
 180 /* create_spi_cmd - create a chip specific SPI command header
 181  * @ks: pointer to switch instance
 182  * @cmd: SPI command for switch
 183  * @address: register address for command
 184  *
 185  * Different chip families use different bit pattern to address the switches
 186  * registers:
 187  *
 188  * KS8995: 8bit command + 8bit address
 189  * KSZ8795: 3bit command + 12bit address + 1bit TR (?)
 190  */
 191 static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd,
 192                                     unsigned address)
 193 {
 194         u16 result = cmd;
 195 
 196         /* make room for address (incl. address shift) */
 197         result <<= ks->chip->addr_width + ks->chip->addr_shift;
 198         /* add address */
 199         result |= address << ks->chip->addr_shift;
 200         /* SPI protocol needs big endian */
 201         return cpu_to_be16(result);
 202 }
 203 /* ------------------------------------------------------------------------ */
 204 static int ks8995_read(struct ks8995_switch *ks, char *buf,
 205                  unsigned offset, size_t count)
 206 {
 207         __be16 cmd;
 208         struct spi_transfer t[2];
 209         struct spi_message m;
 210         int err;
 211 
 212         cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset);
 213         spi_message_init(&m);
 214 
 215         memset(&t, 0, sizeof(t));
 216 
 217         t[0].tx_buf = &cmd;
 218         t[0].len = sizeof(cmd);
 219         spi_message_add_tail(&t[0], &m);
 220 
 221         t[1].rx_buf = buf;
 222         t[1].len = count;
 223         spi_message_add_tail(&t[1], &m);
 224 
 225         mutex_lock(&ks->lock);
 226         err = spi_sync(ks->spi, &m);
 227         mutex_unlock(&ks->lock);
 228 
 229         return err ? err : count;
 230 }
 231 
 232 static int ks8995_write(struct ks8995_switch *ks, char *buf,
 233                  unsigned offset, size_t count)
 234 {
 235         __be16 cmd;
 236         struct spi_transfer t[2];
 237         struct spi_message m;
 238         int err;
 239 
 240         cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset);
 241         spi_message_init(&m);
 242 
 243         memset(&t, 0, sizeof(t));
 244 
 245         t[0].tx_buf = &cmd;
 246         t[0].len = sizeof(cmd);
 247         spi_message_add_tail(&t[0], &m);
 248 
 249         t[1].tx_buf = buf;
 250         t[1].len = count;
 251         spi_message_add_tail(&t[1], &m);
 252 
 253         mutex_lock(&ks->lock);
 254         err = spi_sync(ks->spi, &m);
 255         mutex_unlock(&ks->lock);
 256 
 257         return err ? err : count;
 258 }
 259 
 260 static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf)
 261 {
 262         return ks8995_read(ks, buf, addr, 1) != 1;
 263 }
 264 
 265 static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val)
 266 {
 267         char buf = val;
 268 
 269         return ks8995_write(ks, &buf, addr, 1) != 1;
 270 }
 271 
 272 /* ------------------------------------------------------------------------ */
 273 
 274 static int ks8995_stop(struct ks8995_switch *ks)
 275 {
 276         return ks8995_write_reg(ks, KS8995_REG_ID1, 0);
 277 }
 278 
 279 static int ks8995_start(struct ks8995_switch *ks)
 280 {
 281         return ks8995_write_reg(ks, KS8995_REG_ID1, 1);
 282 }
 283 
 284 static int ks8995_reset(struct ks8995_switch *ks)
 285 {
 286         int err;
 287 
 288         err = ks8995_stop(ks);
 289         if (err)
 290                 return err;
 291 
 292         udelay(KS8995_RESET_DELAY);
 293 
 294         return ks8995_start(ks);
 295 }
 296 
 297 static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj,
 298         struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
 299 {
 300         struct device *dev;
 301         struct ks8995_switch *ks8995;
 302 
 303         dev = container_of(kobj, struct device, kobj);
 304         ks8995 = dev_get_drvdata(dev);
 305 
 306         return ks8995_read(ks8995, buf, off, count);
 307 }
 308 
 309 static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj,
 310         struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
 311 {
 312         struct device *dev;
 313         struct ks8995_switch *ks8995;
 314 
 315         dev = container_of(kobj, struct device, kobj);
 316         ks8995 = dev_get_drvdata(dev);
 317 
 318         return ks8995_write(ks8995, buf, off, count);
 319 }
 320 
 321 /* ks8995_get_revision - get chip revision
 322  * @ks: pointer to switch instance
 323  *
 324  * Verify chip family and id and get chip revision.
 325  */
 326 static int ks8995_get_revision(struct ks8995_switch *ks)
 327 {
 328         int err;
 329         u8 id0, id1, ksz8864_id;
 330 
 331         /* read family id */
 332         err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0);
 333         if (err) {
 334                 err = -EIO;
 335                 goto err_out;
 336         }
 337 
 338         /* verify family id */
 339         if (id0 != ks->chip->family_id) {
 340                 dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n",
 341                         ks->chip->family_id, id0);
 342                 err = -ENODEV;
 343                 goto err_out;
 344         }
 345 
 346         switch (ks->chip->family_id) {
 347         case FAMILY_KS8995:
 348                 /* try reading chip id at CHIP ID1 */
 349                 err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1);
 350                 if (err) {
 351                         err = -EIO;
 352                         goto err_out;
 353                 }
 354 
 355                 /* verify chip id */
 356                 if ((get_chip_id(id1) == CHIPID_M) &&
 357                     (get_chip_id(id1) == ks->chip->chip_id)) {
 358                         /* KS8995MA */
 359                         ks->revision_id = get_chip_rev(id1);
 360                 } else if (get_chip_id(id1) != CHIPID_M) {
 361                         /* KSZ8864RMN */
 362                         err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id);
 363                         if (err) {
 364                                 err = -EIO;
 365                                 goto err_out;
 366                         }
 367 
 368                         if ((ksz8864_id & 0x80) &&
 369                             (ks->chip->chip_id == KSZ8864_CHIP_ID)) {
 370                                 ks->revision_id = get_chip_rev(id1);
 371                         }
 372 
 373                 } else {
 374                         dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n",
 375                                 id1);
 376                         err = -ENODEV;
 377                 }
 378                 break;
 379         case FAMILY_KSZ8795:
 380                 /* try reading chip id at CHIP ID1 */
 381                 err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1);
 382                 if (err) {
 383                         err = -EIO;
 384                         goto err_out;
 385                 }
 386 
 387                 if (get_chip_id(id1) == ks->chip->chip_id) {
 388                         ks->revision_id = get_chip_rev(id1);
 389                 } else {
 390                         dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n",
 391                                 id1);
 392                         err = -ENODEV;
 393                 }
 394                 break;
 395         default:
 396                 dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0);
 397                 err = -ENODEV;
 398                 break;
 399         }
 400 err_out:
 401         return err;
 402 }
 403 
 404 /* ks8995_parse_dt - setup platform data from devicetree
 405  * @ks: pointer to switch instance
 406  *
 407  * Parses supported DT properties and sets up platform data
 408  * accordingly.
 409  */
 410 static void ks8995_parse_dt(struct ks8995_switch *ks)
 411 {
 412         struct device_node *np = ks->spi->dev.of_node;
 413         struct ks8995_pdata *pdata = ks->pdata;
 414 
 415         if (!np)
 416                 return;
 417 
 418         pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0,
 419                 &pdata->reset_gpio_flags);
 420 }
 421 
 422 static const struct bin_attribute ks8995_registers_attr = {
 423         .attr = {
 424                 .name   = "registers",
 425                 .mode   = 0600,
 426         },
 427         .size   = KS8995_REGS_SIZE,
 428         .read   = ks8995_registers_read,
 429         .write  = ks8995_registers_write,
 430 };
 431 
 432 /* ------------------------------------------------------------------------ */
 433 static int ks8995_probe(struct spi_device *spi)
 434 {
 435         struct ks8995_switch *ks;
 436         int err;
 437         int variant = spi_get_device_id(spi)->driver_data;
 438 
 439         if (variant >= max_variant) {
 440                 dev_err(&spi->dev, "bad chip variant %d\n", variant);
 441                 return -ENODEV;
 442         }
 443 
 444         ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL);
 445         if (!ks)
 446                 return -ENOMEM;
 447 
 448         mutex_init(&ks->lock);
 449         ks->spi = spi;
 450         ks->chip = &ks8995_chip[variant];
 451 
 452         if (ks->spi->dev.of_node) {
 453                 ks->pdata = devm_kzalloc(&spi->dev, sizeof(*ks->pdata),
 454                                          GFP_KERNEL);
 455                 if (!ks->pdata)
 456                         return -ENOMEM;
 457 
 458                 ks->pdata->reset_gpio = -1;
 459 
 460                 ks8995_parse_dt(ks);
 461         }
 462 
 463         if (!ks->pdata)
 464                 ks->pdata = spi->dev.platform_data;
 465 
 466         /* de-assert switch reset */
 467         if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio)) {
 468                 unsigned long flags;
 469 
 470                 flags = (ks->pdata->reset_gpio_flags == OF_GPIO_ACTIVE_LOW ?
 471                          GPIOF_ACTIVE_LOW : 0);
 472 
 473                 err = devm_gpio_request_one(&spi->dev,
 474                                             ks->pdata->reset_gpio,
 475                                             flags, "switch-reset");
 476                 if (err) {
 477                         dev_err(&spi->dev,
 478                                 "failed to get reset-gpios: %d\n", err);
 479                         return -EIO;
 480                 }
 481 
 482                 gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 0);
 483         }
 484 
 485         spi_set_drvdata(spi, ks);
 486 
 487         spi->mode = SPI_MODE_0;
 488         spi->bits_per_word = 8;
 489         err = spi_setup(spi);
 490         if (err) {
 491                 dev_err(&spi->dev, "spi_setup failed, err=%d\n", err);
 492                 return err;
 493         }
 494 
 495         err = ks8995_get_revision(ks);
 496         if (err)
 497                 return err;
 498 
 499         memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
 500         ks->regs_attr.size = ks->chip->regs_size;
 501 
 502         err = ks8995_reset(ks);
 503         if (err)
 504                 return err;
 505 
 506         sysfs_attr_init(&ks->regs_attr.attr);
 507         err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
 508         if (err) {
 509                 dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
 510                                     err);
 511                 return err;
 512         }
 513 
 514         dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n",
 515                  ks->chip->name, ks->chip->chip_id, ks->revision_id);
 516 
 517         return 0;
 518 }
 519 
 520 static int ks8995_remove(struct spi_device *spi)
 521 {
 522         struct ks8995_switch *ks = spi_get_drvdata(spi);
 523 
 524         sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr);
 525 
 526         /* assert reset */
 527         if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio))
 528                 gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1);
 529 
 530         return 0;
 531 }
 532 
 533 /* ------------------------------------------------------------------------ */
 534 static struct spi_driver ks8995_driver = {
 535         .driver = {
 536                 .name       = "spi-ks8995",
 537                 .of_match_table = of_match_ptr(ks8895_spi_of_match),
 538         },
 539         .probe    = ks8995_probe,
 540         .remove   = ks8995_remove,
 541         .id_table = ks8995_id,
 542 };
 543 
 544 module_spi_driver(ks8995_driver);
 545 
 546 MODULE_DESCRIPTION(DRV_DESC);
 547 MODULE_VERSION(DRV_VERSION);
 548 MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
 549 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */