All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lars-Peter Clausen <lars@metafoo.de>
To: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-kernel@vger.kernel.org,
	Dimitris Papastamos <dp@opensource.wolfsonmicro.com>,
	Liam Girdwood <lrg@ti.com>, Samuel Oritz <sameo@linux.intel.com>,
	Graeme Gregory <gg@slimlogic.co.uk>
Subject: Re: [PATCH 1/8] regmap: Add generic non-memory mapped register access API
Date: Tue, 21 Jun 2011 01:15:18 +0200	[thread overview]
Message-ID: <4DFFD486.7020901@metafoo.de> (raw)
In-Reply-To: <1308574489-31322-1-git-send-email-broonie@opensource.wolfsonmicro.com>

Very nice!

> [...]
> diff --git a/drivers/regmap/regmap.c b/drivers/regmap/regmap.c
> new file mode 100644
> index 0000000..a8610c7
> --- /dev/null
> +++ b/drivers/regmap/regmap.c
> @@ -0,0 +1,478 @@
> +/*
> + * Register map access API
> + *
> + * Copyright 2011 Wolfson Microelectronics plc
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/err.h>
> +
> +#include <linux/regmap.h>
> +
> +struct regmap;
> +
> +static DEFINE_MUTEX(regmap_bus_lock);
> +static LIST_HEAD(regmap_bus_list);
> +
> +struct regmap_format {
> +	size_t buf_size;
> +	size_t reg_bytes;
> +	size_t val_bytes;
> +	void (*format_write)(struct regmap *map,
> +			     unsigned int reg, unsigned int val);
> +	void (*format_reg)(void *buf, unsigned int reg);
> +	void (*format_val)(void *buf, unsigned int val);
> +	unsigned int (*parse_val)(void *buf);

const void *buf. It probably also makes sense to pass the regmap to all
callbacks, so we can write generic format/parser functions which use
information for example from the regmap_format.

> +};
> +
> +struct regmap {
> +	struct mutex lock;
> +
> +	struct device *dev; /* Device we do I/O on */
> +	void *work_buf;     /* Scratch buffer used to format I/O */
> +	struct regmap_format format;  /* Buffer format */
> +	struct regmap_bus *bus;

const struct regmap_bus

> +};
> +
> +static void regmap_format_4_12_write(struct regmap *map,
> +				     unsigned int reg, unsigned int val)
> +{
> +	u16 *out = map->work_buf;
> +	*out = cpu_to_be16((reg << 12) | val);
> +}
> +
> +static void regmap_format_7_9_write(struct regmap *map,
> +				    unsigned int reg, unsigned int val)
> +{
> +	u16 *out = map->work_buf;
> +	*out = cpu_to_be16((reg << 9) | val);
> +}

It would make sense to keep val_bits around and implement these two generically:
	*out = cpu_to_be16((reg << map->format.val_bits) | val);

> [...]
> +/**
> + * remap_init: Initialise register map
> + *
> + * dev: Device that will be interacted with
> + * config: Configuration for register map
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to a struct regmap.
> + */
> +struct regmap *regmap_init(struct device *dev, struct regmap_config *config)

regmap_alloc would in my opinion be a better name.

