Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* One of these things (CONFIG_HZ) is not like the others..
From: Santosh Shilimkar @ 2013-01-29  6:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5107114C.4070307@linaro.org>

Jon,

On Tuesday 29 January 2013 05:31 AM, John Stultz wrote:
> On 01/27/2013 10:08 PM, Santosh Shilimkar wrote:
>> On Tuesday 22 January 2013 08:35 PM, Santosh Shilimkar wrote:
>>> On Tuesday 22 January 2013 08:21 PM, Russell King - ARM Linux wrote:
>>>> On Tue, Jan 22, 2013 at 03:44:03PM +0530, Santosh Shilimkar wrote:

[..]

>>> Thanks for expanding it. It is really helpful.
>>>
>>>> And I think further discussion is pointless until such research has
>>>> been
>>>> done (or someone who _really_ knows the time keeping/timer/sched code
>>>> inside out comments.)
>>>>
>>> Fully agree about experimentation to re-asses the drift.
>>>  From what I recollect from past, few OMAP customers did
>>> report the time drift issue and that is how the switch
>>> from 100 --> 128 happened.
>>>
>>> Anyway I have added the suggested task to my long todo list.
>>>
>> So I tried to see if any time drift with HZ = 100 on OMAP. I ran the
>> setup for 62 hours and 27 mins with time synced up once with NTP server.
>> I measure about ~174 millisecond drift which is almost noise considering
>> the observed duration was ~224820000 milliseconds.
>
> So 174ms drift doesn't sound great, as < 2ms (often much less - though
> that depends on how close the server is) can be expected with NTP.
> Although its not clear how you were measuring: Did you see a max 174ms
> offset while trying to sync with NTP? Was that offset shortly after
> starting NTP or after NTP converged down?
>
To avoid the server latency, we didn't do continuous sync. The time was 
synced in the beginning and after 62.5 hours (#ntpd -qg) and the drift
of about 174 ms was observed. As you said this could be because of
server sync time along with probably some addition from system calls
from #ntpd. As mentioned, the other run with HZ = 128 which started
15 hours 20 mins is already showing about 24 mS drift now. I will
let it run for couple of more days just to have similar duration run.

Regards,
santosh

^ permalink raw reply

* [GIT PULL 4/4] ARM: bcm2835: defconfig update
From: Stephen Warren @ 2013-01-29  6:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>

The SDHCI and I2C subsytems and drivers are enabled.

Various filesystems are enabled for use with the SDHCI driver.

Various other options expected by distros are enabled. This allows the
"Raspbian" filesystem published by the Raspberry Pi Foundation to boot
to a serial console prompt.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-defconfig

for you to fetch changes up to d1dc7c6c6a6666fff1d40009c71965dc6600d521:

  ARM: bcm2835: defconfig updates

----------------------------------------------------------------

Stephen Warren (1):
      ARM: bcm2835: defconfig updates

 arch/arm/configs/bcm2835_defconfig |   43 ++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 10 deletions(-)

^ permalink raw reply

* [GIT PULL 3/4] ARM: bcm2835: device tree updates
From: Stephen Warren @ 2013-01-29  6:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>

The SoC's SDHCI and MMC controllers are added to device tree, and enabled
in the Raspberry Pi board device tree. Some fixed clocks are added to the
device tree to support these drivers. These could be replaced by real
clocks in the future.

A hard-coded memreserve is removed from device tree; the bootloader should
specify the correct memory node content instead, since the memory layout
is dynamic.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-dt

for you to fetch changes up to 9692c191ffffbd5255bec222b8f0f2854932a408:

  ARM: bcm2835: fix clock node aliasing in device tree

----------------------------------------------------------------

Stephen Warren (4):
      ARM: bcm2835 rpi: remove hard-coded memreserve from DT
      ARM: bcm2835: add SDHCI node to DT
      ARM: bcm2835: add I2C controllers to DT
      ARM: bcm2835: fix clock node aliasing in device tree

 arch/arm/boot/dts/bcm2835-rpi-b.dts |   16 ++++++++++-
 arch/arm/boot/dts/bcm2835.dtsi      |   44 ++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

^ permalink raw reply

* [GIT PULL 2/4] ARM: bcm2835: SoC driver updates
From: Stephen Warren @ 2013-01-29  6:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>

The bcm2835 clock driver is enhanced to allow fixed clocks to be probed
from device tree.

A system power-off implementation is added.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-soc

for you to fetch changes up to 45e9d77a22b7b25373c7b8c0ea0b146168025360:

  ARM: bcm2835: add a pm_power_off implementation

----------------------------------------------------------------

Dom Cobley (1):
      ARM: bcm2835: add a pm_power_off implementation

Stephen Warren (1):
      clk: bcm2835: probe for fixed-clock in device tree

 arch/arm/mach-bcm2835/bcm2835.c |   28 ++++++++++++++++++++++++++++
 drivers/clk/clk-bcm2835.c       |    9 +++++++++
 2 files changed, 37 insertions(+)

^ permalink raw reply

* [GIT PULL 1/4] ARM: bcm2835: cleanup
From: Stephen Warren @ 2013-01-29  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

This pull request simply converts the bcm2835 clocksource driver to use
the recently added CLKSRC_OF feature.

The branch is based on v3.8-rc3, followed by a merge of arm-soc's
timer/cleanup branch.

(For this and pull 4/4, feel free to cherry-pick the one commit if you
want to avoid the short pull requests!)

----------------------------------------------------------------

The following changes since commit b2fc382aad0a8f52803acdc3ac4e5540dbcdf1f6:

  Merge remote-tracking branch 'korg_arm-soc/timer/cleanup' into cleanup

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-cleanup

for you to fetch changes up to c1b724f6659a7e9e32f8fcf6409d053e1b7bccad:

  ARM: bcm2835: make use of CLKSRC_OF

----------------------------------------------------------------

Stephen Warren (1):
      ARM: bcm2835: make use of CLKSRC_OF

 arch/arm/Kconfig                    |    1 +
 arch/arm/mach-bcm2835/bcm2835.c     |    4 ++--
 drivers/clocksource/bcm2835_timer.c |    5 +++--
 include/linux/bcm2835_timer.h       |   22 ----------------------
 4 files changed, 6 insertions(+), 26 deletions(-)
 delete mode 100644 include/linux/bcm2835_timer.h

^ permalink raw reply

* [GIT PULL v2] imx cleanup for 3.9
From: Shawn Guo @ 2013-01-29  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565:

  Linux 3.8-rc1 (2012-12-21 17:19:00 -0800)

are available in the git repository at:

  git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx-cleanup-3.9

for you to fetch changes up to 7356420cd34e40fe27bf26555b0bf3f2849a43dd:

  ARM: imx: Remove mx508 support (2013-01-29 14:05:43 +0800)

----------------------------------------------------------------
I have left out the patch (ARM: dts: imx: use nodes label in board dts)
in question and other dts related changes, and will have them go via DT
branch  to save the cross branch dependency.

----------------------------------------------------------------
Fabio Estevam (3):
      ARM: mach-imx: Kconfig: Do not select Babbage for MACH_IMX51_DT
      ARM: imx: Remove mach-mx51_3ds board
      ARM: imx: Remove mx508 support

Shawn Guo (2):
      ARM: imx: remove unused imx6q_clock_map_io()
      ARM: imx: use debug_ll_io_init() for imx6q

 arch/arm/Kconfig.debug                        |   10 +-
 arch/arm/configs/imx_v6_v7_defconfig          |    1 -
 arch/arm/include/debug/imx.S                  |    2 +-
 arch/arm/mach-imx/Kconfig                     |   36 -
 arch/arm/mach-imx/Makefile                    |    3 -
 arch/arm/mach-imx/Makefile.boot               |    4 -
 arch/arm/mach-imx/clk-imx6q.c                 |    2 -
 arch/arm/mach-imx/common.h                    |   11 -
 arch/arm/mach-imx/cpu-imx5.c                  |   39 -
 arch/arm/mach-imx/devices-imx50.h             |   33 -
 arch/arm/mach-imx/devices/Kconfig             |    2 +-
 arch/arm/mach-imx/devices/platform-fec.c      |    6 -
 arch/arm/mach-imx/devices/platform-imx-i2c.c  |   10 -
 arch/arm/mach-imx/devices/platform-imx-uart.c |   12 -
 arch/arm/mach-imx/hardware.h                  |    6 -
 arch/arm/mach-imx/iomux-mx50.h                |  977 -------------------------
 arch/arm/mach-imx/lluart.c                    |   47 --
 arch/arm/mach-imx/mach-imx6q.c                |    4 +-
 arch/arm/mach-imx/mach-mx50_rdp.c             |  225 ------
 arch/arm/mach-imx/mach-mx51_3ds.c             |  178 -----
 arch/arm/mach-imx/mm-imx5.c                   |   48 --
 arch/arm/mach-imx/mx50.h                      |  290 --------
 arch/arm/mach-imx/mxc.h                       |   13 -
 arch/arm/mach-imx/pm-imx5.c                   |    7 +-
 24 files changed, 11 insertions(+), 1955 deletions(-)
 delete mode 100644 arch/arm/mach-imx/devices-imx50.h
 delete mode 100644 arch/arm/mach-imx/iomux-mx50.h
 delete mode 100644 arch/arm/mach-imx/lluart.c
 delete mode 100644 arch/arm/mach-imx/mach-mx50_rdp.c
 delete mode 100644 arch/arm/mach-imx/mach-mx51_3ds.c
 delete mode 100644 arch/arm/mach-imx/mx50.h

^ permalink raw reply

* [RFC PATCH 0/4] Add support for LZ4-compressed kernels
From: H. Peter Anvin @ 2013-01-29  6:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.02.1301282320430.6300@xanadu.home>

Uhm... you're saying we have to be at one extreme or the other?

We probably could drop the legacy lzma format, but someone might rely on it.

Nicolas Pitre <nico@fluxnic.net> wrote:

>On Mon, 28 Jan 2013, Andrew Morton wrote:
>
>> On Sat, 26 Jan 2013 14:50:43 +0900
>> Kyungsik Lee <kyungsik.lee@lge.com> wrote:
>> 
>> > This patchset is for supporting LZ4 compressed kernel and initial
>ramdisk on
>> > the x86 and ARM architectures.
>> > 
>> > According to http://code.google.com/p/lz4/, LZ4 is a very fast
>lossless
>> > compression algorithm and also features an extremely fast decoder.
>> > 
>> > Kernel Decompression APIs are based on implementation by Yann
>Collet
>> > (http://code.google.com/p/lz4/source/checkout).
>> > De/compression Tools are also provided from the site above.
>> > 
>> > The initial test result on ARM(v7) based board shows that the size
>of kernel
>> > with LZ4 compressed is 8% bigger than LZO compressed  but the
>decompressing
>> > speed is faster(especially under the enabled unaligned memory
>access).
>> > 
>> > Test: 3.4 based kernel built with many modules
>> > Uncompressed kernel size: 13MB
>> > lzo: 6.3MB, 301ms
>> > lz4: 6.8MB, 251ms(167ms, with enabled unaligned memory access)
>> > 
>> > It seems that it___s worth trying LZ4 compressed kernel image or
>ramdisk 
>> > for making the kernel boot more faster.
>> >
>> > ...
>> >
>> >  20 files changed, 663 insertions(+), 3 deletions(-)
>> >
>> > ...
>> >
>> 
>> What's this "with enabled unaligned memory access" thing?  You mean
>"if
>> the arch supports CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS"?  If so,
>> that's only x86, which isn't really in the target market for this
>> patch, yes?
>
>I'm guessing this is referring to commit 5010192d5a.
>
>> It's a lot of code for a 50ms boot-time improvement.  Does anyone
>have
>> any opinions on whether or not the benefits are worth the cost?
>
>Well, we used to have only one compressed format.  Now we have nearly 
>half a dozen, with the same worthiness issue between themselves.  
>Either we keep it very simple, or we make it very flexible.  The former
>
>would argue in favor of removing some of the existing formats, the
>later 
>would let this new format in.
>
>
>Nicolas

-- 
Sent from my mobile phone. Please excuse brevity and lack of formatting.

^ permalink raw reply

* [PATCH v2 07/27] PCI: Add software-emulated host bridge
From: Jason Gunthorpe @ 2013-01-29  6:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAErSpo7-qXZTri-T+v4O3rKk9AXjHE4ckkWZ1UT63SC1fG02-A@mail.gmail.com>

On Mon, Jan 28, 2013 at 07:40:16PM -0700, Bjorn Helgaas wrote:
> On Mon, Jan 28, 2013 at 3:09 PM, Jason Gunthorpe
> <jgunthorpe@obsidianresearch.com> wrote:
> > On Mon, Jan 28, 2013 at 03:03:55PM -0700, Stephen Warren wrote:
> >> On 01/28/2013 01:18 PM, Arnd Bergmann wrote:
> >> > On Monday 28 January 2013, Thomas Petazzoni wrote:
> >> >> From: Thierry Reding <thierry.reding@avionic-design.de>
> >> >>
> >> >> [Thomas Petazzoni:
> >> >>  - Simplify capabilities handling.
> >> >>  - Move to a separate file.
> >> >>  - Fix mask used when writing a 4 bytes value.]
> >> >>
> >> >> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
> >> >> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> >> >
> >> > Not even a description why this is needed?
> >> >
> >> > This patch (together with patch 8) seems like the most controversial
> >> > one of the series, so you should better provide a really good reason
> >> > why we would emulate something in software rather than using whatever
> >> > hardware is there.
> >>
> >> At least on Tegra, there is no HW that exposes PCI configuration
> >> registers for the host bridge itself. Only the root ports have exposed
> >> PCI configuration registers. There was some debate re: whether a host
> >> bridge device needed to exist or not. This patch makes such a device
> >> exist if it's required.
> 
> Host bridges are not actually PCI devices on any architecture.  The
> upstream side of a host bridge is by definition not on a PCI bus.  On
> some architectures, it *looks* like the host bridge is a PCI device
> because it responds to PCI config accesses and you can get to

Sure, you can't discover domains through any standard means, but once
you have found a domain (notably a way to issue config transactions)
then the PCI-E standard actually does place requirements on what
config transactions should return:
 - 0:00.0 is a host bridge config space.
 - 0:XX.X will be one of:
   - A root complex internal function, with some restrictions this
     is basically a PCI end device
   - A PCI-PCI bridge with various mandatory capability headers.
     One of these must show up for every physical PCI-E link
     on the root complex.
This collection of stuff on bus 0 is called the 'root complex'. This
is new in PCI-E, PCI-X and PCI didn't have such requirements.

SOC vendors are taking various liberties with their PCI-E implementations.
 - nvidia followed the standard but did not include the host bridge
   at 0:00.0
 - Marvell ignored everything about the root complex config space
   behavior :)

There are two patch sets in this subject, one for nvidia tegra and one
for Marvell, both presenting to Linux a view of the HW that matches
what the PCI-E spec describes - specifically that there is one domain,
and each PCI-E link/controller shows up as a PCI-PCI bridge on bus 0.

In this model, there is no 'host bridge aperture' hardware, each PCI-E
link has a dedicated aperture and control of that aperture is through
the PCI-PCI bridge window registers, again as PCI-E specifies.

Jason

^ permalink raw reply

* [PATCH v2 19/27] pci: PCIe driver for Marvell Armada 370/XP systems
From: Jason Gunthorpe @ 2013-01-29  5:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAErSpo5H08j=dZx9zapDaf1c9x6VUfuJ5oB=J0M1UFF55pg=mw@mail.gmail.com>

On Mon, Jan 28, 2013 at 08:29:24PM -0700, Bjorn Helgaas wrote:
> On Mon, Jan 28, 2013 at 11:56 AM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com> wrote:
> > This driver implements the support for the PCIe interfaces on the
> > Marvell Armada 370/XP ARM SoCs. In the future, it might be extended to
> > cover earlier families of Marvell SoCs, such as Dove, Orion and
> > Kirkwood.
> >
> > The driver implements the hw_pci operations needed by the core ARM PCI
> > code to setup PCI devices and get their corresponding IRQs, and the
> > pci_ops operations that are used by the PCI core to read/write the
> > configuration space of PCI devices.
> >
> > Since the PCIe interfaces of Marvell SoCs are completely separate and
> > not linked together in a bus, this driver sets up an emulated PCI host
> > bridge, with one PCI-to-PCI bridge as child for each hardware PCIe
> > interface.
> 
> There's no Linux requirement that multiple PCIe interfaces appear to
> be in the same hierarchy.  You can just use pci_scan_root_bus()
> separately on each interface.  Each interface can be in its own domain
> if necessary.

What you suggest is basically what the Marvell driver did originally,
the probelm is that Linux requires a pre-assigned aperture for each
PCI domain/root bus, and these new chips have so many PCI-E ports that
they can exhaust the physical address space, and also a limited
internal HW resource for setting address routing.

Thus they require resource allocation that is sensitive to the devices
present downstream.

By far the simplest solution is to merge all the physical links into a
single domain and rely on existing PCI resource allocation code to
drive allocation of scarce physical address space and demand allocate
the HW routing resource (specifically there are enough resources to
accomidate MMIO only devices on every bus, but not enough to
accomidate MMIO and IO on every bus).

> > +/*
> > + * For a given PCIe interface (represented by a mvebu_pcie_port
> > + * structure), we read the PCI configuration space of the
> > + * corresponding PCI-to-PCI bridge in order to find out which range of
> > + * I/O addresses and memory addresses have been assigned to this PCIe
> > + * interface. Using these informations, we set up the appropriate
> > + * address decoding windows so that the physical address are actually
> > + * resolved to the right PCIe interface.
> > + */
> 
> Are you inferring the host bridge apertures by using the resources
> assigned to devices under the bridge, i.e., taking the union of all

The flow is different, a portion of physical address space is set
aside for use by PCI-E (via DT) and that portion is specified in the
struct resource's ultimately attached to the PCI domain for the bus
scan. You could call that the 'host bridge aperture' though it doesn't
reflect any HW configuration at all. The values come from the device
tree.

During the bus scan the Linux core code splits up that contiguous
space and assigns to the PCI-PCI bridges and devices under that domain.

Each physical PCI-E link on the chip is seen by Linux through the SW
emulated PCI-PCI bridge attached to bus 0. When Linux configures the
bridge windows it triggers this code here to copy that window
information from the PCI config space into non-standard internal HW
registers.

The purpose of the SW PCI-PCI bridge and this code here is to give
the Linux PCI core control over the window (MMIO,IO,busnr) assigned
to the PCI-E link.

This arrangement with PCI-PCI bridges controlling address routing is
part of the PCI-E standard, in this instance Marvell did not implement
the required config space in HW so the driver is working around that
deficiency.

Other drivers, like tegra have a similar design, but their hardware
does implement PCI-PCI bridge configuration space and does drive
address decoding through the HW PCI-PCI window registers.

Having PCI-E links be bridges, not domains/root_bus's is in-line with
the standard and works better with the Linux PCI resource allocator.

Jason

^ permalink raw reply

* [GIT PULL] imx6q cpuidle for 3.9
From: Shawn Guo @ 2013-01-29  5:46 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565:

  Linux 3.8-rc1 (2012-12-21 17:19:00 -0800)

are available in the git repository at:

  git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx6q-cpudile-3.9

for you to fetch changes up to e510aafde64a3fdd741f598e4d2be3c079bf5b0e:

  ARM: imx6q: support WAIT mode using cpuidle (2013-01-29 13:41:42 +0800)

----------------------------------------------------------------
It's imx6q cpuidle series for 3.9.

----------------------------------------------------------------
Shawn Guo (4):
      ARM: imx: return zero in case next event gets a large increment
      ARM: imx: mask gpc interrupts initially
      ARM: imx: move imx6q_cpuidle_driver into a separate file
      ARM: imx6q: support WAIT mode using cpuidle

 arch/arm/mach-imx/Makefile        |    6 ++-
 arch/arm/mach-imx/clk-imx6q.c     |   12 +++++
 arch/arm/mach-imx/common.h        |    3 ++
 arch/arm/mach-imx/cpuidle-imx6q.c |   95 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/cpuidle.h       |    5 ++
 arch/arm/mach-imx/gpc.c           |    5 ++
 arch/arm/mach-imx/mach-imx6q.c    |   17 +++----
 arch/arm/mach-imx/platsmp.c       |   10 ++++
 arch/arm/mach-imx/time.c          |    3 +-
 9 files changed, 143 insertions(+), 13 deletions(-)
 create mode 100644 arch/arm/mach-imx/cpuidle-imx6q.c

^ permalink raw reply

* [PATCH 0/3]  ARM:exynos5:power-domain: Save and restore CLK_TOP_SRC3 via clock framework.
From: Kukjin Kim @ 2013-01-29  5:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357736081-19390-1-git-send-email-prasanna.ps@samsung.com>

Prasanna Kumar wrote:
> 
> After Suspend-Resume operation of exynos5, CLK_TOP_SRC3 register
> modified
> while power gating G-scaler and MFC power domains.This is seen only after
> suspend and resume.
> 
> The solution to this problem is to save CLK_SRC_TOP3 register and restore
> it while powergating. But CLK_SRC_TOP3 register cannot accessed directly
> by power domain code.
> Please refer below URL to know the background of this issue.
> http://www.mail-archive.com/linux-samsung-
> soc at vger.kernel.org/msg14347.html.
> 
> This patch set adds clock framework support for save and restore
> clock register (CLK_SRC_TOP3)  for G-scaler and MFC power domains.
> 
> This patch set depends on
> http://www.mail-archive.com/linux-samsung-
> soc at vger.kernel.org/msg14648.html
> 
> Prasanna Kumar (3):
>   ARM: dts: exynos5: Add power domain clocks to pd node of Gscaler and
> MFC
>   ARM:exynos5:dts: Bindings for clock definitions are added.
>   ARM: exynos5: Add clock save and restore operation(CLK_SRC_TOP3) using
> clock framework.
> 
>  .../bindings/arm/exynos/power_domain.txt           |   14 ++
>  arch/arm/boot/dts/exynos5250.dtsi                  |    2 +
>  arch/arm/mach-exynos/pm_domains.c                  |  125
> ++++++++++++++++++++
>  3 files changed, 141 insertions(+), 0 deletions(-)
> 
> --
> 1.7.5.4

I think, you need to re-submit this after addressing comments from some
guys.

Thanks.

- Kukjin

^ permalink raw reply

* [PATCH V2 REPOST] i2c: add bcm2835 driver
From: Stephen Warren @ 2013-01-29  5:22 UTC (permalink / raw)
  To: linux-arm-kernel

This implements a very basic I2C host driver for the BCM2835 SoC. Missing
features so far are:

* 10-bit addressing.
* DMA.

Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
v2:
* Implemented clock divider configuration based on desired bus rate.
* Make use of module_platform_driver().
* Removed use of devinit.
---
 .../devicetree/bindings/i2c/brcm,bcm2835-i2c.txt   |   20 ++
 drivers/i2c/busses/Kconfig                         |   12 +
 drivers/i2c/busses/Makefile                        |    1 +
 drivers/i2c/busses/i2c-bcm2835.c                   |  346 ++++++++++++++++++++
 4 files changed, 379 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
 create mode 100644 drivers/i2c/busses/i2c-bcm2835.c

diff --git a/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
new file mode 100644
index 0000000..e9de375
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
@@ -0,0 +1,20 @@
+Broadcom BCM2835 I2C controller
+
+Required properties:
+- compatible : Should be "brcm,bcm2835-i2c".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks : The clock feeding the I2C controller.
+
+Recommended properties:
+- clock-frequency : desired I2C bus clock frequency in Hz.
+
+Example:
+
+i2c at 20205000 {
+	compatible = "brcm,bcm2835-i2c";
+	reg = <0x7e205000 0x1000>;
+	interrupts = <2 21>;
+	clocks = <&clk_i2c>;
+	clock-frequency = <100000>;
+};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8bb810e..3cc40ab 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -319,6 +319,18 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_BCM2835
+	tristate "Broadcom BCM2835 I2C controller"
+	depends on ARCH_BCM2835
+	help
+	  If you say yes to this option, support will be included for the
+	  BCM2835 I2C controller.
+
+	  If you don't know what to do here, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-bcm2835.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 6181f3f..a52a891 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 # Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
+obj-$(CONFIG_I2C_BCM2835)	+= i2c-bcm2835.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
new file mode 100644
index 0000000..22a29de
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -0,0 +1,346 @@
+/*
+ * BCM2835 master mode driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define BCM2835_I2C_C		0x0
+#define BCM2835_I2C_S		0x4
+#define BCM2835_I2C_DLEN	0x8
+#define BCM2835_I2C_A		0xc
+#define BCM2835_I2C_FIFO	0x10
+#define BCM2835_I2C_DIV		0x14
+#define BCM2835_I2C_DEL		0x18
+#define BCM2835_I2C_CLKT	0x1c
+
+#define BCM2835_I2C_C_READ	BIT(0)
+#define BCM2835_I2C_C_CLEAR	BIT(4) /* bits 4 and 5 both clear */
+#define BCM2835_I2C_C_ST	BIT(7)
+#define BCM2835_I2C_C_INTD	BIT(8)
+#define BCM2835_I2C_C_INTT	BIT(9)
+#define BCM2835_I2C_C_INTR	BIT(10)
+#define BCM2835_I2C_C_I2CEN	BIT(15)
+
+#define BCM2835_I2C_S_TA	BIT(0)
+#define BCM2835_I2C_S_DONE	BIT(1)
+#define BCM2835_I2C_S_TXW	BIT(2)
+#define BCM2835_I2C_S_RXR	BIT(3)
+#define BCM2835_I2C_S_TXD	BIT(4)
+#define BCM2835_I2C_S_RXD	BIT(5)
+#define BCM2835_I2C_S_TXE	BIT(6)
+#define BCM2835_I2C_S_RXF	BIT(7)
+#define BCM2835_I2C_S_ERR	BIT(8)
+#define BCM2835_I2C_S_CLKT	BIT(9)
+#define BCM2835_I2C_S_LEN	BIT(10) /* Fake bit for SW error reporting */
+
+#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+struct bcm2835_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *clk;
+	struct i2c_adapter adapter;
+	struct completion completion;
+	u32 msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+};
+
+static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
+				      u32 reg, u32 val)
+{
+	writel(val, i2c_dev->regs + reg);
+}
+
+static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
+{
+	return readl(i2c_dev->regs + reg);
+}
+
+static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_TXD))
+			break;
+		bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO,
+				   *i2c_dev->msg_buf);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_RXD))
+			break;
+		*i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev,
+						      BCM2835_I2C_FIFO);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+{
+	struct bcm2835_i2c_dev *i2c_dev = data;
+	u32 val, err;
+
+	val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
+
+	err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+	if (err) {
+		i2c_dev->msg_err = err;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_RXD) {
+		bcm2835_drain_rxfifo(i2c_dev);
+		if (!(val & BCM2835_I2C_S_DONE))
+			return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_DONE) {
+		if (i2c_dev->msg_buf_remaining)
+			i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+		else
+			i2c_dev->msg_err = 0;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_TXD) {
+		bcm2835_fill_txfifo(i2c_dev);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+				struct i2c_msg *msg)
+{
+	u32 c;
+	int ret;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	INIT_COMPLETION(i2c_dev->completion);
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+
+	if (msg->flags & I2C_M_RD) {
+		c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+	} else {
+		c = BCM2835_I2C_C_INTT;
+		bcm2835_fill_txfifo(i2c_dev);
+	}
+	c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+
+	ret = wait_for_completion_timeout(&i2c_dev->completion,
+					  BCM2835_I2C_TIMEOUT);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	if (likely(!i2c_dev->msg_err))
+		return 0;
+
+	if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
+	    (msg->flags & I2C_M_IGNORE_NAK))
+		return 0;
+
+	dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+	if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+		return -EREMOTEIO;
+	else
+		return -EIO;
+}
+
+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
+		if (ret)
+			break;
+	}
+
+	return ret ?: i;
+}
+
+static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm bcm2835_i2c_algo = {
+	.master_xfer	= bcm2835_i2c_xfer,
+	.functionality	= bcm2835_i2c_func,
+};
+
+static int bcm2835_i2c_probe(struct platform_device *pdev)
+{
+	struct bcm2835_i2c_dev *i2c_dev;
+	struct resource *mem, *requested, *irq;
+	u32 bus_clk_rate, divider;
+	int ret;
+	struct i2c_adapter *adap;
+
+	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+	if (!i2c_dev) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_dev\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, i2c_dev);
+	i2c_dev->dev = &pdev->dev;
+	init_completion(&i2c_dev->completion);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No mem resource\n");
+		return -ENODEV;
+	}
+
+	requested = devm_request_mem_region(&pdev->dev, mem->start,
+					    resource_size(mem),
+					    dev_name(&pdev->dev));
+	if (!requested) {
+		dev_err(&pdev->dev, "Could not claim register region\n");
+		return -EBUSY;
+	}
+
+	i2c_dev->regs = devm_ioremap(&pdev->dev, mem->start,
+				     resource_size(mem));
+	if (!i2c_dev->regs) {
+		dev_err(&pdev->dev, "Could not map registers\n");
+		return -ENOMEM;
+	}
+
+	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->clk)) {
+		dev_err(&pdev->dev, "Could not get clock\n");
+		return PTR_ERR(i2c_dev->clk);
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+				   &bus_clk_rate);
+	if (ret < 0) {
+		dev_warn(&pdev->dev,
+			 "Could not read clock-frequency property\n");
+		bus_clk_rate = 100000;
+	}
+
+	divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
+	/*
+	 * Per the datasheet, the register is always interpreted as an even
+	 * number, by rounding down. In other words, the LSB is ignored. So,
+	 * if the LSB is set, increment the divider to avoid any issue.
+	 */
+	if (divider & 1)
+		divider++;
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "No IRQ resource\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq->start, bcm2835_i2c_isr,
+			       IRQF_SHARED, dev_name(&pdev->dev), i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not request IRQ\n");
+		return -ENODEV;
+	}
+
+	adap = &i2c_dev->adapter;
+	i2c_set_adapdata(adap, i2c_dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
+	adap->algo = &bcm2835_i2c_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->nr = -1;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
+
+	ret = i2c_add_numbered_adapter(adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not add adapter\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int bcm2835_i2c_remove(struct platform_device *pdev)
+{
+	struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c_dev->adapter);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_i2c_of_match[] = {
+	{ .compatible = "brcm,bcm2835-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match);
+
+static struct platform_driver bcm2835_i2c_driver = {
+	.probe		= bcm2835_i2c_probe,
+	.remove		= bcm2835_i2c_remove,
+	.driver		= {
+		.name	= "i2c-bcm2835",
+		.owner	= THIS_MODULE,
+		.of_match_table = bcm2835_i2c_of_match,
+	},
+};
+module_platform_driver(bcm2835_i2c_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
+MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:i2c-bcm2835");
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/2] arm: exynos5: Enable PM generic domain support in Kconfig
From: Kukjin Kim @ 2013-01-29  5:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357733733-18769-2-git-send-email-prasanna.ps@samsung.com>

Prasanna Kumar wrote:
> 
> This patch adds support to enable PM generic domains
> under Exynos5 family
> 
> Signed-off-by: Prasanna Kumar <prasanna.ps@samsung.com>
> ---
>  arch/arm/mach-exynos/Kconfig |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-
> exynos/Kconfig
> index e103c29..871be97 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -63,6 +63,7 @@ config SOC_EXYNOS5250
>  	depends on ARCH_EXYNOS5
>  	select S5P_PM if PM
>  	select S5P_SLEEP if PM
> +	select PM_GENERIC_DOMAINS if PM
>  	select S5P_DEV_MFC
>  	select SAMSUNG_DMADEV
>  	help
> --
> 1.7.5.4

Firstly, this patch can be squashed into 2nd one.
Secondly, please put the statements alphanumerically.
Finally, please use the same format for subject like following:
"ARM: EXYNOS: ..."

Thanks.

- Kukjin

^ permalink raw reply

* [PATCH 2/2] ARM: davinci: da850: configure CS2(aemif) for norflash
From: Kumar, Anil @ 2013-01-29  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359436796-25135-1-git-send-email-anilkumar.v@ti.com>

Configure 16 bit data bus width for CS2(aemif) to use the norflash on
DA850.

Signed-off-by: Kumar, Anil <anilkumar.v@ti.com>
---
:100644 100644 37c27af... 540e284... M	arch/arm/mach-davinci/da8xx-dt.c
 arch/arm/mach-davinci/da8xx-dt.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 37c27af..540e284 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -38,12 +38,29 @@ static void __init da8xx_init_irq(void)
 }
 
 #ifdef CONFIG_ARCH_DAVINCI_DA850
+#define DA8XX_AEMIF_CE2CFG_OFFSET       0x10
+#define DA8XX_AEMIF_ASIZE_16BIT         0x1
+
+static void __init da8xx_init_nor(void)
+{
+	void __iomem *aemif_addr;
+
+	aemif_addr = ioremap(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+
+	/* Configure data bus width of CS2 to 16 bit */
+	writel(readl(aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET) |
+			DA8XX_AEMIF_ASIZE_16BIT,
+			aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET);
+
+	iounmap(aemif_addr);
+}
 
 static void __init da850_init_machine(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
 	da8xx_uart_clk_enable();
+	da8xx_init_nor();
 }
 
 static const char *da850_boards_compat[] __initdata = {
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 1/2] ARM: davinci: da850 evm: add norflash DT node
From: Kumar, Anil @ 2013-01-29  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359436796-25135-1-git-send-email-anilkumar.v@ti.com>

Add norflash DT node on DA850 EVM and related pin mux.

Signed-off-by: Kumar, Anil <anilkumar.v@ti.com>
---
:100644 100644 087ba28... 95ffeca... M	arch/arm/boot/dts/da850-evm.dts
:100644 100644 160ebac... 036b02a... M	arch/arm/boot/dts/da850.dtsi
 arch/arm/boot/dts/da850-evm.dts |   25 +++++++++++++++++++++++
 arch/arm/boot/dts/da850.dtsi    |   41 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 087ba28..95ffeca 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -28,4 +28,29 @@
 			status = "okay";
 		};
 	};
+	norflash_cs2 at 60000000 {
+		compatible = "intel,PC28F640P30T85", "cfi-flash";
+		reg = <0x60000000 0x1FFFFFF>;
+		bank-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		linux,mtd-name = "physmap-flash";
+		pinctrl-names = "default";
+		pinctrl-0 = <&norflash_cs2_pins>;
+
+		bootloaders_env at 0 {
+			label = "bootloaders_env";
+			reg = <0 0x80000>;
+		};
+
+		kernel at 80000 {
+			label = "kernel";
+			reg = <0x80000 0x200000>;
+		};
+
+		filesystem at 280000 {
+			label = "filesystem";
+			reg = <0x280000 0x580000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 160ebac..036b02a 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -38,6 +38,47 @@
 			pinctrl-single,register-width = <32>;
 			pinctrl-single,function-mask = <0xffffffff>;
 			status = "disabled";
+
+			norflash_cs2_pins: pinmux_norflash_pins{
+				pinctrl-single,bits = <
+					/* EMA_BA[1] */
+					0x14 0x01000000 0x0f000000
+					/* EMA_CLK, EMA_WAIT[1] */
+					0x18 0x01000001 0x0f00000f
+					/* EMA_OE, EMA_WE, EMA_CS[2] */
+					0x1c 0x00110001 0x00ff000f
+					/*
+					 * EMA_D[0], EMA_D[1], EMA_D[2],
+					 * EMA_D[3], EMA_D[4], EMA_D[5],
+					 * EMA_D[6], EMA_D[7]
+					 */
+					0x24 0x11111111 0xffffffff
+					/*
+					 * EMA_D[8], EMA_D[9], EMA_D[10],
+					 * EMA_D[11], EMA_D[12], EMA_D[13],
+					 * EMA_D[14], EMA_D[15]
+					 */
+					0x20 0x11111111 0xffffffff
+					/*
+					 * EMA_A[0], EMA_A[1], EMA_A[2],
+					 * EMA_A[3], EMA_A[4], EMA_A[5],
+					 * EMA_A[6], EMA_A[7]
+					 */
+					0x30 0x11111111 0xffffffff
+					/*
+					 * EMA_A[8], EMA_A[9], EMA_A[10],
+					 * EMA_A[11], EMA_A[12], EMA_A[13],
+					 * EMA_A[14], EMA_A[15]
+					 */
+					0x2c 0x11111111 0xffffffff
+					/*
+					 * EMA_A[16], EMA_A[17], EMA_A[18],
+					 * EMA_A[19], EMA_A[20], EMA_A[21],
+					 * EMA_A[22]
+					 */
+					0x28 0x11111110 0xfffffff0
+				>;
+			};
 		};
 		serial0: serial at 1c42000 {
 			compatible = "ns16550a";
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 0/2] DaVinci: da850: Add NOR flash DT node support
From: Kumar, Anil @ 2013-01-29  5:19 UTC (permalink / raw)
  To: linux-arm-kernel

Add NOR flash DT node support for DA850 EVM and related pin mux.
Configure 16 bit data bus width for CS2(aemif) to use the norflash on
DA850.

This series is based on top of 3.8-rc4 and the following patches.

 -drivers/pinctrl: grab default handles from device core
  https://patchwork.kernel.org/patch/1862231/
 -ARM: davinci: da850: add pinctrl driver DT entries

Tested on DA850 EVM.

Kumar, Anil (2):
  ARM: davinci: da850 evm: add norflash DT node
  ARM: davinci: da850: configure CS2(aemif) for norflash

 arch/arm/boot/dts/da850-evm.dts  |   25 +++++++++++++++++++++++
 arch/arm/boot/dts/da850.dtsi     |   41 ++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-davinci/da8xx-dt.c |   17 +++++++++++++++
 3 files changed, 83 insertions(+), 0 deletions(-)

-- 
1.7.4.1

^ permalink raw reply

* [PATCH] ARM: gic: add irq_set_affinity to gic_arch_extn
From: Chao Xie @ 2013-01-29  5:17 UTC (permalink / raw)
  To: linux-arm-kernel

gic_arch_extn is used for ARCH specific interrupt controller.
It has added the callbacks for irq_mask/irq_unamsk and so, but
irq_set_affinity is not used.
For SMP architecure, when both cores are powered off, the GIC may
be powered off too. An external interrupt controller can be used
as a logic to detect the interrupt and acknowledge power managment
unitto wake up core.
Because the irqs may be bound to different cors, when set irq
affinity, the external interrupt controller should be set too. Then
it can acknowledge the power managment unit to wake up correct core.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 arch/arm/common/gic.c |   17 +++++++++++------
 1 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 36ae03a..8e4bc8a 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -82,12 +82,15 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
  * Default make them NULL.
  */
 struct irq_chip gic_arch_extn = {
-	.irq_eoi	= NULL,
-	.irq_mask	= NULL,
-	.irq_unmask	= NULL,
-	.irq_retrigger	= NULL,
-	.irq_set_type	= NULL,
-	.irq_set_wake	= NULL,
+	.irq_eoi		= NULL,
+	.irq_mask		= NULL,
+	.irq_unmask		= NULL,
+	.irq_retrigger		= NULL,
+	.irq_set_type		= NULL,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= NULL,
+#endif
+	.irq_set_wake		= NULL,
 };
 
 #ifndef MAX_GIC_NR
@@ -253,6 +256,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 	bit = gic_cpu_map[cpu] << shift;
 
 	raw_spin_lock(&irq_controller_lock);
+	if (gic_arch_extn.irq_set_affinity)
+		return gic_arch_extn.irq_set_affinity(d, mask_val, force);
 	val = readl_relaxed(reg) & ~mask;
 	writel_relaxed(val | bit, reg);
 	raw_spin_unlock(&irq_controller_lock);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 2/2] drivers: net:ethernet: cpsw: add support for VLAN
From: Mugunthan V N @ 2013-01-29  5:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130128204446.GB5509@arwen.pp.htv.fi>

On 1/29/2013 2:14 AM, Felipe Balbi wrote:
> On Tue, Jan 29, 2013 at 01:42:25AM +0530, Mugunthan V N wrote:
>> adding support for VLAN interface for cpsw.
>>
>> CPSW VLAN Capability
>> * Can filter VLAN packets in Hardware
>>
>> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> ---
>>   Documentation/devicetree/bindings/net/cpsw.txt |    2 +
>>   drivers/net/ethernet/ti/cpsw.c                 |  108 +++++++++++++++++++++++-
>>   include/linux/platform_data/cpsw.h             |    1 +
>>   3 files changed, 110 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>> index 6ddd028..99696bf 100644
>> --- a/Documentation/devicetree/bindings/net/cpsw.txt
>> +++ b/Documentation/devicetree/bindings/net/cpsw.txt
>> @@ -24,6 +24,8 @@ Required properties:
>>   Optional properties:
>>   - ti,hwmods		: Must be "cpgmac0"
>>   - no_bd_ram		: Must be 0 or 1
>> +- default_vlan		: Specifies Default VLAN for non tagged packets
>> +			  ALE processing
>>   
>>   Note: "ti,hwmods" field is used to fetch the base address and irq
>>   resources from TI, omap hwmod data base during device registration.
>> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>> index b35e6a7..dee6951 100644
>> --- a/drivers/net/ethernet/ti/cpsw.c
>> +++ b/drivers/net/ethernet/ti/cpsw.c
>> @@ -32,6 +32,7 @@
>>   #include <linux/of.h>
>>   #include <linux/of_net.h>
>>   #include <linux/of_device.h>
>> +#include <linux/if_vlan.h>
>>   
>>   #include <linux/platform_data/cpsw.h>
>>   
>> @@ -72,6 +73,11 @@ do {								\
>>   		dev_notice(priv->dev, format, ## __VA_ARGS__);	\
>>   } while (0)
>>   
>> +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
> use IS_ENABLED() instead.
Will change this in next patch version.
>
>> +#define VLAN_SUPPORT
>> +#define CPSW_VLAN_AWARE_MODE
>> +#endif
>> +
>>   #define ALE_ALL_PORTS		0x7
>>   
>>   #define CPSW_MAJOR_VERSION(reg)		(reg >> 8 & 0x7)
>> @@ -118,6 +124,14 @@ do {								\
>>   #define TX_PRIORITY_MAPPING	0x33221100
>>   #define CPDMA_TX_PRIORITY_MAP	0x76543210
>>   
>> +#ifdef CPSW_VLAN_AWARE_MODE
>> +#define CPSW_VLAN_AWARE		BIT(1)
>> +#define CPSW_ALE_VLAN_AWARE	1
>> +#else
>> +#define CPSW_VLAN_AWARE		0x0
>> +#define CPSW_ALE_VLAN_AWARE	0
>> +#endif
> you should really figure out a way of doing runtime detection for this.
> Depending on driver recompilation just to enable/disable VLAN support
> will be quite boring.
I am not able to find a way to know whether stack is compiled with VLAN 
support or not
without using VLAN_SUPPORT compiler option. Only way is to hack 
cpsw_ndo_vlan_rx_add_vid
and know whether stack has VLAN capability or not which is not advisable.

Regards
Mugunthan V N

^ permalink raw reply

* [PATCH v3 1/1 net-next] net: fec: add napi support to improve proformance
From: Frank Li @ 2013-01-29  5:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130125222306.GA2523@electric-eye.fr.zoreil.com>

2013/1/26 Francois Romieu <romieu@fr.zoreil.com>:
> Waskiewicz Jr, Peter P <peter.p.waskiewicz.jr@intel.com> :
> [...]
>> Also, when you're disabling interrupts above, you're doing that in your
>> HW interrupt handler, you should be using spin_lock_irqsave()/irq_restore().
>
> Does the platform forbid to defer FEC_EIR / FEC_IEVENT write to the napi

I can clean FEC_IEVENT, but rx irq still issue if new package
received. I tested, performance drop if just clean FEC_IEVENT

> poll handler and only disable the irq through FEC_EIMR / FEC_IMASK in
> fec_enet_interrupt so as to remove the spinlock ?

I can remove this spin lock in other way.  I will send new patch.

>
> (Frank, please keep an empty line between variables declarations and
> function body).

Okay.

>
> --
> Ueimor

^ permalink raw reply

* [PATCH v2] cpufreq: instantiate cpufreq-cpu0 as a platform_driver
From: Viresh Kumar @ 2013-01-29  4:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359428020-21068-1-git-send-email-shawn.guo@linaro.org>

On Tue, Jan 29, 2013 at 8:23 AM, Shawn Guo <shawn.guo@linaro.org> wrote:
> As multiplatform build is being adopted by more and more ARM platforms,
> initcall function should be used very carefully.  For example, when
> GENERIC_CPUFREQ_CPU0 is built in the kernel, cpu0_cpufreq_driver_init()
> will be called on all the platforms to initialize cpufreq-cpu0 driver.
>
> To eliminate this undesired the effect, the patch changes cpufreq-cpu0
> driver to have it instantiated as a platform_driver.  Then it will only
> run on platforms that create the platform_device "cpufreq-cpu0".
>
> Along with the change, it also changes cpu_dev to be &pdev->dev,
> so that managed functions can start working, and module build gets
> supported too.
>
> The existing users of cpufreq-cpu0 driver highbank and am33xx are also
> updated accordingly to adapt the changes.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Mark Langsdorf <mark.langsdorf@calxeda.com>
> Cc: AnilKumar Ch <anilkumar@ti.com>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>

^ permalink raw reply

* [PATCH v4 1/1 net-next] net: fec: add napi support to improve proformance
From: Frank Li @ 2013-01-29  4:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add napi support

Before this patch

 iperf -s -i 1
 ------------------------------------------------------------
 Server listening on TCP port 5001
 TCP window size: 85.3 KByte (default)
 ------------------------------------------------------------
 [  4] local 10.192.242.153 port 5001 connected with 10.192.242.138 port 50004
 [ ID] Interval       Transfer     Bandwidth
 [  4]  0.0- 1.0 sec  41.2 MBytes   345 Mbits/sec
 [  4]  1.0- 2.0 sec  43.7 MBytes   367 Mbits/sec
 [  4]  2.0- 3.0 sec  42.8 MBytes   359 Mbits/sec
 [  4]  3.0- 4.0 sec  43.7 MBytes   367 Mbits/sec
 [  4]  4.0- 5.0 sec  42.7 MBytes   359 Mbits/sec
 [  4]  5.0- 6.0 sec  43.8 MBytes   367 Mbits/sec
 [  4]  6.0- 7.0 sec  43.0 MBytes   361 Mbits/sec

After this patch
 [  4]  2.0- 3.0 sec  51.6 MBytes   433 Mbits/sec
 [  4]  3.0- 4.0 sec  51.8 MBytes   435 Mbits/sec
 [  4]  4.0- 5.0 sec  52.2 MBytes   438 Mbits/sec
 [  4]  5.0- 6.0 sec  52.1 MBytes   437 Mbits/sec
 [  4]  6.0- 7.0 sec  52.1 MBytes   437 Mbits/sec
 [  4]  7.0- 8.0 sec  52.3 MBytes   439 Mbits/sec

Signed-off-by: Frank Li <Frank.Li@freescale.com>
Signed-off-by: Fugang Duan <B38611@freescale.com>
---
Change from v3 to v4
 * remove lock to enable\disable rx irq. write expected reg value directly,
   avoid read and write back. 
 
Change from v2 to v3
 * replace fec_enet_rx_int_is_enabled with fec_enet_rx_int_enable
 * replace spin_lock_saveirq with spin_lock in irq handle

Change from v1 to v2
 * Remove use_napi and napi_weight config. Support NAPI only.
 * using napi_gro_receive replace netif_rx

 drivers/net/ethernet/freescale/fec.c |   41 ++++++++++++++++++++++++++++-----
 drivers/net/ethernet/freescale/fec.h |    2 +
 2 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index f52ba33..0287675 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -67,6 +67,7 @@
 #endif
 
 #define DRIVER_NAME	"fec"
+#define FEC_NAPI_WEIGHT	64
 
 /* Pause frame feild and FIFO threshold */
 #define FEC_ENET_FCE	(1 << 5)
@@ -168,6 +169,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
 
 #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
+#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
 
 /* The FEC stores dest/src/type, data, and checksum for receive packets.
  */
@@ -656,8 +658,8 @@ fec_enet_tx(struct net_device *ndev)
  * not been given to the system, we just set the empty indicator,
  * effectively tossing the packet.
  */
-static void
-fec_enet_rx(struct net_device *ndev)
+static int
+fec_enet_rx(struct net_device *ndev, int budget)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
@@ -667,13 +669,12 @@ fec_enet_rx(struct net_device *ndev)
 	struct	sk_buff	*skb;
 	ushort	pkt_len;
 	__u8 *data;
+	int	pkt_received = 0;
 
 #ifdef CONFIG_M532x
 	flush_cache_all();
 #endif
 
-	spin_lock(&fep->hw_lock);
-
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
 	 */
@@ -681,6 +682,10 @@ fec_enet_rx(struct net_device *ndev)
 
 	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
+		if (pkt_received >= budget)
+			break;
+		pkt_received++;
+
 		/* Since we have allocated space to hold a complete frame,
 		 * the last indicator should be set.
 		 */
@@ -762,7 +767,7 @@ fec_enet_rx(struct net_device *ndev)
 			}
 
 			if (!skb_defer_rx_timestamp(skb))
-				netif_rx(skb);
+				napi_gro_receive(&fep->napi, skb);
 		}
 
 		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
@@ -796,7 +801,7 @@ rx_processing_done:
 	}
 	fep->cur_rx = bdp;
 
-	spin_unlock(&fep->hw_lock);
+	return pkt_received;
 }
 
 static irqreturn_t
