0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/regmap.h>
0012 #include <linux/spmi.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015
0016 static int regmap_spmi_base_read(void *context,
0017 const void *reg, size_t reg_size,
0018 void *val, size_t val_size)
0019 {
0020 u8 addr = *(u8 *)reg;
0021 int err = 0;
0022
0023 BUG_ON(reg_size != 1);
0024
0025 while (val_size-- && !err)
0026 err = spmi_register_read(context, addr++, val++);
0027
0028 return err;
0029 }
0030
0031 static int regmap_spmi_base_gather_write(void *context,
0032 const void *reg, size_t reg_size,
0033 const void *val, size_t val_size)
0034 {
0035 const u8 *data = val;
0036 u8 addr = *(u8 *)reg;
0037 int err = 0;
0038
0039 BUG_ON(reg_size != 1);
0040
0041
0042
0043
0044
0045 if (addr == 0 && val_size) {
0046 err = spmi_register_zero_write(context, *data);
0047 if (err)
0048 goto err_out;
0049
0050 data++;
0051 addr++;
0052 val_size--;
0053 }
0054
0055 while (val_size) {
0056 err = spmi_register_write(context, addr, *data);
0057 if (err)
0058 goto err_out;
0059
0060 data++;
0061 addr++;
0062 val_size--;
0063 }
0064
0065 err_out:
0066 return err;
0067 }
0068
0069 static int regmap_spmi_base_write(void *context, const void *data,
0070 size_t count)
0071 {
0072 BUG_ON(count < 1);
0073 return regmap_spmi_base_gather_write(context, data, 1, data + 1,
0074 count - 1);
0075 }
0076
0077 static const struct regmap_bus regmap_spmi_base = {
0078 .read = regmap_spmi_base_read,
0079 .write = regmap_spmi_base_write,
0080 .gather_write = regmap_spmi_base_gather_write,
0081 .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
0082 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
0083 };
0084
0085 struct regmap *__regmap_init_spmi_base(struct spmi_device *sdev,
0086 const struct regmap_config *config,
0087 struct lock_class_key *lock_key,
0088 const char *lock_name)
0089 {
0090 return __regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
0091 lock_key, lock_name);
0092 }
0093 EXPORT_SYMBOL_GPL(__regmap_init_spmi_base);
0094
0095 struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *sdev,
0096 const struct regmap_config *config,
0097 struct lock_class_key *lock_key,
0098 const char *lock_name)
0099 {
0100 return __devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
0101 lock_key, lock_name);
0102 }
0103 EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_base);
0104
0105 static int regmap_spmi_ext_read(void *context,
0106 const void *reg, size_t reg_size,
0107 void *val, size_t val_size)
0108 {
0109 int err = 0;
0110 size_t len;
0111 u16 addr;
0112
0113 BUG_ON(reg_size != 2);
0114
0115 addr = *(u16 *)reg;
0116
0117
0118
0119
0120
0121 while (addr <= 0xFF && val_size) {
0122 len = min_t(size_t, val_size, 16);
0123
0124 err = spmi_ext_register_read(context, addr, val, len);
0125 if (err)
0126 goto err_out;
0127
0128 addr += len;
0129 val += len;
0130 val_size -= len;
0131 }
0132
0133 while (val_size) {
0134 len = min_t(size_t, val_size, 8);
0135
0136 err = spmi_ext_register_readl(context, addr, val, len);
0137 if (err)
0138 goto err_out;
0139
0140 addr += len;
0141 val += len;
0142 val_size -= len;
0143 }
0144
0145 err_out:
0146 return err;
0147 }
0148
0149 static int regmap_spmi_ext_gather_write(void *context,
0150 const void *reg, size_t reg_size,
0151 const void *val, size_t val_size)
0152 {
0153 int err = 0;
0154 size_t len;
0155 u16 addr;
0156
0157 BUG_ON(reg_size != 2);
0158
0159 addr = *(u16 *)reg;
0160
0161 while (addr <= 0xFF && val_size) {
0162 len = min_t(size_t, val_size, 16);
0163
0164 err = spmi_ext_register_write(context, addr, val, len);
0165 if (err)
0166 goto err_out;
0167
0168 addr += len;
0169 val += len;
0170 val_size -= len;
0171 }
0172
0173 while (val_size) {
0174 len = min_t(size_t, val_size, 8);
0175
0176 err = spmi_ext_register_writel(context, addr, val, len);
0177 if (err)
0178 goto err_out;
0179
0180 addr += len;
0181 val += len;
0182 val_size -= len;
0183 }
0184
0185 err_out:
0186 return err;
0187 }
0188
0189 static int regmap_spmi_ext_write(void *context, const void *data,
0190 size_t count)
0191 {
0192 BUG_ON(count < 2);
0193 return regmap_spmi_ext_gather_write(context, data, 2, data + 2,
0194 count - 2);
0195 }
0196
0197 static const struct regmap_bus regmap_spmi_ext = {
0198 .read = regmap_spmi_ext_read,
0199 .write = regmap_spmi_ext_write,
0200 .gather_write = regmap_spmi_ext_gather_write,
0201 .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
0202 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
0203 };
0204
0205 struct regmap *__regmap_init_spmi_ext(struct spmi_device *sdev,
0206 const struct regmap_config *config,
0207 struct lock_class_key *lock_key,
0208 const char *lock_name)
0209 {
0210 return __regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
0211 lock_key, lock_name);
0212 }
0213 EXPORT_SYMBOL_GPL(__regmap_init_spmi_ext);
0214
0215 struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *sdev,
0216 const struct regmap_config *config,
0217 struct lock_class_key *lock_key,
0218 const char *lock_name)
0219 {
0220 return __devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
0221 lock_key, lock_name);
0222 }
0223 EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
0224
0225 MODULE_LICENSE("GPL");