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