root/drivers/i2c/busses/i2c-kempld.c

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

DEFINITIONS

This source file includes following definitions.
  1. kempld_i2c_process
  2. kempld_i2c_xfer
  3. kempld_i2c_device_init
  4. kempld_i2c_func
  5. kempld_i2c_probe
  6. kempld_i2c_remove
  7. kempld_i2c_suspend
  8. kempld_i2c_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * I2C bus driver for Kontron COM modules
   4  *
   5  * Copyright (c) 2010-2013 Kontron Europe GmbH
   6  * Author: Michael Brunner <michael.brunner@kontron.com>
   7  *
   8  * The driver is based on the i2c-ocores driver by Peter Korsgaard.
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/i2c.h>
  14 #include <linux/delay.h>
  15 #include <linux/mfd/kempld.h>
  16 
  17 #define KEMPLD_I2C_PRELOW       0x0b
  18 #define KEMPLD_I2C_PREHIGH      0x0c
  19 #define KEMPLD_I2C_DATA         0x0e
  20 
  21 #define KEMPLD_I2C_CTRL         0x0d
  22 #define I2C_CTRL_IEN            0x40
  23 #define I2C_CTRL_EN             0x80
  24 
  25 #define KEMPLD_I2C_STAT         0x0f
  26 #define I2C_STAT_IF             0x01
  27 #define I2C_STAT_TIP            0x02
  28 #define I2C_STAT_ARBLOST        0x20
  29 #define I2C_STAT_BUSY           0x40
  30 #define I2C_STAT_NACK           0x80
  31 
  32 #define KEMPLD_I2C_CMD          0x0f
  33 #define I2C_CMD_START           0x91
  34 #define I2C_CMD_STOP            0x41
  35 #define I2C_CMD_READ            0x21
  36 #define I2C_CMD_WRITE           0x11
  37 #define I2C_CMD_READ_ACK        0x21
  38 #define I2C_CMD_READ_NACK       0x29
  39 #define I2C_CMD_IACK            0x01
  40 
  41 #define KEMPLD_I2C_FREQ_MAX     2700    /* 2.7 mHz */
  42 #define KEMPLD_I2C_FREQ_STD     100     /* 100 kHz */
  43 
  44 enum {
  45         STATE_DONE = 0,
  46         STATE_INIT,
  47         STATE_ADDR,
  48         STATE_ADDR10,
  49         STATE_START,
  50         STATE_WRITE,
  51         STATE_READ,
  52         STATE_ERROR,
  53 };
  54 
  55 struct kempld_i2c_data {
  56         struct device                   *dev;
  57         struct kempld_device_data       *pld;
  58         struct i2c_adapter              adap;
  59         struct i2c_msg                  *msg;
  60         int                             pos;
  61         int                             nmsgs;
  62         int                             state;
  63         bool                            was_active;
  64 };
  65 
  66 static unsigned int bus_frequency = KEMPLD_I2C_FREQ_STD;
  67 module_param(bus_frequency, uint, 0);
  68 MODULE_PARM_DESC(bus_frequency, "Set I2C bus frequency in kHz (default="
  69                                 __MODULE_STRING(KEMPLD_I2C_FREQ_STD)")");
  70 
  71 static int i2c_bus = -1;
  72 module_param(i2c_bus, int, 0);
  73 MODULE_PARM_DESC(i2c_bus, "Set I2C bus number (default=-1 for dynamic assignment)");
  74 
  75 static bool i2c_gpio_mux;
  76 module_param(i2c_gpio_mux, bool, 0);
  77 MODULE_PARM_DESC(i2c_gpio_mux, "Enable I2C port on GPIO out (default=false)");
  78 
  79 /*
  80  * kempld_get_mutex must be called prior to calling this function.
  81  */
  82 static int kempld_i2c_process(struct kempld_i2c_data *i2c)
  83 {
  84         struct kempld_device_data *pld = i2c->pld;
  85         u8 stat = kempld_read8(pld, KEMPLD_I2C_STAT);
  86         struct i2c_msg *msg = i2c->msg;
  87         u8 addr;
  88 
  89         /* Ready? */
  90         if (stat & I2C_STAT_TIP)
  91                 return -EBUSY;
  92 
  93         if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) {
  94                 /* Stop has been sent */
  95                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_IACK);
  96                 if (i2c->state == STATE_ERROR)
  97                         return -EIO;
  98                 return 0;
  99         }
 100 
 101         /* Error? */
 102         if (stat & I2C_STAT_ARBLOST) {
 103                 i2c->state = STATE_ERROR;
 104                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_STOP);
 105                 return -EAGAIN;
 106         }
 107 
 108         if (i2c->state == STATE_INIT) {
 109                 if (stat & I2C_STAT_BUSY)
 110                         return -EBUSY;
 111 
 112                 i2c->state = STATE_ADDR;
 113         }
 114 
 115         if (i2c->state == STATE_ADDR) {
 116                 /* 10 bit address? */
 117                 if (i2c->msg->flags & I2C_M_TEN) {
 118                         addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
 119                         /* Set read bit if necessary */
 120                         addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
 121                         i2c->state = STATE_ADDR10;
 122                 } else {
 123                         addr = i2c_8bit_addr_from_msg(i2c->msg);
 124                         i2c->state = STATE_START;
 125                 }
 126 
 127                 kempld_write8(pld, KEMPLD_I2C_DATA, addr);
 128                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_START);
 129 
 130                 return 0;
 131         }
 132 
 133         /* Second part of 10 bit addressing */
 134         if (i2c->state == STATE_ADDR10) {
 135                 kempld_write8(pld, KEMPLD_I2C_DATA, i2c->msg->addr & 0xff);
 136                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_WRITE);
 137 
 138                 i2c->state = STATE_START;
 139                 return 0;
 140         }
 141 
 142         if (i2c->state == STATE_START || i2c->state == STATE_WRITE) {
 143                 i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
 144 
 145                 if (stat & I2C_STAT_NACK) {
 146                         i2c->state = STATE_ERROR;
 147                         kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_STOP);
 148                         return -ENXIO;
 149                 }
 150         } else {
 151                 msg->buf[i2c->pos++] = kempld_read8(pld, KEMPLD_I2C_DATA);
 152         }
 153 
 154         if (i2c->pos >= msg->len) {
 155                 i2c->nmsgs--;
 156                 i2c->msg++;
 157                 i2c->pos = 0;
 158                 msg = i2c->msg;
 159 
 160                 if (i2c->nmsgs) {
 161                         if (!(msg->flags & I2C_M_NOSTART)) {
 162                                 i2c->state = STATE_ADDR;
 163                                 return 0;
 164                         } else {
 165                                 i2c->state = (msg->flags & I2C_M_RD)
 166                                         ? STATE_READ : STATE_WRITE;
 167                         }
 168                 } else {
 169                         i2c->state = STATE_DONE;
 170                         kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_STOP);
 171                         return 0;
 172                 }
 173         }
 174 
 175         if (i2c->state == STATE_READ) {
 176                 kempld_write8(pld, KEMPLD_I2C_CMD, i2c->pos == (msg->len - 1) ?
 177                               I2C_CMD_READ_NACK : I2C_CMD_READ_ACK);
 178         } else {
 179                 kempld_write8(pld, KEMPLD_I2C_DATA, msg->buf[i2c->pos++]);
 180                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_WRITE);
 181         }
 182 
 183         return 0;
 184 }
 185 
 186 static int kempld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 187                                 int num)
 188 {
 189         struct kempld_i2c_data *i2c = i2c_get_adapdata(adap);
 190         struct kempld_device_data *pld = i2c->pld;
 191         unsigned long timeout = jiffies + HZ;
 192         int ret;
 193 
 194         i2c->msg = msgs;
 195         i2c->pos = 0;
 196         i2c->nmsgs = num;
 197         i2c->state = STATE_INIT;
 198 
 199         /* Handle the transfer */
 200         while (time_before(jiffies, timeout)) {
 201                 kempld_get_mutex(pld);
 202                 ret = kempld_i2c_process(i2c);
 203                 kempld_release_mutex(pld);
 204 
 205                 if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR)
 206                         return (i2c->state == STATE_DONE) ? num : ret;
 207 
 208                 if (ret == 0)
 209                         timeout = jiffies + HZ;
 210 
 211                 usleep_range(5, 15);
 212         }
 213 
 214         i2c->state = STATE_ERROR;
 215 
 216         return -ETIMEDOUT;
 217 }
 218 
 219 /*
 220  * kempld_get_mutex must be called prior to calling this function.
 221  */
 222 static void kempld_i2c_device_init(struct kempld_i2c_data *i2c)
 223 {
 224         struct kempld_device_data *pld = i2c->pld;
 225         u16 prescale_corr;
 226         long prescale;
 227         u8 ctrl;
 228         u8 stat;
 229         u8 cfg;
 230 
 231         /* Make sure the device is disabled */
 232         ctrl = kempld_read8(pld, KEMPLD_I2C_CTRL);
 233         ctrl &= ~(I2C_CTRL_EN | I2C_CTRL_IEN);
 234         kempld_write8(pld, KEMPLD_I2C_CTRL, ctrl);
 235 
 236         if (bus_frequency > KEMPLD_I2C_FREQ_MAX)
 237                 bus_frequency = KEMPLD_I2C_FREQ_MAX;
 238 
 239         if (pld->info.spec_major == 1)
 240                 prescale = pld->pld_clock / (bus_frequency * 5) - 1000;
 241         else
 242                 prescale = pld->pld_clock / (bus_frequency * 4) - 3000;
 243 
 244         if (prescale < 0)
 245                 prescale = 0;
 246 
 247         /* Round to the best matching value */
 248         prescale_corr = prescale / 1000;
 249         if (prescale % 1000 >= 500)
 250                 prescale_corr++;
 251 
 252         kempld_write8(pld, KEMPLD_I2C_PRELOW, prescale_corr & 0xff);
 253         kempld_write8(pld, KEMPLD_I2C_PREHIGH, prescale_corr >> 8);
 254 
 255         /* Activate I2C bus output on GPIO pins */
 256         cfg = kempld_read8(pld, KEMPLD_CFG);
 257         if (i2c_gpio_mux)
 258                 cfg |= KEMPLD_CFG_GPIO_I2C_MUX;
 259         else
 260                 cfg &= ~KEMPLD_CFG_GPIO_I2C_MUX;
 261         kempld_write8(pld, KEMPLD_CFG, cfg);
 262 
 263         /* Enable the device */
 264         kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_IACK);
 265         ctrl |= I2C_CTRL_EN;
 266         kempld_write8(pld, KEMPLD_I2C_CTRL, ctrl);
 267 
 268         stat = kempld_read8(pld, KEMPLD_I2C_STAT);
 269         if (stat & I2C_STAT_BUSY)
 270                 kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_STOP);
 271 }
 272 
 273 static u32 kempld_i2c_func(struct i2c_adapter *adap)
 274 {
 275         return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
 276 }
 277 
 278 static const struct i2c_algorithm kempld_i2c_algorithm = {
 279         .master_xfer    = kempld_i2c_xfer,
 280         .functionality  = kempld_i2c_func,
 281 };
 282 
 283 static const struct i2c_adapter kempld_i2c_adapter = {
 284         .owner          = THIS_MODULE,
 285         .name           = "i2c-kempld",
 286         .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 287         .algo           = &kempld_i2c_algorithm,
 288 };
 289 
 290 static int kempld_i2c_probe(struct platform_device *pdev)
 291 {
 292         struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent);
 293         struct kempld_i2c_data *i2c;
 294         int ret;
 295         u8 ctrl;
 296 
 297         i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 298         if (!i2c)
 299                 return -ENOMEM;
 300 
 301         i2c->pld = pld;
 302         i2c->dev = &pdev->dev;
 303         i2c->adap = kempld_i2c_adapter;
 304         i2c->adap.dev.parent = i2c->dev;
 305         i2c_set_adapdata(&i2c->adap, i2c);
 306         platform_set_drvdata(pdev, i2c);
 307 
 308         kempld_get_mutex(pld);
 309         ctrl = kempld_read8(pld, KEMPLD_I2C_CTRL);
 310 
 311         if (ctrl & I2C_CTRL_EN)
 312                 i2c->was_active = true;
 313 
 314         kempld_i2c_device_init(i2c);
 315         kempld_release_mutex(pld);
 316 
 317         /* Add I2C adapter to I2C tree */
 318         if (i2c_bus >= -1)
 319                 i2c->adap.nr = i2c_bus;
 320         ret = i2c_add_numbered_adapter(&i2c->adap);
 321         if (ret)
 322                 return ret;
 323 
 324         dev_info(i2c->dev, "I2C bus initialized at %dkHz\n",
 325                  bus_frequency);
 326 
 327         return 0;
 328 }
 329 
 330 static int kempld_i2c_remove(struct platform_device *pdev)
 331 {
 332         struct kempld_i2c_data *i2c = platform_get_drvdata(pdev);
 333         struct kempld_device_data *pld = i2c->pld;
 334         u8 ctrl;
 335 
 336         kempld_get_mutex(pld);
 337         /*
 338          * Disable I2C logic if it was not activated before the
 339          * driver loaded
 340          */
 341         if (!i2c->was_active) {
 342                 ctrl = kempld_read8(pld, KEMPLD_I2C_CTRL);
 343                 ctrl &= ~I2C_CTRL_EN;
 344                 kempld_write8(pld, KEMPLD_I2C_CTRL, ctrl);
 345         }
 346         kempld_release_mutex(pld);
 347 
 348         i2c_del_adapter(&i2c->adap);
 349 
 350         return 0;
 351 }
 352 
 353 #ifdef CONFIG_PM
 354 static int kempld_i2c_suspend(struct platform_device *pdev, pm_message_t state)
 355 {
 356         struct kempld_i2c_data *i2c = platform_get_drvdata(pdev);
 357         struct kempld_device_data *pld = i2c->pld;
 358         u8 ctrl;
 359 
 360         kempld_get_mutex(pld);
 361         ctrl = kempld_read8(pld, KEMPLD_I2C_CTRL);
 362         ctrl &= ~I2C_CTRL_EN;
 363         kempld_write8(pld, KEMPLD_I2C_CTRL, ctrl);
 364         kempld_release_mutex(pld);
 365 
 366         return 0;
 367 }
 368 
 369 static int kempld_i2c_resume(struct platform_device *pdev)
 370 {
 371         struct kempld_i2c_data *i2c = platform_get_drvdata(pdev);
 372         struct kempld_device_data *pld = i2c->pld;
 373 
 374         kempld_get_mutex(pld);
 375         kempld_i2c_device_init(i2c);
 376         kempld_release_mutex(pld);
 377 
 378         return 0;
 379 }
 380 #else
 381 #define kempld_i2c_suspend      NULL
 382 #define kempld_i2c_resume       NULL
 383 #endif
 384 
 385 static struct platform_driver kempld_i2c_driver = {
 386         .driver = {
 387                 .name = "kempld-i2c",
 388         },
 389         .probe          = kempld_i2c_probe,
 390         .remove         = kempld_i2c_remove,
 391         .suspend        = kempld_i2c_suspend,
 392         .resume         = kempld_i2c_resume,
 393 };
 394 
 395 module_platform_driver(kempld_i2c_driver);
 396 
 397 MODULE_DESCRIPTION("KEM PLD I2C Driver");
 398 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
 399 MODULE_LICENSE("GPL");
 400 MODULE_ALIAS("platform:kempld_i2c");

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