@@ -813,7 +818,13 @@ fec_enet_interrupt(int irq, void *dev_id)
 
 		if (int_events & FEC_ENET_RXF) {
 			ret = IRQ_HANDLED;
-			fec_enet_rx(ndev);
+
+			/* Disable the RX interrupt */
+			if (napi_schedule_prep(&fep->napi)) {
+				writel(FEC_RX_DISABLED_IMASK,
+					fep->hwp + FEC_IMASK);
+				__napi_schedule(&fep->napi);
+			}
 		}
 
 		/* Transmit OK, or non-fatal error. Update the buffer
@@ -834,7 +845,18 @@ fec_enet_interrupt(int irq, void *dev_id)
 	return ret;
 }
 
+static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
+{
+	struct net_device *ndev = napi->dev;
+	int pkts = fec_enet_rx(ndev, budget);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	if (pkts < budget) {
+		napi_complete(napi);
+		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+	}
+	return pkts;
+}
 
 /* ------------------------------------------------------------------------- */
 static void fec_get_mac(struct net_device *ndev)
@@ -1392,6 +1414,8 @@ fec_enet_open(struct net_device *ndev)
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int ret;
 
+	napi_enable(&fep->napi);
+
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
@@ -1604,6 +1628,9 @@ static int fec_enet_init(struct net_device *ndev)
 	ndev->netdev_ops = &fec_netdev_ops;
 	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
