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