linux/drivers/mfd/88pm860x-i2c.c
<<
>>
Prefs
   1/*
   2 * I2C driver for Marvell 88PM860x
   3 *
   4 * Copyright (C) 2009 Marvell International Ltd.
   5 *
   6 * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/i2c.h>
  15#include <linux/regmap.h>
  16#include <linux/mfd/88pm860x.h>
  17
  18int pm860x_reg_read(struct i2c_client *i2c, int reg)
  19{
  20        struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  21        struct regmap *map = (i2c == chip->client) ? chip->regmap
  22                                : chip->regmap_companion;
  23        unsigned int data;
  24        int ret;
  25
  26        ret = regmap_read(map, reg, &data);
  27        if (ret < 0)
  28                return ret;
  29        else
  30                return (int)data;
  31}
  32EXPORT_SYMBOL(pm860x_reg_read);
  33
  34int pm860x_reg_write(struct i2c_client *i2c, int reg,
  35                     unsigned char data)
  36{
  37        struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  38        struct regmap *map = (i2c == chip->client) ? chip->regmap
  39                                : chip->regmap_companion;
  40        int ret;
  41
  42        ret = regmap_write(map, reg, data);
  43        return ret;
  44}
  45EXPORT_SYMBOL(pm860x_reg_write);
  46
  47int pm860x_bulk_read(struct i2c_client *i2c, int reg,
  48                     int count, unsigned char *buf)
  49{
  50        struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  51        struct regmap *map = (i2c == chip->client) ? chip->regmap
  52                                : chip->regmap_companion;
  53        int ret;
  54
  55        ret = regmap_raw_read(map, reg, buf, count);
  56        return ret;
  57}
  58EXPORT_SYMBOL(pm860x_bulk_read);
  59
  60int pm860x_bulk_write(struct i2c_client *i2c, int reg,
  61                      int count, unsigned char *buf)
  62{
  63        struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  64        struct regmap *map = (i2c == chip->client) ? chip->regmap
  65                                : chip->regmap_companion;
  66        int ret;
  67
  68        ret = regmap_raw_write(map, reg, buf, count);
  69        return ret;
  70}
  71EXPORT_SYMBOL(pm860x_bulk_write);
  72
  73int pm860x_set_bits(struct i2c_client *i2c, int reg,
  74                    unsigned char mask, unsigned char data)
  75{
  76        struct pm860x_chip *chip = i2c_get_clientdata(i2c);
  77        struct regmap *map = (i2c == chip->client) ? chip->regmap
  78                                : chip->regmap_companion;
  79        int ret;
  80
  81        ret = regmap_update_bits(map, reg, mask, data);
  82        return ret;
  83}
  84EXPORT_SYMBOL(pm860x_set_bits);
  85
  86static int read_device(struct i2c_client *i2c, int reg,
  87                       int bytes, void *dest)
  88{
  89        unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
  90        unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
  91        struct i2c_adapter *adap = i2c->adapter;
  92        struct i2c_msg msg[2] = {
  93                                        {
  94                                                .addr = i2c->addr,
  95                                                .flags = 0,
  96                                                .len = 1,
  97                                                .buf = msgbuf0
  98                                        },
  99                                        {       .addr = i2c->addr,
 100                                                .flags = I2C_M_RD,
 101                                                .len = 0,
 102                                                .buf = msgbuf1
 103                                        },
 104                                };
 105        int num = 1, ret = 0;
 106
 107        if (dest == NULL)
 108                return -EINVAL;
 109        msgbuf0[0] = (unsigned char)reg;        /* command */
 110        msg[1].len = bytes;
 111
 112        /* if data needs to read back, num should be 2 */
 113        if (bytes > 0)
 114                num = 2;
 115        ret = adap->algo->master_xfer(adap, msg, num);
 116        memcpy(dest, msgbuf1, bytes);
 117        if (ret < 0)
 118                return ret;
 119        return 0;
 120}
 121
 122static int write_device(struct i2c_client *i2c, int reg,
 123                        int bytes, void *src)
 124{
 125        unsigned char buf[2];
 126        struct i2c_adapter *adap = i2c->adapter;
 127        struct i2c_msg msg;
 128        int ret;
 129
 130        buf[0] = (unsigned char)reg;
 131        memcpy(&buf[1], src, bytes);
 132        msg.addr = i2c->addr;
 133        msg.flags = 0;
 134        msg.len = bytes + 1;
 135        msg.buf = buf;
 136
 137        ret = adap->algo->master_xfer(adap, &msg, 1);
 138        if (ret < 0)
 139                return ret;
 140        return 0;
 141}
 142
 143int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
 144                          unsigned char data)
 145{
 146        unsigned char zero;
 147        int ret;
 148
 149        i2c_lock_adapter(i2c->adapter);
 150        read_device(i2c, 0xFA, 0, &zero);
 151        read_device(i2c, 0xFB, 0, &zero);
 152        read_device(i2c, 0xFF, 0, &zero);
 153        ret = write_device(i2c, reg, 1, &data);
 154        read_device(i2c, 0xFE, 0, &zero);
 155        read_device(i2c, 0xFC, 0, &zero);
 156        i2c_unlock_adapter(i2c->adapter);
 157        return ret;
 158}
 159EXPORT_SYMBOL(pm860x_page_reg_write);
 160
 161int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
 162                          int count, unsigned char *buf)
 163{
 164        unsigned char zero = 0;
 165        int ret;
 166
 167        i2c_lock_adapter(i2c->adapter);
 168        read_device(i2c, 0xfa, 0, &zero);
 169        read_device(i2c, 0xfb, 0, &zero);
 170        read_device(i2c, 0xff, 0, &zero);
 171        ret = read_device(i2c, reg, count, buf);
 172        read_device(i2c, 0xFE, 0, &zero);
 173        read_device(i2c, 0xFC, 0, &zero);
 174        i2c_unlock_adapter(i2c->adapter);
 175        return ret;
 176}
 177EXPORT_SYMBOL(pm860x_page_bulk_read);
 178