All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-22 23:07 ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:07 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

Thankyou all for providing inputs and comments on previous versions of this
patchset. Here is the v6 of the patchset addressing all the issues raised as
part of previous versions review.

This patchset adds a new simple NVMEM framework to kernel, and it is tested
with various drivers like "QCOM thermal sensors", "QCOM cpr driver",
"begal bone cape manager" and few more on the way.

Greg KH,
 Is it possible to take these patches via your tree Or do you think it
 should go via ARM-SOC tree?

Up until now, NVMEM drivers like eeprom 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.
    
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 NVMEMs.
    
After learning few things about QCOM qfprom and other eeprom/efuses, which
has packed fields at bit level. Which makes it important to add support to
such memories. This version adds support to this type of non volatile
memories by adding support to bit level nvmem-cells.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

patch 1-4 Introduces the NVMEM framework.
Patch 5-6 Adds Qualcomm specific qfprom driver.
Patch 7 migrates an existing driver to nvmem framework.
Patch 8 adds entry in MAINTAINERS.

Its also possible to migrate other nvmem drivers to this framework.

Providers APIs:
	nvmem_register/unregister();

Consumers APIs:
Cell based apis for both DT/Non-DT:
	nvmem_cell_get()/nvmem_cell_put();
	devm_nvmem_cell_get()/devm_nvmem_cell_put();
	of_nvmem_cell_get()
	nvmem_cell_read()/nvmem_cell_write();

Raw byte access apis for both DT/non-DT.
	nvmem_device_get()/nvmem_device_put()
	devm_nvmem_device_get()/nvmem_device_put()
	of_nvmem_device_get()

	nvmem_device_read()/nvmem_device_write();
	nvmem_device_cell_read()/nvmem_device_cell_write();

Device Tree:

	/* Provider */
	qfprom: qfprom@00700000 {
		...

		/* Data cells */
		tsens_calibration: calib@404 {
			reg = <0x404 0x10>;
		};

		tsens_calibration_bckp: calib_bckp@504 {
			reg = <0x504 0x11>;
			bit-offset = 6;
			nbits = 128;
		};

		pvs_version: pvs-version@6 {
			reg = <0x6 0x2>
			bit-offset = 7;
			nbits = 2;
		};

		speed_bin: speed-bin@c{
			reg = <0xc 0x1>;
			bit-offset = 2;
			nbits	= 3;

		};
		...
	};

userspace interface: binary file in /sys/class/nvmem/*/nvmem

ex:
hexdump /sys/class/nvmem/qfprom0/nvmem
                                                                                                                                                                                                                  
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
0000000 0000 0000 0000 0000 0000 0000 0000 0000
...
*
0001000

Changes since v5(https://lkml.org/lkml/2015/5/21/643)
 * skipped regmap patches which are already merged by Mark.
 * Fixed lot of style related comments by Stephen.
 * Fixed sunxi driver.
 * added devm_* variants requested by Stephen.
 * added of_* variants requested by Pantelis Antoniou
 * added read_only options for non-dt drivers.
 * added basic how-to doc.

Changes since v4(https://lkml.org/lkml/2015/3/30/725)
 * rename eeprom to nvmem suggested by Matt Porter
 * added bit level support to nvmem cells, if not framework is
 	not usable for qcom platforms.
 * removed ternary operator shortcut suggested by Mark B.
 * unified consumer/provider apis for both DT and non-DT.
 * added name support for cell.
 * added bit level bindings.
 * added read-only support suggested by Matt Porter and others.
 * added new nvmem_device based consumer apis.

Changes since v3(https://lkml.org/lkml/2015/3/24/1066)
 * simplified logic in bin_attr_eeprom_read/write spotted by Mark Brown.
 * moved from using regmap_bulk_read/write to regmap_raw_read/write
 spotted by Mark Brown
 * Fixed return error codes for the dummy wrappers spotted by Sascha Hauer
 * Fixed various error code checks in core spotted by Sascha Hauer.
 * Simplified consumer bindings suggested by Sascha Hauer.
 * Added eeprom-mmio helper functions.

Changes since v2(https://lkml.org/lkml/2015/3/13/168)
 * Fixed error handling in eeprom_register spotted by Mark Brown
 * Added new regmap_get_max_register() and regmap_get_reg_stride().
 * Fixed module build errors reported by kbuild robot.
 * recycle the ids when eeprom provider is released.

Changes since v1(https://lkml.org/lkml/2015/3/5/153)
 * Fix various Licencing issues spotted by Paul Bolle and Mark Brown
 * Allow eeprom core to build as module spotted by Paul Bolle.
 * Fix various kconfig issues spotted by Paul Bolle.
 * remove unessary atomic varible spotted by Mark Brown.
 * Few cleanups and common up some of the code in core.
 * Add qfprom bindings.

Changes since RFC(https://lkml.org/lkml/2015/2/19/307)
 * Fix documentation and error checks in read/write spotted by Andrew Lunn
 * Kconfig fix suggested by Stephen Boyd.
 * Add module owner suggested by Stephen Boyd and others.
 * Fix unsafe handling of eeprom in unregister spotted by Russell and Mark Brown.
 * seperate bindings patch as suggested by Rob.
 * Add MAINTAINERS as suggested by Rob.
 * Added support to allow reading eeprom for things like serial number which
 * canbe scatters across.
 * Added eeprom data using reg property suggested by Sascha and Stephen.
 * Added non-DT support.
 * Move kerneldoc to the src files spotted by Mark Brown.
 * Remove local list and do eeprom lookup by using class_find_device()


Thanks,
srini

Maxime Ripard (1):
  nvmem: sunxi: Move the SID driver to the nvmem framework

Srinivas Kandagatla (8):
  nvmem: Add a simple NVMEM framework for nvmem providers
  nvmem: Add a simple NVMEM framework for consumers
  nvmem: Add nvmem_device based consumer apis.
  nvmem: Add bindings for simple nvmem framework
  Documentation: nvmem: add nvmem api level and how-to doc
  nvmem: qfprom: Add Qualcomm QFPROM support.
  nvmem: qfprom: Add bindings for qfprom
  nvmem: Add to MAINTAINERS for nvmem framework

 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |   22 -
 .../bindings/misc/allwinner,sunxi-sid.txt          |   17 -
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |   21 +
 Documentation/devicetree/bindings/nvmem/nvmem.txt  |   85 ++
 Documentation/devicetree/bindings/nvmem/qfprom.txt |   35 +
 Documentation/nvmem/nvmem.txt                      |  151 +++
 MAINTAINERS                                        |    9 +
 drivers/Kconfig                                    |    2 +
 drivers/Makefile                                   |    1 +
 drivers/misc/eeprom/Kconfig                        |   13 -
 drivers/misc/eeprom/Makefile                       |    1 -
 drivers/misc/eeprom/sunxi_sid.c                    |  156 ---
 drivers/nvmem/Kconfig                              |   36 +
 drivers/nvmem/Makefile                             |   12 +
 drivers/nvmem/core.c                               | 1069 ++++++++++++++++++++
 drivers/nvmem/qfprom.c                             |   89 ++
 drivers/nvmem/sunxi-sid.c                          |  160 +++
 include/linux/nvmem-consumer.h                     |  154 +++
 include/linux/nvmem-provider.h                     |   48 +
 19 files changed, 1872 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt
 create mode 100644 Documentation/nvmem/nvmem.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 drivers/nvmem/qfprom.c
 create mode 100644 drivers/nvmem/sunxi-sid.c
 create mode 100644 include/linux/nvmem-consumer.h
 create mode 100644 include/linux/nvmem-provider.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-22 23:07 ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:07 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

Thankyou all for providing inputs and comments on previous versions of this
patchset. Here is the v6 of the patchset addressing all the issues raised as
part of previous versions review.

This patchset adds a new simple NVMEM framework to kernel, and it is tested
with various drivers like "QCOM thermal sensors", "QCOM cpr driver",
"begal bone cape manager" and few more on the way.

Greg KH,
 Is it possible to take these patches via your tree Or do you think it
 should go via ARM-SOC tree?

Up until now, NVMEM drivers like eeprom 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.
    
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 NVMEMs.
    
After learning few things about QCOM qfprom and other eeprom/efuses, which
has packed fields at bit level. Which makes it important to add support to
such memories. This version adds support to this type of non volatile
memories by adding support to bit level nvmem-cells.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

patch 1-4 Introduces the NVMEM framework.
Patch 5-6 Adds Qualcomm specific qfprom driver.
Patch 7 migrates an existing driver to nvmem framework.
Patch 8 adds entry in MAINTAINERS.

Its also possible to migrate other nvmem drivers to this framework.

Providers APIs:
	nvmem_register/unregister();

Consumers APIs:
Cell based apis for both DT/Non-DT:
	nvmem_cell_get()/nvmem_cell_put();
	devm_nvmem_cell_get()/devm_nvmem_cell_put();
	of_nvmem_cell_get()
	nvmem_cell_read()/nvmem_cell_write();

Raw byte access apis for both DT/non-DT.
	nvmem_device_get()/nvmem_device_put()
	devm_nvmem_device_get()/nvmem_device_put()
	of_nvmem_device_get()

	nvmem_device_read()/nvmem_device_write();
	nvmem_device_cell_read()/nvmem_device_cell_write();

Device Tree:

	/* Provider */
	qfprom: qfprom@00700000 {
		...

		/* Data cells */
		tsens_calibration: calib@404 {
			reg = <0x404 0x10>;
		};

		tsens_calibration_bckp: calib_bckp@504 {
			reg = <0x504 0x11>;
			bit-offset = 6;
			nbits = 128;
		};

		pvs_version: pvs-version@6 {
			reg = <0x6 0x2>
			bit-offset = 7;
			nbits = 2;
		};

		speed_bin: speed-bin@c{
			reg = <0xc 0x1>;
			bit-offset = 2;
			nbits	= 3;

		};
		...
	};

userspace interface: binary file in /sys/class/nvmem/*/nvmem

ex:
hexdump /sys/class/nvmem/qfprom0/nvmem
                                                                                                                                                                                                                  
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
0000000 0000 0000 0000 0000 0000 0000 0000 0000
...
*
0001000

Changes since v5(https://lkml.org/lkml/2015/5/21/643)
 * skipped regmap patches which are already merged by Mark.
 * Fixed lot of style related comments by Stephen.
 * Fixed sunxi driver.
 * added devm_* variants requested by Stephen.
 * added of_* variants requested by Pantelis Antoniou
 * added read_only options for non-dt drivers.
 * added basic how-to doc.

Changes since v4(https://lkml.org/lkml/2015/3/30/725)
 * rename eeprom to nvmem suggested by Matt Porter
 * added bit level support to nvmem cells, if not framework is
 	not usable for qcom platforms.
 * removed ternary operator shortcut suggested by Mark B.
 * unified consumer/provider apis for both DT and non-DT.
 * added name support for cell.
 * added bit level bindings.
 * added read-only support suggested by Matt Porter and others.
 * added new nvmem_device based consumer apis.

Changes since v3(https://lkml.org/lkml/2015/3/24/1066)
 * simplified logic in bin_attr_eeprom_read/write spotted by Mark Brown.
 * moved from using regmap_bulk_read/write to regmap_raw_read/write
 spotted by Mark Brown
 * Fixed return error codes for the dummy wrappers spotted by Sascha Hauer
 * Fixed various error code checks in core spotted by Sascha Hauer.
 * Simplified consumer bindings suggested by Sascha Hauer.
 * Added eeprom-mmio helper functions.

Changes since v2(https://lkml.org/lkml/2015/3/13/168)
 * Fixed error handling in eeprom_register spotted by Mark Brown
 * Added new regmap_get_max_register() and regmap_get_reg_stride().
 * Fixed module build errors reported by kbuild robot.
 * recycle the ids when eeprom provider is released.

Changes since v1(https://lkml.org/lkml/2015/3/5/153)
 * Fix various Licencing issues spotted by Paul Bolle and Mark Brown
 * Allow eeprom core to build as module spotted by Paul Bolle.
 * Fix various kconfig issues spotted by Paul Bolle.
 * remove unessary atomic varible spotted by Mark Brown.
 * Few cleanups and common up some of the code in core.
 * Add qfprom bindings.

Changes since RFC(https://lkml.org/lkml/2015/2/19/307)
 * Fix documentation and error checks in read/write spotted by Andrew Lunn
 * Kconfig fix suggested by Stephen Boyd.
 * Add module owner suggested by Stephen Boyd and others.
 * Fix unsafe handling of eeprom in unregister spotted by Russell and Mark Brown.
 * seperate bindings patch as suggested by Rob.
 * Add MAINTAINERS as suggested by Rob.
 * Added support to allow reading eeprom for things like serial number which
 * canbe scatters across.
 * Added eeprom data using reg property suggested by Sascha and Stephen.
 * Added non-DT support.
 * Move kerneldoc to the src files spotted by Mark Brown.
 * Remove local list and do eeprom lookup by using class_find_device()


Thanks,
srini

Maxime Ripard (1):
  nvmem: sunxi: Move the SID driver to the nvmem framework

Srinivas Kandagatla (8):
  nvmem: Add a simple NVMEM framework for nvmem providers
  nvmem: Add a simple NVMEM framework for consumers
  nvmem: Add nvmem_device based consumer apis.
  nvmem: Add bindings for simple nvmem framework
  Documentation: nvmem: add nvmem api level and how-to doc
  nvmem: qfprom: Add Qualcomm QFPROM support.
  nvmem: qfprom: Add bindings for qfprom
  nvmem: Add to MAINTAINERS for nvmem framework

 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |   22 -
 .../bindings/misc/allwinner,sunxi-sid.txt          |   17 -
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |   21 +
 Documentation/devicetree/bindings/nvmem/nvmem.txt  |   85 ++
 Documentation/devicetree/bindings/nvmem/qfprom.txt |   35 +
 Documentation/nvmem/nvmem.txt                      |  151 +++
 MAINTAINERS                                        |    9 +
 drivers/Kconfig                                    |    2 +
 drivers/Makefile                                   |    1 +
 drivers/misc/eeprom/Kconfig                        |   13 -
 drivers/misc/eeprom/Makefile                       |    1 -
 drivers/misc/eeprom/sunxi_sid.c                    |  156 ---
 drivers/nvmem/Kconfig                              |   36 +
 drivers/nvmem/Makefile                             |   12 +
 drivers/nvmem/core.c                               | 1069 ++++++++++++++++++++
 drivers/nvmem/qfprom.c                             |   89 ++
 drivers/nvmem/sunxi-sid.c                          |  160 +++
 include/linux/nvmem-consumer.h                     |  154 +++
 include/linux/nvmem-provider.h                     |   48 +
 19 files changed, 1872 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt
 create mode 100644 Documentation/nvmem/nvmem.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 drivers/nvmem/qfprom.c
 create mode 100644 drivers/nvmem/sunxi-sid.c
 create mode 100644 include/linux/nvmem-consumer.h
 create mode 100644 include/linux/nvmem-provider.h

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-22 23:07 ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:07 UTC (permalink / raw)
  To: linux-arm-kernel

Thankyou all for providing inputs and comments on previous versions of this
patchset. Here is the v6 of the patchset addressing all the issues raised as
part of previous versions review.

This patchset adds a new simple NVMEM framework to kernel, and it is tested
with various drivers like "QCOM thermal sensors", "QCOM cpr driver",
"begal bone cape manager" and few more on the way.

Greg KH,
 Is it possible to take these patches via your tree Or do you think it
 should go via ARM-SOC tree?

Up until now, NVMEM drivers like eeprom 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.
    
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 NVMEMs.
    
After learning few things about QCOM qfprom and other eeprom/efuses, which
has packed fields at bit level. Which makes it important to add support to
such memories. This version adds support to this type of non volatile
memories by adding support to bit level nvmem-cells.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

patch 1-4 Introduces the NVMEM framework.
Patch 5-6 Adds Qualcomm specific qfprom driver.
Patch 7 migrates an existing driver to nvmem framework.
Patch 8 adds entry in MAINTAINERS.

Its also possible to migrate other nvmem drivers to this framework.

Providers APIs:
	nvmem_register/unregister();

Consumers APIs:
Cell based apis for both DT/Non-DT:
	nvmem_cell_get()/nvmem_cell_put();
	devm_nvmem_cell_get()/devm_nvmem_cell_put();
	of_nvmem_cell_get()
	nvmem_cell_read()/nvmem_cell_write();

Raw byte access apis for both DT/non-DT.
	nvmem_device_get()/nvmem_device_put()
	devm_nvmem_device_get()/nvmem_device_put()
	of_nvmem_device_get()

	nvmem_device_read()/nvmem_device_write();
	nvmem_device_cell_read()/nvmem_device_cell_write();

Device Tree:

	/* Provider */
	qfprom: qfprom at 00700000 {
		...

		/* Data cells */
		tsens_calibration: calib at 404 {
			reg = <0x404 0x10>;
		};

		tsens_calibration_bckp: calib_bckp at 504 {
			reg = <0x504 0x11>;
			bit-offset = 6;
			nbits = 128;
		};

		pvs_version: pvs-version at 6 {
			reg = <0x6 0x2>
			bit-offset = 7;
			nbits = 2;
		};

		speed_bin: speed-bin at c{
			reg = <0xc 0x1>;
			bit-offset = 2;
			nbits	= 3;

		};
		...
	};

