regcache.c revision 0eef6b0415f58ed16aff95af8c92514ce5c01258
1/*
2 * Register cache access API
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/slab.h>
14#include <trace/events/regmap.h>
15#include <linux/sort.h>
16
17#include "internal.h"
18
19static const struct regcache_ops *cache_types[] = {
20	&regcache_indexed_ops,
21	&regcache_rbtree_ops,
22	&regcache_lzo_ops,
23};
24
25static int regcache_hw_init(struct regmap *map)
26{
27	int i, j;
28	int ret;
29	int count;
30	unsigned int val;
31	void *tmp_buf;
32
33	if (!map->num_reg_defaults_raw)
34		return -EINVAL;
35
36	if (!map->reg_defaults_raw) {
37		dev_warn(map->dev, "No cache defaults, reading back from HW\n");
38		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
39		if (!tmp_buf)
40			return -EINVAL;
41		ret = regmap_bulk_read(map, 0, tmp_buf,
42				       map->num_reg_defaults_raw);
43		if (ret < 0) {
44			kfree(tmp_buf);
45			return ret;
46		}
47		map->reg_defaults_raw = tmp_buf;
48		map->cache_free = 1;
49	}
50
51	/* calculate the size of reg_defaults */
52	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
53		val = regcache_get_val(map->reg_defaults_raw,
54				       i, map->cache_word_size);
55		if (!val)
56			continue;
57		count++;
58	}
59
60	map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
61				      GFP_KERNEL);
62	if (!map->reg_defaults)
63		return -ENOMEM;
64
65	/* fill the reg_defaults */
66	map->num_reg_defaults = count;
67	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
68		val = regcache_get_val(map->reg_defaults_raw,
69				       i, map->cache_word_size);
70		if (!val)
71			continue;
72		map->reg_defaults[j].reg = i;
73		map->reg_defaults[j].def = val;
74		j++;
75	}
76
77	return 0;
78}
79
80int regcache_init(struct regmap *map)
81{
82	int ret;
83	int i;
84	void *tmp_buf;
85
86	if (map->cache_type == REGCACHE_NONE) {
87		map->cache_bypass = true;
88		return 0;
89	}
90
91	for (i = 0; i < ARRAY_SIZE(cache_types); i++)
92		if (cache_types[i]->type == map->cache_type)
93			break;
94
95	if (i == ARRAY_SIZE(cache_types)) {
96		dev_err(map->dev, "Could not match compress type: %d\n",
97			map->cache_type);
98		return -EINVAL;
99	}
100
101	map->cache = NULL;
102	map->cache_ops = cache_types[i];
103
104	if (!map->cache_ops->read ||
105	    !map->cache_ops->write ||
106	    !map->cache_ops->name)
107		return -EINVAL;
108
109	/* We still need to ensure that the reg_defaults
110	 * won't vanish from under us.  We'll need to make
111	 * a copy of it.
112	 */
113	if (map->reg_defaults) {
114		if (!map->num_reg_defaults)
115			return -EINVAL;
116		tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
117				  sizeof(struct reg_default), GFP_KERNEL);
118		if (!tmp_buf)
119			return -ENOMEM;
120		map->reg_defaults = tmp_buf;
121	} else {
122		/* Some devices such as PMICs don't have cache defaults,
123		 * we cope with this by reading back the HW registers and
124		 * crafting the cache defaults by hand.
125		 */
126		ret = regcache_hw_init(map);
127		if (ret < 0)
128			return ret;
129	}
130
131	if (!map->max_register)
132		map->max_register = map->num_reg_defaults_raw;
133
134	if (map->cache_ops->init) {
135		dev_dbg(map->dev, "Initializing %s cache\n",
136			map->cache_ops->name);
137		return map->cache_ops->init(map);
138	}
139	return 0;
140}
141
142void regcache_exit(struct regmap *map)
143{
144	if (map->cache_type == REGCACHE_NONE)
145		return;
146
147	BUG_ON(!map->cache_ops);
148
149	kfree(map->reg_defaults);
150	if (map->cache_free)
151		kfree(map->reg_defaults_raw);
152
153	if (map->cache_ops->exit) {
154		dev_dbg(map->dev, "Destroying %s cache\n",
155			map->cache_ops->name);
156		map->cache_ops->exit(map);
157	}
158}
159
160/**
161 * regcache_read: Fetch the value of a given register from the cache.
162 *
163 * @map: map to configure.
164 * @reg: The register index.
165 * @value: The value to be returned.
166 *
167 * Return a negative value on failure, 0 on success.
168 */
169int regcache_read(struct regmap *map,
170		  unsigned int reg, unsigned int *value)
171{
172	if (map->cache_type == REGCACHE_NONE)
173		return -ENOSYS;
174
175	BUG_ON(!map->cache_ops);
176
177	if (!regmap_readable(map, reg))
178		return -EIO;
179
180	if (!regmap_volatile(map, reg))
181		return map->cache_ops->read(map, reg, value);
182
183	return -EINVAL;
184}
185EXPORT_SYMBOL_GPL(regcache_read);
186
187/**
188 * regcache_write: Set the value of a given register in the cache.
189 *
190 * @map: map to configure.
191 * @reg: The register index.
192 * @value: The new register value.
193 *
194 * Return a negative value on failure, 0 on success.
195 */
196int regcache_write(struct regmap *map,
197		   unsigned int reg, unsigned int value)
198{
199	if (map->cache_type == REGCACHE_NONE)
200		return 0;
201
202	BUG_ON(!map->cache_ops);
203
204	if (!regmap_writeable(map, reg))
205		return -EIO;
206
207	if (!regmap_volatile(map, reg))
208		return map->cache_ops->write(map, reg, value);
209
210	return 0;
211}
212EXPORT_SYMBOL_GPL(regcache_write);
213
214/**
215 * regcache_sync: Sync the register cache with the hardware.
216 *
217 * @map: map to configure.
218 *
219 * Any registers that should not be synced should be marked as
220 * volatile.  In general drivers can choose not to use the provided
221 * syncing functionality if they so require.
222 *
223 * Return a negative value on failure, 0 on success.
224 */
225int regcache_sync(struct regmap *map)
226{
227	int ret = 0;
228	unsigned int val;
229	unsigned int i;
230	const char *name;
231	unsigned int bypass;
232
233	BUG_ON(!map->cache_ops);
234
235	mutex_lock(&map->lock);
236	/* Remember the initial bypass state */
237	bypass = map->cache_bypass;
238	dev_dbg(map->dev, "Syncing %s cache\n",
239		map->cache_ops->name);
240	name = map->cache_ops->name;
241	trace_regcache_sync(map->dev, name, "start");
242	if (map->cache_ops->sync) {
243		ret = map->cache_ops->sync(map);
244	} else {
245		for (i = 0; i < map->num_reg_defaults; i++) {
246			ret = regcache_read(map, i, &val);
247			if (ret < 0)
248				goto out;
249			map->cache_bypass = 1;
250			ret = _regmap_write(map, i, val);
251			map->cache_bypass = 0;
252			if (ret < 0)
253				goto out;
254			dev_dbg(map->dev, "Synced register %#x, value %#x\n",
255				map->reg_defaults[i].reg,
256				map->reg_defaults[i].def);
257		}
258
259	}
260out:
261	trace_regcache_sync(map->dev, name, "stop");
262	/* Restore the bypass state */
263	map->cache_bypass = bypass;
264	mutex_unlock(&map->lock);
265
266	return ret;
267}
268EXPORT_SYMBOL_GPL(regcache_sync);
269
270/**
271 * regcache_cache_only: Put a register map into cache only mode
272 *
273 * @map: map to configure
274 * @cache_only: flag if changes should be written to the hardware
275 *
276 * When a register map is marked as cache only writes to the register
277 * map API will only update the register cache, they will not cause
278 * any hardware changes.  This is useful for allowing portions of
279 * drivers to act as though the device were functioning as normal when
280 * it is disabled for power saving reasons.
281 */
282void regcache_cache_only(struct regmap *map, bool enable)
283{
284	mutex_lock(&map->lock);
285	WARN_ON(map->cache_bypass && enable);
286	map->cache_only = enable;
287	mutex_unlock(&map->lock);
288}
289EXPORT_SYMBOL_GPL(regcache_cache_only);
290
291/**
292 * regcache_cache_bypass: Put a register map into cache bypass mode
293 *
294 * @map: map to configure
295 * @cache_bypass: flag if changes should not be written to the hardware
296 *
297 * When a register map is marked with the cache bypass option, writes
298 * to the register map API will only update the hardware and not the
299 * the cache directly.  This is useful when syncing the cache back to
300 * the hardware.
301 */
302void regcache_cache_bypass(struct regmap *map, bool enable)
303{
304	mutex_lock(&map->lock);
305	WARN_ON(map->cache_only && enable);
306	map->cache_bypass = enable;
307	mutex_unlock(&map->lock);
308}
309EXPORT_SYMBOL_GPL(regcache_cache_bypass);
310
311bool regcache_set_val(void *base, unsigned int idx,
312		      unsigned int val, unsigned int word_size)
313{
314	switch (word_size) {
315	case 1: {
316		u8 *cache = base;
317		if (cache[idx] == val)
318			return true;
319		cache[idx] = val;
320		break;
321	}
322	case 2: {
323		u16 *cache = base;
324		if (cache[idx] == val)
325			return true;
326		cache[idx] = val;
327		break;
328	}
329	default:
330		BUG();
331	}
332	/* unreachable */
333	return false;
334}
335
336unsigned int regcache_get_val(const void *base, unsigned int idx,
337			      unsigned int word_size)
338{
339	if (!base)
340		return -EINVAL;
341
342	switch (word_size) {
343	case 1: {
344		const u8 *cache = base;
345		return cache[idx];
346	}
347	case 2: {
348		const u16 *cache = base;
349		return cache[idx];
350	}
351	default:
352		BUG();
353	}
354	/* unreachable */
355	return -1;
356}
357
358int regcache_lookup_reg(struct regmap *map, unsigned int reg)
359{
360	unsigned int min, max, index;
361
362	min = 0;
363	max = map->num_reg_defaults - 1;
364	do {
365		index = (min + max) / 2;
366		if (map->reg_defaults[index].reg == reg)
367			return index;
368		if (map->reg_defaults[index].reg < reg)
369			min = index + 1;
370		else
371			max = index;
372	} while (min <= max);
373	return -1;
374}
375
376static int regcache_insert_cmp(const void *a, const void *b)
377{
378	const struct reg_default *_a = a;
379	const struct reg_default *_b = b;
380
381	return _a->reg - _b->reg;
382}
383
384int regcache_insert_reg(struct regmap *map, unsigned int reg,
385			unsigned int val)
386{
387	void *tmp;
388
389	tmp = krealloc(map->reg_defaults,
390		       (map->num_reg_defaults + 1) * sizeof(struct reg_default),
391		       GFP_KERNEL);
392	if (!tmp)
393		return -ENOMEM;
394	map->reg_defaults = tmp;
395	map->num_reg_defaults++;
396	map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
397	map->reg_defaults[map->num_reg_defaults - 1].def = val;
398	sort(map->reg_defaults, map->num_reg_defaults,
399	     sizeof(struct reg_default), regcache_insert_cmp, NULL);
400	return 0;
401}
402