Skip to content

Commit cc5d0db

Browse files
MinimumLawbroonie
authored andcommitted
regmap: Add 1-Wire bus support
Add basic support regmap (register map access) API for 1-Wire bus Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 2ea659a commit cc5d0db

File tree

4 files changed

+285
-1
lines changed

4 files changed

+285
-1
lines changed

drivers/base/regmap/Kconfig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# subsystems should select the appropriate symbols.
44

55
config REGMAP
6-
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
6+
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
77
select LZO_COMPRESS
88
select LZO_DECOMPRESS
99
select IRQ_DOMAIN if REGMAP_IRQ
@@ -24,6 +24,10 @@ config REGMAP_SPMI
2424
tristate
2525
depends on SPMI
2626

27+
config REGMAP_W1
28+
tristate
29+
depends on W1
30+
2731
config REGMAP_MMIO
2832
tristate
2933

drivers/base/regmap/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
1010
obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
1111
obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
1212
obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o
13+
obj-$(CONFIG_REGMAP_W1) += regmap-w1.o

drivers/base/regmap/regmap-w1.c

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* Register map access API - W1 (1-Wire) support
3+
*
4+
* Copyright (C) 2017 OAO Radioavionica
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 "../../w1/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+
25+
static 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+
47+
static 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+
73+
static 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+
97+
static 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+
125+
static 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+
150+
static 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+
179+
static 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+
184+
static 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+
189+
static 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+
194+
static 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+
209+
struct 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+
}
225+
EXPORT_SYMBOL_GPL(__regmap_init_w1);
226+
227+
struct 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+
}
243+
EXPORT_SYMBOL_GPL(__devm_regmap_init_w1);
244+
245+
MODULE_LICENSE("GPL");

include/linux/regmap.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,10 @@ struct regmap *__regmap_init_spmi_ext(struct spmi_device *dev,
461461
const struct regmap_config *config,
462462
struct lock_class_key *lock_key,
463463
const char *lock_name);
464+
struct regmap *__regmap_init_w1(struct device *w1_dev,
465+
const struct regmap_config *config,
466+
struct lock_class_key *lock_key,
467+
const char *lock_name);
464468
struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
465469
void __iomem *regs,
466470
const struct regmap_config *config,
@@ -493,6 +497,10 @@ struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *dev,
493497
const struct regmap_config *config,
494498
struct lock_class_key *lock_key,
495499
const char *lock_name);
500+
struct regmap *__devm_regmap_init_w1(struct device *w1_dev,
501+
const struct regmap_config *config,
502+
struct lock_class_key *lock_key,
503+
const char *lock_name);
496504
struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
497505
const char *clk_id,
498506
void __iomem *regs,
@@ -596,6 +604,19 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
596604
__regmap_lockdep_wrapper(__regmap_init_spmi_ext, #config, \
597605
dev, config)
598606

607+
/**
608+
* regmap_init_w1() - Initialise register map
609+
*
610+
* @w1_dev: Device that will be interacted with
611+
* @config: Configuration for register map
612+
*
613+
* The return value will be an ERR_PTR() on error or a valid pointer to
614+
* a struct regmap.
615+
*/
616+
#define regmap_init_w1(w1_dev, config) \
617+
__regmap_lockdep_wrapper(__regmap_init_w1, #config, \
618+
w1_dev, config)
619+
599620
/**
600621
* regmap_init_mmio_clk() - Initialise register map with register clock
601622
*
@@ -711,6 +732,19 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
711732
__regmap_lockdep_wrapper(__devm_regmap_init_spmi_ext, #config, \
712733
dev, config)
713734

735+
/**
736+
* devm_regmap_init_w1() - Initialise managed register map
737+
*
738+
* @w1_dev: Device that will be interacted with
739+
* @config: Configuration for register map
740+
*
741+
* The return value will be an ERR_PTR() on error or a valid pointer
742+
* to a struct regmap. The regmap will be automatically freed by the
743+
* device management code.
744+
*/
745+
#define devm_regmap_init_w1(w1_dev, config) \
746+
__regmap_lockdep_wrapper(__devm_regmap_init_w1, #config, \
747+
w1_dev, config)
714748
/**
715749
* devm_regmap_init_mmio_clk() - Initialise managed register map with clock
716750
*

0 commit comments

Comments
 (0)