All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/6] FPGA Manager Framework
@ 2014-12-17 16:54 ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Intended for after 3.19-rc1

v5 includes changes from feedback from Michal, Steffen, Alan, Greg, and the
kbuild test robot.

The driver is under drivers/staging/fpga/
The header is now in include/linux/fpga/
The sysfs doc is in staging/fpga/Documentation/ABI/
The DT binding is in staging/fpga/Documentation/bindings/

Alan

Alan Tull (6):
  doc: add bindings document for altera fpga manager
  fpga manager: add sysfs interface document
  staging: fpga manager: framework core
  staging: fpga manager: add driver for socfpga fpga manager
  arm: dts: socfpga: add altera fpga manager
  ARM: socfpga: defconfig: enable fpga manager

 arch/arm/boot/dts/socfpga.dtsi                     |    7 +
 arch/arm/configs/socfpga_defconfig                 |    4 +
 drivers/staging/Kconfig                            |    2 +
 drivers/staging/Makefile                           |    1 +
 .../Documentation/ABI/sysfs-class-fpga-manager     |   38 ++
 .../Documentation/bindings/altera-fpga-mgr.txt     |   17 +
 drivers/staging/fpga/Kconfig                       |   29 +
 drivers/staging/fpga/Makefile                      |   11 +
 drivers/staging/fpga/fpga-mgr.c                    |  523 +++++++++++++++
 drivers/staging/fpga/socfpga.c                     |  692 ++++++++++++++++++++
 include/linux/fpga/fpga-mgr.h                      |  124 ++++
 11 files changed, 1448 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
 create mode 100644 drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
 create mode 100644 drivers/staging/fpga/Kconfig
 create mode 100644 drivers/staging/fpga/Makefile
 create mode 100644 drivers/staging/fpga/fpga-mgr.c
 create mode 100644 drivers/staging/fpga/socfpga.c
 create mode 100644 include/linux/fpga/fpga-mgr.h

-- 
1.7.9.5


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

* [PATCH v5 0/6] FPGA Manager Framework
@ 2014-12-17 16:54 ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Intended for after 3.19-rc1

v5 includes changes from feedback from Michal, Steffen, Alan, Greg, and the
kbuild test robot.

The driver is under drivers/staging/fpga/
The header is now in include/linux/fpga/
The sysfs doc is in staging/fpga/Documentation/ABI/
The DT binding is in staging/fpga/Documentation/bindings/

Alan

Alan Tull (6):
  doc: add bindings document for altera fpga manager
  fpga manager: add sysfs interface document
  staging: fpga manager: framework core
  staging: fpga manager: add driver for socfpga fpga manager
  arm: dts: socfpga: add altera fpga manager
  ARM: socfpga: defconfig: enable fpga manager

 arch/arm/boot/dts/socfpga.dtsi                     |    7 +
 arch/arm/configs/socfpga_defconfig                 |    4 +
 drivers/staging/Kconfig                            |    2 +
 drivers/staging/Makefile                           |    1 +
 .../Documentation/ABI/sysfs-class-fpga-manager     |   38 ++
 .../Documentation/bindings/altera-fpga-mgr.txt     |   17 +
 drivers/staging/fpga/Kconfig                       |   29 +
 drivers/staging/fpga/Makefile                      |   11 +
 drivers/staging/fpga/fpga-mgr.c                    |  523 +++++++++++++++
 drivers/staging/fpga/socfpga.c                     |  692 ++++++++++++++++++++
 include/linux/fpga/fpga-mgr.h                      |  124 ++++
 11 files changed, 1448 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
 create mode 100644 drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
 create mode 100644 drivers/staging/fpga/Kconfig
 create mode 100644 drivers/staging/fpga/Makefile
 create mode 100644 drivers/staging/fpga/fpga-mgr.c
 create mode 100644 drivers/staging/fpga/socfpga.c
 create mode 100644 include/linux/fpga/fpga-mgr.h

-- 
1.7.9.5

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

* [PATCH v5 1/6] doc: add bindings document for altera fpga manager
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

New bindings document for Altera fpga manager.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5 : Move bindings to drivers/staging/fpga/Documentation/bindings
---
 .../Documentation/bindings/altera-fpga-mgr.txt     |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt

diff --git a/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt b/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
new file mode 100644
index 0000000..373af7b
--- /dev/null
+++ b/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
@@ -0,0 +1,17 @@
+Altera FPGA Manager
+
+Required properties:
+- compatible : should contain "altr,fpga-mgr"
+- reg        : base address and size for memory mapped io.
+               - The first index is for FPGA manager register access.
+               - The second index is for writing FPGA configuration data.
+- interrupts : interrupt for the FPGA Manager device.
+
+Example:
+
+	hps_0_fpgamgr: fpgamgr@0xff706000 {
+		compatible = "altr,fpga-mgr";
+		reg = <0xFF706000 0x1000
+		       0xFFB90000 0x1000>;
+		interrupts = <0 175 4>;
+	};
-- 
1.7.9.5


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

* [PATCH v5 1/6] doc: add bindings document for altera fpga manager
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	hpa-YMNOUZJC4hwAvxtiuMwx3w, monstr-pSz03upnqPeHXe+LvDLADg,
	michal.simek-gjFFaj9aHVfQT0dZR+AlfA,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, iws-lulEs6mt1IksTUYHLfqkUA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, pavel-ynQEQJNshbs,
	broonie-DgEjT+Ai2ygdnm+yROfE0A, philip-6RQC9ztksjxg9hUCZPvPmw,
	rubini-kaDoWcXyVrEAvxtiuMwx3w, s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ,
	jason-NLaQJdtUoK4Be96aLqz0jA, kyle.teske-acOepvfBmUk,
	nico-QSEj5FYQhm4dnm+yROfE0A, balbi-l0cyMroinI0,
	m.chehab-Sze3O3UU22JBDgjK7y7TUQ, davidb-sgV2jX0FEOL9JmXXK+q4OQ,
	rob-VoJi6FS/r0vR7s880joybQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	cesarb-PWySMVKUnqmsTnJN9+BGXg, sameo-VuQAYsv1563Yd54FQh9/CA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w,
	dinguyen-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
	yvanderv-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx, Alan Tull

From: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>

New bindings document for Altera fpga manager.

Signed-off-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
---
v5 : Move bindings to drivers/staging/fpga/Documentation/bindings
---
 .../Documentation/bindings/altera-fpga-mgr.txt     |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt

diff --git a/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt b/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
new file mode 100644
index 0000000..373af7b
--- /dev/null
+++ b/drivers/staging/fpga/Documentation/bindings/altera-fpga-mgr.txt
@@ -0,0 +1,17 @@
+Altera FPGA Manager
+
+Required properties:
+- compatible : should contain "altr,fpga-mgr"
+- reg        : base address and size for memory mapped io.
+               - The first index is for FPGA manager register access.
+               - The second index is for writing FPGA configuration data.
+- interrupts : interrupt for the FPGA Manager device.
+
+Example:
+
+	hps_0_fpgamgr: fpgamgr@0xff706000 {
+		compatible = "altr,fpga-mgr";
+		reg = <0xFF706000 0x1000
+		       0xFFB90000 0x1000>;
+		interrupts = <0 175 4>;
+	};
-- 
1.7.9.5

--
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 related	[flat|nested] 35+ messages in thread