+	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
+	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
+
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
 	for (i = 0; i < RX_RING_SIZE; i++) {
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 2ebedaf..01579b8 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -249,6 +249,8 @@ struct fec_enet_private {
 	int	bufdesc_ex;
 	int	pause_flag;
 
+	struct	napi_struct napi;
+
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_caps;
 	unsigned long last_overflow_check;
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 0/4] Add support for LZ4-compressed kernels
From: Nicolas Pitre @ 2013-01-29  4:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130128142510.68092e10.akpm@linux-foundation.org>

On Mon, 28 Jan 2013, Andrew Morton wrote:

> On Sat, 26 Jan 2013 14:50:43 +0900
> Kyungsik Lee <kyungsik.lee@lge.com> wrote:
> 
> > This patchset is for supporting LZ4 compressed kernel and initial ramdisk on
> > the x86 and ARM architectures.
> > 
> > According to http://code.google.com/p/lz4/, LZ4 is a very fast lossless
> > compression algorithm and also features an extremely fast decoder.
> > 
> > Kernel Decompression APIs are based on implementation by Yann Collet
> > (http://code.google.com/p/lz4/source/checkout).
> > De/compression Tools are also provided from the site above.
> > 
> > The initial test result on ARM(v7) based board shows that the size of kernel
> > with LZ4 compressed is 8% bigger than LZO compressed  but the decompressing
> > speed is faster(especially under the enabled unaligned memory access).
> > 
> > Test: 3.4 based kernel built with many modules
> > Uncompressed kernel size: 13MB
> > lzo: 6.3MB, 301ms
> > lz4: 6.8MB, 251ms(167ms, with enabled unaligned memory access)
> > 
> > It seems that it___s worth trying LZ4 compressed kernel image or ramdisk 
> > for making the kernel boot more faster.
> >
> > ...
> >
> >  20 files changed, 663 insertions(+), 3 deletions(-)
> >
> > ...
> >
> 
> What's this "with enabled unaligned memory access" thing?  You mean "if
> the arch supports CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS"?  If so,
> that's only x86, which isn't really in the target market for this
> patch, yes?

I'm guessing this is referring to commit 5010192d5a.

> It's a lot of code for a 50ms boot-time improvement.  Does anyone have
> any opinions on whether or not the benefits are worth the cost?

Well, we used to have only one compressed format.  Now we have nearly 
half a dozen, with the same worthiness issue between themselves.  
Either we keep it very simple, or we make it very flexible.  The former 
would argue in favor of removing some of the existing formats, the later 
would let this new format in.


Nicolas

^ permalink raw reply

* [PATCH v2 19/27] pci: PCIe driver for Marvell Armada 370/XP systems
From: Bjorn Helgaas @ 2013-01-29  3:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359399397-29729-20-git-send-email-thomas.petazzoni@free-electrons.com>

On Mon, Jan 28, 2013 at 11:56 AM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> This driver implements the support for the PCIe interfaces on the
> Marvell Armada 370/XP ARM SoCs. In the future, it might be extended to
> cover earlier families of Marvell SoCs, such as Dove, Orion and
> Kirkwood.
>
> The driver implements the hw_pci operations needed by the core ARM PCI
> code to setup PCI devices and get their corresponding IRQs, and the
> pci_ops operations that are used by the PCI core to read/write the
> configuration space of PCI devices.
>
> Since the PCIe interfaces of Marvell SoCs are completely separate and
> not linked together in a bus, this driver sets up an emulated PCI host
> bridge, with one PCI-to-PCI bridge as child for each hardware PCIe
> interface.

There's no Linux requirement that multiple PCIe interfaces appear to
be in the same hierarchy.  You can just use pci_scan_root_bus()
separately on each interface.  Each interface can be in its own domain
if necessary.

> In addition, this driver enumerates the different PCIe slots, and for
> those having a device plugged in, it sets up the necessary address
> decoding windows, using the new armada_370_xp_alloc_pcie_window()
> function from mach-mvebu/addr-map.c.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
>  .../devicetree/bindings/pci/armada-370-xp-pcie.txt |  175 +++++++
>  drivers/pci/host/Kconfig                           |    6 +
>  drivers/pci/host/Makefile                          |    4 +
>  drivers/pci/host/pci-mvebu.c                       |  500 ++++++++++++++++++++
>  4 files changed, 685 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
>  create mode 100644 drivers/pci/host/Makefile
>  create mode 100644 drivers/pci/host/pci-mvebu.c
>
> diff --git a/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
> new file mode 100644
> index 0000000..9313e92
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
> @@ -0,0 +1,175 @@
> +* Marvell Armada 370/XP PCIe interfaces
> +
> +Mandatory properties:
> +- compatible: must be "marvell,armada-370-xp-pcie"
> +- status: either "disabled" or "okay"
> +- #address-cells, set to <3>
> +- #size-cells, set to <2>
> +- #interrupt-cells, set to <1>
> +- bus-range: PCI bus numbers covered
> +- ranges: standard PCI-style address ranges, describing the PCIe
> +  registers for each PCIe interface, and then ranges for the PCI
> +  memory and I/O regions.
> +- interrupt-map-mask and interrupt-map are standard PCI Device Tree
> +  properties to describe the interrupts associated to each PCI
> +  interface.
> +
> +In addition, the Device Tree node must have sub-nodes describing each
> +PCIe interface, having the following mandatory properties:
> +- reg: the address and size of the PCIe registers (translated
> +  addresses according to the ranges property of the parent)
> +- clocks: the clock associated to this PCIe interface
> +- marvell,pcie-port: the physical PCIe port number
> +- status: either "disabled" or "okay"
> +
> +and the following optional properties:
> +- marvell,pcie-lane: the physical PCIe lane number, for ports having
> +  multiple lanes. If this property is not found, we assume that the
> +  value is 0.
> +
> +Example:
> +
> +pcie-controller {
> +       compatible = "marvell,armada-370-xp-pcie";
> +       status = "disabled";
> +
> +       #address-cells = <3>;
> +       #size-cells = <2>;
> +
> +       bus-range = <0x00 0xff>;
> +
> +       ranges = <0x00000800 0 0xd0040000 0xd0040000 0 0x00002000   /* port 0.0 registers */
> +                 0x00004800 0 0xd0042000 0xd0042000 0 0x00002000   /* port 2.0 registers */
> +                 0x00001000 0 0xd0044000 0xd0044000 0 0x00002000   /* port 0.1 registers */
> +                 0x00001800 0 0xd0048000 0xd0048000 0 0x00002000   /* port 0.2 registers */
> +                 0x00002000 0 0xd004C000 0xd004C000 0 0x00002000   /* port 0.3 registers */
> +                 0x00002800 0 0xd0080000 0xd0080000 0 0x00002000   /* port 1.0 registers */
> +                 0x00005000 0 0xd0082000 0xd0082000 0 0x00002000   /* port 3.0 registers */
> +                 0x00003000 0 0xd0084000 0xd0084000 0 0x00002000   /* port 1.1 registers */
> +                 0x00003800 0 0xd0088000 0xd0088000 0 0x00002000   /* port 1.2 registers */
> +                 0x00004000 0 0xd008C000 0xd008C000 0 0x00002000   /* port 1.3 registers */
> +                 0x81000000 0 0          0xc0000000 0 0x00100000   /* downstream I/O */
> +                 0x82000000 0 0          0xc1000000 0 0x08000000>; /* non-prefetchable memory */
> +
> +       #interrupt-cells = <1>;
> +       interrupt-map-mask = <0xf800 0 0 1>;
> +       interrupt-map = <0x0800 0 0 1 &mpic 58
> +                        0x1000 0 0 1 &mpic 59
> +                        0x1800 0 0 1 &mpic 60
> +                        0x2000 0 0 1 &mpic 61
> +                        0x2800 0 0 1 &mpic 62
> +                        0x3000 0 0 1 &mpic 63
> +                        0x3800 0 0 1 &mpic 64
> +                        0x4000 0 0 1 &mpic 65
> +                        0x4800 0 0 1 &mpic 99
> +                        0x5000 0 0 1 &mpic 103>;
> +
> +       pcie at 0,0 {
> +               device_type = "pciex";
> +               reg = <0x0800 0 0xd0040000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <0>;
> +               marvell,pcie-lane = <0>;
> +               clocks = <&gateclk 5>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 0,1 {
> +               device_type = "pciex";
> +               reg = <0x1000 0 0xd0044000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <0>;
> +               marvell,pcie-lane = <1>;
> +               clocks = <&gateclk 6>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 0,2 {
> +               device_type = "pciex";
> +               reg = <0x1800 0 0xd0048000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <0>;
> +               marvell,pcie-lane = <2>;
> +               clocks = <&gateclk 7>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 0,3 {
> +               device_type = "pciex";
> +               reg = <0x2000 0 0xd004C000 0 0xC000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <0>;
> +               marvell,pcie-lane = <3>;
> +               clocks = <&gateclk 8>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 1,0 {
> +               device_type = "pciex";
> +               reg = <0x2800 0 0xd0080000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <1>;
> +               marvell,pcie-lane = <0>;
> +               clocks = <&gateclk 9>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 1,1 {
> +               device_type = "pciex";
> +               reg = <0x3000 0 0xd0084000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <1>;
> +               marvell,pcie-lane = <1>;
> +               clocks = <&gateclk 10>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 1,2 {
> +               device_type = "pciex";
> +               reg = <0x3800 0 0xd0088000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <1>;
> +               marvell,pcie-lane = <2>;
> +               clocks = <&gateclk 11>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 1,3 {
> +               device_type = "pciex";
> +               reg = <0x4000 0 0xd008C000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <1>;
> +               marvell,pcie-lane = <3>;
> +               clocks = <&gateclk 12>;
> +               status = "disabled";
> +       };
> +       pcie at 2,0 {
> +               device_type = "pciex";
> +               reg = <0x4800 0 0xd0042000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <2>;
> +               marvell,pcie-lane = <0>;
> +               clocks = <&gateclk 26>;
> +               status = "disabled";
> +       };
> +
> +       pcie at 3,0 {
> +               device_type = "pciex";
> +               reg = <0x5000 0 0xd0082000 0 0x2000>;
> +               #address-cells = <3>;
> +               #size-cells = <2>;
> +               marvell,pcie-port = <3>;
> +               marvell,pcie-lane = <0>;
> +               clocks = <&gateclk 27>;
> +               status = "disabled";
> +       };
> +};
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index cc3a1af..03e15e7 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -1,4 +1,10 @@
>  menu "PCI host controller drivers"
>         depends on PCI
>
> +config PCI_MVEBU
> +       bool "Marvell EBU PCIe controller"
> +       depends on ARCH_MVEBU
> +       select PCI_SW_HOST_BRIDGE
> +       select PCI_SW_PCI_PCI_BRIDGE
> +
>  endmenu
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> new file mode 100644
> index 0000000..34d6057
> --- /dev/null
> +++ b/drivers/pci/host/Makefile
> @@ -0,0 +1,4 @@
> +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> +ccflags-$(CONFIG_PCI_MVEBU) += \
> +       -I$(srctree)/arch/arm/plat-orion/include \
> +       -I$(srctree)/arch/arm/mach-mvebu/include
> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> new file mode 100644
> index 0000000..4db09e1
> --- /dev/null
> +++ b/drivers/pci/host/pci-mvebu.c
> @@ -0,0 +1,500 @@
> +/*
> + * PCIe driver for Marvell Armada 370 and Armada XP SoCs
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_address.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <plat/pcie.h>
> +#include <mach/addr-map.h>
> +
> +/*
> + * Those are the product IDs used for the emulated PCI Host bridge and
> + * emulated PCI-to-PCI bridges. They are temporary until we get
> + * official IDs assigned.
> + */
> +#define MARVELL_EMULATED_HOST_BRIDGE_ID    4141
> +#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 4242
> +
> +struct mvebu_pcie_port;
> +
> +/* Structure representing all PCIe interfaces */
> +struct mvebu_pcie {
> +       struct pci_sw_host_bridge bridge;
> +       struct platform_device *pdev;
> +       struct mvebu_pcie_port *ports;
> +       struct resource io;
> +       struct resource mem;
> +       struct resource busn;
> +       int nports;
> +};
> +
> +/* Structure representing one PCIe interface */
> +struct mvebu_pcie_port {
> +       void __iomem *base;
> +       spinlock_t conf_lock;
> +       int haslink;
> +       u32 port;
> +       u32 lane;
> +       int devfn;
> +       struct clk *clk;
> +       struct pci_sw_pci_bridge bridge;
> +       struct device_node *dn;
> +};
> +
> +static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)
> +{
> +       return sys->private_data;
> +}
> +
> +/* PCI configuration space write function */
> +static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> +                             int where, int size, u32 val)
> +{
> +       struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
> +
> +       if (bus->number != 0) {
> +               /*
> +                * Accessing a real PCIe interface, where the Linux
> +                * virtual bus number is equal to the hardware PCIe
> +                * interface number + 1
> +                */

This is really weird.  It doesn't seem like a good idea to me, but I
don't understand the whole architecture.

> +               struct mvebu_pcie_port *port;
> +               unsigned long flags;
> +               int porti, ret;
> +
> +               porti = bus->number - 1;
> +               if (porti >= pcie->nports)
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +               port = &pcie->ports[porti];
> +
> +               if (!port->haslink)
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +               if (PCI_SLOT(devfn) != 0)
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +               spin_lock_irqsave(&port->conf_lock, flags);
> +               ret = orion_pcie_wr_conf_bus(port->base, bus->number - 1,
> +                                            PCI_DEVFN(1, PCI_FUNC(devfn)),
> +                                            where, size, val);
> +               spin_unlock_irqrestore(&port->conf_lock, flags);
> +
> +               return ret;
> +       } else {
> +               /*
> +                * Accessing the emulated PCIe devices. In the first
> +                * slot, the emulated host bridge, and in the next
> +                * slots, the PCI-to-PCI bridges that correspond to
> +                * each PCIe hardware interface
> +                */
> +               if (PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) == 0)
> +                       return pci_sw_host_bridge_write(&pcie->bridge, where,
> +                                                       size, val);
> +               else if (PCI_SLOT(devfn) >= 1 &&
> +                        PCI_SLOT(devfn) <= pcie->nports) {
> +                       struct mvebu_pcie_port *port;
> +                       int porti = PCI_SLOT(devfn) - 1;
> +                       port = &pcie->ports[porti];
> +                       return pci_sw_pci_bridge_write(&port->bridge, where,
> +                                                      size, val);
> +               } else {
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +               }
> +       }
> +
> +       return PCIBIOS_SUCCESSFUL;
> +}
> +
> +/* PCI configuration space read function */
> +static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +                             int size, u32 *val)
> +{
> +       struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
> +
> +       if (bus->number != 0) {
> +               /*
> +                * Accessing a real PCIe interface, where the Linux
> +                * virtual bus number is equal to the hardware PCIe
> +                * interface number + 1
> +                */
> +               struct mvebu_pcie_port *port;
> +               unsigned long flags;
> +               int porti, ret;
> +
> +               porti = bus->number - 1;
> +               if (porti >= pcie->nports) {
> +                       *val = 0xffffffff;
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +               }
> +
> +               port = &pcie->ports[porti];
> +
> +               if (!port->haslink || PCI_SLOT(devfn) != 0) {
> +                       *val = 0xffffffff;
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +               }
> +
> +               spin_lock_irqsave(&port->conf_lock, flags);
> +               ret = orion_pcie_rd_conf_bus(port->base, bus->number - 1,
> +                                            PCI_DEVFN(1, PCI_FUNC(devfn)),
> +                                            where, size, val);
> +               spin_unlock_irqrestore(&port->conf_lock, flags);
> +
> +               return ret;
> +       } else {
> +               /*
> +                * Accessing the emulated PCIe devices. In the first
> +                * slot, the emulated host bridge, and in the next
> +                * slots, the PCI-to-PCI bridges that correspond to
> +                * each PCIe hardware interface
> +                */
> +               if (PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) == 0)
> +                       return pci_sw_host_bridge_read(&pcie->bridge, where,
> +                                                      size, val);
> +               else if (PCI_SLOT(devfn) >= 1 &&
> +                        PCI_SLOT(devfn) <= pcie->nports) {
> +                       struct mvebu_pcie_port *port;
> +                       int porti = PCI_SLOT(devfn) - 1;
> +                       port = &pcie->ports[porti];
> +                       return pci_sw_pci_bridge_read(&port->bridge, where,
> +                                                     size, val);
> +               } else {
> +                       *val = 0xffffffff;
> +                       return PCIBIOS_DEVICE_NOT_FOUND;
> +               }
> +       }
> +}
> +
> +static struct pci_ops mvebu_pcie_ops = {
> +       .read = mvebu_pcie_rd_conf,
> +       .write = mvebu_pcie_wr_conf,
> +};
> +
> +static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> +       struct mvebu_pcie *pcie = sys_to_pcie(sys);
> +       int i;
> +
> +       pci_add_resource_offset(&sys->resources, &pcie->io, sys->io_offset);
> +       pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
> +       pci_add_resource(&sys->resources, &pcie->busn);
> +
> +       pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> +
> +       for (i = 0; i < pcie->nports; i++) {
> +               struct mvebu_pcie_port *port = &pcie->ports[i];
> +               orion_pcie_set_local_bus_nr(port->base, i);
> +               orion_pcie_setup(port->base);
> +       }
> +
> +       return 1;
> +}
> +
> +static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +       struct mvebu_pcie *pcie = sys_to_pcie(dev->bus->sysdata);
> +       struct mvebu_pcie_port *port;
> +       struct of_irq oirq;
> +       u32 laddr[3];
> +       int ret;
> +       __be32 intspec;
> +
> +       /*
> +        * Ignore requests related to the emulated host bridge or the
> +        * emulated pci-to-pci bridges
> +        */
> +       if (!dev->bus->number)
> +               return -1;
> +
> +       port = &pcie->ports[dev->bus->number - 1];
> +
> +       /*
> +        * Build an laddr array that describes the PCI device in a DT
> +        * way
> +        */
> +       laddr[0] = cpu_to_be32(port->devfn << 8);
> +       laddr[1] = laddr[2] = 0;
> +       intspec = cpu_to_be32(pin);
> +
> +       ret = of_irq_map_raw(port->dn, &intspec, 1, laddr, &oirq);
> +       if (ret) {
> +               dev_err(&pcie->pdev->dev,
> +                       "%s: of_irq_map_raw() failed, %d\n",
> +                       __func__, ret);
> +               return ret;
> +       }
> +
> +       return irq_create_of_mapping(oirq.controller, oirq.specifier,
> +                                    oirq.size);
> +}
> +
> +/*
> + * For a given PCIe interface (represented by a mvebu_pcie_port
> + * structure), we read the PCI configuration space of the
> + * corresponding PCI-to-PCI bridge in order to find out which range of
> + * I/O addresses and memory addresses have been assigned to this PCIe
> + * interface. Using these informations, we set up the appropriate
> + * address decoding windows so that the physical address are actually
> + * resolved to the right PCIe interface.
> + */

Are you inferring the host bridge apertures by using the resources
assigned to devices under the bridge, i.e., taking the union of all
the BARs and PCI-to-PCI bridge apertures of devices on the root bus?
If so, it would be much better to learn the host bridge apertures via
some non-PCI mechanism that corresponds to the actual hardware
configuration.  The config of devices below the host bridge gives you
hints, of course, but usually they don't consume all the available
space.

> +static int mvebu_pcie_window_config_port(struct mvebu_pcie *pcie,
> +                                        struct mvebu_pcie_port *port)
> +{
> +       unsigned long iobase = 0;
> +       int ret;
> +
> +       if (port->bridge.iolimit >= port->bridge.iobase) {
> +               unsigned long iolimit = 0xFFF |
> +                       ((port->bridge.iolimit & 0xF0) << 8) |
> +                       (port->bridge.iolimitupper << 16);
> +               iobase = ((port->bridge.iobase & 0xF0) << 8) |
> +                       (port->bridge.iobaseupper << 16);
> +               ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
> +                                                     iobase, iolimit-iobase,
> +                                                     IORESOURCE_IO);
> +               if (ret) {
> +                       dev_err(&pcie->pdev->dev,
> +                               "%s: could not alloc PCIe %d:%d window for I/O [0x%lx; 0x%lx]\n",
> +                               __func__, port->port, port->lane,
> +                               iobase, iolimit);
> +                       goto out_io;
> +               }
> +       }
> +
> +       if (port->bridge.memlimit >= port->bridge.membase) {
> +               unsigned long membase =
> +                       ((port->bridge.membase & 0xFFF0) << 16);
> +               unsigned long memlimit =
> +                       ((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF;
> +               ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
> +                                                     membase, memlimit-membase,
> +                                                     IORESOURCE_MEM);
> +               if (ret) {
> +                       dev_err(&pcie->pdev->dev,
> +                               "%s: could not alloc PCIe %d:%d window for MEM [0x%lx; 0x%lx]\n",
> +                               __func__, port->port, port->lane,
> +                               membase, memlimit);
> +                       goto out_mem;
> +               }
> +       }
> +
> +out_mem:
> +       if (port->bridge.iolimit >= port->bridge.iobase)
> +               armada_370_xp_free_pcie_window(iobase);
> +out_io:
> +       return ret;
> +}
> +
> +/*
> + * Set up the address decoding windows for all PCIe interfaces.
> + */
> +static int mvebu_pcie_window_config(struct mvebu_pcie *pcie)
> +{
> +       int i, ret;
> +
> +       for (i = 0; i < pcie->nports; i++) {
> +               struct mvebu_pcie_port *port = &pcie->ports[i];
> +               if (!port->haslink)
> +                       continue;
> +
> +               ret = mvebu_pcie_window_config_port(pcie, port);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
> +                                                const struct resource *res,
> +                                                resource_size_t start,
> +                                                resource_size_t size,
> +                                                resource_size_t align)
> +{
> +       if (!(res->flags & IORESOURCE_IO))
> +               return start;
> +
> +       /*
> +        * The I/O regions must be 64K aligned, because the
> +        * granularity of PCIe I/O address decoding windows is 64 K
> +        */
> +       return round_up(start, SZ_64K);
> +}
> +
> +static int mvebu_pcie_enable(struct mvebu_pcie *pcie)
> +{
> +       struct hw_pci hw;
> +
> +       memset(&hw, 0, sizeof(hw));
> +
> +       hw.nr_controllers = 1;
> +       hw.private_data   = (void **)&pcie;
> +       hw.setup          = mvebu_pcie_setup;
> +       hw.map_irq        = mvebu_pcie_map_irq;
> +       hw.align_resource = mvebu_pcie_align_resource;
> +       hw.ops            = &mvebu_pcie_ops;
> +
> +       pci_common_init(&hw);
> +
> +       return mvebu_pcie_window_config(pcie);
> +}
> +
> +static int __init mvebu_pcie_probe(struct platform_device *pdev)
> +{
> +       struct mvebu_pcie *pcie;
> +       struct device_node *np = pdev->dev.of_node;
> +       struct device_node *child;
> +       const __be32 *range = NULL;
> +       struct resource res;
> +       int i, ret;
> +
> +       pcie = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pcie),
> +                           GFP_KERNEL);
> +       if (!pcie)
> +               return -ENOMEM;
> +
> +       pcie->pdev = pdev;
> +
> +       pci_sw_host_bridge_init(&pcie->bridge);
> +       pcie->bridge.vendor = PCI_VENDOR_ID_MARVELL;
> +       pcie->bridge.device = MARVELL_EMULATED_HOST_BRIDGE_ID;
> +
> +       /* Get the I/O and memory ranges from DT */
> +       while ((range = of_pci_process_ranges(np, &res, range)) != NULL) {
> +               if (resource_type(&res) == IORESOURCE_IO) {
> +                       memcpy(&pcie->io, &res, sizeof(res));
> +                       pcie->io.name = "I/O";
> +               }
> +               if (resource_type(&res) == IORESOURCE_MEM) {
> +                       memcpy(&pcie->mem, &res, sizeof(res));
> +                       pcie->mem.name = "MEM";
> +               }
> +       }
> +
> +       /* Get the bus range */
> +       ret = of_pci_parse_bus_range(np, &pcie->busn);
> +       if (ret) {
> +               dev_err(&pdev->dev, "failed to parse bus-range property: %d\n",
> +                       ret);
> +               return ret;
> +       }
> +
> +       for_each_child_of_node(pdev->dev.of_node, child) {
> +               if (!of_device_is_available(child))
> +                       continue;
> +               pcie->nports++;
> +       }
> +
> +       pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports *
> +                                  sizeof(struct mvebu_pcie_port),
> +                                  GFP_KERNEL);
> +       if (!pcie->ports)
> +               return -ENOMEM;
> +
> +       i = 0;
> +       for_each_child_of_node(pdev->dev.of_node, child) {
> +               struct mvebu_pcie_port *port = &pcie->ports[i];
> +
> +               if (!of_device_is_available(child))
> +                       continue;
> +
> +               if (of_property_read_u32(child, "marvell,pcie-port",
> +                                        &port->port)) {
> +                       dev_warn(&pdev->dev,
> +                                "ignoring PCIe DT node, missing pcie-port property\n");
> +                       continue;
> +               }
> +
> +               if (of_property_read_u32(child, "marvell,pcie-lane",
> +                                        &port->lane))
> +                       port->lane = 0;
> +
> +               port->devfn = of_pci_get_devfn(child);
> +               if (port->devfn < 0)
> +                       continue;
> +
> +               port->base = of_iomap(child, 0);
> +               if (!port->base) {
> +                       dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
> +                               port->port, port->lane);
> +                       continue;
> +               }
> +
> +               if (orion_pcie_link_up(port->base)) {
> +                       port->haslink = 1;
> +                       dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
> +                                port->port, port->lane);
> +               } else {
> +                       port->haslink = 0;
> +                       dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
> +                                port->port, port->lane);
> +               }
> +
> +               port->clk = of_clk_get_by_name(child, NULL);
> +               if (!port->clk) {
> +                       dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
> +                              port->port, port->lane);
> +                       iounmap(port->base);
> +                       port->haslink = 0;
> +                       continue;
> +               }
> +
> +               port->dn = child;
> +
> +               clk_prepare_enable(port->clk);
> +               spin_lock_init(&port->conf_lock);
> +
> +               pci_sw_pci_bridge_init(&port->bridge);
> +               port->bridge.vendor = PCI_VENDOR_ID_MARVELL;
> +               port->bridge.device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
> +               port->bridge.primary_bus = 0;
> +               port->bridge.secondary_bus = PCI_SLOT(port->devfn);
> +               port->bridge.subordinate_bus = PCI_SLOT(port->devfn);
> +
> +               i++;
> +       }
> +
> +       mvebu_pcie_enable(pcie);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id mvebu_pcie_of_match_table[] = {
> +       { .compatible = "marvell,armada-370-xp-pcie", },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
> +
> +static struct platform_driver mvebu_pcie_driver = {
> +       .driver = {
> +               .owner = THIS_MODULE,
> +               .name = "mvebu-pcie",
> +               .of_match_table =
> +                  of_match_ptr(mvebu_pcie_of_match_table),
> +       },
> +};
> +
> +static int mvebu_pcie_init(void)
> +{
> +       return platform_driver_probe(&mvebu_pcie_driver,
> +                                    mvebu_pcie_probe);
> +}
> +
> +subsys_initcall(mvebu_pcie_init);
> +
> +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
> +MODULE_DESCRIPTION("Marvell EBU PCIe driver");
> +MODULE_LICENSE("GPL");
> --
> 1.7.9.5
>

^ permalink raw reply

* [PATCH v4] cpufreq: add imx6q-cpufreq driver
From: Shawn Guo @ 2013-01-29  2:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359214303-3319-1-git-send-email-shawn.guo@linaro.org>

On Sat, Jan 26, 2013 at 11:31:43PM +0800, Shawn Guo wrote:
> Add an imx6q-cpufreq driver for Freescale i.MX6Q SoC to handle the
> hardware specific frequency and voltage scaling requirements.
> 
> The driver supports module build and is instantiated by the platform
> device/driver mechanism, so that it will not be instantiated on other
> platforms, as IMX is built with multiplatform support.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
> Acked-by: Rafael J. Wysocki <rjw@sisk.pl>

Rafael,

I think the patch needs to go via cpufreq tree, as it has dependency
on Nishanth's "PM / OPP : export symbol consolidation" series.

Shawn

^ permalink raw reply

* [PATCH v2] cpufreq: instantiate cpufreq-cpu0 as a platform_driver
From: Shawn Guo @ 2013-01-29  2:53 UTC (permalink / raw)
  To: linux-arm-kernel

As multiplatform build is being adopted by more and more ARM platforms,
initcall function should be used very carefully.  For example, when
GENERIC_CPUFREQ_CPU0 is built in the kernel, cpu0_cpufreq_driver_init()
will be called on all the platforms to initialize cpufreq-cpu0 driver.

To eliminate this undesired the effect, the patch changes cpufreq-cpu0
driver to have it instantiated as a platform_driver.  Then it will only
run on platforms that create the platform_device "cpufreq-cpu0".

Along with the change, it also changes cpu_dev to be &pdev->dev,
so that managed functions can start working, and module build gets
supported too.

The existing users of cpufreq-cpu0 driver highbank and am33xx are also
updated accordingly to adapt the changes.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Mark Langsdorf <mark.langsdorf@calxeda.com>
Cc: AnilKumar Ch <anilkumar@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
Changes since v1:
 * Migrate cpufreq-cpu0 users in the same patch

Rafael,

The patch is based on Mark's highbank-cpufreq series and Nishanth's
"PM / OPP : export symbol consolidation" sereis.

Mark, AnilKumar,

I only compile-tested it on highbank and omap2.  Please give it a test
no hardware to make sure cpufreq-cpu0 still works for you.  Thanks.

Shawn

 arch/arm/mach-omap2/board-generic.c   |    1 +
 arch/arm/mach-omap2/cclock33xx_data.c |    2 +-
 arch/arm/mach-omap2/common.h          |    1 +
 arch/arm/mach-omap2/io.c              |    7 +++++++
 drivers/cpufreq/Kconfig               |    2 +-
 drivers/cpufreq/cpufreq-cpu0.c        |   35 ++++++++++++++++++++++-----------
 drivers/cpufreq/highbank-cpufreq.c    |    5 +++++
 7 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 53cb380b..b945480 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -139,6 +139,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
+	.init_late	= am33xx_init_late,
 	.timer		= &omap3_am33xx_timer,
 	.dt_compat	= am33xx_boards_compat,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
index ea64ad6..acb1620 100644
--- a/arch/arm/mach-omap2/cclock33xx_data.c
+++ b/arch/arm/mach-omap2/cclock33xx_data.c
@@ -850,7 +850,7 @@ static struct omap_clk am33xx_clks[] = {
 	CLK(NULL,	"dpll_core_m5_ck",	&dpll_core_m5_ck,	CK_AM33XX),
 	CLK(NULL,	"dpll_core_m6_ck",	&dpll_core_m6_ck,	CK_AM33XX),
 	CLK(NULL,	"dpll_mpu_ck",		&dpll_mpu_ck,	CK_AM33XX),
-	CLK("cpu0",	NULL,			&dpll_mpu_ck,	CK_AM33XX),
+	CLK("cpufreq-cpu0.0",	NULL,		&dpll_mpu_ck,	CK_AM33XX),
 	CLK(NULL,	"dpll_mpu_m2_ck",	&dpll_mpu_m2_ck,	CK_AM33XX),
 	CLK(NULL,	"dpll_ddr_ck",		&dpll_ddr_ck,	CK_AM33XX),
 	CLK(NULL,	"dpll_ddr_m2_ck",	&dpll_ddr_m2_ck,	CK_AM33XX),
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 948bcaa..e3355df5 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -106,6 +106,7 @@ void omap2430_init_late(void);
 void omap3430_init_late(void);
 void omap35xx_init_late(void);
 void omap3630_init_late(void);
+void am33xx_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
 void omap4430_init_late(void);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 2c3fdd6..7acfb8a 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -535,6 +535,13 @@ void __init omap3630_init_late(void)
 	omap2_clk_enable_autoidle_all();
 }
 
+void __init am33xx_init_late(void)
+{
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
+	platform_device_register_full(&devinfo);
+}
+
 void __init am35xx_init_late(void)
 {
 	omap_mux_late_init();
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index ea512f4..774dc1c 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -180,7 +180,7 @@ config CPU_FREQ_GOV_CONSERVATIVE
 	  If in doubt, say N.
 
 config GENERIC_CPUFREQ_CPU0
-	bool "Generic CPU0 cpufreq driver"
+	tristate "Generic CPU0 cpufreq driver"
 	depends on HAVE_CLK && REGULATOR && PM_OPP && OF
 	select CPU_FREQ_TABLE
 	help
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 90e9d73..519c2f7 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -12,12 +12,12 @@
 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
 
 #include <linux/clk.h>
-#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/opp.h>
+#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
@@ -174,7 +174,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 	.attr = cpu0_cpufreq_attr,
 };
 
-static int cpu0_cpufreq_driver_init(void)
+static int cpu0_cpufreq_probe(struct platform_device *pdev)
 {
 	struct device_node *np;
 	int ret;
@@ -189,23 +189,17 @@ static int cpu0_cpufreq_driver_init(void)
 		return -ENOENT;
 	}
 
-	cpu_dev = get_cpu_device(0);
-	if (!cpu_dev) {
-		pr_err("failed to get cpu0 device\n");
-		ret = -ENODEV;
-		goto out_put_node;
-	}
-
+	cpu_dev = &pdev->dev;
 	cpu_dev->of_node = np;
 
-	cpu_clk = clk_get(cpu_dev, NULL);
+	cpu_clk = devm_clk_get(cpu_dev, NULL);
 	if (IS_ERR(cpu_clk)) {
 		ret = PTR_ERR(cpu_clk);
 		pr_err("failed to get cpu0 clock: %d\n", ret);
 		goto out_put_node;
 	}
 
-	cpu_reg = regulator_get(cpu_dev, "cpu0");
+	cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
 	if (IS_ERR(cpu_reg)) {
 		pr_warn("failed to get cpu0 regulator\n");
 		cpu_reg = NULL;
@@ -266,7 +260,24 @@ out_put_node:
 	of_node_put(np);
 	return ret;
 }
-late_initcall(cpu0_cpufreq_driver_init);
+
+static int cpu0_cpufreq_remove(struct platform_device *pdev)
+{
+	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
+	opp_free_cpufreq_table(cpu_dev, &freq_table);
+
+	return 0;
+}
+
+static struct platform_driver cpu0_cpufreq_platdrv = {
+	.driver = {
+		.name	= "cpufreq-cpu0",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= cpu0_cpufreq_probe,
+	.remove		= cpu0_cpufreq_remove,
+};
+module_platform_driver(cpu0_cpufreq_platdrv);
 
 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
 MODULE_DESCRIPTION("Generic CPU0 cpufreq driver");
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c
index 2ea6276..0491f1f 100644
--- a/drivers/cpufreq/highbank-cpufreq.c
+++ b/drivers/cpufreq/highbank-cpufreq.c
@@ -20,6 +20,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/mailbox.h>
+#include <linux/platform_device.h>
 
 #define HB_CPUFREQ_CHANGE_NOTE	0x80000001
 #define HB_CPUFREQ_IPC_LEN	7
@@ -65,6 +66,7 @@ static struct notifier_block hb_cpufreq_clk_nb = {
 
 static int hb_cpufreq_driver_init(void)
 {
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
 	struct device *cpu_dev;
 	struct clk *cpu_clk;
 	struct device_node *np;
@@ -104,6 +106,9 @@ static int hb_cpufreq_driver_init(void)
 		goto out_put_node;
 	}
 
+	/* Instantiate cpufreq-cpu0 */
+	platform_device_register_full(&devinfo);
+
 out_put_node:
 	of_node_put(np);
 	return ret;
-- 
1.7.9.5

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox