1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/mfd/si476x-prop.c -- Subroutines to access
4 * properties of si476x chips
6 * Copyright (C) 2012 Innovative Converged Devices(ICD)
7 * Copyright (C) 2013 Andrey Smirnov
9 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
11 #include <linux/module.h>
13 #include <linux/mfd/si476x-core.h>
15 struct si476x_property_range
{
19 static bool si476x_core_element_is_in_array(u16 element
,
25 for (i
= 0; i
< size
; i
++)
26 if (element
== array
[i
])
32 static bool si476x_core_element_is_in_range(u16 element
,
33 const struct si476x_property_range range
[],
38 for (i
= 0; i
< size
; i
++)
39 if (element
<= range
[i
].high
&& element
>= range
[i
].low
)
45 static bool si476x_core_is_valid_property_a10(struct si476x_core
*core
,
48 static const u16 valid_properties
[] = {
52 0x0709, 0x070C, 0x070D, 0x70E, 0x710,
59 static const struct si476x_property_range valid_ranges
[] = {
80 return si476x_core_element_is_in_range(property
, valid_ranges
,
81 ARRAY_SIZE(valid_ranges
)) ||
82 si476x_core_element_is_in_array(property
, valid_properties
,
83 ARRAY_SIZE(valid_properties
));
86 static bool si476x_core_is_valid_property_a20(struct si476x_core
*core
,
89 static const u16 valid_properties
[] = {
96 static const struct si476x_property_range valid_ranges
[] = {
100 return si476x_core_is_valid_property_a10(core
, property
) ||
101 si476x_core_element_is_in_range(property
, valid_ranges
,
102 ARRAY_SIZE(valid_ranges
)) ||
103 si476x_core_element_is_in_array(property
, valid_properties
,
104 ARRAY_SIZE(valid_properties
));
107 static bool si476x_core_is_valid_property_a30(struct si476x_core
*core
,
110 static const u16 valid_properties
[] = {
119 static const struct si476x_property_range valid_ranges
[] = {
126 return si476x_core_is_valid_property_a20(core
, property
) ||
127 si476x_core_element_is_in_range(property
, valid_ranges
,
128 ARRAY_SIZE(valid_ranges
)) ||
129 si476x_core_element_is_in_array(property
, valid_properties
,
130 ARRAY_SIZE(valid_properties
));
133 typedef bool (*valid_property_pred_t
) (struct si476x_core
*, u16
);
135 static bool si476x_core_is_valid_property(struct si476x_core
*core
,
138 static const valid_property_pred_t is_valid_property
[] = {
139 [SI476X_REVISION_A10
] = si476x_core_is_valid_property_a10
,
140 [SI476X_REVISION_A20
] = si476x_core_is_valid_property_a20
,
141 [SI476X_REVISION_A30
] = si476x_core_is_valid_property_a30
,
144 BUG_ON(core
->revision
> SI476X_REVISION_A30
||
145 core
->revision
== -1);
146 return is_valid_property
[core
->revision
](core
, property
);
150 static bool si476x_core_is_readonly_property(struct si476x_core
*core
,
153 BUG_ON(core
->revision
> SI476X_REVISION_A30
||
154 core
->revision
== -1);
156 switch (core
->revision
) {
157 case SI476X_REVISION_A10
:
158 return (property
== 0x3200);
159 case SI476X_REVISION_A20
:
160 return (property
== 0x1006 ||
161 property
== 0x2210 ||
163 case SI476X_REVISION_A30
:
170 static bool si476x_core_regmap_readable_register(struct device
*dev
,
173 struct i2c_client
*client
= to_i2c_client(dev
);
174 struct si476x_core
*core
= i2c_get_clientdata(client
);
176 return si476x_core_is_valid_property(core
, (u16
) reg
);
180 static bool si476x_core_regmap_writable_register(struct device
*dev
,
183 struct i2c_client
*client
= to_i2c_client(dev
);
184 struct si476x_core
*core
= i2c_get_clientdata(client
);
186 return si476x_core_is_valid_property(core
, (u16
) reg
) &&
187 !si476x_core_is_readonly_property(core
, (u16
) reg
);
191 static int si476x_core_regmap_write(void *context
, unsigned int reg
,
194 return si476x_core_cmd_set_property(context
, reg
, val
);
197 static int si476x_core_regmap_read(void *context
, unsigned int reg
,
200 struct si476x_core
*core
= context
;
203 err
= si476x_core_cmd_get_property(core
, reg
);
213 static const struct regmap_config si476x_regmap_config
= {
217 .max_register
= 0x4003,
219 .writeable_reg
= si476x_core_regmap_writable_register
,
220 .readable_reg
= si476x_core_regmap_readable_register
,
222 .reg_read
= si476x_core_regmap_read
,
223 .reg_write
= si476x_core_regmap_write
,
225 .cache_type
= REGCACHE_RBTREE
,
228 struct regmap
*devm_regmap_init_si476x(struct si476x_core
*core
)
230 return devm_regmap_init(&core
->client
->dev
, NULL
,
231 core
, &si476x_regmap_config
);
233 EXPORT_SYMBOL_GPL(devm_regmap_init_si476x
);