userspace interface: binary file in /sys/class/nvmem/*/nvmem

ex:
hexdump /sys/class/nvmem/qfprom0/nvmem
                                                                                                                                                                                                                  
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
0000000 0000 0000 0000 0000 0000 0000 0000 0000
...
*
0001000

Changes since v5(https://lkml.org/lkml/2015/5/21/643)
 * skipped regmap patches which are already merged by Mark.
 * Fixed lot of style related comments by Stephen.
 * Fixed sunxi driver.
 * added devm_* variants requested by Stephen.
 * added of_* variants requested by Pantelis Antoniou
 * added read_only options for non-dt drivers.
 * added basic how-to doc.

Changes since v4(https://lkml.org/lkml/2015/3/30/725)
 * rename eeprom to nvmem suggested by Matt Porter
 * added bit level support to nvmem cells, if not framework is
 	not usable for qcom platforms.
 * removed ternary operator shortcut suggested by Mark B.
 * unified consumer/provider apis for both DT and non-DT.
 * added name support for cell.
 * added bit level bindings.
 * added read-only support suggested by Matt Porter and others.
 * added new nvmem_device based consumer apis.

Changes since v3(https://lkml.org/lkml/2015/3/24/1066)
 * simplified logic in bin_attr_eeprom_read/write spotted by Mark Brown.
 * moved from using regmap_bulk_read/write to regmap_raw_read/write
 spotted by Mark Brown
 * Fixed return error codes for the dummy wrappers spotted by Sascha Hauer
 * Fixed various error code checks in core spotted by Sascha Hauer.
 * Simplified consumer bindings suggested by Sascha Hauer.
 * Added eeprom-mmio helper functions.

Changes since v2(https://lkml.org/lkml/2015/3/13/168)
 * Fixed error handling in eeprom_register spotted by Mark Brown
 * Added new regmap_get_max_register() and regmap_get_reg_stride().
 * Fixed module build errors reported by kbuild robot.
 * recycle the ids when eeprom provider is released.

Changes since v1(https://lkml.org/lkml/2015/3/5/153)
 * Fix various Licencing issues spotted by Paul Bolle and Mark Brown
 * Allow eeprom core to build as module spotted by Paul Bolle.
 * Fix various kconfig issues spotted by Paul Bolle.
 * remove unessary atomic varible spotted by Mark Brown.
 * Few cleanups and common up some of the code in core.
 * Add qfprom bindings.

Changes since RFC(https://lkml.org/lkml/2015/2/19/307)
 * Fix documentation and error checks in read/write spotted by Andrew Lunn
 * Kconfig fix suggested by Stephen Boyd.
 * Add module owner suggested by Stephen Boyd and others.
 * Fix unsafe handling of eeprom in unregister spotted by Russell and Mark Brown.
 * seperate bindings patch as suggested by Rob.
 * Add MAINTAINERS as suggested by Rob.
 * Added support to allow reading eeprom for things like serial number which
 * canbe scatters across.
 * Added eeprom data using reg property suggested by Sascha and Stephen.
 * Added non-DT support.
 * Move kerneldoc to the src files spotted by Mark Brown.
 * Remove local list and do eeprom lookup by using class_find_device()


Thanks,
srini

Maxime Ripard (1):
  nvmem: sunxi: Move the SID driver to the nvmem framework

Srinivas Kandagatla (8):
  nvmem: Add a simple NVMEM framework for nvmem providers
  nvmem: Add a simple NVMEM framework for consumers
  nvmem: Add nvmem_device based consumer apis.
  nvmem: Add bindings for simple nvmem framework
  Documentation: nvmem: add nvmem api level and how-to doc
  nvmem: qfprom: Add Qualcomm QFPROM support.
  nvmem: qfprom: Add bindings for qfprom
  nvmem: Add to MAINTAINERS for nvmem framework

 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |   22 -
 .../bindings/misc/allwinner,sunxi-sid.txt          |   17 -
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |   21 +
 Documentation/devicetree/bindings/nvmem/nvmem.txt  |   85 ++
 Documentation/devicetree/bindings/nvmem/qfprom.txt |   35 +
 Documentation/nvmem/nvmem.txt                      |  151 +++
 MAINTAINERS                                        |    9 +
 drivers/Kconfig                                    |    2 +
 drivers/Makefile                                   |    1 +
 drivers/misc/eeprom/Kconfig                        |   13 -
 drivers/misc/eeprom/Makefile                       |    1 -
 drivers/misc/eeprom/sunxi_sid.c                    |  156 ---
 drivers/nvmem/Kconfig                              |   36 +
 drivers/nvmem/Makefile                             |   12 +
 drivers/nvmem/core.c                               | 1069 ++++++++++++++++++++
 drivers/nvmem/qfprom.c                             |   89 ++
 drivers/nvmem/sunxi-sid.c                          |  160 +++
 include/linux/nvmem-consumer.h                     |  154 +++
 include/linux/nvmem-provider.h                     |   48 +
 19 files changed, 1872 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt
 create mode 100644 Documentation/nvmem/nvmem.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 drivers/nvmem/qfprom.c
 create mode 100644 drivers/nvmem/sunxi-sid.c
 create mode 100644 include/linux/nvmem-consumer.h
 create mode 100644 include/linux/nvmem-provider.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw, Srinivas Kandagatla

This patch adds just providers part of the framework just to enable easy
review.

Up until now, NVMEM drivers like eeprom 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/Kconfig                |   2 +
 drivers/Makefile               |   1 +
 drivers/nvmem/Kconfig          |  10 ++
 drivers/nvmem/Makefile         |   6 +
 drivers/nvmem/core.c           | 398 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-provider.h |  54 ++++++
 6 files changed, 471 insertions(+)
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 include/linux/nvmem-provider.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c0cc96b..69d7305 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -182,4 +182,6 @@ source "drivers/thunderbolt/Kconfig"
 
 source "drivers/android/Kconfig"
 
+source "drivers/nvmem/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 46d2554..f86b897 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,4 @@ obj-$(CONFIG_RAS)		+= ras/
 obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
 obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
 obj-$(CONFIG_ANDROID)		+= android/
+obj-$(CONFIG_NVMEM)		+= nvmem/
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
new file mode 100644
index 0000000..f157b6d
--- /dev/null
+++ b/drivers/nvmem/Kconfig
@@ -0,0 +1,10 @@
+menuconfig NVMEM
+	tristate "NVMEM Support"
+	select REGMAP
+	help
+	  Support for NVMEM devices.
+
+	  This framework is designed to provide a generic interface to NVMEM
+	  from both the Linux Kernel and the userspace.
+
+	  If unsure, say no.
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
new file mode 100644
index 0000000..6df2c69
--- /dev/null
+++ b/drivers/nvmem/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for nvmem drivers.
+#
+
+obj-$(CONFIG_NVMEM)		+= nvmem_core.o
+nvmem_core-y			:= core.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
new file mode 100644
index 0000000..17a826d
--- /dev/null
+++ b/drivers/nvmem/core.c
@@ -0,0 +1,398 @@
+/*
+ * nvmem framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+struct nvmem_device {
+	const char		*name;
+	struct regmap		*regmap;
+	struct module		*owner;
+	struct device		dev;
+	int			stride;
+	int			word_size;
+	int			ncells;
+	int			id;
+	int			users;
+	size_t			size;
+	bool			read_only;
+};
+
+struct nvmem_cell {
+	const char *name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+	struct nvmem_device	*nvmem;
+	struct list_head	node;
+};
+
+static DEFINE_MUTEX(nvmem_mutex);
+static DEFINE_IDA(nvmem_ida);
+
+static LIST_HEAD(nvmem_cells);
+static DEFINE_MUTEX(nvmem_cells_mutex);
+
+#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+				    struct bin_attribute *attr,
+				    char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from reading */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from writing */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+/* default read/write permissions */
+static struct bin_attribute bin_attr_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IWUSR | S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+	.write	= bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_attributes[] = {
+	&bin_attr_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_group = {
+	.bin_attrs	= nvmem_bin_attributes,
+};
+
+static const struct attribute_group *nvmem_dev_groups[] = {
+	&nvmem_bin_group,
+	NULL,
+};
+
+/* read only permission */
+static struct bin_attribute bin_attr_ro_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_attributes[] = {
+	&bin_attr_ro_nvmem,
+	NULL,
+};
+static const struct attribute_group nvmem_bin_ro_group = {
+	.bin_attrs	= nvmem_bin_ro_attributes,
+};
+
+static void nvmem_release(struct device *dev)
+{
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+	ida_simple_remove(&nvmem_ida, nvmem->id);
+	kfree(nvmem);
+}
+
+static struct class nvmem_class = {
+	.name		= "nvmem",
+	.dev_groups	= nvmem_dev_groups,
+	.dev_release	= nvmem_release,
+};
+
+static int of_nvmem_match(struct device *dev, const void *nvmem_np)
+{
+	return dev->of_node == nvmem_np;
+}
+
+static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+{
+	struct device *d;
+
+	if (!nvmem_np)
+		return NULL;
+
+	d = class_find_device(&nvmem_class, NULL, nvmem_np, of_nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
+{
+	struct nvmem_cell *p;
+
+	list_for_each_entry(p, &nvmem_cells, node)
+		if (p && !strcmp(p->name, cell_id))
+			return p;
+
+	return NULL;
+}
+
+static void nvmem_cell_drop(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_del(&cell->node);
+	mutex_unlock(&nvmem_cells_mutex);
+	kfree(cell);
+}
+
+static void nvmem_device_remove_all_cells(struct nvmem_device *nvmem)
+{
+	struct nvmem_cell *cell;
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &nvmem_cells) {
+		cell = list_entry(p, struct nvmem_cell, node);
+		if (cell->nvmem == nvmem)
+			nvmem_cell_drop(cell);
+	}
+}
+
+static void nvmem_cell_add(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_add_tail(&cell->node, &nvmem_cells);
+	mutex_unlock(&nvmem_cells_mutex);
+}
+
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+				   struct nvmem_cell_info *info,
+				   struct nvmem_cell *cell)
+{
+	cell->nvmem = nvmem;
+	cell->offset = info->offset;
+	cell->bytes = info->bytes;
+	cell->name = info->name;
+
+	cell->bit_offset = info->bit_offset;
+	cell->nbits = info->nbits;
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+		dev_err(&nvmem->dev,
+			"cell %s unaligned to nvmem stride %d\n",
+			cell->name, nvmem->stride);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int nvmem_add_cells(struct nvmem_device *nvmem,
+			   struct nvmem_config *cfg)
+{
+	struct nvmem_cell **cells;
+	struct nvmem_cell_info *info = cfg->cells;
+	int i, rval;
+
+	cells = kzalloc(sizeof(*cells) * cfg->ncells, GFP_KERNEL);
+	if (!cells)
+		return -ENOMEM;
+
+	for (i = 0; i < cfg->ncells; i++) {
+		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
+		if (!cells[i]) {
+			rval = -ENOMEM;
+			goto err;
+		}
+
+		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
+		if (IS_ERR_VALUE(rval)) {
+			kfree(cells[i]);
+			goto err;
+		}
+
+		nvmem_cell_add(cells[i]);
+	}
+
+	nvmem->ncells = cfg->ncells;
+	/* remove tmp array */
+	kfree(cells);
+
+	return 0;
+err:
+	while (--i)
+		nvmem_cell_drop(cells[i]);
+
+	return rval;
+}
+
+/**
+ * nvmem_register() - Register a nvmem device for given nvmem_config.
+ * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to nvmem_device.
+ */
+
+struct nvmem_device *nvmem_register(struct nvmem_config *config)
+{
+	struct nvmem_device *nvmem;
+	struct regmap *rm;
+	int rval;
+
+	if (!config->dev)
+		return ERR_PTR(-EINVAL);
+
+	rm = dev_get_regmap(config->dev, NULL);
+	if (!rm) {
+		dev_err(config->dev, "Regmap not found\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
+	if (!nvmem)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
+	if (nvmem->id < 0) {
+		kfree(nvmem);
+		return ERR_PTR(nvmem->id);
+	}
+
+	nvmem->regmap = rm;
+	nvmem->owner = config->owner;
+	nvmem->stride = regmap_get_reg_stride(rm);
+	nvmem->word_size = regmap_get_val_bytes(rm);
+	nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+	nvmem->dev.class = &nvmem_class;
+	nvmem->dev.parent = config->dev;
+	nvmem->dev.of_node = config->dev->of_node;
+	dev_set_name(&nvmem->dev, "%s%d",
+		     config->name ? : "nvmem", config->id);
+
+	nvmem->read_only = nvmem->dev.of_node ?
+				of_property_read_bool(nvmem->dev.of_node,
+				"read-only") :
+				config->read_only;
+
+	device_initialize(&nvmem->dev);
+
+	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
+		dev_name(&nvmem->dev));
+
+	rval = device_add(&nvmem->dev);
+	if (rval) {
+		ida_simple_remove(&nvmem_ida, nvmem->id);
+		kfree(nvmem);
+		return ERR_PTR(rval);
+	}
+
+	/* update sysfs attributes */
+	if (nvmem->read_only)
+		sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
+
+	if (config->cells)
+		nvmem_add_cells(nvmem, config);
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(nvmem_register);
+
+/**
+ * nvmem_unregister() - Unregister previously registered nvmem device
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * The return value will be an non zero on error or a zero on success.
+ */
+int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	mutex_lock(&nvmem_mutex);
+	if (nvmem->users) {
+		mutex_unlock(&nvmem_mutex);
+		return -EBUSY;
+	}
+	mutex_unlock(&nvmem_mutex);
+
+	nvmem_device_remove_all_cells(nvmem);
+	device_del(&nvmem->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+static int __init nvmem_init(void)
+{
+	return class_register(&nvmem_class);
+}
+
+static void __exit nvmem_exit(void)
+{
+	class_unregister(&nvmem_class);
+}
+
+subsys_initcall(nvmem_init);
+module_exit(nvmem_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org");
+MODULE_DESCRIPTION("nvmem Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
new file mode 100644
index 0000000..f589d3b
--- /dev/null
+++ b/include/linux/nvmem-provider.h
@@ -0,0 +1,54 @@
+/*
+ * nvmem framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_PROVIDER_H
+#define _LINUX_NVMEM_PROVIDER_H
+
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
+
+struct nvmem_config {
+	struct device		*dev;
+	const char		*name;
+	int			id;
+	struct module		*owner;
+	struct nvmem_cell_info	*cells;
+	int			ncells;
+	bool			read_only;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+struct nvmem_device *nvmem_register(struct nvmem_config *cfg);
+int nvmem_unregister(struct nvmem_device *nvmem);
+
+#else
+
+static inline struct nvmem_device *nvmem_register(struct nvmem_config *cfg)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds just providers part of the framework just to enable easy
review.

Up until now, NVMEM drivers like eeprom 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/Kconfig                |   2 +
 drivers/Makefile               |   1 +
 drivers/nvmem/Kconfig          |  10 ++
 drivers/nvmem/Makefile         |   6 +
 drivers/nvmem/core.c           | 398 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-provider.h |  54 ++++++
 6 files changed, 471 insertions(+)
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 include/linux/nvmem-provider.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c0cc96b..69d7305 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -182,4 +182,6 @@ source "drivers/thunderbolt/Kconfig"
 
 source "drivers/android/Kconfig"
 
+source "drivers/nvmem/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 46d2554..f86b897 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,4 @@ obj-$(CONFIG_RAS)		+= ras/
 obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
 obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
 obj-$(CONFIG_ANDROID)		+= android/
+obj-$(CONFIG_NVMEM)		+= nvmem/
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
new file mode 100644
index 0000000..f157b6d
--- /dev/null
+++ b/drivers/nvmem/Kconfig
@@ -0,0 +1,10 @@
+menuconfig NVMEM
+	tristate "NVMEM Support"
+	select REGMAP
+	help
+	  Support for NVMEM devices.
+
+	  This framework is designed to provide a generic interface to NVMEM
+	  from both the Linux Kernel and the userspace.
+
+	  If unsure, say no.
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
new file mode 100644
index 0000000..6df2c69
--- /dev/null
+++ b/drivers/nvmem/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for nvmem drivers.
+#
+
+obj-$(CONFIG_NVMEM)		+= nvmem_core.o
+nvmem_core-y			:= core.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
new file mode 100644
index 0000000..17a826d
--- /dev/null
+++ b/drivers/nvmem/core.c
@@ -0,0 +1,398 @@
+/*
+ * nvmem framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+struct nvmem_device {
+	const char		*name;
+	struct regmap		*regmap;
+	struct module		*owner;
+	struct device		dev;
+	int			stride;
+	int			word_size;
+	int			ncells;
+	int			id;
+	int			users;
+	size_t			size;
+	bool			read_only;
+};
+
+struct nvmem_cell {
+	const char *name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+	struct nvmem_device	*nvmem;
+	struct list_head	node;
+};
+
+static DEFINE_MUTEX(nvmem_mutex);
+static DEFINE_IDA(nvmem_ida);
+
+static LIST_HEAD(nvmem_cells);
+static DEFINE_MUTEX(nvmem_cells_mutex);
+
+#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+				    struct bin_attribute *attr,
+				    char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from reading */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from writing */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+/* default read/write permissions */
+static struct bin_attribute bin_attr_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IWUSR | S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+	.write	= bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_attributes[] = {
+	&bin_attr_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_group = {
+	.bin_attrs	= nvmem_bin_attributes,
+};
+
+static const struct attribute_group *nvmem_dev_groups[] = {
+	&nvmem_bin_group,
+	NULL,
+};
+
+/* read only permission */
+static struct bin_attribute bin_attr_ro_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_attributes[] = {
+	&bin_attr_ro_nvmem,
+	NULL,
+};
+static const struct attribute_group nvmem_bin_ro_group = {
+	.bin_attrs	= nvmem_bin_ro_attributes,
+};
+
+static void nvmem_release(struct device *dev)
+{
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+	ida_simple_remove(&nvmem_ida, nvmem->id);
+	kfree(nvmem);
+}
+
+static struct class nvmem_class = {
+	.name		= "nvmem",
+	.dev_groups	= nvmem_dev_groups,
+	.dev_release	= nvmem_release,
+};
+
+static int of_nvmem_match(struct device *dev, const void *nvmem_np)
+{
+	return dev->of_node == nvmem_np;
+}
+
+static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+{
+	struct device *d;
+
+	if (!nvmem_np)
+		return NULL;
+
+	d = class_find_device(&nvmem_class, NULL, nvmem_np, of_nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
+{
+	struct nvmem_cell *p;
+
+	list_for_each_entry(p, &nvmem_cells, node)
+		if (p && !strcmp(p->name, cell_id))
+			return p;
+
+	return NULL;
+}
+
+static void nvmem_cell_drop(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_del(&cell->node);
+	mutex_unlock(&nvmem_cells_mutex);
+	kfree(cell);
+}
+
+static void nvmem_device_remove_all_cells(struct nvmem_device *nvmem)
+{
+	struct nvmem_cell *cell;
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &nvmem_cells) {
+		cell = list_entry(p, struct nvmem_cell, node);
+		if (cell->nvmem == nvmem)
+			nvmem_cell_drop(cell);
+	}
+}
+
+static void nvmem_cell_add(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_add_tail(&cell->node, &nvmem_cells);
+	mutex_unlock(&nvmem_cells_mutex);
+}
+
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+				   struct nvmem_cell_info *info,
+				   struct nvmem_cell *cell)
+{
+	cell->nvmem = nvmem;
+	cell->offset = info->offset;
+	cell->bytes = info->bytes;
+	cell->name = info->name;
+
+	cell->bit_offset = info->bit_offset;
+	cell->nbits = info->nbits;
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+		dev_err(&nvmem->dev,
+			"cell %s unaligned to nvmem stride %d\n",
+			cell->name, nvmem->stride);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int nvmem_add_cells(struct nvmem_device *nvmem,
+			   struct nvmem_config *cfg)
+{
+	struct nvmem_cell **cells;
+	struct nvmem_cell_info *info = cfg->cells;
+	int i, rval;
+
+	cells = kzalloc(sizeof(*cells) * cfg->ncells, GFP_KERNEL);
+	if (!cells)
+		return -ENOMEM;
+
+	for (i = 0; i < cfg->ncells; i++) {
+		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
+		if (!cells[i]) {
+			rval = -ENOMEM;
+			goto err;
+		}
+
+		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
+		if (IS_ERR_VALUE(rval)) {
+			kfree(cells[i]);
+			goto err;
+		}
+
+		nvmem_cell_add(cells[i]);
+	}
+
+	nvmem->ncells = cfg->ncells;
+	/* remove tmp array */
+	kfree(cells);
+
+	return 0;
+err:
+	while (--i)
+		nvmem_cell_drop(cells[i]);
+
+	return rval;
+}
+
+/**
+ * nvmem_register() - Register a nvmem device for given nvmem_config.
+ * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to nvmem_device.
+ */
+
+struct nvmem_device *nvmem_register(struct nvmem_config *config)
+{
+	struct nvmem_device *nvmem;
+	struct regmap *rm;
+	int rval;
+
+	if (!config->dev)
+		return ERR_PTR(-EINVAL);
+
+	rm = dev_get_regmap(config->dev, NULL);
+	if (!rm) {
+		dev_err(config->dev, "Regmap not found\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
+	if (!nvmem)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
+	if (nvmem->id < 0) {
+		kfree(nvmem);
+		return ERR_PTR(nvmem->id);
+	}
+
+	nvmem->regmap = rm;
+	nvmem->owner = config->owner;
+	nvmem->stride = regmap_get_reg_stride(rm);
+	nvmem->word_size = regmap_get_val_bytes(rm);
+	nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+	nvmem->dev.class = &nvmem_class;
+	nvmem->dev.parent = config->dev;
+	nvmem->dev.of_node = config->dev->of_node;
+	dev_set_name(&nvmem->dev, "%s%d",
+		     config->name ? : "nvmem", config->id);
+
+	nvmem->read_only = nvmem->dev.of_node ?
+				of_property_read_bool(nvmem->dev.of_node,
+				"read-only") :
+				config->read_only;
+
+	device_initialize(&nvmem->dev);
+
+	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
+		dev_name(&nvmem->dev));
+
+	rval = device_add(&nvmem->dev);
+	if (rval) {
+		ida_simple_remove(&nvmem_ida, nvmem->id);
+		kfree(nvmem);
+		return ERR_PTR(rval);
+	}
+
+	/* update sysfs attributes */
+	if (nvmem->read_only)
+		sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
+
+	if (config->cells)
+		nvmem_add_cells(nvmem, config);
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(nvmem_register);
+
+/**
+ * nvmem_unregister() - Unregister previously registered nvmem device
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * The return value will be an non zero on error or a zero on success.
+ */
+int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	mutex_lock(&nvmem_mutex);
+	if (nvmem->users) {
+		mutex_unlock(&nvmem_mutex);
+		return -EBUSY;
+	}
+	mutex_unlock(&nvmem_mutex);
+
+	nvmem_device_remove_all_cells(nvmem);
+	device_del(&nvmem->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+static int __init nvmem_init(void)
+{
+	return class_register(&nvmem_class);
+}
+
+static void __exit nvmem_exit(void)
+{
+	class_unregister(&nvmem_class);
+}
+
+subsys_initcall(nvmem_init);
+module_exit(nvmem_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("nvmem Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
new file mode 100644
index 0000000..f589d3b
--- /dev/null
+++ b/include/linux/nvmem-provider.h
@@ -0,0 +1,54 @@
+/*
+ * nvmem framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_PROVIDER_H
+#define _LINUX_NVMEM_PROVIDER_H
+
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
+
+struct nvmem_config {
+	struct device		*dev;
+	const char		*name;
+	int			id;
+	struct module		*owner;
+	struct nvmem_cell_info	*cells;
+	int			ncells;
+	bool			read_only;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+struct nvmem_device *nvmem_register(struct nvmem_config *cfg);
+int nvmem_unregister(struct nvmem_device *nvmem);
+
+#else
+
+static inline struct nvmem_device *nvmem_register(struct nvmem_config *cfg)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds just providers part of the framework just to enable easy
review.

Up until now, NVMEM drivers like eeprom 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/Kconfig                |   2 +
 drivers/Makefile               |   1 +
 drivers/nvmem/Kconfig          |  10 ++
 drivers/nvmem/Makefile         |   6 +
 drivers/nvmem/core.c           | 398 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-provider.h |  54 ++++++
 6 files changed, 471 insertions(+)
 create mode 100644 drivers/nvmem/Kconfig
 create mode 100644 drivers/nvmem/Makefile
 create mode 100644 drivers/nvmem/core.c
 create mode 100644 include/linux/nvmem-provider.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c0cc96b..69d7305 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -182,4 +182,6 @@ source "drivers/thunderbolt/Kconfig"
 
 source "drivers/android/Kconfig"
 
+source "drivers/nvmem/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 46d2554..f86b897 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,4 @@ obj-$(CONFIG_RAS)		+= ras/
 obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
 obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
 obj-$(CONFIG_ANDROID)		+= android/
+obj-$(CONFIG_NVMEM)		+= nvmem/
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
new file mode 100644
index 0000000..f157b6d
--- /dev/null
+++ b/drivers/nvmem/Kconfig
@@ -0,0 +1,10 @@
+menuconfig NVMEM
+	tristate "NVMEM Support"
+	select REGMAP
+	help
+	  Support for NVMEM devices.
+
+	  This framework is designed to provide a generic interface to NVMEM
+	  from both the Linux Kernel and the userspace.
+
+	  If unsure, say no.
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
new file mode 100644
index 0000000..6df2c69
--- /dev/null
+++ b/drivers/nvmem/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for nvmem drivers.
+#
+
+obj-$(CONFIG_NVMEM)		+= nvmem_core.o
+nvmem_core-y			:= core.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
new file mode 100644
index 0000000..17a826d
--- /dev/null
+++ b/drivers/nvmem/core.c
@@ -0,0 +1,398 @@
+/*
+ * nvmem framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+struct nvmem_device {
+	const char		*name;
+	struct regmap		*regmap;
+	struct module		*owner;
+	struct device		dev;
+	int			stride;
+	int			word_size;
+	int			ncells;
+	int			id;
+	int			users;
+	size_t			size;
+	bool			read_only;
+};
+
+struct nvmem_cell {
+	const char *name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+	struct nvmem_device	*nvmem;
+	struct list_head	node;
+};
+
+static DEFINE_MUTEX(nvmem_mutex);
+static DEFINE_IDA(nvmem_ida);
+
+static LIST_HEAD(nvmem_cells);
+static DEFINE_MUTEX(nvmem_cells_mutex);
+
+#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+				    struct bin_attribute *attr,
+				    char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from reading */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	int rc;
+
+	/* Stop the user from writing */
+	if (pos > nvmem->size)
+		return 0;
+
+	if (pos + count > nvmem->size)
+		count = nvmem->size - pos;
+
+	count = count/nvmem->word_size * nvmem->word_size;
+
+	rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return count;
+}
+
+/* default read/write permissions */
+static struct bin_attribute bin_attr_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IWUSR | S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+	.write	= bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_attributes[] = {
+	&bin_attr_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_group = {
+	.bin_attrs	= nvmem_bin_attributes,
+};
+
+static const struct attribute_group *nvmem_dev_groups[] = {
+	&nvmem_bin_group,
+	NULL,
+};
+
+/* read only permission */
+static struct bin_attribute bin_attr_ro_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IRUGO,
+	},
+	.read	= bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_attributes[] = {
+	&bin_attr_ro_nvmem,
+	NULL,
+};
+static const struct attribute_group nvmem_bin_ro_group = {
+	.bin_attrs	= nvmem_bin_ro_attributes,
+};
+
+static void nvmem_release(struct device *dev)
+{
+	struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+	ida_simple_remove(&nvmem_ida, nvmem->id);
+	kfree(nvmem);
+}
+
+static struct class nvmem_class = {
+	.name		= "nvmem",
+	.dev_groups	= nvmem_dev_groups,
+	.dev_release	= nvmem_release,
+};
+
+static int of_nvmem_match(struct device *dev, const void *nvmem_np)
+{
+	return dev->of_node == nvmem_np;
+}
+
+static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+{
+	struct device *d;
+
+	if (!nvmem_np)
+		return NULL;
+
+	d = class_find_device(&nvmem_class, NULL, nvmem_np, of_nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
+{
+	struct nvmem_cell *p;
+
+	list_for_each_entry(p, &nvmem_cells, node)
+		if (p && !strcmp(p->name, cell_id))
+			return p;
+
+	return NULL;
+}
+
+static void nvmem_cell_drop(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_del(&cell->node);
+	mutex_unlock(&nvmem_cells_mutex);
+	kfree(cell);
+}
+
+static void nvmem_device_remove_all_cells(struct nvmem_device *nvmem)
+{
+	struct nvmem_cell *cell;
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &nvmem_cells) {
+		cell = list_entry(p, struct nvmem_cell, node);
+		if (cell->nvmem == nvmem)
+			nvmem_cell_drop(cell);
+	}
+}
+
+static void nvmem_cell_add(struct nvmem_cell *cell)
+{
+	mutex_lock(&nvmem_cells_mutex);
+	list_add_tail(&cell->node, &nvmem_cells);
+	mutex_unlock(&nvmem_cells_mutex);
+}
+
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+				   struct nvmem_cell_info *info,
+				   struct nvmem_cell *cell)
+{
+	cell->nvmem = nvmem;
+	cell->offset = info->offset;
+	cell->bytes = info->bytes;
+	cell->name = info->name;
+
+	cell->bit_offset = info->bit_offset;
+	cell->nbits = info->nbits;
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+		dev_err(&nvmem->dev,
+			"cell %s unaligned to nvmem stride %d\n",
+			cell->name, nvmem->stride);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int nvmem_add_cells(struct nvmem_device *nvmem,
+			   struct nvmem_config *cfg)
+{
+	struct nvmem_cell **cells;
+	struct nvmem_cell_info *info = cfg->cells;
+	int i, rval;
+
+	cells = kzalloc(sizeof(*cells) * cfg->ncells, GFP_KERNEL);
+	if (!cells)
+		return -ENOMEM;
+
+	for (i = 0; i < cfg->ncells; i++) {
+		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
+		if (!cells[i]) {
+			rval = -ENOMEM;
+			goto err;
+		}
+
+		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
+		if (IS_ERR_VALUE(rval)) {
+			kfree(cells[i]);
+			goto err;
+		}
+
+		nvmem_cell_add(cells[i]);
+	}
+
+	nvmem->ncells = cfg->ncells;
+	/* remove tmp array */
+	kfree(cells);
+
+	return 0;
+err:
+	while (--i)
+		nvmem_cell_drop(cells[i]);
+
+	return rval;
+}
+
+/**
+ * nvmem_register() - Register a nvmem device for given nvmem_config.
+ * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to nvmem_device.
+ */
+
+struct nvmem_device *nvmem_register(struct nvmem_config *config)
+{
+	struct nvmem_device *nvmem;
+	struct regmap *rm;
+	int rval;
+
+	if (!config->dev)
+		return ERR_PTR(-EINVAL);
+
+	rm = dev_get_regmap(config->dev, NULL);
+	if (!rm) {
+		dev_err(config->dev, "Regmap not found\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
+	if (!nvmem)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
+	if (nvmem->id < 0) {
+		kfree(nvmem);
+		return ERR_PTR(nvmem->id);
+	}
+
+	nvmem->regmap = rm;
+	nvmem->owner = config->owner;
+	nvmem->stride = regmap_get_reg_stride(rm);
+	nvmem->word_size = regmap_get_val_bytes(rm);
+	nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+	nvmem->dev.class = &nvmem_class;
+	nvmem->dev.parent = config->dev;
+	nvmem->dev.of_node = config->dev->of_node;
+	dev_set_name(&nvmem->dev, "%s%d",
+		     config->name ? : "nvmem", config->id);
+
+	nvmem->read_only = nvmem->dev.of_node ?
+				of_property_read_bool(nvmem->dev.of_node,
+				"read-only") :
+				config->read_only;
+
+	device_initialize(&nvmem->dev);
+
+	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
+		dev_name(&nvmem->dev));
+
+	rval = device_add(&nvmem->dev);
+	if (rval) {
+		ida_simple_remove(&nvmem_ida, nvmem->id);
+		kfree(nvmem);
+		return ERR_PTR(rval);
+	}
+
+	/* update sysfs attributes */
+	if (nvmem->read_only)
+		sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
+
+	if (config->cells)
+		nvmem_add_cells(nvmem, config);
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(nvmem_register);
+
+/**
+ * nvmem_unregister() - Unregister previously registered nvmem device
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * The return value will be an non zero on error or a zero on success.
+ */
+int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	mutex_lock(&nvmem_mutex);
+	if (nvmem->users) {
+		mutex_unlock(&nvmem_mutex);
+		return -EBUSY;
+	}
+	mutex_unlock(&nvmem_mutex);
+
+	nvmem_device_remove_all_cells(nvmem);
+	device_del(&nvmem->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+static int __init nvmem_init(void)
+{
+	return class_register(&nvmem_class);
+}
+
+static void __exit nvmem_exit(void)
+{
+	class_unregister(&nvmem_class);
+}
+
+subsys_initcall(nvmem_init);
+module_exit(nvmem_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla at linaro.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard at free-electrons.com");
+MODULE_DESCRIPTION("nvmem Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
new file mode 100644
index 0000000..f589d3b
--- /dev/null
+++ b/include/linux/nvmem-provider.h
@@ -0,0 +1,54 @@
+/*
+ * nvmem framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_PROVIDER_H
+#define _LINUX_NVMEM_PROVIDER_H
+
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
+
+struct nvmem_config {
+	struct device		*dev;
+	const char		*name;
+	int			id;
+	struct module		*owner;
+	struct nvmem_cell_info	*cells;
+	int			ncells;
+	bool			read_only;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+struct nvmem_device *nvmem_register(struct nvmem_config *cfg);
+int nvmem_unregister(struct nvmem_device *nvmem);
+
+#else
+
+static inline struct nvmem_device *nvmem_register(struct nvmem_config *cfg)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_unregister(struct nvmem_device *nvmem)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw, Srinivas Kandagatla

This patch adds just consumers part of the framework just to enable easy
review.

Up until now, nvmem 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
[Maxime Ripard: intial version of the framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/nvmem/core.c           | 415 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  75 ++++++++
 2 files changed, 490 insertions(+)
 create mode 100644 include/linux/nvmem-consumer.h

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 17a826d..78cd5c8 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -16,6 +16,7 @@
 
 #include <linux/device.h>
 #include <linux/nvmem-provider.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
@@ -379,6 +380,420 @@ int nvmem_unregister(struct nvmem_device *nvmem)
 }
 EXPORT_SYMBOL_GPL(nvmem_unregister);
 
+static struct nvmem_device *__nvmem_device_get(struct device_node *np,
+					       struct nvmem_cell **cellp,
+					       const char *cell_id)
+{
+	struct nvmem_device *nvmem = NULL;
+
+	mutex_lock(&nvmem_mutex);
+
+	if (np) {
+		nvmem = of_nvmem_find(np);
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-EPROBE_DEFER);
+		}
+	} else {
+		struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+
+		if (cell) {
+			nvmem = cell->nvmem;
+			*cellp = cell;
+		}
+
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-ENOENT);
+		}
+	}
+
+	nvmem->users++;
+	mutex_unlock(&nvmem_mutex);
+
+	if (!try_module_get(nvmem->owner)) {
+		dev_err(&nvmem->dev,
+			"could not increase module refcount for cell %s\n",
+			nvmem->name);
+
+		mutex_lock(&nvmem_mutex);
+		nvmem->users--;
+		mutex_unlock(&nvmem_mutex);
+
+		return ERR_PTR(-EINVAL);
+	}
+
+	return nvmem;
+}
+
+static void __nvmem_device_put(struct nvmem_device *nvmem)
+{
+	module_put(nvmem->owner);
+	mutex_lock(&nvmem_mutex);
+	nvmem->users--;
+	mutex_unlock(&nvmem_mutex);
+}
+
+static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
+{
+	struct nvmem_cell *cell = NULL;
+	struct nvmem_device *nvmem;
+
+	nvmem = __nvmem_device_get(NULL, &cell, cell_id);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+
+	return cell;
+
+}
+/**
+ * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name from nvmem-cell-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+					    const char *name)
+{
+	struct device_node *cell_np, *nvmem_np;
+	struct nvmem_cell *cell;
+	struct nvmem_device *nvmem;
+	const __be32 *addr;
+	int rval, len, index;
+
+	index = of_property_match_string(np, "nvmem-cell-names", name);
+
+	cell_np = of_parse_phandle(np, "nvmem-cell", index);
+	if (!cell_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem_np = of_get_next_parent(cell_np);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+	addr = of_get_property(cell_np, "reg", &len);
+	if (!addr || (len < 2 * sizeof(int))) {
+		dev_err(&nvmem->dev, "nvmem: invalid reg on %s\n",
+			cell_np->full_name);
+		rval  = -EINVAL;
+		goto err_mem;
+	}
+
+	cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+	if (!cell) {
+		rval = -ENOMEM;
+		goto err_mem;
+	}
+
+	cell->nvmem = nvmem;
+	cell->offset = be32_to_cpup(addr++);
+	cell->bytes = be32_to_cpup(addr);
+	cell->name = cell_np->name;
+
+	of_property_read_u32(cell_np, "bit-offset", &cell->bit_offset);
+	of_property_read_u32(cell_np, "nbits", &cell->nbits);
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+			dev_err(&nvmem->dev,
+				"cell %s unaligned to nvmem stride %d\n",
+				cell->name, nvmem->stride);
+		rval  = -EINVAL;
+		goto err_sanity;
+	}
+
+	nvmem_cell_add(cell);
+
+	return cell;
+
+err_sanity:
+	kfree(cell);
+
+err_mem:
+	__nvmem_device_put(nvmem);
+
+	return ERR_PTR(rval);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+
+/**
+ * nvmem_cell_get() - Get nvmem cell of device form a given cell name
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name to get.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
+{
+	struct nvmem_cell *cell;
+
+	if (dev->of_node) { /* try dt first */
+		cell = of_nvmem_cell_get(dev->of_node, cell_id);
+		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
+			return cell;
+	}
+
+	return nvmem_cell_get_from_list(cell_id);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_get);
+
+static void devm_nvmem_cell_release(struct device *dev, void *res)
+{
+	nvmem_cell_put(*(struct nvmem_cell **)res);
+}
+
+/**
+ * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem id in nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
+{
+	struct nvmem_cell **ptr, *cell;
+
+	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	cell = nvmem_cell_get(dev, id);
+	if (!IS_ERR(cell)) {
+		*ptr = cell;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return cell;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
+
+static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_cell **c = res;
+
+	if (!c || !*c) {
+		WARN_ON(!c || !*c);
+		return 0;
+	}
+	return *c == data;
+}
+
+/**
+ * devm_nvmem_cell_put() - Release previously allocated nvmem cell
+ * from devm_nvmem_cell_get.
+ *
+ * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get()
+ */
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_cell_release, devm_nvmem_cell_match, cell);
+
+	WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_nvmem_cell_put);
+
+/**
+ * nvmem_cell_put() - Release previously allocated nvmem cell.
+ *
+ * @cell: Previously allocated nvmem cell by nvmem_cell_get()
+ */
+void nvmem_cell_put(struct nvmem_cell *cell)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+
+	__nvmem_device_put(nvmem);
+	nvmem_cell_drop(cell);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell,
+						    void *buf)
+{
+	u8 *p, *b;
+	int i, bit_offset = cell->bit_offset;
+
+	p = b = buf;
+	if (bit_offset) {
+		/* First shift */
+		*b++ >>= bit_offset;
+
+		/* setup rest of the bytes if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get bits from next byte and shift them towards msb */
+			*p |= *b << (BITS_PER_BYTE - bit_offset);
+
+			p = b;
+			*b++ >>= bit_offset;
+		}
+
+		/* result fits in less bytes */
+		if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE))
+			*p-- = 0;
+	}
+	/* clear msb bits if any leftover in the last byte */
+	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+}
+
+static int __nvmem_cell_read(struct nvmem_device *nvmem,
+		      struct nvmem_cell *cell,
+		      void *buf, ssize_t *len)
+{
+	int rc;
+
+	rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	/* shift bits in-place */
+	if (cell->bit_offset || cell->bit_offset)
+		nvmem_shift_read_buffer_in_place(cell, buf);
+
+	*len = cell->bytes;
+
+	return *len;
+}
+/**
+ * nvmem_cell_read() - Read a given nvmem cell
+ *
+ * @cell: nvmem cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a char * bufffer.  The buffer should be freed by the consumer with a
+ * kfree().
+ */
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	u8 *buf;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	rc = __nvmem_cell_read(nvmem, cell, buf, len);
+	if (IS_ERR_VALUE(rc)) {
+		kfree(buf);
+		return ERR_PTR(rc);
+	}
+
+	return buf;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
+						    u8 *_buf, int len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int i, rc, nbits, bit_offset = cell->bit_offset;
+	u8 v, *p, *buf, *b, pbyte, pbits;
+
+	nbits = cell->nbits;
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(buf, _buf, len);
+	p = b = buf;
+
+	if (bit_offset) {
+		pbyte = *b;
+		*b <<= bit_offset;
+
+		/* setup the first byte with lsb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+		*b++ |= GENMASK(bit_offset - 1, 0) & v;
+
+		/* setup rest of the byte if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get last byte bits and shift them towards lsb */
+			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
+			pbyte = *b;
+			p = b;
+			*b <<= bit_offset;
+			*b++ |= pbits;
+		}
+	}
+
+	/* if it's not end on byte boundary */
+	if ((nbits + bit_offset) % BITS_PER_BYTE) {
+		/* setup the last byte with msb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap,
+				    cell->offset + cell->bytes - 1, &v, 1);
+		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
+
+	}
+
+	return buf;
+}
+
+/**
+ * nvmem_cell_write() - Write to a given nvmem cell
+ *
+ * @cell: nvmem cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to nvmem cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int rc;
+	void *wbuf = buf;
+
+	if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+	    (cell->bit_offset == 0 && len != cell->bytes))
+		return -EINVAL;
+
+	if (cell->bit_offset || cell->nbits) {
+		wbuf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+		if (IS_ERR(wbuf))
+			return PTR_ERR(wbuf);
+	}
+
+	rc = regmap_raw_write(nvmem->regmap, cell->offset, wbuf, cell->bytes);
+
+	/* free the tmp buffer */
+	if (cell->bit_offset)
+		kfree(wbuf);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
new file mode 100644
index 0000000..123af62
--- /dev/null
+++ b/include/linux/nvmem-consumer.h
@@ -0,0 +1,75 @@
+/*
+ * nvmem framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_CONSUMER_H
+#define _LINUX_NVMEM_CONSUMER_H
+
+struct device;
+/* consumer cookie */
+struct nvmem_cell;
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+/* Cell based interface */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+#else
+
+static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
+						const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev,
+				       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_nvmem_cell_put(struct device *dev,
+				       struct nvmem_cell *cell)
+{
+
+}
+static inline void nvmem_cell_put(struct nvmem_cell *cell)
+{
+}
+
+static inline char *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell,
+				    const char *buf, ssize_t len)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_NVMEM */
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name);
+#else
+static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_NVMEM && CONFIG_OF */
+
+#endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds just consumers part of the framework just to enable easy
review.

Up until now, nvmem 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of the framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 415 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  75 ++++++++
 2 files changed, 490 insertions(+)
 create mode 100644 include/linux/nvmem-consumer.h

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 17a826d..78cd5c8 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -16,6 +16,7 @@
 
 #include <linux/device.h>
 #include <linux/nvmem-provider.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
@@ -379,6 +380,420 @@ int nvmem_unregister(struct nvmem_device *nvmem)
 }
 EXPORT_SYMBOL_GPL(nvmem_unregister);
 
+static struct nvmem_device *__nvmem_device_get(struct device_node *np,
+					       struct nvmem_cell **cellp,
+					       const char *cell_id)
+{
+	struct nvmem_device *nvmem = NULL;
+
+	mutex_lock(&nvmem_mutex);
+
+	if (np) {
+		nvmem = of_nvmem_find(np);
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-EPROBE_DEFER);
+		}
+	} else {
+		struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+
+		if (cell) {
+			nvmem = cell->nvmem;
+			*cellp = cell;
+		}
+
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-ENOENT);
+		}
+	}
+
+	nvmem->users++;
+	mutex_unlock(&nvmem_mutex);
+
+	if (!try_module_get(nvmem->owner)) {
+		dev_err(&nvmem->dev,
+			"could not increase module refcount for cell %s\n",
+			nvmem->name);
+
+		mutex_lock(&nvmem_mutex);
+		nvmem->users--;
+		mutex_unlock(&nvmem_mutex);
+
+		return ERR_PTR(-EINVAL);
+	}
+
+	return nvmem;
+}
+
+static void __nvmem_device_put(struct nvmem_device *nvmem)
+{
+	module_put(nvmem->owner);
+	mutex_lock(&nvmem_mutex);
+	nvmem->users--;
+	mutex_unlock(&nvmem_mutex);
+}
+
+static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
+{
+	struct nvmem_cell *cell = NULL;
+	struct nvmem_device *nvmem;
+
+	nvmem = __nvmem_device_get(NULL, &cell, cell_id);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+
+	return cell;
+
+}
+/**
+ * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name from nvmem-cell-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+					    const char *name)
+{
+	struct device_node *cell_np, *nvmem_np;
+	struct nvmem_cell *cell;
+	struct nvmem_device *nvmem;
+	const __be32 *addr;
+	int rval, len, index;
+
+	index = of_property_match_string(np, "nvmem-cell-names", name);
+
+	cell_np = of_parse_phandle(np, "nvmem-cell", index);
+	if (!cell_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem_np = of_get_next_parent(cell_np);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+	addr = of_get_property(cell_np, "reg", &len);
+	if (!addr || (len < 2 * sizeof(int))) {
+		dev_err(&nvmem->dev, "nvmem: invalid reg on %s\n",
+			cell_np->full_name);
+		rval  = -EINVAL;
+		goto err_mem;
+	}
+
+	cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+	if (!cell) {
+		rval = -ENOMEM;
+		goto err_mem;
+	}
+
+	cell->nvmem = nvmem;
+	cell->offset = be32_to_cpup(addr++);
+	cell->bytes = be32_to_cpup(addr);
+	cell->name = cell_np->name;
+
+	of_property_read_u32(cell_np, "bit-offset", &cell->bit_offset);
+	of_property_read_u32(cell_np, "nbits", &cell->nbits);
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+			dev_err(&nvmem->dev,
+				"cell %s unaligned to nvmem stride %d\n",
+				cell->name, nvmem->stride);
+		rval  = -EINVAL;
+		goto err_sanity;
+	}
+
+	nvmem_cell_add(cell);
+
+	return cell;
+
+err_sanity:
+	kfree(cell);
+
+err_mem:
+	__nvmem_device_put(nvmem);
+
+	return ERR_PTR(rval);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+
+/**
+ * nvmem_cell_get() - Get nvmem cell of device form a given cell name
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name to get.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
+{
+	struct nvmem_cell *cell;
+
+	if (dev->of_node) { /* try dt first */
+		cell = of_nvmem_cell_get(dev->of_node, cell_id);
+		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
+			return cell;
+	}
+
+	return nvmem_cell_get_from_list(cell_id);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_get);
+
+static void devm_nvmem_cell_release(struct device *dev, void *res)
+{
+	nvmem_cell_put(*(struct nvmem_cell **)res);
+}
+
+/**
+ * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem id in nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
+{
+	struct nvmem_cell **ptr, *cell;
+
+	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	cell = nvmem_cell_get(dev, id);
+	if (!IS_ERR(cell)) {
+		*ptr = cell;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return cell;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
+
+static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_cell **c = res;
+
+	if (!c || !*c) {
+		WARN_ON(!c || !*c);
+		return 0;
+	}
+	return *c == data;
+}
+
+/**
+ * devm_nvmem_cell_put() - Release previously allocated nvmem cell
+ * from devm_nvmem_cell_get.
+ *
+ * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get()
+ */
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_cell_release, devm_nvmem_cell_match, cell);
+
+	WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_nvmem_cell_put);
+
+/**
+ * nvmem_cell_put() - Release previously allocated nvmem cell.
+ *
+ * @cell: Previously allocated nvmem cell by nvmem_cell_get()
+ */
+void nvmem_cell_put(struct nvmem_cell *cell)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+
+	__nvmem_device_put(nvmem);
+	nvmem_cell_drop(cell);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell,
+						    void *buf)
+{
+	u8 *p, *b;
+	int i, bit_offset = cell->bit_offset;
+
+	p = b = buf;
+	if (bit_offset) {
+		/* First shift */
+		*b++ >>= bit_offset;
+
+		/* setup rest of the bytes if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get bits from next byte and shift them towards msb */
+			*p |= *b << (BITS_PER_BYTE - bit_offset);
+
+			p = b;
+			*b++ >>= bit_offset;
+		}
+
+		/* result fits in less bytes */
+		if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE))
+			*p-- = 0;
+	}
+	/* clear msb bits if any leftover in the last byte */
+	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+}
+
+static int __nvmem_cell_read(struct nvmem_device *nvmem,
+		      struct nvmem_cell *cell,
+		      void *buf, ssize_t *len)
+{
+	int rc;
+
+	rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	/* shift bits in-place */
+	if (cell->bit_offset || cell->bit_offset)
+		nvmem_shift_read_buffer_in_place(cell, buf);
+
+	*len = cell->bytes;
+
+	return *len;
+}
+/**
+ * nvmem_cell_read() - Read a given nvmem cell
+ *
+ * @cell: nvmem cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a char * bufffer.  The buffer should be freed by the consumer with a
+ * kfree().
+ */
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	u8 *buf;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	rc = __nvmem_cell_read(nvmem, cell, buf, len);
+	if (IS_ERR_VALUE(rc)) {
+		kfree(buf);
+		return ERR_PTR(rc);
+	}
+
+	return buf;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
+						    u8 *_buf, int len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int i, rc, nbits, bit_offset = cell->bit_offset;
+	u8 v, *p, *buf, *b, pbyte, pbits;
+
+	nbits = cell->nbits;
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(buf, _buf, len);
+	p = b = buf;
+
+	if (bit_offset) {
+		pbyte = *b;
+		*b <<= bit_offset;
+
+		/* setup the first byte with lsb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+		*b++ |= GENMASK(bit_offset - 1, 0) & v;
+
+		/* setup rest of the byte if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get last byte bits and shift them towards lsb */
+			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
+			pbyte = *b;
+			p = b;
+			*b <<= bit_offset;
+			*b++ |= pbits;
+		}
+	}
+
+	/* if it's not end on byte boundary */
+	if ((nbits + bit_offset) % BITS_PER_BYTE) {
+		/* setup the last byte with msb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap,
+				    cell->offset + cell->bytes - 1, &v, 1);
+		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
+
+	}
+
+	return buf;
+}
+
+/**
+ * nvmem_cell_write() - Write to a given nvmem cell
+ *
+ * @cell: nvmem cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to nvmem cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int rc;
+	void *wbuf = buf;
+
+	if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+	    (cell->bit_offset == 0 && len != cell->bytes))
+		return -EINVAL;
+
+	if (cell->bit_offset || cell->nbits) {
+		wbuf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+		if (IS_ERR(wbuf))
+			return PTR_ERR(wbuf);
+	}
+
+	rc = regmap_raw_write(nvmem->regmap, cell->offset, wbuf, cell->bytes);
+
+	/* free the tmp buffer */
+	if (cell->bit_offset)
+		kfree(wbuf);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
new file mode 100644
index 0000000..123af62
--- /dev/null
+++ b/include/linux/nvmem-consumer.h
@@ -0,0 +1,75 @@
+/*
+ * nvmem framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_CONSUMER_H
+#define _LINUX_NVMEM_CONSUMER_H
+
+struct device;
+/* consumer cookie */
+struct nvmem_cell;
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+/* Cell based interface */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+#else
+
+static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
+						const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev,
+				       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_nvmem_cell_put(struct device *dev,
+				       struct nvmem_cell *cell)
+{
+
+}
+static inline void nvmem_cell_put(struct nvmem_cell *cell)
+{
+}
+
+static inline char *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell,
+				    const char *buf, ssize_t len)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_NVMEM */
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name);
+#else
+static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_NVMEM && CONFIG_OF */
+
+#endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds just consumers part of the framework just to enable easy
review.

