All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/39] OMAP GPMC driver conversion
@ 2012-05-01 12:19 ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

Hi,

GPMC driver conversion patch series. Some peripherals has GPMC helper
functions, these has been modified to cater to the needs of GPMC
driver. All the boards using GPMC has been adapted to use the new
GPMC driver.

GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
peripherals connected via GPMC are working. Really shaky about OMAP2
GPMC HWMOD entry. Would be helpful if someone can help me in resolving
warning on OMAP3 & verify whether OMAP2 entry is proper. The series
adapts to HWMOD.

Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
changes & cleaned up the now unnecessary exported symbol usages.

This series has been made on top of,
5e136da Linux-omap rebuilt: Updated to -rc5,
A patch by Javier Martinez Canillas <javier-0uQlZySMnqxg9hUCZPvPmw@public.gmane.org>,
OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
has also been incorporated into the series as this was necessary for
igep0020 board.

This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)

I would need help to get these changes tested on other boards using
GPMC. Expected problematic boards are those having OMAP2xxx SoCs,
apollon board. In the case of apollon, in addition to it being
OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly
writing to configuration registers.

Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated.

GPMC driver now provides NAND driver with GPMC-NAND registers so that
OMAP NAND driver can handle those by itself instead of using exported
symbols.

Acquiring CS for NAND has also been incorporated, it has been made as
a separate patch as it is felt that this should probably go away,
explained in the relevant patch.

GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC details can be referred in AM335X Technical Reference Manual
@ http://www.ti.com/lit/pdf/spruh73

v4: Handle wait pin (except for interrupts), enhance configuration
    & timing interface of GPMC to take care of all boards. Dynamic
    allocation of interrupt instead of static. Convert remaining
    peripherals to work with GPMC driver. Handle acquiring NAND CS#,
    adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor
    commenst on v3.
v3: Single device structure passed from platform for peripherals using
    multiple CS instead of using multiple device structure having a few
    redundant data, handle interrupts, GPMC NAND handling by GPMC NAND
    driver instead of GPMC driver
v2: Avoid code movement that kept similar code together (for easy review)

TODO: Cleanup

Regards
Afzal

Afzal Mohammed (38):
  ARM: OMAP2+: gpmc: driver conversion
  ARM: OMAP2+: gpmc: Adapt to HWMOD
  ARM: OMAP2+: gpmc: register details for nand driver
  ARM: OMAP2+: gpmc: Acquire NAND CS value
  ARM: OMAP2+: nand: create platform data structure
  ARM: OMAP2+: onenand: return value in init function
  ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
  ARM: OMAP2+: flash: Adapt to gpmc driver
  ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
  ARM: OMAP3: hwmod data: add gpmc
  ARM: OMAP2xxx: hwmod data: add gpmc
  mtd: nand: omap2: obtain memory from resource
  mtd: nand: omap2: use gpmc provided irqs
  mtd: nand: omap2: handle nand on gpmc
  mtd: onenand: omap: obtain memory from resource
  ARM: OMAP2+: board omap3evm: gpmc driver adaptation
  ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
  ARM: OMAP2+: board apollon: gpmc driver adaptation
  ARM: OMAP2+: board h4: gpmc driver adaptation
  ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
  ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
  ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
  ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
  ARM: OMAP2+: board cm-t35: gpmc driver adaptation
  ARM: OMAP2+: board ldp: gpmc driver adaptation
  ARM: OMAP2+: board n8x0: gpmc driver adaptation
  ARM: OMAP2+: board omap3logic: gpmc driver adaptation
  ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
  ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
  ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
  ARM: OMAP2+: board overo: gpmc driver adaptation
  ARM: OMAP2+: board rm680: gpmc driver adaptation
  ARM: OMAP2+: board rx51: gpmc driver adaptation
  ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
  ARM: OMAP2+: board igep0020: gpmc driver adaptation

Javier Martinez Canillas (1):
  OMAP3: igep0020: Add support for Micron NAND Flash storage memory

 arch/arm/mach-omap2/board-2430sdp.c                |   44 +-
 arch/arm/mach-omap2/board-3430sdp.c                |   18 +-
 arch/arm/mach-omap2/board-3630sdp.c                |   23 +-
 arch/arm/mach-omap2/board-apollon.c                |  152 +--
 arch/arm/mach-omap2/board-cm-t35.c                 |   21 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |   10 +-
 arch/arm/mach-omap2/board-devkit8000.c             |    6 +-
 arch/arm/mach-omap2/board-flash.c                  |  160 ++--
 arch/arm/mach-omap2/board-flash.h                  |   36 +-
 arch/arm/mach-omap2/board-h4.c                     |  130 +--
 arch/arm/mach-omap2/board-igep0020.c               |   99 +-
 arch/arm/mach-omap2/board-ldp.c                    |   26 +-
 arch/arm/mach-omap2/board-n8x0.c                   |   18 +-
 arch/arm/mach-omap2/board-omap3beagle.c            |   22 +-
 arch/arm/mach-omap2/board-omap3evm.c               |   14 +-
 arch/arm/mach-omap2/board-omap3logic.c             |   13 +-
 arch/arm/mach-omap2/board-omap3pandora.c           |   11 +-
 arch/arm/mach-omap2/board-omap3stalker.c           |   13 +-
 arch/arm/mach-omap2/board-omap3touchbook.c         |    6 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |   13 +-
 arch/arm/mach-omap2/board-overo.c                  |   32 +-
 arch/arm/mach-omap2/board-rm680.c                  |   10 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   17 +-
 arch/arm/mach-omap2/board-zoom-debugboard.c        |   47 +-
 arch/arm/mach-omap2/board-zoom.c                   |    5 +-
 arch/arm/mach-omap2/common-board-devices.c         |   46 -
 arch/arm/mach-omap2/common-board-devices.h         |    1 -
 arch/arm/mach-omap2/gpmc-nand.c                    |   84 +-
 arch/arm/mach-omap2/gpmc-onenand.c                 |  111 +--
 arch/arm/mach-omap2/gpmc-smc91x.c                  |   87 +-
 arch/arm/mach-omap2/gpmc-smsc911x.c                |   59 +-
 arch/arm/mach-omap2/gpmc.c                         |  980 +++++++++++++++++---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |   52 ++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 arch/arm/mach-omap2/usb-tusb6010.c                 |  177 ++--
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h      |   10 +-
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h    |    9 +-
 arch/arm/plat-omap/include/plat/gpmc.h             |  110 ++-
 arch/arm/plat-omap/include/plat/nand.h             |   10 +-
 arch/arm/plat-omap/include/plat/onenand.h          |    7 +-
 drivers/mtd/nand/omap2.c                           |  296 ++++--
 drivers/mtd/onenand/omap2.c                        |   29 +-
 include/linux/usb/musb.h                           |    4 +-
 47 files changed, 2110 insertions(+), 988 deletions(-)

-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 00/39] OMAP GPMC driver conversion
@ 2012-05-01 12:19 ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Hi,

GPMC driver conversion patch series. Some peripherals has GPMC helper
functions, these has been modified to cater to the needs of GPMC
driver. All the boards using GPMC has been adapted to use the new
GPMC driver.

GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
peripherals connected via GPMC are working. Really shaky about OMAP2
GPMC HWMOD entry. Would be helpful if someone can help me in resolving
warning on OMAP3 & verify whether OMAP2 entry is proper. The series
adapts to HWMOD.

Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
changes & cleaned up the now unnecessary exported symbol usages.

This series has been made on top of,
5e136da Linux-omap rebuilt: Updated to -rc5,
A patch by Javier Martinez Canillas <javier@dowhile0.org>,
OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
has also been incorporated into the series as this was necessary for
igep0020 board.

This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)

I would need help to get these changes tested on other boards using
GPMC. Expected problematic boards are those having OMAP2xxx SoCs,
apollon board. In the case of apollon, in addition to it being
OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly
writing to configuration registers.

Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated.

GPMC driver now provides NAND driver with GPMC-NAND registers so that
OMAP NAND driver can handle those by itself instead of using exported
symbols.

Acquiring CS for NAND has also been incorporated, it has been made as
a separate patch as it is felt that this should probably go away,
explained in the relevant patch.

GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC details can be referred in AM335X Technical Reference Manual
@ http://www.ti.com/lit/pdf/spruh73

v4: Handle wait pin (except for interrupts), enhance configuration
    & timing interface of GPMC to take care of all boards. Dynamic
    allocation of interrupt instead of static. Convert remaining
    peripherals to work with GPMC driver. Handle acquiring NAND CS#,
    adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor
    commenst on v3.
v3: Single device structure passed from platform for peripherals using
    multiple CS instead of using multiple device structure having a few
    redundant data, handle interrupts, GPMC NAND handling by GPMC NAND
    driver instead of GPMC driver
v2: Avoid code movement that kept similar code together (for easy review)

TODO: Cleanup

Regards
Afzal

Afzal Mohammed (38):
  ARM: OMAP2+: gpmc: driver conversion
  ARM: OMAP2+: gpmc: Adapt to HWMOD
  ARM: OMAP2+: gpmc: register details for nand driver
  ARM: OMAP2+: gpmc: Acquire NAND CS value
  ARM: OMAP2+: nand: create platform data structure
  ARM: OMAP2+: onenand: return value in init function
  ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
  ARM: OMAP2+: flash: Adapt to gpmc driver
  ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
  ARM: OMAP3: hwmod data: add gpmc
  ARM: OMAP2xxx: hwmod data: add gpmc
  mtd: nand: omap2: obtain memory from resource
  mtd: nand: omap2: use gpmc provided irqs
  mtd: nand: omap2: handle nand on gpmc
  mtd: onenand: omap: obtain memory from resource
  ARM: OMAP2+: board omap3evm: gpmc driver adaptation
  ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
  ARM: OMAP2+: board apollon: gpmc driver adaptation
  ARM: OMAP2+: board h4: gpmc driver adaptation
  ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
  ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
  ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
  ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
  ARM: OMAP2+: board cm-t35: gpmc driver adaptation
  ARM: OMAP2+: board ldp: gpmc driver adaptation
  ARM: OMAP2+: board n8x0: gpmc driver adaptation
  ARM: OMAP2+: board omap3logic: gpmc driver adaptation
  ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
  ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
  ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
  ARM: OMAP2+: board overo: gpmc driver adaptation
  ARM: OMAP2+: board rm680: gpmc driver adaptation
  ARM: OMAP2+: board rx51: gpmc driver adaptation
  ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
  ARM: OMAP2+: board igep0020: gpmc driver adaptation

Javier Martinez Canillas (1):
  OMAP3: igep0020: Add support for Micron NAND Flash storage memory

 arch/arm/mach-omap2/board-2430sdp.c                |   44 +-
 arch/arm/mach-omap2/board-3430sdp.c                |   18 +-
 arch/arm/mach-omap2/board-3630sdp.c                |   23 +-
 arch/arm/mach-omap2/board-apollon.c                |  152 +--
 arch/arm/mach-omap2/board-cm-t35.c                 |   21 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |   10 +-
 arch/arm/mach-omap2/board-devkit8000.c             |    6 +-
 arch/arm/mach-omap2/board-flash.c                  |  160 ++--
 arch/arm/mach-omap2/board-flash.h                  |   36 +-
 arch/arm/mach-omap2/board-h4.c                     |  130 +--
 arch/arm/mach-omap2/board-igep0020.c               |   99 +-
 arch/arm/mach-omap2/board-ldp.c                    |   26 +-
 arch/arm/mach-omap2/board-n8x0.c                   |   18 +-
 arch/arm/mach-omap2/board-omap3beagle.c            |   22 +-
 arch/arm/mach-omap2/board-omap3evm.c               |   14 +-
 arch/arm/mach-omap2/board-omap3logic.c             |   13 +-
 arch/arm/mach-omap2/board-omap3pandora.c           |   11 +-
 arch/arm/mach-omap2/board-omap3stalker.c           |   13 +-
 arch/arm/mach-omap2/board-omap3touchbook.c         |    6 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |   13 +-
 arch/arm/mach-omap2/board-overo.c                  |   32 +-
 arch/arm/mach-omap2/board-rm680.c                  |   10 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   17 +-
 arch/arm/mach-omap2/board-zoom-debugboard.c        |   47 +-
 arch/arm/mach-omap2/board-zoom.c                   |    5 +-
 arch/arm/mach-omap2/common-board-devices.c         |   46 -
 arch/arm/mach-omap2/common-board-devices.h         |    1 -
 arch/arm/mach-omap2/gpmc-nand.c                    |   84 +-
 arch/arm/mach-omap2/gpmc-onenand.c                 |  111 +--
 arch/arm/mach-omap2/gpmc-smc91x.c                  |   87 +-
 arch/arm/mach-omap2/gpmc-smsc911x.c                |   59 +-
 arch/arm/mach-omap2/gpmc.c                         |  980 +++++++++++++++++---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |   52 ++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 arch/arm/mach-omap2/usb-tusb6010.c                 |  177 ++--
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h      |   10 +-
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h    |    9 +-
 arch/arm/plat-omap/include/plat/gpmc.h             |  110 ++-
 arch/arm/plat-omap/include/plat/nand.h             |   10 +-
 arch/arm/plat-omap/include/plat/onenand.h          |    7 +-
 drivers/mtd/nand/omap2.c                           |  296 ++++--
 drivers/mtd/onenand/omap2.c                        |   29 +-
 include/linux/usb/musb.h                           |    4 +-
 47 files changed, 2110 insertions(+), 988 deletions(-)

-- 
1.7.10

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

* [PATCH v4 00/39] OMAP GPMC driver conversion
@ 2012-05-01 12:19 ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

GPMC driver conversion patch series. Some peripherals has GPMC helper
functions, these has been modified to cater to the needs of GPMC
driver. All the boards using GPMC has been adapted to use the new
GPMC driver.

GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
peripherals connected via GPMC are working. Really shaky about OMAP2
GPMC HWMOD entry. Would be helpful if someone can help me in resolving
warning on OMAP3 & verify whether OMAP2 entry is proper. The series
adapts to HWMOD.

Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
changes & cleaned up the now unnecessary exported symbol usages.

This series has been made on top of,
5e136da Linux-omap rebuilt: Updated to -rc5,
A patch by Javier Martinez Canillas <javier@dowhile0.org>,
OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
has also been incorporated into the series as this was necessary for
igep0020 board.

This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)

I would need help to get these changes tested on other boards using
GPMC. Expected problematic boards are those having OMAP2xxx SoCs,
apollon board. In the case of apollon, in addition to it being
OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly
writing to configuration registers.

Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated.

GPMC driver now provides NAND driver with GPMC-NAND registers so that
OMAP NAND driver can handle those by itself instead of using exported
symbols.

Acquiring CS for NAND has also been incorporated, it has been made as
a separate patch as it is felt that this should probably go away,
explained in the relevant patch.

GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC details can be referred in AM335X Technical Reference Manual
@ http://www.ti.com/lit/pdf/spruh73

v4: Handle wait pin (except for interrupts), enhance configuration
    & timing interface of GPMC to take care of all boards. Dynamic
    allocation of interrupt instead of static. Convert remaining
    peripherals to work with GPMC driver. Handle acquiring NAND CS#,
    adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor
    commenst on v3.
v3: Single device structure passed from platform for peripherals using
    multiple CS instead of using multiple device structure having a few
    redundant data, handle interrupts, GPMC NAND handling by GPMC NAND
    driver instead of GPMC driver
v2: Avoid code movement that kept similar code together (for easy review)

TODO: Cleanup

Regards
Afzal

Afzal Mohammed (38):
  ARM: OMAP2+: gpmc: driver conversion
  ARM: OMAP2+: gpmc: Adapt to HWMOD
  ARM: OMAP2+: gpmc: register details for nand driver
  ARM: OMAP2+: gpmc: Acquire NAND CS value
  ARM: OMAP2+: nand: create platform data structure
  ARM: OMAP2+: onenand: return value in init function
  ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
  ARM: OMAP2+: flash: Adapt to gpmc driver
  ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
  ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
  ARM: OMAP3: hwmod data: add gpmc
  ARM: OMAP2xxx: hwmod data: add gpmc
  mtd: nand: omap2: obtain memory from resource
  mtd: nand: omap2: use gpmc provided irqs
  mtd: nand: omap2: handle nand on gpmc
  mtd: onenand: omap: obtain memory from resource
  ARM: OMAP2+: board omap3evm: gpmc driver adaptation
  ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
  ARM: OMAP2+: board apollon: gpmc driver adaptation
  ARM: OMAP2+: board h4: gpmc driver adaptation
  ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
  ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
  ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
  ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
  ARM: OMAP2+: board cm-t35: gpmc driver adaptation
  ARM: OMAP2+: board ldp: gpmc driver adaptation
  ARM: OMAP2+: board n8x0: gpmc driver adaptation
  ARM: OMAP2+: board omap3logic: gpmc driver adaptation
  ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
  ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
  ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
  ARM: OMAP2+: board overo: gpmc driver adaptation
  ARM: OMAP2+: board rm680: gpmc driver adaptation
  ARM: OMAP2+: board rx51: gpmc driver adaptation
  ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
  ARM: OMAP2+: board igep0020: gpmc driver adaptation

Javier Martinez Canillas (1):
  OMAP3: igep0020: Add support for Micron NAND Flash storage memory

 arch/arm/mach-omap2/board-2430sdp.c                |   44 +-
 arch/arm/mach-omap2/board-3430sdp.c                |   18 +-
 arch/arm/mach-omap2/board-3630sdp.c                |   23 +-
 arch/arm/mach-omap2/board-apollon.c                |  152 +--
 arch/arm/mach-omap2/board-cm-t35.c                 |   21 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |   10 +-
 arch/arm/mach-omap2/board-devkit8000.c             |    6 +-
 arch/arm/mach-omap2/board-flash.c                  |  160 ++--
 arch/arm/mach-omap2/board-flash.h                  |   36 +-
 arch/arm/mach-omap2/board-h4.c                     |  130 +--
 arch/arm/mach-omap2/board-igep0020.c               |   99 +-
 arch/arm/mach-omap2/board-ldp.c                    |   26 +-
 arch/arm/mach-omap2/board-n8x0.c                   |   18 +-
 arch/arm/mach-omap2/board-omap3beagle.c            |   22 +-
 arch/arm/mach-omap2/board-omap3evm.c               |   14 +-
 arch/arm/mach-omap2/board-omap3logic.c             |   13 +-
 arch/arm/mach-omap2/board-omap3pandora.c           |   11 +-
 arch/arm/mach-omap2/board-omap3stalker.c           |   13 +-
 arch/arm/mach-omap2/board-omap3touchbook.c         |    6 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |   13 +-
 arch/arm/mach-omap2/board-overo.c                  |   32 +-
 arch/arm/mach-omap2/board-rm680.c                  |   10 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   17 +-
 arch/arm/mach-omap2/board-zoom-debugboard.c        |   47 +-
 arch/arm/mach-omap2/board-zoom.c                   |    5 +-
 arch/arm/mach-omap2/common-board-devices.c         |   46 -
 arch/arm/mach-omap2/common-board-devices.h         |    1 -
 arch/arm/mach-omap2/gpmc-nand.c                    |   84 +-
 arch/arm/mach-omap2/gpmc-onenand.c                 |  111 +--
 arch/arm/mach-omap2/gpmc-smc91x.c                  |   87 +-
 arch/arm/mach-omap2/gpmc-smsc911x.c                |   59 +-
 arch/arm/mach-omap2/gpmc.c                         |  980 +++++++++++++++++---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |   52 ++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 arch/arm/mach-omap2/usb-tusb6010.c                 |  177 ++--
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h      |   10 +-
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h    |    9 +-
 arch/arm/plat-omap/include/plat/gpmc.h             |  110 ++-
 arch/arm/plat-omap/include/plat/nand.h             |   10 +-
 arch/arm/plat-omap/include/plat/onenand.h          |    7 +-
 drivers/mtd/nand/omap2.c                           |  296 ++++--
 drivers/mtd/onenand/omap2.c                        |   29 +-
 include/linux/usb/musb.h                           |    4 +-
 47 files changed, 2110 insertions(+), 988 deletions(-)

-- 
1.7.10

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:19     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed, Vaibhav Hiremath, Jon Hunter

Convert GPMC code to driver. Boards using GPMC should provide driver
with type of configuration, timing, CS. Platform devices would then be
created for each connected peripheral (details also to be passed by
board so that it reaches respective driver). And GPMC driver would
populate memory resource details for the connected peripheral driver.
Boards should inform gpmc driver with platform data destined for
peripheral driver. gpmc driver will provide the same information to
peripheral driver.

A peripheral connected to GPMC can have multiple address spaces using
different chip select. Hence GPMC driver has been provided capability
to create platform device for peripheral using mutiple CS. The
peripheral that made it necessary was tusb6010.

Interrupts of GPMC are presented to drivers of connected peripherals
as resource. A fictitious interrupt controller chip handles these
interrupts at GPMC hardware level. Clients can use normal interrupt
APIs. Platform information of peripheral passed to GPMC driver should
indicate interrupts to be used via flags.

Driver is capable of configuring waitpin, waitpin details has to be
provided per CS. Wait pin has been considered as exclusive resource
as multiple peripherals should not using the same pin, at the same
it is valid for mutiple CS to use same waitpin provided they are
a part of single peripheral (eg. tusb6010)

An exported symbol for reconfiguring GPMC settings has been provided.
OneNAND is the one that neccessitated this.

Acquiring CS# for NAND is done on a few boards. It means, depending
on bootloader to embed this information. Probably CS# being used can
be set in the Kernel, and acquiring it can be removed. If ever this
capbility is needed, GPMC driver has to be made aware of handling it.

Modifications has been made keeping in mind that the driver would
have to move to driver folder. This explains requirement of clk_prd
field; even though clk_prd variable is not necessary as
gpmc_get_fclk_period is present in the same file as of now, this will
help in moving the driver easily to drivers folder.

Code related to GPMC clock may have to continue live in platform
folders as input clock is beyond the control of GPMC and calculating
timing for the peripheral may need other helpers. This explains
presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
both doing same work, latter meant to go with driver, former for
calculation in platform code.

Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
suggestions which resulted in improving the code.

Cc: Vaibhav Hiremath <hvaibhav-l0cyMroinI0@public.gmane.org>
Cc: Jon Hunter <jon-hunter-l0cyMroinI0@public.gmane.org>
Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
 2 files changed, 872 insertions(+), 98 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 580e684..12916f3 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -14,8 +14,11 @@
  */
 #undef DEBUG
 
+#include <linux/platform_device.h>
+
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -53,6 +56,45 @@
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
 
+/* GPMC register bits */
+#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
+#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
+#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
+#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
+#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
+#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
+#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
+
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
+#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
+#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
+
+#define	GPMC_WAITPIN_IDX0			0x0
+#define	GPMC_WAITPIN_IDX1			0x1
+#define	GPMC_WAITPIN_IDX2			0x2
+#define	GPMC_WAITPIN_IDX3			0x3
+#define	GPMC_NR_WAITPIN				0x4
+
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
 #define BOOT_ROM_SPACE		0x100000	/* 1MB */
@@ -64,6 +106,55 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+#define	DRIVER_NAME	"omap-gpmc"
+
+#define	GPMC_NR_IRQ		2
+
+#define	HIGH			1
+#define	LOW			-1
+
+struct gpmc_device {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct resource		*gpmc_res;
+	unsigned		gpmc_res_cnt;
+	bool			have_waitpin;
+	unsigned		waitpin;
+	int			waitpin_polarity;
+};
+
+struct gpmc_irq	{
+	unsigned		irq;
+	u32			bitmask;
+};
+
+struct gpmc {
+	struct device		*dev;
+	unsigned long		clk_prd;
+	void __iomem		*io_base;
+	unsigned long		phys_base;
+	u32			memsize;
+	unsigned		cs_map;
+	int			ecc_used;
+	spinlock_t		mem_lock;
+	struct resource		mem_root;
+	struct resource		cs_mem[GPMC_CS_NUM];
+	/* XXX: Or allocate dynamically ? */
+	struct gpmc_device	device[GPMC_CS_NUM];
+	unsigned		num_device;
+	unsigned		master_irq;
+	unsigned		irq_start;
+	struct gpmc_irq		irq[GPMC_NR_IRQ];
+	struct irq_chip		irq_chip;
+	bool			wp;
+	unsigned		waitpin_map;
+	unsigned		revision;
+};
+
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
-static struct resource	gpmc_mem_root;
-static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
-static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
-
-static void __iomem *gpmc_base;
-
 static struct clk *gpmc_l3_clk;
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+static struct gpmc *gpmc;
 
 static void gpmc_write_reg(int idx, u32 val)
 {
-	__raw_writel(val, gpmc_base + idx);
+	writel(val, gpmc->io_base + idx);
 }
 
 static u32 gpmc_read_reg(int idx)
 {
-	return __raw_readl(gpmc_base + idx);
+	return readl(gpmc->io_base + idx);
 }
 
 static void gpmc_cs_write_byte(int cs, int idx, u8 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writeb(val, reg_addr);
 }
 
 static u8 gpmc_cs_read_byte(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readb(reg_addr);
 }
 
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writel(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writel(val, reg_addr);
 }
 
 u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readl(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readl(reg_addr);
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
@@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 	if (time == 0)
 		ticks = 0;
 	else
-		ticks = gpmc_ns_to_ticks(time);
+		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
+
 	nr_bits = end_bit - st_bit + 1;
 	if (ticks >= 1 << nr_bits) {
 #ifdef DEBUG
@@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 #ifdef DEBUG
 	printk(KERN_INFO
 		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
-	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
 			(l >> st_bit) & mask, time);
 #endif
 	l &= ~(mask << st_bit);
@@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 		return -1
 #endif
 
+int gpmc_calc_divider(unsigned int sync_clk)
+{
+	int div;
+	u32 l;
+
+	l = sync_clk + (gpmc->clk_prd - 1);
+	div = l / gpmc->clk_prd;
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
 int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 {
 	int div;
@@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 	return div;
 }
 
+static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+	if (p->cs_extra_delay)
+		l |= GPMC_CONFIG2_CSEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+	if (p->adv_extra_delay)
+		l |= GPMC_CONFIG3_ADVEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+	if (p->oe_extra_delay)
+		l |= GPMC_CONFIG4_OEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
+	if (p->we_extra_delay)
+		l |= GPMC_CONFIG4_WEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
+	if (p->cycle2cyclesamecsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	if (p->cycle2cyclediffcsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
+}
+
 int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 {
 	int div;
 	u32 l;
 
-	div = gpmc_cs_calc_divider(cs, t->sync_clk);
+	div = gpmc_calc_divider(t->sync_clk);
 	if (div < 0)
 		return -1;
 
@@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
-	if (cpu_is_omap34xx()) {
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
+
+	if (gpmc->revision >= 5) {
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
 	}
@@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
 #ifdef DEBUG
 		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
-				cs, (div * gpmc_get_fclk_period()) / 1000, div);
+				cs, (div * gpmc->clk_prd) / 1000, div);
 #endif
 		l &= ~0x03;
 		l |= (div - 1);
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
 	}
 
+	gpmc_cs_onoff_timings(cs, &t->control);
+
 	return 0;
 }
 
@@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
 }
 
-static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
 {
 	u32 l;
 	u32 mask;
@@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
 	return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static int gpmc_cs_set_reserved(int cs, int reserved)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	gpmc_cs_map &= ~(1 << cs);
-	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+	gpmc->cs_map &= ~(1 << cs);
+	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
 
 	return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static int gpmc_cs_reserved(int cs)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	return gpmc_cs_map & (1 << cs);
+	return gpmc->cs_map & (1 << cs);
 }
 
 static unsigned long gpmc_mem_align(unsigned long size)
@@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
 	return size;
 }
 
-static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+static __devinit
+int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
 {
-	struct resource	*res = &gpmc_cs_mem[cs];
+	struct resource	*res = &gpmc->cs_mem[cs];
 	int r;
 
 	size = gpmc_mem_align(size);
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	res->start = base;
 	res->end = base + size - 1;
-	r = request_resource(&gpmc_mem_root, res);
-	spin_unlock(&gpmc_mem_lock);
+	r = request_resource(&gpmc->mem_root, res);
+	spin_unlock(&gpmc->mem_lock);
 
 	return r;
 }
 
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
-	struct resource *res = &gpmc_cs_mem[cs];
+	struct resource *res = &gpmc->cs_mem[cs];
 	int r = -1;
 
 	if (cs > GPMC_CS_NUM)
@@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (size > (1 << GPMC_SECTION_SHIFT))
 		return -ENOMEM;
 
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (gpmc_cs_reserved(cs)) {
 		r = -EBUSY;
 		goto out;
@@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (gpmc_cs_mem_enabled(cs))
 		r = adjust_resource(res, res->start & ~(size - 1), size);
 	if (r < 0)
-		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
 				      size, NULL, NULL);
 	if (r < 0)
 		goto out;
@@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	*base = res->start;
 	gpmc_cs_set_reserved(cs, 1);
 out:
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 	return r;
 }
 EXPORT_SYMBOL(gpmc_cs_request);
 
 void gpmc_cs_free(int cs)
 {
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
 		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
 		BUG();
-		spin_unlock(&gpmc_mem_lock);
+		spin_unlock(&gpmc->mem_lock);
 		return;
 	}
 	gpmc_cs_disable_mem(cs);
-	release_resource(&gpmc_cs_mem[cs]);
+	release_resource(&gpmc->cs_mem[cs]);
 	gpmc_cs_set_reserved(cs, 0);
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 }
 EXPORT_SYMBOL(gpmc_cs_free);
 
@@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
-static void __init gpmc_mem_init(void)
+static __devinit void gpmc_mem_init(void)
 {
 	int cs;
 	unsigned long boot_rom_space = 0;
@@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
 	/* In apollon the CS0 is mapped as 0x0000 0000 */
 	if (machine_is_omap_apollon())
 		boot_rom_space = 0;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
-	gpmc_mem_root.end = GPMC_MEM_END;
+	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc->mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
 	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
@@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	u32 l, irq;
-	int cs, ret = -EINVAL;
-	int gpmc_irq;
+	int ret = -EINVAL;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
 		ck = "core_l3_ck";
-		if (cpu_is_omap2420())
-			l = OMAP2420_GPMC_BASE;
-		else
-			l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
-		l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap44xx()) {
 		ck = "gpmc_ck";
-		l = OMAP44XX_GPMC_BASE;
-		gpmc_irq = OMAP44XX_IRQ_GPMC;
 	}
 
 	if (WARN_ON(!ck))
@@ -728,53 +863,607 @@ static int __init gpmc_init(void)
 		BUG();
 	}
 
-	gpmc_base = ioremap(l, SZ_4K);
-	if (!gpmc_base) {
-		clk_put(gpmc_l3_clk);
-		printk(KERN_ERR "Could not get GPMC register memory\n");
-		BUG();
+	clk_enable(gpmc_l3_clk);
+
+	return 0;
+}
+postcore_initcall(gpmc_init);
+
+static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
+{
+	return gpmc->waitpin_map & (0x1 << waitpin);
+}
+
+static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
+{
+	gpmc->waitpin_map &= ~(0x1 << waitpin);
+	gpmc->waitpin_map |= (0x1 << waitpin);
+}
+
+static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
+{
+	if (!(waitpin < GPMC_NR_WAITPIN))
+		return -ENODEV;
+
+	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
+		return -EBUSY;
+	else
+		gpmc_reserve_waitpin(gpmc, waitpin);
+
+	return 0;
+}
+
+static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
+{
+	int ret;
+
+	if (!gd->have_waitpin)
+		return 0;
+
+	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
+		return ret;
+	} else if (gd->waitpin_polarity) {
+		u32 l = gpmc_read_reg(GPMC_CONFIG);
+		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
+
+		if (gd->waitpin_polarity == HIGH)
+			l |= 1 << shift;
+		else
+			l &= ~(1 << shift);
+
+		gpmc_write_reg(GPMC_CONFIG, l);
 	}
+	return 0;
+}
 
-	clk_enable(gpmc_l3_clk);
+static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
+						unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+	unsigned idx = ~0x0;
+	int polarity = 0;
 
-	l = gpmc_read_reg(GPMC_REVISION);
-	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-	/* Set smart idle mode and automatic L3 clock gating */
-	l = gpmc_read_reg(GPMC_SYSCONFIG);
-	l &= 0x03 << 3;
-	l |= (0x02 << 3) | (1 << 0);
-	gpmc_write_reg(GPMC_SYSCONFIG, l);
-	gpmc_mem_init();
+	switch (conf & GPMC_WAITPIN_MASK) {
+	case GPMC_WAITPIN_0:
+		idx =  GPMC_WAITPIN_IDX0;
+		break;
+	case GPMC_WAITPIN_1:
+		idx =  GPMC_WAITPIN_IDX1;
+		break;
+	case GPMC_WAITPIN_2:
+		idx =  GPMC_WAITPIN_IDX2;
+		break;
+	case GPMC_WAITPIN_3:
+		idx =  GPMC_WAITPIN_IDX3;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
+		return -EINVAL;
+		break;
+	}
 
-	/* initalize the irq_chained */
-	irq = OMAP_GPMC_IRQ_BASE;
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-						handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-		irq++;
+	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
+	case GPMC_WAITPIN_ACTIVE_LOW:
+		polarity = LOW;
+		break;
+	case GPMC_WAITPIN_ACTIVE_HIGH:
+		polarity = HIGH;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
+		return -EINVAL;
+		break;
 	}
 
-	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
-	if (ret)
-		pr_err("gpmc: irq-%d could not claim: err %d\n",
-						gpmc_irq, ret);
-	return ret;
+	if (idx != ~0x0) {
+		if (gd->have_waitpin) {
+			if (gd->waitpin != idx ||
+					gd->waitpin_polarity != polarity) {
+				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
+					gd->waitpin, gd->waitpin_polarity,
+					gd->name, gd->id);
+				return -EBUSY;
+			}
+		} else {
+			gd->have_waitpin = true;
+			gd->waitpin = idx;
+			gd->waitpin_polarity = polarity;
+		}
+
+		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
+		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+	} else if (polarity) {
+		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
+							gd->name, gd->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
+		GPMC_CONFIG1_MUXADDDATA |
+		GPMC_CONFIG1_DEVICETYPE(~0) |
+		GPMC_CONFIG1_DEVICESIZE(~0) |
+		GPMC_CONFIG1_WAIT_WRITE_MON |
+		GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_PAGE_LEN(~0) |
+		GPMC_CONFIG1_WRITETYPE_SYNC |
+		GPMC_CONFIG1_WRITEMULTIPLE |
+		GPMC_CONFIG1_READTYPE_SYNC |
+		GPMC_CONFIG1_READMULTIPLE |
+		GPMC_CONFIG1_WRAPBURST |
+		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
+		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
+
+	if (conf & GPMC_TIMEPARAGRANULARITY)
+		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
+	if (conf & GPMC_MUXADDDATA)
+		l |= GPMC_CONFIG1_MUXADDDATA;
+	if (conf & GPMC_DEVICETYPE_NAND)
+		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
+	if (conf & GPMC_DEVICESIZE_16)
+		l |= GPMC_CONFIG1_DEVICESIZE_16;
+	if (conf & GPMC_WAIT_WRITE_MON)
+		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (conf & GPMC_WAIT_READ_MON)
+		l |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (conf & GPMC_PAGE_LEN_16)
+		l |= GPMC_CONFIG1_PAGE_LEN_16;
+	else if (conf & GPMC_PAGE_LEN_8)
+		l |= GPMC_CONFIG1_PAGE_LEN_8;
+	if (conf & GPMC_WRITETYPE_SYNC)
+		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (conf & GPMC_WRITEMULTIPLE)
+		l |= GPMC_CONFIG1_WRITEMULTIPLE;
+	if (conf & GPMC_READTYPE_SYNC)
+		l |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (conf & GPMC_READMULTIPLE)
+		l |= GPMC_CONFIG1_READMULTIPLE;
+	if (conf & GPMC_WRAPBURST)
+		l |= GPMC_CONFIG1_WRAPBURST;
+	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
+	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
+	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
+	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+	if (conf & GPMC_WRITEPROTECT)
+		gpmc->wp = true;
+}
+
+static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
+			struct gpmc_device *gd, struct gpmc_cs_data *cs)
+{
+	int ret;
+
+	/* some boards rely on bootloader for configuration */
+	if (cs->have_config) {
+		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
+		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
+
+	if (cs->timing) {
+		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
+
+	return 0;
+}
+
+static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
+{
+	int i;
+	struct gpmc_device *gd;
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (!strcmp(gd->name, name) && gd->id == id)
+			return i;
+
+	return -ENOENT;
+}
+
+int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
+{
+	int i;
+
+	i = gpmc_match_device(gpmc, name, id);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
+		return i;
+	}
+
+	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
+		return i;
+	}
+
+	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
+
+}
+EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
+
+static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
+{
+	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
+		return GPMC_IRQ_FIFOEVENTENABLE;
+	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
+		return GPMC_IRQ_COUNT_EVENT;
+	else
+		return 0;
+}
+
+static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
+		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
+			res[n].start = res[n].end = gpmc->irq[i].irq;
+			res[n].flags = IORESOURCE_IRQ;
+			dev_info(gpmc->dev, "irq %u on CS %d\n",
+						res[n].start, cs->cs);
+			n++;
+		}
+
+	return n;
+}
+
+static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	unsigned long start;
+	int ret;
+
+	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
+		return ret;
+	}
+
+	res->start = start + cs->mem_offset;
+	res->end = res->start + cs->mem_size - 1;
+	res->flags = IORESOURCE_MEM;
+
+	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
+							res->end, cs->cs);
+
+	return 1;
+}
+
+static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int num, ret;
+
+	num = gpmc_setup_cs_mem(gpmc, cs, res);
+	if (IS_ERR_VALUE(num))
+		return num;
+
+	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
+
+	return num;
+}
+
+static __devinit int gpmc_setup_device(struct gpmc *gpmc,
+		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
+{
+	int i, n, ret;
+	struct gpmc_cs_data *cs;
+
+	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
+				i < gdp->num_cs; i++, cs++)
+		n += hweight32(cs->irq_config);
+
+	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
+								GFP_KERNEL);
+	if (gd->gpmc_res == NULL) {
+		dev_err(gpmc->dev, "error: memory allocation\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
+			i < gdp->num_cs; cs++, i++) {
+		ret = gpmc_setup_cs(gpmc, gd, cs,
+					gd->gpmc_res + gd->gpmc_res_cnt);
+		if (IS_ERR_VALUE(ret) ||
+				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {
+			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
+			devm_kfree(gpmc->dev, gd->gpmc_res);
+			gd->gpmc_res = NULL;
+			gd->gpmc_res_cnt = 0;
+			return -EINVAL;
+		} else
+			gd->gpmc_res_cnt += ret;
+	}
+
+	gd->name = gdp->name;
+	gd->id = gdp->id;
+	gd->pdata = gdp->pdata;
+	gd->pdata_size = gdp->pdata_size;
+	gd->per_res = gdp->per_res;
+	gd->per_res_cnt = gdp->per_res_cnt;
+
+	return 0;
+}
+
+static __devinit
+struct platform_device *gpmc_create_device(struct gpmc *gpmc,
+					struct gpmc_device *p)
+{
+	int num = p->per_res_cnt + p->gpmc_res_cnt;
+	struct resource *res;
+	struct platform_device *pdev;
+
+	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
+								GFP_KERNEL);
+	if (!res) {
+		dev_err(gpmc->dev, "error: allocating memory\n");
+		return NULL;
+	}
+
+	memcpy((char *)res, (const char *) p->gpmc_res,
+				sizeof(struct resource) * p->gpmc_res_cnt);
+	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
+				sizeof(struct resource) * p->per_res_cnt);
+
+	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
+					res, num, p->pdata, p->pdata_size);
+
+	devm_kfree(gpmc->dev, res);
+
+	return pdev;
 }
-postcore_initcall(gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
-	u8 cs;
+	int i;
+	u32 regval;
+	struct gpmc *gpmc = dev;
+
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
 
-	/* check cs to invoke the irq */
-	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
-	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
-		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (regval & gpmc->irq[i].bitmask)
+			generic_handle_irq(gpmc->irq[i].irq);
+
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
 
 	return IRQ_HANDLED;
 }
 
+static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
+{
+	int i;
+	u32 regval;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (irq == gpmc->irq[i].irq) {
+			regval = gpmc_read_reg(GPMC_IRQENABLE);
+			if (endis)
+				regval |= gpmc->irq[i].bitmask;
+			else
+				regval &= ~gpmc->irq[i].bitmask;
+			gpmc_write_reg(GPMC_IRQENABLE, regval);
+			break;
+		}
+
+	return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
+{
+	int i;
+	u32 regval;
+
+	if (!gpmc->master_irq)
+		return -EINVAL;
+
+	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+	if (IS_ERR_VALUE(gpmc->irq_start)) {
+		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
+		return gpmc->irq_start;
+	}
+
+	gpmc->irq_chip.name = "gpmc";
+	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
+	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
+	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
+	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
+	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
+	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
+	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
+
+	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
+	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		gpmc->irq[i].irq = gpmc->irq_start + i;
+		irq_set_chip_and_handler(gpmc->irq[i].irq,
+					&gpmc->irq_chip, handle_simple_irq);
+		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
+		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
+	}
+
+	/* Disable interrupts */
+	gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+	/* clear interrupts */
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
+							"gpmc", gpmc);
+}
+
+static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
+{
+	u32 l;
+
+	l = gpmc_read_reg(GPMC_CONFIG);
+	if (gpmc->wp == true) {
+		l &= ~GPMC_CONFIG_WRITEPROTECT;
+		dev_info(gpmc->dev, "write protect enabled\n");
+	} else
+		l |= GPMC_CONFIG_WRITEPROTECT;
+	gpmc_write_reg(GPMC_CONFIG, l);
+}
+
+static __devinit int gpmc_probe(struct platform_device *pdev)
+{
+	u32 l;
+	int i;
+	int ret = 0;
+	struct resource *res = NULL;
+	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
+	struct gpmc_device_pdata **gdq = NULL;
+	struct gpmc_device *gd = NULL;
+
+	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
+	if (gpmc == NULL)
+		return -ENOMEM;
+
+	gpmc->dev = &pdev->dev;
+	gpmc->clk_prd = gp->clk_prd;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENOENT;
+
+	gpmc->phys_base = res->start;
+	gpmc->memsize = resource_size(res);
+
+	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
+	if (!gpmc->io_base)
+		return -EADDRNOTAVAIL;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL)
+		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
+	else
+		gpmc->master_irq = res->start;
+
+	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
+		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
+
+	gpmc->ecc_used = -EINVAL;
+	spin_lock_init(&gpmc->mem_lock);
+	platform_set_drvdata(pdev, gpmc);
+
+	l = gpmc_read_reg(GPMC_REVISION);
+	gpmc->revision = (l >> 4) & 0xf;
+	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
+
+	gpmc_mem_init();
+
+	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
+			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		ret = gpmc_setup_device(gpmc, gd, *gdq);
+		if (IS_ERR_VALUE(ret))
+			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
+								(*gdq)->name);
+		else
+			gd++;
+	}
+	gpmc->num_device = gd - gpmc->device;
+
+	gpmc_setup_writeprotect(gpmc);
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (IS_ERR(gpmc_create_device(gpmc, gd)))
+			dev_err(gpmc->dev, "device creation on %s failed\n",
+								gd->name);
+
+	return 0;
+}
+
+static __devexit int gpmc_free_irq(struct gpmc *gpmc)
+{
+	int i;
+
+	if (gpmc->master_irq)
+		free_irq(gpmc->master_irq, gpmc);
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		irq_set_handler(gpmc->irq[i].irq, NULL);
+		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
+		irq_set_chip_data(gpmc->irq[i].irq, NULL);
+		irq_modify_status(gpmc->irq[i].irq, 0, 0);
+	}
+
+	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
+
+	return 0;
+}
+
+static __devexit int gpmc_remove(struct platform_device *pdev)
+{
+	struct gpmc *gpmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	gpmc_free_irq(gpmc);
+
+	return 0;
+}
+
+static struct platform_driver gpmc_driver = {
+	.probe		= gpmc_probe,
+	.remove		= __devexit_p(gpmc_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpmc_driver);
+
 #ifdef CONFIG_ARCH_OMAP3
 static struct omap3_gpmc_regs gpmc_context;
 
@@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
 	unsigned int val;
 
 	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
+	if (gpmc->ecc_used != -EINVAL)
 		return -EINVAL;
 
-	gpmc_ecc_used = cs;
+	gpmc->ecc_used = cs;
 
 	/* clear ecc and enable bits */
 	val = ((0x00000001<<8) | 0x00000001);
@@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 {
 	unsigned int val = 0x0;
 
-	if (gpmc_ecc_used != cs)
+	if (gpmc->ecc_used != cs)
 		return -EINVAL;
 
 	/* read ecc result */
@@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
 	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
 
-	gpmc_ecc_used = -EINVAL;
+	gpmc->ecc_used = -EINVAL;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 1527929..2eedd99 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -11,6 +11,44 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+/* configuration flags */
+#define	GPMC_WRITEPROTECT		BIT(0)
+#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
+#define	GPMC_MUXADDDATA			BIT(2)
+#define	GPMC_DEVICETYPE_NOR		BIT(3)
+#define	GPMC_DEVICETYPE_NAND		BIT(4)
+#define	GPMC_DEVICESIZE_8		BIT(5)
+#define	GPMC_DEVICESIZE_16		BIT(6)
+#define	GPMC_WAIT_WRITE_MON		BIT(7)
+#define	GPMC_WAIT_READ_MON		BIT(8)
+#define	GPMC_PAGE_LEN_4			BIT(9)
+#define	GPMC_PAGE_LEN_8			BIT(10)
+#define	GPMC_PAGE_LEN_16		BIT(11)
+#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
+#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
+#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
+#define	GPMC_WRITETYPE_SYNC		BIT(15)
+#define	GPMC_WRITEMULTIPLE		BIT(16)
+#define	GPMC_READTYPE_SYNC		BIT(17)
+#define	GPMC_READMULTIPLE		BIT(18)
+#define	GPMC_WRAPBURST			BIT(19)
+#define	GPMC_WAITPIN_0			BIT(20)
+#define	GPMC_WAITPIN_1			BIT(21)
+#define	GPMC_WAITPIN_2			BIT(22)
+#define	GPMC_WAITPIN_3			BIT(23)
+#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
+					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
+#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
+#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
+#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
+					GPMC_WAITPIN_ACTIVE_HIGH)
+#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
+#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
+#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
+#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
+#define	GPMC_READTYPE_ASYNC		BIT(30)
+#define	GPMC_WRITETYPE_ASYNC		BIT(31)
+
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
@@ -56,7 +94,11 @@
 #define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
 #define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
 #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_1	(1 << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_2	(1 << 26)
 #define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_PAGE_LEN_16	(0x1 << 24)
+#define GPMC_CONFIG1_PAGE_LEN_8		(0x1 << 23)
 #define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
 #define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
 #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
@@ -73,8 +115,6 @@
 #define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
 #define GPMC_CONFIG7_CSVALID		(1 << 6)
 
-#define GPMC_DEVICETYPE_NOR		0
-#define GPMC_DEVICETYPE_NAND		2
 #define GPMC_CONFIG_WRITEPROTECT	0x00000010
 #define GPMC_STATUS_BUFF_EMPTY		0x00000001
 #define WR_RD_PIN_MONITORING		0x00600000
@@ -94,6 +134,16 @@ enum omap_ecc {
 	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
 };
 
+/* turn on/off type timings */
+struct gpmc_onoff_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+};
+
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
  * (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -126,11 +176,48 @@ struct gpmc_timings {
 	u16 rd_cycle;		/* Total read cycle time */
 	u16 wr_cycle;		/* Total write cycle time */
 
+	u16 cycle2cycle_delay;
+	u16 busturnaround;
+
 	/* The following are only on OMAP3430 */
 	u16 wr_access;		/* WRACCESSTIME */
 	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_onoff_timings control;
+};
+
+struct gpmc_cs_data {
+	unsigned		cs;
+	unsigned long		mem_size;
+	unsigned long		mem_offset;
+	/* some boards rely on bootloader for configuration */
+	bool			have_config;
+	unsigned		config;
+	struct gpmc_timings	*timing;
+	unsigned		irq_config;
+};
+
+struct gpmc_device_pdata {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	/* resources configured via GPMC will be created by GPMC driver */
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct gpmc_cs_data	*cs_data;
+	unsigned		num_cs;
 };
 
+struct gpmc_pdata {
+	/* GPMC_FCLK period in picoseconds */
+	unsigned long			clk_prd;
+	unsigned			num_device;
+	struct gpmc_device_pdata	**device_pdata;
+};
+
+extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
@@ -143,8 +230,6 @@ extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
 extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-01 12:19     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed, Jon Hunter, Vaibhav Hiremath

Convert GPMC code to driver. Boards using GPMC should provide driver
with type of configuration, timing, CS. Platform devices would then be
created for each connected peripheral (details also to be passed by
board so that it reaches respective driver). And GPMC driver would
populate memory resource details for the connected peripheral driver.
Boards should inform gpmc driver with platform data destined for
peripheral driver. gpmc driver will provide the same information to
peripheral driver.

A peripheral connected to GPMC can have multiple address spaces using
different chip select. Hence GPMC driver has been provided capability
to create platform device for peripheral using mutiple CS. The
peripheral that made it necessary was tusb6010.

Interrupts of GPMC are presented to drivers of connected peripherals
as resource. A fictitious interrupt controller chip handles these
interrupts at GPMC hardware level. Clients can use normal interrupt
APIs. Platform information of peripheral passed to GPMC driver should
indicate interrupts to be used via flags.

Driver is capable of configuring waitpin, waitpin details has to be
provided per CS. Wait pin has been considered as exclusive resource
as multiple peripherals should not using the same pin, at the same
it is valid for mutiple CS to use same waitpin provided they are
a part of single peripheral (eg. tusb6010)

An exported symbol for reconfiguring GPMC settings has been provided.
OneNAND is the one that neccessitated this.

Acquiring CS# for NAND is done on a few boards. It means, depending
on bootloader to embed this information. Probably CS# being used can
be set in the Kernel, and acquiring it can be removed. If ever this
capbility is needed, GPMC driver has to be made aware of handling it.

Modifications has been made keeping in mind that the driver would
have to move to driver folder. This explains requirement of clk_prd
field; even though clk_prd variable is not necessary as
gpmc_get_fclk_period is present in the same file as of now, this will
help in moving the driver easily to drivers folder.

Code related to GPMC clock may have to continue live in platform
folders as input clock is beyond the control of GPMC and calculating
timing for the peripheral may need other helpers. This explains
presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
both doing same work, latter meant to go with driver, former for
calculation in platform code.

Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
suggestions which resulted in improving the code.

Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
 2 files changed, 872 insertions(+), 98 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 580e684..12916f3 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -14,8 +14,11 @@
  */
 #undef DEBUG
 
+#include <linux/platform_device.h>
+
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -53,6 +56,45 @@
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
 
+/* GPMC register bits */
+#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
+#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
+#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
+#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
+#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
+#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
+#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
+
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
+#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
+#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
+
+#define	GPMC_WAITPIN_IDX0			0x0
+#define	GPMC_WAITPIN_IDX1			0x1
+#define	GPMC_WAITPIN_IDX2			0x2
+#define	GPMC_WAITPIN_IDX3			0x3
+#define	GPMC_NR_WAITPIN				0x4
+
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
 #define BOOT_ROM_SPACE		0x100000	/* 1MB */
@@ -64,6 +106,55 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+#define	DRIVER_NAME	"omap-gpmc"
+
+#define	GPMC_NR_IRQ		2
+
+#define	HIGH			1
+#define	LOW			-1
+
+struct gpmc_device {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct resource		*gpmc_res;
+	unsigned		gpmc_res_cnt;
+	bool			have_waitpin;
+	unsigned		waitpin;
+	int			waitpin_polarity;
+};
+
+struct gpmc_irq	{
+	unsigned		irq;
+	u32			bitmask;
+};
+
+struct gpmc {
+	struct device		*dev;
+	unsigned long		clk_prd;
+	void __iomem		*io_base;
+	unsigned long		phys_base;
+	u32			memsize;
+	unsigned		cs_map;
+	int			ecc_used;
+	spinlock_t		mem_lock;
+	struct resource		mem_root;
+	struct resource		cs_mem[GPMC_CS_NUM];
+	/* XXX: Or allocate dynamically ? */
+	struct gpmc_device	device[GPMC_CS_NUM];
+	unsigned		num_device;
+	unsigned		master_irq;
+	unsigned		irq_start;
+	struct gpmc_irq		irq[GPMC_NR_IRQ];
+	struct irq_chip		irq_chip;
+	bool			wp;
+	unsigned		waitpin_map;
+	unsigned		revision;
+};
+
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
-static struct resource	gpmc_mem_root;
-static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
-static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
-
-static void __iomem *gpmc_base;
-
 static struct clk *gpmc_l3_clk;
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+static struct gpmc *gpmc;
 
 static void gpmc_write_reg(int idx, u32 val)
 {
-	__raw_writel(val, gpmc_base + idx);
+	writel(val, gpmc->io_base + idx);
 }
 
 static u32 gpmc_read_reg(int idx)
 {
-	return __raw_readl(gpmc_base + idx);
+	return readl(gpmc->io_base + idx);
 }
 
 static void gpmc_cs_write_byte(int cs, int idx, u8 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writeb(val, reg_addr);
 }
 
 static u8 gpmc_cs_read_byte(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readb(reg_addr);
 }
 
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writel(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writel(val, reg_addr);
 }
 
 u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readl(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readl(reg_addr);
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
@@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 	if (time == 0)
 		ticks = 0;
 	else
-		ticks = gpmc_ns_to_ticks(time);
+		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
+
 	nr_bits = end_bit - st_bit + 1;
 	if (ticks >= 1 << nr_bits) {
 #ifdef DEBUG
@@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 #ifdef DEBUG
 	printk(KERN_INFO
 		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
-	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
 			(l >> st_bit) & mask, time);
 #endif
 	l &= ~(mask << st_bit);
@@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 		return -1
 #endif
 
+int gpmc_calc_divider(unsigned int sync_clk)
+{
+	int div;
+	u32 l;
+
+	l = sync_clk + (gpmc->clk_prd - 1);
+	div = l / gpmc->clk_prd;
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
 int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 {
 	int div;
@@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 	return div;
 }
 
+static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+	if (p->cs_extra_delay)
+		l |= GPMC_CONFIG2_CSEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+	if (p->adv_extra_delay)
+		l |= GPMC_CONFIG3_ADVEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+	if (p->oe_extra_delay)
+		l |= GPMC_CONFIG4_OEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
+	if (p->we_extra_delay)
+		l |= GPMC_CONFIG4_WEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
+	if (p->cycle2cyclesamecsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	if (p->cycle2cyclediffcsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
+}
+
 int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 {
 	int div;
 	u32 l;
 
-	div = gpmc_cs_calc_divider(cs, t->sync_clk);
+	div = gpmc_calc_divider(t->sync_clk);
 	if (div < 0)
 		return -1;
 
@@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
-	if (cpu_is_omap34xx()) {
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
+
+	if (gpmc->revision >= 5) {
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
 	}
@@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
 #ifdef DEBUG
 		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
-				cs, (div * gpmc_get_fclk_period()) / 1000, div);
+				cs, (div * gpmc->clk_prd) / 1000, div);
 #endif
 		l &= ~0x03;
 		l |= (div - 1);
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
 	}
 
+	gpmc_cs_onoff_timings(cs, &t->control);
+
 	return 0;
 }
 
@@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
 }
 
-static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
 {
 	u32 l;
 	u32 mask;
@@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
 	return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static int gpmc_cs_set_reserved(int cs, int reserved)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	gpmc_cs_map &= ~(1 << cs);
-	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+	gpmc->cs_map &= ~(1 << cs);
+	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
 
 	return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static int gpmc_cs_reserved(int cs)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	return gpmc_cs_map & (1 << cs);
+	return gpmc->cs_map & (1 << cs);
 }
 
 static unsigned long gpmc_mem_align(unsigned long size)
@@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
 	return size;
 }
 
-static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+static __devinit
+int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
 {
-	struct resource	*res = &gpmc_cs_mem[cs];
+	struct resource	*res = &gpmc->cs_mem[cs];
 	int r;
 
 	size = gpmc_mem_align(size);
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	res->start = base;
 	res->end = base + size - 1;
-	r = request_resource(&gpmc_mem_root, res);
-	spin_unlock(&gpmc_mem_lock);
+	r = request_resource(&gpmc->mem_root, res);
+	spin_unlock(&gpmc->mem_lock);
 
 	return r;
 }
 
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
-	struct resource *res = &gpmc_cs_mem[cs];
+	struct resource *res = &gpmc->cs_mem[cs];
 	int r = -1;
 
 	if (cs > GPMC_CS_NUM)
@@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (size > (1 << GPMC_SECTION_SHIFT))
 		return -ENOMEM;
 
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (gpmc_cs_reserved(cs)) {
 		r = -EBUSY;
 		goto out;
@@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (gpmc_cs_mem_enabled(cs))
 		r = adjust_resource(res, res->start & ~(size - 1), size);
 	if (r < 0)
-		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
 				      size, NULL, NULL);
 	if (r < 0)
 		goto out;
@@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	*base = res->start;
 	gpmc_cs_set_reserved(cs, 1);
 out:
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 	return r;
 }
 EXPORT_SYMBOL(gpmc_cs_request);
 
 void gpmc_cs_free(int cs)
 {
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
 		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
 		BUG();
-		spin_unlock(&gpmc_mem_lock);
+		spin_unlock(&gpmc->mem_lock);
 		return;
 	}
 	gpmc_cs_disable_mem(cs);
-	release_resource(&gpmc_cs_mem[cs]);
+	release_resource(&gpmc->cs_mem[cs]);
 	gpmc_cs_set_reserved(cs, 0);
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 }
 EXPORT_SYMBOL(gpmc_cs_free);
 
@@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
-static void __init gpmc_mem_init(void)
+static __devinit void gpmc_mem_init(void)
 {
 	int cs;
 	unsigned long boot_rom_space = 0;
@@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
 	/* In apollon the CS0 is mapped as 0x0000 0000 */
 	if (machine_is_omap_apollon())
 		boot_rom_space = 0;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
-	gpmc_mem_root.end = GPMC_MEM_END;
+	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc->mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
 	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
@@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	u32 l, irq;
-	int cs, ret = -EINVAL;
-	int gpmc_irq;
+	int ret = -EINVAL;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
 		ck = "core_l3_ck";
-		if (cpu_is_omap2420())
-			l = OMAP2420_GPMC_BASE;
-		else
-			l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
-		l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap44xx()) {
 		ck = "gpmc_ck";
-		l = OMAP44XX_GPMC_BASE;
-		gpmc_irq = OMAP44XX_IRQ_GPMC;
 	}
 
 	if (WARN_ON(!ck))
@@ -728,53 +863,607 @@ static int __init gpmc_init(void)
 		BUG();
 	}
 
-	gpmc_base = ioremap(l, SZ_4K);
-	if (!gpmc_base) {
-		clk_put(gpmc_l3_clk);
-		printk(KERN_ERR "Could not get GPMC register memory\n");
-		BUG();
+	clk_enable(gpmc_l3_clk);
+
+	return 0;
+}
+postcore_initcall(gpmc_init);
+
+static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
+{
+	return gpmc->waitpin_map & (0x1 << waitpin);
+}
+
+static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
+{
+	gpmc->waitpin_map &= ~(0x1 << waitpin);
+	gpmc->waitpin_map |= (0x1 << waitpin);
+}
+
+static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
+{
+	if (!(waitpin < GPMC_NR_WAITPIN))
+		return -ENODEV;
+
+	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
+		return -EBUSY;
+	else
+		gpmc_reserve_waitpin(gpmc, waitpin);
+
+	return 0;
+}
+
+static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
+{
+	int ret;
+
+	if (!gd->have_waitpin)
+		return 0;
+
+	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
+		return ret;
+	} else if (gd->waitpin_polarity) {
+		u32 l = gpmc_read_reg(GPMC_CONFIG);
+		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
+
+		if (gd->waitpin_polarity == HIGH)
+			l |= 1 << shift;
+		else
+			l &= ~(1 << shift);
+
+		gpmc_write_reg(GPMC_CONFIG, l);
 	}
+	return 0;
+}
 
-	clk_enable(gpmc_l3_clk);
+static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
+						unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+	unsigned idx = ~0x0;
+	int polarity = 0;
 
-	l = gpmc_read_reg(GPMC_REVISION);
-	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-	/* Set smart idle mode and automatic L3 clock gating */
-	l = gpmc_read_reg(GPMC_SYSCONFIG);
-	l &= 0x03 << 3;
-	l |= (0x02 << 3) | (1 << 0);
-	gpmc_write_reg(GPMC_SYSCONFIG, l);
-	gpmc_mem_init();
+	switch (conf & GPMC_WAITPIN_MASK) {
+	case GPMC_WAITPIN_0:
+		idx =  GPMC_WAITPIN_IDX0;
+		break;
+	case GPMC_WAITPIN_1:
+		idx =  GPMC_WAITPIN_IDX1;
+		break;
+	case GPMC_WAITPIN_2:
+		idx =  GPMC_WAITPIN_IDX2;
+		break;
+	case GPMC_WAITPIN_3:
+		idx =  GPMC_WAITPIN_IDX3;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
+		return -EINVAL;
+		break;
+	}
 
-	/* initalize the irq_chained */
-	irq = OMAP_GPMC_IRQ_BASE;
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-						handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-		irq++;
+	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
+	case GPMC_WAITPIN_ACTIVE_LOW:
+		polarity = LOW;
+		break;
+	case GPMC_WAITPIN_ACTIVE_HIGH:
+		polarity = HIGH;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
+		return -EINVAL;
+		break;
 	}
 
-	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
-	if (ret)
-		pr_err("gpmc: irq-%d could not claim: err %d\n",
-						gpmc_irq, ret);
-	return ret;
+	if (idx != ~0x0) {
+		if (gd->have_waitpin) {
+			if (gd->waitpin != idx ||
+					gd->waitpin_polarity != polarity) {
+				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
+					gd->waitpin, gd->waitpin_polarity,
+					gd->name, gd->id);
+				return -EBUSY;
+			}
+		} else {
+			gd->have_waitpin = true;
+			gd->waitpin = idx;
+			gd->waitpin_polarity = polarity;
+		}
+
+		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
+		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+	} else if (polarity) {
+		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
+							gd->name, gd->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
+		GPMC_CONFIG1_MUXADDDATA |
+		GPMC_CONFIG1_DEVICETYPE(~0) |
+		GPMC_CONFIG1_DEVICESIZE(~0) |
+		GPMC_CONFIG1_WAIT_WRITE_MON |
+		GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_PAGE_LEN(~0) |
+		GPMC_CONFIG1_WRITETYPE_SYNC |
+		GPMC_CONFIG1_WRITEMULTIPLE |
+		GPMC_CONFIG1_READTYPE_SYNC |
+		GPMC_CONFIG1_READMULTIPLE |
+		GPMC_CONFIG1_WRAPBURST |
+		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
+		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
+
+	if (conf & GPMC_TIMEPARAGRANULARITY)
+		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
+	if (conf & GPMC_MUXADDDATA)
+		l |= GPMC_CONFIG1_MUXADDDATA;
+	if (conf & GPMC_DEVICETYPE_NAND)
+		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
+	if (conf & GPMC_DEVICESIZE_16)
+		l |= GPMC_CONFIG1_DEVICESIZE_16;
+	if (conf & GPMC_WAIT_WRITE_MON)
+		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (conf & GPMC_WAIT_READ_MON)
+		l |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (conf & GPMC_PAGE_LEN_16)
+		l |= GPMC_CONFIG1_PAGE_LEN_16;
+	else if (conf & GPMC_PAGE_LEN_8)
+		l |= GPMC_CONFIG1_PAGE_LEN_8;
+	if (conf & GPMC_WRITETYPE_SYNC)
+		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (conf & GPMC_WRITEMULTIPLE)
+		l |= GPMC_CONFIG1_WRITEMULTIPLE;
+	if (conf & GPMC_READTYPE_SYNC)
+		l |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (conf & GPMC_READMULTIPLE)
+		l |= GPMC_CONFIG1_READMULTIPLE;
+	if (conf & GPMC_WRAPBURST)
+		l |= GPMC_CONFIG1_WRAPBURST;
+	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
+	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
+	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
+	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+	if (conf & GPMC_WRITEPROTECT)
+		gpmc->wp = true;
+}
+
+static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
+			struct gpmc_device *gd, struct gpmc_cs_data *cs)
+{
+	int ret;
+
+	/* some boards rely on bootloader for configuration */
+	if (cs->have_config) {
+		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
+		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
+
+	if (cs->timing) {
+		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
+
+	return 0;
+}
+
+static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
+{
+	int i;
+	struct gpmc_device *gd;
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (!strcmp(gd->name, name) && gd->id == id)
+			return i;
+
+	return -ENOENT;
+}
+
+int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
+{
+	int i;
+
+	i = gpmc_match_device(gpmc, name, id);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
+		return i;
+	}
+
+	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
+		return i;
+	}
+
+	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
+
+}
+EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
+
+static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
+{
+	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
+		return GPMC_IRQ_FIFOEVENTENABLE;
+	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
+		return GPMC_IRQ_COUNT_EVENT;
+	else
+		return 0;
+}
+
+static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
+		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
+			res[n].start = res[n].end = gpmc->irq[i].irq;
+			res[n].flags = IORESOURCE_IRQ;
+			dev_info(gpmc->dev, "irq %u on CS %d\n",
+						res[n].start, cs->cs);
+			n++;
+		}
+
+	return n;
+}
+
+static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	unsigned long start;
+	int ret;
+
+	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
+		return ret;
+	}
+
+	res->start = start + cs->mem_offset;
+	res->end = res->start + cs->mem_size - 1;
+	res->flags = IORESOURCE_MEM;
+
+	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
+							res->end, cs->cs);
+
+	return 1;
+}
+
+static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int num, ret;
+
+	num = gpmc_setup_cs_mem(gpmc, cs, res);
+	if (IS_ERR_VALUE(num))
+		return num;
+
+	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
+
+	return num;
+}
+
+static __devinit int gpmc_setup_device(struct gpmc *gpmc,
+		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
+{
+	int i, n, ret;
+	struct gpmc_cs_data *cs;
+
+	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
+				i < gdp->num_cs; i++, cs++)
+		n += hweight32(cs->irq_config);
+
+	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
+								GFP_KERNEL);
+	if (gd->gpmc_res == NULL) {
+		dev_err(gpmc->dev, "error: memory allocation\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
+			i < gdp->num_cs; cs++, i++) {
+		ret = gpmc_setup_cs(gpmc, gd, cs,
+					gd->gpmc_res + gd->gpmc_res_cnt);
+		if (IS_ERR_VALUE(ret) ||
+				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {
+			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
+			devm_kfree(gpmc->dev, gd->gpmc_res);
+			gd->gpmc_res = NULL;
+			gd->gpmc_res_cnt = 0;
+			return -EINVAL;
+		} else
+			gd->gpmc_res_cnt += ret;
+	}
+
+	gd->name = gdp->name;
+	gd->id = gdp->id;
+	gd->pdata = gdp->pdata;
+	gd->pdata_size = gdp->pdata_size;
+	gd->per_res = gdp->per_res;
+	gd->per_res_cnt = gdp->per_res_cnt;
+
+	return 0;
+}
+
+static __devinit
+struct platform_device *gpmc_create_device(struct gpmc *gpmc,
+					struct gpmc_device *p)
+{
+	int num = p->per_res_cnt + p->gpmc_res_cnt;
+	struct resource *res;
+	struct platform_device *pdev;
+
+	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
+								GFP_KERNEL);
+	if (!res) {
+		dev_err(gpmc->dev, "error: allocating memory\n");
+		return NULL;
+	}
+
+	memcpy((char *)res, (const char *) p->gpmc_res,
+				sizeof(struct resource) * p->gpmc_res_cnt);
+	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
+				sizeof(struct resource) * p->per_res_cnt);
+
+	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
+					res, num, p->pdata, p->pdata_size);
+
+	devm_kfree(gpmc->dev, res);
+
+	return pdev;
 }
-postcore_initcall(gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
-	u8 cs;
+	int i;
+	u32 regval;
+	struct gpmc *gpmc = dev;
+
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
 
-	/* check cs to invoke the irq */
-	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
-	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
-		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (regval & gpmc->irq[i].bitmask)
+			generic_handle_irq(gpmc->irq[i].irq);
+
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
 
 	return IRQ_HANDLED;
 }
 
+static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
+{
+	int i;
+	u32 regval;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (irq == gpmc->irq[i].irq) {
+			regval = gpmc_read_reg(GPMC_IRQENABLE);
+			if (endis)
+				regval |= gpmc->irq[i].bitmask;
+			else
+				regval &= ~gpmc->irq[i].bitmask;
+			gpmc_write_reg(GPMC_IRQENABLE, regval);
+			break;
+		}
+
+	return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
+{
+	int i;
+	u32 regval;
+
+	if (!gpmc->master_irq)
+		return -EINVAL;
+
+	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+	if (IS_ERR_VALUE(gpmc->irq_start)) {
+		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
+		return gpmc->irq_start;
+	}
+
+	gpmc->irq_chip.name = "gpmc";
+	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
+	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
+	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
+	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
+	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
+	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
+	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
+
+	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
+	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		gpmc->irq[i].irq = gpmc->irq_start + i;
+		irq_set_chip_and_handler(gpmc->irq[i].irq,
+					&gpmc->irq_chip, handle_simple_irq);
+		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
+		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
+	}
+
+	/* Disable interrupts */
+	gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+	/* clear interrupts */
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
+							"gpmc", gpmc);
+}
+
+static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
+{
+	u32 l;
+
+	l = gpmc_read_reg(GPMC_CONFIG);
+	if (gpmc->wp == true) {
+		l &= ~GPMC_CONFIG_WRITEPROTECT;
+		dev_info(gpmc->dev, "write protect enabled\n");
+	} else
+		l |= GPMC_CONFIG_WRITEPROTECT;
+	gpmc_write_reg(GPMC_CONFIG, l);
+}
+
+static __devinit int gpmc_probe(struct platform_device *pdev)
+{
+	u32 l;
+	int i;
+	int ret = 0;
+	struct resource *res = NULL;
+	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
+	struct gpmc_device_pdata **gdq = NULL;
+	struct gpmc_device *gd = NULL;
+
+	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
+	if (gpmc == NULL)
+		return -ENOMEM;
+
+	gpmc->dev = &pdev->dev;
+	gpmc->clk_prd = gp->clk_prd;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENOENT;
+
+	gpmc->phys_base = res->start;
+	gpmc->memsize = resource_size(res);
+
+	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
+	if (!gpmc->io_base)
+		return -EADDRNOTAVAIL;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL)
+		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
+	else
+		gpmc->master_irq = res->start;
+
+	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
+		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
+
+	gpmc->ecc_used = -EINVAL;
+	spin_lock_init(&gpmc->mem_lock);
+	platform_set_drvdata(pdev, gpmc);
+
+	l = gpmc_read_reg(GPMC_REVISION);
+	gpmc->revision = (l >> 4) & 0xf;
+	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
+
+	gpmc_mem_init();
+
+	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
+			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		ret = gpmc_setup_device(gpmc, gd, *gdq);
+		if (IS_ERR_VALUE(ret))
+			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
+								(*gdq)->name);
+		else
+			gd++;
+	}
+	gpmc->num_device = gd - gpmc->device;
+
+	gpmc_setup_writeprotect(gpmc);
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (IS_ERR(gpmc_create_device(gpmc, gd)))
+			dev_err(gpmc->dev, "device creation on %s failed\n",
+								gd->name);
+
+	return 0;
+}
+
+static __devexit int gpmc_free_irq(struct gpmc *gpmc)
+{
+	int i;
+
+	if (gpmc->master_irq)
+		free_irq(gpmc->master_irq, gpmc);
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		irq_set_handler(gpmc->irq[i].irq, NULL);
+		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
+		irq_set_chip_data(gpmc->irq[i].irq, NULL);
+		irq_modify_status(gpmc->irq[i].irq, 0, 0);
+	}
+
+	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
+
+	return 0;
+}
+
+static __devexit int gpmc_remove(struct platform_device *pdev)
+{
+	struct gpmc *gpmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	gpmc_free_irq(gpmc);
+
+	return 0;
+}
+
+static struct platform_driver gpmc_driver = {
+	.probe		= gpmc_probe,
+	.remove		= __devexit_p(gpmc_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpmc_driver);
+
 #ifdef CONFIG_ARCH_OMAP3
 static struct omap3_gpmc_regs gpmc_context;
 
@@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
 	unsigned int val;
 
 	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
+	if (gpmc->ecc_used != -EINVAL)
 		return -EINVAL;
 
-	gpmc_ecc_used = cs;
+	gpmc->ecc_used = cs;
 
 	/* clear ecc and enable bits */
 	val = ((0x00000001<<8) | 0x00000001);
@@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 {
 	unsigned int val = 0x0;
 
-	if (gpmc_ecc_used != cs)
+	if (gpmc->ecc_used != cs)
 		return -EINVAL;
 
 	/* read ecc result */
@@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
 	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
 
-	gpmc_ecc_used = -EINVAL;
+	gpmc->ecc_used = -EINVAL;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 1527929..2eedd99 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -11,6 +11,44 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+/* configuration flags */
+#define	GPMC_WRITEPROTECT		BIT(0)
+#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
+#define	GPMC_MUXADDDATA			BIT(2)
+#define	GPMC_DEVICETYPE_NOR		BIT(3)
+#define	GPMC_DEVICETYPE_NAND		BIT(4)
+#define	GPMC_DEVICESIZE_8		BIT(5)
+#define	GPMC_DEVICESIZE_16		BIT(6)
+#define	GPMC_WAIT_WRITE_MON		BIT(7)
+#define	GPMC_WAIT_READ_MON		BIT(8)
+#define	GPMC_PAGE_LEN_4			BIT(9)
+#define	GPMC_PAGE_LEN_8			BIT(10)
+#define	GPMC_PAGE_LEN_16		BIT(11)
+#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
+#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
+#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
+#define	GPMC_WRITETYPE_SYNC		BIT(15)
+#define	GPMC_WRITEMULTIPLE		BIT(16)
+#define	GPMC_READTYPE_SYNC		BIT(17)
+#define	GPMC_READMULTIPLE		BIT(18)
+#define	GPMC_WRAPBURST			BIT(19)
+#define	GPMC_WAITPIN_0			BIT(20)
+#define	GPMC_WAITPIN_1			BIT(21)
+#define	GPMC_WAITPIN_2			BIT(22)
+#define	GPMC_WAITPIN_3			BIT(23)
+#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
+					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
+#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
+#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
+#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
+					GPMC_WAITPIN_ACTIVE_HIGH)
+#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
+#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
+#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
+#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
+#define	GPMC_READTYPE_ASYNC		BIT(30)
+#define	GPMC_WRITETYPE_ASYNC		BIT(31)
+
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
@@ -56,7 +94,11 @@
 #define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
 #define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
 #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_1	(1 << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_2	(1 << 26)
 #define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_PAGE_LEN_16	(0x1 << 24)
+#define GPMC_CONFIG1_PAGE_LEN_8		(0x1 << 23)
 #define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
 #define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
 #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
@@ -73,8 +115,6 @@
 #define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
 #define GPMC_CONFIG7_CSVALID		(1 << 6)
 
-#define GPMC_DEVICETYPE_NOR		0
-#define GPMC_DEVICETYPE_NAND		2
 #define GPMC_CONFIG_WRITEPROTECT	0x00000010
 #define GPMC_STATUS_BUFF_EMPTY		0x00000001
 #define WR_RD_PIN_MONITORING		0x00600000
@@ -94,6 +134,16 @@ enum omap_ecc {
 	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
 };
 
+/* turn on/off type timings */
+struct gpmc_onoff_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+};
+
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
  * (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -126,11 +176,48 @@ struct gpmc_timings {
 	u16 rd_cycle;		/* Total read cycle time */
 	u16 wr_cycle;		/* Total write cycle time */
 
+	u16 cycle2cycle_delay;
+	u16 busturnaround;
+
 	/* The following are only on OMAP3430 */
 	u16 wr_access;		/* WRACCESSTIME */
 	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_onoff_timings control;
+};
+
+struct gpmc_cs_data {
+	unsigned		cs;
+	unsigned long		mem_size;
+	unsigned long		mem_offset;
+	/* some boards rely on bootloader for configuration */
+	bool			have_config;
+	unsigned		config;
+	struct gpmc_timings	*timing;
+	unsigned		irq_config;
+};
+
+struct gpmc_device_pdata {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	/* resources configured via GPMC will be created by GPMC driver */
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct gpmc_cs_data	*cs_data;
+	unsigned		num_cs;
 };
 
+struct gpmc_pdata {
+	/* GPMC_FCLK period in picoseconds */
+	unsigned long			clk_prd;
+	unsigned			num_device;
+	struct gpmc_device_pdata	**device_pdata;
+};
+
+extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
@@ -143,8 +230,6 @@ extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
 extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
-- 
1.7.10

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-01 12:19     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

Convert GPMC code to driver. Boards using GPMC should provide driver
with type of configuration, timing, CS. Platform devices would then be
created for each connected peripheral (details also to be passed by
board so that it reaches respective driver). And GPMC driver would
populate memory resource details for the connected peripheral driver.
Boards should inform gpmc driver with platform data destined for
peripheral driver. gpmc driver will provide the same information to
peripheral driver.

A peripheral connected to GPMC can have multiple address spaces using
different chip select. Hence GPMC driver has been provided capability
to create platform device for peripheral using mutiple CS. The
peripheral that made it necessary was tusb6010.

Interrupts of GPMC are presented to drivers of connected peripherals
as resource. A fictitious interrupt controller chip handles these
interrupts at GPMC hardware level. Clients can use normal interrupt
APIs. Platform information of peripheral passed to GPMC driver should
indicate interrupts to be used via flags.

Driver is capable of configuring waitpin, waitpin details has to be
provided per CS. Wait pin has been considered as exclusive resource
as multiple peripherals should not using the same pin, at the same
it is valid for mutiple CS to use same waitpin provided they are
a part of single peripheral (eg. tusb6010)

An exported symbol for reconfiguring GPMC settings has been provided.
OneNAND is the one that neccessitated this.

Acquiring CS# for NAND is done on a few boards. It means, depending
on bootloader to embed this information. Probably CS# being used can
be set in the Kernel, and acquiring it can be removed. If ever this
capbility is needed, GPMC driver has to be made aware of handling it.

Modifications has been made keeping in mind that the driver would
have to move to driver folder. This explains requirement of clk_prd
field; even though clk_prd variable is not necessary as
gpmc_get_fclk_period is present in the same file as of now, this will
help in moving the driver easily to drivers folder.

Code related to GPMC clock may have to continue live in platform
folders as input clock is beyond the control of GPMC and calculating
timing for the peripheral may need other helpers. This explains
presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
both doing same work, latter meant to go with driver, former for
calculation in platform code.

Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
suggestions which resulted in improving the code.

Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
 2 files changed, 872 insertions(+), 98 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 580e684..12916f3 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -14,8 +14,11 @@
  */
 #undef DEBUG
 
+#include <linux/platform_device.h>
+
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -53,6 +56,45 @@
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
 
+/* GPMC register bits */
+#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
+#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
+#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
+#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
+#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
+#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
+#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
+
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
+#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
+#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
+
+#define	GPMC_WAITPIN_IDX0			0x0
+#define	GPMC_WAITPIN_IDX1			0x1
+#define	GPMC_WAITPIN_IDX2			0x2
+#define	GPMC_WAITPIN_IDX3			0x3
+#define	GPMC_NR_WAITPIN				0x4
+
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
 #define BOOT_ROM_SPACE		0x100000	/* 1MB */
@@ -64,6 +106,55 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+#define	DRIVER_NAME	"omap-gpmc"
+
+#define	GPMC_NR_IRQ		2
+
+#define	HIGH			1
+#define	LOW			-1
+
+struct gpmc_device {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct resource		*gpmc_res;
+	unsigned		gpmc_res_cnt;
+	bool			have_waitpin;
+	unsigned		waitpin;
+	int			waitpin_polarity;
+};
+
+struct gpmc_irq	{
+	unsigned		irq;
+	u32			bitmask;
+};
+
+struct gpmc {
+	struct device		*dev;
+	unsigned long		clk_prd;
+	void __iomem		*io_base;
+	unsigned long		phys_base;
+	u32			memsize;
+	unsigned		cs_map;
+	int			ecc_used;
+	spinlock_t		mem_lock;
+	struct resource		mem_root;
+	struct resource		cs_mem[GPMC_CS_NUM];
+	/* XXX: Or allocate dynamically ? */
+	struct gpmc_device	device[GPMC_CS_NUM];
+	unsigned		num_device;
+	unsigned		master_irq;
+	unsigned		irq_start;
+	struct gpmc_irq		irq[GPMC_NR_IRQ];
+	struct irq_chip		irq_chip;
+	bool			wp;
+	unsigned		waitpin_map;
+	unsigned		revision;
+};
+
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
-static struct resource	gpmc_mem_root;
-static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
-static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
-
-static void __iomem *gpmc_base;
-
 static struct clk *gpmc_l3_clk;
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+static struct gpmc *gpmc;
 
 static void gpmc_write_reg(int idx, u32 val)
 {
-	__raw_writel(val, gpmc_base + idx);
+	writel(val, gpmc->io_base + idx);
 }
 
 static u32 gpmc_read_reg(int idx)
 {
-	return __raw_readl(gpmc_base + idx);
+	return readl(gpmc->io_base + idx);
 }
 
 static void gpmc_cs_write_byte(int cs, int idx, u8 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writeb(val, reg_addr);
 }
 
 static u8 gpmc_cs_read_byte(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readb(reg_addr);
 }
 
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writel(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writel(val, reg_addr);
 }
 
 u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readl(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readl(reg_addr);
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
@@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 	if (time == 0)
 		ticks = 0;
 	else
-		ticks = gpmc_ns_to_ticks(time);
+		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
+
 	nr_bits = end_bit - st_bit + 1;
 	if (ticks >= 1 << nr_bits) {
 #ifdef DEBUG
@@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 #ifdef DEBUG
 	printk(KERN_INFO
 		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
-	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
 			(l >> st_bit) & mask, time);
 #endif
 	l &= ~(mask << st_bit);
@@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 		return -1
 #endif
 
+int gpmc_calc_divider(unsigned int sync_clk)
+{
+	int div;
+	u32 l;
+
+	l = sync_clk + (gpmc->clk_prd - 1);
+	div = l / gpmc->clk_prd;
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
 int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 {
 	int div;
@@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 	return div;
 }
 
+static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+	if (p->cs_extra_delay)
+		l |= GPMC_CONFIG2_CSEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+	if (p->adv_extra_delay)
+		l |= GPMC_CONFIG3_ADVEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+	if (p->oe_extra_delay)
+		l |= GPMC_CONFIG4_OEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
+	if (p->we_extra_delay)
+		l |= GPMC_CONFIG4_WEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
+	if (p->cycle2cyclesamecsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	if (p->cycle2cyclediffcsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
+}
+
 int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 {
 	int div;
 	u32 l;
 
-	div = gpmc_cs_calc_divider(cs, t->sync_clk);
+	div = gpmc_calc_divider(t->sync_clk);
 	if (div < 0)
 		return -1;
 
@@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
-	if (cpu_is_omap34xx()) {
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
+
+	if (gpmc->revision >= 5) {
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
 	}
@@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
 #ifdef DEBUG
 		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
-				cs, (div * gpmc_get_fclk_period()) / 1000, div);
+				cs, (div * gpmc->clk_prd) / 1000, div);
 #endif
 		l &= ~0x03;
 		l |= (div - 1);
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
 	}
 
+	gpmc_cs_onoff_timings(cs, &t->control);
+
 	return 0;
 }
 
@@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
 }
 
-static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
 {
 	u32 l;
 	u32 mask;
@@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
 	return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static int gpmc_cs_set_reserved(int cs, int reserved)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	gpmc_cs_map &= ~(1 << cs);
-	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+	gpmc->cs_map &= ~(1 << cs);
+	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
 
 	return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static int gpmc_cs_reserved(int cs)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	return gpmc_cs_map & (1 << cs);
+	return gpmc->cs_map & (1 << cs);
 }
 
 static unsigned long gpmc_mem_align(unsigned long size)
@@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
 	return size;
 }
 
-static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+static __devinit
+int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
 {
-	struct resource	*res = &gpmc_cs_mem[cs];
+	struct resource	*res = &gpmc->cs_mem[cs];
 	int r;
 
 	size = gpmc_mem_align(size);
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	res->start = base;
 	res->end = base + size - 1;
-	r = request_resource(&gpmc_mem_root, res);
-	spin_unlock(&gpmc_mem_lock);
+	r = request_resource(&gpmc->mem_root, res);
+	spin_unlock(&gpmc->mem_lock);
 
 	return r;
 }
 
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
-	struct resource *res = &gpmc_cs_mem[cs];
+	struct resource *res = &gpmc->cs_mem[cs];
 	int r = -1;
 
 	if (cs > GPMC_CS_NUM)
@@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (size > (1 << GPMC_SECTION_SHIFT))
 		return -ENOMEM;
 
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (gpmc_cs_reserved(cs)) {
 		r = -EBUSY;
 		goto out;
@@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (gpmc_cs_mem_enabled(cs))
 		r = adjust_resource(res, res->start & ~(size - 1), size);
 	if (r < 0)
-		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
 				      size, NULL, NULL);
 	if (r < 0)
 		goto out;
@@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	*base = res->start;
 	gpmc_cs_set_reserved(cs, 1);
 out:
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 	return r;
 }
 EXPORT_SYMBOL(gpmc_cs_request);
 
 void gpmc_cs_free(int cs)
 {
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
 		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
 		BUG();
-		spin_unlock(&gpmc_mem_lock);
+		spin_unlock(&gpmc->mem_lock);
 		return;
 	}
 	gpmc_cs_disable_mem(cs);
-	release_resource(&gpmc_cs_mem[cs]);
+	release_resource(&gpmc->cs_mem[cs]);
 	gpmc_cs_set_reserved(cs, 0);
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 }
 EXPORT_SYMBOL(gpmc_cs_free);
 
@@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
-static void __init gpmc_mem_init(void)
+static __devinit void gpmc_mem_init(void)
 {
 	int cs;
 	unsigned long boot_rom_space = 0;
@@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
 	/* In apollon the CS0 is mapped as 0x0000 0000 */
 	if (machine_is_omap_apollon())
 		boot_rom_space = 0;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
-	gpmc_mem_root.end = GPMC_MEM_END;
+	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc->mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
 	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
@@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	u32 l, irq;
-	int cs, ret = -EINVAL;
-	int gpmc_irq;
+	int ret = -EINVAL;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
 		ck = "core_l3_ck";
-		if (cpu_is_omap2420())
-			l = OMAP2420_GPMC_BASE;
-		else
-			l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
-		l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap44xx()) {
 		ck = "gpmc_ck";
-		l = OMAP44XX_GPMC_BASE;
-		gpmc_irq = OMAP44XX_IRQ_GPMC;
 	}
 
 	if (WARN_ON(!ck))
@@ -728,53 +863,607 @@ static int __init gpmc_init(void)
 		BUG();
 	}
 
-	gpmc_base = ioremap(l, SZ_4K);
-	if (!gpmc_base) {
-		clk_put(gpmc_l3_clk);
-		printk(KERN_ERR "Could not get GPMC register memory\n");
-		BUG();
+	clk_enable(gpmc_l3_clk);
+
+	return 0;
+}
+postcore_initcall(gpmc_init);
+
+static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
+{
+	return gpmc->waitpin_map & (0x1 << waitpin);
+}
+
+static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
+{
+	gpmc->waitpin_map &= ~(0x1 << waitpin);
+	gpmc->waitpin_map |= (0x1 << waitpin);
+}
+
+static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
+{
+	if (!(waitpin < GPMC_NR_WAITPIN))
+		return -ENODEV;
+
+	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
+		return -EBUSY;
+	else
+		gpmc_reserve_waitpin(gpmc, waitpin);
+
+	return 0;
+}
+
+static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
+{
+	int ret;
+
+	if (!gd->have_waitpin)
+		return 0;
+
+	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
+		return ret;
+	} else if (gd->waitpin_polarity) {
+		u32 l = gpmc_read_reg(GPMC_CONFIG);
+		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
+
+		if (gd->waitpin_polarity == HIGH)
+			l |= 1 << shift;
+		else
+			l &= ~(1 << shift);
+
+		gpmc_write_reg(GPMC_CONFIG, l);
 	}
+	return 0;
+}
 
-	clk_enable(gpmc_l3_clk);
+static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
+						unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+	unsigned idx = ~0x0;
+	int polarity = 0;
 
-	l = gpmc_read_reg(GPMC_REVISION);
-	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-	/* Set smart idle mode and automatic L3 clock gating */
-	l = gpmc_read_reg(GPMC_SYSCONFIG);
-	l &= 0x03 << 3;
-	l |= (0x02 << 3) | (1 << 0);
-	gpmc_write_reg(GPMC_SYSCONFIG, l);
-	gpmc_mem_init();
+	switch (conf & GPMC_WAITPIN_MASK) {
+	case GPMC_WAITPIN_0:
+		idx =  GPMC_WAITPIN_IDX0;
+		break;
+	case GPMC_WAITPIN_1:
+		idx =  GPMC_WAITPIN_IDX1;
+		break;
+	case GPMC_WAITPIN_2:
+		idx =  GPMC_WAITPIN_IDX2;
+		break;
+	case GPMC_WAITPIN_3:
+		idx =  GPMC_WAITPIN_IDX3;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
+		return -EINVAL;
+		break;
+	}
 
-	/* initalize the irq_chained */
-	irq = OMAP_GPMC_IRQ_BASE;
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-						handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-		irq++;
+	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
+	case GPMC_WAITPIN_ACTIVE_LOW:
+		polarity = LOW;
+		break;
+	case GPMC_WAITPIN_ACTIVE_HIGH:
+		polarity = HIGH;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
+		return -EINVAL;
+		break;
 	}
 
-	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
-	if (ret)
-		pr_err("gpmc: irq-%d could not claim: err %d\n",
-						gpmc_irq, ret);
-	return ret;
+	if (idx != ~0x0) {
+		if (gd->have_waitpin) {
+			if (gd->waitpin != idx ||
+					gd->waitpin_polarity != polarity) {
+				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
+					gd->waitpin, gd->waitpin_polarity,
+					gd->name, gd->id);
+				return -EBUSY;
+			}
+		} else {
+			gd->have_waitpin = true;
+			gd->waitpin = idx;
+			gd->waitpin_polarity = polarity;
+		}
+
+		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
+		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+	} else if (polarity) {
+		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
+							gd->name, gd->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
+		GPMC_CONFIG1_MUXADDDATA |
+		GPMC_CONFIG1_DEVICETYPE(~0) |
+		GPMC_CONFIG1_DEVICESIZE(~0) |
+		GPMC_CONFIG1_WAIT_WRITE_MON |
+		GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_PAGE_LEN(~0) |
+		GPMC_CONFIG1_WRITETYPE_SYNC |
+		GPMC_CONFIG1_WRITEMULTIPLE |
+		GPMC_CONFIG1_READTYPE_SYNC |
+		GPMC_CONFIG1_READMULTIPLE |
+		GPMC_CONFIG1_WRAPBURST |
+		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
+		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
+
+	if (conf & GPMC_TIMEPARAGRANULARITY)
+		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
+	if (conf & GPMC_MUXADDDATA)
+		l |= GPMC_CONFIG1_MUXADDDATA;
+	if (conf & GPMC_DEVICETYPE_NAND)
+		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
+	if (conf & GPMC_DEVICESIZE_16)
+		l |= GPMC_CONFIG1_DEVICESIZE_16;
+	if (conf & GPMC_WAIT_WRITE_MON)
+		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (conf & GPMC_WAIT_READ_MON)
+		l |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (conf & GPMC_PAGE_LEN_16)
+		l |= GPMC_CONFIG1_PAGE_LEN_16;
+	else if (conf & GPMC_PAGE_LEN_8)
+		l |= GPMC_CONFIG1_PAGE_LEN_8;
+	if (conf & GPMC_WRITETYPE_SYNC)
+		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (conf & GPMC_WRITEMULTIPLE)
+		l |= GPMC_CONFIG1_WRITEMULTIPLE;
+	if (conf & GPMC_READTYPE_SYNC)
+		l |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (conf & GPMC_READMULTIPLE)
+		l |= GPMC_CONFIG1_READMULTIPLE;
+	if (conf & GPMC_WRAPBURST)
+		l |= GPMC_CONFIG1_WRAPBURST;
+	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
+	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
+	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
+	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+	if (conf & GPMC_WRITEPROTECT)
+		gpmc->wp = true;
+}
+
+static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
+			struct gpmc_device *gd, struct gpmc_cs_data *cs)
+{
+	int ret;
+
+	/* some boards rely on bootloader for configuration */
+	if (cs->have_config) {
+		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
+		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
+
+	if (cs->timing) {
+		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
+
+	return 0;
+}
+
+static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
+{
+	int i;
+	struct gpmc_device *gd;
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (!strcmp(gd->name, name) && gd->id == id)
+			return i;
+
+	return -ENOENT;
+}
+
+int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
+{
+	int i;
+
+	i = gpmc_match_device(gpmc, name, id);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
+		return i;
+	}
+
+	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
+		return i;
+	}
+
+	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
+
+}
+EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
+
+static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
+{
+	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
+		return GPMC_IRQ_FIFOEVENTENABLE;
+	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
+		return GPMC_IRQ_COUNT_EVENT;
+	else
+		return 0;
+}
+
+static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
+		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
+			res[n].start = res[n].end = gpmc->irq[i].irq;
+			res[n].flags = IORESOURCE_IRQ;
+			dev_info(gpmc->dev, "irq %u on CS %d\n",
+						res[n].start, cs->cs);
+			n++;
+		}
+
+	return n;
+}
+
+static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	unsigned long start;
+	int ret;
+
+	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
+		return ret;
+	}
+
+	res->start = start + cs->mem_offset;
+	res->end = res->start + cs->mem_size - 1;
+	res->flags = IORESOURCE_MEM;
+
+	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
+							res->end, cs->cs);
+
+	return 1;
+}
+
+static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int num, ret;
+
+	num = gpmc_setup_cs_mem(gpmc, cs, res);
+	if (IS_ERR_VALUE(num))
+		return num;
+
+	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
+
+	return num;
+}
+
+static __devinit int gpmc_setup_device(struct gpmc *gpmc,
+		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
+{
+	int i, n, ret;
+	struct gpmc_cs_data *cs;
+
+	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
+				i < gdp->num_cs; i++, cs++)
+		n += hweight32(cs->irq_config);
+
+	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
+								GFP_KERNEL);
+	if (gd->gpmc_res == NULL) {
+		dev_err(gpmc->dev, "error: memory allocation\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
+			i < gdp->num_cs; cs++, i++) {
+		ret = gpmc_setup_cs(gpmc, gd, cs,
+					gd->gpmc_res + gd->gpmc_res_cnt);
+		if (IS_ERR_VALUE(ret) ||
+				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {
+			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
+			devm_kfree(gpmc->dev, gd->gpmc_res);
+			gd->gpmc_res = NULL;
+			gd->gpmc_res_cnt = 0;
+			return -EINVAL;
+		} else
+			gd->gpmc_res_cnt += ret;
+	}
+
+	gd->name = gdp->name;
+	gd->id = gdp->id;
+	gd->pdata = gdp->pdata;
+	gd->pdata_size = gdp->pdata_size;
+	gd->per_res = gdp->per_res;
+	gd->per_res_cnt = gdp->per_res_cnt;
+
+	return 0;
+}
+
+static __devinit
+struct platform_device *gpmc_create_device(struct gpmc *gpmc,
+					struct gpmc_device *p)
+{
+	int num = p->per_res_cnt + p->gpmc_res_cnt;
+	struct resource *res;
+	struct platform_device *pdev;
+
+	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
+								GFP_KERNEL);
+	if (!res) {
+		dev_err(gpmc->dev, "error: allocating memory\n");
+		return NULL;
+	}
+
+	memcpy((char *)res, (const char *) p->gpmc_res,
+				sizeof(struct resource) * p->gpmc_res_cnt);
+	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
+				sizeof(struct resource) * p->per_res_cnt);
+
+	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
+					res, num, p->pdata, p->pdata_size);
+
+	devm_kfree(gpmc->dev, res);
+
+	return pdev;
 }
-postcore_initcall(gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
-	u8 cs;
+	int i;
+	u32 regval;
+	struct gpmc *gpmc = dev;
+
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
 
-	/* check cs to invoke the irq */
-	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
-	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
-		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (regval & gpmc->irq[i].bitmask)
+			generic_handle_irq(gpmc->irq[i].irq);
+
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
 
 	return IRQ_HANDLED;
 }
 
+static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
+{
+	int i;
+	u32 regval;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (irq == gpmc->irq[i].irq) {
+			regval = gpmc_read_reg(GPMC_IRQENABLE);
+			if (endis)
+				regval |= gpmc->irq[i].bitmask;
+			else
+				regval &= ~gpmc->irq[i].bitmask;
+			gpmc_write_reg(GPMC_IRQENABLE, regval);
+			break;
+		}
+
+	return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
+{
+	int i;
+	u32 regval;
+
+	if (!gpmc->master_irq)
+		return -EINVAL;
+
+	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+	if (IS_ERR_VALUE(gpmc->irq_start)) {
+		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
+		return gpmc->irq_start;
+	}
+
+	gpmc->irq_chip.name = "gpmc";
+	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
+	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
+	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
+	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
+	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
+	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
+	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
+
+	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
+	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		gpmc->irq[i].irq = gpmc->irq_start + i;
+		irq_set_chip_and_handler(gpmc->irq[i].irq,
+					&gpmc->irq_chip, handle_simple_irq);
+		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
+		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
+	}
+
+	/* Disable interrupts */
+	gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+	/* clear interrupts */
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
+							"gpmc", gpmc);
+}
+
+static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
+{
+	u32 l;
+
+	l = gpmc_read_reg(GPMC_CONFIG);
+	if (gpmc->wp == true) {
+		l &= ~GPMC_CONFIG_WRITEPROTECT;
+		dev_info(gpmc->dev, "write protect enabled\n");
+	} else
+		l |= GPMC_CONFIG_WRITEPROTECT;
+	gpmc_write_reg(GPMC_CONFIG, l);
+}
+
+static __devinit int gpmc_probe(struct platform_device *pdev)
+{
+	u32 l;
+	int i;
+	int ret = 0;
+	struct resource *res = NULL;
+	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
+	struct gpmc_device_pdata **gdq = NULL;
+	struct gpmc_device *gd = NULL;
+
+	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
+	if (gpmc == NULL)
+		return -ENOMEM;
+
+	gpmc->dev = &pdev->dev;
+	gpmc->clk_prd = gp->clk_prd;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENOENT;
+
+	gpmc->phys_base = res->start;
+	gpmc->memsize = resource_size(res);
+
+	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
+	if (!gpmc->io_base)
+		return -EADDRNOTAVAIL;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL)
+		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
+	else
+		gpmc->master_irq = res->start;
+
+	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
+		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
+
+	gpmc->ecc_used = -EINVAL;
+	spin_lock_init(&gpmc->mem_lock);
+	platform_set_drvdata(pdev, gpmc);
+
+	l = gpmc_read_reg(GPMC_REVISION);
+	gpmc->revision = (l >> 4) & 0xf;
+	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
+
+	gpmc_mem_init();
+
+	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
+			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		ret = gpmc_setup_device(gpmc, gd, *gdq);
+		if (IS_ERR_VALUE(ret))
+			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
+								(*gdq)->name);
+		else
+			gd++;
+	}
+	gpmc->num_device = gd - gpmc->device;
+
+	gpmc_setup_writeprotect(gpmc);
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (IS_ERR(gpmc_create_device(gpmc, gd)))
+			dev_err(gpmc->dev, "device creation on %s failed\n",
+								gd->name);
+
+	return 0;
+}
+
+static __devexit int gpmc_free_irq(struct gpmc *gpmc)
+{
+	int i;
+
+	if (gpmc->master_irq)
+		free_irq(gpmc->master_irq, gpmc);
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		irq_set_handler(gpmc->irq[i].irq, NULL);
+		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
+		irq_set_chip_data(gpmc->irq[i].irq, NULL);
+		irq_modify_status(gpmc->irq[i].irq, 0, 0);
+	}
+
+	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
+
+	return 0;
+}
+
+static __devexit int gpmc_remove(struct platform_device *pdev)
+{
+	struct gpmc *gpmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	gpmc_free_irq(gpmc);
+
+	return 0;
+}
+
+static struct platform_driver gpmc_driver = {
+	.probe		= gpmc_probe,
+	.remove		= __devexit_p(gpmc_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpmc_driver);
+
 #ifdef CONFIG_ARCH_OMAP3
 static struct omap3_gpmc_regs gpmc_context;
 
@@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
 	unsigned int val;
 
 	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
+	if (gpmc->ecc_used != -EINVAL)
 		return -EINVAL;
 
-	gpmc_ecc_used = cs;
+	gpmc->ecc_used = cs;
 
 	/* clear ecc and enable bits */
 	val = ((0x00000001<<8) | 0x00000001);
@@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 {
 	unsigned int val = 0x0;
 
-	if (gpmc_ecc_used != cs)
+	if (gpmc->ecc_used != cs)
 		return -EINVAL;
 
 	/* read ecc result */
@@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
 	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
 
-	gpmc_ecc_used = -EINVAL;
+	gpmc->ecc_used = -EINVAL;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 1527929..2eedd99 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -11,6 +11,44 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+/* configuration flags */
+#define	GPMC_WRITEPROTECT		BIT(0)
+#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
+#define	GPMC_MUXADDDATA			BIT(2)
+#define	GPMC_DEVICETYPE_NOR		BIT(3)
+#define	GPMC_DEVICETYPE_NAND		BIT(4)
+#define	GPMC_DEVICESIZE_8		BIT(5)
+#define	GPMC_DEVICESIZE_16		BIT(6)
+#define	GPMC_WAIT_WRITE_MON		BIT(7)
+#define	GPMC_WAIT_READ_MON		BIT(8)
+#define	GPMC_PAGE_LEN_4			BIT(9)
+#define	GPMC_PAGE_LEN_8			BIT(10)
+#define	GPMC_PAGE_LEN_16		BIT(11)
+#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
+#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
+#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
+#define	GPMC_WRITETYPE_SYNC		BIT(15)
+#define	GPMC_WRITEMULTIPLE		BIT(16)
+#define	GPMC_READTYPE_SYNC		BIT(17)
+#define	GPMC_READMULTIPLE		BIT(18)
+#define	GPMC_WRAPBURST			BIT(19)
+#define	GPMC_WAITPIN_0			BIT(20)
+#define	GPMC_WAITPIN_1			BIT(21)
+#define	GPMC_WAITPIN_2			BIT(22)
+#define	GPMC_WAITPIN_3			BIT(23)
+#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
+					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
+#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
+#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
+#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
+					GPMC_WAITPIN_ACTIVE_HIGH)
+#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
+#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
+#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
+#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
+#define	GPMC_READTYPE_ASYNC		BIT(30)
+#define	GPMC_WRITETYPE_ASYNC		BIT(31)
+
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
@@ -56,7 +94,11 @@
 #define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
 #define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
 #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_1	(1 << 25)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_2	(1 << 26)
 #define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_PAGE_LEN_16	(0x1 << 24)
+#define GPMC_CONFIG1_PAGE_LEN_8		(0x1 << 23)
 #define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
 #define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
 #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
@@ -73,8 +115,6 @@
 #define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
 #define GPMC_CONFIG7_CSVALID		(1 << 6)
 
-#define GPMC_DEVICETYPE_NOR		0
-#define GPMC_DEVICETYPE_NAND		2
 #define GPMC_CONFIG_WRITEPROTECT	0x00000010
 #define GPMC_STATUS_BUFF_EMPTY		0x00000001
 #define WR_RD_PIN_MONITORING		0x00600000
@@ -94,6 +134,16 @@ enum omap_ecc {
 	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
 };
 
+/* turn on/off type timings */
+struct gpmc_onoff_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+};
+
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
  * (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -126,11 +176,48 @@ struct gpmc_timings {
 	u16 rd_cycle;		/* Total read cycle time */
 	u16 wr_cycle;		/* Total write cycle time */
 
+	u16 cycle2cycle_delay;
+	u16 busturnaround;
+
 	/* The following are only on OMAP3430 */
 	u16 wr_access;		/* WRACCESSTIME */
 	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_onoff_timings control;
+};
+
+struct gpmc_cs_data {
+	unsigned		cs;
+	unsigned long		mem_size;
+	unsigned long		mem_offset;
+	/* some boards rely on bootloader for configuration */
+	bool			have_config;
+	unsigned		config;
+	struct gpmc_timings	*timing;
+	unsigned		irq_config;
+};
+
+struct gpmc_device_pdata {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	/* resources configured via GPMC will be created by GPMC driver */
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct gpmc_cs_data	*cs_data;
+	unsigned		num_cs;
 };
 
+struct gpmc_pdata {
+	/* GPMC_FCLK period in picoseconds */
+	unsigned long			clk_prd;
+	unsigned			num_device;
+	struct gpmc_device_pdata	**device_pdata;
+};
+
+extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
@@ -143,8 +230,6 @@ extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
 extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
-- 
1.7.10

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:19   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Create API for platforms to adapt gpmc to HWMOD

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
 arch/arm/plat-omap/include/plat/gpmc.h |    1 +
 2 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 12916f3..c8d07bb 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -33,6 +33,8 @@
 
 #include <plat/sdrc.h>
 
+#include <plat/omap_device.h>
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+int __init omap_init_gpmc(struct gpmc_pdata *pdata)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	char *name = "omap-gpmc";
+	char *oh_name = "gpmc";
+
+	pdata->clk_prd = gpmc_get_fclk_period();
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
+
+	pdev = omap_device_build(name, -1, oh, pdata,
+					sizeof(*pdata), NULL, 0, 0);
+	if (IS_ERR(pdev)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 			       int time, const char *name)
@@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	int ret = -EINVAL;
-	char *ck = NULL;
-
-	if (cpu_is_omap24xx()) {
-		ck = "core_l3_ck";
-	} else if (cpu_is_omap34xx()) {
-		ck = "gpmc_fck";
-	} else if (cpu_is_omap44xx()) {
-		ck = "gpmc_ck";
-	}
+	char *oh_name = "gpmc";
+	struct omap_hwmod *oh;
 
-	if (WARN_ON(!ck))
-		return ret;
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-	gpmc_l3_clk = clk_get(NULL, ck);
+	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
 	if (IS_ERR(gpmc_l3_clk)) {
-		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-		BUG();
+		pr_err("error: clk_get on %s\n", oh->main_clk);
+		return -EINVAL;
 	}
 
 	clk_enable(gpmc_l3_clk);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 2eedd99..c5cf020 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -217,6 +217,7 @@ struct gpmc_pdata {
 };
 
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
-- 
1.7.10


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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-01 12:19   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Create API for platforms to adapt gpmc to HWMOD

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
 arch/arm/plat-omap/include/plat/gpmc.h |    1 +
 2 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 12916f3..c8d07bb 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -33,6 +33,8 @@
 
 #include <plat/sdrc.h>
 
+#include <plat/omap_device.h>
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+int __init omap_init_gpmc(struct gpmc_pdata *pdata)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	char *name = "omap-gpmc";
+	char *oh_name = "gpmc";
+
+	pdata->clk_prd = gpmc_get_fclk_period();
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
+
+	pdev = omap_device_build(name, -1, oh, pdata,
+					sizeof(*pdata), NULL, 0, 0);
+	if (IS_ERR(pdev)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 			       int time, const char *name)
@@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	int ret = -EINVAL;
-	char *ck = NULL;
-
-	if (cpu_is_omap24xx()) {
-		ck = "core_l3_ck";
-	} else if (cpu_is_omap34xx()) {
-		ck = "gpmc_fck";
-	} else if (cpu_is_omap44xx()) {
-		ck = "gpmc_ck";
-	}
+	char *oh_name = "gpmc";
+	struct omap_hwmod *oh;
 
-	if (WARN_ON(!ck))
-		return ret;
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-	gpmc_l3_clk = clk_get(NULL, ck);
+	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
 	if (IS_ERR(gpmc_l3_clk)) {
-		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-		BUG();
+		pr_err("error: clk_get on %s\n", oh->main_clk);
+		return -EINVAL;
 	}
 
 	clk_enable(gpmc_l3_clk);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 2eedd99..c5cf020 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -217,6 +217,7 @@ struct gpmc_pdata {
 };
 
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
-- 
1.7.10

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-01 12:19   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

Create API for platforms to adapt gpmc to HWMOD

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
 arch/arm/plat-omap/include/plat/gpmc.h |    1 +
 2 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 12916f3..c8d07bb 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -33,6 +33,8 @@
 
 #include <plat/sdrc.h>
 
+#include <plat/omap_device.h>
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+int __init omap_init_gpmc(struct gpmc_pdata *pdata)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	char *name = "omap-gpmc";
+	char *oh_name = "gpmc";
+
+	pdata->clk_prd = gpmc_get_fclk_period();
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
+
+	pdev = omap_device_build(name, -1, oh, pdata,
+					sizeof(*pdata), NULL, 0, 0);
+	if (IS_ERR(pdev)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 			       int time, const char *name)
@@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	int ret = -EINVAL;
-	char *ck = NULL;
-
-	if (cpu_is_omap24xx()) {
-		ck = "core_l3_ck";
-	} else if (cpu_is_omap34xx()) {
-		ck = "gpmc_fck";
-	} else if (cpu_is_omap44xx()) {
-		ck = "gpmc_ck";
-	}
+	char *oh_name = "gpmc";
+	struct omap_hwmod *oh;
 
-	if (WARN_ON(!ck))
-		return ret;
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-	gpmc_l3_clk = clk_get(NULL, ck);
+	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
 	if (IS_ERR(gpmc_l3_clk)) {
-		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-		BUG();
+		pr_err("error: clk_get on %s\n", oh->main_clk);
+		return -EINVAL;
 	}
 
 	clk_enable(gpmc_l3_clk);
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 2eedd99..c5cf020 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -217,6 +217,7 @@ struct gpmc_pdata {
 };
 
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
-- 
1.7.10

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

* [PATCH v4 03/39] ARM: OMAP2+: gpmc: register details for nand driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:19     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

If peripheral connected is NAND, update NAND drivers platform data
with NAND related register addresses so that NAND driver can handle
GPMC NAND operations by itself

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/gpmc.c             |   25 +++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc.h |   16 ++++++++++++++++
 arch/arm/plat-omap/include/plat/nand.h |    1 +
 3 files changed, 42 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index c8d07bb..657ce95 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -30,6 +30,7 @@
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
+#include <plat/nand.h>
 
 #include <plat/sdrc.h>
 
@@ -891,6 +892,28 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
+				struct omap_nand_platform_data *nand)
+{
+	int cs = nand->cs;
+
+	nand->reg.gpmc_status = gpmc->io_base + GPMC_STATUS;
+	nand->reg.gpmc_nand_command = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_address = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_data = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_prefetch_config1 = gpmc->io_base + GPMC_PREFETCH_CONFIG1;
+	nand->reg.gpmc_prefetch_config2 = gpmc->io_base + GPMC_PREFETCH_CONFIG2;
+	nand->reg.gpmc_prefetch_control = gpmc->io_base + GPMC_PREFETCH_CONTROL;
+	nand->reg.gpmc_prefetch_status = gpmc->io_base + GPMC_PREFETCH_STATUS;
+	nand->reg.gpmc_ecc_config = gpmc->io_base + GPMC_ECC_CONFIG;
+	nand->reg.gpmc_ecc_control = gpmc->io_base + GPMC_ECC_CONTROL;
+	nand->reg.gpmc_ecc_size_config = gpmc->io_base + GPMC_ECC_SIZE_CONFIG;
+	nand->reg.gpmc_ecc1_result = gpmc->io_base + GPMC_ECC1_RESULT;
+}
+
 static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
 {
 	return gpmc->waitpin_map & (0x1 << waitpin);
@@ -1427,6 +1450,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		if ((*gdq)->is_nand)
+			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index c5cf020..976a8f0 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -207,6 +207,7 @@ struct gpmc_device_pdata {
 	unsigned		per_res_cnt;
 	struct gpmc_cs_data	*cs_data;
 	unsigned		num_cs;
+	bool			is_nand;
 };
 
 struct gpmc_pdata {
@@ -216,6 +217,21 @@ struct gpmc_pdata {
 	struct gpmc_device_pdata	**device_pdata;
 };
 
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+};
+
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
 extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 67fc506..86e4d9c 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -29,6 +29,7 @@ struct omap_nand_platform_data {
 	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
+	struct gpmc_nand_regs	reg;
 };
 
 /* minimum size for IO mapping */
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 03/39] ARM: OMAP2+: gpmc: register details for nand driver
@ 2012-05-01 12:19     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

If peripheral connected is NAND, update NAND drivers platform data
with NAND related register addresses so that NAND driver can handle
GPMC NAND operations by itself

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |   25 +++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc.h |   16 ++++++++++++++++
 arch/arm/plat-omap/include/plat/nand.h |    1 +
 3 files changed, 42 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index c8d07bb..657ce95 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -30,6 +30,7 @@
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
+#include <plat/nand.h>
 
 #include <plat/sdrc.h>
 
@@ -891,6 +892,28 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
+				struct omap_nand_platform_data *nand)
+{
+	int cs = nand->cs;
+
+	nand->reg.gpmc_status = gpmc->io_base + GPMC_STATUS;
+	nand->reg.gpmc_nand_command = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_address = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_data = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_prefetch_config1 = gpmc->io_base + GPMC_PREFETCH_CONFIG1;
+	nand->reg.gpmc_prefetch_config2 = gpmc->io_base + GPMC_PREFETCH_CONFIG2;
+	nand->reg.gpmc_prefetch_control = gpmc->io_base + GPMC_PREFETCH_CONTROL;
+	nand->reg.gpmc_prefetch_status = gpmc->io_base + GPMC_PREFETCH_STATUS;
+	nand->reg.gpmc_ecc_config = gpmc->io_base + GPMC_ECC_CONFIG;
+	nand->reg.gpmc_ecc_control = gpmc->io_base + GPMC_ECC_CONTROL;
+	nand->reg.gpmc_ecc_size_config = gpmc->io_base + GPMC_ECC_SIZE_CONFIG;
+	nand->reg.gpmc_ecc1_result = gpmc->io_base + GPMC_ECC1_RESULT;
+}
+
 static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
 {
 	return gpmc->waitpin_map & (0x1 << waitpin);
@@ -1427,6 +1450,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		if ((*gdq)->is_nand)
+			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index c5cf020..976a8f0 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -207,6 +207,7 @@ struct gpmc_device_pdata {
 	unsigned		per_res_cnt;
 	struct gpmc_cs_data	*cs_data;
 	unsigned		num_cs;
+	bool			is_nand;
 };
 
 struct gpmc_pdata {
@@ -216,6 +217,21 @@ struct gpmc_pdata {
 	struct gpmc_device_pdata	**device_pdata;
 };
 
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+};
+
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
 extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 67fc506..86e4d9c 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -29,6 +29,7 @@ struct omap_nand_platform_data {
 	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
+	struct gpmc_nand_regs	reg;
 };
 
 /* minimum size for IO mapping */
-- 
1.7.10

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

* [PATCH v4 03/39] ARM: OMAP2+: gpmc: register details for nand driver
@ 2012-05-01 12:19     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

If peripheral connected is NAND, update NAND drivers platform data
with NAND related register addresses so that NAND driver can handle
GPMC NAND operations by itself

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             |   25 +++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc.h |   16 ++++++++++++++++
 arch/arm/plat-omap/include/plat/nand.h |    1 +
 3 files changed, 42 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index c8d07bb..657ce95 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -30,6 +30,7 @@
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
+#include <plat/nand.h>
 
 #include <plat/sdrc.h>
 
@@ -891,6 +892,28 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
+				struct omap_nand_platform_data *nand)
+{
+	int cs = nand->cs;
+
+	nand->reg.gpmc_status = gpmc->io_base + GPMC_STATUS;
+	nand->reg.gpmc_nand_command = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_address = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_data = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_prefetch_config1 = gpmc->io_base + GPMC_PREFETCH_CONFIG1;
+	nand->reg.gpmc_prefetch_config2 = gpmc->io_base + GPMC_PREFETCH_CONFIG2;
+	nand->reg.gpmc_prefetch_control = gpmc->io_base + GPMC_PREFETCH_CONTROL;
+	nand->reg.gpmc_prefetch_status = gpmc->io_base + GPMC_PREFETCH_STATUS;
+	nand->reg.gpmc_ecc_config = gpmc->io_base + GPMC_ECC_CONFIG;
+	nand->reg.gpmc_ecc_control = gpmc->io_base + GPMC_ECC_CONTROL;
+	nand->reg.gpmc_ecc_size_config = gpmc->io_base + GPMC_ECC_SIZE_CONFIG;
+	nand->reg.gpmc_ecc1_result = gpmc->io_base + GPMC_ECC1_RESULT;
+}
+
 static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
 {
 	return gpmc->waitpin_map & (0x1 << waitpin);
@@ -1427,6 +1450,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		if ((*gdq)->is_nand)
+			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index c5cf020..976a8f0 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -207,6 +207,7 @@ struct gpmc_device_pdata {
 	unsigned		per_res_cnt;
 	struct gpmc_cs_data	*cs_data;
 	unsigned		num_cs;
+	bool			is_nand;
 };
 
 struct gpmc_pdata {
@@ -216,6 +217,21 @@ struct gpmc_pdata {
 	struct gpmc_device_pdata	**device_pdata;
 };
 
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+};
+
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
 extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 67fc506..86e4d9c 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -29,6 +29,7 @@ struct omap_nand_platform_data {
 	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
+	struct gpmc_nand_regs	reg;
 };
 
 /* minimum size for IO mapping */
-- 
1.7.10

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

* [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Some boards depend on bootloader to update chip select value for NAND.
It is felt that Kernel should not depend on bootloader to get CS, as
for a particular board CS is hardwired and is fixed, hence this can
directly be updated in Kernel. But as CS value for boards that depend
on this behaviour is not available, educate gpmc driver to acquire
chip select value for NAND. this ideally should be removed once CS
for those boards are available.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 657ce95..ecd3384 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -892,6 +892,30 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
+					struct gpmc_device_pdata *gdp)
+{
+	int cs = 0;
+	struct omap_nand_platform_data *nand = gdp->pdata;
+
+	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
+		return 0;
+
+	while (cs < GPMC_CS_NUM) {
+		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
+				GPMC_CONFIG1_DEVICETYPE_NAND) {
+			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
+			nand->cs = cs;
+			gdp->cs_data->cs = cs;
+			return 0;
+		}
+		cs++;
+	}
+	return -ENODEV;
+}
+
 static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
 				struct omap_nand_platform_data *nand)
 {
@@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
-		if ((*gdq)->is_nand)
+		if ((*gdq)->is_nand) {
+			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
+			if (IS_ERR_VALUE(ret)) {
+				dev_err(gpmc->dev, "CS error: %d\n", ret);
+				continue;
+			}
 			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
+		}
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
-- 
1.7.10


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

* [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Some boards depend on bootloader to update chip select value for NAND.
It is felt that Kernel should not depend on bootloader to get CS, as
for a particular board CS is hardwired and is fixed, hence this can
directly be updated in Kernel. But as CS value for boards that depend
on this behaviour is not available, educate gpmc driver to acquire
chip select value for NAND. this ideally should be removed once CS
for those boards are available.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 657ce95..ecd3384 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -892,6 +892,30 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
+					struct gpmc_device_pdata *gdp)
+{
+	int cs = 0;
+	struct omap_nand_platform_data *nand = gdp->pdata;
+
+	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
+		return 0;
+
+	while (cs < GPMC_CS_NUM) {
+		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
+				GPMC_CONFIG1_DEVICETYPE_NAND) {
+			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
+			nand->cs = cs;
+			gdp->cs_data->cs = cs;
+			return 0;
+		}
+		cs++;
+	}
+	return -ENODEV;
+}
+
 static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
 				struct omap_nand_platform_data *nand)
 {
@@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
-		if ((*gdq)->is_nand)
+		if ((*gdq)->is_nand) {
+			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
+			if (IS_ERR_VALUE(ret)) {
+				dev_err(gpmc->dev, "CS error: %d\n", ret);
+				continue;
+			}
 			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
+		}
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
-- 
1.7.10

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

* [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Some boards depend on bootloader to update chip select value for NAND.
It is felt that Kernel should not depend on bootloader to get CS, as
for a particular board CS is hardwired and is fixed, hence this can
directly be updated in Kernel. But as CS value for boards that depend
on this behaviour is not available, educate gpmc driver to acquire
chip select value for NAND. this ideally should be removed once CS
for those boards are available.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 657ce95..ecd3384 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -892,6 +892,30 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
+					struct gpmc_device_pdata *gdp)
+{
+	int cs = 0;
+	struct omap_nand_platform_data *nand = gdp->pdata;
+
+	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
+		return 0;
+
+	while (cs < GPMC_CS_NUM) {
+		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
+				GPMC_CONFIG1_DEVICETYPE_NAND) {
+			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
+			nand->cs = cs;
+			gdp->cs_data->cs = cs;
+			return 0;
+		}
+		cs++;
+	}
+	return -ENODEV;
+}
+
 static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
 				struct omap_nand_platform_data *nand)
 {
@@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
-		if ((*gdq)->is_nand)
+		if ((*gdq)->is_nand) {
+			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
+			if (IS_ERR_VALUE(ret)) {
+				dev_err(gpmc->dev, "CS error: %d\n", ret);
+				continue;
+			}
 			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
+		}
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
-- 
1.7.10

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

* [PATCH v4 05/39] ARM: OMAP2+: nand: create platform data structure
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

New API for updating nand platform data. This has
been created by unifying the two existing ones and
taking out gpmc hardware handling.

>From now on, platforms can call omap_nand_init to
initialize platform nand structures, it's fields.
Or can statically create the same.

Acquiring gpmc CS for has been removed. Acquiring CS
is done in GPMC driver. To leverage this feature,
pass CS # as any value outside the allowed range of
0 - 7 (this is valid only for connected NAND),
eg. GPMC_CS_NUM (8)

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-devkit8000.c     |    6 ++-
 arch/arm/mach-omap2/board-flash.c          |   61 ++++++++++++++--------------
 arch/arm/mach-omap2/board-flash.h          |   13 ++++--
 arch/arm/mach-omap2/board-ldp.c            |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |    6 ++-
 arch/arm/mach-omap2/board-overo.c          |    5 ++-
 arch/arm/mach-omap2/board-zoom.c           |    5 ++-
 arch/arm/mach-omap2/common-board-devices.c |   46 ---------------------
 arch/arm/mach-omap2/common-board-devices.h |    1 -
 10 files changed, 60 insertions(+), 93 deletions(-)

diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a2010f0..aa352d1 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -59,6 +59,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -648,8 +649,9 @@ static void __init devkit8000_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
-			     ARRAY_SIZE(devkit8000_nand_partitions));
+	board_nand_init(devkit8000_nand_partitions,
+		ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 0349fd2..091aaf6 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 /* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
+struct gpmc_timings nand_default_timings[1] = {
+	{
+		.sync_clk = 0,
 
-	.sync_clk = 0,
+		.cs_on = 0,
+		.cs_rd_off = 36,
+		.cs_wr_off = 36,
 
-	.cs_on = 0,
-	.cs_rd_off = 36,
-	.cs_wr_off = 36,
+		.adv_on = 6,
+		.adv_rd_off = 24,
+		.adv_wr_off = 36,
 
-	.adv_on = 6,
-	.adv_rd_off = 24,
-	.adv_wr_off = 36,
+		.we_off = 30,
+		.oe_off = 48,
 
-	.we_off = 30,
-	.oe_off = 48,
+		.access = 54,
+		.rd_cycle = 72,
+		.wr_cycle = 72,
 
-	.access = 54,
-	.rd_cycle = 72,
-	.wr_cycle = 72,
-
-	.wr_access = 30,
-	.wr_data_mux_bus = 0,
+		.wr_access = 30,
+		.wr_data_mux_bus = 0,
+	},
 };
 
-static struct omap_nand_platform_data board_nand_data = {
-	.gpmc_t		= &nand_timings,
+static struct omap_nand_platform_data omap_nand_data = {
+	.gpmc_t		= nand_default_timings,
 };
 
-void
-__init board_nand_init(struct mtd_partition *nand_parts,
-			u8 nr_parts, u8 cs, int nand_type)
+struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
 {
-	board_nand_data.cs		= cs;
-	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts	= nr_parts;
-	board_nand_data.devsize		= nand_type;
-
-	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
-	gpmc_nand_init(&board_nand_data);
+	omap_nand_data.cs		= cs;
+	omap_nand_data.parts		= nand_parts;
+	omap_nand_data.nr_parts		= nr_parts;
+	omap_nand_data.devsize		= nand_type;
+	omap_nand_data.gpmc_t		= gpmc_t;
+
+	return &omap_nand_data;
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
@@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs, nand_type);
+			partition_info[2].nr_parts, nandcs,
+			nand_type, nand_default_timings);
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index d25503a..052964c 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -39,11 +39,16 @@ static inline void board_flash_init(struct flash_partitions part[],
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type);
+extern struct gpmc_timings nand_default_timings[];
+extern struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t);
 #else
-static inline void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type)
+#define	nand_default_timings	NULL
+static inline struct omap_nand_platform_data *
+board_nand_init(struct mtd_partition *nand_parts,
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
 {
+	return NULL;
 }
 #endif
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 1b60495..b76f28d 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -427,8 +427,8 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+				ZOOM_NAND_CS, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7be8d65..671ac1c 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -51,6 +51,7 @@
 #include "mux.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 /*
@@ -542,8 +543,9 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
-			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	board_nand_init(omap3beagle_nand_partitions,
+		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ae2251f..b691728 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -52,6 +52,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -370,8 +371,9 @@ static void __init omap3_touchbook_init(void)
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
-			     ARRAY_SIZE(omap3touchbook_nand_partitions));
+	board_nand_init(omap3touchbook_nand_partitions,
+		ARRAY_SIZE(omap3touchbook_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 33aa391..e08479a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -57,6 +57,7 @@
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OVERO_GPIO_BT_XGATE	15
@@ -517,8 +518,8 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_nand_flash_init(0, overo_nand_partitions,
-			     ARRAY_SIZE(overo_nand_partitions));
+	board_nand_init(overo_nand_partitions,
+		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 5c20bcc..664e913 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -114,8 +114,9 @@ static void __init omap_zoom_init(void)
 		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
-						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+	board_nand_init(zoom_nand_partitions,
+			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
+			NAND_BUSWIDTH_16, nand_default_timings);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 1706ebc..0fd35a4 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -93,49 +93,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 {
 }
 #endif
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data;
-
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-	u8 cs = 0;
-	u8 nandcs = GPMC_CS_NUM + 1;
-
-	/* find out the chip-select on which NAND exists */
-	while (cs < GPMC_CS_NUM) {
-		u32 ret = 0;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		if ((ret & 0xC00) == 0x800) {
-			printk(KERN_INFO "Found NAND on CS%d\n", cs);
-			if (nandcs > GPMC_CS_NUM)
-				nandcs = cs;
-		}
-		cs++;
-	}
-
-	if (nandcs > GPMC_CS_NUM) {
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				 "in GPMC\n ");
-		return;
-	}
-
-	if (nandcs < GPMC_CS_NUM) {
-		nand_data.cs = nandcs;
-		nand_data.parts = parts;
-		nand_data.nr_parts = nr_parts;
-		nand_data.devsize = options;
-
-		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (gpmc_nand_init(&nand_data) < 0)
-			printk(KERN_ERR "Unable to register NAND device\n");
-	}
-}
-#else
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index a0b4a428..72bb41b 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 		       struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
 
 #endif /* __OMAP_COMMON_BOARD_DEVICES__ */
-- 
1.7.10


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

* [PATCH v4 05/39] ARM: OMAP2+: nand: create platform data structure
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

New API for updating nand platform data. This has
been created by unifying the two existing ones and
taking out gpmc hardware handling.

>From now on, platforms can call omap_nand_init to
initialize platform nand structures, it's fields.
Or can statically create the same.

Acquiring gpmc CS for has been removed. Acquiring CS
is done in GPMC driver. To leverage this feature,
pass CS # as any value outside the allowed range of
0 - 7 (this is valid only for connected NAND),
eg. GPMC_CS_NUM (8)

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-devkit8000.c     |    6 ++-
 arch/arm/mach-omap2/board-flash.c          |   61 ++++++++++++++--------------
 arch/arm/mach-omap2/board-flash.h          |   13 ++++--
 arch/arm/mach-omap2/board-ldp.c            |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |    6 ++-
 arch/arm/mach-omap2/board-overo.c          |    5 ++-
 arch/arm/mach-omap2/board-zoom.c           |    5 ++-
 arch/arm/mach-omap2/common-board-devices.c |   46 ---------------------
 arch/arm/mach-omap2/common-board-devices.h |    1 -
 10 files changed, 60 insertions(+), 93 deletions(-)

diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a2010f0..aa352d1 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -59,6 +59,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -648,8 +649,9 @@ static void __init devkit8000_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
-			     ARRAY_SIZE(devkit8000_nand_partitions));
+	board_nand_init(devkit8000_nand_partitions,
+		ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 0349fd2..091aaf6 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 /* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
+struct gpmc_timings nand_default_timings[1] = {
+	{
+		.sync_clk = 0,
 
-	.sync_clk = 0,
+		.cs_on = 0,
+		.cs_rd_off = 36,
+		.cs_wr_off = 36,
 
-	.cs_on = 0,
-	.cs_rd_off = 36,
-	.cs_wr_off = 36,
+		.adv_on = 6,
+		.adv_rd_off = 24,
+		.adv_wr_off = 36,
 
-	.adv_on = 6,
-	.adv_rd_off = 24,
-	.adv_wr_off = 36,
+		.we_off = 30,
+		.oe_off = 48,
 
-	.we_off = 30,
-	.oe_off = 48,
+		.access = 54,
+		.rd_cycle = 72,
+		.wr_cycle = 72,
 
-	.access = 54,
-	.rd_cycle = 72,
-	.wr_cycle = 72,
-
-	.wr_access = 30,
-	.wr_data_mux_bus = 0,
+		.wr_access = 30,
+		.wr_data_mux_bus = 0,
+	},
 };
 
-static struct omap_nand_platform_data board_nand_data = {
-	.gpmc_t		= &nand_timings,
+static struct omap_nand_platform_data omap_nand_data = {
+	.gpmc_t		= nand_default_timings,
 };
 
-void
-__init board_nand_init(struct mtd_partition *nand_parts,
-			u8 nr_parts, u8 cs, int nand_type)
+struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
 {
-	board_nand_data.cs		= cs;
-	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts	= nr_parts;
-	board_nand_data.devsize		= nand_type;
-
-	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
-	gpmc_nand_init(&board_nand_data);
+	omap_nand_data.cs		= cs;
+	omap_nand_data.parts		= nand_parts;
+	omap_nand_data.nr_parts		= nr_parts;
+	omap_nand_data.devsize		= nand_type;
+	omap_nand_data.gpmc_t		= gpmc_t;
+
+	return &omap_nand_data;
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
@@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs, nand_type);
+			partition_info[2].nr_parts, nandcs,
+			nand_type, nand_default_timings);
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index d25503a..052964c 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -39,11 +39,16 @@ static inline void board_flash_init(struct flash_partitions part[],
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type);
+extern struct gpmc_timings nand_default_timings[];
+extern struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t);
 #else
-static inline void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type)
+#define	nand_default_timings	NULL
+static inline struct omap_nand_platform_data *
+board_nand_init(struct mtd_partition *nand_parts,
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
 {
+	return NULL;
 }
 #endif
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 1b60495..b76f28d 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -427,8 +427,8 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+				ZOOM_NAND_CS, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7be8d65..671ac1c 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -51,6 +51,7 @@
 #include "mux.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 /*
@@ -542,8 +543,9 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
-			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	board_nand_init(omap3beagle_nand_partitions,
+		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ae2251f..b691728 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -52,6 +52,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -370,8 +371,9 @@ static void __init omap3_touchbook_init(void)
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
-			     ARRAY_SIZE(omap3touchbook_nand_partitions));
+	board_nand_init(omap3touchbook_nand_partitions,
+		ARRAY_SIZE(omap3touchbook_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 33aa391..e08479a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -57,6 +57,7 @@
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OVERO_GPIO_BT_XGATE	15
@@ -517,8 +518,8 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_nand_flash_init(0, overo_nand_partitions,
-			     ARRAY_SIZE(overo_nand_partitions));
+	board_nand_init(overo_nand_partitions,
+		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 5c20bcc..664e913 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -114,8 +114,9 @@ static void __init omap_zoom_init(void)
 		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
-						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+	board_nand_init(zoom_nand_partitions,
+			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
+			NAND_BUSWIDTH_16, nand_default_timings);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 1706ebc..0fd35a4 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -93,49 +93,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 {
 }
 #endif
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data;
-
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-	u8 cs = 0;
-	u8 nandcs = GPMC_CS_NUM + 1;
-
-	/* find out the chip-select on which NAND exists */
-	while (cs < GPMC_CS_NUM) {
-		u32 ret = 0;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		if ((ret & 0xC00) == 0x800) {
-			printk(KERN_INFO "Found NAND on CS%d\n", cs);
-			if (nandcs > GPMC_CS_NUM)
-				nandcs = cs;
-		}
-		cs++;
-	}
-
-	if (nandcs > GPMC_CS_NUM) {
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				 "in GPMC\n ");
-		return;
-	}
-
-	if (nandcs < GPMC_CS_NUM) {
-		nand_data.cs = nandcs;
-		nand_data.parts = parts;
-		nand_data.nr_parts = nr_parts;
-		nand_data.devsize = options;
-
-		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (gpmc_nand_init(&nand_data) < 0)
-			printk(KERN_ERR "Unable to register NAND device\n");
-	}
-}
-#else
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index a0b4a428..72bb41b 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 		       struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
 
 #endif /* __OMAP_COMMON_BOARD_DEVICES__ */
-- 
1.7.10

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

* [PATCH v4 05/39] ARM: OMAP2+: nand: create platform data structure
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

New API for updating nand platform data. This has
been created by unifying the two existing ones and
taking out gpmc hardware handling.

>From now on, platforms can call omap_nand_init to
initialize platform nand structures, it's fields.
Or can statically create the same.

Acquiring gpmc CS for has been removed. Acquiring CS
is done in GPMC driver. To leverage this feature,
pass CS # as any value outside the allowed range of
0 - 7 (this is valid only for connected NAND),
eg. GPMC_CS_NUM (8)

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-devkit8000.c     |    6 ++-
 arch/arm/mach-omap2/board-flash.c          |   61 ++++++++++++++--------------
 arch/arm/mach-omap2/board-flash.h          |   13 ++++--
 arch/arm/mach-omap2/board-ldp.c            |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |    6 ++-
 arch/arm/mach-omap2/board-overo.c          |    5 ++-
 arch/arm/mach-omap2/board-zoom.c           |    5 ++-
 arch/arm/mach-omap2/common-board-devices.c |   46 ---------------------
 arch/arm/mach-omap2/common-board-devices.h |    1 -
 10 files changed, 60 insertions(+), 93 deletions(-)

diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a2010f0..aa352d1 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -59,6 +59,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -648,8 +649,9 @@ static void __init devkit8000_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
-			     ARRAY_SIZE(devkit8000_nand_partitions));
+	board_nand_init(devkit8000_nand_partitions,
+		ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 0349fd2..091aaf6 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 /* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
+struct gpmc_timings nand_default_timings[1] = {
+	{
+		.sync_clk = 0,
 
-	.sync_clk = 0,
+		.cs_on = 0,
+		.cs_rd_off = 36,
+		.cs_wr_off = 36,
 
-	.cs_on = 0,
-	.cs_rd_off = 36,
-	.cs_wr_off = 36,
+		.adv_on = 6,
+		.adv_rd_off = 24,
+		.adv_wr_off = 36,
 
-	.adv_on = 6,
-	.adv_rd_off = 24,
-	.adv_wr_off = 36,
+		.we_off = 30,
+		.oe_off = 48,
 
-	.we_off = 30,
-	.oe_off = 48,
+		.access = 54,
+		.rd_cycle = 72,
+		.wr_cycle = 72,
 
-	.access = 54,
-	.rd_cycle = 72,
-	.wr_cycle = 72,
-
-	.wr_access = 30,
-	.wr_data_mux_bus = 0,
+		.wr_access = 30,
+		.wr_data_mux_bus = 0,
+	},
 };
 
-static struct omap_nand_platform_data board_nand_data = {
-	.gpmc_t		= &nand_timings,
+static struct omap_nand_platform_data omap_nand_data = {
+	.gpmc_t		= nand_default_timings,
 };
 
-void
-__init board_nand_init(struct mtd_partition *nand_parts,
-			u8 nr_parts, u8 cs, int nand_type)
+struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
 {
-	board_nand_data.cs		= cs;
-	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts	= nr_parts;
-	board_nand_data.devsize		= nand_type;
-
-	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
-	gpmc_nand_init(&board_nand_data);
+	omap_nand_data.cs		= cs;
+	omap_nand_data.parts		= nand_parts;
+	omap_nand_data.nr_parts		= nr_parts;
+	omap_nand_data.devsize		= nand_type;
+	omap_nand_data.gpmc_t		= gpmc_t;
+
+	return &omap_nand_data;
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
@@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs, nand_type);
+			partition_info[2].nr_parts, nandcs,
+			nand_type, nand_default_timings);
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index d25503a..052964c 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -39,11 +39,16 @@ static inline void board_flash_init(struct flash_partitions part[],
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type);
+extern struct gpmc_timings nand_default_timings[];
+extern struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t);
 #else
-static inline void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type)
+#define	nand_default_timings	NULL
+static inline struct omap_nand_platform_data *
+board_nand_init(struct mtd_partition *nand_parts,
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
 {
+	return NULL;
 }
 #endif
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 1b60495..b76f28d 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -427,8 +427,8 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+				ZOOM_NAND_CS, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7be8d65..671ac1c 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -51,6 +51,7 @@
 #include "mux.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 /*
@@ -542,8 +543,9 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
-			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	board_nand_init(omap3beagle_nand_partitions,
+		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ae2251f..b691728 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -52,6 +52,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -370,8 +371,9 @@ static void __init omap3_touchbook_init(void)
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
-			     ARRAY_SIZE(omap3touchbook_nand_partitions));
+	board_nand_init(omap3touchbook_nand_partitions,
+		ARRAY_SIZE(omap3touchbook_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 33aa391..e08479a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -57,6 +57,7 @@
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OVERO_GPIO_BT_XGATE	15
@@ -517,8 +518,8 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_nand_flash_init(0, overo_nand_partitions,
-			     ARRAY_SIZE(overo_nand_partitions));
+	board_nand_init(overo_nand_partitions,
+		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 5c20bcc..664e913 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -114,8 +114,9 @@ static void __init omap_zoom_init(void)
 		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
-						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+	board_nand_init(zoom_nand_partitions,
+			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
+			NAND_BUSWIDTH_16, nand_default_timings);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 1706ebc..0fd35a4 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -93,49 +93,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 {
 }
 #endif
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data;
-
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-	u8 cs = 0;
-	u8 nandcs = GPMC_CS_NUM + 1;
-
-	/* find out the chip-select on which NAND exists */
-	while (cs < GPMC_CS_NUM) {
-		u32 ret = 0;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		if ((ret & 0xC00) == 0x800) {
-			printk(KERN_INFO "Found NAND on CS%d\n", cs);
-			if (nandcs > GPMC_CS_NUM)
-				nandcs = cs;
-		}
-		cs++;
-	}
-
-	if (nandcs > GPMC_CS_NUM) {
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				 "in GPMC\n ");
-		return;
-	}
-
-	if (nandcs < GPMC_CS_NUM) {
-		nand_data.cs = nandcs;
-		nand_data.parts = parts;
-		nand_data.nr_parts = nr_parts;
-		nand_data.devsize = options;
-
-		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (gpmc_nand_init(&nand_data) < 0)
-			printk(KERN_ERR "Unable to register NAND device\n");
-	}
-}
-#else
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index a0b4a428..72bb41b 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 		       struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
 
 #endif /* __OMAP_COMMON_BOARD_DEVICES__ */
-- 
1.7.10

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

* [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Modify board_onenand_init to return platform data. This
would be required for boards to be able to pass it to
gpmc driver so that it finally reaches onenand driver.

Also un-static the function so that boards can use it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-flash.c |   14 ++++----------
 arch/arm/mach-omap2/board-flash.h |   12 ++++++++++++
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 091aaf6..8727c05 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -87,22 +87,16 @@ static struct omap_onenand_platform_data board_onenand_data = {
 	.dma_channel	= -1,   /* disable DMA in OMAP OneNAND driver */
 };
 
-static void
-__init board_onenand_init(struct mtd_partition *onenand_parts,
-				u8 nr_parts, u8 cs)
+struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs)
 {
 	board_onenand_data.cs		= cs;
 	board_onenand_data.parts	= onenand_parts;
 	board_onenand_data.nr_parts	= nr_parts;
 
-	gpmc_onenand_init(&board_onenand_data);
-}
-#else
-static void
-__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
-{
+	return &board_onenand_data;
 }
-#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
+#endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 052964c..75ba49f 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
 	return NULL;
 }
 #endif
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+extern struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
+#else
+static inline struct omap_onenand_platform_data *
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+	return NULL;
+}
+#endif
-- 
1.7.10


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

* [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Modify board_onenand_init to return platform data. This
would be required for boards to be able to pass it to
gpmc driver so that it finally reaches onenand driver.

Also un-static the function so that boards can use it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-flash.c |   14 ++++----------
 arch/arm/mach-omap2/board-flash.h |   12 ++++++++++++
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 091aaf6..8727c05 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -87,22 +87,16 @@ static struct omap_onenand_platform_data board_onenand_data = {
 	.dma_channel	= -1,   /* disable DMA in OMAP OneNAND driver */
 };
 
-static void
-__init board_onenand_init(struct mtd_partition *onenand_parts,
-				u8 nr_parts, u8 cs)
+struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs)
 {
 	board_onenand_data.cs		= cs;
 	board_onenand_data.parts	= onenand_parts;
 	board_onenand_data.nr_parts	= nr_parts;
 
-	gpmc_onenand_init(&board_onenand_data);
-}
-#else
-static void
-__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
-{
+	return &board_onenand_data;
 }
-#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
+#endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 052964c..75ba49f 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
 	return NULL;
 }
 #endif
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+extern struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
+#else
+static inline struct omap_onenand_platform_data *
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+	return NULL;
+}
+#endif
-- 
1.7.10

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

* [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Modify board_onenand_init to return platform data. This
would be required for boards to be able to pass it to
gpmc driver so that it finally reaches onenand driver.

Also un-static the function so that boards can use it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-flash.c |   14 ++++----------
 arch/arm/mach-omap2/board-flash.h |   12 ++++++++++++
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 091aaf6..8727c05 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -87,22 +87,16 @@ static struct omap_onenand_platform_data board_onenand_data = {
 	.dma_channel	= -1,   /* disable DMA in OMAP OneNAND driver */
 };
 
-static void
-__init board_onenand_init(struct mtd_partition *onenand_parts,
-				u8 nr_parts, u8 cs)
+struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs)
 {
 	board_onenand_data.cs		= cs;
 	board_onenand_data.parts	= onenand_parts;
 	board_onenand_data.nr_parts	= nr_parts;
 
-	gpmc_onenand_init(&board_onenand_data);
-}
-#else
-static void
-__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
-{
+	return &board_onenand_data;
 }
-#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
+#endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 052964c..75ba49f 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
 	return NULL;
 }
 #endif
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+extern struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
+#else
+static inline struct omap_onenand_platform_data *
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+	return NULL;
+}
+#endif
-- 
1.7.10

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

* [PATCH v4 07/39] ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for nand.
As configuring gpmc has been moved to gpmc driver,
populate details needed for the driver to configure
gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/gpmc-nand.c        |   84 ++++++++++++--------------------
 arch/arm/plat-omap/include/plat/nand.h |    8 +--
 2 files changed, 35 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 386dec8..190cdc1 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -21,24 +21,30 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct resource gpmc_nand_resource = {
-	.flags		= IORESOURCE_MEM,
+
+static struct gpmc_cs_data gpmc_nand_cs_info = {
+	.have_config	= true,
+	.config		= GPMC_DEVICETYPE_NAND,
+	.irq_config	= GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT,
 };
 
-static struct platform_device gpmc_nand_device = {
+static struct gpmc_device_pdata gpmc_nand_info = {
 	.name		= "omap2-nand",
 	.id		= 0,
-	.num_resources	= 1,
-	.resource	= &gpmc_nand_resource,
+	.cs_data	= &gpmc_nand_cs_info,
+	.num_cs		= 1,
+	.is_nand	= true,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
-{
-	struct gpmc_timings t;
-	int err;
+static struct gpmc_timings t;
 
-	if (!gpmc_nand_data->gpmc_t)
+static struct gpmc_timings *
+gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	if (!gpmc_nand_data->gpmc_t) {
+		pr_warn("gpmc timings not provided\n");
 		return 0;
+	}
 
 	memset(&t, 0, sizeof(t));
 	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
@@ -68,56 +74,26 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
-	/* Configure GPMC */
-	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-	gpmc_cs_configure(gpmc_nand_data->cs,
-			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
-	if (err)
-		return err;
-
-	return 0;
+	return &t;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+struct gpmc_device_pdata *
+__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 {
-	int err	= 0;
-	struct device *dev = &gpmc_nand_device.dev;
+	gpmc_nand_info.pdata = gpmc_nand_data;
+	gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data);
 
-	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+	gpmc_nand_cs_info.cs = gpmc_nand_data->cs;
+	gpmc_nand_cs_info.mem_size = NAND_IO_SIZE;
 
-	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				&gpmc_nand_data->phys_base);
-	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS\n");
-		return err;
-	}
+	gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data);
 
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
-	}
-
-	/* Enable RD PIN Monitoring Reg */
-	if (gpmc_nand_data->dev_ready) {
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
-	}
-
-	err = platform_device_register(&gpmc_nand_device);
-	if (err < 0) {
-		dev_err(dev, "Unable to register NAND device\n");
-		goto out_free_cs;
-	}
-
-	return 0;
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_nand_cs_info.config |= GPMC_DEVICESIZE_16;
 
-out_free_cs:
-	gpmc_cs_free(gpmc_nand_data->cs);
+	if (gpmc_nand_data->dev_ready)
+		gpmc_nand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON;
 
-	return err;
+	return &gpmc_nand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 86e4d9c..30c61c9 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -36,10 +36,12 @@ struct omap_nand_platform_data {
 #define	NAND_IO_SIZE	4
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d);
 #else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d)
 {
-	return 0;
+	return NULL;
 }
 #endif
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 07/39] ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
@ 2012-05-01 12:20     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for nand.
As configuring gpmc has been moved to gpmc driver,
populate details needed for the driver to configure
gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c        |   84 ++++++++++++--------------------
 arch/arm/plat-omap/include/plat/nand.h |    8 +--
 2 files changed, 35 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 386dec8..190cdc1 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -21,24 +21,30 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct resource gpmc_nand_resource = {
-	.flags		= IORESOURCE_MEM,
+
+static struct gpmc_cs_data gpmc_nand_cs_info = {
+	.have_config	= true,
+	.config		= GPMC_DEVICETYPE_NAND,
+	.irq_config	= GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT,
 };
 
-static struct platform_device gpmc_nand_device = {
+static struct gpmc_device_pdata gpmc_nand_info = {
 	.name		= "omap2-nand",
 	.id		= 0,
-	.num_resources	= 1,
-	.resource	= &gpmc_nand_resource,
+	.cs_data	= &gpmc_nand_cs_info,
+	.num_cs		= 1,
+	.is_nand	= true,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
-{
-	struct gpmc_timings t;
-	int err;
+static struct gpmc_timings t;
 
-	if (!gpmc_nand_data->gpmc_t)
+static struct gpmc_timings *
+gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	if (!gpmc_nand_data->gpmc_t) {
+		pr_warn("gpmc timings not provided\n");
 		return 0;
+	}
 
 	memset(&t, 0, sizeof(t));
 	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
@@ -68,56 +74,26 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
-	/* Configure GPMC */
-	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-	gpmc_cs_configure(gpmc_nand_data->cs,
-			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
-	if (err)
-		return err;
-
-	return 0;
+	return &t;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+struct gpmc_device_pdata *
+__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 {
-	int err	= 0;
-	struct device *dev = &gpmc_nand_device.dev;
+	gpmc_nand_info.pdata = gpmc_nand_data;
+	gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data);
 
-	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+	gpmc_nand_cs_info.cs = gpmc_nand_data->cs;
+	gpmc_nand_cs_info.mem_size = NAND_IO_SIZE;
 
-	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				&gpmc_nand_data->phys_base);
-	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS\n");
-		return err;
-	}
+	gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data);
 
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
-	}
-
-	/* Enable RD PIN Monitoring Reg */
-	if (gpmc_nand_data->dev_ready) {
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
-	}
-
-	err = platform_device_register(&gpmc_nand_device);
-	if (err < 0) {
-		dev_err(dev, "Unable to register NAND device\n");
-		goto out_free_cs;
-	}
-
-	return 0;
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_nand_cs_info.config |= GPMC_DEVICESIZE_16;
 
-out_free_cs:
-	gpmc_cs_free(gpmc_nand_data->cs);
+	if (gpmc_nand_data->dev_ready)
+		gpmc_nand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON;
 
-	return err;
+	return &gpmc_nand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 86e4d9c..30c61c9 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -36,10 +36,12 @@ struct omap_nand_platform_data {
 #define	NAND_IO_SIZE	4
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d);
 #else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d)
 {
-	return 0;
+	return NULL;
 }
 #endif
-- 
1.7.10

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

* [PATCH v4 07/39] ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
@ 2012-05-01 12:20     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Currently gpmc is configured in platform for nand.
As configuring gpmc has been moved to gpmc driver,
populate details needed for the driver to configure
gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c        |   84 ++++++++++++--------------------
 arch/arm/plat-omap/include/plat/nand.h |    8 +--
 2 files changed, 35 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 386dec8..190cdc1 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -21,24 +21,30 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct resource gpmc_nand_resource = {
-	.flags		= IORESOURCE_MEM,
+
+static struct gpmc_cs_data gpmc_nand_cs_info = {
+	.have_config	= true,
+	.config		= GPMC_DEVICETYPE_NAND,
+	.irq_config	= GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT,
 };
 
-static struct platform_device gpmc_nand_device = {
+static struct gpmc_device_pdata gpmc_nand_info = {
 	.name		= "omap2-nand",
 	.id		= 0,
-	.num_resources	= 1,
-	.resource	= &gpmc_nand_resource,
+	.cs_data	= &gpmc_nand_cs_info,
+	.num_cs		= 1,
+	.is_nand	= true,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
-{
-	struct gpmc_timings t;
-	int err;
+static struct gpmc_timings t;
 
-	if (!gpmc_nand_data->gpmc_t)
+static struct gpmc_timings *
+gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	if (!gpmc_nand_data->gpmc_t) {
+		pr_warn("gpmc timings not provided\n");
 		return 0;
+	}
 
 	memset(&t, 0, sizeof(t));
 	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
@@ -68,56 +74,26 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
-	/* Configure GPMC */
-	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-	gpmc_cs_configure(gpmc_nand_data->cs,
-			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
-	if (err)
-		return err;
-
-	return 0;
+	return &t;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+struct gpmc_device_pdata *
+__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 {
-	int err	= 0;
-	struct device *dev = &gpmc_nand_device.dev;
+	gpmc_nand_info.pdata = gpmc_nand_data;
+	gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data);
 
-	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+	gpmc_nand_cs_info.cs = gpmc_nand_data->cs;
+	gpmc_nand_cs_info.mem_size = NAND_IO_SIZE;
 
-	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				&gpmc_nand_data->phys_base);
-	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS\n");
-		return err;
-	}
+	gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data);
 
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
-	}
-
-	/* Enable RD PIN Monitoring Reg */
-	if (gpmc_nand_data->dev_ready) {
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
-	}
-
-	err = platform_device_register(&gpmc_nand_device);
-	if (err < 0) {
-		dev_err(dev, "Unable to register NAND device\n");
-		goto out_free_cs;
-	}
-
-	return 0;
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_nand_cs_info.config |= GPMC_DEVICESIZE_16;
 
-out_free_cs:
-	gpmc_cs_free(gpmc_nand_data->cs);
+	if (gpmc_nand_data->dev_ready)
+		gpmc_nand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON;
 
-	return err;
+	return &gpmc_nand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 86e4d9c..30c61c9 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -36,10 +36,12 @@ struct omap_nand_platform_data {
 #define	NAND_IO_SIZE	4
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d);
 #else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d)
 {
-	return 0;
+	return NULL;
 }
 #endif
-- 
1.7.10

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

* [PATCH v4 08/39] ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for onenand. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-onenand.c        |  111 +++++++++++++++--------------
 arch/arm/plat-omap/include/plat/onenand.h |    7 +-
 2 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index a0fa9bb..d7775d5 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -25,9 +25,17 @@
 
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
-static struct platform_device gpmc_onenand_device = {
+#define ONENAND_IO_SIZE		SZ_128K
+
+static struct gpmc_cs_data gpmc_onenand_cs_info = {
+	.mem_size	= ONENAND_IO_SIZE,
+};
+
+static struct gpmc_device_pdata gpmc_onenand_info = {
 	.name		= "omap2-onenand",
 	.id		= -1,
+	.cs_data	= &gpmc_onenand_cs_info,
+	.num_cs		= 1,
 };
 
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -79,13 +87,17 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 
 	/* Configure GPMC for asynchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 |
+					GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
@@ -180,7 +192,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
 	int cs = cfg->cs, freq = *freq_ptr;
-	u32 reg;
 	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
@@ -276,27 +287,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg |= (1 << 7);
-		reg |= (1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
-	} else {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg &= ~(1 << 7);
-		reg &= ~(1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+		t.control.cs_extra_delay = true;
+		t.control.adv_extra_delay = true;
+		t.control.oe_extra_delay = true;
+		t.control.we_extra_delay = true;
 	}
 
 	/* Set synchronous read timings */
@@ -348,24 +342,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	}
 
 	/* Configure GPMC for synchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_WRAPBURST_SUPP |
-			  GPMC_CONFIG1_READMULTIPLE_SUPP |
-			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
-			  GPMC_CONFIG1_PAGE_LEN(2) |
-			  (cpu_is_omap34xx() ? 0 :
-				(GPMC_CONFIG1_WAIT_READ_MON |
-				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_DEVICETYPE_NOR |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 | GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR | GPMC_WRAPBURST |
+					GPMC_READMULTIPLE | GPMC_PAGE_LEN_16;
+	if (!cpu_is_omap34xx())
+		gpmc_onenand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAITPIN_0;
+	if (sync_read)
+		gpmc_onenand_cs_info.config |= GPMC_READTYPE_SYNC;
+	if (sync_write)
+		gpmc_onenand_cs_info.config |= GPMC_WRITETYPE_SYNC |
+						GPMC_WRITEMULTIPLE;
+	if (fclk_offset == 0)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_0;
+	else if (fclk_offset == 1)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_1;
+	else if (fclk_offset == 2)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_2;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
 
@@ -376,23 +377,21 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
-	struct device *dev = &gpmc_onenand_device.dev;
-
 	/* Set sync timings in GPMC */
 	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
 			freq_ptr) < 0) {
-		dev_err(dev, "Unable to set synchronous mode\n");
+		pr_err("%s: Unable to set synchronous mode\n", __func__);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+struct gpmc_device_pdata *
+__init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
-	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
 
 	if (cpu_is_omap24xx() &&
 			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
@@ -401,8 +400,10 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
-	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		printk(KERN_ERR "Unable to register OneNAND device\n");
-		return;
-	}
+	gpmc_onenand_info.pdata = gpmc_onenand_data;
+	gpmc_onenand_info.pdata_size = sizeof(*gpmc_onenand_data);
+
+	gpmc_onenand_cs_info.cs = gpmc_onenand_data->cs;
+
+	return &gpmc_onenand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h
index 2858667..47cd710 100644
--- a/arch/arm/plat-omap/include/plat/onenand.h
+++ b/arch/arm/plat-omap/include/plat/onenand.h
@@ -40,14 +40,17 @@ struct omap_onenand_platform_data {
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d);
 
 #else
 
 #define board_onenand_data	NULL
 
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10


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

* [PATCH v4 08/39] ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for onenand. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-onenand.c        |  111 +++++++++++++++--------------
 arch/arm/plat-omap/include/plat/onenand.h |    7 +-
 2 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index a0fa9bb..d7775d5 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -25,9 +25,17 @@
 
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
-static struct platform_device gpmc_onenand_device = {
+#define ONENAND_IO_SIZE		SZ_128K
+
+static struct gpmc_cs_data gpmc_onenand_cs_info = {
+	.mem_size	= ONENAND_IO_SIZE,
+};
+
+static struct gpmc_device_pdata gpmc_onenand_info = {
 	.name		= "omap2-onenand",
 	.id		= -1,
+	.cs_data	= &gpmc_onenand_cs_info,
+	.num_cs		= 1,
 };
 
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -79,13 +87,17 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 
 	/* Configure GPMC for asynchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 |
+					GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
@@ -180,7 +192,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
 	int cs = cfg->cs, freq = *freq_ptr;
-	u32 reg;
 	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
@@ -276,27 +287,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg |= (1 << 7);
-		reg |= (1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
-	} else {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg &= ~(1 << 7);
-		reg &= ~(1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+		t.control.cs_extra_delay = true;
+		t.control.adv_extra_delay = true;
+		t.control.oe_extra_delay = true;
+		t.control.we_extra_delay = true;
 	}
 
 	/* Set synchronous read timings */
@@ -348,24 +342,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	}
 
 	/* Configure GPMC for synchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_WRAPBURST_SUPP |
-			  GPMC_CONFIG1_READMULTIPLE_SUPP |
-			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
-			  GPMC_CONFIG1_PAGE_LEN(2) |
-			  (cpu_is_omap34xx() ? 0 :
-				(GPMC_CONFIG1_WAIT_READ_MON |
-				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_DEVICETYPE_NOR |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 | GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR | GPMC_WRAPBURST |
+					GPMC_READMULTIPLE | GPMC_PAGE_LEN_16;
+	if (!cpu_is_omap34xx())
+		gpmc_onenand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAITPIN_0;
+	if (sync_read)
+		gpmc_onenand_cs_info.config |= GPMC_READTYPE_SYNC;
+	if (sync_write)
+		gpmc_onenand_cs_info.config |= GPMC_WRITETYPE_SYNC |
+						GPMC_WRITEMULTIPLE;
+	if (fclk_offset == 0)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_0;
+	else if (fclk_offset == 1)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_1;
+	else if (fclk_offset == 2)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_2;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
 
@@ -376,23 +377,21 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
-	struct device *dev = &gpmc_onenand_device.dev;
-
 	/* Set sync timings in GPMC */
 	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
 			freq_ptr) < 0) {
-		dev_err(dev, "Unable to set synchronous mode\n");
+		pr_err("%s: Unable to set synchronous mode\n", __func__);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+struct gpmc_device_pdata *
+__init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
-	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
 
 	if (cpu_is_omap24xx() &&
 			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
@@ -401,8 +400,10 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
-	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		printk(KERN_ERR "Unable to register OneNAND device\n");
-		return;
-	}
+	gpmc_onenand_info.pdata = gpmc_onenand_data;
+	gpmc_onenand_info.pdata_size = sizeof(*gpmc_onenand_data);
+
+	gpmc_onenand_cs_info.cs = gpmc_onenand_data->cs;
+
+	return &gpmc_onenand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h
index 2858667..47cd710 100644
--- a/arch/arm/plat-omap/include/plat/onenand.h
+++ b/arch/arm/plat-omap/include/plat/onenand.h
@@ -40,14 +40,17 @@ struct omap_onenand_platform_data {
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d);
 
 #else
 
 #define board_onenand_data	NULL
 
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 08/39] ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Currently gpmc is configured in platform for onenand. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-onenand.c        |  111 +++++++++++++++--------------
 arch/arm/plat-omap/include/plat/onenand.h |    7 +-
 2 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index a0fa9bb..d7775d5 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -25,9 +25,17 @@
 
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
-static struct platform_device gpmc_onenand_device = {
+#define ONENAND_IO_SIZE		SZ_128K
+
+static struct gpmc_cs_data gpmc_onenand_cs_info = {
+	.mem_size	= ONENAND_IO_SIZE,
+};
+
+static struct gpmc_device_pdata gpmc_onenand_info = {
 	.name		= "omap2-onenand",
 	.id		= -1,
+	.cs_data	= &gpmc_onenand_cs_info,
+	.num_cs		= 1,
 };
 
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -79,13 +87,17 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 
 	/* Configure GPMC for asynchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 |
+					GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
@@ -180,7 +192,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
 	int cs = cfg->cs, freq = *freq_ptr;
-	u32 reg;
 	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
@@ -276,27 +287,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg |= (1 << 7);
-		reg |= (1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
-	} else {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg &= ~(1 << 7);
-		reg &= ~(1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+		t.control.cs_extra_delay = true;
+		t.control.adv_extra_delay = true;
+		t.control.oe_extra_delay = true;
+		t.control.we_extra_delay = true;
 	}
 
 	/* Set synchronous read timings */
@@ -348,24 +342,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	}
 
 	/* Configure GPMC for synchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_WRAPBURST_SUPP |
-			  GPMC_CONFIG1_READMULTIPLE_SUPP |
-			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
-			  GPMC_CONFIG1_PAGE_LEN(2) |
-			  (cpu_is_omap34xx() ? 0 :
-				(GPMC_CONFIG1_WAIT_READ_MON |
-				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_DEVICETYPE_NOR |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 | GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR | GPMC_WRAPBURST |
+					GPMC_READMULTIPLE | GPMC_PAGE_LEN_16;
+	if (!cpu_is_omap34xx())
+		gpmc_onenand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAITPIN_0;
+	if (sync_read)
+		gpmc_onenand_cs_info.config |= GPMC_READTYPE_SYNC;
+	if (sync_write)
+		gpmc_onenand_cs_info.config |= GPMC_WRITETYPE_SYNC |
+						GPMC_WRITEMULTIPLE;
+	if (fclk_offset == 0)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_0;
+	else if (fclk_offset == 1)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_1;
+	else if (fclk_offset == 2)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_2;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
 
@@ -376,23 +377,21 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
-	struct device *dev = &gpmc_onenand_device.dev;
-
 	/* Set sync timings in GPMC */
 	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
 			freq_ptr) < 0) {
-		dev_err(dev, "Unable to set synchronous mode\n");
+		pr_err("%s: Unable to set synchronous mode\n", __func__);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+struct gpmc_device_pdata *
+__init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
-	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
 
 	if (cpu_is_omap24xx() &&
 			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
@@ -401,8 +400,10 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
-	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		printk(KERN_ERR "Unable to register OneNAND device\n");
-		return;
-	}
+	gpmc_onenand_info.pdata = gpmc_onenand_data;
+	gpmc_onenand_info.pdata_size = sizeof(*gpmc_onenand_data);
+
+	gpmc_onenand_cs_info.cs = gpmc_onenand_data->cs;
+
+	return &gpmc_onenand_info;
 }
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h
index 2858667..47cd710 100644
--- a/arch/arm/plat-omap/include/plat/onenand.h
+++ b/arch/arm/plat-omap/include/plat/onenand.h
@@ -40,14 +40,17 @@ struct omap_onenand_platform_data {
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d);
 
 #else
 
 #define board_onenand_data	NULL
 
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 09/39] ARM: OMAP2+: flash: Adapt to gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc driver has been converted to driver. Modify board_flash_init
so that it can setup gpmc driver platform details for boards

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-3430sdp.c |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c |    3 +-
 arch/arm/mach-omap2/board-flash.c   |   89 +++++++++++++++++++----------------
 arch/arm/mach-omap2/board-flash.h   |   11 +++--
 4 files changed, 58 insertions(+), 47 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index da75f23..ac2e398 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -620,7 +620,7 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 6ef350d..74195b7 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -204,7 +204,8 @@ static void __init omap_sdp_init(void)
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
+		NAND_BUSWIDTH_16, NULL);
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 8727c05..8deead9 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -39,46 +39,33 @@ static struct physmap_flash_data board_nor_data = {
 	.width		= 2,
 };
 
-static struct resource board_nor_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data gpmc_nor_cs_data = {
 };
 
-static struct platform_device board_nor_device = {
+static struct gpmc_device_pdata gpmc_nor_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-			.platform_data = &board_nor_data,
-	},
-	.num_resources	= 1,
-	.resource	= &board_nor_resource,
+	.cs_data	= &gpmc_nor_cs_data,
+	.num_cs		= 1,
 };
 
-static void
-__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+static __init struct gpmc_device_pdata *
+gpmc_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 {
-	int err;
-
 	board_nor_data.parts	= nor_parts;
 	board_nor_data.nr_parts	= nr_parts;
 
-	/* Configure start address and size of NOR device */
-	if (omap_rev() >= OMAP3430_REV_ES1_0) {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV2 - 1;
-	} else {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV1 - 1;
-	}
-	if (err < 0) {
-		pr_err("NOR: Can't request GPMC CS\n");
-		return;
-	}
-	if (platform_device_register(&board_nor_device) < 0)
-		pr_err("Unable to register NOR device\n");
+	gpmc_nor_cs_data.cs	= cs;
+
+	if (omap_rev() >= OMAP3430_REV_ES1_0)
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV2;
+	else
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV1;
+
+	gpmc_nor_data.pdata = &board_nor_data;
+	gpmc_nor_data.pdata_size = sizeof(board_nor_data);
+
+	return &gpmc_nor_data;
 }
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -183,8 +170,11 @@ unmap:
  *
  * @return - void.
  */
-void __init board_flash_init(struct flash_partitions partition_info[],
-			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
+__init struct gpmc_device_pdata **board_flash_init(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][GPMC_CS_NUM],
+				int nand_type,
+				struct gpmc_device_pdata **gpmc_data)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -193,13 +183,18 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	u8		idx;
 	unsigned char	*config_sel = NULL;
 
+	if (gpmc_data == NULL) {
+		pr_err("%s: NULL arguement passed\n", __func__);
+		return NULL;
+	}
+
 	/* REVISIT: Is this return correct idx for 2430 SDP?
 	 * for which cs configuration matches for 2430 SDP?
 	 */
 	idx = get_gpmc0_type();
 	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
 		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
-		return;
+		return gpmc_data;
 	}
 	config_sel = (unsigned char *)(chip_sel_board[idx]);
 
@@ -224,19 +219,31 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	if (norcs > GPMC_CS_NUM)
 		pr_err("NOR: Unable to find configuration in GPMC\n");
 	else
-		board_nor_init(partition_info[0].parts,
+		*gpmc_data++ = gpmc_nor_init(partition_info[0].parts,
 				partition_info[0].nr_parts, norcs);
 
 	if (onenandcs > GPMC_CS_NUM)
 		pr_err("OneNAND: Unable to find configuration in GPMC\n");
-	else
-		board_onenand_init(partition_info[1].parts,
-					partition_info[1].nr_parts, onenandcs);
+	else {
+		struct omap_onenand_platform_data *onenand_data;
+
+		onenand_data = board_onenand_init(partition_info[1].parts,
+				partition_info[1].nr_parts, onenandcs);
+		if (onenand_data != NULL)
+			*gpmc_data++ = gpmc_onenand_init(onenand_data);
+	}
 
 	if (nandcs > GPMC_CS_NUM)
 		pr_err("NAND: Unable to find configuration in GPMC\n");
-	else
-		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs,
-			nand_type, nand_default_timings);
+	else {
+		struct omap_nand_platform_data *nand_data;
+
+		nand_data = board_nand_init(partition_info[2].parts,
+				partition_info[2].nr_parts, nandcs,
+				nand_type, nand_default_timings);
+		if (nand_data != NULL)
+			*gpmc_data++ = gpmc_nand_init(nand_data);
+	}
+
+	return gpmc_data;
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 75ba49f..4dd733d 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -28,12 +28,15 @@ struct flash_partitions {
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM], int nand_type);
+extern struct gpmc_device_pdata **board_flash_init(
+		struct flash_partitions [], char chip_sel[][GPMC_CS_NUM],
+		int nand_type, struct gpmc_device_pdata **gpmc_data);
 #else
-static inline void board_flash_init(struct flash_partitions part[],
-				char chip_sel[][GPMC_CS_NUM], int nand_type)
+static inline struct gpmc_device_pdata **board_flash_init(
+	struct flash_partitions part[], char chip_sel[][GPMC_CS_NUM],
+	int nand_type, struct gpmc_device_pdata **gpmc_data)
 {
+	return NULL;
 }
 #endif
 
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 09/39] ARM: OMAP2+: flash: Adapt to gpmc driver
@ 2012-05-01 12:20     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc driver has been converted to driver. Modify board_flash_init
so that it can setup gpmc driver platform details for boards

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c |    3 +-
 arch/arm/mach-omap2/board-flash.c   |   89 +++++++++++++++++++----------------
 arch/arm/mach-omap2/board-flash.h   |   11 +++--
 4 files changed, 58 insertions(+), 47 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index da75f23..ac2e398 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -620,7 +620,7 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 6ef350d..74195b7 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -204,7 +204,8 @@ static void __init omap_sdp_init(void)
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
+		NAND_BUSWIDTH_16, NULL);
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 8727c05..8deead9 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -39,46 +39,33 @@ static struct physmap_flash_data board_nor_data = {
 	.width		= 2,
 };
 
-static struct resource board_nor_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data gpmc_nor_cs_data = {
 };
 
-static struct platform_device board_nor_device = {
+static struct gpmc_device_pdata gpmc_nor_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-			.platform_data = &board_nor_data,
-	},
-	.num_resources	= 1,
-	.resource	= &board_nor_resource,
+	.cs_data	= &gpmc_nor_cs_data,
+	.num_cs		= 1,
 };
 
-static void
-__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+static __init struct gpmc_device_pdata *
+gpmc_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 {
-	int err;
-
 	board_nor_data.parts	= nor_parts;
 	board_nor_data.nr_parts	= nr_parts;
 
-	/* Configure start address and size of NOR device */
-	if (omap_rev() >= OMAP3430_REV_ES1_0) {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV2 - 1;
-	} else {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV1 - 1;
-	}
-	if (err < 0) {
-		pr_err("NOR: Can't request GPMC CS\n");
-		return;
-	}
-	if (platform_device_register(&board_nor_device) < 0)
-		pr_err("Unable to register NOR device\n");
+	gpmc_nor_cs_data.cs	= cs;
+
+	if (omap_rev() >= OMAP3430_REV_ES1_0)
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV2;
+	else
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV1;
+
+	gpmc_nor_data.pdata = &board_nor_data;
+	gpmc_nor_data.pdata_size = sizeof(board_nor_data);
+
+	return &gpmc_nor_data;
 }
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -183,8 +170,11 @@ unmap:
  *
  * @return - void.
  */
-void __init board_flash_init(struct flash_partitions partition_info[],
-			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
+__init struct gpmc_device_pdata **board_flash_init(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][GPMC_CS_NUM],
+				int nand_type,
+				struct gpmc_device_pdata **gpmc_data)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -193,13 +183,18 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	u8		idx;
 	unsigned char	*config_sel = NULL;
 
+	if (gpmc_data == NULL) {
+		pr_err("%s: NULL arguement passed\n", __func__);
+		return NULL;
+	}
+
 	/* REVISIT: Is this return correct idx for 2430 SDP?
 	 * for which cs configuration matches for 2430 SDP?
 	 */
 	idx = get_gpmc0_type();
 	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
 		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
-		return;
+		return gpmc_data;
 	}
 	config_sel = (unsigned char *)(chip_sel_board[idx]);
 
@@ -224,19 +219,31 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	if (norcs > GPMC_CS_NUM)
 		pr_err("NOR: Unable to find configuration in GPMC\n");
 	else
-		board_nor_init(partition_info[0].parts,
+		*gpmc_data++ = gpmc_nor_init(partition_info[0].parts,
 				partition_info[0].nr_parts, norcs);
 
 	if (onenandcs > GPMC_CS_NUM)
 		pr_err("OneNAND: Unable to find configuration in GPMC\n");
-	else
-		board_onenand_init(partition_info[1].parts,
-					partition_info[1].nr_parts, onenandcs);
+	else {
+		struct omap_onenand_platform_data *onenand_data;
+
+		onenand_data = board_onenand_init(partition_info[1].parts,
+				partition_info[1].nr_parts, onenandcs);
+		if (onenand_data != NULL)
+			*gpmc_data++ = gpmc_onenand_init(onenand_data);
+	}
 
 	if (nandcs > GPMC_CS_NUM)
 		pr_err("NAND: Unable to find configuration in GPMC\n");
-	else
-		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs,
-			nand_type, nand_default_timings);
+	else {
+		struct omap_nand_platform_data *nand_data;
+
+		nand_data = board_nand_init(partition_info[2].parts,
+				partition_info[2].nr_parts, nandcs,
+				nand_type, nand_default_timings);
+		if (nand_data != NULL)
+			*gpmc_data++ = gpmc_nand_init(nand_data);
+	}
+
+	return gpmc_data;
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 75ba49f..4dd733d 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -28,12 +28,15 @@ struct flash_partitions {
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM], int nand_type);
+extern struct gpmc_device_pdata **board_flash_init(
+		struct flash_partitions [], char chip_sel[][GPMC_CS_NUM],
+		int nand_type, struct gpmc_device_pdata **gpmc_data);
 #else
-static inline void board_flash_init(struct flash_partitions part[],
-				char chip_sel[][GPMC_CS_NUM], int nand_type)
+static inline struct gpmc_device_pdata **board_flash_init(
+	struct flash_partitions part[], char chip_sel[][GPMC_CS_NUM],
+	int nand_type, struct gpmc_device_pdata **gpmc_data)
 {
+	return NULL;
 }
 #endif
 
-- 
1.7.10

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

* [PATCH v4 09/39] ARM: OMAP2+: flash: Adapt to gpmc driver
@ 2012-05-01 12:20     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc driver has been converted to driver. Modify board_flash_init
so that it can setup gpmc driver platform details for boards

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c |    3 +-
 arch/arm/mach-omap2/board-flash.c   |   89 +++++++++++++++++++----------------
 arch/arm/mach-omap2/board-flash.h   |   11 +++--
 4 files changed, 58 insertions(+), 47 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index da75f23..ac2e398 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -620,7 +620,7 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 6ef350d..74195b7 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -204,7 +204,8 @@ static void __init omap_sdp_init(void)
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
+		NAND_BUSWIDTH_16, NULL);
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 8727c05..8deead9 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -39,46 +39,33 @@ static struct physmap_flash_data board_nor_data = {
 	.width		= 2,
 };
 
-static struct resource board_nor_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data gpmc_nor_cs_data = {
 };
 
-static struct platform_device board_nor_device = {
+static struct gpmc_device_pdata gpmc_nor_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-			.platform_data = &board_nor_data,
-	},
-	.num_resources	= 1,
-	.resource	= &board_nor_resource,
+	.cs_data	= &gpmc_nor_cs_data,
+	.num_cs		= 1,
 };
 
-static void
-__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+static __init struct gpmc_device_pdata *
+gpmc_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 {
-	int err;
-
 	board_nor_data.parts	= nor_parts;
 	board_nor_data.nr_parts	= nr_parts;
 
-	/* Configure start address and size of NOR device */
-	if (omap_rev() >= OMAP3430_REV_ES1_0) {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV2 - 1;
-	} else {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV1 - 1;
-	}
-	if (err < 0) {
-		pr_err("NOR: Can't request GPMC CS\n");
-		return;
-	}
-	if (platform_device_register(&board_nor_device) < 0)
-		pr_err("Unable to register NOR device\n");
+	gpmc_nor_cs_data.cs	= cs;
+
+	if (omap_rev() >= OMAP3430_REV_ES1_0)
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV2;
+	else
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV1;
+
+	gpmc_nor_data.pdata = &board_nor_data;
+	gpmc_nor_data.pdata_size = sizeof(board_nor_data);
+
+	return &gpmc_nor_data;
 }
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -183,8 +170,11 @@ unmap:
  *
  * @return - void.
  */
-void __init board_flash_init(struct flash_partitions partition_info[],
-			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
+__init struct gpmc_device_pdata **board_flash_init(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][GPMC_CS_NUM],
+				int nand_type,
+				struct gpmc_device_pdata **gpmc_data)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -193,13 +183,18 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	u8		idx;
 	unsigned char	*config_sel = NULL;
 
+	if (gpmc_data == NULL) {
+		pr_err("%s: NULL arguement passed\n", __func__);
+		return NULL;
+	}
+
 	/* REVISIT: Is this return correct idx for 2430 SDP?
 	 * for which cs configuration matches for 2430 SDP?
 	 */
 	idx = get_gpmc0_type();
 	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
 		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
-		return;
+		return gpmc_data;
 	}
 	config_sel = (unsigned char *)(chip_sel_board[idx]);
 
@@ -224,19 +219,31 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	if (norcs > GPMC_CS_NUM)
 		pr_err("NOR: Unable to find configuration in GPMC\n");
 	else
-		board_nor_init(partition_info[0].parts,
+		*gpmc_data++ = gpmc_nor_init(partition_info[0].parts,
 				partition_info[0].nr_parts, norcs);
 
 	if (onenandcs > GPMC_CS_NUM)
 		pr_err("OneNAND: Unable to find configuration in GPMC\n");
-	else
-		board_onenand_init(partition_info[1].parts,
-					partition_info[1].nr_parts, onenandcs);
+	else {
+		struct omap_onenand_platform_data *onenand_data;
+
+		onenand_data = board_onenand_init(partition_info[1].parts,
+				partition_info[1].nr_parts, onenandcs);
+		if (onenand_data != NULL)
+			*gpmc_data++ = gpmc_onenand_init(onenand_data);
+	}
 
 	if (nandcs > GPMC_CS_NUM)
 		pr_err("NAND: Unable to find configuration in GPMC\n");
-	else
-		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs,
-			nand_type, nand_default_timings);
+	else {
+		struct omap_nand_platform_data *nand_data;
+
+		nand_data = board_nand_init(partition_info[2].parts,
+				partition_info[2].nr_parts, nandcs,
+				nand_type, nand_default_timings);
+		if (nand_data != NULL)
+			*gpmc_data++ = gpmc_nand_init(nand_data);
+	}
+
+	return gpmc_data;
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 75ba49f..4dd733d 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -28,12 +28,15 @@ struct flash_partitions {
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM], int nand_type);
+extern struct gpmc_device_pdata **board_flash_init(
+		struct flash_partitions [], char chip_sel[][GPMC_CS_NUM],
+		int nand_type, struct gpmc_device_pdata **gpmc_data);
 #else
-static inline void board_flash_init(struct flash_partitions part[],
-				char chip_sel[][GPMC_CS_NUM], int nand_type)
+static inline struct gpmc_device_pdata **board_flash_init(
+	struct flash_partitions part[], char chip_sel[][GPMC_CS_NUM],
+	int nand_type, struct gpmc_device_pdata **gpmc_data)
 {
+	return NULL;
 }
 #endif
 
-- 
1.7.10

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

* [PATCH v4 10/39] ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc has been converted to driver. And all gpmc related
configuration would be done by gpmc driver. Provide
gpmc driver with sufficient information so that it can
configure.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   59 ++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |    9 +++-
 2 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index b6c77be..2c89685 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -24,13 +24,8 @@
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
-static struct resource gpmc_smsc911x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
+static struct resource gpmc_smsc911x_resources = {
+	.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 };
 
 static struct smsc911x_platform_config gpmc_smsc911x_config = {
@@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = {
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
+__init struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
-	struct platform_device *pdev;
-	unsigned long cs_mem_base;
 	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem region\n");
-		return;
+	gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL);
+	if (gpmc_pdev == NULL)
+		return gpmc_pdev;
+
+	gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL);
+	if (gpmc_pdev == NULL) {
+		kfree(gpmc_pdev);
+		return NULL;
 	}
 
-	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
-	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+	gpmc_pdev->cs_data = gpmc_cs;
+	gpmc_pdev->num_cs = 1;
+	gpmc_pdev->name = "smsc911x";
+	gpmc_pdev->id = gpmc_cfg->id;
+	gpmc_pdev->pdata = &gpmc_smsc911x_config;
+	gpmc_pdev->pdata_size = sizeof(gpmc_smsc911x_config);
+
+	gpmc_cs->cs = gpmc_cfg->cs;
+	gpmc_cs->mem_size = 0x100;
+
+	gpmc_pdev->per_res = &gpmc_smsc911x_resources;
+	gpmc_pdev->per_res_cnt = 1;
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
 		pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
 		goto free1;
 	}
 
-	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
 		ret = gpio_request_one(gpmc_cfg->gpio_reset,
@@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 
 	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
 
-	pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
-		 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
-		 &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
-	if (!pdev) {
-		pr_err("Unable to register platform device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free2;
-	}
-
-	return;
+	return gpmc_pdev;
 
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
 free1:
-	gpmc_cs_free(gpmc_cfg->cs);
+	kfree(gpmc_cs);
+	kfree(gpmc_pdev);
 
 	pr_err("Could not initialize smsc911x device\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
index ea6c9c8..66dc7f1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#include<plat/gpmc.h>
+
 #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
 
 struct omap_smsc911x_platform_data {
@@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data {
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
 
 #else
 
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10


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

* [PATCH v4 10/39] ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc has been converted to driver. And all gpmc related
configuration would be done by gpmc driver. Provide
gpmc driver with sufficient information so that it can
configure.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   59 ++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |    9 +++-
 2 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index b6c77be..2c89685 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -24,13 +24,8 @@
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
-static struct resource gpmc_smsc911x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
+static struct resource gpmc_smsc911x_resources = {
+	.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 };
 
 static struct smsc911x_platform_config gpmc_smsc911x_config = {
@@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = {
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
+__init struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
-	struct platform_device *pdev;
-	unsigned long cs_mem_base;
 	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem region\n");
-		return;
+	gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL);
+	if (gpmc_pdev == NULL)
+		return gpmc_pdev;
+
+	gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL);
+	if (gpmc_pdev == NULL) {
+		kfree(gpmc_pdev);
+		return NULL;
 	}
 
-	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
-	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+	gpmc_pdev->cs_data = gpmc_cs;
+	gpmc_pdev->num_cs = 1;
+	gpmc_pdev->name = "smsc911x";
+	gpmc_pdev->id = gpmc_cfg->id;
+	gpmc_pdev->pdata = &gpmc_smsc911x_config;
+	gpmc_pdev->pdata_size = sizeof(gpmc_smsc911x_config);
+
+	gpmc_cs->cs = gpmc_cfg->cs;
+	gpmc_cs->mem_size = 0x100;
+
+	gpmc_pdev->per_res = &gpmc_smsc911x_resources;
+	gpmc_pdev->per_res_cnt = 1;
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
 		pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
 		goto free1;
 	}
 
-	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
 		ret = gpio_request_one(gpmc_cfg->gpio_reset,
@@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 
 	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
 
-	pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
-		 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
-		 &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
-	if (!pdev) {
-		pr_err("Unable to register platform device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free2;
-	}
-
-	return;
+	return gpmc_pdev;
 
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
 free1:
-	gpmc_cs_free(gpmc_cfg->cs);
+	kfree(gpmc_cs);
+	kfree(gpmc_pdev);
 
 	pr_err("Could not initialize smsc911x device\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
index ea6c9c8..66dc7f1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#include<plat/gpmc.h>
+
 #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
 
 struct omap_smsc911x_platform_data {
@@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data {
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
 
 #else
 
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 10/39] ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc has been converted to driver. And all gpmc related
configuration would be done by gpmc driver. Provide
gpmc driver with sufficient information so that it can
configure.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   59 ++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |    9 +++-
 2 files changed, 39 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index b6c77be..2c89685 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -24,13 +24,8 @@
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
-static struct resource gpmc_smsc911x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
+static struct resource gpmc_smsc911x_resources = {
+	.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 };
 
 static struct smsc911x_platform_config gpmc_smsc911x_config = {
@@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = {
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
+__init struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
-	struct platform_device *pdev;
-	unsigned long cs_mem_base;
 	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem region\n");
-		return;
+	gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL);
+	if (gpmc_pdev == NULL)
+		return gpmc_pdev;
+
+	gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL);
+	if (gpmc_pdev == NULL) {
+		kfree(gpmc_pdev);
+		return NULL;
 	}
 
-	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
-	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+	gpmc_pdev->cs_data = gpmc_cs;
+	gpmc_pdev->num_cs = 1;
+	gpmc_pdev->name = "smsc911x";
+	gpmc_pdev->id = gpmc_cfg->id;
+	gpmc_pdev->pdata = &gpmc_smsc911x_config;
+	gpmc_pdev->pdata_size = sizeof(gpmc_smsc911x_config);
+
+	gpmc_cs->cs = gpmc_cfg->cs;
+	gpmc_cs->mem_size = 0x100;
+
+	gpmc_pdev->per_res = &gpmc_smsc911x_resources;
+	gpmc_pdev->per_res_cnt = 1;
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
 		pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
 		goto free1;
 	}
 
-	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
 		ret = gpio_request_one(gpmc_cfg->gpio_reset,
@@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 
 	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
 
-	pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
-		 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
-		 &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
-	if (!pdev) {
-		pr_err("Unable to register platform device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free2;
-	}
-
-	return;
+	return gpmc_pdev;
 
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
 free1:
-	gpmc_cs_free(gpmc_cfg->cs);
+	kfree(gpmc_cs);
+	kfree(gpmc_pdev);
 
 	pr_err("Could not initialize smsc911x device\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
index ea6c9c8..66dc7f1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#include<plat/gpmc.h>
+
 #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
 
 struct omap_smsc911x_platform_data {
@@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data {
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
 
 #else
 
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 11/39] ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:20   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for smc91x. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c           |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    1 +
 arch/arm/mach-omap2/board-3630sdp.c           |    1 +
 arch/arm/mach-omap2/gpmc-smc91x.c             |   87 +++++++++++--------------
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h |   10 ++-
 5 files changed, 47 insertions(+), 54 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index e658f83..68679a8 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -175,7 +175,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.gpio_irq	= 149,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
-
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ac2e398..367a466 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -434,6 +434,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs		= 3,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 74195b7..143e47f 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -32,6 +32,7 @@
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index ba10c24..9389df1 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -23,13 +23,8 @@
 
 static struct omap_smc91x_platform_data *gpmc_cfg;
 
-static struct resource gpmc_smc91x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct resource gpmc_smc91x_resource = {
+	.flags		= IORESOURCE_IRQ,
 };
 
 static struct smc91x_platdata gpmc_smc91x_info = {
@@ -38,14 +33,17 @@ static struct smc91x_platdata gpmc_smc91x_info = {
 	.ledb	= RPC_LED_TX_RX,
 };
 
-static struct platform_device gpmc_smc91x_device = {
+static struct gpmc_cs_data gpmc_smc91x_cs_data;
+
+static struct gpmc_device_pdata gpmc_smc91x_data = {
 	.name		= "smc91x",
 	.id		= -1,
-	.dev		= {
-		.platform_data = &gpmc_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(gpmc_smc91x_resources),
-	.resource	= gpmc_smc91x_resources,
+	.pdata		= &gpmc_smc91x_info,
+	.pdata_size	= sizeof(gpmc_smc91x_info),
+	.per_res	= &gpmc_smc91x_resource,
+	.per_res_cnt	= 1,
+	.cs_data	= &gpmc_smc91x_cs_data,
+	.num_cs		= 1,
 };
 
 /*
@@ -54,9 +52,10 @@ static struct platform_device gpmc_smc91x_device = {
  * http://www.smsc.com/main/catalog/lan91c96.html
  * REVISIT: Level shifters can add at least to the access latency.
  */
-static int smc91c96_gpmc_retime(void)
+static void smc91c96_gpmc_retime(void)
 {
-	struct gpmc_timings t;
+	/* GPMC timing configuration after this function dies, hence static */
+	static struct gpmc_timings t;
 	const int t3 = 10;	/* Figure 12.2 read and 12.4 write */
 	const int t4_r = 20;	/* Figure 12.2 read */
 	const int t4_w = 5;	/* Figure 12.4 write */
@@ -65,7 +64,6 @@ static int smc91c96_gpmc_retime(void)
 	const int t7 = 5;	/* Figure 12.4 write */
 	const int t8 = 5;	/* Figure 12.4 write */
 	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
-	u32 l;
 
 	memset(&t, 0, sizeof(t));
 
@@ -93,16 +91,17 @@ static int smc91c96_gpmc_retime(void)
 	t.cs_wr_off = t.we_off + t4_w;
 	t.wr_cycle = t20 - t.we_on;
 
-	l = GPMC_CONFIG1_DEVICESIZE_16;
+	gpmc_smc91x_cs_data.have_config = true;
+	gpmc_smc91x_cs_data.config = GPMC_DEVICESIZE_16;
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		l |= GPMC_CONFIG1_MUXADDDATA;
+		gpmc_smc91x_cs_data.config |= GPMC_MUXADDDATA;
 	if (gpmc_cfg->flags & GPMC_READ_MON)
-		l |= GPMC_CONFIG1_WAIT_READ_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_READ_MON;
 	if (gpmc_cfg->flags & GPMC_WRITE_MON)
-		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_WRITE_MON;
+	/* waitpin macros in GPMC header file has to be used by platforms */
 	if (gpmc_cfg->wait_pin)
-		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+		gpmc_smc91x_cs_data.config |= gpmc_cfg->wait_pin;
 
 	/*
 	 * FIXME: Calculate the address and data bus muxed timings.
@@ -111,10 +110,10 @@ static int smc91c96_gpmc_retime(void)
 	 * FPGA in between smc91x and omap as the timings are different
 	 * from above?
 	 */
-	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		return 0;
+	if (gpmc_cfg->skip_timing)
+		return;
 
-	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+	gpmc_smc91x_cs_data.timing = &t;
 }
 
 /*
@@ -122,9 +121,9 @@ static int smc91c96_gpmc_retime(void)
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
+__init struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 {
-	unsigned long cs_mem_base;
 	int ret;
 
 	gpmc_cfg = board_data;
@@ -132,25 +131,19 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 	if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
 		gpmc_cfg->retime = smc91c96_gpmc_retime;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
-	}
+	gpmc_smc91x_cs_data.cs		= gpmc_cfg->cs;
+	gpmc_smc91x_cs_data.mem_offset	= 0x300;
+	gpmc_smc91x_cs_data.mem_size	= 0x10;
 
-	gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
-	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
-	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+	gpmc_smc91x_resource.flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
-	if (gpmc_cfg->retime) {
-		ret = gpmc_cfg->retime();
-		if (ret != 0)
-			goto free1;
-	}
+	if (gpmc_cfg->retime)
+		gpmc_cfg->retime();
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0)
-		goto free1;
+		return NULL;
 
-	gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smc91x_resource.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpmc_cfg->gpio_pwrdwn) {
 		ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn,
@@ -170,21 +163,15 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 		gpio_set_value(gpmc_cfg->gpio_reset, 0);
 	}
 
-	if (platform_device_register(&gpmc_smc91x_device) < 0) {
-		printk(KERN_ERR "Unable to register smc91x device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free3;
-	}
-
-	return;
+	return &gpmc_smc91x_data;
 
 free3:
 	if (gpmc_cfg->gpio_pwrdwn)
 		gpio_free(gpmc_cfg->gpio_pwrdwn);
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
-free1:
-	gpmc_cs_free(gpmc_cfg->cs);
 
 	printk(KERN_ERR "Could not initialize smc91x\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
index b64fbee..f3a01b1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
@@ -22,20 +22,24 @@ struct omap_smc91x_platform_data {
 	int	gpio_reset;
 	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
 	u32	flags;
-	int	(*retime)(void);
+	bool	skip_timing;
+	void	(*retime)(void);
 };
 
 #if defined(CONFIG_SMC91X) || \
 	defined(CONFIG_SMC91X_MODULE)
 
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
 
 #else
 
 #define board_smc91x_data	NULL
 
-static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10


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

* [PATCH v4 11/39] ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for smc91x. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c           |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    1 +
 arch/arm/mach-omap2/board-3630sdp.c           |    1 +
 arch/arm/mach-omap2/gpmc-smc91x.c             |   87 +++++++++++--------------
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h |   10 ++-
 5 files changed, 47 insertions(+), 54 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index e658f83..68679a8 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -175,7 +175,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.gpio_irq	= 149,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
-
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ac2e398..367a466 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -434,6 +434,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs		= 3,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 74195b7..143e47f 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -32,6 +32,7 @@
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index ba10c24..9389df1 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -23,13 +23,8 @@
 
 static struct omap_smc91x_platform_data *gpmc_cfg;
 
-static struct resource gpmc_smc91x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct resource gpmc_smc91x_resource = {
+	.flags		= IORESOURCE_IRQ,
 };
 
 static struct smc91x_platdata gpmc_smc91x_info = {
@@ -38,14 +33,17 @@ static struct smc91x_platdata gpmc_smc91x_info = {
 	.ledb	= RPC_LED_TX_RX,
 };
 
-static struct platform_device gpmc_smc91x_device = {
+static struct gpmc_cs_data gpmc_smc91x_cs_data;
+
+static struct gpmc_device_pdata gpmc_smc91x_data = {
 	.name		= "smc91x",
 	.id		= -1,
-	.dev		= {
-		.platform_data = &gpmc_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(gpmc_smc91x_resources),
-	.resource	= gpmc_smc91x_resources,
+	.pdata		= &gpmc_smc91x_info,
+	.pdata_size	= sizeof(gpmc_smc91x_info),
+	.per_res	= &gpmc_smc91x_resource,
+	.per_res_cnt	= 1,
+	.cs_data	= &gpmc_smc91x_cs_data,
+	.num_cs		= 1,
 };
 
 /*
@@ -54,9 +52,10 @@ static struct platform_device gpmc_smc91x_device = {
  * http://www.smsc.com/main/catalog/lan91c96.html
  * REVISIT: Level shifters can add at least to the access latency.
  */
-static int smc91c96_gpmc_retime(void)
+static void smc91c96_gpmc_retime(void)
 {
-	struct gpmc_timings t;
+	/* GPMC timing configuration after this function dies, hence static */
+	static struct gpmc_timings t;
 	const int t3 = 10;	/* Figure 12.2 read and 12.4 write */
 	const int t4_r = 20;	/* Figure 12.2 read */
 	const int t4_w = 5;	/* Figure 12.4 write */
@@ -65,7 +64,6 @@ static int smc91c96_gpmc_retime(void)
 	const int t7 = 5;	/* Figure 12.4 write */
 	const int t8 = 5;	/* Figure 12.4 write */
 	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
-	u32 l;
 
 	memset(&t, 0, sizeof(t));
 
@@ -93,16 +91,17 @@ static int smc91c96_gpmc_retime(void)
 	t.cs_wr_off = t.we_off + t4_w;
 	t.wr_cycle = t20 - t.we_on;
 
-	l = GPMC_CONFIG1_DEVICESIZE_16;
+	gpmc_smc91x_cs_data.have_config = true;
+	gpmc_smc91x_cs_data.config = GPMC_DEVICESIZE_16;
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		l |= GPMC_CONFIG1_MUXADDDATA;
+		gpmc_smc91x_cs_data.config |= GPMC_MUXADDDATA;
 	if (gpmc_cfg->flags & GPMC_READ_MON)
-		l |= GPMC_CONFIG1_WAIT_READ_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_READ_MON;
 	if (gpmc_cfg->flags & GPMC_WRITE_MON)
-		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_WRITE_MON;
+	/* waitpin macros in GPMC header file has to be used by platforms */
 	if (gpmc_cfg->wait_pin)
-		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+		gpmc_smc91x_cs_data.config |= gpmc_cfg->wait_pin;
 
 	/*
 	 * FIXME: Calculate the address and data bus muxed timings.
@@ -111,10 +110,10 @@ static int smc91c96_gpmc_retime(void)
 	 * FPGA in between smc91x and omap as the timings are different
 	 * from above?
 	 */
-	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		return 0;
+	if (gpmc_cfg->skip_timing)
+		return;
 
-	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+	gpmc_smc91x_cs_data.timing = &t;
 }
 
 /*
@@ -122,9 +121,9 @@ static int smc91c96_gpmc_retime(void)
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
+__init struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 {
-	unsigned long cs_mem_base;
 	int ret;
 
 	gpmc_cfg = board_data;
@@ -132,25 +131,19 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 	if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
 		gpmc_cfg->retime = smc91c96_gpmc_retime;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
-	}
+	gpmc_smc91x_cs_data.cs		= gpmc_cfg->cs;
+	gpmc_smc91x_cs_data.mem_offset	= 0x300;
+	gpmc_smc91x_cs_data.mem_size	= 0x10;
 
-	gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
-	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
-	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+	gpmc_smc91x_resource.flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
-	if (gpmc_cfg->retime) {
-		ret = gpmc_cfg->retime();
-		if (ret != 0)
-			goto free1;
-	}
+	if (gpmc_cfg->retime)
+		gpmc_cfg->retime();
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0)
-		goto free1;
+		return NULL;
 
-	gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smc91x_resource.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpmc_cfg->gpio_pwrdwn) {
 		ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn,
@@ -170,21 +163,15 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 		gpio_set_value(gpmc_cfg->gpio_reset, 0);
 	}
 
-	if (platform_device_register(&gpmc_smc91x_device) < 0) {
-		printk(KERN_ERR "Unable to register smc91x device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free3;
-	}
-
-	return;
+	return &gpmc_smc91x_data;
 
 free3:
 	if (gpmc_cfg->gpio_pwrdwn)
 		gpio_free(gpmc_cfg->gpio_pwrdwn);
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
-free1:
-	gpmc_cs_free(gpmc_cfg->cs);
 
 	printk(KERN_ERR "Could not initialize smc91x\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
index b64fbee..f3a01b1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
@@ -22,20 +22,24 @@ struct omap_smc91x_platform_data {
 	int	gpio_reset;
 	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
 	u32	flags;
-	int	(*retime)(void);
+	bool	skip_timing;
+	void	(*retime)(void);
 };
 
 #if defined(CONFIG_SMC91X) || \
 	defined(CONFIG_SMC91X_MODULE)
 
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
 
 #else
 
 #define board_smc91x_data	NULL
 
-static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 11/39] ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
@ 2012-05-01 12:20   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Currently gpmc is configured in platform for smc91x. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c           |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    1 +
 arch/arm/mach-omap2/board-3630sdp.c           |    1 +
 arch/arm/mach-omap2/gpmc-smc91x.c             |   87 +++++++++++--------------
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h |   10 ++-
 5 files changed, 47 insertions(+), 54 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index e658f83..68679a8 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -175,7 +175,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.gpio_irq	= 149,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
-
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ac2e398..367a466 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -434,6 +434,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs		= 3,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 74195b7..143e47f 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -32,6 +32,7 @@
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index ba10c24..9389df1 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -23,13 +23,8 @@
 
 static struct omap_smc91x_platform_data *gpmc_cfg;
 
-static struct resource gpmc_smc91x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct resource gpmc_smc91x_resource = {
+	.flags		= IORESOURCE_IRQ,
 };
 
 static struct smc91x_platdata gpmc_smc91x_info = {
@@ -38,14 +33,17 @@ static struct smc91x_platdata gpmc_smc91x_info = {
 	.ledb	= RPC_LED_TX_RX,
 };
 
-static struct platform_device gpmc_smc91x_device = {
+static struct gpmc_cs_data gpmc_smc91x_cs_data;
+
+static struct gpmc_device_pdata gpmc_smc91x_data = {
 	.name		= "smc91x",
 	.id		= -1,
-	.dev		= {
-		.platform_data = &gpmc_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(gpmc_smc91x_resources),
-	.resource	= gpmc_smc91x_resources,
+	.pdata		= &gpmc_smc91x_info,
+	.pdata_size	= sizeof(gpmc_smc91x_info),
+	.per_res	= &gpmc_smc91x_resource,
+	.per_res_cnt	= 1,
+	.cs_data	= &gpmc_smc91x_cs_data,
+	.num_cs		= 1,
 };
 
 /*
@@ -54,9 +52,10 @@ static struct platform_device gpmc_smc91x_device = {
  * http://www.smsc.com/main/catalog/lan91c96.html
  * REVISIT: Level shifters can add at least to the access latency.
  */
-static int smc91c96_gpmc_retime(void)
+static void smc91c96_gpmc_retime(void)
 {
-	struct gpmc_timings t;
+	/* GPMC timing configuration after this function dies, hence static */
+	static struct gpmc_timings t;
 	const int t3 = 10;	/* Figure 12.2 read and 12.4 write */
 	const int t4_r = 20;	/* Figure 12.2 read */
 	const int t4_w = 5;	/* Figure 12.4 write */
@@ -65,7 +64,6 @@ static int smc91c96_gpmc_retime(void)
 	const int t7 = 5;	/* Figure 12.4 write */
 	const int t8 = 5;	/* Figure 12.4 write */
 	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
-	u32 l;
 
 	memset(&t, 0, sizeof(t));
 
@@ -93,16 +91,17 @@ static int smc91c96_gpmc_retime(void)
 	t.cs_wr_off = t.we_off + t4_w;
 	t.wr_cycle = t20 - t.we_on;
 
-	l = GPMC_CONFIG1_DEVICESIZE_16;
+	gpmc_smc91x_cs_data.have_config = true;
+	gpmc_smc91x_cs_data.config = GPMC_DEVICESIZE_16;
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		l |= GPMC_CONFIG1_MUXADDDATA;
+		gpmc_smc91x_cs_data.config |= GPMC_MUXADDDATA;
 	if (gpmc_cfg->flags & GPMC_READ_MON)
-		l |= GPMC_CONFIG1_WAIT_READ_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_READ_MON;
 	if (gpmc_cfg->flags & GPMC_WRITE_MON)
-		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+		gpmc_smc91x_cs_data.config |= GPMC_WAIT_WRITE_MON;
+	/* waitpin macros in GPMC header file has to be used by platforms */
 	if (gpmc_cfg->wait_pin)
-		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+		gpmc_smc91x_cs_data.config |= gpmc_cfg->wait_pin;
 
 	/*
 	 * FIXME: Calculate the address and data bus muxed timings.
@@ -111,10 +110,10 @@ static int smc91c96_gpmc_retime(void)
 	 * FPGA in between smc91x and omap as the timings are different
 	 * from above?
 	 */
-	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		return 0;
+	if (gpmc_cfg->skip_timing)
+		return;
 
-	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+	gpmc_smc91x_cs_data.timing = &t;
 }
 
 /*
@@ -122,9 +121,9 @@ static int smc91c96_gpmc_retime(void)
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
+__init struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 {
-	unsigned long cs_mem_base;
 	int ret;
 
 	gpmc_cfg = board_data;
@@ -132,25 +131,19 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 	if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
 		gpmc_cfg->retime = smc91c96_gpmc_retime;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
-	}
+	gpmc_smc91x_cs_data.cs		= gpmc_cfg->cs;
+	gpmc_smc91x_cs_data.mem_offset	= 0x300;
+	gpmc_smc91x_cs_data.mem_size	= 0x10;
 
-	gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
-	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
-	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+	gpmc_smc91x_resource.flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
-	if (gpmc_cfg->retime) {
-		ret = gpmc_cfg->retime();
-		if (ret != 0)
-			goto free1;
-	}
+	if (gpmc_cfg->retime)
+		gpmc_cfg->retime();
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0)
-		goto free1;
+		return NULL;
 
-	gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smc91x_resource.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpmc_cfg->gpio_pwrdwn) {
 		ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn,
@@ -170,21 +163,15 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 		gpio_set_value(gpmc_cfg->gpio_reset, 0);
 	}
 
-	if (platform_device_register(&gpmc_smc91x_device) < 0) {
-		printk(KERN_ERR "Unable to register smc91x device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free3;
-	}
-
-	return;
+	return &gpmc_smc91x_data;
 
 free3:
 	if (gpmc_cfg->gpio_pwrdwn)
 		gpio_free(gpmc_cfg->gpio_pwrdwn);
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
-free1:
-	gpmc_cs_free(gpmc_cfg->cs);
 
 	printk(KERN_ERR "Could not initialize smc91x\n");
+
+	return NULL;
 }
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
index b64fbee..f3a01b1 100644
--- a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+++ b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
@@ -22,20 +22,24 @@ struct omap_smc91x_platform_data {
 	int	gpio_reset;
 	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
 	u32	flags;
-	int	(*retime)(void);
+	bool	skip_timing;
+	void	(*retime)(void);
 };
 
 #if defined(CONFIG_SMC91X) || \
 	defined(CONFIG_SMC91X_MODULE)
 
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
 
 #else
 
 #define board_smc91x_data	NULL
 
-static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
-- 
1.7.10

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

* [PATCH v4 12/39] ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for tusb6010. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/usb-tusb6010.c |  177 ++++++++++++++----------------------
 include/linux/usb/musb.h           |    4 +-
 2 files changed, 70 insertions(+), 111 deletions(-)

diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index db84a46..d7817d2 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -22,6 +22,24 @@
 
 #include "mux.h"
 
+static struct resource tusb_resources = {
+	.name	= "mc",
+	.flags	= IORESOURCE_IRQ,
+};
+
+#define	TUSB_GPMC_CS_ASYNC_IDX	1
+#define	TUSB_GPMC_CS_SYNC_IDX	2
+#define	TUSB_GPMC_CS_NUM	2
+
+static struct gpmc_cs_data gpmc_tusb_cs_data[TUSB_GPMC_CS_NUM];
+
+static struct gpmc_device_pdata gpmc_tusb_data = {
+	.name		= "musb-tusb",
+	.id		= -1,
+	.per_res	= &tusb_resources,
+	.per_res_cnt	= 1,
+};
+
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
@@ -51,9 +69,9 @@ next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static void tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -106,12 +124,12 @@ static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(async_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].timing = &t;
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -174,71 +192,30 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(sync_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].timing = &t;
+
+	return 0;
 }
 
 extern unsigned long gpmc_get_fclk_period(void);
 
 /* tusb driver calls this when it changes the chip's clocking */
-int tusb6010_platform_retime(unsigned is_refclk)
+static int tusb6010_platform_retime(unsigned is_refclk)
 {
-	static const char	error[] =
-		KERN_ERR "tusb6010 %s retime error %d\n";
-
 	unsigned	fclk_ps = gpmc_get_fclk_period();
 	unsigned	sysclk_ps;
-	int		status;
 
 	if (!refclk_psec || fclk_ps == 0)
 		return -ENODEV;
 
 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
 
-	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
-	if (status < 0) {
-		printk(error, "async", status);
-		goto done;
-	}
-	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
-	if (status < 0)
-		printk(error, "sync", status);
-done:
-	return status;
+	tusb_set_async_mode(sysclk_ps, fclk_ps);
+	return tusb_set_sync_mode(sysclk_ps, fclk_ps);
 }
-EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
-
-static struct resource tusb_resources[] = {
-	/* Order is significant!  The start/end fields
-	 * are updated during setup..
-	 */
-	{ /* Asynchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* Synchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* IRQ */
-		.name	= "mc",
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 tusb_dmamask = ~(u32)0;
-
-static struct platform_device tusb_device = {
-	.name		= "musb-tusb",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &tusb_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(tusb_resources),
-	.resource	= tusb_resources,
-};
-
 
 /* this may be called only from board-*.c setup code */
-int __init
+__init struct gpmc_device_pdata *
 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async, unsigned sync,
@@ -249,82 +226,72 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		KERN_ERR "tusb6010 init error %d, %d\n";
 
 	/* ASYNC region, primarily for PIO */
-	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
-				&tusb_resources[0].start);
-	if (status < 0) {
-		printk(error, 1, status);
-		return status;
-	}
-	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].cs		= async;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].mem_size	= 0x1000;
+
 	async_cs = async;
-	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_READTYPE_ASYNC
-			| GPMC_CONFIG1_WRITETYPE_ASYNC
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA);
 
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_ASYNC |
+						GPMC_WRITETYPE_ASYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						waitpin;
 
 	/* SYNC region, primarily for DMA */
-	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
-				&tusb_resources[1].start);
-	if (status < 0) {
-		printk(error, 2, status);
-		return status;
-	}
-	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].cs		= sync;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].mem_size	= 0x1000;
+
 	sync_cs = sync;
-	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_READMULTIPLE_SUPP
-			| GPMC_CONFIG1_READTYPE_SYNC
-			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
-			| GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA
-			/* fclk divider gets set later */
-			);
+
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].have_config = true;
+	/* fclk divider gets set later */
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_SYNC |
+						GPMC_WRITETYPE_SYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						GPMC_CLOCKACTIVATION_TIME_1 |
+						GPMC_READMULTIPLE |
+						GPMC_WRITEMULTIPLE |
+						waitpin;
 
 	/* IRQ */
 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
 	if (status < 0) {
 		printk(error, 3, status);
-		return status;
+		return NULL;
 	}
-	tusb_resources[2].start = irq + IH_GPIO_BASE;
+	tusb_resources.start = irq + IH_GPIO_BASE;
 
 	/* set up memory timings ... can speed them up later */
 	if (!ps_refclk) {
 		printk(error, 4, status);
-		return -ENODEV;
+		return NULL;
 	}
 	refclk_psec = ps_refclk;
 	status = tusb6010_platform_retime(1);
 	if (status < 0) {
 		printk(error, 5, status);
-		return status;
+		return NULL;
 	}
 
-	/* finish device setup ... */
 	if (!data) {
 		printk(error, 6, status);
-		return -ENODEV;
+		return NULL;
 	}
-	tusb_device.dev.platform_data = data;
+	gpmc_tusb_data.pdata = data;
+	gpmc_tusb_data.pdata_size = sizeof(*data);
 
 	/* REVISIT let the driver know what DMA channels work */
-	if (!dmachan)
-		tusb_device.dev.dma_mask = NULL;
-	else {
+	if (dmachan) {
 		/* assume OMAP 2420 ES2.0 and later */
 		if (dmachan & (1 << 0))
 			omap_mux_init_signal("sys_ndmareq0", 0);
@@ -340,11 +307,5 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 			omap_mux_init_signal("sys_ndmareq5", 0);
 	}
 
-	/* so far so good ... register the device */
-	status = platform_device_register(&tusb_device);
-	if (status < 0) {
-		printk(error, 7, status);
-		return status;
-	}
-	return 0;
+	return &gpmc_tusb_data;
 }
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..a7de510 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -139,14 +139,12 @@ struct musb_hdrc_platform_data {
 
 #ifdef	CONFIG_ARCH_OMAP2
 
-extern int __init tusb6010_setup_interface(
+extern __init struct gpmc_device_pdata *tusb6010_setup_interface(
 		struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async_cs, unsigned sync_cs,
 		unsigned irq, unsigned dmachan);
 
-extern int tusb6010_platform_retime(unsigned is_refclk);
-
 #endif	/* OMAP2 */
 
 #endif /* __LINUX_USB_MUSB_H */
-- 
1.7.10


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

* [PATCH v4 12/39] ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Currently gpmc is configured in platform for tusb6010. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/usb-tusb6010.c |  177 ++++++++++++++----------------------
 include/linux/usb/musb.h           |    4 +-
 2 files changed, 70 insertions(+), 111 deletions(-)

diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index db84a46..d7817d2 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -22,6 +22,24 @@
 
 #include "mux.h"
 
+static struct resource tusb_resources = {
+	.name	= "mc",
+	.flags	= IORESOURCE_IRQ,
+};
+
+#define	TUSB_GPMC_CS_ASYNC_IDX	1
+#define	TUSB_GPMC_CS_SYNC_IDX	2
+#define	TUSB_GPMC_CS_NUM	2
+
+static struct gpmc_cs_data gpmc_tusb_cs_data[TUSB_GPMC_CS_NUM];
+
+static struct gpmc_device_pdata gpmc_tusb_data = {
+	.name		= "musb-tusb",
+	.id		= -1,
+	.per_res	= &tusb_resources,
+	.per_res_cnt	= 1,
+};
+
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
@@ -51,9 +69,9 @@ next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static void tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -106,12 +124,12 @@ static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(async_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].timing = &t;
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -174,71 +192,30 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(sync_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].timing = &t;
+
+	return 0;
 }
 
 extern unsigned long gpmc_get_fclk_period(void);
 
 /* tusb driver calls this when it changes the chip's clocking */
-int tusb6010_platform_retime(unsigned is_refclk)
+static int tusb6010_platform_retime(unsigned is_refclk)
 {
-	static const char	error[] =
-		KERN_ERR "tusb6010 %s retime error %d\n";
-
 	unsigned	fclk_ps = gpmc_get_fclk_period();
 	unsigned	sysclk_ps;
-	int		status;
 
 	if (!refclk_psec || fclk_ps == 0)
 		return -ENODEV;
 
 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
 
-	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
-	if (status < 0) {
-		printk(error, "async", status);
-		goto done;
-	}
-	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
-	if (status < 0)
-		printk(error, "sync", status);
-done:
-	return status;
+	tusb_set_async_mode(sysclk_ps, fclk_ps);
+	return tusb_set_sync_mode(sysclk_ps, fclk_ps);
 }
-EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
-
-static struct resource tusb_resources[] = {
-	/* Order is significant!  The start/end fields
-	 * are updated during setup..
-	 */
-	{ /* Asynchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* Synchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* IRQ */
-		.name	= "mc",
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 tusb_dmamask = ~(u32)0;
-
-static struct platform_device tusb_device = {
-	.name		= "musb-tusb",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &tusb_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(tusb_resources),
-	.resource	= tusb_resources,
-};
-
 
 /* this may be called only from board-*.c setup code */
-int __init
+__init struct gpmc_device_pdata *
 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async, unsigned sync,
@@ -249,82 +226,72 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		KERN_ERR "tusb6010 init error %d, %d\n";
 
 	/* ASYNC region, primarily for PIO */
-	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
-				&tusb_resources[0].start);
-	if (status < 0) {
-		printk(error, 1, status);
-		return status;
-	}
-	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].cs		= async;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].mem_size	= 0x1000;
+
 	async_cs = async;
-	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_READTYPE_ASYNC
-			| GPMC_CONFIG1_WRITETYPE_ASYNC
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA);
 
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_ASYNC |
+						GPMC_WRITETYPE_ASYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						waitpin;
 
 	/* SYNC region, primarily for DMA */
-	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
-				&tusb_resources[1].start);
-	if (status < 0) {
-		printk(error, 2, status);
-		return status;
-	}
-	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].cs		= sync;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].mem_size	= 0x1000;
+
 	sync_cs = sync;
-	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_READMULTIPLE_SUPP
-			| GPMC_CONFIG1_READTYPE_SYNC
-			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
-			| GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA
-			/* fclk divider gets set later */
-			);
+
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].have_config = true;
+	/* fclk divider gets set later */
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_SYNC |
+						GPMC_WRITETYPE_SYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						GPMC_CLOCKACTIVATION_TIME_1 |
+						GPMC_READMULTIPLE |
+						GPMC_WRITEMULTIPLE |
+						waitpin;
 
 	/* IRQ */
 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
 	if (status < 0) {
 		printk(error, 3, status);
-		return status;
+		return NULL;
 	}
-	tusb_resources[2].start = irq + IH_GPIO_BASE;
+	tusb_resources.start = irq + IH_GPIO_BASE;
 
 	/* set up memory timings ... can speed them up later */
 	if (!ps_refclk) {
 		printk(error, 4, status);
-		return -ENODEV;
+		return NULL;
 	}
 	refclk_psec = ps_refclk;
 	status = tusb6010_platform_retime(1);
 	if (status < 0) {
 		printk(error, 5, status);
-		return status;
+		return NULL;
 	}
 
-	/* finish device setup ... */
 	if (!data) {
 		printk(error, 6, status);
-		return -ENODEV;
+		return NULL;
 	}
-	tusb_device.dev.platform_data = data;
+	gpmc_tusb_data.pdata = data;
+	gpmc_tusb_data.pdata_size = sizeof(*data);
 
 	/* REVISIT let the driver know what DMA channels work */
-	if (!dmachan)
-		tusb_device.dev.dma_mask = NULL;
-	else {
+	if (dmachan) {
 		/* assume OMAP 2420 ES2.0 and later */
 		if (dmachan & (1 << 0))
 			omap_mux_init_signal("sys_ndmareq0", 0);
@@ -340,11 +307,5 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 			omap_mux_init_signal("sys_ndmareq5", 0);
 	}
 
-	/* so far so good ... register the device */
-	status = platform_device_register(&tusb_device);
-	if (status < 0) {
-		printk(error, 7, status);
-		return status;
-	}
-	return 0;
+	return &gpmc_tusb_data;
 }
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..a7de510 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -139,14 +139,12 @@ struct musb_hdrc_platform_data {
 
 #ifdef	CONFIG_ARCH_OMAP2
 
-extern int __init tusb6010_setup_interface(
+extern __init struct gpmc_device_pdata *tusb6010_setup_interface(
 		struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async_cs, unsigned sync_cs,
 		unsigned irq, unsigned dmachan);
 
-extern int tusb6010_platform_retime(unsigned is_refclk);
-
 #endif	/* OMAP2 */
 
 #endif /* __LINUX_USB_MUSB_H */
-- 
1.7.10

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

* [PATCH v4 12/39] ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

Currently gpmc is configured in platform for tusb6010. As configuring
gpmc has been moved to gpmc driver, populate details needed for the
driver to configure gpmc. gpmc driver would configure based on this
information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/usb-tusb6010.c |  177 ++++++++++++++----------------------
 include/linux/usb/musb.h           |    4 +-
 2 files changed, 70 insertions(+), 111 deletions(-)

diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index db84a46..d7817d2 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -22,6 +22,24 @@
 
 #include "mux.h"
 
+static struct resource tusb_resources = {
+	.name	= "mc",
+	.flags	= IORESOURCE_IRQ,
+};
+
+#define	TUSB_GPMC_CS_ASYNC_IDX	1
+#define	TUSB_GPMC_CS_SYNC_IDX	2
+#define	TUSB_GPMC_CS_NUM	2
+
+static struct gpmc_cs_data gpmc_tusb_cs_data[TUSB_GPMC_CS_NUM];
+
+static struct gpmc_device_pdata gpmc_tusb_data = {
+	.name		= "musb-tusb",
+	.id		= -1,
+	.per_res	= &tusb_resources,
+	.per_res_cnt	= 1,
+};
+
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
@@ -51,9 +69,9 @@ next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static void tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -106,12 +124,12 @@ static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(async_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].timing = &t;
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -174,71 +192,30 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(sync_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].timing = &t;
+
+	return 0;
 }
 
 extern unsigned long gpmc_get_fclk_period(void);
 
 /* tusb driver calls this when it changes the chip's clocking */
-int tusb6010_platform_retime(unsigned is_refclk)
+static int tusb6010_platform_retime(unsigned is_refclk)
 {
-	static const char	error[] =
-		KERN_ERR "tusb6010 %s retime error %d\n";
-
 	unsigned	fclk_ps = gpmc_get_fclk_period();
 	unsigned	sysclk_ps;
-	int		status;
 
 	if (!refclk_psec || fclk_ps == 0)
 		return -ENODEV;
 
 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
 
-	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
-	if (status < 0) {
-		printk(error, "async", status);
-		goto done;
-	}
-	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
-	if (status < 0)
-		printk(error, "sync", status);
-done:
-	return status;
+	tusb_set_async_mode(sysclk_ps, fclk_ps);
+	return tusb_set_sync_mode(sysclk_ps, fclk_ps);
 }
-EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
-
-static struct resource tusb_resources[] = {
-	/* Order is significant!  The start/end fields
-	 * are updated during setup..
-	 */
-	{ /* Asynchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* Synchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* IRQ */
-		.name	= "mc",
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 tusb_dmamask = ~(u32)0;
-
-static struct platform_device tusb_device = {
-	.name		= "musb-tusb",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &tusb_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(tusb_resources),
-	.resource	= tusb_resources,
-};
-
 
 /* this may be called only from board-*.c setup code */
-int __init
+__init struct gpmc_device_pdata *
 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async, unsigned sync,
@@ -249,82 +226,72 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		KERN_ERR "tusb6010 init error %d, %d\n";
 
 	/* ASYNC region, primarily for PIO */
-	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
-				&tusb_resources[0].start);
-	if (status < 0) {
-		printk(error, 1, status);
-		return status;
-	}
-	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].cs		= async;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].mem_size	= 0x1000;
+
 	async_cs = async;
-	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_READTYPE_ASYNC
-			| GPMC_CONFIG1_WRITETYPE_ASYNC
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA);
 
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_ASYNC |
+						GPMC_WRITETYPE_ASYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						waitpin;
 
 	/* SYNC region, primarily for DMA */
-	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
-				&tusb_resources[1].start);
-	if (status < 0) {
-		printk(error, 2, status);
-		return status;
-	}
-	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].cs		= sync;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].mem_size	= 0x1000;
+
 	sync_cs = sync;
-	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_READMULTIPLE_SUPP
-			| GPMC_CONFIG1_READTYPE_SYNC
-			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
-			| GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA
-			/* fclk divider gets set later */
-			);
+
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].have_config = true;
+	/* fclk divider gets set later */
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_SYNC |
+						GPMC_WRITETYPE_SYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						GPMC_CLOCKACTIVATION_TIME_1 |
+						GPMC_READMULTIPLE |
+						GPMC_WRITEMULTIPLE |
+						waitpin;
 
 	/* IRQ */
 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
 	if (status < 0) {
 		printk(error, 3, status);
-		return status;
+		return NULL;
 	}
-	tusb_resources[2].start = irq + IH_GPIO_BASE;
+	tusb_resources.start = irq + IH_GPIO_BASE;
 
 	/* set up memory timings ... can speed them up later */
 	if (!ps_refclk) {
 		printk(error, 4, status);
-		return -ENODEV;
+		return NULL;
 	}
 	refclk_psec = ps_refclk;
 	status = tusb6010_platform_retime(1);
 	if (status < 0) {
 		printk(error, 5, status);
-		return status;
+		return NULL;
 	}
 
-	/* finish device setup ... */
 	if (!data) {
 		printk(error, 6, status);
-		return -ENODEV;
+		return NULL;
 	}
-	tusb_device.dev.platform_data = data;
+	gpmc_tusb_data.pdata = data;
+	gpmc_tusb_data.pdata_size = sizeof(*data);
 
 	/* REVISIT let the driver know what DMA channels work */
-	if (!dmachan)
-		tusb_device.dev.dma_mask = NULL;
-	else {
+	if (dmachan) {
 		/* assume OMAP 2420 ES2.0 and later */
 		if (dmachan & (1 << 0))
 			omap_mux_init_signal("sys_ndmareq0", 0);
@@ -340,11 +307,5 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 			omap_mux_init_signal("sys_ndmareq5", 0);
 	}
 
-	/* so far so good ... register the device */
-	status = platform_device_register(&tusb_device);
-	if (status < 0) {
-		printk(error, 7, status);
-		return status;
-	}
-	return 0;
+	return &gpmc_tusb_data;
 }
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..a7de510 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -139,14 +139,12 @@ struct musb_hdrc_platform_data {
 
 #ifdef	CONFIG_ARCH_OMAP2
 
-extern int __init tusb6010_setup_interface(
+extern __init struct gpmc_device_pdata *tusb6010_setup_interface(
 		struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async_cs, unsigned sync_cs,
 		unsigned irq, unsigned dmachan);
 
-extern int tusb6010_platform_retime(unsigned is_refclk);
-
 #endif	/* OMAP2 */
 
 #endif /* __LINUX_USB_MUSB_H */
-- 
1.7.10

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

* [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 0c65079..4da8394 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1981,6 +1981,40 @@ static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap3xxx_gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+static struct omap_hwmod omap3xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap3xxx_gpmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
+	.mpu_irqs	= omap3xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+};
+
+/*
  * interfaces
  */
 
@@ -3059,6 +3093,23 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+	.master		= &omap3xxx_l3_main_hwmod,
+	.slave		= &omap3xxx_gpmc_hwmod,
+	.clk		= "core_l3_ick",
+	.addr		= omap3xxx_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3103,6 +3154,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap34xx_l4_core__mcspi2,
 	&omap34xx_l4_core__mcspi3,
 	&omap34xx_l4_core__mcspi4,
+	&omap3xxx_l3_main__gpmc,
 	NULL,
 };
 
-- 
1.7.10


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

* [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 0c65079..4da8394 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1981,6 +1981,40 @@ static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap3xxx_gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+static struct omap_hwmod omap3xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap3xxx_gpmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
+	.mpu_irqs	= omap3xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+};
+
+/*
  * interfaces
  */
 
@@ -3059,6 +3093,23 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+	.master		= &omap3xxx_l3_main_hwmod,
+	.slave		= &omap3xxx_gpmc_hwmod,
+	.clk		= "core_l3_ick",
+	.addr		= omap3xxx_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3103,6 +3154,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap34xx_l4_core__mcspi2,
 	&omap34xx_l4_core__mcspi3,
 	&omap34xx_l4_core__mcspi4,
+	&omap3xxx_l3_main__gpmc,
 	NULL,
 };
 
-- 
1.7.10

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

* [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 0c65079..4da8394 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1981,6 +1981,40 @@ static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap3xxx_gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+static struct omap_hwmod omap3xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap3xxx_gpmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
+	.mpu_irqs	= omap3xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+};
+
+/*
  * interfaces
  */
 
@@ -3059,6 +3093,23 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+	.master		= &omap3xxx_l3_main_hwmod,
+	.slave		= &omap3xxx_gpmc_hwmod,
+	.clk		= "core_l3_ick",
+	.addr		= omap3xxx_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3103,6 +3154,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap34xx_l4_core__mcspi2,
 	&omap34xx_l4_core__mcspi3,
 	&omap34xx_l4_core__mcspi4,
+	&omap3xxx_l3_main__gpmc,
 	NULL,
 };
 
-- 
1.7.10

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

* [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 ++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 5 files changed, 80 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 2c087ff..55c8c7b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -428,6 +428,23 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6800A000,
+		.pa_end		= 0x6800AFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2420_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2420_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -468,6 +485,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mailbox,
 	&omap2420_l4_core__mcbsp1,
 	&omap2420_l4_core__mcbsp2,
+	&omap2420_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 71d9f88..dd224cca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -838,6 +838,23 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2430_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -886,6 +903,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp3,
 	&omap2430_l4_core__mcbsp4,
 	&omap2430_l4_core__mcbsp5,
+	&omap2430_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 45aaa07..e75da40 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -175,6 +175,26 @@ struct omap_hwmod_class omap2xxx_mcspi_class = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap2xxx_gpmc_sysc,
+};
+
+/*
  * IP blocks
  */
 
@@ -732,3 +752,24 @@ struct omap_hwmod omap2xxx_mcspi2_hwmod = {
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
 };
+
+/* gpmc */
+static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap2xxx_gpmc_hwmod_class,
+	.mpu_irqs	= omap2xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.prcm		= {
+		.omap2	= {
+			.prcm_reg_id = 3,
+			.module_bit = OMAP24XX_EN_GPMC_MASK,
+			.module_offs = CORE_MOD,
+		},
+	},
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 7aa9156..63e0134 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -74,6 +74,7 @@ extern struct omap_hwmod omap2xxx_gpio3_hwmod;
 extern struct omap_hwmod omap2xxx_gpio4_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 5aa5435..48c722a 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -109,6 +109,8 @@
 #define OMAP2430_EN_MDM_INTC_MASK			(1 << 11)
 #define OMAP2430_EN_USBHS_SHIFT				6
 #define OMAP2430_EN_USBHS_MASK				(1 << 6)
+#define OMAP24XX_EN_GPMC_SHIFT				1
+#define OMAP24XX_EN_GPMC_MASK				(1 << 1)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
 #define OMAP2420_ST_MMC_SHIFT				26
-- 
1.7.10


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

* [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 ++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 5 files changed, 80 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 2c087ff..55c8c7b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -428,6 +428,23 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6800A000,
+		.pa_end		= 0x6800AFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2420_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2420_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -468,6 +485,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mailbox,
 	&omap2420_l4_core__mcbsp1,
 	&omap2420_l4_core__mcbsp2,
+	&omap2420_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 71d9f88..dd224cca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -838,6 +838,23 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2430_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -886,6 +903,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp3,
 	&omap2430_l4_core__mcbsp4,
 	&omap2430_l4_core__mcbsp5,
+	&omap2430_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 45aaa07..e75da40 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -175,6 +175,26 @@ struct omap_hwmod_class omap2xxx_mcspi_class = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap2xxx_gpmc_sysc,
+};
+
+/*
  * IP blocks
  */
 
@@ -732,3 +752,24 @@ struct omap_hwmod omap2xxx_mcspi2_hwmod = {
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
 };
+
+/* gpmc */
+static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap2xxx_gpmc_hwmod_class,
+	.mpu_irqs	= omap2xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.prcm		= {
+		.omap2	= {
+			.prcm_reg_id = 3,
+			.module_bit = OMAP24XX_EN_GPMC_MASK,
+			.module_offs = CORE_MOD,
+		},
+	},
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 7aa9156..63e0134 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -74,6 +74,7 @@ extern struct omap_hwmod omap2xxx_gpio3_hwmod;
 extern struct omap_hwmod omap2xxx_gpio4_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 5aa5435..48c722a 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -109,6 +109,8 @@
 #define OMAP2430_EN_MDM_INTC_MASK			(1 << 11)
 #define OMAP2430_EN_USBHS_SHIFT				6
 #define OMAP2430_EN_USBHS_MASK				(1 << 6)
+#define OMAP24XX_EN_GPMC_SHIFT				1
+#define OMAP24XX_EN_GPMC_MASK				(1 << 1)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
 #define OMAP2420_ST_MMC_SHIFT				26
-- 
1.7.10

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

* [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

Add gpmc hwmod and associated interconnect data

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 ++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 5 files changed, 80 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 2c087ff..55c8c7b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -428,6 +428,23 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6800A000,
+		.pa_end		= 0x6800AFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2420_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2420_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -468,6 +485,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mailbox,
 	&omap2420_l4_core__mcbsp1,
 	&omap2420_l4_core__mcbsp2,
+	&omap2420_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 71d9f88..dd224cca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -838,6 +838,23 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2430_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -886,6 +903,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp3,
 	&omap2430_l4_core__mcbsp4,
 	&omap2430_l4_core__mcbsp5,
+	&omap2430_l3__gpmc,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 45aaa07..e75da40 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -175,6 +175,26 @@ struct omap_hwmod_class omap2xxx_mcspi_class = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap2xxx_gpmc_sysc,
+};
+
+/*
  * IP blocks
  */
 
@@ -732,3 +752,24 @@ struct omap_hwmod omap2xxx_mcspi2_hwmod = {
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
 };
+
+/* gpmc */
+static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap2xxx_gpmc_hwmod_class,
+	.mpu_irqs	= omap2xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.prcm		= {
+		.omap2	= {
+			.prcm_reg_id = 3,
+			.module_bit = OMAP24XX_EN_GPMC_MASK,
+			.module_offs = CORE_MOD,
+		},
+	},
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 7aa9156..63e0134 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -74,6 +74,7 @@ extern struct omap_hwmod omap2xxx_gpio3_hwmod;
 extern struct omap_hwmod omap2xxx_gpio4_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 5aa5435..48c722a 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -109,6 +109,8 @@
 #define OMAP2430_EN_MDM_INTC_MASK			(1 << 11)
 #define OMAP2430_EN_USBHS_SHIFT				6
 #define OMAP2430_EN_USBHS_MASK				(1 << 6)
+#define OMAP24XX_EN_GPMC_SHIFT				1
+#define OMAP24XX_EN_GPMC_MASK				(1 << 1)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
 #define OMAP2420_ST_MMC_SHIFT				26
-- 
1.7.10

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

* [PATCH v4 15/39] mtd: nand: omap2: obtain memory from resource
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc being converted to driver, provides drivers
of peripheral connected memory space used by the
peripheral as memory resource.

Modify nand omap driver to obtain memory detials
from resource structure.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/plat-omap/include/plat/nand.h |    1 -
 drivers/mtd/nand/omap2.c               |   20 ++++++++++++++------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 30c61c9..570c4f4 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -26,7 +26,6 @@ struct omap_nand_platform_data {
 	bool			dev_ready;
 	int			gpmc_irq;
 	enum nand_io		xfer_type;
-	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index c2b0bba..be4b321 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -118,6 +118,7 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
+	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
 	int				gpmc_irq;
@@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	struct omap_nand_platform_data	*pdata;
 	int				err;
 	int				i, offset;
+	struct resource			*res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
-	info->phys_base		= pdata->phys_base;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
@@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
-	/* NAND write protect off */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_WP, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
+		goto out_free_info;
+	}
+
+	info->phys_base = res->start;
+	info->mem_size = resource_size(res);
 
-	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
+	if (!request_mem_region(info->phys_base, info->mem_size,
 				pdev->dev.driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
 	}
 
-	info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
+	info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
 	if (!info->nand.IO_ADDR_R) {
 		err = -ENOMEM;
 		goto out_release_mem_region;
@@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	return 0;
 
 out_release_mem_region:
-	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
 	kfree(info);
 
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 15/39] mtd: nand: omap2: obtain memory from resource
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc being converted to driver, provides drivers
of peripheral connected memory space used by the
peripheral as memory resource.

Modify nand omap driver to obtain memory detials
from resource structure.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/plat-omap/include/plat/nand.h |    1 -
 drivers/mtd/nand/omap2.c               |   20 ++++++++++++++------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 30c61c9..570c4f4 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -26,7 +26,6 @@ struct omap_nand_platform_data {
 	bool			dev_ready;
 	int			gpmc_irq;
 	enum nand_io		xfer_type;
-	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index c2b0bba..be4b321 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -118,6 +118,7 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
+	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
 	int				gpmc_irq;
@@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	struct omap_nand_platform_data	*pdata;
 	int				err;
 	int				i, offset;
+	struct resource			*res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
-	info->phys_base		= pdata->phys_base;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
@@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
-	/* NAND write protect off */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_WP, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
+		goto out_free_info;
+	}
+
+	info->phys_base = res->start;
+	info->mem_size = resource_size(res);
 
-	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
+	if (!request_mem_region(info->phys_base, info->mem_size,
 				pdev->dev.driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
 	}
 
-	info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
+	info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
 	if (!info->nand.IO_ADDR_R) {
 		err = -ENOMEM;
 		goto out_release_mem_region;
@@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	return 0;
 
 out_release_mem_region:
-	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
 	kfree(info);
 
-- 
1.7.10

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

* [PATCH v4 15/39] mtd: nand: omap2: obtain memory from resource
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc being converted to driver, provides drivers
of peripheral connected memory space used by the
peripheral as memory resource.

Modify nand omap driver to obtain memory detials
from resource structure.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/plat-omap/include/plat/nand.h |    1 -
 drivers/mtd/nand/omap2.c               |   20 ++++++++++++++------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 30c61c9..570c4f4 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -26,7 +26,6 @@ struct omap_nand_platform_data {
 	bool			dev_ready;
 	int			gpmc_irq;
 	enum nand_io		xfer_type;
-	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index c2b0bba..be4b321 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -118,6 +118,7 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
+	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
 	int				gpmc_irq;
@@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	struct omap_nand_platform_data	*pdata;
 	int				err;
 	int				i, offset;
+	struct resource			*res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
-	info->phys_base		= pdata->phys_base;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
@@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
-	/* NAND write protect off */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_WP, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
+		goto out_free_info;
+	}
+
+	info->phys_base = res->start;
+	info->mem_size = resource_size(res);
 
-	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
+	if (!request_mem_region(info->phys_base, info->mem_size,
 				pdev->dev.driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
 	}
 
-	info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
+	info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
 	if (!info->nand.IO_ADDR_R) {
 		err = -ENOMEM;
 		goto out_release_mem_region;
@@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	return 0;
 
 out_release_mem_region:
-	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
 	kfree(info);
 
-- 
1.7.10

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

* [PATCH v4 16/39] mtd: nand: omap2: use gpmc provided irqs
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

GPMC driver provides it's clientsd with interrupts that can be used
through struct resource. Make use of it for irq mode functionality.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 drivers/mtd/nand/omap2.c |   67 +++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index be4b321..440536b 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -121,7 +121,8 @@ struct omap_nand_info {
 	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
-	int				gpmc_irq;
+	int				gpmc_irq_fifo;
+	int				gpmc_irq_count;
 	enum {
 		OMAP_NAND_IO_READ = 0,	/* read */
 		OMAP_NAND_IO_WRITE,	/* write */
@@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 {
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
-	u32 irq_stat;
 
-	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 
 		if (info->buf_len && (info->buf_len < bytes))
@@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 						(u32 *)info->buf, bytes >> 2);
 		info->buf = info->buf + bytes;
 
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 	}
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
 
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
-	/* disable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
 
-	/* clear status */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+	disable_irq_nosync(info->gpmc_irq_fifo);
+	disable_irq_nosync(info->gpmc_irq_count);
 
 	return IRQ_HANDLED;
 }
@@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for read to complete */
 	wait_for_completion(&info->comp);
@@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for write to complete */
 	wait_for_completion(&info->comp);
+
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
@@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
+	info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting FIFO IRQ\n");
+
+	info->gpmc_irq_count = platform_get_irq(pdev, 1);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting TERMINALCOUNT IRQ\n");
+
 	info->nand.controller = &info->controller;
 
 	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
@@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_PREFETCH_IRQ:
-		err = request_irq(pdata->gpmc_irq,
-				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		err = request_irq(info->gpmc_irq_fifo,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-fifo", info);
 		if (err) {
 			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-							pdata->gpmc_irq, err);
+						info->gpmc_irq_fifo, err);
 			goto out_release_mem_region;
-		} else {
-			info->gpmc_irq	     = pdata->gpmc_irq;
-			info->nand.read_buf  = omap_read_buf_irq_pref;
-			info->nand.write_buf = omap_write_buf_irq_pref;
 		}
+		err = request_irq(info->gpmc_irq_count,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-count", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+						info->gpmc_irq_count, err);
+			goto out_free_irq_gpmc_fifo;
+		}
+
+		info->nand.read_buf  = omap_read_buf_irq_pref;
+		info->nand.write_buf = omap_write_buf_irq_pref;
+
 		break;
 
 	default:
@@ -1117,6 +1129,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
 	return 0;
 
+out_free_irq_gpmc_fifo:
+	free_irq(info->gpmc_irq_fifo, info);
 out_release_mem_region:
 	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
@@ -1135,8 +1149,11 @@ static int omap_nand_remove(struct platform_device *pdev)
 	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
-	if (info->gpmc_irq)
-		free_irq(info->gpmc_irq, info);
+	if (info->gpmc_irq_fifo > 0)
+		free_irq(info->gpmc_irq_fifo, info);
+
+	if (info->gpmc_irq_count > 0)
+		free_irq(info->gpmc_irq_count, info);
 
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 16/39] mtd: nand: omap2: use gpmc provided irqs
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

GPMC driver provides it's clientsd with interrupts that can be used
through struct resource. Make use of it for irq mode functionality.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c |   67 +++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index be4b321..440536b 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -121,7 +121,8 @@ struct omap_nand_info {
 	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
-	int				gpmc_irq;
+	int				gpmc_irq_fifo;
+	int				gpmc_irq_count;
 	enum {
 		OMAP_NAND_IO_READ = 0,	/* read */
 		OMAP_NAND_IO_WRITE,	/* write */
@@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 {
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
-	u32 irq_stat;
 
-	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 
 		if (info->buf_len && (info->buf_len < bytes))
@@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 						(u32 *)info->buf, bytes >> 2);
 		info->buf = info->buf + bytes;
 
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 	}
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
 
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
-	/* disable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
 
-	/* clear status */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+	disable_irq_nosync(info->gpmc_irq_fifo);
+	disable_irq_nosync(info->gpmc_irq_count);
 
 	return IRQ_HANDLED;
 }
@@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for read to complete */
 	wait_for_completion(&info->comp);
@@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for write to complete */
 	wait_for_completion(&info->comp);
+
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
@@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
+	info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting FIFO IRQ\n");
+
+	info->gpmc_irq_count = platform_get_irq(pdev, 1);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting TERMINALCOUNT IRQ\n");
+
 	info->nand.controller = &info->controller;
 
 	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
@@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_PREFETCH_IRQ:
-		err = request_irq(pdata->gpmc_irq,
-				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		err = request_irq(info->gpmc_irq_fifo,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-fifo", info);
 		if (err) {
 			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-							pdata->gpmc_irq, err);
+						info->gpmc_irq_fifo, err);
 			goto out_release_mem_region;
-		} else {
-			info->gpmc_irq	     = pdata->gpmc_irq;
-			info->nand.read_buf  = omap_read_buf_irq_pref;
-			info->nand.write_buf = omap_write_buf_irq_pref;
 		}
+		err = request_irq(info->gpmc_irq_count,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-count", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+						info->gpmc_irq_count, err);
+			goto out_free_irq_gpmc_fifo;
+		}
+
+		info->nand.read_buf  = omap_read_buf_irq_pref;
+		info->nand.write_buf = omap_write_buf_irq_pref;
+
 		break;
 
 	default:
@@ -1117,6 +1129,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
 	return 0;
 
+out_free_irq_gpmc_fifo:
+	free_irq(info->gpmc_irq_fifo, info);
 out_release_mem_region:
 	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
@@ -1135,8 +1149,11 @@ static int omap_nand_remove(struct platform_device *pdev)
 	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
-	if (info->gpmc_irq)
-		free_irq(info->gpmc_irq, info);
+	if (info->gpmc_irq_fifo > 0)
+		free_irq(info->gpmc_irq_fifo, info);
+
+	if (info->gpmc_irq_count > 0)
+		free_irq(info->gpmc_irq_count, info);
 
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
-- 
1.7.10

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

* [PATCH v4 16/39] mtd: nand: omap2: use gpmc provided irqs
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

GPMC driver provides it's clientsd with interrupts that can be used
through struct resource. Make use of it for irq mode functionality.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c |   67 +++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index be4b321..440536b 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -121,7 +121,8 @@ struct omap_nand_info {
 	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
-	int				gpmc_irq;
+	int				gpmc_irq_fifo;
+	int				gpmc_irq_count;
 	enum {
 		OMAP_NAND_IO_READ = 0,	/* read */
 		OMAP_NAND_IO_WRITE,	/* write */
@@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 {
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
-	u32 irq_stat;
 
-	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 
 		if (info->buf_len && (info->buf_len < bytes))
@@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 						(u32 *)info->buf, bytes >> 2);
 		info->buf = info->buf + bytes;
 
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 	}
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
 
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
-	/* disable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
 
-	/* clear status */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+	disable_irq_nosync(info->gpmc_irq_fifo);
+	disable_irq_nosync(info->gpmc_irq_count);
 
 	return IRQ_HANDLED;
 }
@@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for read to complete */
 	wait_for_completion(&info->comp);
@@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for write to complete */
 	wait_for_completion(&info->comp);
+
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
@@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
+	info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting FIFO IRQ\n");
+
+	info->gpmc_irq_count = platform_get_irq(pdev, 1);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting TERMINALCOUNT IRQ\n");
+
 	info->nand.controller = &info->controller;
 
 	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
@@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_PREFETCH_IRQ:
-		err = request_irq(pdata->gpmc_irq,
-				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		err = request_irq(info->gpmc_irq_fifo,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-fifo", info);
 		if (err) {
 			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-							pdata->gpmc_irq, err);
+						info->gpmc_irq_fifo, err);
 			goto out_release_mem_region;
-		} else {
-			info->gpmc_irq	     = pdata->gpmc_irq;
-			info->nand.read_buf  = omap_read_buf_irq_pref;
-			info->nand.write_buf = omap_write_buf_irq_pref;
 		}
+		err = request_irq(info->gpmc_irq_count,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-count", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+						info->gpmc_irq_count, err);
+			goto out_free_irq_gpmc_fifo;
+		}
+
+		info->nand.read_buf  = omap_read_buf_irq_pref;
+		info->nand.write_buf = omap_write_buf_irq_pref;
+
 		break;
 
 	default:
@@ -1117,6 +1129,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
 	return 0;
 
+out_free_irq_gpmc_fifo:
+	free_irq(info->gpmc_irq_fifo, info);
 out_release_mem_region:
 	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
@@ -1135,8 +1149,11 @@ static int omap_nand_remove(struct platform_device *pdev)
 	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
-	if (info->gpmc_irq)
-		free_irq(info->gpmc_irq, info);
+	if (info->gpmc_irq_fifo > 0)
+		free_irq(info->gpmc_irq_fifo, info);
+
+	if (info->gpmc_irq_count > 0)
+		free_irq(info->gpmc_irq_count, info);
 
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
-- 
1.7.10

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

* [PATCH v4 17/39] mtd: nand: omap2: handle nand on gpmc
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

GPMC driver has been modified to fill NAND platform data with GPMC
NAND register details. As these registers are accessible in NAND
driver itself, configure NAND in GPMC by itself.

Note: Verfying that other CS have not yet enabled for prefetch & ecc
has to be incorporated. Currently this causes no issues as there are
no boards that use NAND on multiple CS. With GPMC modifications,
perhaps it would be better to consider NAND connected on multiple CS
as a single peripheral using multiple CS. This would make handling
multiple CS issues easier.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c |  209 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 165 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 440536b..34fb726 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -129,8 +129,79 @@ struct omap_nand_info {
 	} iomode;
 	u_char				*buf;
 	int					buf_len;
+	struct gpmc_nand_regs		reg;
 };
 
+#define	PREFETCH_CONFIG1_CS_SHIFT	24
+#define	ECC_CONFIG_CS_SHIFT		1
+#define	CS_MASK				0x7
+#define	ENABLE_PREFETCH			(0x1 << 7)
+#define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE1_SHIFT			22
+#define	ECC1RESULTSIZE			0x1
+#define	ECC_CLEAR_SHIFT			8
+#define	ECC1				0x1
+
+/**
+ * omap_prefetch_enable - configures and starts prefetch transfer
+ * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @dma_mode: dma mode enable (1) or disable (0)
+ * @u32_count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ */
+static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode,
+	unsigned int u32_count, int is_write, struct omap_nand_info *info)
+{
+	u32 val;
+
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(readl(info->reg.gpmc_prefetch_control))) {
+		/* Set the amount of bytes to be prefetched */
+		writel(u32_count, info->reg.gpmc_prefetch_config2);
+
+		/* Set dma/mpu mode, the prefetch read / post write and
+		 * enable the engine. Set which cs is has requested for.
+		 */
+		val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
+					ENABLE_PREFETCH |
+					(dma_mode << DMA_MPU_MODE_SHIFT) |
+					(0x1 & is_write));
+		writel(val, info->reg.gpmc_prefetch_config1);
+
+		/*  Start the prefetch engine */
+		writel(0x1, info->reg.gpmc_prefetch_control);
+	} else {
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/**
+ * omap_prefetch_reset - disables and stops the prefetch engine
+ */
+static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
+{
+	u32 config1;
+
+	/* check if the same module/cs is trying to reset */
+	config1 = readl(info->reg.gpmc_prefetch_config1);
+	if (((config1 >> PREFETCH_CONFIG1_CS_SHIFT) & CS_MASK) != cs)
+		return -EINVAL;
+
+	/* Stop the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_control);
+
+	/* Reset/disable the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_config1);
+
+	return 0;
+}
+
 /**
  * omap_hwcontrol - hardware specific access to control-lines
  * @mtd: MTD device structure
@@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 	if (cmd != NAND_CMD_NONE) {
 		if (ctrl & NAND_CLE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_COMMAND, cmd);
+			writeb(cmd, info->reg.gpmc_nand_command);
 
 		else if (ctrl & NAND_ALE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_ADDRESS, cmd);
+			writeb(cmd, info->reg.gpmc_nand_address);
 
 		else /* NAND_NCE */
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_DATA, cmd);
+			writeb(cmd, info->reg.gpmc_nand_data);
 	}
 }
 
@@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		iowrite8(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -226,7 +298,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		iowrite16(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -256,8 +329,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -266,14 +339,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 			omap_read_buf8(mtd, (u_char *)p, len);
 	} else {
 		do {
-			r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			r_count = readl(info->reg.gpmc_prefetch_status);
+			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
 			len -= r_count << 2;
 		} while (len);
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -292,6 +366,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	int i = 0, ret = 0;
 	u16 *p = (u16 *)buf;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -301,8 +376,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -311,7 +386,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 			omap_write_buf8(mtd, (u_char *)p, len);
 	} else {
 		while (len) {
-			w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			w_count = readl(info->reg.gpmc_prefetch_status);
+			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -320,11 +396,14 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		tim = 0;
 		limit = (loops_per_jiffy *
 					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		do {
 			cpu_relax();
+			val = readl(info->reg.gpmc_prefetch_status);
+			val = GPMC_PREFETCH_STATUS_COUNT(val);
+		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -356,6 +435,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	dma_addr_t dma_addr;
 	int ret;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* The fifo depth is 64 bytes max.
 	 * But configure the FIFO-threahold to 32 to get a sync at each frame
@@ -400,8 +480,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -414,11 +494,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	wait_for_completion(&info->comp);
 	tim = 0;
 	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+
+	do {
 		cpu_relax();
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 
 	dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
 	return 0;
@@ -474,7 +558,8 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
 
-	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = readl(info->reg.gpmc_prefetch_status);
+	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -531,8 +616,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	init_completion(&info->comp);
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -546,7 +631,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	wait_for_completion(&info->comp);
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -569,6 +654,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 						struct omap_nand_info, mtd);
 	int ret = 0;
 	unsigned long tim, limit;
+	u32 val;
 
 	if (len <= mtd->oobsize) {
 		omap_write_buf_pref(mtd, buf, len);
@@ -580,8 +666,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	init_completion(&info->comp);
 
 	/* configure and start prefetch transfer : size=24 */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+		(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -597,11 +683,14 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+	do {
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -841,7 +930,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
+	u32 val;
+
+	val = readl(info->reg.gpmc_ecc_config);
+	if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+		return -EINVAL;
+
+	/* read ecc result */
+	val = readl(info->reg.gpmc_ecc1_result);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+	return 0;
 }
 
 /**
@@ -855,8 +957,36 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 							mtd);
 	struct nand_chip *chip = mtd->priv;
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	u32 val;
+
+	/* clear ecc and enable bits */
+	val = ((0x1 << ECC_CLEAR_SHIFT) | ECC1);
+	writel(val, info->reg.gpmc_ecc_control);
+
+	/* program ecc and result sizes */
+	val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) |
+			 ECC1RESULTSIZE);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_READSYN:
+		 writel(0x100, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_WRITE:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	default:
+		dev_info(&info->pdev->dev,
+			"error: unrecognized Mode[%d]!\n", mode);
+		break;
+	}
 
-	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
+	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+	val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+	writel(val, info->reg.gpmc_ecc_config);
 }
 
 /**
@@ -884,10 +1014,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	else
 		timeo += (HZ * 20) / 1000;
 
-	gpmc_nand_write(info->gpmc_cs,
-			GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
+	writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
 	while (time_before(jiffies, timeo)) {
-		status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+		status = readb(info->reg.gpmc_nand_data);
 		if (status & NAND_STATUS_READY)
 			break;
 		cond_resched();
@@ -905,22 +1034,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
 
-	val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	val = readl(info->reg.gpmc_status);
+
 	if ((val & 0x100) == 0x100) {
-		/* Clear IRQ Interrupt */
-		val |= 0x100;
-		val &= ~(0x0);
-		gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, val);
+		return 1;
 	} else {
-		unsigned int cnt = 0;
-		while (cnt++ < 0x1FF) {
-			if  ((val & 0x100) == 0x100)
-				return 0;
-			val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
-		}
+		return 0;
 	}
-
-	return 1;
 }
 
 static int __devinit omap_nand_probe(struct platform_device *pdev)
@@ -949,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
+	info->reg		= pdata->reg;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
-- 
1.7.10


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

* [PATCH v4 17/39] mtd: nand: omap2: handle nand on gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

GPMC driver has been modified to fill NAND platform data with GPMC
NAND register details. As these registers are accessible in NAND
driver itself, configure NAND in GPMC by itself.

Note: Verfying that other CS have not yet enabled for prefetch & ecc
has to be incorporated. Currently this causes no issues as there are
no boards that use NAND on multiple CS. With GPMC modifications,
perhaps it would be better to consider NAND connected on multiple CS
as a single peripheral using multiple CS. This would make handling
multiple CS issues easier.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c |  209 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 165 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 440536b..34fb726 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -129,8 +129,79 @@ struct omap_nand_info {
 	} iomode;
 	u_char				*buf;
 	int					buf_len;
+	struct gpmc_nand_regs		reg;
 };
 
+#define	PREFETCH_CONFIG1_CS_SHIFT	24
+#define	ECC_CONFIG_CS_SHIFT		1
+#define	CS_MASK				0x7
+#define	ENABLE_PREFETCH			(0x1 << 7)
+#define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE1_SHIFT			22
+#define	ECC1RESULTSIZE			0x1
+#define	ECC_CLEAR_SHIFT			8
+#define	ECC1				0x1
+
+/**
+ * omap_prefetch_enable - configures and starts prefetch transfer
+ * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @dma_mode: dma mode enable (1) or disable (0)
+ * @u32_count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ */
+static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode,
+	unsigned int u32_count, int is_write, struct omap_nand_info *info)
+{
+	u32 val;
+
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(readl(info->reg.gpmc_prefetch_control))) {
+		/* Set the amount of bytes to be prefetched */
+		writel(u32_count, info->reg.gpmc_prefetch_config2);
+
+		/* Set dma/mpu mode, the prefetch read / post write and
+		 * enable the engine. Set which cs is has requested for.
+		 */
+		val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
+					ENABLE_PREFETCH |
+					(dma_mode << DMA_MPU_MODE_SHIFT) |
+					(0x1 & is_write));
+		writel(val, info->reg.gpmc_prefetch_config1);
+
+		/*  Start the prefetch engine */
+		writel(0x1, info->reg.gpmc_prefetch_control);
+	} else {
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/**
+ * omap_prefetch_reset - disables and stops the prefetch engine
+ */
+static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
+{
+	u32 config1;
+
+	/* check if the same module/cs is trying to reset */
+	config1 = readl(info->reg.gpmc_prefetch_config1);
+	if (((config1 >> PREFETCH_CONFIG1_CS_SHIFT) & CS_MASK) != cs)
+		return -EINVAL;
+
+	/* Stop the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_control);
+
+	/* Reset/disable the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_config1);
+
+	return 0;
+}
+
 /**
  * omap_hwcontrol - hardware specific access to control-lines
  * @mtd: MTD device structure
@@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 	if (cmd != NAND_CMD_NONE) {
 		if (ctrl & NAND_CLE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_COMMAND, cmd);
+			writeb(cmd, info->reg.gpmc_nand_command);
 
 		else if (ctrl & NAND_ALE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_ADDRESS, cmd);
+			writeb(cmd, info->reg.gpmc_nand_address);
 
 		else /* NAND_NCE */
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_DATA, cmd);
+			writeb(cmd, info->reg.gpmc_nand_data);
 	}
 }
 
@@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		iowrite8(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -226,7 +298,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		iowrite16(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -256,8 +329,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -266,14 +339,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 			omap_read_buf8(mtd, (u_char *)p, len);
 	} else {
 		do {
-			r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			r_count = readl(info->reg.gpmc_prefetch_status);
+			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
 			len -= r_count << 2;
 		} while (len);
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -292,6 +366,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	int i = 0, ret = 0;
 	u16 *p = (u16 *)buf;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -301,8 +376,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -311,7 +386,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 			omap_write_buf8(mtd, (u_char *)p, len);
 	} else {
 		while (len) {
-			w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			w_count = readl(info->reg.gpmc_prefetch_status);
+			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -320,11 +396,14 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		tim = 0;
 		limit = (loops_per_jiffy *
 					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		do {
 			cpu_relax();
+			val = readl(info->reg.gpmc_prefetch_status);
+			val = GPMC_PREFETCH_STATUS_COUNT(val);
+		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -356,6 +435,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	dma_addr_t dma_addr;
 	int ret;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* The fifo depth is 64 bytes max.
 	 * But configure the FIFO-threahold to 32 to get a sync at each frame
@@ -400,8 +480,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -414,11 +494,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	wait_for_completion(&info->comp);
 	tim = 0;
 	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+
+	do {
 		cpu_relax();
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 
 	dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
 	return 0;
@@ -474,7 +558,8 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
 
-	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = readl(info->reg.gpmc_prefetch_status);
+	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -531,8 +616,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	init_completion(&info->comp);
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -546,7 +631,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	wait_for_completion(&info->comp);
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -569,6 +654,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 						struct omap_nand_info, mtd);
 	int ret = 0;
 	unsigned long tim, limit;
+	u32 val;
 
 	if (len <= mtd->oobsize) {
 		omap_write_buf_pref(mtd, buf, len);
@@ -580,8 +666,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	init_completion(&info->comp);
 
 	/* configure and start prefetch transfer : size=24 */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+		(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -597,11 +683,14 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+	do {
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -841,7 +930,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
+	u32 val;
+
+	val = readl(info->reg.gpmc_ecc_config);
+	if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+		return -EINVAL;
+
+	/* read ecc result */
+	val = readl(info->reg.gpmc_ecc1_result);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+	return 0;
 }
 
 /**
@@ -855,8 +957,36 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 							mtd);
 	struct nand_chip *chip = mtd->priv;
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	u32 val;
+
+	/* clear ecc and enable bits */
+	val = ((0x1 << ECC_CLEAR_SHIFT) | ECC1);
+	writel(val, info->reg.gpmc_ecc_control);
+
+	/* program ecc and result sizes */
+	val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) |
+			 ECC1RESULTSIZE);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_READSYN:
+		 writel(0x100, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_WRITE:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	default:
+		dev_info(&info->pdev->dev,
+			"error: unrecognized Mode[%d]!\n", mode);
+		break;
+	}
 
-	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
+	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+	val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+	writel(val, info->reg.gpmc_ecc_config);
 }
 
 /**
@@ -884,10 +1014,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	else
 		timeo += (HZ * 20) / 1000;
 
-	gpmc_nand_write(info->gpmc_cs,
-			GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
+	writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
 	while (time_before(jiffies, timeo)) {
-		status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+		status = readb(info->reg.gpmc_nand_data);
 		if (status & NAND_STATUS_READY)
 			break;
 		cond_resched();
@@ -905,22 +1034,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
 
-	val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	val = readl(info->reg.gpmc_status);
+
 	if ((val & 0x100) == 0x100) {
-		/* Clear IRQ Interrupt */
-		val |= 0x100;
-		val &= ~(0x0);
-		gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, val);
+		return 1;
 	} else {
-		unsigned int cnt = 0;
-		while (cnt++ < 0x1FF) {
-			if  ((val & 0x100) == 0x100)
-				return 0;
-			val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
-		}
+		return 0;
 	}
-
-	return 1;
 }
 
 static int __devinit omap_nand_probe(struct platform_device *pdev)
@@ -949,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
+	info->reg		= pdata->reg;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
-- 
1.7.10

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

* [PATCH v4 17/39] mtd: nand: omap2: handle nand on gpmc
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

GPMC driver has been modified to fill NAND platform data with GPMC
NAND register details. As these registers are accessible in NAND
driver itself, configure NAND in GPMC by itself.

Note: Verfying that other CS have not yet enabled for prefetch & ecc
has to be incorporated. Currently this causes no issues as there are
no boards that use NAND on multiple CS. With GPMC modifications,
perhaps it would be better to consider NAND connected on multiple CS
as a single peripheral using multiple CS. This would make handling
multiple CS issues easier.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c |  209 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 165 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 440536b..34fb726 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -129,8 +129,79 @@ struct omap_nand_info {
 	} iomode;
 	u_char				*buf;
 	int					buf_len;
+	struct gpmc_nand_regs		reg;
 };
 
+#define	PREFETCH_CONFIG1_CS_SHIFT	24
+#define	ECC_CONFIG_CS_SHIFT		1
+#define	CS_MASK				0x7
+#define	ENABLE_PREFETCH			(0x1 << 7)
+#define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE1_SHIFT			22
+#define	ECC1RESULTSIZE			0x1
+#define	ECC_CLEAR_SHIFT			8
+#define	ECC1				0x1
+
+/**
+ * omap_prefetch_enable - configures and starts prefetch transfer
+ * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @dma_mode: dma mode enable (1) or disable (0)
+ * @u32_count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ */
+static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode,
+	unsigned int u32_count, int is_write, struct omap_nand_info *info)
+{
+	u32 val;
+
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(readl(info->reg.gpmc_prefetch_control))) {
+		/* Set the amount of bytes to be prefetched */
+		writel(u32_count, info->reg.gpmc_prefetch_config2);
+
+		/* Set dma/mpu mode, the prefetch read / post write and
+		 * enable the engine. Set which cs is has requested for.
+		 */
+		val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
+					ENABLE_PREFETCH |
+					(dma_mode << DMA_MPU_MODE_SHIFT) |
+					(0x1 & is_write));
+		writel(val, info->reg.gpmc_prefetch_config1);
+
+		/*  Start the prefetch engine */
+		writel(0x1, info->reg.gpmc_prefetch_control);
+	} else {
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/**
+ * omap_prefetch_reset - disables and stops the prefetch engine
+ */
+static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
+{
+	u32 config1;
+
+	/* check if the same module/cs is trying to reset */
+	config1 = readl(info->reg.gpmc_prefetch_config1);
+	if (((config1 >> PREFETCH_CONFIG1_CS_SHIFT) & CS_MASK) != cs)
+		return -EINVAL;
+
+	/* Stop the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_control);
+
+	/* Reset/disable the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_config1);
+
+	return 0;
+}
+
 /**
  * omap_hwcontrol - hardware specific access to control-lines
  * @mtd: MTD device structure
@@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 	if (cmd != NAND_CMD_NONE) {
 		if (ctrl & NAND_CLE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_COMMAND, cmd);
+			writeb(cmd, info->reg.gpmc_nand_command);
 
 		else if (ctrl & NAND_ALE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_ADDRESS, cmd);
+			writeb(cmd, info->reg.gpmc_nand_address);
 
 		else /* NAND_NCE */
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_DATA, cmd);
+			writeb(cmd, info->reg.gpmc_nand_data);
 	}
 }
 
@@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		iowrite8(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -226,7 +298,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		iowrite16(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -256,8 +329,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -266,14 +339,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 			omap_read_buf8(mtd, (u_char *)p, len);
 	} else {
 		do {
-			r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			r_count = readl(info->reg.gpmc_prefetch_status);
+			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
 			len -= r_count << 2;
 		} while (len);
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -292,6 +366,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	int i = 0, ret = 0;
 	u16 *p = (u16 *)buf;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -301,8 +376,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -311,7 +386,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 			omap_write_buf8(mtd, (u_char *)p, len);
 	} else {
 		while (len) {
-			w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			w_count = readl(info->reg.gpmc_prefetch_status);
+			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -320,11 +396,14 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		tim = 0;
 		limit = (loops_per_jiffy *
 					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		do {
 			cpu_relax();
+			val = readl(info->reg.gpmc_prefetch_status);
+			val = GPMC_PREFETCH_STATUS_COUNT(val);
+		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -356,6 +435,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	dma_addr_t dma_addr;
 	int ret;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* The fifo depth is 64 bytes max.
 	 * But configure the FIFO-threahold to 32 to get a sync at each frame
@@ -400,8 +480,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -414,11 +494,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	wait_for_completion(&info->comp);
 	tim = 0;
 	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+
+	do {
 		cpu_relax();
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 
 	dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
 	return 0;
@@ -474,7 +558,8 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
 
-	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = readl(info->reg.gpmc_prefetch_status);
+	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -531,8 +616,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	init_completion(&info->comp);
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -546,7 +631,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	wait_for_completion(&info->comp);
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -569,6 +654,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 						struct omap_nand_info, mtd);
 	int ret = 0;
 	unsigned long tim, limit;
+	u32 val;
 
 	if (len <= mtd->oobsize) {
 		omap_write_buf_pref(mtd, buf, len);
@@ -580,8 +666,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	init_completion(&info->comp);
 
 	/* configure and start prefetch transfer : size=24 */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+		(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -597,11 +683,14 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+	do {
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -841,7 +930,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
+	u32 val;
+
+	val = readl(info->reg.gpmc_ecc_config);
+	if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+		return -EINVAL;
+
+	/* read ecc result */
+	val = readl(info->reg.gpmc_ecc1_result);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+	return 0;
 }
 
 /**
@@ -855,8 +957,36 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 							mtd);
 	struct nand_chip *chip = mtd->priv;
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	u32 val;
+
+	/* clear ecc and enable bits */
+	val = ((0x1 << ECC_CLEAR_SHIFT) | ECC1);
+	writel(val, info->reg.gpmc_ecc_control);
+
+	/* program ecc and result sizes */
+	val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) |
+			 ECC1RESULTSIZE);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_READSYN:
+		 writel(0x100, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_WRITE:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	default:
+		dev_info(&info->pdev->dev,
+			"error: unrecognized Mode[%d]!\n", mode);
+		break;
+	}
 
-	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
+	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+	val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+	writel(val, info->reg.gpmc_ecc_config);
 }
 
 /**
@@ -884,10 +1014,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	else
 		timeo += (HZ * 20) / 1000;
 
-	gpmc_nand_write(info->gpmc_cs,
-			GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
+	writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
 	while (time_before(jiffies, timeo)) {
-		status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+		status = readb(info->reg.gpmc_nand_data);
 		if (status & NAND_STATUS_READY)
 			break;
 		cond_resched();
@@ -905,22 +1034,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
 
-	val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	val = readl(info->reg.gpmc_status);
+
 	if ((val & 0x100) == 0x100) {
-		/* Clear IRQ Interrupt */
-		val |= 0x100;
-		val &= ~(0x0);
-		gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, val);
+		return 1;
 	} else {
-		unsigned int cnt = 0;
-		while (cnt++ < 0x1FF) {
-			if  ((val & 0x100) == 0x100)
-				return 0;
-			val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
-		}
+		return 0;
 	}
-
-	return 1;
 }
 
 static int __devinit omap_nand_probe(struct platform_device *pdev)
@@ -949,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
+	info->reg		= pdata->reg;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
-- 
1.7.10

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

* [PATCH v4 18/39] mtd: onenand: omap: obtain memory from resource
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc being converted to driver, provides drivers of peripheral
connected memory space used by the peripheral as memory resource.
Modify nand omap driver to obtain memory detials from resource
structure. And so remove usage of gpmc exported symbols.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 drivers/mtd/onenand/omap2.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 398a827..3ff893d 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -48,13 +48,13 @@
 
 #define DRIVER_NAME "omap2-onenand"
 
-#define ONENAND_IO_SIZE		SZ_128K
 #define ONENAND_BUFRAM_SIZE	(1024 * 5)
 
 struct omap2_onenand {
 	struct platform_device *pdev;
 	int gpmc_cs;
 	unsigned long phys_base;
+	unsigned int mem_size;
 	int gpio_irq;
 	struct mtd_info mtd;
 	struct onenand_chip onenand;
@@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	struct omap2_onenand *c;
 	struct onenand_chip *this;
 	int r;
+	struct resource *res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 		c->gpio_irq = 0;
 	}
 
-	r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
-	if (r < 0) {
-		dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		r = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
 		goto err_kfree;
 	}
 
-	if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+	c->phys_base = res->start;
+	c->mem_size = resource_size(res);
+
+	if (request_mem_region(c->phys_base, c->mem_size,
 			       pdev->dev.driver->name) == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
-			"size: 0x%x\n",	c->phys_base, ONENAND_IO_SIZE);
+		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, size: 0x%x\n",
+						c->phys_base, c->mem_size);
 		r = -EBUSY;
-		goto err_free_cs;
+		goto err_kfree;
 	}
-	c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+	c->onenand.base = ioremap(c->phys_base, c->mem_size);
 	if (c->onenand.base == NULL) {
 		r = -ENOMEM;
 		goto err_release_mem_region;
@@ -776,9 +781,7 @@ err_release_gpio:
 err_iounmap:
 	iounmap(c->onenand.base);
 err_release_mem_region:
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
-err_free_cs:
-	gpmc_cs_free(c->gpmc_cs);
+	release_mem_region(c->phys_base, c->mem_size);
 err_kfree:
 	kfree(c);
 
@@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 		gpio_free(c->gpio_irq);
 	}
 	iounmap(c->onenand.base);
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+	release_mem_region(c->phys_base, c->mem_size);
 	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 18/39] mtd: onenand: omap: obtain memory from resource
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc being converted to driver, provides drivers of peripheral
connected memory space used by the peripheral as memory resource.
Modify nand omap driver to obtain memory detials from resource
structure. And so remove usage of gpmc exported symbols.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/onenand/omap2.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 398a827..3ff893d 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -48,13 +48,13 @@
 
 #define DRIVER_NAME "omap2-onenand"
 
-#define ONENAND_IO_SIZE		SZ_128K
 #define ONENAND_BUFRAM_SIZE	(1024 * 5)
 
 struct omap2_onenand {
 	struct platform_device *pdev;
 	int gpmc_cs;
 	unsigned long phys_base;
+	unsigned int mem_size;
 	int gpio_irq;
 	struct mtd_info mtd;
 	struct onenand_chip onenand;
@@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	struct omap2_onenand *c;
 	struct onenand_chip *this;
 	int r;
+	struct resource *res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 		c->gpio_irq = 0;
 	}
 
-	r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
-	if (r < 0) {
-		dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		r = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
 		goto err_kfree;
 	}
 
-	if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+	c->phys_base = res->start;
+	c->mem_size = resource_size(res);
+
+	if (request_mem_region(c->phys_base, c->mem_size,
 			       pdev->dev.driver->name) == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
-			"size: 0x%x\n",	c->phys_base, ONENAND_IO_SIZE);
+		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, size: 0x%x\n",
+						c->phys_base, c->mem_size);
 		r = -EBUSY;
-		goto err_free_cs;
+		goto err_kfree;
 	}
-	c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+	c->onenand.base = ioremap(c->phys_base, c->mem_size);
 	if (c->onenand.base == NULL) {
 		r = -ENOMEM;
 		goto err_release_mem_region;
@@ -776,9 +781,7 @@ err_release_gpio:
 err_iounmap:
 	iounmap(c->onenand.base);
 err_release_mem_region:
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
-err_free_cs:
-	gpmc_cs_free(c->gpmc_cs);
+	release_mem_region(c->phys_base, c->mem_size);
 err_kfree:
 	kfree(c);
 
@@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 		gpio_free(c->gpio_irq);
 	}
 	iounmap(c->onenand.base);
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+	release_mem_region(c->phys_base, c->mem_size);
 	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
-- 
1.7.10

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

* [PATCH v4 18/39] mtd: onenand: omap: obtain memory from resource
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc being converted to driver, provides drivers of peripheral
connected memory space used by the peripheral as memory resource.
Modify nand omap driver to obtain memory detials from resource
structure. And so remove usage of gpmc exported symbols.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/onenand/omap2.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 398a827..3ff893d 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -48,13 +48,13 @@
 
 #define DRIVER_NAME "omap2-onenand"
 
-#define ONENAND_IO_SIZE		SZ_128K
 #define ONENAND_BUFRAM_SIZE	(1024 * 5)
 
 struct omap2_onenand {
 	struct platform_device *pdev;
 	int gpmc_cs;
 	unsigned long phys_base;
+	unsigned int mem_size;
 	int gpio_irq;
 	struct mtd_info mtd;
 	struct onenand_chip onenand;
@@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	struct omap2_onenand *c;
 	struct onenand_chip *this;
 	int r;
+	struct resource *res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 		c->gpio_irq = 0;
 	}
 
-	r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
-	if (r < 0) {
-		dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		r = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
 		goto err_kfree;
 	}
 
-	if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+	c->phys_base = res->start;
+	c->mem_size = resource_size(res);
+
+	if (request_mem_region(c->phys_base, c->mem_size,
 			       pdev->dev.driver->name) == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
-			"size: 0x%x\n",	c->phys_base, ONENAND_IO_SIZE);
+		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, size: 0x%x\n",
+						c->phys_base, c->mem_size);
 		r = -EBUSY;
-		goto err_free_cs;
+		goto err_kfree;
 	}
-	c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+	c->onenand.base = ioremap(c->phys_base, c->mem_size);
 	if (c->onenand.base == NULL) {
 		r = -ENOMEM;
 		goto err_release_mem_region;
@@ -776,9 +781,7 @@ err_release_gpio:
 err_iounmap:
 	iounmap(c->onenand.base);
 err_release_mem_region:
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
-err_free_cs:
-	gpmc_cs_free(c->gpmc_cs);
+	release_mem_region(c->phys_base, c->mem_size);
 err_kfree:
 	kfree(c);
 
@@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 		gpio_free(c->gpio_irq);
 	}
 	iounmap(c->onenand.base);
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+	release_mem_region(c->phys_base, c->mem_size);
 	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
-- 
1.7.10

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

* [PATCH v4 19/39] ARM: OMAP2+: board omap3evm: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3evm.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index fd1b481..b00765e 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -43,6 +43,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/gpmc.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -102,6 +103,12 @@ static void __init omap3_evm_get_revision(void)
 	}
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -122,7 +129,11 @@ static inline void __init omap3evm_init_smsc911x(void)
 			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST;
 	}
 
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -679,6 +690,7 @@ static void __init omap3_evm_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
 	omap3evm_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
 }
-- 
1.7.10


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

* [PATCH v4 19/39] ARM: OMAP2+: board omap3evm: gpmc driver adaptation
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3evm.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index fd1b481..b00765e 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -43,6 +43,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/gpmc.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -102,6 +103,12 @@ static void __init omap3_evm_get_revision(void)
 	}
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -122,7 +129,11 @@ static inline void __init omap3evm_init_smsc911x(void)
 			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST;
 	}
 
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -679,6 +690,7 @@ static void __init omap3_evm_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
 	omap3evm_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
 }
-- 
1.7.10

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

* [PATCH v4 19/39] ARM: OMAP2+: board omap3evm: gpmc driver adaptation
@ 2012-05-01 12:21   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3evm.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index fd1b481..b00765e 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -43,6 +43,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/gpmc.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -102,6 +103,12 @@ static void __init omap3_evm_get_revision(void)
 	}
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -122,7 +129,11 @@ static inline void __init omap3evm_init_smsc911x(void)
 			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST;
 	}
 
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -679,6 +690,7 @@ static void __init omap3_evm_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
 	omap3evm_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
 }
-- 
1.7.10

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

* [PATCH v4 20/39] ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:21     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-omap3beagle.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 671ac1c..74bc7f6 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -517,8 +517,16 @@ static void __init beagle_opp_init(void)
 	return;
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static void __init omap3_beagle_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 
@@ -543,9 +551,17 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	board_nand_init(omap3beagle_nand_partitions,
+	nand_data = board_nand_init(omap3beagle_nand_partitions,
 		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
 		NAND_BUSWIDTH_16, NULL);
+	if (nand_data != NULL) {
+		*gpmc_device_data = gpmc_nand_init(nand_data);
+		if (*gpmc_device_data)
+			gpmc_data.num_device++;
+	} else
+		pr_err("error: %s: nand init\n", __func__);
+
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 20/39] ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 671ac1c..74bc7f6 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -517,8 +517,16 @@ static void __init beagle_opp_init(void)
 	return;
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static void __init omap3_beagle_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 
@@ -543,9 +551,17 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	board_nand_init(omap3beagle_nand_partitions,
+	nand_data = board_nand_init(omap3beagle_nand_partitions,
 		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
 		NAND_BUSWIDTH_16, NULL);
+	if (nand_data != NULL) {
+		*gpmc_device_data = gpmc_nand_init(nand_data);
+		if (*gpmc_device_data)
+			gpmc_data.num_device++;
+	} else
+		pr_err("error: %s: nand init\n", __func__);
+
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
-- 
1.7.10

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

* [PATCH v4 20/39] ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
@ 2012-05-01 12:21     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 671ac1c..74bc7f6 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -517,8 +517,16 @@ static void __init beagle_opp_init(void)
 	return;
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static void __init omap3_beagle_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 
@@ -543,9 +551,17 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	board_nand_init(omap3beagle_nand_partitions,
+	nand_data = board_nand_init(omap3beagle_nand_partitions,
 		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
 		NAND_BUSWIDTH_16, NULL);
+	if (nand_data != NULL) {
+		*gpmc_device_data = gpmc_nand_init(nand_data);
+		if (*gpmc_device_data)
+			gpmc_data.num_device++;
+	} else
+		pr_err("error: %s: nand init\n", __func__);
+
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
-- 
1.7.10

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

* [PATCH v4 21/39] ARM: OMAP2+: board apollon: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to
provide gpmc driver with required information. It is believed that
apollon board was added before gpmc-smc91x helper functions were
added. Reuse the now available gpmc_smc91x_init adapted for gpmc
driver.

Note: Timing values were hardcoded and written onto registers,
whether making use of gpmc_smc91x_init would configure timing
properly has to be tested.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-apollon.c |  152 +++++++++--------------------------
 1 file changed, 38 insertions(+), 114 deletions(-)

diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 768ece2..6a402e1 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,6 +39,7 @@
 #include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
+#include <plat/gpmc-smc91x.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,12 @@
 #define APOLLON_ETH_CS		1
 #define APOLLON_ETHR_GPIO_IRQ	74
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition apollon_partitions[] = {
 	{
 		.name		= "X-Loader + U-Boot",
@@ -97,57 +104,26 @@ static struct onenand_platform_data apollon_flash_data = {
 	.nr_parts	= ARRAY_SIZE(apollon_partitions),
 };
 
-static struct resource apollon_flash_resource[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
+static struct gpmc_cs_data apollon_gpmc_onenand_cs_data = {
+	.cs		= APOLLON_FLASH_CS,
+	.mem_size	= SZ_128K,
 };
 
-static struct platform_device apollon_onenand_device = {
+static struct gpmc_device_pdata apollon_gpmc_onenand_data = {
 	.name		= "onenand-flash",
 	.id		= -1,
-	.dev		= {
-		.platform_data	= &apollon_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_flash_resource),
-	.resource	= apollon_flash_resource,
-};
-
-static void __init apollon_flash_init(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
-		printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
-		return;
-	}
-	apollon_flash_resource[0].start = base;
-	apollon_flash_resource[0].end   = base + SZ_128K - 1;
-}
-
-static struct smc91x_platdata appolon_smc91x_info = {
-	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
-	.leda	= RPC_LED_100_10,
-	.ledb	= RPC_LED_TX_RX,
+	.pdata		= &apollon_flash_data,
+	.pdata_size	= sizeof(apollon_flash_data),
+	.cs_data	= &apollon_gpmc_onenand_cs_data,
+	.num_cs		= 1,
 };
 
-static struct resource apollon_smc91x_resources[] = {
-	[0] = {
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device apollon_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= &appolon_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
-	.resource	= apollon_smc91x_resources,
+static struct omap_smc91x_platform_data apollon_smc91x_data = {
+	.gpio_irq	= APOLLON_ETHR_GPIO_IRQ,
+	.cs		= APOLLON_ETH_CS,
+	.wait_pin	= GPMC_WAITPIN_1,
+	.flags		= GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHEDGE |
+				GPMC_MUXADDDATA,
 };
 
 static struct omap_led_config apollon_led_config[] = {
@@ -185,74 +161,9 @@ static struct platform_device apollon_led_device = {
 };
 
 static struct platform_device *apollon_devices[] __initdata = {
-	&apollon_onenand_device,
-	&apollon_smc91x_device,
 	&apollon_led_device,
 };
 
-static inline void __init apollon_init_smc91x(void)
-{
-	unsigned long base;
-
-	unsigned int rate;
-	struct clk *gpmc_fck;
-	int eth_cs;
-	int err;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-
-	eth_cs = APOLLON_ETH_CS;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
-		goto out;
-	}
-	apollon_smc91x_resources[0].start = base + 0x300;
-	apollon_smc91x_resources[0].end   = base + 0x30f;
-	udelay(100);
-
-	omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0);
-	err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq");
-	if (err) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			APOLLON_ETHR_GPIO_IRQ);
-		gpmc_cs_free(APOLLON_ETH_CS);
-	}
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
 static struct omap_usb_config apollon_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0x14,	/* 0:dev 1:host1 2:disable */
@@ -315,12 +226,27 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap_apollon_init(void)
 {
 	u32 v;
+	int err, idx = 0;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-	apollon_init_smc91x();
+	gpmc_device_data[idx++] = &apollon_gpmc_onenand_data;
+	gpmc_data.num_device++;
+
+	omap_mux_init_gpio(apollon_smc91x_data.gpio_irq, 0);
+	err = gpio_request_one(apollon_smc91x_data.gpio_irq,
+			GPIOF_IN, "SMC91x irq");
+	if (err) {
+		pr_err("error: %s: Failed to request GPIO%d for smc91x IRQ\n",
+			__func__, apollon_smc91x_data.gpio_irq);
+	} else {
+		gpmc_device_data[idx++] =
+			gpmc_smc91x_init(&apollon_smc91x_data);
+		gpmc_data.num_device++;
+	}
+	omap_init_gpmc(&gpmc_data);
+
 	apollon_led_init();
-	apollon_flash_init();
 	apollon_usb_init();
 
 	/* REVISIT: where's the correct place */
@@ -339,8 +265,6 @@ static void __init omap_apollon_init(void)
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
-	apollon_smc91x_resources[1].start = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
-	apollon_smc91x_resources[1].end = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 21/39] ARM: OMAP2+: board apollon: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to
provide gpmc driver with required information. It is believed that
apollon board was added before gpmc-smc91x helper functions were
added. Reuse the now available gpmc_smc91x_init adapted for gpmc
driver.

Note: Timing values were hardcoded and written onto registers,
whether making use of gpmc_smc91x_init would configure timing
properly has to be tested.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-apollon.c |  152 +++++++++--------------------------
 1 file changed, 38 insertions(+), 114 deletions(-)

diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 768ece2..6a402e1 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,6 +39,7 @@
 #include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
+#include <plat/gpmc-smc91x.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,12 @@
 #define APOLLON_ETH_CS		1
 #define APOLLON_ETHR_GPIO_IRQ	74
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition apollon_partitions[] = {
 	{
 		.name		= "X-Loader + U-Boot",
@@ -97,57 +104,26 @@ static struct onenand_platform_data apollon_flash_data = {
 	.nr_parts	= ARRAY_SIZE(apollon_partitions),
 };
 
-static struct resource apollon_flash_resource[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
+static struct gpmc_cs_data apollon_gpmc_onenand_cs_data = {
+	.cs		= APOLLON_FLASH_CS,
+	.mem_size	= SZ_128K,
 };
 
-static struct platform_device apollon_onenand_device = {
+static struct gpmc_device_pdata apollon_gpmc_onenand_data = {
 	.name		= "onenand-flash",
 	.id		= -1,
-	.dev		= {
-		.platform_data	= &apollon_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_flash_resource),
-	.resource	= apollon_flash_resource,
-};
-
-static void __init apollon_flash_init(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
-		printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
-		return;
-	}
-	apollon_flash_resource[0].start = base;
-	apollon_flash_resource[0].end   = base + SZ_128K - 1;
-}
-
-static struct smc91x_platdata appolon_smc91x_info = {
-	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
-	.leda	= RPC_LED_100_10,
-	.ledb	= RPC_LED_TX_RX,
+	.pdata		= &apollon_flash_data,
+	.pdata_size	= sizeof(apollon_flash_data),
+	.cs_data	= &apollon_gpmc_onenand_cs_data,
+	.num_cs		= 1,
 };
 
-static struct resource apollon_smc91x_resources[] = {
-	[0] = {
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device apollon_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= &appolon_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
-	.resource	= apollon_smc91x_resources,
+static struct omap_smc91x_platform_data apollon_smc91x_data = {
+	.gpio_irq	= APOLLON_ETHR_GPIO_IRQ,
+	.cs		= APOLLON_ETH_CS,
+	.wait_pin	= GPMC_WAITPIN_1,
+	.flags		= GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHEDGE |
+				GPMC_MUXADDDATA,
 };
 
 static struct omap_led_config apollon_led_config[] = {
@@ -185,74 +161,9 @@ static struct platform_device apollon_led_device = {
 };
 
 static struct platform_device *apollon_devices[] __initdata = {
-	&apollon_onenand_device,
-	&apollon_smc91x_device,
 	&apollon_led_device,
 };
 
-static inline void __init apollon_init_smc91x(void)
-{
-	unsigned long base;
-
-	unsigned int rate;
-	struct clk *gpmc_fck;
-	int eth_cs;
-	int err;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-
-	eth_cs = APOLLON_ETH_CS;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
-		goto out;
-	}
-	apollon_smc91x_resources[0].start = base + 0x300;
-	apollon_smc91x_resources[0].end   = base + 0x30f;
-	udelay(100);
-
-	omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0);
-	err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq");
-	if (err) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			APOLLON_ETHR_GPIO_IRQ);
-		gpmc_cs_free(APOLLON_ETH_CS);
-	}
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
 static struct omap_usb_config apollon_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0x14,	/* 0:dev 1:host1 2:disable */
@@ -315,12 +226,27 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap_apollon_init(void)
 {
 	u32 v;
+	int err, idx = 0;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-	apollon_init_smc91x();
+	gpmc_device_data[idx++] = &apollon_gpmc_onenand_data;
+	gpmc_data.num_device++;
+
+	omap_mux_init_gpio(apollon_smc91x_data.gpio_irq, 0);
+	err = gpio_request_one(apollon_smc91x_data.gpio_irq,
+			GPIOF_IN, "SMC91x irq");
+	if (err) {
+		pr_err("error: %s: Failed to request GPIO%d for smc91x IRQ\n",
+			__func__, apollon_smc91x_data.gpio_irq);
+	} else {
+		gpmc_device_data[idx++] =
+			gpmc_smc91x_init(&apollon_smc91x_data);
+		gpmc_data.num_device++;
+	}
+	omap_init_gpmc(&gpmc_data);
+
 	apollon_led_init();
-	apollon_flash_init();
 	apollon_usb_init();
 
 	/* REVISIT: where's the correct place */
@@ -339,8 +265,6 @@ static void __init omap_apollon_init(void)
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
-	apollon_smc91x_resources[1].start = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
-	apollon_smc91x_resources[1].end = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-- 
1.7.10

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

* [PATCH v4 21/39] ARM: OMAP2+: board apollon: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board code to
provide gpmc driver with required information. It is believed that
apollon board was added before gpmc-smc91x helper functions were
added. Reuse the now available gpmc_smc91x_init adapted for gpmc
driver.

Note: Timing values were hardcoded and written onto registers,
whether making use of gpmc_smc91x_init would configure timing
properly has to be tested.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-apollon.c |  152 +++++++++--------------------------
 1 file changed, 38 insertions(+), 114 deletions(-)

diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 768ece2..6a402e1 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,6 +39,7 @@
 #include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
+#include <plat/gpmc-smc91x.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,12 @@
 #define APOLLON_ETH_CS		1
 #define APOLLON_ETHR_GPIO_IRQ	74
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition apollon_partitions[] = {
 	{
 		.name		= "X-Loader + U-Boot",
@@ -97,57 +104,26 @@ static struct onenand_platform_data apollon_flash_data = {
 	.nr_parts	= ARRAY_SIZE(apollon_partitions),
 };
 
-static struct resource apollon_flash_resource[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
+static struct gpmc_cs_data apollon_gpmc_onenand_cs_data = {
+	.cs		= APOLLON_FLASH_CS,
+	.mem_size	= SZ_128K,
 };
 
-static struct platform_device apollon_onenand_device = {
+static struct gpmc_device_pdata apollon_gpmc_onenand_data = {
 	.name		= "onenand-flash",
 	.id		= -1,
-	.dev		= {
-		.platform_data	= &apollon_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_flash_resource),
-	.resource	= apollon_flash_resource,
-};
-
-static void __init apollon_flash_init(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
-		printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
-		return;
-	}
-	apollon_flash_resource[0].start = base;
-	apollon_flash_resource[0].end   = base + SZ_128K - 1;
-}
-
-static struct smc91x_platdata appolon_smc91x_info = {
-	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
-	.leda	= RPC_LED_100_10,
-	.ledb	= RPC_LED_TX_RX,
+	.pdata		= &apollon_flash_data,
+	.pdata_size	= sizeof(apollon_flash_data),
+	.cs_data	= &apollon_gpmc_onenand_cs_data,
+	.num_cs		= 1,
 };
 
-static struct resource apollon_smc91x_resources[] = {
-	[0] = {
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device apollon_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= &appolon_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
-	.resource	= apollon_smc91x_resources,
+static struct omap_smc91x_platform_data apollon_smc91x_data = {
+	.gpio_irq	= APOLLON_ETHR_GPIO_IRQ,
+	.cs		= APOLLON_ETH_CS,
+	.wait_pin	= GPMC_WAITPIN_1,
+	.flags		= GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHEDGE |
+				GPMC_MUXADDDATA,
 };
 
 static struct omap_led_config apollon_led_config[] = {
@@ -185,74 +161,9 @@ static struct platform_device apollon_led_device = {
 };
 
 static struct platform_device *apollon_devices[] __initdata = {
-	&apollon_onenand_device,
-	&apollon_smc91x_device,
 	&apollon_led_device,
 };
 
-static inline void __init apollon_init_smc91x(void)
-{
-	unsigned long base;
-
-	unsigned int rate;
-	struct clk *gpmc_fck;
-	int eth_cs;
-	int err;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-
-	eth_cs = APOLLON_ETH_CS;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
-		goto out;
-	}
-	apollon_smc91x_resources[0].start = base + 0x300;
-	apollon_smc91x_resources[0].end   = base + 0x30f;
-	udelay(100);
-
-	omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0);
-	err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq");
-	if (err) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			APOLLON_ETHR_GPIO_IRQ);
-		gpmc_cs_free(APOLLON_ETH_CS);
-	}
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
 static struct omap_usb_config apollon_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0x14,	/* 0:dev 1:host1 2:disable */
@@ -315,12 +226,27 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap_apollon_init(void)
 {
 	u32 v;
+	int err, idx = 0;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-	apollon_init_smc91x();
+	gpmc_device_data[idx++] = &apollon_gpmc_onenand_data;
+	gpmc_data.num_device++;
+
+	omap_mux_init_gpio(apollon_smc91x_data.gpio_irq, 0);
+	err = gpio_request_one(apollon_smc91x_data.gpio_irq,
+			GPIOF_IN, "SMC91x irq");
+	if (err) {
+		pr_err("error: %s: Failed to request GPIO%d for smc91x IRQ\n",
+			__func__, apollon_smc91x_data.gpio_irq);
+	} else {
+		gpmc_device_data[idx++] =
+			gpmc_smc91x_init(&apollon_smc91x_data);
+		gpmc_data.num_device++;
+	}
+	omap_init_gpmc(&gpmc_data);
+
 	apollon_led_init();
-	apollon_flash_init();
 	apollon_usb_init();
 
 	/* REVISIT: where's the correct place */
@@ -339,8 +265,6 @@ static void __init omap_apollon_init(void)
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
-	apollon_smc91x_resources[1].start = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
-	apollon_smc91x_resources[1].end = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-- 
1.7.10

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

* [PATCH v4 22/39] ARM: OMAP2+: board h4: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.
Remove unused h4_init_debug too.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-h4.c |  130 +++++-----------------------------------
 1 file changed, 15 insertions(+), 115 deletions(-)

diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 0bbbabe..7926082 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -186,22 +186,24 @@ static struct physmap_flash_data h4_flash_data = {
 	.nr_parts	= ARRAY_SIZE(h4_partitions),
 };
 
-static struct resource h4_flash_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data h4_gpmc_cs_flash_data = {
+	.cs		= H4_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device h4_flash_device = {
+static struct gpmc_device_pdata h4_gpmc_flash_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-		.platform_data	= &h4_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &h4_flash_resource,
+	.pdata		= &h4_flash_data,
+	.pdata_size	= sizeof(h4_flash_data),
+	.cs_data	= &h4_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
 };
 
 static struct panel_generic_dpi_data h4_panel_data = {
@@ -226,109 +228,6 @@ static struct omap_dss_board_info h4_dss_data = {
 	.default_device	= &h4_lcd_device,
 };
 
-/* 2420 Sysboot setup (2430 is different) */
-static u32 get_sysboot_value(void)
-{
-	return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
-		(OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
-		 OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
-		 OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
-}
-
-/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
- *
- * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
- *  correctly.  The macro needs to look at production_id not just hawkeye.
- */
-static u32 is_gpmc_muxed(void)
-{
-	u32 mux;
-	mux = get_sysboot_value();
-	if ((mux & 0xF) == 0xd)
-		return 1;	/* NAND config (could be either) */
-	if (mux & 0x2)		/* if mux'ed */
-		return 1;
-	else
-		return 0;
-}
-
-static inline void __init h4_init_debug(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	unsigned int muxed, rate;
-	struct clk *gpmc_fck;
-
-	eth_cs	= H4_SMC91X_CS;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-
-	if (is_gpmc_muxed())
-		muxed = 0x200;
-	else
-		muxed = 0;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
-			  0x00011000 | muxed);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		goto out;
-	}
-
-	udelay(100);
-
-	omap_mux_init_gpio(92, 0);
-	if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0)
-		gpmc_cs_free(eth_cs);
-
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
-static void __init h4_init_flash(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
-		printk("Can't request GPMC CS for flash\n");
-		return;
-	}
-	h4_flash_resource.start	= base;
-	h4_flash_resource.end	= base + SZ_64M - 1;
-}

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

* [PATCH v4 22/39] ARM: OMAP2+: board h4: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.
Remove unused h4_init_debug too.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-h4.c |  130 +++++-----------------------------------
 1 file changed, 15 insertions(+), 115 deletions(-)

diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 0bbbabe..7926082 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -186,22 +186,24 @@ static struct physmap_flash_data h4_flash_data = {
 	.nr_parts	= ARRAY_SIZE(h4_partitions),
 };
 
-static struct resource h4_flash_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data h4_gpmc_cs_flash_data = {
+	.cs		= H4_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device h4_flash_device = {
+static struct gpmc_device_pdata h4_gpmc_flash_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-		.platform_data	= &h4_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &h4_flash_resource,
+	.pdata		= &h4_flash_data,
+	.pdata_size	= sizeof(h4_flash_data),
+	.cs_data	= &h4_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
 };
 
 static struct panel_generic_dpi_data h4_panel_data = {
@@ -226,109 +228,6 @@ static struct omap_dss_board_info h4_dss_data = {
 	.default_device	= &h4_lcd_device,
 };
 
-/* 2420 Sysboot setup (2430 is different) */
-static u32 get_sysboot_value(void)
-{
-	return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
-		(OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
-		 OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
-		 OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
-}
-
-/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
- *
- * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
- *  correctly.  The macro needs to look at production_id not just hawkeye.
- */
-static u32 is_gpmc_muxed(void)
-{
-	u32 mux;
-	mux = get_sysboot_value();
-	if ((mux & 0xF) == 0xd)
-		return 1;	/* NAND config (could be either) */
-	if (mux & 0x2)		/* if mux'ed */
-		return 1;
-	else
-		return 0;
-}
-
-static inline void __init h4_init_debug(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	unsigned int muxed, rate;
-	struct clk *gpmc_fck;
-
-	eth_cs	= H4_SMC91X_CS;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-
-	if (is_gpmc_muxed())
-		muxed = 0x200;
-	else
-		muxed = 0;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
-			  0x00011000 | muxed);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		goto out;
-	}
-
-	udelay(100);
-
-	omap_mux_init_gpio(92, 0);
-	if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0)
-		gpmc_cs_free(eth_cs);
-
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
-static void __init h4_init_flash(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
-		printk("Can't request GPMC CS for flash\n");
-		return;
-	}
-	h4_flash_resource.start	= base;
-	h4_flash_resource.end	= base + SZ_64M - 1;
-}
-
 static struct omap_usb_config h4_usb_config __initdata = {
 	/* S1.10 OFF -- usb "download port"
 	 * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -380,11 +279,12 @@ static void __init omap_h4_init(void)
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 
-	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	h4_init_flash();
+	*gpmc_device_data = &h4_gpmc_flash_data;
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 
 	omap_display_init(&h4_dss_data);
 }
-- 
1.7.10

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

* [PATCH v4 22/39] ARM: OMAP2+: board h4: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.
Remove unused h4_init_debug too.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-h4.c |  130 +++++-----------------------------------
 1 file changed, 15 insertions(+), 115 deletions(-)

diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 0bbbabe..7926082 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -186,22 +186,24 @@ static struct physmap_flash_data h4_flash_data = {
 	.nr_parts	= ARRAY_SIZE(h4_partitions),
 };
 
-static struct resource h4_flash_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data h4_gpmc_cs_flash_data = {
+	.cs		= H4_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device h4_flash_device = {
+static struct gpmc_device_pdata h4_gpmc_flash_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-		.platform_data	= &h4_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &h4_flash_resource,
+	.pdata		= &h4_flash_data,
+	.pdata_size	= sizeof(h4_flash_data),
+	.cs_data	= &h4_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
 };
 
 static struct panel_generic_dpi_data h4_panel_data = {
@@ -226,109 +228,6 @@ static struct omap_dss_board_info h4_dss_data = {
 	.default_device	= &h4_lcd_device,
 };
 
-/* 2420 Sysboot setup (2430 is different) */
-static u32 get_sysboot_value(void)
-{
-	return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
-		(OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
-		 OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
-		 OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
-}
-
-/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
- *
- * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
- *  correctly.  The macro needs to look at production_id not just hawkeye.
- */
-static u32 is_gpmc_muxed(void)
-{
-	u32 mux;
-	mux = get_sysboot_value();
-	if ((mux & 0xF) == 0xd)
-		return 1;	/* NAND config (could be either) */
-	if (mux & 0x2)		/* if mux'ed */
-		return 1;
-	else
-		return 0;
-}
-
-static inline void __init h4_init_debug(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	unsigned int muxed, rate;
-	struct clk *gpmc_fck;
-
-	eth_cs	= H4_SMC91X_CS;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-
-	if (is_gpmc_muxed())
-		muxed = 0x200;
-	else
-		muxed = 0;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
-			  0x00011000 | muxed);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		goto out;
-	}
-
-	udelay(100);
-
-	omap_mux_init_gpio(92, 0);
-	if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0)
-		gpmc_cs_free(eth_cs);
-
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
-static void __init h4_init_flash(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
-		printk("Can't request GPMC CS for flash\n");
-		return;
-	}
-	h4_flash_resource.start	= base;
-	h4_flash_resource.end	= base + SZ_64M - 1;
-}
-
 static struct omap_usb_config h4_usb_config __initdata = {
 	/* S1.10 OFF -- usb "download port"
 	 * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -380,11 +279,12 @@ static void __init omap_h4_init(void)
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 
-	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	h4_init_flash();
+	*gpmc_device_data = &h4_gpmc_flash_data;
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 
 	omap_display_init(&h4_dss_data);
 }
-- 
1.7.10

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

* [PATCH v4 23/39] ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3630sdp.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 143e47f..4e0298a 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -27,18 +27,29 @@
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
 	.skip_timing	= true,
+	.gpio_irq	= 158,
 };
 
 static void __init board_smc91x_init(void)
 {
-	board_smc91x_data.gpio_irq = 158;
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -204,9 +215,13 @@ static void __init omap_sdp_init(void)
 	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
+
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
-		NAND_BUSWIDTH_16, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_sdp, NAND_BUSWIDTH_16,
+					gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
-- 
1.7.10


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

* [PATCH v4 23/39] ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3630sdp.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 143e47f..4e0298a 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -27,18 +27,29 @@
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
 	.skip_timing	= true,
+	.gpio_irq	= 158,
 };
 
 static void __init board_smc91x_init(void)
 {
-	board_smc91x_data.gpio_irq = 158;
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -204,9 +215,13 @@ static void __init omap_sdp_init(void)
 	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
+
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
-		NAND_BUSWIDTH_16, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_sdp, NAND_BUSWIDTH_16,
+					gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
-- 
1.7.10

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

* [PATCH v4 23/39] ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3630sdp.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 143e47f..4e0298a 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -27,18 +27,29 @@
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
 	.skip_timing	= true,
+	.gpio_irq	= 158,
 };
 
 static void __init board_smc91x_init(void)
 {
-	board_smc91x_data.gpio_irq = 158;
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -204,9 +215,13 @@ static void __init omap_sdp_init(void)
 	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
+
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
-		NAND_BUSWIDTH_16, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_sdp, NAND_BUSWIDTH_16,
+					gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
-- 
1.7.10

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

* [PATCH v4 24/39] ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 367a466..cea5ca5 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -59,6 +59,12 @@
 
 #define TWL4030_MSECURE_GPIO 22
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -444,7 +450,11 @@ static void __init board_smc91x_init(void)
 	else
 		board_smc91x_data.gpio_irq = 29;
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -621,7 +631,10 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_3430, 0, gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
-- 
1.7.10


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

* [PATCH v4 24/39] ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 367a466..cea5ca5 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -59,6 +59,12 @@
 
 #define TWL4030_MSECURE_GPIO 22
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -444,7 +450,11 @@ static void __init board_smc91x_init(void)
 	else
 		board_smc91x_data.gpio_irq = 29;
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -621,7 +631,10 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_3430, 0, gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
-- 
1.7.10

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

* [PATCH v4 24/39] ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 367a466..cea5ca5 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -59,6 +59,12 @@
 
 #define TWL4030_MSECURE_GPIO 22
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -444,7 +450,11 @@ static void __init board_smc91x_init(void)
 	else
 		board_smc91x_data.gpio_irq = 29;
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -621,7 +631,10 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_3430, 0, gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
-- 
1.7.10

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

* [PATCH v4 25/39] ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c |   42 +++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 68679a8..d94ada4 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -46,9 +46,16 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define SDP2430_CS0_BASE	0x04000000
+#define SDP2430_FLASH_CS		0
 #define SECONDARY_LCD_GPIO		147
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -86,24 +93,18 @@ static struct physmap_flash_data sdp2430_flash_data = {
 	.nr_parts	= ARRAY_SIZE(sdp2430_partitions),
 };
 
-static struct resource sdp2430_flash_resource = {
-	.start		= SDP2430_CS0_BASE,
-	.end		= SDP2430_CS0_BASE + SZ_64M - 1,
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data sdp2430_gpmc_cs_flash_data = {
+	.cs		= SDP2430_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device sdp2430_flash_device = {
+static struct gpmc_device_pdata sdp2430_gpmc_flash_device = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev = {
-		.platform_data	= &sdp2430_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &sdp2430_flash_resource,
-};
-
-static struct platform_device *sdp2430_devices[] __initdata = {
-	&sdp2430_flash_device,
+	.pdata		= &sdp2430_flash_data,
+	.pdata_size	= sizeof(sdp2430_flash_data),
+	.cs_data	= &sdp2430_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
 /* LCD */
@@ -181,7 +182,11 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 static void __init board_smc91x_init(void)
 {
 	omap_mux_init_gpio(149, OMAP_PIN_INPUT);
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -276,7 +281,9 @@ static void __init omap_2430sdp_init(void)
 
 	omap2430_i2c_init();
 
-	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
+	*gpmc_cur++ = &sdp2430_gpmc_flash_device;
+	gpmc_data.num_device++;
+
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	omap_hsmmc_init(mmc);
@@ -286,6 +293,7 @@ static void __init omap_2430sdp_init(void)
 	usb_musb_init(NULL);
 
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
-- 
1.7.10


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

* [PATCH v4 25/39] ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c |   42 +++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 68679a8..d94ada4 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -46,9 +46,16 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define SDP2430_CS0_BASE	0x04000000
+#define SDP2430_FLASH_CS		0
 #define SECONDARY_LCD_GPIO		147
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -86,24 +93,18 @@ static struct physmap_flash_data sdp2430_flash_data = {
 	.nr_parts	= ARRAY_SIZE(sdp2430_partitions),
 };
 
-static struct resource sdp2430_flash_resource = {
-	.start		= SDP2430_CS0_BASE,
-	.end		= SDP2430_CS0_BASE + SZ_64M - 1,
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data sdp2430_gpmc_cs_flash_data = {
+	.cs		= SDP2430_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device sdp2430_flash_device = {
+static struct gpmc_device_pdata sdp2430_gpmc_flash_device = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev = {
-		.platform_data	= &sdp2430_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &sdp2430_flash_resource,
-};
-
-static struct platform_device *sdp2430_devices[] __initdata = {
-	&sdp2430_flash_device,
+	.pdata		= &sdp2430_flash_data,
+	.pdata_size	= sizeof(sdp2430_flash_data),
+	.cs_data	= &sdp2430_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
 /* LCD */
@@ -181,7 +182,11 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 static void __init board_smc91x_init(void)
 {
 	omap_mux_init_gpio(149, OMAP_PIN_INPUT);
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -276,7 +281,9 @@ static void __init omap_2430sdp_init(void)
 
 	omap2430_i2c_init();
 
-	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
+	*gpmc_cur++ = &sdp2430_gpmc_flash_device;
+	gpmc_data.num_device++;
+
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	omap_hsmmc_init(mmc);
@@ -286,6 +293,7 @@ static void __init omap_2430sdp_init(void)
 	usb_musb_init(NULL);
 
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
-- 
1.7.10

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

* [PATCH v4 25/39] ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c |   42 +++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 68679a8..d94ada4 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -46,9 +46,16 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define SDP2430_CS0_BASE	0x04000000
+#define SDP2430_FLASH_CS		0
 #define SECONDARY_LCD_GPIO		147
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -86,24 +93,18 @@ static struct physmap_flash_data sdp2430_flash_data = {
 	.nr_parts	= ARRAY_SIZE(sdp2430_partitions),
 };
 
-static struct resource sdp2430_flash_resource = {
-	.start		= SDP2430_CS0_BASE,
-	.end		= SDP2430_CS0_BASE + SZ_64M - 1,
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data sdp2430_gpmc_cs_flash_data = {
+	.cs		= SDP2430_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device sdp2430_flash_device = {
+static struct gpmc_device_pdata sdp2430_gpmc_flash_device = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev = {
-		.platform_data	= &sdp2430_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &sdp2430_flash_resource,
-};
-
-static struct platform_device *sdp2430_devices[] __initdata = {
-	&sdp2430_flash_device,
+	.pdata		= &sdp2430_flash_data,
+	.pdata_size	= sizeof(sdp2430_flash_data),
+	.cs_data	= &sdp2430_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
 /* LCD */
@@ -181,7 +182,11 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 static void __init board_smc91x_init(void)
 {
 	omap_mux_init_gpio(149, OMAP_PIN_INPUT);
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -276,7 +281,9 @@ static void __init omap_2430sdp_init(void)
 
 	omap2430_i2c_init();
 
-	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
+	*gpmc_cur++ = &sdp2430_gpmc_flash_device;
+	gpmc_data.num_device++;
+
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	omap_hsmmc_init(mmc);
@@ -286,6 +293,7 @@ static void __init omap_2430sdp_init(void)
 	usb_musb_init(NULL);
 
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
-- 
1.7.10

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

* [PATCH v4 26/39] ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t3517.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 9e66e16..6aa6b4a 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -234,6 +234,11 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
 	},
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static struct omap_nand_platform_data cm_t3517_nand_data = {
 	.parts			= cm_t3517_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
@@ -242,8 +247,8 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
-		pr_err("CM-T3517: NAND initialization failed\n");
+	*gpmc_device_data = gpmc_nand_init(&cm_t3517_nand_data);
+	gpmc_data.num_device++;
 }
 #else
 static inline void cm_t3517_init_nand(void) {}
@@ -289,6 +294,7 @@ static void __init cm_t3517_init(void)
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
+	omap_init_gpmc(&gpmc_data);
 	cm_t3517_init_rtc();
 	cm_t3517_init_usbh();
 	cm_t3517_init_hecc();
-- 
1.7.10


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

* [PATCH v4 26/39] ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t3517.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 9e66e16..6aa6b4a 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -234,6 +234,11 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
 	},
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static struct omap_nand_platform_data cm_t3517_nand_data = {
 	.parts			= cm_t3517_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
@@ -242,8 +247,8 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
-		pr_err("CM-T3517: NAND initialization failed\n");
+	*gpmc_device_data = gpmc_nand_init(&cm_t3517_nand_data);
+	gpmc_data.num_device++;
 }
 #else
 static inline void cm_t3517_init_nand(void) {}
@@ -289,6 +294,7 @@ static void __init cm_t3517_init(void)
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
+	omap_init_gpmc(&gpmc_data);
 	cm_t3517_init_rtc();
 	cm_t3517_init_usbh();
 	cm_t3517_init_hecc();
-- 
1.7.10

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

* [PATCH v4 26/39] ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t3517.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 9e66e16..6aa6b4a 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -234,6 +234,11 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
 	},
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static struct omap_nand_platform_data cm_t3517_nand_data = {
 	.parts			= cm_t3517_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
@@ -242,8 +247,8 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
-		pr_err("CM-T3517: NAND initialization failed\n");
+	*gpmc_device_data = gpmc_nand_init(&cm_t3517_nand_data);
+	gpmc_data.num_device++;
 }
 #else
 static inline void cm_t3517_init_nand(void) {}
@@ -289,6 +294,7 @@ static void __init cm_t3517_init(void)
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
+	omap_init_gpmc(&gpmc_data);
 	cm_t3517_init_rtc();
 	cm_t3517_init_usbh();
 	cm_t3517_init_hecc();
-- 
1.7.10

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

* [PATCH v4 27/39] ARM: OMAP2+: board cm-t35: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 909a8b9..5b0b637 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -66,6 +66,13 @@
 #include <linux/smsc911x.h>
 #include <plat/gpmc-smsc911x.h>
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = {
 	.id		= 0,
 	.cs             = CM_T35_SMSC911X_CS,
@@ -99,8 +106,17 @@ static void __init cm_t35_init_ethernet(void)
 	regulator_register_fixed(1, sb_t35_smsc911x_supplies,
 				 ARRAY_SIZE(sb_t35_smsc911x_supplies));
 
-	gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
-	gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 1\n");
+
+	*gpmc_cur = gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 2\n");
 }
 #else
 static inline void __init cm_t35_init_ethernet(void) { return; }
@@ -658,6 +674,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
+	omap_init_gpmc(&gpmc_data);
 	cm_t35_init_led();
 	cm_t35_init_display();
 
-- 
1.7.10


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

* [PATCH v4 27/39] ARM: OMAP2+: board cm-t35: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 909a8b9..5b0b637 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -66,6 +66,13 @@
 #include <linux/smsc911x.h>
 #include <plat/gpmc-smsc911x.h>
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = {
 	.id		= 0,
 	.cs             = CM_T35_SMSC911X_CS,
@@ -99,8 +106,17 @@ static void __init cm_t35_init_ethernet(void)
 	regulator_register_fixed(1, sb_t35_smsc911x_supplies,
 				 ARRAY_SIZE(sb_t35_smsc911x_supplies));
 
-	gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
-	gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 1\n");
+
+	*gpmc_cur = gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 2\n");
 }
 #else
 static inline void __init cm_t35_init_ethernet(void) { return; }
@@ -658,6 +674,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
+	omap_init_gpmc(&gpmc_data);
 	cm_t35_init_led();
 	cm_t35_init_display();
 
-- 
1.7.10

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

* [PATCH v4 27/39] ARM: OMAP2+: board cm-t35: gpmc driver adaptation
@ 2012-05-01 12:22   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 909a8b9..5b0b637 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -66,6 +66,13 @@
 #include <linux/smsc911x.h>
 #include <plat/gpmc-smsc911x.h>
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = {
 	.id		= 0,
 	.cs             = CM_T35_SMSC911X_CS,
@@ -99,8 +106,17 @@ static void __init cm_t35_init_ethernet(void)
 	regulator_register_fixed(1, sb_t35_smsc911x_supplies,
 				 ARRAY_SIZE(sb_t35_smsc911x_supplies));
 
-	gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
-	gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 1\n");
+
+	*gpmc_cur = gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 2\n");
 }
 #else
 static inline void __init cm_t35_init_ethernet(void) { return; }
@@ -658,6 +674,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
+	omap_init_gpmc(&gpmc_data);
 	cm_t35_init_led();
 	cm_t35_init_display();
 
-- 
1.7.10

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

* [PATCH v4 28/39] ARM: OMAP2+: board ldp: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-ldp.c |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index b76f28d..1ebc024 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -43,6 +43,7 @@
 #include <asm/delay.h>
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
+#include <plat/nand.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,13 @@
 #define DEBUG_BASE		0x08000000
 #define LDP_ETHR_START		DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
@@ -180,7 +188,9 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init ldp_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
 }
 
 /* LCD */
@@ -418,6 +428,8 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 
 static void __init omap_ldp_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	ldp_init_smsc911x();
@@ -427,8 +439,16 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
-				ZOOM_NAND_CS, 0, nand_default_timings);
+
+	nand_data = board_nand_init(ldp_nand_partitions,
+			ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS,
+			0, nand_default_timings);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
+	omap_init_gpmc(&gpmc_data);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 28/39] ARM: OMAP2+: board ldp: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-ldp.c |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index b76f28d..1ebc024 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -43,6 +43,7 @@
 #include <asm/delay.h>
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
+#include <plat/nand.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,13 @@
 #define DEBUG_BASE		0x08000000
 #define LDP_ETHR_START		DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
@@ -180,7 +188,9 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init ldp_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
 }
 
 /* LCD */
@@ -418,6 +428,8 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 
 static void __init omap_ldp_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	ldp_init_smsc911x();
@@ -427,8 +439,16 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
-				ZOOM_NAND_CS, 0, nand_default_timings);
+
+	nand_data = board_nand_init(ldp_nand_partitions,
+			ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS,
+			0, nand_default_timings);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
+	omap_init_gpmc(&gpmc_data);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
-- 
1.7.10

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

* [PATCH v4 28/39] ARM: OMAP2+: board ldp: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-ldp.c |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index b76f28d..1ebc024 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -43,6 +43,7 @@
 #include <asm/delay.h>
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
+#include <plat/nand.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,13 @@
 #define DEBUG_BASE		0x08000000
 #define LDP_ETHR_START		DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
@@ -180,7 +188,9 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init ldp_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
 }
 
 /* LCD */
@@ -418,6 +428,8 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 
 static void __init omap_ldp_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	ldp_init_smsc911x();
@@ -427,8 +439,16 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
-				ZOOM_NAND_CS, 0, nand_default_timings);
+
+	nand_data = board_nand_init(ldp_nand_partitions,
+			ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS,
+			0, nand_default_timings);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
+	omap_init_gpmc(&gpmc_data);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
-- 
1.7.10

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

* [PATCH v4 29/39] ARM: OMAP2+: board n8x0: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:22     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-n8x0.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 94f6077..d3d866a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -36,6 +36,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/gpmc.h>
 
 #include "mux.h"
 
@@ -45,6 +46,13 @@
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -114,10 +122,12 @@ static void __init n8x0_usb_init(void)
 	}
 	tusb_set_power(0);
 
-	ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
+	*gpmc_cur = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
 					TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS,
 					TUSB6010_GPIO_INT, TUSB6010_DMACHAN);
-	if (ret != 0)
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
 		goto err;
 
 	printk(announce);
@@ -785,7 +795,9 @@ static void __init n8x0_init_machine(void)
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 29/39] ARM: OMAP2+: board n8x0: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-n8x0.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 94f6077..d3d866a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -36,6 +36,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/gpmc.h>
 
 #include "mux.h"
 
@@ -45,6 +46,13 @@
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -114,10 +122,12 @@ static void __init n8x0_usb_init(void)
 	}
 	tusb_set_power(0);
 
-	ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
+	*gpmc_cur = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
 					TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS,
 					TUSB6010_GPIO_INT, TUSB6010_DMACHAN);
-	if (ret != 0)
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
 		goto err;
 
 	printk(announce);
@@ -785,7 +795,9 @@ static void __init n8x0_init_machine(void)
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
-- 
1.7.10

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

* [PATCH v4 29/39] ARM: OMAP2+: board n8x0: gpmc driver adaptation
@ 2012-05-01 12:22     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-n8x0.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 94f6077..d3d866a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -36,6 +36,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/gpmc.h>
 
 #include "mux.h"
 
@@ -45,6 +46,13 @@
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -114,10 +122,12 @@ static void __init n8x0_usb_init(void)
 	}
 	tusb_set_power(0);
 
-	ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
+	*gpmc_cur = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
 					TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS,
 					TUSB6010_GPIO_INT, TUSB6010_DMACHAN);
-	if (ret != 0)
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
 		goto err;
 
 	printk(announce);
@@ -785,7 +795,9 @@ static void __init n8x0_init_machine(void)
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
-- 
1.7.10

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

* [PATCH v4 30/39] ARM: OMAP2+: board omap3logic: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-omap3logic.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 9b3c141..9867fc8 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -55,6 +55,12 @@
 #define OMAP3_TORPEDO_MMC_GPIO_CD		127
 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -180,7 +186,11 @@ static inline void __init board_smsc911x_init(void)
 		return;
 	}
 
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -204,6 +214,7 @@ static void __init omap3logic_init(void)
 	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 30/39] ARM: OMAP2+: board omap3logic: gpmc driver adaptation
@ 2012-05-01 12:23     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3logic.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 9b3c141..9867fc8 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -55,6 +55,12 @@
 #define OMAP3_TORPEDO_MMC_GPIO_CD		127
 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -180,7 +186,11 @@ static inline void __init board_smsc911x_init(void)
 		return;
 	}
 
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -204,6 +214,7 @@ static void __init omap3logic_init(void)
 	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 30/39] ARM: OMAP2+: board omap3logic: gpmc driver adaptation
@ 2012-05-01 12:23     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3logic.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 9b3c141..9867fc8 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -55,6 +55,12 @@
 #define OMAP3_TORPEDO_MMC_GPIO_CD		127
 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -180,7 +186,11 @@ static inline void __init board_smsc911x_init(void)
 		return;
 	}
 
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -204,6 +214,7 @@ static void __init omap3logic_init(void)
 	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 31/39] ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3pandora.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 33d995d..25b2de6 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -57,6 +57,12 @@
 #define PANDORA_WIFI_NRESET_GPIO	23
 #define OMAP3_PANDORA_TS_GPIO		94
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition omap3pandora_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -607,8 +613,9 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
-
+	*gpmc_device_data = gpmc_nand_init(&pandora_nand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-- 
1.7.10


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

* [PATCH v4 31/39] ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3pandora.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 33d995d..25b2de6 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -57,6 +57,12 @@
 #define PANDORA_WIFI_NRESET_GPIO	23
 #define OMAP3_PANDORA_TS_GPIO		94
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition omap3pandora_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -607,8 +613,9 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
-
+	*gpmc_device_data = gpmc_nand_init(&pandora_nand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 31/39] ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3pandora.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 33d995d..25b2de6 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -57,6 +57,12 @@
 #define PANDORA_WIFI_NRESET_GPIO	23
 #define OMAP3_PANDORA_TS_GPIO		94
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition omap3pandora_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -607,8 +613,9 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
-
+	*gpmc_device_data = gpmc_nand_init(&pandora_nand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 32/39] ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3stalker.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 4dffc95..5e92d54 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -56,6 +56,12 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -74,7 +80,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 static inline void __init omap3stalker_init_eth(void)
 {
 	omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -443,6 +453,7 @@ static void __init omap3_stalker_init(void)
 	omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP);
 
 	omap3stalker_init_eth();
+	omap_init_gpmc(&gpmc_data);
 	omap3_stalker_display_init();
 /* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdr_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10


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

* [PATCH v4 32/39] ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3stalker.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 4dffc95..5e92d54 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -56,6 +56,12 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -74,7 +80,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 static inline void __init omap3stalker_init_eth(void)
 {
 	omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -443,6 +453,7 @@ static void __init omap3_stalker_init(void)
 	omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP);
 
 	omap3stalker_init_eth();
+	omap_init_gpmc(&gpmc_data);
 	omap3_stalker_display_init();
 /* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdr_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 32/39] ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap3stalker.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 4dffc95..5e92d54 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -56,6 +56,12 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -74,7 +80,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 static inline void __init omap3stalker_init_eth(void)
 {
 	omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -443,6 +453,7 @@ static void __init omap3_stalker_init(void)
 	omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP);
 
 	omap3stalker_init_eth();
+	omap_init_gpmc(&gpmc_data);
 	omap3_stalker_display_init();
 /* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdr_cke0", OMAP_PIN_OUTPUT);
-- 
1.7.10

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

* [PATCH v4 33/39] ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap4pcm049.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap4pcm049.c b/arch/arm/mach-omap2/board-omap4pcm049.c
index 81de7d5..b4ead86 100644
--- a/arch/arm/mach-omap2/board-omap4pcm049.c
+++ b/arch/arm/mach-omap2/board-omap4pcm049.c
@@ -130,6 +130,12 @@ static struct omap2_hsmmc_info mmc[] = {
 	}, {}	/* Terminator */
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
@@ -147,7 +153,11 @@ static inline void __init pcm049_init_smsc911x(void)
 {
 	omap_mux_init_gpio(OMAP4_PCM049_ETH_GPIO_IRQ, OMAP_PIN_INPUT);
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 #else
 static inline void __init pcm049_init_smsc911x(void) { return; }
@@ -562,6 +572,7 @@ static void __init pcm049_init(void)
 	pm_power_off = pcm049_power_off;
 	omap4_mux_init(board_mux, NULL, OMAP_PACKAGE_CBS);
 	pcm049_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	pcm049_i2c_init();
 	platform_add_devices(pcm049_devices, ARRAY_SIZE(pcm049_devices));
 	board_serial_init();
-- 
1.7.10


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

* [PATCH v4 33/39] ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap4pcm049.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap4pcm049.c b/arch/arm/mach-omap2/board-omap4pcm049.c
index 81de7d5..b4ead86 100644
--- a/arch/arm/mach-omap2/board-omap4pcm049.c
+++ b/arch/arm/mach-omap2/board-omap4pcm049.c
@@ -130,6 +130,12 @@ static struct omap2_hsmmc_info mmc[] = {
 	}, {}	/* Terminator */
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
@@ -147,7 +153,11 @@ static inline void __init pcm049_init_smsc911x(void)
 {
 	omap_mux_init_gpio(OMAP4_PCM049_ETH_GPIO_IRQ, OMAP_PIN_INPUT);
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 #else
 static inline void __init pcm049_init_smsc911x(void) { return; }
@@ -562,6 +572,7 @@ static void __init pcm049_init(void)
 	pm_power_off = pcm049_power_off;
 	omap4_mux_init(board_mux, NULL, OMAP_PACKAGE_CBS);
 	pcm049_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	pcm049_i2c_init();
 	platform_add_devices(pcm049_devices, ARRAY_SIZE(pcm049_devices));
 	board_serial_init();
-- 
1.7.10

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

* [PATCH v4 33/39] ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-omap4pcm049.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-omap4pcm049.c b/arch/arm/mach-omap2/board-omap4pcm049.c
index 81de7d5..b4ead86 100644
--- a/arch/arm/mach-omap2/board-omap4pcm049.c
+++ b/arch/arm/mach-omap2/board-omap4pcm049.c
@@ -130,6 +130,12 @@ static struct omap2_hsmmc_info mmc[] = {
 	}, {}	/* Terminator */
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
@@ -147,7 +153,11 @@ static inline void __init pcm049_init_smsc911x(void)
 {
 	omap_mux_init_gpio(OMAP4_PCM049_ETH_GPIO_IRQ, OMAP_PIN_INPUT);
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 #else
 static inline void __init pcm049_init_smsc911x(void) { return; }
@@ -562,6 +572,7 @@ static void __init pcm049_init(void)
 	pm_power_off = pcm049_power_off;
 	omap4_mux_init(board_mux, NULL, OMAP_PACKAGE_CBS);
 	pcm049_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	pcm049_i2c_init();
 	platform_add_devices(pcm049_devices, ARRAY_SIZE(pcm049_devices));
 	board_serial_init();
-- 
1.7.10

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

* [PATCH v4 34/39] ARM: OMAP2+: board overo: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23     ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
---
 arch/arm/mach-omap2/board-overo.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index e08479a..fa0197e 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -72,6 +72,13 @@
 #define OVERO_SMSC911X2_CS     4
 #define OVERO_SMSC911X2_GPIO   65
 
+static struct gpmc_device_pdata *gpmc_device_data[3];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
@@ -137,8 +144,16 @@ static struct omap_smsc911x_platform_data smsc911x2_cfg = {
 
 static void __init overo_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
-	gpmc_smsc911x_init(&smsc911x2_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x2_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
 }
 
 #else
@@ -509,6 +524,7 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 static void __init overo_init(void)
 {
 	int ret;
+	struct omap_nand_platform_data *nand_data;
 
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -518,12 +534,19 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	board_nand_init(overo_nand_partitions,
+
+	nand_data = board_nand_init(overo_nand_partitions,
 		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
 	overo_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* [PATCH v4 34/39] ARM: OMAP2+: board overo: gpmc driver adaptation
@ 2012-05-01 12:23     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-overo.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index e08479a..fa0197e 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -72,6 +72,13 @@
 #define OVERO_SMSC911X2_CS     4
 #define OVERO_SMSC911X2_GPIO   65
 
+static struct gpmc_device_pdata *gpmc_device_data[3];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
@@ -137,8 +144,16 @@ static struct omap_smsc911x_platform_data smsc911x2_cfg = {
 
 static void __init overo_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
-	gpmc_smsc911x_init(&smsc911x2_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x2_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
 }
 
 #else
@@ -509,6 +524,7 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 static void __init overo_init(void)
 {
 	int ret;
+	struct omap_nand_platform_data *nand_data;
 
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -518,12 +534,19 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	board_nand_init(overo_nand_partitions,
+
+	nand_data = board_nand_init(overo_nand_partitions,
 		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
 	overo_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
-- 
1.7.10

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

* [PATCH v4 34/39] ARM: OMAP2+: board overo: gpmc driver adaptation
@ 2012-05-01 12:23     ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-overo.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index e08479a..fa0197e 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -72,6 +72,13 @@
 #define OVERO_SMSC911X2_CS     4
 #define OVERO_SMSC911X2_GPIO   65
 
+static struct gpmc_device_pdata *gpmc_device_data[3];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
@@ -137,8 +144,16 @@ static struct omap_smsc911x_platform_data smsc911x2_cfg = {
 
 static void __init overo_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
-	gpmc_smsc911x_init(&smsc911x2_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x2_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
 }
 
 #else
@@ -509,6 +524,7 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 static void __init overo_init(void)
 {
 	int ret;
+	struct omap_nand_platform_data *nand_data;
 
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -518,12 +534,19 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	board_nand_init(overo_nand_partitions,
+
+	nand_data = board_nand_init(overo_nand_partitions,
 		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
 	overo_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
-- 
1.7.10

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

* [PATCH v4 35/39] ARM: OMAP2+: board rm680: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rm680.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index ae53d71..e28e606 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -33,6 +33,12 @@
 #include "sdram-nokia.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
@@ -119,7 +125,8 @@ static void __init rm680_peripherals_init(void)
 	platform_add_devices(rm680_peripherals_devices,
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_device_data = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	omap_hsmmc_init(mmc);
 }
 
@@ -141,6 +148,7 @@ static void __init rm680_init(void)
 
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
+	omap_init_gpmc(&gpmc_data);
 }
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-- 
1.7.10


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

* [PATCH v4 35/39] ARM: OMAP2+: board rm680: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rm680.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index ae53d71..e28e606 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -33,6 +33,12 @@
 #include "sdram-nokia.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
@@ -119,7 +125,8 @@ static void __init rm680_peripherals_init(void)
 	platform_add_devices(rm680_peripherals_devices,
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_device_data = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	omap_hsmmc_init(mmc);
 }
 
@@ -141,6 +148,7 @@ static void __init rm680_init(void)
 
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
+	omap_init_gpmc(&gpmc_data);
 }
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-- 
1.7.10

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

* [PATCH v4 35/39] ARM: OMAP2+: board rm680: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rm680.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index ae53d71..e28e606 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -33,6 +33,12 @@
 #include "sdram-nokia.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
@@ -119,7 +125,8 @@ static void __init rm680_peripherals_init(void)
 	platform_add_devices(rm680_peripherals_devices,
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_device_data = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	omap_hsmmc_init(mmc);
 }
 
@@ -141,6 +148,7 @@ static void __init rm680_init(void)
 
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
+	omap_init_gpmc(&gpmc_data);
 }
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-- 
1.7.10

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

* [PATCH v4 36/39] ARM: OMAP2+: board rx51: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ae957c9..af7909e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -73,6 +73,13 @@ enum {
 static struct wl12xx_platform_data wl1251_pdata;
 static struct tsc2005_platform_data tsc2005_pdata;
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
 static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 	.cover_comp_gain = 16,
@@ -1039,7 +1046,11 @@ static void __init board_smc91x_init(void)
 	omap_mux_init_gpio(86, OMAP_PIN_OUTPUT);
 	omap_mux_init_gpio(164, OMAP_PIN_OUTPUT);
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
@@ -1136,8 +1147,10 @@ void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
 	regulator_has_full_constraints();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
 	rx51_init_tsc2005();
-- 
1.7.10


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

* [PATCH v4 36/39] ARM: OMAP2+: board rx51: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ae957c9..af7909e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -73,6 +73,13 @@ enum {
 static struct wl12xx_platform_data wl1251_pdata;
 static struct tsc2005_platform_data tsc2005_pdata;
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
 static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 	.cover_comp_gain = 16,
@@ -1039,7 +1046,11 @@ static void __init board_smc91x_init(void)
 	omap_mux_init_gpio(86, OMAP_PIN_OUTPUT);
 	omap_mux_init_gpio(164, OMAP_PIN_OUTPUT);
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
@@ -1136,8 +1147,10 @@ void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
 	regulator_has_full_constraints();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
 	rx51_init_tsc2005();
-- 
1.7.10

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

* [PATCH v4 36/39] ARM: OMAP2+: board rx51: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ae957c9..af7909e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -73,6 +73,13 @@ enum {
 static struct wl12xx_platform_data wl1251_pdata;
 static struct tsc2005_platform_data tsc2005_pdata;
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
 static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 	.cover_comp_gain = 16,
@@ -1039,7 +1046,11 @@ static void __init board_smc91x_init(void)
 	omap_mux_init_gpio(86, OMAP_PIN_OUTPUT);
 	omap_mux_init_gpio(164, OMAP_PIN_OUTPUT);
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
@@ -1136,8 +1147,10 @@ void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
 	regulator_has_full_constraints();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
 	rx51_init_tsc2005();
-- 
1.7.10

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

* [PATCH v4 37/39] ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-zoom-debugboard.c |   47 +++++++++++++++------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index f64f441..dae7df2 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -31,6 +31,13 @@
 #define DEBUG_BASE		0x08000000
 #define ZOOM_ETHR_START	DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 	.cs             = ZOOM_SMSC911X_CS,
 	.gpio_irq       = ZOOM_SMSC911X_GPIO,
@@ -40,7 +47,11 @@ static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 
 static inline void __init zoom_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: gpmc smsc911x setup\n", __func__);
 }
 
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -56,18 +67,22 @@ static struct plat_serial8250_port serial_platform_data[] = {
 	}
 };
 
-static struct platform_device zoom_debugboard_serial_device = {
+static struct gpmc_cs_data zoom_debugboard_gpmc_cs_serial_data = {
+	.cs		= ZOOM_QUADUART_CS,
+	.mem_size	= SZ_1M,
+};
+
+static struct gpmc_device_pdata zoom_debugboard_gpmc_serial_data = {
 	.name			= "serial8250",
 	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
+	.pdata			= serial_platform_data,
+	.pdata_size		= sizeof(serial_platform_data),
+	.cs_data		= &zoom_debugboard_gpmc_cs_serial_data,
+	.num_cs			= 1,
 };
 
 static inline void __init zoom_init_quaduart(void)
 {
-	int quart_cs;
-	unsigned long cs_mem_base;
 	int quart_gpio = 0;
 
 	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
@@ -78,14 +93,6 @@ static inline void __init zoom_init_quaduart(void)
 		return;
 	}
 
-	quart_cs = ZOOM_QUADUART_CS;
-
-	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem"
-				"for Quad UART(TL16CP754C)\n");
-		return;
-	}
-
 	quart_gpio = ZOOM_QUADUART_GPIO;
 
 	if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0)
@@ -93,6 +100,9 @@ static inline void __init zoom_init_quaduart(void)
 								quart_gpio);
 
 	serial_platform_data[0].irq = gpio_to_irq(102);
+
+	*gpmc_cur++ = &zoom_debugboard_gpmc_serial_data;
+	gpmc_data.num_device++;
 }
 
 static inline int omap_zoom_debugboard_detect(void)
@@ -116,10 +126,6 @@ static inline int omap_zoom_debugboard_detect(void)
 	return ret;
 }
 
-static struct platform_device *zoom_devices[] __initdata = {
-	&zoom_debugboard_serial_device,
-};
-
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
 	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
@@ -133,5 +139,6 @@ int __init zoom_debugboard_init(void)
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	zoom_init_smsc911x();
 	zoom_init_quaduart();
-	return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
+	omap_init_gpmc(&gpmc_data);
+	return 0;
 }
-- 
1.7.10


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

* [PATCH v4 37/39] ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-zoom-debugboard.c |   47 +++++++++++++++------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index f64f441..dae7df2 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -31,6 +31,13 @@
 #define DEBUG_BASE		0x08000000
 #define ZOOM_ETHR_START	DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 	.cs             = ZOOM_SMSC911X_CS,
 	.gpio_irq       = ZOOM_SMSC911X_GPIO,
@@ -40,7 +47,11 @@ static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 
 static inline void __init zoom_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: gpmc smsc911x setup\n", __func__);
 }
 
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -56,18 +67,22 @@ static struct plat_serial8250_port serial_platform_data[] = {
 	}
 };
 
-static struct platform_device zoom_debugboard_serial_device = {
+static struct gpmc_cs_data zoom_debugboard_gpmc_cs_serial_data = {
+	.cs		= ZOOM_QUADUART_CS,
+	.mem_size	= SZ_1M,
+};
+
+static struct gpmc_device_pdata zoom_debugboard_gpmc_serial_data = {
 	.name			= "serial8250",
 	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
+	.pdata			= serial_platform_data,
+	.pdata_size		= sizeof(serial_platform_data),
+	.cs_data		= &zoom_debugboard_gpmc_cs_serial_data,
+	.num_cs			= 1,
 };
 
 static inline void __init zoom_init_quaduart(void)
 {
-	int quart_cs;
-	unsigned long cs_mem_base;
 	int quart_gpio = 0;
 
 	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
@@ -78,14 +93,6 @@ static inline void __init zoom_init_quaduart(void)
 		return;
 	}
 
-	quart_cs = ZOOM_QUADUART_CS;
-
-	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem"
-				"for Quad UART(TL16CP754C)\n");
-		return;
-	}
-
 	quart_gpio = ZOOM_QUADUART_GPIO;
 
 	if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0)
@@ -93,6 +100,9 @@ static inline void __init zoom_init_quaduart(void)
 								quart_gpio);
 
 	serial_platform_data[0].irq = gpio_to_irq(102);
+
+	*gpmc_cur++ = &zoom_debugboard_gpmc_serial_data;
+	gpmc_data.num_device++;
 }
 
 static inline int omap_zoom_debugboard_detect(void)
@@ -116,10 +126,6 @@ static inline int omap_zoom_debugboard_detect(void)
 	return ret;
 }
 
-static struct platform_device *zoom_devices[] __initdata = {
-	&zoom_debugboard_serial_device,
-};
-
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
 	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
@@ -133,5 +139,6 @@ int __init zoom_debugboard_init(void)
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	zoom_init_smsc911x();
 	zoom_init_quaduart();
-	return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
+	omap_init_gpmc(&gpmc_data);
+	return 0;
 }
-- 
1.7.10

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

* [PATCH v4 37/39] ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-zoom-debugboard.c |   47 +++++++++++++++------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index f64f441..dae7df2 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -31,6 +31,13 @@
 #define DEBUG_BASE		0x08000000
 #define ZOOM_ETHR_START	DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 	.cs             = ZOOM_SMSC911X_CS,
 	.gpio_irq       = ZOOM_SMSC911X_GPIO,
@@ -40,7 +47,11 @@ static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 
 static inline void __init zoom_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: gpmc smsc911x setup\n", __func__);
 }
 
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -56,18 +67,22 @@ static struct plat_serial8250_port serial_platform_data[] = {
 	}
 };
 
-static struct platform_device zoom_debugboard_serial_device = {
+static struct gpmc_cs_data zoom_debugboard_gpmc_cs_serial_data = {
+	.cs		= ZOOM_QUADUART_CS,
+	.mem_size	= SZ_1M,
+};
+
+static struct gpmc_device_pdata zoom_debugboard_gpmc_serial_data = {
 	.name			= "serial8250",
 	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
+	.pdata			= serial_platform_data,
+	.pdata_size		= sizeof(serial_platform_data),
+	.cs_data		= &zoom_debugboard_gpmc_cs_serial_data,
+	.num_cs			= 1,
 };
 
 static inline void __init zoom_init_quaduart(void)
 {
-	int quart_cs;
-	unsigned long cs_mem_base;
 	int quart_gpio = 0;
 
 	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
@@ -78,14 +93,6 @@ static inline void __init zoom_init_quaduart(void)
 		return;
 	}
 
-	quart_cs = ZOOM_QUADUART_CS;
-
-	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem"
-				"for Quad UART(TL16CP754C)\n");
-		return;
-	}
-
 	quart_gpio = ZOOM_QUADUART_GPIO;
 
 	if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0)
@@ -93,6 +100,9 @@ static inline void __init zoom_init_quaduart(void)
 								quart_gpio);
 
 	serial_platform_data[0].irq = gpio_to_irq(102);
+
+	*gpmc_cur++ = &zoom_debugboard_gpmc_serial_data;
+	gpmc_data.num_device++;
 }
 
 static inline int omap_zoom_debugboard_detect(void)
@@ -116,10 +126,6 @@ static inline int omap_zoom_debugboard_detect(void)
 	return ret;
 }
 
-static struct platform_device *zoom_devices[] __initdata = {
-	&zoom_debugboard_serial_device,
-};
-
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
 	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
@@ -133,5 +139,6 @@ int __init zoom_debugboard_init(void)
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	zoom_init_smsc911x();
 	zoom_init_quaduart();
-	return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
+	omap_init_gpmc(&gpmc_data);
+	return 0;
 }
-- 
1.7.10

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

* [PATCH v4 38/39] OMAP3: igep0020: Add support for Micron NAND Flash storage memory
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Javier Martinez Canillas, Afzal Mohammed

From: Javier Martinez Canillas <javier@dowhile0.org>

IGEP-based boards can have two different flash memories, a OneNAND or
a NAND device. The boot configuration pins (sys_boot) are used to
specify which memory is available.

Also, this patch removes unnecesary code for registering the OneNAND.

afzal@ti.com: Update to use modified board_nand_init

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: Afzal Mohammed <afzal@ti.com>

fixup: igep
---
 arch/arm/mach-omap2/board-igep0020.c |   75 ++++++++++++++--------------------
 1 file changed, 31 insertions(+), 44 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 930c0d3..6d171ca 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -24,6 +24,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
+#include <linux/mtd/nand.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,6 +41,8 @@
 #include "hsmmc.h"
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
+#include "board-flash.h"
+#include "control.h"
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
@@ -60,6 +64,10 @@
 #define IGEP3_GPIO_LED1_RED	16
 #define IGEP3_GPIO_USBH_NRESET  183
 
+#define IGEP_SYSBOOT_MASK           0x1f
+#define IGEP_SYSBOOT_NAND           0x0f
+#define IGEP_SYSBOOT_ONENAND        0x10
+
 /*
  * IGEP2 Hardware Revision Table
  *
@@ -110,8 +118,10 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+#if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
+	defined(CONFIG_MTD_NAND_OMAP2) ||		\
+	defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 #define ONENAND_MAP             0x20000000
 
@@ -123,7 +133,7 @@ static void __init igep2_get_revision(void)
  * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
  */
 
-static struct mtd_partition igep_onenand_partitions[] = {
+static struct mtd_partition igep_flash_partitions[] = {
 	{
 		.name           = "X-Loader",
 		.offset         = 0,
@@ -151,50 +161,27 @@ static struct mtd_partition igep_onenand_partitions[] = {
 	},
 };
 
-static struct omap_onenand_platform_data igep_onenand_data = {
-	.parts = igep_onenand_partitions,
-	.nr_parts = ARRAY_SIZE(igep_onenand_partitions),
-	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
-};
-
-static struct platform_device igep_onenand_device = {
-	.name		= "omap2-onenand",
-	.id		= -1,
-	.dev = {
-		.platform_data = &igep_onenand_data,
-	},
-};
+static inline u32 igep_get_sysboot_value(void)
+{
+	return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
+}
 
 static void __init igep_flash_init(void)
 {
-	u8 cs = 0;
-	u8 onenandcs = GPMC_CS_NUM + 1;
-
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		u32 ret;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		/* Check if NAND/oneNAND is configured */
-		if ((ret & 0xC00) == 0x800)
-			/* NAND found */
-			pr_err("IGEP: Unsupported NAND found\n");
-		else {
-			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
-				/* ONENAND found */
-				onenandcs = cs;
-		}
-	}
-
-	if (onenandcs > GPMC_CS_NUM) {
-		pr_err("IGEP: Unable to find configuration in GPMC\n");
-		return;
-	}
-
-	igep_onenand_data.cs = onenandcs;
-
-	if (platform_device_register(&igep_onenand_device) < 0)
-		pr_err("IGEP: Unable to register OneNAND device\n");
+	u32 mux;
+	mux = igep_get_sysboot_value();
+
+	if (mux == IGEP_SYSBOOT_NAND) {
+		pr_info("IGEP: initializing NAND memory device\n");
+		board_nand_init(igep_flash_partitions,
+				ARRAY_SIZE(igep_flash_partitions),
+				0, NAND_BUSWIDTH_16, NULL);
+	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		pr_info("IGEP: initializing OneNAND memory device\n");
+		board_onenand_init(igep_flash_partitions,
+				   ARRAY_SIZE(igep_flash_partitions), 0);
+	} else
+		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
 
 #else
-- 
1.7.10


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

* [PATCH v4 38/39] OMAP3: igep0020: Add support for Micron NAND Flash storage memory
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Javier Martinez Canillas, Afzal Mohammed

From: Javier Martinez Canillas <javier@dowhile0.org>

IGEP-based boards can have two different flash memories, a OneNAND or
a NAND device. The boot configuration pins (sys_boot) are used to
specify which memory is available.

Also, this patch removes unnecesary code for registering the OneNAND.

afzal@ti.com: Update to use modified board_nand_init

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: Afzal Mohammed <afzal@ti.com>

fixup: igep
---
 arch/arm/mach-omap2/board-igep0020.c |   75 ++++++++++++++--------------------
 1 file changed, 31 insertions(+), 44 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 930c0d3..6d171ca 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -24,6 +24,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
+#include <linux/mtd/nand.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,6 +41,8 @@
 #include "hsmmc.h"
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
+#include "board-flash.h"
+#include "control.h"
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
@@ -60,6 +64,10 @@
 #define IGEP3_GPIO_LED1_RED	16
 #define IGEP3_GPIO_USBH_NRESET  183
 
+#define IGEP_SYSBOOT_MASK           0x1f
+#define IGEP_SYSBOOT_NAND           0x0f
+#define IGEP_SYSBOOT_ONENAND        0x10
+
 /*
  * IGEP2 Hardware Revision Table
  *
@@ -110,8 +118,10 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+#if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
+	defined(CONFIG_MTD_NAND_OMAP2) ||		\
+	defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 #define ONENAND_MAP             0x20000000
 
@@ -123,7 +133,7 @@ static void __init igep2_get_revision(void)
  * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
  */
 
-static struct mtd_partition igep_onenand_partitions[] = {
+static struct mtd_partition igep_flash_partitions[] = {
 	{
 		.name           = "X-Loader",
 		.offset         = 0,
@@ -151,50 +161,27 @@ static struct mtd_partition igep_onenand_partitions[] = {
 	},
 };
 
-static struct omap_onenand_platform_data igep_onenand_data = {
-	.parts = igep_onenand_partitions,
-	.nr_parts = ARRAY_SIZE(igep_onenand_partitions),
-	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
-};
-
-static struct platform_device igep_onenand_device = {
-	.name		= "omap2-onenand",
-	.id		= -1,
-	.dev = {
-		.platform_data = &igep_onenand_data,
-	},
-};
+static inline u32 igep_get_sysboot_value(void)
+{
+	return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
+}
 
 static void __init igep_flash_init(void)
 {
-	u8 cs = 0;
-	u8 onenandcs = GPMC_CS_NUM + 1;
-
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		u32 ret;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		/* Check if NAND/oneNAND is configured */
-		if ((ret & 0xC00) == 0x800)
-			/* NAND found */
-			pr_err("IGEP: Unsupported NAND found\n");
-		else {
-			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
-				/* ONENAND found */
-				onenandcs = cs;
-		}
-	}
-
-	if (onenandcs > GPMC_CS_NUM) {
-		pr_err("IGEP: Unable to find configuration in GPMC\n");
-		return;
-	}
-
-	igep_onenand_data.cs = onenandcs;
-
-	if (platform_device_register(&igep_onenand_device) < 0)
-		pr_err("IGEP: Unable to register OneNAND device\n");
+	u32 mux;
+	mux = igep_get_sysboot_value();
+
+	if (mux == IGEP_SYSBOOT_NAND) {
+		pr_info("IGEP: initializing NAND memory device\n");
+		board_nand_init(igep_flash_partitions,
+				ARRAY_SIZE(igep_flash_partitions),
+				0, NAND_BUSWIDTH_16, NULL);
+	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		pr_info("IGEP: initializing OneNAND memory device\n");
+		board_onenand_init(igep_flash_partitions,
+				   ARRAY_SIZE(igep_flash_partitions), 0);
+	} else
+		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
 
 #else
-- 
1.7.10

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

* [PATCH v4 38/39] OMAP3: igep0020: Add support for Micron NAND Flash storage memory
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

From: Javier Martinez Canillas <javier@dowhile0.org>

IGEP-based boards can have two different flash memories, a OneNAND or
a NAND device. The boot configuration pins (sys_boot) are used to
specify which memory is available.

Also, this patch removes unnecesary code for registering the OneNAND.

afzal at ti.com: Update to use modified board_nand_init

Signed-off-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: Afzal Mohammed <afzal@ti.com>

fixup: igep
---
 arch/arm/mach-omap2/board-igep0020.c |   75 ++++++++++++++--------------------
 1 file changed, 31 insertions(+), 44 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 930c0d3..6d171ca 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -24,6 +24,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
+#include <linux/mtd/nand.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,6 +41,8 @@
 #include "hsmmc.h"
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
+#include "board-flash.h"
+#include "control.h"
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
@@ -60,6 +64,10 @@
 #define IGEP3_GPIO_LED1_RED	16
 #define IGEP3_GPIO_USBH_NRESET  183
 
+#define IGEP_SYSBOOT_MASK           0x1f
+#define IGEP_SYSBOOT_NAND           0x0f
+#define IGEP_SYSBOOT_ONENAND        0x10
+
 /*
  * IGEP2 Hardware Revision Table
  *
@@ -110,8 +118,10 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+#if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
+	defined(CONFIG_MTD_NAND_OMAP2) ||		\
+	defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 #define ONENAND_MAP             0x20000000
 
@@ -123,7 +133,7 @@ static void __init igep2_get_revision(void)
  * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
  */
 
-static struct mtd_partition igep_onenand_partitions[] = {
+static struct mtd_partition igep_flash_partitions[] = {
 	{
 		.name           = "X-Loader",
 		.offset         = 0,
@@ -151,50 +161,27 @@ static struct mtd_partition igep_onenand_partitions[] = {
 	},
 };
 
-static struct omap_onenand_platform_data igep_onenand_data = {
-	.parts = igep_onenand_partitions,
-	.nr_parts = ARRAY_SIZE(igep_onenand_partitions),
-	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
-};
-
-static struct platform_device igep_onenand_device = {
-	.name		= "omap2-onenand",
-	.id		= -1,
-	.dev = {
-		.platform_data = &igep_onenand_data,
-	},
-};
+static inline u32 igep_get_sysboot_value(void)
+{
+	return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
+}
 
 static void __init igep_flash_init(void)
 {
-	u8 cs = 0;
-	u8 onenandcs = GPMC_CS_NUM + 1;
-
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		u32 ret;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		/* Check if NAND/oneNAND is configured */
-		if ((ret & 0xC00) == 0x800)
-			/* NAND found */
-			pr_err("IGEP: Unsupported NAND found\n");
-		else {
-			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
-				/* ONENAND found */
-				onenandcs = cs;
-		}
-	}
-
-	if (onenandcs > GPMC_CS_NUM) {
-		pr_err("IGEP: Unable to find configuration in GPMC\n");
-		return;
-	}
-
-	igep_onenand_data.cs = onenandcs;
-
-	if (platform_device_register(&igep_onenand_device) < 0)
-		pr_err("IGEP: Unable to register OneNAND device\n");
+	u32 mux;
+	mux = igep_get_sysboot_value();
+
+	if (mux == IGEP_SYSBOOT_NAND) {
+		pr_info("IGEP: initializing NAND memory device\n");
+		board_nand_init(igep_flash_partitions,
+				ARRAY_SIZE(igep_flash_partitions),
+				0, NAND_BUSWIDTH_16, NULL);
+	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		pr_info("IGEP: initializing OneNAND memory device\n");
+		board_onenand_init(igep_flash_partitions,
+				   ARRAY_SIZE(igep_flash_partitions), 0);
+	} else
+		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
 
 #else
-- 
1.7.10

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

* [PATCH v4 39/39] ARM: OMAP2+: board igep0020: gpmc driver adaptation
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-01 12:23   ` Afzal Mohammed
  -1 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-igep0020.c |   32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 6d171ca..91de8ce 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -36,6 +36,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
+#include <plat/nand.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -118,6 +119,13 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
 	defined(CONFIG_MTD_NAND_OMAP2) ||		\
@@ -172,14 +180,26 @@ static void __init igep_flash_init(void)
 	mux = igep_get_sysboot_value();
 
 	if (mux == IGEP_SYSBOOT_NAND) {
+		struct omap_nand_platform_data *nand_data;
+
 		pr_info("IGEP: initializing NAND memory device\n");
-		board_nand_init(igep_flash_partitions,
+		nand_data = board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, NULL);
+				0, NAND_BUSWIDTH_16, nand_default_timings);
+		if (nand_data != NULL) {
+			*gpmc_cur++ = gpmc_nand_init(nand_data);
+			gpmc_data.num_device++;
+		}
 	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		struct omap_onenand_platform_data *onenand_data;
+
 		pr_info("IGEP: initializing OneNAND memory device\n");
-		board_onenand_init(igep_flash_partitions,
+		onenand_data = board_onenand_init(igep_flash_partitions,
 				   ARRAY_SIZE(igep_flash_partitions), 0);
+		if (onenand_data != NULL) {
+			*gpmc_cur++ = gpmc_onenand_init(onenand_data);
+			gpmc_data.num_device++;
+		}
 	} else
 		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
@@ -202,7 +222,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init igep2_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
-- 
1.7.10


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

* [PATCH v4 39/39] ARM: OMAP2+: board igep0020: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd
  Cc: Afzal Mohammed

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-igep0020.c |   32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 6d171ca..91de8ce 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -36,6 +36,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
+#include <plat/nand.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -118,6 +119,13 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
 	defined(CONFIG_MTD_NAND_OMAP2) ||		\
@@ -172,14 +180,26 @@ static void __init igep_flash_init(void)
 	mux = igep_get_sysboot_value();
 
 	if (mux == IGEP_SYSBOOT_NAND) {
+		struct omap_nand_platform_data *nand_data;
+
 		pr_info("IGEP: initializing NAND memory device\n");
-		board_nand_init(igep_flash_partitions,
+		nand_data = board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, NULL);
+				0, NAND_BUSWIDTH_16, nand_default_timings);
+		if (nand_data != NULL) {
+			*gpmc_cur++ = gpmc_nand_init(nand_data);
+			gpmc_data.num_device++;
+		}
 	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		struct omap_onenand_platform_data *onenand_data;
+
 		pr_info("IGEP: initializing OneNAND memory device\n");
-		board_onenand_init(igep_flash_partitions,
+		onenand_data = board_onenand_init(igep_flash_partitions,
 				   ARRAY_SIZE(igep_flash_partitions), 0);
+		if (onenand_data != NULL) {
+			*gpmc_cur++ = gpmc_onenand_init(onenand_data);
+			gpmc_data.num_device++;
+		}
 	} else
 		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
@@ -202,7 +222,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init igep2_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
-- 
1.7.10

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

* [PATCH v4 39/39] ARM: OMAP2+: board igep0020: gpmc driver adaptation
@ 2012-05-01 12:23   ` Afzal Mohammed
  0 siblings, 0 replies; 205+ messages in thread
From: Afzal Mohammed @ 2012-05-01 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc code has been converted to driver. Modify the board
code to provide gpmc driver with required information.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-igep0020.c |   32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 6d171ca..91de8ce 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -36,6 +36,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
+#include <plat/nand.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -118,6 +119,13 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
 	defined(CONFIG_MTD_NAND_OMAP2) ||		\
@@ -172,14 +180,26 @@ static void __init igep_flash_init(void)
 	mux = igep_get_sysboot_value();
 
 	if (mux == IGEP_SYSBOOT_NAND) {
+		struct omap_nand_platform_data *nand_data;
+
 		pr_info("IGEP: initializing NAND memory device\n");
-		board_nand_init(igep_flash_partitions,
+		nand_data = board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, NULL);
+				0, NAND_BUSWIDTH_16, nand_default_timings);
+		if (nand_data != NULL) {
+			*gpmc_cur++ = gpmc_nand_init(nand_data);
+			gpmc_data.num_device++;
+		}
 	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		struct omap_onenand_platform_data *onenand_data;
+
 		pr_info("IGEP: initializing OneNAND memory device\n");
-		board_onenand_init(igep_flash_partitions,
+		onenand_data = board_onenand_init(igep_flash_partitions,
 				   ARRAY_SIZE(igep_flash_partitions), 0);
+		if (onenand_data != NULL) {
+			*gpmc_cur++ = gpmc_onenand_init(onenand_data);
+			gpmc_data.num_device++;
+		}
 	} else
 		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
@@ -202,7 +222,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init igep2_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
-- 
1.7.10

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

* Re: [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
  2012-05-01 12:20   ` Afzal Mohammed
  (?)
@ 2012-05-01 16:49     ` Sergei Shtylyov
  -1 siblings, 0 replies; 205+ messages in thread
From: Sergei Shtylyov @ 2012-05-01 16:49 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd

Hello.

On 01-05-2012 16:20, Afzal Mohammed wrote:

> Modify board_onenand_init to return platform data. This
> would be required for boards to be able to pass it to
> gpmc driver so that it finally reaches onenand driver.

> Also un-static the function so that boards can use it.

> Signed-off-by: Afzal Mohammed<afzal@ti.com>
[...]

> diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
> index 052964c..75ba49f 100644
> --- a/arch/arm/mach-omap2/board-flash.h
> +++ b/arch/arm/mach-omap2/board-flash.h
> @@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
>   	return NULL;
>   }
>   #endif
> +
> +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)

    You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

> +extern struct omap_onenand_platform_data * __init
> +board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
> +#else
> +static inline struct omap_onenand_platform_data *
> +__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
> +{
> +	return NULL;
> +}
> +#endif

WBR, Sergei

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

* Re: [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-01 16:49     ` Sergei Shtylyov
  0 siblings, 0 replies; 205+ messages in thread
From: Sergei Shtylyov @ 2012-05-01 16:49 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, vimal.newwork, grinberg, artem.bityutskiy,
	linux-mtd, linux-omap, dwmw2, linux-arm-kernel, notasas

Hello.

On 01-05-2012 16:20, Afzal Mohammed wrote:

> Modify board_onenand_init to return platform data. This
> would be required for boards to be able to pass it to
> gpmc driver so that it finally reaches onenand driver.

> Also un-static the function so that boards can use it.

> Signed-off-by: Afzal Mohammed<afzal@ti.com>
[...]

> diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
> index 052964c..75ba49f 100644
> --- a/arch/arm/mach-omap2/board-flash.h
> +++ b/arch/arm/mach-omap2/board-flash.h
> @@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
>   	return NULL;
>   }
>   #endif
> +
> +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)

    You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

> +extern struct omap_onenand_platform_data * __init
> +board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
> +#else
> +static inline struct omap_onenand_platform_data *
> +__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
> +{
> +	return NULL;
> +}
> +#endif

WBR, Sergei

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

* [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-01 16:49     ` Sergei Shtylyov
  0 siblings, 0 replies; 205+ messages in thread
From: Sergei Shtylyov @ 2012-05-01 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-05-2012 16:20, Afzal Mohammed wrote:

> Modify board_onenand_init to return platform data. This
> would be required for boards to be able to pass it to
> gpmc driver so that it finally reaches onenand driver.

> Also un-static the function so that boards can use it.

> Signed-off-by: Afzal Mohammed<afzal@ti.com>
[...]

> diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
> index 052964c..75ba49f 100644
> --- a/arch/arm/mach-omap2/board-flash.h
> +++ b/arch/arm/mach-omap2/board-flash.h
> @@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
>   	return NULL;
>   }
>   #endif
> +
> +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)

    You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

> +extern struct omap_onenand_platform_data * __init
> +board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
> +#else
> +static inline struct omap_onenand_platform_data *
> +__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
> +{
> +	return NULL;
> +}
> +#endif

WBR, Sergei

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-01 12:19     ` Afzal Mohammed
  (?)
@ 2012-05-01 17:53         ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 17:53 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Vaibhav Hiremath

Hi Afzal,

Looks good! Some minor comments ...

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Convert GPMC code to driver. Boards using GPMC should provide driver
> with type of configuration, timing, CS. Platform devices would then be
> created for each connected peripheral (details also to be passed by
> board so that it reaches respective driver). And GPMC driver would
> populate memory resource details for the connected peripheral driver.
> Boards should inform gpmc driver with platform data destined for
> peripheral driver. gpmc driver will provide the same information to
> peripheral driver.
> 
> A peripheral connected to GPMC can have multiple address spaces using
> different chip select. Hence GPMC driver has been provided capability
> to create platform device for peripheral using mutiple CS. The
> peripheral that made it necessary was tusb6010.
> 
> Interrupts of GPMC are presented to drivers of connected peripherals
> as resource. A fictitious interrupt controller chip handles these
> interrupts at GPMC hardware level. Clients can use normal interrupt
> APIs. Platform information of peripheral passed to GPMC driver should
> indicate interrupts to be used via flags.
> 
> Driver is capable of configuring waitpin, waitpin details has to be
> provided per CS. Wait pin has been considered as exclusive resource
> as multiple peripherals should not using the same pin, at the same
> it is valid for mutiple CS to use same waitpin provided they are
> a part of single peripheral (eg. tusb6010)
> 
> An exported symbol for reconfiguring GPMC settings has been provided.
> OneNAND is the one that neccessitated this.
> 
> Acquiring CS# for NAND is done on a few boards. It means, depending
> on bootloader to embed this information. Probably CS# being used can
> be set in the Kernel, and acquiring it can be removed. If ever this
> capbility is needed, GPMC driver has to be made aware of handling it.
> 
> Modifications has been made keeping in mind that the driver would
> have to move to driver folder. This explains requirement of clk_prd
> field; even though clk_prd variable is not necessary as
> gpmc_get_fclk_period is present in the same file as of now, this will
> help in moving the driver easily to drivers folder.
> 
> Code related to GPMC clock may have to continue live in platform
> folders as input clock is beyond the control of GPMC and calculating
> timing for the peripheral may need other helpers. This explains
> presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
> both doing same work, latter meant to go with driver, former for
> calculation in platform code.
> 
> Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
> suggestions which resulted in improving the code.
> 
> Cc: Vaibhav Hiremath <hvaibhav-l0cyMroinI0@public.gmane.org>
> Cc: Jon Hunter <jon-hunter-l0cyMroinI0@public.gmane.org>
> Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>
> ---
>  arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
>  arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
>  2 files changed, 872 insertions(+), 98 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 580e684..12916f3 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -14,8 +14,11 @@
>   */
>  #undef DEBUG
>  
> +#include <linux/platform_device.h>
> +
>  #include <linux/irq.h>
>  #include <linux/kernel.h>
> +#include <linux/slab.h>
>  #include <linux/init.h>
>  #include <linux/err.h>
>  #include <linux/clk.h>
> @@ -53,6 +56,45 @@
>  #define GPMC_CS0_OFFSET		0x60
>  #define GPMC_CS_SIZE		0x30
>  
> +/* GPMC register bits */
> +#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
> +#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
> +#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
> +#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
> +#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
> +#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
> +#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
> +
> +#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
> +#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
> +
> +#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
> +#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
> +
> +#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
> +#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
> +
> +#define	GPMC_WAITPIN_IDX0			0x0
> +#define	GPMC_WAITPIN_IDX1			0x1
> +#define	GPMC_WAITPIN_IDX2			0x2
> +#define	GPMC_WAITPIN_IDX3			0x3
> +#define	GPMC_NR_WAITPIN				0x4

How about an enum here? Also OMAP4 only have 3 wait pins and so the
number is device dependent.

>  #define GPMC_MEM_START		0x00000000
>  #define GPMC_MEM_END		0x3FFFFFFF
>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> @@ -64,6 +106,55 @@
>  #define ENABLE_PREFETCH		(0x1 << 7)
>  #define DMA_MPU_MODE		2
>  
> +#define	DRIVER_NAME	"omap-gpmc"
> +
> +#define	GPMC_NR_IRQ		2

Why has this been changed to 2? It was 6 in the previous version. As we
discussed before the number of IRQs should be detected based upon GPMC
IP version.

> +
> +#define	HIGH			1
> +#define	LOW			-1
> +
> +struct gpmc_device {
> +	char			*name;
> +	int			id;
> +	void			*pdata;
> +	unsigned		pdata_size;
> +	struct resource		*per_res;
> +	unsigned		per_res_cnt;
> +	struct resource		*gpmc_res;
> +	unsigned		gpmc_res_cnt;
> +	bool			have_waitpin;
> +	unsigned		waitpin;
> +	int			waitpin_polarity;

I think that it make more sense to have the wait-pin information part of
the gpmc_cs_data structure for the following reasons ...

1. If a device can use multiple CS, then it could use multiple wait signals.
2. Eventually, all board information needs to move to device tree. By
having it in the pdata it will be easier to migrate to device tree.

It may be nice to have "have_waitpin" be an integer too, that indicates
if wait is used for both read and write or just one or the other.

Also, any reason why waitpin_polarity is an int? I see you define LOW as
-1, but I not sure why LOW cannot be 0 as 0 is programmed into the
register for an active low wait signal.

> +};
> +
> +struct gpmc_irq	{
> +	unsigned		irq;
> +	u32			bitmask;
> +};
> +
> +struct gpmc {
> +	struct device		*dev;
> +	unsigned long		clk_prd;
> +	void __iomem		*io_base;
> +	unsigned long		phys_base;
> +	u32			memsize;
> +	unsigned		cs_map;
> +	int			ecc_used;
> +	spinlock_t		mem_lock;
> +	struct resource		mem_root;
> +	struct resource		cs_mem[GPMC_CS_NUM];
> +	/* XXX: Or allocate dynamically ? */
> +	struct gpmc_device	device[GPMC_CS_NUM];
> +	unsigned		num_device;
> +	unsigned		master_irq;
> +	unsigned		irq_start;
> +	struct gpmc_irq		irq[GPMC_NR_IRQ];
> +	struct irq_chip		irq_chip;
> +	bool			wp;
> +	unsigned		waitpin_map;
> +	unsigned		revision;
> +};
> +
>  /* Structure to save gpmc cs context */
>  struct gpmc_cs_config {
>  	u32 config1;
> @@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
>  	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
>  };
>  
> -static struct resource	gpmc_mem_root;
> -static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
> -static DEFINE_SPINLOCK(gpmc_mem_lock);
> -static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
> -static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
> -
> -static void __iomem *gpmc_base;
> -
>  static struct clk *gpmc_l3_clk;
>  
> -static irqreturn_t gpmc_handle_irq(int irq, void *dev);
> +static struct gpmc *gpmc;
>  
>  static void gpmc_write_reg(int idx, u32 val)
>  {
> -	__raw_writel(val, gpmc_base + idx);
> +	writel(val, gpmc->io_base + idx);
>  }
>  
>  static u32 gpmc_read_reg(int idx)
>  {
> -	return __raw_readl(gpmc_base + idx);
> +	return readl(gpmc->io_base + idx);
>  }
>  
>  static void gpmc_cs_write_byte(int cs, int idx, u8 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writeb(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writeb(val, reg_addr);
>  }
>  
>  static u8 gpmc_cs_read_byte(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readb(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readb(reg_addr);
>  }
>  
>  void gpmc_cs_write_reg(int cs, int idx, u32 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writel(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writel(val, reg_addr);
>  }
>  
>  u32 gpmc_cs_read_reg(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readl(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readl(reg_addr);
>  }
>  
>  /* TODO: Add support for gpmc_fck to clock framework and use it */
> @@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  	if (time == 0)
>  		ticks = 0;
>  	else
> -		ticks = gpmc_ns_to_ticks(time);
> +		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
> +
>  	nr_bits = end_bit - st_bit + 1;
>  	if (ticks >= 1 << nr_bits) {
>  #ifdef DEBUG
> @@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  #ifdef DEBUG
>  	printk(KERN_INFO
>  		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
> -	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
> +	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
>  			(l >> st_bit) & mask, time);
>  #endif
>  	l &= ~(mask << st_bit);
> @@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  		return -1
>  #endif
>  
> +int gpmc_calc_divider(unsigned int sync_clk)
> +{
> +	int div;
> +	u32 l;
> +
> +	l = sync_clk + (gpmc->clk_prd - 1);
> +	div = l / gpmc->clk_prd;
> +	if (div > 4)
> +		return -1;
> +	if (div <= 0)
> +		div = 1;
> +
> +	return div;
> +}
> +
>  int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  {
>  	int div;
> @@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  	return div;
>  }
>  
> +static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
> +{
> +	u32 l;
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
> +	if (p->cs_extra_delay)
> +		l |= GPMC_CONFIG2_CSEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
> +	if (p->adv_extra_delay)
> +		l |= GPMC_CONFIG3_ADVEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
> +	if (p->oe_extra_delay)
> +		l |= GPMC_CONFIG4_OEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
> +	if (p->we_extra_delay)
> +		l |= GPMC_CONFIG4_WEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
> +	if (p->cycle2cyclesamecsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	if (p->cycle2cyclediffcsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
> +}
> +
>  int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  {
>  	int div;
>  	u32 l;
>  
> -	div = gpmc_cs_calc_divider(cs, t->sync_clk);
> +	div = gpmc_calc_divider(t->sync_clk);
>  	if (div < 0)
>  		return -1;
>  
> @@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  
>  	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
>  
> -	if (cpu_is_omap34xx()) {
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
> +
> +	if (gpmc->revision >= 5) {
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
>  	}
> @@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
>  #ifdef DEBUG
>  		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
> -				cs, (div * gpmc_get_fclk_period()) / 1000, div);
> +				cs, (div * gpmc->clk_prd) / 1000, div);
>  #endif
>  		l &= ~0x03;
>  		l |= (div - 1);
>  		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>  	}
>  
> +	gpmc_cs_onoff_timings(cs, &t->control);
> +
>  	return 0;
>  }
>  
> @@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
>  	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
>  }
>  
> -static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
> +static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
>  {
>  	u32 l;
>  	u32 mask;
> @@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
>  	return l & GPMC_CONFIG7_CSVALID;
>  }
>  
> -int gpmc_cs_set_reserved(int cs, int reserved)
> +static int gpmc_cs_set_reserved(int cs, int reserved)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	gpmc_cs_map &= ~(1 << cs);
> -	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
> +	gpmc->cs_map &= ~(1 << cs);
> +	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
>  
>  	return 0;
>  }
>  
> -int gpmc_cs_reserved(int cs)
> +static int gpmc_cs_reserved(int cs)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	return gpmc_cs_map & (1 << cs);
> +	return gpmc->cs_map & (1 << cs);
>  }
>  
>  static unsigned long gpmc_mem_align(unsigned long size)
> @@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
>  	return size;
>  }
>  
> -static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
> +static __devinit
> +int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
>  {
> -	struct resource	*res = &gpmc_cs_mem[cs];
> +	struct resource	*res = &gpmc->cs_mem[cs];
>  	int r;
>  
>  	size = gpmc_mem_align(size);
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	res->start = base;
>  	res->end = base + size - 1;
> -	r = request_resource(&gpmc_mem_root, res);
> -	spin_unlock(&gpmc_mem_lock);
> +	r = request_resource(&gpmc->mem_root, res);
> +	spin_unlock(&gpmc->mem_lock);
>  
>  	return r;
>  }
>  
>  int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  {
> -	struct resource *res = &gpmc_cs_mem[cs];
> +	struct resource *res = &gpmc->cs_mem[cs];
>  	int r = -1;
>  
>  	if (cs > GPMC_CS_NUM)
> @@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (size > (1 << GPMC_SECTION_SHIFT))
>  		return -ENOMEM;
>  
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (gpmc_cs_reserved(cs)) {
>  		r = -EBUSY;
>  		goto out;
> @@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (gpmc_cs_mem_enabled(cs))
>  		r = adjust_resource(res, res->start & ~(size - 1), size);
>  	if (r < 0)
> -		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
> +		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
>  				      size, NULL, NULL);
>  	if (r < 0)
>  		goto out;
> @@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	*base = res->start;
>  	gpmc_cs_set_reserved(cs, 1);
>  out:
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  	return r;
>  }
>  EXPORT_SYMBOL(gpmc_cs_request);
>  
>  void gpmc_cs_free(int cs)
>  {
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
>  		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
>  		BUG();
> -		spin_unlock(&gpmc_mem_lock);
> +		spin_unlock(&gpmc->mem_lock);
>  		return;
>  	}
>  	gpmc_cs_disable_mem(cs);
> -	release_resource(&gpmc_cs_mem[cs]);
> +	release_resource(&gpmc->cs_mem[cs]);
>  	gpmc_cs_set_reserved(cs, 0);
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  }
>  EXPORT_SYMBOL(gpmc_cs_free);
>  
> @@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
>  }
>  EXPORT_SYMBOL(gpmc_prefetch_reset);
>  
> -static void __init gpmc_mem_init(void)
> +static __devinit void gpmc_mem_init(void)
>  {
>  	int cs;
>  	unsigned long boot_rom_space = 0;
> @@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
>  	/* In apollon the CS0 is mapped as 0x0000 0000 */
>  	if (machine_is_omap_apollon())
>  		boot_rom_space = 0;
> -	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
> -	gpmc_mem_root.end = GPMC_MEM_END;
> +	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
> +	gpmc->mem_root.end = GPMC_MEM_END;
>  
>  	/* Reserve all regions that has been set up by bootloader */
>  	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> @@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	u32 l, irq;
> -	int cs, ret = -EINVAL;
> -	int gpmc_irq;
> +	int ret = -EINVAL;
>  	char *ck = NULL;
>  
>  	if (cpu_is_omap24xx()) {
>  		ck = "core_l3_ck";
> -		if (cpu_is_omap2420())
> -			l = OMAP2420_GPMC_BASE;
> -		else
> -			l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap34xx()) {
>  		ck = "gpmc_fck";
> -		l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap44xx()) {
>  		ck = "gpmc_ck";
> -		l = OMAP44XX_GPMC_BASE;
> -		gpmc_irq = OMAP44XX_IRQ_GPMC;
>  	}
>  
>  	if (WARN_ON(!ck))
> @@ -728,53 +863,607 @@ static int __init gpmc_init(void)
>  		BUG();
>  	}
>  
> -	gpmc_base = ioremap(l, SZ_4K);
> -	if (!gpmc_base) {
> -		clk_put(gpmc_l3_clk);
> -		printk(KERN_ERR "Could not get GPMC register memory\n");
> -		BUG();
> +	clk_enable(gpmc_l3_clk);
> +
> +	return 0;
> +}
> +postcore_initcall(gpmc_init);
> +
> +static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	return gpmc->waitpin_map & (0x1 << waitpin);
> +}
> +
> +static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	gpmc->waitpin_map &= ~(0x1 << waitpin);
> +	gpmc->waitpin_map |= (0x1 << waitpin);
> +}
> +
> +static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	if (!(waitpin < GPMC_NR_WAITPIN))
> +		return -ENODEV;
> +
> +	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
> +		return -EBUSY;
> +	else
> +		gpmc_reserve_waitpin(gpmc, waitpin);
> +
> +	return 0;
> +}
> +
> +static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
> +{
> +	int ret;
> +
> +	if (!gd->have_waitpin)
> +		return 0;
> +
> +	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
> +		return ret;
> +	} else if (gd->waitpin_polarity) {
> +		u32 l = gpmc_read_reg(GPMC_CONFIG);
> +		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
> +
> +		if (gd->waitpin_polarity == HIGH)
> +			l |= 1 << shift;
> +		else
> +			l &= ~(1 << shift);
> +
> +		gpmc_write_reg(GPMC_CONFIG, l);
>  	}
> +	return 0;
> +}
>  
> -	clk_enable(gpmc_l3_clk);
> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}
>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}
>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {
> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {
> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}

I am not sure about the above code. What happens if a device has
multiple CS signals and uses multiple wait signals?

I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
cannot be combined. I think that it would be a fair assumption to make
that anyone using the waitpin does so inconjunction with the CS (I think
that they would have too).

However, if there is a reason for splitting it up this way please
explain why.

> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
> +		GPMC_CONFIG1_MUXADDDATA |
> +		GPMC_CONFIG1_DEVICETYPE(~0) |
> +		GPMC_CONFIG1_DEVICESIZE(~0) |
> +		GPMC_CONFIG1_WAIT_WRITE_MON |
> +		GPMC_CONFIG1_WAIT_READ_MON |
> +		GPMC_CONFIG1_PAGE_LEN(~0) |
> +		GPMC_CONFIG1_WRITETYPE_SYNC |
> +		GPMC_CONFIG1_WRITEMULTIPLE |
> +		GPMC_CONFIG1_READTYPE_SYNC |
> +		GPMC_CONFIG1_READMULTIPLE |
> +		GPMC_CONFIG1_WRAPBURST |
> +		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
> +		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
> +
> +	if (conf & GPMC_TIMEPARAGRANULARITY)
> +		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
> +	if (conf & GPMC_MUXADDDATA)
> +		l |= GPMC_CONFIG1_MUXADDDATA;
> +	if (conf & GPMC_DEVICETYPE_NAND)
> +		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
> +	if (conf & GPMC_DEVICESIZE_16)
> +		l |= GPMC_CONFIG1_DEVICESIZE_16;
> +	if (conf & GPMC_WAIT_WRITE_MON)
> +		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
> +	if (conf & GPMC_WAIT_READ_MON)
> +		l |= GPMC_CONFIG1_WAIT_READ_MON;
> +	if (conf & GPMC_PAGE_LEN_16)
> +		l |= GPMC_CONFIG1_PAGE_LEN_16;
> +	else if (conf & GPMC_PAGE_LEN_8)
> +		l |= GPMC_CONFIG1_PAGE_LEN_8;
> +	if (conf & GPMC_WRITETYPE_SYNC)
> +		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
> +	if (conf & GPMC_WRITEMULTIPLE)
> +		l |= GPMC_CONFIG1_WRITEMULTIPLE;
> +	if (conf & GPMC_READTYPE_SYNC)
> +		l |= GPMC_CONFIG1_READTYPE_SYNC;
> +	if (conf & GPMC_READMULTIPLE)
> +		l |= GPMC_CONFIG1_READMULTIPLE;
> +	if (conf & GPMC_WRAPBURST)
> +		l |= GPMC_CONFIG1_WRAPBURST;
> +	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
> +	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
> +	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
> +	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
> +
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +
> +	if (conf & GPMC_WRITEPROTECT)
> +		gpmc->wp = true;
> +}
> +
> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)

The name of this function is not 100% clear to me. What do you mean by
"nonres"?

> +{
> +	int ret;
> +
> +	/* some boards rely on bootloader for configuration */
> +	if (cs->have_config) {
> +		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
> +		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
> +
> +	if (cs->timing) {
> +		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
> +
> +	return 0;
> +}
> +
> +static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
> +{
> +	int i;
> +	struct gpmc_device *gd;
> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (!strcmp(gd->name, name) && gd->id == id)
> +			return i;
> +
> +	return -ENOENT;
> +}
> +
> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)

What scenario is this function used in? May be worth adding a comment
about the function.

> +{
> +	int i;
> +
> +	i = gpmc_match_device(gpmc, name, id);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
> +		return i;
> +	}
> +
> +	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
> +		return i;
> +	}
> +
> +	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
> +
> +}
> +EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
> +
> +static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
> +{
> +	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
> +		return GPMC_IRQ_FIFOEVENTENABLE;
> +	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
> +		return GPMC_IRQ_COUNT_EVENT;
> +	else
> +		return 0;
> +}
> +
> +static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int i, n;
> +
> +	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
> +		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
> +			res[n].start = res[n].end = gpmc->irq[i].irq;
> +			res[n].flags = IORESOURCE_IRQ;
> +			dev_info(gpmc->dev, "irq %u on CS %d\n",
> +						res[n].start, cs->cs);
> +			n++;
> +		}
> +
> +	return n;
> +}
> +
> +static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	unsigned long start;
> +	int ret;
> +
> +	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
> +		return ret;
> +	}
> +
> +	res->start = start + cs->mem_offset;
> +	res->end = res->start + cs->mem_size - 1;
> +	res->flags = IORESOURCE_MEM;
> +
> +	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
> +							res->end, cs->cs);
> +
> +	return 1;
> +}
> +
> +static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int num, ret;
> +
> +	num = gpmc_setup_cs_mem(gpmc, cs, res);
> +	if (IS_ERR_VALUE(num))
> +		return num;
> +
> +	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
> +
> +	return num;
> +}
> +
> +static __devinit int gpmc_setup_device(struct gpmc *gpmc,
> +		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
> +{
> +	int i, n, ret;
> +	struct gpmc_cs_data *cs;
> +
> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> +				i < gdp->num_cs; i++, cs++)
> +		n += hweight32(cs->irq_config);

As you know I am not a fan of these overloaded for-loops as I find them
hard to read ;-)

Why not ...

n = gdp->num_cs;
cs = gdp->cs_data;

/* Calculate total number of irqs used by device */	
for (i = 0, i < gdp->num_cs; i++)
	n += hweight32(cs[i].irq_flags & GPMC_IRQ_MASK);

> +	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
> +								GFP_KERNEL);
> +	if (gd->gpmc_res == NULL) {
> +		dev_err(gpmc->dev, "error: memory allocation\n");
> +		return -ENOMEM;
> +	}
> +
> +	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
> +			i < gdp->num_cs; cs++, i++) {

By the way, if you make the above change, you can also remove "cs =
gdp->cs_data" from this for-loop as it is already initialised.

> +		ret = gpmc_setup_cs(gpmc, gd, cs,
> +					gd->gpmc_res + gd->gpmc_res_cnt);
> +		if (IS_ERR_VALUE(ret) ||
> +				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {

May be consider moving gpmc_setup_waitpin into gpmc_setup_cs as it makes
sense that it is part of the cs setup.

> +			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
> +			devm_kfree(gpmc->dev, gd->gpmc_res);
> +			gd->gpmc_res = NULL;
> +			gd->gpmc_res_cnt = 0;
> +			return -EINVAL;
> +		} else
> +			gd->gpmc_res_cnt += ret;
> +	}
> +
> +	gd->name = gdp->name;
> +	gd->id = gdp->id;
> +	gd->pdata = gdp->pdata;
> +	gd->pdata_size = gdp->pdata_size;
> +	gd->per_res = gdp->per_res;
> +	gd->per_res_cnt = gdp->per_res_cnt;
> +
> +	return 0;
> +}
> +
> +static __devinit
> +struct platform_device *gpmc_create_device(struct gpmc *gpmc,
> +					struct gpmc_device *p)
> +{
> +	int num = p->per_res_cnt + p->gpmc_res_cnt;
> +	struct resource *res;
> +	struct platform_device *pdev;
> +
> +	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
> +								GFP_KERNEL);
> +	if (!res) {
> +		dev_err(gpmc->dev, "error: allocating memory\n");
> +		return NULL;
> +	}
> +
> +	memcpy((char *)res, (const char *) p->gpmc_res,
> +				sizeof(struct resource) * p->gpmc_res_cnt);
> +	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
> +				sizeof(struct resource) * p->per_res_cnt);
> +
> +	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
> +					res, num, p->pdata, p->pdata_size);
> +
> +	devm_kfree(gpmc->dev, res);
> +
> +	return pdev;
>  }
> -postcore_initcall(gpmc_init);
>  
>  static irqreturn_t gpmc_handle_irq(int irq, void *dev)
>  {
> -	u8 cs;
> +	int i;
> +	u32 regval;
> +	struct gpmc *gpmc = dev;
> +
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
>  
> -	/* check cs to invoke the irq */
> -	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
> -	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
> -		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (regval & gpmc->irq[i].bitmask)
> +			generic_handle_irq(gpmc->irq[i].irq);
> +
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
>  
>  	return IRQ_HANDLED;
>  }
>  
> +static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
> +{
> +	int i;
> +	u32 regval;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (irq == gpmc->irq[i].irq) {
> +			regval = gpmc_read_reg(GPMC_IRQENABLE);
> +			if (endis)
> +				regval |= gpmc->irq[i].bitmask;
> +			else
> +				regval &= ~gpmc->irq[i].bitmask;
> +			gpmc_write_reg(GPMC_IRQENABLE, regval);
> +			break;
> +		}
> +
> +	return 0;
> +}
> +
> +static void gpmc_irq_disable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
> +}
> +
> +static void gpmc_irq_enable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
> +}
> +
> +static void gpmc_irq_noop(struct irq_data *data) { }
> +
> +static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
> +
> +static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +	u32 regval;
> +
> +	if (!gpmc->master_irq)
> +		return -EINVAL;
> +
> +	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
> +	if (IS_ERR_VALUE(gpmc->irq_start)) {
> +		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
> +		return gpmc->irq_start;
> +	}
> +
> +	gpmc->irq_chip.name = "gpmc";
> +	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
> +	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
> +	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
> +	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
> +
> +	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
> +	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		gpmc->irq[i].irq = gpmc->irq_start + i;
> +		irq_set_chip_and_handler(gpmc->irq[i].irq,
> +					&gpmc->irq_chip, handle_simple_irq);
> +		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
> +		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
> +	}
> +
> +	/* Disable interrupts */
> +	gpmc_write_reg(GPMC_IRQENABLE, 0);
> +
> +	/* clear interrupts */
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
> +
> +	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
> +							"gpmc", gpmc);
> +}
> +
> +static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
> +{
> +	u32 l;
> +
> +	l = gpmc_read_reg(GPMC_CONFIG);
> +	if (gpmc->wp == true) {
> +		l &= ~GPMC_CONFIG_WRITEPROTECT;
> +		dev_info(gpmc->dev, "write protect enabled\n");
> +	} else
> +		l |= GPMC_CONFIG_WRITEPROTECT;
> +	gpmc_write_reg(GPMC_CONFIG, l);
> +}
> +
> +static __devinit int gpmc_probe(struct platform_device *pdev)
> +{
> +	u32 l;
> +	int i;
> +	int ret = 0;
> +	struct resource *res = NULL;
> +	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
> +	struct gpmc_device_pdata **gdq = NULL;
> +	struct gpmc_device *gd = NULL;
> +
> +	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
> +	if (gpmc == NULL)
> +		return -ENOMEM;
> +
> +	gpmc->dev = &pdev->dev;
> +	gpmc->clk_prd = gp->clk_prd;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (res == NULL)
> +		return -ENOENT;
> +
> +	gpmc->phys_base = res->start;
> +	gpmc->memsize = resource_size(res);
> +
> +	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
> +	if (!gpmc->io_base)
> +		return -EADDRNOTAVAIL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (res == NULL)
> +		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
> +	else
> +		gpmc->master_irq = res->start;
> +
> +	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
> +		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
> +
> +	gpmc->ecc_used = -EINVAL;
> +	spin_lock_init(&gpmc->mem_lock);
> +	platform_set_drvdata(pdev, gpmc);
> +
> +	l = gpmc_read_reg(GPMC_REVISION);
> +	gpmc->revision = (l >> 4) & 0xf;
> +	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
> +
> +	gpmc_mem_init();
> +
> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> +			(i < gp->num_device) && (*gdq); i++, gdq++) {

You have num_devices now and so do you really need the "&& (*gdq)"?
Seems redundant.

> +		ret = gpmc_setup_device(gpmc, gd, *gdq);

gdp[i]

> +		if (IS_ERR_VALUE(ret))
> +			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
> +								(*gdq)->name);
> +		else
> +			gd++;
> +	}
> +	gpmc->num_device = gd - gpmc->device;
> +
> +	gpmc_setup_writeprotect(gpmc);

Write protect is a pin and there is only one. Like the waitpins and CS
signals this needs to be associated with a device. It would make sense
that this is associated with the cs data.

> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (IS_ERR(gpmc_create_device(gpmc, gd)))
> +			dev_err(gpmc->dev, "device creation on %s failed\n",
> +								gd->name);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_free_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +
> +	if (gpmc->master_irq)
> +		free_irq(gpmc->master_irq, gpmc);
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		irq_set_handler(gpmc->irq[i].irq, NULL);
> +		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
> +		irq_set_chip_data(gpmc->irq[i].irq, NULL);
> +		irq_modify_status(gpmc->irq[i].irq, 0, 0);
> +	}
> +
> +	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_remove(struct platform_device *pdev)
> +{
> +	struct gpmc *gpmc = platform_get_drvdata(pdev);
> +
> +	platform_set_drvdata(pdev, NULL);
> +	gpmc_free_irq(gpmc);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver gpmc_driver = {
> +	.probe		= gpmc_probe,
> +	.remove		= __devexit_p(gpmc_remove),
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +module_platform_driver(gpmc_driver);
> +
>  #ifdef CONFIG_ARCH_OMAP3
>  static struct omap3_gpmc_regs gpmc_context;
>  
> @@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
>  	unsigned int val;
>  
>  	/* check if ecc module is in used */
> -	if (gpmc_ecc_used != -EINVAL)
> +	if (gpmc->ecc_used != -EINVAL)
>  		return -EINVAL;
>  
> -	gpmc_ecc_used = cs;
> +	gpmc->ecc_used = cs;
>  
>  	/* clear ecc and enable bits */
>  	val = ((0x00000001<<8) | 0x00000001);
> @@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  {
>  	unsigned int val = 0x0;
>  
> -	if (gpmc_ecc_used != cs)
> +	if (gpmc->ecc_used != cs)
>  		return -EINVAL;
>  
>  	/* read ecc result */
> @@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
>  	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
>  
> -	gpmc_ecc_used = -EINVAL;
> +	gpmc->ecc_used = -EINVAL;
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 1527929..2eedd99 100644
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -11,6 +11,44 @@
>  #ifndef __OMAP2_GPMC_H
>  #define __OMAP2_GPMC_H
>  
> +/* configuration flags */
> +#define	GPMC_WRITEPROTECT		BIT(0)
> +#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
> +#define	GPMC_MUXADDDATA			BIT(2)
> +#define	GPMC_DEVICETYPE_NOR		BIT(3)
> +#define	GPMC_DEVICETYPE_NAND		BIT(4)
> +#define	GPMC_DEVICESIZE_8		BIT(5)
> +#define	GPMC_DEVICESIZE_16		BIT(6)
> +#define	GPMC_WAIT_WRITE_MON		BIT(7)
> +#define	GPMC_WAIT_READ_MON		BIT(8)
> +#define	GPMC_PAGE_LEN_4			BIT(9)
> +#define	GPMC_PAGE_LEN_8			BIT(10)
> +#define	GPMC_PAGE_LEN_16		BIT(11)
> +#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
> +#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
> +#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
> +#define	GPMC_WRITETYPE_SYNC		BIT(15)
> +#define	GPMC_WRITEMULTIPLE		BIT(16)
> +#define	GPMC_READTYPE_SYNC		BIT(17)
> +#define	GPMC_READMULTIPLE		BIT(18)
> +#define	GPMC_WRAPBURST			BIT(19)
> +#define	GPMC_WAITPIN_0			BIT(20)
> +#define	GPMC_WAITPIN_1			BIT(21)
> +#define	GPMC_WAITPIN_2			BIT(22)
> +#define	GPMC_WAITPIN_3			BIT(23)
> +#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
> +					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
> +#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
> +#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
> +#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
> +					GPMC_WAITPIN_ACTIVE_HIGH)
> +#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
> +#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
> +#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
> +#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
> +#define	GPMC_READTYPE_ASYNC		BIT(30)
> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> +

Please keep in mind that eventually this has to all be moved into device
tree and so at that point these configuration flags will have to be
re-worked. However, just a FYI.

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-01 17:53         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 17:53 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, Vaibhav Hiremath, vimal.newwork, grinberg,
	artem.bityutskiy, linux-mtd, linux-omap, dwmw2, linux-arm-kernel,
	notasas

Hi Afzal,

Looks good! Some minor comments ...

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Convert GPMC code to driver. Boards using GPMC should provide driver
> with type of configuration, timing, CS. Platform devices would then be
> created for each connected peripheral (details also to be passed by
> board so that it reaches respective driver). And GPMC driver would
> populate memory resource details for the connected peripheral driver.
> Boards should inform gpmc driver with platform data destined for
> peripheral driver. gpmc driver will provide the same information to
> peripheral driver.
> 
> A peripheral connected to GPMC can have multiple address spaces using
> different chip select. Hence GPMC driver has been provided capability
> to create platform device for peripheral using mutiple CS. The
> peripheral that made it necessary was tusb6010.
> 
> Interrupts of GPMC are presented to drivers of connected peripherals
> as resource. A fictitious interrupt controller chip handles these
> interrupts at GPMC hardware level. Clients can use normal interrupt
> APIs. Platform information of peripheral passed to GPMC driver should
> indicate interrupts to be used via flags.
> 
> Driver is capable of configuring waitpin, waitpin details has to be
> provided per CS. Wait pin has been considered as exclusive resource
> as multiple peripherals should not using the same pin, at the same
> it is valid for mutiple CS to use same waitpin provided they are
> a part of single peripheral (eg. tusb6010)
> 
> An exported symbol for reconfiguring GPMC settings has been provided.
> OneNAND is the one that neccessitated this.
> 
> Acquiring CS# for NAND is done on a few boards. It means, depending
> on bootloader to embed this information. Probably CS# being used can
> be set in the Kernel, and acquiring it can be removed. If ever this
> capbility is needed, GPMC driver has to be made aware of handling it.
> 
> Modifications has been made keeping in mind that the driver would
> have to move to driver folder. This explains requirement of clk_prd
> field; even though clk_prd variable is not necessary as
> gpmc_get_fclk_period is present in the same file as of now, this will
> help in moving the driver easily to drivers folder.
> 
> Code related to GPMC clock may have to continue live in platform
> folders as input clock is beyond the control of GPMC and calculating
> timing for the peripheral may need other helpers. This explains
> presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
> both doing same work, latter meant to go with driver, former for
> calculation in platform code.
> 
> Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
> suggestions which resulted in improving the code.
> 
> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
>  arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
>  2 files changed, 872 insertions(+), 98 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 580e684..12916f3 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -14,8 +14,11 @@
>   */
>  #undef DEBUG
>  
> +#include <linux/platform_device.h>
> +
>  #include <linux/irq.h>
>  #include <linux/kernel.h>
> +#include <linux/slab.h>
>  #include <linux/init.h>
>  #include <linux/err.h>
>  #include <linux/clk.h>
> @@ -53,6 +56,45 @@
>  #define GPMC_CS0_OFFSET		0x60
>  #define GPMC_CS_SIZE		0x30
>  
> +/* GPMC register bits */
> +#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
> +#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
> +#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
> +#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
> +#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
> +#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
> +#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
> +
> +#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
> +#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
> +
> +#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
> +#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
> +
> +#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
> +#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
> +
> +#define	GPMC_WAITPIN_IDX0			0x0
> +#define	GPMC_WAITPIN_IDX1			0x1
> +#define	GPMC_WAITPIN_IDX2			0x2
> +#define	GPMC_WAITPIN_IDX3			0x3
> +#define	GPMC_NR_WAITPIN				0x4

How about an enum here? Also OMAP4 only have 3 wait pins and so the
number is device dependent.

>  #define GPMC_MEM_START		0x00000000
>  #define GPMC_MEM_END		0x3FFFFFFF
>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> @@ -64,6 +106,55 @@
>  #define ENABLE_PREFETCH		(0x1 << 7)
>  #define DMA_MPU_MODE		2
>  
> +#define	DRIVER_NAME	"omap-gpmc"
> +
> +#define	GPMC_NR_IRQ		2

Why has this been changed to 2? It was 6 in the previous version. As we
discussed before the number of IRQs should be detected based upon GPMC
IP version.

> +
> +#define	HIGH			1
> +#define	LOW			-1
> +
> +struct gpmc_device {
> +	char			*name;
> +	int			id;
> +	void			*pdata;
> +	unsigned		pdata_size;
> +	struct resource		*per_res;
> +	unsigned		per_res_cnt;
> +	struct resource		*gpmc_res;
> +	unsigned		gpmc_res_cnt;
> +	bool			have_waitpin;
> +	unsigned		waitpin;
> +	int			waitpin_polarity;

I think that it make more sense to have the wait-pin information part of
the gpmc_cs_data structure for the following reasons ...

1. If a device can use multiple CS, then it could use multiple wait signals.
2. Eventually, all board information needs to move to device tree. By
having it in the pdata it will be easier to migrate to device tree.

It may be nice to have "have_waitpin" be an integer too, that indicates
if wait is used for both read and write or just one or the other.

Also, any reason why waitpin_polarity is an int? I see you define LOW as
-1, but I not sure why LOW cannot be 0 as 0 is programmed into the
register for an active low wait signal.

> +};
> +
> +struct gpmc_irq	{
> +	unsigned		irq;
> +	u32			bitmask;
> +};
> +
> +struct gpmc {
> +	struct device		*dev;
> +	unsigned long		clk_prd;
> +	void __iomem		*io_base;
> +	unsigned long		phys_base;
> +	u32			memsize;
> +	unsigned		cs_map;
> +	int			ecc_used;
> +	spinlock_t		mem_lock;
> +	struct resource		mem_root;
> +	struct resource		cs_mem[GPMC_CS_NUM];
> +	/* XXX: Or allocate dynamically ? */
> +	struct gpmc_device	device[GPMC_CS_NUM];
> +	unsigned		num_device;
> +	unsigned		master_irq;
> +	unsigned		irq_start;
> +	struct gpmc_irq		irq[GPMC_NR_IRQ];
> +	struct irq_chip		irq_chip;
> +	bool			wp;
> +	unsigned		waitpin_map;
> +	unsigned		revision;
> +};
> +
>  /* Structure to save gpmc cs context */
>  struct gpmc_cs_config {
>  	u32 config1;
> @@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
>  	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
>  };
>  
> -static struct resource	gpmc_mem_root;
> -static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
> -static DEFINE_SPINLOCK(gpmc_mem_lock);
> -static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
> -static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
> -
> -static void __iomem *gpmc_base;
> -
>  static struct clk *gpmc_l3_clk;
>  
> -static irqreturn_t gpmc_handle_irq(int irq, void *dev);
> +static struct gpmc *gpmc;
>  
>  static void gpmc_write_reg(int idx, u32 val)
>  {
> -	__raw_writel(val, gpmc_base + idx);
> +	writel(val, gpmc->io_base + idx);
>  }
>  
>  static u32 gpmc_read_reg(int idx)
>  {
> -	return __raw_readl(gpmc_base + idx);
> +	return readl(gpmc->io_base + idx);
>  }
>  
>  static void gpmc_cs_write_byte(int cs, int idx, u8 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writeb(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writeb(val, reg_addr);
>  }
>  
>  static u8 gpmc_cs_read_byte(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readb(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readb(reg_addr);
>  }
>  
>  void gpmc_cs_write_reg(int cs, int idx, u32 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writel(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writel(val, reg_addr);
>  }
>  
>  u32 gpmc_cs_read_reg(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readl(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readl(reg_addr);
>  }
>  
>  /* TODO: Add support for gpmc_fck to clock framework and use it */
> @@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  	if (time == 0)
>  		ticks = 0;
>  	else
> -		ticks = gpmc_ns_to_ticks(time);
> +		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
> +
>  	nr_bits = end_bit - st_bit + 1;
>  	if (ticks >= 1 << nr_bits) {
>  #ifdef DEBUG
> @@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  #ifdef DEBUG
>  	printk(KERN_INFO
>  		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
> -	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
> +	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
>  			(l >> st_bit) & mask, time);
>  #endif
>  	l &= ~(mask << st_bit);
> @@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  		return -1
>  #endif
>  
> +int gpmc_calc_divider(unsigned int sync_clk)
> +{
> +	int div;
> +	u32 l;
> +
> +	l = sync_clk + (gpmc->clk_prd - 1);
> +	div = l / gpmc->clk_prd;
> +	if (div > 4)
> +		return -1;
> +	if (div <= 0)
> +		div = 1;
> +
> +	return div;
> +}
> +
>  int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  {
>  	int div;
> @@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  	return div;
>  }
>  
> +static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
> +{
> +	u32 l;
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
> +	if (p->cs_extra_delay)
> +		l |= GPMC_CONFIG2_CSEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
> +	if (p->adv_extra_delay)
> +		l |= GPMC_CONFIG3_ADVEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
> +	if (p->oe_extra_delay)
> +		l |= GPMC_CONFIG4_OEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
> +	if (p->we_extra_delay)
> +		l |= GPMC_CONFIG4_WEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
> +	if (p->cycle2cyclesamecsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	if (p->cycle2cyclediffcsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
> +}
> +
>  int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  {
>  	int div;
>  	u32 l;
>  
> -	div = gpmc_cs_calc_divider(cs, t->sync_clk);
> +	div = gpmc_calc_divider(t->sync_clk);
>  	if (div < 0)
>  		return -1;
>  
> @@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  
>  	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
>  
> -	if (cpu_is_omap34xx()) {
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
> +
> +	if (gpmc->revision >= 5) {
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
>  	}
> @@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
>  #ifdef DEBUG
>  		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
> -				cs, (div * gpmc_get_fclk_period()) / 1000, div);
> +				cs, (div * gpmc->clk_prd) / 1000, div);
>  #endif
>  		l &= ~0x03;
>  		l |= (div - 1);
>  		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>  	}
>  
> +	gpmc_cs_onoff_timings(cs, &t->control);
> +
>  	return 0;
>  }
>  
> @@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
>  	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
>  }
>  
> -static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
> +static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
>  {
>  	u32 l;
>  	u32 mask;
> @@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
>  	return l & GPMC_CONFIG7_CSVALID;
>  }
>  
> -int gpmc_cs_set_reserved(int cs, int reserved)
> +static int gpmc_cs_set_reserved(int cs, int reserved)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	gpmc_cs_map &= ~(1 << cs);
> -	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
> +	gpmc->cs_map &= ~(1 << cs);
> +	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
>  
>  	return 0;
>  }
>  
> -int gpmc_cs_reserved(int cs)
> +static int gpmc_cs_reserved(int cs)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	return gpmc_cs_map & (1 << cs);
> +	return gpmc->cs_map & (1 << cs);
>  }
>  
>  static unsigned long gpmc_mem_align(unsigned long size)
> @@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
>  	return size;
>  }
>  
> -static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
> +static __devinit
> +int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
>  {
> -	struct resource	*res = &gpmc_cs_mem[cs];
> +	struct resource	*res = &gpmc->cs_mem[cs];
>  	int r;
>  
>  	size = gpmc_mem_align(size);
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	res->start = base;
>  	res->end = base + size - 1;
> -	r = request_resource(&gpmc_mem_root, res);
> -	spin_unlock(&gpmc_mem_lock);
> +	r = request_resource(&gpmc->mem_root, res);
> +	spin_unlock(&gpmc->mem_lock);
>  
>  	return r;
>  }
>  
>  int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  {
> -	struct resource *res = &gpmc_cs_mem[cs];
> +	struct resource *res = &gpmc->cs_mem[cs];
>  	int r = -1;
>  
>  	if (cs > GPMC_CS_NUM)
> @@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (size > (1 << GPMC_SECTION_SHIFT))
>  		return -ENOMEM;
>  
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (gpmc_cs_reserved(cs)) {
>  		r = -EBUSY;
>  		goto out;
> @@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (gpmc_cs_mem_enabled(cs))
>  		r = adjust_resource(res, res->start & ~(size - 1), size);
>  	if (r < 0)
> -		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
> +		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
>  				      size, NULL, NULL);
>  	if (r < 0)
>  		goto out;
> @@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	*base = res->start;
>  	gpmc_cs_set_reserved(cs, 1);
>  out:
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  	return r;
>  }
>  EXPORT_SYMBOL(gpmc_cs_request);
>  
>  void gpmc_cs_free(int cs)
>  {
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
>  		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
>  		BUG();
> -		spin_unlock(&gpmc_mem_lock);
> +		spin_unlock(&gpmc->mem_lock);
>  		return;
>  	}
>  	gpmc_cs_disable_mem(cs);
> -	release_resource(&gpmc_cs_mem[cs]);
> +	release_resource(&gpmc->cs_mem[cs]);
>  	gpmc_cs_set_reserved(cs, 0);
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  }
>  EXPORT_SYMBOL(gpmc_cs_free);
>  
> @@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
>  }
>  EXPORT_SYMBOL(gpmc_prefetch_reset);
>  
> -static void __init gpmc_mem_init(void)
> +static __devinit void gpmc_mem_init(void)
>  {
>  	int cs;
>  	unsigned long boot_rom_space = 0;
> @@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
>  	/* In apollon the CS0 is mapped as 0x0000 0000 */
>  	if (machine_is_omap_apollon())
>  		boot_rom_space = 0;
> -	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
> -	gpmc_mem_root.end = GPMC_MEM_END;
> +	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
> +	gpmc->mem_root.end = GPMC_MEM_END;
>  
>  	/* Reserve all regions that has been set up by bootloader */
>  	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> @@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	u32 l, irq;
> -	int cs, ret = -EINVAL;
> -	int gpmc_irq;
> +	int ret = -EINVAL;
>  	char *ck = NULL;
>  
>  	if (cpu_is_omap24xx()) {
>  		ck = "core_l3_ck";
> -		if (cpu_is_omap2420())
> -			l = OMAP2420_GPMC_BASE;
> -		else
> -			l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap34xx()) {
>  		ck = "gpmc_fck";
> -		l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap44xx()) {
>  		ck = "gpmc_ck";
> -		l = OMAP44XX_GPMC_BASE;
> -		gpmc_irq = OMAP44XX_IRQ_GPMC;
>  	}
>  
>  	if (WARN_ON(!ck))
> @@ -728,53 +863,607 @@ static int __init gpmc_init(void)
>  		BUG();
>  	}
>  
> -	gpmc_base = ioremap(l, SZ_4K);
> -	if (!gpmc_base) {
> -		clk_put(gpmc_l3_clk);
> -		printk(KERN_ERR "Could not get GPMC register memory\n");
> -		BUG();
> +	clk_enable(gpmc_l3_clk);
> +
> +	return 0;
> +}
> +postcore_initcall(gpmc_init);
> +
> +static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	return gpmc->waitpin_map & (0x1 << waitpin);
> +}
> +
> +static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	gpmc->waitpin_map &= ~(0x1 << waitpin);
> +	gpmc->waitpin_map |= (0x1 << waitpin);
> +}
> +
> +static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	if (!(waitpin < GPMC_NR_WAITPIN))
> +		return -ENODEV;
> +
> +	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
> +		return -EBUSY;
> +	else
> +		gpmc_reserve_waitpin(gpmc, waitpin);
> +
> +	return 0;
> +}
> +
> +static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
> +{
> +	int ret;
> +
> +	if (!gd->have_waitpin)
> +		return 0;
> +
> +	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
> +		return ret;
> +	} else if (gd->waitpin_polarity) {
> +		u32 l = gpmc_read_reg(GPMC_CONFIG);
> +		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
> +
> +		if (gd->waitpin_polarity == HIGH)
> +			l |= 1 << shift;
> +		else
> +			l &= ~(1 << shift);
> +
> +		gpmc_write_reg(GPMC_CONFIG, l);
>  	}
> +	return 0;
> +}
>  
> -	clk_enable(gpmc_l3_clk);
> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}
>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}
>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {
> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {
> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}

I am not sure about the above code. What happens if a device has
multiple CS signals and uses multiple wait signals?

I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
cannot be combined. I think that it would be a fair assumption to make
that anyone using the waitpin does so inconjunction with the CS (I think
that they would have too).

However, if there is a reason for splitting it up this way please
explain why.

> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
> +		GPMC_CONFIG1_MUXADDDATA |
> +		GPMC_CONFIG1_DEVICETYPE(~0) |
> +		GPMC_CONFIG1_DEVICESIZE(~0) |
> +		GPMC_CONFIG1_WAIT_WRITE_MON |
> +		GPMC_CONFIG1_WAIT_READ_MON |
> +		GPMC_CONFIG1_PAGE_LEN(~0) |
> +		GPMC_CONFIG1_WRITETYPE_SYNC |
> +		GPMC_CONFIG1_WRITEMULTIPLE |
> +		GPMC_CONFIG1_READTYPE_SYNC |
> +		GPMC_CONFIG1_READMULTIPLE |
> +		GPMC_CONFIG1_WRAPBURST |
> +		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
> +		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
> +
> +	if (conf & GPMC_TIMEPARAGRANULARITY)
> +		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
> +	if (conf & GPMC_MUXADDDATA)
> +		l |= GPMC_CONFIG1_MUXADDDATA;
> +	if (conf & GPMC_DEVICETYPE_NAND)
> +		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
> +	if (conf & GPMC_DEVICESIZE_16)
> +		l |= GPMC_CONFIG1_DEVICESIZE_16;
> +	if (conf & GPMC_WAIT_WRITE_MON)
> +		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
> +	if (conf & GPMC_WAIT_READ_MON)
> +		l |= GPMC_CONFIG1_WAIT_READ_MON;
> +	if (conf & GPMC_PAGE_LEN_16)
> +		l |= GPMC_CONFIG1_PAGE_LEN_16;
> +	else if (conf & GPMC_PAGE_LEN_8)
> +		l |= GPMC_CONFIG1_PAGE_LEN_8;
> +	if (conf & GPMC_WRITETYPE_SYNC)
> +		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
> +	if (conf & GPMC_WRITEMULTIPLE)
> +		l |= GPMC_CONFIG1_WRITEMULTIPLE;
> +	if (conf & GPMC_READTYPE_SYNC)
> +		l |= GPMC_CONFIG1_READTYPE_SYNC;
> +	if (conf & GPMC_READMULTIPLE)
> +		l |= GPMC_CONFIG1_READMULTIPLE;
> +	if (conf & GPMC_WRAPBURST)
> +		l |= GPMC_CONFIG1_WRAPBURST;
> +	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
> +	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
> +	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
> +	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
> +
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +
> +	if (conf & GPMC_WRITEPROTECT)
> +		gpmc->wp = true;
> +}
> +
> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)

The name of this function is not 100% clear to me. What do you mean by
"nonres"?

> +{
> +	int ret;
> +
> +	/* some boards rely on bootloader for configuration */
> +	if (cs->have_config) {
> +		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
> +		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
> +
> +	if (cs->timing) {
> +		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
> +
> +	return 0;
> +}
> +
> +static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
> +{
> +	int i;
> +	struct gpmc_device *gd;
> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (!strcmp(gd->name, name) && gd->id == id)
> +			return i;
> +
> +	return -ENOENT;
> +}
> +
> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)

What scenario is this function used in? May be worth adding a comment
about the function.

> +{
> +	int i;
> +
> +	i = gpmc_match_device(gpmc, name, id);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
> +		return i;
> +	}
> +
> +	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
> +		return i;
> +	}
> +
> +	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
> +
> +}
> +EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
> +
> +static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
> +{
> +	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
> +		return GPMC_IRQ_FIFOEVENTENABLE;
> +	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
> +		return GPMC_IRQ_COUNT_EVENT;
> +	else
> +		return 0;
> +}
> +
> +static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int i, n;
> +
> +	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
> +		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
> +			res[n].start = res[n].end = gpmc->irq[i].irq;
> +			res[n].flags = IORESOURCE_IRQ;
> +			dev_info(gpmc->dev, "irq %u on CS %d\n",
> +						res[n].start, cs->cs);
> +			n++;
> +		}
> +
> +	return n;
> +}
> +
> +static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	unsigned long start;
> +	int ret;
> +
> +	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
> +		return ret;
> +	}
> +
> +	res->start = start + cs->mem_offset;
> +	res->end = res->start + cs->mem_size - 1;
> +	res->flags = IORESOURCE_MEM;
> +
> +	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
> +							res->end, cs->cs);
> +
> +	return 1;
> +}
> +
> +static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int num, ret;
> +
> +	num = gpmc_setup_cs_mem(gpmc, cs, res);
> +	if (IS_ERR_VALUE(num))
> +		return num;
> +
> +	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
> +
> +	return num;
> +}
> +
> +static __devinit int gpmc_setup_device(struct gpmc *gpmc,
> +		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
> +{
> +	int i, n, ret;
> +	struct gpmc_cs_data *cs;
> +
> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> +				i < gdp->num_cs; i++, cs++)
> +		n += hweight32(cs->irq_config);

As you know I am not a fan of these overloaded for-loops as I find them
hard to read ;-)

Why not ...

n = gdp->num_cs;
cs = gdp->cs_data;

/* Calculate total number of irqs used by device */	
for (i = 0, i < gdp->num_cs; i++)
	n += hweight32(cs[i].irq_flags & GPMC_IRQ_MASK);

> +	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
> +								GFP_KERNEL);
> +	if (gd->gpmc_res == NULL) {
> +		dev_err(gpmc->dev, "error: memory allocation\n");
> +		return -ENOMEM;
> +	}
> +
> +	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
> +			i < gdp->num_cs; cs++, i++) {

By the way, if you make the above change, you can also remove "cs =
gdp->cs_data" from this for-loop as it is already initialised.

> +		ret = gpmc_setup_cs(gpmc, gd, cs,
> +					gd->gpmc_res + gd->gpmc_res_cnt);
> +		if (IS_ERR_VALUE(ret) ||
> +				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {

May be consider moving gpmc_setup_waitpin into gpmc_setup_cs as it makes
sense that it is part of the cs setup.

> +			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
> +			devm_kfree(gpmc->dev, gd->gpmc_res);
> +			gd->gpmc_res = NULL;
> +			gd->gpmc_res_cnt = 0;
> +			return -EINVAL;
> +		} else
> +			gd->gpmc_res_cnt += ret;
> +	}
> +
> +	gd->name = gdp->name;
> +	gd->id = gdp->id;
> +	gd->pdata = gdp->pdata;
> +	gd->pdata_size = gdp->pdata_size;
> +	gd->per_res = gdp->per_res;
> +	gd->per_res_cnt = gdp->per_res_cnt;
> +
> +	return 0;
> +}
> +
> +static __devinit
> +struct platform_device *gpmc_create_device(struct gpmc *gpmc,
> +					struct gpmc_device *p)
> +{
> +	int num = p->per_res_cnt + p->gpmc_res_cnt;
> +	struct resource *res;
> +	struct platform_device *pdev;
> +
> +	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
> +								GFP_KERNEL);
> +	if (!res) {
> +		dev_err(gpmc->dev, "error: allocating memory\n");
> +		return NULL;
> +	}
> +
> +	memcpy((char *)res, (const char *) p->gpmc_res,
> +				sizeof(struct resource) * p->gpmc_res_cnt);
> +	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
> +				sizeof(struct resource) * p->per_res_cnt);
> +
> +	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
> +					res, num, p->pdata, p->pdata_size);
> +
> +	devm_kfree(gpmc->dev, res);
> +
> +	return pdev;
>  }
> -postcore_initcall(gpmc_init);
>  
>  static irqreturn_t gpmc_handle_irq(int irq, void *dev)
>  {
> -	u8 cs;
> +	int i;
> +	u32 regval;
> +	struct gpmc *gpmc = dev;
> +
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
>  
> -	/* check cs to invoke the irq */
> -	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
> -	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
> -		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (regval & gpmc->irq[i].bitmask)
> +			generic_handle_irq(gpmc->irq[i].irq);
> +
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
>  
>  	return IRQ_HANDLED;
>  }
>  
> +static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
> +{
> +	int i;
> +	u32 regval;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (irq == gpmc->irq[i].irq) {
> +			regval = gpmc_read_reg(GPMC_IRQENABLE);
> +			if (endis)
> +				regval |= gpmc->irq[i].bitmask;
> +			else
> +				regval &= ~gpmc->irq[i].bitmask;
> +			gpmc_write_reg(GPMC_IRQENABLE, regval);
> +			break;
> +		}
> +
> +	return 0;
> +}
> +
> +static void gpmc_irq_disable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
> +}
> +
> +static void gpmc_irq_enable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
> +}
> +
> +static void gpmc_irq_noop(struct irq_data *data) { }
> +
> +static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
> +
> +static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +	u32 regval;
> +
> +	if (!gpmc->master_irq)
> +		return -EINVAL;
> +
> +	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
> +	if (IS_ERR_VALUE(gpmc->irq_start)) {
> +		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
> +		return gpmc->irq_start;
> +	}
> +
> +	gpmc->irq_chip.name = "gpmc";
> +	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
> +	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
> +	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
> +	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
> +
> +	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
> +	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		gpmc->irq[i].irq = gpmc->irq_start + i;
> +		irq_set_chip_and_handler(gpmc->irq[i].irq,
> +					&gpmc->irq_chip, handle_simple_irq);
> +		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
> +		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
> +	}
> +
> +	/* Disable interrupts */
> +	gpmc_write_reg(GPMC_IRQENABLE, 0);
> +
> +	/* clear interrupts */
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
> +
> +	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
> +							"gpmc", gpmc);
> +}
> +
> +static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
> +{
> +	u32 l;
> +
> +	l = gpmc_read_reg(GPMC_CONFIG);
> +	if (gpmc->wp == true) {
> +		l &= ~GPMC_CONFIG_WRITEPROTECT;
> +		dev_info(gpmc->dev, "write protect enabled\n");
> +	} else
> +		l |= GPMC_CONFIG_WRITEPROTECT;
> +	gpmc_write_reg(GPMC_CONFIG, l);
> +}
> +
> +static __devinit int gpmc_probe(struct platform_device *pdev)
> +{
> +	u32 l;
> +	int i;
> +	int ret = 0;
> +	struct resource *res = NULL;
> +	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
> +	struct gpmc_device_pdata **gdq = NULL;
> +	struct gpmc_device *gd = NULL;
> +
> +	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
> +	if (gpmc == NULL)
> +		return -ENOMEM;
> +
> +	gpmc->dev = &pdev->dev;
> +	gpmc->clk_prd = gp->clk_prd;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (res == NULL)
> +		return -ENOENT;
> +
> +	gpmc->phys_base = res->start;
> +	gpmc->memsize = resource_size(res);
> +
> +	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
> +	if (!gpmc->io_base)
> +		return -EADDRNOTAVAIL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (res == NULL)
> +		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
> +	else
> +		gpmc->master_irq = res->start;
> +
> +	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
> +		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
> +
> +	gpmc->ecc_used = -EINVAL;
> +	spin_lock_init(&gpmc->mem_lock);
> +	platform_set_drvdata(pdev, gpmc);
> +
> +	l = gpmc_read_reg(GPMC_REVISION);
> +	gpmc->revision = (l >> 4) & 0xf;
> +	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
> +
> +	gpmc_mem_init();
> +
> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> +			(i < gp->num_device) && (*gdq); i++, gdq++) {

You have num_devices now and so do you really need the "&& (*gdq)"?
Seems redundant.

> +		ret = gpmc_setup_device(gpmc, gd, *gdq);

gdp[i]

> +		if (IS_ERR_VALUE(ret))
> +			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
> +								(*gdq)->name);
> +		else
> +			gd++;
> +	}
> +	gpmc->num_device = gd - gpmc->device;
> +
> +	gpmc_setup_writeprotect(gpmc);

Write protect is a pin and there is only one. Like the waitpins and CS
signals this needs to be associated with a device. It would make sense
that this is associated with the cs data.

> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (IS_ERR(gpmc_create_device(gpmc, gd)))
> +			dev_err(gpmc->dev, "device creation on %s failed\n",
> +								gd->name);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_free_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +
> +	if (gpmc->master_irq)
> +		free_irq(gpmc->master_irq, gpmc);
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		irq_set_handler(gpmc->irq[i].irq, NULL);
> +		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
> +		irq_set_chip_data(gpmc->irq[i].irq, NULL);
> +		irq_modify_status(gpmc->irq[i].irq, 0, 0);
> +	}
> +
> +	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_remove(struct platform_device *pdev)
> +{
> +	struct gpmc *gpmc = platform_get_drvdata(pdev);
> +
> +	platform_set_drvdata(pdev, NULL);
> +	gpmc_free_irq(gpmc);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver gpmc_driver = {
> +	.probe		= gpmc_probe,
> +	.remove		= __devexit_p(gpmc_remove),
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +module_platform_driver(gpmc_driver);
> +
>  #ifdef CONFIG_ARCH_OMAP3
>  static struct omap3_gpmc_regs gpmc_context;
>  
> @@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
>  	unsigned int val;
>  
>  	/* check if ecc module is in used */
> -	if (gpmc_ecc_used != -EINVAL)
> +	if (gpmc->ecc_used != -EINVAL)
>  		return -EINVAL;
>  
> -	gpmc_ecc_used = cs;
> +	gpmc->ecc_used = cs;
>  
>  	/* clear ecc and enable bits */
>  	val = ((0x00000001<<8) | 0x00000001);
> @@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  {
>  	unsigned int val = 0x0;
>  
> -	if (gpmc_ecc_used != cs)
> +	if (gpmc->ecc_used != cs)
>  		return -EINVAL;
>  
>  	/* read ecc result */
> @@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
>  	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
>  
> -	gpmc_ecc_used = -EINVAL;
> +	gpmc->ecc_used = -EINVAL;
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 1527929..2eedd99 100644
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -11,6 +11,44 @@
>  #ifndef __OMAP2_GPMC_H
>  #define __OMAP2_GPMC_H
>  
> +/* configuration flags */
> +#define	GPMC_WRITEPROTECT		BIT(0)
> +#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
> +#define	GPMC_MUXADDDATA			BIT(2)
> +#define	GPMC_DEVICETYPE_NOR		BIT(3)
> +#define	GPMC_DEVICETYPE_NAND		BIT(4)
> +#define	GPMC_DEVICESIZE_8		BIT(5)
> +#define	GPMC_DEVICESIZE_16		BIT(6)
> +#define	GPMC_WAIT_WRITE_MON		BIT(7)
> +#define	GPMC_WAIT_READ_MON		BIT(8)
> +#define	GPMC_PAGE_LEN_4			BIT(9)
> +#define	GPMC_PAGE_LEN_8			BIT(10)
> +#define	GPMC_PAGE_LEN_16		BIT(11)
> +#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
> +#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
> +#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
> +#define	GPMC_WRITETYPE_SYNC		BIT(15)
> +#define	GPMC_WRITEMULTIPLE		BIT(16)
> +#define	GPMC_READTYPE_SYNC		BIT(17)
> +#define	GPMC_READMULTIPLE		BIT(18)
> +#define	GPMC_WRAPBURST			BIT(19)
> +#define	GPMC_WAITPIN_0			BIT(20)
> +#define	GPMC_WAITPIN_1			BIT(21)
> +#define	GPMC_WAITPIN_2			BIT(22)
> +#define	GPMC_WAITPIN_3			BIT(23)
> +#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
> +					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
> +#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
> +#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
> +#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
> +					GPMC_WAITPIN_ACTIVE_HIGH)
> +#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
> +#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
> +#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
> +#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
> +#define	GPMC_READTYPE_ASYNC		BIT(30)
> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> +

Please keep in mind that eventually this has to all be moved into device
tree and so at that point these configuration flags will have to be
re-worked. However, just a FYI.

Cheers
Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-01 17:53         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 17:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

Looks good! Some minor comments ...

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Convert GPMC code to driver. Boards using GPMC should provide driver
> with type of configuration, timing, CS. Platform devices would then be
> created for each connected peripheral (details also to be passed by
> board so that it reaches respective driver). And GPMC driver would
> populate memory resource details for the connected peripheral driver.
> Boards should inform gpmc driver with platform data destined for
> peripheral driver. gpmc driver will provide the same information to
> peripheral driver.
> 
> A peripheral connected to GPMC can have multiple address spaces using
> different chip select. Hence GPMC driver has been provided capability
> to create platform device for peripheral using mutiple CS. The
> peripheral that made it necessary was tusb6010.
> 
> Interrupts of GPMC are presented to drivers of connected peripherals
> as resource. A fictitious interrupt controller chip handles these
> interrupts at GPMC hardware level. Clients can use normal interrupt
> APIs. Platform information of peripheral passed to GPMC driver should
> indicate interrupts to be used via flags.
> 
> Driver is capable of configuring waitpin, waitpin details has to be
> provided per CS. Wait pin has been considered as exclusive resource
> as multiple peripherals should not using the same pin, at the same
> it is valid for mutiple CS to use same waitpin provided they are
> a part of single peripheral (eg. tusb6010)
> 
> An exported symbol for reconfiguring GPMC settings has been provided.
> OneNAND is the one that neccessitated this.
> 
> Acquiring CS# for NAND is done on a few boards. It means, depending
> on bootloader to embed this information. Probably CS# being used can
> be set in the Kernel, and acquiring it can be removed. If ever this
> capbility is needed, GPMC driver has to be made aware of handling it.
> 
> Modifications has been made keeping in mind that the driver would
> have to move to driver folder. This explains requirement of clk_prd
> field; even though clk_prd variable is not necessary as
> gpmc_get_fclk_period is present in the same file as of now, this will
> help in moving the driver easily to drivers folder.
> 
> Code related to GPMC clock may have to continue live in platform
> folders as input clock is beyond the control of GPMC and calculating
> timing for the peripheral may need other helpers. This explains
> presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider',
> both doing same work, latter meant to go with driver, former for
> calculation in platform code.
> 
> Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good
> suggestions which resulted in improving the code.
> 
> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
>  arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
>  2 files changed, 872 insertions(+), 98 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 580e684..12916f3 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -14,8 +14,11 @@
>   */
>  #undef DEBUG
>  
> +#include <linux/platform_device.h>
> +
>  #include <linux/irq.h>
>  #include <linux/kernel.h>
> +#include <linux/slab.h>
>  #include <linux/init.h>
>  #include <linux/err.h>
>  #include <linux/clk.h>
> @@ -53,6 +56,45 @@
>  #define GPMC_CS0_OFFSET		0x60
>  #define GPMC_CS_SIZE		0x30
>  
> +/* GPMC register bits */
> +#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
> +#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
> +#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
> +#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
> +#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
> +#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
> +#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
> +#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
> +				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
> +#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
> +				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
> +
> +#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
> +
> +#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
> +#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
> +
> +#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
> +#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
> +
> +#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
> +#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
> +
> +#define	GPMC_WAITPIN_IDX0			0x0
> +#define	GPMC_WAITPIN_IDX1			0x1
> +#define	GPMC_WAITPIN_IDX2			0x2
> +#define	GPMC_WAITPIN_IDX3			0x3
> +#define	GPMC_NR_WAITPIN				0x4

How about an enum here? Also OMAP4 only have 3 wait pins and so the
number is device dependent.

>  #define GPMC_MEM_START		0x00000000
>  #define GPMC_MEM_END		0x3FFFFFFF
>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> @@ -64,6 +106,55 @@
>  #define ENABLE_PREFETCH		(0x1 << 7)
>  #define DMA_MPU_MODE		2
>  
> +#define	DRIVER_NAME	"omap-gpmc"
> +
> +#define	GPMC_NR_IRQ		2

Why has this been changed to 2? It was 6 in the previous version. As we
discussed before the number of IRQs should be detected based upon GPMC
IP version.

> +
> +#define	HIGH			1
> +#define	LOW			-1
> +
> +struct gpmc_device {
> +	char			*name;
> +	int			id;
> +	void			*pdata;
> +	unsigned		pdata_size;
> +	struct resource		*per_res;
> +	unsigned		per_res_cnt;
> +	struct resource		*gpmc_res;
> +	unsigned		gpmc_res_cnt;
> +	bool			have_waitpin;
> +	unsigned		waitpin;
> +	int			waitpin_polarity;

I think that it make more sense to have the wait-pin information part of
the gpmc_cs_data structure for the following reasons ...

1. If a device can use multiple CS, then it could use multiple wait signals.
2. Eventually, all board information needs to move to device tree. By
having it in the pdata it will be easier to migrate to device tree.

It may be nice to have "have_waitpin" be an integer too, that indicates
if wait is used for both read and write or just one or the other.

Also, any reason why waitpin_polarity is an int? I see you define LOW as
-1, but I not sure why LOW cannot be 0 as 0 is programmed into the
register for an active low wait signal.

> +};
> +
> +struct gpmc_irq	{
> +	unsigned		irq;
> +	u32			bitmask;
> +};
> +
> +struct gpmc {
> +	struct device		*dev;
> +	unsigned long		clk_prd;
> +	void __iomem		*io_base;
> +	unsigned long		phys_base;
> +	u32			memsize;
> +	unsigned		cs_map;
> +	int			ecc_used;
> +	spinlock_t		mem_lock;
> +	struct resource		mem_root;
> +	struct resource		cs_mem[GPMC_CS_NUM];
> +	/* XXX: Or allocate dynamically ? */
> +	struct gpmc_device	device[GPMC_CS_NUM];
> +	unsigned		num_device;
> +	unsigned		master_irq;
> +	unsigned		irq_start;
> +	struct gpmc_irq		irq[GPMC_NR_IRQ];
> +	struct irq_chip		irq_chip;
> +	bool			wp;
> +	unsigned		waitpin_map;
> +	unsigned		revision;
> +};
> +
>  /* Structure to save gpmc cs context */
>  struct gpmc_cs_config {
>  	u32 config1;
> @@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
>  	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
>  };
>  
> -static struct resource	gpmc_mem_root;
> -static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
> -static DEFINE_SPINLOCK(gpmc_mem_lock);
> -static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
> -static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
> -
> -static void __iomem *gpmc_base;
> -
>  static struct clk *gpmc_l3_clk;
>  
> -static irqreturn_t gpmc_handle_irq(int irq, void *dev);
> +static struct gpmc *gpmc;
>  
>  static void gpmc_write_reg(int idx, u32 val)
>  {
> -	__raw_writel(val, gpmc_base + idx);
> +	writel(val, gpmc->io_base + idx);
>  }
>  
>  static u32 gpmc_read_reg(int idx)
>  {
> -	return __raw_readl(gpmc_base + idx);
> +	return readl(gpmc->io_base + idx);
>  }
>  
>  static void gpmc_cs_write_byte(int cs, int idx, u8 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writeb(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writeb(val, reg_addr);
>  }
>  
>  static u8 gpmc_cs_read_byte(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readb(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readb(reg_addr);
>  }
>  
>  void gpmc_cs_write_reg(int cs, int idx, u32 val)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	__raw_writel(val, reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	writel(val, reg_addr);
>  }
>  
>  u32 gpmc_cs_read_reg(int cs, int idx)
>  {
>  	void __iomem *reg_addr;
>  
> -	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> -	return __raw_readl(reg_addr);
> +	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
> +	return readl(reg_addr);
>  }
>  
>  /* TODO: Add support for gpmc_fck to clock framework and use it */
> @@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  	if (time == 0)
>  		ticks = 0;
>  	else
> -		ticks = gpmc_ns_to_ticks(time);
> +		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
> +
>  	nr_bits = end_bit - st_bit + 1;
>  	if (ticks >= 1 << nr_bits) {
>  #ifdef DEBUG
> @@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  #ifdef DEBUG
>  	printk(KERN_INFO
>  		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
> -	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
> +	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
>  			(l >> st_bit) & mask, time);
>  #endif
>  	l &= ~(mask << st_bit);
> @@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  		return -1
>  #endif
>  
> +int gpmc_calc_divider(unsigned int sync_clk)
> +{
> +	int div;
> +	u32 l;
> +
> +	l = sync_clk + (gpmc->clk_prd - 1);
> +	div = l / gpmc->clk_prd;
> +	if (div > 4)
> +		return -1;
> +	if (div <= 0)
> +		div = 1;
> +
> +	return div;
> +}
> +
>  int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  {
>  	int div;
> @@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
>  	return div;
>  }
>  
> +static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
> +{
> +	u32 l;
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
> +	if (p->cs_extra_delay)
> +		l |= GPMC_CONFIG2_CSEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
> +	if (p->adv_extra_delay)
> +		l |= GPMC_CONFIG3_ADVEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
> +	if (p->oe_extra_delay)
> +		l |= GPMC_CONFIG4_OEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
> +	if (p->we_extra_delay)
> +		l |= GPMC_CONFIG4_WEEXTRADELAY;
> +	else
> +		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
> +
> +	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
> +	if (p->cycle2cyclesamecsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
> +	if (p->cycle2cyclediffcsen)
> +		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	else
> +		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
> +}
> +
>  int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  {
>  	int div;
>  	u32 l;
>  
> -	div = gpmc_cs_calc_divider(cs, t->sync_clk);
> +	div = gpmc_calc_divider(t->sync_clk);
>  	if (div < 0)
>  		return -1;
>  
> @@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  
>  	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
>  
> -	if (cpu_is_omap34xx()) {
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
> +	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
> +
> +	if (gpmc->revision >= 5) {
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
>  		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
>  	}
> @@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
>  	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
>  #ifdef DEBUG
>  		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
> -				cs, (div * gpmc_get_fclk_period()) / 1000, div);
> +				cs, (div * gpmc->clk_prd) / 1000, div);
>  #endif
>  		l &= ~0x03;
>  		l |= (div - 1);
>  		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>  	}
>  
> +	gpmc_cs_onoff_timings(cs, &t->control);
> +
>  	return 0;
>  }
>  
> @@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
>  	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
>  }
>  
> -static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
> +static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
>  {
>  	u32 l;
>  	u32 mask;
> @@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
>  	return l & GPMC_CONFIG7_CSVALID;
>  }
>  
> -int gpmc_cs_set_reserved(int cs, int reserved)
> +static int gpmc_cs_set_reserved(int cs, int reserved)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	gpmc_cs_map &= ~(1 << cs);
> -	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
> +	gpmc->cs_map &= ~(1 << cs);
> +	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
>  
>  	return 0;
>  }
>  
> -int gpmc_cs_reserved(int cs)
> +static int gpmc_cs_reserved(int cs)
>  {
>  	if (cs > GPMC_CS_NUM)
>  		return -ENODEV;
>  
> -	return gpmc_cs_map & (1 << cs);
> +	return gpmc->cs_map & (1 << cs);
>  }
>  
>  static unsigned long gpmc_mem_align(unsigned long size)
> @@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
>  	return size;
>  }
>  
> -static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
> +static __devinit
> +int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
>  {
> -	struct resource	*res = &gpmc_cs_mem[cs];
> +	struct resource	*res = &gpmc->cs_mem[cs];
>  	int r;
>  
>  	size = gpmc_mem_align(size);
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	res->start = base;
>  	res->end = base + size - 1;
> -	r = request_resource(&gpmc_mem_root, res);
> -	spin_unlock(&gpmc_mem_lock);
> +	r = request_resource(&gpmc->mem_root, res);
> +	spin_unlock(&gpmc->mem_lock);
>  
>  	return r;
>  }
>  
>  int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  {
> -	struct resource *res = &gpmc_cs_mem[cs];
> +	struct resource *res = &gpmc->cs_mem[cs];
>  	int r = -1;
>  
>  	if (cs > GPMC_CS_NUM)
> @@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (size > (1 << GPMC_SECTION_SHIFT))
>  		return -ENOMEM;
>  
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (gpmc_cs_reserved(cs)) {
>  		r = -EBUSY;
>  		goto out;
> @@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	if (gpmc_cs_mem_enabled(cs))
>  		r = adjust_resource(res, res->start & ~(size - 1), size);
>  	if (r < 0)
> -		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
> +		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
>  				      size, NULL, NULL);
>  	if (r < 0)
>  		goto out;
> @@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
>  	*base = res->start;
>  	gpmc_cs_set_reserved(cs, 1);
>  out:
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  	return r;
>  }
>  EXPORT_SYMBOL(gpmc_cs_request);
>  
>  void gpmc_cs_free(int cs)
>  {
> -	spin_lock(&gpmc_mem_lock);
> +	spin_lock(&gpmc->mem_lock);
>  	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
>  		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
>  		BUG();
> -		spin_unlock(&gpmc_mem_lock);
> +		spin_unlock(&gpmc->mem_lock);
>  		return;
>  	}
>  	gpmc_cs_disable_mem(cs);
> -	release_resource(&gpmc_cs_mem[cs]);
> +	release_resource(&gpmc->cs_mem[cs]);
>  	gpmc_cs_set_reserved(cs, 0);
> -	spin_unlock(&gpmc_mem_lock);
> +	spin_unlock(&gpmc->mem_lock);
>  }
>  EXPORT_SYMBOL(gpmc_cs_free);
>  
> @@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
>  }
>  EXPORT_SYMBOL(gpmc_prefetch_reset);
>  
> -static void __init gpmc_mem_init(void)
> +static __devinit void gpmc_mem_init(void)
>  {
>  	int cs;
>  	unsigned long boot_rom_space = 0;
> @@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
>  	/* In apollon the CS0 is mapped as 0x0000 0000 */
>  	if (machine_is_omap_apollon())
>  		boot_rom_space = 0;
> -	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
> -	gpmc_mem_root.end = GPMC_MEM_END;
> +	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
> +	gpmc->mem_root.end = GPMC_MEM_END;
>  
>  	/* Reserve all regions that has been set up by bootloader */
>  	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> @@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	u32 l, irq;
> -	int cs, ret = -EINVAL;
> -	int gpmc_irq;
> +	int ret = -EINVAL;
>  	char *ck = NULL;
>  
>  	if (cpu_is_omap24xx()) {
>  		ck = "core_l3_ck";
> -		if (cpu_is_omap2420())
> -			l = OMAP2420_GPMC_BASE;
> -		else
> -			l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap34xx()) {
>  		ck = "gpmc_fck";
> -		l = OMAP34XX_GPMC_BASE;
> -		gpmc_irq = INT_34XX_GPMC_IRQ;
>  	} else if (cpu_is_omap44xx()) {
>  		ck = "gpmc_ck";
> -		l = OMAP44XX_GPMC_BASE;
> -		gpmc_irq = OMAP44XX_IRQ_GPMC;
>  	}
>  
>  	if (WARN_ON(!ck))
> @@ -728,53 +863,607 @@ static int __init gpmc_init(void)
>  		BUG();
>  	}
>  
> -	gpmc_base = ioremap(l, SZ_4K);
> -	if (!gpmc_base) {
> -		clk_put(gpmc_l3_clk);
> -		printk(KERN_ERR "Could not get GPMC register memory\n");
> -		BUG();
> +	clk_enable(gpmc_l3_clk);
> +
> +	return 0;
> +}
> +postcore_initcall(gpmc_init);
> +
> +static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	return gpmc->waitpin_map & (0x1 << waitpin);
> +}
> +
> +static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	gpmc->waitpin_map &= ~(0x1 << waitpin);
> +	gpmc->waitpin_map |= (0x1 << waitpin);
> +}
> +
> +static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
> +{
> +	if (!(waitpin < GPMC_NR_WAITPIN))
> +		return -ENODEV;
> +
> +	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
> +		return -EBUSY;
> +	else
> +		gpmc_reserve_waitpin(gpmc, waitpin);
> +
> +	return 0;
> +}
> +
> +static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
> +{
> +	int ret;
> +
> +	if (!gd->have_waitpin)
> +		return 0;
> +
> +	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
> +		return ret;
> +	} else if (gd->waitpin_polarity) {
> +		u32 l = gpmc_read_reg(GPMC_CONFIG);
> +		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
> +
> +		if (gd->waitpin_polarity == HIGH)
> +			l |= 1 << shift;
> +		else
> +			l &= ~(1 << shift);
> +
> +		gpmc_write_reg(GPMC_CONFIG, l);
>  	}
> +	return 0;
> +}
>  
> -	clk_enable(gpmc_l3_clk);
> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}
>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}
>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {
> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {
> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}

I am not sure about the above code. What happens if a device has
multiple CS signals and uses multiple wait signals?

I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
cannot be combined. I think that it would be a fair assumption to make
that anyone using the waitpin does so inconjunction with the CS (I think
that they would have too).

However, if there is a reason for splitting it up this way please
explain why.

> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
> +		GPMC_CONFIG1_MUXADDDATA |
> +		GPMC_CONFIG1_DEVICETYPE(~0) |
> +		GPMC_CONFIG1_DEVICESIZE(~0) |
> +		GPMC_CONFIG1_WAIT_WRITE_MON |
> +		GPMC_CONFIG1_WAIT_READ_MON |
> +		GPMC_CONFIG1_PAGE_LEN(~0) |
> +		GPMC_CONFIG1_WRITETYPE_SYNC |
> +		GPMC_CONFIG1_WRITEMULTIPLE |
> +		GPMC_CONFIG1_READTYPE_SYNC |
> +		GPMC_CONFIG1_READMULTIPLE |
> +		GPMC_CONFIG1_WRAPBURST |
> +		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
> +		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
> +
> +	if (conf & GPMC_TIMEPARAGRANULARITY)
> +		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
> +	if (conf & GPMC_MUXADDDATA)
> +		l |= GPMC_CONFIG1_MUXADDDATA;
> +	if (conf & GPMC_DEVICETYPE_NAND)
> +		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
> +	if (conf & GPMC_DEVICESIZE_16)
> +		l |= GPMC_CONFIG1_DEVICESIZE_16;
> +	if (conf & GPMC_WAIT_WRITE_MON)
> +		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
> +	if (conf & GPMC_WAIT_READ_MON)
> +		l |= GPMC_CONFIG1_WAIT_READ_MON;
> +	if (conf & GPMC_PAGE_LEN_16)
> +		l |= GPMC_CONFIG1_PAGE_LEN_16;
> +	else if (conf & GPMC_PAGE_LEN_8)
> +		l |= GPMC_CONFIG1_PAGE_LEN_8;
> +	if (conf & GPMC_WRITETYPE_SYNC)
> +		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
> +	if (conf & GPMC_WRITEMULTIPLE)
> +		l |= GPMC_CONFIG1_WRITEMULTIPLE;
> +	if (conf & GPMC_READTYPE_SYNC)
> +		l |= GPMC_CONFIG1_READTYPE_SYNC;
> +	if (conf & GPMC_READMULTIPLE)
> +		l |= GPMC_CONFIG1_READMULTIPLE;
> +	if (conf & GPMC_WRAPBURST)
> +		l |= GPMC_CONFIG1_WRAPBURST;
> +	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
> +	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
> +		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
> +	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
> +	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
> +		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
> +
> +	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +
> +	if (conf & GPMC_WRITEPROTECT)
> +		gpmc->wp = true;
> +}
> +
> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)

The name of this function is not 100% clear to me. What do you mean by
"nonres"?

> +{
> +	int ret;
> +
> +	/* some boards rely on bootloader for configuration */
> +	if (cs->have_config) {
> +		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
> +		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
> +
> +	if (cs->timing) {
> +		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
> +		if (IS_ERR_VALUE(ret)) {
> +			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
> +			return ret;
> +		}
> +	} else
> +		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
> +
> +	return 0;
> +}
> +
> +static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
> +{
> +	int i;
> +	struct gpmc_device *gd;
> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (!strcmp(gd->name, name) && gd->id == id)
> +			return i;
> +
> +	return -ENOENT;
> +}
> +
> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)

What scenario is this function used in? May be worth adding a comment
about the function.

> +{
> +	int i;
> +
> +	i = gpmc_match_device(gpmc, name, id);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
> +		return i;
> +	}
> +
> +	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
> +	if (IS_ERR_VALUE(i)) {
> +		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
> +		return i;
> +	}
> +
> +	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
> +
> +}
> +EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
> +
> +static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
> +{
> +	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
> +		return GPMC_IRQ_FIFOEVENTENABLE;
> +	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
> +		return GPMC_IRQ_COUNT_EVENT;
> +	else
> +		return 0;
> +}
> +
> +static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int i, n;
> +
> +	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
> +		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
> +			res[n].start = res[n].end = gpmc->irq[i].irq;
> +			res[n].flags = IORESOURCE_IRQ;
> +			dev_info(gpmc->dev, "irq %u on CS %d\n",
> +						res[n].start, cs->cs);
> +			n++;
> +		}
> +
> +	return n;
> +}
> +
> +static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	unsigned long start;
> +	int ret;
> +
> +	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
> +		return ret;
> +	}
> +
> +	res->start = start + cs->mem_offset;
> +	res->end = res->start + cs->mem_size - 1;
> +	res->flags = IORESOURCE_MEM;
> +
> +	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
> +							res->end, cs->cs);
> +
> +	return 1;
> +}
> +
> +static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
> +			struct gpmc_cs_data *cs, struct resource *res)
> +{
> +	int num, ret;
> +
> +	num = gpmc_setup_cs_mem(gpmc, cs, res);
> +	if (IS_ERR_VALUE(num))
> +		return num;
> +
> +	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
> +	if (IS_ERR_VALUE(ret))
> +		return ret;
> +
> +	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
> +
> +	return num;
> +}
> +
> +static __devinit int gpmc_setup_device(struct gpmc *gpmc,
> +		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
> +{
> +	int i, n, ret;
> +	struct gpmc_cs_data *cs;
> +
> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> +				i < gdp->num_cs; i++, cs++)
> +		n += hweight32(cs->irq_config);

As you know I am not a fan of these overloaded for-loops as I find them
hard to read ;-)

Why not ...

n = gdp->num_cs;
cs = gdp->cs_data;

/* Calculate total number of irqs used by device */	
for (i = 0, i < gdp->num_cs; i++)
	n += hweight32(cs[i].irq_flags & GPMC_IRQ_MASK);

> +	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
> +								GFP_KERNEL);
> +	if (gd->gpmc_res == NULL) {
> +		dev_err(gpmc->dev, "error: memory allocation\n");
> +		return -ENOMEM;
> +	}
> +
> +	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
> +			i < gdp->num_cs; cs++, i++) {

By the way, if you make the above change, you can also remove "cs =
gdp->cs_data" from this for-loop as it is already initialised.

> +		ret = gpmc_setup_cs(gpmc, gd, cs,
> +					gd->gpmc_res + gd->gpmc_res_cnt);
> +		if (IS_ERR_VALUE(ret) ||
> +				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {

May be consider moving gpmc_setup_waitpin into gpmc_setup_cs as it makes
sense that it is part of the cs setup.

> +			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
> +			devm_kfree(gpmc->dev, gd->gpmc_res);
> +			gd->gpmc_res = NULL;
> +			gd->gpmc_res_cnt = 0;
> +			return -EINVAL;
> +		} else
> +			gd->gpmc_res_cnt += ret;
> +	}
> +
> +	gd->name = gdp->name;
> +	gd->id = gdp->id;
> +	gd->pdata = gdp->pdata;
> +	gd->pdata_size = gdp->pdata_size;
> +	gd->per_res = gdp->per_res;
> +	gd->per_res_cnt = gdp->per_res_cnt;
> +
> +	return 0;
> +}
> +
> +static __devinit
> +struct platform_device *gpmc_create_device(struct gpmc *gpmc,
> +					struct gpmc_device *p)
> +{
> +	int num = p->per_res_cnt + p->gpmc_res_cnt;
> +	struct resource *res;
> +	struct platform_device *pdev;
> +
> +	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
> +								GFP_KERNEL);
> +	if (!res) {
> +		dev_err(gpmc->dev, "error: allocating memory\n");
> +		return NULL;
> +	}
> +
> +	memcpy((char *)res, (const char *) p->gpmc_res,
> +				sizeof(struct resource) * p->gpmc_res_cnt);
> +	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
> +				sizeof(struct resource) * p->per_res_cnt);
> +
> +	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
> +					res, num, p->pdata, p->pdata_size);
> +
> +	devm_kfree(gpmc->dev, res);
> +
> +	return pdev;
>  }
> -postcore_initcall(gpmc_init);
>  
>  static irqreturn_t gpmc_handle_irq(int irq, void *dev)
>  {
> -	u8 cs;
> +	int i;
> +	u32 regval;
> +	struct gpmc *gpmc = dev;
> +
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
>  
> -	/* check cs to invoke the irq */
> -	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
> -	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
> -		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (regval & gpmc->irq[i].bitmask)
> +			generic_handle_irq(gpmc->irq[i].irq);
> +
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
>  
>  	return IRQ_HANDLED;
>  }
>  
> +static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
> +{
> +	int i;
> +	u32 regval;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++)
> +		if (irq == gpmc->irq[i].irq) {
> +			regval = gpmc_read_reg(GPMC_IRQENABLE);
> +			if (endis)
> +				regval |= gpmc->irq[i].bitmask;
> +			else
> +				regval &= ~gpmc->irq[i].bitmask;
> +			gpmc_write_reg(GPMC_IRQENABLE, regval);
> +			break;
> +		}
> +
> +	return 0;
> +}
> +
> +static void gpmc_irq_disable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
> +}
> +
> +static void gpmc_irq_enable(struct irq_data *p)
> +{
> +	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
> +}
> +
> +static void gpmc_irq_noop(struct irq_data *data) { }
> +
> +static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
> +
> +static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +	u32 regval;
> +
> +	if (!gpmc->master_irq)
> +		return -EINVAL;
> +
> +	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
> +	if (IS_ERR_VALUE(gpmc->irq_start)) {
> +		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
> +		return gpmc->irq_start;
> +	}
> +
> +	gpmc->irq_chip.name = "gpmc";
> +	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
> +	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
> +	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
> +	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
> +	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
> +
> +	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
> +	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		gpmc->irq[i].irq = gpmc->irq_start + i;
> +		irq_set_chip_and_handler(gpmc->irq[i].irq,
> +					&gpmc->irq_chip, handle_simple_irq);
> +		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
> +		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
> +	}
> +
> +	/* Disable interrupts */
> +	gpmc_write_reg(GPMC_IRQENABLE, 0);
> +
> +	/* clear interrupts */
> +	regval = gpmc_read_reg(GPMC_IRQSTATUS);
> +	gpmc_write_reg(GPMC_IRQSTATUS, regval);
> +
> +	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
> +							"gpmc", gpmc);
> +}
> +
> +static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
> +{
> +	u32 l;
> +
> +	l = gpmc_read_reg(GPMC_CONFIG);
> +	if (gpmc->wp == true) {
> +		l &= ~GPMC_CONFIG_WRITEPROTECT;
> +		dev_info(gpmc->dev, "write protect enabled\n");
> +	} else
> +		l |= GPMC_CONFIG_WRITEPROTECT;
> +	gpmc_write_reg(GPMC_CONFIG, l);
> +}
> +
> +static __devinit int gpmc_probe(struct platform_device *pdev)
> +{
> +	u32 l;
> +	int i;
> +	int ret = 0;
> +	struct resource *res = NULL;
> +	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
> +	struct gpmc_device_pdata **gdq = NULL;
> +	struct gpmc_device *gd = NULL;
> +
> +	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
> +	if (gpmc == NULL)
> +		return -ENOMEM;
> +
> +	gpmc->dev = &pdev->dev;
> +	gpmc->clk_prd = gp->clk_prd;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (res == NULL)
> +		return -ENOENT;
> +
> +	gpmc->phys_base = res->start;
> +	gpmc->memsize = resource_size(res);
> +
> +	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
> +	if (!gpmc->io_base)
> +		return -EADDRNOTAVAIL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (res == NULL)
> +		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
> +	else
> +		gpmc->master_irq = res->start;
> +
> +	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
> +		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
> +
> +	gpmc->ecc_used = -EINVAL;
> +	spin_lock_init(&gpmc->mem_lock);
> +	platform_set_drvdata(pdev, gpmc);
> +
> +	l = gpmc_read_reg(GPMC_REVISION);
> +	gpmc->revision = (l >> 4) & 0xf;
> +	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
> +
> +	gpmc_mem_init();
> +
> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> +			(i < gp->num_device) && (*gdq); i++, gdq++) {

You have num_devices now and so do you really need the "&& (*gdq)"?
Seems redundant.

> +		ret = gpmc_setup_device(gpmc, gd, *gdq);

gdp[i]

> +		if (IS_ERR_VALUE(ret))
> +			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
> +								(*gdq)->name);
> +		else
> +			gd++;
> +	}
> +	gpmc->num_device = gd - gpmc->device;
> +
> +	gpmc_setup_writeprotect(gpmc);

Write protect is a pin and there is only one. Like the waitpins and CS
signals this needs to be associated with a device. It would make sense
that this is associated with the cs data.

> +
> +	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
> +		if (IS_ERR(gpmc_create_device(gpmc, gd)))
> +			dev_err(gpmc->dev, "device creation on %s failed\n",
> +								gd->name);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_free_irq(struct gpmc *gpmc)
> +{
> +	int i;
> +
> +	if (gpmc->master_irq)
> +		free_irq(gpmc->master_irq, gpmc);
> +
> +	for (i = 0; i < GPMC_NR_IRQ; i++) {
> +		irq_set_handler(gpmc->irq[i].irq, NULL);
> +		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
> +		irq_set_chip_data(gpmc->irq[i].irq, NULL);
> +		irq_modify_status(gpmc->irq[i].irq, 0, 0);
> +	}
> +
> +	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
> +
> +	return 0;
> +}
> +
> +static __devexit int gpmc_remove(struct platform_device *pdev)
> +{
> +	struct gpmc *gpmc = platform_get_drvdata(pdev);
> +
> +	platform_set_drvdata(pdev, NULL);
> +	gpmc_free_irq(gpmc);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver gpmc_driver = {
> +	.probe		= gpmc_probe,
> +	.remove		= __devexit_p(gpmc_remove),
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +module_platform_driver(gpmc_driver);
> +
>  #ifdef CONFIG_ARCH_OMAP3
>  static struct omap3_gpmc_regs gpmc_context;
>  
> @@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
>  	unsigned int val;
>  
>  	/* check if ecc module is in used */
> -	if (gpmc_ecc_used != -EINVAL)
> +	if (gpmc->ecc_used != -EINVAL)
>  		return -EINVAL;
>  
> -	gpmc_ecc_used = cs;
> +	gpmc->ecc_used = cs;
>  
>  	/* clear ecc and enable bits */
>  	val = ((0x00000001<<8) | 0x00000001);
> @@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  {
>  	unsigned int val = 0x0;
>  
> -	if (gpmc_ecc_used != cs)
> +	if (gpmc->ecc_used != cs)
>  		return -EINVAL;
>  
>  	/* read ecc result */
> @@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
>  	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
>  	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
>  
> -	gpmc_ecc_used = -EINVAL;
> +	gpmc->ecc_used = -EINVAL;
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 1527929..2eedd99 100644
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -11,6 +11,44 @@
>  #ifndef __OMAP2_GPMC_H
>  #define __OMAP2_GPMC_H
>  
> +/* configuration flags */
> +#define	GPMC_WRITEPROTECT		BIT(0)
> +#define	GPMC_TIMEPARAGRANULARITY	BIT(1)
> +#define	GPMC_MUXADDDATA			BIT(2)
> +#define	GPMC_DEVICETYPE_NOR		BIT(3)
> +#define	GPMC_DEVICETYPE_NAND		BIT(4)
> +#define	GPMC_DEVICESIZE_8		BIT(5)
> +#define	GPMC_DEVICESIZE_16		BIT(6)
> +#define	GPMC_WAIT_WRITE_MON		BIT(7)
> +#define	GPMC_WAIT_READ_MON		BIT(8)
> +#define	GPMC_PAGE_LEN_4			BIT(9)
> +#define	GPMC_PAGE_LEN_8			BIT(10)
> +#define	GPMC_PAGE_LEN_16		BIT(11)
> +#define	GPMC_CLOCKACTIVATIONTIME_0	BIT(12)
> +#define	GPMC_CLOCKACTIVATIONTIME_1	BIT(13)
> +#define	GPMC_CLOCKACTIVATIONTIME_2	BIT(14)
> +#define	GPMC_WRITETYPE_SYNC		BIT(15)
> +#define	GPMC_WRITEMULTIPLE		BIT(16)
> +#define	GPMC_READTYPE_SYNC		BIT(17)
> +#define	GPMC_READMULTIPLE		BIT(18)
> +#define	GPMC_WRAPBURST			BIT(19)
> +#define	GPMC_WAITPIN_0			BIT(20)
> +#define	GPMC_WAITPIN_1			BIT(21)
> +#define	GPMC_WAITPIN_2			BIT(22)
> +#define	GPMC_WAITPIN_3			BIT(23)
> +#define	GPMC_WAITPIN_MASK		(GPMC_WAITPIN_0 | GPMC_WAITPIN_1 | \
> +					GPMC_WAITPIN_2 | GPMC_WAITPIN_3)
> +#define	GPMC_WAITPIN_ACTIVE_LOW		BIT(24)
> +#define	GPMC_WAITPIN_ACTIVE_HIGH	BIT(25)
> +#define	GPMC_WAITPIN_POLARITY_MASK	(GPMC_WAITPIN_ACTIVE_LOW | \
> +					GPMC_WAITPIN_ACTIVE_HIGH)
> +#define	GPMC_WAITPIN_MONITOR_TIME_1	BIT(26)
> +#define	GPMC_WAITPIN_MONITOR_TIME_2	BIT(27)
> +#define	GPMC_CLOCKACTIVATION_TIME_1	BIT(28)
> +#define	GPMC_CLOCKACTIVATION_TIME_2	BIT(29)
> +#define	GPMC_READTYPE_ASYNC		BIT(30)
> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> +

Please keep in mind that eventually this has to all be moved into device
tree and so at that point these configuration flags will have to be
re-worked. However, just a FYI.

Cheers
Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-01 12:19   ` Afzal Mohammed
  (?)
@ 2012-05-01 20:41     ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 20:41 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Create API for platforms to adapt gpmc to HWMOD
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
>  arch/arm/plat-omap/include/plat/gpmc.h |    1 +
>  2 files changed, 38 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 12916f3..c8d07bb 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -33,6 +33,8 @@
>  
>  #include <plat/sdrc.h>
>  
> +#include <plat/omap_device.h>
> +
>  /* GPMC register offsets */
>  #define GPMC_REVISION		0x00
>  #define GPMC_SYSCONFIG		0x10
> @@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
>  	return ticks * gpmc_get_fclk_period() / 1000;
>  }
>  
> +int __init omap_init_gpmc(struct gpmc_pdata *pdata)
> +{
> +	struct omap_hwmod *oh;
> +	struct platform_device *pdev;
> +	char *name = "omap-gpmc";
> +	char *oh_name = "gpmc";
> +
> +	pdata->clk_prd = gpmc_get_fclk_period();

Does this need to be done here? May be this should be done in the probe
function. You could store the handle to the main clk in the pdata.

> +
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
> +
> +	pdev = omap_device_build(name, -1, oh, pdata,
> +					sizeof(*pdata), NULL, 0, 0);
> +	if (IS_ERR(pdev)) {
> +		WARN(1, "Can't build omap_device for %s:%s.\n",
> +						name, oh->name);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	return 0;
> +}
>  #ifdef DEBUG
>  static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  			       int time, const char *name)
> @@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	int ret = -EINVAL;
> -	char *ck = NULL;
> -
> -	if (cpu_is_omap24xx()) {
> -		ck = "core_l3_ck";
> -	} else if (cpu_is_omap34xx()) {
> -		ck = "gpmc_fck";
> -	} else if (cpu_is_omap44xx()) {
> -		ck = "gpmc_ck";
> -	}
> +	char *oh_name = "gpmc";
> +	struct omap_hwmod *oh;
>  
> -	if (WARN_ON(!ck))
> -		return ret;
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
>  
> -	gpmc_l3_clk = clk_get(NULL, ck);
> +	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
>  	if (IS_ERR(gpmc_l3_clk)) {
> -		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
> -		BUG();
> +		pr_err("error: clk_get on %s\n", oh->main_clk);
> +		return -EINVAL;
>  	}
>  
>  	clk_enable(gpmc_l3_clk);

I would have thought we should be able to remove the gpmc_init function
completely by now. Most of the code should be moved to the probe function.

Also now with hwmod in place, we should be able to remove the
clk_enable/disable functions and use the pm_runtime APIs instead.

Cheers
Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-01 20:41     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 20:41 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, vimal.newwork, grinberg, artem.bityutskiy,
	linux-mtd, linux-omap, dwmw2, linux-arm-kernel, notasas

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Create API for platforms to adapt gpmc to HWMOD
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
>  arch/arm/plat-omap/include/plat/gpmc.h |    1 +
>  2 files changed, 38 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 12916f3..c8d07bb 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -33,6 +33,8 @@
>  
>  #include <plat/sdrc.h>
>  
> +#include <plat/omap_device.h>
> +
>  /* GPMC register offsets */
>  #define GPMC_REVISION		0x00
>  #define GPMC_SYSCONFIG		0x10
> @@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
>  	return ticks * gpmc_get_fclk_period() / 1000;
>  }
>  
> +int __init omap_init_gpmc(struct gpmc_pdata *pdata)
> +{
> +	struct omap_hwmod *oh;
> +	struct platform_device *pdev;
> +	char *name = "omap-gpmc";
> +	char *oh_name = "gpmc";
> +
> +	pdata->clk_prd = gpmc_get_fclk_period();

Does this need to be done here? May be this should be done in the probe
function. You could store the handle to the main clk in the pdata.

> +
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
> +
> +	pdev = omap_device_build(name, -1, oh, pdata,
> +					sizeof(*pdata), NULL, 0, 0);
> +	if (IS_ERR(pdev)) {
> +		WARN(1, "Can't build omap_device for %s:%s.\n",
> +						name, oh->name);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	return 0;
> +}
>  #ifdef DEBUG
>  static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  			       int time, const char *name)
> @@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	int ret = -EINVAL;
> -	char *ck = NULL;
> -
> -	if (cpu_is_omap24xx()) {
> -		ck = "core_l3_ck";
> -	} else if (cpu_is_omap34xx()) {
> -		ck = "gpmc_fck";
> -	} else if (cpu_is_omap44xx()) {
> -		ck = "gpmc_ck";
> -	}
> +	char *oh_name = "gpmc";
> +	struct omap_hwmod *oh;
>  
> -	if (WARN_ON(!ck))
> -		return ret;
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
>  
> -	gpmc_l3_clk = clk_get(NULL, ck);
> +	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
>  	if (IS_ERR(gpmc_l3_clk)) {
> -		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
> -		BUG();
> +		pr_err("error: clk_get on %s\n", oh->main_clk);
> +		return -EINVAL;
>  	}
>  
>  	clk_enable(gpmc_l3_clk);

I would have thought we should be able to remove the gpmc_init function
completely by now. Most of the code should be moved to the probe function.

Also now with hwmod in place, we should be able to remove the
clk_enable/disable functions and use the pm_runtime APIs instead.

Cheers
Jon

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-01 20:41     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 20:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:
> Create API for platforms to adapt gpmc to HWMOD
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
>  arch/arm/plat-omap/include/plat/gpmc.h |    1 +
>  2 files changed, 38 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 12916f3..c8d07bb 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -33,6 +33,8 @@
>  
>  #include <plat/sdrc.h>
>  
> +#include <plat/omap_device.h>
> +
>  /* GPMC register offsets */
>  #define GPMC_REVISION		0x00
>  #define GPMC_SYSCONFIG		0x10
> @@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
>  	return ticks * gpmc_get_fclk_period() / 1000;
>  }
>  
> +int __init omap_init_gpmc(struct gpmc_pdata *pdata)
> +{
> +	struct omap_hwmod *oh;
> +	struct platform_device *pdev;
> +	char *name = "omap-gpmc";
> +	char *oh_name = "gpmc";
> +
> +	pdata->clk_prd = gpmc_get_fclk_period();

Does this need to be done here? May be this should be done in the probe
function. You could store the handle to the main clk in the pdata.

> +
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
> +
> +	pdev = omap_device_build(name, -1, oh, pdata,
> +					sizeof(*pdata), NULL, 0, 0);
> +	if (IS_ERR(pdev)) {
> +		WARN(1, "Can't build omap_device for %s:%s.\n",
> +						name, oh->name);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	return 0;
> +}
>  #ifdef DEBUG
>  static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
>  			       int time, const char *name)
> @@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
>  
>  static int __init gpmc_init(void)
>  {
> -	int ret = -EINVAL;
> -	char *ck = NULL;
> -
> -	if (cpu_is_omap24xx()) {
> -		ck = "core_l3_ck";
> -	} else if (cpu_is_omap34xx()) {
> -		ck = "gpmc_fck";
> -	} else if (cpu_is_omap44xx()) {
> -		ck = "gpmc_ck";
> -	}
> +	char *oh_name = "gpmc";
> +	struct omap_hwmod *oh;
>  
> -	if (WARN_ON(!ck))
> -		return ret;
> +	oh = omap_hwmod_lookup(oh_name);
> +	if (!oh) {
> +		pr_err("Could not look up %s\n", oh_name);
> +		return -ENODEV;
> +	}
>  
> -	gpmc_l3_clk = clk_get(NULL, ck);
> +	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
>  	if (IS_ERR(gpmc_l3_clk)) {
> -		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
> -		BUG();
> +		pr_err("error: clk_get on %s\n", oh->main_clk);
> +		return -EINVAL;
>  	}
>  
>  	clk_enable(gpmc_l3_clk);

I would have thought we should be able to remove the gpmc_init function
completely by now. Most of the code should be moved to the probe function.

Also now with hwmod in place, we should be able to remove the
clk_enable/disable functions and use the pm_runtime APIs instead.

Cheers
Jon

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

* Re: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-01 12:20   ` Afzal Mohammed
  (?)
@ 2012-05-01 21:16     ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 21:16 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd

Hi Afzal,

On 05/01/2012 07:20 AM, Afzal Mohammed wrote:
> Some boards depend on bootloader to update chip select value for NAND.
> It is felt that Kernel should not depend on bootloader to get CS, as
> for a particular board CS is hardwired and is fixed, hence this can
> directly be updated in Kernel. But as CS value for boards that depend
> on this behaviour is not available, educate gpmc driver to acquire
> chip select value for NAND. this ideally should be removed once CS
> for those boards are available.

Do you know how many boards require this? If so which are those boards?

> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 657ce95..ecd3384 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -892,6 +892,30 @@ static int __init gpmc_init(void)
>  }
>  postcore_initcall(gpmc_init);
>  
> +static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
> +					struct gpmc_device_pdata *gdp)
> +{
> +	int cs = 0;
> +	struct omap_nand_platform_data *nand = gdp->pdata;
> +
> +	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
> +		return 0;
> +
> +	while (cs < GPMC_CS_NUM) {
> +		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
> +				GPMC_CONFIG1_DEVICETYPE_NAND) {
> +			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
> +			nand->cs = cs;
> +			gdp->cs_data->cs = cs;
> +			return 0;
> +		}
> +		cs++;
> +	}
> +	return -ENODEV;
> +}
> +
>  static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
>  				struct omap_nand_platform_data *nand)
>  {
> @@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
>  
>  	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>  			(i < gp->num_device) && (*gdq); i++, gdq++) {
> -		if ((*gdq)->is_nand)
> +		if ((*gdq)->is_nand) {
> +			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
> +			if (IS_ERR_VALUE(ret)) {
> +				dev_err(gpmc->dev, "CS error: %d\n", ret);
> +				continue;
> +			}

Should this code be marked with a FIXME?

Cheers
Jon

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

* Re: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-01 21:16     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 21:16 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, vimal.newwork, grinberg, artem.bityutskiy,
	linux-mtd, linux-omap, dwmw2, linux-arm-kernel, notasas

Hi Afzal,

On 05/01/2012 07:20 AM, Afzal Mohammed wrote:
> Some boards depend on bootloader to update chip select value for NAND.
> It is felt that Kernel should not depend on bootloader to get CS, as
> for a particular board CS is hardwired and is fixed, hence this can
> directly be updated in Kernel. But as CS value for boards that depend
> on this behaviour is not available, educate gpmc driver to acquire
> chip select value for NAND. this ideally should be removed once CS
> for those boards are available.

Do you know how many boards require this? If so which are those boards?

> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 657ce95..ecd3384 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -892,6 +892,30 @@ static int __init gpmc_init(void)
>  }
>  postcore_initcall(gpmc_init);
>  
> +static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
> +					struct gpmc_device_pdata *gdp)
> +{
> +	int cs = 0;
> +	struct omap_nand_platform_data *nand = gdp->pdata;
> +
> +	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
> +		return 0;
> +
> +	while (cs < GPMC_CS_NUM) {
> +		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
> +				GPMC_CONFIG1_DEVICETYPE_NAND) {
> +			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
> +			nand->cs = cs;
> +			gdp->cs_data->cs = cs;
> +			return 0;
> +		}
> +		cs++;
> +	}
> +	return -ENODEV;
> +}
> +
>  static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
>  				struct omap_nand_platform_data *nand)
>  {
> @@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
>  
>  	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>  			(i < gp->num_device) && (*gdq); i++, gdq++) {
> -		if ((*gdq)->is_nand)
> +		if ((*gdq)->is_nand) {
> +			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
> +			if (IS_ERR_VALUE(ret)) {
> +				dev_err(gpmc->dev, "CS error: %d\n", ret);
> +				continue;
> +			}

Should this code be marked with a FIXME?

Cheers
Jon

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

* [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-01 21:16     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-01 21:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/01/2012 07:20 AM, Afzal Mohammed wrote:
> Some boards depend on bootloader to update chip select value for NAND.
> It is felt that Kernel should not depend on bootloader to get CS, as
> for a particular board CS is hardwired and is fixed, hence this can
> directly be updated in Kernel. But as CS value for boards that depend
> on this behaviour is not available, educate gpmc driver to acquire
> chip select value for NAND. this ideally should be removed once CS
> for those boards are available.

Do you know how many boards require this? If so which are those boards?

> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> ---
>  arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 657ce95..ecd3384 100644
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -892,6 +892,30 @@ static int __init gpmc_init(void)
>  }
>  postcore_initcall(gpmc_init);
>  
> +static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
> +					struct gpmc_device_pdata *gdp)
> +{
> +	int cs = 0;
> +	struct omap_nand_platform_data *nand = gdp->pdata;
> +
> +	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
> +		return 0;
> +
> +	while (cs < GPMC_CS_NUM) {
> +		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +
> +		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
> +				GPMC_CONFIG1_DEVICETYPE_NAND) {
> +			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
> +			nand->cs = cs;
> +			gdp->cs_data->cs = cs;
> +			return 0;
> +		}
> +		cs++;
> +	}
> +	return -ENODEV;
> +}
> +
>  static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
>  				struct omap_nand_platform_data *nand)
>  {
> @@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
>  
>  	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>  			(i < gp->num_device) && (*gdq); i++, gdq++) {
> -		if ((*gdq)->is_nand)
> +		if ((*gdq)->is_nand) {
> +			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
> +			if (IS_ERR_VALUE(ret)) {
> +				dev_err(gpmc->dev, "CS error: %d\n", ret);
> +				continue;
> +			}

Should this code be marked with a FIXME?

Cheers
Jon

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-01 17:53         ` Jon Hunter
  (?)
@ 2012-05-03  8:23             ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:23 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hire

Hi Jon,

On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
> Hi Afzal,
> 
> Looks good! Some minor comments ...

Thanks

> > +#define	GPMC_WAITPIN_IDX0			0x0
> > +#define	GPMC_WAITPIN_IDX1			0x1
> > +#define	GPMC_WAITPIN_IDX2			0x2
> > +#define	GPMC_WAITPIN_IDX3			0x3
> > +#define	GPMC_NR_WAITPIN				0x4
> 
> How about an enum here? Also OMAP4 only have 3 wait pins and so the
> number is device dependent.

Ok

> 
> >  #define GPMC_MEM_START		0x00000000
> >  #define GPMC_MEM_END		0x3FFFFFFF
> >  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> > @@ -64,6 +106,55 @@
> >  #define ENABLE_PREFETCH		(0x1 << 7)
> >  #define DMA_MPU_MODE		2
> >  
> > +#define	DRIVER_NAME	"omap-gpmc"
> > +
> > +#define	GPMC_NR_IRQ		2
> 
> Why has this been changed to 2? It was 6 in the previous version. As we
> discussed before the number of IRQs should be detected based upon GPMC
> IP version.

As mentioned in the cover letter,

"Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated."

Priority in this series is to convert into a driver, get all boards working
on mainline. Once all boards are working with gpmc driver, these features
which are not required for currently supported boards can be added later.

> > +struct gpmc_device {
> > +	char			*name;
> > +	int			id;
> > +	void			*pdata;
> > +	unsigned		pdata_size;
> > +	struct resource		*per_res;
> > +	unsigned		per_res_cnt;
> > +	struct resource		*gpmc_res;
> > +	unsigned		gpmc_res_cnt;
> > +	bool			have_waitpin;
> > +	unsigned		waitpin;
> > +	int			waitpin_polarity;
> 
> I think that it make more sense to have the wait-pin information part of
> the gpmc_cs_data structure for the following reasons ...

Waitpin information is indeed a part of cs as far as boards are concerned,
it is only that it gets propogated to device

> 
> 1. If a device can use multiple CS, then it could use multiple wait signals.
> 2. Eventually, all board information needs to move to device tree. By
> having it in the pdata it will be easier to migrate to device tree.
> 
> It may be nice to have "have_waitpin" be an integer too, that indicates
> if wait is used for both read and write or just one or the other.
> 
> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> register for an active low wait signal.

Only intention is not to alter default waitpin polarity value, i.e. if
any board does make use of it w/o knowledge of Kernel, I don't want to
break it, there may be an argument saying that the board code is buggy,
while if some board does so, it is, but don't want to break working one.

Here unless user explicitly set the flag, it does nothing on polarity

> > +	if (idx != ~0x0) {
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> 
> I am not sure about the above code. What happens if a device has
> multiple CS signals and uses multiple wait signals?
> 
> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
> cannot be combined. I think that it would be a fair assumption to make
> that anyone using the waitpin does so inconjunction with the CS (I think
> that they would have too).
> 
> However, if there is a reason for splitting it up this way please
> explain why.

Initially it was done per CS, the problem happened while trying to
convert tusb6010. It had multiple CS, but using same waitpin. Problem
with incorporating this onto CS is we have to sacrifice on wait pin
conflict prevention capability. The code now handles case of wait pin
conflict per device, the code can be extended to have multiple
wait pin per device also. But I prefer to defer it to later, not as
part of this series, as this feature what you asking for is not required
for any of the existing boards. I can add it in this series if there is
a strong opinion in the community for the same in this series.

Policy that is being followed here is first sit, then straighten legs, ;)

> > +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> > +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
> 
> The name of this function is not 100% clear to me. What do you mean by
> "nonres"?

It means anything other than resources like memory & irq, happened for
want of better name, if you have one, name it, will put it.

> > +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> 
> What scenario is this function used in? May be worth adding a comment
> about the function.

Ok, it was required for OneNAND, as it needs to reconfigure

> > +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> > +				i < gdp->num_cs; i++, cs++)
> > +		n += hweight32(cs->irq_config);
> 
> As you know I am not a fan of these overloaded for-loops as I find them
> hard to read ;-)
> 
> Why not ...
> 
> n = gdp->num_cs;
> cs = gdp->cs_data;


Well, you also know that I am big fan of it; difference of opinion,
my preference is to keep loop control statements together with "for",
unless there is a cry from community that it should not be this way.
I believe that it is not that much unreadable.

> > +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> > +			(i < gp->num_device) && (*gdq); i++, gdq++) {
> 
> You have num_devices now and so do you really need the "&& (*gdq)"?
> Seems redundant.

num_device is something that I never wanted to add, was happy with,
NULL entry termination, only because of your repeated comments,
I added this. And this additional check now prevents NULL dereference.

> > +	gpmc_setup_writeprotect(gpmc);
> 
> Write protect is a pin and there is only one. Like the waitpins and CS
> signals this needs to be associated with a device. It would make sense
> that this is associated with the cs data.

As far as platform are concerned, it is associated with cs, it is only
that while configuring CS, it is propagated such that it is done once.


> > +#define	GPMC_READTYPE_ASYNC		BIT(30)
> > +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> > +
> 
> Please keep in mind that eventually this has to all be moved into device
> tree and so at that point these configuration flags will have to be
> re-worked. However, just a FYI.

On device tree matters, my mind is next to blank, thanks for mentioning it.

Regards
Afzal
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-03  8:23             ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:23 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
> Hi Afzal,
> 
> Looks good! Some minor comments ...

Thanks

> > +#define	GPMC_WAITPIN_IDX0			0x0
> > +#define	GPMC_WAITPIN_IDX1			0x1
> > +#define	GPMC_WAITPIN_IDX2			0x2
> > +#define	GPMC_WAITPIN_IDX3			0x3
> > +#define	GPMC_NR_WAITPIN				0x4
> 
> How about an enum here? Also OMAP4 only have 3 wait pins and so the
> number is device dependent.

Ok

> 
> >  #define GPMC_MEM_START		0x00000000
> >  #define GPMC_MEM_END		0x3FFFFFFF
> >  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> > @@ -64,6 +106,55 @@
> >  #define ENABLE_PREFETCH		(0x1 << 7)
> >  #define DMA_MPU_MODE		2
> >  
> > +#define	DRIVER_NAME	"omap-gpmc"
> > +
> > +#define	GPMC_NR_IRQ		2
> 
> Why has this been changed to 2? It was 6 in the previous version. As we
> discussed before the number of IRQs should be detected based upon GPMC
> IP version.

As mentioned in the cover letter,

"Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated."

Priority in this series is to convert into a driver, get all boards working
on mainline. Once all boards are working with gpmc driver, these features
which are not required for currently supported boards can be added later.

> > +struct gpmc_device {
> > +	char			*name;
> > +	int			id;
> > +	void			*pdata;
> > +	unsigned		pdata_size;
> > +	struct resource		*per_res;
> > +	unsigned		per_res_cnt;
> > +	struct resource		*gpmc_res;
> > +	unsigned		gpmc_res_cnt;
> > +	bool			have_waitpin;
> > +	unsigned		waitpin;
> > +	int			waitpin_polarity;
> 
> I think that it make more sense to have the wait-pin information part of
> the gpmc_cs_data structure for the following reasons ...

Waitpin information is indeed a part of cs as far as boards are concerned,
it is only that it gets propogated to device

> 
> 1. If a device can use multiple CS, then it could use multiple wait signals.
> 2. Eventually, all board information needs to move to device tree. By
> having it in the pdata it will be easier to migrate to device tree.
> 
> It may be nice to have "have_waitpin" be an integer too, that indicates
> if wait is used for both read and write or just one or the other.
> 
> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> register for an active low wait signal.

Only intention is not to alter default waitpin polarity value, i.e. if
any board does make use of it w/o knowledge of Kernel, I don't want to
break it, there may be an argument saying that the board code is buggy,
while if some board does so, it is, but don't want to break working one.

Here unless user explicitly set the flag, it does nothing on polarity

> > +	if (idx != ~0x0) {
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> 
> I am not sure about the above code. What happens if a device has
> multiple CS signals and uses multiple wait signals?
> 
> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
> cannot be combined. I think that it would be a fair assumption to make
> that anyone using the waitpin does so inconjunction with the CS (I think
> that they would have too).
> 
> However, if there is a reason for splitting it up this way please
> explain why.

Initially it was done per CS, the problem happened while trying to
convert tusb6010. It had multiple CS, but using same waitpin. Problem
with incorporating this onto CS is we have to sacrifice on wait pin
conflict prevention capability. The code now handles case of wait pin
conflict per device, the code can be extended to have multiple
wait pin per device also. But I prefer to defer it to later, not as
part of this series, as this feature what you asking for is not required
for any of the existing boards. I can add it in this series if there is
a strong opinion in the community for the same in this series.

Policy that is being followed here is first sit, then straighten legs, ;)

> > +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> > +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
> 
> The name of this function is not 100% clear to me. What do you mean by
> "nonres"?

It means anything other than resources like memory & irq, happened for
want of better name, if you have one, name it, will put it.

> > +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> 
> What scenario is this function used in? May be worth adding a comment
> about the function.

Ok, it was required for OneNAND, as it needs to reconfigure

> > +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> > +				i < gdp->num_cs; i++, cs++)
> > +		n += hweight32(cs->irq_config);
> 
> As you know I am not a fan of these overloaded for-loops as I find them
> hard to read ;-)
> 
> Why not ...
> 
> n = gdp->num_cs;
> cs = gdp->cs_data;


Well, you also know that I am big fan of it; difference of opinion,
my preference is to keep loop control statements together with "for",
unless there is a cry from community that it should not be this way.
I believe that it is not that much unreadable.

> > +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> > +			(i < gp->num_device) && (*gdq); i++, gdq++) {
> 
> You have num_devices now and so do you really need the "&& (*gdq)"?
> Seems redundant.

num_device is something that I never wanted to add, was happy with,
NULL entry termination, only because of your repeated comments,
I added this. And this additional check now prevents NULL dereference.

> > +	gpmc_setup_writeprotect(gpmc);
> 
> Write protect is a pin and there is only one. Like the waitpins and CS
> signals this needs to be associated with a device. It would make sense
> that this is associated with the cs data.

As far as platform are concerned, it is associated with cs, it is only
that while configuring CS, it is propagated such that it is done once.


> > +#define	GPMC_READTYPE_ASYNC		BIT(30)
> > +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> > +
> 
> Please keep in mind that eventually this has to all be moved into device
> tree and so at that point these configuration flags will have to be
> re-worked. However, just a FYI.

On device tree matters, my mind is next to blank, thanks for mentioning it.

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-03  8:23             ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
> Hi Afzal,
> 
> Looks good! Some minor comments ...

Thanks

> > +#define	GPMC_WAITPIN_IDX0			0x0
> > +#define	GPMC_WAITPIN_IDX1			0x1
> > +#define	GPMC_WAITPIN_IDX2			0x2
> > +#define	GPMC_WAITPIN_IDX3			0x3
> > +#define	GPMC_NR_WAITPIN				0x4
> 
> How about an enum here? Also OMAP4 only have 3 wait pins and so the
> number is device dependent.

Ok

> 
> >  #define GPMC_MEM_START		0x00000000
> >  #define GPMC_MEM_END		0x3FFFFFFF
> >  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
> > @@ -64,6 +106,55 @@
> >  #define ENABLE_PREFETCH		(0x1 << 7)
> >  #define DMA_MPU_MODE		2
> >  
> > +#define	DRIVER_NAME	"omap-gpmc"
> > +
> > +#define	GPMC_NR_IRQ		2
> 
> Why has this been changed to 2? It was 6 in the previous version. As we
> discussed before the number of IRQs should be detected based upon GPMC
> IP version.

As mentioned in the cover letter,

"Additional features that currently boards in mainline does not make
use of like, waitpin interrupt handling, changes to leverage revision
6 IP differences has not been incorporated."

Priority in this series is to convert into a driver, get all boards working
on mainline. Once all boards are working with gpmc driver, these features
which are not required for currently supported boards can be added later.

> > +struct gpmc_device {
> > +	char			*name;
> > +	int			id;
> > +	void			*pdata;
> > +	unsigned		pdata_size;
> > +	struct resource		*per_res;
> > +	unsigned		per_res_cnt;
> > +	struct resource		*gpmc_res;
> > +	unsigned		gpmc_res_cnt;
> > +	bool			have_waitpin;
> > +	unsigned		waitpin;
> > +	int			waitpin_polarity;
> 
> I think that it make more sense to have the wait-pin information part of
> the gpmc_cs_data structure for the following reasons ...

Waitpin information is indeed a part of cs as far as boards are concerned,
it is only that it gets propogated to device

> 
> 1. If a device can use multiple CS, then it could use multiple wait signals.
> 2. Eventually, all board information needs to move to device tree. By
> having it in the pdata it will be easier to migrate to device tree.
> 
> It may be nice to have "have_waitpin" be an integer too, that indicates
> if wait is used for both read and write or just one or the other.
> 
> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> register for an active low wait signal.

Only intention is not to alter default waitpin polarity value, i.e. if
any board does make use of it w/o knowledge of Kernel, I don't want to
break it, there may be an argument saying that the board code is buggy,
while if some board does so, it is, but don't want to break working one.

Here unless user explicitly set the flag, it does nothing on polarity

> > +	if (idx != ~0x0) {
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> 
> I am not sure about the above code. What happens if a device has
> multiple CS signals and uses multiple wait signals?
> 
> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
> cannot be combined. I think that it would be a fair assumption to make
> that anyone using the waitpin does so inconjunction with the CS (I think
> that they would have too).
> 
> However, if there is a reason for splitting it up this way please
> explain why.

Initially it was done per CS, the problem happened while trying to
convert tusb6010. It had multiple CS, but using same waitpin. Problem
with incorporating this onto CS is we have to sacrifice on wait pin
conflict prevention capability. The code now handles case of wait pin
conflict per device, the code can be extended to have multiple
wait pin per device also. But I prefer to defer it to later, not as
part of this series, as this feature what you asking for is not required
for any of the existing boards. I can add it in this series if there is
a strong opinion in the community for the same in this series.

Policy that is being followed here is first sit, then straighten legs, ;)

> > +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
> > +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
> 
> The name of this function is not 100% clear to me. What do you mean by
> "nonres"?

It means anything other than resources like memory & irq, happened for
want of better name, if you have one, name it, will put it.

> > +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> 
> What scenario is this function used in? May be worth adding a comment
> about the function.

Ok, it was required for OneNAND, as it needs to reconfigure

> > +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
> > +				i < gdp->num_cs; i++, cs++)
> > +		n += hweight32(cs->irq_config);
> 
> As you know I am not a fan of these overloaded for-loops as I find them
> hard to read ;-)
> 
> Why not ...
> 
> n = gdp->num_cs;
> cs = gdp->cs_data;


Well, you also know that I am big fan of it; difference of opinion,
my preference is to keep loop control statements together with "for",
unless there is a cry from community that it should not be this way.
I believe that it is not that much unreadable.

> > +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
> > +			(i < gp->num_device) && (*gdq); i++, gdq++) {
> 
> You have num_devices now and so do you really need the "&& (*gdq)"?
> Seems redundant.

num_device is something that I never wanted to add, was happy with,
NULL entry termination, only because of your repeated comments,
I added this. And this additional check now prevents NULL dereference.

> > +	gpmc_setup_writeprotect(gpmc);
> 
> Write protect is a pin and there is only one. Like the waitpins and CS
> signals this needs to be associated with a device. It would make sense
> that this is associated with the cs data.

As far as platform are concerned, it is associated with cs, it is only
that while configuring CS, it is propagated such that it is done once.


> > +#define	GPMC_READTYPE_ASYNC		BIT(30)
> > +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
> > +
> 
> Please keep in mind that eventually this has to all be moved into device
> tree and so at that point these configuration flags will have to be
> re-worked. However, just a FYI.

On device tree matters, my mind is next to blank, thanks for mentioning it.

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-01 20:41     ` Jon Hunter
  (?)
@ 2012-05-03  8:37       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:37 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Jon,

On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
> > +
> > +	pdata->clk_prd = gpmc_get_fclk_period();
> 
> Does this need to be done here? May be this should be done in the probe
> function. You could store the handle to the main clk in the pdata.

This is done so that migration of gpmc driver to the drivers folder
would be smooth, remember that this function will still live here.
 
> > +		pr_err("error: clk_get on %s\n", oh->main_clk);
> > +		return -EINVAL;
> >  	}
> >  
> >  	clk_enable(gpmc_l3_clk);
> 
> I would have thought we should be able to remove the gpmc_init function
> completely by now. Most of the code should be moved to the probe function.
> 
> Also now with hwmod in place, we should be able to remove the
> clk_enable/disable functions and use the pm_runtime APIs instead.

There was no plan to add rpm in this series, but now that you have
brought it up, I will adapt the driver to rpm.

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-03  8:37       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:37 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Jon,

On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
> > +
> > +	pdata->clk_prd = gpmc_get_fclk_period();
> 
> Does this need to be done here? May be this should be done in the probe
> function. You could store the handle to the main clk in the pdata.

This is done so that migration of gpmc driver to the drivers folder
would be smooth, remember that this function will still live here.
 
> > +		pr_err("error: clk_get on %s\n", oh->main_clk);
> > +		return -EINVAL;
> >  	}
> >  
> >  	clk_enable(gpmc_l3_clk);
> 
> I would have thought we should be able to remove the gpmc_init function
> completely by now. Most of the code should be moved to the probe function.
> 
> Also now with hwmod in place, we should be able to remove the
> clk_enable/disable functions and use the pm_runtime APIs instead.

There was no plan to add rpm in this series, but now that you have
brought it up, I will adapt the driver to rpm.

Regards
Afzal

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-03  8:37       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
> > +
> > +	pdata->clk_prd = gpmc_get_fclk_period();
> 
> Does this need to be done here? May be this should be done in the probe
> function. You could store the handle to the main clk in the pdata.

This is done so that migration of gpmc driver to the drivers folder
would be smooth, remember that this function will still live here.
 
> > +		pr_err("error: clk_get on %s\n", oh->main_clk);
> > +		return -EINVAL;
> >  	}
> >  
> >  	clk_enable(gpmc_l3_clk);
> 
> I would have thought we should be able to remove the gpmc_init function
> completely by now. Most of the code should be moved to the probe function.
> 
> Also now with hwmod in place, we should be able to remove the
> clk_enable/disable functions and use the pm_runtime APIs instead.

There was no plan to add rpm in this series, but now that you have
brought it up, I will adapt the driver to rpm.

Regards
Afzal

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

* RE: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-01 21:16     ` Jon Hunter
  (?)
@ 2012-05-03  8:42       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:42 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Jon,

On Wed, May 02, 2012 at 02:46:02, Hunter, Jon wrote:
> > Some boards depend on bootloader to update chip select value for NAND.
> > It is felt that Kernel should not depend on bootloader to get CS, as
> > for a particular board CS is hardwired and is fixed, hence this can
> > directly be updated in Kernel. But as CS value for boards that depend
> > on this behaviour is not available, educate gpmc driver to acquire
> > chip select value for NAND. this ideally should be removed once CS
> > for those boards are available.
> 
> Do you know how many boards require this? If so which are those boards?

devkit8000, beagle board, omap3touchbook, overo.

Beagle board, found out to be zero.

> Should this code be marked with a FIXME?

Will let Tony decide it.

Regards
Afzal

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

* RE: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-03  8:42       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:42 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Jon,

On Wed, May 02, 2012 at 02:46:02, Hunter, Jon wrote:
> > Some boards depend on bootloader to update chip select value for NAND.
> > It is felt that Kernel should not depend on bootloader to get CS, as
> > for a particular board CS is hardwired and is fixed, hence this can
> > directly be updated in Kernel. But as CS value for boards that depend
> > on this behaviour is not available, educate gpmc driver to acquire
> > chip select value for NAND. this ideally should be removed once CS
> > for those boards are available.
> 
> Do you know how many boards require this? If so which are those boards?

devkit8000, beagle board, omap3touchbook, overo.

Beagle board, found out to be zero.

> Should this code be marked with a FIXME?

Will let Tony decide it.

Regards
Afzal

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

* [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
@ 2012-05-03  8:42       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Wed, May 02, 2012 at 02:46:02, Hunter, Jon wrote:
> > Some boards depend on bootloader to update chip select value for NAND.
> > It is felt that Kernel should not depend on bootloader to get CS, as
> > for a particular board CS is hardwired and is fixed, hence this can
> > directly be updated in Kernel. But as CS value for boards that depend
> > on this behaviour is not available, educate gpmc driver to acquire
> > chip select value for NAND. this ideally should be removed once CS
> > for those boards are available.
> 
> Do you know how many boards require this? If so which are those boards?

devkit8000, beagle board, omap3touchbook, overo.

Beagle board, found out to be zero.

> Should this code be marked with a FIXME?

Will let Tony decide it.

Regards
Afzal

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

* RE: [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
  2012-05-01 16:49     ` Sergei Shtylyov
  (?)
@ 2012-05-03  8:54       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:54 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Sergei,

On Tue, May 01, 2012 at 22:19:37, Sergei Shtylyov wrote:
> > +
> > +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> > +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
> 
>     You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

Thanks for educating me.

Regards
Afzal

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

* RE: [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-03  8:54       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:54 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Sergei,

On Tue, May 01, 2012 at 22:19:37, Sergei Shtylyov wrote:
> > +
> > +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> > +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
> 
>     You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

Thanks for educating me.

Regards
Afzal

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

* [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function
@ 2012-05-03  8:54       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-03  8:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergei,

On Tue, May 01, 2012 at 22:19:37, Sergei Shtylyov wrote:
> > +
> > +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
> > +		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
> 
>     You can use IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) instead these two.

Thanks for educating me.

Regards
Afzal

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-03  8:23             ` Mohammed, Afzal
  (?)
@ 2012-05-04 16:20                 ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:20 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hire

Hi Afzal,

On 05/03/2012 03:23 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
>> Hi Afzal,
>>
>> Looks good! Some minor comments ...
> 
> Thanks
> 
>>> +#define	GPMC_WAITPIN_IDX0			0x0
>>> +#define	GPMC_WAITPIN_IDX1			0x1
>>> +#define	GPMC_WAITPIN_IDX2			0x2
>>> +#define	GPMC_WAITPIN_IDX3			0x3
>>> +#define	GPMC_NR_WAITPIN				0x4
>>
>> How about an enum here? Also OMAP4 only have 3 wait pins and so the
>> number is device dependent.
> 
> Ok
> 
>>
>>>  #define GPMC_MEM_START		0x00000000
>>>  #define GPMC_MEM_END		0x3FFFFFFF
>>>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
>>> @@ -64,6 +106,55 @@
>>>  #define ENABLE_PREFETCH		(0x1 << 7)
>>>  #define DMA_MPU_MODE		2
>>>  
>>> +#define	DRIVER_NAME	"omap-gpmc"
>>> +
>>> +#define	GPMC_NR_IRQ		2
>>
>> Why has this been changed to 2? It was 6 in the previous version. As we
>> discussed before the number of IRQs should be detected based upon GPMC
>> IP version.
> 
> As mentioned in the cover letter,
> 
> "Additional features that currently boards in mainline does not make
> use of like, waitpin interrupt handling, changes to leverage revision
> 6 IP differences has not been incorporated."
> 
> Priority in this series is to convert into a driver, get all boards working
> on mainline. Once all boards are working with gpmc driver, these features
> which are not required for currently supported boards can be added later.

Yes, but I meant why 2 and not say 5? Anyway, I think that this should
be marked with a comment like a TODO so it is clear that this needs to
be re-visited.

>>> +struct gpmc_device {
>>> +	char			*name;
>>> +	int			id;
>>> +	void			*pdata;
>>> +	unsigned		pdata_size;
>>> +	struct resource		*per_res;
>>> +	unsigned		per_res_cnt;
>>> +	struct resource		*gpmc_res;
>>> +	unsigned		gpmc_res_cnt;
>>> +	bool			have_waitpin;
>>> +	unsigned		waitpin;
>>> +	int			waitpin_polarity;
>>
>> I think that it make more sense to have the wait-pin information part of
>> the gpmc_cs_data structure for the following reasons ...
> 
> Waitpin information is indeed a part of cs as far as boards are concerned,
> it is only that it gets propogated to device

Why does the device's driver care? From my point of view, the wait-pin
is just part of the interface setup/configuration. The external device
may require this and assumes that this has been setup along with the CS
and interface timing, but the device's driver should not care. Remember
this is just a ready signal used to stall the access. Once configured,
software should be unaware of it.

>> 1. If a device can use multiple CS, then it could use multiple wait signals.
>> 2. Eventually, all board information needs to move to device tree. By
>> having it in the pdata it will be easier to migrate to device tree.
>>
>> It may be nice to have "have_waitpin" be an integer too, that indicates
>> if wait is used for both read and write or just one or the other.
>>
>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>> register for an active low wait signal.
> 
> Only intention is not to alter default waitpin polarity value, i.e. if
> any board does make use of it w/o knowledge of Kernel, I don't want to
> break it, there may be an argument saying that the board code is buggy,
> while if some board does so, it is, but don't want to break working one.
> 
> Here unless user explicitly set the flag, it does nothing on polarity

Ok. Do such scenario's exist today? Please note that board code will be
removed in the future and device-tree will replace. So if there are no
cases today, I would not be concerned. Unless this could be something
that has already been configured by the bootloader. However, in that
case would be even call this function?

>>> +	if (idx != ~0x0) {
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>
>> I am not sure about the above code. What happens if a device has
>> multiple CS signals and uses multiple wait signals?
>>
>> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
>> cannot be combined. I think that it would be a fair assumption to make
>> that anyone using the waitpin does so inconjunction with the CS (I think
>> that they would have too).
>>
>> However, if there is a reason for splitting it up this way please
>> explain why.
> 
> Initially it was done per CS, the problem happened while trying to
> convert tusb6010. It had multiple CS, but using same waitpin. Problem
> with incorporating this onto CS is we have to sacrifice on wait pin
> conflict prevention capability. The code now handles case of wait pin
> conflict per device, the code can be extended to have multiple
> wait pin per device also. But I prefer to defer it to later, not as
> part of this series, as this feature what you asking for is not required
> for any of the existing boards. I can add it in this series if there is
> a strong opinion in the community for the same in this series.

Ok, yes this does make sense. I wonder if we can clean up the all the
nested if-statements in gpmc_setup_cs_waitpin(). Seems there could be
some redundancy.

> Policy that is being followed here is first sit, then straighten legs, ;)

Ha! Crawl before walking ;-)

>>> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
>>> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
>>
>> The name of this function is not 100% clear to me. What do you mean by
>> "nonres"?
> 
> It means anything other than resources like memory & irq, happened for
> want of better name, if you have one, name it, will put it.

Not really, but may be worth adding a comment.

>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>
>> What scenario is this function used in? May be worth adding a comment
>> about the function.
> 
> Ok, it was required for OneNAND, as it needs to reconfigure

Ok, but why is that? Unless this is something generic about one-nand I
don't comprehend. I have a high-level understanding of one-nand, but I
am not familiar with the specifics that require it to be reconfigured.

>>> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
>>> +				i < gdp->num_cs; i++, cs++)
>>> +		n += hweight32(cs->irq_config);
>>
>> As you know I am not a fan of these overloaded for-loops as I find them
>> hard to read ;-)
>>
>> Why not ...
>>
>> n = gdp->num_cs;
>> cs = gdp->cs_data;
> 
> 
> Well, you also know that I am big fan of it; difference of opinion,
> my preference is to keep loop control statements together with "for",
> unless there is a cry from community that it should not be this way.
> I believe that it is not that much unreadable.

Ok.

>>> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>>> +			(i < gp->num_device) && (*gdq); i++, gdq++) {
>>
>> You have num_devices now and so do you really need the "&& (*gdq)"?
>> Seems redundant.
> 
> num_device is something that I never wanted to add, was happy with,
> NULL entry termination, only because of your repeated comments,
> I added this. And this additional check now prevents NULL dereference.

Ok, but I would go with one or the other. Make it NULL terminated but
maybe add a comment?

>>> +	gpmc_setup_writeprotect(gpmc);
>>
>> Write protect is a pin and there is only one. Like the waitpins and CS
>> signals this needs to be associated with a device. It would make sense
>> that this is associated with the cs data.
> 
> As far as platform are concerned, it is associated with cs, it is only
> that while configuring CS, it is propagated such that it is done once.

Hmmm ... but here it looks like if write-protect is used you are going
to turn it on. A feature like this seems that it does need to be handled
by the device's driver. Enabling and disabling write-protect are
functions that I would expect are exported to the device's driver and
not directly enabled in the gpmc driver during probe. However, maybe is
could be valid for the write protect to be enabled by default which
could make sense. However, I don't see anywhere else in the driver to
control it.

Shouldn't we warn on multiple devices trying to use write-protect when
parsing their configuration?

>>> +#define	GPMC_READTYPE_ASYNC		BIT(30)
>>> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
>>> +
>>
>> Please keep in mind that eventually this has to all be moved into device
>> tree and so at that point these configuration flags will have to be
>> re-worked. However, just a FYI.
> 
> On device tree matters, my mind is next to blank, thanks for mentioning it.

No problem. For now lets not worry too much.

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-04 16:20                 ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:20 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Afzal,

On 05/03/2012 03:23 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
>> Hi Afzal,
>>
>> Looks good! Some minor comments ...
> 
> Thanks
> 
>>> +#define	GPMC_WAITPIN_IDX0			0x0
>>> +#define	GPMC_WAITPIN_IDX1			0x1
>>> +#define	GPMC_WAITPIN_IDX2			0x2
>>> +#define	GPMC_WAITPIN_IDX3			0x3
>>> +#define	GPMC_NR_WAITPIN				0x4
>>
>> How about an enum here? Also OMAP4 only have 3 wait pins and so the
>> number is device dependent.
> 
> Ok
> 
>>
>>>  #define GPMC_MEM_START		0x00000000
>>>  #define GPMC_MEM_END		0x3FFFFFFF
>>>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
>>> @@ -64,6 +106,55 @@
>>>  #define ENABLE_PREFETCH		(0x1 << 7)
>>>  #define DMA_MPU_MODE		2
>>>  
>>> +#define	DRIVER_NAME	"omap-gpmc"
>>> +
>>> +#define	GPMC_NR_IRQ		2
>>
>> Why has this been changed to 2? It was 6 in the previous version. As we
>> discussed before the number of IRQs should be detected based upon GPMC
>> IP version.
> 
> As mentioned in the cover letter,
> 
> "Additional features that currently boards in mainline does not make
> use of like, waitpin interrupt handling, changes to leverage revision
> 6 IP differences has not been incorporated."
> 
> Priority in this series is to convert into a driver, get all boards working
> on mainline. Once all boards are working with gpmc driver, these features
> which are not required for currently supported boards can be added later.

Yes, but I meant why 2 and not say 5? Anyway, I think that this should
be marked with a comment like a TODO so it is clear that this needs to
be re-visited.

>>> +struct gpmc_device {
>>> +	char			*name;
>>> +	int			id;
>>> +	void			*pdata;
>>> +	unsigned		pdata_size;
>>> +	struct resource		*per_res;
>>> +	unsigned		per_res_cnt;
>>> +	struct resource		*gpmc_res;
>>> +	unsigned		gpmc_res_cnt;
>>> +	bool			have_waitpin;
>>> +	unsigned		waitpin;
>>> +	int			waitpin_polarity;
>>
>> I think that it make more sense to have the wait-pin information part of
>> the gpmc_cs_data structure for the following reasons ...
> 
> Waitpin information is indeed a part of cs as far as boards are concerned,
> it is only that it gets propogated to device

Why does the device's driver care? From my point of view, the wait-pin
is just part of the interface setup/configuration. The external device
may require this and assumes that this has been setup along with the CS
and interface timing, but the device's driver should not care. Remember
this is just a ready signal used to stall the access. Once configured,
software should be unaware of it.

>> 1. If a device can use multiple CS, then it could use multiple wait signals.
>> 2. Eventually, all board information needs to move to device tree. By
>> having it in the pdata it will be easier to migrate to device tree.
>>
>> It may be nice to have "have_waitpin" be an integer too, that indicates
>> if wait is used for both read and write or just one or the other.
>>
>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>> register for an active low wait signal.
> 
> Only intention is not to alter default waitpin polarity value, i.e. if
> any board does make use of it w/o knowledge of Kernel, I don't want to
> break it, there may be an argument saying that the board code is buggy,
> while if some board does so, it is, but don't want to break working one.
> 
> Here unless user explicitly set the flag, it does nothing on polarity

Ok. Do such scenario's exist today? Please note that board code will be
removed in the future and device-tree will replace. So if there are no
cases today, I would not be concerned. Unless this could be something
that has already been configured by the bootloader. However, in that
case would be even call this function?

>>> +	if (idx != ~0x0) {
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>
>> I am not sure about the above code. What happens if a device has
>> multiple CS signals and uses multiple wait signals?
>>
>> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
>> cannot be combined. I think that it would be a fair assumption to make
>> that anyone using the waitpin does so inconjunction with the CS (I think
>> that they would have too).
>>
>> However, if there is a reason for splitting it up this way please
>> explain why.
> 
> Initially it was done per CS, the problem happened while trying to
> convert tusb6010. It had multiple CS, but using same waitpin. Problem
> with incorporating this onto CS is we have to sacrifice on wait pin
> conflict prevention capability. The code now handles case of wait pin
> conflict per device, the code can be extended to have multiple
> wait pin per device also. But I prefer to defer it to later, not as
> part of this series, as this feature what you asking for is not required
> for any of the existing boards. I can add it in this series if there is
> a strong opinion in the community for the same in this series.

Ok, yes this does make sense. I wonder if we can clean up the all the
nested if-statements in gpmc_setup_cs_waitpin(). Seems there could be
some redundancy.

> Policy that is being followed here is first sit, then straighten legs, ;)

Ha! Crawl before walking ;-)

>>> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
>>> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
>>
>> The name of this function is not 100% clear to me. What do you mean by
>> "nonres"?
> 
> It means anything other than resources like memory & irq, happened for
> want of better name, if you have one, name it, will put it.

Not really, but may be worth adding a comment.

>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>
>> What scenario is this function used in? May be worth adding a comment
>> about the function.
> 
> Ok, it was required for OneNAND, as it needs to reconfigure

Ok, but why is that? Unless this is something generic about one-nand I
don't comprehend. I have a high-level understanding of one-nand, but I
am not familiar with the specifics that require it to be reconfigured.

>>> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
>>> +				i < gdp->num_cs; i++, cs++)
>>> +		n += hweight32(cs->irq_config);
>>
>> As you know I am not a fan of these overloaded for-loops as I find them
>> hard to read ;-)
>>
>> Why not ...
>>
>> n = gdp->num_cs;
>> cs = gdp->cs_data;
> 
> 
> Well, you also know that I am big fan of it; difference of opinion,
> my preference is to keep loop control statements together with "for",
> unless there is a cry from community that it should not be this way.
> I believe that it is not that much unreadable.

Ok.

>>> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>>> +			(i < gp->num_device) && (*gdq); i++, gdq++) {
>>
>> You have num_devices now and so do you really need the "&& (*gdq)"?
>> Seems redundant.
> 
> num_device is something that I never wanted to add, was happy with,
> NULL entry termination, only because of your repeated comments,
> I added this. And this additional check now prevents NULL dereference.

Ok, but I would go with one or the other. Make it NULL terminated but
maybe add a comment?

>>> +	gpmc_setup_writeprotect(gpmc);
>>
>> Write protect is a pin and there is only one. Like the waitpins and CS
>> signals this needs to be associated with a device. It would make sense
>> that this is associated with the cs data.
> 
> As far as platform are concerned, it is associated with cs, it is only
> that while configuring CS, it is propagated such that it is done once.

Hmmm ... but here it looks like if write-protect is used you are going
to turn it on. A feature like this seems that it does need to be handled
by the device's driver. Enabling and disabling write-protect are
functions that I would expect are exported to the device's driver and
not directly enabled in the gpmc driver during probe. However, maybe is
could be valid for the write protect to be enabled by default which
could make sense. However, I don't see anywhere else in the driver to
control it.

Shouldn't we warn on multiple devices trying to use write-protect when
parsing their configuration?

>>> +#define	GPMC_READTYPE_ASYNC		BIT(30)
>>> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
>>> +
>>
>> Please keep in mind that eventually this has to all be moved into device
>> tree and so at that point these configuration flags will have to be
>> re-worked. However, just a FYI.
> 
> On device tree matters, my mind is next to blank, thanks for mentioning it.

No problem. For now lets not worry too much.

Cheers
Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-04 16:20                 ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/03/2012 03:23 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Tue, May 01, 2012 at 23:23:00, Hunter, Jon wrote:
>> Hi Afzal,
>>
>> Looks good! Some minor comments ...
> 
> Thanks
> 
>>> +#define	GPMC_WAITPIN_IDX0			0x0
>>> +#define	GPMC_WAITPIN_IDX1			0x1
>>> +#define	GPMC_WAITPIN_IDX2			0x2
>>> +#define	GPMC_WAITPIN_IDX3			0x3
>>> +#define	GPMC_NR_WAITPIN				0x4
>>
>> How about an enum here? Also OMAP4 only have 3 wait pins and so the
>> number is device dependent.
> 
> Ok
> 
>>
>>>  #define GPMC_MEM_START		0x00000000
>>>  #define GPMC_MEM_END		0x3FFFFFFF
>>>  #define BOOT_ROM_SPACE		0x100000	/* 1MB */
>>> @@ -64,6 +106,55 @@
>>>  #define ENABLE_PREFETCH		(0x1 << 7)
>>>  #define DMA_MPU_MODE		2
>>>  
>>> +#define	DRIVER_NAME	"omap-gpmc"
>>> +
>>> +#define	GPMC_NR_IRQ		2
>>
>> Why has this been changed to 2? It was 6 in the previous version. As we
>> discussed before the number of IRQs should be detected based upon GPMC
>> IP version.
> 
> As mentioned in the cover letter,
> 
> "Additional features that currently boards in mainline does not make
> use of like, waitpin interrupt handling, changes to leverage revision
> 6 IP differences has not been incorporated."
> 
> Priority in this series is to convert into a driver, get all boards working
> on mainline. Once all boards are working with gpmc driver, these features
> which are not required for currently supported boards can be added later.

Yes, but I meant why 2 and not say 5? Anyway, I think that this should
be marked with a comment like a TODO so it is clear that this needs to
be re-visited.

>>> +struct gpmc_device {
>>> +	char			*name;
>>> +	int			id;
>>> +	void			*pdata;
>>> +	unsigned		pdata_size;
>>> +	struct resource		*per_res;
>>> +	unsigned		per_res_cnt;
>>> +	struct resource		*gpmc_res;
>>> +	unsigned		gpmc_res_cnt;
>>> +	bool			have_waitpin;
>>> +	unsigned		waitpin;
>>> +	int			waitpin_polarity;
>>
>> I think that it make more sense to have the wait-pin information part of
>> the gpmc_cs_data structure for the following reasons ...
> 
> Waitpin information is indeed a part of cs as far as boards are concerned,
> it is only that it gets propogated to device

Why does the device's driver care? From my point of view, the wait-pin
is just part of the interface setup/configuration. The external device
may require this and assumes that this has been setup along with the CS
and interface timing, but the device's driver should not care. Remember
this is just a ready signal used to stall the access. Once configured,
software should be unaware of it.

>> 1. If a device can use multiple CS, then it could use multiple wait signals.
>> 2. Eventually, all board information needs to move to device tree. By
>> having it in the pdata it will be easier to migrate to device tree.
>>
>> It may be nice to have "have_waitpin" be an integer too, that indicates
>> if wait is used for both read and write or just one or the other.
>>
>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>> register for an active low wait signal.
> 
> Only intention is not to alter default waitpin polarity value, i.e. if
> any board does make use of it w/o knowledge of Kernel, I don't want to
> break it, there may be an argument saying that the board code is buggy,
> while if some board does so, it is, but don't want to break working one.
> 
> Here unless user explicitly set the flag, it does nothing on polarity

Ok. Do such scenario's exist today? Please note that board code will be
removed in the future and device-tree will replace. So if there are no
cases today, I would not be concerned. Unless this could be something
that has already been configured by the bootloader. However, in that
case would be even call this function?

>>> +	if (idx != ~0x0) {
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>
>> I am not sure about the above code. What happens if a device has
>> multiple CS signals and uses multiple wait signals?
>>
>> I am also not sure why gpmc_setup_cs_waitpin and gpmc_setup_waitpin
>> cannot be combined. I think that it would be a fair assumption to make
>> that anyone using the waitpin does so inconjunction with the CS (I think
>> that they would have too).
>>
>> However, if there is a reason for splitting it up this way please
>> explain why.
> 
> Initially it was done per CS, the problem happened while trying to
> convert tusb6010. It had multiple CS, but using same waitpin. Problem
> with incorporating this onto CS is we have to sacrifice on wait pin
> conflict prevention capability. The code now handles case of wait pin
> conflict per device, the code can be extended to have multiple
> wait pin per device also. But I prefer to defer it to later, not as
> part of this series, as this feature what you asking for is not required
> for any of the existing boards. I can add it in this series if there is
> a strong opinion in the community for the same in this series.

Ok, yes this does make sense. I wonder if we can clean up the all the
nested if-statements in gpmc_setup_cs_waitpin(). Seems there could be
some redundancy.

> Policy that is being followed here is first sit, then straighten legs, ;)

Ha! Crawl before walking ;-)

>>> +static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
>>> +			struct gpmc_device *gd, struct gpmc_cs_data *cs)
>>
>> The name of this function is not 100% clear to me. What do you mean by
>> "nonres"?
> 
> It means anything other than resources like memory & irq, happened for
> want of better name, if you have one, name it, will put it.

Not really, but may be worth adding a comment.

>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>
>> What scenario is this function used in? May be worth adding a comment
>> about the function.
> 
> Ok, it was required for OneNAND, as it needs to reconfigure

Ok, but why is that? Unless this is something generic about one-nand I
don't comprehend. I have a high-level understanding of one-nand, but I
am not familiar with the specifics that require it to be reconfigured.

>>> +	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
>>> +				i < gdp->num_cs; i++, cs++)
>>> +		n += hweight32(cs->irq_config);
>>
>> As you know I am not a fan of these overloaded for-loops as I find them
>> hard to read ;-)
>>
>> Why not ...
>>
>> n = gdp->num_cs;
>> cs = gdp->cs_data;
> 
> 
> Well, you also know that I am big fan of it; difference of opinion,
> my preference is to keep loop control statements together with "for",
> unless there is a cry from community that it should not be this way.
> I believe that it is not that much unreadable.

Ok.

>>> +	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
>>> +			(i < gp->num_device) && (*gdq); i++, gdq++) {
>>
>> You have num_devices now and so do you really need the "&& (*gdq)"?
>> Seems redundant.
> 
> num_device is something that I never wanted to add, was happy with,
> NULL entry termination, only because of your repeated comments,
> I added this. And this additional check now prevents NULL dereference.

Ok, but I would go with one or the other. Make it NULL terminated but
maybe add a comment?

>>> +	gpmc_setup_writeprotect(gpmc);
>>
>> Write protect is a pin and there is only one. Like the waitpins and CS
>> signals this needs to be associated with a device. It would make sense
>> that this is associated with the cs data.
> 
> As far as platform are concerned, it is associated with cs, it is only
> that while configuring CS, it is propagated such that it is done once.

Hmmm ... but here it looks like if write-protect is used you are going
to turn it on. A feature like this seems that it does need to be handled
by the device's driver. Enabling and disabling write-protect are
functions that I would expect are exported to the device's driver and
not directly enabled in the gpmc driver during probe. However, maybe is
could be valid for the write protect to be enabled by default which
could make sense. However, I don't see anywhere else in the driver to
control it.

Shouldn't we warn on multiple devices trying to use write-protect when
parsing their configuration?

>>> +#define	GPMC_READTYPE_ASYNC		BIT(30)
>>> +#define	GPMC_WRITETYPE_ASYNC		BIT(31)
>>> +
>>
>> Please keep in mind that eventually this has to all be moved into device
>> tree and so at that point these configuration flags will have to be
>> re-worked. However, just a FYI.
> 
> On device tree matters, my mind is next to blank, thanks for mentioning it.

No problem. For now lets not worry too much.

Cheers
Jon

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-01 12:19     ` Afzal Mohammed
  (?)
@ 2012-05-04 16:27         ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:27 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Vaibhav Hiremath

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:

[...]

> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}

Why not combined case 0 and default? Both are invalid configurations so
just report invalid selection.

>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}

Again, combine case 0 and default as these are invalid.

>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {

If you combine the above cases, then you can drop the idx test here.

> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {

Don't need the else as you are going to return in the above.

> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}
> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;

Drop this else-if. The above switch statements will report the bad
configuration. This seems a bit redundant.

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-04 16:27         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:27 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, Vaibhav Hiremath, vimal.newwork, grinberg,
	artem.bityutskiy, linux-mtd, linux-omap, dwmw2, linux-arm-kernel,
	notasas

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:

[...]

> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}

Why not combined case 0 and default? Both are invalid configurations so
just report invalid selection.

>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}

Again, combine case 0 and default as these are invalid.

>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {

If you combine the above cases, then you can drop the idx test here.

> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {

Don't need the else as you are going to return in the above.

> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}
> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;

Drop this else-if. The above switch statements will report the bad
configuration. This seems a bit redundant.

Cheers
Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-04 16:27         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/01/2012 07:19 AM, Afzal Mohammed wrote:

[...]

> +static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
> +						unsigned cs, unsigned conf)
> +{
> +	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> +	unsigned idx = ~0x0;
> +	int polarity = 0;
>  
> -	l = gpmc_read_reg(GPMC_REVISION);
> -	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
> -	/* Set smart idle mode and automatic L3 clock gating */
> -	l = gpmc_read_reg(GPMC_SYSCONFIG);
> -	l &= 0x03 << 3;
> -	l |= (0x02 << 3) | (1 << 0);
> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> -	gpmc_mem_init();
> +	switch (conf & GPMC_WAITPIN_MASK) {
> +	case GPMC_WAITPIN_0:
> +		idx =  GPMC_WAITPIN_IDX0;
> +		break;
> +	case GPMC_WAITPIN_1:
> +		idx =  GPMC_WAITPIN_IDX1;
> +		break;
> +	case GPMC_WAITPIN_2:
> +		idx =  GPMC_WAITPIN_IDX2;
> +		break;
> +	case GPMC_WAITPIN_3:
> +		idx =  GPMC_WAITPIN_IDX3;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> +		return -EINVAL;
> +		break;
> +	}

Why not combined case 0 and default? Both are invalid configurations so
just report invalid selection.

>  
> -	/* initalize the irq_chained */
> -	irq = OMAP_GPMC_IRQ_BASE;
> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> -						handle_simple_irq);
> -		set_irq_flags(irq, IRQF_VALID);
> -		irq++;
> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> +	case GPMC_WAITPIN_ACTIVE_LOW:
> +		polarity = LOW;
> +		break;
> +	case GPMC_WAITPIN_ACTIVE_HIGH:
> +		polarity = HIGH;
> +		break;
> +	/* no waitpin */
> +	case 0:
> +		break;
> +	default:
> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> +		return -EINVAL;
> +		break;
>  	}

Again, combine case 0 and default as these are invalid.

>  
> -	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
> -	if (ret)
> -		pr_err("gpmc: irq-%d could not claim: err %d\n",
> -						gpmc_irq, ret);
> -	return ret;
> +	if (idx != ~0x0) {

If you combine the above cases, then you can drop the idx test here.

> +		if (gd->have_waitpin) {
> +			if (gd->waitpin != idx ||
> +					gd->waitpin_polarity != polarity) {
> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> +					gd->waitpin, gd->waitpin_polarity,
> +					gd->name, gd->id);
> +				return -EBUSY;
> +			}
> +		} else {

Don't need the else as you are going to return in the above.

> +			gd->have_waitpin = true;
> +			gd->waitpin = idx;
> +			gd->waitpin_polarity = polarity;
> +		}
> +
> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> +	} else if (polarity) {
> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> +							gd->name, gd->id);
> +		return -EINVAL;

Drop this else-if. The above switch statements will report the bad
configuration. This seems a bit redundant.

Cheers
Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-03  8:37       ` Mohammed, Afzal
  (?)
@ 2012-05-04 16:30         ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:30 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Afzal,

On 05/03/2012 03:37 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
>>> +
>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>
>> Does this need to be done here? May be this should be done in the probe
>> function. You could store the handle to the main clk in the pdata.
> 
> This is done so that migration of gpmc driver to the drivers folder
> would be smooth, remember that this function will still live here.

Sure, but why call this here?

>>> +		pr_err("error: clk_get on %s\n", oh->main_clk);
>>> +		return -EINVAL;
>>>  	}
>>>  
>>>  	clk_enable(gpmc_l3_clk);
>>
>> I would have thought we should be able to remove the gpmc_init function
>> completely by now. Most of the code should be moved to the probe function.
>>
>> Also now with hwmod in place, we should be able to remove the
>> clk_enable/disable functions and use the pm_runtime APIs instead.
> 
> There was no plan to add rpm in this series, but now that you have
> brought it up, I will adapt the driver to rpm.

Ok, great.

Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-04 16:30         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:30 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Afzal,

On 05/03/2012 03:37 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
>>> +
>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>
>> Does this need to be done here? May be this should be done in the probe
>> function. You could store the handle to the main clk in the pdata.
> 
> This is done so that migration of gpmc driver to the drivers folder
> would be smooth, remember that this function will still live here.

Sure, but why call this here?

>>> +		pr_err("error: clk_get on %s\n", oh->main_clk);
>>> +		return -EINVAL;
>>>  	}
>>>  
>>>  	clk_enable(gpmc_l3_clk);
>>
>> I would have thought we should be able to remove the gpmc_init function
>> completely by now. Most of the code should be moved to the probe function.
>>
>> Also now with hwmod in place, we should be able to remove the
>> clk_enable/disable functions and use the pm_runtime APIs instead.
> 
> There was no plan to add rpm in this series, but now that you have
> brought it up, I will adapt the driver to rpm.

Ok, great.

Jon

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-04 16:30         ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-04 16:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/03/2012 03:37 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Wed, May 02, 2012 at 02:11:48, Hunter, Jon wrote:
>>> +
>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>
>> Does this need to be done here? May be this should be done in the probe
>> function. You could store the handle to the main clk in the pdata.
> 
> This is done so that migration of gpmc driver to the drivers folder
> would be smooth, remember that this function will still live here.

Sure, but why call this here?

>>> +		pr_err("error: clk_get on %s\n", oh->main_clk);
>>> +		return -EINVAL;
>>>  	}
>>>  
>>>  	clk_enable(gpmc_l3_clk);
>>
>> I would have thought we should be able to remove the gpmc_init function
>> completely by now. Most of the code should be moved to the probe function.
>>
>> Also now with hwmod in place, we should be able to remove the
>> clk_enable/disable functions and use the pm_runtime APIs instead.
> 
> There was no plan to add rpm in this series, but now that you have
> brought it up, I will adapt the driver to rpm.

Ok, great.

Jon

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

* Re: [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
  2012-05-01 12:21   ` Afzal Mohammed
  (?)
@ 2012-05-06  2:09       ` Paul Walmsley
  -1 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	khilman-l0cyMroinI0, balbi-l0cyMroinI0,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, nm-l0cyMroinI0,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal-l0cyMroinI0@public.gmane.org>

The comments from

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
@ 2012-05-06  2:09       ` Paul Walmsley
  0 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, vimal.newwork, grinberg, artem.bityutskiy,
	linux-mtd, linux-omap, dwmw2, linux-arm-kernel, notasas

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>

The comments from

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul

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

* [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc
@ 2012-05-06  2:09       ` Paul Walmsley
  0 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>

The comments from

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul

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

* Re: [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
  2012-05-01 12:21   ` Afzal Mohammed
  (?)
@ 2012-05-06  2:09     ` Paul Walmsley
  -1 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: tony, linux, khilman, balbi, dwmw2, kyungmin.park, gregkh, nm,
	grinberg, notasas, artem.bityutskiy, vimal.newwork, dbaryshkov,
	linux-omap, linux-arm-kernel, linux-usb, linux-mtd

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>

The comments from 

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul

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

* Re: [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
@ 2012-05-06  2:09     ` Paul Walmsley
  0 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: Afzal Mohammed
  Cc: khilman, nm, linux, tony, gregkh, linux-usb, balbi, dbaryshkov,
	kyungmin.park, vimal.newwork, grinberg, artem.bityutskiy,
	linux-mtd, linux-omap, dwmw2, linux-arm-kernel, notasas

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>

The comments from 

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul

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

* [PATCH v4 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
@ 2012-05-06  2:09     ` Paul Walmsley
  0 siblings, 0 replies; 205+ messages in thread
From: Paul Walmsley @ 2012-05-06  2:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Afzal,

On Tue, 1 May 2012, Afzal Mohammed wrote:

> Add gpmc hwmod and associated interconnect data
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>

The comments from 

http://marc.info/?l=linux-omap&m=133626998315039&w=2

also apply to this patch.


- Paul

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-04 16:20                 ` Jon Hunter
  (?)
@ 2012-05-07 10:57                   ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 10:57 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Jon,

On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
> > As mentioned in the cover letter,
> > 
> > "Additional features that currently boards in mainline does not make
> > use of like, waitpin interrupt handling, changes to leverage revision
> > 6 IP differences has not been incorporated."
> > 
> > Priority in this series is to convert into a driver, get all boards working
> > on mainline. Once all boards are working with gpmc driver, these features
> > which are not required for currently supported boards can be added later.
> 
> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
> be marked with a comment like a TODO so it is clear that this needs to
> be re-visited.

Ok, it will be marked with TODO

> >> I think that it make more sense to have the wait-pin information part of
> >> the gpmc_cs_data structure for the following reasons ...
> > 
> > Waitpin information is indeed a part of cs as far as boards are concerned,
> > it is only that it gets propogated to device
> 
> Why does the device's driver care? From my point of view, the wait-pin
> is just part of the interface setup/configuration. The external device
> may require this and assumes that this has been setup along with the CS
> and interface timing, but the device's driver should not care. Remember
> this is just a ready signal used to stall the access. Once configured,
> software should be unaware of it.

By device, it is referred to gpmc device which only gpmc driver is aware,
the peripheral device's driver is not at all aware.

> >> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> >> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> >> register for an active low wait signal.
> > 
> > Only intention is not to alter default waitpin polarity value, i.e. if
> > any board does make use of it w/o knowledge of Kernel, I don't want to
> > break it, there may be an argument saying that the board code is buggy,
> > while if some board does so, it is, but don't want to break working one.
> > 
> > Here unless user explicitly set the flag, it does nothing on polarity
> 
> Ok. Do such scenario's exist today? Please note that board code will be
> removed in the future and device-tree will replace. So if there are no
> cases today, I would not be concerned. Unless this could be something
> that has already been configured by the bootloader. However, in that
> case would be even call this function?

Let me check this, here only intent was to play safe, as I have
only two boards to test.

> >>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> >>
> >> What scenario is this function used in? May be worth adding a comment
> >> about the function.
> > 
> > Ok, it was required for OneNAND, as it needs to reconfigure
> 
> Ok, but why is that? Unless this is something generic about one-nand I
> don't comprehend. I have a high-level understanding of one-nand, but I
> am not familiar with the specifics that require it to be reconfigured.

Not too familiar with OneNAND, from the code it has been understood
that to set into sync mode, first it may have to set to async mode, read
frequency from OneNAND, then setup sync mode for that frequency.


> >>> +	gpmc_setup_writeprotect(gpmc);
> >>
> >> Write protect is a pin and there is only one. Like the waitpins and CS
> >> signals this needs to be associated with a device. It would make sense
> >> that this is associated with the cs data.
> > 
> > As far as platform are concerned, it is associated with cs, it is only
> > that while configuring CS, it is propagated such that it is done once.
> 
> Hmmm ... but here it looks like if write-protect is used you are going
> to turn it on. A feature like this seems that it does need to be handled
> by the device's driver. Enabling and disabling write-protect are
> functions that I would expect are exported to the device's driver and
> not directly enabled in the gpmc driver during probe. However, maybe is
> could be valid for the write protect to be enabled by default which
> could make sense. However, I don't see anywhere else in the driver to
> control it.
> 
> Shouldn't we warn on multiple devices trying to use write-protect when
> parsing their configuration?

Even if a single device sets write protect, kernel will log it.

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 10:57                   ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 10:57 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
> > As mentioned in the cover letter,
> > 
> > "Additional features that currently boards in mainline does not make
> > use of like, waitpin interrupt handling, changes to leverage revision
> > 6 IP differences has not been incorporated."
> > 
> > Priority in this series is to convert into a driver, get all boards working
> > on mainline. Once all boards are working with gpmc driver, these features
> > which are not required for currently supported boards can be added later.
> 
> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
> be marked with a comment like a TODO so it is clear that this needs to
> be re-visited.

Ok, it will be marked with TODO

> >> I think that it make more sense to have the wait-pin information part of
> >> the gpmc_cs_data structure for the following reasons ...
> > 
> > Waitpin information is indeed a part of cs as far as boards are concerned,
> > it is only that it gets propogated to device
> 
> Why does the device's driver care? From my point of view, the wait-pin
> is just part of the interface setup/configuration. The external device
> may require this and assumes that this has been setup along with the CS
> and interface timing, but the device's driver should not care. Remember
> this is just a ready signal used to stall the access. Once configured,
> software should be unaware of it.

By device, it is referred to gpmc device which only gpmc driver is aware,
the peripheral device's driver is not at all aware.

> >> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> >> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> >> register for an active low wait signal.
> > 
> > Only intention is not to alter default waitpin polarity value, i.e. if
> > any board does make use of it w/o knowledge of Kernel, I don't want to
> > break it, there may be an argument saying that the board code is buggy,
> > while if some board does so, it is, but don't want to break working one.
> > 
> > Here unless user explicitly set the flag, it does nothing on polarity
> 
> Ok. Do such scenario's exist today? Please note that board code will be
> removed in the future and device-tree will replace. So if there are no
> cases today, I would not be concerned. Unless this could be something
> that has already been configured by the bootloader. However, in that
> case would be even call this function?

Let me check this, here only intent was to play safe, as I have
only two boards to test.

> >>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> >>
> >> What scenario is this function used in? May be worth adding a comment
> >> about the function.
> > 
> > Ok, it was required for OneNAND, as it needs to reconfigure
> 
> Ok, but why is that? Unless this is something generic about one-nand I
> don't comprehend. I have a high-level understanding of one-nand, but I
> am not familiar with the specifics that require it to be reconfigured.

Not too familiar with OneNAND, from the code it has been understood
that to set into sync mode, first it may have to set to async mode, read
frequency from OneNAND, then setup sync mode for that frequency.


> >>> +	gpmc_setup_writeprotect(gpmc);
> >>
> >> Write protect is a pin and there is only one. Like the waitpins and CS
> >> signals this needs to be associated with a device. It would make sense
> >> that this is associated with the cs data.
> > 
> > As far as platform are concerned, it is associated with cs, it is only
> > that while configuring CS, it is propagated such that it is done once.
> 
> Hmmm ... but here it looks like if write-protect is used you are going
> to turn it on. A feature like this seems that it does need to be handled
> by the device's driver. Enabling and disabling write-protect are
> functions that I would expect are exported to the device's driver and
> not directly enabled in the gpmc driver during probe. However, maybe is
> could be valid for the write protect to be enabled by default which
> could make sense. However, I don't see anywhere else in the driver to
> control it.
> 
> Shouldn't we warn on multiple devices trying to use write-protect when
> parsing their configuration?

Even if a single device sets write protect, kernel will log it.

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 10:57                   ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
> > As mentioned in the cover letter,
> > 
> > "Additional features that currently boards in mainline does not make
> > use of like, waitpin interrupt handling, changes to leverage revision
> > 6 IP differences has not been incorporated."
> > 
> > Priority in this series is to convert into a driver, get all boards working
> > on mainline. Once all boards are working with gpmc driver, these features
> > which are not required for currently supported boards can be added later.
> 
> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
> be marked with a comment like a TODO so it is clear that this needs to
> be re-visited.

Ok, it will be marked with TODO

> >> I think that it make more sense to have the wait-pin information part of
> >> the gpmc_cs_data structure for the following reasons ...
> > 
> > Waitpin information is indeed a part of cs as far as boards are concerned,
> > it is only that it gets propogated to device
> 
> Why does the device's driver care? From my point of view, the wait-pin
> is just part of the interface setup/configuration. The external device
> may require this and assumes that this has been setup along with the CS
> and interface timing, but the device's driver should not care. Remember
> this is just a ready signal used to stall the access. Once configured,
> software should be unaware of it.

By device, it is referred to gpmc device which only gpmc driver is aware,
the peripheral device's driver is not at all aware.

> >> Also, any reason why waitpin_polarity is an int? I see you define LOW as
> >> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
> >> register for an active low wait signal.
> > 
> > Only intention is not to alter default waitpin polarity value, i.e. if
> > any board does make use of it w/o knowledge of Kernel, I don't want to
> > break it, there may be an argument saying that the board code is buggy,
> > while if some board does so, it is, but don't want to break working one.
> > 
> > Here unless user explicitly set the flag, it does nothing on polarity
> 
> Ok. Do such scenario's exist today? Please note that board code will be
> removed in the future and device-tree will replace. So if there are no
> cases today, I would not be concerned. Unless this could be something
> that has already been configured by the bootloader. However, in that
> case would be even call this function?

Let me check this, here only intent was to play safe, as I have
only two boards to test.

> >>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
> >>
> >> What scenario is this function used in? May be worth adding a comment
> >> about the function.
> > 
> > Ok, it was required for OneNAND, as it needs to reconfigure
> 
> Ok, but why is that? Unless this is something generic about one-nand I
> don't comprehend. I have a high-level understanding of one-nand, but I
> am not familiar with the specifics that require it to be reconfigured.

Not too familiar with OneNAND, from the code it has been understood
that to set into sync mode, first it may have to set to async mode, read
frequency from OneNAND, then setup sync mode for that frequency.


> >>> +	gpmc_setup_writeprotect(gpmc);
> >>
> >> Write protect is a pin and there is only one. Like the waitpins and CS
> >> signals this needs to be associated with a device. It would make sense
> >> that this is associated with the cs data.
> > 
> > As far as platform are concerned, it is associated with cs, it is only
> > that while configuring CS, it is propagated such that it is done once.
> 
> Hmmm ... but here it looks like if write-protect is used you are going
> to turn it on. A feature like this seems that it does need to be handled
> by the device's driver. Enabling and disabling write-protect are
> functions that I would expect are exported to the device's driver and
> not directly enabled in the gpmc driver during probe. However, maybe is
> could be valid for the write protect to be enabled by default which
> could make sense. However, I don't see anywhere else in the driver to
> control it.
> 
> Shouldn't we warn on multiple devices trying to use write-protect when
> parsing their configuration?

Even if a single device sets write protect, kernel will log it.

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-04 16:27         ` Jon Hunter
  (?)
@ 2012-05-07 11:01             ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:01 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hire

Hi Jon,

On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
> > -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> > -	gpmc_mem_init();
> > +	switch (conf & GPMC_WAITPIN_MASK) {
> > +	case GPMC_WAITPIN_0:
> > +		idx =  GPMC_WAITPIN_IDX0;
> > +		break;
> > +	case GPMC_WAITPIN_1:
> > +		idx =  GPMC_WAITPIN_IDX1;
> > +		break;
> > +	case GPMC_WAITPIN_2:
> > +		idx =  GPMC_WAITPIN_IDX2;
> > +		break;
> > +	case GPMC_WAITPIN_3:
> > +		idx =  GPMC_WAITPIN_IDX3;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> > +		return -EINVAL;
> > +		break;
> > +	}
> 
> Why not combined case 0 and default? Both are invalid configurations so
> just report invalid selection.

Case 0 is not invalid, a case where waitpin is not used, default refers
to when a user selects multiple waitpins wrongly.

> 
> >  
> > -	/* initalize the irq_chained */
> > -	irq = OMAP_GPMC_IRQ_BASE;
> > -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> > -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> > -						handle_simple_irq);
> > -		set_irq_flags(irq, IRQF_VALID);
> > -		irq++;
> > +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> > +	case GPMC_WAITPIN_ACTIVE_LOW:
> > +		polarity = LOW;
> > +		break;
> > +	case GPMC_WAITPIN_ACTIVE_HIGH:
> > +		polarity = HIGH;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> > +		return -EINVAL;
> > +		break;
> >  	}
> 
> Again, combine case 0 and default as these are invalid.

Similar to above

> 
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> 
> Don't need the else as you are going to return in the above.

Not always, only in case of error

> 
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> > +
> > +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> > +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> > +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> > +	} else if (polarity) {
> > +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> > +							gd->name, gd->id);
> > +		return -EINVAL;
> 
> Drop this else-if. The above switch statements will report the bad
> configuration. This seems a bit redundant.

This is required as switch statements will not report error if polarity
is specified, w/o waitpin to be used.

Regards
Afzal
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 11:01             ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:01 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
> > -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> > -	gpmc_mem_init();
> > +	switch (conf & GPMC_WAITPIN_MASK) {
> > +	case GPMC_WAITPIN_0:
> > +		idx =  GPMC_WAITPIN_IDX0;
> > +		break;
> > +	case GPMC_WAITPIN_1:
> > +		idx =  GPMC_WAITPIN_IDX1;
> > +		break;
> > +	case GPMC_WAITPIN_2:
> > +		idx =  GPMC_WAITPIN_IDX2;
> > +		break;
> > +	case GPMC_WAITPIN_3:
> > +		idx =  GPMC_WAITPIN_IDX3;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> > +		return -EINVAL;
> > +		break;
> > +	}
> 
> Why not combined case 0 and default? Both are invalid configurations so
> just report invalid selection.

Case 0 is not invalid, a case where waitpin is not used, default refers
to when a user selects multiple waitpins wrongly.

> 
> >  
> > -	/* initalize the irq_chained */
> > -	irq = OMAP_GPMC_IRQ_BASE;
> > -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> > -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> > -						handle_simple_irq);
> > -		set_irq_flags(irq, IRQF_VALID);
> > -		irq++;
> > +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> > +	case GPMC_WAITPIN_ACTIVE_LOW:
> > +		polarity = LOW;
> > +		break;
> > +	case GPMC_WAITPIN_ACTIVE_HIGH:
> > +		polarity = HIGH;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> > +		return -EINVAL;
> > +		break;
> >  	}
> 
> Again, combine case 0 and default as these are invalid.

Similar to above

> 
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> 
> Don't need the else as you are going to return in the above.

Not always, only in case of error

> 
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> > +
> > +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> > +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> > +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> > +	} else if (polarity) {
> > +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> > +							gd->name, gd->id);
> > +		return -EINVAL;
> 
> Drop this else-if. The above switch statements will report the bad
> configuration. This seems a bit redundant.

This is required as switch statements will not report error if polarity
is specified, w/o waitpin to be used.

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 11:01             ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
> > -	gpmc_write_reg(GPMC_SYSCONFIG, l);
> > -	gpmc_mem_init();
> > +	switch (conf & GPMC_WAITPIN_MASK) {
> > +	case GPMC_WAITPIN_0:
> > +		idx =  GPMC_WAITPIN_IDX0;
> > +		break;
> > +	case GPMC_WAITPIN_1:
> > +		idx =  GPMC_WAITPIN_IDX1;
> > +		break;
> > +	case GPMC_WAITPIN_2:
> > +		idx =  GPMC_WAITPIN_IDX2;
> > +		break;
> > +	case GPMC_WAITPIN_3:
> > +		idx =  GPMC_WAITPIN_IDX3;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> > +		return -EINVAL;
> > +		break;
> > +	}
> 
> Why not combined case 0 and default? Both are invalid configurations so
> just report invalid selection.

Case 0 is not invalid, a case where waitpin is not used, default refers
to when a user selects multiple waitpins wrongly.

> 
> >  
> > -	/* initalize the irq_chained */
> > -	irq = OMAP_GPMC_IRQ_BASE;
> > -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
> > -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
> > -						handle_simple_irq);
> > -		set_irq_flags(irq, IRQF_VALID);
> > -		irq++;
> > +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
> > +	case GPMC_WAITPIN_ACTIVE_LOW:
> > +		polarity = LOW;
> > +		break;
> > +	case GPMC_WAITPIN_ACTIVE_HIGH:
> > +		polarity = HIGH;
> > +		break;
> > +	/* no waitpin */
> > +	case 0:
> > +		break;
> > +	default:
> > +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
> > +		return -EINVAL;
> > +		break;
> >  	}
> 
> Again, combine case 0 and default as these are invalid.

Similar to above

> 
> > +		if (gd->have_waitpin) {
> > +			if (gd->waitpin != idx ||
> > +					gd->waitpin_polarity != polarity) {
> > +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> > +					gd->waitpin, gd->waitpin_polarity,
> > +					gd->name, gd->id);
> > +				return -EBUSY;
> > +			}
> > +		} else {
> 
> Don't need the else as you are going to return in the above.

Not always, only in case of error

> 
> > +			gd->have_waitpin = true;
> > +			gd->waitpin = idx;
> > +			gd->waitpin_polarity = polarity;
> > +		}
> > +
> > +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
> > +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
> > +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
> > +	} else if (polarity) {
> > +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
> > +							gd->name, gd->id);
> > +		return -EINVAL;
> 
> Drop this else-if. The above switch statements will report the bad
> configuration. This seems a bit redundant.

This is required as switch statements will not report error if polarity
is specified, w/o waitpin to be used.

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-04 16:30         ` Jon Hunter
  (?)
@ 2012-05-07 11:02           ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:02 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Jon,

On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
> >>> +
> >>> +	pdata->clk_prd = gpmc_get_fclk_period();
> >>
> >> Does this need to be done here? May be this should be done in the probe
> >> function. You could store the handle to the main clk in the pdata.
> > 
> > This is done so that migration of gpmc driver to the drivers folder
> > would be smooth, remember that this function will still live here.
> 
> Sure, but why call this here?

Clk_prd is a platform data passed to the driver, so platform code
updates it, where else can it be done ?

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-07 11:02           ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:02 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Jon,

On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
> >>> +
> >>> +	pdata->clk_prd = gpmc_get_fclk_period();
> >>
> >> Does this need to be done here? May be this should be done in the probe
> >> function. You could store the handle to the main clk in the pdata.
> > 
> > This is done so that migration of gpmc driver to the drivers folder
> > would be smooth, remember that this function will still live here.
> 
> Sure, but why call this here?

Clk_prd is a platform data passed to the driver, so platform code
updates it, where else can it be done ?

Regards
Afzal

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-07 11:02           ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-07 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
> >>> +
> >>> +	pdata->clk_prd = gpmc_get_fclk_period();
> >>
> >> Does this need to be done here? May be this should be done in the probe
> >> function. You could store the handle to the main clk in the pdata.
> > 
> > This is done so that migration of gpmc driver to the drivers folder
> > would be smooth, remember that this function will still live here.
> 
> Sure, but why call this here?

Clk_prd is a platform data passed to the driver, so platform code
updates it, where else can it be done ?

Regards
Afzal

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-07 11:01             ` Mohammed, Afzal
  (?)
@ 2012-05-07 16:02               ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:02 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Afzal,

On 05/07/2012 06:01 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
>>> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
>>> -	gpmc_mem_init();
>>> +	switch (conf & GPMC_WAITPIN_MASK) {
>>> +	case GPMC_WAITPIN_0:
>>> +		idx =  GPMC_WAITPIN_IDX0;
>>> +		break;
>>> +	case GPMC_WAITPIN_1:
>>> +		idx =  GPMC_WAITPIN_IDX1;
>>> +		break;
>>> +	case GPMC_WAITPIN_2:
>>> +		idx =  GPMC_WAITPIN_IDX2;
>>> +		break;
>>> +	case GPMC_WAITPIN_3:
>>> +		idx =  GPMC_WAITPIN_IDX3;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>> +		return -EINVAL;
>>> +		break;
>>> +	}
>>
>> Why not combined case 0 and default? Both are invalid configurations so
>> just report invalid selection.
> 
> Case 0 is not invalid, a case where waitpin is not used, default refers
> to when a user selects multiple waitpins wrongly.

Ok. Then for case 0, just return here. If the polarity is set, you could
print an error here.

>>
>>>  
>>> -	/* initalize the irq_chained */
>>> -	irq = OMAP_GPMC_IRQ_BASE;
>>> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
>>> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
>>> -						handle_simple_irq);
>>> -		set_irq_flags(irq, IRQF_VALID);
>>> -		irq++;
>>> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
>>> +	case GPMC_WAITPIN_ACTIVE_LOW:
>>> +		polarity = LOW;
>>> +		break;
>>> +	case GPMC_WAITPIN_ACTIVE_HIGH:
>>> +		polarity = HIGH;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
>>> +		return -EINVAL;
>>> +		break;
>>>  	}
>>
>> Again, combine case 0 and default as these are invalid.
> 
> Similar to above

If you return above, then case 0 is not needed.

>>
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>
>> Don't need the else as you are going to return in the above.
> 
> Not always, only in case of error

Ok, but seems that it can be simplified a little.

What happens if a device uses more than one wait-pin? In other words a
device with two chip-selects that uses two wait-pins?

>>
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>> +
>>> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
>>> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
>>> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>>> +	} else if (polarity) {
>>> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
>>> +							gd->name, gd->id);
>>> +		return -EINVAL;
>>
>> Drop this else-if. The above switch statements will report the bad
>> configuration. This seems a bit redundant.
> 
> This is required as switch statements will not report error if polarity
> is specified, w/o waitpin to be used.

Ok, may be you can print that above when you detect that there are no
wait-pins selected.

Jon

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 16:02               ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:02 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Afzal,

On 05/07/2012 06:01 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
>>> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
>>> -	gpmc_mem_init();
>>> +	switch (conf & GPMC_WAITPIN_MASK) {
>>> +	case GPMC_WAITPIN_0:
>>> +		idx =  GPMC_WAITPIN_IDX0;
>>> +		break;
>>> +	case GPMC_WAITPIN_1:
>>> +		idx =  GPMC_WAITPIN_IDX1;
>>> +		break;
>>> +	case GPMC_WAITPIN_2:
>>> +		idx =  GPMC_WAITPIN_IDX2;
>>> +		break;
>>> +	case GPMC_WAITPIN_3:
>>> +		idx =  GPMC_WAITPIN_IDX3;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>> +		return -EINVAL;
>>> +		break;
>>> +	}
>>
>> Why not combined case 0 and default? Both are invalid configurations so
>> just report invalid selection.
> 
> Case 0 is not invalid, a case where waitpin is not used, default refers
> to when a user selects multiple waitpins wrongly.

Ok. Then for case 0, just return here. If the polarity is set, you could
print an error here.

>>
>>>  
>>> -	/* initalize the irq_chained */
>>> -	irq = OMAP_GPMC_IRQ_BASE;
>>> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
>>> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
>>> -						handle_simple_irq);
>>> -		set_irq_flags(irq, IRQF_VALID);
>>> -		irq++;
>>> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
>>> +	case GPMC_WAITPIN_ACTIVE_LOW:
>>> +		polarity = LOW;
>>> +		break;
>>> +	case GPMC_WAITPIN_ACTIVE_HIGH:
>>> +		polarity = HIGH;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
>>> +		return -EINVAL;
>>> +		break;
>>>  	}
>>
>> Again, combine case 0 and default as these are invalid.
> 
> Similar to above

If you return above, then case 0 is not needed.

>>
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>
>> Don't need the else as you are going to return in the above.
> 
> Not always, only in case of error

Ok, but seems that it can be simplified a little.

What happens if a device uses more than one wait-pin? In other words a
device with two chip-selects that uses two wait-pins?

>>
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>> +
>>> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
>>> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
>>> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>>> +	} else if (polarity) {
>>> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
>>> +							gd->name, gd->id);
>>> +		return -EINVAL;
>>
>> Drop this else-if. The above switch statements will report the bad
>> configuration. This seems a bit redundant.
> 
> This is required as switch statements will not report error if polarity
> is specified, w/o waitpin to be used.

Ok, may be you can print that above when you detect that there are no
wait-pins selected.

Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 16:02               ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/07/2012 06:01 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:57:10, Hunter, Jon wrote:
>>> -	gpmc_write_reg(GPMC_SYSCONFIG, l);
>>> -	gpmc_mem_init();
>>> +	switch (conf & GPMC_WAITPIN_MASK) {
>>> +	case GPMC_WAITPIN_0:
>>> +		idx =  GPMC_WAITPIN_IDX0;
>>> +		break;
>>> +	case GPMC_WAITPIN_1:
>>> +		idx =  GPMC_WAITPIN_IDX1;
>>> +		break;
>>> +	case GPMC_WAITPIN_2:
>>> +		idx =  GPMC_WAITPIN_IDX2;
>>> +		break;
>>> +	case GPMC_WAITPIN_3:
>>> +		idx =  GPMC_WAITPIN_IDX3;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>> +		return -EINVAL;
>>> +		break;
>>> +	}
>>
>> Why not combined case 0 and default? Both are invalid configurations so
>> just report invalid selection.
> 
> Case 0 is not invalid, a case where waitpin is not used, default refers
> to when a user selects multiple waitpins wrongly.

Ok. Then for case 0, just return here. If the polarity is set, you could
print an error here.

>>
>>>  
>>> -	/* initalize the irq_chained */
>>> -	irq = OMAP_GPMC_IRQ_BASE;
>>> -	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
>>> -		irq_set_chip_and_handler(irq, &dummy_irq_chip,
>>> -						handle_simple_irq);
>>> -		set_irq_flags(irq, IRQF_VALID);
>>> -		irq++;
>>> +	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
>>> +	case GPMC_WAITPIN_ACTIVE_LOW:
>>> +		polarity = LOW;
>>> +		break;
>>> +	case GPMC_WAITPIN_ACTIVE_HIGH:
>>> +		polarity = HIGH;
>>> +		break;
>>> +	/* no waitpin */
>>> +	case 0:
>>> +		break;
>>> +	default:
>>> +		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
>>> +		return -EINVAL;
>>> +		break;
>>>  	}
>>
>> Again, combine case 0 and default as these are invalid.
> 
> Similar to above

If you return above, then case 0 is not needed.

>>
>>> +		if (gd->have_waitpin) {
>>> +			if (gd->waitpin != idx ||
>>> +					gd->waitpin_polarity != polarity) {
>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>> +					gd->waitpin, gd->waitpin_polarity,
>>> +					gd->name, gd->id);
>>> +				return -EBUSY;
>>> +			}
>>> +		} else {
>>
>> Don't need the else as you are going to return in the above.
> 
> Not always, only in case of error

Ok, but seems that it can be simplified a little.

What happens if a device uses more than one wait-pin? In other words a
device with two chip-selects that uses two wait-pins?

>>
>>> +			gd->have_waitpin = true;
>>> +			gd->waitpin = idx;
>>> +			gd->waitpin_polarity = polarity;
>>> +		}
>>> +
>>> +		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
>>> +		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
>>> +		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
>>> +	} else if (polarity) {
>>> +		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
>>> +							gd->name, gd->id);
>>> +		return -EINVAL;
>>
>> Drop this else-if. The above switch statements will report the bad
>> configuration. This seems a bit redundant.
> 
> This is required as switch statements will not report error if polarity
> is specified, w/o waitpin to be used.

Ok, may be you can print that above when you detect that there are no
wait-pins selected.

Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-07 11:02           ` Mohammed, Afzal
  (?)
@ 2012-05-07 16:12               ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:12 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Afzal,

On 05/07/2012 06:02 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
>>>>> +
>>>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>>>
>>>> Does this need to be done here? May be this should be done in the probe
>>>> function. You could store the handle to the main clk in the pdata.
>>>
>>> This is done so that migration of gpmc driver to the drivers folder
>>> would be smooth, remember that this function will still live here.
>>
>> Sure, but why call this here?
> 
> Clk_prd is a platform data passed to the driver, so platform code
> updates it, where else can it be done ?

The point is that you can pass what ever you like. You do not need to
pass the frequency you can pass the clock handle instead.

What happens it the clk_get() of the gpmc_l3_clk fails during the init?

In fact if you migrate to runtime pm then we should not have the clk_get
in the gpmc_init any more.

Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-07 16:12               ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:12 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Afzal,

On 05/07/2012 06:02 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
>>>>> +
>>>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>>>
>>>> Does this need to be done here? May be this should be done in the probe
>>>> function. You could store the handle to the main clk in the pdata.
>>>
>>> This is done so that migration of gpmc driver to the drivers folder
>>> would be smooth, remember that this function will still live here.
>>
>> Sure, but why call this here?
> 
> Clk_prd is a platform data passed to the driver, so platform code
> updates it, where else can it be done ?

The point is that you can pass what ever you like. You do not need to
pass the frequency you can pass the clock handle instead.

What happens it the clk_get() of the gpmc_l3_clk fails during the init?

In fact if you migrate to runtime pm then we should not have the clk_get
in the gpmc_init any more.

Jon

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-07 16:12               ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/07/2012 06:02 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 22:00:21, Hunter, Jon wrote:
>>>>> +
>>>>> +	pdata->clk_prd = gpmc_get_fclk_period();
>>>>
>>>> Does this need to be done here? May be this should be done in the probe
>>>> function. You could store the handle to the main clk in the pdata.
>>>
>>> This is done so that migration of gpmc driver to the drivers folder
>>> would be smooth, remember that this function will still live here.
>>
>> Sure, but why call this here?
> 
> Clk_prd is a platform data passed to the driver, so platform code
> updates it, where else can it be done ?

The point is that you can pass what ever you like. You do not need to
pass the frequency you can pass the clock handle instead.

What happens it the clk_get() of the gpmc_l3_clk fails during the init?

In fact if you migrate to runtime pm then we should not have the clk_get
in the gpmc_init any more.

Jon

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-07 10:57                   ` Mohammed, Afzal
  (?)
@ 2012-05-07 16:23                     ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:23 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Afzal,

On 05/07/2012 05:57 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
>>> As mentioned in the cover letter,
>>>
>>> "Additional features that currently boards in mainline does not make
>>> use of like, waitpin interrupt handling, changes to leverage revision
>>> 6 IP differences has not been incorporated."
>>>
>>> Priority in this series is to convert into a driver, get all boards working
>>> on mainline. Once all boards are working with gpmc driver, these features
>>> which are not required for currently supported boards can be added later.
>>
>> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
>> be marked with a comment like a TODO so it is clear that this needs to
>> be re-visited.
> 
> Ok, it will be marked with TODO
> 
>>>> I think that it make more sense to have the wait-pin information part of
>>>> the gpmc_cs_data structure for the following reasons ...
>>>
>>> Waitpin information is indeed a part of cs as far as boards are concerned,
>>> it is only that it gets propogated to device
>>
>> Why does the device's driver care? From my point of view, the wait-pin
>> is just part of the interface setup/configuration. The external device
>> may require this and assumes that this has been setup along with the CS
>> and interface timing, but the device's driver should not care. Remember
>> this is just a ready signal used to stall the access. Once configured,
>> software should be unaware of it.
> 
> By device, it is referred to gpmc device which only gpmc driver is aware,
> the peripheral device's driver is not at all aware.
> 
>>>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>>>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>>>> register for an active low wait signal.
>>>
>>> Only intention is not to alter default waitpin polarity value, i.e. if
>>> any board does make use of it w/o knowledge of Kernel, I don't want to
>>> break it, there may be an argument saying that the board code is buggy,
>>> while if some board does so, it is, but don't want to break working one.
>>>
>>> Here unless user explicitly set the flag, it does nothing on polarity
>>
>> Ok. Do such scenario's exist today? Please note that board code will be
>> removed in the future and device-tree will replace. So if there are no
>> cases today, I would not be concerned. Unless this could be something
>> that has already been configured by the bootloader. However, in that
>> case would be even call this function?
> 
> Let me check this, here only intent was to play safe, as I have
> only two boards to test.
> 
>>>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>>>
>>>> What scenario is this function used in? May be worth adding a comment
>>>> about the function.
>>>
>>> Ok, it was required for OneNAND, as it needs to reconfigure
>>
>> Ok, but why is that? Unless this is something generic about one-nand I
>> don't comprehend. I have a high-level understanding of one-nand, but I
>> am not familiar with the specifics that require it to be reconfigured.
> 
> Not too familiar with OneNAND, from the code it has been understood
> that to set into sync mode, first it may have to set to async mode, read
> frequency from OneNAND, then setup sync mode for that frequency.
> 
> 
>>>>> +	gpmc_setup_writeprotect(gpmc);
>>>>
>>>> Write protect is a pin and there is only one. Like the waitpins and CS
>>>> signals this needs to be associated with a device. It would make sense
>>>> that this is associated with the cs data.
>>>
>>> As far as platform are concerned, it is associated with cs, it is only
>>> that while configuring CS, it is propagated such that it is done once.
>>
>> Hmmm ... but here it looks like if write-protect is used you are going
>> to turn it on. A feature like this seems that it does need to be handled
>> by the device's driver. Enabling and disabling write-protect are
>> functions that I would expect are exported to the device's driver and
>> not directly enabled in the gpmc driver during probe. However, maybe is
>> could be valid for the write protect to be enabled by default which
>> could make sense. However, I don't see anywhere else in the driver to
>> control it.
>>
>> Shouldn't we warn on multiple devices trying to use write-protect when
>> parsing their configuration?
> 
> Even if a single device sets write protect, kernel will log it.

That does not seem sufficient. It should be flagged as an error.

Write protect is a resource like the CS and waitpins and so I would have
thought that it should be reserved in the same way.

Jon

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 16:23                     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:23 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Afzal,

On 05/07/2012 05:57 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
>>> As mentioned in the cover letter,
>>>
>>> "Additional features that currently boards in mainline does not make
>>> use of like, waitpin interrupt handling, changes to leverage revision
>>> 6 IP differences has not been incorporated."
>>>
>>> Priority in this series is to convert into a driver, get all boards working
>>> on mainline. Once all boards are working with gpmc driver, these features
>>> which are not required for currently supported boards can be added later.
>>
>> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
>> be marked with a comment like a TODO so it is clear that this needs to
>> be re-visited.
> 
> Ok, it will be marked with TODO
> 
>>>> I think that it make more sense to have the wait-pin information part of
>>>> the gpmc_cs_data structure for the following reasons ...
>>>
>>> Waitpin information is indeed a part of cs as far as boards are concerned,
>>> it is only that it gets propogated to device
>>
>> Why does the device's driver care? From my point of view, the wait-pin
>> is just part of the interface setup/configuration. The external device
>> may require this and assumes that this has been setup along with the CS
>> and interface timing, but the device's driver should not care. Remember
>> this is just a ready signal used to stall the access. Once configured,
>> software should be unaware of it.
> 
> By device, it is referred to gpmc device which only gpmc driver is aware,
> the peripheral device's driver is not at all aware.
> 
>>>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>>>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>>>> register for an active low wait signal.
>>>
>>> Only intention is not to alter default waitpin polarity value, i.e. if
>>> any board does make use of it w/o knowledge of Kernel, I don't want to
>>> break it, there may be an argument saying that the board code is buggy,
>>> while if some board does so, it is, but don't want to break working one.
>>>
>>> Here unless user explicitly set the flag, it does nothing on polarity
>>
>> Ok. Do such scenario's exist today? Please note that board code will be
>> removed in the future and device-tree will replace. So if there are no
>> cases today, I would not be concerned. Unless this could be something
>> that has already been configured by the bootloader. However, in that
>> case would be even call this function?
> 
> Let me check this, here only intent was to play safe, as I have
> only two boards to test.
> 
>>>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>>>
>>>> What scenario is this function used in? May be worth adding a comment
>>>> about the function.
>>>
>>> Ok, it was required for OneNAND, as it needs to reconfigure
>>
>> Ok, but why is that? Unless this is something generic about one-nand I
>> don't comprehend. I have a high-level understanding of one-nand, but I
>> am not familiar with the specifics that require it to be reconfigured.
> 
> Not too familiar with OneNAND, from the code it has been understood
> that to set into sync mode, first it may have to set to async mode, read
> frequency from OneNAND, then setup sync mode for that frequency.
> 
> 
>>>>> +	gpmc_setup_writeprotect(gpmc);
>>>>
>>>> Write protect is a pin and there is only one. Like the waitpins and CS
>>>> signals this needs to be associated with a device. It would make sense
>>>> that this is associated with the cs data.
>>>
>>> As far as platform are concerned, it is associated with cs, it is only
>>> that while configuring CS, it is propagated such that it is done once.
>>
>> Hmmm ... but here it looks like if write-protect is used you are going
>> to turn it on. A feature like this seems that it does need to be handled
>> by the device's driver. Enabling and disabling write-protect are
>> functions that I would expect are exported to the device's driver and
>> not directly enabled in the gpmc driver during probe. However, maybe is
>> could be valid for the write protect to be enabled by default which
>> could make sense. However, I don't see anywhere else in the driver to
>> control it.
>>
>> Shouldn't we warn on multiple devices trying to use write-protect when
>> parsing their configuration?
> 
> Even if a single device sets write protect, kernel will log it.

That does not seem sufficient. It should be flagged as an error.

Write protect is a resource like the CS and waitpins and so I would have
thought that it should be reserved in the same way.

Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-07 16:23                     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-07 16:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/07/2012 05:57 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Fri, May 04, 2012 at 21:50:16, Hunter, Jon wrote:
>>> As mentioned in the cover letter,
>>>
>>> "Additional features that currently boards in mainline does not make
>>> use of like, waitpin interrupt handling, changes to leverage revision
>>> 6 IP differences has not been incorporated."
>>>
>>> Priority in this series is to convert into a driver, get all boards working
>>> on mainline. Once all boards are working with gpmc driver, these features
>>> which are not required for currently supported boards can be added later.
>>
>> Yes, but I meant why 2 and not say 5? Anyway, I think that this should
>> be marked with a comment like a TODO so it is clear that this needs to
>> be re-visited.
> 
> Ok, it will be marked with TODO
> 
>>>> I think that it make more sense to have the wait-pin information part of
>>>> the gpmc_cs_data structure for the following reasons ...
>>>
>>> Waitpin information is indeed a part of cs as far as boards are concerned,
>>> it is only that it gets propogated to device
>>
>> Why does the device's driver care? From my point of view, the wait-pin
>> is just part of the interface setup/configuration. The external device
>> may require this and assumes that this has been setup along with the CS
>> and interface timing, but the device's driver should not care. Remember
>> this is just a ready signal used to stall the access. Once configured,
>> software should be unaware of it.
> 
> By device, it is referred to gpmc device which only gpmc driver is aware,
> the peripheral device's driver is not at all aware.
> 
>>>> Also, any reason why waitpin_polarity is an int? I see you define LOW as
>>>> -1, but I not sure why LOW cannot be 0 as 0 is programmed into the
>>>> register for an active low wait signal.
>>>
>>> Only intention is not to alter default waitpin polarity value, i.e. if
>>> any board does make use of it w/o knowledge of Kernel, I don't want to
>>> break it, there may be an argument saying that the board code is buggy,
>>> while if some board does so, it is, but don't want to break working one.
>>>
>>> Here unless user explicitly set the flag, it does nothing on polarity
>>
>> Ok. Do such scenario's exist today? Please note that board code will be
>> removed in the future and device-tree will replace. So if there are no
>> cases today, I would not be concerned. Unless this could be something
>> that has already been configured by the bootloader. However, in that
>> case would be even call this function?
> 
> Let me check this, here only intent was to play safe, as I have
> only two boards to test.
> 
>>>>> +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
>>>>
>>>> What scenario is this function used in? May be worth adding a comment
>>>> about the function.
>>>
>>> Ok, it was required for OneNAND, as it needs to reconfigure
>>
>> Ok, but why is that? Unless this is something generic about one-nand I
>> don't comprehend. I have a high-level understanding of one-nand, but I
>> am not familiar with the specifics that require it to be reconfigured.
> 
> Not too familiar with OneNAND, from the code it has been understood
> that to set into sync mode, first it may have to set to async mode, read
> frequency from OneNAND, then setup sync mode for that frequency.
> 
> 
>>>>> +	gpmc_setup_writeprotect(gpmc);
>>>>
>>>> Write protect is a pin and there is only one. Like the waitpins and CS
>>>> signals this needs to be associated with a device. It would make sense
>>>> that this is associated with the cs data.
>>>
>>> As far as platform are concerned, it is associated with cs, it is only
>>> that while configuring CS, it is propagated such that it is done once.
>>
>> Hmmm ... but here it looks like if write-protect is used you are going
>> to turn it on. A feature like this seems that it does need to be handled
>> by the device's driver. Enabling and disabling write-protect are
>> functions that I would expect are exported to the device's driver and
>> not directly enabled in the gpmc driver during probe. However, maybe is
>> could be valid for the write protect to be enabled by default which
>> could make sense. However, I don't see anywhere else in the driver to
>> control it.
>>
>> Shouldn't we warn on multiple devices trying to use write-protect when
>> parsing their configuration?
> 
> Even if a single device sets write protect, kernel will log it.

That does not seem sufficient. It should be flagged as an error.

Write protect is a resource like the CS and waitpins and so I would have
thought that it should be reserved in the same way.

Jon

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-07 16:02               ` Jon Hunter
  (?)
@ 2012-05-08  6:18                 ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:18 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Jon,

On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:

> >>> +	/* no waitpin */
> >>> +	case 0:
> >>> +		break;
> >>> +	default:
> >>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> >>> +		return -EINVAL;
> >>> +		break;
> >>> +	}
> >>
> >> Why not combined case 0 and default? Both are invalid configurations so
> >> just report invalid selection.
> > 
> > Case 0 is not invalid, a case where waitpin is not used, default refers
> > to when a user selects multiple waitpins wrongly.
> 
> Ok. Then for case 0, just return here. If the polarity is set, you could
> print an error here.

Different ways of doing things, this looks cleaner to me as already it is
checked, and time of execution in both cases would not differ much.

> >>> +		if (gd->have_waitpin) {
> >>> +			if (gd->waitpin != idx ||
> >>> +					gd->waitpin_polarity != polarity) {
> >>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> >>> +					gd->waitpin, gd->waitpin_polarity,
> >>> +					gd->name, gd->id);
> >>> +				return -EBUSY;
> >>> +			}
> >>> +		} else {
> >>
> >> Don't need the else as you are going to return in the above.
> > 
> > Not always, only in case of error
> 
> Ok, but seems that it can be simplified a little.
> 
> What happens if a device uses more than one wait-pin? In other words a
> device with two chip-selects that uses two wait-pins?

Please re-read http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67702.html
and your reply

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08  6:18                 ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:18 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:

> >>> +	/* no waitpin */
> >>> +	case 0:
> >>> +		break;
> >>> +	default:
> >>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> >>> +		return -EINVAL;
> >>> +		break;
> >>> +	}
> >>
> >> Why not combined case 0 and default? Both are invalid configurations so
> >> just report invalid selection.
> > 
> > Case 0 is not invalid, a case where waitpin is not used, default refers
> > to when a user selects multiple waitpins wrongly.
> 
> Ok. Then for case 0, just return here. If the polarity is set, you could
> print an error here.

Different ways of doing things, this looks cleaner to me as already it is
checked, and time of execution in both cases would not differ much.

> >>> +		if (gd->have_waitpin) {
> >>> +			if (gd->waitpin != idx ||
> >>> +					gd->waitpin_polarity != polarity) {
> >>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> >>> +					gd->waitpin, gd->waitpin_polarity,
> >>> +					gd->name, gd->id);
> >>> +				return -EBUSY;
> >>> +			}
> >>> +		} else {
> >>
> >> Don't need the else as you are going to return in the above.
> > 
> > Not always, only in case of error
> 
> Ok, but seems that it can be simplified a little.
> 
> What happens if a device uses more than one wait-pin? In other words a
> device with two chip-selects that uses two wait-pins?

Please re-read http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67702.html
and your reply

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08  6:18                 ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:

> >>> +	/* no waitpin */
> >>> +	case 0:
> >>> +		break;
> >>> +	default:
> >>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
> >>> +		return -EINVAL;
> >>> +		break;
> >>> +	}
> >>
> >> Why not combined case 0 and default? Both are invalid configurations so
> >> just report invalid selection.
> > 
> > Case 0 is not invalid, a case where waitpin is not used, default refers
> > to when a user selects multiple waitpins wrongly.
> 
> Ok. Then for case 0, just return here. If the polarity is set, you could
> print an error here.

Different ways of doing things, this looks cleaner to me as already it is
checked, and time of execution in both cases would not differ much.

> >>> +		if (gd->have_waitpin) {
> >>> +			if (gd->waitpin != idx ||
> >>> +					gd->waitpin_polarity != polarity) {
> >>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
> >>> +					gd->waitpin, gd->waitpin_polarity,
> >>> +					gd->name, gd->id);
> >>> +				return -EBUSY;
> >>> +			}
> >>> +		} else {
> >>
> >> Don't need the else as you are going to return in the above.
> > 
> > Not always, only in case of error
> 
> Ok, but seems that it can be simplified a little.
> 
> What happens if a device uses more than one wait-pin? In other words a
> device with two chip-selects that uses two wait-pins?

Please re-read http://www.mail-archive.com/linux-omap at vger.kernel.org/msg67702.html
and your reply

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-07 16:12               ` Jon Hunter
  (?)
@ 2012-05-08  6:24                 ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:24 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Jon,

On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:

> > Clk_prd is a platform data passed to the driver, so platform code
> > updates it, where else can it be done ?
> 
> The point is that you can pass what ever you like. You do not need to
> pass the frequency you can pass the clock handle instead.

As clk rate is required in platform code for timing calculation, and
already available, period was passed

> 
> What happens it the clk_get() of the gpmc_l3_clk fails during the init?

Thanks for bringing this point, invalid clk_prd has to be handled by driver.

> 
> In fact if you migrate to runtime pm then we should not have the clk_get
> in the gpmc_init any more.

Even if converted to RPM, to get clk rate, clk_get has to be done
somewhere, right ?

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-08  6:24                 ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:24 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Jon,

On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:

> > Clk_prd is a platform data passed to the driver, so platform code
> > updates it, where else can it be done ?
> 
> The point is that you can pass what ever you like. You do not need to
> pass the frequency you can pass the clock handle instead.

As clk rate is required in platform code for timing calculation, and
already available, period was passed

> 
> What happens it the clk_get() of the gpmc_l3_clk fails during the init?

Thanks for bringing this point, invalid clk_prd has to be handled by driver.

> 
> In fact if you migrate to runtime pm then we should not have the clk_get
> in the gpmc_init any more.

Even if converted to RPM, to get clk rate, clk_get has to be done
somewhere, right ?

Regards
Afzal

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-08  6:24                 ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:

> > Clk_prd is a platform data passed to the driver, so platform code
> > updates it, where else can it be done ?
> 
> The point is that you can pass what ever you like. You do not need to
> pass the frequency you can pass the clock handle instead.

As clk rate is required in platform code for timing calculation, and
already available, period was passed

> 
> What happens it the clk_get() of the gpmc_l3_clk fails during the init?

Thanks for bringing this point, invalid clk_prd has to be handled by driver.

> 
> In fact if you migrate to runtime pm then we should not have the clk_get
> in the gpmc_init any more.

Even if converted to RPM, to get clk rate, clk_get has to be done
somewhere, right ?

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-07 16:23                     ` Jon Hunter
  (?)
@ 2012-05-08  6:27                       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:27 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Jon,

On Mon, May 07, 2012 at 21:53:34, Hunter, Jon wrote:

> >>>> Write protect is a pin and there is only one. Like the waitpins and CS
> >>>> signals this needs to be associated with a device. It would make sense
> >>>> that this is associated with the cs data.
> >>>
> >>> As far as platform are concerned, it is associated with cs, it is only
> >>> that while configuring CS, it is propagated such that it is done once.
> >>
> >> Hmmm ... but here it looks like if write-protect is used you are going
> >> to turn it on. A feature like this seems that it does need to be handled
> >> by the device's driver. Enabling and disabling write-protect are
> >> functions that I would expect are exported to the device's driver and
> >> not directly enabled in the gpmc driver during probe. However, maybe is
> >> could be valid for the write protect to be enabled by default which
> >> could make sense. However, I don't see anywhere else in the driver to
> >> control it.
> >>
> >> Shouldn't we warn on multiple devices trying to use write-protect when
> >> parsing their configuration?
> > 
> > Even if a single device sets write protect, kernel will log it.
> 
> That does not seem sufficient. It should be flagged as an error.
> 
> Write protect is a resource like the CS and waitpins and so I would have
> thought that it should be reserved in the same way.

Isn't it valid for multiple devices to make use of write protect pin ?

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08  6:27                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:27 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Mon, May 07, 2012 at 21:53:34, Hunter, Jon wrote:

> >>>> Write protect is a pin and there is only one. Like the waitpins and CS
> >>>> signals this needs to be associated with a device. It would make sense
> >>>> that this is associated with the cs data.
> >>>
> >>> As far as platform are concerned, it is associated with cs, it is only
> >>> that while configuring CS, it is propagated such that it is done once.
> >>
> >> Hmmm ... but here it looks like if write-protect is used you are going
> >> to turn it on. A feature like this seems that it does need to be handled
> >> by the device's driver. Enabling and disabling write-protect are
> >> functions that I would expect are exported to the device's driver and
> >> not directly enabled in the gpmc driver during probe. However, maybe is
> >> could be valid for the write protect to be enabled by default which
> >> could make sense. However, I don't see anywhere else in the driver to
> >> control it.
> >>
> >> Shouldn't we warn on multiple devices trying to use write-protect when
> >> parsing their configuration?
> > 
> > Even if a single device sets write protect, kernel will log it.
> 
> That does not seem sufficient. It should be flagged as an error.
> 
> Write protect is a resource like the CS and waitpins and so I would have
> thought that it should be reserved in the same way.

Isn't it valid for multiple devices to make use of write protect pin ?

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08  6:27                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08  6:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Mon, May 07, 2012 at 21:53:34, Hunter, Jon wrote:

> >>>> Write protect is a pin and there is only one. Like the waitpins and CS
> >>>> signals this needs to be associated with a device. It would make sense
> >>>> that this is associated with the cs data.
> >>>
> >>> As far as platform are concerned, it is associated with cs, it is only
> >>> that while configuring CS, it is propagated such that it is done once.
> >>
> >> Hmmm ... but here it looks like if write-protect is used you are going
> >> to turn it on. A feature like this seems that it does need to be handled
> >> by the device's driver. Enabling and disabling write-protect are
> >> functions that I would expect are exported to the device's driver and
> >> not directly enabled in the gpmc driver during probe. However, maybe is
> >> could be valid for the write protect to be enabled by default which
> >> could make sense. However, I don't see anywhere else in the driver to
> >> control it.
> >>
> >> Shouldn't we warn on multiple devices trying to use write-protect when
> >> parsing their configuration?
> > 
> > Even if a single device sets write protect, kernel will log it.
> 
> That does not seem sufficient. It should be flagged as an error.
> 
> Write protect is a resource like the CS and waitpins and so I would have
> thought that it should be reserved in the same way.

Isn't it valid for multiple devices to make use of write protect pin ?

Regards
Afzal

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

* RE: [PATCH v4 00/39] OMAP GPMC driver conversion
  2012-05-01 12:19 ` Afzal Mohammed
  (?)
@ 2012-05-08 11:27     ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08 11:27 UTC (permalink / raw)
  To: Mohammed, Afzal, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, Hilman, Kevin, Balbi, Felipe,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

Hi Tony,

On Tue, May 01, 2012 at 17:49:03, Mohammed, Afzal wrote:
> GPMC driver conversion patch series. Some peripherals has GPMC helper
> functions, these has been modified to cater to the needs of GPMC
> driver. All the boards using GPMC has been adapted to use the new
> GPMC driver.
> 
> GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
> spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
> peripherals connected via GPMC are working. Really shaky about OMAP2
> GPMC HWMOD entry. Would be helpful if someone can help me in resolving
> warning on OMAP3 & verify whether OMAP2 entry is proper. The series
> adapts to HWMOD.
> 
> Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
> changes & cleaned up the now unnecessary exported symbol usages.
> 
> This series has been made on top of,
> 5e136da Linux-omap rebuilt: Updated to -rc5,
> A patch by Javier Martinez Canillas <javier-0uQlZySMnqxg9hUCZPvPmw@public.gmane.org>,
> OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
> has also been incorporated into the series as this was necessary for
> igep0020 board.
> 
> This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)


Please let me know your comments on this series.

Regards
Afzal
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* RE: [PATCH v4 00/39] OMAP GPMC driver conversion
@ 2012-05-08 11:27     ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08 11:27 UTC (permalink / raw)
  To: Mohammed, Afzal, tony, linux, Hilman, Kevin, Balbi, Felipe,
	dwmw2, kyungmin.park, gregkh, Menon, Nishanth, grinberg, notasas,
	artem.bityutskiy, vimal.newwork, dbaryshkov, linux-omap,
	linux-arm-kernel, linux-usb, linux-mtd

Hi Tony,

On Tue, May 01, 2012 at 17:49:03, Mohammed, Afzal wrote:
> GPMC driver conversion patch series. Some peripherals has GPMC helper
> functions, these has been modified to cater to the needs of GPMC
> driver. All the boards using GPMC has been adapted to use the new
> GPMC driver.
> 
> GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
> spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
> peripherals connected via GPMC are working. Really shaky about OMAP2
> GPMC HWMOD entry. Would be helpful if someone can help me in resolving
> warning on OMAP3 & verify whether OMAP2 entry is proper. The series
> adapts to HWMOD.
> 
> Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
> changes & cleaned up the now unnecessary exported symbol usages.
> 
> This series has been made on top of,
> 5e136da Linux-omap rebuilt: Updated to -rc5,
> A patch by Javier Martinez Canillas <javier@dowhile0.org>,
> OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
> has also been incorporated into the series as this was necessary for
> igep0020 board.
> 
> This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)


Please let me know your comments on this series.

Regards
Afzal

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

* [PATCH v4 00/39] OMAP GPMC driver conversion
@ 2012-05-08 11:27     ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-08 11:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

On Tue, May 01, 2012 at 17:49:03, Mohammed, Afzal wrote:
> GPMC driver conversion patch series. Some peripherals has GPMC helper
> functions, these has been modified to cater to the needs of GPMC
> driver. All the boards using GPMC has been adapted to use the new
> GPMC driver.
> 
> GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does
> spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but
> peripherals connected via GPMC are working. Really shaky about OMAP2
> GPMC HWMOD entry. Would be helpful if someone can help me in resolving
> warning on OMAP3 & verify whether OMAP2 entry is proper. The series
> adapts to HWMOD.
> 
> Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC
> changes & cleaned up the now unnecessary exported symbol usages.
> 
> This series has been made on top of,
> 5e136da Linux-omap rebuilt: Updated to -rc5,
> A patch by Javier Martinez Canillas <javier@dowhile0.org>,
> OMAP3: igep0020: Add support for Micron NAND Flash storage memory,
> has also been incorporated into the series as this was necessary for
> igep0020 board.
> 
> This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)


Please let me know your comments on this series.

Regards
Afzal

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

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-08  6:18                 ` Mohammed, Afzal
  (?)
@ 2012-05-08 15:08                     ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:08 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hire

Hi  Afzal,

On 05/08/2012 01:18 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:
> 
>>>>> +	/* no waitpin */
>>>>> +	case 0:
>>>>> +		break;
>>>>> +	default:
>>>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>>>> +		return -EINVAL;
>>>>> +		break;
>>>>> +	}
>>>>
>>>> Why not combined case 0 and default? Both are invalid configurations so
>>>> just report invalid selection.
>>>
>>> Case 0 is not invalid, a case where waitpin is not used, default refers
>>> to when a user selects multiple waitpins wrongly.
>>
>> Ok. Then for case 0, just return here. If the polarity is set, you could
>> print an error here.
> 
> Different ways of doing things, this looks cleaner to me as already it is
> checked, and time of execution in both cases would not differ much.

Sure. However, I think that this could be simplified so that it is
easier to read. At a minimum you may wish to add some comments to
explain the purposes of the multi-level if-statements as it is not
intuitive for the reader.

>>>>> +		if (gd->have_waitpin) {
>>>>> +			if (gd->waitpin != idx ||
>>>>> +					gd->waitpin_polarity != polarity) {
>>>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>>>> +					gd->waitpin, gd->waitpin_polarity,
>>>>> +					gd->name, gd->id);
>>>>> +				return -EBUSY;
>>>>> +			}
>>>>> +		} else {
>>>>
>>>> Don't need the else as you are going to return in the above.
>>>
>>> Not always, only in case of error
>>
>> Ok, but seems that it can be simplified a little.
>>
>> What happens if a device uses more than one wait-pin? In other words a
>> device with two chip-selects that uses two wait-pins?
> 
> Please re-read http://www.mail-archive.com/linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg67702.html
> and your reply

Ok thats fine. Sorry for my repeated questions, but I think that this
just highlights that this code is not clear in it purpose. So again may
be some comments would make this all clearer.

Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* Re: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08 15:08                     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:08 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi  Afzal,

On 05/08/2012 01:18 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:
> 
>>>>> +	/* no waitpin */
>>>>> +	case 0:
>>>>> +		break;
>>>>> +	default:
>>>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>>>> +		return -EINVAL;
>>>>> +		break;
>>>>> +	}
>>>>
>>>> Why not combined case 0 and default? Both are invalid configurations so
>>>> just report invalid selection.
>>>
>>> Case 0 is not invalid, a case where waitpin is not used, default refers
>>> to when a user selects multiple waitpins wrongly.
>>
>> Ok. Then for case 0, just return here. If the polarity is set, you could
>> print an error here.
> 
> Different ways of doing things, this looks cleaner to me as already it is
> checked, and time of execution in both cases would not differ much.

Sure. However, I think that this could be simplified so that it is
easier to read. At a minimum you may wish to add some comments to
explain the purposes of the multi-level if-statements as it is not
intuitive for the reader.

>>>>> +		if (gd->have_waitpin) {
>>>>> +			if (gd->waitpin != idx ||
>>>>> +					gd->waitpin_polarity != polarity) {
>>>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>>>> +					gd->waitpin, gd->waitpin_polarity,
>>>>> +					gd->name, gd->id);
>>>>> +				return -EBUSY;
>>>>> +			}
>>>>> +		} else {
>>>>
>>>> Don't need the else as you are going to return in the above.
>>>
>>> Not always, only in case of error
>>
>> Ok, but seems that it can be simplified a little.
>>
>> What happens if a device uses more than one wait-pin? In other words a
>> device with two chip-selects that uses two wait-pins?
> 
> Please re-read http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67702.html
> and your reply

Ok thats fine. Sorry for my repeated questions, but I think that this
just highlights that this code is not clear in it purpose. So again may
be some comments would make this all clearer.

Jon

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-08 15:08                     ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi  Afzal,

On 05/08/2012 01:18 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:32:58, Hunter, Jon wrote:
> 
>>>>> +	/* no waitpin */
>>>>> +	case 0:
>>>>> +		break;
>>>>> +	default:
>>>>> +		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
>>>>> +		return -EINVAL;
>>>>> +		break;
>>>>> +	}
>>>>
>>>> Why not combined case 0 and default? Both are invalid configurations so
>>>> just report invalid selection.
>>>
>>> Case 0 is not invalid, a case where waitpin is not used, default refers
>>> to when a user selects multiple waitpins wrongly.
>>
>> Ok. Then for case 0, just return here. If the polarity is set, you could
>> print an error here.
> 
> Different ways of doing things, this looks cleaner to me as already it is
> checked, and time of execution in both cases would not differ much.

Sure. However, I think that this could be simplified so that it is
easier to read. At a minimum you may wish to add some comments to
explain the purposes of the multi-level if-statements as it is not
intuitive for the reader.

>>>>> +		if (gd->have_waitpin) {
>>>>> +			if (gd->waitpin != idx ||
>>>>> +					gd->waitpin_polarity != polarity) {
>>>>> +				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
>>>>> +					gd->waitpin, gd->waitpin_polarity,
>>>>> +					gd->name, gd->id);
>>>>> +				return -EBUSY;
>>>>> +			}
>>>>> +		} else {
>>>>
>>>> Don't need the else as you are going to return in the above.
>>>
>>> Not always, only in case of error
>>
>> Ok, but seems that it can be simplified a little.
>>
>> What happens if a device uses more than one wait-pin? In other words a
>> device with two chip-selects that uses two wait-pins?
> 
> Please re-read http://www.mail-archive.com/linux-omap at vger.kernel.org/msg67702.html
> and your reply

Ok thats fine. Sorry for my repeated questions, but I think that this
just highlights that this code is not clear in it purpose. So again may
be some comments would make this all clearer.

Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-08  6:24                 ` Mohammed, Afzal
  (?)
@ 2012-05-08 15:13                   ` Jon Hunter
  -1 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:13 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd

Hi Afzal,

On 05/08/2012 01:24 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:
> 
>>> Clk_prd is a platform data passed to the driver, so platform code
>>> updates it, where else can it be done ?
>>
>> The point is that you can pass what ever you like. You do not need to
>> pass the frequency you can pass the clock handle instead.
> 
> As clk rate is required in platform code for timing calculation, and
> already available, period was passed

Sure.

>>
>> What happens it the clk_get() of the gpmc_l3_clk fails during the init?
> 
> Thanks for bringing this point, invalid clk_prd has to be handled by driver.
> 
>>
>> In fact if you migrate to runtime pm then we should not have the clk_get
>> in the gpmc_init any more.
> 
> Even if converted to RPM, to get clk rate, clk_get has to be done
> somewhere, right ?

Yes exactly. However, you could now do this in the driver itself like
the probe function. Or may be just pass the frequency of the gpmc fclk
to the driver and let the driver convert to the period. No reason we
need to convert to the period outside of the driver. Hence, we can keep
the function to do the conversion static in the driver and don't need to
expose externally.

Jon

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

* Re: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-08 15:13                   ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:13 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Afzal,

On 05/08/2012 01:24 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:
> 
>>> Clk_prd is a platform data passed to the driver, so platform code
>>> updates it, where else can it be done ?
>>
>> The point is that you can pass what ever you like. You do not need to
>> pass the frequency you can pass the clock handle instead.
> 
> As clk rate is required in platform code for timing calculation, and
> already available, period was passed

Sure.

>>
>> What happens it the clk_get() of the gpmc_l3_clk fails during the init?
> 
> Thanks for bringing this point, invalid clk_prd has to be handled by driver.
> 
>>
>> In fact if you migrate to runtime pm then we should not have the clk_get
>> in the gpmc_init any more.
> 
> Even if converted to RPM, to get clk rate, clk_get has to be done
> somewhere, right ?

Yes exactly. However, you could now do this in the driver itself like
the probe function. Or may be just pass the frequency of the gpmc fclk
to the driver and let the driver convert to the period. No reason we
need to convert to the period outside of the driver. Hence, we can keep
the function to do the conversion static in the driver and don't need to
expose externally.

Jon

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-08 15:13                   ` Jon Hunter
  0 siblings, 0 replies; 205+ messages in thread
From: Jon Hunter @ 2012-05-08 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Afzal,

On 05/08/2012 01:24 AM, Mohammed, Afzal wrote:
> Hi Jon,
> 
> On Mon, May 07, 2012 at 21:42:35, Hunter, Jon wrote:
> 
>>> Clk_prd is a platform data passed to the driver, so platform code
>>> updates it, where else can it be done ?
>>
>> The point is that you can pass what ever you like. You do not need to
>> pass the frequency you can pass the clock handle instead.
> 
> As clk rate is required in platform code for timing calculation, and
> already available, period was passed

Sure.

>>
>> What happens it the clk_get() of the gpmc_l3_clk fails during the init?
> 
> Thanks for bringing this point, invalid clk_prd has to be handled by driver.
> 
>>
>> In fact if you migrate to runtime pm then we should not have the clk_get
>> in the gpmc_init any more.
> 
> Even if converted to RPM, to get clk rate, clk_get has to be done
> somewhere, right ?

Yes exactly. However, you could now do this in the driver itself like
the probe function. Or may be just pass the frequency of the gpmc fclk
to the driver and let the driver convert to the period. No reason we
need to convert to the period outside of the driver. Hence, we can keep
the function to do the conversion static in the driver and don't need to
expose externally.

Jon

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
  2012-05-08 15:08                     ` Jon Hunter
  (?)
@ 2012-05-10  5:10                       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:10 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony, linux, Hilman, Kevin, Balbi, Felipe, dwmw2, kyungmin.park,
	gregkh, Menon, Nishanth, grinberg, notasas, artem.bityutskiy,
	vimal.newwork, dbaryshkov, linux-omap, linux-arm-kernel,
	linux-usb, linux-mtd, Hire

Hi Jon,

On Tue, May 08, 2012 at 20:38:24, Hunter, Jon wrote:

> > Different ways of doing things, this looks cleaner to me as already it is
> > checked, and time of execution in both cases would not differ much.
> 
> Sure. However, I think that this could be simplified so that it is
> easier to read. At a minimum you may wish to add some comments to
> explain the purposes of the multi-level if-statements as it is not
> intuitive for the reader.

Ok

> >> What happens if a device uses more than one wait-pin? In other words a
> >> device with two chip-selects that uses two wait-pins?
> > 
> > Please re-read http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67702.html
> > and your reply
> 
> Ok thats fine. Sorry for my repeated questions, but I think that this
> just highlights that this code is not clear in it purpose. So again may
> be some comments would make this all clearer.

Ok

Regards
Afzal

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

* RE: [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-10  5:10                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:10 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, Hiremath, Vaibhav,
	vimal.newwork, grinberg, artem.bityutskiy, linux-mtd, linux-omap,
	dwmw2, linux-arm-kernel, notasas

Hi Jon,

On Tue, May 08, 2012 at 20:38:24, Hunter, Jon wrote:

> > Different ways of doing things, this looks cleaner to me as already it is
> > checked, and time of execution in both cases would not differ much.
> 
> Sure. However, I think that this could be simplified so that it is
> easier to read. At a minimum you may wish to add some comments to
> explain the purposes of the multi-level if-statements as it is not
> intuitive for the reader.

Ok

> >> What happens if a device uses more than one wait-pin? In other words a
> >> device with two chip-selects that uses two wait-pins?
> > 
> > Please re-read http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67702.html
> > and your reply
> 
> Ok thats fine. Sorry for my repeated questions, but I think that this
> just highlights that this code is not clear in it purpose. So again may
> be some comments would make this all clearer.

Ok

Regards
Afzal

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

* [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion
@ 2012-05-10  5:10                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Tue, May 08, 2012 at 20:38:24, Hunter, Jon wrote:

> > Different ways of doing things, this looks cleaner to me as already it is
> > checked, and time of execution in both cases would not differ much.
> 
> Sure. However, I think that this could be simplified so that it is
> easier to read. At a minimum you may wish to add some comments to
> explain the purposes of the multi-level if-statements as it is not
> intuitive for the reader.

Ok

> >> What happens if a device uses more than one wait-pin? In other words a
> >> device with two chip-selects that uses two wait-pins?
> > 
> > Please re-read http://www.mail-archive.com/linux-omap at vger.kernel.org/msg67702.html
> > and your reply
> 
> Ok thats fine. Sorry for my repeated questions, but I think that this
> just highlights that this code is not clear in it purpose. So again may
> be some comments would make this all clearer.

Ok

Regards
Afzal

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

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
  2012-05-08 15:13                   ` Jon Hunter
  (?)
@ 2012-05-10  5:17                       ` Mohammed, Afzal
  -1 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:17 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Hilman, Kevin, Balbi, Felipe, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Menon, Nishanth,
	grinberg-UTxiZqZC01RS1MOuV/RT9w, notasas-Re5JQEeQqe8AvxtiuMwx3w,
	artem.bityutskiy-VuQAYsv1563Yd54FQh9/CA,
	vimal.newwork-Re5JQEeQqe8AvxtiuMwx3w,
	dbaryshkov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Jon,

On Tue, May 08, 2012 at 20:43:19, Hunter, Jon wrote:

> >> In fact if you migrate to runtime pm then we should not have the clk_get
> >> in the gpmc_init any more.
> > 
> > Even if converted to RPM, to get clk rate, clk_get has to be done
> > somewhere, right ?
> 
> Yes exactly. However, you could now do this in the driver itself like
> the probe function. Or may be just pass the frequency of the gpmc fclk
> to the driver and let the driver convert to the period. No reason we
> need to convert to the period outside of the driver. Hence, we can keep
> the function to do the conversion static in the driver and don't need to
> expose externally.

But platform need period before driver is probed (for calculating
peripheral timings to be passed for driver)

Regards
Afzal
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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] 205+ messages in thread

* RE: [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-10  5:17                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:17 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: Hilman, Kevin, Menon, Nishanth, linux, tony, gregkh, linux-usb,
	Balbi, Felipe, dbaryshkov, kyungmin.park, vimal.newwork,
	grinberg, artem.bityutskiy, linux-mtd, linux-omap, dwmw2,
	linux-arm-kernel, notasas

Hi Jon,

On Tue, May 08, 2012 at 20:43:19, Hunter, Jon wrote:

> >> In fact if you migrate to runtime pm then we should not have the clk_get
> >> in the gpmc_init any more.
> > 
> > Even if converted to RPM, to get clk rate, clk_get has to be done
> > somewhere, right ?
> 
> Yes exactly. However, you could now do this in the driver itself like
> the probe function. Or may be just pass the frequency of the gpmc fclk
> to the driver and let the driver convert to the period. No reason we
> need to convert to the period outside of the driver. Hence, we can keep
> the function to do the conversion static in the driver and don't need to
> expose externally.

But platform need period before driver is probed (for calculating
peripheral timings to be passed for driver)

Regards
Afzal

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

* [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
@ 2012-05-10  5:17                       ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-10  5:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Tue, May 08, 2012 at 20:43:19, Hunter, Jon wrote:

> >> In fact if you migrate to runtime pm then we should not have the clk_get
> >> in the gpmc_init any more.
> > 
> > Even if converted to RPM, to get clk rate, clk_get has to be done
> > somewhere, right ?
> 
> Yes exactly. However, you could now do this in the driver itself like
> the probe function. Or may be just pass the frequency of the gpmc fclk
> to the driver and let the driver convert to the period. No reason we
> need to convert to the period outside of the driver. Hence, we can keep
> the function to do the conversion static in the driver and don't need to
> expose externally.

But platform need period before driver is probed (for calculating
peripheral timings to be passed for driver)

Regards
Afzal

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

* RE: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-03  8:42       ` Mohammed, Afzal
  (?)
  (?)
@ 2012-05-14 10:33       ` Mohammed, Afzal
  2012-05-15  6:30         ` Thomas Weber
  2012-05-25  9:50         ` Tony Lindgren
  -1 siblings, 2 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-14 10:33 UTC (permalink / raw)
  To: tony; +Cc: artem.bityutskiy, linux-omap, linux-mtd

Hi All,

On Thu, May 03, 2012 at 14:12:11, Mohammed, Afzal wrote:

> > > Some boards depend on bootloader to update chip select value for NAND.
> > > It is felt that Kernel should not depend on bootloader to get CS, as
> > > for a particular board CS is hardwired and is fixed, hence this can
> > > directly be updated in Kernel. But as CS value for boards that depend
> > > on this behaviour is not available, educate gpmc driver to acquire
> > > chip select value for NAND. this ideally should be removed once CS
> > > for those boards are available.
> > 
> > Do you know how many boards require this? If so which are those boards?
> 
> devkit8000, beagle board, omap3touchbook, overo.
> 
> Beagle board, found out to be zero.

I need a help.

Can someone familiar with boards - devkit8000, omap3touchbook, overo boards,
let me know GPMC CS on which NAND is connected.

Hi Tony,

I am planning to provide actual CS # used for NAND on above boards instead of
finding the value at runtime. Is there any reason that NAND CS# is found out
at runtime ? (hence remove necessity of omap_nand_flash_init()).

Presence of this also causes an additional dependency of bootloader.

As CS # depends on wiring on the board, my understanding is that it will be
fixed for a given board. Are you ok if acquiring NAND CS # is removed ?

Removal of this helps in simplifying gpmc driver (undergoing conversion).

Regards
Afzal

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

* Re: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-14 10:33       ` Mohammed, Afzal
@ 2012-05-15  6:30         ` Thomas Weber
  2012-05-15  6:37           ` Mohammed, Afzal
  2012-05-25  9:50         ` Tony Lindgren
  1 sibling, 1 reply; 205+ messages in thread
From: Thomas Weber @ 2012-05-15  6:30 UTC (permalink / raw)
  To: Mohammed, Afzal; +Cc: tony, artem.bityutskiy, linux-omap, linux-mtd

Hello Afzal,

On 05/14/12 12:33, Mohammed, Afzal wrote:
> Hi All,
>
> On Thu, May 03, 2012 at 14:12:11, Mohammed, Afzal wrote:
>
>>>> Some boards depend on bootloader to update chip select value for NAND.
>>>> It is felt that Kernel should not depend on bootloader to get CS, as
>>>> for a particular board CS is hardwired and is fixed, hence this can
>>>> directly be updated in Kernel. But as CS value for boards that depend
>>>> on this behaviour is not available, educate gpmc driver to acquire
>>>> chip select value for NAND. this ideally should be removed once CS
>>>> for those boards are available.
>>> Do you know how many boards require this? If so which are those boards?
>> devkit8000, beagle board, omap3touchbook, overo.
>>
>> Beagle board, found out to be zero.
> I need a help.
>
> Can someone familiar with boards - devkit8000, omap3touchbook, overo boards,
> let me know GPMC CS on which NAND is connected.
On Devkit8000 the NAND is connected to CS0.
I thought that all NAND devices for booting are connected to CS0, 
because of ROM code?

According to spruf98w.pdf:

25.4.7.4 NAND
...
  * The device is connected to CS0.
...

Regards,
Thomas

> Hi Tony,
>
> I am planning to provide actual CS # used for NAND on above boards instead of
> finding the value at runtime. Is there any reason that NAND CS# is found out
> at runtime ? (hence remove necessity of omap_nand_flash_init()).
>
> Presence of this also causes an additional dependency of bootloader.
>
> As CS # depends on wiring on the board, my understanding is that it will be
> fixed for a given board. Are you ok if acquiring NAND CS # is removed ?
>
> Removal of this helps in simplifying gpmc driver (undergoing conversion).
>
> Regards
> Afzal
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* RE: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-15  6:30         ` Thomas Weber
@ 2012-05-15  6:37           ` Mohammed, Afzal
  0 siblings, 0 replies; 205+ messages in thread
From: Mohammed, Afzal @ 2012-05-15  6:37 UTC (permalink / raw)
  To: Thomas Weber; +Cc: tony, artem.bityutskiy, linux-omap, linux-mtd

Hi Thomas,

On Tue, May 15, 2012 at 12:00:32, Thomas Weber wrote:

> > I need a help.
> >
> > Can someone familiar with boards - devkit8000, omap3touchbook, overo boards,
> > let me know GPMC CS on which NAND is connected.
> On Devkit8000 the NAND is connected to CS0.

Thanks for the information

> I thought that all NAND devices for booting are connected to CS0, 
> because of ROM code?
> 
> According to spruf98w.pdf:
> 
> 25.4.7.4 NAND
> ...
>   * The device is connected to CS0.

Yes, expecting they should be, looking for confirmation.

Regards
Afzal

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

* Re: [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
  2012-05-14 10:33       ` Mohammed, Afzal
  2012-05-15  6:30         ` Thomas Weber
@ 2012-05-25  9:50         ` Tony Lindgren
  1 sibling, 0 replies; 205+ messages in thread
From: Tony Lindgren @ 2012-05-25  9:50 UTC (permalink / raw)
  To: Mohammed, Afzal; +Cc: artem.bityutskiy, linux-omap, linux-mtd

* Mohammed, Afzal <afzal@ti.com> [120514 03:37]:
> 
> Hi Tony,
> 
> I am planning to provide actual CS # used for NAND on above boards instead of
> finding the value at runtime. Is there any reason that NAND CS# is found out
> at runtime ? (hence remove necessity of omap_nand_flash_init()).

Yes makes sense. All the board specific data like that should come from
device tree eventually.

Regards,

Tony

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

end of thread, other threads:[~2012-05-25  9:50 UTC | newest]

Thread overview: 205+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-01 12:19 [PATCH v4 00/39] OMAP GPMC driver conversion Afzal Mohammed
2012-05-01 12:19 ` Afzal Mohammed
2012-05-01 12:19 ` Afzal Mohammed
2012-05-01 12:19 ` [PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD Afzal Mohammed
2012-05-01 12:19   ` Afzal Mohammed
2012-05-01 12:19   ` Afzal Mohammed
2012-05-01 20:41   ` Jon Hunter
2012-05-01 20:41     ` Jon Hunter
2012-05-01 20:41     ` Jon Hunter
2012-05-03  8:37     ` Mohammed, Afzal
2012-05-03  8:37       ` Mohammed, Afzal
2012-05-03  8:37       ` Mohammed, Afzal
2012-05-04 16:30       ` Jon Hunter
2012-05-04 16:30         ` Jon Hunter
2012-05-04 16:30         ` Jon Hunter
2012-05-07 11:02         ` Mohammed, Afzal
2012-05-07 11:02           ` Mohammed, Afzal
2012-05-07 11:02           ` Mohammed, Afzal
     [not found]           ` <C8443D0743D26F4388EA172BF4E2A7A93E987159-Er742YJ7I/eIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2012-05-07 16:12             ` Jon Hunter
2012-05-07 16:12               ` Jon Hunter
2012-05-07 16:12               ` Jon Hunter
2012-05-08  6:24               ` Mohammed, Afzal
2012-05-08  6:24                 ` Mohammed, Afzal
2012-05-08  6:24                 ` Mohammed, Afzal
2012-05-08 15:13                 ` Jon Hunter
2012-05-08 15:13                   ` Jon Hunter
2012-05-08 15:13                   ` Jon Hunter
     [not found]                   ` <4FA9380F.90700-l0cyMroinI0@public.gmane.org>
2012-05-10  5:17                     ` Mohammed, Afzal
2012-05-10  5:17                       ` Mohammed, Afzal
2012-05-10  5:17                       ` Mohammed, Afzal
2012-05-01 12:20 ` [PATCH v4 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 21:16   ` Jon Hunter
2012-05-01 21:16     ` Jon Hunter
2012-05-01 21:16     ` Jon Hunter
2012-05-03  8:42     ` Mohammed, Afzal
2012-05-03  8:42       ` Mohammed, Afzal
2012-05-03  8:42       ` Mohammed, Afzal
2012-05-14 10:33       ` Mohammed, Afzal
2012-05-15  6:30         ` Thomas Weber
2012-05-15  6:37           ` Mohammed, Afzal
2012-05-25  9:50         ` Tony Lindgren
2012-05-01 12:20 ` [PATCH v4 05/39] ARM: OMAP2+: nand: create platform data structure Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20 ` [PATCH v4 06/39] ARM: OMAP2+: onenand: return value in init function Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 16:49   ` Sergei Shtylyov
2012-05-01 16:49     ` Sergei Shtylyov
2012-05-01 16:49     ` Sergei Shtylyov
2012-05-03  8:54     ` Mohammed, Afzal
2012-05-03  8:54       ` Mohammed, Afzal
2012-05-03  8:54       ` Mohammed, Afzal
2012-05-01 12:20 ` [PATCH v4 08/39] ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20 ` [PATCH v4 10/39] ARM: OMAP2+: gpmc-smsc911x: " Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20 ` [PATCH v4 11/39] ARM: OMAP2+: gpmc-smc91x: " Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:20   ` Afzal Mohammed
2012-05-01 12:21 ` [PATCH v4 12/39] ARM: OMAP2+: gpmc-tusb6010: Adapt to " Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21 ` [PATCH v4 13/39] ARM: OMAP3: hwmod data: add gpmc Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
     [not found]   ` <1d1a0ae293834061a15f1b19f903b81bfa01befc.1335874494.git.afzal-l0cyMroinI0@public.gmane.org>
2012-05-06  2:09     ` Paul Walmsley
2012-05-06  2:09       ` Paul Walmsley
2012-05-06  2:09       ` Paul Walmsley
2012-05-01 12:21 ` [PATCH v4 14/39] ARM: OMAP2xxx: " Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-06  2:09   ` Paul Walmsley
2012-05-06  2:09     ` Paul Walmsley
2012-05-06  2:09     ` Paul Walmsley
2012-05-01 12:21 ` [PATCH v4 17/39] mtd: nand: omap2: handle nand on gpmc Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21 ` [PATCH v4 19/39] ARM: OMAP2+: board omap3evm: gpmc driver adaptation Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
2012-05-01 12:21   ` Afzal Mohammed
     [not found] ` <cover.1335874494.git.afzal-l0cyMroinI0@public.gmane.org>
2012-05-01 12:19   ` [PATCH v4 01/39] ARM: OMAP2+: gpmc: driver conversion Afzal Mohammed
2012-05-01 12:19     ` Afzal Mohammed
2012-05-01 12:19     ` Afzal Mohammed
     [not found]     ` <363273a9ef82d6836197929157aa9a8eb8f5171a.1335874494.git.afzal-l0cyMroinI0@public.gmane.org>
2012-05-01 17:53       ` Jon Hunter
2012-05-01 17:53         ` Jon Hunter
2012-05-01 17:53         ` Jon Hunter
     [not found]         ` <4FA022FC.5040703-l0cyMroinI0@public.gmane.org>
2012-05-03  8:23           ` Mohammed, Afzal
2012-05-03  8:23             ` Mohammed, Afzal
2012-05-03  8:23             ` Mohammed, Afzal
     [not found]             ` <C8443D0743D26F4388EA172BF4E2A7A93E982967-Er742YJ7I/eIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2012-05-04 16:20               ` Jon Hunter
2012-05-04 16:20                 ` Jon Hunter
2012-05-04 16:20                 ` Jon Hunter
2012-05-07 10:57                 ` Mohammed, Afzal
2012-05-07 10:57                   ` Mohammed, Afzal
2012-05-07 10:57                   ` Mohammed, Afzal
2012-05-07 16:23                   ` Jon Hunter
2012-05-07 16:23                     ` Jon Hunter
2012-05-07 16:23                     ` Jon Hunter
2012-05-08  6:27                     ` Mohammed, Afzal
2012-05-08  6:27                       ` Mohammed, Afzal
2012-05-08  6:27                       ` Mohammed, Afzal
2012-05-04 16:27       ` Jon Hunter
2012-05-04 16:27         ` Jon Hunter
2012-05-04 16:27         ` Jon Hunter
     [not found]         ` <4FA4035E.6020308-l0cyMroinI0@public.gmane.org>
2012-05-07 11:01           ` Mohammed, Afzal
2012-05-07 11:01             ` Mohammed, Afzal
2012-05-07 11:01             ` Mohammed, Afzal
2012-05-07 16:02             ` Jon Hunter
2012-05-07 16:02               ` Jon Hunter
2012-05-07 16:02               ` Jon Hunter
2012-05-08  6:18               ` Mohammed, Afzal
2012-05-08  6:18                 ` Mohammed, Afzal
2012-05-08  6:18                 ` Mohammed, Afzal
     [not found]                 ` <C8443D0743D26F4388EA172BF4E2A7A93E9878EC-Er742YJ7I/eIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2012-05-08 15:08                   ` Jon Hunter
2012-05-08 15:08                     ` Jon Hunter
2012-05-08 15:08                     ` Jon Hunter
2012-05-10  5:10                     ` Mohammed, Afzal
2012-05-10  5:10                       ` Mohammed, Afzal
2012-05-10  5:10                       ` Mohammed, Afzal
2012-05-01 12:19   ` [PATCH v4 03/39] ARM: OMAP2+: gpmc: register details for nand driver Afzal Mohammed
2012-05-01 12:19     ` Afzal Mohammed
2012-05-01 12:19     ` Afzal Mohammed
2012-05-01 12:20   ` [PATCH v4 07/39] ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver Afzal Mohammed
2012-05-01 12:20     ` Afzal Mohammed
2012-05-01 12:20     ` Afzal Mohammed
2012-05-01 12:20   ` [PATCH v4 09/39] ARM: OMAP2+: flash: Adapt to " Afzal Mohammed
2012-05-01 12:20     ` Afzal Mohammed
2012-05-01 12:20     ` Afzal Mohammed
2012-05-01 12:21   ` [PATCH v4 15/39] mtd: nand: omap2: obtain memory from resource Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21   ` [PATCH v4 16/39] mtd: nand: omap2: use gpmc provided irqs Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21   ` [PATCH v4 18/39] mtd: onenand: omap: obtain memory from resource Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21   ` [PATCH v4 20/39] ARM: OMAP2+: board omap3beagle: gpmc driver adaptation Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:21     ` Afzal Mohammed
2012-05-01 12:22   ` [PATCH v4 21/39] ARM: OMAP2+: board apollon: " Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22   ` [PATCH v4 22/39] ARM: OMAP2+: board h4: " Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22   ` [PATCH v4 28/39] ARM: OMAP2+: board ldp: " Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22   ` [PATCH v4 29/39] ARM: OMAP2+: board n8x0: " Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:22     ` Afzal Mohammed
2012-05-01 12:23   ` [PATCH v4 30/39] ARM: OMAP2+: board omap3logic: " Afzal Mohammed
2012-05-01 12:23     ` Afzal Mohammed
2012-05-01 12:23     ` Afzal Mohammed
2012-05-01 12:23   ` [PATCH v4 34/39] ARM: OMAP2+: board overo: " Afzal Mohammed
2012-05-01 12:23     ` Afzal Mohammed
2012-05-01 12:23     ` Afzal Mohammed
2012-05-08 11:27   ` [PATCH v4 00/39] OMAP GPMC driver conversion Mohammed, Afzal
2012-05-08 11:27     ` Mohammed, Afzal
2012-05-08 11:27     ` Mohammed, Afzal
2012-05-01 12:22 ` [PATCH v4 23/39] ARM: OMAP2+: board 3630sdp: gpmc driver adaptation Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22 ` [PATCH v4 24/39] ARM: OMAP2+: board 3430sdp: " Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22 ` [PATCH v4 25/39] ARM: OMAP2+: board 2430sdp: " Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22 ` [PATCH v4 26/39] ARM: OMAP2+: board cm-t3517: " Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22 ` [PATCH v4 27/39] ARM: OMAP2+: board cm-t35: " Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:22   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 31/39] ARM: OMAP2+: board omap3pandora: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 32/39] ARM: OMAP2+: board omap3stalker: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 33/39] ARM: OMAP2+: board omap4pcm049: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 35/39] ARM: OMAP2+: board rm680: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 36/39] ARM: OMAP2+: board rx51: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 37/39] ARM: OMAP2+: board zoom-debugboard: " Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 38/39] OMAP3: igep0020: Add support for Micron NAND Flash storage memory Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23 ` [PATCH v4 39/39] ARM: OMAP2+: board igep0020: gpmc driver adaptation Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed
2012-05-01 12:23   ` Afzal Mohammed

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.