[PATCH v3 4/9] eeprom: Add a simple EEPROM framework for eeprom consumers

Sascha Hauer s.hauer at pengutronix.de
Wed Mar 25 00:16:30 PDT 2015


On Tue, Mar 24, 2015 at 10:30:19PM +0000, Srinivas Kandagatla wrote:
> This patch adds just consumers part of the framework just to enable easy
> review.
> 
> Up until now, EEPROM drivers were stored in drivers/misc, where they all had to
> duplicate pretty much the same code to register a sysfs file, allow in-kernel
> users to access the content of the devices they were driving, etc.
> 
> This was also a problem as far as other in-kernel users were involved, since
> the solutions used were pretty much different from on driver to another, there
> was a rather big abstraction leak.
> 
> This introduction of this framework aims at solving this. It also introduces DT
> representation for consumer devices to go get the data they require (MAC
> Addresses, SoC/Revision ID, part numbers, and so on) from the EEPROMs.
> 
> Having regmap interface to this framework would give much better
> abstraction for eeproms on different buses.

Thanks for working on this. This is something that is missing in the
kernel, it looks very promising to me.

Some comments inline

> +static struct eeprom_cell *__eeprom_cell_get(struct device_node *cell_np,
> +					     const char *ename,
> +					     struct eeprom_block *blocks,
> +					     int nblocks)
> +{
> +	struct eeprom_cell *cell;
> +	struct eeprom_device *eeprom = NULL;

No need to initialize.

> +	struct property *prop;
> +	const __be32 *vp;
> +	u32 pv;
> +	int i, rval;
> +
> +	mutex_lock(&eeprom_mutex);
> +
> +	eeprom = cell_np ? of_eeprom_find(cell_np->parent) : eeprom_find(ename);
> +	if (!eeprom) {
> +		mutex_unlock(&eeprom_mutex);
> +		return ERR_PTR(-EPROBE_DEFER);
> +	}
> +

> +/**
> + * of_eeprom_cell_get(): Get eeprom cell of device form a given index
> + *
> + * @dev: Device that will be interacted with
> + * @index: eeprom index in eeproms property.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to a struct eeprom_cell.  The eeprom_cell will be freed by the
> + * eeprom_cell_put().
> + */
> +struct eeprom_cell *of_eeprom_cell_get(struct device *dev, int index)
> +{

I think the consumer API could be improved. The dev pointer is only used
to get the struct device_node out of it, so the device_node could be
passed in directly. As written in my other mail I think the binding
would be better like "calibration = <&tsens_calibration>;", so this
function could be:

of_eeprom_cell_get(struct device_node *np, const char *name)

With this we could also get eeprom cells from subnodes which do not have
a struct device bound to them.

> +	struct device_node *cell_np;
> +
> +	if (!dev || !dev->of_node)
> +		return ERR_PTR(-EINVAL);
> +
> +	cell_np = of_parse_phandle(dev->of_node, "eeproms", index);
> +	if (!cell_np)
> +		return ERR_PTR(-EPROBE_DEFER);

-EPROBE_DEFER is not appropriate here. If of_parse_phandle fails it
won't work next time.

> +
> +	return __eeprom_cell_get(cell_np, NULL, NULL, 0);
> +}
> +EXPORT_SYMBOL_GPL(of_eeprom_cell_get);
> +
> +/**
> + * eeprom_cell_write(): Write to a given eeprom cell
> + *
> + * @cell: eeprom cell to be written.
> + * @buf: Buffer to be written.
> + * @len: length of buffer to be written to eeprom cell.
> + *
> + * The return value will be an non zero on error or a zero on successful write.

No, it returns the length.

> + */
> +int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len)
> +{
> +	struct eeprom_device *eeprom = cell->eeprom;
> +	int i, rc, offset = 0;
> +
> +	if (!eeprom || !eeprom->regmap || len != cell->size)
> +		return -EINVAL;
> +
> +	for (i = 0; i < cell->nblocks; i++) {
> +		rc = regmap_bulk_write(eeprom->regmap, cell->blocks[i].offset,
> +				 buf + offset,
> +				 cell->blocks[i].count);
> +
> +		if (IS_ERR_VALUE(rc))
> +			return rc;
> +
> +		offset += cell->blocks[i].count;
> +	}
> +
> +	return len;
> +}
> +EXPORT_SYMBOL_GPL(eeprom_cell_write);
> +

> +static inline char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
> +{
> +	return NULL;
> +}

The documentation above the real function states that this function
either returns an ERR_PTR() or a valid pointer. The wrapper should then
do the same.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the linux-arm-kernel mailing list