cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

regmap-w1.c (5493B)


      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 const 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 const 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 const 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");