> [...]
> +static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
> +			    unsigned int val_len)
> +{
> +	u8 *u8 = map->work_buf;
> +	int ret;
> +
> +	map->format.format_reg(map->work_buf, reg);
> +
> +	/*
> +	 * Some buses flag reads by setting the high bit in the
> +	 * register addresss; since it's always the high bit for all
> +	 * current formats we can do this here rather than in
> +	 * formatting.  This may break if we get interesting formats.
> +	 */
> +	if (map->bus->read_flag_in_reg)
> +		u8[0] |= 0x80;

This is rather specific. Making this a per device mask or bit offset, would
make more sense in my opinion. I have for example one SPI codec device which
uses the 7th bit to indicate a read. And I also have devices on a custom bus,
which needs to set the upper bit to indicate a write, so a mask for both write
and read would be good.

> +
> +	ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
> +			     val, map->format.val_bytes);
> +	if (ret != 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> [...]
> +/**
> + * regmap_bulk_read: Read multiple registers from the device
> + *
> + * @map: Register map to write to
> + * @reg: First register to be read from
> + * @val: Pointer to store read value, in native register size for device
> + * @val_count: Number of registers to read
> + *
> + * A value of zero will be returned on success, a negative errno will
> + * be returned in error cases.
> + */
> +int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
> +		     size_t val_count)
> +{
> +	int ret, i;
> +	size_t val_bytes = map->format.val_bytes;
> +
> +	if (!map->format.parse_val)
> +		return -EINVAL;
> +
> +	ret = regmap_raw_read(map, reg, val, val_bytes);

val_bytes * val_count

> +	if (ret != 0)
> +		return ret;
> +
> +	for (i = 0; i < val_count * val_bytes; i += val_bytes)
> +		map->format.parse_val(val + i);

This doesn't make sense. parse_val returns the parsed value, but doesn't modify
the parsed data. It would make sense to make the interface similar to
regmap_read and make the returned values a unsigned integer array and use a
bounce buffer for reading them from the device.

> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(regmap_bulk_read);
> +
> [...]
> diff --git a/include/linux/regmap.h b/include/linux/regmap.h
> new file mode 100644
> index 0000000..0c2e402
> --- /dev/null
> +++ b/include/linux/regmap.h
> @@ -0,0 +1,75 @@
> +#ifndef __LINUX_REGMAP_H
> +#define __LINUX_REGMAP_H
> +
> +/*
> + * Register map access API
> + *
> + * Copyright 2011 Wolfson Microelectronics plc
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/list.h>

#include <linux/module.h>

> +
> +struct regmap_config {
> +	int reg_bits;
> +	int val_bits;

size_t for both?

> +};
> +
> ...
> +
> +struct regmap *regmap_init(struct device *dev, struct regmap_config *config);

const struct regmap_config

> +void regmap_free(struct regmap *map);
> +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
> +int regmap_raw_write(struct regmap *map, unsigned int reg,
> +		     const void *val, size_t val_len);
> +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
> +int regmap_raw_read(struct regmap *map, unsigned int reg,
> +		    void *val, size_t val_len);
> +int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
> +		     size_t val_count);

What about bulk_write?

  parent reply	other threads:[~2011-06-20 23:16 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-20 12:46 [PATCH 0/8] Generic I2C and SPI register map library Mark Brown
2011-06-20 12:54 ` [PATCH 1/8] regmap: Add generic non-memory mapped register access API Mark Brown
2011-06-20 12:54   ` [PATCH 2/8] regmap: Add I2C bus support Mark Brown
2011-06-20 23:22     ` Lars-Peter Clausen
2011-06-20 23:41       ` Mark Brown
2011-06-21  0:01         ` Lars-Peter Clausen
2011-06-20 12:54   ` [PATCH 3/8] regmap: Add SPI " Mark Brown
2011-06-20 23:26     ` Lars-Peter Clausen
2011-06-20 23:45       ` Mark Brown
2011-06-21  0:00         ` Lars-Peter Clausen
2011-06-20 12:54   ` [PATCH 4/8] ASoC: Use new register map API for ASoC generic physical I/O Mark Brown
2011-06-20 12:54   ` [PATCH 5/8] mfd: Convert WM831x to use regmap API Mark Brown
2011-06-20 12:54   ` [PATCH 6/8] mfd: Convert WM8994 to use new register map API Mark Brown
2011-06-20 12:54   ` [PATCH 7/8] mfd: Convert pcf50633 " Mark Brown
2011-06-20 12:54   ` [PATCH 8/8] regulator: Convert tps65023 to use regmap API Mark Brown
2011-06-20 23:15   ` Lars-Peter Clausen [this message]
2011-06-21  0:14     ` [PATCH 1/8] regmap: Add generic non-memory mapped register access API Mark Brown
2011-06-21  0:45       ` Lars-Peter Clausen
2011-06-21  1:24         ` Mark Brown
2011-06-21 11:47           ` Dimitris Papastamos
2011-06-21 12:07             ` Mark Brown
2011-06-21 11:43   ` Dimitris Papastamos
2011-06-21 12:07     ` Mark Brown
2011-06-22 18:44 [PATCH 0/8] Generic I2C and SPI register map library Mark Brown
2011-06-22 18:45 ` [PATCH 1/8] regmap: Add generic non-memory mapped register access API Mark Brown
2011-06-22 19:03   ` Lars-Peter Clausen
2011-06-22 19:11     ` Mark Brown
2011-06-22 19:20       ` Lars-Peter Clausen
2011-06-22 19:42         ` Mark Brown
2011-07-01  0:22   ` Ben Hutchings
2011-07-01  2:38     ` Mark Brown
2011-06-30  5:58 [PATCH 0/8] regmap: Generic I2C and SPI register map library Mark Brown
2011-06-30  6:00 ` [PATCH 1/8] regmap: Add generic non-memory mapped register access API Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DFFD486.7020901@metafoo.de \
    --to=lars@metafoo.de \
    --cc=broonie@opensource.wolfsonmicro.com \
    --cc=dp@opensource.wolfsonmicro.com \
    --cc=gg@slimlogic.co.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lrg@ti.com \
    --cc=sameo@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.