Up until now, nvmem 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 nvmems.

Having regmap interface to this framework would give much better
abstraction for nvmems on different buses.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of the framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 415 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  75 ++++++++
 2 files changed, 490 insertions(+)
 create mode 100644 include/linux/nvmem-consumer.h

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 17a826d..78cd5c8 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -16,6 +16,7 @@
 
 #include <linux/device.h>
 #include <linux/nvmem-provider.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
@@ -379,6 +380,420 @@ int nvmem_unregister(struct nvmem_device *nvmem)
 }
 EXPORT_SYMBOL_GPL(nvmem_unregister);
 
+static struct nvmem_device *__nvmem_device_get(struct device_node *np,
+					       struct nvmem_cell **cellp,
+					       const char *cell_id)
+{
+	struct nvmem_device *nvmem = NULL;
+
+	mutex_lock(&nvmem_mutex);
+
+	if (np) {
+		nvmem = of_nvmem_find(np);
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-EPROBE_DEFER);
+		}
+	} else {
+		struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+
+		if (cell) {
+			nvmem = cell->nvmem;
+			*cellp = cell;
+		}
+
+		if (!nvmem) {
+			mutex_unlock(&nvmem_mutex);
+			return ERR_PTR(-ENOENT);
+		}
+	}
+
+	nvmem->users++;
+	mutex_unlock(&nvmem_mutex);
+
+	if (!try_module_get(nvmem->owner)) {
+		dev_err(&nvmem->dev,
+			"could not increase module refcount for cell %s\n",
+			nvmem->name);
+
+		mutex_lock(&nvmem_mutex);
+		nvmem->users--;
+		mutex_unlock(&nvmem_mutex);
+
+		return ERR_PTR(-EINVAL);
+	}
+
+	return nvmem;
+}
+
+static void __nvmem_device_put(struct nvmem_device *nvmem)
+{
+	module_put(nvmem->owner);
+	mutex_lock(&nvmem_mutex);
+	nvmem->users--;
+	mutex_unlock(&nvmem_mutex);
+}
+
+static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
+{
+	struct nvmem_cell *cell = NULL;
+	struct nvmem_device *nvmem;
+
+	nvmem = __nvmem_device_get(NULL, &cell, cell_id);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+
+	return cell;
+
+}
+/**
+ * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name from nvmem-cell-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+					    const char *name)
+{
+	struct device_node *cell_np, *nvmem_np;
+	struct nvmem_cell *cell;
+	struct nvmem_device *nvmem;
+	const __be32 *addr;
+	int rval, len, index;
+
+	index = of_property_match_string(np, "nvmem-cell-names", name);
+
+	cell_np = of_parse_phandle(np, "nvmem-cell", index);
+	if (!cell_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem_np = of_get_next_parent(cell_np);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+	if (IS_ERR(nvmem))
+		return ERR_CAST(nvmem);
+
+	addr = of_get_property(cell_np, "reg", &len);
+	if (!addr || (len < 2 * sizeof(int))) {
+		dev_err(&nvmem->dev, "nvmem: invalid reg on %s\n",
+			cell_np->full_name);
+		rval  = -EINVAL;
+		goto err_mem;
+	}
+
+	cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+	if (!cell) {
+		rval = -ENOMEM;
+		goto err_mem;
+	}
+
+	cell->nvmem = nvmem;
+	cell->offset = be32_to_cpup(addr++);
+	cell->bytes = be32_to_cpup(addr);
+	cell->name = cell_np->name;
+
+	of_property_read_u32(cell_np, "bit-offset", &cell->bit_offset);
+	of_property_read_u32(cell_np, "nbits", &cell->nbits);
+
+	if (cell->nbits)
+		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+					   BITS_PER_BYTE);
+
+	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+			dev_err(&nvmem->dev,
+				"cell %s unaligned to nvmem stride %d\n",
+				cell->name, nvmem->stride);
+		rval  = -EINVAL;
+		goto err_sanity;
+	}
+
+	nvmem_cell_add(cell);
+
+	return cell;
+
+err_sanity:
+	kfree(cell);
+
+err_mem:
+	__nvmem_device_put(nvmem);
+
+	return ERR_PTR(rval);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+
+/**
+ * nvmem_cell_get() - Get nvmem cell of device form a given cell name
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name to get.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
+{
+	struct nvmem_cell *cell;
+
+	if (dev->of_node) { /* try dt first */
+		cell = of_nvmem_cell_get(dev->of_node, cell_id);
+		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
+			return cell;
+	}
+
+	return nvmem_cell_get_from_list(cell_id);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_get);
+
+static void devm_nvmem_cell_release(struct device *dev, void *res)
+{
+	nvmem_cell_put(*(struct nvmem_cell **)res);
+}
+
+/**
+ * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem id in nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
+{
+	struct nvmem_cell **ptr, *cell;
+
+	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	cell = nvmem_cell_get(dev, id);
+	if (!IS_ERR(cell)) {
+		*ptr = cell;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return cell;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
+
+static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_cell **c = res;
+
+	if (!c || !*c) {
+		WARN_ON(!c || !*c);
+		return 0;
+	}
+	return *c == data;
+}
+
+/**
+ * devm_nvmem_cell_put() - Release previously allocated nvmem cell
+ * from devm_nvmem_cell_get.
+ *
+ * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get()
+ */
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_cell_release, devm_nvmem_cell_match, cell);
+
+	WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_nvmem_cell_put);
+
+/**
+ * nvmem_cell_put() - Release previously allocated nvmem cell.
+ *
+ * @cell: Previously allocated nvmem cell by nvmem_cell_get()
+ */
+void nvmem_cell_put(struct nvmem_cell *cell)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+
+	__nvmem_device_put(nvmem);
+	nvmem_cell_drop(cell);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell,
+						    void *buf)
+{
+	u8 *p, *b;
+	int i, bit_offset = cell->bit_offset;
+
+	p = b = buf;
+	if (bit_offset) {
+		/* First shift */
+		*b++ >>= bit_offset;
+
+		/* setup rest of the bytes if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get bits from next byte and shift them towards msb */
+			*p |= *b << (BITS_PER_BYTE - bit_offset);
+
+			p = b;
+			*b++ >>= bit_offset;
+		}
+
+		/* result fits in less bytes */
+		if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE))
+			*p-- = 0;
+	}
+	/* clear msb bits if any leftover in the last byte */
+	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+}
+
+static int __nvmem_cell_read(struct nvmem_device *nvmem,
+		      struct nvmem_cell *cell,
+		      void *buf, ssize_t *len)
+{
+	int rc;
+
+	rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	/* shift bits in-place */
+	if (cell->bit_offset || cell->bit_offset)
+		nvmem_shift_read_buffer_in_place(cell, buf);
+
+	*len = cell->bytes;
+
+	return *len;
+}
+/**
+ * nvmem_cell_read() - Read a given nvmem cell
+ *
+ * @cell: nvmem cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a char * bufffer.  The buffer should be freed by the consumer with a
+ * kfree().
+ */
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	u8 *buf;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	rc = __nvmem_cell_read(nvmem, cell, buf, len);
+	if (IS_ERR_VALUE(rc)) {
+		kfree(buf);
+		return ERR_PTR(rc);
+	}
+
+	return buf;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
+						    u8 *_buf, int len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int i, rc, nbits, bit_offset = cell->bit_offset;
+	u8 v, *p, *buf, *b, pbyte, pbits;
+
+	nbits = cell->nbits;
+	buf = kzalloc(cell->bytes, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(buf, _buf, len);
+	p = b = buf;
+
+	if (bit_offset) {
+		pbyte = *b;
+		*b <<= bit_offset;
+
+		/* setup the first byte with lsb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+		*b++ |= GENMASK(bit_offset - 1, 0) & v;
+
+		/* setup rest of the byte if any */
+		for (i = 1; i < cell->bytes; i++) {
+			/* Get last byte bits and shift them towards lsb */
+			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
+			pbyte = *b;
+			p = b;
+			*b <<= bit_offset;
+			*b++ |= pbits;
+		}
+	}
+
+	/* if it's not end on byte boundary */
+	if ((nbits + bit_offset) % BITS_PER_BYTE) {
+		/* setup the last byte with msb bits from nvmem */
+		rc = regmap_raw_read(nvmem->regmap,
+				    cell->offset + cell->bytes - 1, &v, 1);
+		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
+
+	}
+
+	return buf;
+}
+
+/**
+ * nvmem_cell_write() - Write to a given nvmem cell
+ *
+ * @cell: nvmem cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to nvmem cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
+{
+	struct nvmem_device *nvmem = cell->nvmem;
+	int rc;
+	void *wbuf = buf;
+
+	if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+	    (cell->bit_offset == 0 && len != cell->bytes))
+		return -EINVAL;
+
+	if (cell->bit_offset || cell->nbits) {
+		wbuf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+		if (IS_ERR(wbuf))
+			return PTR_ERR(wbuf);
+	}
+
+	rc = regmap_raw_write(nvmem->regmap, cell->offset, wbuf, cell->bytes);
+
+	/* free the tmp buffer */
+	if (cell->bit_offset)
+		kfree(wbuf);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
new file mode 100644
index 0000000..123af62
--- /dev/null
+++ b/include/linux/nvmem-consumer.h
@@ -0,0 +1,75 @@
+/*
+ * nvmem framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_NVMEM_CONSUMER_H
+#define _LINUX_NVMEM_CONSUMER_H
+
+struct device;
+/* consumer cookie */
+struct nvmem_cell;
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+/* Cell based interface */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+#else
+
+static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
+						const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev,
+				       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_nvmem_cell_put(struct device *dev,
+				       struct nvmem_cell *cell)
+{
+
+}
+static inline void nvmem_cell_put(struct nvmem_cell *cell)
+{
+}
+
+static inline char *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell,
+				    const char *buf, ssize_t len)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_NVMEM */
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name);
+#else
+static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+				     const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_NVMEM && CONFIG_OF */
+
+#endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:08   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds read/write apis which are based on nvmem_device. It is
common that the drivers like omap cape manager or qcom cpr driver to
access bytes directly at particular offset in the eeprom and not from
nvmem cell info in DT. These driver would need to get access to the nvmem
directly, which is what these new APIS provide.

These wrapper apis would help such users to avoid code duplication in
there drivers and also avoid them reading a big eeprom blob and parsing
it internally in there driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 256 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  79 +++++++++++++
 include/linux/nvmem-provider.h |  10 +-
 3 files changed, 337 insertions(+), 8 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 78cd5c8..82b564c 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -434,6 +434,147 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
 	mutex_unlock(&nvmem_mutex);
 }
 
+static int nvmem_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), data);
+}
+
+static struct nvmem_device *nvmem_find(const char *name)
+{
+	struct device *d;
+
+	d = class_find_device(&nvmem_class, NULL, name, nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+/**
+ * of_nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev node: Device tree node that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
+{
+
+	struct device_node *nvmem_np;
+	int index;
+
+	index = of_property_match_string(np, "nvmem-names", id);
+
+	nvmem_np = of_parse_phandle(np, "nvmem", index);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	return __nvmem_device_get(nvmem_np, NULL, NULL);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_device_get);
+
+
+/**
+ * nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev : Device that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
+{
+	if (dev->of_node) { /* try dt first */
+		struct nvmem_device *nvmem;
+
+		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
+
+		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
+			return nvmem;
+
+	}
+
+	return nvmem_find(dev_name);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get);
+
+static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_device **nvmem = res;
+	if (!nvmem || !*nvmem) {
+		WARN_ON(!nvmem || !*nvmem);
+		return 0;
+	}
+	return *nvmem == data;
+}
+
+static void devm_nvmem_device_release(struct device *dev, void *res)
+{
+	nvmem_device_put(*(struct nvmem_device **)res);
+}
+
+/**
+ * devm_nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
+ * that needs to be released.
+ */
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_device_release,
+			     devm_nvmem_device_match, nvmem);
+
+	WARN_ON(ret);
+
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
+
+/**
+ * nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device that needs to be released.
+ */
+void nvmem_device_put(struct nvmem_device *nvmem)
+{
+	__nvmem_device_put(nvmem);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_put);
+
+/**
+ * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem name in nvmems property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
+{
+	struct nvmem_device **ptr, *nvmem;
+
+	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem = nvmem_device_get(dev, id);
+	if (!IS_ERR(nvmem)) {
+		*ptr = nvmem;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
 static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
 {
 	struct nvmem_cell *cell = NULL;
@@ -794,6 +935,121 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
 }
 EXPORT_SYMBOL_GPL(nvmem_cell_write);
 
+/**
+ * nvmem_device_cell_read() - Read a given nvmem device and cell
+ *
+ * @nvmem: nvmem device to read from.
+ * @info: nvmem cell info to be read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc, len;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
+
+/**
+ * nvmem_device_cell_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @info: nvmem cell info to be written
+ * @buf: buffer to be written to cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return nvmem_cell_write(&cell, buf, cell.bytes);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
+/**
+ * nvmem_device_read() - Read from a given nvmem device
+ *
+ * @nvmem: nvmem device to read from.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_read(struct nvmem_device *nvmem,
+		      unsigned int offset,
+		      size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_read);
+
+/**
+ * nvmem_device_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to write.
+ * @buf: buffer to be written.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_write(struct nvmem_device *nvmem,
+		       unsigned int offset,
+		       size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 123af62..f9acc43 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -15,6 +15,15 @@
 struct device;
 /* consumer cookie */
 struct nvmem_cell;
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
 
 #if IS_ENABLED(CONFIG_NVMEM)
 
@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
 void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
 int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
 
+/* direct nvmem device read/write interface */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
 #else
 
 static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -59,17 +83,72 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
 {
 	return -ENOSYS;
 }
+
+static inline struct nvmem_device *nvmem_device_get(struct device *dev,
+						    const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+							 const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void nvmem_device_put(struct nvmem_device *nvmem)
+{
+}
+
+static inline void devm_nvmem_device_put(struct device *dev,
+					 struct nvmem_device *nvmem)
+{
+}
+
+static inline int nvmem_device_cell_read(struct nvmem_device *nvmem,
+					 struct nvmem_cell_info *info,
+					 void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+					  struct nvmem_cell_info *info,
+					  void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+				    unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+				     unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
 struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name);
+struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+					 const char *name);
 #else
 static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name)
 {
 	return ERR_PTR(-ENOSYS);
 }
+
+static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+						       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif /* CONFIG_NVMEM && CONFIG_OF */
 
 #endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index f589d3b..74eed42 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -12,15 +12,9 @@
 #ifndef _LINUX_NVMEM_PROVIDER_H
 #define _LINUX_NVMEM_PROVIDER_H
 
-struct nvmem_device;
+#include <linux/nvmem-consumer.h>
 
-struct nvmem_cell_info {
-	const char		*name;
-	int			offset;
-	int			bytes;
-	int			bit_offset;
-	int			nbits;
-};
+struct nvmem_device;
 
 struct nvmem_config {
 	struct device		*dev;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
@ 2015-06-22 23:08   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds read/write apis which are based on nvmem_device. It is
common that the drivers like omap cape manager or qcom cpr driver to
access bytes directly at particular offset in the eeprom and not from
nvmem cell info in DT. These driver would need to get access to the nvmem
directly, which is what these new APIS provide.

These wrapper apis would help such users to avoid code duplication in
there drivers and also avoid them reading a big eeprom blob and parsing
it internally in there driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 256 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  79 +++++++++++++
 include/linux/nvmem-provider.h |  10 +-
 3 files changed, 337 insertions(+), 8 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 78cd5c8..82b564c 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -434,6 +434,147 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
 	mutex_unlock(&nvmem_mutex);
 }
 
+static int nvmem_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), data);
+}
+
+static struct nvmem_device *nvmem_find(const char *name)
+{
+	struct device *d;
+
+	d = class_find_device(&nvmem_class, NULL, name, nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+/**
+ * of_nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev node: Device tree node that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
+{
+
+	struct device_node *nvmem_np;
+	int index;
+
+	index = of_property_match_string(np, "nvmem-names", id);
+
+	nvmem_np = of_parse_phandle(np, "nvmem", index);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	return __nvmem_device_get(nvmem_np, NULL, NULL);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_device_get);
+
+
+/**
+ * nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev : Device that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
+{
+	if (dev->of_node) { /* try dt first */
+		struct nvmem_device *nvmem;
+
+		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
+
+		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
+			return nvmem;
+
+	}
+
+	return nvmem_find(dev_name);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get);
+
+static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_device **nvmem = res;
+	if (!nvmem || !*nvmem) {
+		WARN_ON(!nvmem || !*nvmem);
+		return 0;
+	}
+	return *nvmem == data;
+}
+
+static void devm_nvmem_device_release(struct device *dev, void *res)
+{
+	nvmem_device_put(*(struct nvmem_device **)res);
+}
+
+/**
+ * devm_nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
+ * that needs to be released.
+ */
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_device_release,
+			     devm_nvmem_device_match, nvmem);
+
+	WARN_ON(ret);
+
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
+
+/**
+ * nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device that needs to be released.
+ */
+void nvmem_device_put(struct nvmem_device *nvmem)
+{
+	__nvmem_device_put(nvmem);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_put);
+
+/**
+ * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem name in nvmems property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
+{
+	struct nvmem_device **ptr, *nvmem;
+
+	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem = nvmem_device_get(dev, id);
+	if (!IS_ERR(nvmem)) {
+		*ptr = nvmem;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
 static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
 {
 	struct nvmem_cell *cell = NULL;
@@ -794,6 +935,121 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
 }
 EXPORT_SYMBOL_GPL(nvmem_cell_write);
 
+/**
+ * nvmem_device_cell_read() - Read a given nvmem device and cell
+ *
+ * @nvmem: nvmem device to read from.
+ * @info: nvmem cell info to be read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc, len;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
+
+/**
+ * nvmem_device_cell_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @info: nvmem cell info to be written
+ * @buf: buffer to be written to cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return nvmem_cell_write(&cell, buf, cell.bytes);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
+/**
+ * nvmem_device_read() - Read from a given nvmem device
+ *
+ * @nvmem: nvmem device to read from.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_read(struct nvmem_device *nvmem,
+		      unsigned int offset,
+		      size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_read);
+
+/**
+ * nvmem_device_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to write.
+ * @buf: buffer to be written.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_write(struct nvmem_device *nvmem,
+		       unsigned int offset,
+		       size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 123af62..f9acc43 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -15,6 +15,15 @@
 struct device;
 /* consumer cookie */
 struct nvmem_cell;
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
 
 #if IS_ENABLED(CONFIG_NVMEM)
 
@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
 void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
 int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
 