* [PATCH v5 2/6] fpga manager: add sysfs interface document
  2014-12-17 16:54 ` atull
@ 2014-12-17 16:54   ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add documentation under drivers/staging for new fpga manager's
sysfs interface.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5  : (actually second version, but keeping version numbers
      aligned with rest of patch series)
      Move document to drivers/staging/fpga/Documentation/ABI
---
 .../Documentation/ABI/sysfs-class-fpga-manager     |   38 ++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager

diff --git a/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager b/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
new file mode 100644
index 0000000..eb600f2
--- /dev/null
+++ b/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
@@ -0,0 +1,38 @@
+What:		/sys/class/fpga_manager/<fpga>/name
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Name of low level driver.
+
+What:		/sys/class/fpga_manager/<fpga>/firmware
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Name of the FPGA image file to load using firmware class.
+
+What:		/sys/class/fpga_manager/<fpga>/reset
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Write 1 to reset the FPGA
+
+What:		/sys/class/fpga_manager/<fpga>/state
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Read state of fpga framework state machine as a string.
+		Valid states may vary by manufacturer; superset is:
+		* unknown		= can't determine state
+		* power_off		= FPGA power is off
+		* power_up		= FPGA reports power is up
+		* reset			= FPGA held in reset state
+		* firmware_request	= firmware class request in progress
+		* firmware_request_err	= firmware request failed
+		* write_init		= FPGA being prepared for programming
+		* write_init_err	= Error while preparing FPGA for
+					  programming
+		* write			= FPGA ready to receive image data
+		* write_err		= Error while programming
+		* write_complete	= Doing post programming steps
+		* write_complete_err	= Error while doing post programming
+		* operating		= FPGA is programmed and operating
-- 
1.7.9.5


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

* [PATCH v5 2/6] fpga manager: add sysfs interface document
@ 2014-12-17 16:54   ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add documentation under drivers/staging for new fpga manager's
sysfs interface.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5  : (actually second version, but keeping version numbers
      aligned with rest of patch series)
      Move document to drivers/staging/fpga/Documentation/ABI
---
 .../Documentation/ABI/sysfs-class-fpga-manager     |   38 ++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager

diff --git a/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager b/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
new file mode 100644
index 0000000..eb600f2
--- /dev/null
+++ b/drivers/staging/fpga/Documentation/ABI/sysfs-class-fpga-manager
@@ -0,0 +1,38 @@
+What:		/sys/class/fpga_manager/<fpga>/name
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Name of low level driver.
+
+What:		/sys/class/fpga_manager/<fpga>/firmware
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Name of the FPGA image file to load using firmware class.
+
+What:		/sys/class/fpga_manager/<fpga>/reset
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Write 1 to reset the FPGA
+
+What:		/sys/class/fpga_manager/<fpga>/state
+Date:		October 2014
+KernelVersion:	3.18
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Read state of fpga framework state machine as a string.
+		Valid states may vary by manufacturer; superset is:
+		* unknown		= can't determine state
+		* power_off		= FPGA power is off
+		* power_up		= FPGA reports power is up
+		* reset			= FPGA held in reset state
+		* firmware_request	= firmware class request in progress
+		* firmware_request_err	= firmware request failed
+		* write_init		= FPGA being prepared for programming
+		* write_init_err	= Error while preparing FPGA for
+					  programming
+		* write			= FPGA ready to receive image data
+		* write_err		= Error while programming
+		* write_complete	= Doing post programming steps
+		* write_complete_err	= Error while doing post programming
+		* operating		= FPGA is programmed and operating
-- 
1.7.9.5

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

* [PATCH v5 3/6] staging: fpga manager: framework core
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Supports standard ops for low level FPGA drivers.
Various manufacturors' FPGAs can be supported by adding low
level drivers.  Each driver needs to register its ops
using fpga_mgr_register().

Exports methods of doing operations to program  FPGAs. These
should be sufficient for individual drivers to request FPGA
programming directly if desired.

Adds a sysfs interface.  The sysfs interface can be compiled out
where desired in production builds.

Resume is supported by calling low level driver's resume
function, then reloading the firmware image.

The following are exported as GPL:
* fpga_mgr_reset
   Reset the FGPA.

* fpga_mgr_write
   Write a image (in buffer) to the FPGA.

* fpga_mgr_firmware_write
   Request firmware by file name and write it to the FPGA.

* fpga_mgr_name
   Get name of FPGA manager.

* fpga_mgr_state
   Get a state of framework as a string.

* fpga_mgr_register and fpga_mgr_remove
   Register/unregister low level fpga manager driver.

The following sysfs files are created:
* /sys/class/fpga_manager/<fpga>/name
  Name of low level driver.

* /sys/class/fpga_manager/<fpga>/firmware
  Name of FPGA image file to load using firmware class.
  $ echo image.rbf > /sys/class/fpga_manager/<fpga>/firmware

  read: read back name of image file previous loaded
  $ cat /sys/class/fpga_manager/<fpga>/firmware

* /sys/class/fpga_manager/<fpga>/reset
  reset the FPGA
  $ echo 1 > /sys/class/fpga_manager/<fpga>/reset

* /sys/class/fpga_manager/<fpga>/state
  State of fpga framework state machine

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v2: s/mangager/manager/
    check for invalid request_nr
    add fpga reset interface
    rework the state code
    remove FPGA_MGR_FAIL flag
    add _ERR states to fpga manager states enum
    low level state op now returns a state enum value
    initialize framework state from driver state op
    remove unused fpga read stuff
    merge sysfs.c into fpga-mgr.c
    move suspend/resume from bus.c to fpga-mgr.c

v3: Add struct device to fpga_manager (not as a pointer)
    Add to_fpga_manager
    Don't get irq in fpga-mgr.c (let low level driver do it)
    remove from struct fpga_manager: nr, np, parent
    get rid of fpga_mgr_get_new_minor()
    simplify fpga_manager_register:
      reorder parameters
      use dev instead of pdev
    get rid of code that used to make more sense when this
      was a char driver, don't alloc_chrdev_region
    use a mutex instead of flags

v4: Move to drivers/staging

v5: Make some things be static
    Kconfig: add 'if FPGA'
    Makefile: s/fpga-mgr-core.o/fpga-mgr.o/
    clean up includes
    use enum fpga_mgr_states instead of int
    static const char *state_str
    use DEVICE_ATTR_RO/RW/WO and ATTRIBUTE_GROUPS
    return -EINVAL instead of BUG_ON
    move ida_simple_get after kzalloc
    clean up fpga_mgr_remove
    fpga-mgr.h: remove '#if IS_ENABLED(CONFIG_FPGA)'
    add kernel-doc documentation
    Move header to new include/linux/fpga folder
    static const struct fpga_mgr_ops
    dev_info msg simplified
---
 drivers/staging/Kconfig         |    2 +
 drivers/staging/Makefile        |    1 +
 drivers/staging/fpga/Kconfig    |   24 ++
 drivers/staging/fpga/Makefile   |   10 +
 drivers/staging/fpga/fpga-mgr.c |  523 +++++++++++++++++++++++++++++++++++++++
 include/linux/fpga/fpga-mgr.h   |  124 ++++++++++
 6 files changed, 684 insertions(+)
 create mode 100644 drivers/staging/fpga/Kconfig
 create mode 100644 drivers/staging/fpga/Makefile
 create mode 100644 drivers/staging/fpga/fpga-mgr.c
 create mode 100644 include/linux/fpga/fpga-mgr.h

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 4690ae9..4338a4c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig"
 
 source "drivers/staging/unisys/Kconfig"
 
+source "drivers/staging/fpga/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index c780a0e..43654a2 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
 obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
 obj-$(CONFIG_CRYPTO_SKEIN)	+= skein/
 obj-$(CONFIG_UNISYSSPAR)	+= unisys/
+obj-$(CONFIG_FPGA)		+= fpga/
diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
new file mode 100644
index 0000000..89ebafc
--- /dev/null
+++ b/drivers/staging/fpga/Kconfig
@@ -0,0 +1,24 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA devices"
+
+config FPGA
+	tristate "FPGA Framework"
+	help
+	  Say Y here if you want support for configuring FPGAs from the
+	  kernel.  The FPGA framework adds a FPGA manager class and FPGA
+	  manager drivers.
+
+if FPGA
+
+config FPGA_MGR_SYSFS
+	bool "FPGA Manager SysFS Interface"
+	depends on SYSFS
+	help
+	  FPGA Manager SysFS interface.
+
+endif # FPGA
+
+endmenu
diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
new file mode 100644
index 0000000..ff6c677
--- /dev/null
+++ b/drivers/staging/fpga/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+fpga-mgr-core-y += fpga-mgr.o
+
+# Core FPGA Manager Framework
+obj-$(CONFIG_FPGA)			+= fpga-mgr.o
+
+# FPGA Manager Drivers
diff --git a/drivers/staging/fpga/fpga-mgr.c b/drivers/staging/fpga/fpga-mgr.c
new file mode 100644
index 0000000..671b114
--- /dev/null
+++ b/drivers/staging/fpga/fpga-mgr.c
@@ -0,0 +1,523 @@
+/*
+ * FPGA Manager Core
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * With code from the mailing list:
+ * Copyright (C) 2013 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(fpga_mgr_mutex);
+static DEFINE_IDA(fpga_mgr_ida);
+static struct class *fpga_mgr_class;
+
+static LIST_HEAD(fpga_manager_list);
+
+/**
+ * fpga_mgr_low_level_state - get FPGA state from low level driver
+ * @mgr: fpga manager
+ *
+ * This will be used to initialize framework state
+ */
+static enum fpga_mgr_states fpga_mgr_low_level_state(struct fpga_manager *mgr)
+{
+	if (!mgr || !mgr->mops || !mgr->mops->state)
+		return FPGA_MGR_STATE_UNKNOWN;
+
+	return mgr->mops->state(mgr);
+}
+
+/**
+ * __fpga_mgr_reset - unlocked version of fpga_mgr_reset
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_reset(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (!mgr->mops->reset)
+		return -EINVAL;
+
+	ret = mgr->mops->reset(mgr);
+
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	return ret;
+}
+
+/**
+ * fpga_mgr_reset - reset the fpga
+ * @mgr: fpga manager
+ */
+int fpga_mgr_reset(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	ret = __fpga_mgr_reset(mgr);
+
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_reset);
+
+/**
+ * __fpga_mgr_stage_init - prepare fpga for configuration
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_stage_write_init(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (mgr->mops->write_init) {
+		mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+		ret = mgr->mops->write_init(mgr);
+		if (ret) {
+			mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_stage_write - write buffer to fpga
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+static int __fpga_mgr_stage_write(struct fpga_manager *mgr, const char *buf,
+				  size_t count)
+{
+	int ret;
+
+	mgr->state = FPGA_MGR_STATE_WRITE;
+	ret = mgr->mops->write(mgr, buf, count);
+	if (ret) {
+		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_stage_complete - after writing, place fpga in operating state
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_stage_write_complete(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (mgr->mops->write_complete) {
+		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+		ret = mgr->mops->write_complete(mgr);
+		if (ret) {
+			mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+			return ret;
+		}
+	}
+
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_write - whole fpga image write cycle
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+static int __fpga_mgr_write(struct fpga_manager *mgr, const char *buf,
+			    size_t count)
+{
+	int ret;
+
+	ret = __fpga_mgr_stage_write_init(mgr);
+	if (ret)
+		return ret;
+
+	ret = __fpga_mgr_stage_write(mgr, buf, count);
+	if (ret)
+		return ret;
+
+	return __fpga_mgr_stage_write_complete(mgr);
+}
+
+/**
+ * fpga_mgr_write - do complete fpga image write cycle
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
+{
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	dev_info(&mgr->dev, "writing buffer to %s\n", mgr->name);
+
+	ret = __fpga_mgr_write(mgr, buf, count);
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_write);
+
+/**
+ * fpga_mgr_firmware_write - request firmware and write to fpga
+ * @mgr: fpga manager
+ * @image_name: name of image file on the firmware search path
+ *
+ * Grab lock, request firmware, and write out to the FPGA.
+ * Update the state before each step to provide info on what step
+ * failed if there is a failure.
+ */
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name)
+{
+	const struct firmware *fw;
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	dev_info(&mgr->dev, "writing %s to %s\n", image_name, mgr->name);
+
+	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+	ret = request_firmware(&fw, image_name, &mgr->dev);
+	if (ret) {
+		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+		goto fw_wr_exit;
+	}
+
+	ret = __fpga_mgr_write(mgr, fw->data, fw->size);
+	if (ret)
+		goto fw_wr_exit;
+
+	strcpy(mgr->image_name, image_name);
+
+fw_wr_exit:
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
+
+/**
+ * fpga_mgr_name - returns the fpga manager name
+ * @mgr: fpga manager
+ * @buf: buffer to receive the name
+ */
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf)
+{
+	if (!mgr)
+		return -ENODEV;
+
+	return sprintf(buf, "%s\n", mgr->name);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_name);
+
+#if IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)
+static const char * const state_str[] = {
+	[FPGA_MGR_STATE_UNKNOWN] =		"unknown",
+	[FPGA_MGR_STATE_POWER_OFF] =		"power_off",
+	[FPGA_MGR_STATE_POWER_UP] =		"power_up",
+	[FPGA_MGR_STATE_RESET] =		"reset",
+
+	/* write sequence */
+	[FPGA_MGR_STATE_FIRMWARE_REQ] =		"firmware_request",
+	[FPGA_MGR_STATE_FIRMWARE_REQ_ERR] =	"firmware_request_err",
+	[FPGA_MGR_STATE_WRITE_INIT] =		"write_init",
+	[FPGA_MGR_STATE_WRITE_INIT_ERR] =	"write_init_err",
+	[FPGA_MGR_STATE_WRITE] =		"write",
+	[FPGA_MGR_STATE_WRITE_ERR] =		"write_err",
+	[FPGA_MGR_STATE_WRITE_COMPLETE] =	"write_complete",
+	[FPGA_MGR_STATE_WRITE_COMPLETE_ERR] =	"write_complete_err",
+
+	[FPGA_MGR_STATE_OPERATING] =		"operating",
+};
+
+/*
+ * class attributes
+ */
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return fpga_mgr_name(mgr, buf);
+}
+
+static ssize_t state_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return sprintf(buf, "%s\n", state_str[mgr->state]);
+}
+
+static ssize_t firmware_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return sprintf(buf, "%s\n", mgr->image_name);
+}
+
+static ssize_t firmware_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	unsigned int len;
+	char image_name[NAME_MAX];
+	int ret;
+
+	/* lose terminating \n */
+	strcpy(image_name, buf);
+	len = strlen(image_name);
+	if (image_name[len - 1] == '\n')
+		image_name[len - 1] = 0;
+
+	ret = fpga_mgr_firmware_write(mgr, image_name);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t reset_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val == 1) {
+		ret = fpga_mgr_reset(mgr);
+		if (ret)
+			return ret;
+	} else {
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(state);
+static DEVICE_ATTR_RW(firmware);
+static DEVICE_ATTR_WO(reset);
+
+static struct attribute *fpga_mgr_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_state.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_reset.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(fpga_mgr);
+#else
+#define fpga_mgr_groups NULL
+#endif /* CONFIG_FPGA_MGR_SYSFS */
+
+static int fpga_mgr_suspend(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	if (!mgr)
+		return -ENODEV;
+
+	if (mgr->mops->suspend)
+		return mgr->mops->suspend(mgr);
+
+	return 0;
+}
+
+static int fpga_mgr_resume(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	int ret = 0;
+
+	if (!mgr)
+		return -ENODEV;
+
+	if (mgr->mops->resume) {
+		ret = mgr->mops->resume(mgr);
+		if (ret)
+			return ret;
+	}
+
+	if (strlen(mgr->image_name) != 0)
+		fpga_mgr_firmware_write(mgr, mgr->image_name);
+
+	return 0;
+}
+
+static const struct dev_pm_ops fpga_mgr_dev_pm_ops = {
+	.suspend	= fpga_mgr_suspend,
+	.resume		= fpga_mgr_resume,
+};
+
+static void fpga_mgr_dev_release(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	dev_dbg(dev, "releasing '%s'\n", mgr->name);
+
+	if (mgr->mops->fpga_remove)
+		mgr->mops->fpga_remove(mgr);
+
+	mgr->mops = NULL;
+
+	mutex_lock(&fpga_mgr_mutex);
+	list_del(&mgr->list);
+	mutex_unlock(&fpga_mgr_mutex);
+
+	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
+	kfree(mgr);
+}
+
+/**
+ * fpga_mgr_register - register a low level fpga manager driver
+ * @dev: fpga manager device
+ * @name: fpga manager name
+ * @mops: pointer to structure of fpga manager ops
+ * @priv: fpga manager private data
+ */
+int fpga_mgr_register(struct device *dev, const char *name,
+		      const struct fpga_manager_ops *mops,
+		      void *priv)
+{
+	struct fpga_manager *mgr;
+	int id, ret;
+
+	if (!mops || !name || !strlen(name))
+		return -EINVAL;
+
+	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+	if (!mgr)
+		return -ENOMEM;
+
+	id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return id;
+
+	mutex_init(&mgr->lock);
+
+	mgr->name = name;
+	mgr->mops = mops;
+	mgr->priv = priv;
+
+	/*
+	 * Initialize framework state by requesting low level driver read state
+	 * from device.  FPGA may be in reset mode or may have been programmed
+	 * by bootloader or EEPROM.
+	 */
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	INIT_LIST_HEAD(&mgr->list);
+	mutex_lock(&fpga_mgr_mutex);
+	list_add(&mgr->list, &fpga_manager_list);
+	mutex_unlock(&fpga_mgr_mutex);
+
+	device_initialize(&mgr->dev);
+	mgr->dev.class = fpga_mgr_class;
+	mgr->dev.parent = dev;
+	mgr->dev.of_node = dev->of_node;
+	mgr->dev.release = fpga_mgr_dev_release;
+	mgr->dev.id = id;
+	dev_set_name(&mgr->dev, "%d", id);
+	ret = device_add(&mgr->dev);
+	if (ret)
+		goto error_device;
+
+	dev_info(&mgr->dev, "%s registered\n", mgr->name);
+
+	return 0;
+
+error_device:
+	ida_simple_remove(&fpga_mgr_ida, id);
+	kfree(mgr);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_register);
+
+/**
+ * fpga_mgr_remove - remove a low level fpga manager driver
+ * @dev: fpga manager device
+ */
+void fpga_mgr_remove(struct platform_device *pdev)
+{
+	struct list_head *tmp;
+	struct fpga_manager *mgr = NULL;
+
+	list_for_each(tmp, &fpga_manager_list) {
+		mgr = list_entry(tmp, struct fpga_manager, list);
+		if (mgr->dev.parent == &pdev->dev) {
+			device_unregister(&mgr->dev);
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_remove);
+
+static int __init fpga_mgr_dev_init(void)
+{
+	pr_info("FPGA Manager framework driver\n");
+
+	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
+	if (IS_ERR(fpga_mgr_class))
+		return PTR_ERR(fpga_mgr_class);
+
+	fpga_mgr_class->dev_groups = fpga_mgr_groups;
+	fpga_mgr_class->pm = &fpga_mgr_dev_pm_ops;
+
+	return 0;
+}
+
+static void __exit fpga_mgr_dev_exit(void)
+{
+	class_destroy(fpga_mgr_class);
+	ida_destroy(&fpga_mgr_ida);
+}
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("FPGA Manager framework driver");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_mgr_dev_init);
+module_exit(fpga_mgr_dev_exit);
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
new file mode 100644
index 0000000..29c76d6
--- /dev/null
+++ b/include/linux/fpga/fpga-mgr.h
@@ -0,0 +1,124 @@
+/*
+ * FPGA Framework
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/limits.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+struct fpga_manager;
+
+/**
+ * struct fpga_manager_ops - ops for low level fpga manager drivers
+ * @state: returns an enum value of the FPGA's state
+ * @reset: put FPGA into reset state
+ * @write_init: prepare the FPGA to receive confuration data
+ * @write: write count bytes of configuration data to the FPGA
+ * @write_complete: set FPGA to operating state after writing is done
+ * @fpga_remove: optional: Set FPGA into a specific state during driver remove
+ * @suspend: optional: low level fpga suspend
+ * @resume: optional: low level fpga resume
+ *
+ * fpga_manager_ops are the low level functions implemented by a specific
+ * fpga manager driver.  The optional ones are tested for NULL before being
+ * called, so leaving them out is fine.
+ */
+struct fpga_manager_ops {
+	enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
+	int (*reset)(struct fpga_manager *mgr);
+	int (*write_init)(struct fpga_manager *mgr);
+	int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
+	int (*write_complete)(struct fpga_manager *mgr);
+	void (*fpga_remove)(struct fpga_manager *mgr);
+	int (*suspend)(struct fpga_manager *mgr);
+	int (*resume)(struct fpga_manager *mgr);
+};
+
+/**
+ * enum fpga_mgr_states - fpga framework states
+ * @FPGA_MGR_STATE_UNKNOWN: can't determine state
+ * @FPGA_MGR_STATE_POWER_OFF: FPGA power is off
+ * @FPGA_MGR_STATE_POWER_UP: FPGA reports power is up
+ * @FPGA_MGR_STATE_RESET: FPGA in reset state
+ * @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
+ * @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
+ * @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
+ * @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
+ * @FPGA_MGR_STATE_WRITE: writing image to FPGA
+ * @FPGA_MGR_STATE_WRITE_ERR: Error while writing FPGA
+ * @FPGA_MGR_STATE_WRITE_COMPLETE: Doing post programming steps
+ * @FPGA_MGR_STATE_WRITE_COMPLETE_ERR: Error during WRITE_COMPLETE
+ * @FPGA_MGR_STATE_OPERATING: FPGA is programmed and operating
+ */
+enum fpga_mgr_states {
+	FPGA_MGR_STATE_UNKNOWN,
+	FPGA_MGR_STATE_POWER_OFF,
+	FPGA_MGR_STATE_POWER_UP,
+	FPGA_MGR_STATE_RESET,
+
+	/* write sequence */
+	FPGA_MGR_STATE_FIRMWARE_REQ,
+	FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
+	FPGA_MGR_STATE_WRITE_INIT,
+	FPGA_MGR_STATE_WRITE_INIT_ERR,
+	FPGA_MGR_STATE_WRITE,
+	FPGA_MGR_STATE_WRITE_ERR,
+	FPGA_MGR_STATE_WRITE_COMPLETE,
+	FPGA_MGR_STATE_WRITE_COMPLETE_ERR,
+
+	FPGA_MGR_STATE_OPERATING,
+};
+
+/**
+ * struct fpga_manager - fpga manager structure
+ * @name: name of low level fpga manager
+ * @dev: fpga manager device
+ * @list: entry in list of all fpga managers
+ * @lock: lock on calls to fpga manager ops
+ * @state: state of fpga manager
+ * @image_name: name of fpga image file if any
+ * @mops: pointer to struct of fpga manager ops
+ * @priv: low level driver private date
+ */
+struct fpga_manager {
+	const char *name;
+	struct device dev;
+	struct list_head list;
+	struct mutex lock;	/* lock on calls to ops */
+	enum fpga_mgr_states state;
+	char image_name[NAME_MAX];
+
+	const struct fpga_manager_ops *mops;
+	void *priv;
+};
+
+#define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
+
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name);
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count);
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf);
+int fpga_mgr_reset(struct fpga_manager *mgr);
+int fpga_mgr_register(struct device *pdev, const char *name,
+		      const struct fpga_manager_ops *mops, void *priv);
+void fpga_mgr_remove(struct platform_device *pdev);
+
+#endif /*_LINUX_FPGA_MGR_H */
-- 
1.7.9.5


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

* [PATCH v5 3/6] staging: fpga manager: framework core
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	hpa-YMNOUZJC4hwAvxtiuMwx3w, monstr-pSz03upnqPeHXe+LvDLADg,
	michal.simek-gjFFaj9aHVfQT0dZR+AlfA,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, iws-lulEs6mt1IksTUYHLfqkUA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, pavel-ynQEQJNshbs,
	broonie-DgEjT+Ai2ygdnm+yROfE0A, philip-6RQC9ztksjxg9hUCZPvPmw,
	rubini-kaDoWcXyVrEAvxtiuMwx3w, s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ,
	jason-NLaQJdtUoK4Be96aLqz0jA, kyle.teske-acOepvfBmUk,
	nico-QSEj5FYQhm4dnm+yROfE0A, balbi-l0cyMroinI0,
	m.chehab-Sze3O3UU22JBDgjK7y7TUQ, davidb-sgV2jX0FEOL9JmXXK+q4OQ,
	rob-VoJi6FS/r0vR7s880joybQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	cesarb-PWySMVKUnqmsTnJN9+BGXg, sameo-VuQAYsv1563Yd54FQh9/CA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w,
	dinguyen-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
	yvanderv-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx, Alan Tull

From: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>

Supports standard ops for low level FPGA drivers.
Various manufacturors' FPGAs can be supported by adding low
level drivers.  Each driver needs to register its ops
using fpga_mgr_register().

Exports methods of doing operations to program  FPGAs. These
should be sufficient for individual drivers to request FPGA
programming directly if desired.

Adds a sysfs interface.  The sysfs interface can be compiled out
where desired in production builds.

Resume is supported by calling low level driver's resume
function, then reloading the firmware image.

The following are exported as GPL:
* fpga_mgr_reset
   Reset the FGPA.

* fpga_mgr_write
   Write a image (in buffer) to the FPGA.

* fpga_mgr_firmware_write
   Request firmware by file name and write it to the FPGA.

* fpga_mgr_name
   Get name of FPGA manager.

* fpga_mgr_state
   Get a state of framework as a string.

* fpga_mgr_register and fpga_mgr_remove
   Register/unregister low level fpga manager driver.

The following sysfs files are created:
* /sys/class/fpga_manager/<fpga>/name
  Name of low level driver.

* /sys/class/fpga_manager/<fpga>/firmware
  Name of FPGA image file to load using firmware class.
  $ echo image.rbf > /sys/class/fpga_manager/<fpga>/firmware

  read: read back name of image file previous loaded
  $ cat /sys/class/fpga_manager/<fpga>/firmware

* /sys/class/fpga_manager/<fpga>/reset
  reset the FPGA
  $ echo 1 > /sys/class/fpga_manager/<fpga>/reset

* /sys/class/fpga_manager/<fpga>/state
  State of fpga framework state machine

Signed-off-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
---
v2: s/mangager/manager/
    check for invalid request_nr
    add fpga reset interface
    rework the state code
    remove FPGA_MGR_FAIL flag
    add _ERR states to fpga manager states enum
    low level state op now returns a state enum value
    initialize framework state from driver state op
    remove unused fpga read stuff
    merge sysfs.c into fpga-mgr.c
    move suspend/resume from bus.c to fpga-mgr.c

v3: Add struct device to fpga_manager (not as a pointer)
    Add to_fpga_manager
    Don't get irq in fpga-mgr.c (let low level driver do it)
    remove from struct fpga_manager: nr, np, parent
    get rid of fpga_mgr_get_new_minor()
    simplify fpga_manager_register:
      reorder parameters
      use dev instead of pdev
    get rid of code that used to make more sense when this
      was a char driver, don't alloc_chrdev_region
    use a mutex instead of flags

v4: Move to drivers/staging

v5: Make some things be static
    Kconfig: add 'if FPGA'
    Makefile: s/fpga-mgr-core.o/fpga-mgr.o/
    clean up includes
    use enum fpga_mgr_states instead of int
    static const char *state_str
    use DEVICE_ATTR_RO/RW/WO and ATTRIBUTE_GROUPS
    return -EINVAL instead of BUG_ON
    move ida_simple_get after kzalloc
    clean up fpga_mgr_remove
    fpga-mgr.h: remove '#if IS_ENABLED(CONFIG_FPGA)'
    add kernel-doc documentation
    Move header to new include/linux/fpga folder
    static const struct fpga_mgr_ops
    dev_info msg simplified
---
 drivers/staging/Kconfig         |    2 +
 drivers/staging/Makefile        |    1 +
 drivers/staging/fpga/Kconfig    |   24 ++
 drivers/staging/fpga/Makefile   |   10 +
 drivers/staging/fpga/fpga-mgr.c |  523 +++++++++++++++++++++++++++++++++++++++
 include/linux/fpga/fpga-mgr.h   |  124 ++++++++++
 6 files changed, 684 insertions(+)
 create mode 100644 drivers/staging/fpga/Kconfig
 create mode 100644 drivers/staging/fpga/Makefile
 create mode 100644 drivers/staging/fpga/fpga-mgr.c
 create mode 100644 include/linux/fpga/fpga-mgr.h

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 4690ae9..4338a4c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig"
 
 source "drivers/staging/unisys/Kconfig"
 
+source "drivers/staging/fpga/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index c780a0e..43654a2 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
 obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
 obj-$(CONFIG_CRYPTO_SKEIN)	+= skein/
 obj-$(CONFIG_UNISYSSPAR)	+= unisys/
+obj-$(CONFIG_FPGA)		+= fpga/
diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
new file mode 100644
index 0000000..89ebafc
--- /dev/null
+++ b/drivers/staging/fpga/Kconfig
@@ -0,0 +1,24 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA devices"
+
+config FPGA
+	tristate "FPGA Framework"
+	help
+	  Say Y here if you want support for configuring FPGAs from the
+	  kernel.  The FPGA framework adds a FPGA manager class and FPGA
+	  manager drivers.
+
+if FPGA
+
+config FPGA_MGR_SYSFS
+	bool "FPGA Manager SysFS Interface"
+	depends on SYSFS
+	help
+	  FPGA Manager SysFS interface.
+
+endif # FPGA
+
+endmenu
diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
new file mode 100644
index 0000000..ff6c677
--- /dev/null
+++ b/drivers/staging/fpga/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+fpga-mgr-core-y += fpga-mgr.o
+
+# Core FPGA Manager Framework
+obj-$(CONFIG_FPGA)			+= fpga-mgr.o
+
+# FPGA Manager Drivers
diff --git a/drivers/staging/fpga/fpga-mgr.c b/drivers/staging/fpga/fpga-mgr.c
new file mode 100644
index 0000000..671b114
--- /dev/null
+++ b/drivers/staging/fpga/fpga-mgr.c
@@ -0,0 +1,523 @@
+/*
+ * FPGA Manager Core
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * With code from the mailing list:
+ * Copyright (C) 2013 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(fpga_mgr_mutex);
+static DEFINE_IDA(fpga_mgr_ida);
+static struct class *fpga_mgr_class;
+
+static LIST_HEAD(fpga_manager_list);
+
+/**
+ * fpga_mgr_low_level_state - get FPGA state from low level driver
+ * @mgr: fpga manager
+ *
+ * This will be used to initialize framework state
+ */
+static enum fpga_mgr_states fpga_mgr_low_level_state(struct fpga_manager *mgr)
+{
+	if (!mgr || !mgr->mops || !mgr->mops->state)
+		return FPGA_MGR_STATE_UNKNOWN;
+
+	return mgr->mops->state(mgr);
+}
+
+/**
+ * __fpga_mgr_reset - unlocked version of fpga_mgr_reset
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_reset(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (!mgr->mops->reset)
+		return -EINVAL;
+
+	ret = mgr->mops->reset(mgr);
+
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	return ret;
+}
+
+/**
+ * fpga_mgr_reset - reset the fpga
+ * @mgr: fpga manager
+ */
+int fpga_mgr_reset(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	ret = __fpga_mgr_reset(mgr);
+
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_reset);
+
+/**
+ * __fpga_mgr_stage_init - prepare fpga for configuration
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_stage_write_init(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (mgr->mops->write_init) {
+		mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+		ret = mgr->mops->write_init(mgr);
+		if (ret) {
+			mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_stage_write - write buffer to fpga
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+static int __fpga_mgr_stage_write(struct fpga_manager *mgr, const char *buf,
+				  size_t count)
+{
+	int ret;
+
+	mgr->state = FPGA_MGR_STATE_WRITE;
+	ret = mgr->mops->write(mgr, buf, count);
+	if (ret) {
+		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_stage_complete - after writing, place fpga in operating state
+ * @mgr: fpga manager
+ */
+static int __fpga_mgr_stage_write_complete(struct fpga_manager *mgr)
+{
+	int ret;
+
+	if (mgr->mops->write_complete) {
+		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+		ret = mgr->mops->write_complete(mgr);
+		if (ret) {
+			mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+			return ret;
+		}
+	}
+
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	return 0;
+}
+
+/**
+ * __fpga_mgr_write - whole fpga image write cycle
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+static int __fpga_mgr_write(struct fpga_manager *mgr, const char *buf,
+			    size_t count)
+{
+	int ret;
+
+	ret = __fpga_mgr_stage_write_init(mgr);
+	if (ret)
+		return ret;
+
+	ret = __fpga_mgr_stage_write(mgr, buf, count);
+	if (ret)
+		return ret;
+
+	return __fpga_mgr_stage_write_complete(mgr);
+}
+
+/**
+ * fpga_mgr_write - do complete fpga image write cycle
+ * @mgr: fpga manager
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ */
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
+{
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	dev_info(&mgr->dev, "writing buffer to %s\n", mgr->name);
+
+	ret = __fpga_mgr_write(mgr, buf, count);
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_write);
+
+/**
+ * fpga_mgr_firmware_write - request firmware and write to fpga
+ * @mgr: fpga manager
+ * @image_name: name of image file on the firmware search path
+ *
+ * Grab lock, request firmware, and write out to the FPGA.
+ * Update the state before each step to provide info on what step
+ * failed if there is a failure.
+ */
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name)
+{
+	const struct firmware *fw;
+	int ret;
+
+	if (!mutex_trylock(&mgr->lock))
+		return -EBUSY;
+
+	dev_info(&mgr->dev, "writing %s to %s\n", image_name, mgr->name);
+
+	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+	ret = request_firmware(&fw, image_name, &mgr->dev);
+	if (ret) {
+		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+		goto fw_wr_exit;
+	}
+
+	ret = __fpga_mgr_write(mgr, fw->data, fw->size);
+	if (ret)
+		goto fw_wr_exit;
+
+	strcpy(mgr->image_name, image_name);
+
+fw_wr_exit:
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
+
+/**
+ * fpga_mgr_name - returns the fpga manager name
+ * @mgr: fpga manager
+ * @buf: buffer to receive the name
+ */
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf)
+{
+	if (!mgr)
+		return -ENODEV;
+
+	return sprintf(buf, "%s\n", mgr->name);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_name);
+
+#if IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)
+static const char * const state_str[] = {
+	[FPGA_MGR_STATE_UNKNOWN] =		"unknown",
+	[FPGA_MGR_STATE_POWER_OFF] =		"power_off",
+	[FPGA_MGR_STATE_POWER_UP] =		"power_up",
+	[FPGA_MGR_STATE_RESET] =		"reset",
+
+	/* write sequence */
+	[FPGA_MGR_STATE_FIRMWARE_REQ] =		"firmware_request",
+	[FPGA_MGR_STATE_FIRMWARE_REQ_ERR] =	"firmware_request_err",
+	[FPGA_MGR_STATE_WRITE_INIT] =		"write_init",
+	[FPGA_MGR_STATE_WRITE_INIT_ERR] =	"write_init_err",
+	[FPGA_MGR_STATE_WRITE] =		"write",
+	[FPGA_MGR_STATE_WRITE_ERR] =		"write_err",
+	[FPGA_MGR_STATE_WRITE_COMPLETE] =	"write_complete",
+	[FPGA_MGR_STATE_WRITE_COMPLETE_ERR] =	"write_complete_err",
+
+	[FPGA_MGR_STATE_OPERATING] =		"operating",
+};
+
+/*
+ * class attributes
+ */
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return fpga_mgr_name(mgr, buf);
+}
+
+static ssize_t state_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return sprintf(buf, "%s\n", state_str[mgr->state]);
+}
+
+static ssize_t firmware_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return sprintf(buf, "%s\n", mgr->image_name);
+}
+
+static ssize_t firmware_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	unsigned int len;
+	char image_name[NAME_MAX];
+	int ret;
+
+	/* lose terminating \n */
+	strcpy(image_name, buf);
+	len = strlen(image_name);
+	if (image_name[len - 1] == '\n')
+		image_name[len - 1] = 0;
+
+	ret = fpga_mgr_firmware_write(mgr, image_name);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t reset_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val == 1) {
+		ret = fpga_mgr_reset(mgr);
+		if (ret)
+			return ret;
+	} else {
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(state);
+static DEVICE_ATTR_RW(firmware);
+static DEVICE_ATTR_WO(reset);
+
+static struct attribute *fpga_mgr_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_state.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_reset.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(fpga_mgr);
+#else
+#define fpga_mgr_groups NULL
+#endif /* CONFIG_FPGA_MGR_SYSFS */
+
+static int fpga_mgr_suspend(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	if (!mgr)
+		return -ENODEV;
+
+	if (mgr->mops->suspend)
+		return mgr->mops->suspend(mgr);
+
+	return 0;
+}
+
+static int fpga_mgr_resume(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	int ret = 0;
+
+	if (!mgr)
+		return -ENODEV;
+
+	if (mgr->mops->resume) {
+		ret = mgr->mops->resume(mgr);
+		if (ret)
+			return ret;
+	}
+
+	if (strlen(mgr->image_name) != 0)
+		fpga_mgr_firmware_write(mgr, mgr->image_name);
+
+	return 0;
+}
+
+static const struct dev_pm_ops fpga_mgr_dev_pm_ops = {
+	.suspend	= fpga_mgr_suspend,
+	.resume		= fpga_mgr_resume,
+};
+
+static void fpga_mgr_dev_release(struct device *dev)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	dev_dbg(dev, "releasing '%s'\n", mgr->name);
+
+	if (mgr->mops->fpga_remove)
+		mgr->mops->fpga_remove(mgr);
+
+	mgr->mops = NULL;
+
+	mutex_lock(&fpga_mgr_mutex);
+	list_del(&mgr->list);
+	mutex_unlock(&fpga_mgr_mutex);
+
+	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
+	kfree(mgr);
+}
+
+/**
+ * fpga_mgr_register - register a low level fpga manager driver
+ * @dev: fpga manager device
+ * @name: fpga manager name
+ * @mops: pointer to structure of fpga manager ops
+ * @priv: fpga manager private data
+ */
+int fpga_mgr_register(struct device *dev, const char *name,
+		      const struct fpga_manager_ops *mops,
+		      void *priv)
+{
+	struct fpga_manager *mgr;
+	int id, ret;
+
+	if (!mops || !name || !strlen(name))
+		return -EINVAL;
+
+	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+	if (!mgr)
+		return -ENOMEM;
+
+	id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return id;
+
+	mutex_init(&mgr->lock);
+
+	mgr->name = name;
+	mgr->mops = mops;
+	mgr->priv = priv;
+
+	/*
+	 * Initialize framework state by requesting low level driver read state
+	 * from device.  FPGA may be in reset mode or may have been programmed
+	 * by bootloader or EEPROM.
+	 */
+	mgr->state = fpga_mgr_low_level_state(mgr);
+
+	INIT_LIST_HEAD(&mgr->list);
+	mutex_lock(&fpga_mgr_mutex);
+	list_add(&mgr->list, &fpga_manager_list);
+	mutex_unlock(&fpga_mgr_mutex);
+
+	device_initialize(&mgr->dev);
+	mgr->dev.class = fpga_mgr_class;
+	mgr->dev.parent = dev;
+	mgr->dev.of_node = dev->of_node;
+	mgr->dev.release = fpga_mgr_dev_release;
+	mgr->dev.id = id;
+	dev_set_name(&mgr->dev, "%d", id);
+	ret = device_add(&mgr->dev);
+	if (ret)
+		goto error_device;
+
+	dev_info(&mgr->dev, "%s registered\n", mgr->name);
+
+	return 0;
+
+error_device:
+	ida_simple_remove(&fpga_mgr_ida, id);
+	kfree(mgr);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_register);
+
+/**
+ * fpga_mgr_remove - remove a low level fpga manager driver
+ * @dev: fpga manager device
+ */
+void fpga_mgr_remove(struct platform_device *pdev)
+{
+	struct list_head *tmp;
+	struct fpga_manager *mgr = NULL;
+
+	list_for_each(tmp, &fpga_manager_list) {
+		mgr = list_entry(tmp, struct fpga_manager, list);
+		if (mgr->dev.parent == &pdev->dev) {
+			device_unregister(&mgr->dev);
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_remove);
+
+static int __init fpga_mgr_dev_init(void)
+{
+	pr_info("FPGA Manager framework driver\n");
+
+	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
+	if (IS_ERR(fpga_mgr_class))
+		return PTR_ERR(fpga_mgr_class);
+
+	fpga_mgr_class->dev_groups = fpga_mgr_groups;
+	fpga_mgr_class->pm = &fpga_mgr_dev_pm_ops;
+
+	return 0;
+}
+
+static void __exit fpga_mgr_dev_exit(void)
+{
+	class_destroy(fpga_mgr_class);
+	ida_destroy(&fpga_mgr_ida);
+}
+
+MODULE_AUTHOR("Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>");
+MODULE_DESCRIPTION("FPGA Manager framework driver");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_mgr_dev_init);
+module_exit(fpga_mgr_dev_exit);
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
new file mode 100644
index 0000000..29c76d6
--- /dev/null
+++ b/include/linux/fpga/fpga-mgr.h
@@ -0,0 +1,124 @@
+/*
+ * FPGA Framework
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/limits.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+struct fpga_manager;
+
+/**
+ * struct fpga_manager_ops - ops for low level fpga manager drivers
+ * @state: returns an enum value of the FPGA's state
+ * @reset: put FPGA into reset state
+ * @write_init: prepare the FPGA to receive confuration data
+ * @write: write count bytes of configuration data to the FPGA
+ * @write_complete: set FPGA to operating state after writing is done
+ * @fpga_remove: optional: Set FPGA into a specific state during driver remove
+ * @suspend: optional: low level fpga suspend
+ * @resume: optional: low level fpga resume
+ *
+ * fpga_manager_ops are the low level functions implemented by a specific
+ * fpga manager driver.  The optional ones are tested for NULL before being
+ * called, so leaving them out is fine.
+ */
+struct fpga_manager_ops {
+	enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
+	int (*reset)(struct fpga_manager *mgr);
+	int (*write_init)(struct fpga_manager *mgr);
+	int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
+	int (*write_complete)(struct fpga_manager *mgr);
+	void (*fpga_remove)(struct fpga_manager *mgr);
+	int (*suspend)(struct fpga_manager *mgr);
+	int (*resume)(struct fpga_manager *mgr);
+};
+
+/**
+ * enum fpga_mgr_states - fpga framework states
+ * @FPGA_MGR_STATE_UNKNOWN: can't determine state
+ * @FPGA_MGR_STATE_POWER_OFF: FPGA power is off
+ * @FPGA_MGR_STATE_POWER_UP: FPGA reports power is up
+ * @FPGA_MGR_STATE_RESET: FPGA in reset state
+ * @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
+ * @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
+ * @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
+ * @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
+ * @FPGA_MGR_STATE_WRITE: writing image to FPGA
+ * @FPGA_MGR_STATE_WRITE_ERR: Error while writing FPGA
+ * @FPGA_MGR_STATE_WRITE_COMPLETE: Doing post programming steps
+ * @FPGA_MGR_STATE_WRITE_COMPLETE_ERR: Error during WRITE_COMPLETE
+ * @FPGA_MGR_STATE_OPERATING: FPGA is programmed and operating
+ */
+enum fpga_mgr_states {
+	FPGA_MGR_STATE_UNKNOWN,
+	FPGA_MGR_STATE_POWER_OFF,
+	FPGA_MGR_STATE_POWER_UP,
+	FPGA_MGR_STATE_RESET,
+
+	/* write sequence */
+	FPGA_MGR_STATE_FIRMWARE_REQ,
+	FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
+	FPGA_MGR_STATE_WRITE_INIT,
+	FPGA_MGR_STATE_WRITE_INIT_ERR,
+	FPGA_MGR_STATE_WRITE,
+	FPGA_MGR_STATE_WRITE_ERR,
+	FPGA_MGR_STATE_WRITE_COMPLETE,
+	FPGA_MGR_STATE_WRITE_COMPLETE_ERR,
+
+	FPGA_MGR_STATE_OPERATING,
+};
+
+/**
+ * struct fpga_manager - fpga manager structure
+ * @name: name of low level fpga manager
+ * @dev: fpga manager device
+ * @list: entry in list of all fpga managers
+ * @lock: lock on calls to fpga manager ops
+ * @state: state of fpga manager
+ * @image_name: name of fpga image file if any
+ * @mops: pointer to struct of fpga manager ops
+ * @priv: low level driver private date
+ */
+struct fpga_manager {
+	const char *name;
+	struct device dev;
+	struct list_head list;
+	struct mutex lock;	/* lock on calls to ops */
+	enum fpga_mgr_states state;
+	char image_name[NAME_MAX];
+
+	const struct fpga_manager_ops *mops;
+	void *priv;
+};
+
+#define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
+
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name);
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count);
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf);
+int fpga_mgr_reset(struct fpga_manager *mgr);
+int fpga_mgr_register(struct device *pdev, const char *name,
+		      const struct fpga_manager_ops *mops, void *priv);
+void fpga_mgr_remove(struct platform_device *pdev);
+
+#endif /*_LINUX_FPGA_MGR_H */
-- 
1.7.9.5

--
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 related	[flat|nested] 35+ messages in thread

* [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add driver to fpga manager framework to allow configuration
of FPGA in Altera SoCFPGA parts.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v2: fpga_manager struct now contains struct device
    fpga_manager_register parameters now take device

v3: skip a version to align versions

v4: move to drivers/staging

v5: fix array_size.cocci warnings
    fix platform_no_drv_owner.cocci warnings
    Remove .owner = THIS_MODULE
    include asm/irq.h
    clean up list of includes
    use altera_fpga_reset for ops
    use enum fpga_mgr_states or u32 as needed
    use devm_request_irq
    check irq <= 0 instead of == NO_IRQ
    Use ARRAY_SIZE
    rename altera -> socfpga
    static const socfpga_fpga_ops
    header moved to linux/fpga/ folder
    remove ifdef'ed code
    use platform_get_resource and platform_get_irq
    move .probe and .remove lines adjacent
    use module_platform_driver
    use __maybe_unused
    only need to 'if (IS_ENABLED(CONFIG_REGULATOR))' in one fn
    fix "unsigned 'mode' is never < 0"
---
 drivers/staging/fpga/Kconfig   |    5 +
 drivers/staging/fpga/Makefile  |    1 +
 drivers/staging/fpga/socfpga.c |  692 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 698 insertions(+)
 create mode 100644 drivers/staging/fpga/socfpga.c

diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
index 89ebafc..ce17342 100644
--- a/drivers/staging/fpga/Kconfig
+++ b/drivers/staging/fpga/Kconfig
@@ -19,6 +19,11 @@ config FPGA_MGR_SYSFS
 	help
 	  FPGA Manager SysFS interface.
 
+config FPGA_MGR_SOCFPGA
+	tristate "Altera SOCFPGA"
+	help
+	  FPGA manager driver support for Altera SOCFPGA.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
index ff6c677..97f7751 100644
--- a/drivers/staging/fpga/Makefile
+++ b/drivers/staging/fpga/Makefile
@@ -8,3 +8,4 @@ fpga-mgr-core-y += fpga-mgr.o
 obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 
 # FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
diff --git a/drivers/staging/fpga/socfpga.c b/drivers/staging/fpga/socfpga.c
new file mode 100644
index 0000000..ad9e99f
--- /dev/null
+++ b/drivers/staging/fpga/socfpga.c
@@ -0,0 +1,692 @@
+/*
+ * FPGA Manager Driver for Altera SOCFPGA
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/regulator/consumer.h>
+
+/* Register offsets */
+#define SOCFPGA_FPGMGR_STAT_OFST				0x0
+#define SOCFPGA_FPGMGR_CTL_OFST					0x4
+#define SOCFPGA_FPGMGR_DCLKCNT_OFST				0x8
+#define SOCFPGA_FPGMGR_DCLKSTAT_OFST				0xc
+#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST				0x830
+#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST				0x834
+#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST			0x838
+#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST			0x83c
+#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST			0x840
+#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST			0x844
+#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST			0x84c
+#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST			0x850
+
+/* Register bit defines */
+/* SOCFPGA_FPGMGR_STAT register mode field values */
+#define SOCFPGA_FPGMGR_STAT_POWER_UP				0x0 /*ramping*/
+#define SOCFPGA_FPGMGR_STAT_RESET				0x1
+#define SOCFPGA_FPGMGR_STAT_CFG					0x2
+#define SOCFPGA_FPGMGR_STAT_INIT				0x3
+#define SOCFPGA_FPGMGR_STAT_USER_MODE				0x4
+#define SOCFPGA_FPGMGR_STAT_UNKNOWN				0x5
+#define SOCFPGA_FPGMGR_STAT_STATE_MASK				0x7
+/* This is a flag value that doesn't really happen in this register field */
+#define SOCFPGA_FPGMGR_STAT_POWER_OFF				0x0
+
+#define MSEL_PP16_FAST_NOAES_NODC				0x0
+#define MSEL_PP16_FAST_AES_NODC					0x1
+#define MSEL_PP16_FAST_AESOPT_DC				0x2
+#define MSEL_PP16_SLOW_NOAES_NODC				0x4
+#define MSEL_PP16_SLOW_AES_NODC					0x5
+#define MSEL_PP16_SLOW_AESOPT_DC				0x6
+#define MSEL_PP32_FAST_NOAES_NODC				0x8
+#define MSEL_PP32_FAST_AES_NODC					0x9
+#define MSEL_PP32_FAST_AESOPT_DC				0xa
+#define MSEL_PP32_SLOW_NOAES_NODC				0xc
+#define MSEL_PP32_SLOW_AES_NODC					0xd
+#define MSEL_PP32_SLOW_AESOPT_DC				0xe
+#define SOCFPGA_FPGMGR_STAT_MSEL_MASK				0x000000f8
+#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT				3
+
+/* SOCFPGA_FPGMGR_CTL register */
+#define SOCFPGA_FPGMGR_CTL_EN					0x00000001
+#define SOCFPGA_FPGMGR_CTL_NCE					0x00000002
+#define SOCFPGA_FPGMGR_CTL_NCFGPULL				0x00000004
+
+#define CDRATIO_X1						0x00000000
+#define CDRATIO_X2						0x00000040
+#define CDRATIO_X4						0x00000080
+#define CDRATIO_X8						0x000000c0
+#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK				0x000000c0
+
+#define SOCFPGA_FPGMGR_CTL_AXICFGEN				0x00000100
+
+#define CFGWDTH_16						0x00000000
+#define CFGWDTH_32						0x00000200
+#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK				0x00000200
+
+/* SOCFPGA_FPGMGR_DCLKSTAT register */
+#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE			0x1
+
+/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */
+#define SOCFPGA_FPGMGR_MON_NSTATUS				0x0001
+#define SOCFPGA_FPGMGR_MON_CONF_DONE				0x0002
+#define SOCFPGA_FPGMGR_MON_INIT_DONE				0x0004
+#define SOCFPGA_FPGMGR_MON_CRC_ERROR				0x0008
+#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE			0x0010
+#define SOCFPGA_FPGMGR_MON_PR_READY				0x0020
+#define SOCFPGA_FPGMGR_MON_PR_ERROR				0x0040
+#define SOCFPGA_FPGMGR_MON_PR_DONE				0x0080
+#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN				0x0100
+#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN				0x0200
+#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN			0x0400
+#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON			0x0800
+#define SOCFPGA_FPGMGR_MON_STATUS_MASK				0x0fff
+
+#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3
+#define SOCFPGA_RESUME_TIMEOUT 3
+
+/* In power-up order. Reverse for power-down. */
+static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = {
+	"FPGA-1.5V",
+	"FPGA-1.1V",
+	"FPGA-2.5V",
+};
+
+struct socfpga_fpga_priv {
+	void __iomem *fpga_base_addr;
+	void __iomem *fpga_data_addr;
+	struct completion status_complete;
+	int irq;
+	struct regulator *fpga_supplies[SOCFPGA_FPGMGR_NUM_SUPPLIES];
+};
+
+struct cfgmgr_mode {
+	/* Values to set in the CTRL register */
+	u32 ctrl;
+
+	/* flag that this table entry is a valid mode */
+	bool valid;
+};
+
+/* For SOCFPGA_FPGMGR_STAT_MSEL field */
+static struct cfgmgr_mode cfgmgr_modes[] = {
+	[MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+	[MSEL_PP16_FAST_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
+	[MSEL_PP16_FAST_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
+	[MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+	[MSEL_PP16_SLOW_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
+	[MSEL_PP16_SLOW_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
+	[MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+	[MSEL_PP32_FAST_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
+	[MSEL_PP32_FAST_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
+	[MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+	[MSEL_PP32_SLOW_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
+	[MSEL_PP32_SLOW_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
+};
+
+static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset)
+{
+	return readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset,
+				u32 value)
+{
+	writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv,
+				  u32 reg_offset)
+{
+	return __raw_readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv,
+				    u32 reg_offset, u32 value)
+{
+	__raw_writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value)
+{
+	writel(value, priv->fpga_data_addr);
+}
+
+static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv,
+					  u32 offset, u32 bits)
+{
+	u32 val;
+
+	val = socfpga_fpga_readl(priv, offset);
+	val |= bits;
+	socfpga_fpga_writel(priv, offset, val);
+}
+
+static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv,
+					  u32 offset, u32 bits)
+{
+	u32 val;
+
+	val = socfpga_fpga_readl(priv, offset);
+	val &= ~bits;
+	socfpga_fpga_writel(priv, offset, val);
+}
+
+static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv)
+{
+	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) &
+		SOCFPGA_FPGMGR_MON_STATUS_MASK;
+}
+
+static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv)
+{
+	u32 status = socfpga_fpga_mon_status_get(priv);
+
+	if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0)
+		return SOCFPGA_FPGMGR_STAT_POWER_OFF;
+
+	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) &
+		SOCFPGA_FPGMGR_STAT_STATE_MASK;
+}
+
+static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv)
+{
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST,
+			    SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE);
+}
+
+/*
+ * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear
+ * the complete status.
+ */
+static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv,
+						u32 count)
+{
+	int timeout = 2;
+	u32 done;
+
+	/* Clear any existing DONE status. */
+	if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST))
+		socfpga_fpga_clear_done_status(priv);
+
+	/* Issue the DCLK count. */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count);
+
+	/* Poll DCLKSTAT to see if it completed in the timeout period. */
+	do {
+		done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST);
+		if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) {
+			socfpga_fpga_clear_done_status(priv);
+			return 0;
+		}
+		udelay(1);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv,
+				       u32 state)
+{
+	int timeout = 2;
+
+	/*
+	 * HW doesn't support an interrupt for changes in state, so poll to see
+	 * if it matches the requested state within the timeout period.
+	 */
+	do {
+		if ((socfpga_fpga_state_get(priv) & state) != 0)
+			return 0;
+		msleep(20);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs)
+{
+	/* set irqs to level sensitive */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0);
+
+	/* set interrupt polarity */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs);
+
+	/* clear irqs */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+	/* unmask interrupts */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0);
+
+	/* enable interrupts */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs);
+}
+
+static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv)
+{
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+}
+
+static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
+{
+	struct socfpga_fpga_priv *priv = dev_id;
+	u32 irqs, st;
+	bool conf_done, nstatus;
+
+	/* clear irqs */
+	irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST);
+
+	socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+	st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST);
+	conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0;
+	nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0;
+
+	/* success */
+	if (conf_done && nstatus) {
+		/* disable irqs */
+		socfpga_fpga_raw_writel(priv,
+					SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+		complete(&priv->status_complete);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
+{
+	int timeout, ret = 0;
+
+	socfpga_fpga_disable_irqs(priv);
+	init_completion(&priv->status_complete);
+	socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
+
+	timeout = wait_for_completion_interruptible_timeout(
+						&priv->status_complete,
+						msecs_to_jiffies(10));
+	if (timeout == 0)
+		ret = -ETIMEDOUT;
+
+	socfpga_fpga_disable_irqs(priv);
+	return ret;
+}
+
+static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv)
+{
+	u32 msel;
+
+	msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST);
+	msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK;
+	msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT;
+
+	/* Check that this MSEL setting is supported */
+	if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid)
+		return -EINVAL;
+
+	return msel;
+}
+
+static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv)
+{
+	u32 ctrl_reg;
+	int mode;
+
+	/* get value from MSEL pins */
+	mode = socfpga_fpga_cfg_mode_get(priv);
+	if (mode < 0)
+		return mode;
+
+	/* Adjust CTRL for the CDRATIO */
+	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK;
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK;
+	ctrl_reg |= cfgmgr_modes[mode].ctrl;
+
+	/* Set NCE to 0. */
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	return 0;
+}
+
+static int socfpga_fpga_reset(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 ctrl_reg, status;
+	int ret;
+
+	/*
+	 * Step 1:
+	 *  - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode
+	 *  - Set CTRL.NCE to 0
+	 */
+	ret = socfpga_fpga_cfg_mode_set(priv);
+	if (ret)
+		return ret;
+
+	/* Step 2: Set CTRL.EN to 1 */
+	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_EN);
+
+	/* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */
+	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+	ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	/* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */
+	status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET);
+
+	/* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	/* Timeout waiting for reset */
+	if (status)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/*
+ * Prepare the FPGA to receive the configuration data.
+ */
+static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	int ret;
+
+	/* Steps 1 - 5: Reset the FPGA */
+	ret = socfpga_fpga_reset(mgr);
+	if (ret)
+		return ret;
+
+	/* Step 6: Wait for FPGA to enter configuration phase */
+	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG))
+		return -ETIMEDOUT;
+
+	/* Step 7: Clear nSTATUS interrupt */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST,
+			    SOCFPGA_FPGMGR_MON_NSTATUS);
+
+	/* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */
+	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+	return 0;
+}
+
+/*
+ * Step 9: write data to the FPGA data register
+ */
+static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr,
+					    const char *buf, size_t count)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 *buffer_32 = (u32 *)buf;
+	size_t i = 0;
+
+	if (count <= 0)
+		return -EINVAL;
+
+	/* Write out the complete 32-bit chunks. */
+	while (count >= sizeof(u32)) {
+		socfpga_fpga_data_writel(priv, buffer_32[i++]);
+		count -= sizeof(u32);
+	}
+
+	/* Write out remaining non 32-bit chunks. */
+	switch (count) {
+	case 3:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
+		break;
+	case 2:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
+		break;
+	case 1:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
+		break;
+	default:
+		/* This will never happen. */
+		break;
+	}
+
+	return 0;
+}
+
+static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 status;
+
+	/*
+	 * Step 10:
+	 *  - Observe CONF_DONE and nSTATUS (active low)
+	 *  - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful
+	 *  - if CONF_DONE = 0 and nSTATUS = 0, configuration failed
+	 */
+	status = socfpga_fpga_wait_for_config_done(priv);
+	if (status)
+		return status;
+
+	/* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */
+	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+	/*
+	 * Step 12:
+	 *  - Write 4 to DCLKCNT
+	 *  - Wait for STATUS.DCNTDONE = 1
+	 *  - Clear W1C bit in STATUS.DCNTDONE
+	 */
+	if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4))
+		return -ETIMEDOUT;
+
+	/* Step 13: Wait for STATUS.MODE to report USER MODE */
+	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE))
+		return -ETIMEDOUT;
+
+	/* Step 14: Set CTRL.EN to 0 */
+	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_EN);
+
+	return 0;
+}
+
+/* Translate state register values to FPGA framework state */
+static const enum fpga_mgr_states socfpga_state_to_framework_state[] = {
+	[SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF,
+	[SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET,
+	[SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT,
+	[SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT,
+	[SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING,
+	[SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN,
+};
+
+static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	enum fpga_mgr_states ret;
+	u32 state;
+
+	state = socfpga_fpga_state_get(priv);
+
+	if (state < ARRAY_SIZE(socfpga_state_to_framework_state))
+		ret = socfpga_state_to_framework_state[state];
+	else
+		ret = FPGA_MGR_STATE_UNKNOWN;
+
+	return ret;
+}
+
+static int socfpga_fpga_regulators_on(struct socfpga_fpga_priv *priv)
+{
+	int i, ret;
+
+	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
+		ret = regulator_enable(priv->fpga_supplies[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void socfpga_fpga_regulators_power_off(struct socfpga_fpga_priv *priv)
+{
+	int i;
+
+	for (i = SOCFPGA_FPGMGR_NUM_SUPPLIES - 1; i >= 0; i--)
+		regulator_disable(priv->fpga_supplies[i]);
+}
+
+static int socfpga_fpga_regulator_probe(struct platform_device *pdev,
+					struct socfpga_fpga_priv *priv)
+{
+	struct regulator *supply;
+	unsigned int i;
+
+	if (!IS_ENABLED(CONFIG_REGULATOR))
+		return 0;
+
+	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
+		supply = devm_regulator_get_optional(&pdev->dev,
+						     supply_names[i]);
+		if (IS_ERR(supply)) {
+			dev_err(&pdev->dev, "could not get regulators");
+			return -EPROBE_DEFER;
+		}
+		priv->fpga_supplies[i] = supply;
+	}
+
+	return socfpga_fpga_regulators_on(priv);
+}
+
+static int socfpga_fpga_suspend(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+
+	socfpga_fpga_regulators_power_off(priv);
+
+	return 0;
+}
+
+static int socfpga_fpga_resume(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 state;
+	unsigned int timeout;
+	int ret;
+
+	ret = socfpga_fpga_regulators_on(priv);
+	if (ret)
+		return ret;
+
+	for (timeout = 0; timeout < SOCFPGA_RESUME_TIMEOUT; timeout++) {
+		state = socfpga_fpga_state_get(priv);
+		if (state != SOCFPGA_FPGMGR_STAT_POWER_OFF)
+			break;
+		msleep(20);
+	}
+	if (state == SOCFPGA_FPGMGR_STAT_POWER_OFF)
+		return -ETIMEDOUT;
+
+	return ret;
+}
+
+static const struct fpga_manager_ops socfpga_fpga_ops = {
+	.reset = socfpga_fpga_reset,
+	.state = socfpga_fpga_ops_state,
+	.write_init = socfpga_fpga_ops_configure_init,
+	.write = socfpga_fpga_ops_configure_write,
+	.write_complete = socfpga_fpga_ops_configure_complete,
+	.suspend = socfpga_fpga_suspend,
+	.resume = socfpga_fpga_resume,
+};
+
+static int socfpga_fpga_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct socfpga_fpga_priv *priv;
+	struct resource *res;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ret = socfpga_fpga_regulator_probe(pdev, priv);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->fpga_base_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->fpga_base_addr))
+		return PTR_ERR(priv->fpga_base_addr);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->fpga_data_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->fpga_data_addr))
+		return PTR_ERR(priv->fpga_base_addr);
+
+	priv->irq = platform_get_irq(pdev, 0);
+	if (priv->irq < 0)
+		return priv->irq;
+
+	ret = devm_request_irq(dev, priv->irq, socfpga_fpga_isr, 0,
+			       dev_name(dev), priv);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
+				 &socfpga_fpga_ops, priv);
+}
+
+static int socfpga_fpga_remove(struct platform_device *pdev)
+{
+	fpga_mgr_remove(pdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id socfpga_fpga_of_match[] = {
+	{ .compatible = "altr,fpga-mgr", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, socfpga_fpga_of_match);
+#endif
+
+static struct platform_driver socfpga_fpga_driver = {
+	.probe = socfpga_fpga_probe,
+	.remove = socfpga_fpga_remove,
+	.driver = {
+		.name	= "socfpga_fpga_manager",
+		.of_match_table = of_match_ptr(socfpga_fpga_of_match),
+	},
+};
+
+module_platform_driver(socfpga_fpga_driver);
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("Altera SOCFPGA FPGA Manager");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
@ 2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  0 siblings, 0 replies; 35+ messages in thread
From: atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	hpa-YMNOUZJC4hwAvxtiuMwx3w, monstr-pSz03upnqPeHXe+LvDLADg,
	michal.simek-gjFFaj9aHVfQT0dZR+AlfA,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, iws-lulEs6mt1IksTUYHLfqkUA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, pavel-ynQEQJNshbs,
	broonie-DgEjT+Ai2ygdnm+yROfE0A, philip-6RQC9ztksjxg9hUCZPvPmw,
	rubini-kaDoWcXyVrEAvxtiuMwx3w, s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ,
	jason-NLaQJdtUoK4Be96aLqz0jA, kyle.teske-acOepvfBmUk,
	nico-QSEj5FYQhm4dnm+yROfE0A, balbi-l0cyMroinI0,
	m.chehab-Sze3O3UU22JBDgjK7y7TUQ, davidb-sgV2jX0FEOL9JmXXK+q4OQ,
	rob-VoJi6FS/r0vR7s880joybQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	cesarb-PWySMVKUnqmsTnJN9+BGXg, sameo-VuQAYsv1563Yd54FQh9/CA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w,
	dinguyen-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
	yvanderv-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx, Alan Tull

From: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>

Add driver to fpga manager framework to allow configuration
of FPGA in Altera SoCFPGA parts.

Signed-off-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
---
v2: fpga_manager struct now contains struct device
    fpga_manager_register parameters now take device

v3: skip a version to align versions

v4: move to drivers/staging

v5: fix array_size.cocci warnings
    fix platform_no_drv_owner.cocci warnings
    Remove .owner = THIS_MODULE
    include asm/irq.h
    clean up list of includes
    use altera_fpga_reset for ops
    use enum fpga_mgr_states or u32 as needed
    use devm_request_irq
    check irq <= 0 instead of == NO_IRQ
    Use ARRAY_SIZE
    rename altera -> socfpga
    static const socfpga_fpga_ops
    header moved to linux/fpga/ folder
    remove ifdef'ed code
    use platform_get_resource and platform_get_irq
    move .probe and .remove lines adjacent
    use module_platform_driver
    use __maybe_unused
    only need to 'if (IS_ENABLED(CONFIG_REGULATOR))' in one fn
    fix "unsigned 'mode' is never < 0"
---
 drivers/staging/fpga/Kconfig   |    5 +
 drivers/staging/fpga/Makefile  |    1 +
 drivers/staging/fpga/socfpga.c |  692 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 698 insertions(+)
 create mode 100644 drivers/staging/fpga/socfpga.c

diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
index 89ebafc..ce17342 100644
--- a/drivers/staging/fpga/Kconfig
+++ b/drivers/staging/fpga/Kconfig
@@ -19,6 +19,11 @@ config FPGA_MGR_SYSFS
 	help
 	  FPGA Manager SysFS interface.
 
+config FPGA_MGR_SOCFPGA
+	tristate "Altera SOCFPGA"
+	help
+	  FPGA manager driver support for Altera SOCFPGA.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
index ff6c677..97f7751 100644
--- a/drivers/staging/fpga/Makefile
+++ b/drivers/staging/fpga/Makefile
@@ -8,3 +8,4 @@ fpga-mgr-core-y += fpga-mgr.o
 obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 
 # FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
diff --git a/drivers/staging/fpga/socfpga.c b/drivers/staging/fpga/socfpga.c
new file mode 100644
index 0000000..ad9e99f
--- /dev/null
+++ b/drivers/staging/fpga/socfpga.c
@@ -0,0 +1,692 @@
+/*
+ * FPGA Manager Driver for Altera SOCFPGA
+ *
+ *  Copyright (C) 2013-2014 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/regulator/consumer.h>
+
+/* Register offsets */
+#define SOCFPGA_FPGMGR_STAT_OFST				0x0
+#define SOCFPGA_FPGMGR_CTL_OFST					0x4
+#define SOCFPGA_FPGMGR_DCLKCNT_OFST				0x8
+#define SOCFPGA_FPGMGR_DCLKSTAT_OFST				0xc
+#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST				0x830
+#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST				0x834
+#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST			0x838
+#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST			0x83c
+#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST			0x840
+#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST			0x844
+#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST			0x84c
+#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST			0x850
+
+/* Register bit defines */
+/* SOCFPGA_FPGMGR_STAT register mode field values */
+#define SOCFPGA_FPGMGR_STAT_POWER_UP				0x0 /*ramping*/
+#define SOCFPGA_FPGMGR_STAT_RESET				0x1
+#define SOCFPGA_FPGMGR_STAT_CFG					0x2
+#define SOCFPGA_FPGMGR_STAT_INIT				0x3
+#define SOCFPGA_FPGMGR_STAT_USER_MODE				0x4
+#define SOCFPGA_FPGMGR_STAT_UNKNOWN				0x5
+#define SOCFPGA_FPGMGR_STAT_STATE_MASK				0x7
+/* This is a flag value that doesn't really happen in this register field */
+#define SOCFPGA_FPGMGR_STAT_POWER_OFF				0x0
+
+#define MSEL_PP16_FAST_NOAES_NODC				0x0
+#define MSEL_PP16_FAST_AES_NODC					0x1
+#define MSEL_PP16_FAST_AESOPT_DC				0x2
+#define MSEL_PP16_SLOW_NOAES_NODC				0x4
+#define MSEL_PP16_SLOW_AES_NODC					0x5
+#define MSEL_PP16_SLOW_AESOPT_DC				0x6
+#define MSEL_PP32_FAST_NOAES_NODC				0x8
+#define MSEL_PP32_FAST_AES_NODC					0x9
+#define MSEL_PP32_FAST_AESOPT_DC				0xa
+#define MSEL_PP32_SLOW_NOAES_NODC				0xc
+#define MSEL_PP32_SLOW_AES_NODC					0xd
+#define MSEL_PP32_SLOW_AESOPT_DC				0xe
+#define SOCFPGA_FPGMGR_STAT_MSEL_MASK				0x000000f8
+#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT				3
+
+/* SOCFPGA_FPGMGR_CTL register */
+#define SOCFPGA_FPGMGR_CTL_EN					0x00000001
+#define SOCFPGA_FPGMGR_CTL_NCE					0x00000002
+#define SOCFPGA_FPGMGR_CTL_NCFGPULL				0x00000004
+
+#define CDRATIO_X1						0x00000000
+#define CDRATIO_X2						0x00000040
+#define CDRATIO_X4						0x00000080
+#define CDRATIO_X8						0x000000c0
+#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK				0x000000c0
+
+#define SOCFPGA_FPGMGR_CTL_AXICFGEN				0x00000100
+
+#define CFGWDTH_16						0x00000000
+#define CFGWDTH_32						0x00000200
+#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK				0x00000200
+
+/* SOCFPGA_FPGMGR_DCLKSTAT register */
+#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE			0x1
+
+/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */
+#define SOCFPGA_FPGMGR_MON_NSTATUS				0x0001
+#define SOCFPGA_FPGMGR_MON_CONF_DONE				0x0002
+#define SOCFPGA_FPGMGR_MON_INIT_DONE				0x0004
+#define SOCFPGA_FPGMGR_MON_CRC_ERROR				0x0008
+#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE			0x0010
+#define SOCFPGA_FPGMGR_MON_PR_READY				0x0020
+#define SOCFPGA_FPGMGR_MON_PR_ERROR				0x0040
+#define SOCFPGA_FPGMGR_MON_PR_DONE				0x0080
+#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN				0x0100
+#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN				0x0200
+#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN			0x0400
+#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON			0x0800
+#define SOCFPGA_FPGMGR_MON_STATUS_MASK				0x0fff
+
+#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3
+#define SOCFPGA_RESUME_TIMEOUT 3
+
+/* In power-up order. Reverse for power-down. */
+static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = {
+	"FPGA-1.5V",
+	"FPGA-1.1V",
+	"FPGA-2.5V",
+};
+
+struct socfpga_fpga_priv {
+	void __iomem *fpga_base_addr;
+	void __iomem *fpga_data_addr;
+	struct completion status_complete;
+	int irq;
+	struct regulator *fpga_supplies[SOCFPGA_FPGMGR_NUM_SUPPLIES];
+};
+
+struct cfgmgr_mode {
+	/* Values to set in the CTRL register */
+	u32 ctrl;
+
+	/* flag that this table entry is a valid mode */
+	bool valid;
+};
+
+/* For SOCFPGA_FPGMGR_STAT_MSEL field */
+static struct cfgmgr_mode cfgmgr_modes[] = {
+	[MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+	[MSEL_PP16_FAST_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
+	[MSEL_PP16_FAST_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
+	[MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
+	[MSEL_PP16_SLOW_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
+	[MSEL_PP16_SLOW_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
+	[MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+	[MSEL_PP32_FAST_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
+	[MSEL_PP32_FAST_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
+	[MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
+	[MSEL_PP32_SLOW_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
+	[MSEL_PP32_SLOW_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
+};
+
+static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset)
+{
+	return readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset,
+				u32 value)
+{
+	writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv,
+				  u32 reg_offset)
+{
+	return __raw_readl(priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv,
+				    u32 reg_offset, u32 value)
+{
+	__raw_writel(value, priv->fpga_base_addr + reg_offset);
+}
+
+static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value)
+{
+	writel(value, priv->fpga_data_addr);
+}
+
+static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv,
+					  u32 offset, u32 bits)
+{
+	u32 val;
+
+	val = socfpga_fpga_readl(priv, offset);
+	val |= bits;
+	socfpga_fpga_writel(priv, offset, val);
+}
+
+static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv,
+					  u32 offset, u32 bits)
+{
+	u32 val;
+
+	val = socfpga_fpga_readl(priv, offset);
+	val &= ~bits;
+	socfpga_fpga_writel(priv, offset, val);
+}
+
+static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv)
+{
+	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) &
+		SOCFPGA_FPGMGR_MON_STATUS_MASK;
+}
+
+static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv)
+{
+	u32 status = socfpga_fpga_mon_status_get(priv);
+
+	if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0)
+		return SOCFPGA_FPGMGR_STAT_POWER_OFF;
+
+	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) &
+		SOCFPGA_FPGMGR_STAT_STATE_MASK;
+}
+
+static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv)
+{
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST,
+			    SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE);
+}
+
+/*
+ * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear
+ * the complete status.
+ */
+static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv,
+						u32 count)
+{
+	int timeout = 2;
+	u32 done;
+
+	/* Clear any existing DONE status. */
+	if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST))
+		socfpga_fpga_clear_done_status(priv);
+
+	/* Issue the DCLK count. */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count);
+
+	/* Poll DCLKSTAT to see if it completed in the timeout period. */
+	do {
+		done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST);
+		if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) {
+			socfpga_fpga_clear_done_status(priv);
+			return 0;
+		}
+		udelay(1);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv,
+				       u32 state)
+{
+	int timeout = 2;
+
+	/*
+	 * HW doesn't support an interrupt for changes in state, so poll to see
+	 * if it matches the requested state within the timeout period.
+	 */
+	do {
+		if ((socfpga_fpga_state_get(priv) & state) != 0)
+			return 0;
+		msleep(20);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs)
+{
+	/* set irqs to level sensitive */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0);
+
+	/* set interrupt polarity */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs);
+
+	/* clear irqs */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+	/* unmask interrupts */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0);
+
+	/* enable interrupts */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs);
+}
+
+static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv)
+{
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+}
+
+static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
+{
+	struct socfpga_fpga_priv *priv = dev_id;
+	u32 irqs, st;
+	bool conf_done, nstatus;
+
+	/* clear irqs */
+	irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST);
+
+	socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
+
+	st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST);
+	conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0;
+	nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0;
+
+	/* success */
+	if (conf_done && nstatus) {
+		/* disable irqs */
+		socfpga_fpga_raw_writel(priv,
+					SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
+		complete(&priv->status_complete);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
+{
+	int timeout, ret = 0;
+
+	socfpga_fpga_disable_irqs(priv);
+	init_completion(&priv->status_complete);
+	socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
+
+	timeout = wait_for_completion_interruptible_timeout(
+						&priv->status_complete,
+						msecs_to_jiffies(10));
+	if (timeout == 0)
+		ret = -ETIMEDOUT;
+
+	socfpga_fpga_disable_irqs(priv);
+	return ret;
+}
+
+static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv)
+{
+	u32 msel;
+
+	msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST);
+	msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK;
+	msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT;
+
+	/* Check that this MSEL setting is supported */
+	if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid)
+		return -EINVAL;
+
+	return msel;
+}
+
+static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv)
+{
+	u32 ctrl_reg;
+	int mode;
+
+	/* get value from MSEL pins */
+	mode = socfpga_fpga_cfg_mode_get(priv);
+	if (mode < 0)
+		return mode;
+
+	/* Adjust CTRL for the CDRATIO */
+	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK;
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK;
+	ctrl_reg |= cfgmgr_modes[mode].ctrl;
+
+	/* Set NCE to 0. */
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	return 0;
+}
+
+static int socfpga_fpga_reset(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 ctrl_reg, status;
+	int ret;
+
+	/*
+	 * Step 1:
+	 *  - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode
+	 *  - Set CTRL.NCE to 0
+	 */
+	ret = socfpga_fpga_cfg_mode_set(priv);
+	if (ret)
+		return ret;
+
+	/* Step 2: Set CTRL.EN to 1 */
+	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_EN);
+
+	/* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */
+	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
+	ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	/* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */
+	status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET);
+
+	/* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */
+	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL;
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
+
+	/* Timeout waiting for reset */
+	if (status)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/*
+ * Prepare the FPGA to receive the configuration data.
+ */
+static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	int ret;
+
+	/* Steps 1 - 5: Reset the FPGA */
+	ret = socfpga_fpga_reset(mgr);
+	if (ret)
+		return ret;
+
+	/* Step 6: Wait for FPGA to enter configuration phase */
+	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG))
+		return -ETIMEDOUT;
+
+	/* Step 7: Clear nSTATUS interrupt */
+	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST,
+			    SOCFPGA_FPGMGR_MON_NSTATUS);
+
+	/* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */
+	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+	return 0;
+}
+
+/*
+ * Step 9: write data to the FPGA data register
+ */
+static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr,
+					    const char *buf, size_t count)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 *buffer_32 = (u32 *)buf;
+	size_t i = 0;
+
+	if (count <= 0)
+		return -EINVAL;
+
+	/* Write out the complete 32-bit chunks. */
+	while (count >= sizeof(u32)) {
+		socfpga_fpga_data_writel(priv, buffer_32[i++]);
+		count -= sizeof(u32);
+	}
+
+	/* Write out remaining non 32-bit chunks. */
+	switch (count) {
+	case 3:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
+		break;
+	case 2:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
+		break;
+	case 1:
+		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
+		break;
+	default:
+		/* This will never happen. */
+		break;
+	}
+
+	return 0;
+}
+
+static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 status;
+
+	/*
+	 * Step 10:
+	 *  - Observe CONF_DONE and nSTATUS (active low)
+	 *  - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful
+	 *  - if CONF_DONE = 0 and nSTATUS = 0, configuration failed
+	 */
+	status = socfpga_fpga_wait_for_config_done(priv);
+	if (status)
+		return status;
+
+	/* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */
+	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
+
+	/*
+	 * Step 12:
+	 *  - Write 4 to DCLKCNT
+	 *  - Wait for STATUS.DCNTDONE = 1
+	 *  - Clear W1C bit in STATUS.DCNTDONE
+	 */
+	if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4))
+		return -ETIMEDOUT;
+
+	/* Step 13: Wait for STATUS.MODE to report USER MODE */
+	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE))
+		return -ETIMEDOUT;
+
+	/* Step 14: Set CTRL.EN to 0 */
+	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
+			       SOCFPGA_FPGMGR_CTL_EN);
+
+	return 0;
+}
+
+/* Translate state register values to FPGA framework state */
+static const enum fpga_mgr_states socfpga_state_to_framework_state[] = {
+	[SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF,
+	[SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET,
+	[SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT,
+	[SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT,
+	[SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING,
+	[SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN,
+};
+
+static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	enum fpga_mgr_states ret;
+	u32 state;
+
+	state = socfpga_fpga_state_get(priv);
+
+	if (state < ARRAY_SIZE(socfpga_state_to_framework_state))
+		ret = socfpga_state_to_framework_state[state];
+	else
+		ret = FPGA_MGR_STATE_UNKNOWN;
+
+	return ret;
+}
+
+static int socfpga_fpga_regulators_on(struct socfpga_fpga_priv *priv)
+{
+	int i, ret;
+
+	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
+		ret = regulator_enable(priv->fpga_supplies[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void socfpga_fpga_regulators_power_off(struct socfpga_fpga_priv *priv)
+{
+	int i;
+
+	for (i = SOCFPGA_FPGMGR_NUM_SUPPLIES - 1; i >= 0; i--)
+		regulator_disable(priv->fpga_supplies[i]);
+}
+
+static int socfpga_fpga_regulator_probe(struct platform_device *pdev,
+					struct socfpga_fpga_priv *priv)
+{
+	struct regulator *supply;
+	unsigned int i;
+
+	if (!IS_ENABLED(CONFIG_REGULATOR))
+		return 0;
+
+	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
+		supply = devm_regulator_get_optional(&pdev->dev,
+						     supply_names[i]);
+		if (IS_ERR(supply)) {
+			dev_err(&pdev->dev, "could not get regulators");
+			return -EPROBE_DEFER;
+		}
+		priv->fpga_supplies[i] = supply;
+	}
+
+	return socfpga_fpga_regulators_on(priv);
+}
+
+static int socfpga_fpga_suspend(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+
+	socfpga_fpga_regulators_power_off(priv);
+
+	return 0;
+}
+
+static int socfpga_fpga_resume(struct fpga_manager *mgr)
+{
+	struct socfpga_fpga_priv *priv = mgr->priv;
+	u32 state;
+	unsigned int timeout;
+	int ret;
+
+	ret = socfpga_fpga_regulators_on(priv);
+	if (ret)
+		return ret;
+
+	for (timeout = 0; timeout < SOCFPGA_RESUME_TIMEOUT; timeout++) {
+		state = socfpga_fpga_state_get(priv);
+		if (state != SOCFPGA_FPGMGR_STAT_POWER_OFF)
+			break;
+		msleep(20);
+	}
+	if (state == SOCFPGA_FPGMGR_STAT_POWER_OFF)
+		return -ETIMEDOUT;
+
+	return ret;
+}
+
+static const struct fpga_manager_ops socfpga_fpga_ops = {
+	.reset = socfpga_fpga_reset,
+	.state = socfpga_fpga_ops_state,
+	.write_init = socfpga_fpga_ops_configure_init,
+	.write = socfpga_fpga_ops_configure_write,
+	.write_complete = socfpga_fpga_ops_configure_complete,
+	.suspend = socfpga_fpga_suspend,
+	.resume = socfpga_fpga_resume,
+};
+
+static int socfpga_fpga_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct socfpga_fpga_priv *priv;
+	struct resource *res;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ret = socfpga_fpga_regulator_probe(pdev, priv);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->fpga_base_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->fpga_base_addr))
+		return PTR_ERR(priv->fpga_base_addr);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->fpga_data_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->fpga_data_addr))
+		return PTR_ERR(priv->fpga_base_addr);
+
+	priv->irq = platform_get_irq(pdev, 0);
+	if (priv->irq < 0)
+		return priv->irq;
+
+	ret = devm_request_irq(dev, priv->irq, socfpga_fpga_isr, 0,
+			       dev_name(dev), priv);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
+				 &socfpga_fpga_ops, priv);
+}
+
+static int socfpga_fpga_remove(struct platform_device *pdev)
+{
+	fpga_mgr_remove(pdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id socfpga_fpga_of_match[] = {
+	{ .compatible = "altr,fpga-mgr", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, socfpga_fpga_of_match);
+#endif
+
+static struct platform_driver socfpga_fpga_driver = {
+	.probe = socfpga_fpga_probe,
+	.remove = socfpga_fpga_remove,
+	.driver = {
+		.name	= "socfpga_fpga_manager",
+		.of_match_table = of_match_ptr(socfpga_fpga_of_match),
+	},
+};
+
+module_platform_driver(socfpga_fpga_driver);
+
+MODULE_AUTHOR("Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>");
+MODULE_DESCRIPTION("Altera SOCFPGA FPGA Manager");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

--
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 related	[flat|nested] 35+ messages in thread

* [PATCH v5 5/6] arm: dts: socfpga: add altera fpga manager
  2014-12-17 16:54 ` atull
