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 18 int 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 } 32 EXPORT_SYMBOL(pm860x_reg_read); 33 34 int 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 } 45 EXPORT_SYMBOL(pm860x_reg_write); 46 47 int 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 } 58 EXPORT_SYMBOL(pm860x_bulk_read); 59 60 int 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 } 71 EXPORT_SYMBOL(pm860x_bulk_write); 72 73 int 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 } 84 EXPORT_SYMBOL(pm860x_set_bits); 85 86 static 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 122 static 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 143 int 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 } 159 EXPORT_SYMBOL(pm860x_page_reg_write); 160 161 int 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 } 177 EXPORT_SYMBOL(pm860x_page_bulk_read); 178