+/* direct nvmem device read/write interface */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
 #else
 
 static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -59,17 +83,72 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
 {
 	return -ENOSYS;
 }
+
+static inline struct nvmem_device *nvmem_device_get(struct device *dev,
+						    const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+							 const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void nvmem_device_put(struct nvmem_device *nvmem)
+{
+}
+
+static inline void devm_nvmem_device_put(struct device *dev,
+					 struct nvmem_device *nvmem)
+{
+}
+
+static inline int nvmem_device_cell_read(struct nvmem_device *nvmem,
+					 struct nvmem_cell_info *info,
+					 void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+					  struct nvmem_cell_info *info,
+					  void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+				    unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+				     unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
 struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name);
+struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+					 const char *name);
 #else
 static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name)
 {
 	return ERR_PTR(-ENOSYS);
 }
+
+static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+						       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif /* CONFIG_NVMEM && CONFIG_OF */
 
 #endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index f589d3b..74eed42 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -12,15 +12,9 @@
 #ifndef _LINUX_NVMEM_PROVIDER_H
 #define _LINUX_NVMEM_PROVIDER_H
 
-struct nvmem_device;
+#include <linux/nvmem-consumer.h>
 
-struct nvmem_cell_info {
-	const char		*name;
-	int			offset;
-	int			bytes;
-	int			bit_offset;
-	int			nbits;
-};
+struct nvmem_device;
 
 struct nvmem_config {
 	struct device		*dev;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
@ 2015-06-22 23:08   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds read/write apis which are based on nvmem_device. It is
common that the drivers like omap cape manager or qcom cpr driver to
access bytes directly at particular offset in the eeprom and not from
nvmem cell info in DT. These driver would need to get access to the nvmem
directly, which is what these new APIS provide.

These wrapper apis would help such users to avoid code duplication in
there drivers and also avoid them reading a big eeprom blob and parsing
it internally in there driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 256 +++++++++++++++++++++++++++++++++++++++++
 include/linux/nvmem-consumer.h |  79 +++++++++++++
 include/linux/nvmem-provider.h |  10 +-
 3 files changed, 337 insertions(+), 8 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 78cd5c8..82b564c 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -434,6 +434,147 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
 	mutex_unlock(&nvmem_mutex);
 }
 
+static int nvmem_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), data);
+}
+
+static struct nvmem_device *nvmem_find(const char *name)
+{
+	struct device *d;
+
+	d = class_find_device(&nvmem_class, NULL, name, nvmem_match);
+
+	return d ? to_nvmem_device(d) : NULL;
+}
+
+/**
+ * of_nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev node: Device tree node that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
+{
+
+	struct device_node *nvmem_np;
+	int index;
+
+	index = of_property_match_string(np, "nvmem-names", id);
+
+	nvmem_np = of_parse_phandle(np, "nvmem", index);
+	if (!nvmem_np)
+		return ERR_PTR(-EINVAL);
+
+	return __nvmem_device_get(nvmem_np, NULL, NULL);
+
+}
+EXPORT_SYMBOL_GPL(of_nvmem_device_get);
+
+
+/**
+ * nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev : Device that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_device.
+ */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
+{
+	if (dev->of_node) { /* try dt first */
+		struct nvmem_device *nvmem;
+
+		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
+
+		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
+			return nvmem;
+
+	}
+
+	return nvmem_find(dev_name);
+
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get);
+
+static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
+{
+	struct nvmem_device **nvmem = res;
+	if (!nvmem || !*nvmem) {
+		WARN_ON(!nvmem || !*nvmem);
+		return 0;
+	}
+	return *nvmem == data;
+}
+
+static void devm_nvmem_device_release(struct device *dev, void *res)
+{
+	nvmem_device_put(*(struct nvmem_device **)res);
+}
+
+/**
+ * devm_nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
+ * that needs to be released.
+ */
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_nvmem_device_release,
+			     devm_nvmem_device_match, nvmem);
+
+	WARN_ON(ret);
+
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
+
+/**
+ * nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device that needs to be released.
+ */
+void nvmem_device_put(struct nvmem_device *nvmem)
+{
+	__nvmem_device_put(nvmem);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_put);
+
+/**
+ * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem name in nvmems property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
+{
+	struct nvmem_device **ptr, *nvmem;
+
+	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	nvmem = nvmem_device_get(dev, id);
+	if (!IS_ERR(nvmem)) {
+		*ptr = nvmem;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
 static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
 {
 	struct nvmem_cell *cell = NULL;
@@ -794,6 +935,121 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len)
 }
 EXPORT_SYMBOL_GPL(nvmem_cell_write);
 
+/**
+ * nvmem_device_cell_read() - Read a given nvmem device and cell
+ *
+ * @nvmem: nvmem device to read from.
+ * @info: nvmem cell info to be read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc, len;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
+
+/**
+ * nvmem_device_cell_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @info: nvmem cell info to be written
+ * @buf: buffer to be written to cell.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf)
+{
+	struct nvmem_cell cell;
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return nvmem_cell_write(&cell, buf, cell.bytes);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
+/**
+ * nvmem_device_read() - Read from a given nvmem device
+ *
+ * @nvmem: nvmem device to read from.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * The return value would be length of successful bytes read on success
+ * and error code in error cases.
+ */
+int nvmem_device_read(struct nvmem_device *nvmem,
+		      unsigned int offset,
+		      size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_read);
+
+/**
+ * nvmem_device_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to write.
+ * @buf: buffer to be written.
+ *
+ * The return value will be an length of bytes written or non zero on failure.
+ * */
+int nvmem_device_write(struct nvmem_device *nvmem,
+		       unsigned int offset,
+		       size_t bytes, void *buf)
+{
+	int rc;
+
+	if (!nvmem || !nvmem->regmap)
+		return -EINVAL;
+
+	rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+
+	if (IS_ERR_VALUE(rc))
+		return rc;
+
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_write);
+
 static int __init nvmem_init(void)
 {
 	return class_register(&nvmem_class);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 123af62..f9acc43 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -15,6 +15,15 @@
 struct device;
 /* consumer cookie */
 struct nvmem_cell;
+struct nvmem_device;
+
+struct nvmem_cell_info {
+	const char		*name;
+	int			offset;
+	int			bytes;
+	int			bit_offset;
+	int			nbits;
+};
 
 #if IS_ENABLED(CONFIG_NVMEM)
 
@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
 void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
 int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
 
+/* direct nvmem device read/write interface */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
 #else
 
 static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -59,17 +83,72 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
 {
 	return -ENOSYS;
 }
+
+static inline struct nvmem_device *nvmem_device_get(struct device *dev,
+						    const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+							 const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void nvmem_device_put(struct nvmem_device *nvmem)
+{
+}
+
+static inline void devm_nvmem_device_put(struct device *dev,
+					 struct nvmem_device *nvmem)
+{
+}
+
+static inline int nvmem_device_cell_read(struct nvmem_device *nvmem,
+					 struct nvmem_cell_info *info,
+					 void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+					  struct nvmem_cell_info *info,
+					  void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+				    unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+				     unsigned int offset, size_t bytes, void *buf)
+{
+	return -ENOSYS;
+}
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
 struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name);
+struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+					 const char *name);
 #else
 static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
 				     const char *name)
 {
 	return ERR_PTR(-ENOSYS);
 }
+
+static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+						       const char *name)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif /* CONFIG_NVMEM && CONFIG_OF */
 
 #endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index f589d3b..74eed42 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -12,15 +12,9 @@
 #ifndef _LINUX_NVMEM_PROVIDER_H
 #define _LINUX_NVMEM_PROVIDER_H
 
-struct nvmem_device;
+#include <linux/nvmem-consumer.h>
 
-struct nvmem_cell_info {
-	const char		*name;
-	int			offset;
-	int			bytes;
-	int			bit_offset;
-	int			nbits;
-};
+struct nvmem_device;
 
 struct nvmem_config {
 	struct device		*dev;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw, Srinivas Kandagatla

This patch adds bindings for simple nvmem framework which allows nvmem
consumers to talk to nvmem providers to get access to nvmem cell data.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/devicetree/bindings/nvmem/nvmem.txt | 85 +++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt

diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
new file mode 100644
index 0000000..d1a37e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
@@ -0,0 +1,85 @@
+= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on NVMEM, for the OS to be able to retrieve these information
+and act upon it. Obviously, the OS has to know about where to retrieve
+these data from, and where they are stored on the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+of this node.
+
+Optional properties:
+ read-only: Mark the provider as read only.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in nvmem provider.
+
+Required properties:
+reg:	specifies the offset in byte within that storage device, start bit
+	in the byte and the length in bits of the data we care about.
+	There could be more than one offset-length pairs in this property.
+
+Optional properties:
+
+bit-offset: specifies the offset in bit within the address range specified
+	by reg property. Can take values from 0-7.
+nbits: specifies number of bits this cell occupies starting from bit-offset.
+
+For example:
+
+	/* Provider */
+	qfprom: qfprom@00700000 {
+		...
+
+		/* Data cells */
+		tsens_calibration: calib@404 {
+			reg = <0x404 0x10>;
+		};
+
+		tsens_calibration_bckp: calib_bckp@504 {
+			reg = <0x504 0x11>;
+			bit-offset = 6;
+			nbits = 128;
+		};
+
+		pvs_version: pvs-version@6 {
+			reg = <0x6 0x2>
+			bit-offset = 7;
+			nbits = 2;
+		};
+
+		speed_bin: speed-bin@c{
+			reg = <0xc 0x1>;
+			bit-offset = 2;
+			nbits	= 3;
+
+		};
+		...
+	};
+
+= Data consumers =
+Are device nodes which consume nvmem data cells/providers.
+
+Required-properties:
+nvmem-cell: list of phandle to the nvmem data cells.
+nvmem-cell-names: names for the each nvmem-cell specified. Required if
+	nvmem-cell is used.
+
+Optional-properties:
+nvmem	: list of phandles to nvmem providers.
+nvmem-names: names for the each nvmem provider. required if nvmem is used.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds bindings for simple nvmem framework which allows nvmem
consumers to talk to nvmem providers to get access to nvmem cell data.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/devicetree/bindings/nvmem/nvmem.txt | 85 +++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt

diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
new file mode 100644
index 0000000..d1a37e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
@@ -0,0 +1,85 @@
+= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on NVMEM, for the OS to be able to retrieve these information
+and act upon it. Obviously, the OS has to know about where to retrieve
+these data from, and where they are stored on the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+of this node.
+
+Optional properties:
+ read-only: Mark the provider as read only.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in nvmem provider.
+
+Required properties:
+reg:	specifies the offset in byte within that storage device, start bit
+	in the byte and the length in bits of the data we care about.
+	There could be more than one offset-length pairs in this property.
+
+Optional properties:
+
+bit-offset: specifies the offset in bit within the address range specified
+	by reg property. Can take values from 0-7.
+nbits: specifies number of bits this cell occupies starting from bit-offset.
+
+For example:
+
+	/* Provider */
+	qfprom: qfprom@00700000 {
+		...
+
+		/* Data cells */
+		tsens_calibration: calib@404 {
+			reg = <0x404 0x10>;
+		};
+
+		tsens_calibration_bckp: calib_bckp@504 {
+			reg = <0x504 0x11>;
+			bit-offset = 6;
+			nbits = 128;
+		};
+
+		pvs_version: pvs-version@6 {
+			reg = <0x6 0x2>
+			bit-offset = 7;
+			nbits = 2;
+		};
+
+		speed_bin: speed-bin@c{
+			reg = <0xc 0x1>;
+			bit-offset = 2;
+			nbits	= 3;
+
+		};
+		...
+	};
+
+= Data consumers =
+Are device nodes which consume nvmem data cells/providers.
+
+Required-properties:
+nvmem-cell: list of phandle to the nvmem data cells.
+nvmem-cell-names: names for the each nvmem-cell specified. Required if
+	nvmem-cell is used.
+
+Optional-properties:
+nvmem	: list of phandles to nvmem providers.
+nvmem-names: names for the each nvmem provider. required if nvmem is used.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
@ 2015-06-22 23:08     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds bindings for simple nvmem framework which allows nvmem
consumers to talk to nvmem providers to get access to nvmem cell data.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[Maxime Ripard: intial version of eeprom framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/devicetree/bindings/nvmem/nvmem.txt | 85 +++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt

diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
new file mode 100644
index 0000000..d1a37e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
@@ -0,0 +1,85 @@
+= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on NVMEM, for the OS to be able to retrieve these information
+and act upon it. Obviously, the OS has to know about where to retrieve
+these data from, and where they are stored on the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+of this node.
+
+Optional properties:
+ read-only: Mark the provider as read only.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in nvmem provider.
+
+Required properties:
+reg:	specifies the offset in byte within that storage device, start bit
+	in the byte and the length in bits of the data we care about.
+	There could be more than one offset-length pairs in this property.
+
+Optional properties:
+
+bit-offset: specifies the offset in bit within the address range specified
+	by reg property. Can take values from 0-7.
+nbits: specifies number of bits this cell occupies starting from bit-offset.
+
+For example:
+
+	/* Provider */
+	qfprom: qfprom at 00700000 {
+		...
+
+		/* Data cells */
+		tsens_calibration: calib at 404 {
+			reg = <0x404 0x10>;
+		};
+
+		tsens_calibration_bckp: calib_bckp at 504 {
+			reg = <0x504 0x11>;
+			bit-offset = 6;
+			nbits = 128;
+		};
+
+		pvs_version: pvs-version at 6 {
+			reg = <0x6 0x2>
+			bit-offset = 7;
+			nbits = 2;
+		};
+
+		speed_bin: speed-bin at c{
+			reg = <0xc 0x1>;
+			bit-offset = 2;
+			nbits	= 3;
+
+		};
+		...
+	};
+
+= Data consumers =
+Are device nodes which consume nvmem data cells/providers.
+
+Required-properties:
+nvmem-cell: list of phandle to the nvmem data cells.
+nvmem-cell-names: names for the each nvmem-cell specified. Required if
+	nvmem-cell is used.
+
+Optional-properties:
+nvmem	: list of phandles to nvmem providers.
+nvmem-names: names for the each nvmem provider. required if nvmem is used.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 5/9] Documentation: nvmem: add nvmem api level and how-to doc
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch add basic how-to and api summary documentation for simple
NVMEM framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/nvmem/nvmem.txt | 151 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 Documentation/nvmem/nvmem.txt

diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
new file mode 100644
index 0000000..28b3579
--- /dev/null
+++ b/Documentation/nvmem/nvmem.txt
@@ -0,0 +1,151 @@
+			    NVMEM SUBSYSTEM
+	  Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+This document explains the Simple NVMEM Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+===============
+*NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to
+retrieve configuration or SOC or Device specific data from a non volatile memories
+like eeprom, efuses and so on.
+
+Up until now, NVMEM drivers like eeprom 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.
+
+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 NVMEMs.
+This framework is based on regmap, so that most of the abstraction
+available in regmap can be reused, across multiple types of buses.
+
+NVMEM Providers
++++++++++++++++
+
+NVMEM provider refers to an entity that implements methods to initialize, read
+and write the non-volatile memory.
+
+2. Registering/Unregistering the NVMEM provider
+===============================================
+
+A NVMEM provider can register with NVMEM core by suppling relevant
+nvmem configuration to nvmem_register(), on success core would return a valid
+nvmem_device pointer.
+
+nvmem_unregister(nvmem) is used to unregister the already registered provider.
+
+For example for simple qfprom case:
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	...
+	econfig.dev = &pdev->dev;
+	nvmem = nvmem_register(&econfig);
+	...
+}
+
+It is mandatory that the NVMEM provider has a regmap associated with its
+struct device.
+
+NVMEM Consumers
++++++++++++++++
+
+NVMEM consumers are the entities which make use of the NVMEM provider to
+read/write into NVMEM.
+
+3. NVMEM cell based consumer APIs.
+=================================
+
+NVMEM cells are the data entries/fields in the NVMEM.
+The NVMEM framework provides 3 APIs to read/write NVMEM cells.
+
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+*nvmem_cell_get() apis will get a reference to nvmem cell for a given id,
+and nvmem_cell_read/write() can then directly read or write to the cell.
+Once the usage of the cell is finished the consumer should call *nvmem_cell_put()
+to free all the allocation memory for the cell.
+
+4. Direct NVMEM device based consumer APIs.
+==========================================
+
+In some instances it is necessary to directly read/write the NVMEM.
+To facilitate such consumers NVMEM framework provides below apis.
+
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
+Before the consumers can read/write NVMEM directly, it should get hold
+of nvmem_controller from one of the *nvmem_device_get() api.
+
+Difference between these apis and cell based apis is that these apis
+always take nvmem_device as parameter.
+
+5. Releasing a reference to the NVMEM
+=====================================
+
+When the consumers no longer needs the NVMEM, it has to release the reference
+to the NVMEM it has obtained using the APIs mentioned in the above section.
+NVMEM framework provides 2 APIs to release a reference to the NVMEM.
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+
+Both these APIs are used to release a reference to the NVMEM and
+devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated
+with this NVMEM.
+
+Userspace
++++++++++
+
+6. Userspace binary interface.
+==============================
+
+Userspace can read/write the raw NVMEM file located at /sys/class/nvmem/*/nvmem
+
+ex:
+
+hexdump /sys/class/nvmem/qfprom0/nvmem
+
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+*
+00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+...
+*
+0001000
+
+7. DeviceTree Binding
+=====================
+
+The documentation for NVMEM dt binding can be found @
+Documentation/devicetree/bindings/nvmem/nvmem.txt
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 5/9] Documentation: nvmem: add nvmem api level and how-to doc
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch add basic how-to and api summary documentation for simple
NVMEM framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/nvmem/nvmem.txt | 151 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 Documentation/nvmem/nvmem.txt

diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
new file mode 100644
index 0000000..28b3579
--- /dev/null
+++ b/Documentation/nvmem/nvmem.txt
@@ -0,0 +1,151 @@
+			    NVMEM SUBSYSTEM
+	  Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+This document explains the Simple NVMEM Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+===============
+*NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to
+retrieve configuration or SOC or Device specific data from a non volatile memories
+like eeprom, efuses and so on.
+
+Up until now, NVMEM drivers like eeprom 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.
+
+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 NVMEMs.
+This framework is based on regmap, so that most of the abstraction
+available in regmap can be reused, across multiple types of buses.
+
+NVMEM Providers
++++++++++++++++
+
+NVMEM provider refers to an entity that implements methods to initialize, read
+and write the non-volatile memory.
+
+2. Registering/Unregistering the NVMEM provider
+===============================================
+
+A NVMEM provider can register with NVMEM core by suppling relevant
+nvmem configuration to nvmem_register(), on success core would return a valid
+nvmem_device pointer.
+
+nvmem_unregister(nvmem) is used to unregister the already registered provider.
+
+For example for simple qfprom case:
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	...
+	econfig.dev = &pdev->dev;
+	nvmem = nvmem_register(&econfig);
+	...
+}
+
+It is mandatory that the NVMEM provider has a regmap associated with its
+struct device.
+
+NVMEM Consumers
++++++++++++++++
+
+NVMEM consumers are the entities which make use of the NVMEM provider to
+read/write into NVMEM.
+
+3. NVMEM cell based consumer APIs.
+=================================
+
+NVMEM cells are the data entries/fields in the NVMEM.
+The NVMEM framework provides 3 APIs to read/write NVMEM cells.
+
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+*nvmem_cell_get() apis will get a reference to nvmem cell for a given id,
+and nvmem_cell_read/write() can then directly read or write to the cell.
+Once the usage of the cell is finished the consumer should call *nvmem_cell_put()
+to free all the allocation memory for the cell.
+
+4. Direct NVMEM device based consumer APIs.
+==========================================
+
+In some instances it is necessary to directly read/write the NVMEM.
+To facilitate such consumers NVMEM framework provides below apis.
+
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
+Before the consumers can read/write NVMEM directly, it should get hold
+of nvmem_controller from one of the *nvmem_device_get() api.
+
+Difference between these apis and cell based apis is that these apis
+always take nvmem_device as parameter.
+
+5. Releasing a reference to the NVMEM
+=====================================
+
+When the consumers no longer needs the NVMEM, it has to release the reference
+to the NVMEM it has obtained using the APIs mentioned in the above section.
+NVMEM framework provides 2 APIs to release a reference to the NVMEM.
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+
+Both these APIs are used to release a reference to the NVMEM and
+devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated
+with this NVMEM.
+
+Userspace
++++++++++
+
+6. Userspace binary interface.
+==============================
+
+Userspace can read/write the raw NVMEM file located at /sys/class/nvmem/*/nvmem
+
+ex:
+
+hexdump /sys/class/nvmem/qfprom0/nvmem
+
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+*
+00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+...
+*
+0001000
+
+7. DeviceTree Binding
+=====================
+
+The documentation for NVMEM dt binding can be found @
+Documentation/devicetree/bindings/nvmem/nvmem.txt
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 5/9] Documentation: nvmem: add nvmem api level and how-to doc
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add basic how-to and api summary documentation for simple
NVMEM framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/nvmem/nvmem.txt | 151 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 Documentation/nvmem/nvmem.txt

diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
new file mode 100644
index 0000000..28b3579
--- /dev/null
+++ b/Documentation/nvmem/nvmem.txt
@@ -0,0 +1,151 @@
+			    NVMEM SUBSYSTEM
+	  Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+This document explains the Simple NVMEM Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+===============
+*NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to
+retrieve configuration or SOC or Device specific data from a non volatile memories
+like eeprom, efuses and so on.
+
+Up until now, NVMEM drivers like eeprom 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.
+
+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 NVMEMs.
+This framework is based on regmap, so that most of the abstraction
+available in regmap can be reused, across multiple types of buses.
+
+NVMEM Providers
++++++++++++++++
+
+NVMEM provider refers to an entity that implements methods to initialize, read
+and write the non-volatile memory.
+
+2. Registering/Unregistering the NVMEM provider
+===============================================
+
+A NVMEM provider can register with NVMEM core by suppling relevant
+nvmem configuration to nvmem_register(), on success core would return a valid
+nvmem_device pointer.
+
+nvmem_unregister(nvmem) is used to unregister the already registered provider.
+
+For example for simple qfprom case:
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	...
+	econfig.dev = &pdev->dev;
+	nvmem = nvmem_register(&econfig);
+	...
+}
+
+It is mandatory that the NVMEM provider has a regmap associated with its
+struct device.
+
+NVMEM Consumers
++++++++++++++++
+
+NVMEM consumers are the entities which make use of the NVMEM provider to
+read/write into NVMEM.
+
+3. NVMEM cell based consumer APIs.
+=================================
+
+NVMEM cells are the data entries/fields in the NVMEM.
+The NVMEM framework provides 3 APIs to read/write NVMEM cells.
+
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+*nvmem_cell_get() apis will get a reference to nvmem cell for a given id,
+and nvmem_cell_read/write() can then directly read or write to the cell.
+Once the usage of the cell is finished the consumer should call *nvmem_cell_put()
+to free all the allocation memory for the cell.
+
+4. Direct NVMEM device based consumer APIs.
+==========================================
+
+In some instances it is necessary to directly read/write the NVMEM.
+To facilitate such consumers NVMEM framework provides below apis.
+
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+					   const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+			   struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+			    struct nvmem_cell_info *info, void *buf);
+
+Before the consumers can read/write NVMEM directly, it should get hold
+of nvmem_controller from one of the *nvmem_device_get() api.
+
+Difference between these apis and cell based apis is that these apis
+always take nvmem_device as parameter.
+
+5. Releasing a reference to the NVMEM
+=====================================
+
+When the consumers no longer needs the NVMEM, it has to release the reference
+to the NVMEM it has obtained using the APIs mentioned in the above section.
+NVMEM framework provides 2 APIs to release a reference to the NVMEM.
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+
+Both these APIs are used to release a reference to the NVMEM and
+devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated
+with this NVMEM.
+
+Userspace
++++++++++
+
+6. Userspace binary interface.
+==============================
+
+Userspace can read/write the raw NVMEM file located at /sys/class/nvmem/*/nvmem
+
+ex:
+
+hexdump /sys/class/nvmem/qfprom0/nvmem
+
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+*
+00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+...
+*
+0001000
+
+7. DeviceTree Binding
+=====================
+
+The documentation for NVMEM dt binding can be found @
+Documentation/devicetree/bindings/nvmem/nvmem.txt
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds QFPROM support driver which is used by other drivers
like thermal sensor and cpufreq.

On MSM parts there are some efuses (called qfprom) these fuses store
things like calibration data, speed bins.. etc. Drivers like cpufreq,
thermal sensors would read out this data for configuring the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/Kconfig  | 15 +++++++++
 drivers/nvmem/Makefile |  4 +++
 drivers/nvmem/qfprom.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/nvmem/qfprom.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index f157b6d..7fff0e2 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -8,3 +8,18 @@ menuconfig NVMEM
 	  from both the Linux Kernel and the userspace.
 
 	  If unsure, say no.
+
+if NVMEM
+
+config QCOM_QFPROM
+	tristate "QCOM QFPROM Support"
+	depends on ARCH_QCOM || COMPILE_TEST
+	select REGMAP_MMIO
+	help
+	  Say y here to enable QFPROM support. The QFPROM provides access
+	  functions for QFPROM data to rest of the drivers via nvmem interface.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called nvmem-qfprom.
+
+endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 6df2c69..ff44fe9 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -4,3 +4,7 @@
 
 obj-$(CONFIG_NVMEM)		+= nvmem_core.o
 nvmem_core-y			:= core.o
+
+# Devices
+obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
+nvmem_qfprom-y			:= qfprom.o
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
new file mode 100644
index 0000000..7f7a82f
--- /dev/null
+++ b/drivers/nvmem/qfprom.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+static struct regmap_config qfprom_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+};
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	void __iomem *base;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+	{ .compatible = "qcom,qfprom",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+	.probe = qfprom_probe,
+	.remove = qfprom_remove,
+	.driver = {
+		.name = "qcom,qfprom",
+		.of_match_table = qfprom_of_match,
+	},
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds QFPROM support driver which is used by other drivers
like thermal sensor and cpufreq.

On MSM parts there are some efuses (called qfprom) these fuses store
things like calibration data, speed bins.. etc. Drivers like cpufreq,
thermal sensors would read out this data for configuring the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/Kconfig  | 15 +++++++++
 drivers/nvmem/Makefile |  4 +++
 drivers/nvmem/qfprom.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/nvmem/qfprom.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index f157b6d..7fff0e2 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -8,3 +8,18 @@ menuconfig NVMEM
 	  from both the Linux Kernel and the userspace.
 
 	  If unsure, say no.
+
+if NVMEM
+
+config QCOM_QFPROM
+	tristate "QCOM QFPROM Support"
+	depends on ARCH_QCOM || COMPILE_TEST
+	select REGMAP_MMIO
+	help
+	  Say y here to enable QFPROM support. The QFPROM provides access
+	  functions for QFPROM data to rest of the drivers via nvmem interface.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called nvmem-qfprom.
+
+endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 6df2c69..ff44fe9 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -4,3 +4,7 @@
 
 obj-$(CONFIG_NVMEM)		+= nvmem_core.o
 nvmem_core-y			:= core.o
+
+# Devices
+obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
+nvmem_qfprom-y			:= qfprom.o
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
new file mode 100644
index 0000000..7f7a82f
--- /dev/null
+++ b/drivers/nvmem/qfprom.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+static struct regmap_config qfprom_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+};
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	void __iomem *base;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+	{ .compatible = "qcom,qfprom",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+	.probe = qfprom_probe,
+	.remove = qfprom_remove,
+	.driver = {
+		.name = "qcom,qfprom",
+		.of_match_table = qfprom_of_match,
+	},
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
@ 2015-06-22 23:09   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds QFPROM support driver which is used by other drivers
like thermal sensor and cpufreq.

On MSM parts there are some efuses (called qfprom) these fuses store
things like calibration data, speed bins.. etc. Drivers like cpufreq,
thermal sensors would read out this data for configuring the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/Kconfig  | 15 +++++++++
 drivers/nvmem/Makefile |  4 +++
 drivers/nvmem/qfprom.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/nvmem/qfprom.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index f157b6d..7fff0e2 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -8,3 +8,18 @@ menuconfig NVMEM
 	  from both the Linux Kernel and the userspace.
 
 	  If unsure, say no.
+
+if NVMEM
+
+config QCOM_QFPROM
+	tristate "QCOM QFPROM Support"
+	depends on ARCH_QCOM || COMPILE_TEST
+	select REGMAP_MMIO
+	help
+	  Say y here to enable QFPROM support. The QFPROM provides access
+	  functions for QFPROM data to rest of the drivers via nvmem interface.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called nvmem-qfprom.
+
+endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 6df2c69..ff44fe9 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -4,3 +4,7 @@
 
 obj-$(CONFIG_NVMEM)		+= nvmem_core.o
 nvmem_core-y			:= core.o
+
+# Devices
+obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
+nvmem_qfprom-y			:= qfprom.o
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
new file mode 100644
index 0000000..7f7a82f
--- /dev/null
+++ b/drivers/nvmem/qfprom.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+static struct regmap_config qfprom_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+};
+
+static struct nvmem_config econfig = {
+	.name = "qfprom",
+	.owner = THIS_MODULE,
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	void __iomem *base;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+	{ .compatible = "qcom,qfprom",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+	.probe = qfprom_probe,
+	.remove = qfprom_remove,
+	.driver = {
+		.name = "qcom,qfprom",
+		.of_match_table = qfprom_of_match,
+	},
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw, Srinivas Kandagatla

This patch adds bindings for qfprom found in QCOM SOCs. QFPROM driver
is based on simple nvmem framework.

Reviewed-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/devicetree/bindings/nvmem/qfprom.txt | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt

diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt
new file mode 100644
index 0000000..8a8d55f
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/qfprom.txt
@@ -0,0 +1,35 @@
+= Qualcomm QFPROM device tree bindings =
+
+This binding is intended to represent QFPROM which is found in most QCOM SOCs.
+
+Required properties:
+- compatible: should be "qcom,qfprom"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+	qfprom: qfprom@00700000 {
+		compatible 	= "qcom,qfprom";
+		reg		= <0x00700000 0x8000>;
+		...
+		/* Data cells */
+		tsens_calibration: calib@404 {
+			reg = <0x4404 0x10>;
+		};
+	};
+
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds bindings for qfprom found in QCOM SOCs. QFPROM driver
is based on simple nvmem framework.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/devicetree/bindings/nvmem/qfprom.txt | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt

diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt
new file mode 100644
index 0000000..8a8d55f
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/qfprom.txt
@@ -0,0 +1,35 @@
+= Qualcomm QFPROM device tree bindings =
+
+This binding is intended to represent QFPROM which is found in most QCOM SOCs.
+
+Required properties:
+- compatible: should be "qcom,qfprom"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+	qfprom: qfprom@00700000 {
+		compatible 	= "qcom,qfprom";
+		reg		= <0x00700000 0x8000>;
+		...
+		/* Data cells */
+		tsens_calibration: calib@404 {
+			reg = <0x4404 0x10>;
+		};
+	};
+
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds bindings for qfprom found in QCOM SOCs. QFPROM driver
is based on simple nvmem framework.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/devicetree/bindings/nvmem/qfprom.txt | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/qfprom.txt

diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt
new file mode 100644
index 0000000..8a8d55f
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/qfprom.txt
@@ -0,0 +1,35 @@
+= Qualcomm QFPROM device tree bindings =
+
+This binding is intended to represent QFPROM which is found in most QCOM SOCs.
+
+Required properties:
+- compatible: should be "qcom,qfprom"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+	qfprom: qfprom at 00700000 {
+		compatible 	= "qcom,qfprom";
+		reg		= <0x00700000 0x8000>;
+		...
+		/* Data cells */
+		tsens_calibration: calib at 404 {
+			reg = <0x4404 0x10>;
+		};
+	};
+
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	tsens {
+		...
+		nvmem-cell = <&tsens_calibration>;
+		nvmem-cell-names = "calibration";
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw, Srinivas Kandagatla

From: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Now that we have the nvmem framework, we can consolidate the common
driver code. Move the driver to the framework, and hopefully, it will
fix the sysfs file creation race.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
[srinivas.kandagatla: Moved to regmap based EEPROM framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |  22 ---
 .../bindings/misc/allwinner,sunxi-sid.txt          |  17 ---
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |  21 +++
 drivers/misc/eeprom/Kconfig                        |  13 --
 drivers/misc/eeprom/Makefile                       |   1 -
 drivers/misc/eeprom/sunxi_sid.c                    | 156 --------------------
 drivers/nvmem/Kconfig                              |  11 ++
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/sunxi-sid.c                          | 160 +++++++++++++++++++++
 9 files changed, 194 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/sunxi-sid.c

diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644
index ffb9536..0000000
--- a/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+++ /dev/null
@@ -1,22 +0,0 @@
-What:		/sys/devices/*/<our-device>/eeprom
-Date:		August 2013
-Contact:	Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>
-Description:	read-only access to the SID (Security-ID) on current
-		A-series SoC's from Allwinner. Currently supports A10, A10s, A13
-		and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
-		whereas the newer A20 SoC exposes 512 bytes split into sections.
-		Besides the 16 bytes of SID, there's also an SJTAG area,
-		HDMI-HDCP key and some custom keys. Below a quick overview, for
-		details see the user manual:
-		0x000  128 bit root-key (sun[457]i)
-		0x010  128 bit boot-key (sun7i)
-		0x020   64 bit security-jtag-key (sun7i)
-		0x028   16 bit key configuration (sun7i)
-		0x02b   16 bit custom-vendor-key (sun7i)
-		0x02c  320 bit low general key (sun7i)
-		0x040   32 bit read-control access (sun7i)
-		0x064  224 bit low general key (sun7i)
-		0x080 2304 bit HDCP-key (sun7i)
-		0x1a0  768 bit high general key (sun7i)
-Users:		any user space application which wants to read the SID on
-		Allwinner's A-series of CPU's.
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
deleted file mode 100644
index fabdf64..0000000
--- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Allwinner sunxi-sid
-
-Required properties:
-- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
-- reg: Should contain registers location and length
-
-Example for sun4i:
-	sid@01c23800 {
-		compatible = "allwinner,sun4i-a10-sid";
-		reg = <0x01c23800 0x10>
-	};
-
-Example for sun7i:
-	sid@01c23800 {
-		compatible = "allwinner,sun7i-a20-sid";
-		reg = <0x01c23800 0x200>
-	};
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
new file mode 100644
index 0000000..d543ed3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
@@ -0,0 +1,21 @@
+Allwinner sunxi-sid
+
+Required properties:
+- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example for sun4i:
+	sid@01c23800 {
+		compatible = "allwinner,sun4i-a10-sid";
+		reg = <0x01c23800 0x10>
+	};
+
+Example for sun7i:
+	sid@01c23800 {
+		compatible = "allwinner,sun7i-a20-sid";
+		reg = <0x01c23800 0x200>
+	};
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..04f2e1f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,17 +96,4 @@ config EEPROM_DIGSY_MTC_CFG
 
 	  If unsure, say N.
 
-config EEPROM_SUNXI_SID
-	tristate "Allwinner sunxi security ID support"
-	depends on ARCH_SUNXI && SYSFS
-	help
-	  This is a driver for the 'security ID' available on various Allwinner
-	  devices.
-
-	  Due to the potential risks involved with changing e-fuses,
-	  this driver is read-only.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called sunxi_sid.
-
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,5 +4,4 @@ obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID)	+= sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644
index 8385177..0000000
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>
- * http://www.linux-sunxi.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
-	void __iomem *reg_base;
-	unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
-			      const unsigned int offset)
-{
-	u32 sid_key;
-
-	if (offset >= sid_data->keysize)
-		return 0;
-
-	sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
-	sid_key >>= (offset % 4) * 8;
-
-	return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
-			struct bin_attribute *attr, char *buf,
-			loff_t pos, size_t size)
-{
-	struct platform_device *pdev;
-	struct sunxi_sid_data *sid_data;
-	int i;
-
-	pdev = to_platform_device(kobj_to_dev(kobj));
-	sid_data = platform_get_drvdata(pdev);
-
-	if (pos < 0 || pos >= sid_data->keysize)
-		return 0;
-	if (size > sid_data->keysize - pos)
-		size = sid_data->keysize - pos;
-
-	for (i = 0; i < size; i++)
-		buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
-	return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
-	.attr = { .name = "eeprom", .mode = S_IRUGO, },
-	.read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
-	device_remove_bin_file(&pdev->dev, &sid_bin_attr);
-	dev_dbg(&pdev->dev, "driver unloaded\n");
-
-	return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
-	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
-	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
-	{/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
-	struct sunxi_sid_data *sid_data;
-	struct resource *res;
-	const struct of_device_id *of_dev_id;
-	u8 *entropy;
-	unsigned int i;
-
-	sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
-				GFP_KERNEL);
-	if (!sid_data)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(sid_data->reg_base))
-		return PTR_ERR(sid_data->reg_base);
-
-	of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
-	if (!of_dev_id)
-		return -ENODEV;
-	sid_data->keysize = (int)of_dev_id->data;
-
-	platform_set_drvdata(pdev, sid_data);
-
-	sid_bin_attr.size = sid_data->keysize;
-	if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
-		return -ENODEV;
-
-	entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
-	for (i = 0; i < sid_data->keysize; i++)
-		entropy[i] = sunxi_sid_read_byte(sid_data, i);
-	add_device_randomness(entropy, sid_data->keysize);
-	kfree(entropy);
-
-	dev_dbg(&pdev->dev, "loaded\n");
-
-	return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
-	.probe = sunxi_sid_probe,
-	.remove = sunxi_sid_remove,
-	.driver = {
-		.name = DRV_NAME,
-		.of_match_table = sunxi_sid_of_match,
-	},
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 7fff0e2..b3a6405 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -22,4 +22,15 @@ config QCOM_QFPROM
 	  This driver can also be built as a module. If so, the module
 	  will be called nvmem-qfprom.
 
+config NVMEM_SUNXI_SID
+	tristate "Allwinner SoCs SID support"
+	depends on ARCH_SUNXI
+	select REGMAP_MMIO
+	help
+	  This is a driver for the 'security ID' available on various Allwinner
+	  devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called eeprom-sunxi-sid.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index ff44fe9..7d18489 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -8,3 +8,5 @@ nvmem_core-y			:= core.o
 # Devices
 obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
 nvmem_qfprom-y			:= qfprom.o
+obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem-sunxi-sid.o
+nvmem-sunxi-sid-y		:= sunxi-sid.o
diff --git a/drivers/nvmem/sunxi-sid.c b/drivers/nvmem/sunxi-sid.c
new file mode 100644
index 0000000..4b39716
--- /dev/null
+++ b/drivers/nvmem/sunxi-sid.c
@@ -0,0 +1,160 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+
+static struct nvmem_config econfig = {
+	.name = "sunxi-sid",
+	.read_only = true,
+	.owner = THIS_MODULE,
+};
+
+struct sunxi_sid {
+	void __iomem		*base;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
+			      const unsigned int offset)
+{
+	u32 sid_key;
+
+	sid_key = ioread32be(sid->base + round_down(offset, 4));
+	sid_key >>= (offset % 4) * 8;
+
+	return sid_key; /* Only return the last byte */
+}
+
+static int sunxi_sid_read(void *context,
+			    const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	struct sunxi_sid *sid = context;
+	unsigned int offset = *(u32 *)reg;
+	u8 *buf = val;
+
+	while (val_size) {
+		*buf++ = sunxi_sid_read_byte(sid, offset);
+		val_size--;
+		offset++;
+	}
+
+	return 0;
+}
+
+static int sunxi_sid_write(void *context, const void *data, size_t count)
+{
+	/* Unimplemented */
+	return 0;
+}
+
+static struct regmap_bus sunxi_sid_bus = {
+	.read = sunxi_sid_read,
+	.write = sunxi_sid_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static struct regmap_config sunxi_sid_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	struct sunxi_sid *sid;
+
+	sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+	if (!sid)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sid->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sid->base))
+		return PTR_ERR(sid->base);
+
+	sunxi_sid_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
+				  &sunxi_sid_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-sid" },
+	{ .compatible = "allwinner,sun7i-a20-sid" },
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct platform_driver sunxi_sid_driver = {
+	.probe = sunxi_sid_probe,
+	.remove = sunxi_sid_remove,
+	.driver = {
+		.name = "eeprom-sunxi-sid",
+		.of_match_table = sunxi_sid_of_match,
+	},
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver-dxLnbx3+1qmEVqv0pETR8A@public.gmane.org>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

From: Maxime Ripard <maxime.ripard@free-electrons.com>

Now that we have the nvmem framework, we can consolidate the common
driver code. Move the driver to the framework, and hopefully, it will
fix the sysfs file creation race.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[srinivas.kandagatla: Moved to regmap based EEPROM framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |  22 ---
 .../bindings/misc/allwinner,sunxi-sid.txt          |  17 ---
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |  21 +++
 drivers/misc/eeprom/Kconfig                        |  13 --
 drivers/misc/eeprom/Makefile                       |   1 -
 drivers/misc/eeprom/sunxi_sid.c                    | 156 --------------------
 drivers/nvmem/Kconfig                              |  11 ++
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/sunxi-sid.c                          | 160 +++++++++++++++++++++
 9 files changed, 194 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/sunxi-sid.c

diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644
index ffb9536..0000000
--- a/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+++ /dev/null
@@ -1,22 +0,0 @@
-What:		/sys/devices/*/<our-device>/eeprom
-Date:		August 2013
-Contact:	Oliver Schinagl <oliver@schinagl.nl>
-Description:	read-only access to the SID (Security-ID) on current
-		A-series SoC's from Allwinner. Currently supports A10, A10s, A13
-		and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
-		whereas the newer A20 SoC exposes 512 bytes split into sections.
-		Besides the 16 bytes of SID, there's also an SJTAG area,
-		HDMI-HDCP key and some custom keys. Below a quick overview, for
-		details see the user manual:
-		0x000  128 bit root-key (sun[457]i)
-		0x010  128 bit boot-key (sun7i)
-		0x020   64 bit security-jtag-key (sun7i)
-		0x028   16 bit key configuration (sun7i)
-		0x02b   16 bit custom-vendor-key (sun7i)
-		0x02c  320 bit low general key (sun7i)
-		0x040   32 bit read-control access (sun7i)
-		0x064  224 bit low general key (sun7i)
-		0x080 2304 bit HDCP-key (sun7i)
-		0x1a0  768 bit high general key (sun7i)
-Users:		any user space application which wants to read the SID on
-		Allwinner's A-series of CPU's.
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
deleted file mode 100644
index fabdf64..0000000
--- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Allwinner sunxi-sid
-
-Required properties:
-- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
-- reg: Should contain registers location and length
-
-Example for sun4i:
-	sid@01c23800 {
-		compatible = "allwinner,sun4i-a10-sid";
-		reg = <0x01c23800 0x10>
-	};
-
-Example for sun7i:
-	sid@01c23800 {
-		compatible = "allwinner,sun7i-a20-sid";
-		reg = <0x01c23800 0x200>
-	};
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
new file mode 100644
index 0000000..d543ed3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
@@ -0,0 +1,21 @@
+Allwinner sunxi-sid
+
+Required properties:
+- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example for sun4i:
+	sid@01c23800 {
+		compatible = "allwinner,sun4i-a10-sid";
+		reg = <0x01c23800 0x10>
+	};
+
+Example for sun7i:
+	sid@01c23800 {
+		compatible = "allwinner,sun7i-a20-sid";
+		reg = <0x01c23800 0x200>
+	};
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..04f2e1f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,17 +96,4 @@ config EEPROM_DIGSY_MTC_CFG
 
 	  If unsure, say N.
 
-config EEPROM_SUNXI_SID
-	tristate "Allwinner sunxi security ID support"
-	depends on ARCH_SUNXI && SYSFS
-	help
-	  This is a driver for the 'security ID' available on various Allwinner
-	  devices.
-
-	  Due to the potential risks involved with changing e-fuses,
-	  this driver is read-only.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called sunxi_sid.
-
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,5 +4,4 @@ obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID)	+= sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644
index 8385177..0000000
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://www.linux-sunxi.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
-	void __iomem *reg_base;
-	unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
-			      const unsigned int offset)
-{
-	u32 sid_key;
-
-	if (offset >= sid_data->keysize)
-		return 0;
-
-	sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
-	sid_key >>= (offset % 4) * 8;
-
-	return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
-			struct bin_attribute *attr, char *buf,
-			loff_t pos, size_t size)
-{
-	struct platform_device *pdev;
-	struct sunxi_sid_data *sid_data;
-	int i;
-
-	pdev = to_platform_device(kobj_to_dev(kobj));
-	sid_data = platform_get_drvdata(pdev);
-
-	if (pos < 0 || pos >= sid_data->keysize)
-		return 0;
-	if (size > sid_data->keysize - pos)
-		size = sid_data->keysize - pos;
-
-	for (i = 0; i < size; i++)
-		buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
-	return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
-	.attr = { .name = "eeprom", .mode = S_IRUGO, },
-	.read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
-	device_remove_bin_file(&pdev->dev, &sid_bin_attr);
-	dev_dbg(&pdev->dev, "driver unloaded\n");
-
-	return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
-	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
-	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
-	{/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
-	struct sunxi_sid_data *sid_data;
-	struct resource *res;
-	const struct of_device_id *of_dev_id;
-	u8 *entropy;
-	unsigned int i;
-
-	sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
-				GFP_KERNEL);
-	if (!sid_data)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(sid_data->reg_base))
-		return PTR_ERR(sid_data->reg_base);
-
-	of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
-	if (!of_dev_id)
-		return -ENODEV;
-	sid_data->keysize = (int)of_dev_id->data;
-
-	platform_set_drvdata(pdev, sid_data);
-
-	sid_bin_attr.size = sid_data->keysize;
-	if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
-		return -ENODEV;
-
-	entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
-	for (i = 0; i < sid_data->keysize; i++)
-		entropy[i] = sunxi_sid_read_byte(sid_data, i);
-	add_device_randomness(entropy, sid_data->keysize);
-	kfree(entropy);
-
-	dev_dbg(&pdev->dev, "loaded\n");
-
-	return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
-	.probe = sunxi_sid_probe,
-	.remove = sunxi_sid_remove,
-	.driver = {
-		.name = DRV_NAME,
-		.of_match_table = sunxi_sid_of_match,
-	},
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 7fff0e2..b3a6405 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -22,4 +22,15 @@ config QCOM_QFPROM
 	  This driver can also be built as a module. If so, the module
 	  will be called nvmem-qfprom.
 
+config NVMEM_SUNXI_SID
+	tristate "Allwinner SoCs SID support"
+	depends on ARCH_SUNXI
+	select REGMAP_MMIO
+	help
+	  This is a driver for the 'security ID' available on various Allwinner
+	  devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called eeprom-sunxi-sid.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index ff44fe9..7d18489 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -8,3 +8,5 @@ nvmem_core-y			:= core.o
 # Devices
 obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
 nvmem_qfprom-y			:= qfprom.o
+obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem-sunxi-sid.o
+nvmem-sunxi-sid-y		:= sunxi-sid.o
diff --git a/drivers/nvmem/sunxi-sid.c b/drivers/nvmem/sunxi-sid.c
new file mode 100644
index 0000000..4b39716
--- /dev/null
+++ b/drivers/nvmem/sunxi-sid.c
@@ -0,0 +1,160 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+
+static struct nvmem_config econfig = {
+	.name = "sunxi-sid",
+	.read_only = true,
+	.owner = THIS_MODULE,
+};
+
+struct sunxi_sid {
+	void __iomem		*base;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
+			      const unsigned int offset)
+{
+	u32 sid_key;
+
+	sid_key = ioread32be(sid->base + round_down(offset, 4));
+	sid_key >>= (offset % 4) * 8;
+
+	return sid_key; /* Only return the last byte */
+}
+
+static int sunxi_sid_read(void *context,
+			    const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	struct sunxi_sid *sid = context;
+	unsigned int offset = *(u32 *)reg;
+	u8 *buf = val;
+
+	while (val_size) {
+		*buf++ = sunxi_sid_read_byte(sid, offset);
+		val_size--;
+		offset++;
+	}
+
+	return 0;
+}
+
+static int sunxi_sid_write(void *context, const void *data, size_t count)
+{
+	/* Unimplemented */
+	return 0;
+}
+
+static struct regmap_bus sunxi_sid_bus = {
+	.read = sunxi_sid_read,
+	.write = sunxi_sid_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static struct regmap_config sunxi_sid_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	struct sunxi_sid *sid;
+
+	sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+	if (!sid)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sid->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sid->base))
+		return PTR_ERR(sid->base);
+
+	sunxi_sid_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
+				  &sunxi_sid_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-sid" },
+	{ .compatible = "allwinner,sun7i-a20-sid" },
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct platform_driver sunxi_sid_driver = {
+	.probe = sunxi_sid_probe,
+	.remove = sunxi_sid_remove,
+	.driver = {
+		.name = "eeprom-sunxi-sid",
+		.of_match_table = sunxi_sid_of_match,
+	},
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
@ 2015-06-22 23:09     ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:09 UTC (permalink / raw)
  To: linux-arm-kernel

From: Maxime Ripard <maxime.ripard@free-electrons.com>

Now that we have the nvmem framework, we can consolidate the common
driver code. Move the driver to the framework, and hopefully, it will
fix the sysfs file creation race.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
[srinivas.kandagatla: Moved to regmap based EEPROM framework]
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 Documentation/ABI/testing/sysfs-driver-sunxi-sid   |  22 ---
 .../bindings/misc/allwinner,sunxi-sid.txt          |  17 ---
 .../bindings/nvmem/allwinner,sunxi-sid.txt         |  21 +++
 drivers/misc/eeprom/Kconfig                        |  13 --
 drivers/misc/eeprom/Makefile                       |   1 -
 drivers/misc/eeprom/sunxi_sid.c                    | 156 --------------------
 drivers/nvmem/Kconfig                              |  11 ++
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/sunxi-sid.c                          | 160 +++++++++++++++++++++
 9 files changed, 194 insertions(+), 209 deletions(-)
 delete mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
 delete mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
 delete mode 100644 drivers/misc/eeprom/sunxi_sid.c
 create mode 100644 drivers/nvmem/sunxi-sid.c

diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644
index ffb9536..0000000
--- a/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+++ /dev/null
@@ -1,22 +0,0 @@
-What:		/sys/devices/*/<our-device>/eeprom
-Date:		August 2013
-Contact:	Oliver Schinagl <oliver@schinagl.nl>
-Description:	read-only access to the SID (Security-ID) on current
-		A-series SoC's from Allwinner. Currently supports A10, A10s, A13
-		and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
-		whereas the newer A20 SoC exposes 512 bytes split into sections.
-		Besides the 16 bytes of SID, there's also an SJTAG area,
-		HDMI-HDCP key and some custom keys. Below a quick overview, for
-		details see the user manual:
-		0x000  128 bit root-key (sun[457]i)
-		0x010  128 bit boot-key (sun7i)
-		0x020   64 bit security-jtag-key (sun7i)
-		0x028   16 bit key configuration (sun7i)
-		0x02b   16 bit custom-vendor-key (sun7i)
-		0x02c  320 bit low general key (sun7i)
-		0x040   32 bit read-control access (sun7i)
-		0x064  224 bit low general key (sun7i)
-		0x080 2304 bit HDCP-key (sun7i)
-		0x1a0  768 bit high general key (sun7i)
-Users:		any user space application which wants to read the SID on
-		Allwinner's A-series of CPU's.
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
deleted file mode 100644
index fabdf64..0000000
--- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Allwinner sunxi-sid
-
-Required properties:
-- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
-- reg: Should contain registers location and length
-
-Example for sun4i:
-	sid at 01c23800 {
-		compatible = "allwinner,sun4i-a10-sid";
-		reg = <0x01c23800 0x10>
-	};
-
-Example for sun7i:
-	sid at 01c23800 {
-		compatible = "allwinner,sun7i-a20-sid";
-		reg = <0x01c23800 0x200>
-	};
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
new file mode 100644
index 0000000..d543ed3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
@@ -0,0 +1,21 @@
+Allwinner sunxi-sid
+
+Required properties:
+- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example for sun4i:
+	sid at 01c23800 {
+		compatible = "allwinner,sun4i-a10-sid";
+		reg = <0x01c23800 0x10>
+	};
+
+Example for sun7i:
+	sid at 01c23800 {
+		compatible = "allwinner,sun7i-a20-sid";
+		reg = <0x01c23800 0x200>
+	};
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..04f2e1f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,17 +96,4 @@ config EEPROM_DIGSY_MTC_CFG
 
 	  If unsure, say N.
 
-config EEPROM_SUNXI_SID
-	tristate "Allwinner sunxi security ID support"
-	depends on ARCH_SUNXI && SYSFS
-	help
-	  This is a driver for the 'security ID' available on various Allwinner
-	  devices.
-
-	  Due to the potential risks involved with changing e-fuses,
-	  this driver is read-only.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called sunxi_sid.
-
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,5 +4,4 @@ obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID)	+= sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644
index 8385177..0000000
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://www.linux-sunxi.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
-	void __iomem *reg_base;
-	unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
-			      const unsigned int offset)
-{
-	u32 sid_key;
-
-	if (offset >= sid_data->keysize)
-		return 0;
-
-	sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
-	sid_key >>= (offset % 4) * 8;
-
-	return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
-			struct bin_attribute *attr, char *buf,
-			loff_t pos, size_t size)
-{
-	struct platform_device *pdev;
-	struct sunxi_sid_data *sid_data;
-	int i;
-
-	pdev = to_platform_device(kobj_to_dev(kobj));
-	sid_data = platform_get_drvdata(pdev);
-
-	if (pos < 0 || pos >= sid_data->keysize)
-		return 0;
-	if (size > sid_data->keysize - pos)
-		size = sid_data->keysize - pos;
-
-	for (i = 0; i < size; i++)
-		buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
-	return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
-	.attr = { .name = "eeprom", .mode = S_IRUGO, },
-	.read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
-	device_remove_bin_file(&pdev->dev, &sid_bin_attr);
-	dev_dbg(&pdev->dev, "driver unloaded\n");
-
-	return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
-	{ .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
-	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
-	{/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
-	struct sunxi_sid_data *sid_data;
-	struct resource *res;
-	const struct of_device_id *of_dev_id;
-	u8 *entropy;
-	unsigned int i;
-
-	sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
-				GFP_KERNEL);
-	if (!sid_data)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(sid_data->reg_base))
-		return PTR_ERR(sid_data->reg_base);
-
-	of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
-	if (!of_dev_id)
-		return -ENODEV;
-	sid_data->keysize = (int)of_dev_id->data;
-
-	platform_set_drvdata(pdev, sid_data);
-
-	sid_bin_attr.size = sid_data->keysize;
-	if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
-		return -ENODEV;
-
-	entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
-	for (i = 0; i < sid_data->keysize; i++)
-		entropy[i] = sunxi_sid_read_byte(sid_data, i);
-	add_device_randomness(entropy, sid_data->keysize);
-	kfree(entropy);
-
-	dev_dbg(&pdev->dev, "loaded\n");
-
-	return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
-	.probe = sunxi_sid_probe,
-	.remove = sunxi_sid_remove,
-	.driver = {
-		.name = DRV_NAME,
-		.of_match_table = sunxi_sid_of_match,
-	},
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 7fff0e2..b3a6405 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -22,4 +22,15 @@ config QCOM_QFPROM
 	  This driver can also be built as a module. If so, the module
 	  will be called nvmem-qfprom.
 
+config NVMEM_SUNXI_SID
+	tristate "Allwinner SoCs SID support"
+	depends on ARCH_SUNXI
+	select REGMAP_MMIO
+	help
+	  This is a driver for the 'security ID' available on various Allwinner
+	  devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called eeprom-sunxi-sid.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index ff44fe9..7d18489 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -8,3 +8,5 @@ nvmem_core-y			:= core.o
 # Devices
 obj-$(CONFIG_QCOM_QFPROM)	+= nvmem_qfprom.o
 nvmem_qfprom-y			:= qfprom.o
+obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem-sunxi-sid.o
+nvmem-sunxi-sid-y		:= sunxi-sid.o
diff --git a/drivers/nvmem/sunxi-sid.c b/drivers/nvmem/sunxi-sid.c
new file mode 100644
index 0000000..4b39716
--- /dev/null
+++ b/drivers/nvmem/sunxi-sid.c
@@ -0,0 +1,160 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/platform_device.h>
+#include <linux/nvmem-provider.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+
+static struct nvmem_config econfig = {
+	.name = "sunxi-sid",
+	.read_only = true,
+	.owner = THIS_MODULE,
+};
+
+struct sunxi_sid {
+	void __iomem		*base;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
+			      const unsigned int offset)
+{
+	u32 sid_key;
+
+	sid_key = ioread32be(sid->base + round_down(offset, 4));
+	sid_key >>= (offset % 4) * 8;
+
+	return sid_key; /* Only return the last byte */
+}
+
+static int sunxi_sid_read(void *context,
+			    const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	struct sunxi_sid *sid = context;
+	unsigned int offset = *(u32 *)reg;
+	u8 *buf = val;
+
+	while (val_size) {
+		*buf++ = sunxi_sid_read_byte(sid, offset);
+		val_size--;
+		offset++;
+	}
+
+	return 0;
+}
+
+static int sunxi_sid_write(void *context, const void *data, size_t count)
+{
+	/* Unimplemented */
+	return 0;
+}
+
+static struct regmap_bus sunxi_sid_bus = {
+	.read = sunxi_sid_read,
+	.write = sunxi_sid_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static struct regmap_config sunxi_sid_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	struct sunxi_sid *sid;
+
+	sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+	if (!sid)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sid->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sid->base))
+		return PTR_ERR(sid->base);
+
+	sunxi_sid_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
+				  &sunxi_sid_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-sid" },
+	{ .compatible = "allwinner,sun7i-a20-sid" },
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct platform_driver sunxi_sid_driver = {
+	.probe = sunxi_sid_probe,
+	.remove = sunxi_sid_remove,
+	.driver = {
+		.name = "eeprom-sunxi-sid",
+		.of_match_table = sunxi_sid_of_match,
+	},
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 9/9] nvmem: Add to MAINTAINERS for nvmem framework
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-22 23:15   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:15 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds MAINTAINERS to nvmem framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b2ef613..26e1829 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6993,6 +6993,15 @@ S:	Supported
 F:	drivers/block/nvme*
 F:	include/linux/nvme.h
 