@ 2014-12-17 16:54   ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add Altera FGPA manager to device tree.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5 : remove simple-bus and associated stuff
---
 arch/arm/boot/dts/socfpga.dtsi |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 4472fd9..a0a452b 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -751,5 +751,12 @@
 			compatible = "altr,sys-mgr", "syscon";
 			reg = <0xffd08000 0x4000>;
 		};
+
+		hps_0_fpgamgr: fpgamgr@0xff706000 {
+			compatible = "altr,fpga-mgr";
+			reg = <0xFF706000 0x1000
+			       0xFFB90000 0x1000>;
+			interrupts = <0 175 4>;
+		};
 	};
 };
-- 
1.7.9.5


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

* [PATCH v5 5/6] arm: dts: socfpga: add altera fpga manager
@ 2014-12-17 16:54   ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add Altera FGPA manager to device tree.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5 : remove simple-bus and associated stuff
---
 arch/arm/boot/dts/socfpga.dtsi |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 4472fd9..a0a452b 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -751,5 +751,12 @@
 			compatible = "altr,sys-mgr", "syscon";
 			reg = <0xffd08000 0x4000>;
 		};
+
+		hps_0_fpgamgr: fpgamgr@0xff706000 {
+			compatible = "altr,fpga-mgr";
+			reg = <0xFF706000 0x1000
+			       0xFFB90000 0x1000>;
+			interrupts = <0 175 4>;
+		};
 	};
 };
