linux/drivers/i2c/busses/i2c-xgene-slimpro.c
<<
>>
Prefs
   1/*
   2 * X-Gene SLIMpro I2C Driver
   3 *
   4 * Copyright (c) 2014, Applied Micro Circuits Corporation
   5 * Author: Feng Kan <fkan@apm.com>
   6 * Author: Hieu Le <hnle@apm.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  20 *
  21 * This driver provides support for X-Gene SLIMpro I2C device access
  22 * using the APM X-Gene SLIMpro mailbox driver.
  23 *
  24 */
  25#include <linux/acpi.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/i2c.h>
  28#include <linux/interrupt.h>
  29#include <linux/mailbox_client.h>
  30#include <linux/module.h>
  31#include <linux/of.h>
  32#include <linux/platform_device.h>
  33#include <linux/version.h>
  34
  35#define MAILBOX_OP_TIMEOUT              1000    /* Operation time out in ms */
  36#define MAILBOX_I2C_INDEX               0
  37#define SLIMPRO_IIC_BUS                 1       /* Use I2C bus 1 only */
  38
  39#define SMBUS_CMD_LEN                   1
  40#define BYTE_DATA                       1
  41#define WORD_DATA                       2
  42#define BLOCK_DATA                      3
  43
  44#define SLIMPRO_IIC_I2C_PROTOCOL        0
  45#define SLIMPRO_IIC_SMB_PROTOCOL        1
  46
  47#define SLIMPRO_IIC_READ                0
  48#define SLIMPRO_IIC_WRITE               1
  49
  50#define IIC_SMB_WITHOUT_DATA_LEN        0
  51#define IIC_SMB_WITH_DATA_LEN           1
  52
  53#define SLIMPRO_DEBUG_MSG               0
  54#define SLIMPRO_MSG_TYPE_SHIFT          28
  55#define SLIMPRO_DBG_SUBTYPE_I2C1READ    4
  56#define SLIMPRO_DBGMSG_TYPE_SHIFT       24
  57#define SLIMPRO_DBGMSG_TYPE_MASK        0x0F000000U
  58#define SLIMPRO_IIC_DEV_SHIFT           23
  59#define SLIMPRO_IIC_DEV_MASK            0x00800000U
  60#define SLIMPRO_IIC_DEVID_SHIFT         13
  61#define SLIMPRO_IIC_DEVID_MASK          0x007FE000U
  62#define SLIMPRO_IIC_RW_SHIFT            12
  63#define SLIMPRO_IIC_RW_MASK             0x00001000U
  64#define SLIMPRO_IIC_PROTO_SHIFT         11
  65#define SLIMPRO_IIC_PROTO_MASK          0x00000800U
  66#define SLIMPRO_IIC_ADDRLEN_SHIFT       8
  67#define SLIMPRO_IIC_ADDRLEN_MASK        0x00000700U
  68#define SLIMPRO_IIC_DATALEN_SHIFT       0
  69#define SLIMPRO_IIC_DATALEN_MASK        0x000000FFU
  70
  71/*
  72 * SLIMpro I2C message encode
  73 *
  74 * dev          - Controller number (0-based)
  75 * chip         - I2C chip address
  76 * op           - SLIMPRO_IIC_READ or SLIMPRO_IIC_WRITE
  77 * proto        - SLIMPRO_IIC_SMB_PROTOCOL or SLIMPRO_IIC_I2C_PROTOCOL
  78 * addrlen      - Length of the address field
  79 * datalen      - Length of the data field
  80 */
  81#define SLIMPRO_IIC_ENCODE_MSG(dev, chip, op, proto, addrlen, datalen) \
  82        ((SLIMPRO_DEBUG_MSG << SLIMPRO_MSG_TYPE_SHIFT) | \
  83        ((SLIMPRO_DBG_SUBTYPE_I2C1READ << SLIMPRO_DBGMSG_TYPE_SHIFT) & \
  84        SLIMPRO_DBGMSG_TYPE_MASK) | \
  85        ((dev << SLIMPRO_IIC_DEV_SHIFT) & SLIMPRO_IIC_DEV_MASK) | \
  86        ((chip << SLIMPRO_IIC_DEVID_SHIFT) & SLIMPRO_IIC_DEVID_MASK) | \
  87        ((op << SLIMPRO_IIC_RW_SHIFT) & SLIMPRO_IIC_RW_MASK) | \
  88        ((proto << SLIMPRO_IIC_PROTO_SHIFT) & SLIMPRO_IIC_PROTO_MASK) | \
  89        ((addrlen << SLIMPRO_IIC_ADDRLEN_SHIFT) & SLIMPRO_IIC_ADDRLEN_MASK) | \
  90        ((datalen << SLIMPRO_IIC_DATALEN_SHIFT) & SLIMPRO_IIC_DATALEN_MASK))
  91
  92/*
  93 * Encode for upper address for block data
  94 */
  95#define SLIMPRO_IIC_ENCODE_FLAG_BUFADDR                 0x80000000
  96#define SLIMPRO_IIC_ENCODE_FLAG_WITH_DATA_LEN(a)        ((u32) (((a) << 30) \
  97                                                                & 0x40000000))
  98#define SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(a)             ((u32) (((a) >> 12) \
  99                                                                & 0x3FF00000))
 100#define SLIMPRO_IIC_ENCODE_ADDR(a)                      ((a) & 0x000FFFFF)
 101
 102struct slimpro_i2c_dev {
 103        struct i2c_adapter adapter;
 104        struct device *dev;
 105        struct mbox_chan *mbox_chan;
 106        struct mbox_client mbox_client;
 107        struct completion rd_complete;
 108        u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* dma_buffer[0] is used for length */
 109        u32 *resp_msg;
 110};
 111
 112#define to_slimpro_i2c_dev(cl)  \
 113                container_of(cl, struct slimpro_i2c_dev, mbox_client)
 114
 115static void slimpro_i2c_rx_cb(struct mbox_client *cl, void *mssg)
 116{
 117        struct slimpro_i2c_dev *ctx = to_slimpro_i2c_dev(cl);
 118
 119        /*
 120         * Response message format:
 121         * mssg[0] is the return code of the operation
 122         * mssg[1] is the first data word
 123         * mssg[2] is NOT used
 124         */
 125        if (ctx->resp_msg)
 126                *ctx->resp_msg = ((u32 *)mssg)[1];
 127
 128        if (ctx->mbox_client.tx_block)
 129                complete(&ctx->rd_complete);
 130}
 131
 132static int start_i2c_msg_xfer(struct slimpro_i2c_dev *ctx)
 133{
 134        if (ctx->mbox_client.tx_block) {
 135                if (!wait_for_completion_timeout(&ctx->rd_complete,
 136                                                 msecs_to_jiffies(MAILBOX_OP_TIMEOUT)))
 137                        return -ETIMEDOUT;
 138        }
 139
 140        /* Check of invalid data or no device */
 141        if (*ctx->resp_msg == 0xffffffff)
 142                return -ENODEV;
 143
 144        return 0;
 145}
 146
 147static int slimpro_i2c_rd(struct slimpro_i2c_dev *ctx, u32 chip,
 148                          u32 addr, u32 addrlen, u32 protocol,
 149                          u32 readlen, u32 *data)
 150{
 151        u32 msg[3];
 152        int rc;
 153
 154        msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip,
 155                                        SLIMPRO_IIC_READ, protocol, addrlen, readlen);
 156        msg[1] = SLIMPRO_IIC_ENCODE_ADDR(addr);
 157        msg[2] = 0;
 158        ctx->resp_msg = data;
 159        rc = mbox_send_message(ctx->mbox_chan, &msg);
 160        if (rc < 0)
 161                goto err;
 162
 163        rc = start_i2c_msg_xfer(ctx);
 164err:
 165        ctx->resp_msg = NULL;
 166        return rc;
 167}
 168
 169static int slimpro_i2c_wr(struct slimpro_i2c_dev *ctx, u32 chip,
 170                          u32 addr, u32 addrlen, u32 protocol, u32 writelen,
 171                          u32 data)
 172{
 173        u32 msg[3];
 174        int rc;
 175
 176        msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip,
 177                                        SLIMPRO_IIC_WRITE, protocol, addrlen, writelen);
 178        msg[1] = SLIMPRO_IIC_ENCODE_ADDR(addr);
 179        msg[2] = data;
 180        ctx->resp_msg = msg;
 181
 182        rc = mbox_send_message(ctx->mbox_chan, &msg);
 183        if (rc < 0)
 184                goto err;
 185
 186        rc = start_i2c_msg_xfer(ctx);
 187err:
 188        ctx->resp_msg = NULL;
 189        return rc;
 190}
 191
 192static int slimpro_i2c_blkrd(struct slimpro_i2c_dev *ctx, u32 chip, u32 addr,
 193                             u32 addrlen, u32 protocol, u32 readlen,
 194                             u32 with_data_len, void *data)
 195{
 196        dma_addr_t paddr;
 197        u32 msg[3];
 198        int rc;
 199
 200        paddr = dma_map_single(ctx->dev, ctx->dma_buffer, readlen, DMA_FROM_DEVICE);
 201        if (dma_mapping_error(ctx->dev, paddr)) {
 202                dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n",
 203                        ctx->dma_buffer);
 204                rc = -ENOMEM;
 205                goto err;
 206        }
 207
 208        msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, SLIMPRO_IIC_READ,
 209                                        protocol, addrlen, readlen);
 210        msg[1] = SLIMPRO_IIC_ENCODE_FLAG_BUFADDR |
 211                 SLIMPRO_IIC_ENCODE_FLAG_WITH_DATA_LEN(with_data_len) |
 212                 SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(paddr) |
 213                 SLIMPRO_IIC_ENCODE_ADDR(addr);
 214        msg[2] = (u32)paddr;
 215        ctx->resp_msg = msg;
 216
 217        rc = mbox_send_message(ctx->mbox_chan, &msg);
 218        if (rc < 0)
 219                goto err_unmap;
 220
 221        rc = start_i2c_msg_xfer(ctx);
 222
 223        /* Copy to destination */
 224        memcpy(data, ctx->dma_buffer, readlen);
 225
 226err_unmap:
 227        dma_unmap_single(ctx->dev, paddr, readlen, DMA_FROM_DEVICE);
 228err:
 229        ctx->resp_msg = NULL;
 230        return rc;
 231}
 232
 233static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip,
 234                             u32 addr, u32 addrlen, u32 protocol, u32 writelen,
 235                             void *data)
 236{
 237        dma_addr_t paddr;
 238        u32 msg[3];
 239        int rc;
 240
 241        memcpy(ctx->dma_buffer, data, writelen);
 242        paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
 243                               DMA_TO_DEVICE);
 244        if (dma_mapping_error(ctx->dev, paddr)) {
 245                dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n",
 246                        ctx->dma_buffer);
 247                rc = -ENOMEM;
 248                goto err;
 249        }
 250
 251        msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, SLIMPRO_IIC_WRITE,
 252                                        protocol, addrlen, writelen);
 253        msg[1] = SLIMPRO_IIC_ENCODE_FLAG_BUFADDR |
 254                 SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(paddr) |
 255                 SLIMPRO_IIC_ENCODE_ADDR(addr);
 256        msg[2] = (u32)paddr;
 257        ctx->resp_msg = msg;
 258
 259        if (ctx->mbox_client.tx_block)
 260                reinit_completion(&ctx->rd_complete);
 261
 262        rc = mbox_send_message(ctx->mbox_chan, &msg);
 263        if (rc < 0)
 264                goto err_unmap;
 265
 266        rc = start_i2c_msg_xfer(ctx);
 267
 268err_unmap:
 269        dma_unmap_single(ctx->dev, paddr, writelen, DMA_TO_DEVICE);
 270err:
 271        ctx->resp_msg = NULL;
 272        return rc;
 273}
 274
 275static int xgene_slimpro_i2c_xfer(struct i2c_adapter *adap, u16 addr,
 276                                  unsigned short flags, char read_write,
 277                                  u8 command, int size,
 278                                  union i2c_smbus_data *data)
 279{
 280        struct slimpro_i2c_dev *ctx = i2c_get_adapdata(adap);
 281        int ret = -EOPNOTSUPP;
 282        u32 val;
 283
 284        switch (size) {
 285        case I2C_SMBUS_BYTE:
 286                if (read_write == I2C_SMBUS_READ) {
 287                        ret = slimpro_i2c_rd(ctx, addr, 0, 0,
 288                                             SLIMPRO_IIC_SMB_PROTOCOL,
 289                                             BYTE_DATA, &val);
 290                        data->byte = val;
 291                } else {
 292                        ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN,
 293                                             SLIMPRO_IIC_SMB_PROTOCOL,
 294                                             0, 0);
 295                }
 296                break;
 297        case I2C_SMBUS_BYTE_DATA:
 298                if (read_write == I2C_SMBUS_READ) {
 299                        ret = slimpro_i2c_rd(ctx, addr, command, SMBUS_CMD_LEN,
 300                                             SLIMPRO_IIC_SMB_PROTOCOL,
 301                                             BYTE_DATA, &val);
 302                        data->byte = val;
 303                } else {
 304                        val = data->byte;
 305                        ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN,
 306                                             SLIMPRO_IIC_SMB_PROTOCOL,
 307                                             BYTE_DATA, val);
 308                }
 309                break;
 310        case I2C_SMBUS_WORD_DATA:
 311                if (read_write == I2C_SMBUS_READ) {
 312                        ret = slimpro_i2c_rd(ctx, addr, command, SMBUS_CMD_LEN,
 313                                             SLIMPRO_IIC_SMB_PROTOCOL,
 314                                             WORD_DATA, &val);
 315                        data->word = val;
 316                } else {
 317                        val = data->word;
 318                        ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN,
 319                                             SLIMPRO_IIC_SMB_PROTOCOL,
 320                                             WORD_DATA, val);
 321                }
 322                break;
 323        case I2C_SMBUS_BLOCK_DATA:
 324                if (read_write == I2C_SMBUS_READ) {
 325                        ret = slimpro_i2c_blkrd(ctx, addr, command,
 326                                                SMBUS_CMD_LEN,
 327                                                SLIMPRO_IIC_SMB_PROTOCOL,
 328                                                I2C_SMBUS_BLOCK_MAX + 1,
 329                                                IIC_SMB_WITH_DATA_LEN,
 330                                                &data->block[0]);
 331
 332                } else {
 333                        ret = slimpro_i2c_blkwr(ctx, addr, command,
 334                                                SMBUS_CMD_LEN,
 335                                                SLIMPRO_IIC_SMB_PROTOCOL,
 336                                                data->block[0] + 1,
 337                                                &data->block[0]);
 338                }
 339                break;
 340        case I2C_SMBUS_I2C_BLOCK_DATA:
 341                if (read_write == I2C_SMBUS_READ) {
 342                        ret = slimpro_i2c_blkrd(ctx, addr,
 343                                                command,
 344                                                SMBUS_CMD_LEN,
 345                                                SLIMPRO_IIC_I2C_PROTOCOL,
 346                                                I2C_SMBUS_BLOCK_MAX,
 347                                                IIC_SMB_WITHOUT_DATA_LEN,
 348                                                &data->block[1]);
 349                } else {
 350                        ret = slimpro_i2c_blkwr(ctx, addr, command,
 351                                                SMBUS_CMD_LEN,
 352                                                SLIMPRO_IIC_I2C_PROTOCOL,
 353                                                data->block[0],
 354                                                &data->block[1]);
 355                }
 356                break;
 357        default:
 358                break;
 359        }
 360        return ret;
 361}
 362
 363/*
 364* Return list of supported functionality.
 365*/
 366static u32 xgene_slimpro_i2c_func(struct i2c_adapter *adapter)
 367{
 368        return I2C_FUNC_SMBUS_BYTE |
 369                I2C_FUNC_SMBUS_BYTE_DATA |
 370                I2C_FUNC_SMBUS_WORD_DATA |
 371                I2C_FUNC_SMBUS_BLOCK_DATA |
 372                I2C_FUNC_SMBUS_I2C_BLOCK;
 373}
 374
 375static const struct i2c_algorithm xgene_slimpro_i2c_algorithm = {
 376        .smbus_xfer = xgene_slimpro_i2c_xfer,
 377        .functionality = xgene_slimpro_i2c_func,
 378};
 379
 380static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
 381{
 382        struct slimpro_i2c_dev *ctx;
 383        struct i2c_adapter *adapter;
 384        struct mbox_client *cl;
 385        int rc;
 386
 387        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 388        if (!ctx)
 389                return -ENOMEM;
 390
 391        ctx->dev = &pdev->dev;
 392        platform_set_drvdata(pdev, ctx);
 393        cl = &ctx->mbox_client;
 394
 395        /* Request mailbox channel */
 396        cl->dev = &pdev->dev;
 397        cl->rx_callback = slimpro_i2c_rx_cb;
 398        cl->tx_block = true;
 399        init_completion(&ctx->rd_complete);
 400        cl->tx_tout = MAILBOX_OP_TIMEOUT;
 401        cl->knows_txdone = false;
 402        ctx->mbox_chan = mbox_request_channel(cl, MAILBOX_I2C_INDEX);
 403        if (IS_ERR(ctx->mbox_chan)) {
 404                dev_err(&pdev->dev, "i2c mailbox channel request failed\n");
 405                return PTR_ERR(ctx->mbox_chan);
 406        }
 407
 408        rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 409        if (rc)
 410                dev_warn(&pdev->dev, "Unable to set dma mask\n");
 411
 412        /* Setup I2C adapter */
 413        adapter = &ctx->adapter;
 414        snprintf(adapter->name, sizeof(adapter->name), "MAILBOX I2C");
 415        adapter->algo = &xgene_slimpro_i2c_algorithm;
 416        adapter->class = I2C_CLASS_HWMON;
 417        adapter->dev.parent = &pdev->dev;
 418        adapter->dev.of_node = pdev->dev.of_node;
 419        ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev));
 420        i2c_set_adapdata(adapter, ctx);
 421        rc = i2c_add_adapter(adapter);
 422        if (rc) {
 423                mbox_free_channel(ctx->mbox_chan);
 424                return rc;
 425        }
 426
 427        dev_info(&pdev->dev, "Mailbox I2C Adapter registered\n");
 428        return 0;
 429}
 430
 431static int xgene_slimpro_i2c_remove(struct platform_device *pdev)
 432{
 433        struct slimpro_i2c_dev *ctx = platform_get_drvdata(pdev);
 434
 435        i2c_del_adapter(&ctx->adapter);
 436
 437        mbox_free_channel(ctx->mbox_chan);
 438
 439        return 0;
 440}
 441
 442static const struct of_device_id xgene_slimpro_i2c_dt_ids[] = {
 443        {.compatible = "apm,xgene-slimpro-i2c" },
 444        {},
 445};
 446MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids);
 447
 448#ifdef CONFIG_ACPI
 449static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = {
 450        {"APMC0D40", 0},
 451        {}
 452};
 453MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids);
 454#endif
 455
 456static struct platform_driver xgene_slimpro_i2c_driver = {
 457        .probe  = xgene_slimpro_i2c_probe,
 458        .remove = xgene_slimpro_i2c_remove,
 459        .driver = {
 460                .name   = "xgene-slimpro-i2c",
 461                .of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids),
 462                .acpi_match_table = ACPI_PTR(xgene_slimpro_i2c_acpi_ids)
 463        },
 464};
 465
 466module_platform_driver(xgene_slimpro_i2c_driver);
 467
 468MODULE_DESCRIPTION("APM X-Gene SLIMpro I2C driver");
 469MODULE_AUTHOR("Feng Kan <fkan@apm.com>");
 470MODULE_AUTHOR("Hieu Le <hnle@apm.com>");
 471MODULE_LICENSE("GPL");
 472