+NVMEM FRAMEWORK
+M:	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+S:	Maintained
+F:	drivers/nvmem/
+F:	Documentation/devicetree/bindings/nvmem/
+F:	include/linux/nvmem-provider.h
+F:	include/linux/nvmem-consumer.h
+
 NXP-NCI NFC DRIVER
 M:	Clément Perrochaud <clement.perrochaud@effinnov.com>
 R:	Charles Gorand <charles.gorand@effinnov.com>
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 9/9] nvmem: Add to MAINTAINERS for nvmem framework
@ 2015-06-22 23:15   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:15 UTC (permalink / raw)
  To: linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt,
	Srinivas Kandagatla

This patch adds MAINTAINERS to nvmem framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b2ef613..26e1829 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6993,6 +6993,15 @@ S:	Supported
 F:	drivers/block/nvme*
 F:	include/linux/nvme.h
 
+NVMEM FRAMEWORK
+M:	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+S:	Maintained
+F:	drivers/nvmem/
+F:	Documentation/devicetree/bindings/nvmem/
+F:	include/linux/nvmem-provider.h
+F:	include/linux/nvmem-consumer.h
+
 NXP-NCI NFC DRIVER
 M:	Clément Perrochaud <clement.perrochaud@effinnov.com>
 R:	Charles Gorand <charles.gorand@effinnov.com>
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 9/9] nvmem: Add to MAINTAINERS for nvmem framework
@ 2015-06-22 23:15   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-22 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds MAINTAINERS to nvmem framework.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b2ef613..26e1829 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6993,6 +6993,15 @@ S:	Supported
 F:	drivers/block/nvme*
 F:	include/linux/nvme.h
 
+NVMEM FRAMEWORK
+M:	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+S:	Maintained
+F:	drivers/nvmem/
+F:	Documentation/devicetree/bindings/nvmem/
+F:	include/linux/nvmem-provider.h
+F:	include/linux/nvmem-consumer.h
+
 NXP-NCI NFC DRIVER
 M:	Cl?ment Perrochaud <clement.perrochaud@effinnov.com>
 R:	Charles Gorand <charles.gorand@effinnov.com>
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-22 23:08     ` Srinivas Kandagatla
  (?)
@ 2015-06-23  4:52       ` Joe Perches
  -1 siblings, 0 replies; 92+ messages in thread
From: Joe Perches @ 2015-06-23  4:52 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: linux-arm-kernel, Greg Kroah-Hartman, Maxime Ripard, Rob Herring,
	Kumar Gala, Mark Brown, s.hauer, linux-api, linux-kernel,
	devicetree, linux-arm-msm, arnd, sboyd, pantelis.antoniou,
	mporter, stefan.wahren, wxt

On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
> This patch adds just providers part of the framework just to enable easy
> review.
[]
>  include/linux/nvmem-provider.h |  54 ++++++

Unless there are going to be users of nvmem-provider.h
outside of the drivers/nvmem directory, perhaps that
file (and nvmem-consumer.h) should be in drivers/nvmem/

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-23  4:52       ` Joe Perches
  0 siblings, 0 replies; 92+ messages in thread
From: Joe Perches @ 2015-06-23  4:52 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: linux-arm-kernel, Greg Kroah-Hartman, Maxime Ripard, Rob Herring,
	Kumar Gala, Mark Brown, s.hauer, linux-api, linux-kernel,
	devicetree, linux-arm-msm, arnd, sboyd, pantelis.antoniou,
	mporter, stefan.wahren, wxt

On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
> This patch adds just providers part of the framework just to enable easy
> review.
[]
>  include/linux/nvmem-provider.h |  54 ++++++

Unless there are going to be users of nvmem-provider.h
outside of the drivers/nvmem directory, perhaps that
file (and nvmem-consumer.h) should be in drivers/nvmem/


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-23  4:52       ` Joe Perches
  0 siblings, 0 replies; 92+ messages in thread
From: Joe Perches @ 2015-06-23  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
> This patch adds just providers part of the framework just to enable easy
> review.
[]
>  include/linux/nvmem-provider.h |  54 ++++++

Unless there are going to be users of nvmem-provider.h
outside of the drivers/nvmem directory, perhaps that
file (and nvmem-consumer.h) should be in drivers/nvmem/

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
  2015-06-22 23:09     ` Srinivas Kandagatla
  (?)
@ 2015-06-23  9:25         ` Rajendra Nayak
  -1 siblings, 0 replies; 92+ messages in thread
From: Rajendra Nayak @ 2015-06-23  9:25 UTC (permalink / raw)
  To: Srinivas Kandagatla,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw

[]..

> +Example:
> +
> +	qfprom: qfprom@00700000 {
> +		compatible 	= "qcom,qfprom";
> +		reg		= <0x00700000 0x8000>;
> +		...
> +		/* Data cells */
> +		tsens_calibration: calib@404 {
> +			reg = <0x4404 0x10>;
> +		};
> +	};
> +
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	tsens {
> +		...
> +		nvmem-cell = <&tsens_calibration>;

Shouldn't this be nvmem-cells instead?

> +		nvmem-cell-names = "calibration";
> +	};
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
@ 2015-06-23  9:25         ` Rajendra Nayak
  0 siblings, 0 replies; 92+ messages in thread
From: Rajendra Nayak @ 2015-06-23  9:25 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt

[]..

> +Example:
> +
> +	qfprom: qfprom@00700000 {
> +		compatible 	= "qcom,qfprom";
> +		reg		= <0x00700000 0x8000>;
> +		...
> +		/* Data cells */
> +		tsens_calibration: calib@404 {
> +			reg = <0x4404 0x10>;
> +		};
> +	};
> +
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	tsens {
> +		...
> +		nvmem-cell = <&tsens_calibration>;

Shouldn't this be nvmem-cells instead?

> +		nvmem-cell-names = "calibration";
> +	};
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
@ 2015-06-23  9:25         ` Rajendra Nayak
  0 siblings, 0 replies; 92+ messages in thread
From: Rajendra Nayak @ 2015-06-23  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

[]..

> +Example:
> +
> +	qfprom: qfprom at 00700000 {
> +		compatible 	= "qcom,qfprom";
> +		reg		= <0x00700000 0x8000>;
> +		...
> +		/* Data cells */
> +		tsens_calibration: calib at 404 {
> +			reg = <0x4404 0x10>;
> +		};
> +	};
> +
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	tsens {
> +		...
> +		nvmem-cell = <&tsens_calibration>;

Shouldn't this be nvmem-cells instead?

> +		nvmem-cell-names = "calibration";
> +	};
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-23  4:52       ` Joe Perches
@ 2015-06-23  9:26         ` Pantelis Antoniou
  -1 siblings, 0 replies; 92+ messages in thread
From: Pantelis Antoniou @ 2015-06-23  9:26 UTC (permalink / raw)
  To: Joe Perches
  Cc: Srinivas Kandagatla, linux-arm-kernel, Greg Kroah-Hartman,
	Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm,
	Arnd Bergmann, sboyd, Matt Porter, stefan.wahren, wxt

Hi Joe,

> On Jun 23, 2015, at 05:52 , Joe Perches <joe@perches.com> wrote:
> 
> On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>> This patch adds just providers part of the framework just to enable easy
>> review.
> []
>> include/linux/nvmem-provider.h |  54 ++++++
> 
> Unless there are going to be users of nvmem-provider.h
> outside of the drivers/nvmem directory, perhaps that
> file (and nvmem-consumer.h) should be in drivers/nvmem/
> 
> 

nvmem-consumer.h should be accessible from any driver, no?

And unfortunately nvmem-provider should be accessible too.
There are already eeprom drivers in the eeprom/misc directory that
cannot be moved yet to drivers/nvmem (like at24).

They need the provider definitions while they provide both the old
style interface, and the new NVMEM based one.

When we move them to the drivers/nvmem directory, then yes the
provider header file should move there.

Regards

— Pantelis

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-23  9:26         ` Pantelis Antoniou
  0 siblings, 0 replies; 92+ messages in thread
From: Pantelis Antoniou @ 2015-06-23  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Joe,

> On Jun 23, 2015, at 05:52 , Joe Perches <joe@perches.com> wrote:
> 
> On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>> This patch adds just providers part of the framework just to enable easy
>> review.
> []
>> include/linux/nvmem-provider.h |  54 ++++++
> 
> Unless there are going to be users of nvmem-provider.h
> outside of the drivers/nvmem directory, perhaps that
> file (and nvmem-consumer.h) should be in drivers/nvmem/
> 
> 

nvmem-consumer.h should be accessible from any driver, no?

And unfortunately nvmem-provider should be accessible too.
There are already eeprom drivers in the eeprom/misc directory that
cannot be moved yet to drivers/nvmem (like at24).

They need the provider definitions while they provide both the old
style interface, and the new NVMEM based one.

When we move them to the drivers/nvmem directory, then yes the
provider header file should move there.

Regards

? Pantelis

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-22 23:07 ` Srinivas Kandagatla
  (?)
@ 2015-06-23 19:47     ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 19:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 23. Juni 2015 um
> 01:07 geschrieben:
>
>
> [...]
>
> Device Tree:
>
> /* Provider */
> qfprom: qfprom@00700000 {
> ...
>
> /* Data cells */
> tsens_calibration: calib@404 {
> reg = <0x404 0x10>;
> };
>
> tsens_calibration_bckp: calib_bckp@504 {
> reg = <0x504 0x11>;
> bit-offset = 6;
> nbits = 128;
> };
>
> pvs_version: pvs-version@6 {
> reg = <0x6 0x2>
> bit-offset = 7;
> nbits = 2;
> };
>
> speed_bin: speed-bin@c{
> reg = <0xc 0x1>;
> bit-offset = 2;
> nbits = 3;
>
> };
> ...
> };
>
> userspace interface: binary file in /sys/class/nvmem/*/nvmem
>
> ex:
> hexdump /sys/class/nvmem/qfprom0/nvmem
>
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> ...
> *
> 0001000
>

i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
hexdump would readout the complete register range defined in provider DT node.

How can i achieve that hexdump only reads the data area within the register
range?

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-23 19:47     ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 19:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:07 geschrieben:
>
>
> [...]
>
> Device Tree:
>
> /* Provider */
> qfprom: qfprom@00700000 {
> ...
>
> /* Data cells */
> tsens_calibration: calib@404 {
> reg = <0x404 0x10>;
> };
>
> tsens_calibration_bckp: calib_bckp@504 {
> reg = <0x504 0x11>;
> bit-offset = 6;
> nbits = 128;
> };
>
> pvs_version: pvs-version@6 {
> reg = <0x6 0x2>
> bit-offset = 7;
> nbits = 2;
> };
>
> speed_bin: speed-bin@c{
> reg = <0xc 0x1>;
> bit-offset = 2;
> nbits = 3;
>
> };
> ...
> };
>
> userspace interface: binary file in /sys/class/nvmem/*/nvmem
>
> ex:
> hexdump /sys/class/nvmem/qfprom0/nvmem
>
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> ...
> *
> 0001000
>

i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
hexdump would readout the complete register range defined in provider DT node.

How can i achieve that hexdump only reads the data area within the register
range?

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-23 19:47     ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 19:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:07 geschrieben:
>
>
> [...]
>
> Device Tree:
>
> /* Provider */
> qfprom: qfprom at 00700000 {
> ...
>
> /* Data cells */
> tsens_calibration: calib at 404 {
> reg = <0x404 0x10>;
> };
>
> tsens_calibration_bckp: calib_bckp at 504 {
> reg = <0x504 0x11>;
> bit-offset = 6;
> nbits = 128;
> };
>
> pvs_version: pvs-version at 6 {
> reg = <0x6 0x2>
> bit-offset = 7;
> nbits = 2;
> };
>
> speed_bin: speed-bin at c{
> reg = <0xc 0x1>;
> bit-offset = 2;
> nbits = 3;
>
> };
> ...
> };
>
> userspace interface: binary file in /sys/class/nvmem/*/nvmem
>
> ex:
> hexdump /sys/class/nvmem/qfprom0/nvmem
>
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> ...
> *
> 0001000
>

i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
hexdump would readout the complete register range defined in provider DT node.

How can i achieve that hexdump only reads the data area within the register
range?

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-22 23:08     ` Srinivas Kandagatla
  (?)
@ 2015-06-23 20:10         ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:10 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown

Hi Srinivas,

sorry for the messed up indention.

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/drivers/nvmem/Kconfig
> @@ -0,0 +1,10 @@
> +menuconfig NVMEM
> + tristate "NVMEM Support"
> + select REGMAP
> + help
> + Support for NVMEM devices.
> +
> + This framework is designed to provide a generic interface to NVMEM
> + from both the Linux Kernel and the userspace.

In order to avoid confusion it would be good to write here what does NVMEM mean.

> +
> + If unsure, say no.
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> new file mode 100644
> index 0000000..6df2c69
> --- /dev/null
> +++ b/drivers/nvmem/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for nvmem drivers.
> +#
> +
> +obj-$(CONFIG_NVMEM) += nvmem_core.o
> +nvmem_core-y := core.o
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> new file mode 100644
> index 0000000..17a826d
> --- /dev/null
> +++ b/drivers/nvmem/core.c
> @@ -0,0 +1,398 @@
> +/*
> + * nvmem framework core.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/export.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/init.h>
> +#include <linux/regmap.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>

Sorting alphabetically would by nice

> + [...]
> +/**
> + * nvmem_register() - Register a nvmem device for given nvmem_config.
> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
> + *
> + * @config: nvmem device configuration with which nvmem device is created.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to nvmem_device.
> + */
> +
> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
> +{
> + struct nvmem_device *nvmem;
> + struct regmap *rm;
> + int rval;
> +
> + if (!config->dev)
> + return ERR_PTR(-EINVAL);
> +
> + rm = dev_get_regmap(config->dev, NULL);
> + if (!rm) {
> + dev_err(config->dev, "Regmap not found\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
> + if (!nvmem)
> + return ERR_PTR(-ENOMEM);
> +
> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
> + if (nvmem->id < 0) {
> + kfree(nvmem);
> + return ERR_PTR(nvmem->id);
> + }
> +
> + nvmem->regmap = rm;
> + nvmem->owner = config->owner;
> + nvmem->stride = regmap_get_reg_stride(rm);
> + nvmem->word_size = regmap_get_val_bytes(rm);
> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
> + nvmem->dev.class = &nvmem_class;
> + nvmem->dev.parent = config->dev;
> + nvmem->dev.of_node = config->dev->of_node;
> + dev_set_name(&nvmem->dev, "%s%d",
> + config->name ? : "nvmem", config->id);
> +
> + nvmem->read_only = nvmem->dev.of_node ?
> + of_property_read_bool(nvmem->dev.of_node,
> + "read-only") :
> + config->read_only;
> +
> + device_initialize(&nvmem->dev);
> +
> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
> + dev_name(&nvmem->dev));
> +
> + rval = device_add(&nvmem->dev);
> + if (rval) {
> + ida_simple_remove(&nvmem_ida, nvmem->id);
> + kfree(nvmem);
> + return ERR_PTR(rval);
> + }
> +
> + /* update sysfs attributes */
> + if (nvmem->read_only)
> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
> +
> + if (config->cells)
> + nvmem_add_cells(nvmem, config);

I think this would be a better place for the debug message from above.
Additionally we could add the cell count and so on.

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-23 20:10         ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:10 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown

Hi Srinivas,

sorry for the messed up indention.

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/drivers/nvmem/Kconfig
> @@ -0,0 +1,10 @@
> +menuconfig NVMEM
> + tristate "NVMEM Support"
> + select REGMAP
> + help
> + Support for NVMEM devices.
> +
> + This framework is designed to provide a generic interface to NVMEM
> + from both the Linux Kernel and the userspace.

In order to avoid confusion it would be good to write here what does NVMEM mean.

> +
> + If unsure, say no.
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> new file mode 100644
> index 0000000..6df2c69
> --- /dev/null
> +++ b/drivers/nvmem/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for nvmem drivers.
> +#
> +
> +obj-$(CONFIG_NVMEM) += nvmem_core.o
> +nvmem_core-y := core.o
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> new file mode 100644
> index 0000000..17a826d
> --- /dev/null
> +++ b/drivers/nvmem/core.c
> @@ -0,0 +1,398 @@
> +/*
> + * nvmem framework core.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/export.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/init.h>
> +#include <linux/regmap.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>

Sorting alphabetically would by nice

> + [...]
> +/**
> + * nvmem_register() - Register a nvmem device for given nvmem_config.
> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
> + *
> + * @config: nvmem device configuration with which nvmem device is created.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to nvmem_device.
> + */
> +
> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
> +{
> + struct nvmem_device *nvmem;
> + struct regmap *rm;
> + int rval;
> +
> + if (!config->dev)
> + return ERR_PTR(-EINVAL);
> +
> + rm = dev_get_regmap(config->dev, NULL);
> + if (!rm) {
> + dev_err(config->dev, "Regmap not found\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
> + if (!nvmem)
> + return ERR_PTR(-ENOMEM);
> +
> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
> + if (nvmem->id < 0) {
> + kfree(nvmem);
> + return ERR_PTR(nvmem->id);
> + }
> +
> + nvmem->regmap = rm;
> + nvmem->owner = config->owner;
> + nvmem->stride = regmap_get_reg_stride(rm);
> + nvmem->word_size = regmap_get_val_bytes(rm);
> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
> + nvmem->dev.class = &nvmem_class;
> + nvmem->dev.parent = config->dev;
> + nvmem->dev.of_node = config->dev->of_node;
> + dev_set_name(&nvmem->dev, "%s%d",
> + config->name ? : "nvmem", config->id);
> +
> + nvmem->read_only = nvmem->dev.of_node ?
> + of_property_read_bool(nvmem->dev.of_node,
> + "read-only") :
> + config->read_only;
> +
> + device_initialize(&nvmem->dev);
> +
> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
> + dev_name(&nvmem->dev));
> +
> + rval = device_add(&nvmem->dev);
> + if (rval) {
> + ida_simple_remove(&nvmem_ida, nvmem->id);
> + kfree(nvmem);
> + return ERR_PTR(rval);
> + }
> +
> + /* update sysfs attributes */
> + if (nvmem->read_only)
> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
> +
> + if (config->cells)
> + nvmem_add_cells(nvmem, config);

I think this would be a better place for the debug message from above.
Additionally we could add the cell count and so on.

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-23 20:10         ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Srinivas,

sorry for the messed up indention.

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/drivers/nvmem/Kconfig
> @@ -0,0 +1,10 @@
> +menuconfig NVMEM
> + tristate "NVMEM Support"
> + select REGMAP
> + help
> + Support for NVMEM devices.
> +
> + This framework is designed to provide a generic interface to NVMEM
> + from both the Linux Kernel and the userspace.

In order to avoid confusion it would be good to write here what does NVMEM mean.

> +
> + If unsure, say no.
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> new file mode 100644
> index 0000000..6df2c69
> --- /dev/null
> +++ b/drivers/nvmem/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for nvmem drivers.
> +#
> +
> +obj-$(CONFIG_NVMEM) += nvmem_core.o
> +nvmem_core-y := core.o
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> new file mode 100644
> index 0000000..17a826d
> --- /dev/null
> +++ b/drivers/nvmem/core.c
> @@ -0,0 +1,398 @@
> +/*
> + * nvmem framework core.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/export.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/init.h>
> +#include <linux/regmap.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>

Sorting alphabetically would by nice

> + [...]
> +/**
> + * nvmem_register() - Register a nvmem device for given nvmem_config.
> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
> + *
> + * @config: nvmem device configuration with which nvmem device is created.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to nvmem_device.
> + */
> +
> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
> +{
> + struct nvmem_device *nvmem;
> + struct regmap *rm;
> + int rval;
> +
> + if (!config->dev)
> + return ERR_PTR(-EINVAL);
> +
> + rm = dev_get_regmap(config->dev, NULL);
> + if (!rm) {
> + dev_err(config->dev, "Regmap not found\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
> + if (!nvmem)
> + return ERR_PTR(-ENOMEM);
> +
> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
> + if (nvmem->id < 0) {
> + kfree(nvmem);
> + return ERR_PTR(nvmem->id);
> + }
> +
> + nvmem->regmap = rm;
> + nvmem->owner = config->owner;
> + nvmem->stride = regmap_get_reg_stride(rm);
> + nvmem->word_size = regmap_get_val_bytes(rm);
> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
> + nvmem->dev.class = &nvmem_class;
> + nvmem->dev.parent = config->dev;
> + nvmem->dev.of_node = config->dev->of_node;
> + dev_set_name(&nvmem->dev, "%s%d",
> + config->name ? : "nvmem", config->id);
> +
> + nvmem->read_only = nvmem->dev.of_node ?
> + of_property_read_bool(nvmem->dev.of_node,
> + "read-only") :
> + config->read_only;
> +
> + device_initialize(&nvmem->dev);
> +
> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
> + dev_name(&nvmem->dev));
> +
> + rval = device_add(&nvmem->dev);
> + if (rval) {
> + ida_simple_remove(&nvmem_ida, nvmem->id);
> + kfree(nvmem);
> + return ERR_PTR(rval);
> + }
> +
> + /* update sysfs attributes */
> + if (nvmem->read_only)
> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
> +
> + if (config->cells)
> + nvmem_add_cells(nvmem, config);

I think this would be a better place for the debug message from above.
Additionally we could add the cell count and so on.

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
  2015-06-22 23:08     ` Srinivas Kandagatla
  (?)
@ 2015-06-23 20:16         ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:16 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/include/linux/nvmem-consumer.h
> @@ -0,0 +1,75 @@
> +/*
> + * nvmem framework consumer.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_NVMEM_CONSUMER_H
> +#define _LINUX_NVMEM_CONSUMER_H
> +
> +struct device;

Do we need forward declaration of struct device_node too?

> +/* consumer cookie */
> [...]
> +}
> +#endif /* CONFIG_NVMEM */
> +
> +#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
> +struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name);
> +#else
> +static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name)
> +{
> + return ERR_PTR(-ENOSYS);
> +}
> +#endif /* CONFIG_NVMEM && CONFIG_OF */
> +
> +#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
> --
> 1.9.1

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-23 20:16         ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:16 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/include/linux/nvmem-consumer.h
> @@ -0,0 +1,75 @@
> +/*
> + * nvmem framework consumer.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_NVMEM_CONSUMER_H
> +#define _LINUX_NVMEM_CONSUMER_H
> +
> +struct device;

Do we need forward declaration of struct device_node too?

> +/* consumer cookie */
> [...]
> +}
> +#endif /* CONFIG_NVMEM */
> +
> +#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
> +struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name);
> +#else
> +static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name)
> +{
> + return ERR_PTR(-ENOSYS);
> +}
> +#endif /* CONFIG_NVMEM && CONFIG_OF */
> +
> +#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
> --
> 1.9.1

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-23 20:16         ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:16 UTC (permalink / raw)
  To: linux-arm-kernel


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> [...]
> --- /dev/null
> +++ b/include/linux/nvmem-consumer.h
> @@ -0,0 +1,75 @@
> +/*
> + * nvmem framework consumer.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_NVMEM_CONSUMER_H
> +#define _LINUX_NVMEM_CONSUMER_H
> +
> +struct device;

Do we need forward declaration of struct device_node too?

> +/* consumer cookie */
> [...]
> +}
> +#endif /* CONFIG_NVMEM */
> +
> +#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
> +struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name);
> +#else
> +static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
> + const char *name)
> +{
> + return ERR_PTR(-ENOSYS);
> +}
> +#endif /* CONFIG_NVMEM && CONFIG_OF */
> +
> +#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
> --
> 1.9.1

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
  2015-06-22 23:08   ` Srinivas Kandagatla
  (?)
@ 2015-06-23 20:28       ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:28 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> This patch adds read/write apis which are based on nvmem_device. It is
> common that the drivers like omap cape manager or qcom cpr driver to
> access bytes directly at particular offset in the eeprom and not from
> nvmem cell info in DT. These driver would need to get access to the nvmem
> directly, which is what these new APIS provide.
>
> [...]
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 123af62..f9acc43 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -15,6 +15,15 @@
> struct device;
> /* consumer cookie */
> struct nvmem_cell;
> +struct nvmem_device;
> +
> +struct nvmem_cell_info {
> + const char *name;
> + int offset;
> + int bytes;
> + int bit_offset;
> + int nbits;
> +};
>
> #if IS_ENABLED(CONFIG_NVMEM)
>
> @@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
> nvmem_cell *cell);
> void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
> int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>
> +/* direct nvmem device read/write interface */
> +struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
> +struct nvmem_device *devm_nvmem_device_get(struct device *dev,
> + const char *name);
> +void nvmem_device_put(struct nvmem_device *nvmem);
> +void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
> +int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);
> +int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);

Maybe i mixed something but those functions use the datatype unsigned int for
offset
and the offset in the structs use datatype int. Looks a little bit inconsistent.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
@ 2015-06-23 20:28       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:28 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> This patch adds read/write apis which are based on nvmem_device. It is
> common that the drivers like omap cape manager or qcom cpr driver to
> access bytes directly at particular offset in the eeprom and not from
> nvmem cell info in DT. These driver would need to get access to the nvmem
> directly, which is what these new APIS provide.
>
> [...]
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 123af62..f9acc43 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -15,6 +15,15 @@
> struct device;
> /* consumer cookie */
> struct nvmem_cell;
> +struct nvmem_device;
> +
> +struct nvmem_cell_info {
> + const char *name;
> + int offset;
> + int bytes;
> + int bit_offset;
> + int nbits;
> +};
>
> #if IS_ENABLED(CONFIG_NVMEM)
>
> @@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
> nvmem_cell *cell);
> void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
> int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>
> +/* direct nvmem device read/write interface */
> +struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
> +struct nvmem_device *devm_nvmem_device_get(struct device *dev,
> + const char *name);
> +void nvmem_device_put(struct nvmem_device *nvmem);
> +void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
> +int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);
> +int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);

Maybe i mixed something but those functions use the datatype unsigned int for
offset
and the offset in the structs use datatype int. Looks a little bit inconsistent.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
@ 2015-06-23 20:28       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:28 UTC (permalink / raw)
  To: linux-arm-kernel


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> This patch adds read/write apis which are based on nvmem_device. It is
> common that the drivers like omap cape manager or qcom cpr driver to
> access bytes directly at particular offset in the eeprom and not from
> nvmem cell info in DT. These driver would need to get access to the nvmem
> directly, which is what these new APIS provide.
>
> [...]
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 123af62..f9acc43 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -15,6 +15,15 @@
> struct device;
> /* consumer cookie */
> struct nvmem_cell;
> +struct nvmem_device;
> +
> +struct nvmem_cell_info {
> + const char *name;
> + int offset;
> + int bytes;
> + int bit_offset;
> + int nbits;
> +};
>
> #if IS_ENABLED(CONFIG_NVMEM)
>
> @@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
> nvmem_cell *cell);
> void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
> int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>
> +/* direct nvmem device read/write interface */
> +struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
> +struct nvmem_device *devm_nvmem_device_get(struct device *dev,
> + const char *name);
> +void nvmem_device_put(struct nvmem_device *nvmem);
> +void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
> +int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);
> +int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
> + size_t bytes, void *buf);

Maybe i mixed something but those functions use the datatype unsigned int for
offset
and the offset in the structs use datatype int. Looks a little bit inconsistent.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
  2015-06-22 23:08     ` Srinivas Kandagatla
@ 2015-06-23 20:35       ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:35 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> This patch adds bindings for simple nvmem framework which allows nvmem
> consumers to talk to nvmem providers to get access to nvmem cell data.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> [Maxime Ripard: intial version of eeprom framework]
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
> Documentation/devicetree/bindings/nvmem/nvmem.txt | 85 +++++++++++++++++++++++
> 1 file changed, 85 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt
>
> diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt
> b/Documentation/devicetree/bindings/nvmem/nvmem.txt
> new file mode 100644
> index 0000000..d1a37e7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
> @@ -0,0 +1,85 @@
> += NVMEM(Non Volatile Memory) Data Device Tree Bindings =
> +
> +This binding is intended to represent the location of hardware
> +configuration data stored in NVMEMs like eeprom, efuses and so on.
> +
> +On a significant proportion of boards, the manufacturer has stored
> +some data on NVMEM, for the OS to be able to retrieve these information
> +and act upon it. Obviously, the OS has to know about where to retrieve
> +these data from, and where they are stored on the storage device.
> +
> +This document is here to document this.
> +
> += Data providers =
> +Contains bindings specific to provider drivers and data cells as children
> +of this node.
> +
> +Optional properties:
> + read-only: Mark the provider as read only.
> +
> += Data cells =
> +These are the child nodes of the provider which contain data cell
> +information like offset and size in nvmem provider.
> +
> +Required properties:
> +reg: specifies the offset in byte within that storage device, start bit
> + in the byte and the length in bits of the data we care about.

Is the second parameter really in bits, not bytes?

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
@ 2015-06-23 20:35       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:35 UTC (permalink / raw)
  To: linux-arm-kernel


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:08 geschrieben:
>
>
> This patch adds bindings for simple nvmem framework which allows nvmem
> consumers to talk to nvmem providers to get access to nvmem cell data.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> [Maxime Ripard: intial version of eeprom framework]
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
> Documentation/devicetree/bindings/nvmem/nvmem.txt | 85 +++++++++++++++++++++++
> 1 file changed, 85 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem.txt
>
> diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt
> b/Documentation/devicetree/bindings/nvmem/nvmem.txt
> new file mode 100644
> index 0000000..d1a37e7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
> @@ -0,0 +1,85 @@
> += NVMEM(Non Volatile Memory) Data Device Tree Bindings =
> +
> +This binding is intended to represent the location of hardware
> +configuration data stored in NVMEMs like eeprom, efuses and so on.
> +
> +On a significant proportion of boards, the manufacturer has stored
> +some data on NVMEM, for the OS to be able to retrieve these information
> +and act upon it. Obviously, the OS has to know about where to retrieve
> +these data from, and where they are stored on the storage device.
> +
> +This document is here to document this.
> +
> += Data providers =
> +Contains bindings specific to provider drivers and data cells as children
> +of this node.
> +
> +Optional properties:
> + read-only: Mark the provider as read only.
> +
> += Data cells =
> +These are the child nodes of the provider which contain data cell
> +information like offset and size in nvmem provider.
> +
> +Required properties:
> +reg: specifies the offset in byte within that storage device, start bit
> + in the byte and the length in bits of the data we care about.

Is the second parameter really in bits, not bytes?

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
  2015-06-22 23:09     ` Srinivas Kandagatla
