root/drivers/i2c/busses/i2c-tegra-bpmp.c

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

DEFINITIONS

This source file includes following definitions.
  1. tegra_bpmp_xlate_flags
  2. tegra_bpmp_serialize_i2c_msg
  3. tegra_bpmp_i2c_deserialize
  4. tegra_bpmp_i2c_msg_len_check
  5. tegra_bpmp_i2c_msg_xfer
  6. tegra_bpmp_i2c_xfer_common
  7. tegra_bpmp_i2c_xfer
  8. tegra_bpmp_i2c_xfer_atomic
  9. tegra_bpmp_i2c_func
  10. tegra_bpmp_i2c_probe
  11. tegra_bpmp_i2c_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * drivers/i2c/busses/i2c-tegra-bpmp.c
   4  *
   5  * Copyright (c) 2016 NVIDIA Corporation.  All rights reserved.
   6  *
   7  * Author: Shardar Shariff Md <smohammed@nvidia.com>
   8  */
   9 
  10 #include <linux/err.h>
  11 #include <linux/i2c.h>
  12 #include <linux/init.h>
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 #include <linux/of_device.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/pm_runtime.h>
  18 
  19 #include <soc/tegra/bpmp-abi.h>
  20 #include <soc/tegra/bpmp.h>
  21 
  22 /*
  23  * Serialized I2C message header size is 6 bytes and includes address, flags
  24  * and length
  25  */
  26 #define SERIALI2C_HDR_SIZE 6
  27 
  28 struct tegra_bpmp_i2c {
  29         struct i2c_adapter adapter;
  30         struct device *dev;
  31 
  32         struct tegra_bpmp *bpmp;
  33         unsigned int bus;
  34 };
  35 
  36 /*
  37  * Linux flags are translated to BPMP defined I2C flags that are used in BPMP
  38  * firmware I2C driver to avoid any issues in future if Linux I2C flags are
  39  * changed.
  40  */
  41 static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
  42 {
  43         if (flags & I2C_M_TEN) {
  44                 *out |= SERIALI2C_TEN;
  45                 flags &= ~I2C_M_TEN;
  46         }
  47 
  48         if (flags & I2C_M_RD) {
  49                 *out |= SERIALI2C_RD;
  50                 flags &= ~I2C_M_RD;
  51         }
  52 
  53         if (flags & I2C_M_STOP) {
  54                 *out |= SERIALI2C_STOP;
  55                 flags &= ~I2C_M_STOP;
  56         }
  57 
  58         if (flags & I2C_M_NOSTART) {
  59                 *out |= SERIALI2C_NOSTART;
  60                 flags &= ~I2C_M_NOSTART;
  61         }
  62 
  63         if (flags & I2C_M_REV_DIR_ADDR) {
  64                 *out |= SERIALI2C_REV_DIR_ADDR;
  65                 flags &= ~I2C_M_REV_DIR_ADDR;
  66         }
  67 
  68         if (flags & I2C_M_IGNORE_NAK) {
  69                 *out |= SERIALI2C_IGNORE_NAK;
  70                 flags &= ~I2C_M_IGNORE_NAK;
  71         }
  72 
  73         if (flags & I2C_M_NO_RD_ACK) {
  74                 *out |= SERIALI2C_NO_RD_ACK;
  75                 flags &= ~I2C_M_NO_RD_ACK;
  76         }
  77 
  78         if (flags & I2C_M_RECV_LEN) {
  79                 *out |= SERIALI2C_RECV_LEN;
  80                 flags &= ~I2C_M_RECV_LEN;
  81         }
  82 
  83         return (flags != 0) ? -EINVAL : 0;
  84 }
  85 
  86 /**
  87  * The serialized I2C format is simply the following:
  88  * [addr little-endian][flags little-endian][len little-endian][data if write]
  89  * [addr little-endian][flags little-endian][len little-endian][data if write]
  90  *  ...
  91  *
  92  * The flags are translated from Linux kernel representation to seriali2c
  93  * representation. Any undefined flag being set causes an error.
  94  *
  95  * The data is there only for writes. Reads have the data transferred in the
  96  * other direction, and thus data is not present.
  97  *
  98  * See deserialize_i2c documentation for the data format in the other direction.
  99  */
 100 static int tegra_bpmp_serialize_i2c_msg(struct tegra_bpmp_i2c *i2c,
 101                                         struct mrq_i2c_request *request,
 102                                         struct i2c_msg *msgs,
 103                                         unsigned int num)
 104 {
 105         char *buf = request->xfer.data_buf;
 106         unsigned int i, j, pos = 0;
 107         int err;
 108 
 109         for (i = 0; i < num; i++) {
 110                 struct i2c_msg *msg = &msgs[i];
 111                 u16 flags = 0;
 112 
 113                 err = tegra_bpmp_xlate_flags(msg->flags, &flags);
 114                 if (err < 0)
 115                         return err;
 116 
 117                 buf[pos++] = msg->addr & 0xff;
 118                 buf[pos++] = (msg->addr & 0xff00) >> 8;
 119                 buf[pos++] = flags & 0xff;
 120                 buf[pos++] = (flags & 0xff00) >> 8;
 121                 buf[pos++] = msg->len & 0xff;
 122                 buf[pos++] = (msg->len & 0xff00) >> 8;
 123 
 124                 if ((flags & SERIALI2C_RD) == 0) {
 125                         for (j = 0; j < msg->len; j++)
 126                                 buf[pos++] = msg->buf[j];
 127                 }
 128         }
 129 
 130         request->xfer.data_size = pos;
 131 
 132         return 0;
 133 }
 134 
 135 /**
 136  * The data in the BPMP -> CPU direction is composed of sequential blocks for
 137  * those messages that have I2C_M_RD. So, for example, if you have:
 138  *
 139  * - !I2C_M_RD, len == 5, data == a0 01 02 03 04
 140  * - !I2C_M_RD, len == 1, data == a0
 141  * - I2C_M_RD, len == 2, data == [uninitialized buffer 1]
 142  * - !I2C_M_RD, len == 1, data == a2
 143  * - I2C_M_RD, len == 2, data == [uninitialized buffer 2]
 144  *
 145  * ...then the data in the BPMP -> CPU direction would be 4 bytes total, and
 146  * would contain 2 bytes that will go to uninitialized buffer 1, and 2 bytes
 147  * that will go to uninitialized buffer 2.
 148  */
 149 static int tegra_bpmp_i2c_deserialize(struct tegra_bpmp_i2c *i2c,
 150                                       struct mrq_i2c_response *response,
 151                                       struct i2c_msg *msgs,
 152                                       unsigned int num)
 153 {
 154         size_t size = response->xfer.data_size, len = 0, pos = 0;
 155         char *buf = response->xfer.data_buf;
 156         unsigned int i;
 157 
 158         for (i = 0; i < num; i++)
 159                 if (msgs[i].flags & I2C_M_RD)
 160                         len += msgs[i].len;
 161 
 162         if (len != size)
 163                 return -EINVAL;
 164 
 165         for (i = 0; i < num; i++) {
 166                 if (msgs[i].flags & I2C_M_RD) {
 167                         memcpy(msgs[i].buf, buf + pos, msgs[i].len);
 168                         pos += msgs[i].len;
 169                 }
 170         }
 171 
 172         return 0;
 173 }
 174 
 175 static int tegra_bpmp_i2c_msg_len_check(struct i2c_msg *msgs, unsigned int num)
 176 {
 177         size_t tx_len = 0, rx_len = 0;
 178         unsigned int i;
 179 
 180         for (i = 0; i < num; i++)
 181                 if (!(msgs[i].flags & I2C_M_RD))
 182                         tx_len += SERIALI2C_HDR_SIZE + msgs[i].len;
 183 
 184         if (tx_len > TEGRA_I2C_IPC_MAX_IN_BUF_SIZE)
 185                 return -EINVAL;
 186 
 187         for (i = 0; i < num; i++)
 188                 if ((msgs[i].flags & I2C_M_RD))
 189                         rx_len += msgs[i].len;
 190 
 191         if (rx_len > TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE)
 192                 return -EINVAL;
 193 
 194         return 0;
 195 }
 196 
 197 static int tegra_bpmp_i2c_msg_xfer(struct tegra_bpmp_i2c *i2c,
 198                                    struct mrq_i2c_request *request,
 199                                    struct mrq_i2c_response *response,
 200                                    bool atomic)
 201 {
 202         struct tegra_bpmp_message msg;
 203         int err;
 204 
 205         request->cmd = CMD_I2C_XFER;
 206         request->xfer.bus_id = i2c->bus;
 207 
 208         memset(&msg, 0, sizeof(msg));
 209         msg.mrq = MRQ_I2C;
 210         msg.tx.data = request;
 211         msg.tx.size = sizeof(*request);
 212         msg.rx.data = response;
 213         msg.rx.size = sizeof(*response);
 214 
 215         if (atomic)
 216                 err = tegra_bpmp_transfer_atomic(i2c->bpmp, &msg);
 217         else
 218                 err = tegra_bpmp_transfer(i2c->bpmp, &msg);
 219 
 220         return err;
 221 }
 222 
 223 static int tegra_bpmp_i2c_xfer_common(struct i2c_adapter *adapter,
 224                                       struct i2c_msg *msgs, int num,
 225                                       bool atomic)
 226 {
 227         struct tegra_bpmp_i2c *i2c = i2c_get_adapdata(adapter);
 228         struct mrq_i2c_response response;
 229         struct mrq_i2c_request request;
 230         int err;
 231 
 232         err = tegra_bpmp_i2c_msg_len_check(msgs, num);
 233         if (err < 0) {
 234                 dev_err(i2c->dev, "unsupported message length\n");
 235                 return err;
 236         }
 237 
 238         memset(&request, 0, sizeof(request));
 239         memset(&response, 0, sizeof(response));
 240 
 241         err = tegra_bpmp_serialize_i2c_msg(i2c, &request, msgs, num);
 242         if (err < 0) {
 243                 dev_err(i2c->dev, "failed to serialize message: %d\n", err);
 244                 return err;
 245         }
 246 
 247         err = tegra_bpmp_i2c_msg_xfer(i2c, &request, &response, atomic);
 248         if (err < 0) {
 249                 dev_err(i2c->dev, "failed to transfer message: %d\n", err);
 250                 return err;
 251         }
 252 
 253         err = tegra_bpmp_i2c_deserialize(i2c, &response, msgs, num);
 254         if (err < 0) {
 255                 dev_err(i2c->dev, "failed to deserialize message: %d\n", err);
 256                 return err;
 257         }
 258 
 259         return num;
 260 }
 261 
 262 static int tegra_bpmp_i2c_xfer(struct i2c_adapter *adapter,
 263                                struct i2c_msg *msgs, int num)
 264 {
 265         return tegra_bpmp_i2c_xfer_common(adapter, msgs, num, false);
 266 }
 267 
 268 static int tegra_bpmp_i2c_xfer_atomic(struct i2c_adapter *adapter,
 269                                       struct i2c_msg *msgs, int num)
 270 {
 271         return tegra_bpmp_i2c_xfer_common(adapter, msgs, num, true);
 272 }
 273 
 274 static u32 tegra_bpmp_i2c_func(struct i2c_adapter *adapter)
 275 {
 276         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
 277                I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART;
 278 }
 279 
 280 static const struct i2c_algorithm tegra_bpmp_i2c_algo = {
 281         .master_xfer = tegra_bpmp_i2c_xfer,
 282         .master_xfer_atomic = tegra_bpmp_i2c_xfer_atomic,
 283         .functionality = tegra_bpmp_i2c_func,
 284 };
 285 
 286 static int tegra_bpmp_i2c_probe(struct platform_device *pdev)
 287 {
 288         struct tegra_bpmp_i2c *i2c;
 289         u32 value;
 290         int err;
 291 
 292         i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 293         if (!i2c)
 294                 return -ENOMEM;
 295 
 296         i2c->dev = &pdev->dev;
 297 
 298         i2c->bpmp = dev_get_drvdata(pdev->dev.parent);
 299         if (!i2c->bpmp)
 300                 return -ENODEV;
 301 
 302         err = of_property_read_u32(pdev->dev.of_node, "nvidia,bpmp-bus-id",
 303                                    &value);
 304         if (err < 0)
 305                 return err;
 306 
 307         i2c->bus = value;
 308 
 309         i2c_set_adapdata(&i2c->adapter, i2c);
 310         i2c->adapter.owner = THIS_MODULE;
 311         strlcpy(i2c->adapter.name, "Tegra BPMP I2C adapter",
 312                 sizeof(i2c->adapter.name));
 313         i2c->adapter.algo = &tegra_bpmp_i2c_algo;
 314         i2c->adapter.dev.parent = &pdev->dev;
 315         i2c->adapter.dev.of_node = pdev->dev.of_node;
 316 
 317         platform_set_drvdata(pdev, i2c);
 318 
 319         return i2c_add_adapter(&i2c->adapter);
 320 }
 321 
 322 static int tegra_bpmp_i2c_remove(struct platform_device *pdev)
 323 {
 324         struct tegra_bpmp_i2c *i2c = platform_get_drvdata(pdev);
 325 
 326         i2c_del_adapter(&i2c->adapter);
 327 
 328         return 0;
 329 }
 330 
 331 static const struct of_device_id tegra_bpmp_i2c_of_match[] = {
 332         { .compatible = "nvidia,tegra186-bpmp-i2c", },
 333         { }
 334 };
 335 MODULE_DEVICE_TABLE(of, tegra_bpmp_i2c_of_match);
 336 
 337 static struct platform_driver tegra_bpmp_i2c_driver = {
 338         .driver = {
 339                 .name = "tegra-bpmp-i2c",
 340                 .of_match_table = tegra_bpmp_i2c_of_match,
 341         },
 342         .probe = tegra_bpmp_i2c_probe,
 343         .remove = tegra_bpmp_i2c_remove,
 344 };
 345 module_platform_driver(tegra_bpmp_i2c_driver);
 346 
 347 MODULE_DESCRIPTION("NVIDIA Tegra BPMP I2C bus controller driver");
 348 MODULE_AUTHOR("Shardar Shariff Md <smohammed@nvidia.com>");
 349 MODULE_AUTHOR("Juha-Matti Tilli");
 350 MODULE_LICENSE("GPL v2");

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