Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * I2C driver for Marvell 88PM860x
0004  *
0005  * Copyright (C) 2009 Marvell International Ltd.
0006  *
0007  * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
0008  */
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/regmap.h>
0013 #include <linux/mfd/88pm860x.h>
0014 
0015 int pm860x_reg_read(struct i2c_client *i2c, int reg)
0016 {
0017     struct pm860x_chip *chip = i2c_get_clientdata(i2c);
0018     struct regmap *map = (i2c == chip->client) ? chip->regmap
0019                 : chip->regmap_companion;
0020     unsigned int data;
0021     int ret;
0022 
0023     ret = regmap_read(map, reg, &data);
0024     if (ret < 0)
0025         return ret;
0026     else
0027         return (int)data;
0028 }
0029 EXPORT_SYMBOL(pm860x_reg_read);
0030 
0031 int pm860x_reg_write(struct i2c_client *i2c, int reg,
0032              unsigned char data)
0033 {
0034     struct pm860x_chip *chip = i2c_get_clientdata(i2c);
0035     struct regmap *map = (i2c == chip->client) ? chip->regmap
0036                 : chip->regmap_companion;
0037     int ret;
0038 
0039     ret = regmap_write(map, reg, data);
0040     return ret;
0041 }
0042 EXPORT_SYMBOL(pm860x_reg_write);
0043 
0044 int pm860x_bulk_read(struct i2c_client *i2c, int reg,
0045              int count, unsigned char *buf)
0046 {
0047     struct pm860x_chip *chip = i2c_get_clientdata(i2c);
0048     struct regmap *map = (i2c == chip->client) ? chip->regmap
0049                 : chip->regmap_companion;
0050     int ret;
0051 
0052     ret = regmap_raw_read(map, reg, buf, count);
0053     return ret;
0054 }
0055 EXPORT_SYMBOL(pm860x_bulk_read);
0056 
0057 int pm860x_bulk_write(struct i2c_client *i2c, int reg,
0058               int count, unsigned char *buf)
0059 {
0060     struct pm860x_chip *chip = i2c_get_clientdata(i2c);
0061     struct regmap *map = (i2c == chip->client) ? chip->regmap
0062                 : chip->regmap_companion;
0063     int ret;
0064 
0065     ret = regmap_raw_write(map, reg, buf, count);
0066     return ret;
0067 }
0068 EXPORT_SYMBOL(pm860x_bulk_write);
0069 
0070 int pm860x_set_bits(struct i2c_client *i2c, int reg,
0071             unsigned char mask, unsigned char data)
0072 {
0073     struct pm860x_chip *chip = i2c_get_clientdata(i2c);
0074     struct regmap *map = (i2c == chip->client) ? chip->regmap
0075                 : chip->regmap_companion;
0076     int ret;
0077 
0078     ret = regmap_update_bits(map, reg, mask, data);
0079     return ret;
0080 }
0081 EXPORT_SYMBOL(pm860x_set_bits);
0082 
0083 static int read_device(struct i2c_client *i2c, int reg,
0084                int bytes, void *dest)
0085 {
0086     unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
0087     unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
0088     struct i2c_adapter *adap = i2c->adapter;
0089     struct i2c_msg msg[2] = {
0090                     {
0091                         .addr = i2c->addr,
0092                         .flags = 0,
0093                         .len = 1,
0094                         .buf = msgbuf0
0095                     },
0096                     {   .addr = i2c->addr,
0097                         .flags = I2C_M_RD,
0098                         .len = 0,
0099                         .buf = msgbuf1
0100                     },
0101                 };
0102     int num = 1, ret = 0;
0103 
0104     if (dest == NULL)
0105         return -EINVAL;
0106     msgbuf0[0] = (unsigned char)reg;    /* command */
0107     msg[1].len = bytes;
0108 
0109     /* if data needs to read back, num should be 2 */
0110     if (bytes > 0)
0111         num = 2;
0112     ret = adap->algo->master_xfer(adap, msg, num);
0113     memcpy(dest, msgbuf1, bytes);
0114     if (ret < 0)
0115         return ret;
0116     return 0;
0117 }
0118 
0119 static int write_device(struct i2c_client *i2c, int reg,
0120             int bytes, void *src)
0121 {
0122     unsigned char buf[2];
0123     struct i2c_adapter *adap = i2c->adapter;
0124     struct i2c_msg msg;
0125     int ret;
0126 
0127     buf[0] = (unsigned char)reg;
0128     memcpy(&buf[1], src, bytes);
0129     msg.addr = i2c->addr;
0130     msg.flags = 0;
0131     msg.len = bytes + 1;
0132     msg.buf = buf;
0133 
0134     ret = adap->algo->master_xfer(adap, &msg, 1);
0135     if (ret < 0)
0136         return ret;
0137     return 0;
0138 }
0139 
0140 int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
0141               unsigned char data)
0142 {
0143     unsigned char zero;
0144     int ret;
0145 
0146     i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
0147     read_device(i2c, 0xFA, 0, &zero);
0148     read_device(i2c, 0xFB, 0, &zero);
0149     read_device(i2c, 0xFF, 0, &zero);
0150     ret = write_device(i2c, reg, 1, &data);
0151     read_device(i2c, 0xFE, 0, &zero);
0152     read_device(i2c, 0xFC, 0, &zero);
0153     i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
0154     return ret;
0155 }
0156 EXPORT_SYMBOL(pm860x_page_reg_write);
0157 
0158 int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
0159               int count, unsigned char *buf)
0160 {
0161     unsigned char zero = 0;
0162     int ret;
0163 
0164     i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
0165     read_device(i2c, 0xfa, 0, &zero);
0166     read_device(i2c, 0xfb, 0, &zero);
0167     read_device(i2c, 0xff, 0, &zero);
0168     ret = read_device(i2c, reg, count, buf);
0169     read_device(i2c, 0xFE, 0, &zero);
0170     read_device(i2c, 0xFC, 0, &zero);
0171     i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
0172     return ret;
0173 }
0174 EXPORT_SYMBOL(pm860x_page_bulk_read);