@ 2015-06-23 20:44       ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:44 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:09 geschrieben:
>
>
> From: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Now that we have the nvmem framework, we can consolidate the common
> driver code. Move the driver to the framework, and hopefully, it will
> fix the sysfs file creation race.
> --- /dev/null
> +++ b/drivers/nvmem/sunxi-sid.c
> [...]
> +
> +static int sunxi_sid_write(void *context, const void *data, size_t count)
> +{
> + /* Unimplemented */
> + return 0;
> +}
> +

I think it should be clear that the write operation isn't implemented. It's more
important to know the function should make
regmap_init happy.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
@ 2015-06-23 20:44       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-23 20:44 UTC (permalink / raw)
  To: linux-arm-kernel


> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> 01:09 geschrieben:
>
>
> From: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Now that we have the nvmem framework, we can consolidate the common
> driver code. Move the driver to the framework, and hopefully, it will
> fix the sysfs file creation race.
> --- /dev/null
> +++ b/drivers/nvmem/sunxi-sid.c
> [...]
> +
> +static int sunxi_sid_write(void *context, const void *data, size_t count)
> +{
> + /* Unimplemented */
> + return 0;
> +}
> +

I think it should be clear that the write operation isn't implemented. It's more
important to know the function should make
regmap_init happy.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-23 19:47     ` Stefan Wahren
@ 2015-06-24  5:54       ` Sanchayan Maity
  -1 siblings, 0 replies; 92+ messages in thread
From: Sanchayan Maity @ 2015-06-24  5:54 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel, devicetree,
	arnd, linux-api, s.hauer, sboyd, linux-kernel, pantelis.antoniou,
	Rob Herring, Mark Brown, Kumar Gala, mporter, Maxime Ripard,
	linux-arm-msm, wxt

Hello,

On 15-06-23 21:47:34, Stefan Wahren wrote:
> Hi Srinivas,
> 
> > Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> > 01:07 geschrieben:
> >
> >
> > [...]
> >
> > Device Tree:
> >
> > /* Provider */
> > qfprom: qfprom@00700000 {
> > ...
> >
> > /* Data cells */
> > tsens_calibration: calib@404 {
> > reg = <0x404 0x10>;
> > };
> >
> > tsens_calibration_bckp: calib_bckp@504 {
> > reg = <0x504 0x11>;
> > bit-offset = 6;
> > nbits = 128;
> > };
> >
> > pvs_version: pvs-version@6 {
> > reg = <0x6 0x2>
> > bit-offset = 7;
> > nbits = 2;
> > };
> >
> > speed_bin: speed-bin@c{
> > reg = <0xc 0x1>;
> > bit-offset = 2;
> > nbits = 3;
> >
> > };
> > ...
> > };
> >
> > userspace interface: binary file in /sys/class/nvmem/*/nvmem
> >
> > ex:
> > hexdump /sys/class/nvmem/qfprom0/nvmem
> >
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > *
> > 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > ...
> > *
> > 0001000
> >
> 
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
> hexdump would readout the complete register range defined in provider DT node.
> 
> How can i achieve that hexdump only reads the data area within the register
> range?

I also had a similar question in my mind.

- Sanchayan.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24  5:54       ` Sanchayan Maity
  0 siblings, 0 replies; 92+ messages in thread
From: Sanchayan Maity @ 2015-06-24  5:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On 15-06-23 21:47:34, Stefan Wahren wrote:
> Hi Srinivas,
> 
> > Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> > 01:07 geschrieben:
> >
> >
> > [...]
> >
> > Device Tree:
> >
> > /* Provider */
> > qfprom: qfprom at 00700000 {
> > ...
> >
> > /* Data cells */
> > tsens_calibration: calib at 404 {
> > reg = <0x404 0x10>;
> > };
> >
> > tsens_calibration_bckp: calib_bckp at 504 {
> > reg = <0x504 0x11>;
> > bit-offset = 6;
> > nbits = 128;
> > };
> >
> > pvs_version: pvs-version at 6 {
> > reg = <0x6 0x2>
> > bit-offset = 7;
> > nbits = 2;
> > };
> >
> > speed_bin: speed-bin at c{
> > reg = <0xc 0x1>;
> > bit-offset = 2;
> > nbits = 3;
> >
> > };
> > ...
> > };
> >
> > userspace interface: binary file in /sys/class/nvmem/*/nvmem
> >
> > ex:
> > hexdump /sys/class/nvmem/qfprom0/nvmem
> >
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > *
> > 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > ...
> > *
> > 0001000
> >
> 
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
> hexdump would readout the complete register range defined in provider DT node.
> 
> How can i achieve that hexdump only reads the data area within the register
> range?

I also had a similar question in my mind.

- Sanchayan.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-23 19:47     ` Stefan Wahren
@ 2015-06-24  9:46       ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:46 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 20:47, Stefan Wahren wrote:
>> 0001000
>> >
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
That's cool.

> hexdump would readout the complete register range defined in provider DT node.
>
> How can i achieve that hexdump only reads the data area within the register
> range?

If the question is just about hexdump, then hexdump itself can read file 
from given offset and size.

But I believe the real question is "How can we dump each nvmem cell 
independently"

In one of my replies I mentioned that am planning to add sysfs entries 
under /sys/class/nvmem/<provider>/cells/

ex:
for qfprom tsens calibration it would look like:

$ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration

0000000 e000 0c00 0c00 0000 0c00
...

Is that what you guys are looking for?

--srini
>
> Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24  9:46       ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:46 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 20:47, Stefan Wahren wrote:
>> 0001000
>> >
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
That's cool.

> hexdump would readout the complete register range defined in provider DT node.
>
> How can i achieve that hexdump only reads the data area within the register
> range?

If the question is just about hexdump, then hexdump itself can read file 
from given offset and size.

But I believe the real question is "How can we dump each nvmem cell 
independently"

In one of my replies I mentioned that am planning to add sysfs entries 
under /sys/class/nvmem/<provider>/cells/

ex:
for qfprom tsens calibration it would look like:

$ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration

0000000 e000 0c00 0c00 0000 0c00
...

Is that what you guys are looking for?

--srini
>
> Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
  2015-06-23 20:44       ` Stefan Wahren
@ 2015-06-24  9:48         ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:48 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 21:44, Stefan Wahren wrote:
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
>> 01:09 geschrieben:
>>
>>
>> From: Maxime Ripard <maxime.ripard@free-electrons.com>
>>
>> Now that we have the nvmem framework, we can consolidate the common
>> driver code. Move the driver to the framework, and hopefully, it will
>> fix the sysfs file creation race.
>> --- /dev/null
>> +++ b/drivers/nvmem/sunxi-sid.c
>> [...]
>> +
>> +static int sunxi_sid_write(void *context, const void *data, size_t count)
>> +{
>> + /* Unimplemented */
>> + return 0;
>> +}
>> +
>
> I think it should be clear that the write operation isn't implemented. It's more
> important to know the function should make
> regmap_init happy.


I totally agree with you.. It was just to make regmap_init happy. Indeed 
I thought of adding this comment, but forgot over the time :-) I will 
fix it.

--srini


> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
@ 2015-06-24  9:48         ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:48 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 21:44, Stefan Wahren wrote:
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
>> 01:09 geschrieben:
>>
>>
>> From: Maxime Ripard <maxime.ripard@free-electrons.com>
>>
>> Now that we have the nvmem framework, we can consolidate the common
>> driver code. Move the driver to the framework, and hopefully, it will
>> fix the sysfs file creation race.
>> --- /dev/null
>> +++ b/drivers/nvmem/sunxi-sid.c
>> [...]
>> +
>> +static int sunxi_sid_write(void *context, const void *data, size_t count)
>> +{
>> + /* Unimplemented */
>> + return 0;
>> +}
>> +
>
> I think it should be clear that the write operation isn't implemented. It's more
> important to know the function should make
> regmap_init happy.


I totally agree with you.. It was just to make regmap_init happy. Indeed 
I thought of adding this comment, but forgot over the time :-) I will 
fix it.

--srini


> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
  2015-06-23  9:25         ` Rajendra Nayak
@ 2015-06-24  9:49           ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:49 UTC (permalink / raw)
  To: Rajendra Nayak, linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt



On 23/06/15 10:25, Rajendra Nayak wrote:
> []..
>
>> +Example:
>> +
>> +    qfprom: qfprom@00700000 {
>> +        compatible     = "qcom,qfprom";
>> +        reg        = <0x00700000 0x8000>;
>> +        ...
>> +        /* Data cells */
>> +        tsens_calibration: calib@404 {
>> +            reg = <0x4404 0x10>;
>> +        };
>> +    };
>> +
>> +
>> += Data consumers =
>> +Are device nodes which consume nvmem data cells.
>> +
>> +For example:
>> +
>> +    tsens {
>> +        ...
>> +        nvmem-cell = <&tsens_calibration>;
>
> Shouldn't this be nvmem-cells instead?
>
You are correct, Will fix it in next version.

--srini
>> +        nvmem-cell-names = "calibration";
>> +    };
>>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
@ 2015-06-24  9:49           ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:49 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 10:25, Rajendra Nayak wrote:
> []..
>
>> +Example:
>> +
>> +    qfprom: qfprom at 00700000 {
>> +        compatible     = "qcom,qfprom";
>> +        reg        = <0x00700000 0x8000>;
>> +        ...
>> +        /* Data cells */
>> +        tsens_calibration: calib at 404 {
>> +            reg = <0x4404 0x10>;
>> +        };
>> +    };
>> +
>> +
>> += Data consumers =
>> +Are device nodes which consume nvmem data cells.
>> +
>> +For example:
>> +
>> +    tsens {
>> +        ...
>> +        nvmem-cell = <&tsens_calibration>;
>
> Shouldn't this be nvmem-cells instead?
>
You are correct, Will fix it in next version.

--srini
>> +        nvmem-cell-names = "calibration";
>> +    };
>>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
  2015-06-23 20:35       ` Stefan Wahren
  (?)
@ 2015-06-24  9:51           ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:51 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown



On 23/06/15 21:35, Stefan Wahren wrote:
>> +Required properties:
>> >+reg: specifies the offset in byte within that storage device, start bit
>> >+ in the byte and the length in bits of the data we care about.
> Is the second parameter really in bits, not bytes?
Thanks for spotting this, I will fix this.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
@ 2015-06-24  9:51           ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:51 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 21:35, Stefan Wahren wrote:
>> +Required properties:
>> >+reg: specifies the offset in byte within that storage device, start bit
>> >+ in the byte and the length in bits of the data we care about.
> Is the second parameter really in bits, not bytes?
Thanks for spotting this, I will fix this.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
@ 2015-06-24  9:51           ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:51 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 21:35, Stefan Wahren wrote:
>> +Required properties:
>> >+reg: specifies the offset in byte within that storage device, start bit
>> >+ in the byte and the length in bits of the data we care about.
> Is the second parameter really in bits, not bytes?
Thanks for spotting this, I will fix this.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
  2015-06-23 20:28       ` Stefan Wahren
@ 2015-06-24  9:52         ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:52 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 21:28, Stefan Wahren wrote:
>> >@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
>> >nvmem_cell *cell);
>> >void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
>> >int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>> >
>> >+/* direct nvmem device read/write interface */
>> >+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
>> >+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
>> >+ const char *name);
>> >+void nvmem_device_put(struct nvmem_device *nvmem);
>> >+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
>> >+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
>> >+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
> Maybe i mixed something but those functions use the datatype unsigned int for
> offset
> and the offset in the structs use datatype int. Looks a little bit inconsistent.
thanks for comments,

I will have a relook at this and see if I can fix it.

thanks,
srini

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
@ 2015-06-24  9:52         ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:52 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 21:28, Stefan Wahren wrote:
>> >@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
>> >nvmem_cell *cell);
>> >void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
>> >int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>> >
>> >+/* direct nvmem device read/write interface */
>> >+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
>> >+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
>> >+ const char *name);
>> >+void nvmem_device_put(struct nvmem_device *nvmem);
>> >+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
>> >+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
>> >+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
> Maybe i mixed something but those functions use the datatype unsigned int for
> offset
> and the offset in the structs use datatype int. Looks a little bit inconsistent.
thanks for comments,

I will have a relook at this and see if I can fix it.

thanks,
srini

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
  2015-06-23 20:16         ` Stefan Wahren
  (?)
@ 2015-06-24  9:53             ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:53 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown



On 23/06/15 21:16, Stefan Wahren wrote:
>> +
>> >+struct device;
> Do we need forward declaration of struct device_node too?
>
Yep, Will fix it in next version.
--srini
>> >+/* consumer cookie */
>> >[...]

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-24  9:53             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:53 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 21:16, Stefan Wahren wrote:
>> +
>> >+struct device;
> Do we need forward declaration of struct device_node too?
>
Yep, Will fix it in next version.
--srini
>> >+/* consumer cookie */
>> >[...]

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
@ 2015-06-24  9:53             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:53 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 21:16, Stefan Wahren wrote:
>> +
>> >+struct device;
> Do we need forward declaration of struct device_node too?
>
Yep, Will fix it in next version.
--srini
>> >+/* consumer cookie */
>> >[...]

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-23 20:10         ` Stefan Wahren
  (?)
@ 2015-06-24  9:54             ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:54 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown



On 23/06/15 21:10, Stefan Wahren wrote:
> Hi Srinivas,
>
> sorry for the messed up indention.
>
NP,
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/nvmem-provider.h>
>> +#include <linux/export.h>
>> +#include <linux/fs.h>
>> +#include <linux/idr.h>
>> +#include <linux/init.h>
>> +#include <linux/regmap.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>
> Sorting alphabetically would by nice
>
Good Idea.

>> + [...]
>> +/**
>> + * nvmem_register() - Register a nvmem device for given nvmem_config.
>> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
>> + *
>> + * @config: nvmem device configuration with which nvmem device is created.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to nvmem_device.
>> + */
>> +
>> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
>> +{
>> + struct nvmem_device *nvmem;
>> + struct regmap *rm;
>> + int rval;
>> +
>> + if (!config->dev)
>> + return ERR_PTR(-EINVAL);
>> +
>> + rm = dev_get_regmap(config->dev, NULL);
>> + if (!rm) {
>> + dev_err(config->dev, "Regmap not found\n");
>> + return ERR_PTR(-EINVAL);
>> + }
>> +
>> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
>> + if (!nvmem)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
>> + if (nvmem->id < 0) {
>> + kfree(nvmem);
>> + return ERR_PTR(nvmem->id);
>> + }
>> +
>> + nvmem->regmap = rm;
>> + nvmem->owner = config->owner;
>> + nvmem->stride = regmap_get_reg_stride(rm);
>> + nvmem->word_size = regmap_get_val_bytes(rm);
>> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
>> + nvmem->dev.class = &nvmem_class;
>> + nvmem->dev.parent = config->dev;
>> + nvmem->dev.of_node = config->dev->of_node;
>> + dev_set_name(&nvmem->dev, "%s%d",
>> + config->name ? : "nvmem", config->id);
>> +
>> + nvmem->read_only = nvmem->dev.of_node ?
>> + of_property_read_bool(nvmem->dev.of_node,
>> + "read-only") :
>> + config->read_only;
>> +
>> + device_initialize(&nvmem->dev);
>> +
>> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
>> + dev_name(&nvmem->dev));
>> +
>> + rval = device_add(&nvmem->dev);
>> + if (rval) {
>> + ida_simple_remove(&nvmem_ida, nvmem->id);
>> + kfree(nvmem);
>> + return ERR_PTR(rval);
>> + }
>> +
>> + /* update sysfs attributes */
>> + if (nvmem->read_only)
>> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
>> +
>> + if (config->cells)
>> + nvmem_add_cells(nvmem, config);
>
> I think this would be a better place for the debug message from above.
> Additionally we could add the cell count and so on.
I will give it a try.

thanks,
srini
>
> Stefan
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-24  9:54             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:54 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown



On 23/06/15 21:10, Stefan Wahren wrote:
> Hi Srinivas,
>
> sorry for the messed up indention.
>
NP,
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/nvmem-provider.h>
>> +#include <linux/export.h>
>> +#include <linux/fs.h>
>> +#include <linux/idr.h>
>> +#include <linux/init.h>
>> +#include <linux/regmap.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>
> Sorting alphabetically would by nice
>
Good Idea.

>> + [...]
>> +/**
>> + * nvmem_register() - Register a nvmem device for given nvmem_config.
>> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
>> + *
>> + * @config: nvmem device configuration with which nvmem device is created.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to nvmem_device.
>> + */
>> +
>> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
>> +{
>> + struct nvmem_device *nvmem;
>> + struct regmap *rm;
>> + int rval;
>> +
>> + if (!config->dev)
>> + return ERR_PTR(-EINVAL);
>> +
>> + rm = dev_get_regmap(config->dev, NULL);
>> + if (!rm) {
>> + dev_err(config->dev, "Regmap not found\n");
>> + return ERR_PTR(-EINVAL);
>> + }
>> +
>> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
>> + if (!nvmem)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
>> + if (nvmem->id < 0) {
>> + kfree(nvmem);
>> + return ERR_PTR(nvmem->id);
>> + }
>> +
>> + nvmem->regmap = rm;
>> + nvmem->owner = config->owner;
>> + nvmem->stride = regmap_get_reg_stride(rm);
>> + nvmem->word_size = regmap_get_val_bytes(rm);
>> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
>> + nvmem->dev.class = &nvmem_class;
>> + nvmem->dev.parent = config->dev;
>> + nvmem->dev.of_node = config->dev->of_node;
>> + dev_set_name(&nvmem->dev, "%s%d",
>> + config->name ? : "nvmem", config->id);
>> +
>> + nvmem->read_only = nvmem->dev.of_node ?
>> + of_property_read_bool(nvmem->dev.of_node,
>> + "read-only") :
>> + config->read_only;
>> +
>> + device_initialize(&nvmem->dev);
>> +
>> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
>> + dev_name(&nvmem->dev));
>> +
>> + rval = device_add(&nvmem->dev);
>> + if (rval) {
>> + ida_simple_remove(&nvmem_ida, nvmem->id);
>> + kfree(nvmem);
>> + return ERR_PTR(rval);
>> + }
>> +
>> + /* update sysfs attributes */
>> + if (nvmem->read_only)
>> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
>> +
>> + if (config->cells)
>> + nvmem_add_cells(nvmem, config);
>
> I think this would be a better place for the debug message from above.
> Additionally we could add the cell count and so on.
I will give it a try.

thanks,
srini
>
> Stefan
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-24  9:54             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:54 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 21:10, Stefan Wahren wrote:
> Hi Srinivas,
>
> sorry for the messed up indention.
>
NP,
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/nvmem-provider.h>
>> +#include <linux/export.h>
>> +#include <linux/fs.h>
>> +#include <linux/idr.h>
>> +#include <linux/init.h>
>> +#include <linux/regmap.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>
> Sorting alphabetically would by nice
>
Good Idea.

>> + [...]
>> +/**
>> + * nvmem_register() - Register a nvmem device for given nvmem_config.
>> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
>> + *
>> + * @config: nvmem device configuration with which nvmem device is created.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to nvmem_device.
>> + */
>> +
>> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
>> +{
>> + struct nvmem_device *nvmem;
>> + struct regmap *rm;
>> + int rval;
>> +
>> + if (!config->dev)
>> + return ERR_PTR(-EINVAL);
>> +
>> + rm = dev_get_regmap(config->dev, NULL);
>> + if (!rm) {
>> + dev_err(config->dev, "Regmap not found\n");
>> + return ERR_PTR(-EINVAL);
>> + }
>> +
>> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
>> + if (!nvmem)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
>> + if (nvmem->id < 0) {
>> + kfree(nvmem);
>> + return ERR_PTR(nvmem->id);
>> + }
>> +
>> + nvmem->regmap = rm;
>> + nvmem->owner = config->owner;
>> + nvmem->stride = regmap_get_reg_stride(rm);
>> + nvmem->word_size = regmap_get_val_bytes(rm);
>> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
>> + nvmem->dev.class = &nvmem_class;
>> + nvmem->dev.parent = config->dev;
>> + nvmem->dev.of_node = config->dev->of_node;
>> + dev_set_name(&nvmem->dev, "%s%d",
>> + config->name ? : "nvmem", config->id);
>> +
>> + nvmem->read_only = nvmem->dev.of_node ?
>> + of_property_read_bool(nvmem->dev.of_node,
>> + "read-only") :
>> + config->read_only;
>> +
>> + device_initialize(&nvmem->dev);
>> +
>> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
>> + dev_name(&nvmem->dev));
>> +
>> + rval = device_add(&nvmem->dev);
>> + if (rval) {
>> + ida_simple_remove(&nvmem_ida, nvmem->id);
>> + kfree(nvmem);
>> + return ERR_PTR(rval);
>> + }
>> +
>> + /* update sysfs attributes */
>> + if (nvmem->read_only)
>> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
>> +
>> + if (config->cells)
>> + nvmem_add_cells(nvmem, config);
>
> I think this would be a better place for the debug message from above.
> Additionally we could add the cell count and so on.
I will give it a try.

thanks,
srini
>
> Stefan
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
  2015-06-23  9:26         ` Pantelis Antoniou
  (?)
@ 2015-06-24  9:56             ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:56 UTC (permalink / raw)
  To: Pantelis Antoniou, Joe Perches
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Greg Kroah-Hartman, Maxime Ripard, Rob Herring, Kumar Gala,
	Mark Brown, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, Matt Porter,
	stefan.wahren-eS4NqCHxEME, wxt-TNX95d0MmH7DzftRWevZcw



On 23/06/15 10:26, Pantelis Antoniou wrote:
> Hi Joe,
>
>> >On Jun 23, 2015, at 05:52 , Joe Perches<joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>  wrote:
>> >
>> >On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>>> >>This patch adds just providers part of the framework just to enable easy
>>> >>review.
>> >[]
>>> >>include/linux/nvmem-provider.h |  54 ++++++
>> >
>> >Unless there are going to be users of nvmem-provider.h
>> >outside of the drivers/nvmem directory, perhaps that
>> >file (and nvmem-consumer.h) should be in drivers/nvmem/
>> >
>> >
> nvmem-consumer.h should be accessible from any driver, no?
>
> And unfortunately nvmem-provider should be accessible too.
> There are already eeprom drivers in the eeprom/misc directory that
> cannot be moved yet to drivers/nvmem (like at24).
>
> They need the provider definitions while they provide both the old
> style interface, and the new NVMEM based one.
>
> When we move them to the drivers/nvmem directory, then yes the
> provider header file should move there.

Yep, that's the plan.

---srini
>
> Regards
>
> — Pantelis
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-24  9:56             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:56 UTC (permalink / raw)
  To: Pantelis Antoniou, Joe Perches
  Cc: linux-arm-kernel, Greg Kroah-Hartman, Maxime Ripard, Rob Herring,
	Kumar Gala, Mark Brown, s.hauer, linux-api, linux-kernel,
	devicetree, linux-arm-msm, Arnd Bergmann, sboyd, Matt Porter,
	stefan.wahren, wxt



On 23/06/15 10:26, Pantelis Antoniou wrote:
> Hi Joe,
>
>> >On Jun 23, 2015, at 05:52 , Joe Perches<joe@perches.com>  wrote:
>> >
>> >On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>>> >>This patch adds just providers part of the framework just to enable easy
>>> >>review.
>> >[]
>>> >>include/linux/nvmem-provider.h |  54 ++++++
>> >
>> >Unless there are going to be users of nvmem-provider.h
>> >outside of the drivers/nvmem directory, perhaps that
>> >file (and nvmem-consumer.h) should be in drivers/nvmem/
>> >
>> >
> nvmem-consumer.h should be accessible from any driver, no?
>
> And unfortunately nvmem-provider should be accessible too.
> There are already eeprom drivers in the eeprom/misc directory that
> cannot be moved yet to drivers/nvmem (like at24).
>
> They need the provider definitions while they provide both the old
> style interface, and the new NVMEM based one.
>
> When we move them to the drivers/nvmem directory, then yes the
> provider header file should move there.

Yep, that's the plan.

---srini
>
> Regards
>
> — Pantelis
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
@ 2015-06-24  9:56             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24  9:56 UTC (permalink / raw)
  To: linux-arm-kernel



On 23/06/15 10:26, Pantelis Antoniou wrote:
> Hi Joe,
>
>> >On Jun 23, 2015, at 05:52 , Joe Perches<joe@perches.com>  wrote:
>> >
>> >On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>>> >>This patch adds just providers part of the framework just to enable easy
>>> >>review.
>> >[]
>>> >>include/linux/nvmem-provider.h |  54 ++++++
>> >
>> >Unless there are going to be users of nvmem-provider.h
>> >outside of the drivers/nvmem directory, perhaps that
>> >file (and nvmem-consumer.h) should be in drivers/nvmem/
>> >
>> >
> nvmem-consumer.h should be accessible from any driver, no?
>
> And unfortunately nvmem-provider should be accessible too.
> There are already eeprom drivers in the eeprom/misc directory that
> cannot be moved yet to drivers/nvmem (like at24).
>
> They need the provider definitions while they provide both the old
> style interface, and the new NVMEM based one.
>
> When we move them to the drivers/nvmem directory, then yes the
> provider header file should move there.

Yep, that's the plan.

---srini
>
> Regards
>
> ? Pantelis
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-24  9:46       ` Srinivas Kandagatla
@ 2015-06-24 12:30         ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-24 12:30 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel
  Cc: Greg Kroah-Hartman, wxt, linux-api, Kumar Gala, Rob Herring,
	sboyd, arnd, s.hauer, linux-kernel, linux-arm-msm, mporter,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown

Hi Srinivas,

Am 24.06.2015 um 11:46 schrieb Srinivas Kandagatla:
>
>
> On 23/06/15 20:47, Stefan Wahren wrote:
>>> 0001000
>>> >
>> i want to port OCOTP driver for MXS, which hasn't MMIO. From my
>> understanding
> That's cool.
>
>> hexdump would readout the complete register range defined in provider
>> DT node.
>>
>> How can i achieve that hexdump only reads the data area within the
>> register
>> range?
>
> If the question is just about hexdump, then hexdump itself can read
> file from given offset and size.

yes, this is my question at first. Let me show the difference between
the current implementation and my expectations as a user.

$ hexdump /sys/class/nvmem/mxs-ocotp/nvmem

Current implementation: dump the complete register range defined in DT

User expectation: dump only the data from OCOTP block

Let me explain it for i.MX28 OCOTP

0x8002c000 // Start of OCOTP register block (defined in DT)

0x8002c020 // First data register

0x8002c290 // Last data register

0x8002dfff // End of OCOTP register block (defined in DT)

My knowledge about regmap is limited, but how can i achieve that hexdump
give me only the data registers? From my understanding this should be
handled in regmap and not in the read function.

Are my expectations about the raw access wrong?


>
> But I believe the real question is "How can we dump each nvmem cell
> independently"
>
> In one of my replies I mentioned that am planning to add sysfs entries
> under /sys/class/nvmem/<provider>/cells/
>
> ex:
> for qfprom tsens calibration it would look like:
>
> $ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration
>
> 0000000 e000 0c00 0c00 0000 0c00
> ...
>
> Is that what you guys are looking for?

That would be nice, too :-)

>
> --srini
>>
>> Stefan

TIA

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 12:30         ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-24 12:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Srinivas,

Am 24.06.2015 um 11:46 schrieb Srinivas Kandagatla:
>
>
> On 23/06/15 20:47, Stefan Wahren wrote:
>>> 0001000
>>> >
>> i want to port OCOTP driver for MXS, which hasn't MMIO. From my
>> understanding
> That's cool.
>
>> hexdump would readout the complete register range defined in provider
>> DT node.
>>
>> How can i achieve that hexdump only reads the data area within the
>> register
>> range?
>
> If the question is just about hexdump, then hexdump itself can read
> file from given offset and size.

yes, this is my question at first. Let me show the difference between
the current implementation and my expectations as a user.

$ hexdump /sys/class/nvmem/mxs-ocotp/nvmem

Current implementation: dump the complete register range defined in DT

User expectation: dump only the data from OCOTP block

Let me explain it for i.MX28 OCOTP

0x8002c000 // Start of OCOTP register block (defined in DT)

0x8002c020 // First data register

0x8002c290 // Last data register

0x8002dfff // End of OCOTP register block (defined in DT)

My knowledge about regmap is limited, but how can i achieve that hexdump
give me only the data registers? From my understanding this should be
handled in regmap and not in the read function.

Are my expectations about the raw access wrong?


>
> But I believe the real question is "How can we dump each nvmem cell
> independently"
>
> In one of my replies I mentioned that am planning to add sysfs entries
> under /sys/class/nvmem/<provider>/cells/
>
> ex:
> for qfprom tsens calibration it would look like:
>
> $ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration
>
> 0000000 e000 0c00 0c00 0000 0c00
> ...
>
> Is that what you guys are looking for?

That would be nice, too :-)

>
> --srini
>>
>> Stefan

TIA

Stefan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-24 12:30         ` Stefan Wahren
  (?)
