All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/11] Update support for MPC512x
@ 2010-01-19 20:24 ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A
  Cc: dzu-ynQEQJNshbs, wd-ynQEQJNshbs, Anatolij Gustschin,
	Grant Likely, John Rigby, Dan Williams,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

The following patch series brings support for the Freescale MPC512x
processsors up to date:

[PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
[PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
[PATCH 03/11] powerpc/mpc5121: Add machine restart support
[PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
[PATCH 05/11] rtc: Add MPC5121 Real time clock driver
[PATCH 06/11] mtd: Add NAND Flash Controller driver
[PATCH 07/11] dma: Add MPC512x DMA driver
[PATCH 08/11] powerpc/mpc5121: add USB host support
[PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support
[PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS
[PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS

The patches are based on v2.6.33-rc4 and cover the following
items:

- platform, DTS
- DMA
- FEC Ethernet
- UART (without h/w flow control)
- I2C
- NAND
- RTC

The code has been tested on the Freescale/STX "MPC5121ADS" board
(board rev. 4) with a MPC5121e Rev. 2. No attempt was made to provide
backward compatibility to older silicon revisions or older revisions
of the board.

Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: John Rigby <jcrigby-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: <rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org>
Cc: <linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Cc: <linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
---
 Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 +
 arch/powerpc/boot/dts/mpc5121ads.dts           |   35 +-
 arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++++++++++
 arch/powerpc/include/asm/mpc5xxx.h             |   14 +-
 arch/powerpc/platforms/512x/Kconfig            |    6 +
 arch/powerpc/platforms/512x/Makefile           |    2 +-
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    9 +
 arch/powerpc/platforms/512x/mpc5121_generic.c  |   13 +
 arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++
 arch/powerpc/platforms/512x/mpc512x.h          |    5 +
 arch/powerpc/platforms/512x/mpc512x_shared.c   |  320 +++++-
 arch/powerpc/sysdev/fsl_soc.c                  |   10 +
 arch/powerpc/sysdev/fsl_soc.h                  |   10 +
 drivers/dma/Kconfig                            |    7 +
 drivers/dma/Makefile                           |    1 +
 drivers/dma/mpc512x_dma.c                      |  636 +++++++++
 drivers/dma/mpc512x_dma.h                      |  192 +++
 drivers/i2c/busses/Kconfig                     |    9 +-
 drivers/i2c/busses/i2c-mpc.c                   |   23 +
 drivers/mtd/nand/Kconfig                       |    7 +
 drivers/mtd/nand/Makefile                      |    1 +
 drivers/mtd/nand/mpc5121_nfc.c                 |  916 +++++++++++++
 drivers/net/fs_enet/Kconfig                    |   10 +-
 drivers/net/fs_enet/fs_enet-main.c             |   43 +
 drivers/net/fs_enet/fs_enet.h                  |   40 +-
 drivers/net/fs_enet/mac-fec.c                  |  132 ++-
 drivers/net/fs_enet/mii-fec.c                  |   55 +-
 drivers/net/fs_enet/mpc5121_fec.h              |   64 +
 drivers/net/fs_enet/mpc8xx_fec.h               |   37 +
 drivers/rtc/Kconfig                            |   10 +
 drivers/rtc/Makefile                           |    1 +
 drivers/rtc/rtc-mpc5121.c                      |  408 ++++++
 drivers/usb/host/ehci-fsl.c                    |  213 +++-
 drivers/usb/host/ehci-fsl.h                    |   19 +-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/video/fsl-diu-fb.c                     |   40 +-
 drivers/video/fsl-diu-fb.h                     |  223 ----
 include/linux/fsl-diu-fb.h                     |  223 ++++
 include/linux/fsl_devices.h                    |   10 +
 39 files changed, 5193 insertions(+), 340 deletions(-)
--
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] 62+ messages in thread

* [PATCH 0/11] Update support for MPC512x
@ 2010-01-19 20:24 ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A
  Cc: dzu-ynQEQJNshbs, wd-ynQEQJNshbs, Anatolij Gustschin,
	Grant Likely, John Rigby, Dan Williams,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

The following patch series brings support for the Freescale MPC512x
processsors up to date:

[PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
[PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
[PATCH 03/11] powerpc/mpc5121: Add machine restart support
[PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
[PATCH 05/11] rtc: Add MPC5121 Real time clock driver
[PATCH 06/11] mtd: Add NAND Flash Controller driver
[PATCH 07/11] dma: Add MPC512x DMA driver
[PATCH 08/11] powerpc/mpc5121: add USB host support
[PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support
[PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS
[PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS

The patches are based on v2.6.33-rc4 and cover the following
items:

- platform, DTS
- DMA
- FEC Ethernet
- UART (without h/w flow control)
- I2C
- NAND
- RTC

The code has been tested on the Freescale/STX "MPC5121ADS" board
(board rev. 4) with a MPC5121e Rev. 2. No attempt was made to provide
backward compatibility to older silicon revisions or older revisions
of the board.

Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: John Rigby <jcrigby-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: <rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org>
Cc: <linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Cc: <linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
---
 Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 +
 arch/powerpc/boot/dts/mpc5121ads.dts           |   35 +-
 arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++++++++++
 arch/powerpc/include/asm/mpc5xxx.h             |   14 +-
 arch/powerpc/platforms/512x/Kconfig            |    6 +
 arch/powerpc/platforms/512x/Makefile           |    2 +-
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    9 +
 arch/powerpc/platforms/512x/mpc5121_generic.c  |   13 +
 arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++
 arch/powerpc/platforms/512x/mpc512x.h          |    5 +
 arch/powerpc/platforms/512x/mpc512x_shared.c   |  320 +++++-
 arch/powerpc/sysdev/fsl_soc.c                  |   10 +
 arch/powerpc/sysdev/fsl_soc.h                  |   10 +
 drivers/dma/Kconfig                            |    7 +
 drivers/dma/Makefile                           |    1 +
 drivers/dma/mpc512x_dma.c                      |  636 +++++++++
 drivers/dma/mpc512x_dma.h                      |  192 +++
 drivers/i2c/busses/Kconfig                     |    9 +-
 drivers/i2c/busses/i2c-mpc.c                   |   23 +
 drivers/mtd/nand/Kconfig                       |    7 +
 drivers/mtd/nand/Makefile                      |    1 +
 drivers/mtd/nand/mpc5121_nfc.c                 |  916 +++++++++++++
 drivers/net/fs_enet/Kconfig                    |   10 +-
 drivers/net/fs_enet/fs_enet-main.c             |   43 +
 drivers/net/fs_enet/fs_enet.h                  |   40 +-
 drivers/net/fs_enet/mac-fec.c                  |  132 ++-
 drivers/net/fs_enet/mii-fec.c                  |   55 +-
 drivers/net/fs_enet/mpc5121_fec.h              |   64 +
 drivers/net/fs_enet/mpc8xx_fec.h               |   37 +
 drivers/rtc/Kconfig                            |   10 +
 drivers/rtc/Makefile                           |    1 +
 drivers/rtc/rtc-mpc5121.c                      |  408 ++++++
 drivers/usb/host/ehci-fsl.c                    |  213 +++-
 drivers/usb/host/ehci-fsl.h                    |   19 +-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/video/fsl-diu-fb.c                     |   40 +-
 drivers/video/fsl-diu-fb.h                     |  223 ----
 include/linux/fsl-diu-fb.h                     |  223 ++++
 include/linux/fsl_devices.h                    |   10 +
 39 files changed, 5193 insertions(+), 340 deletions(-)
--
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] 62+ messages in thread

* [PATCH 0/11] Update support for MPC512x
@ 2010-01-19 20:24 ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: wd, dzu, netdev, linux-usb, linux-mtd, linux-i2c, rtc-linux,
	Dan Williams, Anatolij Gustschin

The following patch series brings support for the Freescale MPC512x
processsors up to date:

[PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
[PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
[PATCH 03/11] powerpc/mpc5121: Add machine restart support
[PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
[PATCH 05/11] rtc: Add MPC5121 Real time clock driver
[PATCH 06/11] mtd: Add NAND Flash Controller driver
[PATCH 07/11] dma: Add MPC512x DMA driver
[PATCH 08/11] powerpc/mpc5121: add USB host support
[PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support
[PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS
[PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS

The patches are based on v2.6.33-rc4 and cover the following
items:

- platform, DTS
- DMA
- FEC Ethernet
- UART (without h/w flow control)
- I2C
- NAND
- RTC

The code has been tested on the Freescale/STX "MPC5121ADS" board
(board rev. 4) with a MPC5121e Rev. 2. No attempt was made to provide
backward compatibility to older silicon revisions or older revisions
of the board.

Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: <netdev@vger.kernel.org>
Cc: <linux-i2c@vger.kernel.org>
Cc: <rtc-linux@googlegroups.com>
Cc: <linux-mtd@lists.infradead.org>
Cc: <linux-usb@vger.kernel.org>
---
 Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 +
 arch/powerpc/boot/dts/mpc5121ads.dts           |   35 +-
 arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++++++++++
 arch/powerpc/include/asm/mpc5xxx.h             |   14 +-
 arch/powerpc/platforms/512x/Kconfig            |    6 +
 arch/powerpc/platforms/512x/Makefile           |    2 +-
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    9 +
 arch/powerpc/platforms/512x/mpc5121_generic.c  |   13 +
 arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++
 arch/powerpc/platforms/512x/mpc512x.h          |    5 +
 arch/powerpc/platforms/512x/mpc512x_shared.c   |  320 +++++-
 arch/powerpc/sysdev/fsl_soc.c                  |   10 +
 arch/powerpc/sysdev/fsl_soc.h                  |   10 +
 drivers/dma/Kconfig                            |    7 +
 drivers/dma/Makefile                           |    1 +
 drivers/dma/mpc512x_dma.c                      |  636 +++++++++
 drivers/dma/mpc512x_dma.h                      |  192 +++
 drivers/i2c/busses/Kconfig                     |    9 +-
 drivers/i2c/busses/i2c-mpc.c                   |   23 +
 drivers/mtd/nand/Kconfig                       |    7 +
 drivers/mtd/nand/Makefile                      |    1 +
 drivers/mtd/nand/mpc5121_nfc.c                 |  916 +++++++++++++
 drivers/net/fs_enet/Kconfig                    |   10 +-
 drivers/net/fs_enet/fs_enet-main.c             |   43 +
 drivers/net/fs_enet/fs_enet.h                  |   40 +-
 drivers/net/fs_enet/mac-fec.c                  |  132 ++-
 drivers/net/fs_enet/mii-fec.c                  |   55 +-
 drivers/net/fs_enet/mpc5121_fec.h              |   64 +
 drivers/net/fs_enet/mpc8xx_fec.h               |   37 +
 drivers/rtc/Kconfig                            |   10 +
 drivers/rtc/Makefile                           |    1 +
 drivers/rtc/rtc-mpc5121.c                      |  408 ++++++
 drivers/usb/host/ehci-fsl.c                    |  213 +++-
 drivers/usb/host/ehci-fsl.h                    |   19 +-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/video/fsl-diu-fb.c                     |   40 +-
 drivers/video/fsl-diu-fb.h                     |  223 ----
 include/linux/fsl-diu-fb.h                     |  223 ++++
 include/linux/fsl_devices.h                    |   10 +
 39 files changed, 5193 insertions(+), 340 deletions(-)

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

* [PATCH 0/11] Update support for MPC512x
@ 2010-01-19 20:24 ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: John Rigby, dzu, netdev, linux-usb, Grant Likely, linux-mtd,
	linux-i2c, rtc-linux, Dan Williams, Anatolij Gustschin

The following patch series brings support for the Freescale MPC512x
processsors up to date:

[PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
[PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
[PATCH 03/11] powerpc/mpc5121: Add machine restart support
[PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
[PATCH 05/11] rtc: Add MPC5121 Real time clock driver
[PATCH 06/11] mtd: Add NAND Flash Controller driver
[PATCH 07/11] dma: Add MPC512x DMA driver
[PATCH 08/11] powerpc/mpc5121: add USB host support
[PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support
[PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS
[PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS

The patches are based on v2.6.33-rc4 and cover the following
items:

- platform, DTS
- DMA
- FEC Ethernet
- UART (without h/w flow control)
- I2C
- NAND
- RTC

The code has been tested on the Freescale/STX "MPC5121ADS" board
(board rev. 4) with a MPC5121e Rev. 2. No attempt was made to provide
backward compatibility to older silicon revisions or older revisions
of the board.

Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: <netdev@vger.kernel.org>
Cc: <linux-i2c@vger.kernel.org>
Cc: <rtc-linux@googlegroups.com>
Cc: <linux-mtd@lists.infradead.org>
Cc: <linux-usb@vger.kernel.org>
---
 Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 +
 arch/powerpc/boot/dts/mpc5121ads.dts           |   35 +-
 arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++++++++++
 arch/powerpc/include/asm/mpc5xxx.h             |   14 +-
 arch/powerpc/platforms/512x/Kconfig            |    6 +
 arch/powerpc/platforms/512x/Makefile           |    2 +-
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    9 +
 arch/powerpc/platforms/512x/mpc5121_generic.c  |   13 +
 arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++
 arch/powerpc/platforms/512x/mpc512x.h          |    5 +
 arch/powerpc/platforms/512x/mpc512x_shared.c   |  320 +++++-
 arch/powerpc/sysdev/fsl_soc.c                  |   10 +
 arch/powerpc/sysdev/fsl_soc.h                  |   10 +
 drivers/dma/Kconfig                            |    7 +
 drivers/dma/Makefile                           |    1 +
 drivers/dma/mpc512x_dma.c                      |  636 +++++++++
 drivers/dma/mpc512x_dma.h                      |  192 +++
 drivers/i2c/busses/Kconfig                     |    9 +-
 drivers/i2c/busses/i2c-mpc.c                   |   23 +
 drivers/mtd/nand/Kconfig                       |    7 +
 drivers/mtd/nand/Makefile                      |    1 +
 drivers/mtd/nand/mpc5121_nfc.c                 |  916 +++++++++++++
 drivers/net/fs_enet/Kconfig                    |   10 +-
 drivers/net/fs_enet/fs_enet-main.c             |   43 +
 drivers/net/fs_enet/fs_enet.h                  |   40 +-
 drivers/net/fs_enet/mac-fec.c                  |  132 ++-
 drivers/net/fs_enet/mii-fec.c                  |   55 +-
 drivers/net/fs_enet/mpc5121_fec.h              |   64 +
 drivers/net/fs_enet/mpc8xx_fec.h               |   37 +
 drivers/rtc/Kconfig                            |   10 +
 drivers/rtc/Makefile                           |    1 +
 drivers/rtc/rtc-mpc5121.c                      |  408 ++++++
 drivers/usb/host/ehci-fsl.c                    |  213 +++-
 drivers/usb/host/ehci-fsl.h                    |   19 +-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/video/fsl-diu-fb.c                     |   40 +-
 drivers/video/fsl-diu-fb.h                     |  223 ----
 include/linux/fsl-diu-fb.h                     |  223 ++++
 include/linux/fsl_devices.h                    |   10 +
 39 files changed, 5193 insertions(+), 340 deletions(-)

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

* [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
  2010-01-19 20:24 ` Anatolij Gustschin
@ 2010-01-19 20:24   ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: dzu, wd, Anatolij Gustschin, John Rigby, Piotr Ziecik, netdev,
	Grant Likely, John Rigby

    drivers/net/fs_enet/*
        Enable fs_enet driver to work 5121 FEC
        Enable it with CONFIG_FS_ENET_MPC5121_FEC

Signed-off-by: John Rigby <jrigby@freescale.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <netdev@vger.kernel.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/net/fs_enet/Kconfig        |   10 ++-
 drivers/net/fs_enet/fs_enet-main.c |    4 +
 drivers/net/fs_enet/fs_enet.h      |   40 +++++++++++-
 drivers/net/fs_enet/mac-fec.c      |  132 +++++++++++++++++++++++++++++-------
 drivers/net/fs_enet/mii-fec.c      |   55 +++++++++++-----
 drivers/net/fs_enet/mpc5121_fec.h  |   64 +++++++++++++++++
 drivers/net/fs_enet/mpc8xx_fec.h   |   37 ++++++++++
 7 files changed, 297 insertions(+), 45 deletions(-)
 create mode 100644 drivers/net/fs_enet/mpc5121_fec.h
 create mode 100644 drivers/net/fs_enet/mpc8xx_fec.h

diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 562ea68..fc073b5 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,9 +1,13 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on CPM1 || CPM2
+       depends on CPM1 || CPM2 || PPC_MPC512x
        select MII
        select PHYLIB
 
+config FS_ENET_MPC5121_FEC
+	def_bool y if (FS_ENET && PPC_MPC512x)
+	select FS_ENET_HAS_FEC
+
 config FS_ENET_HAS_SCC
 	bool "Chip has an SCC usable for ethernet"
 	depends on FS_ENET && (CPM1 || CPM2)
@@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC
 
 config FS_ENET_HAS_FEC
 	bool "Chip has an FEC usable for ethernet"
-	depends on FS_ENET && CPM1
+	depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
 	select FS_ENET_MDIO_FEC
 	default y
 
 config FS_ENET_MDIO_FEC
 	tristate "MDIO driver for FEC"
-	depends on FS_ENET && CPM1
+	depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
 
 config FS_ENET_MDIO_FCC
 	tristate "MDIO driver for FCC"
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index ec2f503..909b78d 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1104,6 +1104,10 @@ static struct of_device_id fs_enet_match[] = {
 #endif
 #ifdef CONFIG_FS_ENET_HAS_FEC
 	{
+		.compatible = "fsl,mpc5121-fec",
+		.data = (void *)&fs_fec_ops,
+	},
+	{
 		.compatible = "fsl,pq1-fec-enet",
 		.data = (void *)&fs_fec_ops,
 	},
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index ef01e09..577a352 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -13,11 +13,47 @@
 
 #ifdef CONFIG_CPM1
 #include <asm/cpm1.h>
+#endif
+
+#if defined(CONFIG_FS_ENET_HAS_FEC)
+#include <asm/cpm.h>
+#include "mpc8xx_fec.h"
+#include "mpc5121_fec.h"
 
 struct fec_info {
-	fec_t __iomem *fecp;
+	void __iomem *fecp;
+	void __iomem *fec_r_cntrl;
+	void __iomem *fec_ecntrl;
+	void __iomem *fec_ievent;
+	void __iomem *fec_mii_data;
+	void __iomem *fec_mii_speed;
 	u32 mii_speed;
 };
+
+struct reg_tbl {
+	void __iomem *fec_ievent;
+	void __iomem *fec_imask;
+	void __iomem *fec_r_des_active;
+	void __iomem *fec_x_des_active;
+	void __iomem *fec_r_des_start;
+	void __iomem *fec_x_des_start;
+	void __iomem *fec_r_cntrl;
+	void __iomem *fec_ecntrl;
+	void __iomem *fec_ivec;
+	void __iomem *fec_mii_speed;
+	void __iomem *fec_addr_low;
+	void __iomem *fec_addr_high;
+	void __iomem *fec_hash_table_high;
+	void __iomem *fec_hash_table_low;
+	void __iomem *fec_r_buff_size;
+	void __iomem *fec_r_bound;
+	void __iomem *fec_r_fstart;
+	void __iomem *fec_x_fstart;
+	void __iomem *fec_fun_code;
+	void __iomem *fec_r_hash;
+	void __iomem *fec_x_cntrl;
+	void __iomem *fec_dma_control;
+};
 #endif
 
 #ifdef CONFIG_CPM2
@@ -113,7 +149,9 @@ struct fs_enet_private {
 		struct {
 			int idx;		/* FEC1 = 0, FEC2 = 1  */
 			void __iomem *fecp;	/* hw registers        */
+			struct reg_tbl *rtbl;	/* used registers table */
 			u32 hthi, htlo;		/* state for multicast */
+			u32 fec_id;
 		} fec;
 
 		struct {
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index ca7bcb8..4a5d5ca 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -64,10 +64,10 @@
 #endif
 
 /* write */
-#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
+#define FW(_fecp, _reg, _v) __fs_out32((_fecp)->fec_ ## _reg, (_v))
 
 /* read */
-#define FR(_fecp, _reg)	__fs_in32(&(_fecp)->fec_ ## _reg)
+#define FR(_fecp, _reg)	__fs_in32((_fecp)->fec_ ## _reg)
 
 /* set bits */
 #define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
@@ -75,12 +75,23 @@
 /* clear bits */
 #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
 
+/* register address macros */
+#define fec_reg_addr(_type, _reg) \
+	(fep->fec.rtbl->fec_##_reg = \
+		fep->fec.fecp + (int)&((__typeof__(_type) *)NULL)->fec_##_reg)
+
+#define fec_reg_mpc8xx(_reg) \
+	fec_reg_addr(struct mpc8xx_fec, _reg)
+
+#define fec_reg_mpc5121(_reg) \
+	fec_reg_addr(struct mpc5121_fec, _reg)
+
 /*
  * Delay to wait for FEC reset command to complete (in us)
  */
 #define FEC_RESET_DELAY		50
 
-static int whack_reset(fec_t __iomem *fecp)
+static int whack_reset(struct reg_tbl *fecp)
 {
 	int i;
 
@@ -106,6 +117,50 @@ static int do_pd_setup(struct fs_enet_private *fep)
 	if (!fep->fcc.fccp)
 		return -EINVAL;
 
+	fep->fec.rtbl = kzalloc(sizeof(*fep->fec.rtbl), GFP_KERNEL);
+	if (!fep->fec.rtbl) {
+		iounmap(fep->fec.fecp);
+		return -ENOMEM;
+	}
+
+	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec")) {
+		fep->fec.fec_id = FS_ENET_MPC5121_FEC;
+		fec_reg_mpc5121(ievent);
+		fec_reg_mpc5121(imask);
+		fec_reg_mpc5121(r_cntrl);
+		fec_reg_mpc5121(ecntrl);
+		fec_reg_mpc5121(r_des_active);
+		fec_reg_mpc5121(x_des_active);
+		fec_reg_mpc5121(r_des_start);
+		fec_reg_mpc5121(x_des_start);
+		fec_reg_mpc5121(addr_low);
+		fec_reg_mpc5121(addr_high);
+		fec_reg_mpc5121(hash_table_high);
+		fec_reg_mpc5121(hash_table_low);
+		fec_reg_mpc5121(r_buff_size);
+		fec_reg_mpc5121(mii_speed);
+		fec_reg_mpc5121(x_cntrl);
+		fec_reg_mpc5121(dma_control);
+	} else {
+		fec_reg_mpc8xx(ievent);
+		fec_reg_mpc8xx(imask);
+		fec_reg_mpc8xx(r_cntrl);
+		fec_reg_mpc8xx(ecntrl);
+		fec_reg_mpc8xx(mii_speed);
+		fec_reg_mpc8xx(r_des_active);
+		fec_reg_mpc8xx(x_des_active);
+		fec_reg_mpc8xx(r_des_start);
+		fec_reg_mpc8xx(x_des_start);
+		fec_reg_mpc8xx(ivec);
+		fec_reg_mpc8xx(addr_low);
+		fec_reg_mpc8xx(addr_high);
+		fec_reg_mpc8xx(hash_table_high);
+		fec_reg_mpc8xx(hash_table_low);
+		fec_reg_mpc8xx(r_buff_size);
+		fec_reg_mpc8xx(x_fstart);
+		fec_reg_mpc8xx(r_hash);
+		fec_reg_mpc8xx(x_cntrl);
+	}
 	return 0;
 }
 
@@ -162,13 +217,15 @@ static void free_bd(struct net_device *dev)
 
 static void cleanup_data(struct net_device *dev)
 {
-	/* nothing */
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	kfree(fep->fec.rtbl);
 }
 
 static void set_promiscuous_mode(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
 }
@@ -216,7 +273,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
 static void set_multicast_finish(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	/* if all multi or too many multicasts; just enable all */
 	if ((dev->flags & IFF_ALLMULTI) != 0 ||
@@ -246,7 +303,7 @@ static void set_multicast_list(struct net_device *dev)
 static void restart(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 	const struct fs_platform_info *fpi = fep->fpi;
 	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
 	int r;
@@ -255,7 +312,7 @@ static void restart(struct net_device *dev)
 	struct mii_bus* mii = fep->phydev->bus;
 	struct fec_info* fec_inf = mii->priv;
 
-	r = whack_reset(fep->fec.fecp);
+	r = whack_reset(fecp);
 	if (r != 0)
 		printk(KERN_ERR DRV_MODULE_NAME
 				": %s FEC Reset FAILED!\n", dev->name);
@@ -281,7 +338,10 @@ static void restart(struct net_device *dev)
 	 * Set maximum receive buffer size.
 	 */
 	FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
-	FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16);
+	else
+		FW(fecp, r_hash, PKT_MAXBUF_SIZE);
 
 	/* get physical address */
 	rx_bd_base_phys = fep->ring_mem_addr;
@@ -296,9 +356,13 @@ static void restart(struct net_device *dev)
 	fs_init_bds(dev);
 
 	/*
-	 * Enable big endian and don't care about SDMA FC.
+	 * Enable big endian.
 	 */
-	FW(fecp, fun_code, 0x78000000);
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		FS(fecp, dma_control, 0xC0000000);
+	else
+		/* Don't care about SDMA Function Code. */
+		FW(fecp, fun_code, 0x78000000);
 
 	/*
 	 * Set MII speed.
@@ -309,9 +373,20 @@ static void restart(struct net_device *dev)
 	 * Clear any outstanding interrupt.
 	 */
 	FW(fecp, ievent, 0xffc0);
-	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+	if (fep->fec.fec_id != FS_ENET_MPC5121_FEC)
+		FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+
+	/* MII enable */
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC) {
+		/*
+		 * Only set requested bit - do not touch maximum packet
+		 * size configured earlier.
+		 */
+		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	} else {
+		FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	}
 
-	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 	/*
 	 * adjust to duplex mode
 	 */
@@ -340,7 +415,7 @@ static void stop(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 	const struct fs_platform_info *fpi = fep->fpi;
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	struct fec_info* feci= fep->phydev->bus->priv;
 
@@ -378,7 +453,7 @@ static void stop(struct net_device *dev)
 static void napi_clear_rx_event(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -386,7 +461,7 @@ static void napi_clear_rx_event(struct net_device *dev)
 static void napi_enable_rx(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -394,7 +469,7 @@ static void napi_enable_rx(struct net_device *dev)
 static void napi_disable_rx(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -402,7 +477,7 @@ static void napi_disable_rx(struct net_device *dev)
 static void rx_bd_done(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, r_des_active, 0x01000000);
 }
@@ -410,7 +485,7 @@ static void rx_bd_done(struct net_device *dev)
 static void tx_kickstart(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, x_des_active, 0x01000000);
 }
@@ -418,7 +493,7 @@ static void tx_kickstart(struct net_device *dev)
 static u32 get_int_events(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	return FR(fecp, ievent) & FR(fecp, imask);
 }
@@ -426,7 +501,7 @@ static u32 get_int_events(struct net_device *dev)
 static void clear_int_events(struct net_device *dev, u32 int_events)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, ievent, int_events);
 }
@@ -440,18 +515,26 @@ static void ev_error(struct net_device *dev, u32 int_events)
 static int get_regs(struct net_device *dev, void *p, int *sizep)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
+	int size;
 
-	if (*sizep < sizeof(fec_t))
+	size = fep->fec.fec_id ? sizeof(struct mpc5121_fec) :
+				 sizeof(struct mpc8xx_fec);
+	if (*sizep < size)
 		return -EINVAL;
 
-	memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t));
+	memcpy_fromio(p, fep->fec.fecp, size);
 
 	return 0;
 }
 
 static int get_regs_len(struct net_device *dev)
 {
-	return sizeof(fec_t);
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		return sizeof(struct mpc5121_fec);
+	else
+		return sizeof(struct mpc8xx_fec);
 }
 
 static void tx_restart(struct net_device *dev)
@@ -481,4 +564,3 @@ const struct fs_ops fs_fec_ops = {
 	.allocate_bd		= allocate_bd,
 	.free_bd		= free_bd,
 };
-
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 96eba42..1ea10de 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -49,24 +49,33 @@
 
 #define FEC_MII_LOOPS	10000
 
+#define fec_reg_addr(_type, _reg) \
+	(fec->fec_##_reg = \
+		fec->fecp + (int)&((__typeof__(_type) *)NULL)->fec_##_reg)
+
+#define fec_reg_mpc8xx(_reg) \
+	fec_reg_addr(struct mpc8xx_fec, _reg)
+
+#define fec_reg_mpc5121(_reg) \
+	fec_reg_addr(struct mpc5121_fec, _reg)
+
 static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 {
 	struct fec_info* fec = bus->priv;
-	fec_t __iomem *fecp = fec->fecp;
 	int i, ret = -1;
 
-	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
+	BUG_ON((in_be32(fec->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
-	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+	out_be32(fec->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
 
 	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+		if ((in_be32(fec->fec_ievent) & FEC_ENET_MII) != 0)
 			break;
 
 	if (i < FEC_MII_LOOPS) {
-		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
-		ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+		out_be32(fec->fec_ievent, FEC_ENET_MII);
+		ret = in_be32(fec->fec_mii_data) & 0xffff;
 	}
 
 	return ret;
@@ -75,21 +84,21 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
 {
 	struct fec_info* fec = bus->priv;
-	fec_t __iomem *fecp = fec->fecp;
 	int i;
 
 	/* this must never happen */
-	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
+	BUG_ON((in_be32(fec->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
-	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+	out_be32(fec->fec_mii_data, (phy_id << 23) |
+				    mk_mii_write(location, val));
 
 	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+		if ((in_be32(fec->fec_ievent) & FEC_ENET_MII) != 0)
 			break;
 
 	if (i < FEC_MII_LOOPS)
-		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+		out_be32(fec->fec_ievent, FEC_ENET_MII);
 
 	return 0;
 
@@ -134,6 +143,20 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 	if (!fec->fecp)
 		goto out_fec;
 
+	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec-mdio")) {
+		fec_reg_mpc5121(ecntrl);
+		fec_reg_mpc5121(ievent);
+		fec_reg_mpc5121(mii_data);
+		fec_reg_mpc5121(mii_speed);
+		fec_reg_mpc5121(r_cntrl);
+	} else {
+		fec_reg_mpc8xx(ecntrl);
+		fec_reg_mpc8xx(ievent);
+		fec_reg_mpc8xx(mii_data);
+		fec_reg_mpc8xx(mii_speed);
+		fec_reg_mpc8xx(r_cntrl);
+	}
+
 	if (get_bus_freq) {
 		clock = get_bus_freq(ofdev->node);
 		if (!clock) {
@@ -158,11 +181,11 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 
 	fec->mii_speed = speed << 1;
 
-	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
-	                                  FEC_ECNTRL_ETHER_EN);
-	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
-	clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed);
+	setbits32(fec->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+	setbits32(fec->fec_ecntrl, FEC_ECNTRL_PINMUX |
+				   FEC_ECNTRL_ETHER_EN);
+	out_be32(fec->fec_ievent, FEC_ENET_MII);
+	clrsetbits_be32(fec->fec_mii_speed, 0x7E, fec->mii_speed);
 
 	new_bus->phy_mask = ~0;
 	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
diff --git a/drivers/net/fs_enet/mpc5121_fec.h b/drivers/net/fs_enet/mpc5121_fec.h
new file mode 100644
index 0000000..18d4fb3
--- /dev/null
+++ b/drivers/net/fs_enet/mpc5121_fec.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: John Rigby, <jrigby@freescale.com>
+ *
+ * Modified version of drivers/net/fec.h:
+ *
+ *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire SoC
+ *		   processors.
+ *
+ *	(C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 2000-2001, Lineo (www.lineo.com)
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef MPC5121_FEC_H
+#define MPC5121_FEC_H
+
+struct mpc5121_fec {
+	u32 fec_reserved0;
+	u32 fec_ievent;			/* Interrupt event reg */
+	u32 fec_imask;			/* Interrupt mask reg */
+	u32 fec_reserved1;
+	u32 fec_r_des_active;		/* Receive descriptor reg */
+	u32 fec_x_des_active;		/* Transmit descriptor reg */
+	u32 fec_reserved2[3];
+	u32 fec_ecntrl;			/* Ethernet control reg */
+	u32 fec_reserved3[6];
+	u32 fec_mii_data;		/* MII manage frame reg */
+	u32 fec_mii_speed;		/* MII speed control reg */
+	u32 fec_reserved4[7];
+	u32 fec_mib_ctrlstat;		/* MIB control/status reg */
+	u32 fec_reserved5[7];
+	u32 fec_r_cntrl;		/* Receive control reg */
+	u32 fec_reserved6[15];
+	u32 fec_x_cntrl;		/* Transmit Control reg */
+	u32 fec_reserved7[7];
+	u32 fec_addr_low;		/* Low 32bits MAC address */
+	u32 fec_addr_high;		/* High 16bits MAC address */
+	u32 fec_opd;			/* Opcode + Pause duration */
+	u32 fec_reserved8[10];
+	u32 fec_hash_table_high;	/* High 32bits hash table */
+	u32 fec_hash_table_low;		/* Low 32bits hash table */
+	u32 fec_grp_hash_table_high;	/* High 32bits hash table */
+	u32 fec_grp_hash_table_low;	/* Low 32bits hash table */
+	u32 fec_reserved9[7];
+	u32 fec_x_wmrk;			/* FIFO transmit water mark */
+	u32 fec_reserved10;
+	u32 fec_r_bound;		/* FIFO receive bound reg */
+	u32 fec_r_fstart;		/* FIFO receive start reg */
+	u32 fec_reserved11[11];
+	u32 fec_r_des_start;		/* Receive descriptor ring */
+	u32 fec_x_des_start;		/* Transmit descriptor ring */
+	u32 fec_r_buff_size;		/* Maximum receive buff size */
+	u32 fec_reserved12[26];
+	u32 fec_dma_control;		/* DMA Endian and other ctrl */
+};
+
+#define FS_ENET_MPC5121_FEC	0x1
+
+#endif /* MPC5121_FEC_H */
diff --git a/drivers/net/fs_enet/mpc8xx_fec.h b/drivers/net/fs_enet/mpc8xx_fec.h
new file mode 100644
index 0000000..aa78445
--- /dev/null
+++ b/drivers/net/fs_enet/mpc8xx_fec.h
@@ -0,0 +1,37 @@
+/* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+
+struct mpc8xx_fec {
+	uint	fec_addr_low;		/* lower 32 bits of station address */
+	ushort	fec_addr_high;		/* upper 16 bits of station address */
+	ushort	res1;			/* reserved			    */
+	uint	fec_hash_table_high;	/* upper 32-bits of hash table	    */
+	uint	fec_hash_table_low;	/* lower 32-bits of hash table	    */
+	uint	fec_r_des_start;	/* beginning of Rx descriptor ring  */
+	uint	fec_x_des_start;	/* beginning of Tx descriptor ring  */
+	uint	fec_r_buff_size;	/* Rx buffer size		    */
+	uint	res2[9];		/* reserved			    */
+	uint	fec_ecntrl;		/* ethernet control register	    */
+	uint	fec_ievent;		/* interrupt event register	    */
+	uint	fec_imask;		/* interrupt mask register	    */
+	uint	fec_ivec;		/* interrupt level and vector status */
+	uint	fec_r_des_active;	/* Rx ring updated flag		    */
+	uint	fec_x_des_active;	/* Tx ring updated flag		    */
+	uint	res3[10];		/* reserved			    */
+	uint	fec_mii_data;		/* MII data register		    */
+	uint	fec_mii_speed;		/* MII speed control register	    */
+	uint	res4[17];		/* reserved			    */
+	uint	fec_r_bound;		/* end of RAM (read-only)	    */
+	uint	fec_r_fstart;		/* Rx FIFO start address	    */
+	uint	res5[6];		/* reserved			    */
+	uint	fec_x_fstart;		/* Tx FIFO start address	    */
+	uint	res6[17];		/* reserved			    */
+	uint	fec_fun_code;		/* fec SDMA function code	    */
+	uint	res7[3];		/* reserved			    */
+	uint	fec_r_cntrl;		/* Rx control register		    */
+	uint	fec_r_hash;		/* Rx hash register		    */
+	uint	res8[14];		/* reserved			    */
+	uint	fec_x_cntrl;		/* Tx control register		    */
+	uint	res9[0x1e];		/* reserved			    */
+};
-- 
1.5.6.3


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

* [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
@ 2010-01-19 20:24   ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: wd, John Rigby, netdev, Anatolij Gustschin, dzu, Piotr Ziecik

    drivers/net/fs_enet/*
        Enable fs_enet driver to work 5121 FEC
        Enable it with CONFIG_FS_ENET_MPC5121_FEC

Signed-off-by: John Rigby <jrigby@freescale.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <netdev@vger.kernel.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/net/fs_enet/Kconfig        |   10 ++-
 drivers/net/fs_enet/fs_enet-main.c |    4 +
 drivers/net/fs_enet/fs_enet.h      |   40 +++++++++++-
 drivers/net/fs_enet/mac-fec.c      |  132 +++++++++++++++++++++++++++++-------
 drivers/net/fs_enet/mii-fec.c      |   55 +++++++++++-----
 drivers/net/fs_enet/mpc5121_fec.h  |   64 +++++++++++++++++
 drivers/net/fs_enet/mpc8xx_fec.h   |   37 ++++++++++
 7 files changed, 297 insertions(+), 45 deletions(-)
 create mode 100644 drivers/net/fs_enet/mpc5121_fec.h
 create mode 100644 drivers/net/fs_enet/mpc8xx_fec.h

diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 562ea68..fc073b5 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,9 +1,13 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on CPM1 || CPM2
+       depends on CPM1 || CPM2 || PPC_MPC512x
        select MII
        select PHYLIB
 
+config FS_ENET_MPC5121_FEC
+	def_bool y if (FS_ENET && PPC_MPC512x)
+	select FS_ENET_HAS_FEC
+
 config FS_ENET_HAS_SCC
 	bool "Chip has an SCC usable for ethernet"
 	depends on FS_ENET && (CPM1 || CPM2)
@@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC
 
 config FS_ENET_HAS_FEC
 	bool "Chip has an FEC usable for ethernet"
-	depends on FS_ENET && CPM1
+	depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
 	select FS_ENET_MDIO_FEC
 	default y
 
 config FS_ENET_MDIO_FEC
 	tristate "MDIO driver for FEC"
-	depends on FS_ENET && CPM1
+	depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC)
 
 config FS_ENET_MDIO_FCC
 	tristate "MDIO driver for FCC"
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index ec2f503..909b78d 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1104,6 +1104,10 @@ static struct of_device_id fs_enet_match[] = {
 #endif
 #ifdef CONFIG_FS_ENET_HAS_FEC
 	{
+		.compatible = "fsl,mpc5121-fec",
+		.data = (void *)&fs_fec_ops,
+	},
+	{
 		.compatible = "fsl,pq1-fec-enet",
 		.data = (void *)&fs_fec_ops,
 	},
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index ef01e09..577a352 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -13,11 +13,47 @@
 
 #ifdef CONFIG_CPM1
 #include <asm/cpm1.h>
+#endif
+
+#if defined(CONFIG_FS_ENET_HAS_FEC)
+#include <asm/cpm.h>
+#include "mpc8xx_fec.h"
+#include "mpc5121_fec.h"
 
 struct fec_info {
-	fec_t __iomem *fecp;
+	void __iomem *fecp;
+	void __iomem *fec_r_cntrl;
+	void __iomem *fec_ecntrl;
+	void __iomem *fec_ievent;
+	void __iomem *fec_mii_data;
+	void __iomem *fec_mii_speed;
 	u32 mii_speed;
 };
+
+struct reg_tbl {
+	void __iomem *fec_ievent;
+	void __iomem *fec_imask;
+	void __iomem *fec_r_des_active;
+	void __iomem *fec_x_des_active;
+	void __iomem *fec_r_des_start;
+	void __iomem *fec_x_des_start;
+	void __iomem *fec_r_cntrl;
+	void __iomem *fec_ecntrl;
+	void __iomem *fec_ivec;
+	void __iomem *fec_mii_speed;
+	void __iomem *fec_addr_low;
+	void __iomem *fec_addr_high;
+	void __iomem *fec_hash_table_high;
+	void __iomem *fec_hash_table_low;
+	void __iomem *fec_r_buff_size;
+	void __iomem *fec_r_bound;
+	void __iomem *fec_r_fstart;
+	void __iomem *fec_x_fstart;
+	void __iomem *fec_fun_code;
+	void __iomem *fec_r_hash;
+	void __iomem *fec_x_cntrl;
+	void __iomem *fec_dma_control;
+};
 #endif
 
 #ifdef CONFIG_CPM2
@@ -113,7 +149,9 @@ struct fs_enet_private {
 		struct {
 			int idx;		/* FEC1 = 0, FEC2 = 1  */
 			void __iomem *fecp;	/* hw registers        */
+			struct reg_tbl *rtbl;	/* used registers table */
 			u32 hthi, htlo;		/* state for multicast */
+			u32 fec_id;
 		} fec;
 
 		struct {
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index ca7bcb8..4a5d5ca 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -64,10 +64,10 @@
 #endif
 
 /* write */
-#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
+#define FW(_fecp, _reg, _v) __fs_out32((_fecp)->fec_ ## _reg, (_v))
 
 /* read */
-#define FR(_fecp, _reg)	__fs_in32(&(_fecp)->fec_ ## _reg)
+#define FR(_fecp, _reg)	__fs_in32((_fecp)->fec_ ## _reg)
 
 /* set bits */
 #define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
@@ -75,12 +75,23 @@
 /* clear bits */
 #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
 
+/* register address macros */
+#define fec_reg_addr(_type, _reg) \
+	(fep->fec.rtbl->fec_##_reg = \
+		fep->fec.fecp + (int)&((__typeof__(_type) *)NULL)->fec_##_reg)
+
+#define fec_reg_mpc8xx(_reg) \
+	fec_reg_addr(struct mpc8xx_fec, _reg)
+
+#define fec_reg_mpc5121(_reg) \
+	fec_reg_addr(struct mpc5121_fec, _reg)
+
 /*
  * Delay to wait for FEC reset command to complete (in us)
  */
 #define FEC_RESET_DELAY		50
 
-static int whack_reset(fec_t __iomem *fecp)
+static int whack_reset(struct reg_tbl *fecp)
 {
 	int i;
 
@@ -106,6 +117,50 @@ static int do_pd_setup(struct fs_enet_private *fep)
 	if (!fep->fcc.fccp)
 		return -EINVAL;
 
+	fep->fec.rtbl = kzalloc(sizeof(*fep->fec.rtbl), GFP_KERNEL);
+	if (!fep->fec.rtbl) {
+		iounmap(fep->fec.fecp);
+		return -ENOMEM;
+	}
+
+	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec")) {
+		fep->fec.fec_id = FS_ENET_MPC5121_FEC;
+		fec_reg_mpc5121(ievent);
+		fec_reg_mpc5121(imask);
+		fec_reg_mpc5121(r_cntrl);
+		fec_reg_mpc5121(ecntrl);
+		fec_reg_mpc5121(r_des_active);
+		fec_reg_mpc5121(x_des_active);
+		fec_reg_mpc5121(r_des_start);
+		fec_reg_mpc5121(x_des_start);
+		fec_reg_mpc5121(addr_low);
+		fec_reg_mpc5121(addr_high);
+		fec_reg_mpc5121(hash_table_high);
+		fec_reg_mpc5121(hash_table_low);
+		fec_reg_mpc5121(r_buff_size);
+		fec_reg_mpc5121(mii_speed);
+		fec_reg_mpc5121(x_cntrl);
+		fec_reg_mpc5121(dma_control);
+	} else {
+		fec_reg_mpc8xx(ievent);
+		fec_reg_mpc8xx(imask);
+		fec_reg_mpc8xx(r_cntrl);
+		fec_reg_mpc8xx(ecntrl);
+		fec_reg_mpc8xx(mii_speed);
+		fec_reg_mpc8xx(r_des_active);
+		fec_reg_mpc8xx(x_des_active);
+		fec_reg_mpc8xx(r_des_start);
+		fec_reg_mpc8xx(x_des_start);
+		fec_reg_mpc8xx(ivec);
+		fec_reg_mpc8xx(addr_low);
+		fec_reg_mpc8xx(addr_high);
+		fec_reg_mpc8xx(hash_table_high);
+		fec_reg_mpc8xx(hash_table_low);
+		fec_reg_mpc8xx(r_buff_size);
+		fec_reg_mpc8xx(x_fstart);
+		fec_reg_mpc8xx(r_hash);
+		fec_reg_mpc8xx(x_cntrl);
+	}
 	return 0;
 }
 
@@ -162,13 +217,15 @@ static void free_bd(struct net_device *dev)
 
 static void cleanup_data(struct net_device *dev)
 {
-	/* nothing */
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	kfree(fep->fec.rtbl);
 }
 
 static void set_promiscuous_mode(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
 }
@@ -216,7 +273,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac)
 static void set_multicast_finish(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	/* if all multi or too many multicasts; just enable all */
 	if ((dev->flags & IFF_ALLMULTI) != 0 ||
@@ -246,7 +303,7 @@ static void set_multicast_list(struct net_device *dev)
 static void restart(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 	const struct fs_platform_info *fpi = fep->fpi;
 	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
 	int r;
@@ -255,7 +312,7 @@ static void restart(struct net_device *dev)
 	struct mii_bus* mii = fep->phydev->bus;
 	struct fec_info* fec_inf = mii->priv;
 
-	r = whack_reset(fep->fec.fecp);
+	r = whack_reset(fecp);
 	if (r != 0)
 		printk(KERN_ERR DRV_MODULE_NAME
 				": %s FEC Reset FAILED!\n", dev->name);
@@ -281,7 +338,10 @@ static void restart(struct net_device *dev)
 	 * Set maximum receive buffer size.
 	 */
 	FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
-	FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16);
+	else
+		FW(fecp, r_hash, PKT_MAXBUF_SIZE);
 
 	/* get physical address */
 	rx_bd_base_phys = fep->ring_mem_addr;
@@ -296,9 +356,13 @@ static void restart(struct net_device *dev)
 	fs_init_bds(dev);
 
 	/*
-	 * Enable big endian and don't care about SDMA FC.
+	 * Enable big endian.
 	 */
-	FW(fecp, fun_code, 0x78000000);
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		FS(fecp, dma_control, 0xC0000000);
+	else
+		/* Don't care about SDMA Function Code. */
+		FW(fecp, fun_code, 0x78000000);
 
 	/*
 	 * Set MII speed.
@@ -309,9 +373,20 @@ static void restart(struct net_device *dev)
 	 * Clear any outstanding interrupt.
 	 */
 	FW(fecp, ievent, 0xffc0);
-	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+	if (fep->fec.fec_id != FS_ENET_MPC5121_FEC)
+		FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+
+	/* MII enable */
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC) {
+		/*
+		 * Only set requested bit - do not touch maximum packet
+		 * size configured earlier.
+		 */
+		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	} else {
+		FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	}
 
-	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 	/*
 	 * adjust to duplex mode
 	 */
@@ -340,7 +415,7 @@ static void stop(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 	const struct fs_platform_info *fpi = fep->fpi;
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	struct fec_info* feci= fep->phydev->bus->priv;
 
@@ -378,7 +453,7 @@ static void stop(struct net_device *dev)
 static void napi_clear_rx_event(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -386,7 +461,7 @@ static void napi_clear_rx_event(struct net_device *dev)
 static void napi_enable_rx(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -394,7 +469,7 @@ static void napi_enable_rx(struct net_device *dev)
 static void napi_disable_rx(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
 }
@@ -402,7 +477,7 @@ static void napi_disable_rx(struct net_device *dev)
 static void rx_bd_done(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, r_des_active, 0x01000000);
 }
@@ -410,7 +485,7 @@ static void rx_bd_done(struct net_device *dev)
 static void tx_kickstart(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, x_des_active, 0x01000000);
 }
@@ -418,7 +493,7 @@ static void tx_kickstart(struct net_device *dev)
 static u32 get_int_events(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	return FR(fecp, ievent) & FR(fecp, imask);
 }
@@ -426,7 +501,7 @@ static u32 get_int_events(struct net_device *dev)
 static void clear_int_events(struct net_device *dev, u32 int_events)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	fec_t __iomem *fecp = fep->fec.fecp;
+	struct reg_tbl *fecp = fep->fec.rtbl;
 
 	FW(fecp, ievent, int_events);
 }
@@ -440,18 +515,26 @@ static void ev_error(struct net_device *dev, u32 int_events)
 static int get_regs(struct net_device *dev, void *p, int *sizep)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
+	int size;
 
-	if (*sizep < sizeof(fec_t))
+	size = fep->fec.fec_id ? sizeof(struct mpc5121_fec) :
+				 sizeof(struct mpc8xx_fec);
+	if (*sizep < size)
 		return -EINVAL;
 
-	memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t));
+	memcpy_fromio(p, fep->fec.fecp, size);
 
 	return 0;
 }
 
 static int get_regs_len(struct net_device *dev)
 {
-	return sizeof(fec_t);
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC)
+		return sizeof(struct mpc5121_fec);
+	else
+		return sizeof(struct mpc8xx_fec);
 }
 
 static void tx_restart(struct net_device *dev)
@@ -481,4 +564,3 @@ const struct fs_ops fs_fec_ops = {
 	.allocate_bd		= allocate_bd,
 	.free_bd		= free_bd,
 };
-
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 96eba42..1ea10de 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -49,24 +49,33 @@
 
 #define FEC_MII_LOOPS	10000
 
+#define fec_reg_addr(_type, _reg) \
+	(fec->fec_##_reg = \
+		fec->fecp + (int)&((__typeof__(_type) *)NULL)->fec_##_reg)
+
+#define fec_reg_mpc8xx(_reg) \
+	fec_reg_addr(struct mpc8xx_fec, _reg)
+
+#define fec_reg_mpc5121(_reg) \
+	fec_reg_addr(struct mpc5121_fec, _reg)
+
 static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 {
 	struct fec_info* fec = bus->priv;
-	fec_t __iomem *fecp = fec->fecp;
 	int i, ret = -1;
 
-	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
+	BUG_ON((in_be32(fec->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
-	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+	out_be32(fec->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
 
 	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+		if ((in_be32(fec->fec_ievent) & FEC_ENET_MII) != 0)
 			break;
 
 	if (i < FEC_MII_LOOPS) {
-		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
-		ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+		out_be32(fec->fec_ievent, FEC_ENET_MII);
+		ret = in_be32(fec->fec_mii_data) & 0xffff;
 	}
 
 	return ret;
@@ -75,21 +84,21 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
 {
 	struct fec_info* fec = bus->priv;
-	fec_t __iomem *fecp = fec->fecp;
 	int i;
 
 	/* this must never happen */
-	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
+	BUG_ON((in_be32(fec->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
-	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+	out_be32(fec->fec_mii_data, (phy_id << 23) |
+				    mk_mii_write(location, val));
 
 	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+		if ((in_be32(fec->fec_ievent) & FEC_ENET_MII) != 0)
 			break;
 
 	if (i < FEC_MII_LOOPS)
-		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+		out_be32(fec->fec_ievent, FEC_ENET_MII);
 
 	return 0;
 
@@ -134,6 +143,20 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 	if (!fec->fecp)
 		goto out_fec;
 
+	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec-mdio")) {
+		fec_reg_mpc5121(ecntrl);
+		fec_reg_mpc5121(ievent);
+		fec_reg_mpc5121(mii_data);
+		fec_reg_mpc5121(mii_speed);
+		fec_reg_mpc5121(r_cntrl);
+	} else {
+		fec_reg_mpc8xx(ecntrl);
+		fec_reg_mpc8xx(ievent);
+		fec_reg_mpc8xx(mii_data);
+		fec_reg_mpc8xx(mii_speed);
+		fec_reg_mpc8xx(r_cntrl);
+	}
+
 	if (get_bus_freq) {
 		clock = get_bus_freq(ofdev->node);
 		if (!clock) {
@@ -158,11 +181,11 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 
 	fec->mii_speed = speed << 1;
 
-	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
-	                                  FEC_ECNTRL_ETHER_EN);
-	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
-	clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed);
+	setbits32(fec->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+	setbits32(fec->fec_ecntrl, FEC_ECNTRL_PINMUX |
+				   FEC_ECNTRL_ETHER_EN);
+	out_be32(fec->fec_ievent, FEC_ENET_MII);
+	clrsetbits_be32(fec->fec_mii_speed, 0x7E, fec->mii_speed);
 
 	new_bus->phy_mask = ~0;
 	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
diff --git a/drivers/net/fs_enet/mpc5121_fec.h b/drivers/net/fs_enet/mpc5121_fec.h
new file mode 100644
index 0000000..18d4fb3
--- /dev/null
+++ b/drivers/net/fs_enet/mpc5121_fec.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: John Rigby, <jrigby@freescale.com>
+ *
+ * Modified version of drivers/net/fec.h:
+ *
+ *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire SoC
+ *		   processors.
+ *
+ *	(C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 2000-2001, Lineo (www.lineo.com)
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef MPC5121_FEC_H
+#define MPC5121_FEC_H
+
+struct mpc5121_fec {
+	u32 fec_reserved0;
+	u32 fec_ievent;			/* Interrupt event reg */
+	u32 fec_imask;			/* Interrupt mask reg */
+	u32 fec_reserved1;
+	u32 fec_r_des_active;		/* Receive descriptor reg */
+	u32 fec_x_des_active;		/* Transmit descriptor reg */
+	u32 fec_reserved2[3];
+	u32 fec_ecntrl;			/* Ethernet control reg */
+	u32 fec_reserved3[6];
+	u32 fec_mii_data;		/* MII manage frame reg */
+	u32 fec_mii_speed;		/* MII speed control reg */
+	u32 fec_reserved4[7];
+	u32 fec_mib_ctrlstat;		/* MIB control/status reg */
+	u32 fec_reserved5[7];
+	u32 fec_r_cntrl;		/* Receive control reg */
+	u32 fec_reserved6[15];
+	u32 fec_x_cntrl;		/* Transmit Control reg */
+	u32 fec_reserved7[7];
+	u32 fec_addr_low;		/* Low 32bits MAC address */
+	u32 fec_addr_high;		/* High 16bits MAC address */
+	u32 fec_opd;			/* Opcode + Pause duration */
+	u32 fec_reserved8[10];
+	u32 fec_hash_table_high;	/* High 32bits hash table */
+	u32 fec_hash_table_low;		/* Low 32bits hash table */
+	u32 fec_grp_hash_table_high;	/* High 32bits hash table */
+	u32 fec_grp_hash_table_low;	/* Low 32bits hash table */
+	u32 fec_reserved9[7];
+	u32 fec_x_wmrk;			/* FIFO transmit water mark */
+	u32 fec_reserved10;
+	u32 fec_r_bound;		/* FIFO receive bound reg */
+	u32 fec_r_fstart;		/* FIFO receive start reg */
+	u32 fec_reserved11[11];
+	u32 fec_r_des_start;		/* Receive descriptor ring */
+	u32 fec_x_des_start;		/* Transmit descriptor ring */
+	u32 fec_r_buff_size;		/* Maximum receive buff size */
+	u32 fec_reserved12[26];
+	u32 fec_dma_control;		/* DMA Endian and other ctrl */
+};
+
+#define FS_ENET_MPC5121_FEC	0x1
+
+#endif /* MPC5121_FEC_H */
diff --git a/drivers/net/fs_enet/mpc8xx_fec.h b/drivers/net/fs_enet/mpc8xx_fec.h
new file mode 100644
index 0000000..aa78445
--- /dev/null
+++ b/drivers/net/fs_enet/mpc8xx_fec.h
@@ -0,0 +1,37 @@
+/* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+
+struct mpc8xx_fec {
+	uint	fec_addr_low;		/* lower 32 bits of station address */
+	ushort	fec_addr_high;		/* upper 16 bits of station address */
+	ushort	res1;			/* reserved			    */
+	uint	fec_hash_table_high;	/* upper 32-bits of hash table	    */
+	uint	fec_hash_table_low;	/* lower 32-bits of hash table	    */
+	uint	fec_r_des_start;	/* beginning of Rx descriptor ring  */
+	uint	fec_x_des_start;	/* beginning of Tx descriptor ring  */
+	uint	fec_r_buff_size;	/* Rx buffer size		    */
+	uint	res2[9];		/* reserved			    */
+	uint	fec_ecntrl;		/* ethernet control register	    */
+	uint	fec_ievent;		/* interrupt event register	    */
+	uint	fec_imask;		/* interrupt mask register	    */
+	uint	fec_ivec;		/* interrupt level and vector status */
+	uint	fec_r_des_active;	/* Rx ring updated flag		    */
+	uint	fec_x_des_active;	/* Tx ring updated flag		    */
+	uint	res3[10];		/* reserved			    */
+	uint	fec_mii_data;		/* MII data register		    */
+	uint	fec_mii_speed;		/* MII speed control register	    */
+	uint	res4[17];		/* reserved			    */
+	uint	fec_r_bound;		/* end of RAM (read-only)	    */
+	uint	fec_r_fstart;		/* Rx FIFO start address	    */
+	uint	res5[6];		/* reserved			    */
+	uint	fec_x_fstart;		/* Tx FIFO start address	    */
+	uint	res6[17];		/* reserved			    */
+	uint	fec_fun_code;		/* fec SDMA function code	    */
+	uint	res7[3];		/* reserved			    */
+	uint	fec_r_cntrl;		/* Rx control register		    */
+	uint	fec_r_hash;		/* Rx hash register		    */
+	uint	res8[14];		/* reserved			    */
+	uint	fec_x_cntrl;		/* Tx control register		    */
+	uint	res9[0x1e];		/* reserved			    */
+};
-- 
1.5.6.3

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

* [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
  2010-01-19 20:24 ` Anatolij Gustschin
@ 2010-01-19 20:24   ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: dzu, wd, John Rigby, John Rigby, Piotr Ziecik,
	Anatolij Gustschin, netdev, Grant Likely

From: John Rigby <jcrigby@gmail.com>

The FEC on 5121 has problems with misaligned tx buffers.
The RM says any alignment is ok but empirical results
show that packet buffers ending in 0x1E will sometimes
hang the FEC.  Other bad alignment does not hang but will
cause silent TX failures resulting in about a 1% packet
loss as tested by ping -f from a remote host.

This patch is a work around that copies every tx packet
to an aligned skb before sending.

Signed-off-by: John Rigby <jrigby@freescale.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <netdev@vger.kernel.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/net/fs_enet/fs_enet-main.c |   39 ++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 909b78d..a391219 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -587,6 +587,33 @@ void fs_cleanup_bds(struct net_device *dev)
 
 /**********************************************************************************/
 
+static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
+					       struct sk_buff *skb)
+{
+	struct sk_buff *new_skb;
+
+	/* Alloc new skb */
+	new_skb = dev_alloc_skb(ENET_RX_FRSIZE + 32);
+	if (!new_skb) {
+		printk(KERN_WARNING DRV_MODULE_NAME
+				": %s Memory squeeze, dropping tx packet.\n",
+								dev->name);
+		return NULL;
+	}
+
+	/* Make sure new skb is properly aligned */
+	skb_align(new_skb, 32);
+
+	/* Copy data to new skb ... */
+	skb_copy_from_linear_data(skb, new_skb->data, skb->len);
+	skb_put(new_skb, skb->len);
+
+	/* ... and free an old one */
+	dev_kfree_skb_any(skb);
+
+	return new_skb;
+}
+
 static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
@@ -595,6 +622,18 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	u16 sc;
 	unsigned long flags;
 
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC) {
+		skb = tx_skb_align_workaround(dev, skb);
+		if (!skb) {
+			/*
+			 * We have lost packet due to memory allocation error
+			 * in tx_skb_align_workaround(). Hopefully original skb
+			 * is still valid, so try transmit it later.
+			 */
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	spin_lock_irqsave(&fep->tx_lock, flags);
 
 	/*
-- 
1.5.6.3


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

* [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
@ 2010-01-19 20:24   ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: wd, John Rigby, netdev, Anatolij Gustschin, dzu, Piotr Ziecik

From: John Rigby <jcrigby@gmail.com>

The FEC on 5121 has problems with misaligned tx buffers.
The RM says any alignment is ok but empirical results
show that packet buffers ending in 0x1E will sometimes
hang the FEC.  Other bad alignment does not hang but will
cause silent TX failures resulting in about a 1% packet
loss as tested by ping -f from a remote host.

This patch is a work around that copies every tx packet
to an aligned skb before sending.

Signed-off-by: John Rigby <jrigby@freescale.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <netdev@vger.kernel.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/net/fs_enet/fs_enet-main.c |   39 ++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 909b78d..a391219 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -587,6 +587,33 @@ void fs_cleanup_bds(struct net_device *dev)
 
 /**********************************************************************************/
 
+static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
+					       struct sk_buff *skb)
+{
+	struct sk_buff *new_skb;
+
+	/* Alloc new skb */
+	new_skb = dev_alloc_skb(ENET_RX_FRSIZE + 32);
+	if (!new_skb) {
+		printk(KERN_WARNING DRV_MODULE_NAME
+				": %s Memory squeeze, dropping tx packet.\n",
+								dev->name);
+		return NULL;
+	}
+
+	/* Make sure new skb is properly aligned */
+	skb_align(new_skb, 32);
+
+	/* Copy data to new skb ... */
+	skb_copy_from_linear_data(skb, new_skb->data, skb->len);
+	skb_put(new_skb, skb->len);
+
+	/* ... and free an old one */
+	dev_kfree_skb_any(skb);
+
+	return new_skb;
+}
+
 static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
@@ -595,6 +622,18 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	u16 sc;
 	unsigned long flags;
 
+	if (fep->fec.fec_id == FS_ENET_MPC5121_FEC) {
+		skb = tx_skb_align_workaround(dev, skb);
+		if (!skb) {
+			/*
+			 * We have lost packet due to memory allocation error
+			 * in tx_skb_align_workaround(). Hopefully original skb
+			 * is still valid, so try transmit it later.
+			 */
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	spin_lock_irqsave(&fep->tx_lock, flags);
 
 	/*
-- 
1.5.6.3

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

* [PATCH 03/11] powerpc/mpc5121: Add machine restart support
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (4 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  2010-01-20 11:28   ` Wolfram Sang
  -1 siblings, 1 reply; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wd, dzu, Anatolij Gustschin, Piotr Ziecik

Add reset module registers representation and
machine restart callback for mpc5121 platform.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 arch/powerpc/include/asm/mpc5xxx.h            |   14 +++++++++-
 arch/powerpc/platforms/512x/mpc5121_ads.c     |    1 +
 arch/powerpc/platforms/512x/mpc5121_generic.c |    1 +
 arch/powerpc/platforms/512x/mpc512x.h         |    1 +
 arch/powerpc/platforms/512x/mpc512x_shared.c  |   35 +++++++++++++++++++++++++
 5 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5xxx.h b/arch/powerpc/include/asm/mpc5xxx.h
index 5ce9c5f..0004986 100644
--- a/arch/powerpc/include/asm/mpc5xxx.h
+++ b/arch/powerpc/include/asm/mpc5xxx.h
@@ -18,5 +18,17 @@
 
 extern unsigned long mpc5xxx_get_bus_frequency(struct device_node *node);
 
-#endif /* __ASM_POWERPC_MPC5xxx_H__ */
+/* MPC512x Reset module registers */
+struct mpc512x_reset_module {
+	u32	rcwlr;	/* Reset Configuration Word Low Register */
+	u32	rcwhr;	/* Reset Configuration Word High Register */
+	u32	reserved1;
+	u32	reserved2;
+	u32	rsr;	/* Reset Status Register */
+	u32	rmr;	/* Reset Mode Register */
+	u32	rpr;	/* Reset Protection Register */
+	u32	rcr;	/* Reset Control Register */
+	u32	rcer;	/* Reset Control Enable Register */
+};
 
+#endif /* __ASM_POWERPC_MPC5xxx_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index 441abc4..2f40404 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -68,4 +68,5 @@ define_machine(mpc5121_ads) {
 	.init_IRQ		= mpc5121_ads_init_IRQ,
 	.get_irq		= ipic_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
+	.restart		= mpc512x_restart,
 };
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
index 2479de9..de4c3f7 100644
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
@@ -55,4 +55,5 @@ define_machine(mpc5121_generic) {
 	.init_IRQ		= mpc512x_init_IRQ,
 	.get_irq		= ipic_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
+	.restart		= mpc512x_restart,
 };
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index 22a5352..c38875c 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -12,5 +12,6 @@
 #ifndef __MPC512X_H__
 #define __MPC512X_H__
 extern void __init mpc512x_init_IRQ(void);
+extern void mpc512x_restart(char *cmd);
 void __init mpc512x_declare_of_platform_devices(void);
 #endif				/* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 434d683..8a0d577 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -21,9 +21,44 @@
 #include <asm/ipic.h>
 #include <asm/prom.h>
 #include <asm/time.h>
+#include <asm/mpc5xxx.h>
 
 #include "mpc512x.h"
 
+static void __iomem *reset_module_base;
+
+static int __init mpc512x_restart_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
+	if (!np)
+		return -1;
+
+	reset_module_base = of_iomap(np, 0);
+	of_node_put(np);
+
+	return 0;
+}
+
+arch_initcall(mpc512x_restart_init);
+
+void mpc512x_restart(char *cmd)
+{
+	struct mpc512x_reset_module *rm = reset_module_base;
+
+	if (rm) {
+		/* Enable software reset "RSTE" */
+		out_be32(&rm->rpr, 0x52535445);
+		/* Set software hard reset */
+		out_be32(&rm->rcr, 0x2);
+	} else {
+		printk(KERN_ERR ": Restart module not mapped.\n");
+	}
+	for (;;)
+		;
+}
+
 void __init mpc512x_init_IRQ(void)
 {
 	struct device_node *np;
-- 
1.5.6.3

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

* [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
  2010-01-19 20:24 ` Anatolij Gustschin
@ 2010-01-19 20:24     ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A
  Cc: dzu-ynQEQJNshbs, wd-ynQEQJNshbs, Piotr Ziecik,
	Anatolij Gustschin, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Grant Likely, John Rigby

From: Piotr Ziecik <kosmo-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>

    - Update Kconfig for i2c-mpc driver.
    - Enable I2C interrupts on MPC5121.

Signed-off-by: Piotr Ziecik <kosmo-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Signed-off-by: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
Signed-off-by: Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org>
Cc: <linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: John Rigby <jcrigby-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/i2c/busses/Kconfig   |    9 +++++----
 drivers/i2c/busses/i2c-mpc.c |   23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 5f318ce..f481f30 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -418,13 +418,14 @@ config I2C_IXP2000
 	  instead.
 
 config I2C_MPC
-	tristate "MPC107/824x/85xx/52xx/86xx"
+	tristate "MPC107/824x/85xx/512x/52xx/86xx"
 	depends on PPC32
 	help
 	  If you say yes to this option, support will be included for the
-	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-	  family processors, though interrupts are known not to work.
+	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245,
+	  MPC85xx/MPC8641 and MPC512x family processors. The driver may
+	  also work on 52xx family processors, though interrupts are known
+	  not to work.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f627001..84eeb25 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
 		}
 	}
 
+	if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {
+		struct device_node *np;
+		void __iomem *i2cctl;
+
+		/* Enable I2C interrupts */
+		np = of_find_compatible_node(NULL, NULL,
+					     "fsl,mpc5121-i2c-ctrl");
+		if (np) {
+			i2cctl = of_iomap(np, 0);
+			if (i2cctl) {
+				/*
+				 * Set interrupt enable bits:
+				 *  - I2C-0: bit 24,
+				 *  - I2C-1: bit 26,
+				 *  - I2C-2: bit 28.
+				 */
+				out_be32(i2cctl, 0x15000000);
+				iounmap(i2cctl);
+			}
+			of_node_put(np);
+		}
+	}
+
 	dev_set_drvdata(&op->dev, i2c);
 
 	i2c->adap = mpc_ops;
-- 
1.5.6.3

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

* [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
@ 2010-01-19 20:24     ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wd, dzu, linux-i2c, Anatolij Gustschin, Piotr Ziecik

From: Piotr Ziecik <kosmo@semihalf.com>

    - Update Kconfig for i2c-mpc driver.
    - Enable I2C interrupts on MPC5121.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <linux-i2c@vger.kernel.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/i2c/busses/Kconfig   |    9 +++++----
 drivers/i2c/busses/i2c-mpc.c |   23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 5f318ce..f481f30 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -418,13 +418,14 @@ config I2C_IXP2000
 	  instead.
 
 config I2C_MPC
-	tristate "MPC107/824x/85xx/52xx/86xx"
+	tristate "MPC107/824x/85xx/512x/52xx/86xx"
 	depends on PPC32
 	help
 	  If you say yes to this option, support will be included for the
-	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-	  family processors, though interrupts are known not to work.
+	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245,
+	  MPC85xx/MPC8641 and MPC512x family processors. The driver may
+	  also work on 52xx family processors, though interrupts are known
+	  not to work.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f627001..84eeb25 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
 		}
 	}
 
+	if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {
+		struct device_node *np;
+		void __iomem *i2cctl;
+
+		/* Enable I2C interrupts */
+		np = of_find_compatible_node(NULL, NULL,
+					     "fsl,mpc5121-i2c-ctrl");
+		if (np) {
+			i2cctl = of_iomap(np, 0);
+			if (i2cctl) {
+				/*
+				 * Set interrupt enable bits:
+				 *  - I2C-0: bit 24,
+				 *  - I2C-1: bit 26,
+				 *  - I2C-2: bit 28.
+				 */
+				out_be32(i2cctl, 0x15000000);
+				iounmap(i2cctl);
+			}
+			of_node_put(np);
+		}
+	}
+
 	dev_set_drvdata(&op->dev, i2c);
 
 	i2c->adap = mpc_ops;
-- 
1.5.6.3

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

* [PATCH 05/11] rtc: Add MPC5121 Real time clock driver
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (6 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  2010-01-20 11:01   ` Wolfram Sang
  2010-01-20 22:19   ` [rtc-linux] " Alessandro Zummo
  -1 siblings, 2 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: wd, John Rigby, rtc-linux, Anatolij Gustschin, dzu, Piotr Ziecik

From: John Rigby <jrigby@freescale.com>

Based on Domen Puncer's rtc driver for 5200 posted to
the ppclinux mailing list:
        http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=11675
but never commited anywhere.

Changes to Domen's original:

    Changed filenames/routine names from mpc5200* to mpc5121*
    Changed match to only care about compatible and use "fsl,"
    convention for compatible.

    Make alarms more sane by dealing with lack of second alarm resolution.

    Deal with the fact that most of the 5121 rtc registers are not persistent
    across a reset even with a battery attached:

        Use actual_time register for time keeping
        and target_time register as an offset to linux time

        The target_time register would normally be used for hibernation
        but hibernation does not work on current silicon

Signed-off-by: John Rigby <jcrigby@gmail.com>
Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <rtc-linux@googlegroups.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/rtc/Kconfig       |   10 +
 drivers/rtc/Makefile      |    1 +
 drivers/rtc/rtc-mpc5121.c |  408 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 419 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-mpc5121.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 8167e9e..e51b094 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -868,4 +868,14 @@ config RTC_DRV_MC13783
 	help
 	  This enables support for the Freescale MC13783 PMIC RTC
 
+config RTC_DRV_MPC5121
+	tristate "Freescale MPC5121 built-in RTC"
+	depends on RTC_CLASS
+	help
+	  If you say yes here you will get support for the
+	  built-in RTC MPC5121.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-mpc5121.
+
 endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index e5160fd..db1dcd4 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MC13783)	+= rtc-mc13783.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
+obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o
 obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
new file mode 100644
index 0000000..63460cb
--- /dev/null
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -0,0 +1,408 @@
+/*
+ * Real-time clock driver for MPC5121
+ *
+ * Copyright 2007, Domen Puncer <domen.puncer@telargo.com>
+ * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * History:
+ *
+ * Based on mpc5200_rtc.c written by Domen Puncer <domen.puncer@telargo.com>
+ *   posted to linuxppc-embedded mailing list:
+ *     http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=11675
+ *   but never committed to any public tree.
+ *
+ * Author: John Rigby <jrigby@freescale.com>
+ *   Converted to 5121 rtc driver.
+ *
+ *   Make alarms more sane by dealing with lack of second alarm resolution.
+ *
+ *   Use actual_time time register for time keeping since it is persistent
+ *   and the normal rtc registers are not.  Use target_time register as an
+ *   offset to linux time.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+
+struct mpc5121_rtc_regs {
+	u8 set_time;		/* RTC + 0x00 */
+	u8 hour_set;		/* RTC + 0x01 */
+	u8 minute_set;		/* RTC + 0x02 */
+	u8 second_set;		/* RTC + 0x03 */
+
+	u8 set_date;		/* RTC + 0x04 */
+	u8 month_set;		/* RTC + 0x05 */
+	u8 weekday_set;		/* RTC + 0x06 */
+	u8 date_set;		/* RTC + 0x07 */
+
+	u8 write_sw;		/* RTC + 0x08 */
+	u8 sw_set;		/* RTC + 0x09 */
+	u16 year_set;		/* RTC + 0x0a */
+
+	u8 alm_enable;		/* RTC + 0x0c */
+	u8 alm_hour_set;	/* RTC + 0x0d */
+	u8 alm_min_set;		/* RTC + 0x0e */
+	u8 int_enable;		/* RTC + 0x0f */
+
+	u8 reserved1;
+	u8 hour;		/* RTC + 0x11 */
+	u8 minute;		/* RTC + 0x12 */
+	u8 second;		/* RTC + 0x13 */
+
+	u8 month;		/* RTC + 0x14 */
+	u8 wday_mday;		/* RTC + 0x15 */
+	u16 year;		/* RTC + 0x16 */
+
+	u8 int_alm;		/* RTC + 0x18 */
+	u8 int_sw;		/* RTC + 0x19 */
+	u8 alm_status;		/* RTC + 0x1a */
+	u8 sw_minute;		/* RTC + 0x1b */
+
+	u8 bus_error_1;		/* RTC + 0x1c */
+	u8 int_day;		/* RTC + 0x1d */
+	u8 int_min;		/* RTC + 0x1e */
+	u8 int_sec;		/* RTC + 0x1f */
+
+	/*
+	 * target_time:
+	 *	intended to be used for hibernation but hibernation
+	 *	does not work on silicon rev 1.5 so use it for non-volatile
+	 *	storage of offset between the actual_time register and linux
+	 *	time
+	 */
+	u32 target_time;	/* RTC + 0x20 */
+	/*
+	 * actual_time:
+	 * 	readonly time since VBAT_RTC was last connected
+	 */
+	u32 actual_time;	/* RTC + 0x24 */
+	u32 keep_alive;		/* RTC + 0x28 */
+};
+
+struct mpc5121_rtc_data {
+	unsigned irq;
+	unsigned irq_periodic;
+	struct mpc5121_rtc_regs __iomem *regs;
+	struct rtc_device *rtc;
+	struct rtc_wkalrm wkalarm;
+};
+
+/*
+ * Update second/minute/hour registers.
+ *
+ * This is just so alarm will work.
+ */
+static void mpc5121_rtc_update_smh(struct mpc5121_rtc_regs __iomem *regs,
+	struct rtc_time *tm)
+{
+	out_8(&regs->second_set, tm->tm_sec);
+	out_8(&regs->minute_set, tm->tm_min);
+	out_8(&regs->hour_set, tm->tm_hour);
+
+	/* set time sequence */
+	out_8(&regs->set_time, 0x1);
+	out_8(&regs->set_time, 0x3);
+	out_8(&regs->set_time, 0x1);
+	out_8(&regs->set_time, 0x0);
+}
+
+static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+	unsigned long now;
+
+	/*
+	 * linux time is actual_time plus the offset saved in target_time
+	 */
+	now = in_be32(&regs->actual_time) + in_be32(&regs->target_time);
+
+	rtc_time_to_tm(now, tm);
+
+	/*
+	 * update second minute hour registers
+	 * so alarms will work
+	 */
+	mpc5121_rtc_update_smh(regs, tm);
+
+	return 0;
+}
+
+static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+	int ret;
+	unsigned long now;
+
+
+	/*
+	 * The actual_time register is read only so we write the offset
+	 * between it and linux time to the target_time register.
+	 */
+	ret = rtc_tm_to_time(tm, &now);
+	if (ret == 0)
+		out_be32(&regs->target_time, now - in_be32(&regs->actual_time));
+
+	/*
+	 * update second minute hour registers
+	 * so alarms will work
+	 */
+	mpc5121_rtc_update_smh(regs, tm);
+
+	return 0;
+}
+
+static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	*alarm = rtc->wkalarm;
+
+	alarm->pending = in_8(&regs->alm_status);
+
+	return 0;
+}
+
+static int mpc5121_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	/*
+	 * the alarm has no seconds so deal with it
+	 */
+	if (alarm->time.tm_sec) {
+		alarm->time.tm_sec = 0;
+		alarm->time.tm_min++;
+		if (alarm->time.tm_min >= 60) {
+			alarm->time.tm_min = 0;
+			alarm->time.tm_hour++;
+			if (alarm->time.tm_hour >= 24)
+				alarm->time.tm_hour = 0;
+		}
+	}
+
+	alarm->time.tm_mday = -1;
+	alarm->time.tm_mon = -1;
+	alarm->time.tm_year = -1;
+
+	out_8(&regs->alm_min_set, alarm->time.tm_min);
+	out_8(&regs->alm_hour_set, alarm->time.tm_hour);
+
+	out_8(&regs->alm_enable, alarm->enabled);
+
+	rtc->wkalarm = *alarm;
+	return 0;
+}
+
+static irqreturn_t mpc5121_rtc_handler(int irq, void *dev)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	if (in_8(&regs->int_alm)) {
+		/* acknowledge and clear status */
+		out_8(&regs->int_alm, 1);
+		out_8(&regs->alm_status, 1);
+
+		rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t mpc5121_rtc_handler_upd(int irq, void *dev)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	if (in_8(&regs->int_sec) && (in_8(&regs->int_enable) & 0x1)) {
+		/* acknowledge */
+		out_8(&regs->int_sec, 1);
+
+		rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int mpc5121_rtc_ioctl(struct device *dev, unsigned int cmd,
+							unsigned long arg)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	switch (cmd) {
+		/* alarm interrupt */
+	case RTC_AIE_ON:
+		out_8(&regs->alm_enable, 1);
+		rtc->wkalarm.enabled = 1;
+		break;
+	case RTC_AIE_OFF:
+		out_8(&regs->alm_enable, 0);
+		rtc->wkalarm.enabled = 0;
+		break;
+
+		/* update interrupt */
+	case RTC_UIE_ON:
+		out_8(&regs->int_enable,
+				(in_8(&regs->int_enable) & ~0x8) | 0x1);
+		break;
+	case RTC_UIE_OFF:
+		out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
+		break;
+
+		/* no periodic interrupts */
+	case RTC_IRQP_READ:
+	case RTC_IRQP_SET:
+		return -ENOTTY;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static const struct rtc_class_ops mpc5121_rtc_ops = {
+	.read_time = mpc5121_rtc_read_time,
+	.set_time = mpc5121_rtc_set_time,
+	.read_alarm = mpc5121_rtc_read_alarm,
+	.set_alarm = mpc5121_rtc_set_alarm,
+	.ioctl = mpc5121_rtc_ioctl,
+};
+
+static int __devinit mpc5121_rtc_probe(struct of_device *op,
+					const struct of_device_id *match)
+{
+	struct mpc5121_rtc_data *rtc;
+	int err = 0;
+	u32 ka;
+
+	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+	if (!rtc) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rtc->regs = of_iomap(op->node, 0);
+
+	if (!rtc->regs) {
+		printk(KERN_ERR "%s: couldn't map io space\n", __func__);
+		err = -ENOSYS;
+		goto out_free;
+	}
+
+	device_init_wakeup(&op->dev, 1);
+
+	rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
+						&mpc5121_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc)) {
+		err = PTR_ERR(rtc->rtc);
+		goto out_unmap;
+	}
+
+	dev_set_drvdata(&op->dev, rtc);
+
+	rtc->irq = irq_of_parse_and_map(op->node, 1);
+	err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
+						"mpc5121-rtc", &op->dev);
+	if (err) {
+		printk(KERN_ERR "%s: could not request irq: %i\n",
+							__func__, rtc->irq);
+		goto out_dispose;
+	}
+
+	rtc->irq_periodic = irq_of_parse_and_map(op->node, 0);
+	err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
+				 IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
+	if (err) {
+		printk(KERN_ERR "%s: could not request irq: %i\n",
+						__func__, rtc->irq_periodic);
+		goto out_dispose2;
+	}
+
+	ka = in_be32(&rtc->regs->keep_alive);
+	if (ka & 0x02) {
+		printk(KERN_WARNING
+			"mpc5121-rtc: Battery or oscillator failure!\n");
+		out_be32(&rtc->regs->keep_alive, ka);
+	}
+
+	goto out;
+
+out_dispose2:
+	irq_dispose_mapping(rtc->irq_periodic);
+	free_irq(rtc->irq, &op->dev);
+out_dispose:
+	irq_dispose_mapping(rtc->irq);
+out_unmap:
+	iounmap(rtc->regs);
+out_free:
+	kfree(rtc);
+out:
+	return err;
+}
+
+static int __devexit mpc5121_rtc_remove(struct of_device *op)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	/* disable interrupt, so there are no nasty surprises */
+	out_8(&regs->alm_enable, 0);
+	out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
+
+	rtc_device_unregister(rtc->rtc);
+	iounmap(rtc->regs);
+	free_irq(rtc->irq, &op->dev);
+	free_irq(rtc->irq_periodic, &op->dev);
+	irq_dispose_mapping(rtc->irq);
+	irq_dispose_mapping(rtc->irq_periodic);
+	dev_set_drvdata(&op->dev, NULL);
+	kfree(rtc);
+
+	return 0;
+}
+
+static struct of_device_id mpc5121_rtc_match[] = {
+	{ .compatible = "fsl,mpc5121-rtc", },
+	{},
+};
+
+static struct of_platform_driver mpc5121_rtc_driver = {
+	.owner = THIS_MODULE,
+	.name = "mpc5121-rtc",
+	.match_table = mpc5121_rtc_match,
+	.probe = mpc5121_rtc_probe,
+	.remove = mpc5121_rtc_remove,
+};
+
+static int __init mpc5121_rtc_init(void)
+{
+	return of_register_platform_driver(&mpc5121_rtc_driver);
+}
+
+static void __exit mpc5121_rtc_exit(void)
+{
+	of_unregister_platform_driver(&mpc5121_rtc_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Rigby <jrigby@freescale.com>");
+
+module_init(mpc5121_rtc_init);
+module_exit(mpc5121_rtc_exit);
-- 
1.5.6.3

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

* [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
  2010-01-19 20:24 ` Anatolij Gustschin
@ 2010-01-19 20:24   ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wd, dzu, linux-mtd, Anatolij Gustschin, Piotr Ziecik

From: Piotr Ziecik <kosmo@semihalf.com>

Adds NAND Flash Controller driver for MPC5121 Revision 2.
All device features, except hardware ECC and power management,
are supported.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <linux-mtd@lists.infradead.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 arch/powerpc/platforms/512x/mpc512x_shared.c |    1 +
 drivers/mtd/nand/Kconfig                     |    7 +
 drivers/mtd/nand/Makefile                    |    1 +
 drivers/mtd/nand/mpc5121_nfc.c               |  916 ++++++++++++++++++++++++++
 4 files changed, 925 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mpc5121_nfc.c

diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 8a0d577..38d49ad 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -83,6 +83,7 @@ void __init mpc512x_init_IRQ(void)
 static struct of_device_id __initdata of_bus_ids[] = {
 	{ .compatible = "fsl,mpc5121-immr", },
 	{ .compatible = "fsl,mpc5121-localbus", },
+	{ .compatible = "fsl,mpc5121-nfc", },
 	{},
 };
 
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 677cd53..099f002 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -442,6 +442,13 @@ config MTD_NAND_FSL_UPM
 	  Enables support for NAND Flash chips wired onto Freescale PowerPC
 	  processor localbus with User-Programmable Machine support.
 
+config MTD_NAND_MPC5121_NFC
+	tristate "MPC5121 built-in NAND Flash Controller support"
+	depends on PPC_MPC512x
+	help
+	  This enables the driver for the NAND flash controller on the
+	  MPC5121 SoC.
+
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
 	depends on ARCH_MX2 || ARCH_MX3
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1407bd1..d4ddf05 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -42,5 +42,6 @@ obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_W90P910)		+= w90p910_nand.o
 obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
+obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
new file mode 100644
index 0000000..2980eb1
--- /dev/null
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -0,0 +1,916 @@
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc.
+ * Copyright 2009 Semihalf.
+ *
+ * Approved as OSADL project by a majority of OSADL members and funded
+ * by OSADL membership fees in 2009;  for details see www.osadl.org.
+ *
+ * Based on original driver from Freescale Semiconductor
+ * written by John Rigby <jrigby@freescale.com> on basis
+ * of drivers/mtd/nand/mxc_nand.c. Reworked and extended
+ * Piotr Ziecik <kosmo@semihalf.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <asm/mpc5xxx.h>
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n)	((n) *  0x200)
+
+/* Addresses for NFC SPARE BUFFER areas */
+#define NFC_SPARE_BUFFERS	8
+#define NFC_SPARE_LEN		0x40
+#define NFC_SPARE_AREA(n)	(0x1000 + ((n) * NFC_SPARE_LEN))
+
+/* MPC5121 NFC registers */
+#define NFC_BUF_ADDR		0x1E04
+#define NFC_FLASH_ADDR		0x1E06
+#define NFC_FLASH_CMD		0x1E08
+#define NFC_CONFIG		0x1E0A
+#define NFC_ECC_STATUS1		0x1E0C
+#define NFC_ECC_STATUS2		0x1E0E
+#define NFC_SPAS		0x1E10
+#define NFC_WRPROT		0x1E12
+#define NFC_NF_WRPRST		0x1E18
+#define NFC_CONFIG1		0x1E1A
+#define NFC_CONFIG2		0x1E1C
+#define NFC_UNLOCKSTART_BLK0	0x1E20
+#define NFC_UNLOCKEND_BLK0	0x1E22
+#define NFC_UNLOCKSTART_BLK1	0x1E24
+#define NFC_UNLOCKEND_BLK1	0x1E26
+#define NFC_UNLOCKSTART_BLK2	0x1E28
+#define NFC_UNLOCKEND_BLK2	0x1E2A
+#define NFC_UNLOCKSTART_BLK3	0x1E2C
+#define NFC_UNLOCKEND_BLK3	0x1E2E
+
+/* Bit Definitions: NFC_BUF_ADDR */
+#define NFC_RBA_MASK		(7 << 0)
+#define NFC_ACTIVE_CS_SHIFT	5
+#define NFC_ACTIVE_CS_MASK	(3 << NFC_ACTIVE_CS_SHIFT)
+
+/* Bit Definitions: NFC_CONFIG */
+#define NFC_BLS_UNLOCKED	(1 << 1)
+
+/* Bit Definitions: NFC_CONFIG1 */
+#define NFC_ECC_4BIT		(1 << 0)
+#define NFC_FULL_PAGE_DMA	(1 << 1)
+#define NFC_SPARE_ONLY		(1 << 2)
+#define NFC_ECC_ENABLE		(1 << 3)
+#define NFC_INT_MASK		(1 << 4)
+#define NFC_BIG_ENDIAN		(1 << 5)
+#define NFC_RESET		(1 << 6)
+#define NFC_CE			(1 << 7)
+#define NFC_ONE_CYCLE		(1 << 8)
+#define NFC_PPB_32		(0 << 9)
+#define NFC_PPB_64		(1 << 9)
+#define NFC_PPB_128		(2 << 9)
+#define NFC_PPB_256		(3 << 9)
+#define NFC_PPB_MASK		(3 << 9)
+#define NFC_FULL_PAGE_INT	(1 << 11)
+
+/* Bit Definitions: NFC_CONFIG2 */
+#define NFC_COMMAND		(1 << 0)
+#define NFC_ADDRESS		(1 << 1)
+#define NFC_INPUT		(1 << 2)
+#define NFC_OUTPUT		(1 << 3)
+#define NFC_ID			(1 << 4)
+#define NFC_STATUS		(1 << 5)
+#define NFC_CMD_FAIL		(1 << 15)
+#define NFC_INT			(1 << 15)
+
+/* Bit Definitions: NFC_WRPROT */
+#define NFC_WPC_LOCK_TIGHT	(1 << 0)
+#define NFC_WPC_LOCK		(1 << 1)
+#define NFC_WPC_UNLOCK		(1 << 2)
+
+#define	DRV_NAME		"mpc5121_nfc"
+
+/* Timeouts */
+#define NFC_RESET_TIMEOUT	1000		/* 1 ms */
+#define NFC_TIMEOUT		(HZ / 10)	/* 1/10 s */
+
+struct mpc5121_nfc_prv {
+	struct mtd_info		mtd;
+	struct nand_chip	chip;
+	int			irq;
+	void __iomem		*regs;
+	struct clk		*clk;
+	wait_queue_head_t	irq_waitq;
+	uint			column;
+	int			spareonly;
+	void __iomem		*csreg;
+	struct device		*dev;
+};
+
+static void mpc5121_nfc_done(struct mtd_info *mtd);
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
+#endif
+
+/* Read NFC register */
+static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	return in_be16(prv->regs + reg);
+}
+
+/* Write NFC register */
+static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	out_be16(prv->regs + reg, val);
+}
+
+/* Set bits in NFC register */
+static inline void nfc_set(struct mtd_info *mtd, uint reg, u16 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
+}
+
+/* Clear bits in NFC register */
+static inline void nfc_clear(struct mtd_info *mtd, uint reg, u16 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
+}
+
+/* Invoke address cycle */
+static inline void mpc5121_nfc_send_addr(struct mtd_info *mtd, u16 addr)
+{
+	nfc_write(mtd, NFC_FLASH_ADDR, addr);
+	nfc_write(mtd, NFC_CONFIG2, NFC_ADDRESS);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Invoke command cycle */
+static inline void mpc5121_nfc_send_cmd(struct mtd_info *mtd, u16 cmd)
+{
+	nfc_write(mtd, NFC_FLASH_CMD, cmd);
+	nfc_write(mtd, NFC_CONFIG2, NFC_COMMAND);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Send data from NFC buffers to NAND flash */
+static inline void mpc5121_nfc_send_prog_page(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_INPUT);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive data from NAND flash */
+static inline void mpc5121_nfc_send_read_page(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_OUTPUT);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive ID from NAND flash */
+static inline void mpc5121_nfc_send_read_id(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_ID);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive status from NAND flash */
+static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_STATUS);
+	mpc5121_nfc_done(mtd);
+}
+
+/* NFC interrupt handler */
+static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
+{
+	struct mtd_info *mtd = data;
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK);
+	wake_up(&prv->irq_waitq);
+
+	return IRQ_HANDLED;
+}
+
+/* Wait for operation complete */
+static void mpc5121_nfc_done(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	int rv;
+
+	if ((nfc_read(mtd, NFC_CONFIG2) & NFC_INT) == 0) {
+		nfc_clear(mtd, NFC_CONFIG1, NFC_INT_MASK);
+		rv = wait_event_timeout(prv->irq_waitq,
+			(nfc_read(mtd, NFC_CONFIG2) & NFC_INT), NFC_TIMEOUT);
+
+		if (!rv)
+			dev_warn(prv->dev,
+				"Timeout while waiting for interrupt.\n");
+	}
+
+	nfc_clear(mtd, NFC_CONFIG2, NFC_INT);
+}
+
+/* Do address cycle(s) */
+static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	u32 pagemask = chip->pagemask;
+
+	if (column != -1) {
+		mpc5121_nfc_send_addr(mtd, column);
+		if (mtd->writesize > 512)
+			mpc5121_nfc_send_addr(mtd, column >> 8);
+	}
+
+	if (page != -1) {
+		do {
+			mpc5121_nfc_send_addr(mtd, page & 0xFF);
+			page >>= 8;
+			pagemask >>= 8;
+		} while (pagemask);
+	}
+}
+
+/* Control chip select signals */
+static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	if (chip < 0) {
+		nfc_clear(mtd, NFC_CONFIG1, NFC_CE);
+		return;
+	}
+
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_ACTIVE_CS_MASK);
+	nfc_set(mtd, NFC_BUF_ADDR, (chip << NFC_ACTIVE_CS_SHIFT) &
+							NFC_ACTIVE_CS_MASK);
+	nfc_set(mtd, NFC_CONFIG1, NFC_CE);
+}
+
+/* Init external chip select logic on ADS5121 board */
+static int ads5121_chipselect_init(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct device_node *dn;
+
+	dn = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld");
+	if (dn) {
+		prv->csreg = of_iomap(dn, 0);
+		of_node_put(dn);
+		if (!prv->csreg)
+			return -ENOMEM;
+
+		/* CPLD Register 9 controls NAND /CE Lines */
+		prv->csreg += 9;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/* Control chips select signal on ADS5121 board */
+static void ads5121_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	u8 v;
+
+	v = in_8(prv->csreg);
+	v |= 0x0F;
+
+	if (chip >= 0) {
+		mpc5121_nfc_select_chip(mtd, 0);
+		v &= ~(1 << chip);
+	} else
+		mpc5121_nfc_select_chip(mtd, -1);
+
+	out_8(prv->csreg, v);
+}
+
+/* Read NAND Ready/Busy signal */
+static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles ready/busy signal internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+/* Write command to NAND flash */
+static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
+							int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	prv->column = (column >= 0) ? column : 0;
+	prv->spareonly = 0;
+
+	switch (command) {
+	case NAND_CMD_PAGEPROG:
+		mpc5121_nfc_send_prog_page(mtd);
+		break;
+	/*
+	 * NFC does not support sub-page reads and writes,
+	 * so emulate them using full page transfers.
+	 */
+	case NAND_CMD_READ0:
+		column = 0;
+		break;
+
+	case NAND_CMD_READ1:
+		prv->column += 256;
+		command = NAND_CMD_READ0;
+		column = 0;
+		break;
+
+	case NAND_CMD_READOOB:
+		prv->spareonly = 1;
+		command = NAND_CMD_READ0;
+		column = 0;
+		break;
+
+	case NAND_CMD_SEQIN:
+		mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page);
+		column = 0;
+		break;
+
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+	case NAND_CMD_READID:
+	case NAND_CMD_STATUS:
+		break;
+
+	default:
+		return;
+	}
+
+	mpc5121_nfc_send_cmd(mtd, command);
+	mpc5121_nfc_addr_cycle(mtd, column, page);
+
+	switch (command) {
+	case NAND_CMD_READ0:
+		if (mtd->writesize > 512)
+			mpc5121_nfc_send_cmd(mtd, NAND_CMD_READSTART);
+		mpc5121_nfc_send_read_page(mtd);
+		break;
+
+	case NAND_CMD_READID:
+		mpc5121_nfc_send_read_id(mtd);
+		break;
+
+	case NAND_CMD_STATUS:
+		mpc5121_nfc_send_read_status(mtd);
+		if (chip->options & NAND_BUSWIDTH_16)
+			prv->column = 1;
+		else
+			prv->column = 0;
+		break;
+	}
+}
+
+/* Copy data from/to NFC spare buffers. */
+static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
+						u8 *buffer, uint size, int wr)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	uint o, s, sbsize, blksize;
+
+	/*
+	 * NAND spare area is available through NFC spare buffers.
+	 * The NFC divides spare area into (page_size / 512) chunks.
+	 * Each chunk is placed into separate spare memory area, using
+	 * first (spare_size / num_of_chunks) bytes of the buffer.
+	 *
+	 * For NAND device in which the spare area is not divided fully
+	 * by the number of chunks, number of used bytes in each spare
+	 * buffer is rounded down to the nearest even number of bytes,
+	 * and all remaining bytes are added to the last used spare area.
+	 *
+	 * For more information read section 26.6.10 of MPC5121e
+	 * Microcontroller Reference Manual, Rev. 3.
+	 */
+
+	/* Calculate number of valid bytes in each spare buffer */
+	sbsize = (mtd->oobsize / (mtd->writesize / 512)) & ~1;
+
+	while (size) {
+		/* Calculate spare buffer number */
+		s = offset / sbsize;
+		if (s > NFC_SPARE_BUFFERS - 1)
+			s = NFC_SPARE_BUFFERS - 1;
+
+		/*
+		 * Calculate offset to requested data block in selected spare
+		 * buffer and its size.
+		 */
+		o = offset - (s * sbsize);
+		blksize = min(sbsize - o, size);
+
+		if (wr)
+			memcpy_toio(prv->regs + NFC_SPARE_AREA(s) + o,
+							buffer, blksize);
+		else
+			memcpy_fromio(buffer,
+				prv->regs + NFC_SPARE_AREA(s) + o, blksize);
+
+		buffer += blksize;
+		offset += blksize;
+		size -= blksize;
+	};
+}
+
+/* Copy data from/to NFC main and spare buffers */
+static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
+									int wr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	uint c = prv->column;
+	uint l;
+
+	/* Handle spare area access */
+	if (prv->spareonly || c >= mtd->writesize) {
+		/* Calculate offset from beginning of spare area */
+		if (c >= mtd->writesize)
+			c -= mtd->writesize;
+
+		prv->column += len;
+		mpc5121_nfc_copy_spare(mtd, c, buf, len, wr);
+		return;
+	}
+
+	/*
+	 * Handle main area access - limit copy length to prevent
+	 * crossing main/spare boundary.
+	 */
+	l = min((uint)len, mtd->writesize - c);
+	prv->column += l;
+
+	if (wr)
+		memcpy_toio(prv->regs + NFC_MAIN_AREA(0) + c, buf, l);
+	else
+		memcpy_fromio(buf, prv->regs + NFC_MAIN_AREA(0) + c, l);
+
+	/* Handle crossing main/spare boundary */
+	if (l != len) {
+		buf += l;
+		len -= l;
+		mpc5121_nfc_buf_copy(mtd, buf, len, wr);
+	}
+}
+
+/* Read data from NFC buffers */
+static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	mpc5121_nfc_buf_copy(mtd, buf, len, 0);
+}
+
+/* Write data to NFC buffers */
+static void mpc5121_nfc_write_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
+}
+
+/* Compare buffer with NAND flash */
+static int mpc5121_nfc_verify_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mpc5121_nfc_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/* Read byte from NFC buffers */
+static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd)
+{
+	u8 tmp;
+
+	mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/* Read word from NFC buffers */
+static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
+{
+	u16 tmp;
+
+	mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/*
+ * Read NFC configuration from Reset Config Word
+ *
+ * NFC is configured during reset in basis of information stored
+ * in Reset Config Word. There is no other way to set NAND block
+ * size, spare size and bus width.
+ */
+static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct mpc512x_reset_module *rm;
+	struct device_node *rmnode;
+	uint rcw_pagesize = 0;
+	uint rcw_sparesize = 0;
+	uint rcw_width;
+	uint rcwh;
+	uint romloc, ps;
+
+	rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
+	if (!rmnode) {
+		dev_err(prv->dev, "Missing 'fsl,mpc5121-reset' "
+					"node in device tree!\n");
+		return -ENODEV;
+	}
+
+	rm = of_iomap(rmnode, 0);
+	if (!rm) {
+		dev_err(prv->dev, "Error mapping reset module node!\n");
+		return -EBUSY;
+	}
+
+	rcwh = in_be32(&rm->rcwhr);
+
+	/* Bit 6: NFC bus width */
+	rcw_width = ((rcwh >> 6) & 0x1) ? 2 : 1;
+
+	/* Bit 7: NFC Page/Spare size */
+	ps = (rcwh >> 7) & 0x1;
+
+	/* Bits [22:21]: ROM Location */
+	romloc = (rcwh >> 21) & 0x3;
+
+	/* Decode RCW bits */
+	switch ((ps << 2) | romloc) {
+	case 0x00:
+	case 0x01:
+		rcw_pagesize = 512;
+		rcw_sparesize = 16;
+		break;
+	case 0x02:
+	case 0x03:
+		rcw_pagesize = 4096;
+		rcw_sparesize = 128;
+		break;
+	case 0x04:
+	case 0x05:
+		rcw_pagesize = 2048;
+		rcw_sparesize = 64;
+		break;
+	case 0x06:
+	case 0x07:
+		rcw_pagesize = 4096;
+		rcw_sparesize = 218;
+		break;
+	}
+
+	mtd->writesize = rcw_pagesize;
+	mtd->oobsize = rcw_sparesize;
+	if (rcw_width == 2)
+		chip->options |= NAND_BUSWIDTH_16;
+
+	dev_notice(prv->dev, "Configured for "
+				"%u-bit NAND, page size %u "
+				"with %u spare.\n",
+				rcw_width * 8, rcw_pagesize,
+				rcw_sparesize);
+	iounmap(rm);
+	of_node_put(rmnode);
+	return 0;
+}
+
+/* Free driver resources */
+static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	if (prv->clk) {
+		clk_disable(prv->clk);
+		clk_put(prv->clk);
+	}
+
+	if (prv->csreg)
+		iounmap(prv->csreg);
+}
+
+static int __init mpc5121_nfc_probe(struct of_device *op,
+					const struct of_device_id *match)
+{
+	struct device_node *rootnode, *dn = op->node;
+	struct device *dev = &op->dev;
+	struct mpc5121_nfc_prv *prv;
+	struct resource res;
+	struct mtd_info *mtd;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *parts;
+#endif
+	struct nand_chip *chip;
+	unsigned long regs_paddr, regs_size;
+	const uint *chips_no;
+	int resettime = 0;
+	int retval = 0;
+	int rev, len;
+
+	/*
+	 * Check SoC revision. This driver supports only NFC
+	 * in MPC5121 revision 2.
+	 */
+	rev = (mfspr(SPRN_SVR) >> 4) & 0xF;
+	if (rev != 2) {
+		dev_err(dev, "SoC revision %u is not supported!\n", rev);
+		return -ENXIO;
+	}
+
+	prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL);
+	if (!prv) {
+		dev_err(dev, "Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	mtd = &prv->mtd;
+	chip = &prv->chip;
+
+	mtd->priv = chip;
+	chip->priv = prv;
+	prv->dev = dev;
+
+	/* Read NFC configuration from Reset Config Word */
+	retval = mpc5121_nfc_read_hw_config(mtd);
+	if (retval) {
+		dev_err(dev, "Unable to read NFC config!\n");
+		return retval;
+	}
+
+	prv->irq = irq_of_parse_and_map(dn, 0);
+	if (prv->irq == NO_IRQ) {
+		dev_err(dev, "Error mapping IRQ!\n");
+		return -EINVAL;
+	}
+
+	retval = of_address_to_resource(dn, 0, &res);
+	if (retval) {
+		dev_err(dev, "Error parsing memory region!\n");
+		return retval;
+	}
+
+	chips_no = of_get_property(dn, "chips", &len);
+	if (!chips_no || len != sizeof(*chips_no)) {
+		dev_err(dev, "Invalid/missing 'chips' property!\n");
+		return -EINVAL;
+	}
+
+	regs_paddr = res.start;
+	regs_size = res.end - res.start + 1;
+
+	if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) {
+		dev_err(dev, "Error requesting memory region!\n");
+		return -EBUSY;
+	}
+
+	prv->regs = devm_ioremap(dev, regs_paddr, regs_size);
+	if (!prv->regs) {
+		dev_err(dev, "Error mapping memory region!\n");
+		return -ENOMEM;
+	}
+
+	mtd->name = "MPC5121 NAND";
+	chip->dev_ready = mpc5121_nfc_dev_ready;
+	chip->cmdfunc = mpc5121_nfc_command;
+	chip->read_byte = mpc5121_nfc_read_byte;
+	chip->read_word = mpc5121_nfc_read_word;
+	chip->read_buf = mpc5121_nfc_read_buf;
+	chip->write_buf = mpc5121_nfc_write_buf;
+	chip->verify_buf = mpc5121_nfc_verify_buf;
+	chip->select_chip = mpc5121_nfc_select_chip;
+	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
+	chip->ecc.mode = NAND_ECC_SOFT;
+
+	/* Support external chip-select logic on ADS5121 board */
+	rootnode = of_find_node_by_path("/");
+	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
+		retval = ads5121_chipselect_init(mtd);
+		if (retval) {
+			dev_err(dev, "Chipselect init error!\n");
+			of_node_put(rootnode);
+			return retval;
+		}
+
+		chip->select_chip = ads5121_select_chip;
+	}
+	of_node_put(rootnode);
+
+	/* Enable NFC clock */
+	prv->clk = clk_get(dev, "nfc_clk");
+	if (!prv->clk) {
+		dev_err(dev, "Unable to acquire NFC clock!\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	clk_enable(prv->clk);
+
+	/* Reset NAND Flash controller */
+	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
+	while (nfc_read(mtd, NFC_CONFIG1) & NFC_RESET) {
+		if (resettime++ >= NFC_RESET_TIMEOUT) {
+			dev_err(dev, "Timeout while resetting NFC!\n");
+			retval = -EINVAL;
+			goto error;
+		}
+
+		udelay(1);
+	}
+
+	/* Enable write to NFC memory */
+	nfc_write(mtd, NFC_CONFIG, NFC_BLS_UNLOCKED);
+
+	/* Enable write to all NAND pages */
+	nfc_write(mtd, NFC_UNLOCKSTART_BLK0, 0x0000);
+	nfc_write(mtd, NFC_UNLOCKEND_BLK0, 0xFFFF);
+	nfc_write(mtd, NFC_WRPROT, NFC_WPC_UNLOCK);
+
+	/*
+	 * Setup NFC:
+	 *	- Big Endian transfers,
+	 *	- Interrupt after full page read/write.
+	 */
+	nfc_write(mtd, NFC_CONFIG1, NFC_BIG_ENDIAN | NFC_INT_MASK |
+							NFC_FULL_PAGE_INT);
+
+	/* Set spare area size */
+	nfc_write(mtd, NFC_SPAS, mtd->oobsize >> 1);
+
+	init_waitqueue_head(&prv->irq_waitq);
+	retval = devm_request_irq(dev, prv->irq, &mpc5121_nfc_irq, 0, DRV_NAME,
+									mtd);
+	if (retval) {
+		dev_err(dev, "Error requesting IRQ!\n");
+		goto error;
+	}
+
+	/* Detect NAND chips */
+	if (nand_scan(mtd, *chips_no)) {
+		dev_err(dev, "NAND Flash not found !\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -ENXIO;
+		goto error;
+	}
+
+	/* Set erase block size */
+	switch (mtd->erasesize / mtd->writesize) {
+	case 32:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_32);
+		break;
+
+	case 64:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_64);
+		break;
+
+	case 128:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_128);
+		break;
+
+	case 256:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_256);
+		break;
+
+	default:
+		dev_err(dev, "Unsupported NAND flash!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -ENXIO;
+		goto error;
+	}
+
+	dev_set_drvdata(dev, mtd);
+
+	/* Register device in MTD */
+#ifdef CONFIG_MTD_PARTITIONS
+	retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
+#ifdef CONFIG_MTD_OF_PARTS
+	if (retval == 0)
+		retval = of_mtd_parse_partitions(dev, dn, &parts);
+#endif
+	if (retval < 0) {
+		dev_err(dev, "Error parsing MTD partitions!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -EINVAL;
+		goto error;
+	}
+
+	if (retval > 0)
+		retval = add_mtd_partitions(mtd, parts, retval);
+	else
+#endif
+		retval = add_mtd_device(mtd);
+
+	if (retval) {
+		dev_err(dev, "Error adding MTD device!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		goto error;
+	}
+
+	return 0;
+error:
+	mpc5121_nfc_free(dev, mtd);
+	return retval;
+}
+
+static int __exit mpc5121_nfc_remove(struct of_device *op)
+{
+	struct device *dev = &op->dev;
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	nand_release(mtd);
+	devm_free_irq(dev, prv->irq, mtd);
+	mpc5121_nfc_free(dev, mtd);
+
+	return 0;
+}
+
+static struct of_device_id mpc5121_nfc_match[] = {
+	{ .compatible = "fsl,mpc5121-nfc", },
+	{},
+};
+
+static struct of_platform_driver mpc5121_nfc_driver = {
+	.match_table	= mpc5121_nfc_match,
+	.probe		= mpc5121_nfc_probe,
+	.remove		= __exit_p(mpc5121_nfc_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mpc5121_nfc_init(void)
+{
+	return of_register_platform_driver(&mpc5121_nfc_driver);
+}
+
+module_init(mpc5121_nfc_init);
+
+static void __exit mpc5121_nfc_cleanup(void)
+{
+	of_unregister_platform_driver(&mpc5121_nfc_driver);
+}
+
+module_exit(mpc5121_nfc_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MPC5121 NAND MTD driver");
+MODULE_LICENSE("GPL");
-- 
1.5.6.3

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

* [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
@ 2010-01-19 20:24   ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: John Rigby, dzu, Grant Likely, linux-mtd, Anatolij Gustschin,
	Piotr Ziecik

From: Piotr Ziecik <kosmo@semihalf.com>

Adds NAND Flash Controller driver for MPC5121 Revision 2.
All device features, except hardware ECC and power management,
are supported.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: <linux-mtd@lists.infradead.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 arch/powerpc/platforms/512x/mpc512x_shared.c |    1 +
 drivers/mtd/nand/Kconfig                     |    7 +
 drivers/mtd/nand/Makefile                    |    1 +
 drivers/mtd/nand/mpc5121_nfc.c               |  916 ++++++++++++++++++++++++++
 4 files changed, 925 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mpc5121_nfc.c

diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 8a0d577..38d49ad 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -83,6 +83,7 @@ void __init mpc512x_init_IRQ(void)
 static struct of_device_id __initdata of_bus_ids[] = {
 	{ .compatible = "fsl,mpc5121-immr", },
 	{ .compatible = "fsl,mpc5121-localbus", },
+	{ .compatible = "fsl,mpc5121-nfc", },
 	{},
 };
 
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 677cd53..099f002 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -442,6 +442,13 @@ config MTD_NAND_FSL_UPM
 	  Enables support for NAND Flash chips wired onto Freescale PowerPC
 	  processor localbus with User-Programmable Machine support.
 
+config MTD_NAND_MPC5121_NFC
+	tristate "MPC5121 built-in NAND Flash Controller support"
+	depends on PPC_MPC512x
+	help
+	  This enables the driver for the NAND flash controller on the
+	  MPC5121 SoC.
+
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
 	depends on ARCH_MX2 || ARCH_MX3
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1407bd1..d4ddf05 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -42,5 +42,6 @@ obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_W90P910)		+= w90p910_nand.o
 obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
+obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
new file mode 100644
index 0000000..2980eb1
--- /dev/null
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -0,0 +1,916 @@
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc.
+ * Copyright 2009 Semihalf.
+ *
+ * Approved as OSADL project by a majority of OSADL members and funded
+ * by OSADL membership fees in 2009;  for details see www.osadl.org.
+ *
+ * Based on original driver from Freescale Semiconductor
+ * written by John Rigby <jrigby@freescale.com> on basis
+ * of drivers/mtd/nand/mxc_nand.c. Reworked and extended
+ * Piotr Ziecik <kosmo@semihalf.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <asm/mpc5xxx.h>
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n)	((n) *  0x200)
+
+/* Addresses for NFC SPARE BUFFER areas */
+#define NFC_SPARE_BUFFERS	8
+#define NFC_SPARE_LEN		0x40
+#define NFC_SPARE_AREA(n)	(0x1000 + ((n) * NFC_SPARE_LEN))
+
+/* MPC5121 NFC registers */
+#define NFC_BUF_ADDR		0x1E04
+#define NFC_FLASH_ADDR		0x1E06
+#define NFC_FLASH_CMD		0x1E08
+#define NFC_CONFIG		0x1E0A
+#define NFC_ECC_STATUS1		0x1E0C
+#define NFC_ECC_STATUS2		0x1E0E
+#define NFC_SPAS		0x1E10
+#define NFC_WRPROT		0x1E12
+#define NFC_NF_WRPRST		0x1E18
+#define NFC_CONFIG1		0x1E1A
+#define NFC_CONFIG2		0x1E1C
+#define NFC_UNLOCKSTART_BLK0	0x1E20
+#define NFC_UNLOCKEND_BLK0	0x1E22
+#define NFC_UNLOCKSTART_BLK1	0x1E24
+#define NFC_UNLOCKEND_BLK1	0x1E26
+#define NFC_UNLOCKSTART_BLK2	0x1E28
+#define NFC_UNLOCKEND_BLK2	0x1E2A
+#define NFC_UNLOCKSTART_BLK3	0x1E2C
+#define NFC_UNLOCKEND_BLK3	0x1E2E
+
+/* Bit Definitions: NFC_BUF_ADDR */
+#define NFC_RBA_MASK		(7 << 0)
+#define NFC_ACTIVE_CS_SHIFT	5
+#define NFC_ACTIVE_CS_MASK	(3 << NFC_ACTIVE_CS_SHIFT)
+
+/* Bit Definitions: NFC_CONFIG */
+#define NFC_BLS_UNLOCKED	(1 << 1)
+
+/* Bit Definitions: NFC_CONFIG1 */
+#define NFC_ECC_4BIT		(1 << 0)
+#define NFC_FULL_PAGE_DMA	(1 << 1)
+#define NFC_SPARE_ONLY		(1 << 2)
+#define NFC_ECC_ENABLE		(1 << 3)
+#define NFC_INT_MASK		(1 << 4)
+#define NFC_BIG_ENDIAN		(1 << 5)
+#define NFC_RESET		(1 << 6)
+#define NFC_CE			(1 << 7)
+#define NFC_ONE_CYCLE		(1 << 8)
+#define NFC_PPB_32		(0 << 9)
+#define NFC_PPB_64		(1 << 9)
+#define NFC_PPB_128		(2 << 9)
+#define NFC_PPB_256		(3 << 9)
+#define NFC_PPB_MASK		(3 << 9)
+#define NFC_FULL_PAGE_INT	(1 << 11)
+
+/* Bit Definitions: NFC_CONFIG2 */
+#define NFC_COMMAND		(1 << 0)
+#define NFC_ADDRESS		(1 << 1)
+#define NFC_INPUT		(1 << 2)
+#define NFC_OUTPUT		(1 << 3)
+#define NFC_ID			(1 << 4)
+#define NFC_STATUS		(1 << 5)
+#define NFC_CMD_FAIL		(1 << 15)
+#define NFC_INT			(1 << 15)
+
+/* Bit Definitions: NFC_WRPROT */
+#define NFC_WPC_LOCK_TIGHT	(1 << 0)
+#define NFC_WPC_LOCK		(1 << 1)
+#define NFC_WPC_UNLOCK		(1 << 2)
+
+#define	DRV_NAME		"mpc5121_nfc"
+
+/* Timeouts */
+#define NFC_RESET_TIMEOUT	1000		/* 1 ms */
+#define NFC_TIMEOUT		(HZ / 10)	/* 1/10 s */
+
+struct mpc5121_nfc_prv {
+	struct mtd_info		mtd;
+	struct nand_chip	chip;
+	int			irq;
+	void __iomem		*regs;
+	struct clk		*clk;
+	wait_queue_head_t	irq_waitq;
+	uint			column;
+	int			spareonly;
+	void __iomem		*csreg;
+	struct device		*dev;
+};
+
+static void mpc5121_nfc_done(struct mtd_info *mtd);
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
+#endif
+
+/* Read NFC register */
+static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	return in_be16(prv->regs + reg);
+}
+
+/* Write NFC register */
+static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	out_be16(prv->regs + reg, val);
+}
+
+/* Set bits in NFC register */
+static inline void nfc_set(struct mtd_info *mtd, uint reg, u16 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
+}
+
+/* Clear bits in NFC register */
+static inline void nfc_clear(struct mtd_info *mtd, uint reg, u16 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
+}
+
+/* Invoke address cycle */
+static inline void mpc5121_nfc_send_addr(struct mtd_info *mtd, u16 addr)
+{
+	nfc_write(mtd, NFC_FLASH_ADDR, addr);
+	nfc_write(mtd, NFC_CONFIG2, NFC_ADDRESS);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Invoke command cycle */
+static inline void mpc5121_nfc_send_cmd(struct mtd_info *mtd, u16 cmd)
+{
+	nfc_write(mtd, NFC_FLASH_CMD, cmd);
+	nfc_write(mtd, NFC_CONFIG2, NFC_COMMAND);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Send data from NFC buffers to NAND flash */
+static inline void mpc5121_nfc_send_prog_page(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_INPUT);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive data from NAND flash */
+static inline void mpc5121_nfc_send_read_page(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_OUTPUT);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive ID from NAND flash */
+static inline void mpc5121_nfc_send_read_id(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_ID);
+	mpc5121_nfc_done(mtd);
+}
+
+/* Receive status from NAND flash */
+static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
+{
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK);
+	nfc_write(mtd, NFC_CONFIG2, NFC_STATUS);
+	mpc5121_nfc_done(mtd);
+}
+
+/* NFC interrupt handler */
+static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
+{
+	struct mtd_info *mtd = data;
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK);
+	wake_up(&prv->irq_waitq);
+
+	return IRQ_HANDLED;
+}
+
+/* Wait for operation complete */
+static void mpc5121_nfc_done(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	int rv;
+
+	if ((nfc_read(mtd, NFC_CONFIG2) & NFC_INT) == 0) {
+		nfc_clear(mtd, NFC_CONFIG1, NFC_INT_MASK);
+		rv = wait_event_timeout(prv->irq_waitq,
+			(nfc_read(mtd, NFC_CONFIG2) & NFC_INT), NFC_TIMEOUT);
+
+		if (!rv)
+			dev_warn(prv->dev,
+				"Timeout while waiting for interrupt.\n");
+	}
+
+	nfc_clear(mtd, NFC_CONFIG2, NFC_INT);
+}
+
+/* Do address cycle(s) */
+static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	u32 pagemask = chip->pagemask;
+
+	if (column != -1) {
+		mpc5121_nfc_send_addr(mtd, column);
+		if (mtd->writesize > 512)
+			mpc5121_nfc_send_addr(mtd, column >> 8);
+	}
+
+	if (page != -1) {
+		do {
+			mpc5121_nfc_send_addr(mtd, page & 0xFF);
+			page >>= 8;
+			pagemask >>= 8;
+		} while (pagemask);
+	}
+}
+
+/* Control chip select signals */
+static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	if (chip < 0) {
+		nfc_clear(mtd, NFC_CONFIG1, NFC_CE);
+		return;
+	}
+
+	nfc_clear(mtd, NFC_BUF_ADDR, NFC_ACTIVE_CS_MASK);
+	nfc_set(mtd, NFC_BUF_ADDR, (chip << NFC_ACTIVE_CS_SHIFT) &
+							NFC_ACTIVE_CS_MASK);
+	nfc_set(mtd, NFC_CONFIG1, NFC_CE);
+}
+
+/* Init external chip select logic on ADS5121 board */
+static int ads5121_chipselect_init(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct device_node *dn;
+
+	dn = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld");
+	if (dn) {
+		prv->csreg = of_iomap(dn, 0);
+		of_node_put(dn);
+		if (!prv->csreg)
+			return -ENOMEM;
+
+		/* CPLD Register 9 controls NAND /CE Lines */
+		prv->csreg += 9;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/* Control chips select signal on ADS5121 board */
+static void ads5121_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	u8 v;
+
+	v = in_8(prv->csreg);
+	v |= 0x0F;
+
+	if (chip >= 0) {
+		mpc5121_nfc_select_chip(mtd, 0);
+		v &= ~(1 << chip);
+	} else
+		mpc5121_nfc_select_chip(mtd, -1);
+
+	out_8(prv->csreg, v);
+}
+
+/* Read NAND Ready/Busy signal */
+static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles ready/busy signal internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+/* Write command to NAND flash */
+static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
+							int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	prv->column = (column >= 0) ? column : 0;
+	prv->spareonly = 0;
+
+	switch (command) {
+	case NAND_CMD_PAGEPROG:
+		mpc5121_nfc_send_prog_page(mtd);
+		break;
+	/*
+	 * NFC does not support sub-page reads and writes,
+	 * so emulate them using full page transfers.
+	 */
+	case NAND_CMD_READ0:
+		column = 0;
+		break;
+
+	case NAND_CMD_READ1:
+		prv->column += 256;
+		command = NAND_CMD_READ0;
+		column = 0;
+		break;
+
+	case NAND_CMD_READOOB:
+		prv->spareonly = 1;
+		command = NAND_CMD_READ0;
+		column = 0;
+		break;
+
+	case NAND_CMD_SEQIN:
+		mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page);
+		column = 0;
+		break;
+
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+	case NAND_CMD_READID:
+	case NAND_CMD_STATUS:
+		break;
+
+	default:
+		return;
+	}
+
+	mpc5121_nfc_send_cmd(mtd, command);
+	mpc5121_nfc_addr_cycle(mtd, column, page);
+
+	switch (command) {
+	case NAND_CMD_READ0:
+		if (mtd->writesize > 512)
+			mpc5121_nfc_send_cmd(mtd, NAND_CMD_READSTART);
+		mpc5121_nfc_send_read_page(mtd);
+		break;
+
+	case NAND_CMD_READID:
+		mpc5121_nfc_send_read_id(mtd);
+		break;
+
+	case NAND_CMD_STATUS:
+		mpc5121_nfc_send_read_status(mtd);
+		if (chip->options & NAND_BUSWIDTH_16)
+			prv->column = 1;
+		else
+			prv->column = 0;
+		break;
+	}
+}
+
+/* Copy data from/to NFC spare buffers. */
+static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
+						u8 *buffer, uint size, int wr)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	uint o, s, sbsize, blksize;
+
+	/*
+	 * NAND spare area is available through NFC spare buffers.
+	 * The NFC divides spare area into (page_size / 512) chunks.
+	 * Each chunk is placed into separate spare memory area, using
+	 * first (spare_size / num_of_chunks) bytes of the buffer.
+	 *
+	 * For NAND device in which the spare area is not divided fully
+	 * by the number of chunks, number of used bytes in each spare
+	 * buffer is rounded down to the nearest even number of bytes,
+	 * and all remaining bytes are added to the last used spare area.
+	 *
+	 * For more information read section 26.6.10 of MPC5121e
+	 * Microcontroller Reference Manual, Rev. 3.
+	 */
+
+	/* Calculate number of valid bytes in each spare buffer */
+	sbsize = (mtd->oobsize / (mtd->writesize / 512)) & ~1;
+
+	while (size) {
+		/* Calculate spare buffer number */
+		s = offset / sbsize;
+		if (s > NFC_SPARE_BUFFERS - 1)
+			s = NFC_SPARE_BUFFERS - 1;
+
+		/*
+		 * Calculate offset to requested data block in selected spare
+		 * buffer and its size.
+		 */
+		o = offset - (s * sbsize);
+		blksize = min(sbsize - o, size);
+
+		if (wr)
+			memcpy_toio(prv->regs + NFC_SPARE_AREA(s) + o,
+							buffer, blksize);
+		else
+			memcpy_fromio(buffer,
+				prv->regs + NFC_SPARE_AREA(s) + o, blksize);
+
+		buffer += blksize;
+		offset += blksize;
+		size -= blksize;
+	};
+}
+
+/* Copy data from/to NFC main and spare buffers */
+static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
+									int wr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	uint c = prv->column;
+	uint l;
+
+	/* Handle spare area access */
+	if (prv->spareonly || c >= mtd->writesize) {
+		/* Calculate offset from beginning of spare area */
+		if (c >= mtd->writesize)
+			c -= mtd->writesize;
+
+		prv->column += len;
+		mpc5121_nfc_copy_spare(mtd, c, buf, len, wr);
+		return;
+	}
+
+	/*
+	 * Handle main area access - limit copy length to prevent
+	 * crossing main/spare boundary.
+	 */
+	l = min((uint)len, mtd->writesize - c);
+	prv->column += l;
+
+	if (wr)
+		memcpy_toio(prv->regs + NFC_MAIN_AREA(0) + c, buf, l);
+	else
+		memcpy_fromio(buf, prv->regs + NFC_MAIN_AREA(0) + c, l);
+
+	/* Handle crossing main/spare boundary */
+	if (l != len) {
+		buf += l;
+		len -= l;
+		mpc5121_nfc_buf_copy(mtd, buf, len, wr);
+	}
+}
+
+/* Read data from NFC buffers */
+static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	mpc5121_nfc_buf_copy(mtd, buf, len, 0);
+}
+
+/* Write data to NFC buffers */
+static void mpc5121_nfc_write_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
+}
+
+/* Compare buffer with NAND flash */
+static int mpc5121_nfc_verify_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mpc5121_nfc_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/* Read byte from NFC buffers */
+static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd)
+{
+	u8 tmp;
+
+	mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/* Read word from NFC buffers */
+static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
+{
+	u16 tmp;
+
+	mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/*
+ * Read NFC configuration from Reset Config Word
+ *
+ * NFC is configured during reset in basis of information stored
+ * in Reset Config Word. There is no other way to set NAND block
+ * size, spare size and bus width.
+ */
+static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct mpc512x_reset_module *rm;
+	struct device_node *rmnode;
+	uint rcw_pagesize = 0;
+	uint rcw_sparesize = 0;
+	uint rcw_width;
+	uint rcwh;
+	uint romloc, ps;
+
+	rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
+	if (!rmnode) {
+		dev_err(prv->dev, "Missing 'fsl,mpc5121-reset' "
+					"node in device tree!\n");
+		return -ENODEV;
+	}
+
+	rm = of_iomap(rmnode, 0);
+	if (!rm) {
+		dev_err(prv->dev, "Error mapping reset module node!\n");
+		return -EBUSY;
+	}
+
+	rcwh = in_be32(&rm->rcwhr);
+
+	/* Bit 6: NFC bus width */
+	rcw_width = ((rcwh >> 6) & 0x1) ? 2 : 1;
+
+	/* Bit 7: NFC Page/Spare size */
+	ps = (rcwh >> 7) & 0x1;
+
+	/* Bits [22:21]: ROM Location */
+	romloc = (rcwh >> 21) & 0x3;
+
+	/* Decode RCW bits */
+	switch ((ps << 2) | romloc) {
+	case 0x00:
+	case 0x01:
+		rcw_pagesize = 512;
+		rcw_sparesize = 16;
+		break;
+	case 0x02:
+	case 0x03:
+		rcw_pagesize = 4096;
+		rcw_sparesize = 128;
+		break;
+	case 0x04:
+	case 0x05:
+		rcw_pagesize = 2048;
+		rcw_sparesize = 64;
+		break;
+	case 0x06:
+	case 0x07:
+		rcw_pagesize = 4096;
+		rcw_sparesize = 218;
+		break;
+	}
+
+	mtd->writesize = rcw_pagesize;
+	mtd->oobsize = rcw_sparesize;
+	if (rcw_width == 2)
+		chip->options |= NAND_BUSWIDTH_16;
+
+	dev_notice(prv->dev, "Configured for "
+				"%u-bit NAND, page size %u "
+				"with %u spare.\n",
+				rcw_width * 8, rcw_pagesize,
+				rcw_sparesize);
+	iounmap(rm);
+	of_node_put(rmnode);
+	return 0;
+}
+
+/* Free driver resources */
+static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	if (prv->clk) {
+		clk_disable(prv->clk);
+		clk_put(prv->clk);
+	}
+
+	if (prv->csreg)
+		iounmap(prv->csreg);
+}
+
+static int __init mpc5121_nfc_probe(struct of_device *op,
+					const struct of_device_id *match)
+{
+	struct device_node *rootnode, *dn = op->node;
+	struct device *dev = &op->dev;
+	struct mpc5121_nfc_prv *prv;
+	struct resource res;
+	struct mtd_info *mtd;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *parts;
+#endif
+	struct nand_chip *chip;
+	unsigned long regs_paddr, regs_size;
+	const uint *chips_no;
+	int resettime = 0;
+	int retval = 0;
+	int rev, len;
+
+	/*
+	 * Check SoC revision. This driver supports only NFC
+	 * in MPC5121 revision 2.
+	 */
+	rev = (mfspr(SPRN_SVR) >> 4) & 0xF;
+	if (rev != 2) {
+		dev_err(dev, "SoC revision %u is not supported!\n", rev);
+		return -ENXIO;
+	}
+
+	prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL);
+	if (!prv) {
+		dev_err(dev, "Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	mtd = &prv->mtd;
+	chip = &prv->chip;
+
+	mtd->priv = chip;
+	chip->priv = prv;
+	prv->dev = dev;
+
+	/* Read NFC configuration from Reset Config Word */
+	retval = mpc5121_nfc_read_hw_config(mtd);
+	if (retval) {
+		dev_err(dev, "Unable to read NFC config!\n");
+		return retval;
+	}
+
+	prv->irq = irq_of_parse_and_map(dn, 0);
+	if (prv->irq == NO_IRQ) {
+		dev_err(dev, "Error mapping IRQ!\n");
+		return -EINVAL;
+	}
+
+	retval = of_address_to_resource(dn, 0, &res);
+	if (retval) {
+		dev_err(dev, "Error parsing memory region!\n");
+		return retval;
+	}
+
+	chips_no = of_get_property(dn, "chips", &len);
+	if (!chips_no || len != sizeof(*chips_no)) {
+		dev_err(dev, "Invalid/missing 'chips' property!\n");
+		return -EINVAL;
+	}
+
+	regs_paddr = res.start;
+	regs_size = res.end - res.start + 1;
+
+	if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) {
+		dev_err(dev, "Error requesting memory region!\n");
+		return -EBUSY;
+	}
+
+	prv->regs = devm_ioremap(dev, regs_paddr, regs_size);
+	if (!prv->regs) {
+		dev_err(dev, "Error mapping memory region!\n");
+		return -ENOMEM;
+	}
+
+	mtd->name = "MPC5121 NAND";
+	chip->dev_ready = mpc5121_nfc_dev_ready;
+	chip->cmdfunc = mpc5121_nfc_command;
+	chip->read_byte = mpc5121_nfc_read_byte;
+	chip->read_word = mpc5121_nfc_read_word;
+	chip->read_buf = mpc5121_nfc_read_buf;
+	chip->write_buf = mpc5121_nfc_write_buf;
+	chip->verify_buf = mpc5121_nfc_verify_buf;
+	chip->select_chip = mpc5121_nfc_select_chip;
+	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
+	chip->ecc.mode = NAND_ECC_SOFT;
+
+	/* Support external chip-select logic on ADS5121 board */
+	rootnode = of_find_node_by_path("/");
+	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
+		retval = ads5121_chipselect_init(mtd);
+		if (retval) {
+			dev_err(dev, "Chipselect init error!\n");
+			of_node_put(rootnode);
+			return retval;
+		}
+
+		chip->select_chip = ads5121_select_chip;
+	}
+	of_node_put(rootnode);
+
+	/* Enable NFC clock */
+	prv->clk = clk_get(dev, "nfc_clk");
+	if (!prv->clk) {
+		dev_err(dev, "Unable to acquire NFC clock!\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	clk_enable(prv->clk);
+
+	/* Reset NAND Flash controller */
+	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
+	while (nfc_read(mtd, NFC_CONFIG1) & NFC_RESET) {
+		if (resettime++ >= NFC_RESET_TIMEOUT) {
+			dev_err(dev, "Timeout while resetting NFC!\n");
+			retval = -EINVAL;
+			goto error;
+		}
+
+		udelay(1);
+	}
+
+	/* Enable write to NFC memory */
+	nfc_write(mtd, NFC_CONFIG, NFC_BLS_UNLOCKED);
+
+	/* Enable write to all NAND pages */
+	nfc_write(mtd, NFC_UNLOCKSTART_BLK0, 0x0000);
+	nfc_write(mtd, NFC_UNLOCKEND_BLK0, 0xFFFF);
+	nfc_write(mtd, NFC_WRPROT, NFC_WPC_UNLOCK);
+
+	/*
+	 * Setup NFC:
+	 *	- Big Endian transfers,
+	 *	- Interrupt after full page read/write.
+	 */
+	nfc_write(mtd, NFC_CONFIG1, NFC_BIG_ENDIAN | NFC_INT_MASK |
+							NFC_FULL_PAGE_INT);
+
+	/* Set spare area size */
+	nfc_write(mtd, NFC_SPAS, mtd->oobsize >> 1);
+
+	init_waitqueue_head(&prv->irq_waitq);
+	retval = devm_request_irq(dev, prv->irq, &mpc5121_nfc_irq, 0, DRV_NAME,
+									mtd);
+	if (retval) {
+		dev_err(dev, "Error requesting IRQ!\n");
+		goto error;
+	}
+
+	/* Detect NAND chips */
+	if (nand_scan(mtd, *chips_no)) {
+		dev_err(dev, "NAND Flash not found !\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -ENXIO;
+		goto error;
+	}
+
+	/* Set erase block size */
+	switch (mtd->erasesize / mtd->writesize) {
+	case 32:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_32);
+		break;
+
+	case 64:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_64);
+		break;
+
+	case 128:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_128);
+		break;
+
+	case 256:
+		nfc_set(mtd, NFC_CONFIG1, NFC_PPB_256);
+		break;
+
+	default:
+		dev_err(dev, "Unsupported NAND flash!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -ENXIO;
+		goto error;
+	}
+
+	dev_set_drvdata(dev, mtd);
+
+	/* Register device in MTD */
+#ifdef CONFIG_MTD_PARTITIONS
+	retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
+#ifdef CONFIG_MTD_OF_PARTS
+	if (retval == 0)
+		retval = of_mtd_parse_partitions(dev, dn, &parts);
+#endif
+	if (retval < 0) {
+		dev_err(dev, "Error parsing MTD partitions!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -EINVAL;
+		goto error;
+	}
+
+	if (retval > 0)
+		retval = add_mtd_partitions(mtd, parts, retval);
+	else
+#endif
+		retval = add_mtd_device(mtd);
+
+	if (retval) {
+		dev_err(dev, "Error adding MTD device!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		goto error;
+	}
+
+	return 0;
+error:
+	mpc5121_nfc_free(dev, mtd);
+	return retval;
+}
+
+static int __exit mpc5121_nfc_remove(struct of_device *op)
+{
+	struct device *dev = &op->dev;
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5121_nfc_prv *prv = chip->priv;
+
+	nand_release(mtd);
+	devm_free_irq(dev, prv->irq, mtd);
+	mpc5121_nfc_free(dev, mtd);
+
+	return 0;
+}
+
+static struct of_device_id mpc5121_nfc_match[] = {
+	{ .compatible = "fsl,mpc5121-nfc", },
+	{},
+};
+
+static struct of_platform_driver mpc5121_nfc_driver = {
+	.match_table	= mpc5121_nfc_match,
+	.probe		= mpc5121_nfc_probe,
+	.remove		= __exit_p(mpc5121_nfc_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mpc5121_nfc_init(void)
+{
+	return of_register_platform_driver(&mpc5121_nfc_driver);
+}
+
+module_init(mpc5121_nfc_init);
+
+static void __exit mpc5121_nfc_cleanup(void)
+{
+	of_unregister_platform_driver(&mpc5121_nfc_driver);
+}
+
+module_exit(mpc5121_nfc_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MPC5121 NAND MTD driver");
+MODULE_LICENSE("GPL");
-- 
1.5.6.3

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

* [PATCH 07/11] dma: Add MPC512x DMA driver
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (8 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  2010-01-21 17:22   ` Grant Likely
  -1 siblings, 1 reply; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wd, dzu, Dan Williams, Anatolij Gustschin, Piotr Ziecik

From: Piotr Ziecik <kosmo@semihalf.com>

Adds initial version of MPC512x DMA driver.
Only memory to memory transfers are currenly supported.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: John Rigby <jcrigby@gmail.com>
---
 drivers/dma/Kconfig       |    7 +
 drivers/dma/Makefile      |    1 +
 drivers/dma/mpc512x_dma.c |  636 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/dma/mpc512x_dma.h |  192 ++++++++++++++
 4 files changed, 836 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dma/mpc512x_dma.c
 create mode 100644 drivers/dma/mpc512x_dma.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index e02d74b..ac67a53 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -69,6 +69,13 @@ config FSL_DMA
 	  The Elo is the DMA controller on some 82xx and 83xx parts, and the
 	  Elo Plus is the DMA controller on 85xx and 86xx parts.
 
+config MPC512X_DMA
+	tristate "Freescale MPC512x built-in DMA engine support"
+	depends on PPC_MPC512x
+	select DMA_ENGINE
+	---help---
+	  Enable support for the Freescale MPC512x built-in DMA engine.
+
 config MV_XOR
 	bool "Marvell XOR engine support"
 	depends on PLAT_ORION
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 807053d..4696bcf 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
new file mode 100644
index 0000000..f89b6c2
--- /dev/null
+++ b/drivers/dma/mpc512x_dma.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) Semihalf 2009
+ *
+ * Written by: Piotr Ziecik <kosmo@semihalf.com>
+ *
+ * Approved as OSADL project by a majority of OSADL members and funded
+ * by OSADL membership fees in 2009;  for details see www.osadl.org.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This is initial version of MPC5121 DMA driver. Only memory to memory
+ * transfers are supported (tested using dmatest module).
+ */
+
+#include <linux/module.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <linux/random.h>
+
+#include "mpc512x_dma.h"
+
+#define DRV_NAME	"mpc512x_dma"
+
+/* Convert struct dma_chan to struct mpc_dma_chan */
+static inline struct mpc_dma_chan *dma_chan_to_mpc_dma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct mpc_dma_chan, chan);
+}
+
+/* Convert struct dma_chan to struct mpc_dma */
+static inline struct mpc_dma *dma_chan_to_mpc_dma(struct dma_chan *c)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(c);
+	return container_of(mchan, struct mpc_dma, channels[c->chan_id]);
+}
+
+/*
+ * Execute all queued DMA descriptors.
+ *
+ * Following requirements must be met while calling mpc_dma_execute():
+ * 	a) mchan->lock is acquired,
+ * 	b) mchan->active list is empty,
+ * 	c) mchan->queued list contains at least one entry.
+ */
+static void mpc_dma_execute(struct mpc_dma_chan *mchan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(&mchan->chan);
+	struct mpc_dma_desc *first = NULL;
+	struct mpc_dma_desc *prev = NULL;
+	struct mpc_dma_desc *mdesc;
+	int cid = mchan->chan.chan_id;
+
+	/* Move all queued descriptors to active list */
+	list_splice_tail_init(&mchan->queued, &mchan->active);
+
+	/* Chain descriptors into one transaction */
+	list_for_each_entry(mdesc, &mchan->active, node) {
+		if (!first)
+			first = mdesc;
+
+		if (!prev) {
+			prev = mdesc;
+			continue;
+		}
+
+		prev->tcd->dlast_sga = mdesc->tcd_paddr;
+		prev->tcd->e_sg = 1;
+		mdesc->tcd->start = 1;
+
+		prev = mdesc;
+	}
+
+	prev->tcd->start = 0;
+	prev->tcd->int_maj = 1;
+
+	/* Send first descriptor in chain into hardware */
+	memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd));
+	out_8(&mdma->regs->dmassrt, cid);
+}
+
+/* Handle interrupt on one half of DMA controller (32 channels) */
+static void mpc_dma_irq_process(struct mpc_dma *mdma, u32 is, u32 es, int off)
+{
+	struct mpc_dma_chan *mchan;
+	struct mpc_dma_desc *mdesc;
+	u32 status = is | es;
+	int ch;
+
+	while ((ch = fls(status) - 1) >= 0) {
+		status &= ~(1 << ch);
+		mchan = &mdma->channels[ch + off];
+
+		spin_lock(&mchan->lock);
+
+		/* Check error status */
+		if (es & (1 << ch))
+			list_for_each_entry(mdesc, &mchan->active, node)
+				mdesc->error = -EIO;
+
+		/* Execute queued descriptors */
+		list_splice_tail_init(&mchan->active, &mchan->completed);
+		if (!list_empty(&mchan->queued))
+			mpc_dma_execute(mchan);
+
+		spin_unlock(&mchan->lock);
+	}
+}
+
+/* Interrupt handler */
+static irqreturn_t mpc_dma_irq(int irq, void *data)
+{
+	struct mpc_dma *mdma = data;
+	uint es;
+
+	/* Save error status register */
+	es = in_be32(&mdma->regs->dmaes);
+	spin_lock(&mdma->error_status_lock);
+	if ((es & MPC_DMA_DMAES_VLD) && mdma->error_status == 0)
+		mdma->error_status = es;
+	spin_unlock(&mdma->error_status_lock);
+
+	/* Handle interrupt on each channel */
+	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
+					in_be32(&mdma->regs->dmaerrh), 32);
+	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
+					in_be32(&mdma->regs->dmaerrl), 0);
+
+	/* Ack interrupt on all channels */
+	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+
+	/* Schedule tasklet */
+	tasklet_schedule(&mdma->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+/* DMA Tasklet */
+static void mpc_dma_tasklet(unsigned long data)
+{
+	struct mpc_dma *mdma = (void *)data;
+	dma_cookie_t last_cookie = 0;
+	struct mpc_dma_chan *mchan;
+	struct mpc_dma_desc *mdesc;
+	struct dma_async_tx_descriptor *desc;
+	unsigned long flags;
+	LIST_HEAD(list);
+	uint es;
+	int i;
+
+	spin_lock_irqsave(&mdma->error_status_lock, flags);
+	es = mdma->error_status;
+	mdma->error_status = 0;
+	spin_unlock_irqrestore(&mdma->error_status_lock, flags);
+
+	/* Print nice error report */
+	if (es) {
+		dev_err(mdma->dma.dev,
+			"Hardware reported following error(s) on channel %u:\n",
+						      MPC_DMA_DMAES_ERRCHN(es));
+
+		if (es & MPC_DMA_DMAES_GPE)
+			dev_err(mdma->dma.dev, "- Group Priority Error\n");
+		if (es & MPC_DMA_DMAES_CPE)
+			dev_err(mdma->dma.dev, "- Channel Priority Error\n");
+		if (es & MPC_DMA_DMAES_SAE)
+			dev_err(mdma->dma.dev, "- Source Address Error\n");
+		if (es & MPC_DMA_DMAES_SOE)
+			dev_err(mdma->dma.dev, "- Source Offset"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_DAE)
+			dev_err(mdma->dma.dev, "- Destination Address"
+								" Error\n");
+		if (es & MPC_DMA_DMAES_DOE)
+			dev_err(mdma->dma.dev, "- Destination Offset"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_NCE)
+			dev_err(mdma->dma.dev, "- NBytes/Citter"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_SGE)
+			dev_err(mdma->dma.dev, "- Scatter/Gather"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_SBE)
+			dev_err(mdma->dma.dev, "- Source Bus Error\n");
+		if (es & MPC_DMA_DMAES_DBE)
+			dev_err(mdma->dma.dev, "- Destination Bus Error\n");
+	}
+
+	for (i = 0; i < mdma->dma.chancnt; i++) {
+		mchan = &mdma->channels[i];
+
+		/* Get all completed descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		if (!list_empty(&mchan->completed))
+			list_splice_tail_init(&mchan->completed, &list);
+		spin_unlock_irqrestore(&mchan->lock, flags);
+
+		if (list_empty(&list))
+			continue;
+
+		/* Execute callbacks and run dependencies */
+		list_for_each_entry(mdesc, &list, node) {
+			desc = &mdesc->desc;
+
+			if (desc->callback)
+				desc->callback(desc->callback_param);
+
+			last_cookie = desc->cookie;
+			dma_run_dependencies(desc);
+		}
+
+		/* Free descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		list_splice_tail_init(&list, &mchan->free);
+		mchan->completed_cookie = last_cookie;
+		spin_unlock_irqrestore(&mchan->lock, flags);
+	}
+}
+
+/* Submit descriptor to hardware */
+static dma_cookie_t mpc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(txd->chan);
+	struct mpc_dma_desc *mdesc;
+	unsigned long flags;
+	dma_cookie_t cookie;
+
+	mdesc = container_of(txd, struct mpc_dma_desc, desc);
+
+	spin_lock_irqsave(&mchan->lock, flags);
+
+	/* Move descriptor to queue */
+	list_move_tail(&mdesc->node, &mchan->queued);
+
+	/* If channel is idle, execute all queued descriptors */
+	if (list_empty(&mchan->active))
+		mpc_dma_execute(mchan);
+
+	/* Update cookie */
+	cookie = mchan->chan.cookie + 1;
+	if (cookie <= 0)
+		cookie = 1;
+
+	mchan->chan.cookie = cookie;
+	mdesc->desc.cookie = cookie;
+
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	return cookie;
+}
+
+/* Alloc channel resources */
+static int mpc_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc;
+	struct mpc_dma_tcd *tcd;
+	dma_addr_t tcd_paddr;
+	unsigned long flags;
+	LIST_HEAD(descs);
+	int i;
+
+	/* Alloc DMA memory for Transfer Control Descriptors */
+	tcd = dma_alloc_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+							&tcd_paddr, GFP_KERNEL);
+	if (!tcd)
+		return -ENOMEM;
+
+	/* Alloc descriptors for this channel */
+	for (i = 0; i < MPC_DMA_DESCRIPTORS; i++) {
+		mdesc = kzalloc(sizeof(struct mpc_dma_desc), GFP_KERNEL);
+		if (!mdesc) {
+			dev_notice(mdma->dma.dev, "Memory allocation error. "
+					"Allocated only %u descriptors\n", i);
+			break;
+		}
+
+		dma_async_tx_descriptor_init(&mdesc->desc, chan);
+		mdesc->desc.flags = DMA_CTRL_ACK;
+		mdesc->desc.tx_submit = mpc_dma_tx_submit;
+
+		mdesc->tcd = &tcd[i];
+		mdesc->tcd_paddr = tcd_paddr + (i * sizeof(struct mpc_dma_tcd));
+
+		list_add_tail(&mdesc->node, &descs);
+	}
+
+	/* Return error only if no descriptors were allocated */
+	if (i == 0) {
+		dma_free_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+								tcd, tcd_paddr);
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&mchan->lock, flags);
+	mchan->tcd = tcd;
+	mchan->tcd_paddr = tcd_paddr;
+	list_splice_tail_init(&descs, &mchan->free);
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	/* Enable Error Interrupt */
+	out_8(&mdma->regs->dmaseei, chan->chan_id);
+
+	return 0;
+}
+
+/* Free channel resources */
+static void mpc_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc, *tmp;
+	struct mpc_dma_tcd *tcd;
+	dma_addr_t tcd_paddr;
+	unsigned long flags;
+	LIST_HEAD(descs);
+
+	spin_lock_irqsave(&mchan->lock, flags);
+
+	/* Channel must be idle */
+	BUG_ON(!list_empty(&mchan->prepared));
+	BUG_ON(!list_empty(&mchan->queued));
+	BUG_ON(!list_empty(&mchan->active));
+	BUG_ON(!list_empty(&mchan->completed));
+
+	/* Move data */
+	list_splice_tail_init(&mchan->free, &descs);
+	tcd = mchan->tcd;
+	tcd_paddr = mchan->tcd_paddr;
+
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	/* Free DMA memory used by descriptors */
+	dma_free_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+								tcd, tcd_paddr);
+
+	/* Free descriptors */
+	list_for_each_entry_safe(mdesc, tmp, &descs, node)
+		kfree(mdesc);
+
+	/* Disable Error Interrupt */
+	out_8(&mdma->regs->dmaceei, chan->chan_id);
+}
+
+/* Send all pending descriptor to hardware */
+static void mpc_dma_issue_pending(struct dma_chan *chan)
+{
+	/*
+	 * We are posting descriptors to the hardware as soon as
+	 * they are ready, so this function does nothing.
+	 */
+}
+
+/* Check request completion status */
+static enum dma_status
+mpc_dma_is_tx_complete(struct dma_chan *chan, dma_cookie_t cookie,
+					dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	unsigned long flags;
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	spin_lock_irqsave(&mchan->lock, flags);
+	last_used = mchan->chan.cookie;
+	last_complete = mchan->completed_cookie;
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	if (done)
+		*done = last_complete;
+
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/* Prepare descriptor for memory to memory copy */
+static struct dma_async_tx_descriptor *
+mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
+					size_t len, unsigned long flags)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc = NULL;
+	struct mpc_dma_tcd *tcd;
+	unsigned long iflags;
+
+	/* Get free descriptor */
+	spin_lock_irqsave(&mchan->lock, iflags);
+	if (!list_empty(&mchan->free)) {
+		mdesc = list_first_entry(&mchan->free, struct mpc_dma_desc,
+									node);
+		list_del(&mdesc->node);
+	}
+	spin_unlock_irqrestore(&mchan->lock, iflags);
+
+	if (!mdesc)
+		return NULL;
+
+	mdesc->error = 0;
+	tcd = mdesc->tcd;
+
+	/* Prepare Transfer Control Descriptor for this transaction */
+	memset(tcd, 0, sizeof(struct mpc_dma_tcd));
+
+	if (IS_ALIGNED(src | dst | len, 32)) {
+		tcd->ssize = MPC_DMA_TSIZE_32;
+		tcd->dsize = MPC_DMA_TSIZE_32;
+		tcd->soff = 32;
+		tcd->doff = 32;
+	} else if (IS_ALIGNED(src | dst | len, 16)) {
+		tcd->ssize = MPC_DMA_TSIZE_16;
+		tcd->dsize = MPC_DMA_TSIZE_16;
+		tcd->soff = 16;
+		tcd->doff = 16;
+	} else if (IS_ALIGNED(src | dst | len, 4)) {
+		tcd->ssize = MPC_DMA_TSIZE_4;
+		tcd->dsize = MPC_DMA_TSIZE_4;
+		tcd->soff = 4;
+		tcd->doff = 4;
+	} else if (IS_ALIGNED(src | dst | len, 2)) {
+		tcd->ssize = MPC_DMA_TSIZE_2;
+		tcd->dsize = MPC_DMA_TSIZE_2;
+		tcd->soff = 2;
+		tcd->doff = 2;
+	} else {
+		tcd->ssize = MPC_DMA_TSIZE_1;
+		tcd->dsize = MPC_DMA_TSIZE_1;
+		tcd->soff = 1;
+		tcd->doff = 1;
+	}
+
+	tcd->saddr = src;
+	tcd->daddr = dst;
+	tcd->nbytes = len;
+	tcd->biter = 1;
+	tcd->citer = 1;
+
+	/* Place descriptor in prepared list */
+	spin_lock_irqsave(&mchan->lock, iflags);
+	list_add_tail(&mdesc->node, &mchan->prepared);
+	spin_unlock_irqrestore(&mchan->lock, iflags);
+
+	return &mdesc->desc;
+}
+
+static int __init mpc_dma_probe(struct of_device *op,
+					const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct device *dev = &op->dev;
+	struct dma_device *dma;
+	struct mpc_dma *mdma;
+	struct mpc_dma_chan *mchan;
+	struct resource res;
+	ulong regs_start, regs_size;
+	int retval, i;
+
+	mdma = devm_kzalloc(dev, sizeof(struct mpc_dma), GFP_KERNEL);
+	if (!mdma) {
+		dev_err(dev, "Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	mdma->irq = irq_of_parse_and_map(dn, 0);
+	if (mdma->irq == NO_IRQ) {
+		dev_err(dev, "Error mapping IRQ!\n");
+		return -EINVAL;
+	}
+
+	retval = of_address_to_resource(dn, 0, &res);
+	if (retval) {
+		dev_err(dev, "Error parsing memory region!\n");
+		return retval;
+	}
+
+	regs_start = res.start;
+	regs_size = res.end - res.start + 1;
+
+	if (!devm_request_mem_region(dev, regs_start, regs_size, DRV_NAME)) {
+		dev_err(dev, "Error requesting memory region!\n");
+		return -EBUSY;
+	}
+
+	mdma->regs = devm_ioremap(dev, regs_start, regs_size);
+	if (!mdma->regs) {
+		dev_err(dev, "Error mapping memory region!\n");
+		return -ENOMEM;
+	}
+
+	mdma->tcd = (struct mpc_dma_tcd *)((u8 *)(mdma->regs)
+							+ MPC_DMA_TCD_OFFSET);
+
+	retval = devm_request_irq(dev, mdma->irq, &mpc_dma_irq, 0, DRV_NAME,
+									mdma);
+	if (retval) {
+		dev_err(dev, "Error requesting IRQ!\n");
+		return -EINVAL;
+	}
+
+	spin_lock_init(&mdma->error_status_lock);
+
+	dma = &mdma->dma;
+	dma->dev = dev;
+	dma->chancnt = MPC_DMA_CHANNELS;
+	dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
+	dma->device_free_chan_resources = mpc_dma_free_chan_resources;
+	dma->device_issue_pending = mpc_dma_issue_pending;
+	dma->device_is_tx_complete = mpc_dma_is_tx_complete;
+	dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy;
+
+	INIT_LIST_HEAD(&dma->channels);
+	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
+
+	for (i = 0; i < dma->chancnt; i++) {
+		mchan = &mdma->channels[i];
+
+		mchan->chan.device = dma;
+		mchan->chan.chan_id = i;
+		mchan->chan.cookie = 1;
+		mchan->completed_cookie = mchan->chan.cookie;
+
+		INIT_LIST_HEAD(&mchan->free);
+		INIT_LIST_HEAD(&mchan->prepared);
+		INIT_LIST_HEAD(&mchan->queued);
+		INIT_LIST_HEAD(&mchan->active);
+		INIT_LIST_HEAD(&mchan->completed);
+
+		spin_lock_init(&mchan->lock);
+		list_add_tail(&mchan->chan.device_node, &dma->channels);
+	}
+
+	tasklet_init(&mdma->tasklet, mpc_dma_tasklet, (unsigned long)mdma);
+
+	/*
+	 * Configure DMA Engine:
+	 * - Dynamic clock,
+	 * - Round-robin group arbitration,
+	 * - Round-robin channel arbitration.
+	 */
+	out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
+				MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
+
+	/* Disable hardware DMA requests */
+	out_be32(&mdma->regs->dmaerqh, 0);
+	out_be32(&mdma->regs->dmaerql, 0);
+
+	/* Disable error interrupts */
+	out_be32(&mdma->regs->dmaeeih, 0);
+	out_be32(&mdma->regs->dmaeeil, 0);
+
+	/* Clear interrupts status */
+	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+
+	/* Route interrupts to IPIC */
+	out_be32(&mdma->regs->dmaihsa, 0);
+	out_be32(&mdma->regs->dmailsa, 0);
+
+	/* Register DMA engine */
+	dev_set_drvdata(dev, mdma);
+	retval = dma_async_device_register(dma);
+	if (retval)
+		devm_free_irq(dev, mdma->irq, mdma);
+
+	return retval;
+}
+
+static void __exit mpc_dma_remove(struct of_device *op)
+{
+	struct device *dev = &op->dev;
+	struct mpc_dma *mdma = dev_get_drvdata(dev);
+
+	devm_free_irq(dev, mdma->irq, mdma);
+}
+
+static struct of_device_id mpc_dma_match[] = {
+	{ .compatible = "fsl,mpc5121-dma", },
+	{},
+};
+
+static struct of_platform_driver mpc_dma_driver = {
+	.match_table	= mpc_dma_match,
+	.probe		= mpc_dma_probe,
+	.remove		= __exit_p(mpc_dma_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mpc_dma_init(void)
+{
+	return of_register_platform_driver(&mpc_dma_driver);
+}
+module_init(mpc_dma_init);
+
+static void __exit mpc_dma_exit(void)
+{
+	of_unregister_platform_driver(&mpc_dma_driver);
+}
+module_exit(mpc_dma_exit);
+
+/* MODULE API */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");
diff --git a/drivers/dma/mpc512x_dma.h b/drivers/dma/mpc512x_dma.h
new file mode 100644
index 0000000..867415b
--- /dev/null
+++ b/drivers/dma/mpc512x_dma.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
+ * Copyright (C) Semihalf, 2009.
+ *
+ * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
+ * (defines, structures and comments) was taken from MPC5121 DMA driver
+ * written by Hongjun Chen <hong-jun.chen@freescale.com>.
+ *
+ * Approved as OSADL project by a majority of OSADL members and funded
+ * by OSADL membership fees in 2009;  for details see www.osadl.org.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _MPC512X_DMA_H_
+#define _MPC512X_DMA_H_
+
+#include <linux/dmaengine.h>
+
+/* Number of DMA Transfer descriptors allocated per channel */
+#define MPC_DMA_DESCRIPTORS	64
+
+/* Macro definitions */
+#define MPC_DMA_CHANNELS	64
+#define MPC_DMA_TCD_OFFSET	0x1000
+
+/* Arbitration mode of group and channel */
+#define MPC_DMA_DMACR_EDCG	(1 << 31)
+#define MPC_DMA_DMACR_ERGA	(1 << 3)
+#define MPC_DMA_DMACR_ERCA	(1 << 2)
+
+/* Error codes */
+#define MPC_DMA_DMAES_VLD	(1 << 31)
+#define MPC_DMA_DMAES_GPE	(1 << 15)
+#define MPC_DMA_DMAES_CPE	(1 << 14)
+#define MPC_DMA_DMAES_ERRCHN(err) \
+				(((err) >> 8) & 0x3f)
+#define MPC_DMA_DMAES_SAE	(1 << 7)
+#define MPC_DMA_DMAES_SOE	(1 << 6)
+#define MPC_DMA_DMAES_DAE	(1 << 5)
+#define MPC_DMA_DMAES_DOE	(1 << 4)
+#define MPC_DMA_DMAES_NCE	(1 << 3)
+#define MPC_DMA_DMAES_SGE	(1 << 2)
+#define MPC_DMA_DMAES_SBE	(1 << 1)
+#define MPC_DMA_DMAES_DBE	(1 << 0)
+
+#define MPC_DMA_TSIZE_1		0x00
+#define MPC_DMA_TSIZE_2		0x01
+#define MPC_DMA_TSIZE_4		0x02
+#define MPC_DMA_TSIZE_16	0x04
+#define MPC_DMA_TSIZE_32	0x05
+
+/* MPC5121 DMA engine registers */
+struct __attribute__ ((__packed__)) mpc_dma_regs {
+	/* 0x00 */
+	u32 dmacr;		/* DMA control register */
+	u32 dmaes;		/* DMA error status */
+	/* 0x08 */
+	u32 dmaerqh;		/* DMA enable request high(channels 63~32) */
+	u32 dmaerql;		/* DMA enable request low(channels 31~0) */
+	u32 dmaeeih;		/* DMA enable error interrupt high(ch63~32) */
+	u32 dmaeeil;		/* DMA enable error interrupt low(ch31~0) */
+	/* 0x18 */
+	u8 dmaserq;		/* DMA set enable request */
+	u8 dmacerq;		/* DMA clear enable request */
+	u8 dmaseei;		/* DMA set enable error interrupt */
+	u8 dmaceei;		/* DMA clear enable error interrupt */
+	/* 0x1c */
+	u8 dmacint;		/* DMA clear interrupt request */
+	u8 dmacerr;		/* DMA clear error */
+	u8 dmassrt;		/* DMA set start bit */
+	u8 dmacdne;		/* DMA clear DONE status bit */
+	/* 0x20 */
+	u32 dmainth;		/* DMA interrupt request high(ch63~32) */
+	u32 dmaintl;		/* DMA interrupt request low(ch31~0) */
+	u32 dmaerrh;		/* DMA error high(ch63~32) */
+	u32 dmaerrl;		/* DMA error low(ch31~0) */
+	/* 0x30 */
+	u32 dmahrsh;		/* DMA hw request status high(ch63~32) */
+	u32 dmahrsl;		/* DMA hardware request status low(ch31~0) */
+	u32 dmaihsa;		/* DMA interrupt high select AXE(ch63~32) */
+	u32 dmailsa;		/* DMA interrupt low select AXE(ch31~0) */
+	/* 0x40 ~ 0xff */
+	u32 reserve0[48];	/* Reserved */
+	/* 0x100 */
+	u8 dchpri[MPC_DMA_CHANNELS];
+	/* DMA channels(0~63) priority */
+};
+
+struct __attribute__ ((__packed__)) mpc_dma_tcd {
+	/* 0x00 */
+	u32 saddr;		/* Source address */
+
+	u32 smod:5;		/* Source address modulo */
+	u32 ssize:3;		/* Source data transfer size */
+	u32 dmod:5;		/* Destination address modulo */
+	u32 dsize:3;		/* Destination data transfer size */
+	u32 soff:16;		/* Signed source address offset */
+
+	/* 0x08 */
+	u32 nbytes;		/* Inner "minor" byte count */
+	u32 slast;		/* Last source address adjustment */
+	u32 daddr;		/* Destination address */
+
+	/* 0x14 */
+	u32 citer_elink:1;	/* Enable channel-to-channel linking on
+				 * minor loop complete
+				 */
+	u32 citer_linkch:6;	/* Link channel for minor loop complete */
+	u32 citer:9;		/* Current "major" iteration count */
+	u32 doff:16;		/* Signed destination address offset */
+
+	/* 0x18 */
+	u32 dlast_sga;		/* Last Destination address adjustment/scatter
+				 * gather address
+				 */
+
+	/* 0x1c */
+	u32 biter_elink:1;	/* Enable channel-to-channel linking on major
+				 * loop complete
+				 */
+	u32 biter_linkch:6;
+	u32 biter:9;		/* Beginning "major" iteration count */
+	u32 bwc:2;		/* Bandwidth control */
+	u32 major_linkch:6;	/* Link channel number */
+	u32 done:1;		/* Channel done */
+	u32 active:1;		/* Channel active */
+	u32 major_elink:1;	/* Enable channel-to-channel linking on major
+				 * loop complete
+				 */
+	u32 e_sg:1;		/* Enable scatter/gather processing */
+	u32 d_req:1;		/* Disable request */
+	u32 int_half:1;		/* Enable an interrupt when major counter is
+				 * half complete
+				 */
+	u32 int_maj:1;		/* Enable an interrupt when major iteration
+				 * count completes
+				 */
+	u32 start:1;		/* Channel start */
+};
+
+struct mpc_dma_desc {
+	struct dma_async_tx_descriptor	desc;
+	struct mpc_dma_tcd		*tcd;
+	dma_addr_t			tcd_paddr;
+	int				error;
+	struct list_head		node;
+};
+
+struct mpc_dma_chan {
+	struct dma_chan			chan;
+	struct list_head		free;
+	struct list_head		prepared;
+	struct list_head		queued;
+	struct list_head		active;
+	struct list_head		completed;
+	struct mpc_dma_tcd		*tcd;
+	dma_addr_t			tcd_paddr;
+	dma_cookie_t			completed_cookie;
+
+	/* Lock for this structure */
+	spinlock_t			lock;
+};
+
+struct mpc_dma {
+	struct dma_device		dma;
+	struct tasklet_struct		tasklet;
+	struct mpc_dma_chan		channels[MPC_DMA_CHANNELS];
+	struct mpc_dma_regs __iomem	*regs;
+	struct mpc_dma_tcd __iomem	*tcd;
+	int				irq;
+	uint				error_status;
+
+	/* Lock for error_status field in this structure */
+	spinlock_t			error_status_lock;
+};
+
+#endif /* _MPC512X_DMA_H_ */
-- 
1.5.6.3

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

* [PATCH 08/11] powerpc/mpc5121: add USB host support
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (9 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
       [not found]   ` <1263932653-3634-9-git-send-email-agust-ynQEQJNshbs@public.gmane.org>
  -1 siblings, 1 reply; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: wd, dzu, linux-usb, Bruce Schmid, Anatolij Gustschin

Platform specific code for MPC5121 USB Host support.
MPC5121 Rev 2.0 silicon EHCI registers are big endian.
Add appropriate support by specifying "big-endian-regs"
property in device tree node for USB controller. Also
allow specifying DRVVBUS and PWR_FAULT signal polarity
of MPC5121 internal PHY using "invert-drvvbus" and
"invert-pwr-fault" properties.

Signed-off-by: Bruce Schmid <duck@freescale.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: linux-usb@vger.kernel.org
Cc: Grant Likely <grant.likely@secretlab.ca>
---
Note that EHCI FSL driver extention in this patch
applies on top of the following two patches (in the
linux-next tree):

commit 23c3314b88f91db51bd198ed92e34cffb67788dd
Author: Anton Vorontsov <avorontsov@ru.mvista.com>
Date:   Mon Dec 14 18:41:12 2009 +0300

    USB: ehci-fsl: Add power management support

commit bf4bf2d9f646eb0cc531d213a13ffcedf9d6785f
Author: Anton Vorontsov <avorontsov@ru.mvista.com>
Date:   Mon Dec 14 18:41:05 2009 +0300

    USB: ehci-fsl: Fix sparse warnings

 Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 ++
 arch/powerpc/platforms/512x/Kconfig            |    6 +
 arch/powerpc/platforms/512x/Makefile           |    2 +-
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    1 +
 arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++++++++++++++++++++++++
 arch/powerpc/platforms/512x/mpc512x.h          |    1 +
 arch/powerpc/sysdev/fsl_soc.c                  |   10 ++
 arch/powerpc/sysdev/fsl_soc.h                  |    9 ++
 drivers/usb/host/ehci-fsl.c                    |  116 +++++++++++++++++-------
 drivers/usb/host/ehci-fsl.h                    |   19 ++++-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 include/linux/fsl_devices.h                    |   10 ++
 12 files changed, 265 insertions(+), 36 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/mpc5121_usb.c

diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
index b001524..9050154 100644
--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
@@ -33,6 +33,14 @@ Recommended properties :
  - interrupt-parent : the phandle for the interrupt controller that
    services interrupts for this device.
 
+Optional properties :
+ - big-endian-regs : boolean; if defined, indicates the USB host
+   controller registers format is big endian.
+ - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
+   power polarity of internal PHY signal DRVVBUS is inverted.
+ - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
+   PWR_FAULT signal polarity is inverted.
+
 Example multi port host USB controller device node :
 	usb@22000 {
 		compatible = "fsl-usb2-mph";
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index 4dac9b0..3fec738 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -9,6 +9,9 @@ config PPC_MPC512x
 config PPC_MPC5121
 	bool
 	select PPC_MPC512x
+	select USB_ARCH_HAS_EHCI
+	select USB_EHCI_BIG_ENDIAN_DESC
+	select USB_EHCI_BIG_ENDIAN_MMIO
 
 config MPC5121_ADS
 	bool "Freescale MPC5121E ADS"
@@ -30,3 +33,6 @@ config MPC5121_GENERIC
 
 	  Compatible boards include:  Protonic LVT base boards (ZANMCU
 	  and VICVT2).
+
+config USB_FSL_BIG_ENDIAN_MMIO
+	bool
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 90be2f5..49adabc 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,6 +1,6 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-y				+= clock.o mpc512x_shared.o mpc5121_usb.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC5121_GENERIC)	+= mpc5121_generic.o
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index 2f40404..a497c14 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
 	for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
 		mpc83xx_add_bridge(np);
 #endif
+	mpc5121_usb_init();
 }
 
 static void __init mpc5121_ads_init_IRQ(void)
diff --git a/arch/powerpc/platforms/512x/mpc5121_usb.c b/arch/powerpc/platforms/512x/mpc5121_usb.c
new file mode 100644
index 0000000..7b45651
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc5121_usb.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Bruce Schmid <duck@freescale.com>, Tue Oct 2 2007
+ *
+ * Description:
+ * MPC5121 USB platform-specific routines
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/fsl_devices.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/stddef.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+
+#define USBGENCTRL		0x200		/* NOTE: big endian */
+#define GC_WU_INT_CLR		(1 << 5)	/* Wakeup int clear */
+#define GC_ULPI_SEL		(1 << 4)	/* ULPI i/f select (usb0 only)*/
+#define GC_PPP			(1 << 3)	/* Inv. Port Power Polarity */
+#define GC_PFP			(1 << 2)	/* Inv. Power Fault Polarity */
+#define GC_WU_ULPI_EN		(1 << 1)	/* Wakeup on ULPI event */
+#define GC_WU_IE		(1 << 1)	/* Wakeup interrupt enable */
+
+#define ISIPHYCTRL		0x204		/* NOTE: big endian */
+#define PHYCTRL_PHYE		(1 << 4)	/* On-chip UTMI PHY enable */
+#define PHYCTRL_BSENH		(1 << 3)	/* Bit Stuff Enable High */
+#define PHYCTRL_BSEN		(1 << 2)	/* Bit Stuff Enable */
+#define PHYCTRL_LSFE		(1 << 1)	/* Line State Filter Enable */
+#define PHYCTRL_PXE		(1 << 0)	/* PHY oscillator enable */
+
+static struct clk *dr_clk1;
+static struct clk *dr_clk2;
+static int dr_used;
+
+static int mpc5121_usb_dr_init(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	/* enable the clock if we haven't already */
+	if (!dr_used) {
+		dr_clk1 = clk_get(&pdev->dev, "usb1_clk");
+		if (IS_ERR(dr_clk1)) {
+			dev_err(&pdev->dev, "usb1: clk_get failed\n");
+			return -ENODEV;
+		}
+		clk_enable(dr_clk1);
+		dr_clk2 = clk_get(&pdev->dev, "usb2_clk");
+		if (IS_ERR(dr_clk2)) {
+			dev_err(&pdev->dev, "usb2: clk_get failed\n");
+			return -ENODEV;
+		}
+		clk_enable(dr_clk2);
+	}
+	dr_used++;
+
+	pdata->big_endian_desc = 1;
+	pdata->es = 1;
+
+	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
+		struct device_node *np;
+		u32 reg = 0;
+
+		np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-usb2-dr");
+		if (!np) {
+			pr_err("No USB node found\n");
+			return -ENODEV;
+		}
+
+		if (of_get_property(np, "invert-drvvbus", NULL))
+			reg |= GC_PPP;
+
+		if (of_get_property(np, "invert-pwr-fault", NULL))
+			reg |= GC_PFP;
+
+		of_node_put(np);
+		out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
+		out_be32(pdata->regs + USBGENCTRL, reg);
+	}
+	return 0;
+}
+
+static void mpc5121_usb_dr_uninit(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	pdata->regs = NULL;
+
+	dr_used--;
+	if (!dr_used) {
+		clk_disable(dr_clk1);
+		clk_disable(dr_clk2);
+		clk_put(dr_clk1);
+		clk_put(dr_clk2);
+		dr_clk1 = NULL;
+		dr_clk2 = NULL;
+	}
+}
+
+void mpc5121_usb_init(void)
+{
+	fsl_platform_usb_ops.init = mpc5121_usb_dr_init;
+	fsl_platform_usb_ops.uninit = mpc5121_usb_dr_uninit;
+}
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index c38875c..e92a282 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -13,5 +13,6 @@
 #define __MPC512X_H__
 extern void __init mpc512x_init_IRQ(void);
 extern void mpc512x_restart(char *cmd);
+extern void mpc5121_usb_init(void);
 void __init mpc512x_declare_of_platform_devices(void);
 #endif				/* __MPC512X_H__ */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index b91f7ac..19a455d 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -209,6 +209,9 @@ static int __init of_add_fixed_phys(void)
 arch_initcall(of_add_fixed_phys);
 #endif /* CONFIG_FIXED_PHY */
 
+struct fsl_platform_usb_ops fsl_platform_usb_ops;
+EXPORT_SYMBOL(fsl_platform_usb_ops);
+
 static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
 {
 	if (!phy_type)
@@ -267,6 +270,9 @@ static int __init fsl_usb_of_init(void)
 		if (prop)
 			usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
 
+		if (of_get_property(np, "big-endian-regs", NULL))
+			usb_data.big_endian_mmio = 1;
+
 		prop = of_get_property(np, "phy_type", NULL);
 		usb_data.phy_mode = determine_usb_phy(prop);
 
@@ -332,9 +338,13 @@ static int __init fsl_usb_of_init(void)
 			ret = -EINVAL;
 			goto err;
 		}
+		if (of_get_property(np, "big-endian-regs", NULL))
+			usb_data.big_endian_mmio = 1;
 
 		prop = of_get_property(np, "phy_type", NULL);
 		usb_data.phy_mode = determine_usb_phy(prop);
+		usb_data.platform_init = fsl_platform_usb_ops.init;
+		usb_data.platform_uninit = fsl_platform_usb_ops.uninit;
 
 		if (usb_dev_dr_host) {
 			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 42381bb..19754be 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -35,5 +35,14 @@ struct platform_diu_data_ops {
 extern struct platform_diu_data_ops diu_ops;
 #endif
 
+struct platform_device;
+
+struct fsl_platform_usb_ops {
+	int (*init)(struct platform_device *);
+	void (*uninit)(struct platform_device *);
+};
+
+extern struct fsl_platform_usb_ops fsl_platform_usb_ops;
+
 #endif
 #endif
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0e26aa1..c4ec00c 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 	pr_debug("initializing FSL-SOC USB Controller\n");
 
 	/* Need platform data for setup */
-	pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data;
+	pdata = pdev->dev.platform_data;
 	if (!pdata) {
 		dev_err(&pdev->dev,
 			"No platform data for %s.\n", dev_name(&pdev->dev));
@@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 		return -ENODEV;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
 		dev_err(&pdev->dev,
 			"Found HC with no IRQ. Check %s setup!\n",
 			dev_name(&pdev->dev));
 		return -ENODEV;
 	}
-	irq = res->start;
 
 	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
@@ -116,13 +115,39 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 		goto err3;
 	}
 
-	/* Enable USB controller */
-	temp = in_be32(hcd->regs + 0x500);
-	out_be32(hcd->regs + 0x500, temp | 0x4);
+	pdata->regs = hcd->regs;
+
+	/*
+	 * do platform specific init: check the clock, grab/config pins, etc.
+	 */
+	if (pdata->platform_init && pdata->platform_init(pdev)) {
+		retval = -ENODEV;
+		goto err3;
+	}
+
+	/*
+	 * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
+	 * flag for 83xx or 8536 system interface registers.
+	 */
+	if (pdata->big_endian_mmio)
+		temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
+	else
+		temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
+
+	if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
+		pdata->have_sysif_regs = 1;
+
+	/* Enable USB controller, 83xx or 8536 */
+	if (pdata->have_sysif_regs)
+		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
 
 	/* Set to Host mode */
-	temp = in_le32(hcd->regs + 0x1a8);
-	out_le32(hcd->regs + 0x1a8, temp | 0x3);
+	if (pdata->big_endian_mmio) {
+		setbits32(hcd->regs + FSL_SOC_USB_USBMODE, USBMODE_CM_HOST);
+	} else {
+		clrsetbits_le32(hcd->regs + FSL_SOC_USB_USBMODE,
+				USBMODE_CM_MASK, USBMODE_CM_HOST);
+	}
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
@@ -137,6 +162,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 	usb_put_hcd(hcd);
       err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+	if (pdata->platform_uninit)
+		pdata->platform_uninit(pdev);
 	return retval;
 }
 
@@ -154,17 +181,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 {
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
 	usb_remove_hcd(hcd);
+
+	/*
+	 * do platform specific un-initialization:
+	 * release iomux pins, disable clock, etc.
+	 */
+	if (pdata->platform_uninit)
+		pdata->platform_uninit(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 }
 
-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
-			      enum fsl_usb2_phy_modes phy_mode,
-			      unsigned int port_offset)
+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+			       enum fsl_usb2_phy_modes phy_mode,
+			       unsigned int port_offset)
 {
-	u32 portsc = 0;
+	u32 portsc;
+
+	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
+	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portsc |= PORT_PTS_ULPI;
@@ -184,20 +224,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 }
 
-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
-	u32 temp;
+	u32 tmp;
+
+	pdata = hcd->self.controller->platform_data;
 
-	pdata =
-	    (struct fsl_usb2_platform_data *)hcd->self.controller->
-	    platform_data;
 	/* Enable PHY interface in the control reg. */
-	temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-	out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	if (pdata->have_sysif_regs) {
+		tmp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+		out_be32(non_ehci + FSL_SOC_USB_CTRL, tmp | 0x00000004);
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	}
 
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
 	/*
@@ -214,7 +255,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
 
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
-		mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 		unsigned int chip, rev, svr;
@@ -228,27 +269,31 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
 			ehci->has_fsl_port_bug = 1;
 
 		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
 	}
 
 	/* put controller in host mode. */
-	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+	tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
+	ehci_writel(ehci, tmp, non_ehci + FSL_SOC_USB_USBMODE);
+
+	if (pdata->have_sysif_regs) {
 #ifdef CONFIG_PPC_85xx
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
 #else
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
 #endif
-	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+	}
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-	mpc83xx_usb_setup(ehci_to_hcd(ehci));
+	ehci_fsl_usb_setup(ehci);
 	ehci_port_power(ehci, 0);
 
 	return 0;
@@ -259,6 +304,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
+	struct fsl_usb2_platform_data *pdata;
+
+	pdata = hcd->self.controller->platform_data;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
@@ -369,7 +419,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_USB2,
+	.flags = HCD_USB2 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index b5e59db..3525bb4 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005 freescale semiconductor
+/* Copyright (C) 2005-2009 Freescale Semiconductor, Inc. All rights reserved.
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -19,6 +19,11 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ID		0x0
+#define ID_MSK			0x3f
+#define NID_MSK			0x3f00
+#define FSL_SOC_USB_SBUSCFG	0x90
+#define FSL_SOC_USB_BURSTSIZE	0x160
 #define FSL_SOC_USB_ULPIVP	0x170
 #define FSL_SOC_USB_PORTSC1	0x184
 #define PORT_PTS_MSK		(3<<30)
@@ -26,8 +31,20 @@
 #define PORT_PTS_ULPI		(2<<30)
 #define	PORT_PTS_SERIAL		(3<<30)
 #define PORT_PTS_PTW		(1<<28)
+#define PORT_PTS_PHCD		(1<<23)
 #define FSL_SOC_USB_PORTSC2	0x188
 #define FSL_SOC_USB_USBMODE	0x1a8
+#define USBMODE_CM_MASK		(3 << 0)	/* controller mode mask */
+#define USBMODE_CM_HOST		(3 << 0)	/* controller mode: host */
+#define USBMODE_ES		(1 << 2)	/* (Big) Endian Select */
+
+#define FSL_SOC_USB_USBGENCTRL 	0x200
+#define USBGENCTRL_PPP 		(1 << 3)
+#define USBGENCTRL_PFP		(1 << 2)
+#define FSL_SOC_USB_ISIPHYCTRL	0x204
+#define ISIPHYCTRL_PXE		(1)
+#define ISIPHYCTRL_PHYE		(1 << 4)
+
 #define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index aeda96e..1e7e004 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
-	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
+	qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	qtd->hw_next = EHCI_LIST_END(ehci);
 	qtd->hw_alt_next = EHCI_LIST_END(ehci);
 	INIT_LIST_HEAD (&qtd->qtd_list);
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 28e33fe..dfe603f 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -58,11 +58,21 @@ enum fsl_usb2_phy_modes {
 	FSL_USB2_PHY_SERIAL,
 };
 
+struct platform_device;
 struct fsl_usb2_platform_data {
 	/* board specific information */
 	enum fsl_usb2_operating_modes	operating_mode;
 	enum fsl_usb2_phy_modes		phy_mode;
 	unsigned int			port_enables;
+
+	char				*name;		/* pretty print */
+	int (*platform_init) (struct platform_device *);
+	void (*platform_uninit) (struct platform_device *);
+	void __iomem			*regs;	/* ioremap'd register base */
+	unsigned			big_endian_mmio:1;
+	unsigned			big_endian_desc:1;
+	unsigned			es:1;		/* need USBMODE:ES */
+	unsigned			have_sysif_regs:1;
 };
 
 /* Flags in fsl_usb2_mph_platform_data */
-- 
1.5.6.3

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

* [PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (10 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: John Rigby, Anatolij Gustschin, wd, dzu

MPC5121 DIU configuration/setup as initialized by the boot
loader currently will get lost while booting Linux. As a
result displaying the boot splash is not possible through
the boot process.

To prevent this we reserve configured DIU frame buffer
address range while booting and preserve AOI descriptor
and gamma table so that DIU continues displaying through
the whole boot process. On first open from user space
DIU frame buffer driver releases the reserved frame
buffer area and continues to operate as usual.

The patch also moves drivers/video/fsl-diu-fb.h file to
include/linux as we use some DIU structures in platform
code.

'diu_ops' callbacks in platform code borrowed from John's
DIU code.

Signed-off-by: John Rigby <jrigby@gmail.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/platforms/512x/mpc5121_ads.c     |    7 +
 arch/powerpc/platforms/512x/mpc5121_generic.c |   12 +
 arch/powerpc/platforms/512x/mpc512x.h         |    3 +
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  284 ++++++++++++++++++++++++-
 arch/powerpc/sysdev/fsl_soc.h                 |    1 +
 drivers/video/fsl-diu-fb.c                    |   40 +++-
 {drivers/video => include/linux}/fsl-diu-fb.h |    0 
 7 files changed, 341 insertions(+), 6 deletions(-)
 rename {drivers/video => include/linux}/fsl-diu-fb.h (100%)

diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index a497c14..213354e 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
 	for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
 		mpc83xx_add_bridge(np);
 #endif
+	mpc512x_setup_diu();
 	mpc5121_usb_init();
 }
 
@@ -61,12 +62,18 @@ static int __init mpc5121_ads_probe(void)
 	return of_flat_dt_is_compatible(root, "fsl,mpc5121ads");
 }
 
+void __init mpc5121_ads_init_early(void)
+{
+	mpc512x_init_diu();
+}
+
 define_machine(mpc5121_ads) {
 	.name			= "MPC5121 ADS",
 	.probe			= mpc5121_ads_probe,
 	.setup_arch		= mpc5121_ads_setup_arch,
 	.init			= mpc512x_declare_of_platform_devices,
 	.init_IRQ		= mpc5121_ads_init_IRQ,
+	.init_early		= mpc5121_ads_init_early,
 	.get_irq		= ipic_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
 	.restart		= mpc512x_restart,
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
index de4c3f7..38d8bf2 100644
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
@@ -48,10 +48,22 @@ static int __init mpc5121_generic_probe(void)
 	return board[i] != NULL;
 }
 
+void __init mpc512x_generic_init_early(void)
+{
+	mpc512x_init_diu();
+}
+
+void __init mpc512x_generic_setup_arch(void)
+{
+	mpc512x_setup_diu();
+}
+
 define_machine(mpc5121_generic) {
 	.name			= "MPC5121 generic",
 	.probe			= mpc5121_generic_probe,
 	.init			= mpc512x_declare_of_platform_devices,
+	.init_early		= mpc512x_generic_init_early,
+	.setup_arch		= mpc512x_generic_setup_arch,
 	.init_IRQ		= mpc512x_init_IRQ,
 	.get_irq		= ipic_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index e92a282..9ad7dc5 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -14,5 +14,8 @@
 extern void __init mpc512x_init_IRQ(void);
 extern void mpc512x_restart(char *cmd);
 extern void mpc5121_usb_init(void);
+extern void __init mpc512x_init_diu(void);
+extern void __init mpc512x_setup_diu(void);
+extern struct fsl_diu_shared_fb diu_shared_fb;
 void __init mpc512x_declare_of_platform_devices(void);
 #endif				/* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 38d49ad..b9b5a23 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -16,7 +16,11 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/of_platform.h>
+#include <linux/fsl-diu-fb.h>
+#include <linux/bootmem.h>
+#include <sysdev/fsl_soc.h>
 
+#include <asm/cacheflush.h>
 #include <asm/machdep.h>
 #include <asm/ipic.h>
 #include <asm/prom.h>
@@ -59,6 +63,285 @@ void mpc512x_restart(char *cmd)
 		;
 }
 
+
+struct fsl_diu_shared_fb {
+	char		gamma[0x300];	/* 32-bit aligned! */
+	struct diu_ad	ad0;		/* 32-bit aligned! */
+	phys_addr_t	fb_phys;
+	size_t		fb_len;
+	bool		in_use;
+};
+
+unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
+				      int monitor_port)
+{
+	unsigned int pix_fmt;
+
+	switch (bits_per_pixel) {
+	case 32:
+		pix_fmt = 0x88883316;
+		break;
+	case 24:
+		pix_fmt = 0x88082219;
+		break;
+	case 16:
+		pix_fmt = 0x65053118;
+		break;
+	default:
+		pix_fmt = 0x00000400;
+	}
+	return pix_fmt;
+}
+
+void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+{
+}
+
+void mpc512x_set_monitor_port(int monitor_port)
+{
+}
+
+#define CCM_SCFR1	0x0000000c
+#define DIU_DIV_MASK	0x000000ff
+void mpc512x_set_pixel_clock(unsigned int pixclock)
+{
+	unsigned long bestval, bestfreq, speed_ccb, busfreq;
+	unsigned long minpixclock, maxpixclock, pixval;
+	struct device_node *np;
+	void __iomem *ccm;
+	u32 temp;
+	long err;
+	int i;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!np) {
+		pr_err("Can't find clock control module.\n");
+		return;
+	}
+
+	ccm = of_iomap(np, 0);
+	if (!ccm) {
+		pr_err("Can't map clock control module reg.\n");
+		of_node_put(np);
+		return;
+	}
+	of_node_put(np);
+
+	busfreq = 200000000;
+	np = of_find_node_by_type(NULL, "cpu");
+	if (np) {
+		unsigned int size;
+		const unsigned int *prop =
+			of_get_property(np, "bus-frequency", &size);
+		if (prop)
+			busfreq = *prop;
+		of_node_put(np);
+	}
+
+	/* Pixel Clock configuration */
+	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
+	speed_ccb = busfreq * 4;
+
+	/* Calculate the pixel clock with the smallest error */
+	/* calculate the following in steps to avoid overflow */
+	pr_debug("DIU pixclock in ps - %d\n", pixclock);
+	temp = 1;
+	temp *= 1000000000;
+	temp /= pixclock;
+	temp *= 1000;
+	pixclock = temp;
+	pr_debug("DIU pixclock freq - %u\n", pixclock);
+
+	temp *= 5;
+	temp /= 100;  /* pixclock * 0.05 */
+	pr_debug("deviation = %d\n", temp);
+	minpixclock = pixclock - temp;
+	maxpixclock = pixclock + temp;
+	pr_debug("DIU minpixclock - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
+	pixval = speed_ccb/pixclock;
+	pr_debug("DIU pixval = %lu\n", pixval);
+
+	err = 100000000;
+	bestval = pixval;
+	pr_debug("DIU bestval = %lu\n", bestval);
+
+	bestfreq = 0;
+	for (i = -1; i <= 1; i++) {
+		temp = speed_ccb / (pixval+i);
+		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
+			i, pixval, temp);
+		if ((temp < minpixclock) || (temp > maxpixclock))
+			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
+				minpixclock, maxpixclock);
+		else if (abs(temp - pixclock) < err) {
+			pr_debug("Entered the else if block %d\n", i);
+			err = abs(temp - pixclock);
+			bestval = pixval + i;
+			bestfreq = temp;
+		}
+	}
+
+	pr_debug("DIU chose = %lx\n", bestval);
+	pr_debug("DIU error = %ld\n NomPixClk ", err);
+	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
+	/* Modify DIU_DIV in CCM SCFR1 */
+	temp = in_be32(ccm + CCM_SCFR1);
+	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
+	temp &= ~DIU_DIV_MASK;
+	temp |= (bestval & DIU_DIV_MASK);
+	out_be32(ccm + CCM_SCFR1, temp);
+	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
+	iounmap(ccm);
+}
+
+ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0 - 5121 LCD\n");
+}
+
+int mpc512x_set_sysfs_monitor_port(int val)
+{
+	return 0;
+}
+
+struct fsl_diu_shared_fb diu_shared_fb __attribute__ ((__aligned__(8)));
+EXPORT_SYMBOL_GPL(diu_shared_fb);
+
+#if defined(CONFIG_FB_FSL_DIU) || \
+    defined(CONFIG_FB_FSL_DIU_MODULE)
+static inline void mpc512x_free_bootmem(struct page *page)
+{
+	__ClearPageReserved(page);
+	BUG_ON(PageTail(page));
+	BUG_ON(atomic_read(&page->_count) > 1);
+	atomic_set(&page->_count, 1);
+	__free_page(page);
+	totalram_pages++;
+}
+
+void mpc512x_release_bootmem(void)
+{
+	unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK;
+	unsigned long size = diu_shared_fb.fb_len;
+	unsigned long start, end;
+
+	if (diu_shared_fb.in_use) {
+		start = PFN_UP(addr);
+		end = PFN_DOWN(addr + size);
+
+		for (; start < end; start++)
+			mpc512x_free_bootmem(pfn_to_page(start));
+
+		diu_shared_fb.in_use = false;
+	}
+	diu_ops.release_bootmem	= NULL;
+}
+#endif
+
+/*
+ * Check if DIU was pre-initialized. If so, perform steps
+ * needed to continue displaying through the whole boot process.
+ * Move area descriptor and gamma table elsewhere, they are
+ * destroyed by bootmem allocator otherwise. The frame buffer
+ * address range will be reserved in setup_arch() after bootmem
+ * allocator is up.
+ */
+void __init mpc512x_init_diu(void)
+{
+	struct device_node *np;
+	void __iomem *diu_reg;
+	phys_addr_t desc;
+	void __iomem *vaddr;
+	unsigned long mode, pix_fmt, res, bpp;
+	unsigned long dst;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,diu");
+	if (!np) {
+		pr_err("No DIU node\n");
+		return;
+	}
+
+	diu_reg = of_iomap(np, 0);
+	of_node_put(np);
+	if (!diu_reg) {
+		pr_err("Can't map DIU\n");
+		return;
+	}
+
+	mode = in_be32(diu_reg + 0x1c);
+	if (mode != 1) {
+		pr_info("%s: DIU OFF\n", __func__);
+		goto out;
+	}
+
+	desc = in_be32(diu_reg);
+	vaddr = ioremap(desc, sizeof(struct diu_ad));
+	if (!vaddr) {
+		pr_err("Can't map DIU area desc.\n");
+		goto out;
+	}
+	memcpy(&diu_shared_fb.ad0, vaddr, sizeof(struct diu_ad));
+	/* flush fb area descriptor */
+	dst = (unsigned long)&diu_shared_fb.ad0;
+	flush_dcache_range(dst, dst + sizeof(struct diu_ad) - 1);
+
+	res = in_be32(diu_reg + 0x28);
+	pix_fmt = in_le32(vaddr);
+	bpp = ((pix_fmt >> 16) & 0x3) + 1;
+	diu_shared_fb.fb_phys = in_le32(vaddr + 4);
+	diu_shared_fb.fb_len = ((res & 0xfff0000) >> 16) * (res & 0xfff) * bpp;
+	diu_shared_fb.in_use = true;
+	iounmap(vaddr);
+
+	desc = in_be32(diu_reg + 0xc);
+	vaddr = ioremap(desc, sizeof(diu_shared_fb.gamma));
+	if (!vaddr) {
+		pr_err("Can't map DIU area desc.\n");
+		diu_shared_fb.in_use = false;
+		goto out;
+	}
+	memcpy(&diu_shared_fb.gamma, vaddr, sizeof(diu_shared_fb.gamma));
+	/* flush gamma table */
+	dst = (unsigned long)&diu_shared_fb.gamma;
+	flush_dcache_range(dst, dst + sizeof(diu_shared_fb.gamma) - 1);
+
+	iounmap(vaddr);
+	out_be32(diu_reg + 0xc, virt_to_phys(&diu_shared_fb.gamma));
+	out_be32(diu_reg + 4, 0);
+	out_be32(diu_reg + 8, 0);
+	out_be32(diu_reg, virt_to_phys(&diu_shared_fb.ad0));
+
+out:
+	iounmap(diu_reg);
+}
+
+void __init mpc512x_setup_diu(void)
+{
+	int ret;
+
+	if (diu_shared_fb.in_use) {
+		ret = reserve_bootmem(diu_shared_fb.fb_phys,
+				      diu_shared_fb.fb_len,
+				      BOOTMEM_EXCLUSIVE);
+		if (ret) {
+			pr_err("%s: reserve bootmem failed\n", __func__);
+			diu_shared_fb.in_use = false;
+		}
+	}
+
+#if defined(CONFIG_FB_FSL_DIU) || \
+    defined(CONFIG_FB_FSL_DIU_MODULE)
+	diu_ops.get_pixel_format	= mpc512x_get_pixel_format;
+	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
+	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
+	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
+	diu_ops.show_monitor_port	= mpc512x_show_monitor_port;
+	diu_ops.set_sysfs_monitor_port	= mpc512x_set_sysfs_monitor_port;
+	diu_ops.release_bootmem		= mpc512x_release_bootmem;
+#endif
+}
+
 void __init mpc512x_init_IRQ(void)
 {
 	struct device_node *np;
@@ -93,4 +376,3 @@ void __init mpc512x_declare_of_platform_devices(void)
 		printk(KERN_ERR __FILE__ ": "
 			"Error while probing of_platform bus\n");
 }
-
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 19754be..346057d 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -30,6 +30,7 @@ struct platform_diu_data_ops {
 	void (*set_pixel_clock) (unsigned int pixclock);
 	ssize_t (*show_monitor_port) (int monitor_port, char *buf);
 	int (*set_sysfs_monitor_port) (int val);
+	void (*release_bootmem) (void);
 };
 
 extern struct platform_diu_data_ops diu_ops;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 72d68b3..29c7f31 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -34,7 +34,7 @@
 #include <linux/of_platform.h>
 
 #include <sysdev/fsl_soc.h>
-#include "fsl-diu-fb.h"
+#include <linux/fsl-diu-fb.h>
 
 /*
  * These parameters give default parameters
@@ -178,6 +178,21 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
 		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 		.vmode		= FB_VMODE_NONINTERLACED
 	},
+	{
+		.name		= "800x480-60",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 31250,
+		.left_margin	= 86,
+		.right_margin	= 42,
+		.upper_margin	= 33,
+		.lower_margin	= 10,
+		.hsync_len	= 128,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED
+	},
 };
 
 static char *fb_mode = "1024x768-32@60";
@@ -329,8 +344,11 @@ static int fsl_diu_enable_panel(struct fb_info *info)
 	if (mfbi->type != MFB_TYPE_OFF) {
 		switch (mfbi->index) {
 		case 0:				/* plane 0 */
-			if (hw->desc[0] != ad->paddr)
+			if (in_be32(&hw->desc[0]) != ad->paddr) {
+				out_be32(&dr.diu_reg->diu_mode, 0);
 				out_be32(&hw->desc[0], ad->paddr);
+				out_be32(&dr.diu_reg->diu_mode, 1);
+			}
 			break;
 		case 1:				/* plane 1 AOI 0 */
 			cmfbi = machine_data->fsl_diu_info[2]->par;
@@ -389,7 +407,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
 
 	switch (mfbi->index) {
 	case 0:					/* plane 0 */
-		if (hw->desc[0] != machine_data->dummy_ad->paddr)
+		if (in_be32(&hw->desc[0]) != machine_data->dummy_ad->paddr)
 			out_be32(&hw->desc[0],
 				machine_data->dummy_ad->paddr);
 		break;
@@ -1100,6 +1118,10 @@ static int fsl_diu_open(struct fb_info *info, int user)
 	struct mfb_info *mfbi = info->par;
 	int res = 0;
 
+	/* free boot splash memory on first /dev/fb0 open */
+	if (!mfbi->index && diu_ops.release_bootmem)
+		diu_ops.release_bootmem();
+
 	spin_lock(&diu_lock);
 	mfbi->count++;
 	if (mfbi->count == 1) {
@@ -1427,6 +1449,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
 	int ret, i, error = 0;
 	struct resource res;
 	struct fsl_diu_data *machine_data;
+	int diu_mode;
 
 	machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
 	if (!machine_data)
@@ -1463,7 +1486,9 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
 		goto error2;
 	}
 
-	out_be32(&dr.diu_reg->diu_mode, 0);		/* disable DIU anyway*/
+	diu_mode = in_be32(&dr.diu_reg->diu_mode);
+	if (diu_mode != MFB_MODE1)
+		out_be32(&dr.diu_reg->diu_mode, 0);	/* disable DIU */
 
 	/* Get the IRQ of the DIU */
 	machine_data->irq = irq_of_parse_and_map(np, 0);
@@ -1511,7 +1536,12 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
 	machine_data->dummy_ad->offset_xyd = 0;
 	machine_data->dummy_ad->next_ad = 0;
 
-	out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
+	/* Let DIU display splash screen if it was pre-initialized
+	 * by the bootloader, set dummy area descriptor otherwise.
+	 */
+	if (diu_mode != MFB_MODE1)
+		out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
+
 	out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
 	out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
 
diff --git a/drivers/video/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h
similarity index 100%
rename from drivers/video/fsl-diu-fb.h
rename to include/linux/fsl-diu-fb.h
-- 
1.5.6.3

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

* [PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (11 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Anatolij Gustschin, wd, dzu, Piotr Ziecik

Collects several changes needed after applying
previous mpc5121 platform and driver patches:

- Add mpc5121 reset module node
- Clean up and fix NAND description, remove unused properties
  here and correct NAND flash chip size.
- Add I2C RTC node for m41t80 RTC
- Fix compatible property in DMA node
- Remove unused cell-index properties from CAN nodes
- Fix compatible property in DIU node
- USB node changes:
    - remove 'port0/1' properties as these are only used
      for multi-port host(MHP) module which is not available
      on MPC5121.
    - MPC5121 Rev 2.0 EHCI registers are big endian.
      'big-endian-regs' property in USB node indicates
      this now.
    - use 'invert-drvvbus' and 'invert-pwr-fault' in
      USB node for internal PHY to specify polarities
      of appropriate port pins.

Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Detlev Zundel <dzu@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/boot/dts/mpc5121ads.dts |   35 +++++++++++++++++++--------------
 1 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index c353dac..22c107f 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -62,17 +62,12 @@
 		interrupt-parent = < &ipic >;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		bank-width = <1>;
 		// ADS has two Hynix 512MB Nand flash chips in a single
-		// stacked package .
+		// stacked package.
 		chips = <2>;
-		nand0@0 {
-			label = "nand0";
-			reg = <0x00000000 0x02000000>; 	// first 32 MB of chip 0
-		};
-		nand1@20000000 {
-			label = "nand1";
-			reg = <0x20000000 0x02000000>; 	// first 32 MB of chip 1
+		nand@0 {
+			label = "nand";
+			reg = <0x00000000 0x40000000>;	// 512MB + 512MB
 		};
 	};
 
@@ -166,6 +161,11 @@
 			interrupt-parent = < &ipic >;
 		};
 
+		reset@e00 {	// Reset module
+			compatible = "fsl,mpc5121-reset";
+			reg = <0xe00 0x100>;
+		};
+
 		clock@f00 {	// Clock control
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
@@ -187,7 +187,6 @@
 
 		mscan@1300 {
 			compatible = "fsl,mpc5121-mscan";
-			cell-index = <0>;
 			interrupts = <12 0x8>;
 			interrupt-parent = < &ipic >;
 			reg = <0x1300 0x80>;
@@ -195,7 +194,6 @@
 
 		mscan@1380 {
 			compatible = "fsl,mpc5121-mscan";
-			cell-index = <1>;
 			interrupts = <13 0x8>;
 			interrupt-parent = < &ipic >;
 			reg = <0x1380 0x80>;
@@ -219,6 +217,11 @@
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
 			interrupt-parent = < &ipic >;
+
+			rtc@68 {
+				compatible = "stm,m41t80";
+				reg = <0x68>;
+			};
 		};
 
 		i2c@1740 {
@@ -244,7 +247,7 @@
 		};
 
 		display@2100 {
-			compatible = "fsl,mpc5121-diu", "fsl-diu";
+			compatible = "fsl,mpc5121-diu", "fsl,diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
 			interrupt-parent = < &ipic >;
@@ -285,7 +288,7 @@
 		//	interrupts = <43 0x8>;
 		//	dr_mode = "otg";
 		//	phy_type = "ulpi";
-		//	port1;
+		//	big-endian-regs;
 		//};
 
 		// USB0 using internal UTMI PHY
@@ -298,7 +301,9 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
-			port0;
+			big-endian-regs;
+			invert-drvvbus;
+			invert-pwr-fault;
 		};
 
 		// IO control
@@ -365,7 +370,7 @@
 		};
 
 		dma@14000 {
-			compatible = "fsl,mpc5121-dma2";
+			compatible = "fsl,mpc5121-dma";
 			reg = <0x14000 0x1800>;
 			interrupts = <65 0x8>;
 			interrupt-parent = < &ipic >;
-- 
1.5.6.3

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

* [PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS
  2010-01-19 20:24 ` Anatolij Gustschin
                   ` (12 preceding siblings ...)
  (?)
@ 2010-01-19 20:24 ` Anatolij Gustschin
  2010-01-21 17:47   ` Grant Likely
  -1 siblings, 1 reply; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-19 20:24 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Anatolij Gustschin, wd, dzu

From: Wolfgang Denk <wd@denx.de>

As more MPC512x based boards will be coming soon, a new directory
arch/powerpc/configs/512x/ for board specific config files is created,
following the example of other processor families.

In a first step, we just copy (and update) the existing defconfig
file for the mpc5121ads board. When new boards get added, the old
arch/powerpc/configs/mpc5121_defconfig file will get adjusted to
allow for a generic kernel image for MPC512x based boards.

Signed-off-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Detlev Zundel <dzu@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
This default config is provided only for easier testing.

 arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++++++++++
 1 files changed, 1662 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/configs/512x/mpc5121ads_defconfig

diff --git a/arch/powerpc/configs/512x/mpc5121ads_defconfig b/arch/powerpc/configs/512x/mpc5121ads_defconfig
new file mode 100644
index 0000000..c1e4e63
--- /dev/null
+++ b/arch/powerpc/configs/512x/mpc5121ads_defconfig
@@ -0,0 +1,1662 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc4
+# Tue Jan 19 15:35:31 2010
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_PPC_BOOK3S_32=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
+# CONFIG_SMP is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_NR_IRQS=512
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+CONFIG_PPC_MSI_BITMAP=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_CHRP is not set
+CONFIG_PPC_MPC512x=y
+CONFIG_PPC_MPC5121=y
+CONFIG_MPC5121_ADS=y
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_QUICC_ENGINE is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_MAX_ACTIVE_REGIONS=32
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=y
+CONFIG_CAN_DEV=y
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MSCAN=y
+# CONFIG_CAN_SJA1000 is not set
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_NAND_FSL_ELBC is not set
+CONFIG_MTD_NAND_MPC5121_NFC=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_XIP=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_ATL2 is not set
+# CONFIG_XILINX_EMACLITE is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_MPC5121_FEC=y
+CONFIG_FS_ENET_HAS_FEC=y
+CONFIG_FS_ENET_MDIO_FEC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_AIRO is not set
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_FSL_DIU=y
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+# CONFIG_THRUSTMASTER_FF is not set
+CONFIG_HID_ZEROPLUS=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y
+# CONFIG_XPS_USB_HCD_XILINX is not set
+CONFIG_USB_EHCI_FSL=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+CONFIG_RTC_DRV_M41T80=y
+# CONFIG_RTC_DRV_M41T80_WDT is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_GENERIC is not set
+CONFIG_RTC_DRV_MPC5121=y
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_FSL_DMA is not set
+CONFIG_MPC512X_DMA=y
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_FS_XIP=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_PPC_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
-- 
1.5.6.3

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
  2010-01-19 20:24   ` Anatolij Gustschin
@ 2010-01-19 20:37     ` David Miller
  -1 siblings, 0 replies; 62+ messages in thread
From: David Miller @ 2010-01-19 20:37 UTC (permalink / raw)
  To: agust; +Cc: linuxppc-dev, dzu, wd, jcrigby, jrigby, kosmo, netdev, grant.likely


Well... where are the other 9 patches?

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
@ 2010-01-19 20:37     ` David Miller
  0 siblings, 0 replies; 62+ messages in thread
From: David Miller @ 2010-01-19 20:37 UTC (permalink / raw)
  To: agust; +Cc: kosmo, dzu, netdev, linuxppc-dev, jrigby, wd


Well... where are the other 9 patches?

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

* Re: [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
  2010-01-19 20:24   ` Anatolij Gustschin
  (?)
@ 2010-01-19 20:48   ` Scott Wood
  2010-01-20 11:20       ` Anatolij Gustschin
  -1 siblings, 1 reply; 62+ messages in thread
From: Scott Wood @ 2010-01-19 20:48 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Piotr Ziecik, dzu, netdev, linuxppc-dev, John Rigby, wd

Anatolij Gustschin wrote:
> +struct reg_tbl {
> +	void __iomem *fec_ievent;
> +	void __iomem *fec_imask;
> +	void __iomem *fec_r_des_active;
> +	void __iomem *fec_x_des_active;
> +	void __iomem *fec_r_des_start;
> +	void __iomem *fec_x_des_start;
> +	void __iomem *fec_r_cntrl;
> +	void __iomem *fec_ecntrl;
> +	void __iomem *fec_ivec;
> +	void __iomem *fec_mii_speed;
> +	void __iomem *fec_addr_low;
> +	void __iomem *fec_addr_high;
> +	void __iomem *fec_hash_table_high;
> +	void __iomem *fec_hash_table_low;
> +	void __iomem *fec_r_buff_size;
> +	void __iomem *fec_r_bound;
> +	void __iomem *fec_r_fstart;
> +	void __iomem *fec_x_fstart;
> +	void __iomem *fec_fun_code;
> +	void __iomem *fec_r_hash;
> +	void __iomem *fec_x_cntrl;
> +	void __iomem *fec_dma_control;
> +};

Why void and not the specific type?

>  static void set_promiscuous_mode(struct net_device *dev)
>  {
>  	struct fs_enet_private *fep = netdev_priv(dev);
> -	fec_t __iomem *fecp = fep->fec.fecp;
> +	struct reg_tbl *fecp = fep->fec.rtbl;

Hmm, having something called "fecp" that is a different type than other 
"fecp"s could be confusing.

> @@ -134,6 +143,20 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
>  	if (!fec->fecp)
>  		goto out_fec;
>  
> +	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec-mdio")) {

You can put a data pointer in the of_platform match struct, instead of 
re-checking the compatible.

-Scott

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
  2010-01-19 20:37     ` David Miller
@ 2010-01-19 23:42       ` Stephen Rothwell
  -1 siblings, 0 replies; 62+ messages in thread
From: Stephen Rothwell @ 2010-01-19 23:42 UTC (permalink / raw)
  To: David Miller; +Cc: agust, kosmo, dzu, netdev, linuxppc-dev, jrigby, wd

[-- Attachment #1: Type: text/plain, Size: 320 bytes --]

Hi Dave,

On Tue, 19 Jan 2010 12:37:06 -0800 (PST) David Miller <davem@davemloft.net> wrote:
>
> Well... where are the other 9 patches?

I think the other 9 are not network related, just PowerPC related.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
@ 2010-01-19 23:42       ` Stephen Rothwell
  0 siblings, 0 replies; 62+ messages in thread
From: Stephen Rothwell @ 2010-01-19 23:42 UTC (permalink / raw)
  To: David Miller; +Cc: kosmo, jrigby, netdev, linuxppc-dev, agust, dzu, wd

[-- Attachment #1: Type: text/plain, Size: 320 bytes --]

Hi Dave,

On Tue, 19 Jan 2010 12:37:06 -0800 (PST) David Miller <davem@davemloft.net> wrote:
>
> Well... where are the other 9 patches?

I think the other 9 are not network related, just PowerPC related.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
  2010-01-19 23:42       ` Stephen Rothwell
@ 2010-01-20  4:04         ` David Miller
  -1 siblings, 0 replies; 62+ messages in thread
From: David Miller @ 2010-01-20  4:04 UTC (permalink / raw)
  To: sfr; +Cc: agust, kosmo, dzu, netdev, linuxppc-dev, jrigby, wd

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 20 Jan 2010 10:42:25 +1100

> On Tue, 19 Jan 2010 12:37:06 -0800 (PST) David Miller <davem@davemloft.net> wrote:
>>
>> Well... where are the other 9 patches?
> 
> I think the other 9 are not network related, just PowerPC related.

Ok, but that's very confusing.

If it's meant to go into two different trees split the
patches up into two different series.

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
@ 2010-01-20  4:04         ` David Miller
  0 siblings, 0 replies; 62+ messages in thread
From: David Miller @ 2010-01-20  4:04 UTC (permalink / raw)
  To: sfr; +Cc: kosmo, jrigby, netdev, linuxppc-dev, agust, dzu, wd

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 20 Jan 2010 10:42:25 +1100

> On Tue, 19 Jan 2010 12:37:06 -0800 (PST) David Miller <davem@davemloft.net> wrote:
>>
>> Well... where are the other 9 patches?
> 
> I think the other 9 are not network related, just PowerPC related.

Ok, but that's very confusing.

If it's meant to go into two different trees split the
patches up into two different series.

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
  2010-01-19 20:24   ` Anatolij Gustschin
@ 2010-01-20 10:22     ` Wolfram Sang
  -1 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 10:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev, wd, John Rigby, netdev, dzu, Piotr Ziecik

[-- Attachment #1: Type: text/plain, Size: 1126 bytes --]

> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
> index 909b78d..a391219 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -587,6 +587,33 @@ void fs_cleanup_bds(struct net_device *dev)
>  
>  /**********************************************************************************/
>  
> +static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
> +					       struct sk_buff *skb)
> +{
> +	struct sk_buff *new_skb;
> +
> +	/* Alloc new skb */
> +	new_skb = dev_alloc_skb(ENET_RX_FRSIZE + 32);
> +	if (!new_skb) {
> +		printk(KERN_WARNING DRV_MODULE_NAME
> +				": %s Memory squeeze, dropping tx packet.\n",
> +								dev->name);

I understand this type of printk fits to the rest of the code, I just wonder if
new (and patched) printouts shouldn't be converted to dev_*? Might be one line
then, and more consistent to what other drivers produce.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121
@ 2010-01-20 10:22     ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 10:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Piotr Ziecik, dzu, netdev, linuxppc-dev, John Rigby, wd

[-- Attachment #1: Type: text/plain, Size: 1126 bytes --]

> diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
> index 909b78d..a391219 100644
> --- a/drivers/net/fs_enet/fs_enet-main.c
> +++ b/drivers/net/fs_enet/fs_enet-main.c
> @@ -587,6 +587,33 @@ void fs_cleanup_bds(struct net_device *dev)
>  
>  /**********************************************************************************/
>  
> +static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
> +					       struct sk_buff *skb)
> +{
> +	struct sk_buff *new_skb;
> +
> +	/* Alloc new skb */
> +	new_skb = dev_alloc_skb(ENET_RX_FRSIZE + 32);
> +	if (!new_skb) {
> +		printk(KERN_WARNING DRV_MODULE_NAME
> +				": %s Memory squeeze, dropping tx packet.\n",
> +								dev->name);

I understand this type of printk fits to the rest of the code, I just wonder if
new (and patched) printouts shouldn't be converted to dev_*? Might be one line
then, and more consistent to what other drivers produce.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
  2010-01-19 20:24   ` Anatolij Gustschin
@ 2010-01-20 10:49     ` Wolfram Sang
  -1 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 10:49 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, linux-mtd, wd, dzu, Piotr Ziecik

[-- Attachment #1: Type: text/plain, Size: 1576 bytes --]

On Tue, Jan 19, 2010 at 09:24:08PM +0100, Anatolij Gustschin wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
> 
> Adds NAND Flash Controller driver for MPC5121 Revision 2.
> All device features, except hardware ECC and power management,
> are supported.
> 
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <linux-mtd@lists.infradead.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> ---

Please include a logfile with changes since the last version. This really
helps.

> +static int __init mpc5121_nfc_probe(struct of_device *op,
> +					const struct of_device_id *match)

[...]

> +{
> +	/* Support external chip-select logic on ADS5121 board */
> +	rootnode = of_find_node_by_path("/");
> +	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
> +		retval = ads5121_chipselect_init(mtd);
> +		if (retval) {
> +			dev_err(dev, "Chipselect init error!\n");
> +			of_node_put(rootnode);
> +			return retval;
> +		}
> +
> +		chip->select_chip = ads5121_select_chip;
> +	}
> +	of_node_put(rootnode);

If we have to live with the platform-stuff being in the driver, maybe a table
having the compatible-string and an init-function pointer per entry will make
it scale better with the number of boards?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
@ 2010-01-20 10:49     ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 10:49 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, linux-mtd, dzu, Piotr Ziecik

[-- Attachment #1: Type: text/plain, Size: 1576 bytes --]

On Tue, Jan 19, 2010 at 09:24:08PM +0100, Anatolij Gustschin wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
> 
> Adds NAND Flash Controller driver for MPC5121 Revision 2.
> All device features, except hardware ECC and power management,
> are supported.
> 
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <linux-mtd@lists.infradead.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> ---

Please include a logfile with changes since the last version. This really
helps.

> +static int __init mpc5121_nfc_probe(struct of_device *op,
> +					const struct of_device_id *match)

[...]

> +{
> +	/* Support external chip-select logic on ADS5121 board */
> +	rootnode = of_find_node_by_path("/");
> +	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
> +		retval = ads5121_chipselect_init(mtd);
> +		if (retval) {
> +			dev_err(dev, "Chipselect init error!\n");
> +			of_node_put(rootnode);
> +			return retval;
> +		}
> +
> +		chip->select_chip = ads5121_select_chip;
> +	}
> +	of_node_put(rootnode);

If we have to live with the platform-stuff being in the driver, maybe a table
having the compatible-string and an init-function pointer per entry will make
it scale better with the number of boards?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 05/11] rtc: Add MPC5121 Real time clock driver
  2010-01-19 20:24 ` [PATCH 05/11] rtc: Add MPC5121 Real time clock driver Anatolij Gustschin
@ 2010-01-20 11:01   ` Wolfram Sang
  2010-01-20 22:19   ` [rtc-linux] " Alessandro Zummo
  1 sibling, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 11:01 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Piotr Ziecik, dzu, rtc-linux, linuxppc-dev, John Rigby, wd

[-- Attachment #1: Type: text/plain, Size: 1535 bytes --]

On Tue, Jan 19, 2010 at 09:24:07PM +0100, Anatolij Gustschin wrote:
> From: John Rigby <jrigby@freescale.com>
> 
> Based on Domen Puncer's rtc driver for 5200 posted to
> the ppclinux mailing list:
>         http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=11675
> but never commited anywhere.
> 
> Changes to Domen's original:
> 
>     Changed filenames/routine names from mpc5200* to mpc5121*
>     Changed match to only care about compatible and use "fsl,"
>     convention for compatible.
> 
>     Make alarms more sane by dealing with lack of second alarm resolution.
> 
>     Deal with the fact that most of the 5121 rtc registers are not persistent
>     across a reset even with a battery attached:
> 
>         Use actual_time register for time keeping
>         and target_time register as an offset to linux time
> 
>         The target_time register would normally be used for hibernation
>         but hibernation does not work on current silicon

Last time, we discussed if it makes sense to rename it to mpc5xxx, as the rtc
is quite similar to the mpc5200 one. I then checked and parts of the
differences include that it is not possible on a 5200 to use the tricks to keep
the RTC persistent across resets. Thus, I think the patch is okay with not
supporting the 5200. Its rtc seems pretty useless.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
  2010-01-19 20:48   ` Scott Wood
@ 2010-01-20 11:20       ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-20 11:20 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, wd, John Rigby, netdev, dzu, Piotr Ziecik

Scott Wood <scottwood@freescale.com> wrote:

> > +	void __iomem *fec_fun_code;
> > +	void __iomem *fec_r_hash;
> > +	void __iomem *fec_x_cntrl;
> > +	void __iomem *fec_dma_control;
> > +};
> 
> Why void and not the specific type?

Ok, I will fix it for using u32 __iomem *.

> >  static void set_promiscuous_mode(struct net_device *dev)
> >  {
> >  	struct fs_enet_private *fep = netdev_priv(dev);
> > -	fec_t __iomem *fecp = fep->fec.fecp;
> > +	struct reg_tbl *fecp = fep->fec.rtbl;
> 
> Hmm, having something called "fecp" that is a different type than other 
> "fecp"s could be confusing.

Ok, I will use 'regp' instead of 'fecp' then.

> > @@ -134,6 +143,20 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
> >  	if (!fec->fecp)
> >  		goto out_fec;
> >  
> > +	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec-mdio")) {
> 
> You can put a data pointer in the of_platform match struct, instead of 
> re-checking the compatible.

.data pointer in 'fs_enet_mdio_fec_match' is already used for
mpc5xxx_get_bus_frequency(). Setting .data to some sort of FEC ID in
match struct for "fsl,pq1-fec-mdio" would be confusing to.
Would a simple

if (!strncmp(match->compatible, "fsl,mpc5121-fec-mdio",
             sizeof(match->compatible))) {

suffice here?

Thanks!

Anatolij

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

* Re: [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
@ 2010-01-20 11:20       ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-20 11:20 UTC (permalink / raw)
  To: Scott Wood; +Cc: Piotr Ziecik, dzu, netdev, linuxppc-dev, John Rigby, wd

Scott Wood <scottwood@freescale.com> wrote:

> > +	void __iomem *fec_fun_code;
> > +	void __iomem *fec_r_hash;
> > +	void __iomem *fec_x_cntrl;
> > +	void __iomem *fec_dma_control;
> > +};
> 
> Why void and not the specific type?

Ok, I will fix it for using u32 __iomem *.

> >  static void set_promiscuous_mode(struct net_device *dev)
> >  {
> >  	struct fs_enet_private *fep = netdev_priv(dev);
> > -	fec_t __iomem *fecp = fep->fec.fecp;
> > +	struct reg_tbl *fecp = fep->fec.rtbl;
> 
> Hmm, having something called "fecp" that is a different type than other 
> "fecp"s could be confusing.

Ok, I will use 'regp' instead of 'fecp' then.

> > @@ -134,6 +143,20 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
> >  	if (!fec->fecp)
> >  		goto out_fec;
> >  
> > +	if (of_device_is_compatible(ofdev->node, "fsl,mpc5121-fec-mdio")) {
> 
> You can put a data pointer in the of_platform match struct, instead of 
> re-checking the compatible.

.data pointer in 'fs_enet_mdio_fec_match' is already used for
mpc5xxx_get_bus_frequency(). Setting .data to some sort of FEC ID in
match struct for "fsl,pq1-fec-mdio" would be confusing to.
Would a simple

if (!strncmp(match->compatible, "fsl,mpc5121-fec-mdio",
             sizeof(match->compatible))) {

suffice here?

Thanks!

Anatolij

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

* Re: [PATCH 0/11] Update support for MPC512x
  2010-01-19 20:24 ` Anatolij Gustschin
  (?)
@ 2010-01-20 11:22     ` Wolfram Sang
  -1 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 11:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, Grant Likely, John Rigby, Dan Williams,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]


> The patches are based on v2.6.33-rc4 and cover the following
> items:

The USB-patch needs two patches from linux-next. For convenience, don't you
have a git-tree somewhere? :)

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-20 11:22     ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 11:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: wd, dzu, netdev, linux-usb, linuxppc-dev, linux-mtd, linux-i2c,
	rtc-linux, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]


> The patches are based on v2.6.33-rc4 and cover the following
> items:

The USB-patch needs two patches from linux-next. For convenience, don't you
have a git-tree somewhere? :)

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-20 11:22     ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 11:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: John Rigby, dzu, netdev, linux-usb, Grant Likely, linuxppc-dev,
	linux-mtd, linux-i2c, rtc-linux, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]


> The patches are based on v2.6.33-rc4 and cover the following
> items:

The USB-patch needs two patches from linux-next. For convenience, don't you
have a git-tree somewhere? :)

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 03/11] powerpc/mpc5121: Add machine restart support
  2010-01-19 20:24 ` [PATCH 03/11] powerpc/mpc5121: Add machine restart support Anatolij Gustschin
@ 2010-01-20 11:28   ` Wolfram Sang
  2010-01-26  7:53     ` Anatolij Gustschin
  0 siblings, 1 reply; 62+ messages in thread
From: Wolfram Sang @ 2010-01-20 11:28 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, wd, dzu, Piotr Ziecik

[-- Attachment #1: Type: text/plain, Size: 4776 bytes --]

On Tue, Jan 19, 2010 at 09:24:05PM +0100, Anatolij Gustschin wrote:
> Add reset module registers representation and
> machine restart callback for mpc5121 platform.
> 
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>

Looks good to me. Minor nits below.

> ---
>  arch/powerpc/include/asm/mpc5xxx.h            |   14 +++++++++-
>  arch/powerpc/platforms/512x/mpc5121_ads.c     |    1 +
>  arch/powerpc/platforms/512x/mpc5121_generic.c |    1 +
>  arch/powerpc/platforms/512x/mpc512x.h         |    1 +
>  arch/powerpc/platforms/512x/mpc512x_shared.c  |   35 +++++++++++++++++++++++++
>  5 files changed, 51 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/mpc5xxx.h b/arch/powerpc/include/asm/mpc5xxx.h
> index 5ce9c5f..0004986 100644
> --- a/arch/powerpc/include/asm/mpc5xxx.h
> +++ b/arch/powerpc/include/asm/mpc5xxx.h
> @@ -18,5 +18,17 @@
>  
>  extern unsigned long mpc5xxx_get_bus_frequency(struct device_node *node);
>  
> -#endif /* __ASM_POWERPC_MPC5xxx_H__ */
> +/* MPC512x Reset module registers */
> +struct mpc512x_reset_module {
> +	u32	rcwlr;	/* Reset Configuration Word Low Register */
> +	u32	rcwhr;	/* Reset Configuration Word High Register */
> +	u32	reserved1;
> +	u32	reserved2;
> +	u32	rsr;	/* Reset Status Register */
> +	u32	rmr;	/* Reset Mode Register */
> +	u32	rpr;	/* Reset Protection Register */
> +	u32	rcr;	/* Reset Control Register */
> +	u32	rcer;	/* Reset Control Enable Register */
> +};
>  
> +#endif /* __ASM_POWERPC_MPC5xxx_H__ */
> diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
> index 441abc4..2f40404 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_ads.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
> @@ -68,4 +68,5 @@ define_machine(mpc5121_ads) {
>  	.init_IRQ		= mpc5121_ads_init_IRQ,
>  	.get_irq		= ipic_get_irq,
>  	.calibrate_decr		= generic_calibrate_decr,
> +	.restart		= mpc512x_restart,
>  };
> diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
> index 2479de9..de4c3f7 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_generic.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
> @@ -55,4 +55,5 @@ define_machine(mpc5121_generic) {
>  	.init_IRQ		= mpc512x_init_IRQ,
>  	.get_irq		= ipic_get_irq,
>  	.calibrate_decr		= generic_calibrate_decr,
> +	.restart		= mpc512x_restart,
>  };
> diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
> index 22a5352..c38875c 100644
> --- a/arch/powerpc/platforms/512x/mpc512x.h
> +++ b/arch/powerpc/platforms/512x/mpc512x.h
> @@ -12,5 +12,6 @@
>  #ifndef __MPC512X_H__
>  #define __MPC512X_H__
>  extern void __init mpc512x_init_IRQ(void);
> +extern void mpc512x_restart(char *cmd);
>  void __init mpc512x_declare_of_platform_devices(void);
>  #endif				/* __MPC512X_H__ */
> diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
> index 434d683..8a0d577 100644
> --- a/arch/powerpc/platforms/512x/mpc512x_shared.c
> +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
> @@ -21,9 +21,44 @@
>  #include <asm/ipic.h>
>  #include <asm/prom.h>
>  #include <asm/time.h>
> +#include <asm/mpc5xxx.h>
>  
>  #include "mpc512x.h"
>  
> +static void __iomem *reset_module_base;

type here also?

> +
> +static int __init mpc512x_restart_init(void)
> +{
> +	struct device_node *np;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
> +	if (!np)
> +		return -1;
> +
> +	reset_module_base = of_iomap(np, 0);
> +	of_node_put(np);
> +
> +	return 0;
> +}
> +

Drop this empty line?

> +arch_initcall(mpc512x_restart_init);
> +
> +void mpc512x_restart(char *cmd)
> +{
> +	struct mpc512x_reset_module *rm = reset_module_base;
> +
> +	if (rm) {
> +		/* Enable software reset "RSTE" */
> +		out_be32(&rm->rpr, 0x52535445);
> +		/* Set software hard reset */
> +		out_be32(&rm->rcr, 0x2);
> +	} else {
> +		printk(KERN_ERR ": Restart module not mapped.\n");

The colon is a leftover?

> +	}
> +	for (;;)
> +		;
> +}
> +
>  void __init mpc512x_init_IRQ(void)
>  {
>  	struct device_node *np;
> -- 
> 1.5.6.3
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
  2010-01-20 11:20       ` Anatolij Gustschin
@ 2010-01-20 17:02         ` Scott Wood
  -1 siblings, 0 replies; 62+ messages in thread
From: Scott Wood @ 2010-01-20 17:02 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev, wd, John Rigby, netdev, dzu, Piotr Ziecik

Anatolij Gustschin wrote:
> Scott Wood <scottwood@freescale.com> wrote:
>> You can put a data pointer in the of_platform match struct, instead of 
>> re-checking the compatible.
> 
> .data pointer in 'fs_enet_mdio_fec_match' is already used for
> mpc5xxx_get_bus_frequency(). Setting .data to some sort of FEC ID in
> match struct for "fsl,pq1-fec-mdio" would be confusing to.

You could point .data to a struct if there are multiple things.

-Scott

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

* Re: [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver
@ 2010-01-20 17:02         ` Scott Wood
  0 siblings, 0 replies; 62+ messages in thread
From: Scott Wood @ 2010-01-20 17:02 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Piotr Ziecik, dzu, netdev, linuxppc-dev, John Rigby, wd

Anatolij Gustschin wrote:
> Scott Wood <scottwood@freescale.com> wrote:
>> You can put a data pointer in the of_platform match struct, instead of 
>> re-checking the compatible.
> 
> .data pointer in 'fs_enet_mdio_fec_match' is already used for
> mpc5xxx_get_bus_frequency(). Setting .data to some sort of FEC ID in
> match struct for "fsl,pq1-fec-mdio" would be confusing to.

You could point .data to a struct if there are multiple things.

-Scott

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

* Re: [rtc-linux] [PATCH 05/11] rtc: Add MPC5121 Real time clock driver
  2010-01-19 20:24 ` [PATCH 05/11] rtc: Add MPC5121 Real time clock driver Anatolij Gustschin
  2010-01-20 11:01   ` Wolfram Sang
@ 2010-01-20 22:19   ` Alessandro Zummo
  1 sibling, 0 replies; 62+ messages in thread
From: Alessandro Zummo @ 2010-01-20 22:19 UTC (permalink / raw)
  To: rtc-linux; +Cc: wd, dzu, linuxppc-dev, John Rigby, agust, Piotr Ziecik

On Tue, 19 Jan 2010 21:24:07 +0100
Anatolij Gustschin <agust@denx.de> wrote:

 Hi,

  thank for you submission. A few comments below. You might
 want to read http://groups.google.com/group/rtc-linux/web/checklist?pli=1

> From: John Rigby <jrigby@freescale.com>
> 
> Based on Domen Puncer's rtc driver for 5200 posted to
> the ppclinux mailing list:
>         http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=11675
> but never commited anywhere.
> 
> Changes to Domen's original:
> 
>     Changed filenames/routine names from mpc5200* to mpc5121*
>     Changed match to only care about compatible and use "fsl,"
>     convention for compatible.
> 
>     Make alarms more sane by dealing with lack of second alarm resolution.
> 
>     Deal with the fact that most of the 5121 rtc registers are not persistent
>     across a reset even with a battery attached:
> 
>         Use actual_time register for time keeping
>         and target_time register as an offset to linux time
> 
>         The target_time register would normally be used for hibernation
>         but hibernation does not work on current silicon 
> Signed-off-by: John Rigby <jcrigby@gmail.com>
> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: <rtc-linux@googlegroups.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> ---
>  drivers/rtc/Kconfig       |   10 +
>  drivers/rtc/Makefile      |    1 +
>  drivers/rtc/rtc-mpc5121.c |  408 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 419 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/rtc/rtc-mpc5121.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 8167e9e..e51b094 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -868,4 +868,14 @@ config RTC_DRV_MC13783
>  	help
>  	  This enables support for the Freescale MC13783 PMIC RTC
>  
> +config RTC_DRV_MPC5121
> +	tristate "Freescale MPC5121 built-in RTC"
> +	depends on RTC_CLASS
> +	help
> +	  If you say yes here you will get support for the
> +	  built-in RTC MPC5121.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called rtc-mpc5121.
> +
>  endif # RTC_CLASS
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index e5160fd..db1dcd4 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
>  obj-$(CONFIG_RTC_DRV_MC13783)	+= rtc-mc13783.o
>  obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
>  obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
> +obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o
>  obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
>  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
>  obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o
> diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
> new file mode 100644
> index 0000000..63460cb
> --- /dev/null
> +++ b/drivers/rtc/rtc-mpc5121.c
> @@ -0,0 +1,408 @@
> +/*
> + * Real-time clock driver for MPC5121
> + *
> + * Copyright 2007, Domen Puncer <domen.puncer@telargo.com>
> + * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/*
> + * History:
> + *
> + * Based on mpc5200_rtc.c written by Domen Puncer <domen.puncer@telargo.com>
> + *   posted to linuxppc-embedded mailing list:
> + *     http://patchwork.ozlabs.org/linuxppc-embedded/patch?id=11675
> + *   but never committed to any public tree.
> + *
> + * Author: John Rigby <jrigby@freescale.com>
> + *   Converted to 5121 rtc driver.
> + *
> + *   Make alarms more sane by dealing with lack of second alarm resolution.
> + *
> + *   Use actual_time time register for time keeping since it is persistent
> + *   and the normal rtc registers are not.  Use target_time register as an
> + *   offset to linux time.
> + *
> + */

 The history goes in the changelog. Author(s) name on the top.

> +#include <linux/module.h>
> +#include <linux/rtc.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/io.h>
> +
> +struct mpc5121_rtc_regs {
> +	u8 set_time;		/* RTC + 0x00 */
> +	u8 hour_set;		/* RTC + 0x01 */
> +	u8 minute_set;		/* RTC + 0x02 */
> +	u8 second_set;		/* RTC + 0x03 */
> +
> +	u8 set_date;		/* RTC + 0x04 */
> +	u8 month_set;		/* RTC + 0x05 */
> +	u8 weekday_set;		/* RTC + 0x06 */
> +	u8 date_set;		/* RTC + 0x07 */
> +
> +	u8 write_sw;		/* RTC + 0x08 */
> +	u8 sw_set;		/* RTC + 0x09 */
> +	u16 year_set;		/* RTC + 0x0a */
> +
> +	u8 alm_enable;		/* RTC + 0x0c */
> +	u8 alm_hour_set;	/* RTC + 0x0d */
> +	u8 alm_min_set;		/* RTC + 0x0e */
> +	u8 int_enable;		/* RTC + 0x0f */
> +
> +	u8 reserved1;
> +	u8 hour;		/* RTC + 0x11 */
> +	u8 minute;		/* RTC + 0x12 */
> +	u8 second;		/* RTC + 0x13 */
> +
> +	u8 month;		/* RTC + 0x14 */
> +	u8 wday_mday;		/* RTC + 0x15 */
> +	u16 year;		/* RTC + 0x16 */
> +
> +	u8 int_alm;		/* RTC + 0x18 */
> +	u8 int_sw;		/* RTC + 0x19 */
> +	u8 alm_status;		/* RTC + 0x1a */
> +	u8 sw_minute;		/* RTC + 0x1b */
> +
> +	u8 bus_error_1;		/* RTC + 0x1c */
> +	u8 int_day;		/* RTC + 0x1d */
> +	u8 int_min;		/* RTC + 0x1e */
> +	u8 int_sec;		/* RTC + 0x1f */
> +
> +	/*
> +	 * target_time:
> +	 *	intended to be used for hibernation but hibernation
> +	 *	does not work on silicon rev 1.5 so use it for non-volatile
> +	 *	storage of offset between the actual_time register and linux
> +	 *	time
> +	 */
> +	u32 target_time;	/* RTC + 0x20 */
> +	/*
> +	 * actual_time:
> +	 * 	readonly time since VBAT_RTC was last connected
> +	 */
> +	u32 actual_time;	/* RTC + 0x24 */
> +	u32 keep_alive;		/* RTC + 0x28 */
> +};
> +
> +struct mpc5121_rtc_data {
> +	unsigned irq;
> +	unsigned irq_periodic;
> +	struct mpc5121_rtc_regs __iomem *regs;
> +	struct rtc_device *rtc;
> +	struct rtc_wkalrm wkalarm;
> +};
> +
> +/*
> + * Update second/minute/hour registers.
> + *
> + * This is just so alarm will work.
> + */
> +static void mpc5121_rtc_update_smh(struct mpc5121_rtc_regs __iomem *regs,
> +	struct rtc_time *tm)
> +{
> +	out_8(&regs->second_set, tm->tm_sec);
> +	out_8(&regs->minute_set, tm->tm_min);
> +	out_8(&regs->hour_set, tm->tm_hour);
> +
> +	/* set time sequence */
> +	out_8(&regs->set_time, 0x1);
> +	out_8(&regs->set_time, 0x3);
> +	out_8(&regs->set_time, 0x1);
> +	out_8(&regs->set_time, 0x0);
> +}
> +
> +static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +	unsigned long now;
> +
> +	/*
> +	 * linux time is actual_time plus the offset saved in target_time
> +	 */
> +	now = in_be32(&regs->actual_time) + in_be32(&regs->target_time);
> +
> +	rtc_time_to_tm(now, tm);
> +
> +	/*
> +	 * update second minute hour registers
> +	 * so alarms will work
> +	 */
> +	mpc5121_rtc_update_smh(regs, tm);
> +
> +	return 0;
> +}
> +
> +static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +	int ret;
> +	unsigned long now;
> +
> +
> +	/*
> +	 * The actual_time register is read only so we write the offset
> +	 * between it and linux time to the target_time register.
> +	 */
> +	ret = rtc_tm_to_time(tm, &now);
> +	if (ret == 0)
> +		out_be32(&regs->target_time, now - in_be32(&regs->actual_time));
> +
> +	/*
> +	 * update second minute hour registers
> +	 * so alarms will work
> +	 */
> +	mpc5121_rtc_update_smh(regs, tm);
> +
> +	return 0;
> +}
> +
> +static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	*alarm = rtc->wkalarm;
> +
> +	alarm->pending = in_8(&regs->alm_status);
> +
> +	return 0;
> +}
> +
> +static int mpc5121_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	/*
> +	 * the alarm has no seconds so deal with it
> +	 */
> +	if (alarm->time.tm_sec) {
> +		alarm->time.tm_sec = 0;
> +		alarm->time.tm_min++;
> +		if (alarm->time.tm_min >= 60) {
> +			alarm->time.tm_min = 0;
> +			alarm->time.tm_hour++;
> +			if (alarm->time.tm_hour >= 24)
> +				alarm->time.tm_hour = 0;
> +		}
> +	}
> +
> +	alarm->time.tm_mday = -1;
> +	alarm->time.tm_mon = -1;
> +	alarm->time.tm_year = -1;
> +
> +	out_8(&regs->alm_min_set, alarm->time.tm_min);
> +	out_8(&regs->alm_hour_set, alarm->time.tm_hour);
> +
> +	out_8(&regs->alm_enable, alarm->enabled);
> +
> +	rtc->wkalarm = *alarm;
> +	return 0;
> +}
> +
> +static irqreturn_t mpc5121_rtc_handler(int irq, void *dev)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	if (in_8(&regs->int_alm)) {
> +		/* acknowledge and clear status */
> +		out_8(&regs->int_alm, 1);
> +		out_8(&regs->alm_status, 1);
> +
> +		rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static irqreturn_t mpc5121_rtc_handler_upd(int irq, void *dev)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	if (in_8(&regs->int_sec) && (in_8(&regs->int_enable) & 0x1)) {
> +		/* acknowledge */
> +		out_8(&regs->int_sec, 1);
> +
> +		rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF);
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static int mpc5121_rtc_ioctl(struct device *dev, unsigned int cmd,
> +							unsigned long arg)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	switch (cmd) {
> +		/* alarm interrupt */
> +	case RTC_AIE_ON:
> +		out_8(&regs->alm_enable, 1);
> +		rtc->wkalarm.enabled = 1;
> +		break;
> +	case RTC_AIE_OFF:
> +		out_8(&regs->alm_enable, 0);
> +		rtc->wkalarm.enabled = 0;
> +		break;
> +
> +		/* update interrupt */
> +	case RTC_UIE_ON:
> +		out_8(&regs->int_enable,
> +				(in_8(&regs->int_enable) & ~0x8) | 0x1);
> +		break;
> +	case RTC_UIE_OFF:
> +		out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
> +		break;
> +
> +		/* no periodic interrupts */
> +	case RTC_IRQP_READ:
> +	case RTC_IRQP_SET:
> +		return -ENOTTY;
> +
> +	default:
> +		return -ENOIOCTLCMD;
> +	}
> +	return 0;
> +}

 please implement the alarm/irq interface vie the ->ops
 structure.


> +
> +static const struct rtc_class_ops mpc5121_rtc_ops = {
> +	.read_time = mpc5121_rtc_read_time,
> +	.set_time = mpc5121_rtc_set_time,
> +	.read_alarm = mpc5121_rtc_read_alarm,
> +	.set_alarm = mpc5121_rtc_set_alarm,
> +	.ioctl = mpc5121_rtc_ioctl,
> +};
> +
> +static int __devinit mpc5121_rtc_probe(struct of_device *op,
> +					const struct of_device_id *match)
> +{
> +	struct mpc5121_rtc_data *rtc;
> +	int err = 0;
> +	u32 ka;
> +
> +	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
> +	if (!rtc) {
> +		err = -ENOMEM;
> +		goto out;
> +	}

 return -ENOMEM;

> +
> +	rtc->regs = of_iomap(op->node, 0);
> +
 
 extra empty line

> +	if (!rtc->regs) {
> +		printk(KERN_ERR "%s: couldn't map io space\n", __func__);
> +		err = -ENOSYS;
> +		goto out_free;
> +	}
> +
> +	device_init_wakeup(&op->dev, 1);
> +
> +	rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
> +						&mpc5121_rtc_ops, THIS_MODULE);
> +	if (IS_ERR(rtc->rtc)) {
> +		err = PTR_ERR(rtc->rtc);
> +		goto out_unmap;
> +	}
> +
> +	dev_set_drvdata(&op->dev, rtc);
> +
> +	rtc->irq = irq_of_parse_and_map(op->node, 1);
> +	err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
> +						"mpc5121-rtc", &op->dev);
> +	if (err) {
> +		printk(KERN_ERR "%s: could not request irq: %i\n",
> +							__func__, rtc->irq);
> +		goto out_dispose;
> +	}
> +
> +	rtc->irq_periodic = irq_of_parse_and_map(op->node, 0);
> +	err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
> +				 IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
> +	if (err) {
> +		printk(KERN_ERR "%s: could not request irq: %i\n",
> +						__func__, rtc->irq_periodic);
> +		goto out_dispose2;
> +	}
> +
> +	ka = in_be32(&rtc->regs->keep_alive);
> +	if (ka & 0x02) {
> +		printk(KERN_WARNING
> +			"mpc5121-rtc: Battery or oscillator failure!\n");
> +		out_be32(&rtc->regs->keep_alive, ka);
> +	}
> +
> +	goto out;
> +
> +out_dispose2:
> +	irq_dispose_mapping(rtc->irq_periodic);
> +	free_irq(rtc->irq, &op->dev);
> +out_dispose:
> +	irq_dispose_mapping(rtc->irq);
> +out_unmap:
> +	iounmap(rtc->regs);
> +out_free:
> +	kfree(rtc);
> +out:
> +	return err;
> +}
> +
> +static int __devexit mpc5121_rtc_remove(struct of_device *op)
> +{
> +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev);
> +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
> +
> +	/* disable interrupt, so there are no nasty surprises */
> +	out_8(&regs->alm_enable, 0);
> +	out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
> +
> +	rtc_device_unregister(rtc->rtc);
> +	iounmap(rtc->regs);
> +	free_irq(rtc->irq, &op->dev);
> +	free_irq(rtc->irq_periodic, &op->dev);
> +	irq_dispose_mapping(rtc->irq);
> +	irq_dispose_mapping(rtc->irq_periodic);
> +	dev_set_drvdata(&op->dev, NULL);
> +	kfree(rtc);
> +
> +	return 0;
> +}
> +
> +static struct of_device_id mpc5121_rtc_match[] = {
> +	{ .compatible = "fsl,mpc5121-rtc", },
> +	{},
> +};
> +
> +static struct of_platform_driver mpc5121_rtc_driver = {
> +	.owner = THIS_MODULE,
> +	.name = "mpc5121-rtc",
> +	.match_table = mpc5121_rtc_match,
> +	.probe = mpc5121_rtc_probe,
> +	.remove = mpc5121_rtc_remove,
> +};
> +
> +static int __init mpc5121_rtc_init(void)
> +{
> +	return of_register_platform_driver(&mpc5121_rtc_driver);
> +}
> +
> +static void __exit mpc5121_rtc_exit(void)
> +{
> +	of_unregister_platform_driver(&mpc5121_rtc_driver);
> +}
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("John Rigby <jrigby@freescale.com>");
> +
> +module_init(mpc5121_rtc_init);
> +module_exit(mpc5121_rtc_exit);
> -- 
> 1.5.6.3
> 


-- 

 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it

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

* Re: [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
  2010-01-19 20:24     ` Anatolij Gustschin
@ 2010-01-21 17:12         ` Grant Likely
  -1 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:12 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, Piotr Ziecik, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	John Rigby

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org> wrote:
> From: Piotr Ziecik <kosmo-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
>
>    - Update Kconfig for i2c-mpc driver.
>    - Enable I2C interrupts on MPC5121.
>
> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
> index f627001..84eeb25 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
>                }
>        }
>
> +       if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {

Rather than doing stuff like this with explicit compatible checks in
the probe hook, consider using the .data pointer in the of match
table.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* Re: [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
@ 2010-01-21 17:12         ` Grant Likely
  0 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:12 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: wd, dzu, linuxppc-dev, linux-i2c, Piotr Ziecik

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
>
> =A0 =A0- Update Kconfig for i2c-mpc driver.
> =A0 =A0- Enable I2C interrupts on MPC5121.
>
> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
> index f627001..84eeb25 100644
> --- a/drivers/i2c/busses/i2c-mpc.c
> +++ b/drivers/i2c/busses/i2c-mpc.c
> @@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device =
*op,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {

Rather than doing stuff like this with explicit compatible checks in
the probe hook, consider using the .data pointer in the of match
table.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* Re: [PATCH 07/11] dma: Add MPC512x DMA driver
  2010-01-19 20:24 ` [PATCH 07/11] dma: Add MPC512x DMA driver Anatolij Gustschin
@ 2010-01-21 17:22   ` Grant Likely
  2010-01-26  8:03     ` Anatolij Gustschin
  0 siblings, 1 reply; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:22 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: wd, dzu, linuxppc-dev, Dan Williams, Piotr Ziecik

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Piotr Ziecik <kosmo@semihalf.com>
>
> Adds initial version of MPC512x DMA driver.
> Only memory to memory transfers are currenly supported.

Comments below on brief review.  I've not looked at the code in-depth.

> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: John Rigby <jcrigby@gmail.com>
> ---
> =A0drivers/dma/Kconfig =A0 =A0 =A0 | =A0 =A07 +
> =A0drivers/dma/Makefile =A0 =A0 =A0| =A0 =A01 +
> =A0drivers/dma/mpc512x_dma.c | =A0636 +++++++++++++++++++++++++++++++++++=
++++++++++
> =A0drivers/dma/mpc512x_dma.h | =A0192 ++++++++++++++

Unless the stuff in the .h file is used by other .c files, it really
belongs in mpc512x_dma.c

> +static int __init mpc_dma_probe(struct of_device *op,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 const struct of_device_id *match)

__devinit

> +static void __exit mpc_dma_remove(struct of_device *op)

__devexit

> +{
> + =A0 =A0 =A0 struct device *dev =3D &op->dev;
> + =A0 =A0 =A0 struct mpc_dma *mdma =3D dev_get_drvdata(dev);
> +
> + =A0 =A0 =A0 devm_free_irq(dev, mdma->irq, mdma);
> +}

No unregistration of the dma device?  No unmapping?  No kfree()?

> +
> +static struct of_device_id mpc_dma_match[] =3D {
> + =A0 =A0 =A0 { .compatible =3D "fsl,mpc5121-dma", },
> + =A0 =A0 =A0 {},
> +};
> +
> +static struct of_platform_driver mpc_dma_driver =3D {
> + =A0 =A0 =A0 .match_table =A0 =A0=3D mpc_dma_match,
> + =A0 =A0 =A0 .probe =A0 =A0 =A0 =A0 =A0=3D mpc_dma_probe,
> + =A0 =A0 =A0 .remove =A0 =A0 =A0 =A0 =3D __exit_p(mpc_dma_remove),

__devexit_p()

> + =A0 =A0 =A0 .driver =A0 =A0 =A0 =A0 =3D {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .name =A0 =3D DRV_NAME,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .owner =A0=3D THIS_MODULE,
> + =A0 =A0 =A0 },
> +};
> +
> +static int __init mpc_dma_init(void)
> +{
> + =A0 =A0 =A0 return of_register_platform_driver(&mpc_dma_driver);
> +}
> +module_init(mpc_dma_init);
> +
> +static void __exit mpc_dma_exit(void)
> +{
> + =A0 =A0 =A0 of_unregister_platform_driver(&mpc_dma_driver);
> +}
> +module_exit(mpc_dma_exit);
> +
> +/* MODULE API */

Meaningless comment.

> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");

Thanks,
g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
  2010-01-19 20:24 ` [PATCH 08/11] powerpc/mpc5121: add USB host support Anatolij Gustschin
@ 2010-01-21 17:43       ` Grant Likely
  0 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:43 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, Bruce Schmid, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org> wrote:
> Platform specific code for MPC5121 USB Host support.
> MPC5121 Rev 2.0 silicon EHCI registers are big endian.
> Add appropriate support by specifying "big-endian-regs"
> property in device tree node for USB controller. Also
> allow specifying DRVVBUS and PWR_FAULT signal polarity
> of MPC5121 internal PHY using "invert-drvvbus" and
> "invert-pwr-fault" properties.
>
> Signed-off-by: Bruce Schmid <duck-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> Signed-off-by: Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org>
> Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> Note that EHCI FSL driver extention in this patch
> applies on top of the following two patches (in the
> linux-next tree):
>
> commit 23c3314b88f91db51bd198ed92e34cffb67788dd
> Author: Anton Vorontsov <avorontsov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
> Date:   Mon Dec 14 18:41:12 2009 +0300
>
>    USB: ehci-fsl: Add power management support
>
> commit bf4bf2d9f646eb0cc531d213a13ffcedf9d6785f
> Author: Anton Vorontsov <avorontsov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
> Date:   Mon Dec 14 18:41:05 2009 +0300
>
>    USB: ehci-fsl: Fix sparse warnings
>
>  Documentation/powerpc/dts-bindings/fsl/usb.txt |    8 ++
>  arch/powerpc/platforms/512x/Kconfig            |    6 +
>  arch/powerpc/platforms/512x/Makefile           |    2 +-
>  arch/powerpc/platforms/512x/mpc5121_ads.c      |    1 +
>  arch/powerpc/platforms/512x/mpc5121_usb.c      |  117 ++++++++++++++++++++++++
>  arch/powerpc/platforms/512x/mpc512x.h          |    1 +
>  arch/powerpc/sysdev/fsl_soc.c                  |   10 ++
>  arch/powerpc/sysdev/fsl_soc.h                  |    9 ++
>  drivers/usb/host/ehci-fsl.c                    |  116 +++++++++++++++++-------
>  drivers/usb/host/ehci-fsl.h                    |   19 ++++-
>  drivers/usb/host/ehci-mem.c                    |    2 +-
>  include/linux/fsl_devices.h                    |   10 ++
>  12 files changed, 265 insertions(+), 36 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/mpc5121_usb.c
>
> diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> index b001524..9050154 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> @@ -33,6 +33,14 @@ Recommended properties :
>  - interrupt-parent : the phandle for the interrupt controller that
>    services interrupts for this device.
>
> +Optional properties :

> + - big-endian-regs : boolean; if defined, indicates the USB host
> +   controller registers format is big endian.

Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
the match table and use the .data pointer for setting device specific
quirks.

> + - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
> +   power polarity of internal PHY signal DRVVBUS is inverted.
> + - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
> +   PWR_FAULT signal polarity is inverted.

These are also characteristics of the chip, not the board, right?  If
so then these also can be determined implicitly by the compatible
value.

Finally, these are all freescale specific properties.  If you still
need them, then prefix the property names with 'fsl,'

> +
>  Example multi port host USB controller device node :
>        usb@22000 {
>                compatible = "fsl-usb2-mph";
> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
> index 4dac9b0..3fec738 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -9,6 +9,9 @@ config PPC_MPC512x
>  config PPC_MPC5121
>        bool
>        select PPC_MPC512x
> +       select USB_ARCH_HAS_EHCI
> +       select USB_EHCI_BIG_ENDIAN_DESC
> +       select USB_EHCI_BIG_ENDIAN_MMIO
>
>  config MPC5121_ADS
>        bool "Freescale MPC5121E ADS"
> @@ -30,3 +33,6 @@ config MPC5121_GENERIC
>
>          Compatible boards include:  Protonic LVT base boards (ZANMCU
>          and VICVT2).
> +
> +config USB_FSL_BIG_ENDIAN_MMIO
> +       bool

What's this for?

> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
> index 90be2f5..49adabc 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,6 +1,6 @@
>  #
>  # Makefile for the Freescale PowerPC 512x linux kernel.
>  #
> -obj-y                          += clock.o mpc512x_shared.o
> +obj-y                          += clock.o mpc512x_shared.o mpc5121_usb.o
>  obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
>  obj-$(CONFIG_MPC5121_GENERIC)  += mpc5121_generic.o
> diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
> index 2f40404..a497c14 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_ads.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
> @@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
>        for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
>                mpc83xx_add_bridge(np);
>  #endif
> +       mpc5121_usb_init();
>  }
>
>  static void __init mpc5121_ads_init_IRQ(void)
> diff --git a/arch/powerpc/platforms/512x/mpc5121_usb.c b/arch/powerpc/platforms/512x/mpc5121_usb.c
> new file mode 100644
> index 0000000..7b45651
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/mpc5121_usb.c
> @@ -0,0 +1,117 @@
> +/*
> + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Bruce Schmid <duck-KZfg59tc24xl57MIdRCFDg@public.gmane.org>, Tue Oct 2 2007
> + *
> + * Description:
> + * MPC5121 USB platform-specific routines
> + *
> + * This is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/stddef.h>
> +#include <linux/of_platform.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#define USBGENCTRL             0x200           /* NOTE: big endian */
> +#define GC_WU_INT_CLR          (1 << 5)        /* Wakeup int clear */
> +#define GC_ULPI_SEL            (1 << 4)        /* ULPI i/f select (usb0 only)*/
> +#define GC_PPP                 (1 << 3)        /* Inv. Port Power Polarity */
> +#define GC_PFP                 (1 << 2)        /* Inv. Power Fault Polarity */
> +#define GC_WU_ULPI_EN          (1 << 1)        /* Wakeup on ULPI event */
> +#define GC_WU_IE               (1 << 1)        /* Wakeup interrupt enable */
> +
> +#define ISIPHYCTRL             0x204           /* NOTE: big endian */
> +#define PHYCTRL_PHYE           (1 << 4)        /* On-chip UTMI PHY enable */
> +#define PHYCTRL_BSENH          (1 << 3)        /* Bit Stuff Enable High */
> +#define PHYCTRL_BSEN           (1 << 2)        /* Bit Stuff Enable */
> +#define PHYCTRL_LSFE           (1 << 1)        /* Line State Filter Enable */
> +#define PHYCTRL_PXE            (1 << 0)        /* PHY oscillator enable */
> +
> +static struct clk *dr_clk1;
> +static struct clk *dr_clk2;
> +static int dr_used;
> +
> +static int mpc5121_usb_dr_init(struct platform_device *pdev)
> +{
> +       struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
> +
> +       /* enable the clock if we haven't already */
> +       if (!dr_used) {
> +               dr_clk1 = clk_get(&pdev->dev, "usb1_clk");
> +               if (IS_ERR(dr_clk1)) {
> +                       dev_err(&pdev->dev, "usb1: clk_get failed\n");
> +                       return -ENODEV;
> +               }
> +               clk_enable(dr_clk1);
> +               dr_clk2 = clk_get(&pdev->dev, "usb2_clk");
> +               if (IS_ERR(dr_clk2)) {
> +                       dev_err(&pdev->dev, "usb2: clk_get failed\n");
> +                       return -ENODEV;
> +               }
> +               clk_enable(dr_clk2);
> +       }
> +       dr_used++;
> +
> +       pdata->big_endian_desc = 1;
> +       pdata->es = 1;
> +
> +       if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
> +               struct device_node *np;
> +               u32 reg = 0;
> +
> +               np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-usb2-dr");
> +               if (!np) {
> +                       pr_err("No USB node found\n");
> +                       return -ENODEV;
> +               }
> +
> +               if (of_get_property(np, "invert-drvvbus", NULL))
> +                       reg |= GC_PPP;
> +
> +               if (of_get_property(np, "invert-pwr-fault", NULL))
> +                       reg |= GC_PFP;
> +
> +               of_node_put(np);
> +               out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
> +               out_be32(pdata->regs + USBGENCTRL, reg);
> +       }
> +       return 0;
> +}
> +
> +static void mpc5121_usb_dr_uninit(struct platform_device *pdev)
> +{
> +       struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
> +
> +       pdata->regs = NULL;
> +
> +       dr_used--;
> +       if (!dr_used) {
> +               clk_disable(dr_clk1);
> +               clk_disable(dr_clk2);
> +               clk_put(dr_clk1);
> +               clk_put(dr_clk2);
> +               dr_clk1 = NULL;
> +               dr_clk2 = NULL;
> +       }
> +}
> +
> +void mpc5121_usb_init(void)
> +{
> +       fsl_platform_usb_ops.init = mpc5121_usb_dr_init;
> +       fsl_platform_usb_ops.uninit = mpc5121_usb_dr_uninit;
> +}

Hmmm... I'm not fond of using the fsl_soc.c stuff instead of
drivers/usb/host/ehci-ppc-of.c, but I understand why you're doing it.
Given the constraints, I guess this is okay, but this USB common code
needs some refactoring (I'm not asking you to do it).

> diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
> index c38875c..e92a282 100644
> --- a/arch/powerpc/platforms/512x/mpc512x.h
> +++ b/arch/powerpc/platforms/512x/mpc512x.h
> @@ -13,5 +13,6 @@
>  #define __MPC512X_H__
>  extern void __init mpc512x_init_IRQ(void);
>  extern void mpc512x_restart(char *cmd);
> +extern void mpc5121_usb_init(void);
>  void __init mpc512x_declare_of_platform_devices(void);
>  #endif                         /* __MPC512X_H__ */
> diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
> index b91f7ac..19a455d 100644
> --- a/arch/powerpc/sysdev/fsl_soc.c
> +++ b/arch/powerpc/sysdev/fsl_soc.c
> @@ -209,6 +209,9 @@ static int __init of_add_fixed_phys(void)
>  arch_initcall(of_add_fixed_phys);
>  #endif /* CONFIG_FIXED_PHY */
>
> +struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +EXPORT_SYMBOL(fsl_platform_usb_ops);
> +
>  static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
>  {
>        if (!phy_type)
> @@ -267,6 +270,9 @@ static int __init fsl_usb_of_init(void)
>                if (prop)
>                        usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
>
> +               if (of_get_property(np, "big-endian-regs", NULL))
> +                       usb_data.big_endian_mmio = 1;
> +
>                prop = of_get_property(np, "phy_type", NULL);
>                usb_data.phy_mode = determine_usb_phy(prop);
>
> @@ -332,9 +338,13 @@ static int __init fsl_usb_of_init(void)
>                        ret = -EINVAL;
>                        goto err;
>                }
> +               if (of_get_property(np, "big-endian-regs", NULL))
> +                       usb_data.big_endian_mmio = 1;
>
>                prop = of_get_property(np, "phy_type", NULL);
>                usb_data.phy_mode = determine_usb_phy(prop);
> +               usb_data.platform_init = fsl_platform_usb_ops.init;
> +               usb_data.platform_uninit = fsl_platform_usb_ops.uninit;
>
>                if (usb_dev_dr_host) {
>                        usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
> diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
> index 42381bb..19754be 100644
> --- a/arch/powerpc/sysdev/fsl_soc.h
> +++ b/arch/powerpc/sysdev/fsl_soc.h
> @@ -35,5 +35,14 @@ struct platform_diu_data_ops {
>  extern struct platform_diu_data_ops diu_ops;
>  #endif
>
> +struct platform_device;
> +
> +struct fsl_platform_usb_ops {
> +       int (*init)(struct platform_device *);
> +       void (*uninit)(struct platform_device *);
> +};
> +
> +extern struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +
>  #endif
>  #endif
> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
> index 0e26aa1..c4ec00c 100644
> --- a/drivers/usb/host/ehci-fsl.c
> +++ b/drivers/usb/host/ehci-fsl.c
> @@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
>        pr_debug("initializing FSL-SOC USB Controller\n");
>
>        /* Need platform data for setup */
> -       pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data;
> +       pdata = pdev->dev.platform_data;
>        if (!pdata) {
>                dev_err(&pdev->dev,
>                        "No platform data for %s.\n", dev_name(&pdev->dev));
> @@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
>                return -ENODEV;
>        }
>
> -       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> -       if (!res) {
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0) {
>                dev_err(&pdev->dev,
>                        "Found HC with no IRQ. Check %s setup!\n",
>                        dev_name(&pdev->dev));
>                return -ENODEV;
>        }
> -       irq = res->start;

Put this hunk in a separate patch.

>
>        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
>        if (!hcd) {
> @@ -116,13 +115,39 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
>                goto err3;
>        }
>
> -       /* Enable USB controller */
> -       temp = in_be32(hcd->regs + 0x500);
> -       out_be32(hcd->regs + 0x500, temp | 0x4);
> +       pdata->regs = hcd->regs;
> +
> +       /*
> +        * do platform specific init: check the clock, grab/config pins, etc.
> +        */
> +       if (pdata->platform_init && pdata->platform_init(pdev)) {
> +               retval = -ENODEV;
> +               goto err3;
> +       }
> +
> +       /*
> +        * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
> +        * flag for 83xx or 8536 system interface registers.
> +        */
> +       if (pdata->big_endian_mmio)
> +               temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
> +       else
> +               temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
> +
> +       if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
> +               pdata->have_sysif_regs = 1;
> +
> +       /* Enable USB controller, 83xx or 8536 */
> +       if (pdata->have_sysif_regs)
> +               setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
>
>        /* Set to Host mode */
> -       temp = in_le32(hcd->regs + 0x1a8);
> -       out_le32(hcd->regs + 0x1a8, temp | 0x3);
> +       if (pdata->big_endian_mmio) {
> +               setbits32(hcd->regs + FSL_SOC_USB_USBMODE, USBMODE_CM_HOST);
> +       } else {
> +               clrsetbits_le32(hcd->regs + FSL_SOC_USB_USBMODE,
> +                               USBMODE_CM_MASK, USBMODE_CM_HOST);
> +       }
>
>        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
>        if (retval != 0)
> @@ -137,6 +162,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
>        usb_put_hcd(hcd);
>       err1:
>        dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
> +       if (pdata->platform_uninit)
> +               pdata->platform_uninit(pdev);
>        return retval;
>  }
>
> @@ -154,17 +181,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
>  static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
>                               struct platform_device *pdev)
>  {
> +       struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
> +
>        usb_remove_hcd(hcd);
> +
> +       /*
> +        * do platform specific un-initialization:
> +        * release iomux pins, disable clock, etc.
> +        */
> +       if (pdata->platform_uninit)
> +               pdata->platform_uninit(pdev);
>        iounmap(hcd->regs);
>        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
>        usb_put_hcd(hcd);
>  }
>
> -static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
> -                             enum fsl_usb2_phy_modes phy_mode,
> -                             unsigned int port_offset)
> +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
> +                              enum fsl_usb2_phy_modes phy_mode,
> +                              unsigned int port_offset)
>  {
> -       u32 portsc = 0;
> +       u32 portsc;
> +
> +       portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
> +       portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
> +
>        switch (phy_mode) {
>        case FSL_USB2_PHY_ULPI:
>                portsc |= PORT_PTS_ULPI;
> @@ -184,20 +224,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
>        ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
>  }
>
> -static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> +static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
>  {
> -       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> +       struct usb_hcd *hcd = ehci_to_hcd(ehci);
>        struct fsl_usb2_platform_data *pdata;
>        void __iomem *non_ehci = hcd->regs;
> -       u32 temp;
> +       u32 tmp;
> +
> +       pdata = hcd->self.controller->platform_data;
>
> -       pdata =
> -           (struct fsl_usb2_platform_data *)hcd->self.controller->
> -           platform_data;
>        /* Enable PHY interface in the control reg. */
> -       temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
> -       out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
> -       out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
> +       if (pdata->have_sysif_regs) {
> +               tmp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
> +               out_be32(non_ehci + FSL_SOC_USB_CTRL, tmp | 0x00000004);
> +               out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
> +       }
>
>  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
>        /*
> @@ -214,7 +255,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
>
>        if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
>                        (pdata->operating_mode == FSL_USB2_DR_OTG))
> -               mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
> +               ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
>
>        if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
>                unsigned int chip, rev, svr;
> @@ -228,27 +269,31 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
>                        ehci->has_fsl_port_bug = 1;
>
>                if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
> -                       mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
> +                       ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
>                if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
> -                       mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
> +                       ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
>        }
>
>        /* put controller in host mode. */
> -       ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
> +       tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
> +       ehci_writel(ehci, tmp, non_ehci + FSL_SOC_USB_USBMODE);
> +
> +       if (pdata->have_sysif_regs) {
>  #ifdef CONFIG_PPC_85xx
> -       out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> -       out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> +               out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> +               out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
>  #else
> -       out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> -       out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> +               out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> +               out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
>  #endif
> -       out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> +               out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> +       }
>  }

Unrelated whitespace changes.  Put in separate patch.

>
>  /* called after powerup, by probe or system-pm "wakeup" */
>  static int ehci_fsl_reinit(struct ehci_hcd *ehci)
>  {
> -       mpc83xx_usb_setup(ehci_to_hcd(ehci));
> +       ehci_fsl_usb_setup(ehci);
>        ehci_port_power(ehci, 0);
>
>        return 0;
> @@ -259,6 +304,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
>  {
>        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>        int retval;
> +       struct fsl_usb2_platform_data *pdata;
> +
> +       pdata = hcd->self.controller->platform_data;
> +       ehci->big_endian_desc = pdata->big_endian_desc;
> +       ehci->big_endian_mmio = pdata->big_endian_mmio;
>
>        /* EHCI registers start at offset 0x100 */
>        ehci->caps = hcd->regs + 0x100;
> @@ -369,7 +419,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
>         * generic hardware linkage
>         */
>        .irq = ehci_irq,
> -       .flags = HCD_USB2,
> +       .flags = HCD_USB2 | HCD_MEMORY,
>
>        /*
>         * basic lifecycle operations
> diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
> index b5e59db..3525bb4 100644
> --- a/drivers/usb/host/ehci-fsl.h
> +++ b/drivers/usb/host/ehci-fsl.h
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2005 freescale semiconductor
> +/* Copyright (C) 2005-2009 Freescale Semiconductor, Inc. All rights reserved.
>  * Copyright (c) 2005 MontaVista Software
>  *
>  * This program is free software; you can redistribute  it and/or modify it
> @@ -19,6 +19,11 @@
>  #define _EHCI_FSL_H
>
>  /* offsets for the non-ehci registers in the FSL SOC USB controller */
> +#define FSL_SOC_USB_ID         0x0
> +#define ID_MSK                 0x3f
> +#define NID_MSK                        0x3f00
> +#define FSL_SOC_USB_SBUSCFG    0x90
> +#define FSL_SOC_USB_BURSTSIZE  0x160
>  #define FSL_SOC_USB_ULPIVP     0x170
>  #define FSL_SOC_USB_PORTSC1    0x184
>  #define PORT_PTS_MSK           (3<<30)
> @@ -26,8 +31,20 @@
>  #define PORT_PTS_ULPI          (2<<30)
>  #define        PORT_PTS_SERIAL         (3<<30)
>  #define PORT_PTS_PTW           (1<<28)
> +#define PORT_PTS_PHCD          (1<<23)
>  #define FSL_SOC_USB_PORTSC2    0x188
>  #define FSL_SOC_USB_USBMODE    0x1a8
> +#define USBMODE_CM_MASK                (3 << 0)        /* controller mode mask */
> +#define USBMODE_CM_HOST                (3 << 0)        /* controller mode: host */
> +#define USBMODE_ES             (1 << 2)        /* (Big) Endian Select */
> +
> +#define FSL_SOC_USB_USBGENCTRL         0x200
> +#define USBGENCTRL_PPP                 (1 << 3)
> +#define USBGENCTRL_PFP         (1 << 2)
> +#define FSL_SOC_USB_ISIPHYCTRL 0x204
> +#define ISIPHYCTRL_PXE         (1)
> +#define ISIPHYCTRL_PHYE                (1 << 4)
> +
>  #define FSL_SOC_USB_SNOOP1     0x400   /* NOTE: big-endian */
>  #define FSL_SOC_USB_SNOOP2     0x404   /* NOTE: big-endian */
>  #define FSL_SOC_USB_AGECNTTHRSH        0x408   /* NOTE: big-endian */
> diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
> index aeda96e..1e7e004 100644
> --- a/drivers/usb/host/ehci-mem.c
> +++ b/drivers/usb/host/ehci-mem.c
> @@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
>  {
>        memset (qtd, 0, sizeof *qtd);
>        qtd->qtd_dma = dma;
> -       qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
> +       qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
>        qtd->hw_next = EHCI_LIST_END(ehci);
>        qtd->hw_alt_next = EHCI_LIST_END(ehci);
>        INIT_LIST_HEAD (&qtd->qtd_list);
> diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
> index 28e33fe..dfe603f 100644
> --- a/include/linux/fsl_devices.h
> +++ b/include/linux/fsl_devices.h
> @@ -58,11 +58,21 @@ enum fsl_usb2_phy_modes {
>        FSL_USB2_PHY_SERIAL,
>  };
>
> +struct platform_device;
>  struct fsl_usb2_platform_data {
>        /* board specific information */
>        enum fsl_usb2_operating_modes   operating_mode;
>        enum fsl_usb2_phy_modes         phy_mode;
>        unsigned int                    port_enables;
> +
> +       char                            *name;          /* pretty print */
> +       int (*platform_init) (struct platform_device *);
> +       void (*platform_uninit) (struct platform_device *);
> +       void __iomem                    *regs;  /* ioremap'd register base */
> +       unsigned                        big_endian_mmio:1;
> +       unsigned                        big_endian_desc:1;
> +       unsigned                        es:1;           /* need USBMODE:ES */
> +       unsigned                        have_sysif_regs:1;
>  };

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--
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] 62+ messages in thread

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
@ 2010-01-21 17:43       ` Grant Likely
  0 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:43 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: wd, dzu, devicetree-discuss, linux-usb, linuxppc-dev, Bruce Schmid

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> Platform specific code for MPC5121 USB Host support.
> MPC5121 Rev 2.0 silicon EHCI registers are big endian.
> Add appropriate support by specifying "big-endian-regs"
> property in device tree node for USB controller. Also
> allow specifying DRVVBUS and PWR_FAULT signal polarity
> of MPC5121 internal PHY using "invert-drvvbus" and
> "invert-pwr-fault" properties.
>
> Signed-off-by: Bruce Schmid <duck@freescale.com>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: linux-usb@vger.kernel.org
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
> Note that EHCI FSL driver extention in this patch
> applies on top of the following two patches (in the
> linux-next tree):
>
> commit 23c3314b88f91db51bd198ed92e34cffb67788dd
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: =A0 Mon Dec 14 18:41:12 2009 +0300
>
> =A0 =A0USB: ehci-fsl: Add power management support
>
> commit bf4bf2d9f646eb0cc531d213a13ffcedf9d6785f
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: =A0 Mon Dec 14 18:41:05 2009 +0300
>
> =A0 =A0USB: ehci-fsl: Fix sparse warnings
>
> =A0Documentation/powerpc/dts-bindings/fsl/usb.txt | =A0 =A08 ++
> =A0arch/powerpc/platforms/512x/Kconfig =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A06 =
+
> =A0arch/powerpc/platforms/512x/Makefile =A0 =A0 =A0 =A0 =A0 | =A0 =A02 +-
> =A0arch/powerpc/platforms/512x/mpc5121_ads.c =A0 =A0 =A0| =A0 =A01 +
> =A0arch/powerpc/platforms/512x/mpc5121_usb.c =A0 =A0 =A0| =A0117 ++++++++=
++++++++++++++++
> =A0arch/powerpc/platforms/512x/mpc512x.h =A0 =A0 =A0 =A0 =A0| =A0 =A01 +
> =A0arch/powerpc/sysdev/fsl_soc.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0=
 10 ++
> =A0arch/powerpc/sysdev/fsl_soc.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0=
 =A09 ++
> =A0drivers/usb/host/ehci-fsl.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0116 +++++++++++++++++-------
> =A0drivers/usb/host/ehci-fsl.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 19 ++++-
> =A0drivers/usb/host/ehci-mem.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 =A02 +-
> =A0include/linux/fsl_devices.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 10 ++
> =A012 files changed, 265 insertions(+), 36 deletions(-)
> =A0create mode 100644 arch/powerpc/platforms/512x/mpc5121_usb.c
>
> diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentati=
on/powerpc/dts-bindings/fsl/usb.txt
> index b001524..9050154 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> @@ -33,6 +33,14 @@ Recommended properties :
> =A0- interrupt-parent : the phandle for the interrupt controller that
> =A0 =A0services interrupts for this device.
>
> +Optional properties :

> + - big-endian-regs : boolean; if defined, indicates the USB host
> + =A0 controller registers format is big endian.

Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
the match table and use the .data pointer for setting device specific
quirks.

> + - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
> + =A0 power polarity of internal PHY signal DRVVBUS is inverted.
> + - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
> + =A0 PWR_FAULT signal polarity is inverted.

These are also characteristics of the chip, not the board, right?  If
so then these also can be determined implicitly by the compatible
value.

Finally, these are all freescale specific properties.  If you still
need them, then prefix the property names with 'fsl,'

> +
> =A0Example multi port host USB controller device node :
> =A0 =A0 =A0 =A0usb@22000 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "fsl-usb2-mph";
> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms=
/512x/Kconfig
> index 4dac9b0..3fec738 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -9,6 +9,9 @@ config PPC_MPC512x
> =A0config PPC_MPC5121
> =A0 =A0 =A0 =A0bool
> =A0 =A0 =A0 =A0select PPC_MPC512x
> + =A0 =A0 =A0 select USB_ARCH_HAS_EHCI
> + =A0 =A0 =A0 select USB_EHCI_BIG_ENDIAN_DESC
> + =A0 =A0 =A0 select USB_EHCI_BIG_ENDIAN_MMIO
>
> =A0config MPC5121_ADS
> =A0 =A0 =A0 =A0bool "Freescale MPC5121E ADS"
> @@ -30,3 +33,6 @@ config MPC5121_GENERIC
>
> =A0 =A0 =A0 =A0 =A0Compatible boards include: =A0Protonic LVT base boards=
 (ZANMCU
> =A0 =A0 =A0 =A0 =A0and VICVT2).
> +
> +config USB_FSL_BIG_ENDIAN_MMIO
> + =A0 =A0 =A0 bool

What's this for?

> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platform=
s/512x/Makefile
> index 90be2f5..49adabc 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,6 +1,6 @@
> =A0#
> =A0# Makefile for the Freescale PowerPC 512x linux kernel.
> =A0#
> -obj-y =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0+=3D clock.o mp=
c512x_shared.o
> +obj-y =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0+=3D clock.o mp=
c512x_shared.o mpc5121_usb.o
> =A0obj-$(CONFIG_MPC5121_ADS) =A0 =A0 =A0+=3D mpc5121_ads.o mpc5121_ads_cp=
ld.o
> =A0obj-$(CONFIG_MPC5121_GENERIC) =A0+=3D mpc5121_generic.o
> diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/pla=
tforms/512x/mpc5121_ads.c
> index 2f40404..a497c14 100644
> --- a/arch/powerpc/platforms/512x/mpc5121_ads.c
> +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
> @@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
> =A0 =A0 =A0 =A0for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mpc83xx_add_bridge(np);
> =A0#endif
> + =A0 =A0 =A0 mpc5121_usb_init();
> =A0}
>
> =A0static void __init mpc5121_ads_init_IRQ(void)
> diff --git a/arch/powerpc/platforms/512x/mpc5121_usb.c b/arch/powerpc/pla=
tforms/512x/mpc5121_usb.c
> new file mode 100644
> index 0000000..7b45651
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/mpc5121_usb.c
> @@ -0,0 +1,117 @@
> +/*
> + * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights rese=
rved.
> + *
> + * Author: Bruce Schmid <duck@freescale.com>, Tue Oct 2 2007
> + *
> + * Description:
> + * MPC5121 USB platform-specific routines
> + *
> + * This is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/stddef.h>
> +#include <linux/of_platform.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#define USBGENCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x200 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define GC_WU_INT_CLR =A0 =A0 =A0 =A0 =A0(1 << 5) =A0 =A0 =A0 =A0/* Wake=
up int clear */
> +#define GC_ULPI_SEL =A0 =A0 =A0 =A0 =A0 =A0(1 << 4) =A0 =A0 =A0 =A0/* UL=
PI i/f select (usb0 only)*/
> +#define GC_PPP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3) =A0 =A0 =A0 =A0/=
* Inv. Port Power Polarity */
> +#define GC_PFP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/=
* Inv. Power Fault Polarity */
> +#define GC_WU_ULPI_EN =A0 =A0 =A0 =A0 =A0(1 << 1) =A0 =A0 =A0 =A0/* Wake=
up on ULPI event */
> +#define GC_WU_IE =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* =
Wakeup interrupt enable */
> +
> +#define ISIPHYCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x204 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define PHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 (1 << 4) =A0 =A0 =A0 =A0/* On-c=
hip UTMI PHY enable */
> +#define PHYCTRL_BSENH =A0 =A0 =A0 =A0 =A0(1 << 3) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable High */
> +#define PHYCTRL_BSEN =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable */
> +#define PHYCTRL_LSFE =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* Line=
 State Filter Enable */
> +#define PHYCTRL_PXE =A0 =A0 =A0 =A0 =A0 =A0(1 << 0) =A0 =A0 =A0 =A0/* PH=
Y oscillator enable */
> +
> +static struct clk *dr_clk1;
> +static struct clk *dr_clk2;
> +static int dr_used;
> +
> +static int mpc5121_usb_dr_init(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> + =A0 =A0 =A0 /* enable the clock if we haven't already */
> + =A0 =A0 =A0 if (!dr_used) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk1 =3D clk_get(&pdev->dev, "usb1_clk")=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (IS_ERR(dr_clk1)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&pdev->dev, "usb1: =
clk_get failed\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_enable(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk2 =3D clk_get(&pdev->dev, "usb2_clk")=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (IS_ERR(dr_clk2)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&pdev->dev, "usb2: =
clk_get failed\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_enable(dr_clk2);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 dr_used++;
> +
> + =A0 =A0 =A0 pdata->big_endian_desc =3D 1;
> + =A0 =A0 =A0 pdata->es =3D 1;
> +
> + =A0 =A0 =A0 if (pdata->phy_mode =3D=3D FSL_USB2_PHY_UTMI_WIDE) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct device_node *np;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 reg =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, =
"fsl,mpc5121-usb2-dr");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("No USB node found\n=
");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "invert-drvvbus", N=
ULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PPP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "invert-pwr-fault",=
 NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PFP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_=
PHYE | PHYCTRL_PXE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + USBGENCTRL, reg);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static void mpc5121_usb_dr_uninit(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> + =A0 =A0 =A0 pdata->regs =3D NULL;
> +
> + =A0 =A0 =A0 dr_used--;
> + =A0 =A0 =A0 if (!dr_used) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_disable(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_disable(dr_clk2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_put(dr_clk1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_put(dr_clk2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk1 =3D NULL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_clk2 =3D NULL;
> + =A0 =A0 =A0 }
> +}
> +
> +void mpc5121_usb_init(void)
> +{
> + =A0 =A0 =A0 fsl_platform_usb_ops.init =3D mpc5121_usb_dr_init;
> + =A0 =A0 =A0 fsl_platform_usb_ops.uninit =3D mpc5121_usb_dr_uninit;
> +}

Hmmm... I'm not fond of using the fsl_soc.c stuff instead of
drivers/usb/host/ehci-ppc-of.c, but I understand why you're doing it.
Given the constraints, I guess this is okay, but this USB common code
needs some refactoring (I'm not asking you to do it).

> diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platfor=
ms/512x/mpc512x.h
> index c38875c..e92a282 100644
> --- a/arch/powerpc/platforms/512x/mpc512x.h
> +++ b/arch/powerpc/platforms/512x/mpc512x.h
> @@ -13,5 +13,6 @@
> =A0#define __MPC512X_H__
> =A0extern void __init mpc512x_init_IRQ(void);
> =A0extern void mpc512x_restart(char *cmd);
> +extern void mpc5121_usb_init(void);
> =A0void __init mpc512x_declare_of_platform_devices(void);
> =A0#endif =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* __MPC512X_H_=
_ */
> diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.=
c
> index b91f7ac..19a455d 100644
> --- a/arch/powerpc/sysdev/fsl_soc.c
> +++ b/arch/powerpc/sysdev/fsl_soc.c
> @@ -209,6 +209,9 @@ static int __init of_add_fixed_phys(void)
> =A0arch_initcall(of_add_fixed_phys);
> =A0#endif /* CONFIG_FIXED_PHY */
>
> +struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +EXPORT_SYMBOL(fsl_platform_usb_ops);
> +
> =A0static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
> =A0{
> =A0 =A0 =A0 =A0if (!phy_type)
> @@ -267,6 +270,9 @@ static int __init fsl_usb_of_init(void)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (prop)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.port_enables |=3D=
 FSL_USB2_PORT1_ENABLED;
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "big-endian-regs", =
NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.big_endian_mmio =
=3D 1;
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prop =3D of_get_property(np, "phy_type", N=
ULL);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.phy_mode =3D determine_usb_phy(pr=
op);
>
> @@ -332,9 +338,13 @@ static int __init fsl_usb_of_init(void)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D -EINVAL;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto err;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "big-endian-regs", =
NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.big_endian_mmio =
=3D 1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prop =3D of_get_property(np, "phy_type", N=
ULL);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_data.phy_mode =3D determine_usb_phy(pr=
op);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.platform_init =3D fsl_platform_usb=
_ops.init;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_data.platform_uninit =3D fsl_platform_u=
sb_ops.uninit;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (usb_dev_dr_host) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usb_dev_dr_host->dev.coher=
ent_dma_mask =3D 0xffffffffUL;
> diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.=
h
> index 42381bb..19754be 100644
> --- a/arch/powerpc/sysdev/fsl_soc.h
> +++ b/arch/powerpc/sysdev/fsl_soc.h
> @@ -35,5 +35,14 @@ struct platform_diu_data_ops {
> =A0extern struct platform_diu_data_ops diu_ops;
> =A0#endif
>
> +struct platform_device;
> +
> +struct fsl_platform_usb_ops {
> + =A0 =A0 =A0 int (*init)(struct platform_device *);
> + =A0 =A0 =A0 void (*uninit)(struct platform_device *);
> +};
> +
> +extern struct fsl_platform_usb_ops fsl_platform_usb_ops;
> +
> =A0#endif
> =A0#endif
> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
> index 0e26aa1..c4ec00c 100644
> --- a/drivers/usb/host/ehci-fsl.c
> +++ b/drivers/usb/host/ehci-fsl.c
> @@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *dr=
iver,
> =A0 =A0 =A0 =A0pr_debug("initializing FSL-SOC USB Controller\n");
>
> =A0 =A0 =A0 =A0/* Need platform data for setup */
> - =A0 =A0 =A0 pdata =3D (struct fsl_usb2_platform_data *)pdev->dev.platfo=
rm_data;
> + =A0 =A0 =A0 pdata =3D pdev->dev.platform_data;
> =A0 =A0 =A0 =A0if (!pdata) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_err(&pdev->dev,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"No platform data for %s.\=
n", dev_name(&pdev->dev));
> @@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver *=
driver,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENODEV;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> - =A0 =A0 =A0 if (!res) {
> + =A0 =A0 =A0 irq =3D platform_get_irq(pdev, 0);
> + =A0 =A0 =A0 if (irq < 0) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_err(&pdev->dev,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"Found HC with no IRQ. Che=
ck %s setup!\n",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_name(&pdev->dev));
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENODEV;
> =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 irq =3D res->start;

Put this hunk in a separate patch.

>
> =A0 =A0 =A0 =A0hcd =3D usb_create_hcd(driver, &pdev->dev, dev_name(&pdev-=
>dev));
> =A0 =A0 =A0 =A0if (!hcd) {
> @@ -116,13 +115,39 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
 *driver,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto err3;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 /* Enable USB controller */
> - =A0 =A0 =A0 temp =3D in_be32(hcd->regs + 0x500);
> - =A0 =A0 =A0 out_be32(hcd->regs + 0x500, temp | 0x4);
> + =A0 =A0 =A0 pdata->regs =3D hcd->regs;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific init: check the clock, grab/confi=
g pins, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->platform_init && pdata->platform_init(pdev)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err3;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Check if it is MPC5121 SoC, otherwise set pdata->have_=
sysif_regs
> + =A0 =A0 =A0 =A0* flag for 83xx or 8536 system interface registers.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->big_endian_mmio)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_be32(hcd->regs + FSL_SOC_USB_ID=
);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_le32(hcd->regs + FSL_SOC_USB_ID=
);
> +
> + =A0 =A0 =A0 if ((temp & ID_MSK) !=3D (~((temp & NID_MSK) >> 8) & ID_MSK=
))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->have_sysif_regs =3D 1;
> +
> + =A0 =A0 =A0 /* Enable USB controller, 83xx or 8536 */
> + =A0 =A0 =A0 if (pdata->have_sysif_regs)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4=
);
>
> =A0 =A0 =A0 =A0/* Set to Host mode */
> - =A0 =A0 =A0 temp =3D in_le32(hcd->regs + 0x1a8);
> - =A0 =A0 =A0 out_le32(hcd->regs + 0x1a8, temp | 0x3);
> + =A0 =A0 =A0 if (pdata->big_endian_mmio) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_USBMODE, =
USBMODE_CM_HOST);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clrsetbits_le32(hcd->regs + FSL_SOC_USB_USB=
MODE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 USBMODE_CM_=
MASK, USBMODE_CM_HOST);
> + =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0retval =3D usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHAR=
ED);
> =A0 =A0 =A0 =A0if (retval !=3D 0)
> @@ -137,6 +162,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *=
driver,
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0 =A0 =A0 err1:
> =A0 =A0 =A0 =A0dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->=
dev), retval);
> + =A0 =A0 =A0 if (pdata->platform_uninit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->platform_uninit(pdev);
> =A0 =A0 =A0 =A0return retval;
> =A0}
>
> @@ -154,17 +181,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
 *driver,
> =A0static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct platfo=
rm_device *pdev)
> =A0{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> =A0 =A0 =A0 =A0usb_remove_hcd(hcd);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific un-initialization:
> + =A0 =A0 =A0 =A0* release iomux pins, disable clock, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->platform_uninit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->platform_uninit(pdev);
> =A0 =A0 =A0 =A0iounmap(hcd->regs);
> =A0 =A0 =A0 =A0release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0}
>
> -static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum fsl_usb2_p=
hy_modes phy_mode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int po=
rt_offset)
> +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0enum fsl_usb=
2_phy_modes phy_mode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int=
 port_offset)
> =A0{
> - =A0 =A0 =A0 u32 portsc =3D 0;
> + =A0 =A0 =A0 u32 portsc;
> +
> + =A0 =A0 =A0 portsc =3D ehci_readl(ehci, &ehci->regs->port_status[port_o=
ffset]);
> + =A0 =A0 =A0 portsc &=3D ~(PORT_PTS_MSK | PORT_PTS_PTW);
> +
> =A0 =A0 =A0 =A0switch (phy_mode) {
> =A0 =A0 =A0 =A0case FSL_USB2_PHY_ULPI:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0portsc |=3D PORT_PTS_ULPI;
> @@ -184,20 +224,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci=
,
> =A0 =A0 =A0 =A0ehci_writel(ehci, portsc, &ehci->regs->port_status[port_of=
fset]);
> =A0}
>
> -static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> +static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> + =A0 =A0 =A0 struct usb_hcd *hcd =3D ehci_to_hcd(ehci);
> =A0 =A0 =A0 =A0struct fsl_usb2_platform_data *pdata;
> =A0 =A0 =A0 =A0void __iomem *non_ehci =3D hcd->regs;
> - =A0 =A0 =A0 u32 temp;
> + =A0 =A0 =A0 u32 tmp;
> +
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
>
> - =A0 =A0 =A0 pdata =3D
> - =A0 =A0 =A0 =A0 =A0 (struct fsl_usb2_platform_data *)hcd->self.controll=
er->
> - =A0 =A0 =A0 =A0 =A0 platform_data;
> =A0 =A0 =A0 =A0/* Enable PHY interface in the control reg. */
> - =A0 =A0 =A0 temp =3D in_be32(non_ehci + FSL_SOC_USB_CTRL);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D in_be32(non_ehci + FSL_SOC_USB_CTRL=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, tmp |=
 0x00000004);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0=
000001b);
> + =A0 =A0 =A0 }
>
> =A0#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
> =A0 =A0 =A0 =A0/*
> @@ -214,7 +255,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
>
> =A0 =A0 =A0 =A0if ((pdata->operating_mode =3D=3D FSL_USB2_DR_HOST) ||
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(pdata->operating_mode =3D=
=3D FSL_USB2_DR_OTG))
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pdata->phy_mode, 0)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0=
);
>
> =A0 =A0 =A0 =A0if (pdata->operating_mode =3D=3D FSL_USB2_MPH_HOST) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int chip, rev, svr;
> @@ -228,27 +269,31 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ehci->has_fsl_port_bug =3D=
 1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT0_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 0);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT1_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 1);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0/* put controller in host mode. */
> - =A0 =A0 =A0 ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMOD=
E);
> + =A0 =A0 =A0 tmp =3D USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
> + =A0 =A0 =A0 ehci_writel(ehci, tmp, non_ehci + FSL_SOC_USB_USBMODE);
> +
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> =A0#ifdef CONFIG_PPC_85xx
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
00000008);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000080);
> =A0#else
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
0000000c);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000040);
> =A0#endif
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x0=
0000001);
> + =A0 =A0 =A0 }
> =A0}

Unrelated whitespace changes.  Put in separate patch.

>
> =A0/* called after powerup, by probe or system-pm "wakeup" */
> =A0static int ehci_fsl_reinit(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 mpc83xx_usb_setup(ehci_to_hcd(ehci));
> + =A0 =A0 =A0 ehci_fsl_usb_setup(ehci);
> =A0 =A0 =A0 =A0ehci_port_power(ehci, 0);
>
> =A0 =A0 =A0 =A0return 0;
> @@ -259,6 +304,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
> =A0{
> =A0 =A0 =A0 =A0struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> =A0 =A0 =A0 =A0int retval;
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata;
> +
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
> + =A0 =A0 =A0 ehci->big_endian_desc =3D pdata->big_endian_desc;
> + =A0 =A0 =A0 ehci->big_endian_mmio =3D pdata->big_endian_mmio;
>
> =A0 =A0 =A0 =A0/* EHCI registers start at offset 0x100 */
> =A0 =A0 =A0 =A0ehci->caps =3D hcd->regs + 0x100;
> @@ -369,7 +419,7 @@ static const struct hc_driver ehci_fsl_hc_driver =3D =
{
> =A0 =A0 =A0 =A0 * generic hardware linkage
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0.irq =3D ehci_irq,
> - =A0 =A0 =A0 .flags =3D HCD_USB2,
> + =A0 =A0 =A0 .flags =3D HCD_USB2 | HCD_MEMORY,
>
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * basic lifecycle operations
> diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
> index b5e59db..3525bb4 100644
> --- a/drivers/usb/host/ehci-fsl.h
> +++ b/drivers/usb/host/ehci-fsl.h
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2005 freescale semiconductor
> +/* Copyright (C) 2005-2009 Freescale Semiconductor, Inc. All rights rese=
rved.
> =A0* Copyright (c) 2005 MontaVista Software
> =A0*
> =A0* This program is free software; you can redistribute =A0it and/or mod=
ify it
> @@ -19,6 +19,11 @@
> =A0#define _EHCI_FSL_H
>
> =A0/* offsets for the non-ehci registers in the FSL SOC USB controller */
> +#define FSL_SOC_USB_ID =A0 =A0 =A0 =A0 0x0
> +#define ID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x3f
> +#define NID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x3f00
> +#define FSL_SOC_USB_SBUSCFG =A0 =A00x90
> +#define FSL_SOC_USB_BURSTSIZE =A00x160
> =A0#define FSL_SOC_USB_ULPIVP =A0 =A0 0x170
> =A0#define FSL_SOC_USB_PORTSC1 =A0 =A00x184
> =A0#define PORT_PTS_MSK =A0 =A0 =A0 =A0 =A0 (3<<30)
> @@ -26,8 +31,20 @@
> =A0#define PORT_PTS_ULPI =A0 =A0 =A0 =A0 =A0(2<<30)
> =A0#define =A0 =A0 =A0 =A0PORT_PTS_SERIAL =A0 =A0 =A0 =A0 (3<<30)
> =A0#define PORT_PTS_PTW =A0 =A0 =A0 =A0 =A0 (1<<28)
> +#define PORT_PTS_PHCD =A0 =A0 =A0 =A0 =A0(1<<23)
> =A0#define FSL_SOC_USB_PORTSC2 =A0 =A00x188
> =A0#define FSL_SOC_USB_USBMODE =A0 =A00x1a8
> +#define USBMODE_CM_MASK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode mask */
> +#define USBMODE_CM_HOST =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode: host */
> +#define USBMODE_ES =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* (B=
ig) Endian Select */
> +
> +#define FSL_SOC_USB_USBGENCTRL =A0 =A0 =A0 =A0 0x200
> +#define USBGENCTRL_PPP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3)
> +#define USBGENCTRL_PFP =A0 =A0 =A0 =A0 (1 << 2)
> +#define FSL_SOC_USB_ISIPHYCTRL 0x204
> +#define ISIPHYCTRL_PXE =A0 =A0 =A0 =A0 (1)
> +#define ISIPHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 4)
> +
> =A0#define FSL_SOC_USB_SNOOP1 =A0 =A0 0x400 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_SNOOP2 =A0 =A0 0x404 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_AGECNTTHRSH =A0 =A0 =A0 =A00x408 =A0 /* NOTE: big-=
endian */
> diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
> index aeda96e..1e7e004 100644
> --- a/drivers/usb/host/ehci-mem.c
> +++ b/drivers/usb/host/ehci-mem.c
> @@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci,=
 struct ehci_qtd *qtd,
> =A0{
> =A0 =A0 =A0 =A0memset (qtd, 0, sizeof *qtd);
> =A0 =A0 =A0 =A0qtd->qtd_dma =3D dma;
> - =A0 =A0 =A0 qtd->hw_token =3D cpu_to_le32 (QTD_STS_HALT);
> + =A0 =A0 =A0 qtd->hw_token =3D cpu_to_hc32(ehci, QTD_STS_HALT);
> =A0 =A0 =A0 =A0qtd->hw_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0qtd->hw_alt_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0INIT_LIST_HEAD (&qtd->qtd_list);
> diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
> index 28e33fe..dfe603f 100644
> --- a/include/linux/fsl_devices.h
> +++ b/include/linux/fsl_devices.h
> @@ -58,11 +58,21 @@ enum fsl_usb2_phy_modes {
> =A0 =A0 =A0 =A0FSL_USB2_PHY_SERIAL,
> =A0};
>
> +struct platform_device;
> =A0struct fsl_usb2_platform_data {
> =A0 =A0 =A0 =A0/* board specific information */
> =A0 =A0 =A0 =A0enum fsl_usb2_operating_modes =A0 operating_mode;
> =A0 =A0 =A0 =A0enum fsl_usb2_phy_modes =A0 =A0 =A0 =A0 phy_mode;
> =A0 =A0 =A0 =A0unsigned int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0port_e=
nables;
> +
> + =A0 =A0 =A0 char =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0*name; =A0 =A0 =A0 =A0 =A0/* pretty print */
> + =A0 =A0 =A0 int (*platform_init) (struct platform_device *);
> + =A0 =A0 =A0 void (*platform_uninit) (struct platform_device *);
> + =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*regs; =
=A0/* ioremap'd register base */
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0big=
_endian_mmio:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0big=
_endian_desc:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0es:=
1; =A0 =A0 =A0 =A0 =A0 /* need USBMODE:ES */
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hav=
e_sysif_regs:1;
> =A0};

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

* Re: [PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS
  2010-01-19 20:24 ` [PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS Anatolij Gustschin
@ 2010-01-21 17:47   ` Grant Likely
  0 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-21 17:47 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, wd, dzu

On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> From: Wolfgang Denk <wd@denx.de>
>
> As more MPC512x based boards will be coming soon, a new directory
> arch/powerpc/configs/512x/ for board specific config files is created,
> following the example of other processor families.
>
> In a first step, we just copy (and update) the existing defconfig
> file for the mpc5121ads board. When new boards get added, the old
> arch/powerpc/configs/mpc5121_defconfig file will get adjusted to
> allow for a generic kernel image for MPC512x based boards.
>
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> Signed-off-by: Detlev Zundel <dzu@denx.de>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> This default config is provided only for easier testing.
>
> =A0arch/powerpc/configs/512x/mpc5121ads_defconfig | 1662 ++++++++++++++++=
++++++++

I'm not a fan off adding one-per-board defconfigs to mainline.  To
start, please just name this arch/powerpc/configs/512x_defconfig

g.

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

* Re: [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
  2010-01-21 17:12         ` Grant Likely
@ 2010-01-22 12:15             ` Wolfgang Grandegger
  -1 siblings, 0 replies; 62+ messages in thread
From: Wolfgang Grandegger @ 2010-01-22 12:15 UTC (permalink / raw)
  To: Grant Likely
  Cc: Anatolij Gustschin, wd-ynQEQJNshbs, dzu-ynQEQJNshbs,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Piotr Ziecik

Grant Likely wrote:
> On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org> wrote:
>> From: Piotr Ziecik <kosmo-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
>>
>>    - Update Kconfig for i2c-mpc driver.
>>    - Enable I2C interrupts on MPC5121.
>>
>> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
>> index f627001..84eeb25 100644
>> --- a/drivers/i2c/busses/i2c-mpc.c
>> +++ b/drivers/i2c/busses/i2c-mpc.c
>> @@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
>>                }
>>        }
>>
>> +       if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {
> 
> Rather than doing stuff like this with explicit compatible checks in
> the probe hook, consider using the .data pointer in the of match
> table.

Yes, and it does also not use the clock setting code of the MPC5200,
which should work for the MPC512x as well. I already have a patch in my
pipeline, which I will roll out after some more testing.

Wolfgang.

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

* Re: [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support
@ 2010-01-22 12:15             ` Wolfgang Grandegger
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfgang Grandegger @ 2010-01-22 12:15 UTC (permalink / raw)
  To: Grant Likely
  Cc: Piotr Ziecik, dzu, linuxppc-dev, linux-i2c, Anatolij Gustschin, wd

Grant Likely wrote:
> On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
>> From: Piotr Ziecik <kosmo@semihalf.com>
>>
>>    - Update Kconfig for i2c-mpc driver.
>>    - Enable I2C interrupts on MPC5121.
>>
>> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
>> index f627001..84eeb25 100644
>> --- a/drivers/i2c/busses/i2c-mpc.c
>> +++ b/drivers/i2c/busses/i2c-mpc.c
>> @@ -540,6 +540,29 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
>>                }
>>        }
>>
>> +       if (of_device_is_compatible(op->node, "fsl,mpc5121-i2c")) {
> 
> Rather than doing stuff like this with explicit compatible checks in
> the probe hook, consider using the .data pointer in the of match
> table.

Yes, and it does also not use the clock setting code of the MPC5200,
which should work for the MPC512x as well. I already have a patch in my
pipeline, which I will roll out after some more testing.

Wolfgang.

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

* Re: [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
  2010-01-20 10:49     ` Wolfram Sang
@ 2010-01-25 15:56       ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-25 15:56 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: wd, dzu, linuxppc-dev, linux-mtd, Piotr Ziecik

Hi Wolfram,

Wolfram Sang <w.sang@pengutronix.de> wrote:

> Please include a logfile with changes since the last version. This really
> helps.

Ok.

> > +static int __init mpc5121_nfc_probe(struct of_device *op,
> > +					const struct of_device_id *match)
> 
> [...]
> 
> > +{
> > +	/* Support external chip-select logic on ADS5121 board */
> > +	rootnode = of_find_node_by_path("/");
> > +	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
> > +		retval = ads5121_chipselect_init(mtd);
> > +		if (retval) {
> > +			dev_err(dev, "Chipselect init error!\n");
> > +			of_node_put(rootnode);
> > +			return retval;
> > +		}
> > +
> > +		chip->select_chip = ads5121_select_chip;
> > +	}
> > +	of_node_put(rootnode);
> 
> If we have to live with the platform-stuff being in the driver, maybe a table
> having the compatible-string and an init-function pointer per entry will make
> it scale better with the number of boards?

Maybe something like in the patch below can be accepted?

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 2980eb1..6807e72 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -127,6 +127,10 @@ struct mpc5121_nfc_prv {
 	struct device		*dev;
 };
 
+struct mpc5121_nfc_match_data {
+	int (*init)(struct mtd_info *);
+};
+
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -279,6 +283,26 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
 	nfc_set(mtd, NFC_CONFIG1, NFC_CE);
 }
 
+/* Control chips select signal on ADS5121 board */
+static void ads5121_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	u8 v;
+
+	/* CPLD Register 9 controls NAND /CE Lines */
+	v = in_8(prv->csreg + 9);
+	v |= 0x0F;
+
+	if (chip >= 0) {
+		mpc5121_nfc_select_chip(mtd, 0);
+		v &= ~(1 << chip);
+	} else
+		mpc5121_nfc_select_chip(mtd, -1);
+
+	out_8(prv->csreg + 9, v);
+}
+
 /* Init external chip select logic on ADS5121 board */
 static int ads5121_chipselect_init(struct mtd_info *mtd)
 {
@@ -293,33 +317,13 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
 		if (!prv->csreg)
 			return -ENOMEM;
 
-		/* CPLD Register 9 controls NAND /CE Lines */
-		prv->csreg += 9;
+		chip->select_chip = ads5121_select_chip;
 		return 0;
 	}
 
 	return -EINVAL;
 }
 
-/* Control chips select signal on ADS5121 board */
-static void ads5121_select_chip(struct mtd_info *mtd, int chip)
-{
-	struct nand_chip *nand = mtd->priv;
-	struct mpc5121_nfc_prv *prv = nand->priv;
-	u8 v;
-
-	v = in_8(prv->csreg);
-	v |= 0x0F;
-
-	if (chip >= 0) {
-		mpc5121_nfc_select_chip(mtd, 0);
-		v &= ~(1 << chip);
-	} else
-		mpc5121_nfc_select_chip(mtd, -1);
-
-	out_8(prv->csreg, v);
-}
-
 /* Read NAND Ready/Busy signal */
 static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
 {
@@ -649,7 +653,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int __init mpc5121_nfc_probe(struct of_device *op,
 					const struct of_device_id *match)
 {
-	struct device_node *rootnode, *dn = op->node;
+	struct device_node *dn = op->node;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -663,6 +667,7 @@ static int __init mpc5121_nfc_probe(struct of_device *op,
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
+	struct mpc5121_nfc_match_data *data = match->data;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -738,19 +743,13 @@ static int __init mpc5121_nfc_probe(struct of_device *op,
 	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
 	chip->ecc.mode = NAND_ECC_SOFT;
 
-	/* Support external chip-select logic on ADS5121 board */
-	rootnode = of_find_node_by_path("/");
-	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
-		retval = ads5121_chipselect_init(mtd);
+	if (data && data->init) {
+		retval = data->init(mtd);
 		if (retval) {
 			dev_err(dev, "Chipselect init error!\n");
-			of_node_put(rootnode);
-			return retval;
+			goto error;
 		}
-
-		chip->select_chip = ads5121_select_chip;
 	}
-	of_node_put(rootnode);
 
 	/* Enable NFC clock */
 	prv->clk = clk_get(dev, "nfc_clk");
@@ -884,6 +883,11 @@ static int __exit mpc5121_nfc_remove(struct of_device *op)
 
 static struct of_device_id mpc5121_nfc_match[] = {
 	{ .compatible = "fsl,mpc5121-nfc", },
+	{ .compatible = "fsl,mpc5121ads-nfc",
+	  .data = &(struct mpc5121_nfc_match_data) {
+			.init = ads5121_chipselect_init,
+		},
+	},
 	{},
 };
 

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

* Re: [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver
@ 2010-01-25 15:56       ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-25 15:56 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: dzu, Grant Likely, linuxppc-dev, linux-mtd, Piotr Ziecik

Hi Wolfram,

Wolfram Sang <w.sang@pengutronix.de> wrote:

> Please include a logfile with changes since the last version. This really
> helps.

Ok.

> > +static int __init mpc5121_nfc_probe(struct of_device *op,
> > +					const struct of_device_id *match)
> 
> [...]
> 
> > +{
> > +	/* Support external chip-select logic on ADS5121 board */
> > +	rootnode = of_find_node_by_path("/");
> > +	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
> > +		retval = ads5121_chipselect_init(mtd);
> > +		if (retval) {
> > +			dev_err(dev, "Chipselect init error!\n");
> > +			of_node_put(rootnode);
> > +			return retval;
> > +		}
> > +
> > +		chip->select_chip = ads5121_select_chip;
> > +	}
> > +	of_node_put(rootnode);
> 
> If we have to live with the platform-stuff being in the driver, maybe a table
> having the compatible-string and an init-function pointer per entry will make
> it scale better with the number of boards?

Maybe something like in the patch below can be accepted?

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 2980eb1..6807e72 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -127,6 +127,10 @@ struct mpc5121_nfc_prv {
 	struct device		*dev;
 };
 
+struct mpc5121_nfc_match_data {
+	int (*init)(struct mtd_info *);
+};
+
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -279,6 +283,26 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
 	nfc_set(mtd, NFC_CONFIG1, NFC_CE);
 }
 
+/* Control chips select signal on ADS5121 board */
+static void ads5121_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5121_nfc_prv *prv = nand->priv;
+	u8 v;
+
+	/* CPLD Register 9 controls NAND /CE Lines */
+	v = in_8(prv->csreg + 9);
+	v |= 0x0F;
+
+	if (chip >= 0) {
+		mpc5121_nfc_select_chip(mtd, 0);
+		v &= ~(1 << chip);
+	} else
+		mpc5121_nfc_select_chip(mtd, -1);
+
+	out_8(prv->csreg + 9, v);
+}
+
 /* Init external chip select logic on ADS5121 board */
 static int ads5121_chipselect_init(struct mtd_info *mtd)
 {
@@ -293,33 +317,13 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
 		if (!prv->csreg)
 			return -ENOMEM;
 
-		/* CPLD Register 9 controls NAND /CE Lines */
-		prv->csreg += 9;
+		chip->select_chip = ads5121_select_chip;
 		return 0;
 	}
 
 	return -EINVAL;
 }
 
-/* Control chips select signal on ADS5121 board */
-static void ads5121_select_chip(struct mtd_info *mtd, int chip)
-{
-	struct nand_chip *nand = mtd->priv;
-	struct mpc5121_nfc_prv *prv = nand->priv;
-	u8 v;
-
-	v = in_8(prv->csreg);
-	v |= 0x0F;
-
-	if (chip >= 0) {
-		mpc5121_nfc_select_chip(mtd, 0);
-		v &= ~(1 << chip);
-	} else
-		mpc5121_nfc_select_chip(mtd, -1);
-
-	out_8(prv->csreg, v);
-}
-
 /* Read NAND Ready/Busy signal */
 static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
 {
@@ -649,7 +653,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int __init mpc5121_nfc_probe(struct of_device *op,
 					const struct of_device_id *match)
 {
-	struct device_node *rootnode, *dn = op->node;
+	struct device_node *dn = op->node;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -663,6 +667,7 @@ static int __init mpc5121_nfc_probe(struct of_device *op,
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
+	struct mpc5121_nfc_match_data *data = match->data;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -738,19 +743,13 @@ static int __init mpc5121_nfc_probe(struct of_device *op,
 	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT;
 	chip->ecc.mode = NAND_ECC_SOFT;
 
-	/* Support external chip-select logic on ADS5121 board */
-	rootnode = of_find_node_by_path("/");
-	if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) {
-		retval = ads5121_chipselect_init(mtd);
+	if (data && data->init) {
+		retval = data->init(mtd);
 		if (retval) {
 			dev_err(dev, "Chipselect init error!\n");
-			of_node_put(rootnode);
-			return retval;
+			goto error;
 		}
-
-		chip->select_chip = ads5121_select_chip;
 	}
-	of_node_put(rootnode);
 
 	/* Enable NFC clock */
 	prv->clk = clk_get(dev, "nfc_clk");
@@ -884,6 +883,11 @@ static int __exit mpc5121_nfc_remove(struct of_device *op)
 
 static struct of_device_id mpc5121_nfc_match[] = {
 	{ .compatible = "fsl,mpc5121-nfc", },
+	{ .compatible = "fsl,mpc5121ads-nfc",
+	  .data = &(struct mpc5121_nfc_match_data) {
+			.init = ads5121_chipselect_init,
+		},
+	},
 	{},
 };
 

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

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
  2010-01-21 17:43       ` Grant Likely
@ 2010-01-25 17:00           ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-25 17:00 UTC (permalink / raw)
  To: Grant Likely
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss

On Thu, 21 Jan 2010 10:43:34 -0700
Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:

> > diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> > index b001524..9050154 100644
> > --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
> > +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> > @@ -33,6 +33,14 @@ Recommended properties :
> >  - interrupt-parent : the phandle for the interrupt controller that
> >    services interrupts for this device.
> >
> > +Optional properties :
> 
> > + - big-endian-regs : boolean; if defined, indicates the USB host
> > +   controller registers format is big endian.
> 
> Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
> the match table and use the .data pointer for setting device specific
> quirks.

There is no match table. fsl_usb_of_init() is an arch_initcall and
tests other properties using the same approach.

> > + - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
> > +   power polarity of internal PHY signal DRVVBUS is inverted.
> > + - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
> > +   PWR_FAULT signal polarity is inverted.
> 
> These are also characteristics of the chip, not the board, right?  If
> so then these also can be determined implicitly by the compatible
> value.

No, these are characteristics of the board. The internal USB PHY doesn't
provide supply voltage. Some boards use MIC2025 switches which require active
high DRVVBUS and active low PWR_FAULT. Some boards could use MIC2026 or
MAX1838 which require other polarities.

> Finally, these are all freescale specific properties.  If you still
> need them, then prefix the property names with 'fsl,'

OK.

> > ...
> > +
> > +config USB_FSL_BIG_ENDIAN_MMIO
> > +       bool
> 
> What's this for?

This is currently unused (will be used later), I will remove it for now.

> > ...
> > @@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
> >                return -ENODEV;
> >        }
> >
> > -       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> > -       if (!res) {
> > +       irq = platform_get_irq(pdev, 0);
> > +       if (irq < 0) {
> >                dev_err(&pdev->dev,
> >                        "Found HC with no IRQ. Check %s setup!\n",
> >                        dev_name(&pdev->dev));
> >                return -ENODEV;
> >        }
> > -       irq = res->start;
> 
> Put this hunk in a separate patch.

OK.

> > ...
> > +       if (pdata->have_sysif_regs) {
> >  #ifdef CONFIG_PPC_85xx
> > -       out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> > -       out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> > +               out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> > +               out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> >  #else
> > -       out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> > -       out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> > +               out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> > +               out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> >  #endif
> > -       out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> > +               out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> > +       }
> >  }
> 
> Unrelated whitespace changes.  Put in separate patch.

OK.

Thanks,

Anatolij
--
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] 62+ messages in thread

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
@ 2010-01-25 17:00           ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-25 17:00 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, devicetree-discuss, linux-usb, wd, dzu

On Thu, 21 Jan 2010 10:43:34 -0700
Grant Likely <grant.likely@secretlab.ca> wrote:

> > diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documenta=
tion/powerpc/dts-bindings/fsl/usb.txt
> > index b001524..9050154 100644
> > --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
> > +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
> > @@ -33,6 +33,14 @@ Recommended properties :
> > =C2=A0- interrupt-parent : the phandle for the interrupt controller that
> > =C2=A0 =C2=A0services interrupts for this device.
> >
> > +Optional properties :
>=20
> > + - big-endian-regs : boolean; if defined, indicates the USB host
> > + =C2=A0 controller registers format is big endian.
>=20
> Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
> the match table and use the .data pointer for setting device specific
> quirks.

There is no match table. fsl_usb_of_init() is an arch_initcall and
tests other properties using the same approach.

> > + - invert-drvvbus : boolean; for MPC5121 only. Indicates the port
> > + =C2=A0 power polarity of internal PHY signal DRVVBUS is inverted.
> > + - invert-pwr-fault : boolean; for MPC5121 only. Indicates the
> > + =C2=A0 PWR_FAULT signal polarity is inverted.
>=20
> These are also characteristics of the chip, not the board, right?  If
> so then these also can be determined implicitly by the compatible
> value.

No, these are characteristics of the board. The internal USB PHY doesn't
provide supply voltage. Some boards use MIC2025 switches which require acti=
ve
high DRVVBUS and active low PWR_FAULT. Some boards could use MIC2026 or
MAX1838 which require other polarities.

> Finally, these are all freescale specific properties.  If you still
> need them, then prefix the property names with 'fsl,'

OK.

> > ...
> > +
> > +config USB_FSL_BIG_ENDIAN_MMIO
> > + =C2=A0 =C2=A0 =C2=A0 bool
>=20
> What's this for?

This is currently unused (will be used later), I will remove it for now.

> > ...
> > @@ -77,14 +77,13 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
 *driver,
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -ENODEV;
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> >
> > - =C2=A0 =C2=A0 =C2=A0 res =3D platform_get_resource(pdev, IORESOURCE_I=
RQ, 0);
> > - =C2=A0 =C2=A0 =C2=A0 if (!res) {
> > + =C2=A0 =C2=A0 =C2=A0 irq =3D platform_get_irq(pdev, 0);
> > + =C2=A0 =C2=A0 =C2=A0 if (irq < 0) {
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(&pdev->d=
ev,
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0"Found HC with no IRQ. Check %s setup!\n",
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0dev_name(&pdev->dev));
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -ENODEV;
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> > - =C2=A0 =C2=A0 =C2=A0 irq =3D res->start;
>=20
> Put this hunk in a separate patch.

OK.

> > ...
> > + =C2=A0 =C2=A0 =C2=A0 if (pdata->have_sysif_regs) {
> > =C2=A0#ifdef CONFIG_PPC_85xx
> > - =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000=
008);
> > - =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x0=
0000080);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + =
FSL_SOC_USB_PRICTRL, 0x00000008);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + =
FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> > =C2=A0#else
> > - =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000=
00c);
> > - =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x0=
0000040);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + =
FSL_SOC_USB_PRICTRL, 0x0000000c);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + =
FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> > =C2=A0#endif
> > - =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x000000=
01);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(non_ehci + =
FSL_SOC_USB_SICTRL, 0x00000001);
> > + =C2=A0 =C2=A0 =C2=A0 }
> > =C2=A0}
>=20
> Unrelated whitespace changes.  Put in separate patch.

OK.

Thanks,

Anatolij

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

* Re: [PATCH 03/11] powerpc/mpc5121: Add machine restart support
  2010-01-20 11:28   ` Wolfram Sang
@ 2010-01-26  7:53     ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-26  7:53 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: linuxppc-dev, wd, dzu, Piotr Ziecik

On Wed, 20 Jan 2010 12:28:43 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:

> > +static void __iomem *reset_module_base;
> 
> type here also?

Ok.

> > +
> > +static int __init mpc512x_restart_init(void)
> > +{
> > +	struct device_node *np;
> > +
> > +	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
> > +	if (!np)
> > +		return -1;
> > +
> > +	reset_module_base = of_iomap(np, 0);
> > +	of_node_put(np);
> > +
> > +	return 0;
> > +}
> > +
> 
> Drop this empty line?

Ok.

> > +	} else {
> > +		printk(KERN_ERR ": Restart module not mapped.\n");
> 
> The colon is a leftover?

Yes, will fix for using pr_error() and resubmit.

Thanks,
Anatolij

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

* Re: [PATCH 07/11] dma: Add MPC512x DMA driver
  2010-01-21 17:22   ` Grant Likely
@ 2010-01-26  8:03     ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-26  8:03 UTC (permalink / raw)
  To: Grant Likely; +Cc: wd, dzu, linuxppc-dev, Dan Williams, Piotr Ziecik

On Thu, 21 Jan 2010 10:22:27 -0700
Grant Likely <grant.likely@secretlab.ca> wrote:

> On Tue, Jan 19, 2010 at 1:24 PM, Anatolij Gustschin <agust@denx.de> wrote:
> > From: Piotr Ziecik <kosmo@semihalf.com>
> >
> > Adds initial version of MPC512x DMA driver.
> > Only memory to memory transfers are currenly supported.
>=20
> Comments below on brief review.  I've not looked at the code in-depth.

> > ...
> > =C2=A0drivers/dma/Kconfig =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A07 +
> > =C2=A0drivers/dma/Makefile =C2=A0 =C2=A0 =C2=A0| =C2=A0 =C2=A01 +
> > =C2=A0drivers/dma/mpc512x_dma.c | =C2=A0636 +++++++++++++++++++++++++++=
++++++++++++++++++
> > =C2=A0drivers/dma/mpc512x_dma.h | =C2=A0192 ++++++++++++++
>=20
> Unless the stuff in the .h file is used by other .c files, it really
> belongs in mpc512x_dma.c

Ok, will be moved to .c file in next version.

>=20
> > +static int __init mpc_dma_probe(struct of_device *op,
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 const struc=
t of_device_id *match)
>=20
> __devinit
>=20
> > +static void __exit mpc_dma_remove(struct of_device *op)
>=20
> __devexit

Ok.

> > +{
> > + =C2=A0 =C2=A0 =C2=A0 struct device *dev =3D &op->dev;
> > + =C2=A0 =C2=A0 =C2=A0 struct mpc_dma *mdma =3D dev_get_drvdata(dev);
> > +
> > + =C2=A0 =C2=A0 =C2=A0 devm_free_irq(dev, mdma->irq, mdma);
> > +}
>=20
> No unregistration of the dma device?  No unmapping?  No kfree()?

I will add unregistration of the dma device. Unmapping and
freeing should be done automatically on driver detach, mapping
and allocation is done by devm_ioremap() and devm_kzalloc().

> > +static struct of_platform_driver mpc_dma_driver =3D {
> > + =C2=A0 =C2=A0 =C2=A0 .match_table =C2=A0 =C2=A0=3D mpc_dma_match,
> > + =C2=A0 =C2=A0 =C2=A0 .probe =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D mpc=
_dma_probe,
> > + =C2=A0 =C2=A0 =C2=A0 .remove =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D __exit_p=
(mpc_dma_remove),
>=20
> __devexit_p()

Ok.

> > +module_exit(mpc_dma_exit);
> > +
> > +/* MODULE API */
>=20
> Meaningless comment.

Ok, will remove it.

Thanks,
Anatolij

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

* Re: [PATCH 0/11] Update support for MPC512x
  2010-01-20 11:22     ` Wolfram Sang
  (?)
@ 2010-01-26  8:06         ` Anatolij Gustschin
  -1 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-26  8:06 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, Grant Likely, John Rigby, Dan Williams,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On Wed, 20 Jan 2010 12:22:32 +0100
Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:

> 
> > The patches are based on v2.6.33-rc4 and cover the following
> > items:
> 
> The USB-patch needs two patches from linux-next. For convenience, don't you
> have a git-tree somewhere? :)

No, I don't have a git tree for this now, sorry.

Anatolij

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-26  8:06         ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-26  8:06 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: wd, dzu, netdev, linux-usb, linuxppc-dev, linux-mtd, linux-i2c,
	rtc-linux, Dan Williams

On Wed, 20 Jan 2010 12:22:32 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:

> 
> > The patches are based on v2.6.33-rc4 and cover the following
> > items:
> 
> The USB-patch needs two patches from linux-next. For convenience, don't you
> have a git-tree somewhere? :)

No, I don't have a git tree for this now, sorry.

Anatolij

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-26  8:06         ` Anatolij Gustschin
  0 siblings, 0 replies; 62+ messages in thread
From: Anatolij Gustschin @ 2010-01-26  8:06 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: John Rigby, dzu, netdev, linux-usb, Grant Likely, linuxppc-dev,
	linux-mtd, linux-i2c, rtc-linux, Dan Williams

On Wed, 20 Jan 2010 12:22:32 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:

> 
> > The patches are based on v2.6.33-rc4 and cover the following
> > items:
> 
> The USB-patch needs two patches from linux-next. For convenience, don't you
> have a git-tree somewhere? :)

No, I don't have a git tree for this now, sorry.

Anatolij

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

* Re: [PATCH 0/11] Update support for MPC512x
  2010-01-26  8:06         ` Anatolij Gustschin
  (?)
@ 2010-01-26 12:16           ` Wolfram Sang
  -1 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-26 12:16 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: John Rigby, dzu, netdev, linux-usb, Grant Likely, linuxppc-dev,
	linux-mtd, linux-i2c, rtc-linux, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

> No, I don't have a git tree for this now, sorry.

No problem, I set one up at:

	git://git.pengutronix.de/git/wsa/linux-2.6.git

It is based on 2.6.33-rc5 and contains the newest patches for FEC and I2C. (I
will pick up the patches as they show up on the lists, so this tree will be
rebased!)

This tree includes all MPC5121-patches and the two USB-patches from Anton. I
haven't actually tested them yet, but they all applied cleanly, at least.
Testing will come soon...

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-26 12:16           ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-26 12:16 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: rtc-linux, dzu, netdev, linux-usb, linuxppc-dev, linux-mtd,
	linux-i2c, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

> No, I don't have a git tree for this now, sorry.

No problem, I set one up at:

	git://git.pengutronix.de/git/wsa/linux-2.6.git

It is based on 2.6.33-rc5 and contains the newest patches for FEC and I2C. (I
will pick up the patches as they show up on the lists, so this tree will be
rebased!)

This tree includes all MPC5121-patches and the two USB-patches from Anton. I
haven't actually tested them yet, but they all applied cleanly, at least.
Testing will come soon...

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 0/11] Update support for MPC512x
@ 2010-01-26 12:16           ` Wolfram Sang
  0 siblings, 0 replies; 62+ messages in thread
From: Wolfram Sang @ 2010-01-26 12:16 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: John Rigby, rtc-linux, dzu, netdev, linux-usb, Grant Likely,
	linuxppc-dev, linux-mtd, linux-i2c, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 671 bytes --]

> No, I don't have a git tree for this now, sorry.

No problem, I set one up at:

	git://git.pengutronix.de/git/wsa/linux-2.6.git

It is based on 2.6.33-rc5 and contains the newest patches for FEC and I2C. (I
will pick up the patches as they show up on the lists, so this tree will be
rebased!)

This tree includes all MPC5121-patches and the two USB-patches from Anton. I
haven't actually tested them yet, but they all applied cleanly, at least.
Testing will come soon...

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
  2010-01-25 17:00           ` Anatolij Gustschin
@ 2010-01-27 16:52             ` Grant Likely
  -1 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-27 16:52 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A, dzu-ynQEQJNshbs,
	wd-ynQEQJNshbs, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss

On Mon, Jan 25, 2010 at 10:00 AM, Anatolij Gustschin <agust-ynQEQJNshbs@public.gmane.org> wrote:
> On Thu, 21 Jan 2010 10:43:34 -0700
> Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
>
>> > diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
>> > index b001524..9050154 100644
>> > --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
>> > +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
>> > @@ -33,6 +33,14 @@ Recommended properties :
>> >  - interrupt-parent : the phandle for the interrupt controller that
>> >    services interrupts for this device.
>> >
>> > +Optional properties :
>>
>> > + - big-endian-regs : boolean; if defined, indicates the USB host
>> > +   controller registers format is big endian.
>>
>> Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
>> the match table and use the .data pointer for setting device specific
>> quirks.

Still, don't use a new property to describe this.  The regs being
big-endian is all wrapped up in the definition of what
fsl,mpc5121-usb2-dr means.  You should also drop fsl-usb2-dr from the
compatible list in the .dts file since this device is *not* compatible
with it due to the endian difference.  Test for fsl,mpc5121-usb2-dr
explicitly, and adapt the driver behaviour accordingly.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--
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] 62+ messages in thread

* Re: [PATCH 08/11] powerpc/mpc5121: add USB host support
@ 2010-01-27 16:52             ` Grant Likely
  0 siblings, 0 replies; 62+ messages in thread
From: Grant Likely @ 2010-01-27 16:52 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev, devicetree-discuss, linux-usb, wd, dzu

On Mon, Jan 25, 2010 at 10:00 AM, Anatolij Gustschin <agust@denx.de> wrote:
> On Thu, 21 Jan 2010 10:43:34 -0700
> Grant Likely <grant.likely@secretlab.ca> wrote:
>
>> > diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Document=
ation/powerpc/dts-bindings/fsl/usb.txt
>> > index b001524..9050154 100644
>> > --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
>> > +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
>> > @@ -33,6 +33,14 @@ Recommended properties :
>> > =A0- interrupt-parent : the phandle for the interrupt controller that
>> > =A0 =A0services interrupts for this device.
>> >
>> > +Optional properties :
>>
>> > + - big-endian-regs : boolean; if defined, indicates the USB host
>> > + =A0 controller registers format is big endian.
>>
>> Rather than testing for this explicitly, add fsl,mpc5121-usb2-dr to
>> the match table and use the .data pointer for setting device specific
>> quirks.

Still, don't use a new property to describe this.  The regs being
big-endian is all wrapped up in the definition of what
fsl,mpc5121-usb2-dr means.  You should also drop fsl-usb2-dr from the
compatible list in the .dts file since this device is *not* compatible
with it due to the endian difference.  Test for fsl,mpc5121-usb2-dr
explicitly, and adapt the driver behaviour accordingly.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

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

end of thread, other threads:[~2010-01-27 16:52 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-19 20:24 [PATCH 0/11] Update support for MPC512x Anatolij Gustschin
2010-01-19 20:24 ` Anatolij Gustschin
2010-01-19 20:24 ` Anatolij Gustschin
2010-01-19 20:24 ` Anatolij Gustschin
2010-01-19 20:24 ` [PATCH 01/11] fs_enet: Add support for MPC512x to fs_enet driver Anatolij Gustschin
2010-01-19 20:24   ` Anatolij Gustschin
2010-01-19 20:48   ` Scott Wood
2010-01-20 11:20     ` Anatolij Gustschin
2010-01-20 11:20       ` Anatolij Gustschin
2010-01-20 17:02       ` Scott Wood
2010-01-20 17:02         ` Scott Wood
2010-01-19 20:24 ` [PATCH 02/11] fs_enet: Add FEC TX Alignment workaround for MPC5121 Anatolij Gustschin
2010-01-19 20:24   ` Anatolij Gustschin
2010-01-19 20:37   ` David Miller
2010-01-19 20:37     ` David Miller
2010-01-19 23:42     ` Stephen Rothwell
2010-01-19 23:42       ` Stephen Rothwell
2010-01-20  4:04       ` David Miller
2010-01-20  4:04         ` David Miller
2010-01-20 10:22   ` Wolfram Sang
2010-01-20 10:22     ` Wolfram Sang
2010-01-19 20:24 ` [PATCH 03/11] powerpc/mpc5121: Add machine restart support Anatolij Gustschin
2010-01-20 11:28   ` Wolfram Sang
2010-01-26  7:53     ` Anatolij Gustschin
     [not found] ` <1263932653-3634-1-git-send-email-agust-ynQEQJNshbs@public.gmane.org>
2010-01-19 20:24   ` [PATCH 04/11] i2c-mpc: Add MPC5121 I2C bus support Anatolij Gustschin
2010-01-19 20:24     ` Anatolij Gustschin
     [not found]     ` <1263932653-3634-5-git-send-email-agust-ynQEQJNshbs@public.gmane.org>
2010-01-21 17:12       ` Grant Likely
2010-01-21 17:12         ` Grant Likely
     [not found]         ` <fa686aa41001210912r5fd2a5a4g8a072e0c41ee4107-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-01-22 12:15           ` Wolfgang Grandegger
2010-01-22 12:15             ` Wolfgang Grandegger
2010-01-20 11:22   ` [PATCH 0/11] Update support for MPC512x Wolfram Sang
2010-01-20 11:22     ` Wolfram Sang
2010-01-20 11:22     ` Wolfram Sang
     [not found]     ` <20100120112232.GD5041-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2010-01-26  8:06       ` Anatolij Gustschin
2010-01-26  8:06         ` Anatolij Gustschin
2010-01-26  8:06         ` Anatolij Gustschin
2010-01-26 12:16         ` Wolfram Sang
2010-01-26 12:16           ` Wolfram Sang
2010-01-26 12:16           ` Wolfram Sang
2010-01-19 20:24 ` [PATCH 05/11] rtc: Add MPC5121 Real time clock driver Anatolij Gustschin
2010-01-20 11:01   ` Wolfram Sang
2010-01-20 22:19   ` [rtc-linux] " Alessandro Zummo
2010-01-19 20:24 ` [PATCH 06/11] mtd: Add MPC5121 NAND Flash Controller driver Anatolij Gustschin
2010-01-19 20:24   ` Anatolij Gustschin
2010-01-20 10:49   ` Wolfram Sang
2010-01-20 10:49     ` Wolfram Sang
2010-01-25 15:56     ` Anatolij Gustschin
2010-01-25 15:56       ` Anatolij Gustschin
2010-01-19 20:24 ` [PATCH 07/11] dma: Add MPC512x DMA driver Anatolij Gustschin
2010-01-21 17:22   ` Grant Likely
2010-01-26  8:03     ` Anatolij Gustschin
2010-01-19 20:24 ` [PATCH 08/11] powerpc/mpc5121: add USB host support Anatolij Gustschin
     [not found]   ` <1263932653-3634-9-git-send-email-agust-ynQEQJNshbs@public.gmane.org>
2010-01-21 17:43     ` Grant Likely
2010-01-21 17:43       ` Grant Likely
     [not found]       ` <fa686aa41001210943i3739f693uecf0c05ef0a81c1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-01-25 17:00         ` Anatolij Gustschin
2010-01-25 17:00           ` Anatolij Gustschin
2010-01-27 16:52           ` Grant Likely
2010-01-27 16:52             ` Grant Likely
2010-01-19 20:24 ` [PATCH 09/11] powerpc/mpc512x: shared DIU framebuffer support Anatolij Gustschin
2010-01-19 20:24 ` [PATCH 10/11] powerpc/mpc5121: update mpc5121ads DTS Anatolij Gustschin
2010-01-19 20:24 ` [PATCH 11/11] powerpc/mpc5121: Add default config for MPC5121ADS Anatolij Gustschin
2010-01-21 17:47   ` Grant Likely

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.