-- 
1.7.9.5

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

* [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
  2014-12-17 16:54 ` atull
@ 2014-12-17 16:54   ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Enable FPGA manager for Altera socfpga.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
---
 arch/arm/configs/socfpga_defconfig |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index a2956c3..f1d6a3b 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
 CONFIG_USB_DWC2_HOST=y
 CONFIG_MMC=y
 CONFIG_MMC_DW=y
+CONFIG_STAGING=y
+CONFIG_FPGA=y
+CONFIG_FPGA_MGR_SYSFS=y
+CONFIG_FPGA_MGR_SOCFPGA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-- 
1.7.9.5


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

* [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 16:54   ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 16:54 UTC (permalink / raw)
  To: gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Enable FPGA manager for Altera socfpga.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
---
 arch/arm/configs/socfpga_defconfig |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index a2956c3..f1d6a3b 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
 CONFIG_USB_DWC2_HOST=y
 CONFIG_MMC=y
 CONFIG_MMC_DW=y
+CONFIG_STAGING=y
+CONFIG_FPGA=y
+CONFIG_FPGA_MGR_SYSFS=y
+CONFIG_FPGA_MGR_SOCFPGA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-- 
1.7.9.5

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
  2014-12-17 16:54   ` atull
  (?)
@ 2014-12-17 17:32   ` Greg KH
  2014-12-17 18:33       ` Michal Simek
                       ` (2 more replies)
  -1 siblings, 3 replies; 35+ messages in thread
From: Greg KH @ 2014-12-17 17:32 UTC (permalink / raw)
  To: atull
  Cc: jgunthorpe, hpa, monstr, michal.simek, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv

On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> From: Alan Tull <atull@opensource.altera.com>
> 
> Enable FPGA manager for Altera socfpga.
> 
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> ---
> v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> ---
>  arch/arm/configs/socfpga_defconfig |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> index a2956c3..f1d6a3b 100644
> --- a/arch/arm/configs/socfpga_defconfig
> +++ b/arch/arm/configs/socfpga_defconfig
> @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
>  CONFIG_USB_DWC2_HOST=y
>  CONFIG_MMC=y
>  CONFIG_MMC_DW=y
> +CONFIG_STAGING=y
> +CONFIG_FPGA=y
> +CONFIG_FPGA_MGR_SYSFS=y
> +CONFIG_FPGA_MGR_SOCFPGA=y
>  CONFIG_EXT2_FS=y
>  CONFIG_EXT2_FS_XATTR=y
>  CONFIG_EXT2_FS_POSIX_ACL=y

Do defconfigs really matter anymore?

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 18:33       ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-17 18:33 UTC (permalink / raw)
  To: Greg KH, atull
  Cc: jgunthorpe, hpa, monstr, michal.simek, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv, Monam Agarwal, Insop Song

On 12/17/2014 06:32 PM, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
>> From: Alan Tull <atull@opensource.altera.com>
>>
>> Enable FPGA manager for Altera socfpga.
>>
>> Signed-off-by: Alan Tull <atull@opensource.altera.com>
>> ---
>> v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
>> ---
>>  arch/arm/configs/socfpga_defconfig |    4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
>> index a2956c3..f1d6a3b 100644
>> --- a/arch/arm/configs/socfpga_defconfig
>> +++ b/arch/arm/configs/socfpga_defconfig
>> @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
>>  CONFIG_USB_DWC2_HOST=y
>>  CONFIG_MMC=y
>>  CONFIG_MMC_DW=y
>> +CONFIG_STAGING=y
>> +CONFIG_FPGA=y
>> +CONFIG_FPGA_MGR_SYSFS=y
>> +CONFIG_FPGA_MGR_SOCFPGA=y
>>  CONFIG_EXT2_FS=y
>>  CONFIG_EXT2_FS_XATTR=y
>>  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

If they want but anyway simply 5/6 and 6/6 shouldn't be the part of this series
because they should go through arm-soc tree.

I will look at other patches tmr.

Monam, Insop: I think you should join this process because gs_fpgaboot
should be one backend driver of this interface.

Thanks,
Michal

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 18:33       ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-17 18:33 UTC (permalink / raw)
  To: Greg KH, atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
  Cc: jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	hpa-YMNOUZJC4hwAvxtiuMwx3w, monstr-pSz03upnqPeHXe+LvDLADg,
	michal.simek-gjFFaj9aHVfQT0dZR+AlfA,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, iws-lulEs6mt1IksTUYHLfqkUA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, pavel-ynQEQJNshbs,
	broonie-DgEjT+Ai2ygdnm+yROfE0A, philip-6RQC9ztksjxg9hUCZPvPmw,
	rubini-kaDoWcXyVrEAvxtiuMwx3w, s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ,
	jason-NLaQJdtUoK4Be96aLqz0jA, kyle.teske-acOepvfBmUk,
	nico-QSEj5FYQhm4dnm+yROfE0A, balbi-l0cyMroinI0,
	m.chehab-Sze3O3UU22JBDgjK7y7TUQ, davidb-sgV2jX0FEOL9JmXXK+q4OQ,
	rob-VoJi6FS/r0vR7s880joybQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	cesarb-PWySMVKUnqmsTnJN9+BGXg, sameo-VuQAYsv1563Yd54FQh9/CA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	delicious.quinoa-Re5JQEeQqe8AvxtiuMwx3w, dinguyen

On 12/17/2014 06:32 PM, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org wrote:
>> From: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
>>
>> Enable FPGA manager for Altera socfpga.
>>
>> Signed-off-by: Alan Tull <atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx@public.gmane.org>
>> ---
>> v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
>> ---
>>  arch/arm/configs/socfpga_defconfig |    4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
>> index a2956c3..f1d6a3b 100644
>> --- a/arch/arm/configs/socfpga_defconfig
>> +++ b/arch/arm/configs/socfpga_defconfig
>> @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
>>  CONFIG_USB_DWC2_HOST=y
>>  CONFIG_MMC=y
>>  CONFIG_MMC_DW=y
>> +CONFIG_STAGING=y
>> +CONFIG_FPGA=y
>> +CONFIG_FPGA_MGR_SYSFS=y
>> +CONFIG_FPGA_MGR_SOCFPGA=y
>>  CONFIG_EXT2_FS=y
>>  CONFIG_EXT2_FS_XATTR=y
>>  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

If they want but anyway simply 5/6 and 6/6 shouldn't be the part of this series
because they should go through arm-soc tree.

I will look at other patches tmr.

Monam, Insop: I think you should join this process because gs_fpgaboot
should be one backend driver of this interface.

Thanks,
Michal
--
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] 35+ messages in thread

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
  2014-12-17 17:32   ` Greg KH
@ 2014-12-17 18:46       ` Jason Cooper
  2014-12-17 18:46       ` Jason Cooper
  2014-12-17 22:00       ` Pavel Machek
  2 siblings, 0 replies; 35+ messages in thread
From: Jason Cooper @ 2014-12-17 18:46 UTC (permalink / raw)
  To: Greg KH
  Cc: atull, jgunthorpe, hpa, monstr, michal.simek, rdunlap,
	linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, kyle.teske, nico, balbi, m.chehab, davidb, rob,
	davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv

On Wed, Dec 17, 2014 at 09:32:16AM -0800, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> > From: Alan Tull <atull@opensource.altera.com>
> > 
> > Enable FPGA manager for Altera socfpga.
> > 
> > Signed-off-by: Alan Tull <atull@opensource.altera.com>
> > ---
> > v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> > ---
> >  arch/arm/configs/socfpga_defconfig |    4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> > index a2956c3..f1d6a3b 100644
> > --- a/arch/arm/configs/socfpga_defconfig
> > +++ b/arch/arm/configs/socfpga_defconfig
> > @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >  CONFIG_USB_DWC2_HOST=y
> >  CONFIG_MMC=y
> >  CONFIG_MMC_DW=y
> > +CONFIG_STAGING=y
> > +CONFIG_FPGA=y
> > +CONFIG_FPGA_MGR_SYSFS=y
> > +CONFIG_FPGA_MGR_SOCFPGA=y
> >  CONFIG_EXT2_FS=y
> >  CONFIG_EXT2_FS_XATTR=y
> >  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

Very much so.  arm-soc uses them as a standard build test target and
boot target on their bootfarms.  Please see the arm-buildbot mailinglist
at:

  http://lists.linaro.org/mailman/listinfo/kernel-build-reports

And December's results so far:

  http://lists.linaro.org/pipermail/kernel-build-reports/2014-December/thread.html

hth,

Jason.

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 18:46       ` Jason Cooper
  0 siblings, 0 replies; 35+ messages in thread
From: Jason Cooper @ 2014-12-17 18:46 UTC (permalink / raw)
  To: Greg KH
  Cc: mark.rutland, linux-doc, rubini, pantelis.antoniou, hpa,
	s.trumtrar, devel, sameo, nico, ijc+devicetree, michal.simek,
	kyle.teske, jgunthorpe, grant.likely, davidb, linus.walleij,
	cesarb, devicetree, pawel.moll, iws, atull, broonie, philip,
	dinguyen, monstr, pavel, yvanderv, linux-kernel, balbi,
	delicious.quinoa, robh+dt, rob, galak, akpm, davem, m.chehab

On Wed, Dec 17, 2014 at 09:32:16AM -0800, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> > From: Alan Tull <atull@opensource.altera.com>
> > 
> > Enable FPGA manager for Altera socfpga.
> > 
> > Signed-off-by: Alan Tull <atull@opensource.altera.com>
> > ---
> > v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> > ---
> >  arch/arm/configs/socfpga_defconfig |    4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> > index a2956c3..f1d6a3b 100644
> > --- a/arch/arm/configs/socfpga_defconfig
> > +++ b/arch/arm/configs/socfpga_defconfig
> > @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >  CONFIG_USB_DWC2_HOST=y
> >  CONFIG_MMC=y
> >  CONFIG_MMC_DW=y
> > +CONFIG_STAGING=y
> > +CONFIG_FPGA=y
> > +CONFIG_FPGA_MGR_SYSFS=y
> > +CONFIG_FPGA_MGR_SOCFPGA=y
> >  CONFIG_EXT2_FS=y
> >  CONFIG_EXT2_FS_XATTR=y
> >  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

Very much so.  arm-soc uses them as a standard build test target and
boot target on their bootfarms.  Please see the arm-buildbot mailinglist
at:

  http://lists.linaro.org/mailman/listinfo/kernel-build-reports

And December's results so far:

  http://lists.linaro.org/pipermail/kernel-build-reports/2014-December/thread.html

hth,

Jason.

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
  2014-12-17 18:33       ` Michal Simek
@ 2014-12-17 19:41         ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 19:41 UTC (permalink / raw)
  To: Michal Simek
  Cc: Greg KH, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv, Monam Agarwal, Insop Song

On Wed, 17 Dec 2014, Michal Simek wrote:

> On 12/17/2014 06:32 PM, Greg KH wrote:
> > On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> >> From: Alan Tull <atull@opensource.altera.com>
> >>
> >> Enable FPGA manager for Altera socfpga.
> >>
> >> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> >> ---
> >> v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> >> ---
> >>  arch/arm/configs/socfpga_defconfig |    4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> >> index a2956c3..f1d6a3b 100644
> >> --- a/arch/arm/configs/socfpga_defconfig
> >> +++ b/arch/arm/configs/socfpga_defconfig
> >> @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >>  CONFIG_USB_DWC2_HOST=y
> >>  CONFIG_MMC=y
> >>  CONFIG_MMC_DW=y
> >> +CONFIG_STAGING=y
> >> +CONFIG_FPGA=y
> >> +CONFIG_FPGA_MGR_SYSFS=y
> >> +CONFIG_FPGA_MGR_SOCFPGA=y
> >>  CONFIG_EXT2_FS=y
> >>  CONFIG_EXT2_FS_XATTR=y
> >>  CONFIG_EXT2_FS_POSIX_ACL=y
> > 
> > Do defconfigs really matter anymore?
> 
> If they want but anyway simply 5/6 and 6/6 shouldn't be the part of this series
> because they should go through arm-soc tree.
> 
> I will look at other patches tmr.
> 
> Monam, Insop: I think you should join this process because gs_fpgaboot
> should be one backend driver of this interface.
> 
> Thanks,
> Michal
> 

OK, we can drop 5/6 and 6/6 from this series.  I'll handle them 
separately.

Alan

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 19:41         ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-17 19:41 UTC (permalink / raw)
  To: Michal Simek
  Cc: Greg KH, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa

On Wed, 17 Dec 2014, Michal Simek wrote:

> On 12/17/2014 06:32 PM, Greg KH wrote:
> > On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> >> From: Alan Tull <atull@opensource.altera.com>
> >>
> >> Enable FPGA manager for Altera socfpga.
> >>
> >> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> >> ---
> >> v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> >> ---
> >>  arch/arm/configs/socfpga_defconfig |    4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> >> index a2956c3..f1d6a3b 100644
> >> --- a/arch/arm/configs/socfpga_defconfig
> >> +++ b/arch/arm/configs/socfpga_defconfig
> >> @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >>  CONFIG_USB_DWC2_HOST=y
> >>  CONFIG_MMC=y
> >>  CONFIG_MMC_DW=y
> >> +CONFIG_STAGING=y
> >> +CONFIG_FPGA=y
> >> +CONFIG_FPGA_MGR_SYSFS=y
> >> +CONFIG_FPGA_MGR_SOCFPGA=y
> >>  CONFIG_EXT2_FS=y
> >>  CONFIG_EXT2_FS_XATTR=y
> >>  CONFIG_EXT2_FS_POSIX_ACL=y
> > 
> > Do defconfigs really matter anymore?
> 
> If they want but anyway simply 5/6 and 6/6 shouldn't be the part of this series
> because they should go through arm-soc tree.
> 
> I will look at other patches tmr.
> 
> Monam, Insop: I think you should join this process because gs_fpgaboot
> should be one backend driver of this interface.
> 
> Thanks,
> Michal
> 

OK, we can drop 5/6 and 6/6 from this series.  I'll handle them 
separately.

Alan

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
  2014-12-17 17:32   ` Greg KH
@ 2014-12-17 22:00       ` Pavel Machek
  2014-12-17 18:46       ` Jason Cooper
  2014-12-17 22:00       ` Pavel Machek
  2 siblings, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2014-12-17 22:00 UTC (permalink / raw)
  To: Greg KH
  Cc: atull, jgunthorpe, hpa, monstr, michal.simek, rdunlap,
	linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv

On Wed 2014-12-17 09:32:16, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> > From: Alan Tull <atull@opensource.altera.com>
> > 
> > Enable FPGA manager for Altera socfpga.
> > 
> > Signed-off-by: Alan Tull <atull@opensource.altera.com>
> > ---
> > v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> > ---
> >  arch/arm/configs/socfpga_defconfig |    4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> > index a2956c3..f1d6a3b 100644
> > --- a/arch/arm/configs/socfpga_defconfig
> > +++ b/arch/arm/configs/socfpga_defconfig
> > @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >  CONFIG_USB_DWC2_HOST=y
> >  CONFIG_MMC=y
> >  CONFIG_MMC_DW=y
> > +CONFIG_STAGING=y
> > +CONFIG_FPGA=y
> > +CONFIG_FPGA_MGR_SYSFS=y
> > +CONFIG_FPGA_MGR_SOCFPGA=y
> >  CONFIG_EXT2_FS=y
> >  CONFIG_EXT2_FS_XATTR=y
> >  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

For embedded, yes they do. It should not be that way, but figuring out
useful configuration can take hours...
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: [PATCH v5 6/6] ARM: socfpga: defconfig: enable fpga manager
@ 2014-12-17 22:00       ` Pavel Machek
  0 siblings, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2014-12-17 22:00 UTC (permalink / raw)
  To: Greg KH
  Cc: mark.rutland, linux-doc, rubini, pantelis.antoniou, hpa,
	s.trumtrar, devel, sameo, nico, ijc+devicetree, michal.simek,
	kyle.teske, jgunthorpe, grant.likely, davidb, linus.walleij,
	cesarb, devicetree, jason, pawel.moll, iws, atull, broonie,
	philip, dinguyen, monstr, yvanderv, linux-kernel, balbi,
	delicious.quinoa, robh+dt, rob, galak, akpm, davem, m.chehab

On Wed 2014-12-17 09:32:16, Greg KH wrote:
> On Wed, Dec 17, 2014 at 10:54:49AM -0600, atull@opensource.altera.com wrote:
> > From: Alan Tull <atull@opensource.altera.com>
> > 
> > Enable FPGA manager for Altera socfpga.
> > 
> > Signed-off-by: Alan Tull <atull@opensource.altera.com>
> > ---
> > v5: s/CONFIG_FPGA_MGR_ALTERA/CONFIG_FPGA_MGR_SOCFPGA/
> > ---
> >  arch/arm/configs/socfpga_defconfig |    4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
> > index a2956c3..f1d6a3b 100644
> > --- a/arch/arm/configs/socfpga_defconfig
> > +++ b/arch/arm/configs/socfpga_defconfig
> > @@ -86,6 +86,10 @@ CONFIG_USB_DWC2=y
> >  CONFIG_USB_DWC2_HOST=y
> >  CONFIG_MMC=y
> >  CONFIG_MMC_DW=y
> > +CONFIG_STAGING=y
> > +CONFIG_FPGA=y
> > +CONFIG_FPGA_MGR_SYSFS=y
> > +CONFIG_FPGA_MGR_SOCFPGA=y
> >  CONFIG_EXT2_FS=y
> >  CONFIG_EXT2_FS_XATTR=y
> >  CONFIG_EXT2_FS_POSIX_ACL=y
> 
> Do defconfigs really matter anymore?

For embedded, yes they do. It should not be that way, but figuring out
useful configuration can take hours...
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
  2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
@ 2014-12-18 15:31     ` Michal Simek
  -1 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-18 15:31 UTC (permalink / raw)
  To: atull, gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv

On 12/17/2014 05:54 PM, atull@opensource.altera.com wrote:
> From: Alan Tull <atull@opensource.altera.com>
> 
> Add driver to fpga manager framework to allow configuration
> of FPGA in Altera SoCFPGA parts.
> 
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> ---
> v2: fpga_manager struct now contains struct device
>     fpga_manager_register parameters now take device
> 
> v3: skip a version to align versions
> 
> v4: move to drivers/staging
> 
> v5: fix array_size.cocci warnings
>     fix platform_no_drv_owner.cocci warnings
>     Remove .owner = THIS_MODULE
>     include asm/irq.h
>     clean up list of includes
>     use altera_fpga_reset for ops
>     use enum fpga_mgr_states or u32 as needed
>     use devm_request_irq
>     check irq <= 0 instead of == NO_IRQ
>     Use ARRAY_SIZE
>     rename altera -> socfpga
>     static const socfpga_fpga_ops
>     header moved to linux/fpga/ folder
>     remove ifdef'ed code
>     use platform_get_resource and platform_get_irq
>     move .probe and .remove lines adjacent
>     use module_platform_driver
>     use __maybe_unused
>     only need to 'if (IS_ENABLED(CONFIG_REGULATOR))' in one fn
>     fix "unsigned 'mode' is never < 0"
> ---
>  drivers/staging/fpga/Kconfig   |    5 +
>  drivers/staging/fpga/Makefile  |    1 +
>  drivers/staging/fpga/socfpga.c |  692 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 698 insertions(+)
>  create mode 100644 drivers/staging/fpga/socfpga.c
> 
> diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
> index 89ebafc..ce17342 100644
> --- a/drivers/staging/fpga/Kconfig
> +++ b/drivers/staging/fpga/Kconfig
> @@ -19,6 +19,11 @@ config FPGA_MGR_SYSFS
>  	help
>  	  FPGA Manager SysFS interface.
>  
> +config FPGA_MGR_SOCFPGA
> +	tristate "Altera SOCFPGA"
> +	help
> +	  FPGA manager driver support for Altera SOCFPGA.
> +
>  endif # FPGA
>  
>  endmenu
> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> index ff6c677..97f7751 100644
> --- a/drivers/staging/fpga/Makefile
> +++ b/drivers/staging/fpga/Makefile
> @@ -8,3 +8,4 @@ fpga-mgr-core-y += fpga-mgr.o
>  obj-$(CONFIG_FPGA)			+= fpga-mgr.o
>  
>  # FPGA Manager Drivers
> +obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
> diff --git a/drivers/staging/fpga/socfpga.c b/drivers/staging/fpga/socfpga.c
> new file mode 100644
> index 0000000..ad9e99f
> --- /dev/null
> +++ b/drivers/staging/fpga/socfpga.c
> @@ -0,0 +1,692 @@
> +/*
> + * FPGA Manager Driver for Altera SOCFPGA
> + *
> + *  Copyright (C) 2013-2014 Altera Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/pm.h>
> +#include <linux/string.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* Register offsets */
> +#define SOCFPGA_FPGMGR_STAT_OFST				0x0
> +#define SOCFPGA_FPGMGR_CTL_OFST					0x4
> +#define SOCFPGA_FPGMGR_DCLKCNT_OFST				0x8
> +#define SOCFPGA_FPGMGR_DCLKSTAT_OFST				0xc
> +#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST				0x830
> +#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST				0x834
> +#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST			0x838
> +#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST			0x83c
> +#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST			0x840
> +#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST			0x844
> +#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST			0x84c
> +#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST			0x850
> +
> +/* Register bit defines */
> +/* SOCFPGA_FPGMGR_STAT register mode field values */
> +#define SOCFPGA_FPGMGR_STAT_POWER_UP				0x0 /*ramping*/
> +#define SOCFPGA_FPGMGR_STAT_RESET				0x1
> +#define SOCFPGA_FPGMGR_STAT_CFG					0x2
> +#define SOCFPGA_FPGMGR_STAT_INIT				0x3
> +#define SOCFPGA_FPGMGR_STAT_USER_MODE				0x4
> +#define SOCFPGA_FPGMGR_STAT_UNKNOWN				0x5
> +#define SOCFPGA_FPGMGR_STAT_STATE_MASK				0x7
> +/* This is a flag value that doesn't really happen in this register field */
> +#define SOCFPGA_FPGMGR_STAT_POWER_OFF				0x0
> +
> +#define MSEL_PP16_FAST_NOAES_NODC				0x0
> +#define MSEL_PP16_FAST_AES_NODC					0x1
> +#define MSEL_PP16_FAST_AESOPT_DC				0x2
> +#define MSEL_PP16_SLOW_NOAES_NODC				0x4
> +#define MSEL_PP16_SLOW_AES_NODC					0x5
> +#define MSEL_PP16_SLOW_AESOPT_DC				0x6
> +#define MSEL_PP32_FAST_NOAES_NODC				0x8
> +#define MSEL_PP32_FAST_AES_NODC					0x9
> +#define MSEL_PP32_FAST_AESOPT_DC				0xa
> +#define MSEL_PP32_SLOW_NOAES_NODC				0xc
> +#define MSEL_PP32_SLOW_AES_NODC					0xd
> +#define MSEL_PP32_SLOW_AESOPT_DC				0xe
> +#define SOCFPGA_FPGMGR_STAT_MSEL_MASK				0x000000f8
> +#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT				3
> +
> +/* SOCFPGA_FPGMGR_CTL register */
> +#define SOCFPGA_FPGMGR_CTL_EN					0x00000001
> +#define SOCFPGA_FPGMGR_CTL_NCE					0x00000002
> +#define SOCFPGA_FPGMGR_CTL_NCFGPULL				0x00000004
> +
> +#define CDRATIO_X1						0x00000000
> +#define CDRATIO_X2						0x00000040
> +#define CDRATIO_X4						0x00000080
> +#define CDRATIO_X8						0x000000c0
> +#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK				0x000000c0
> +
> +#define SOCFPGA_FPGMGR_CTL_AXICFGEN				0x00000100
> +
> +#define CFGWDTH_16						0x00000000
> +#define CFGWDTH_32						0x00000200
> +#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK				0x00000200
> +
> +/* SOCFPGA_FPGMGR_DCLKSTAT register */
> +#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE			0x1
> +
> +/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */
> +#define SOCFPGA_FPGMGR_MON_NSTATUS				0x0001
> +#define SOCFPGA_FPGMGR_MON_CONF_DONE				0x0002
> +#define SOCFPGA_FPGMGR_MON_INIT_DONE				0x0004
> +#define SOCFPGA_FPGMGR_MON_CRC_ERROR				0x0008
> +#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE			0x0010
> +#define SOCFPGA_FPGMGR_MON_PR_READY				0x0020
> +#define SOCFPGA_FPGMGR_MON_PR_ERROR				0x0040
> +#define SOCFPGA_FPGMGR_MON_PR_DONE				0x0080
> +#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN				0x0100
> +#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN				0x0200
> +#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN			0x0400
> +#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON			0x0800
> +#define SOCFPGA_FPGMGR_MON_STATUS_MASK				0x0fff
> +
> +#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3
> +#define SOCFPGA_RESUME_TIMEOUT 3
> +
> +/* In power-up order. Reverse for power-down. */
> +static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = {
> +	"FPGA-1.5V",
> +	"FPGA-1.1V",
> +	"FPGA-2.5V",
> +};
> +
> +struct socfpga_fpga_priv {
> +	void __iomem *fpga_base_addr;
> +	void __iomem *fpga_data_addr;
> +	struct completion status_complete;
> +	int irq;
> +	struct regulator *fpga_supplies[SOCFPGA_FPGMGR_NUM_SUPPLIES];
> +};
> +
> +struct cfgmgr_mode {
> +	/* Values to set in the CTRL register */
> +	u32 ctrl;
> +
> +	/* flag that this table entry is a valid mode */
> +	bool valid;
> +};
> +
> +/* For SOCFPGA_FPGMGR_STAT_MSEL field */
> +static struct cfgmgr_mode cfgmgr_modes[] = {
> +	[MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
> +	[MSEL_PP16_FAST_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
> +	[MSEL_PP16_FAST_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
> +	[MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
> +	[MSEL_PP16_SLOW_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
> +	[MSEL_PP16_SLOW_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
> +	[MSEL_PP32_FAST_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_FAST_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
> +	[MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
> +	[MSEL_PP32_SLOW_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_SLOW_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
> +};
> +
> +static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset)
> +{
> +	return readl(priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset,
> +				u32 value)
> +{
> +	writel(value, priv->fpga_base_addr + reg_offset);
> +}
> +
> +static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv,
> +				  u32 reg_offset)
> +{
> +	return __raw_readl(priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv,
> +				    u32 reg_offset, u32 value)
> +{
> +	__raw_writel(value, priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value)
> +{
> +	writel(value, priv->fpga_data_addr);
> +}
> +
> +static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv,
> +					  u32 offset, u32 bits)
> +{
> +	u32 val;
> +
> +	val = socfpga_fpga_readl(priv, offset);
> +	val |= bits;
> +	socfpga_fpga_writel(priv, offset, val);
> +}
> +
> +static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv,
> +					  u32 offset, u32 bits)
> +{
> +	u32 val;
> +
> +	val = socfpga_fpga_readl(priv, offset);
> +	val &= ~bits;
> +	socfpga_fpga_writel(priv, offset, val);
> +}
> +
> +static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv)
> +{
> +	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) &
> +		SOCFPGA_FPGMGR_MON_STATUS_MASK;
> +}
> +
> +static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv)
> +{
> +	u32 status = socfpga_fpga_mon_status_get(priv);
> +
> +	if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0)
> +		return SOCFPGA_FPGMGR_STAT_POWER_OFF;
> +
> +	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) &
> +		SOCFPGA_FPGMGR_STAT_STATE_MASK;
> +}
> +
> +static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv)
> +{
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST,
> +			    SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE);
> +}
> +
> +/*
> + * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear
> + * the complete status.
> + */
> +static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv,
> +						u32 count)
> +{
> +	int timeout = 2;
> +	u32 done;
> +
> +	/* Clear any existing DONE status. */
> +	if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST))
> +		socfpga_fpga_clear_done_status(priv);
> +
> +	/* Issue the DCLK count. */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count);
> +
> +	/* Poll DCLKSTAT to see if it completed in the timeout period. */
> +	do {
> +		done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST);
> +		if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) {
> +			socfpga_fpga_clear_done_status(priv);
> +			return 0;
> +		}
> +		udelay(1);
> +	} while (timeout--);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv,
> +				       u32 state)
> +{
> +	int timeout = 2;
> +
> +	/*
> +	 * HW doesn't support an interrupt for changes in state, so poll to see
> +	 * if it matches the requested state within the timeout period.
> +	 */
> +	do {
> +		if ((socfpga_fpga_state_get(priv) & state) != 0)
> +			return 0;
> +		msleep(20);
> +	} while (timeout--);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs)
> +{
> +	/* set irqs to level sensitive */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0);
> +
> +	/* set interrupt polarity */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs);
> +
> +	/* clear irqs */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
> +
> +	/* unmask interrupts */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0);
> +
> +	/* enable interrupts */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs);
> +}
> +
> +static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv)
> +{
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
> +}
> +
> +static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
> +{
> +	struct socfpga_fpga_priv *priv = dev_id;
> +	u32 irqs, st;
> +	bool conf_done, nstatus;
> +
> +	/* clear irqs */
> +	irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST);
> +
> +	socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
> +
> +	st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST);
> +	conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0;
> +	nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0;
> +
> +	/* success */
> +	if (conf_done && nstatus) {
> +		/* disable irqs */
> +		socfpga_fpga_raw_writel(priv,
> +					SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
> +		complete(&priv->status_complete);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
> +{
> +	int timeout, ret = 0;
> +
> +	socfpga_fpga_disable_irqs(priv);
> +	init_completion(&priv->status_complete);
> +	socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
> +
> +	timeout = wait_for_completion_interruptible_timeout(
> +						&priv->status_complete,
> +						msecs_to_jiffies(10));
> +	if (timeout == 0)
> +		ret = -ETIMEDOUT;
> +
> +	socfpga_fpga_disable_irqs(priv);
> +	return ret;
> +}
> +
> +static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv)
> +{
> +	u32 msel;
> +
> +	msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST);
> +	msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK;
> +	msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT;
> +
> +	/* Check that this MSEL setting is supported */
> +	if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid)
> +		return -EINVAL;
> +
> +	return msel;
> +}
> +
> +static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv)
> +{
> +	u32 ctrl_reg;
> +	int mode;
> +
> +	/* get value from MSEL pins */
> +	mode = socfpga_fpga_cfg_mode_get(priv);
> +	if (mode < 0)
> +		return mode;
> +
> +	/* Adjust CTRL for the CDRATIO */
> +	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK;
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK;
> +	ctrl_reg |= cfgmgr_modes[mode].ctrl;
> +
> +	/* Set NCE to 0. */
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_reset(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 ctrl_reg, status;
> +	int ret;
> +
> +	/*
> +	 * Step 1:
> +	 *  - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode
> +	 *  - Set CTRL.NCE to 0
> +	 */
> +	ret = socfpga_fpga_cfg_mode_set(priv);
> +	if (ret)
> +		return ret;
> +
> +	/* Step 2: Set CTRL.EN to 1 */
> +	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_EN);
> +
> +	/* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */
> +	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
> +	ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	/* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */
> +	status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET);
> +
> +	/* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	/* Timeout waiting for reset */
> +	if (status)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +/*
> + * Prepare the FPGA to receive the configuration data.
> + */
> +static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	int ret;
> +
> +	/* Steps 1 - 5: Reset the FPGA */
> +	ret = socfpga_fpga_reset(mgr);
> +	if (ret)
> +		return ret;
> +
> +	/* Step 6: Wait for FPGA to enter configuration phase */
> +	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG))
> +		return -ETIMEDOUT;
> +
> +	/* Step 7: Clear nSTATUS interrupt */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST,
> +			    SOCFPGA_FPGMGR_MON_NSTATUS);
> +
> +	/* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */
> +	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
> +
> +	return 0;
> +}
> +
> +/*
> + * Step 9: write data to the FPGA data register
> + */
> +static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr,
> +					    const char *buf, size_t count)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 *buffer_32 = (u32 *)buf;
> +	size_t i = 0;
> +
> +	if (count <= 0)
> +		return -EINVAL;
> +
> +	/* Write out the complete 32-bit chunks. */
> +	while (count >= sizeof(u32)) {
> +		socfpga_fpga_data_writel(priv, buffer_32[i++]);
> +		count -= sizeof(u32);
> +	}
> +
> +	/* Write out remaining non 32-bit chunks. */
> +	switch (count) {
> +	case 3:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
> +		break;
> +	case 2:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
> +		break;
> +	case 1:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
> +		break;
> +	default:
> +		/* This will never happen. */

why not just return any error code here even if this can't happen.


> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 status;
> +
> +	/*
> +	 * Step 10:
> +	 *  - Observe CONF_DONE and nSTATUS (active low)
> +	 *  - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful
> +	 *  - if CONF_DONE = 0 and nSTATUS = 0, configuration failed
> +	 */
> +	status = socfpga_fpga_wait_for_config_done(priv);
> +	if (status)
> +		return status;
> +
> +	/* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */
> +	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
> +
> +	/*
> +	 * Step 12:
> +	 *  - Write 4 to DCLKCNT
> +	 *  - Wait for STATUS.DCNTDONE = 1
> +	 *  - Clear W1C bit in STATUS.DCNTDONE
> +	 */
> +	if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4))
> +		return -ETIMEDOUT;
> +
> +	/* Step 13: Wait for STATUS.MODE to report USER MODE */
> +	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE))
> +		return -ETIMEDOUT;
> +
> +	/* Step 14: Set CTRL.EN to 0 */
> +	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_EN);
> +
> +	return 0;
> +}
> +
> +/* Translate state register values to FPGA framework state */
> +static const enum fpga_mgr_states socfpga_state_to_framework_state[] = {
> +	[SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF,
> +	[SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET,
> +	[SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT,
> +	[SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT,
> +	[SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING,
> +	[SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN,
> +};
> +
> +static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	enum fpga_mgr_states ret;
> +	u32 state;
> +
> +	state = socfpga_fpga_state_get(priv);
> +
> +	if (state < ARRAY_SIZE(socfpga_state_to_framework_state))
> +		ret = socfpga_state_to_framework_state[state];
> +	else
> +		ret = FPGA_MGR_STATE_UNKNOWN;
> +
> +	return ret;
> +}
> +
> +static int socfpga_fpga_regulators_on(struct socfpga_fpga_priv *priv)
> +{
> +	int i, ret;
> +
> +	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
> +		ret = regulator_enable(priv->fpga_supplies[i]);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void socfpga_fpga_regulators_power_off(struct socfpga_fpga_priv *priv)
> +{
> +	int i;
> +
> +	for (i = SOCFPGA_FPGMGR_NUM_SUPPLIES - 1; i >= 0; i--)
> +		regulator_disable(priv->fpga_supplies[i]);
> +}
> +
> +static int socfpga_fpga_regulator_probe(struct platform_device *pdev,
> +					struct socfpga_fpga_priv *priv)
> +{
> +	struct regulator *supply;
> +	unsigned int i;
> +
> +	if (!IS_ENABLED(CONFIG_REGULATOR))
> +		return 0;
> +
> +	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
> +		supply = devm_regulator_get_optional(&pdev->dev,
> +						     supply_names[i]);
> +		if (IS_ERR(supply)) {
> +			dev_err(&pdev->dev, "could not get regulators");
> +			return -EPROBE_DEFER;
> +		}
> +		priv->fpga_supplies[i] = supply;
> +	}
> +
> +	return socfpga_fpga_regulators_on(priv);
> +}
> +
> +static int socfpga_fpga_suspend(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +
> +	socfpga_fpga_regulators_power_off(priv);
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_resume(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 state;
> +	unsigned int timeout;

add it to one line.

The rest is looks good to me. I think this is good to go in.

Acked-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal

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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
@ 2014-12-18 15:31     ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-18 15:31 UTC (permalink / raw)
  To: atull, gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv

On 12/17/2014 05:54 PM, atull@opensource.altera.com wrote:
> From: Alan Tull <atull@opensource.altera.com>
> 
> Add driver to fpga manager framework to allow configuration
> of FPGA in Altera SoCFPGA parts.
> 
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> ---
> v2: fpga_manager struct now contains struct device
>     fpga_manager_register parameters now take device
> 
> v3: skip a version to align versions
> 
> v4: move to drivers/staging
> 
> v5: fix array_size.cocci warnings
>     fix platform_no_drv_owner.cocci warnings
>     Remove .owner = THIS_MODULE
>     include asm/irq.h
>     clean up list of includes
>     use altera_fpga_reset for ops
>     use enum fpga_mgr_states or u32 as needed
>     use devm_request_irq
>     check irq <= 0 instead of == NO_IRQ
>     Use ARRAY_SIZE
>     rename altera -> socfpga
>     static const socfpga_fpga_ops
>     header moved to linux/fpga/ folder
>     remove ifdef'ed code
>     use platform_get_resource and platform_get_irq
>     move .probe and .remove lines adjacent
>     use module_platform_driver
>     use __maybe_unused
>     only need to 'if (IS_ENABLED(CONFIG_REGULATOR))' in one fn
>     fix "unsigned 'mode' is never < 0"
> ---
>  drivers/staging/fpga/Kconfig   |    5 +
>  drivers/staging/fpga/Makefile  |    1 +
>  drivers/staging/fpga/socfpga.c |  692 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 698 insertions(+)
>  create mode 100644 drivers/staging/fpga/socfpga.c
> 
> diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
> index 89ebafc..ce17342 100644
> --- a/drivers/staging/fpga/Kconfig
> +++ b/drivers/staging/fpga/Kconfig
> @@ -19,6 +19,11 @@ config FPGA_MGR_SYSFS
>  	help
>  	  FPGA Manager SysFS interface.
>  
> +config FPGA_MGR_SOCFPGA
> +	tristate "Altera SOCFPGA"
> +	help
> +	  FPGA manager driver support for Altera SOCFPGA.
> +
>  endif # FPGA
>  
>  endmenu
> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> index ff6c677..97f7751 100644
> --- a/drivers/staging/fpga/Makefile
> +++ b/drivers/staging/fpga/Makefile
> @@ -8,3 +8,4 @@ fpga-mgr-core-y += fpga-mgr.o
>  obj-$(CONFIG_FPGA)			+= fpga-mgr.o
>  
>  # FPGA Manager Drivers
> +obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
> diff --git a/drivers/staging/fpga/socfpga.c b/drivers/staging/fpga/socfpga.c
> new file mode 100644
> index 0000000..ad9e99f
> --- /dev/null
> +++ b/drivers/staging/fpga/socfpga.c
> @@ -0,0 +1,692 @@
> +/*
> + * FPGA Manager Driver for Altera SOCFPGA
> + *
> + *  Copyright (C) 2013-2014 Altera Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/pm.h>
> +#include <linux/string.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* Register offsets */
> +#define SOCFPGA_FPGMGR_STAT_OFST				0x0
> +#define SOCFPGA_FPGMGR_CTL_OFST					0x4
> +#define SOCFPGA_FPGMGR_DCLKCNT_OFST				0x8
> +#define SOCFPGA_FPGMGR_DCLKSTAT_OFST				0xc
> +#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST				0x830
> +#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST				0x834
> +#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST			0x838
> +#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST			0x83c
> +#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST			0x840
> +#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST			0x844
> +#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST			0x84c
> +#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST			0x850
> +
> +/* Register bit defines */
> +/* SOCFPGA_FPGMGR_STAT register mode field values */
> +#define SOCFPGA_FPGMGR_STAT_POWER_UP				0x0 /*ramping*/
> +#define SOCFPGA_FPGMGR_STAT_RESET				0x1
> +#define SOCFPGA_FPGMGR_STAT_CFG					0x2
> +#define SOCFPGA_FPGMGR_STAT_INIT				0x3
> +#define SOCFPGA_FPGMGR_STAT_USER_MODE				0x4
> +#define SOCFPGA_FPGMGR_STAT_UNKNOWN				0x5
> +#define SOCFPGA_FPGMGR_STAT_STATE_MASK				0x7
> +/* This is a flag value that doesn't really happen in this register field */
> +#define SOCFPGA_FPGMGR_STAT_POWER_OFF				0x0
> +
> +#define MSEL_PP16_FAST_NOAES_NODC				0x0
> +#define MSEL_PP16_FAST_AES_NODC					0x1
> +#define MSEL_PP16_FAST_AESOPT_DC				0x2
> +#define MSEL_PP16_SLOW_NOAES_NODC				0x4
> +#define MSEL_PP16_SLOW_AES_NODC					0x5
> +#define MSEL_PP16_SLOW_AESOPT_DC				0x6
> +#define MSEL_PP32_FAST_NOAES_NODC				0x8
> +#define MSEL_PP32_FAST_AES_NODC					0x9
> +#define MSEL_PP32_FAST_AESOPT_DC				0xa
> +#define MSEL_PP32_SLOW_NOAES_NODC				0xc
> +#define MSEL_PP32_SLOW_AES_NODC					0xd
> +#define MSEL_PP32_SLOW_AESOPT_DC				0xe
> +#define SOCFPGA_FPGMGR_STAT_MSEL_MASK				0x000000f8
> +#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT				3
> +
> +/* SOCFPGA_FPGMGR_CTL register */
> +#define SOCFPGA_FPGMGR_CTL_EN					0x00000001
> +#define SOCFPGA_FPGMGR_CTL_NCE					0x00000002
> +#define SOCFPGA_FPGMGR_CTL_NCFGPULL				0x00000004
> +
> +#define CDRATIO_X1						0x00000000
> +#define CDRATIO_X2						0x00000040
> +#define CDRATIO_X4						0x00000080
> +#define CDRATIO_X8						0x000000c0
> +#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK				0x000000c0
> +
> +#define SOCFPGA_FPGMGR_CTL_AXICFGEN				0x00000100
> +
> +#define CFGWDTH_16						0x00000000
> +#define CFGWDTH_32						0x00000200
> +#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK				0x00000200
> +
> +/* SOCFPGA_FPGMGR_DCLKSTAT register */
> +#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE			0x1
> +
> +/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */
> +#define SOCFPGA_FPGMGR_MON_NSTATUS				0x0001
> +#define SOCFPGA_FPGMGR_MON_CONF_DONE				0x0002
> +#define SOCFPGA_FPGMGR_MON_INIT_DONE				0x0004
> +#define SOCFPGA_FPGMGR_MON_CRC_ERROR				0x0008
> +#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE			0x0010
> +#define SOCFPGA_FPGMGR_MON_PR_READY				0x0020
> +#define SOCFPGA_FPGMGR_MON_PR_ERROR				0x0040
> +#define SOCFPGA_FPGMGR_MON_PR_DONE				0x0080
> +#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN				0x0100
> +#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN				0x0200
> +#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN			0x0400
> +#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON			0x0800
> +#define SOCFPGA_FPGMGR_MON_STATUS_MASK				0x0fff
> +
> +#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3
> +#define SOCFPGA_RESUME_TIMEOUT 3
> +
> +/* In power-up order. Reverse for power-down. */
> +static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = {
> +	"FPGA-1.5V",
> +	"FPGA-1.1V",
> +	"FPGA-2.5V",
> +};
> +
> +struct socfpga_fpga_priv {
> +	void __iomem *fpga_base_addr;
> +	void __iomem *fpga_data_addr;
> +	struct completion status_complete;
> +	int irq;
> +	struct regulator *fpga_supplies[SOCFPGA_FPGMGR_NUM_SUPPLIES];
> +};
> +
> +struct cfgmgr_mode {
> +	/* Values to set in the CTRL register */
> +	u32 ctrl;
> +
> +	/* flag that this table entry is a valid mode */
> +	bool valid;
> +};
> +
> +/* For SOCFPGA_FPGMGR_STAT_MSEL field */
> +static struct cfgmgr_mode cfgmgr_modes[] = {
> +	[MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
> +	[MSEL_PP16_FAST_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
> +	[MSEL_PP16_FAST_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
> +	[MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 },
> +	[MSEL_PP16_SLOW_AES_NODC] =   { CFGWDTH_16 | CDRATIO_X2, 1 },
> +	[MSEL_PP16_SLOW_AESOPT_DC] =  { CFGWDTH_16 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
> +	[MSEL_PP32_FAST_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_FAST_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
> +	[MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 },
> +	[MSEL_PP32_SLOW_AES_NODC] =   { CFGWDTH_32 | CDRATIO_X4, 1 },
> +	[MSEL_PP32_SLOW_AESOPT_DC] =  { CFGWDTH_32 | CDRATIO_X8, 1 },
> +};
> +
> +static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset)
> +{
> +	return readl(priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset,
> +				u32 value)
> +{
> +	writel(value, priv->fpga_base_addr + reg_offset);
> +}
> +
> +static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv,
> +				  u32 reg_offset)
> +{
> +	return __raw_readl(priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv,
> +				    u32 reg_offset, u32 value)
> +{
> +	__raw_writel(value, priv->fpga_base_addr + reg_offset);
> +}
> +
> +static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value)
> +{
> +	writel(value, priv->fpga_data_addr);
> +}
> +
> +static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv,
> +					  u32 offset, u32 bits)
> +{
> +	u32 val;
> +
> +	val = socfpga_fpga_readl(priv, offset);
> +	val |= bits;
> +	socfpga_fpga_writel(priv, offset, val);
> +}
> +
> +static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv,
> +					  u32 offset, u32 bits)
> +{
> +	u32 val;
> +
> +	val = socfpga_fpga_readl(priv, offset);
> +	val &= ~bits;
> +	socfpga_fpga_writel(priv, offset, val);
> +}
> +
> +static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv)
> +{
> +	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) &
> +		SOCFPGA_FPGMGR_MON_STATUS_MASK;
> +}
> +
> +static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv)
> +{
> +	u32 status = socfpga_fpga_mon_status_get(priv);
> +
> +	if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0)
> +		return SOCFPGA_FPGMGR_STAT_POWER_OFF;
> +
> +	return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) &
> +		SOCFPGA_FPGMGR_STAT_STATE_MASK;
> +}
> +
> +static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv)
> +{
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST,
> +			    SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE);
> +}
> +
> +/*
> + * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear
> + * the complete status.
> + */
> +static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv,
> +						u32 count)
> +{
> +	int timeout = 2;
> +	u32 done;
> +
> +	/* Clear any existing DONE status. */
> +	if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST))
> +		socfpga_fpga_clear_done_status(priv);
> +
> +	/* Issue the DCLK count. */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count);
> +
> +	/* Poll DCLKSTAT to see if it completed in the timeout period. */
> +	do {
> +		done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST);
> +		if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) {
> +			socfpga_fpga_clear_done_status(priv);
> +			return 0;
> +		}
> +		udelay(1);
> +	} while (timeout--);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv,
> +				       u32 state)
> +{
> +	int timeout = 2;
> +
> +	/*
> +	 * HW doesn't support an interrupt for changes in state, so poll to see
> +	 * if it matches the requested state within the timeout period.
> +	 */
> +	do {
> +		if ((socfpga_fpga_state_get(priv) & state) != 0)
> +			return 0;
> +		msleep(20);
> +	} while (timeout--);
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs)
> +{
> +	/* set irqs to level sensitive */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0);
> +
> +	/* set interrupt polarity */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs);
> +
> +	/* clear irqs */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
> +
> +	/* unmask interrupts */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0);
> +
> +	/* enable interrupts */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs);
> +}
> +
> +static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv)
> +{
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
> +}
> +
> +static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
> +{
> +	struct socfpga_fpga_priv *priv = dev_id;
> +	u32 irqs, st;
> +	bool conf_done, nstatus;
> +
> +	/* clear irqs */
> +	irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST);
> +
> +	socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs);
> +
> +	st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST);
> +	conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0;
> +	nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0;
> +
> +	/* success */
> +	if (conf_done && nstatus) {
> +		/* disable irqs */
> +		socfpga_fpga_raw_writel(priv,
> +					SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0);
> +		complete(&priv->status_complete);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
> +{
> +	int timeout, ret = 0;
> +
> +	socfpga_fpga_disable_irqs(priv);
> +	init_completion(&priv->status_complete);
> +	socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
> +
> +	timeout = wait_for_completion_interruptible_timeout(
> +						&priv->status_complete,
> +						msecs_to_jiffies(10));
> +	if (timeout == 0)
> +		ret = -ETIMEDOUT;
> +
> +	socfpga_fpga_disable_irqs(priv);
> +	return ret;
> +}
> +
> +static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv)
> +{
> +	u32 msel;
> +
> +	msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST);
> +	msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK;
> +	msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT;
> +
> +	/* Check that this MSEL setting is supported */
> +	if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid)
> +		return -EINVAL;
> +
> +	return msel;
> +}
> +
> +static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv)
> +{
> +	u32 ctrl_reg;
> +	int mode;
> +
> +	/* get value from MSEL pins */
> +	mode = socfpga_fpga_cfg_mode_get(priv);
> +	if (mode < 0)
> +		return mode;
> +
> +	/* Adjust CTRL for the CDRATIO */
> +	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK;
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK;
> +	ctrl_reg |= cfgmgr_modes[mode].ctrl;
> +
> +	/* Set NCE to 0. */
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_reset(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 ctrl_reg, status;
> +	int ret;
> +
> +	/*
> +	 * Step 1:
> +	 *  - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode
> +	 *  - Set CTRL.NCE to 0
> +	 */
> +	ret = socfpga_fpga_cfg_mode_set(priv);
> +	if (ret)
> +		return ret;
> +
> +	/* Step 2: Set CTRL.EN to 1 */
> +	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_EN);
> +
> +	/* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */
> +	ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST);
> +	ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	/* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */
> +	status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET);
> +
> +	/* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */
> +	ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL;
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg);
> +
> +	/* Timeout waiting for reset */
> +	if (status)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +/*
> + * Prepare the FPGA to receive the configuration data.
> + */
> +static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	int ret;
> +
> +	/* Steps 1 - 5: Reset the FPGA */
> +	ret = socfpga_fpga_reset(mgr);
> +	if (ret)
> +		return ret;
> +
> +	/* Step 6: Wait for FPGA to enter configuration phase */
> +	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG))
> +		return -ETIMEDOUT;
> +
> +	/* Step 7: Clear nSTATUS interrupt */
> +	socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST,
> +			    SOCFPGA_FPGMGR_MON_NSTATUS);
> +
> +	/* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */
> +	socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
> +
> +	return 0;
> +}
> +
> +/*
> + * Step 9: write data to the FPGA data register
> + */
> +static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr,
> +					    const char *buf, size_t count)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 *buffer_32 = (u32 *)buf;
> +	size_t i = 0;
> +
> +	if (count <= 0)
> +		return -EINVAL;
> +
> +	/* Write out the complete 32-bit chunks. */
> +	while (count >= sizeof(u32)) {
> +		socfpga_fpga_data_writel(priv, buffer_32[i++]);
> +		count -= sizeof(u32);
> +	}
> +
> +	/* Write out remaining non 32-bit chunks. */
> +	switch (count) {
> +	case 3:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
> +		break;
> +	case 2:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
> +		break;
> +	case 1:
> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
> +		break;
> +	default:
> +		/* This will never happen. */

why not just return any error code here even if this can't happen.


> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 status;
> +
> +	/*
> +	 * Step 10:
> +	 *  - Observe CONF_DONE and nSTATUS (active low)
> +	 *  - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful
> +	 *  - if CONF_DONE = 0 and nSTATUS = 0, configuration failed
> +	 */
> +	status = socfpga_fpga_wait_for_config_done(priv);
> +	if (status)
> +		return status;
> +
> +	/* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */
> +	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_AXICFGEN);
> +
> +	/*
> +	 * Step 12:
> +	 *  - Write 4 to DCLKCNT
> +	 *  - Wait for STATUS.DCNTDONE = 1
> +	 *  - Clear W1C bit in STATUS.DCNTDONE
> +	 */
> +	if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4))
> +		return -ETIMEDOUT;
> +
> +	/* Step 13: Wait for STATUS.MODE to report USER MODE */
> +	if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE))
> +		return -ETIMEDOUT;
> +
> +	/* Step 14: Set CTRL.EN to 0 */
> +	socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST,
> +			       SOCFPGA_FPGMGR_CTL_EN);
> +
> +	return 0;
> +}
> +
> +/* Translate state register values to FPGA framework state */
> +static const enum fpga_mgr_states socfpga_state_to_framework_state[] = {
> +	[SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF,
> +	[SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET,
> +	[SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT,
> +	[SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT,
> +	[SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING,
> +	[SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN,
> +};
> +
> +static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	enum fpga_mgr_states ret;
> +	u32 state;
> +
> +	state = socfpga_fpga_state_get(priv);
> +
> +	if (state < ARRAY_SIZE(socfpga_state_to_framework_state))
> +		ret = socfpga_state_to_framework_state[state];
> +	else
> +		ret = FPGA_MGR_STATE_UNKNOWN;
> +
> +	return ret;
> +}
> +
> +static int socfpga_fpga_regulators_on(struct socfpga_fpga_priv *priv)
> +{
> +	int i, ret;
> +
> +	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
> +		ret = regulator_enable(priv->fpga_supplies[i]);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void socfpga_fpga_regulators_power_off(struct socfpga_fpga_priv *priv)
> +{
> +	int i;
> +
> +	for (i = SOCFPGA_FPGMGR_NUM_SUPPLIES - 1; i >= 0; i--)
> +		regulator_disable(priv->fpga_supplies[i]);
> +}
> +
> +static int socfpga_fpga_regulator_probe(struct platform_device *pdev,
> +					struct socfpga_fpga_priv *priv)
> +{
> +	struct regulator *supply;
> +	unsigned int i;
> +
> +	if (!IS_ENABLED(CONFIG_REGULATOR))
> +		return 0;
> +
> +	for (i = 0; i < SOCFPGA_FPGMGR_NUM_SUPPLIES; i++) {
> +		supply = devm_regulator_get_optional(&pdev->dev,
> +						     supply_names[i]);
> +		if (IS_ERR(supply)) {
> +			dev_err(&pdev->dev, "could not get regulators");
> +			return -EPROBE_DEFER;
> +		}
> +		priv->fpga_supplies[i] = supply;
> +	}
> +
> +	return socfpga_fpga_regulators_on(priv);
> +}
> +
> +static int socfpga_fpga_suspend(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +
> +	socfpga_fpga_regulators_power_off(priv);
> +
> +	return 0;
> +}
> +
> +static int socfpga_fpga_resume(struct fpga_manager *mgr)
> +{
> +	struct socfpga_fpga_priv *priv = mgr->priv;
> +	u32 state;
> +	unsigned int timeout;

add it to one line.

The rest is looks good to me. I think this is good to go in.

Acked-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal

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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
  2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
@ 2014-12-18 18:16     ` Michal Simek
  -1 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-18 18:16 UTC (permalink / raw)
  To: atull, gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: linux-kernel, devicetree, pantelis.antoniou, robh+dt,
	grant.likely, iws, linux-doc, pavel, broonie, philip, rubini,
	s.trumtrar, jason, kyle.teske, nico, balbi, m.chehab, davidb,
	rob, davem, cesarb, sameo, akpm, linus.walleij, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devel, delicious.quinoa,
	dinguyen, yvanderv

Hi Alan,

first of all - there are these kernel-doc warnings.

Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'


On 12/17/2014 05:54 PM, atull@opensource.altera.com wrote:
> From: Alan Tull <atull@opensource.altera.com>
> 
> Supports standard ops for low level FPGA drivers.
> Various manufacturors' FPGAs can be supported by adding low
> level drivers.  Each driver needs to register its ops
> using fpga_mgr_register().
> 
> Exports methods of doing operations to program  FPGAs. These
> should be sufficient for individual drivers to request FPGA
> programming directly if desired.
> 
> Adds a sysfs interface.  The sysfs interface can be compiled out
> where desired in production builds.
> 
> Resume is supported by calling low level driver's resume
> function, then reloading the firmware image.
> 
> The following are exported as GPL:
> * fpga_mgr_reset
>    Reset the FGPA.
> 
> * fpga_mgr_write
>    Write a image (in buffer) to the FPGA.
> 
> * fpga_mgr_firmware_write
>    Request firmware by file name and write it to the FPGA.
> 
> * fpga_mgr_name
>    Get name of FPGA manager.
> 
> * fpga_mgr_state
>    Get a state of framework as a string.
> 
> * fpga_mgr_register and fpga_mgr_remove
>    Register/unregister low level fpga manager driver.
> 
> The following sysfs files are created:
> * /sys/class/fpga_manager/<fpga>/name
>   Name of low level driver.
> 
> * /sys/class/fpga_manager/<fpga>/firmware
>   Name of FPGA image file to load using firmware class.
>   $ echo image.rbf > /sys/class/fpga_manager/<fpga>/firmware
> 
>   read: read back name of image file previous loaded
>   $ cat /sys/class/fpga_manager/<fpga>/firmware
> 
> * /sys/class/fpga_manager/<fpga>/reset
>   reset the FPGA
>   $ echo 1 > /sys/class/fpga_manager/<fpga>/reset
> 
> * /sys/class/fpga_manager/<fpga>/state
>   State of fpga framework state machine
> 
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> ---
> v2: s/mangager/manager/
>     check for invalid request_nr
>     add fpga reset interface
>     rework the state code
>     remove FPGA_MGR_FAIL flag
>     add _ERR states to fpga manager states enum
>     low level state op now returns a state enum value
>     initialize framework state from driver state op
>     remove unused fpga read stuff
>     merge sysfs.c into fpga-mgr.c
>     move suspend/resume from bus.c to fpga-mgr.c
> 
> v3: Add struct device to fpga_manager (not as a pointer)
>     Add to_fpga_manager
>     Don't get irq in fpga-mgr.c (let low level driver do it)
>     remove from struct fpga_manager: nr, np, parent
>     get rid of fpga_mgr_get_new_minor()
>     simplify fpga_manager_register:
>       reorder parameters
>       use dev instead of pdev
>     get rid of code that used to make more sense when this
>       was a char driver, don't alloc_chrdev_region
>     use a mutex instead of flags
> 
> v4: Move to drivers/staging
> 
> v5: Make some things be static
>     Kconfig: add 'if FPGA'
>     Makefile: s/fpga-mgr-core.o/fpga-mgr.o/
>     clean up includes
>     use enum fpga_mgr_states instead of int
>     static const char *state_str
>     use DEVICE_ATTR_RO/RW/WO and ATTRIBUTE_GROUPS
>     return -EINVAL instead of BUG_ON
>     move ida_simple_get after kzalloc
>     clean up fpga_mgr_remove
>     fpga-mgr.h: remove '#if IS_ENABLED(CONFIG_FPGA)'
>     add kernel-doc documentation
>     Move header to new include/linux/fpga folder
>     static const struct fpga_mgr_ops
>     dev_info msg simplified
> ---
>  drivers/staging/Kconfig         |    2 +
>  drivers/staging/Makefile        |    1 +
>  drivers/staging/fpga/Kconfig    |   24 ++
>  drivers/staging/fpga/Makefile   |   10 +
>  drivers/staging/fpga/fpga-mgr.c |  523 +++++++++++++++++++++++++++++++++++++++
>  include/linux/fpga/fpga-mgr.h   |  124 ++++++++++
>  6 files changed, 684 insertions(+)
>  create mode 100644 drivers/staging/fpga/Kconfig
>  create mode 100644 drivers/staging/fpga/Makefile
>  create mode 100644 drivers/staging/fpga/fpga-mgr.c
>  create mode 100644 include/linux/fpga/fpga-mgr.h
> 
> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
> index 4690ae9..4338a4c 100644
> --- a/drivers/staging/Kconfig
> +++ b/drivers/staging/Kconfig
> @@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig"
>  
>  source "drivers/staging/unisys/Kconfig"
>  
> +source "drivers/staging/fpga/Kconfig"
> +
>  endif # STAGING
> diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
> index c780a0e..43654a2 100644
> --- a/drivers/staging/Makefile
> +++ b/drivers/staging/Makefile
> @@ -46,3 +46,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
>  obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
>  obj-$(CONFIG_CRYPTO_SKEIN)	+= skein/
>  obj-$(CONFIG_UNISYSSPAR)	+= unisys/
> +obj-$(CONFIG_FPGA)		+= fpga/
> diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
> new file mode 100644
> index 0000000..89ebafc
> --- /dev/null
> +++ b/drivers/staging/fpga/Kconfig
> @@ -0,0 +1,24 @@
> +#
> +# FPGA framework configuration
> +#
> +
> +menu "FPGA devices"
> +
> +config FPGA
> +	tristate "FPGA Framework"
> +	help
> +	  Say Y here if you want support for configuring FPGAs from the
> +	  kernel.  The FPGA framework adds a FPGA manager class and FPGA
> +	  manager drivers.
> +
> +if FPGA
> +
> +config FPGA_MGR_SYSFS
> +	bool "FPGA Manager SysFS Interface"
> +	depends on SYSFS
> +	help
> +	  FPGA Manager SysFS interface.
> +
> +endif # FPGA
> +
> +endmenu
> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> new file mode 100644
> index 0000000..ff6c677
> --- /dev/null
> +++ b/drivers/staging/fpga/Makefile
> @@ -0,0 +1,10 @@
> +#
> +# Makefile for the fpga framework and fpga manager drivers.
> +#
> +
> +fpga-mgr-core-y += fpga-mgr.o

remove this line - it is unused.

> +
> +# Core FPGA Manager Framework
> +obj-$(CONFIG_FPGA)			+= fpga-mgr.o
> +
> +# FPGA Manager Drivers
> diff --git a/drivers/staging/fpga/fpga-mgr.c b/drivers/staging/fpga/fpga-mgr.c
> new file mode 100644
> index 0000000..671b114
> --- /dev/null
> +++ b/drivers/staging/fpga/fpga-mgr.c
> @@ -0,0 +1,523 @@
> +/*
> + * FPGA Manager Core
> + *
> + *  Copyright (C) 2013-2014 Altera Corporation
> + *
> + * With code from the mailing list:
> + * Copyright (C) 2013 Xilinx, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/delay.h>
> +#include <linux/firmware.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/idr.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/slab.h>
> +
> +static DEFINE_MUTEX(fpga_mgr_mutex);
> +static DEFINE_IDA(fpga_mgr_ida);
> +static struct class *fpga_mgr_class;
> +
> +static LIST_HEAD(fpga_manager_list);
> +
> +/**
> + * fpga_mgr_low_level_state - get FPGA state from low level driver
> + * @mgr: fpga manager
> + *
> + * This will be used to initialize framework state
> + */
> +static enum fpga_mgr_states fpga_mgr_low_level_state(struct fpga_manager *mgr)
> +{
> +	if (!mgr || !mgr->mops || !mgr->mops->state)
> +		return FPGA_MGR_STATE_UNKNOWN;
> +
> +	return mgr->mops->state(mgr);
> +}
> +
> +/**
> + * __fpga_mgr_reset - unlocked version of fpga_mgr_reset
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_reset(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (!mgr->mops->reset)
> +		return -EINVAL;
> +
> +	ret = mgr->mops->reset(mgr);
> +
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	return ret;
> +}
> +
> +/**
> + * fpga_mgr_reset - reset the fpga
> + * @mgr: fpga manager
> + */
> +int fpga_mgr_reset(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	ret = __fpga_mgr_reset(mgr);
> +
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_reset);
> +
> +/**
> + * __fpga_mgr_stage_init - prepare fpga for configuration
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_stage_write_init(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (mgr->mops->write_init) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_INIT;
> +		ret = mgr->mops->write_init(mgr);
> +		if (ret) {
> +			mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_stage_write - write buffer to fpga
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +static int __fpga_mgr_stage_write(struct fpga_manager *mgr, const char *buf,
> +				  size_t count)
> +{
> +	int ret;
> +
> +	mgr->state = FPGA_MGR_STATE_WRITE;
> +	ret = mgr->mops->write(mgr, buf, count);
> +	if (ret) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_stage_complete - after writing, place fpga in operating state
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_stage_write_complete(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (mgr->mops->write_complete) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
> +		ret = mgr->mops->write_complete(mgr);
> +		if (ret) {
> +			mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
> +			return ret;
> +		}
> +	}
> +
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_write - whole fpga image write cycle
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +static int __fpga_mgr_write(struct fpga_manager *mgr, const char *buf,
> +			    size_t count)
> +{
> +	int ret;
> +
> +	ret = __fpga_mgr_stage_write_init(mgr);
> +	if (ret)
> +		return ret;
> +
> +	ret = __fpga_mgr_stage_write(mgr, buf, count);
> +	if (ret)
> +		return ret;
> +
> +	return __fpga_mgr_stage_write_complete(mgr);
> +}
> +
> +/**
> + * fpga_mgr_write - do complete fpga image write cycle
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
> +{
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	dev_info(&mgr->dev, "writing buffer to %s\n", mgr->name);
> +
> +	ret = __fpga_mgr_write(mgr, buf, count);
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_write);
> +
> +/**
> + * fpga_mgr_firmware_write - request firmware and write to fpga
> + * @mgr: fpga manager
> + * @image_name: name of image file on the firmware search path
> + *
> + * Grab lock, request firmware, and write out to the FPGA.
> + * Update the state before each step to provide info on what step
> + * failed if there is a failure.
> + */
> +int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name)
> +{
> +	const struct firmware *fw;
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	dev_info(&mgr->dev, "writing %s to %s\n", image_name, mgr->name);
> +
> +	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
> +	ret = request_firmware(&fw, image_name, &mgr->dev);
> +	if (ret) {
> +		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
> +		goto fw_wr_exit;
> +	}
> +
> +	ret = __fpga_mgr_write(mgr, fw->data, fw->size);
> +	if (ret)
> +		goto fw_wr_exit;
> +
> +	strcpy(mgr->image_name, image_name);
> +
> +fw_wr_exit:
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
> +
> +/**
> + * fpga_mgr_name - returns the fpga manager name
> + * @mgr: fpga manager
> + * @buf: buffer to receive the name
> + */
> +int fpga_mgr_name(struct fpga_manager *mgr, char *buf)
> +{
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	return sprintf(buf, "%s\n", mgr->name);
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_name);
> +
> +#if IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)

remove this line

> +static const char * const state_str[] = {
> +	[FPGA_MGR_STATE_UNKNOWN] =		"unknown",
> +	[FPGA_MGR_STATE_POWER_OFF] =		"power_off",
> +	[FPGA_MGR_STATE_POWER_UP] =		"power_up",
> +	[FPGA_MGR_STATE_RESET] =		"reset",
> +
> +	/* write sequence */
> +	[FPGA_MGR_STATE_FIRMWARE_REQ] =		"firmware_request",
> +	[FPGA_MGR_STATE_FIRMWARE_REQ_ERR] =	"firmware_request_err",
> +	[FPGA_MGR_STATE_WRITE_INIT] =		"write_init",
> +	[FPGA_MGR_STATE_WRITE_INIT_ERR] =	"write_init_err",
> +	[FPGA_MGR_STATE_WRITE] =		"write",
> +	[FPGA_MGR_STATE_WRITE_ERR] =		"write_err",
> +	[FPGA_MGR_STATE_WRITE_COMPLETE] =	"write_complete",
> +	[FPGA_MGR_STATE_WRITE_COMPLETE_ERR] =	"write_complete_err",
> +
> +	[FPGA_MGR_STATE_OPERATING] =		"operating",
> +};
> +
> +/*
> + * class attributes
> + */
> +static ssize_t name_show(struct device *dev,
> +			 struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return fpga_mgr_name(mgr, buf);
> +}
> +
> +static ssize_t state_show(struct device *dev,
> +			  struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return sprintf(buf, "%s\n", state_str[mgr->state]);
> +}
> +
> +static ssize_t firmware_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return sprintf(buf, "%s\n", mgr->image_name);
> +}
> +
> +static ssize_t firmware_store(struct device *dev,
> +			      struct device_attribute *attr,
> +			      const char *buf, size_t count)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	unsigned int len;
> +	char image_name[NAME_MAX];
> +	int ret;
> +
> +	/* lose terminating \n */
> +	strcpy(image_name, buf);
> +	len = strlen(image_name);
> +	if (image_name[len - 1] == '\n')
> +		image_name[len - 1] = 0;
> +
> +	ret = fpga_mgr_firmware_write(mgr, image_name);
> +	if (ret)
> +		return ret;
> +
> +	return count;
> +}
> +
> +static ssize_t reset_store(struct device *dev,
> +			   struct device_attribute *attr,
> +			   const char *buf, size_t count)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	unsigned long val;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val == 1) {
> +		ret = fpga_mgr_reset(mgr);
> +		if (ret)
> +			return ret;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR_RO(name);
> +static DEVICE_ATTR_RO(state);
> +static DEVICE_ATTR_RW(firmware);
> +static DEVICE_ATTR_WO(reset);
> +
> +static struct attribute *fpga_mgr_attrs[] = {
> +	&dev_attr_name.attr,
> +	&dev_attr_state.attr,
> +	&dev_attr_firmware.attr,
> +	&dev_attr_reset.attr,
> +	NULL,
> +};
> +ATTRIBUTE_GROUPS(fpga_mgr);
> +#else
> +#define fpga_mgr_groups NULL
> +#endif /* CONFIG_FPGA_MGR_SYSFS */

remove these 3 lines and look below.

> +
> +static int fpga_mgr_suspend(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	if (mgr->mops->suspend)
> +		return mgr->mops->suspend(mgr);
> +
> +	return 0;
> +}
> +
> +static int fpga_mgr_resume(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	int ret = 0;
> +
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	if (mgr->mops->resume) {
> +		ret = mgr->mops->resume(mgr);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (strlen(mgr->image_name) != 0)
> +		fpga_mgr_firmware_write(mgr, mgr->image_name);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops fpga_mgr_dev_pm_ops = {
> +	.suspend	= fpga_mgr_suspend,
> +	.resume		= fpga_mgr_resume,
> +};
> +
> +static void fpga_mgr_dev_release(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	dev_dbg(dev, "releasing '%s'\n", mgr->name);
> +
> +	if (mgr->mops->fpga_remove)
> +		mgr->mops->fpga_remove(mgr);
> +
> +	mgr->mops = NULL;
> +
> +	mutex_lock(&fpga_mgr_mutex);
> +	list_del(&mgr->list);
> +	mutex_unlock(&fpga_mgr_mutex);
> +
> +	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
> +	kfree(mgr);
> +}
> +
> +/**
> + * fpga_mgr_register - register a low level fpga manager driver
> + * @dev: fpga manager device
> + * @name: fpga manager name
> + * @mops: pointer to structure of fpga manager ops
> + * @priv: fpga manager private data
> + */
> +int fpga_mgr_register(struct device *dev, const char *name,
> +		      const struct fpga_manager_ops *mops,
> +		      void *priv)
> +{
> +	struct fpga_manager *mgr;
> +	int id, ret;
> +
> +	if (!mops || !name || !strlen(name))
> +		return -EINVAL;
> +
> +	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> +	if (!mgr)
> +		return -ENOMEM;
> +
> +	id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
> +	if (id < 0)
> +		return id;
> +
> +	mutex_init(&mgr->lock);
> +
> +	mgr->name = name;
> +	mgr->mops = mops;
> +	mgr->priv = priv;
> +
> +	/*
> +	 * Initialize framework state by requesting low level driver read state
> +	 * from device.  FPGA may be in reset mode or may have been programmed
> +	 * by bootloader or EEPROM.
> +	 */
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	INIT_LIST_HEAD(&mgr->list);
> +	mutex_lock(&fpga_mgr_mutex);
> +	list_add(&mgr->list, &fpga_manager_list);
> +	mutex_unlock(&fpga_mgr_mutex);
> +
> +	device_initialize(&mgr->dev);
> +	mgr->dev.class = fpga_mgr_class;
> +	mgr->dev.parent = dev;
> +	mgr->dev.of_node = dev->of_node;
> +	mgr->dev.release = fpga_mgr_dev_release;
> +	mgr->dev.id = id;
> +	dev_set_name(&mgr->dev, "%d", id);
> +	ret = device_add(&mgr->dev);
> +	if (ret)
> +		goto error_device;
> +
> +	dev_info(&mgr->dev, "%s registered\n", mgr->name);
> +
> +	return 0;
> +
> +error_device:
> +	ida_simple_remove(&fpga_mgr_ida, id);
> +	kfree(mgr);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_register);
> +
> +/**
> + * fpga_mgr_remove - remove a low level fpga manager driver
> + * @dev: fpga manager device
> + */
> +void fpga_mgr_remove(struct platform_device *pdev)
> +{
> +	struct list_head *tmp;
> +	struct fpga_manager *mgr = NULL;
> +
> +	list_for_each(tmp, &fpga_manager_list) {
> +		mgr = list_entry(tmp, struct fpga_manager, list);
> +		if (mgr->dev.parent == &pdev->dev) {
> +			device_unregister(&mgr->dev);
> +			break;
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_remove);
> +
> +static int __init fpga_mgr_dev_init(void)
> +{
> +	pr_info("FPGA Manager framework driver\n");
> +
> +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
> +	if (IS_ERR(fpga_mgr_class))
> +		return PTR_ERR(fpga_mgr_class);
> +
> +	fpga_mgr_class->dev_groups = fpga_mgr_groups;


Write this here.
       if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
             fpga_mgr_class->dev_groups = fpga_mgr_groups;
       }

I have tested it and it is working just fine. You can compile this
driver with SYSFS=n
The whole code is built and config option just export it.
I think it is better than having #if there.

Greg: Is there any problem with this solution?

BTW: I have pushed my branch to zero day testing system to get better coverage

Thanks,
Michal



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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
@ 2014-12-18 18:16     ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-18 18:16 UTC (permalink / raw)
  To: atull, gregkh, jgunthorpe, hpa, monstr, michal.simek, rdunlap
  Cc: mark.rutland, linux-doc, rubini, pantelis.antoniou, s.trumtrar,
	devel, sameo, nico, ijc+devicetree, kyle.teske, grant.likely,
	davidb, linus.walleij, cesarb, devicetree, jason, pawel.moll,
	iws, broonie, philip, dinguyen, pavel, yvanderv, linux-kernel,
	balbi, delicious.quinoa, robh+dt, rob, galak, akpm, davem,
	m.chehab

Hi Alan,

first of all - there are these kernel-doc warnings.

Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'


On 12/17/2014 05:54 PM, atull@opensource.altera.com wrote:
> From: Alan Tull <atull@opensource.altera.com>
> 
> Supports standard ops for low level FPGA drivers.
> Various manufacturors' FPGAs can be supported by adding low
> level drivers.  Each driver needs to register its ops
> using fpga_mgr_register().
> 
> Exports methods of doing operations to program  FPGAs. These
> should be sufficient for individual drivers to request FPGA
> programming directly if desired.
> 
> Adds a sysfs interface.  The sysfs interface can be compiled out
> where desired in production builds.
> 
> Resume is supported by calling low level driver's resume
> function, then reloading the firmware image.
> 
> The following are exported as GPL:
> * fpga_mgr_reset
>    Reset the FGPA.
> 
> * fpga_mgr_write
>    Write a image (in buffer) to the FPGA.
> 
> * fpga_mgr_firmware_write
>    Request firmware by file name and write it to the FPGA.
> 
> * fpga_mgr_name
>    Get name of FPGA manager.
> 
> * fpga_mgr_state
>    Get a state of framework as a string.
> 
> * fpga_mgr_register and fpga_mgr_remove
>    Register/unregister low level fpga manager driver.
> 
> The following sysfs files are created:
> * /sys/class/fpga_manager/<fpga>/name
>   Name of low level driver.
> 
> * /sys/class/fpga_manager/<fpga>/firmware
>   Name of FPGA image file to load using firmware class.
>   $ echo image.rbf > /sys/class/fpga_manager/<fpga>/firmware
> 
>   read: read back name of image file previous loaded
>   $ cat /sys/class/fpga_manager/<fpga>/firmware
> 
> * /sys/class/fpga_manager/<fpga>/reset
>   reset the FPGA
>   $ echo 1 > /sys/class/fpga_manager/<fpga>/reset
> 
> * /sys/class/fpga_manager/<fpga>/state
>   State of fpga framework state machine
> 
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> ---
> v2: s/mangager/manager/
>     check for invalid request_nr
>     add fpga reset interface
>     rework the state code
>     remove FPGA_MGR_FAIL flag
>     add _ERR states to fpga manager states enum
>     low level state op now returns a state enum value
>     initialize framework state from driver state op
>     remove unused fpga read stuff
>     merge sysfs.c into fpga-mgr.c
>     move suspend/resume from bus.c to fpga-mgr.c
> 
> v3: Add struct device to fpga_manager (not as a pointer)
>     Add to_fpga_manager
>     Don't get irq in fpga-mgr.c (let low level driver do it)
>     remove from struct fpga_manager: nr, np, parent
>     get rid of fpga_mgr_get_new_minor()
>     simplify fpga_manager_register:
>       reorder parameters
>       use dev instead of pdev
>     get rid of code that used to make more sense when this
>       was a char driver, don't alloc_chrdev_region
>     use a mutex instead of flags
> 
> v4: Move to drivers/staging
> 
> v5: Make some things be static
>     Kconfig: add 'if FPGA'
>     Makefile: s/fpga-mgr-core.o/fpga-mgr.o/
>     clean up includes
>     use enum fpga_mgr_states instead of int
>     static const char *state_str
>     use DEVICE_ATTR_RO/RW/WO and ATTRIBUTE_GROUPS
>     return -EINVAL instead of BUG_ON
>     move ida_simple_get after kzalloc
>     clean up fpga_mgr_remove
>     fpga-mgr.h: remove '#if IS_ENABLED(CONFIG_FPGA)'
>     add kernel-doc documentation
>     Move header to new include/linux/fpga folder
>     static const struct fpga_mgr_ops
>     dev_info msg simplified
> ---
>  drivers/staging/Kconfig         |    2 +
>  drivers/staging/Makefile        |    1 +
>  drivers/staging/fpga/Kconfig    |   24 ++
>  drivers/staging/fpga/Makefile   |   10 +
>  drivers/staging/fpga/fpga-mgr.c |  523 +++++++++++++++++++++++++++++++++++++++
>  include/linux/fpga/fpga-mgr.h   |  124 ++++++++++
>  6 files changed, 684 insertions(+)
>  create mode 100644 drivers/staging/fpga/Kconfig
>  create mode 100644 drivers/staging/fpga/Makefile
>  create mode 100644 drivers/staging/fpga/fpga-mgr.c
>  create mode 100644 include/linux/fpga/fpga-mgr.h
> 
> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
> index 4690ae9..4338a4c 100644
> --- a/drivers/staging/Kconfig
> +++ b/drivers/staging/Kconfig
> @@ -108,4 +108,6 @@ source "drivers/staging/skein/Kconfig"
>  
>  source "drivers/staging/unisys/Kconfig"
>  
> +source "drivers/staging/fpga/Kconfig"
> +
>  endif # STAGING
> diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
> index c780a0e..43654a2 100644
> --- a/drivers/staging/Makefile
> +++ b/drivers/staging/Makefile
> @@ -46,3 +46,4 @@ obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
>  obj-$(CONFIG_GS_FPGABOOT)	+= gs_fpgaboot/
>  obj-$(CONFIG_CRYPTO_SKEIN)	+= skein/
>  obj-$(CONFIG_UNISYSSPAR)	+= unisys/
> +obj-$(CONFIG_FPGA)		+= fpga/
> diff --git a/drivers/staging/fpga/Kconfig b/drivers/staging/fpga/Kconfig
> new file mode 100644
> index 0000000..89ebafc
> --- /dev/null
> +++ b/drivers/staging/fpga/Kconfig
> @@ -0,0 +1,24 @@
> +#
> +# FPGA framework configuration
> +#
> +
> +menu "FPGA devices"
> +
> +config FPGA
> +	tristate "FPGA Framework"
> +	help
> +	  Say Y here if you want support for configuring FPGAs from the
> +	  kernel.  The FPGA framework adds a FPGA manager class and FPGA
> +	  manager drivers.
> +
> +if FPGA
> +
> +config FPGA_MGR_SYSFS
> +	bool "FPGA Manager SysFS Interface"
> +	depends on SYSFS
> +	help
> +	  FPGA Manager SysFS interface.
> +
> +endif # FPGA
> +
> +endmenu
> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> new file mode 100644
> index 0000000..ff6c677
> --- /dev/null
> +++ b/drivers/staging/fpga/Makefile
> @@ -0,0 +1,10 @@
> +#
> +# Makefile for the fpga framework and fpga manager drivers.
> +#
> +
> +fpga-mgr-core-y += fpga-mgr.o

remove this line - it is unused.

> +
> +# Core FPGA Manager Framework
> +obj-$(CONFIG_FPGA)			+= fpga-mgr.o
> +
> +# FPGA Manager Drivers
> diff --git a/drivers/staging/fpga/fpga-mgr.c b/drivers/staging/fpga/fpga-mgr.c
> new file mode 100644
> index 0000000..671b114
> --- /dev/null
> +++ b/drivers/staging/fpga/fpga-mgr.c
> @@ -0,0 +1,523 @@
> +/*
> + * FPGA Manager Core
> + *
> + *  Copyright (C) 2013-2014 Altera Corporation
> + *
> + * With code from the mailing list:
> + * Copyright (C) 2013 Xilinx, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <linux/delay.h>
> +#include <linux/firmware.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/idr.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/slab.h>
> +
> +static DEFINE_MUTEX(fpga_mgr_mutex);
> +static DEFINE_IDA(fpga_mgr_ida);
> +static struct class *fpga_mgr_class;
> +
> +static LIST_HEAD(fpga_manager_list);
> +
> +/**
> + * fpga_mgr_low_level_state - get FPGA state from low level driver
> + * @mgr: fpga manager
> + *
> + * This will be used to initialize framework state
> + */
> +static enum fpga_mgr_states fpga_mgr_low_level_state(struct fpga_manager *mgr)
> +{
> +	if (!mgr || !mgr->mops || !mgr->mops->state)
> +		return FPGA_MGR_STATE_UNKNOWN;
> +
> +	return mgr->mops->state(mgr);
> +}
> +
> +/**
> + * __fpga_mgr_reset - unlocked version of fpga_mgr_reset
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_reset(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (!mgr->mops->reset)
> +		return -EINVAL;
> +
> +	ret = mgr->mops->reset(mgr);
> +
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	return ret;
> +}
> +
> +/**
> + * fpga_mgr_reset - reset the fpga
> + * @mgr: fpga manager
> + */
> +int fpga_mgr_reset(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	ret = __fpga_mgr_reset(mgr);
> +
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_reset);
> +
> +/**
> + * __fpga_mgr_stage_init - prepare fpga for configuration
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_stage_write_init(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (mgr->mops->write_init) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_INIT;
> +		ret = mgr->mops->write_init(mgr);
> +		if (ret) {
> +			mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_stage_write - write buffer to fpga
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +static int __fpga_mgr_stage_write(struct fpga_manager *mgr, const char *buf,
> +				  size_t count)
> +{
> +	int ret;
> +
> +	mgr->state = FPGA_MGR_STATE_WRITE;
> +	ret = mgr->mops->write(mgr, buf, count);
> +	if (ret) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_stage_complete - after writing, place fpga in operating state
> + * @mgr: fpga manager
> + */
> +static int __fpga_mgr_stage_write_complete(struct fpga_manager *mgr)
> +{
> +	int ret;
> +
> +	if (mgr->mops->write_complete) {
> +		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
> +		ret = mgr->mops->write_complete(mgr);
> +		if (ret) {
> +			mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
> +			return ret;
> +		}
> +	}
> +
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	return 0;
> +}
> +
> +/**
> + * __fpga_mgr_write - whole fpga image write cycle
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +static int __fpga_mgr_write(struct fpga_manager *mgr, const char *buf,
> +			    size_t count)
> +{
> +	int ret;
> +
> +	ret = __fpga_mgr_stage_write_init(mgr);
> +	if (ret)
> +		return ret;
> +
> +	ret = __fpga_mgr_stage_write(mgr, buf, count);
> +	if (ret)
> +		return ret;
> +
> +	return __fpga_mgr_stage_write_complete(mgr);
> +}
> +
> +/**
> + * fpga_mgr_write - do complete fpga image write cycle
> + * @mgr: fpga manager
> + * @buf: buffer contain fpga image
> + * @count: byte count of buf
> + */
> +int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
> +{
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	dev_info(&mgr->dev, "writing buffer to %s\n", mgr->name);
> +
> +	ret = __fpga_mgr_write(mgr, buf, count);
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_write);
> +
> +/**
> + * fpga_mgr_firmware_write - request firmware and write to fpga
> + * @mgr: fpga manager
> + * @image_name: name of image file on the firmware search path
> + *
> + * Grab lock, request firmware, and write out to the FPGA.
> + * Update the state before each step to provide info on what step
> + * failed if there is a failure.
> + */
> +int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *image_name)
> +{
> +	const struct firmware *fw;
> +	int ret;
> +
> +	if (!mutex_trylock(&mgr->lock))
> +		return -EBUSY;
> +
> +	dev_info(&mgr->dev, "writing %s to %s\n", image_name, mgr->name);
> +
> +	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
> +	ret = request_firmware(&fw, image_name, &mgr->dev);
> +	if (ret) {
> +		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
> +		goto fw_wr_exit;
> +	}
> +
> +	ret = __fpga_mgr_write(mgr, fw->data, fw->size);
> +	if (ret)
> +		goto fw_wr_exit;
> +
> +	strcpy(mgr->image_name, image_name);
> +
> +fw_wr_exit:
> +	mutex_unlock(&mgr->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
> +
> +/**
> + * fpga_mgr_name - returns the fpga manager name
> + * @mgr: fpga manager
> + * @buf: buffer to receive the name
> + */
> +int fpga_mgr_name(struct fpga_manager *mgr, char *buf)
> +{
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	return sprintf(buf, "%s\n", mgr->name);
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_name);
> +
> +#if IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)

remove this line

> +static const char * const state_str[] = {
> +	[FPGA_MGR_STATE_UNKNOWN] =		"unknown",
> +	[FPGA_MGR_STATE_POWER_OFF] =		"power_off",
> +	[FPGA_MGR_STATE_POWER_UP] =		"power_up",
> +	[FPGA_MGR_STATE_RESET] =		"reset",
> +
> +	/* write sequence */
> +	[FPGA_MGR_STATE_FIRMWARE_REQ] =		"firmware_request",
> +	[FPGA_MGR_STATE_FIRMWARE_REQ_ERR] =	"firmware_request_err",
> +	[FPGA_MGR_STATE_WRITE_INIT] =		"write_init",
> +	[FPGA_MGR_STATE_WRITE_INIT_ERR] =	"write_init_err",
> +	[FPGA_MGR_STATE_WRITE] =		"write",
> +	[FPGA_MGR_STATE_WRITE_ERR] =		"write_err",
> +	[FPGA_MGR_STATE_WRITE_COMPLETE] =	"write_complete",
> +	[FPGA_MGR_STATE_WRITE_COMPLETE_ERR] =	"write_complete_err",
> +
> +	[FPGA_MGR_STATE_OPERATING] =		"operating",
> +};
> +
> +/*
> + * class attributes
> + */
> +static ssize_t name_show(struct device *dev,
> +			 struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return fpga_mgr_name(mgr, buf);
> +}
> +
> +static ssize_t state_show(struct device *dev,
> +			  struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return sprintf(buf, "%s\n", state_str[mgr->state]);
> +}
> +
> +static ssize_t firmware_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	return sprintf(buf, "%s\n", mgr->image_name);
> +}
> +
> +static ssize_t firmware_store(struct device *dev,
> +			      struct device_attribute *attr,
> +			      const char *buf, size_t count)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	unsigned int len;
> +	char image_name[NAME_MAX];
> +	int ret;
> +
> +	/* lose terminating \n */
> +	strcpy(image_name, buf);
> +	len = strlen(image_name);
> +	if (image_name[len - 1] == '\n')
> +		image_name[len - 1] = 0;
> +
> +	ret = fpga_mgr_firmware_write(mgr, image_name);
> +	if (ret)
> +		return ret;
> +
> +	return count;
> +}
> +
> +static ssize_t reset_store(struct device *dev,
> +			   struct device_attribute *attr,
> +			   const char *buf, size_t count)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	unsigned long val;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val == 1) {
> +		ret = fpga_mgr_reset(mgr);
> +		if (ret)
> +			return ret;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR_RO(name);
> +static DEVICE_ATTR_RO(state);
> +static DEVICE_ATTR_RW(firmware);
> +static DEVICE_ATTR_WO(reset);
> +
> +static struct attribute *fpga_mgr_attrs[] = {
> +	&dev_attr_name.attr,
> +	&dev_attr_state.attr,
> +	&dev_attr_firmware.attr,
> +	&dev_attr_reset.attr,
> +	NULL,
> +};
> +ATTRIBUTE_GROUPS(fpga_mgr);
> +#else
> +#define fpga_mgr_groups NULL
> +#endif /* CONFIG_FPGA_MGR_SYSFS */

remove these 3 lines and look below.

> +
> +static int fpga_mgr_suspend(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	if (mgr->mops->suspend)
> +		return mgr->mops->suspend(mgr);
> +
> +	return 0;
> +}
> +
> +static int fpga_mgr_resume(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +	int ret = 0;
> +
> +	if (!mgr)
> +		return -ENODEV;
> +
> +	if (mgr->mops->resume) {
> +		ret = mgr->mops->resume(mgr);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (strlen(mgr->image_name) != 0)
> +		fpga_mgr_firmware_write(mgr, mgr->image_name);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops fpga_mgr_dev_pm_ops = {
> +	.suspend	= fpga_mgr_suspend,
> +	.resume		= fpga_mgr_resume,
> +};
> +
> +static void fpga_mgr_dev_release(struct device *dev)
> +{
> +	struct fpga_manager *mgr = to_fpga_manager(dev);
> +
> +	dev_dbg(dev, "releasing '%s'\n", mgr->name);
> +
> +	if (mgr->mops->fpga_remove)
> +		mgr->mops->fpga_remove(mgr);
> +
> +	mgr->mops = NULL;
> +
> +	mutex_lock(&fpga_mgr_mutex);
> +	list_del(&mgr->list);
> +	mutex_unlock(&fpga_mgr_mutex);
> +
> +	ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
> +	kfree(mgr);
> +}
> +
> +/**
> + * fpga_mgr_register - register a low level fpga manager driver
> + * @dev: fpga manager device
> + * @name: fpga manager name
> + * @mops: pointer to structure of fpga manager ops
> + * @priv: fpga manager private data
> + */
> +int fpga_mgr_register(struct device *dev, const char *name,
> +		      const struct fpga_manager_ops *mops,
> +		      void *priv)
> +{
> +	struct fpga_manager *mgr;
> +	int id, ret;
> +
> +	if (!mops || !name || !strlen(name))
> +		return -EINVAL;
> +
> +	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
> +	if (!mgr)
> +		return -ENOMEM;
> +
> +	id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
> +	if (id < 0)
> +		return id;
> +
> +	mutex_init(&mgr->lock);
> +
> +	mgr->name = name;
> +	mgr->mops = mops;
> +	mgr->priv = priv;
> +
> +	/*
> +	 * Initialize framework state by requesting low level driver read state
> +	 * from device.  FPGA may be in reset mode or may have been programmed
> +	 * by bootloader or EEPROM.
> +	 */
> +	mgr->state = fpga_mgr_low_level_state(mgr);
> +
> +	INIT_LIST_HEAD(&mgr->list);
> +	mutex_lock(&fpga_mgr_mutex);
> +	list_add(&mgr->list, &fpga_manager_list);
> +	mutex_unlock(&fpga_mgr_mutex);
> +
> +	device_initialize(&mgr->dev);
> +	mgr->dev.class = fpga_mgr_class;
> +	mgr->dev.parent = dev;
> +	mgr->dev.of_node = dev->of_node;
> +	mgr->dev.release = fpga_mgr_dev_release;
> +	mgr->dev.id = id;
> +	dev_set_name(&mgr->dev, "%d", id);
> +	ret = device_add(&mgr->dev);
> +	if (ret)
> +		goto error_device;
> +
> +	dev_info(&mgr->dev, "%s registered\n", mgr->name);
> +
> +	return 0;
> +
> +error_device:
> +	ida_simple_remove(&fpga_mgr_ida, id);
> +	kfree(mgr);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_register);
> +
> +/**
> + * fpga_mgr_remove - remove a low level fpga manager driver
> + * @dev: fpga manager device
> + */
> +void fpga_mgr_remove(struct platform_device *pdev)
> +{
> +	struct list_head *tmp;
> +	struct fpga_manager *mgr = NULL;
> +
> +	list_for_each(tmp, &fpga_manager_list) {
> +		mgr = list_entry(tmp, struct fpga_manager, list);
> +		if (mgr->dev.parent == &pdev->dev) {
> +			device_unregister(&mgr->dev);
> +			break;
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(fpga_mgr_remove);
> +
> +static int __init fpga_mgr_dev_init(void)
> +{
> +	pr_info("FPGA Manager framework driver\n");
> +
> +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
> +	if (IS_ERR(fpga_mgr_class))
> +		return PTR_ERR(fpga_mgr_class);
> +
> +	fpga_mgr_class->dev_groups = fpga_mgr_groups;


Write this here.
       if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
             fpga_mgr_class->dev_groups = fpga_mgr_groups;
       }

I have tested it and it is working just fine. You can compile this
driver with SYSFS=n
The whole code is built and config option just export it.
I think it is better than having #if there.

Greg: Is there any problem with this solution?

BTW: I have pushed my branch to zero day testing system to get better coverage

Thanks,
Michal

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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
  2014-12-18 18:16     ` Michal Simek
@ 2014-12-18 20:46       ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-18 20:46 UTC (permalink / raw)
  To: Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv

On Thu, 18 Dec 2014, Michal Simek wrote:

> Hi Alan,
> 
> first of all - there are these kernel-doc warnings.
> 
> Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
> Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
> Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
> Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
> Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
> Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
> Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
> Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
> Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
> Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
> Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
> Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
> Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
> Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
> Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
> Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
> Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
> Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
> Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
> Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
> Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
> Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
> Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
> Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
> Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'
> 

I see the warnings now.  I wasn't using the '-v' option for kernel-doc.
Fixed in v6.

> > diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> > new file mode 100644
> > index 0000000..ff6c677
> > --- /dev/null
> > +++ b/drivers/staging/fpga/Makefile
> > @@ -0,0 +1,10 @@
> > +#
> > +# Makefile for the fpga framework and fpga manager drivers.
> > +#
> > +
> > +fpga-mgr-core-y += fpga-mgr.o
> 
> remove this line - it is unused.
> 

OK

> > +static int __init fpga_mgr_dev_init(void)
> > +{
> > +	pr_info("FPGA Manager framework driver\n");
> > +
> > +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
> > +	if (IS_ERR(fpga_mgr_class))
> > +		return PTR_ERR(fpga_mgr_class);
> > +
> > +	fpga_mgr_class->dev_groups = fpga_mgr_groups;
> 
> 
> Write this here.
>        if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
>              fpga_mgr_class->dev_groups = fpga_mgr_groups;
>        }
> 
> I have tested it and it is working just fine. You can compile this
> driver with SYSFS=n
> The whole code is built and config option just export it.
> I think it is better than having #if there.
> 
> Greg: Is there any problem with this solution?
> 

I'm cool with this myself.  I'll add in v6.

> BTW: I have pushed my branch to zero day testing system to get better coverage
> 

Michal, I've already done that with each submission.  Assuming you are
referring to the kbuild test robot.

Alan

> Thanks,
> Michal
> 
> 
> 

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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
@ 2014-12-18 20:46       ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-18 20:46 UTC (permalink / raw)
  To: Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguye

On Thu, 18 Dec 2014, Michal Simek wrote:

> Hi Alan,
> 
> first of all - there are these kernel-doc warnings.
> 
> Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
> Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
> Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
> Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
> Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
> Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
> Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
> Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
> Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
> Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
> Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
> Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
> Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
> Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
> Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
> Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
> Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
> Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
> Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
> Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
> Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
> Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
> Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
> Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
> Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'
> 

I see the warnings now.  I wasn't using the '-v' option for kernel-doc.
Fixed in v6.

> > diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
> > new file mode 100644
> > index 0000000..ff6c677
> > --- /dev/null
> > +++ b/drivers/staging/fpga/Makefile
> > @@ -0,0 +1,10 @@
> > +#
> > +# Makefile for the fpga framework and fpga manager drivers.
> > +#
> > +
> > +fpga-mgr-core-y += fpga-mgr.o
> 
> remove this line - it is unused.
> 

OK

> > +static int __init fpga_mgr_dev_init(void)
> > +{
> > +	pr_info("FPGA Manager framework driver\n");
> > +
> > +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
> > +	if (IS_ERR(fpga_mgr_class))
> > +		return PTR_ERR(fpga_mgr_class);
> > +
> > +	fpga_mgr_class->dev_groups = fpga_mgr_groups;
> 
> 
> Write this here.
>        if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
>              fpga_mgr_class->dev_groups = fpga_mgr_groups;
>        }
> 
> I have tested it and it is working just fine. You can compile this
> driver with SYSFS=n
> The whole code is built and config option just export it.
> I think it is better than having #if there.
> 
> Greg: Is there any problem with this solution?
> 

I'm cool with this myself.  I'll add in v6.

> BTW: I have pushed my branch to zero day testing system to get better coverage
> 

Michal, I've already done that with each submission.  Assuming you are
referring to the kbuild test robot.

Alan

> Thanks,
> Michal
> 
> 
> 

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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
  2014-12-18 15:31     ` Michal Simek
@ 2014-12-18 20:59       ` atull
  -1 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-18 20:59 UTC (permalink / raw)
  To: Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv

On Thu, 18 Dec 2014, Michal Simek wrote:

Hi Michal,

> > +
> > +	/* Write out remaining non 32-bit chunks. */
> > +	switch (count) {
> > +	case 3:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
> > +		break;
> > +	case 2:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
> > +		break;
> > +	case 1:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
> > +		break;
> > +	default:
> > +		/* This will never happen. */
> 
> why not just return any error code here even if this can't happen.
> 

OK. Will be in v6.

> 
> add it to one line.
> 
> The rest is looks good to me. I think this is good to go in.
> 
> Acked-by: Michal Simek <michal.simek@xilinx.com>
> 
> Thanks,
> Michal
> 

Thanks for the feedback.  So patches 1-4 look good now?

For v6 I will leave out patches 5/6 and 6/6.

Alan

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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
@ 2014-12-18 20:59       ` atull
  0 siblings, 0 replies; 35+ messages in thread
From: atull @ 2014-12-18 20:59 UTC (permalink / raw)
  To: Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguye

On Thu, 18 Dec 2014, Michal Simek wrote:

Hi Michal,

> > +
> > +	/* Write out remaining non 32-bit chunks. */
> > +	switch (count) {
> > +	case 3:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
> > +		break;
> > +	case 2:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
> > +		break;
> > +	case 1:
> > +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
> > +		break;
> > +	default:
> > +		/* This will never happen. */
> 
> why not just return any error code here even if this can't happen.
> 

OK. Will be in v6.

> 
> add it to one line.
> 
> The rest is looks good to me. I think this is good to go in.
> 
> Acked-by: Michal Simek <michal.simek@xilinx.com>
> 
> Thanks,
> Michal
> 

Thanks for the feedback.  So patches 1-4 look good now?

For v6 I will leave out patches 5/6 and 6/6.

Alan

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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
  2014-12-18 20:46       ` atull
@ 2014-12-19  7:22         ` Michal Simek
  -1 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-19  7:22 UTC (permalink / raw)
  To: atull, Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv

On 12/18/2014 09:46 PM, atull wrote:
> On Thu, 18 Dec 2014, Michal Simek wrote:
> 
>> Hi Alan,
>>
>> first of all - there are these kernel-doc warnings.
>>
>> Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
>> Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
>> Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
>> Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
>> Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
>> Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
>> Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
>> Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
>> Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
>> Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
>> Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
>> Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
>> Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
>> Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
>> Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
>> Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
>> Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'
>>
> 
> I see the warnings now.  I wasn't using the '-v' option for kernel-doc.
> Fixed in v6.
> 
>>> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
>>> new file mode 100644
>>> index 0000000..ff6c677
>>> --- /dev/null
>>> +++ b/drivers/staging/fpga/Makefile
>>> @@ -0,0 +1,10 @@
>>> +#
>>> +# Makefile for the fpga framework and fpga manager drivers.
>>> +#
>>> +
>>> +fpga-mgr-core-y += fpga-mgr.o
>>
>> remove this line - it is unused.
>>
> 
> OK
> 
>>> +static int __init fpga_mgr_dev_init(void)
>>> +{
>>> +	pr_info("FPGA Manager framework driver\n");
>>> +
>>> +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
>>> +	if (IS_ERR(fpga_mgr_class))
>>> +		return PTR_ERR(fpga_mgr_class);
>>> +
>>> +	fpga_mgr_class->dev_groups = fpga_mgr_groups;
>>
>>
>> Write this here.
>>        if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
>>              fpga_mgr_class->dev_groups = fpga_mgr_groups;
>>        }
>>
>> I have tested it and it is working just fine. You can compile this
>> driver with SYSFS=n
>> The whole code is built and config option just export it.
>> I think it is better than having #if there.
>>
>> Greg: Is there any problem with this solution?
>>
> 
> I'm cool with this myself.  I'll add in v6.
> 
>> BTW: I have pushed my branch to zero day testing system to get better coverage
>>
> 
> Michal, I've already done that with each submission.  Assuming you are
> referring to the kbuild test robot.

Yes, Kbuild test robot.

Thanks,
Michal



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

* Re: [PATCH v5 3/6] staging: fpga manager: framework core
@ 2014-12-19  7:22         ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-19  7:22 UTC (permalink / raw)
  To: atull, Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguye

On 12/18/2014 09:46 PM, atull wrote:
> On Thu, 18 Dec 2014, Michal Simek wrote:
> 
>> Hi Alan,
>>
>> first of all - there are these kernel-doc warnings.
>>
>> Info(drivers/staging/fpga/fpga-mgr.c:37): Scanning doc for fpga_mgr_low_level_state
>> Warning(drivers/staging/fpga/fpga-mgr.c:43): No description found for return value of 'fpga_mgr_low_level_state'
>> Info(drivers/staging/fpga/fpga-mgr.c:51): Scanning doc for __fpga_mgr_reset
>> Warning(drivers/staging/fpga/fpga-mgr.c:55): No description found for return value of '__fpga_mgr_reset'
>> Info(drivers/staging/fpga/fpga-mgr.c:69): Scanning doc for fpga_mgr_reset
>> Warning(drivers/staging/fpga/fpga-mgr.c:73): No description found for return value of 'fpga_mgr_reset'
>> Info(drivers/staging/fpga/fpga-mgr.c:88): Scanning doc for __fpga_mgr_stage_init
>> Warning(drivers/staging/fpga/fpga-mgr.c:92): No description found for return value of '__fpga_mgr_stage_write_init'
>> Info(drivers/staging/fpga/fpga-mgr.c:108): Scanning doc for __fpga_mgr_stage_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:115): No description found for return value of '__fpga_mgr_stage_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:129): Scanning doc for __fpga_mgr_stage_complete
>> Warning(drivers/staging/fpga/fpga-mgr.c:133): No description found for return value of '__fpga_mgr_stage_write_complete'
>> Info(drivers/staging/fpga/fpga-mgr.c:151): Scanning doc for __fpga_mgr_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:158): No description found for return value of '__fpga_mgr_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:173): Scanning doc for fpga_mgr_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:179): No description found for return value of 'fpga_mgr_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:195): Scanning doc for fpga_mgr_firmware_write
>> Warning(drivers/staging/fpga/fpga-mgr.c:204): No description found for return value of 'fpga_mgr_firmware_write'
>> Info(drivers/staging/fpga/fpga-mgr.c:234): Scanning doc for fpga_mgr_name
>> Warning(drivers/staging/fpga/fpga-mgr.c:239): No description found for return value of 'fpga_mgr_name'
>> Info(drivers/staging/fpga/fpga-mgr.c:414): Scanning doc for fpga_mgr_register
>> Warning(drivers/staging/fpga/fpga-mgr.c:423): No description found for return value of 'fpga_mgr_register'
>> Info(drivers/staging/fpga/fpga-mgr.c:480): Scanning doc for fpga_mgr_remove
>> Warning(drivers/staging/fpga/fpga-mgr.c:484): No description found for parameter 'pdev'
>> Warning(drivers/staging/fpga/fpga-mgr.c:484): Excess function parameter 'dev' description in 'fpga_mgr_remove'
>>
> 
> I see the warnings now.  I wasn't using the '-v' option for kernel-doc.
> Fixed in v6.
> 
>>> diff --git a/drivers/staging/fpga/Makefile b/drivers/staging/fpga/Makefile
>>> new file mode 100644
>>> index 0000000..ff6c677
>>> --- /dev/null
>>> +++ b/drivers/staging/fpga/Makefile
>>> @@ -0,0 +1,10 @@
>>> +#
>>> +# Makefile for the fpga framework and fpga manager drivers.
>>> +#
>>> +
>>> +fpga-mgr-core-y += fpga-mgr.o
>>
>> remove this line - it is unused.
>>
> 
> OK
> 
>>> +static int __init fpga_mgr_dev_init(void)
>>> +{
>>> +	pr_info("FPGA Manager framework driver\n");
>>> +
>>> +	fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
>>> +	if (IS_ERR(fpga_mgr_class))
>>> +		return PTR_ERR(fpga_mgr_class);
>>> +
>>> +	fpga_mgr_class->dev_groups = fpga_mgr_groups;
>>
>>
>> Write this here.
>>        if (IS_ENABLED(CONFIG_FPGA_MGR_SYSFS)) {
>>              fpga_mgr_class->dev_groups = fpga_mgr_groups;
>>        }
>>
>> I have tested it and it is working just fine. You can compile this
>> driver with SYSFS=n
>> The whole code is built and config option just export it.
>> I think it is better than having #if there.
>>
>> Greg: Is there any problem with this solution?
>>
> 
> I'm cool with this myself.  I'll add in v6.
> 
>> BTW: I have pushed my branch to zero day testing system to get better coverage
>>
> 
> Michal, I've already done that with each submission.  Assuming you are
> referring to the kbuild test robot.

Yes, Kbuild test robot.

Thanks,
Michal



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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
  2014-12-18 20:59       ` atull
@ 2014-12-19  7:30         ` Michal Simek
  -1 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-19  7:30 UTC (permalink / raw)
  To: atull, Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguyen,
	yvanderv

On 12/18/2014 09:59 PM, atull wrote:
> On Thu, 18 Dec 2014, Michal Simek wrote:
> 
> Hi Michal,
> 
>>> +
>>> +	/* Write out remaining non 32-bit chunks. */
>>> +	switch (count) {
>>> +	case 3:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
>>> +		break;
>>> +	case 2:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
>>> +		break;
>>> +	case 1:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
>>> +		break;
>>> +	default:
>>> +		/* This will never happen. */
>>
>> why not just return any error code here even if this can't happen.
>>
> 
> OK. Will be in v6.
> 
>>
>> add it to one line.
>>
>> The rest is looks good to me. I think this is good to go in.
>>
>> Acked-by: Michal Simek <michal.simek@xilinx.com>
>>
>> Thanks,
>> Michal
>>
> 
> Thanks for the feedback.  So patches 1-4 look good now?

Will look at them.

M


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

* Re: [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager
@ 2014-12-19  7:30         ` Michal Simek
  0 siblings, 0 replies; 35+ messages in thread
From: Michal Simek @ 2014-12-19  7:30 UTC (permalink / raw)
  To: atull, Michal Simek
  Cc: gregkh, jgunthorpe, hpa, monstr, rdunlap, linux-kernel,
	devicetree, pantelis.antoniou, robh+dt, grant.likely, iws,
	linux-doc, pavel, broonie, philip, rubini, s.trumtrar, jason,
	kyle.teske, nico, balbi, m.chehab, davidb, rob, davem, cesarb,
	sameo, akpm, linus.walleij, pawel.moll, mark.rutland,
	ijc+devicetree, galak, devel, delicious.quinoa, dinguye

On 12/18/2014 09:59 PM, atull wrote:
> On Thu, 18 Dec 2014, Michal Simek wrote:
> 
> Hi Michal,
> 
>>> +
>>> +	/* Write out remaining non 32-bit chunks. */
>>> +	switch (count) {
>>> +	case 3:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff);
>>> +		break;
>>> +	case 2:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff);
>>> +		break;
>>> +	case 1:
>>> +		socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff);
>>> +		break;
>>> +	default:
>>> +		/* This will never happen. */
>>
>> why not just return any error code here even if this can't happen.
>>
> 
> OK. Will be in v6.
> 
>>
>> add it to one line.
>>
>> The rest is looks good to me. I think this is good to go in.
>>
>> Acked-by: Michal Simek <michal.simek@xilinx.com>
>>
>> Thanks,
>> Michal
>>
> 
> Thanks for the feedback.  So patches 1-4 look good now?

Will look at them.

M


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

end of thread, other threads:[~2014-12-19  7:31 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-17 16:54 [PATCH v5 0/6] FPGA Manager Framework atull
2014-12-17 16:54 ` atull
2014-12-17 16:54 ` [PATCH v5 1/6] doc: add bindings document for altera fpga manager atull
2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
2014-12-17 16:54 ` [PATCH v5 2/6] fpga manager: add sysfs interface document atull
2014-12-17 16:54   ` atull
2014-12-17 16:54 ` [PATCH v5 3/6] staging: fpga manager: framework core atull
2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
2014-12-18 18:16   ` Michal Simek
2014-12-18 18:16     ` Michal Simek
2014-12-18 20:46     ` atull
2014-12-18 20:46       ` atull
2014-12-19  7:22       ` Michal Simek
2014-12-19  7:22         ` Michal Simek
2014-12-17 16:54 ` [PATCH v5 4/6] staging: fpga manager: add driver for socfpga fpga manager atull
2014-12-17 16:54   ` atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx
2014-12-18 15:31   ` Michal Simek
2014-12-18 15:31     ` Michal Simek
2014-12-18 20:59     ` atull
2014-12-18 20:59       ` atull
2014-12-19  7:30       ` Michal Simek
2014-12-19  7:30         ` Michal Simek
2014-12-17 16:54 ` [PATCH v5 5/6] arm: dts: socfpga: add altera " atull
2014-12-17 16:54   ` atull
2014-12-17 16:54 ` [PATCH v5 6/6] ARM: socfpga: defconfig: enable " atull
2014-12-17 16:54   ` atull
2014-12-17 17:32   ` Greg KH
2014-12-17 18:33     ` Michal Simek
2014-12-17 18:33       ` Michal Simek
2014-12-17 19:41       ` atull
2014-12-17 19:41         ` atull
2014-12-17 18:46     ` Jason Cooper
2014-12-17 18:46       ` Jason Cooper
2014-12-17 22:00     ` Pavel Machek
2014-12-17 22:00       ` Pavel Machek

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.