@ 2015-06-24 13:03             ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24 13:03 UTC (permalink / raw)
  To: Stefan Wahren, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Greg Kroah-Hartman, wxt-TNX95d0MmH7DzftRWevZcw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Kumar Gala, Rob Herring,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown



On 24/06/15 13:30, Stefan Wahren wrote:
>> >If the question is just about hexdump, then hexdump itself can read
>> >file from given offset and size.
> yes, this is my question at first. Let me show the difference between
> the current implementation and my expectations as a user.
>
> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>
> Current implementation: dump the complete register range defined in DT
>
Its dumping the range which is specified in the provider regmap. If the 
requirement is to dump only particular range, this has to be made 
explicit while creating regmap, which is to specify the base address to 
start from "First data register" and max_register to be "Last data 
register "- "First data register"

> User expectation: dump only the data from OCOTP block
>
> Let me explain it for i.MX28 OCOTP
>
> 0x8002c000 // Start of OCOTP register block (defined in DT)
>
> 0x8002c020 // First data register
>
> 0x8002c290 // Last data register
>
> 0x8002dfff // End of OCOTP register block (defined in DT)
>
> My knowledge about regmap is limited, but how can i achieve that hexdump
> give me only the data registers? From my understanding this should be
> handled in regmap and not in the read function.

Setup the base and regmap_config correctly in the provider driver before 
calling regmap_init_mmio().

Let me know if you need more details.

--srini

>
> Are my expectations about the raw access wrong?
>
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 13:03             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24 13:03 UTC (permalink / raw)
  To: Stefan Wahren, linux-arm-kernel
  Cc: Greg Kroah-Hartman, wxt, linux-api, Kumar Gala, Rob Herring,
	sboyd, arnd, s.hauer, linux-kernel, linux-arm-msm, mporter,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown



On 24/06/15 13:30, Stefan Wahren wrote:
>> >If the question is just about hexdump, then hexdump itself can read
>> >file from given offset and size.
> yes, this is my question at first. Let me show the difference between
> the current implementation and my expectations as a user.
>
> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>
> Current implementation: dump the complete register range defined in DT
>
Its dumping the range which is specified in the provider regmap. If the 
requirement is to dump only particular range, this has to be made 
explicit while creating regmap, which is to specify the base address to 
start from "First data register" and max_register to be "Last data 
register "- "First data register"

> User expectation: dump only the data from OCOTP block
>
> Let me explain it for i.MX28 OCOTP
>
> 0x8002c000 // Start of OCOTP register block (defined in DT)
>
> 0x8002c020 // First data register
>
> 0x8002c290 // Last data register
>
> 0x8002dfff // End of OCOTP register block (defined in DT)
>
> My knowledge about regmap is limited, but how can i achieve that hexdump
> give me only the data registers? From my understanding this should be
> handled in regmap and not in the read function.

Setup the base and regmap_config correctly in the provider driver before 
calling regmap_init_mmio().

Let me know if you need more details.

--srini

>
> Are my expectations about the raw access wrong?
>
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 13:03             ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24 13:03 UTC (permalink / raw)
  To: linux-arm-kernel



On 24/06/15 13:30, Stefan Wahren wrote:
>> >If the question is just about hexdump, then hexdump itself can read
>> >file from given offset and size.
> yes, this is my question at first. Let me show the difference between
> the current implementation and my expectations as a user.
>
> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>
> Current implementation: dump the complete register range defined in DT
>
Its dumping the range which is specified in the provider regmap. If the 
requirement is to dump only particular range, this has to be made 
explicit while creating regmap, which is to specify the base address to 
start from "First data register" and max_register to be "Last data 
register "- "First data register"

> User expectation: dump only the data from OCOTP block
>
> Let me explain it for i.MX28 OCOTP
>
> 0x8002c000 // Start of OCOTP register block (defined in DT)
>
> 0x8002c020 // First data register
>
> 0x8002c290 // Last data register
>
> 0x8002dfff // End of OCOTP register block (defined in DT)
>
> My knowledge about regmap is limited, but how can i achieve that hexdump
> give me only the data registers? From my understanding this should be
> handled in regmap and not in the read function.

Setup the base and regmap_config correctly in the provider driver before 
calling regmap_init_mmio().

Let me know if you need more details.

--srini

>
> Are my expectations about the raw access wrong?
>
>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-24 13:03             ` Srinivas Kandagatla
  (?)
@ 2015-06-24 17:47                 ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-24 17:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Kumar Gala, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 24. Juni 2015 um
> 15:03 geschrieben:
>
>
>
>
> On 24/06/15 13:30, Stefan Wahren wrote:
> >> >If the question is just about hexdump, then hexdump itself can read
> >> >file from given offset and size.
> > yes, this is my question at first. Let me show the difference between
> > the current implementation and my expectations as a user.
> >
> > $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >
> > Current implementation: dump the complete register range defined in DT
> >
> Its dumping the range which is specified in the provider regmap. If the
> requirement is to dump only particular range, this has to be made
> explicit while creating regmap, which is to specify the base address to
> start from "First data register" and max_register to be "Last data
> register "- "First data register"

i know about max_register, but i can't find the base address in regmap_config.

Do you mean struct regmap_access_table *rd_table ?

>
> > User expectation: dump only the data from OCOTP block
> >
> > Let me explain it for i.MX28 OCOTP
> >
> > 0x8002c000 // Start of OCOTP register block (defined in DT)
> >
> > 0x8002c020 // First data register
> >
> > 0x8002c290 // Last data register
> >
> > 0x8002dfff // End of OCOTP register block (defined in DT)
> >
> > My knowledge about regmap is limited, but how can i achieve that hexdump
> > give me only the data registers? From my understanding this should be
> > handled in regmap and not in the read function.
>
> Setup the base and regmap_config correctly in the provider driver before
> calling regmap_init_mmio().
>
> Let me know if you need more details.

Yes, please.

Stefan

>
> --srini
>
> >
> > Are my expectations about the raw access wrong?
> >
> >
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 17:47                 ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-24 17:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel
  Cc: wxt, linux-api, Rob Herring, Kumar Gala, sboyd, arnd, s.hauer,
	Greg Kroah-Hartman, linux-kernel, linux-arm-msm, mporter,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
> 15:03 geschrieben:
>
>
>
>
> On 24/06/15 13:30, Stefan Wahren wrote:
> >> >If the question is just about hexdump, then hexdump itself can read
> >> >file from given offset and size.
> > yes, this is my question at first. Let me show the difference between
> > the current implementation and my expectations as a user.
> >
> > $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >
> > Current implementation: dump the complete register range defined in DT
> >
> Its dumping the range which is specified in the provider regmap. If the
> requirement is to dump only particular range, this has to be made
> explicit while creating regmap, which is to specify the base address to
> start from "First data register" and max_register to be "Last data
> register "- "First data register"

i know about max_register, but i can't find the base address in regmap_config.

Do you mean struct regmap_access_table *rd_table ?

>
> > User expectation: dump only the data from OCOTP block
> >
> > Let me explain it for i.MX28 OCOTP
> >
> > 0x8002c000 // Start of OCOTP register block (defined in DT)
> >
> > 0x8002c020 // First data register
> >
> > 0x8002c290 // Last data register
> >
> > 0x8002dfff // End of OCOTP register block (defined in DT)
> >
> > My knowledge about regmap is limited, but how can i achieve that hexdump
> > give me only the data registers? From my understanding this should be
> > handled in regmap and not in the read function.
>
> Setup the base and regmap_config correctly in the provider driver before
> calling regmap_init_mmio().
>
> Let me know if you need more details.

Yes, please.

Stefan

>
> --srini
>
> >
> > Are my expectations about the raw access wrong?
> >
> >
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 17:47                 ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-24 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
> 15:03 geschrieben:
>
>
>
>
> On 24/06/15 13:30, Stefan Wahren wrote:
> >> >If the question is just about hexdump, then hexdump itself can read
> >> >file from given offset and size.
> > yes, this is my question at first. Let me show the difference between
> > the current implementation and my expectations as a user.
> >
> > $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >
> > Current implementation: dump the complete register range defined in DT
> >
> Its dumping the range which is specified in the provider regmap. If the
> requirement is to dump only particular range, this has to be made
> explicit while creating regmap, which is to specify the base address to
> start from "First data register" and max_register to be "Last data
> register "- "First data register"

i know about max_register, but i can't find the base address in regmap_config.

Do you mean struct regmap_access_table *rd_table ?

>
> > User expectation: dump only the data from OCOTP block
> >
> > Let me explain it for i.MX28 OCOTP
> >
> > 0x8002c000 // Start of OCOTP register block (defined in DT)
> >
> > 0x8002c020 // First data register
> >
> > 0x8002c290 // Last data register
> >
> > 0x8002dfff // End of OCOTP register block (defined in DT)
> >
> > My knowledge about regmap is limited, but how can i achieve that hexdump
> > give me only the data registers? From my understanding this should be
> > handled in regmap and not in the read function.
>
> Setup the base and regmap_config correctly in the provider driver before
> calling regmap_init_mmio().
>
> Let me know if you need more details.

Yes, please.

Stefan

>
> --srini
>
> >
> > Are my expectations about the raw access wrong?
> >
> >
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-24 17:47                 ` Stefan Wahren
@ 2015-06-24 18:50                   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24 18:50 UTC (permalink / raw)
  To: Stefan Wahren, linux-arm-kernel
  Cc: wxt, linux-api, Rob Herring, Kumar Gala, sboyd, arnd, s.hauer,
	Greg Kroah-Hartman, linux-kernel, linux-arm-msm, mporter,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown



On 24/06/15 18:47, Stefan Wahren wrote:
> Hi Srinivas,
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
>> 15:03 geschrieben:
>>
>>
>>
>>
>> On 24/06/15 13:30, Stefan Wahren wrote:
>>>>> If the question is just about hexdump, then hexdump itself can read
>>>>> file from given offset and size.
>>> yes, this is my question at first. Let me show the difference between
>>> the current implementation and my expectations as a user.
>>>
>>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>>>
>>> Current implementation: dump the complete register range defined in DT
>>>
>> Its dumping the range which is specified in the provider regmap. If the
>> requirement is to dump only particular range, this has to be made
>> explicit while creating regmap, which is to specify the base address to
>> start from "First data register" and max_register to be "Last data
>> register "- "First data register"
>
> i know about max_register, but i can't find the base address in regmap_config.
>
Base is not in the regmap config, its the value which you pass to the

For example, if I had to do similar change to qfprom driver It would 
look like:


 ><-----------------------cut---------------------------------><
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 7f7a82f..26ced95 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -52,9 +52,9 @@ static int qfprom_probe(struct platform_device *pdev)
         if (IS_ERR(base))
                 return PTR_ERR(base);

-       qfprom_regmap_config.max_register = resource_size(res) - 1;
+       qfprom_regmap_config.max_register = my_data_size;

-       regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+       regmap = devm_regmap_init_mmio(dev, base + data_offset, 
&qfprom_regmap_config);
         if (IS_ERR(regmap)) {
                 dev_err(dev, "regmap init failed\n");
                 return PTR_ERR(regmap);
 ><-----------------------cut---------------------------------><


--srini


> Do you mean struct regmap_access_table *rd_table ?
>
>>
>>> User expectation: dump only the data from OCOTP block
>>>
>>> Let me explain it for i.MX28 OCOTP
>>>
>>> 0x8002c000 // Start of OCOTP register block (defined in DT)
>>>
>>> 0x8002c020 // First data register
>>>
>>> 0x8002c290 // Last data register
>>>
>>> 0x8002dfff // End of OCOTP register block (defined in DT)
>>>
>>> My knowledge about regmap is limited, but how can i achieve that hexdump
>>> give me only the data registers? From my understanding this should be
>>> handled in regmap and not in the read function.
>>
>> Setup the base and regmap_config correctly in the provider driver before
>> calling regmap_init_mmio().
>>
>> Let me know if you need more details.
>
> Yes, please.
>
> Stefan
>
>>
>> --srini
>>
>>>
>>> Are my expectations about the raw access wrong?
>>>
>>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-24 18:50                   ` Srinivas Kandagatla
  0 siblings, 0 replies; 92+ messages in thread
From: Srinivas Kandagatla @ 2015-06-24 18:50 UTC (permalink / raw)
  To: linux-arm-kernel



On 24/06/15 18:47, Stefan Wahren wrote:
> Hi Srinivas,
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
>> 15:03 geschrieben:
>>
>>
>>
>>
>> On 24/06/15 13:30, Stefan Wahren wrote:
>>>>> If the question is just about hexdump, then hexdump itself can read
>>>>> file from given offset and size.
>>> yes, this is my question at first. Let me show the difference between
>>> the current implementation and my expectations as a user.
>>>
>>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>>>
>>> Current implementation: dump the complete register range defined in DT
>>>
>> Its dumping the range which is specified in the provider regmap. If the
>> requirement is to dump only particular range, this has to be made
>> explicit while creating regmap, which is to specify the base address to
>> start from "First data register" and max_register to be "Last data
>> register "- "First data register"
>
> i know about max_register, but i can't find the base address in regmap_config.
>
Base is not in the regmap config, its the value which you pass to the

For example, if I had to do similar change to qfprom driver It would 
look like:


 ><-----------------------cut---------------------------------><
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 7f7a82f..26ced95 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -52,9 +52,9 @@ static int qfprom_probe(struct platform_device *pdev)
         if (IS_ERR(base))
                 return PTR_ERR(base);

-       qfprom_regmap_config.max_register = resource_size(res) - 1;
+       qfprom_regmap_config.max_register = my_data_size;

-       regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+       regmap = devm_regmap_init_mmio(dev, base + data_offset, 
&qfprom_regmap_config);
         if (IS_ERR(regmap)) {
                 dev_err(dev, "regmap init failed\n");
                 return PTR_ERR(regmap);
 ><-----------------------cut---------------------------------><


--srini


> Do you mean struct regmap_access_table *rd_table ?
>
>>
>>> User expectation: dump only the data from OCOTP block
>>>
>>> Let me explain it for i.MX28 OCOTP
>>>
>>> 0x8002c000 // Start of OCOTP register block (defined in DT)
>>>
>>> 0x8002c020 // First data register
>>>
>>> 0x8002c290 // Last data register
>>>
>>> 0x8002dfff // End of OCOTP register block (defined in DT)
>>>
>>> My knowledge about regmap is limited, but how can i achieve that hexdump
>>> give me only the data registers? From my understanding this should be
>>> handled in regmap and not in the read function.
>>
>> Setup the base and regmap_config correctly in the provider driver before
>> calling regmap_init_mmio().
>>
>> Let me know if you need more details.
>
> Yes, please.
>
> Stefan
>
>>
>> --srini
>>
>>>
>>> Are my expectations about the raw access wrong?
>>>
>>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply related	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
  2015-06-22 23:09   ` Srinivas Kandagatla
  (?)
@ 2015-06-24 22:07       ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-06-24 22:07 UTC (permalink / raw)
  To: Srinivas Kandagatla,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w, stefan.wahren-eS4NqCHxEME,
	wxt-TNX95d0MmH7DzftRWevZcw

On 06/22/2015 04:09 PM, Srinivas Kandagatla wrote:
> diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
> new file mode 100644
> index 0000000..7f7a82f
> --- /dev/null
> +++ b/drivers/nvmem/qfprom.c
> @@ -0,0 +1,89 @@
>
> +
> +#include <linux/platform_device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +#include <linux/device.h>
> +#include <linux/io.h>

Is this include used?

> +#include <linux/module.h>
> +#include <linux/delay.h>

Is this include used?

> +#include <linux/of.h>
> +
> +static struct regmap_config qfprom_regmap_config = {

Can this be const?

> +	.reg_bits = 32,
> +	.val_bits = 8,
> +	.reg_stride = 1,
> +};
> +
> +static struct nvmem_config econfig = {

And this one too?

> +	.name = "qfprom",
> +	.owner = THIS_MODULE,
> +};
> +


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
@ 2015-06-24 22:07       ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-06-24 22:07 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd,
	pantelis.antoniou, mporter, stefan.wahren, wxt

On 06/22/2015 04:09 PM, Srinivas Kandagatla wrote:
> diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
> new file mode 100644
> index 0000000..7f7a82f
> --- /dev/null
> +++ b/drivers/nvmem/qfprom.c
> @@ -0,0 +1,89 @@
>
> +
> +#include <linux/platform_device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +#include <linux/device.h>
> +#include <linux/io.h>

Is this include used?

> +#include <linux/module.h>
> +#include <linux/delay.h>

Is this include used?

> +#include <linux/of.h>
> +
> +static struct regmap_config qfprom_regmap_config = {

Can this be const?

> +	.reg_bits = 32,
> +	.val_bits = 8,
> +	.reg_stride = 1,
> +};
> +
> +static struct nvmem_config econfig = {

And this one too?

> +	.name = "qfprom",
> +	.owner = THIS_MODULE,
> +};
> +


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support.
@ 2015-06-24 22:07       ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-06-24 22:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/22/2015 04:09 PM, Srinivas Kandagatla wrote:
> diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
> new file mode 100644
> index 0000000..7f7a82f
> --- /dev/null
> +++ b/drivers/nvmem/qfprom.c
> @@ -0,0 +1,89 @@
>
> +
> +#include <linux/platform_device.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +#include <linux/device.h>
> +#include <linux/io.h>

Is this include used?

> +#include <linux/module.h>
> +#include <linux/delay.h>

Is this include used?

> +#include <linux/of.h>
> +
> +static struct regmap_config qfprom_regmap_config = {

Can this be const?

> +	.reg_bits = 32,
> +	.val_bits = 8,
> +	.reg_stride = 1,
> +};
> +
> +static struct nvmem_config econfig = {

And this one too?

> +	.name = "qfprom",
> +	.owner = THIS_MODULE,
> +};
> +


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
  2015-06-24 18:50                   ` Srinivas Kandagatla
  (?)
@ 2015-06-30 17:47                       ` Stefan Wahren
  -1 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-30 17:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, arnd-r2nGTMty4D4,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 24. Juni 2015 um
> 20:50 geschrieben:
>
>
>
>
> On 24/06/15 18:47, Stefan Wahren wrote:
> > Hi Srinivas,
> >
> >> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 24. Juni 2015
> >> um
> >> 15:03 geschrieben:
> >>
> >>
> >>
> >>
> >> On 24/06/15 13:30, Stefan Wahren wrote:
> >>>>> If the question is just about hexdump, then hexdump itself can read
> >>>>> file from given offset and size.
> >>> yes, this is my question at first. Let me show the difference between
> >>> the current implementation and my expectations as a user.
> >>>
> >>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >>>
> >>> Current implementation: dump the complete register range defined in DT
> >>>
> >> Its dumping the range which is specified in the provider regmap. If the
> >> requirement is to dump only particular range, this has to be made
> >> explicit while creating regmap, which is to specify the base address to
> >> start from "First data register" and max_register to be "Last data
> >> register "- "First data register"
> >
> > i know about max_register, but i can't find the base address in
> > regmap_config.
> >
> Base is not in the regmap config, its the value which you pass to the
>

thanks for you explanation. I was confused by the word base because in your
example
it is the context variable.

Now i've successful tested my first version of the OCOTP driver based on NVMEM
framework [1].

Currently only the raw sysfs access is working. So i have another question:

How do i get the cell info from the devicetree for the nvmem_config?

I expected a function like of_nvmem_cell_info_get() .

Regards
Stefan

[1] -
https://github.com/lategoodbye/fsl_ocotp/commit/7c98e19755b69f761885b0e1ceb2c258a7c47ade
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-30 17:47                       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-30 17:47 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, arnd, sboyd, s.hauer,
	Greg Kroah-Hartman, linux-kernel, mporter, linux-arm-msm,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
> 20:50 geschrieben:
>
>
>
>
> On 24/06/15 18:47, Stefan Wahren wrote:
> > Hi Srinivas,
> >
> >> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015
> >> um
> >> 15:03 geschrieben:
> >>
> >>
> >>
> >>
> >> On 24/06/15 13:30, Stefan Wahren wrote:
> >>>>> If the question is just about hexdump, then hexdump itself can read
> >>>>> file from given offset and size.
> >>> yes, this is my question at first. Let me show the difference between
> >>> the current implementation and my expectations as a user.
> >>>
> >>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >>>
> >>> Current implementation: dump the complete register range defined in DT
> >>>
> >> Its dumping the range which is specified in the provider regmap. If the
> >> requirement is to dump only particular range, this has to be made
> >> explicit while creating regmap, which is to specify the base address to
> >> start from "First data register" and max_register to be "Last data
> >> register "- "First data register"
> >
> > i know about max_register, but i can't find the base address in
> > regmap_config.
> >
> Base is not in the regmap config, its the value which you pass to the
>

thanks for you explanation. I was confused by the word base because in your
example
it is the context variable.

Now i've successful tested my first version of the OCOTP driver based on NVMEM
framework [1].

Currently only the raw sysfs access is working. So i have another question:

How do i get the cell info from the devicetree for the nvmem_config?

I expected a function like of_nvmem_cell_info_get() .

Regards
Stefan

[1] -
https://github.com/lategoodbye/fsl_ocotp/commit/7c98e19755b69f761885b0e1ceb2c258a7c47ade

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
@ 2015-06-30 17:47                       ` Stefan Wahren
  0 siblings, 0 replies; 92+ messages in thread
From: Stefan Wahren @ 2015-06-30 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Srinivas,

> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
> 20:50 geschrieben:
>
>
>
>
> On 24/06/15 18:47, Stefan Wahren wrote:
> > Hi Srinivas,
> >
> >> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015
> >> um
> >> 15:03 geschrieben:
> >>
> >>
> >>
> >>
> >> On 24/06/15 13:30, Stefan Wahren wrote:
> >>>>> If the question is just about hexdump, then hexdump itself can read
> >>>>> file from given offset and size.
> >>> yes, this is my question at first. Let me show the difference between
> >>> the current implementation and my expectations as a user.
> >>>
> >>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >>>
> >>> Current implementation: dump the complete register range defined in DT
> >>>
> >> Its dumping the range which is specified in the provider regmap. If the
> >> requirement is to dump only particular range, this has to be made
> >> explicit while creating regmap, which is to specify the base address to
> >> start from "First data register" and max_register to be "Last data
> >> register "- "First data register"
> >
> > i know about max_register, but i can't find the base address in
> > regmap_config.
> >
> Base is not in the regmap config, its the value which you pass to the
>

thanks for you explanation. I was confused by the word base because in your
example
it is the context variable.

Now i've successful tested my first version of the OCOTP driver based on NVMEM
framework [1].

Currently only the raw sysfs access is working. So i have another question:

How do i get the cell info from the devicetree for the nvmem_config?

I expected a function like of_nvmem_cell_info_get() .

Regards
Stefan

[1] -
https://github.com/lategoodbye/fsl_ocotp/commit/7c98e19755b69f761885b0e1ceb2c258a7c47ade

^ permalink raw reply	[flat|nested] 92+ messages in thread

end of thread, other threads:[~2015-06-30 17:47 UTC | newest]

Thread overview: 92+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-22 23:07 [PATCH v6 0/9] Add simple NVMEM Framework via regmap Srinivas Kandagatla
2015-06-22 23:07 ` Srinivas Kandagatla
2015-06-22 23:07 ` Srinivas Kandagatla
2015-06-22 23:08 ` [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis Srinivas Kandagatla
2015-06-22 23:08   ` Srinivas Kandagatla
2015-06-22 23:08   ` Srinivas Kandagatla
     [not found]   ` <1435014527-26265-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-23 20:28     ` Stefan Wahren
2015-06-23 20:28       ` Stefan Wahren
2015-06-23 20:28       ` Stefan Wahren
2015-06-24  9:52       ` Srinivas Kandagatla
2015-06-24  9:52         ` Srinivas Kandagatla
2015-06-22 23:09 ` [PATCH v6 5/9] Documentation: nvmem: add nvmem api level and how-to doc Srinivas Kandagatla
2015-06-22 23:09   ` Srinivas Kandagatla
2015-06-22 23:09   ` Srinivas Kandagatla
2015-06-22 23:09 ` [PATCH v6 6/9] nvmem: qfprom: Add Qualcomm QFPROM support Srinivas Kandagatla
2015-06-22 23:09   ` Srinivas Kandagatla
2015-06-22 23:09   ` Srinivas Kandagatla
     [not found]   ` <1435014556-26392-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-24 22:07     ` Stephen Boyd
2015-06-24 22:07       ` Stephen Boyd
2015-06-24 22:07       ` Stephen Boyd
     [not found] ` <1435014459-26138-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-22 23:08   ` [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
2015-06-23  4:52     ` Joe Perches
2015-06-23  4:52       ` Joe Perches
2015-06-23  4:52       ` Joe Perches
2015-06-23  9:26       ` Pantelis Antoniou
2015-06-23  9:26         ` Pantelis Antoniou
     [not found]         ` <7BE8C921-180A-411D-A3C0-5D2A7AE3AB6A-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
2015-06-24  9:56           ` Srinivas Kandagatla
2015-06-24  9:56             ` Srinivas Kandagatla
2015-06-24  9:56             ` Srinivas Kandagatla
     [not found]     ` <1435014507-26181-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-23 20:10       ` Stefan Wahren
2015-06-23 20:10         ` Stefan Wahren
2015-06-23 20:10         ` Stefan Wahren
     [not found]         ` <982684639.251832.1435090259373.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>
2015-06-24  9:54           ` Srinivas Kandagatla
2015-06-24  9:54             ` Srinivas Kandagatla
2015-06-24  9:54             ` Srinivas Kandagatla
2015-06-22 23:08   ` [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
     [not found]     ` <1435014518-26223-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-23 20:16       ` Stefan Wahren
2015-06-23 20:16         ` Stefan Wahren
2015-06-23 20:16         ` Stefan Wahren
     [not found]         ` <272462057.251967.1435090588801.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>
2015-06-24  9:53           ` Srinivas Kandagatla
2015-06-24  9:53             ` Srinivas Kandagatla
2015-06-24  9:53             ` Srinivas Kandagatla
2015-06-22 23:08   ` [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
2015-06-22 23:08     ` Srinivas Kandagatla
2015-06-23 20:35     ` Stefan Wahren
2015-06-23 20:35       ` Stefan Wahren
     [not found]       ` <1670081084.252423.1435091735127.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>
2015-06-24  9:51         ` Srinivas Kandagatla
2015-06-24  9:51           ` Srinivas Kandagatla
2015-06-24  9:51           ` Srinivas Kandagatla
2015-06-22 23:09   ` [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom Srinivas Kandagatla
2015-06-22 23:09     ` Srinivas Kandagatla
2015-06-22 23:09     ` Srinivas Kandagatla
     [not found]     ` <1435014570-26434-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-23  9:25       ` Rajendra Nayak
2015-06-23  9:25         ` Rajendra Nayak
2015-06-23  9:25         ` Rajendra Nayak
2015-06-24  9:49         ` Srinivas Kandagatla
2015-06-24  9:49           ` Srinivas Kandagatla
2015-06-22 23:09   ` [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework Srinivas Kandagatla
2015-06-22 23:09     ` Srinivas Kandagatla
2015-06-22 23:09     ` Srinivas Kandagatla
2015-06-23 20:44     ` Stefan Wahren
2015-06-23 20:44       ` Stefan Wahren
2015-06-24  9:48       ` Srinivas Kandagatla
2015-06-24  9:48         ` Srinivas Kandagatla
2015-06-23 19:47   ` [PATCH v6 0/9] Add simple NVMEM Framework via regmap Stefan Wahren
2015-06-23 19:47     ` Stefan Wahren
2015-06-23 19:47     ` Stefan Wahren
2015-06-24  5:54     ` Sanchayan Maity
2015-06-24  5:54       ` Sanchayan Maity
2015-06-24  9:46     ` Srinivas Kandagatla
2015-06-24  9:46       ` Srinivas Kandagatla
2015-06-24 12:30       ` Stefan Wahren
2015-06-24 12:30         ` Stefan Wahren
     [not found]         ` <558AA2E2.1010606-eS4NqCHxEME@public.gmane.org>
2015-06-24 13:03           ` Srinivas Kandagatla
2015-06-24 13:03             ` Srinivas Kandagatla
2015-06-24 13:03             ` Srinivas Kandagatla
     [not found]             ` <558AAA8D.8030209-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-24 17:47               ` Stefan Wahren
2015-06-24 17:47                 ` Stefan Wahren
2015-06-24 17:47                 ` Stefan Wahren
2015-06-24 18:50                 ` Srinivas Kandagatla
2015-06-24 18:50                   ` Srinivas Kandagatla
     [not found]                   ` <558AFC0B.1050400-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-06-30 17:47                     ` Stefan Wahren
2015-06-30 17:47                       ` Stefan Wahren
2015-06-30 17:47                       ` Stefan Wahren
2015-06-22 23:15 ` [PATCH v6 9/9] nvmem: Add to MAINTAINERS for nvmem framework Srinivas Kandagatla
2015-06-22 23:15   ` Srinivas Kandagatla
2015-06-22 23:15   ` Srinivas Kandagatla

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.