linux/drivers/i2c/busses/scx200_acb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
   4
   5    National Semiconductor SCx200 ACCESS.bus support
   6    Also supports the AMD CS5535 and AMD CS5536
   7
   8    Based on i2c-keywest.c which is:
   9        Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  10        Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
  11
  12*/
  13
  14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/module.h>
  17#include <linux/errno.h>
  18#include <linux/kernel.h>
  19#include <linux/init.h>
  20#include <linux/i2c.h>
  21#include <linux/pci.h>
  22#include <linux/platform_device.h>
  23#include <linux/delay.h>
  24#include <linux/mutex.h>
  25#include <linux/slab.h>
  26#include <linux/io.h>
  27
  28#include <linux/scx200.h>
  29
  30MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
  31MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
  32MODULE_ALIAS("platform:cs5535-smb");
  33MODULE_LICENSE("GPL");
  34
  35#define MAX_DEVICES 4
  36static int base[MAX_DEVICES] = { 0x820, 0x840 };
  37module_param_hw_array(base, int, ioport, NULL, 0);
  38MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
  39
  40#define POLL_TIMEOUT    (HZ/5)
  41
  42enum scx200_acb_state {
  43        state_idle,
  44        state_address,
  45        state_command,
  46        state_repeat_start,
  47        state_quick,
  48        state_read,
  49        state_write,
  50};
  51
  52static const char *scx200_acb_state_name[] = {
  53        "idle",
  54        "address",
  55        "command",
  56        "repeat_start",
  57        "quick",
  58        "read",
  59        "write",
  60};
  61
  62/* Physical interface */
  63struct scx200_acb_iface {
  64        struct scx200_acb_iface *next;
  65        struct i2c_adapter adapter;
  66        unsigned base;
  67        struct mutex mutex;
  68
  69        /* State machine data */
  70        enum scx200_acb_state state;
  71        int result;
  72        u8 address_byte;
  73        u8 command;
  74        u8 *ptr;
  75        char needs_reset;
  76        unsigned len;
  77};
  78
  79/* Register Definitions */
  80#define ACBSDA          (iface->base + 0)
  81#define ACBST           (iface->base + 1)
  82#define    ACBST_SDAST          0x40 /* SDA Status */
  83#define    ACBST_BER            0x20
  84#define    ACBST_NEGACK         0x10 /* Negative Acknowledge */
  85#define    ACBST_STASTR         0x08 /* Stall After Start */
  86#define    ACBST_MASTER         0x02
  87#define ACBCST          (iface->base + 2)
  88#define    ACBCST_BB            0x02
  89#define ACBCTL1         (iface->base + 3)
  90#define    ACBCTL1_STASTRE      0x80
  91#define    ACBCTL1_NMINTE       0x40
  92#define    ACBCTL1_ACK          0x10
  93#define    ACBCTL1_STOP         0x02
  94#define    ACBCTL1_START        0x01
  95#define ACBADDR         (iface->base + 4)
  96#define ACBCTL2         (iface->base + 5)
  97#define    ACBCTL2_ENABLE       0x01
  98
  99/************************************************************************/
 100
 101static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
 102{
 103        const char *errmsg;
 104
 105        dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n",
 106                scx200_acb_state_name[iface->state], status);
 107
 108        if (status & ACBST_BER) {
 109                errmsg = "bus error";
 110                goto error;
 111        }
 112        if (!(status & ACBST_MASTER)) {
 113                errmsg = "not master";
 114                goto error;
 115        }
 116        if (status & ACBST_NEGACK) {
 117                dev_dbg(&iface->adapter.dev, "negative ack in state %s\n",
 118                        scx200_acb_state_name[iface->state]);
 119
 120                iface->state = state_idle;
 121                iface->result = -ENXIO;
 122
 123                outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
 124                outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
 125
 126                /* Reset the status register */
 127                outb(0, ACBST);
 128                return;
 129        }
 130
 131        switch (iface->state) {
 132        case state_idle:
 133                dev_warn(&iface->adapter.dev, "interrupt in idle state\n");
 134                break;
 135
 136        case state_address:
 137                /* Do a pointer write first */
 138                outb(iface->address_byte & ~1, ACBSDA);
 139
 140                iface->state = state_command;
 141                break;
 142
 143        case state_command:
 144                outb(iface->command, ACBSDA);
 145
 146                if (iface->address_byte & 1)
 147                        iface->state = state_repeat_start;
 148                else
 149                        iface->state = state_write;
 150                break;
 151
 152        case state_repeat_start:
 153                outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
 154                fallthrough;
 155
 156        case state_quick:
 157                if (iface->address_byte & 1) {
 158                        if (iface->len == 1)
 159                                outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
 160                        else
 161                                outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
 162                        outb(iface->address_byte, ACBSDA);
 163
 164                        iface->state = state_read;
 165                } else {
 166                        outb(iface->address_byte, ACBSDA);
 167
 168                        iface->state = state_write;
 169                }
 170                break;
 171
 172        case state_read:
 173                /* Set ACK if _next_ byte will be the last one */
 174                if (iface->len == 2)
 175                        outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
 176                else
 177                        outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
 178
 179                if (iface->len == 1) {
 180                        iface->result = 0;
 181                        iface->state = state_idle;
 182                        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
 183                }
 184
 185                *iface->ptr++ = inb(ACBSDA);
 186                --iface->len;
 187
 188                break;
 189
 190        case state_write:
 191                if (iface->len == 0) {
 192                        iface->result = 0;
 193                        iface->state = state_idle;
 194                        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
 195                        break;
 196                }
 197
 198                outb(*iface->ptr++, ACBSDA);
 199                --iface->len;
 200
 201                break;
 202        }
 203
 204        return;
 205
 206 error:
 207        dev_err(&iface->adapter.dev,
 208                "%s in state %s (addr=0x%02x, len=%d, status=0x%02x)\n", errmsg,
 209                scx200_acb_state_name[iface->state], iface->address_byte,
 210                iface->len, status);
 211
 212        iface->state = state_idle;
 213        iface->result = -EIO;
 214        iface->needs_reset = 1;
 215}
 216
 217static void scx200_acb_poll(struct scx200_acb_iface *iface)
 218{
 219        u8 status;
 220        unsigned long timeout;
 221
 222        timeout = jiffies + POLL_TIMEOUT;
 223        while (1) {
 224                status = inb(ACBST);
 225
 226                /* Reset the status register to avoid the hang */
 227                outb(0, ACBST);
 228
 229                if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
 230                        scx200_acb_machine(iface, status);
 231                        return;
 232                }
 233                if (time_after(jiffies, timeout))
 234                        break;
 235                cpu_relax();
 236                cond_resched();
 237        }
 238
 239        dev_err(&iface->adapter.dev, "timeout in state %s\n",
 240                scx200_acb_state_name[iface->state]);
 241
 242        iface->state = state_idle;
 243        iface->result = -EIO;
 244        iface->needs_reset = 1;
 245}
 246
 247static void scx200_acb_reset(struct scx200_acb_iface *iface)
 248{
 249        /* Disable the ACCESS.bus device and Configure the SCL
 250           frequency: 16 clock cycles */
 251        outb(0x70, ACBCTL2);
 252        /* Polling mode */
 253        outb(0, ACBCTL1);
 254        /* Disable slave address */
 255        outb(0, ACBADDR);
 256        /* Enable the ACCESS.bus device */
 257        outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
 258        /* Free STALL after START */
 259        outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1);
 260        /* Send a STOP */
 261        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
 262        /* Clear BER, NEGACK and STASTR bits */
 263        outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST);
 264        /* Clear BB bit */
 265        outb(inb(ACBCST) | ACBCST_BB, ACBCST);
 266}
 267
 268static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
 269                                 u16 address, unsigned short flags,
 270                                 char rw, u8 command, int size,
 271                                 union i2c_smbus_data *data)
 272{
 273        struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
 274        int len;
 275        u8 *buffer;
 276        u16 cur_word;
 277        int rc;
 278
 279        switch (size) {
 280        case I2C_SMBUS_QUICK:
 281                len = 0;
 282                buffer = NULL;
 283                break;
 284
 285        case I2C_SMBUS_BYTE:
 286                len = 1;
 287                buffer = rw ? &data->byte : &command;
 288                break;
 289
 290        case I2C_SMBUS_BYTE_DATA:
 291                len = 1;
 292                buffer = &data->byte;
 293                break;
 294
 295        case I2C_SMBUS_WORD_DATA:
 296                len = 2;
 297                cur_word = cpu_to_le16(data->word);
 298                buffer = (u8 *)&cur_word;
 299                break;
 300
 301        case I2C_SMBUS_I2C_BLOCK_DATA:
 302                len = data->block[0];
 303                if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
 304                        return -EINVAL;
 305                buffer = &data->block[1];
 306                break;
 307
 308        default:
 309                return -EINVAL;
 310        }
 311
 312        dev_dbg(&adapter->dev,
 313                "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
 314                size, address, command, len, rw);
 315
 316        if (!len && rw == I2C_SMBUS_READ) {
 317                dev_dbg(&adapter->dev, "zero length read\n");
 318                return -EINVAL;
 319        }
 320
 321        mutex_lock(&iface->mutex);
 322
 323        iface->address_byte = (address << 1) | rw;
 324        iface->command = command;
 325        iface->ptr = buffer;
 326        iface->len = len;
 327        iface->result = -EINVAL;
 328        iface->needs_reset = 0;
 329
 330        outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
 331
 332        if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)
 333                iface->state = state_quick;
 334        else
 335                iface->state = state_address;
 336
 337        while (iface->state != state_idle)
 338                scx200_acb_poll(iface);
 339
 340        if (iface->needs_reset)
 341                scx200_acb_reset(iface);
 342
 343        rc = iface->result;
 344
 345        mutex_unlock(&iface->mutex);
 346
 347        if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ)
 348                data->word = le16_to_cpu(cur_word);
 349
 350#ifdef DEBUG
 351        dev_dbg(&adapter->dev, "transfer done, result: %d", rc);
 352        if (buffer) {
 353                int i;
 354                printk(" data:");
 355                for (i = 0; i < len; ++i)
 356                        printk(" %02x", buffer[i]);
 357        }
 358        printk("\n");
 359#endif
 360
 361        return rc;
 362}
 363
 364static u32 scx200_acb_func(struct i2c_adapter *adapter)
 365{
 366        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 367               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 368               I2C_FUNC_SMBUS_I2C_BLOCK;
 369}
 370
 371/* For now, we only handle combined mode (smbus) */
 372static const struct i2c_algorithm scx200_acb_algorithm = {
 373        .smbus_xfer     = scx200_acb_smbus_xfer,
 374        .functionality  = scx200_acb_func,
 375};
 376
 377static struct scx200_acb_iface *scx200_acb_list;
 378static DEFINE_MUTEX(scx200_acb_list_mutex);
 379
 380static int scx200_acb_probe(struct scx200_acb_iface *iface)
 381{
 382        u8 val;
 383
 384        /* Disable the ACCESS.bus device and Configure the SCL
 385           frequency: 16 clock cycles */
 386        outb(0x70, ACBCTL2);
 387
 388        if (inb(ACBCTL2) != 0x70) {
 389                pr_debug("ACBCTL2 readback failed\n");
 390                return -ENXIO;
 391        }
 392
 393        outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
 394
 395        val = inb(ACBCTL1);
 396        if (val) {
 397                pr_debug("disabled, but ACBCTL1=0x%02x\n", val);
 398                return -ENXIO;
 399        }
 400
 401        outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
 402
 403        outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
 404
 405        val = inb(ACBCTL1);
 406        if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
 407                pr_debug("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n",
 408                         val);
 409                return -ENXIO;
 410        }
 411
 412        return 0;
 413}
 414
 415static struct scx200_acb_iface *scx200_create_iface(const char *text,
 416                struct device *dev, int index)
 417{
 418        struct scx200_acb_iface *iface;
 419        struct i2c_adapter *adapter;
 420
 421        iface = kzalloc(sizeof(*iface), GFP_KERNEL);
 422        if (!iface)
 423                return NULL;
 424
 425        adapter = &iface->adapter;
 426        i2c_set_adapdata(adapter, iface);
 427        snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
 428        adapter->owner = THIS_MODULE;
 429        adapter->algo = &scx200_acb_algorithm;
 430        adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
 431        adapter->dev.parent = dev;
 432
 433        mutex_init(&iface->mutex);
 434
 435        return iface;
 436}
 437
 438static int scx200_acb_create(struct scx200_acb_iface *iface)
 439{
 440        struct i2c_adapter *adapter;
 441        int rc;
 442
 443        adapter = &iface->adapter;
 444
 445        rc = scx200_acb_probe(iface);
 446        if (rc) {
 447                pr_warn("probe failed\n");
 448                return rc;
 449        }
 450
 451        scx200_acb_reset(iface);
 452
 453        if (i2c_add_adapter(adapter) < 0) {
 454                pr_err("failed to register\n");
 455                return -ENODEV;
 456        }
 457
 458        if (!adapter->dev.parent) {
 459                /* If there's no dev, we're tracking (ISA) ifaces manually */
 460                mutex_lock(&scx200_acb_list_mutex);
 461                iface->next = scx200_acb_list;
 462                scx200_acb_list = iface;
 463                mutex_unlock(&scx200_acb_list_mutex);
 464        }
 465
 466        return 0;
 467}
 468
 469static struct scx200_acb_iface *scx200_create_dev(const char *text,
 470                unsigned long base, int index, struct device *dev)
 471{
 472        struct scx200_acb_iface *iface;
 473        int rc;
 474
 475        iface = scx200_create_iface(text, dev, index);
 476
 477        if (iface == NULL)
 478                return NULL;
 479
 480        if (!request_region(base, 8, iface->adapter.name)) {
 481                pr_err("can't allocate io 0x%lx-0x%lx\n", base, base + 8 - 1);
 482                goto errout_free;
 483        }
 484
 485        iface->base = base;
 486        rc = scx200_acb_create(iface);
 487
 488        if (rc == 0)
 489                return iface;
 490
 491        release_region(base, 8);
 492 errout_free:
 493        kfree(iface);
 494        return NULL;
 495}
 496
 497static int scx200_probe(struct platform_device *pdev)
 498{
 499        struct scx200_acb_iface *iface;
 500        struct resource *res;
 501
 502        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 503        if (!res) {
 504                dev_err(&pdev->dev, "can't fetch device resource info\n");
 505                return -ENODEV;
 506        }
 507
 508        iface = scx200_create_dev("CS5535", res->start, 0, &pdev->dev);
 509        if (!iface)
 510                return -EIO;
 511
 512        dev_info(&pdev->dev, "SCx200 device '%s' registered\n",
 513                        iface->adapter.name);
 514        platform_set_drvdata(pdev, iface);
 515
 516        return 0;
 517}
 518
 519static void scx200_cleanup_iface(struct scx200_acb_iface *iface)
 520{
 521        i2c_del_adapter(&iface->adapter);
 522        release_region(iface->base, 8);
 523        kfree(iface);
 524}
 525
 526static int scx200_remove(struct platform_device *pdev)
 527{
 528        struct scx200_acb_iface *iface;
 529
 530        iface = platform_get_drvdata(pdev);
 531        scx200_cleanup_iface(iface);
 532
 533        return 0;
 534}
 535
 536static struct platform_driver scx200_pci_driver = {
 537        .driver = {
 538                .name = "cs5535-smb",
 539        },
 540        .probe = scx200_probe,
 541        .remove = scx200_remove,
 542};
 543
 544static const struct pci_device_id scx200_isa[] = {
 545        { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
 546        { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
 547        { 0, }
 548};
 549
 550static __init void scx200_scan_isa(void)
 551{
 552        int i;
 553
 554        if (!pci_dev_present(scx200_isa))
 555                return;
 556
 557        for (i = 0; i < MAX_DEVICES; ++i) {
 558                if (base[i] == 0)
 559                        continue;
 560
 561                /* XXX: should we care about failures? */
 562                scx200_create_dev("SCx200", base[i], i, NULL);
 563        }
 564}
 565
 566static int __init scx200_acb_init(void)
 567{
 568        pr_debug("NatSemi SCx200 ACCESS.bus Driver\n");
 569
 570        /* First scan for ISA-based devices */
 571        scx200_scan_isa();      /* XXX: should we care about errors? */
 572
 573        /* If at least one bus was created, init must succeed */
 574        if (scx200_acb_list)
 575                return 0;
 576
 577        /* No ISA devices; register the platform driver for PCI-based devices */
 578        return platform_driver_register(&scx200_pci_driver);
 579}
 580
 581static void __exit scx200_acb_cleanup(void)
 582{
 583        struct scx200_acb_iface *iface;
 584
 585        platform_driver_unregister(&scx200_pci_driver);
 586
 587        mutex_lock(&scx200_acb_list_mutex);
 588        while ((iface = scx200_acb_list) != NULL) {
 589                scx200_acb_list = iface->next;
 590                mutex_unlock(&scx200_acb_list_mutex);
 591
 592                scx200_cleanup_iface(iface);
 593
 594                mutex_lock(&scx200_acb_list_mutex);
 595        }
 596        mutex_unlock(&scx200_acb_list_mutex);
 597}
 598
 599module_init(scx200_acb_init);
 600module_exit(scx200_acb_cleanup);
 601
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.