linux/drivers/base/regmap/regmap-w1.c
<<
>>
Prefs
   1/*
   2 * Register map access API - W1 (1-Wire) support
   3 *
   4 * Copyright (c) 2017 Radioavionica Corporation
   5 * Author: Alex A. Mihaylov <minimumlaw@rambler.ru>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation
  10 */
  11
  12#include <linux/regmap.h>
  13#include <linux/module.h>
  14#include <linux/w1.h>
  15
  16#include "internal.h"
  17
  18#define W1_CMD_READ_DATA        0x69
  19#define W1_CMD_WRITE_DATA       0x6C
  20
  21/*
  22 * 1-Wire slaves registers with addess 8 bit and data 8 bit
  23 */
  24
  25static int w1_reg_a8_v8_read(void *context, unsigned int reg, unsigned int *val)
  26{
  27        struct device *dev = context;
  28        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
  29        int ret = 0;
  30
  31        if (reg > 255)
  32                return -EINVAL;
  33
  34        mutex_lock(&sl->master->bus_mutex);
  35        if (!w1_reset_select_slave(sl)) {
  36                w1_write_8(sl->master, W1_CMD_READ_DATA);
  37                w1_write_8(sl->master, reg);
  38                *val = w1_read_8(sl->master);
  39        } else {
  40                ret = -ENODEV;
  41        }
  42        mutex_unlock(&sl->master->bus_mutex);
  43
  44        return ret;
  45}
  46
  47static int w1_reg_a8_v8_write(void *context, unsigned int reg, unsigned int val)
  48{
  49        struct device *dev = context;
  50        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
  51        int ret = 0;
  52
  53        if (reg > 255)
  54                return -EINVAL;
  55
  56        mutex_lock(&sl->master->bus_mutex);
  57        if (!w1_reset_select_slave(sl)) {
  58                w1_write_8(sl->master, W1_CMD_WRITE_DATA);
  59                w1_write_8(sl->master, reg);
  60                w1_write_8(sl->master, val);
  61        } else {
  62                ret = -ENODEV;
  63        }
  64        mutex_unlock(&sl->master->bus_mutex);
  65
  66        return ret;
  67}
  68
  69/*
  70 * 1-Wire slaves registers with addess 8 bit and data 16 bit
  71 */
  72
  73static int w1_reg_a8_v16_read(void *context, unsigned int reg,
  74                                unsigned int *val)
  75{
  76        struct device *dev = context;
  77        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
  78        int ret = 0;
  79
  80        if (reg > 255)
  81                return -EINVAL;
  82
  83        mutex_lock(&sl->master->bus_mutex);
  84        if (!w1_reset_select_slave(sl)) {
  85                w1_write_8(sl->master, W1_CMD_READ_DATA);
  86                w1_write_8(sl->master, reg);
  87                *val = w1_read_8(sl->master);
  88                *val |= w1_read_8(sl->master)<<8;
  89        } else {
  90                ret = -ENODEV;
  91        }
  92        mutex_unlock(&sl->master->bus_mutex);
  93
  94        return ret;
  95}
  96
  97static int w1_reg_a8_v16_write(void *context, unsigned int reg,
  98                                unsigned int val)
  99{
 100        struct device *dev = context;
 101        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 102        int ret = 0;
 103
 104        if (reg > 255)
 105                return -EINVAL;
 106
 107        mutex_lock(&sl->master->bus_mutex);
 108        if (!w1_reset_select_slave(sl)) {
 109                w1_write_8(sl->master, W1_CMD_WRITE_DATA);
 110                w1_write_8(sl->master, reg);
 111                w1_write_8(sl->master, val & 0x00FF);
 112                w1_write_8(sl->master, val>>8 & 0x00FF);
 113        } else {
 114                ret = -ENODEV;
 115        }
 116        mutex_unlock(&sl->master->bus_mutex);
 117
 118        return ret;
 119}
 120
 121/*
 122 * 1-Wire slaves registers with addess 16 bit and data 16 bit
 123 */
 124
 125static int w1_reg_a16_v16_read(void *context, unsigned int reg,
 126                                unsigned int *val)
 127{
 128        struct device *dev = context;
 129        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 130        int ret = 0;
 131
 132        if (reg > 65535)
 133                return -EINVAL;
 134
 135        mutex_lock(&sl->master->bus_mutex);
 136        if (!w1_reset_select_slave(sl)) {
 137                w1_write_8(sl->master, W1_CMD_READ_DATA);
 138                w1_write_8(sl->master, reg & 0x00FF);
 139                w1_write_8(sl->master, reg>>8 & 0x00FF);
 140                *val = w1_read_8(sl->master);
 141                *val |= w1_read_8(sl->master)<<8;
 142        } else {
 143                ret = -ENODEV;
 144        }
 145        mutex_unlock(&sl->master->bus_mutex);
 146
 147        return ret;
 148}
 149
 150static int w1_reg_a16_v16_write(void *context, unsigned int reg,
 151                                unsigned int val)
 152{
 153        struct device *dev = context;
 154        struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 155        int ret = 0;
 156
 157        if (reg > 65535)
 158                return -EINVAL;
 159
 160        mutex_lock(&sl->master->bus_mutex);
 161        if (!w1_reset_select_slave(sl)) {
 162                w1_write_8(sl->master, W1_CMD_WRITE_DATA);
 163                w1_write_8(sl->master, reg & 0x00FF);
 164                w1_write_8(sl->master, reg>>8 & 0x00FF);
 165                w1_write_8(sl->master, val & 0x00FF);
 166                w1_write_8(sl->master, val>>8 & 0x00FF);
 167        } else {
 168                ret = -ENODEV;
 169        }
 170        mutex_unlock(&sl->master->bus_mutex);
 171
 172        return ret;
 173}
 174
 175/*
 176 * Various types of supported bus addressing
 177 */
 178
 179static struct regmap_bus regmap_w1_bus_a8_v8 = {
 180        .reg_read = w1_reg_a8_v8_read,
 181        .reg_write = w1_reg_a8_v8_write,
 182};
 183
 184static struct regmap_bus regmap_w1_bus_a8_v16 = {
 185        .reg_read = w1_reg_a8_v16_read,
 186        .reg_write = w1_reg_a8_v16_write,
 187};
 188
 189static struct regmap_bus regmap_w1_bus_a16_v16 = {
 190        .reg_read = w1_reg_a16_v16_read,
 191        .reg_write = w1_reg_a16_v16_write,
 192};
 193
 194static const struct regmap_bus *regmap_get_w1_bus(struct device *w1_dev,
 195                                        const struct regmap_config *config)
 196{
 197        if (config->reg_bits == 8 && config->val_bits == 8)
 198                return &regmap_w1_bus_a8_v8;
 199
 200        if (config->reg_bits == 8 && config->val_bits == 16)
 201                return &regmap_w1_bus_a8_v16;
 202
 203        if (config->reg_bits == 16 && config->val_bits == 16)
 204                return &regmap_w1_bus_a16_v16;
 205
 206        return ERR_PTR(-ENOTSUPP);
 207}
 208
 209struct regmap *__regmap_init_w1(struct device *w1_dev,
 210                                 const struct regmap_config *config,
 211                                 struct lock_class_key *lock_key,
 212                                 const char *lock_name)
 213{
 214
 215        const struct regmap_bus *bus = regmap_get_w1_bus(w1_dev, config);
 216
 217        if (IS_ERR(bus))
 218                return ERR_CAST(bus);
 219
 220        return __regmap_init(w1_dev, bus, w1_dev, config,
 221                         lock_key, lock_name);
 222
 223        return NULL;
 224}
 225EXPORT_SYMBOL_GPL(__regmap_init_w1);
 226
 227struct regmap *__devm_regmap_init_w1(struct device *w1_dev,
 228                                 const struct regmap_config *config,
 229                                 struct lock_class_key *lock_key,
 230                                 const char *lock_name)
 231{
 232
 233        const struct regmap_bus *bus = regmap_get_w1_bus(w1_dev, config);
 234
 235        if (IS_ERR(bus))
 236                return ERR_CAST(bus);
 237
 238        return __devm_regmap_init(w1_dev, bus, w1_dev, config,
 239                                 lock_key, lock_name);
 240
 241        return NULL;
 242}
 243EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
 244
 245MODULE_LICENSE("GPL");
 246