* mvebu: Can we make the orion-mdio clock a requirement?
From: Thomas Petazzoni @ 2014-07-21 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CD743D.9080700@gmail.com>
Dear Sebastian Hesselbarth,
On Mon, 21 Jul 2014 22:12:45 +0200, Sebastian Hesselbarth wrote:
> > However, yes, I tend to agree, making the clock mandatory would
> > probably be a good thing.
>
> We can always pass TCLK on Orion5x if there is a need for a mandatory
> clock. Anyway, IIRC clock framework should now properly return
> -EPROPEDEFER only if there is a clock property set. If there is none,
> the error is different and can be catched on Orion5x.
Yes, I already use tclk on Orion5x for various clock references.
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* mvebu: Can we make the orion-mdio clock a requirement?
From: Sebastian Hesselbarth @ 2014-07-21 20:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721212818.2d4920c4@free-electrons.com>
On 07/21/2014 09:28 PM, Thomas Petazzoni wrote:
> On Mon, 21 Jul 2014 16:06:15 -0300, Ezequiel Garcia wrote:
>> Currently the mvmdio driver does not require a clock to be declared,
>> and instead this is optional.
>>
>> However (almost) all the platforms that currently use it, i.e. the
>> Armada, Kirkwood and Dove SoCs, require some clock to be enabled before
>> the MDIO registers can be accessed.
>>
>> The Orion5x SoC doesn't declare any clock for neither the ethernet node,
>> nor the MDIO node. Is that correct?
>
> There are no gatable clocks on Orion5x, so unless the driver really
> wants a clock, there's no hard requirement to give a clock reference.
>
>> Do you think we could make the clock a required property in the mvmdio
>> devicetree node? How would that behave in the non-DT case?
>
> I don't think the mvmdio driver is used in non-DT contexts.
>
> However, yes, I tend to agree, making the clock mandatory would
> probably be a good thing.
We can always pass TCLK on Orion5x if there is a need for a mandatory
clock. Anyway, IIRC clock framework should now properly return
-EPROPEDEFER only if there is a clock property set. If there is none,
the error is different and can be catched on Orion5x.
Sebastian
^ permalink raw reply
* [PATCHv4 2/5] lib/genalloc.c: Add genpool range check function
From: Laura Abbott @ 2014-07-21 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOesGMiKBNDmJhiY-yK0uZmG-MnK82=ffNGxqasLKozqgpQQpw@mail.gmail.com>
On 7/9/2014 3:33 PM, Olof Johansson wrote:
> On Wed, Jul 2, 2014 at 11:03 AM, Laura Abbott <lauraa@codeaurora.org> wrote:
>>
>> After allocating an address from a particular genpool,
>> there is no good way to verify if that address actually
>> belongs to a genpool. Introduce addr_in_gen_pool which
>> will return if an address plus size falls completely
>> within the genpool range.
>>
>> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
>
> Reviewed-by: Olof Johansson <olof@lixom.net>
>
> What's the merge path for this code? Part of the arm64 code that needs
> it, I presume?
>
My plan was to have the entire series go through the arm64 tree unless
someone has a better idea.
Thanks,
Laura
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [PATCHv4 3/5] common: dma-mapping: Introduce common remapping functions
From: Laura Abbott @ 2014-07-21 19:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140718135349.GB4608@arm.com>
On 7/18/2014 6:53 AM, Catalin Marinas wrote:
> On Wed, Jul 02, 2014 at 07:03:36PM +0100, Laura Abbott wrote:
>> +void *dma_common_pages_remap(struct page **pages, size_t size,
>> + unsigned long vm_flags, pgprot_t prot,
>> + const void *caller)
>> +{
>> + struct vm_struct *area;
>> +
>> + area = get_vm_area_caller(size, vm_flags, caller);
>> + if (!area)
>> + return NULL;
>> +
>> + if (map_vm_area(area, prot, &pages)) {
>> + vunmap(area->addr);
>> + return NULL;
>> + }
>> +
>> + return area->addr;
>> +}
>
> Why not just replace this function with vmap()? It is nearly identical.
>
With this version, the caller stored and printed via /proc/vmallocinfo
is the actual caller of the DMA API whereas if we just call vmap we
don't get any useful caller information. Going to vmap would change
the existing behavior on ARM so it seems unwise to switch. Another
option is to move this into vmalloc.c and add vmap_caller.
Thanks,
Laura
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* mvebu: Can we make the orion-mdio clock a requirement?
From: Thomas Petazzoni @ 2014-07-21 19:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721190614.GB20027@arch.cereza>
Dear Ezequiel Garcia,
On Mon, 21 Jul 2014 16:06:15 -0300, Ezequiel Garcia wrote:
> Currently the mvmdio driver does not require a clock to be declared,
> and instead this is optional.
>
> However (almost) all the platforms that currently use it, i.e. the
> Armada, Kirkwood and Dove SoCs, require some clock to be enabled before
> the MDIO registers can be accessed.
>
> The Orion5x SoC doesn't declare any clock for neither the ethernet node,
> nor the MDIO node. Is that correct?
There are no gatable clocks on Orion5x, so unless the driver really
wants a clock, there's no hard requirement to give a clock reference.
> Do you think we could make the clock a required property in the mvmdio
> devicetree node? How would that behave in the non-DT case?
I don't think the mvmdio driver is used in non-DT contexts.
However, yes, I tend to agree, making the clock mandatory would
probably be a good thing.
Best regards,
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* mvebu: Can we make the orion-mdio clock a requirement?
From: Ezequiel Garcia @ 2014-07-21 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Helly everyone,
Currently the mvmdio driver does not require a clock to be declared,
and instead this is optional.
However (almost) all the platforms that currently use it, i.e. the
Armada, Kirkwood and Dove SoCs, require some clock to be enabled before
the MDIO registers can be accessed.
The Orion5x SoC doesn't declare any clock for neither the ethernet node,
nor the MDIO node. Is that correct?
Do you think we could make the clock a required property in the mvmdio
devicetree node? How would that behave in the non-DT case?
Thanks,
--
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH] platform: Make platform_bus device a platform device
From: Greg Kroah-Hartman @ 2014-07-21 18:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405962034-25482-1-git-send-email-pawel.moll@arm.com>
On Mon, Jul 21, 2014 at 06:00:34PM +0100, Pawel Moll wrote:
> ... describing the root of the device tree, so one can write
> a platform driver initializing the platform.
>
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> ---
>
> For what it's worth, the patch I came up back then.
> *Untested* against current head...
I like the idea, nice...
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Laurent Pinchart @ 2014-07-21 18:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721161810.282ca5e5@bbrezillon>
Hi Boris,
On Monday 21 July 2014 16:18:10 Boris BREZILLON wrote:
> On Mon, 21 Jul 2014 15:47:52 +0200 Laurent Pinchart wrote:
> > On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> >> On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> >>> On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> >>>> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> >>>>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> >>>>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> >>>>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
> >>>>>>>> On Mon, Jul 21, 2014 at 11:57:37AM +0200, Boris BREZILLON wrote:
> >>>> [snip]
> >>>>
> >>>>>>>>> The new drm_display_info structure should look like this [2]
> >>>>>>>>> (except that color_formats and bpc have not be removed yet), and
> >>>>>>>>> [1] is just here to show how the video_bus_format enum would
> >>>>>>>>> look like.
> >>>>>>>>>
> >>>>>>>>> [1] http://code.bulix.org/rfd0yx-86557
> >>>>>>>>> [2] http://code.bulix.org/7n03b4-86556
> >>>>>>>>
> >>>>>>>> Quoting from your paste:
> >>>>>>>> + const enum video_bus_format *bus_formats;
> >>>>>>>> + int nbus_formats;
> >>>>>>>>
> >>>>>>>> Do we really need more than one?
> >>>>>>>
> >>>>>>> We do if we want to replace the color_formats and bpc fields.
> >>>>>>
> >>>>>> Yes, that's what I was about to answer :-).
> >>>>>
> >>>>> Maybe we don't need to replace color_formats and bpc field
> >>>>> immediately. That could be done in a follow-up patch.
> >>>>
> >>>> We don't need to replace them right now, but we should at least agree
> >>>> on how to replace them. Introducing a new field that would need to be
> >>>> replaced in the near future when removing color_formats and bpc would
> >>>> be a waste of time.
> >>>
> >>> Sure. One of the problems I see with replacing color_formats and bpc
> >>> with the above is that some of the bits within color_formats are set
> >>> when the EDID is parsed. That implies that if they are replaced with
> >>> an array of formats, the array would need to be reallocated during
> >>> EDID parsing. That sounds like ugliness.
> >>>
> >>> But if you can find a nice way to make it work that'd be great.
> >>
> >> How about using a list instead of an array ?
> >> This way we can add elements to this list when parsing the EDID.
> >>
> >> Or we can just define a maximum size for the bus_formats array when
> >> retrieving this info from EDID. If I'm correct we have at most 18 bus
> >>
> >> formats:
> >> - 3 color formats:
> >> * RGB 4:4:4
> >> * YCbCr 4:4:4
> >> * YCbCr 4:4:2
> >>
> >> - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
> >
> > bpc isn't a bitmask, so EDID supports up to three formats only.
>
> Yes, bpc only contains a single value for now, and it fits the
> DRM_EDID_DIGITAL_DEPTH field [1] (an enum defining the supported pixel
> depth).
> ITOH, DRM_EDID_HDMI_DC_XX [2] (which are referenced in the new
> drm_assign_hdmi_deep_color_info function) are just bitmasks and thus a
> display might support several color depth.
>
> As a result, I wonder if we shouldn't start supporting several color depths
> (as we do for color formats)
If there's a use case for that, sure. It wouldn't be difficult, given that a
bus format defines both the color format and the depths.
> [1]http://lxr.free-electrons.com/source/drivers/gpu/drm/drm_edid.c#L3436
> [2]https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/driv
> ers/gpu/drm/drm_edid.c?id=refs/tags/v3.16-rc6#n3440
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Laurent Pinchart @ 2014-07-21 18:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721162136.286f5b62@bbrezillon>
Hi Boris and Thierry,
On Monday 21 July 2014 16:21:36 Boris BREZILLON wrote:
> On Mon, 21 Jul 2014 15:54:12 +0200 Thierry Reding wrote:
> > On Mon, Jul 21, 2014 at 03:47:52PM +0200, Laurent Pinchart wrote:
> >> On Monday 21 July 2014 15:43:13 Boris BREZILLON wrote:
> >>> On Mon, 21 Jul 2014 15:30:35 +0200 Thierry Reding wrote:
> >>>> On Mon, Jul 21, 2014 at 03:22:05PM +0200, Laurent Pinchart wrote:
> >>>>> On Monday 21 July 2014 14:55:23 Thierry Reding wrote:
> >>>>>> On Mon, Jul 21, 2014 at 02:34:28PM +0200, Boris BREZILLON wrote:
> >>>>>>> On Mon, 21 Jul 2014 14:16:42 +0200 Laurent Pinchart wrote:
> >>>>>>>> On Monday 21 July 2014 14:12:47 Thierry Reding wrote:
[snip]
> >>>>>>>>> Quoting from your paste:
> >>>>>>>>> + const enum video_bus_format *bus_formats;
> >>>>>>>>> + int nbus_formats;
> >>>>>>>>>
> >>>>>>>>> Do we really need more than one?
> >>>>>>>>
> >>>>>>>> We do if we want to replace the color_formats and bpc fields.
> >>>>>>>
> >>>>>>> Yes, that's what I was about to answer :-).
> >>>>>>
> >>>>>> Maybe we don't need to replace color_formats and bpc field
> >>>>>> immediately. That could be done in a follow-up patch.
> >>>>>
> >>>>> We don't need to replace them right now, but we should at least
> >>>>> agree on how to replace them. Introducing a new field that would
> >>>>> need to be replaced in the near future when removing color_formats
> >>>>> and bpc would be a waste of time.
> >>>>
> >>>> Sure. One of the problems I see with replacing color_formats and bpc
> >>>> with the above is that some of the bits within color_formats are set
> >>>> when the EDID is parsed. That implies that if they are replaced with
> >>>> an array of formats, the array would need to be reallocated during
> >>>> EDID parsing. That sounds like ugliness.
> >>>>
> >>>> But if you can find a nice way to make it work that'd be great.
> >>>
> >>> How about using a list instead of an array ?
> >>> This way we can add elements to this list when parsing the EDID.
> >>>
> >>> Or we can just define a maximum size for the bus_formats array when
> >>> retrieving this info from EDID. If I'm correct we have at most 18 bus
> >>>
> >>> formats:
> >>> - 3 color formats:
> >>> * RGB 4:4:4
> >>> * YCbCr 4:4:4
> >>> * YCbCr 4:4:2
> >>> - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
> >>
> >> bpc isn't a bitmask, so EDID supports up to three formats only.
> >>
> >> The color_formats field is computed in the drm_add_display_info()
> >> function. You could easily turn it into a local variable and allocate
> >> and fill the formats array at the end of the function.
> >
> > But you also need to be careful to keep whatever formats the driver might
> > have set explicitly.
Do we have drivers that explicitly add formats to the formats parsed from EDID
data ? If so, what's the use case ?
> Okay, in this case, using a list is a better idea, don't you think ?
I'd prefer an array if possible, as that would be easier to use for drivers.
In any case, we need to define who allocates and frees the array or the list
elements, how and when.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [RFC] arm: section split in boot/compressed/head.S
From: Ard Biesheuvel @ 2014-07-21 18:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721175432.GB4179@bivouac.eciton.net>
On 21 July 2014 19:54, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> Reported-by: Roy Franz <roy.franz@linaro.org>
>
> The current code in boot/compressed/head.S executes pretty much
> sequentially from "start", all the way until the end of
> "dtb_check_done". However, shortly after the "not_angel" symbol, there
> is a section change, in the form of a ".text" directive.
>
> This means any literal pools in .start end up getting inserted into
> the middle of the instruction stream.
>
> Would something like the below (pardon the semantic silliness) be an
> acceptable fix?
>
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 3a8b32d..8ee05e9 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -149,6 +149,10 @@ start:
> mov r0, #0x17 @ angel_SWIreason_EnterSVC
> ARM( swi 0x123456 ) @ angel_SWI_ARM
> THUMB( svc 0xab ) @ angel_SWI_THUMB
> + b angel
The idea appears to be that code in .start sections from other
platform specific object files gets put there, so it gets executed
extremely early.
Jumping over it kind of defeats the purpose here.
Instead, adding an explicit .ltorg and jumping over /that/ should do
the trick, I think, but perhaps it's better just to open code the
literal pool in this case.
--
Ard.
> +
> + .text
> +angel:
> not_angel:
> safe_svcmode_maskall r0
> msr spsr_cxsf, r9 @ Save the CPU boot mode in
> @@ -163,8 +167,6 @@ not_angel:
> * by the linker here, but it should preserve r7, r8, and r9.
> */
>
> - .text
> -
> #ifdef CONFIG_AUTO_ZRELADDR
> @ determine final kernel image address
> mov r4, pc
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 0/6] Migrate PXA27x platforms to clock framework
From: Robert Jarzmik @ 2014-07-21 18:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405353263-13424-1-git-send-email-robert.jarzmik@free.fr>
Robert Jarzmik <robert.jarzmik@free.fr> writes:
> This is the second opus of this serie.
Ping ?
--
Robert
^ permalink raw reply
* [PATCH v2] PCI: imx6: fix boot hang when link already enabled
From: Lucas Stach @ 2014-07-21 18:17 UTC (permalink / raw)
To: linux-arm-kernel
This fixes a boot hang observed when the bootloader
already enabled the PCIe link for it's own use. The
fundamental problem is that Freescale forgot to wire
up the core reset, so software doesn't have a sane way
to get the core into a defined state.
According to the DW PCIe core reference manual configuration
of the core may only happen when the LTSSM is disabled, so
this is one of the first things we need to do. Apparently
this isn't safe to do when the LTSSM is in any other state
than "detect" as we observe an instant machine hang when
trying to do so while the link is already up.
As a workaround force LTSSM into detect state right before
hitting the disable switch.
Reported-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
v2: messed up the first submission by omitting a chunk
Fabios delay workaround worked because of the following
conditions:
1. The driver gets probed and pulls the peripheral reset GPIO
2. Peripheral is held in reset, so won't answer any link
negotiation requests
3. The LTSSM times out and falls back into detect state
after 24ms (that's why a 30ms delay helps)
4. After LTSSM entered detect state it's safe to hit the
disable switch
---
drivers/pci/host/pci-imx6.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index a568efaa331c..1c4b4b81fe15 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -49,6 +49,9 @@ struct imx6_pcie {
/* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700
+#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
+#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
+#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
@@ -214,7 +217,15 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
{
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ u32 val;
+
+ val = readl(pp->dbi_base + PCIE_PL_PFLR);
+ val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+ val |= PCIE_PL_PFLR_FORCE_LINK;
+ writel(val, pp->dbi_base + PCIE_PL_PFLR);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
--
2.0.1
^ permalink raw reply related
* [PATCH v2 0/3] iommu: Remove OMAP IOVMM driver
From: Laurent Pinchart @ 2014-07-21 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721093336.GR18374@atomide.com>
Hi Tony and Joerg,
On Monday 21 July 2014 02:33:36 Tony Lindgren wrote:
> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> [140721 02:16]:
> > Hi Suman, Joerg and Tony,
> >
> > On Friday 18 July 2014 11:53:56 Suman Anna wrote:
> > > On 07/18/2014 05:49 AM, Laurent Pinchart wrote:
> > > > Hello,
> > > >
> > > > The OMAP3 ISP driver was the only user of the OMAP IOVMM API. Now that
> > > > is has been ported to the DMA API, remove the unused virtual memory
> > > > manager.
> > > >
> > > > The removal is split in three patches to ease upstream merge. The
> > > > first patch removes the omap-iovmm driver, the second patch removes
> > > > setting of now unused platform data fields from arch code, and the
> > > > last patch cleans up the platform data structure.
> > >
> > > Thanks for the revised series, it looks good. I have also tested the
> > > series on OMAP3, OMAP4 and OMAP5.
> > >
> > > For the changes in the entire series,
> > > Acked-by: Suman Anna <s-anna@ti.com>
> >
> > Thank you.
> >
> > > > I'd like to get at least the first patch merged in v3.17. To avoid
> > > > splitting the series across three kernel versions, it would be nice to
> > > > also merge at least the second patch for v3.17. If there's no risk of
> > > > conflict everything could be merged in one go through the ARM SoC
> > > > tree. Otherwise a stable branch with patch 1/3 will be needed to base
> > > > the arch change on.
> > > >
> > > > Joerg, Tony, how would you like to proceed ?
> >
> > The v3.17 merge window is getting close, it's probably too late to merge
> > patch 2/3. Joerg, could you please take 1/3 in your tree for v3.17 ? 2/3
> > and 3/3 would then get in v3.18. Tony, how would you like to proceed for
> > those ?
>
> How about Joerg maybe do an immutable branch against v3.16-rc1
> with just these three patches and merge it into your tree?
>
> That way I too can merge the minimal branch in if there are conflics.
> If that works for Joerg, then for arch/arm/*omap* changes:
>
> Acked-by: Tony Lindgren <tony@atomide.com>
I've created an immutable branch (or, rather, immutable until the changes
reach mainline, at which point I will remove the branch) on top of v3.16-rc1
with just the three patches from this series. You can find it at.
git://linuxtv.org/pinchartl/media.git omap/iommu
Tony, is there still time to get this (and especially patch 2/3, which touches
arch/ code) in v3.17 ?
> If the above is too complicated, then how about Laurent resend patches
> 2 - 3 once the dependencies have cleared so I can pick them up. This
> is assuming nothing breaks with patchs 2 - 3 missing naturally :)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH v3 4/4] arm: pxa: add non device-tree timer link to clocksource
From: Robert Jarzmik @ 2014-07-21 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CD25A4.7030606@linaro.org>
Daniel Lezcano <daniel.lezcano@linaro.org> writes:
> On 07/14/2014 06:52 PM, Robert Jarzmik wrote:
>> As clocksource pxa_timer was moved to clocksource framework, the
>> pxa_timer initialization needs to be a bit amended, to pass the
>> necessary informations to clocksource, ie :
>> - the timer interrupt (mach specific)
>> - the timer registers base (ditto)
>> - the timer clockrate
>>
>> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
>>
>> ---
>> Since V2: Arnd's comment : moved extern declaration into .h file
>> ---
>
> Shall I take the patches 4-5 also ?
Mmm you mean patch 4 I think.
Then I'd like you too, because it's linked in the serie, and without it the
former non-DT platforms break, hence I'd like all the serie to go through 1
tree.
Yet we'd need Haojian's ack here. Haojian, would you give your blessing on the
serie and agree that Daniel carries all the patches including patch 4/4 ?
Cheers.
--
Robert
^ permalink raw reply
* [PATCH] PCI: imx6: fix boot hang when link already enabled
From: Lucas Stach @ 2014-07-21 18:12 UTC (permalink / raw)
To: linux-arm-kernel
This fixes a boot hang observed when the bootloader
already enabled the PCIe link for it's own use. The
fundamental problem is that Freescale forgot to wire
up the core reset, so software doesn't have a sane way
to get the core into a defined state.
According to the DW PCIe core reference manual configuration
of the core may only happen when the LTSSM is disabled, so
this is one of the first things we do. Apparently this isn't
safe to do when the LTSSM is in any other state than
"detect" as we observe an instant machine hang when trying to
do so while the link is already up.
As a workaround force LTSSM into detect state right before
hitting the disable switch.
Reported-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
Fabios delay workaround worked because of the following
conditions:
1. The driver gets probed and pulls the peripheral reset GPIO
2. Peripheral is held in reset, so won't answer any link
negotiation requests
3. The LTSSM times out and falls back into detect state
after 24ms (that's why a 30ms delay helps)
4. After LTSSM entered detect state it's safe to hit the
disable switch
---
drivers/pci/host/pci-imx6.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index afa450c54aba..1c4b4b81fe15 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -49,6 +49,9 @@ struct imx6_pcie {
/* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700
+#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
+#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
+#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
@@ -214,6 +217,12 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
{
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ u32 val;
+
+ val = readl(pp->dbi_base + PCIE_PL_PFLR);
+ val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+ val |= PCIE_PL_PFLR_FORCE_LINK;
+ writel(val, pp->dbi_base + PCIE_PL_PFLR);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
--
2.0.1
^ permalink raw reply related
* [RFC] arm: section split in boot/compressed/head.S
From: Leif Lindholm @ 2014-07-21 17:54 UTC (permalink / raw)
To: linux-arm-kernel
Reported-by: Roy Franz <roy.franz@linaro.org>
The current code in boot/compressed/head.S executes pretty much
sequentially from "start", all the way until the end of
"dtb_check_done". However, shortly after the "not_angel" symbol, there
is a section change, in the form of a ".text" directive.
This means any literal pools in .start end up getting inserted into
the middle of the instruction stream.
Would something like the below (pardon the semantic silliness) be an
acceptable fix?
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 3a8b32d..8ee05e9 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -149,6 +149,10 @@ start:
mov r0, #0x17 @ angel_SWIreason_EnterSVC
ARM( swi 0x123456 ) @ angel_SWI_ARM
THUMB( svc 0xab ) @ angel_SWI_THUMB
+ b angel
+
+ .text
+angel:
not_angel:
safe_svcmode_maskall r0
msr spsr_cxsf, r9 @ Save the CPU boot mode in
@@ -163,8 +167,6 @@ not_angel:
* by the linker here, but it should preserve r7, r8, and r9.
*/
- .text
-
#ifdef CONFIG_AUTO_ZRELADDR
@ determine final kernel image address
mov r4, pc
^ permalink raw reply related
* [GIT PULL] omap soc clean-up for v3.17 merge window
From: Olof Johansson @ 2014-07-21 17:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721123000.GB18374@atomide.com>
On Mon, Jul 21, 2014 at 5:30 AM, Tony Lindgren <tony@atomide.com> wrote:
> The following changes since commit cd3de83f147601356395b57a8673e9c5ff1e59d1:
>
> Linux 3.16-rc4 (2014-07-06 12:37:51 -0700)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.17/soc-cleanup
>
> for you to fetch changes up to 3db53918e306d3960bf9e12eea8b2fd3f7d0fd62:
>
> Merge tag 'for-v3.17/omap-clock-a' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.17/soc (2014-07-21 00:35:38 -0700)
>
> ----------------------------------------------------------------
>
> SoC specific omap clean-up for v3.17 merge window:
>
> - Changes to PRM and clock related code to help move
> things to drivers
>
> - Removal of unused ctrl module defines that no longer
> are needed with things moving to .dts files and
> drivers
>
Merged, thanks.
-Olof
^ permalink raw reply
* [PATCH v3 1/2] ARM: at91/dt: describe rgmii ethernet phy connected to sama5d3xek boards
From: Florian Fainelli @ 2014-07-21 17:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53C92D70.6050604@atmel.com>
2014-07-18 7:21 GMT-07:00 Nicolas Ferre <nicolas.ferre@atmel.com>:
> On 10/07/2014 21:59, Boris BREZILLON :
>> Add ethernet-phy nodes and specify phy interrupt (connected to pin PB25)
>> and board specific timing configs.
>>
>> Atmel has two different HW designs for its CPU modules: the first one
>> (produced by Embest) is connecting PHYAD[0-2] pins to pull up resistors
>> and the other one (produced by Ronetix) is connecting PHYAD0 to a pull up
>> resistor and PHYAD[1-2] to pull down resistors.
>> As a result, Ronetix design will have its PHY available at address 0x1 and
>> Embest design at 0x7.
>> By defining both phys we're letting the phy core detect the one actually
>> available on the MDIO bus.
>>
>> Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
>> ---
>>
>> Florian, I dropped your Reviewed-by tag because this patch has slightly
>> changed.
>
> Hi Florian,
>
> I would like to have your Ack on this one as we discussed this solution
> with you.
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
>
> Thanks, bye,
>
>
>> arch/arm/boot/dts/sama5d3xcm.dtsi | 30 ++++++++++++++++++++++++++++++
>> 1 file changed, 30 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi
>> index b0b1331..755369e 100644
>> --- a/arch/arm/boot/dts/sama5d3xcm.dtsi
>> +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi
>> @@ -34,6 +34,36 @@
>>
>> macb0: ethernet at f0028000 {
>> phy-mode = "rgmii";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + ethernet-phy at 1 {
>> + reg = <0x1>;
>> + interrupt-parent = <&pioB>;
>> + interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
>> + txen-skew-ps = <800>;
>> + txc-skew-ps = <3000>;
>> + rxdv-skew-ps = <400>;
>> + rxc-skew-ps = <3000>;
>> + rxd0-skew-ps = <400>;
>> + rxd1-skew-ps = <400>;
>> + rxd2-skew-ps = <400>;
>> + rxd3-skew-ps = <400>;
>> + };
>> +
>> + ethernet-phy at 7 {
>> + reg = <0x7>;
>> + interrupt-parent = <&pioB>;
>> + interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
>> + txen-skew-ps = <800>;
>> + txc-skew-ps = <3000>;
>> + rxdv-skew-ps = <400>;
>> + rxc-skew-ps = <3000>;
>> + rxd0-skew-ps = <400>;
>> + rxd1-skew-ps = <400>;
>> + rxd2-skew-ps = <400>;
>> + rxd3-skew-ps = <400>;
>> + };
>> };
>>
>> pmc: pmc at fffffc00 {
>>
>
>
> --
> Nicolas Ferre
--
Florian
^ permalink raw reply
* [PATCH 1/2] PM / devfreq: Export helper functions for drivers
From: Punit Agrawal @ 2014-07-21 17:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <32148397.172891405898897186.JavaMail.weblogic@epml01>
??? <myungjoo.ham@samsung.com> writes:
> Sender : Punit Agrawal<punit.agrawal@arm.com>
>> From: ?rjan Eide
>>
>> These functions are indended for use by drivers and should be available
>> also when the driver is built as a module.
>>
>> Cc: MyungJoo Ham
>> Cc: Kyungmin Park
>> Signed-off-by: ?rjan Eide
>
> Dear Punit,
Hi MyungJoo,
>
>
> Just being curious, is there any reason not to use EXPORT_SYMBOL_GPL ?
No reason other than to match the existing EXPORT_SYMBOLs in this file.
Would you prefer this and the following patch to use EXPORT_SYMBOL_GPL
instead?
>
>
> Cheers,
> MyungJoo.
>
> --
> MyungJoo Ham (???), PHD
> Frontier CS Lab, Software Center
> Samsung Electronics
> Cell: +82-10-6714-2858--
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RESEND PATCH v3 06/11] drm: add DT bindings documentation for atmel-hlcdc-dc driver
From: Russell King - ARM Linux @ 2014-07-21 17:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140721154313.1de8bf6f@bbrezillon>
On Mon, Jul 21, 2014 at 03:43:13PM +0200, Boris BREZILLON wrote:
> How about using a list instead of an array ?
> This way we can add elements to this list when parsing the EDID.
>
> Or we can just define a maximum size for the bus_formats array when
> retrieving this info from EDID. If I'm correct we have at most 18 bus
> formats:
> - 3 color formats:
> * RGB 4:4:4
> * YCbCr 4:4:4
> * YCbCr 4:4:2
> - 6 color depths: 6, 8, 10, 12, 14 and 16 bits per color
This starts to worry me. What are we trying to do here - are we trying
to encode the connection between the CRTC and the encoder, the encoder
and the connector, or the connector and the device?
The encoder to connector and connector to device is mostly a function of
the interface spec itself (for example, many HDMI encoders take either a
RGB or YUV input and can convert it to the HDMI specified colourspaces for
transmission over the connector.)
If you want to do encoder to connector, what about VGA or some other
analogue signalling such as TV composite? It's easy to take this too
far...
Surely the only one which matters is the CRTC to the encoder - that's
certainly true of all the setups I've come across so far. As for that
interface, CRTCs I've seen can produce a /wide/ range of different
representations.
Some CRTCs (eg, AMBA CLCD) produce R, G, B signals scrunched down on to
the LSB bits of a LCD data bus (so RGB888 uses 24 bits, RGB444 would
use the LSB 12 bits of those 24 - rather than outputting the R4 bits on
a subset of the R8 bits.)
What about RGB565 - where you have differing number of bits for the
green channel from red/blue?
Then you have red/blue colour swapping at the CRTC (and similar for YUV)
such as on Dove / Armada.
Then there are some encoders have the ability to almost arbitarily map
their input pins according to whatever you choose (eg, TDA998x).
This problem isn't as quite as simple as "this is what EDID gives us"
and "these are the number of bits representing a colour".
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [RFC] cpufreq: Add bindings for CPU clock sharing topology
From: Rob Herring @ 2014-07-21 17:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CA8D95.8010108@ti.com>
On Sat, Jul 19, 2014 at 10:24 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> Viresh,
>
> On Saturday 19 July 2014 10:46 AM, Viresh Kumar wrote:
>> On 19 July 2014 03:22, Olof Johansson <olof@lixom.net> wrote:
>>> What is the current API that is being broken, in your opinion?
>>
>> So, currently the nodes doesn't have any such property. And drivers
>> consider all of them as sharing clocks, for eg: cpufreq-cpu0.
>>
>> Now, if we use those older DT's after the new changes, drivers would
>> consider CPUs as having separate clocks. And that would be opposite
>> of what currently happens.
>>
>> Not sure if this counts as broken.
>>
>>>> But if that isn't the case, the bindings are very simple & clear to handle.
>>>> Diff for new bindings:
>>>
>>> It's somewhat confusing to see a diff to the patch instead of a new
>>> version. It seems to remove the cpu 0 entry now?
>>
>> Not really, I removed an unwanted example. This is how it looks:
>>
>>
>>
>> * Generic CPUFreq clock bindings
>>
>> Clock lines may or may not be shared among different CPUs on a platform.
>>
>> Possible configurations:
>> 1.) All CPUs share a single clock line
>> 2.) All CPUs have independent clock lines
>> 3.) CPUs within a group/cluster share clock line but each group/cluster have a
>> separate line for itself
>>
>> Optional Properties:
>> - clock-master: Contains phandle of the master cpu controlling clocks.
>>
>> Ideally there is nothing like a "master" CPU as any CPU can play with DVFS
>> settings. But we have to choose one cpu out of a group, so that others can
>> point to it.
>>
>> If there is no "clock-master" property for a cpu node, it is considered as
>> master. It may or may not have other slave CPUs pointing towards it.
>>
>
> Sorry for jumping late, but one of the point I was raising as part of your
> other series was to extend the CPU topology bindings to cover the voltage
> domain information which is probably what is really needed to let the
> CPUfreq extract the information. Not sure if it was already discussed.
>
> After all the CPU clocks, cluster, clock-gating, power domains are pretty much
> related. So instead of having new binding for CPUFreq, I was wondering whether
> we can extend the CPU topology binding information to include missing information.
> Scheduler work anyway needs that information.
>
> Ref: Documentation/devicetree/bindings/arm/topology.txt
>
> Does that make sense ?
To me, but every time I suggest adding things to the topology the ARM
folks object... I really think we should have built the topology into
the /cpus hierarchy. Then we could add properties at the correct place
in the hierarchy where they are common.
I don't really like the proposal here. It just doesn't look like a
clean description of the h/w.
Ignoring compatibility, I would like to see something like
operating-points and/or the clock properties be moved up to /cpus if
they are shared and be per cpu node when they are not. This of course
does not work if you have independent OPPs for each cluster with a
shared clock within cluster.
The operating-points binding has obvious shortcomings and this is
another example. Someone needs to step up with a new binding that
addresses this and all other issues (e.g. turbo modes, extra per OPP
data, etc.). I don't really want to see halfway fixes to the binding
that ignore the other issues (unless there is a really simple
solution).
Rob
^ permalink raw reply
* [PATCH] platform: Make platform_bus device a platform device
From: Pawel Moll @ 2014-07-21 17:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOesGMgvd1HbjywN7BDPtr8ZU7vucWH48B=AW3TZjng73YA8WA@mail.gmail.com>
... describing the root of the device tree, so one can write
a platform driver initializing the platform.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
For what it's worth, the patch I came up back then.
*Untested* against current head...
arch/arm/mach-imx/devices/devices.c | 4 ++--
arch/unicore32/kernel/puv3-core.c | 2 +-
arch/unicore32/kernel/puv3-nb0916.c | 6 +++---
drivers/base/platform.c | 18 ++++++++++++------
drivers/char/tile-srom.c | 2 +-
drivers/mmc/host/sdhci-pltfm.c | 2 +-
drivers/scsi/hosts.c | 2 +-
include/linux/platform_device.h | 2 +-
8 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
index 1b4366a..48c3817 100644
--- a/arch/arm/mach-imx/devices/devices.c
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -24,12 +24,12 @@
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
- .parent = &platform_bus,
+ .parent = &platform_bus.dev,
};
struct device mxc_ahb_bus = {
.init_name = "mxc_ahb",
- .parent = &platform_bus,
+ .parent = &platform_bus.dev,
};
int __init mxc_device_init(void)
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 254adee..28d1387 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -272,7 +272,7 @@ void __init puv3_core_init(void)
platform_device_register_simple("PKUnity-v3-UART", 1,
puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
- platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+ platform_device_register_resndata(&platform_bus.dev, "musb_hdrc", -1,
puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
&puv3_usb_plat, sizeof(puv3_usb_plat));
}
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
index 0c6618e..4b1c462 100644
--- a/arch/unicore32/kernel/puv3-nb0916.c
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -112,13 +112,13 @@ int __init mach_nb0916_init(void)
platform_device_register_simple("PKUnity-v3-I2C", -1,
puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
- platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+ platform_device_register_data(&platform_bus.dev, "pwm-backlight", -1,
&nb0916_backlight_data, sizeof(nb0916_backlight_data));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(&platform_bus.dev, "gpio-keys", -1,
&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
- platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+ platform_device_register_resndata(&platform_bus.dev, "physmap-flash", -1,
&physmap_flash_resource, 1,
&physmap_flash_data, sizeof(physmap_flash_data));
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index eee48c4..cb69b38 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -30,8 +30,8 @@
/* For automatically allocated device IDs */
static DEFINE_IDA(platform_devid_ida);
-struct device platform_bus = {
- .init_name = "platform",
+struct platform_device platform_bus = {
+ .name = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);
@@ -300,7 +300,7 @@ int platform_device_add(struct platform_device *pdev)
return -EINVAL;
if (!pdev->dev.parent)
- pdev->dev.parent = &platform_bus;
+ pdev->dev.parent = &platform_bus.dev;
pdev->dev.bus = &platform_bus_type;
@@ -946,12 +946,18 @@ int __init platform_bus_init(void)
early_platform_cleanup();
- error = device_register(&platform_bus);
+ dev_set_name(&platform_bus.dev, "%s", platform_bus.name);
+ error = device_register(&platform_bus.name);
if (error)
return error;
error = bus_register(&platform_bus_type);
- if (error)
- device_unregister(&platform_bus);
+ if (!error) {
+ platform_bus.dev.of_node = allnodes;
+ platform_bus.dev.bus = &platform_bus_type;
+ bus_add_device(&platform_bus.dev);
+ } else {
+ device_unregister(&platform_bus.dev);
+ }
return error;
}
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index bd37747..4e4b7a2 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -350,7 +350,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
return -EIO;
- dev = device_create(srom_class, &platform_bus,
+ dev = device_create(srom_class, &platform_bus.dev,
MKDEV(srom_major, index), srom, "%d", index);
return PTR_ERR_OR_ZERO(dev);
}
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 7e834fb..9a2b0d0 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -137,7 +137,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
dev_err(&pdev->dev, "Invalid iomem size!\n");
/* Some PCI-based MFD need the parent here */
- if (pdev->dev.parent != &platform_bus && !np)
+ if (pdev->dev.parent != &platform_bus.dev && !np)
host = sdhci_alloc_host(pdev->dev.parent,
sizeof(struct sdhci_pltfm_host) + priv_size);
else
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 3cbb57a..c14c36f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -218,7 +218,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
goto fail;
if (!shost->shost_gendev.parent)
- shost->shost_gendev.parent = dev ? dev : &platform_bus;
+ shost->shost_gendev.parent = dev ? dev : &platform_bus.dev;
if (!dma_dev)
dma_dev = shost->shost_gendev.parent;
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 16f6654..a99032a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -44,7 +44,7 @@ extern int platform_device_register(struct platform_device *);
extern void platform_device_unregister(struct platform_device *);
extern struct bus_type platform_bus_type;
-extern struct device platform_bus;
+extern struct platform_device platform_bus;
extern void arch_setup_pdev_archdata(struct platform_device *);
extern struct resource *platform_get_resource(struct platform_device *,
--
1.9.1
^ permalink raw reply related
* [PATCH v7 5/5] PCI: keystone: Update maintainer information
From: Murali Karicheri @ 2014-07-21 16:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405961925-27248-1-git-send-email-m-karicheri2@ti.com>
Update the MAINTAINERS file for the keystone PCIe driver
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
CC: Santosh Shilimkar <santosh.shilimkar@ti.com>
CC: Russell King <linux@arm.linux.org.uk>
CC: Grant Likely <grant.likely@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Mohit Kumar <mohit.kumar@st.com>
CC: Jingoo Han <jg1.han@samsung.com>
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Pratyush Anand <pratyush.anand@st.com>
CC: Richard Zhu <r65037@freescale.com>
CC: Kishon Vijay Abraham I <kishon@ti.com>
CC: Marek Vasut <marex@denx.de>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Randy Dunlap <rdunlap@infradead.org>
CC: Grant Likely <grant.likely@linaro.org>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 61a8f48..919b6b1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6805,6 +6805,13 @@ L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/pci/host/*imx6*
+PCI DRIVER FOR keystone
+M: Murali Karicheri <m-karicheri2@ti.com>
+L: linux-pci at vger.kernel.org
+L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/pci/host/*keystone*
+
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
M: Jason Cooper <jason@lakedaemon.net>
--
1.7.9.5
^ permalink raw reply related
* [PATCH v7 4/5] PCI: add PCI controller for keystone PCIe h/w
From: Murali Karicheri @ 2014-07-21 16:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405961925-27248-1-git-send-email-m-karicheri2@ti.com>
keystone PCIe controller is based on v3.65 version of the
designware h/w. Main differences are
1. No ATU support
2. Legacy and MSI irq functions are implemented in
application register space
3. MSI interrupts are multiplexed over 8 IRQ lines to the Host
side.
All of the Application register space handing code are organized into
pci-keystone-dw.c and the functions are called from pci-keystone.c
to implement PCI controller driver. Also add necessary DT documentation
for the driver.
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
CC: Santosh Shilimkar <santosh.shilimkar@ti.com>
CC: Russell King <linux@arm.linux.org.uk>
CC: Grant Likely <grant.likely@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Jingoo Han <jg1.han@samsung.com>
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Richard Zhu <r65037@freescale.com>
CC: Kishon Vijay Abraham I <kishon@ti.com>
CC: Marek Vasut <marex@denx.de>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Randy Dunlap <rdunlap@infradead.org>
CC: Grant Likely <grant.likely@linaro.org>
---
.../devicetree/bindings/pci/pci-keystone.txt | 68 +++
drivers/pci/host/Kconfig | 5 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pci-keystone-dw.c | 521 ++++++++++++++++++++
drivers/pci/host/pci-keystone.c | 386 +++++++++++++++
drivers/pci/host/pci-keystone.h | 58 +++
6 files changed, 1039 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/pci-keystone.txt
create mode 100644 drivers/pci/host/pci-keystone-dw.c
create mode 100644 drivers/pci/host/pci-keystone.c
create mode 100644 drivers/pci/host/pci-keystone.h
diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
new file mode 100644
index 0000000..1bd0476
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -0,0 +1,68 @@
+TI Keystone PCIe interface
+
+Keystone PCI host Controller is based on Designware PCI h/w version 3.65.
+It shares common functions with PCIE Designware core driver and inherit
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt
+
+Please refer to Documentation/devicetree/bindings/pci/designware-pci.txt
+for the details of designware DT bindings. Additional properties are
+described here as well propeties that are not applicable.
+
+Required Properties:-
+
+compatibility: "ti,keystone-pcie"
+reg: index 1 is the base address and length of DW application registers.
+ index 2 is the base address and length of PCI mode configuration
+ register.
+ index 3 is the base address and length of PCI device ID register.
+
+pcie_msi_intc : Interrupt controller device node for MSI irq chip
+ interrupt-cells: should be set to 1
+ interrupt-parent: Parent interrupt controller phandle
+ interrupts: GIC interrupt lines connected to PCI MSI interrupt lines
+
+ Example:
+ pcie_msi_intc: msi-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+ };
+
+pcie_intc: Interrupt controller device node for Legacy irq chip
+ interrupt-cells: should be set to 1
+ interrupt-parent: Parent interrupt controller phandle
+ interrupts: GIC interrupt lines connected to PCI Legacy interrupt lines
+
+ Example:
+ pcie_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 28 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
+ };
+
+Optional properties:-
+ phys: phandle to Generic Keystone SerDes phy for PCI
+ phy-names: name of the Generic Keystine SerDes phy for PCI
+ - If boot loader already does PCI link establishment, then phys and
+ phy-names shouldn't be present.
+
+Designware DT Properties not applicable for Keystone PCI
+
+1. pcie_bus clock-names not used. Instead, a phandle to phys is used.
+
+Note for PCI driver usage
+=========================
+Driver requires pci=pcie_bus_perf in the bootargs for proper functioning.
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 21df477..f8bc475 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -46,4 +46,9 @@ config PCI_HOST_GENERIC
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
+config PCI_KEYSTONE
+ bool "TI Keystone PCIe controller"
+ depends on ARCH_KEYSTONE
+ select PCIE_DW
+ select PCIEPORTBUS
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 611ba4b..d1b6ce1 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
+obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
new file mode 100644
index 0000000..701acb4
--- /dev/null
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -0,0 +1,521 @@
+/*
+ * Designware application register space functions for Keystone PCI controller
+ *
+ * Copyright (C) 2013-2014 Texas Instruments., Ltd.
+ * http://www.ti.com
+ *
+ * Author: Murali Karicheri <m-karicheri2@ti.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+#include "pci-keystone.h"
+
+/* Application register defines */
+#define LTSSM_EN_VAL 1
+#define LTSSM_STATE_MASK 0x1f
+#define LTSSM_STATE_L0 0x11
+#define DBI_CS2_EN_VAL 0x20
+#define OB_XLAT_EN_VAL 2
+
+/* Application registers */
+#define CMD_STATUS 0x004
+#define CFG_SETUP 0x008
+#define OB_SIZE 0x030
+#define CFG_PCIM_WIN_SZ_IDX 3
+#define CFG_PCIM_WIN_CNT 32
+#define SPACE0_REMOTE_CFG_OFFSET 0x1000
+#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
+#define OB_OFFSET_HI(n) (0x204 + (8 * n))
+
+/* IRQ register defines */
+#define IRQ_EOI 0x050
+#define IRQ_STATUS 0x184
+#define IRQ_ENABLE_SET 0x188
+#define IRQ_ENABLE_CLR 0x18c
+
+#define MSI_IRQ 0x054
+#define MSI0_IRQ_STATUS 0x104
+#define MSI0_IRQ_ENABLE_SET 0x108
+#define MSI0_IRQ_ENABLE_CLR 0x10c
+#define IRQ_STATUS 0x184
+#define MSI_IRQ_OFFSET 4
+
+/* Config space registers */
+#define DEBUG0 0x728
+
+#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
+
+static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
+{
+ return sys->private_data;
+}
+
+static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
+ u32 *bit_pos)
+{
+ *reg_offset = offset % 8;
+ *bit_pos = offset >> 3;
+}
+
+u32 ks_dw_pcie_get_msi_data(struct pcie_port *pp)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+
+ return ks_pcie->app.start + MSI_IRQ;
+}
+
+void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie , int offset)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ u32 pending, vector;
+ int src, virq;
+
+ pending = readl(ks_pcie->va_app_base + MSI0_IRQ_STATUS + (offset << 4));
+ /*
+ * MSI0, Status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
+ * shows 1, 9, 17, 25 and so forth
+ */
+ for (src = 0; src < 4; src++) {
+ if (BIT(src) & pending) {
+ vector = offset + (src << 3);
+ virq = irq_linear_revmap(pp->irq_domain, vector);
+ dev_dbg(pp->dev,
+ "irq: bit %d, vector %d, virq %d\n",
+ src, vector, virq);
+ generic_handle_irq(virq);
+ }
+ }
+}
+
+static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
+{
+ u32 offset, reg_offset, bit_pos;
+ struct keystone_pcie *ks_pcie;
+ unsigned int irq = d->irq;
+ struct msi_desc *msi;
+ struct pcie_port *pp;
+
+ msi = irq_get_msi_desc(irq);
+ pp = sys_to_pcie(msi->dev->bus->sysdata);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+ update_reg_offset_bit_pos(offset, ®_offset, &bit_pos);
+
+ writel(BIT(bit_pos),
+ ks_pcie->va_app_base + MSI0_IRQ_STATUS + (reg_offset << 4));
+ writel(reg_offset + MSI_IRQ_OFFSET, ks_pcie->va_app_base + IRQ_EOI);
+}
+
+void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
+{
+ u32 reg_offset, bit_pos;
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+
+ update_reg_offset_bit_pos(irq, ®_offset, &bit_pos);
+ writel(BIT(bit_pos),
+ ks_pcie->va_app_base + MSI0_IRQ_ENABLE_SET + (reg_offset << 4));
+}
+
+void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
+{
+ u32 reg_offset, bit_pos;
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+
+ update_reg_offset_bit_pos(irq, ®_offset, &bit_pos);
+ writel(BIT(bit_pos),
+ ks_pcie->va_app_base + MSI0_IRQ_ENABLE_CLR + (reg_offset << 4));
+}
+
+static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
+{
+ struct keystone_pcie *ks_pcie;
+ unsigned int irq = d->irq;
+ struct msi_desc *msi;
+ struct pcie_port *pp;
+ u32 offset;
+
+ msi = irq_get_msi_desc(irq);
+ pp = sys_to_pcie(msi->dev->bus->sysdata);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+
+ /* mask the end point if PVM implemented */
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ if (msi->msi_attrib.maskbit)
+ mask_msi_irq(d);
+ }
+
+ ks_dw_pcie_msi_clear_irq(pp, offset);
+}
+
+static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
+{
+ struct keystone_pcie *ks_pcie;
+ unsigned int irq = d->irq;
+ struct msi_desc *msi;
+ struct pcie_port *pp;
+ u32 offset;
+
+ msi = irq_get_msi_desc(irq);
+ pp = sys_to_pcie(msi->dev->bus->sysdata);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+
+ /* mask the end point if PVM implemented */
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ if (msi->msi_attrib.maskbit)
+ unmask_msi_irq(d);
+ }
+
+ ks_dw_pcie_msi_set_irq(pp, offset);
+}
+
+static struct irq_chip ks_dw_pcie_msi_irq_chip = {
+ .name = "Keystone-PCIe-MSI-IRQ",
+ .irq_ack = ks_dw_pcie_msi_irq_ack,
+ .irq_mask = ks_dw_pcie_msi_irq_mask,
+ .irq_unmask = ks_dw_pcie_msi_irq_unmask,
+};
+
+static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip,
+ handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+ set_irq_flags(irq, IRQF_VALID);
+
+ return 0;
+}
+
+const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
+ .map = ks_dw_pcie_msi_map,
+};
+
+int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
+ struct msi_chip *chip)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+ int i;
+
+ pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
+ MAX_MSI_IRQS,
+ &ks_dw_pcie_msi_domain_ops,
+ chip);
+ if (!pp->irq_domain) {
+ dev_err(pp->dev, "irq domain init failed\n");
+ return -ENXIO;
+ }
+
+ for (i = 0; i < MAX_MSI_IRQS; i++)
+ irq_create_mapping(pp->irq_domain, i);
+
+ return 0;
+}
+
+void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
+{
+ int i;
+
+ for (i = 0; i < MAX_LEGACY_IRQS; i++)
+ writel(0x1, ks_pcie->va_app_base + IRQ_ENABLE_SET + (i << 4));
+}
+
+void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ u32 pending;
+ int virq;
+
+ pending = readl(ks_pcie->va_app_base + IRQ_STATUS + (offset << 4));
+
+ if (BIT(0) & pending) {
+ virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
+ dev_dbg(pp->dev,
+ ": irq: irq_offset %d, virq %d\n", offset, virq);
+ generic_handle_irq(virq);
+ }
+
+ /* EOI the INTx interrupt */
+ writel(offset, ks_pcie->va_app_base + IRQ_EOI);
+}
+
+static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
+{
+}
+
+static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
+{
+}
+
+static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
+{
+}
+
+static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
+ .name = "Keystone-PCI-Legacy-IRQ",
+ .irq_ack = ks_dw_pcie_ack_legacy_irq,
+ .irq_mask = ks_dw_pcie_mask_legacy_irq,
+ .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
+};
+
+static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
+ unsigned int irq, irq_hw_number_t hw_irq)
+{
+ irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
+ handle_level_irq);
+ irq_set_chip_data(irq, d->host_data);
+ set_irq_flags(irq, IRQF_VALID);
+
+ return 0;
+}
+
+static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domian_ops = {
+ .map = ks_dw_pcie_init_legacy_irq_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+/**
+ * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask registers
+ *
+ * Since modification of dbi_cs2 involves different clock domain, read the
+ * status back to ensure the transition is complete.
+ */
+static void ks_dw_pcie_set_dbi_mode(void __iomem *reg_virt)
+{
+ u32 val;
+
+ writel(DBI_CS2_EN_VAL | readl(reg_virt + CMD_STATUS),
+ reg_virt + CMD_STATUS);
+
+ do {
+ val = readl(reg_virt + CMD_STATUS);
+ } while (!(val & DBI_CS2_EN_VAL));
+}
+
+/**
+ * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
+ *
+ * Since modification of dbi_cs2 involves different clock domain, read the
+ * status back to ensure the transition is complete.
+ */
+static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
+{
+ u32 val;
+
+ writel(~DBI_CS2_EN_VAL & readl(reg_virt + CMD_STATUS),
+ reg_virt + CMD_STATUS);
+
+ do {
+ val = readl(reg_virt + CMD_STATUS);
+ } while (val & DBI_CS2_EN_VAL);
+}
+
+void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ u32 start = pp->mem.start, end = pp->mem.end;
+ int i, tr_size;
+
+ /* disable BARS for inbound access */
+ ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
+ writel(0, pp->dbi_base + PCI_BASE_ADDRESS_0);
+ writel(0, pp->dbi_base + PCI_BASE_ADDRESS_1);
+ ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
+
+ /* Set outbound translation size per window division */
+ writel(CFG_PCIM_WIN_SZ_IDX & 0x7, ks_pcie->va_app_base + OB_SIZE);
+
+ tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
+
+ /* Using Direct 1:1 mapping of RC <-> PCI memory space */
+ for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
+ writel(start | 1, ks_pcie->va_app_base + OB_OFFSET_INDEX(i));
+ writel(0, ks_pcie->va_app_base + OB_OFFSET_HI(i));
+ start += tr_size;
+ }
+
+ /* Enable OB translation */
+ writel(OB_XLAT_EN_VAL | readl(ks_pcie->va_app_base + CMD_STATUS),
+ ks_pcie->va_app_base + CMD_STATUS);
+}
+
+/**
+ * ks_pcie_cfg_setup() - Set up configuration space address for a
+ * device
+ *
+ * @ks_pcie: ptr to keystone_pcie structure
+ * @bus: Bus number the device is residing on
+ * @devfn: device, function number info
+ *
+ * Forms and returns the address of configuration space mapped in PCIESS
+ * address space 0. Also configures CFG_SETUP for remote configuration space
+ * access.
+ *
+ * The address space has two regions to access configuration - local and remote.
+ * We access local region for bus 0 (as RC is attached on bus 0) and remote
+ * region for others with TYPE 1 access when bus > 1. As for device on bus = 1,
+ * we will do TYPE 0 access as it will be on our secondary bus (logical).
+ * CFG_SETUP is needed only for remote configuration access.
+ */
+static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
+ unsigned int devfn)
+{
+ u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
+ struct pcie_port *pp = &ks_pcie->pp;
+ u32 regval;
+
+ if (bus == 0)
+ return pp->dbi_base;
+
+ regval = (bus << 16) | (device << 8) | function;
+ /*
+ * Since Bus#1 will be a virtual bus, we need to have TYPE0
+ * access only.
+ * TYPE 1
+ */
+ if (bus != 1)
+ regval |= BIT(24);
+
+ writel(regval, ks_pcie->va_app_base + CFG_SETUP);
+ return pp->va_cfg0_base;
+}
+
+int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+ u8 bus_num = bus->number;
+ void __iomem *addr;
+ int ret;
+
+ addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+ ret = dw_pcie_cfg_read(addr + (where & ~0x3), where, size, val);
+
+ return ret;
+}
+
+int ks_dw_pcie_wr_other_conf(struct pcie_port *pp,
+ struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+ u8 bus_num = bus->number;
+ void __iomem *addr;
+
+ addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+
+ return dw_pcie_cfg_write(addr + (where & ~0x3), where, size, val);
+}
+
+/**
+ * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
+ *
+ * This sets BAR0 to enable inbound access for MSI_IRQ register
+ */
+void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+
+ /* Configure and set up BAR0 */
+ ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
+
+ /* Enable BAR0 */
+ writel(1, pp->dbi_base + PCI_BASE_ADDRESS_0);
+ writel(SZ_4K - 1, pp->dbi_base + PCI_BASE_ADDRESS_0);
+
+ ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
+
+ /*
+ * For BAR0, just setting bus address for inbound writes (MSI) should
+ * be sufficient. Use physical address to avoid any conflicts.
+ */
+ writel(ks_pcie->app.start, pp->dbi_base + PCI_BASE_ADDRESS_0);
+}
+
+/**
+ * ks_dw_pcie_link_up() - Check if link up
+ *
+ */
+int ks_dw_pcie_link_up(struct pcie_port *pp)
+{
+ u32 val = readl(pp->dbi_base + DEBUG0);
+
+ return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
+}
+
+void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+
+ /* first disable Link training */
+ val = readl(ks_pcie->va_app_base + CMD_STATUS);
+ val &= ~LTSSM_EN_VAL;
+ writel(LTSSM_EN_VAL | val, ks_pcie->va_app_base + CMD_STATUS);
+
+ /* Initiate Link Training. */
+ val = readl(ks_pcie->va_app_base + CMD_STATUS);
+ writel(LTSSM_EN_VAL | val, ks_pcie->va_app_base + CMD_STATUS);
+}
+
+/**
+ * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
+ *
+ * It ioremap the register resources, initialize legacy irq domain
+ * and then call dw_pcie_v3_65_host_init() API to intialize the Keystone
+ * PCI host controller.
+ *
+ */
+int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
+ struct device_node *msi_intc_np)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ struct platform_device *pdev = to_platform_device(pp->dev);
+ struct resource *res;
+
+ /* index 0 is the config reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pp->dbi_base = devm_ioremap_resource(pp->dev, res);
+ if (IS_ERR(pp->dbi_base))
+ return PTR_ERR(pp->dbi_base);
+
+ /*
+ * we set these same and is used in pcie rd/wr_other_conf
+ * functions
+ */
+ pp->va_cfg0_base = pp->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
+ pp->va_cfg1_base = pp->va_cfg0_base;
+
+ /* index 1 is the application reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ks_pcie->app = *res;
+ ks_pcie->va_app_base = devm_ioremap_resource(pp->dev, res);
+ if (IS_ERR(ks_pcie->va_app_base))
+ return PTR_ERR(ks_pcie->va_app_base);
+
+ /* create legacy irq domain */
+ ks_pcie->legacy_irq_domain =
+ irq_domain_add_linear(ks_pcie->legacy_intc_np,
+ MAX_LEGACY_IRQS,
+ &ks_dw_pcie_legacy_irq_domian_ops,
+ NULL);
+ if (!ks_pcie->legacy_irq_domain) {
+ dev_err(pp->dev, "Failed to add irq domain for legacy irqs\n");
+ return -EINVAL;
+ }
+
+ return dw_pcie_host_init(pp);
+}
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
new file mode 100644
index 0000000..c1cfaef
--- /dev/null
+++ b/drivers/pci/host/pci-keystone.c
@@ -0,0 +1,386 @@
+/*
+ * PCIe host controller driver for Texas Instruments Keystone SoCs
+ *
+ * Copyright (C) 2013-2014 Texas Instruments., Ltd.
+ * http://www.ti.com
+ *
+ * Author: Murali Karicheri <m-karicheri2@ti.com>
+ * Implementation based on pci-exynos.c and pcie-designware.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irqchip/chained_irq.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+
+#include "pcie-designware.h"
+#include "pci-keystone.h"
+
+#define DRIVER_NAME "keystone-pcie"
+
+/* driver specific constants */
+#define MAX_MSI_HOST_IRQS 8
+#define MAX_LEGACY_HOST_IRQS 4
+
+/* RC mode settings masks */
+#define PCIE_RC_MODE BIT(2)
+#define PCIE_MODE_MASK (BIT(1) | BIT(2))
+
+/* DEV_STAT_CTRL */
+#define PCIE_CAP_BASE 0x70
+
+#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
+
+static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ int count = 200;
+
+ dw_pcie_setup_rc(pp);
+
+ if (dw_pcie_link_up(pp)) {
+ dev_err(pp->dev, "Link already up\n");
+ return 0;
+ }
+
+ ks_dw_pcie_initiate_link_train(ks_pcie);
+ /* check if the link is up or not */
+ while (!dw_pcie_link_up(pp)) {
+ usleep_range(100, 1000);
+ if (--count) {
+ ks_dw_pcie_initiate_link_train(ks_pcie);
+ continue;
+ }
+ dev_err(pp->dev, "phy link never came up\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
+ u32 offset = irq - ks_pcie->msi_host_irqs[0];
+ struct pcie_port *pp = &ks_pcie->pp;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ dev_dbg(pp->dev, "ks_pci_msi_irq_handler, irq %d\n", irq);
+
+ /*
+ * The chained irq handler installation would have replaced normal
+ * interrupt driver handler so we need to take care of mask/unmask and
+ * ack operation.
+ */
+ chained_irq_enter(chip, desc);
+ ks_dw_pcie_handle_msi_irq(ks_pcie, offset);
+ chained_irq_exit(chip, desc);
+}
+
+/**
+ * ks_pcie_legacy_irq_handler() - Handle legacy interrupt
+ * @irq: IRQ line for legacy interrupts
+ * @desc: Pointer to irq descriptor
+ *
+ * Traverse through pending legacy interrupts and invoke handler for each. Also
+ * takes care of interrupt controller level mask/ack operation.
+ */
+static void ks_pcie_legacy_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
+ struct pcie_port *pp = &ks_pcie->pp;
+ u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ dev_dbg(pp->dev, ": Handling legacy irq %d\n", irq);
+
+ /*
+ * The chained irq handler installation would have replaced normal
+ * interrupt driver handler so we need to take care of mask/unmask and
+ * ack operation.
+ */
+ chained_irq_enter(chip, desc);
+ ks_dw_pcie_handle_legacy_irq(ks_pcie, irq_offset);
+ chained_irq_exit(chip, desc);
+}
+
+static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
+ char *controller, int *num_irqs)
+{
+ int temp, max_host_irqs, legacy = 1, *host_irqs, ret = -EINVAL;
+ struct device *dev = ks_pcie->pp.dev;
+ struct device_node *np_pcie = dev->of_node, **np_temp;
+
+ if (!strcmp(controller, "msi-interrupt-controller"))
+ legacy = 0;
+
+ if (legacy) {
+ np_temp = &ks_pcie->legacy_intc_np;
+ max_host_irqs = MAX_LEGACY_HOST_IRQS;
+ host_irqs = &ks_pcie->legacy_host_irqs[0];
+ } else {
+ np_temp = &ks_pcie->msi_intc_np;
+ max_host_irqs = MAX_MSI_HOST_IRQS;
+ host_irqs = &ks_pcie->msi_host_irqs[0];
+ }
+
+ /* interrupt controller is in a child node */
+ *np_temp = of_find_node_by_name(np_pcie, controller);
+ if (!(*np_temp)) {
+ dev_err(dev, "Node for %s is absent\n", controller);
+ goto out;
+ }
+ temp = of_irq_count(*np_temp);
+ if (!temp)
+ goto out;
+ if (temp > max_host_irqs)
+ dev_warn(dev, "Too many %s interrupts defined %u\n",
+ (legacy ? "legacy" : "MSI"), temp);
+
+ /*
+ * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
+ * 7 (MSI)
+ */
+ for (temp = 0; temp < max_host_irqs; temp++) {
+ host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
+ if (host_irqs[temp] < 0)
+ break;
+ }
+ if (temp) {
+ *num_irqs = temp;
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
+{
+ int i;
+
+ /* Legacy IRQ */
+ for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
+ irq_set_handler_data(ks_pcie->legacy_host_irqs[i], ks_pcie);
+ irq_set_chained_handler(ks_pcie->legacy_host_irqs[i],
+ ks_pcie_legacy_irq_handler);
+ }
+ ks_dw_pcie_enable_legacy_irqs(ks_pcie);
+
+ /* MSI IRQ */
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
+ irq_set_chained_handler(ks_pcie->msi_host_irqs[i],
+ ks_pcie_msi_irq_handler);
+ irq_set_handler_data(ks_pcie->msi_host_irqs[i],
+ ks_pcie);
+ }
+ }
+}
+
+/*
+ * When a PCI device does not exist during config cycles, keystone host gets a
+ * bus error instead of returning 0xffffffff. This handler always returns 0
+ * for this kind of faults.
+ */
+static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs)
+{
+ unsigned long instr = *(unsigned long *) instruction_pointer(regs);
+
+ if ((instr & 0x0e100090) == 0x00100090) {
+ int reg = (instr >> 12) & 15;
+
+ regs->uregs[reg] = -1;
+ regs->ARM_pc += 4;
+ }
+
+ return 0;
+}
+
+static void __init ks_pcie_host_init(struct pcie_port *pp)
+{
+ u32 vendor_device_id, val;
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
+
+ ks_pcie_establish_link(ks_pcie);
+ ks_dw_pcie_setup_rc_app_regs(ks_pcie);
+ ks_pcie_setup_interrupts(ks_pcie);
+ writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
+ pp->dbi_base + PCI_IO_BASE);
+
+ /* update the Vendor ID */
+ vendor_device_id = readl(ks_pcie->va_reg_pciid);
+ writew((vendor_device_id >> 16), pp->dbi_base + PCI_DEVICE_ID);
+
+ /* update the DEV_STAT_CTRL to publish right mrrs */
+ val = readl(pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
+ val &= ~PCI_EXP_DEVCTL_READRQ;
+ /* set the mrrs to 256 bytes */
+ val |= BIT(12);
+ writel(val, pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
+
+ /*
+ * PCIe access errors that result into OCP errors are caught by ARM as
+ * "External aborts"
+ */
+ hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
+ "Asynchronous external abort");
+}
+
+static struct pcie_host_ops keystone_pcie_host_ops = {
+ .rd_other_conf = ks_dw_pcie_rd_other_conf,
+ .wr_other_conf = ks_dw_pcie_wr_other_conf,
+ .link_up = ks_dw_pcie_link_up,
+ .host_init = ks_pcie_host_init,
+ .msi_set_irq = ks_dw_pcie_msi_set_irq,
+ .msi_clear_irq = ks_dw_pcie_msi_clear_irq,
+ .get_msi_data = ks_dw_pcie_get_msi_data,
+ .msi_host_init = ks_dw_pcie_msi_host_init,
+ .scan_bus = ks_dw_pcie_v3_65_scan_bus,
+};
+
+static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
+ struct platform_device *pdev)
+{
+ struct pcie_port *pp = &ks_pcie->pp;
+ int ret;
+
+ ret = ks_pcie_get_irq_controller_info(ks_pcie,
+ "legacy-interrupt-controller",
+ &ks_pcie->num_legacy_host_irqs);
+ if (ret)
+ return ret;
+
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ ret = ks_pcie_get_irq_controller_info(ks_pcie,
+ "msi-interrupt-controller",
+ &ks_pcie->num_msi_host_irqs);
+ if (ret)
+ return ret;
+ }
+
+ pp->root_bus_nr = -1;
+ pp->ops = &keystone_pcie_host_ops;
+ ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static const struct of_device_id ks_pcie_of_match[] = {
+ {
+ .type = "pci",
+ .compatible = "ti,keystone-pcie",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ks_pcie_of_match);
+
+static int __exit ks_pcie_remove(struct platform_device *pdev)
+{
+ struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ks_pcie->clk);
+
+ return 0;
+}
+
+static int __init ks_pcie_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct keystone_pcie *ks_pcie;
+ struct pcie_port *pp;
+ struct resource *res;
+ void __iomem *reg_p;
+ struct phy *phy;
+ int ret = 0;
+ u32 val;
+
+ ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie),
+ GFP_KERNEL);
+ if (!ks_pcie) {
+ dev_err(dev, "no memory for keystone pcie\n");
+ return -ENOMEM;
+ }
+ pp = &ks_pcie->pp;
+
+ /* index 2 is the devcfg register for RC mode settings */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ reg_p = devm_ioremap_resource(dev, res);
+ if (IS_ERR(reg_p))
+ return PTR_ERR(reg_p);
+
+ /* enable RC mode in devcfg */
+ val = readl(reg_p);
+ val &= ~PCIE_MODE_MASK;
+ val |= PCIE_RC_MODE;
+ writel(val, reg_p);
+
+ /* initialize SerDes Phy if present */
+ phy = devm_phy_get(dev, "pcie-phy");
+ if (!IS_ERR_OR_NULL(phy)) {
+ ret = phy_init(phy);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* index 3 is to read PCI DEVICE_ID */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ reg_p = devm_ioremap_resource(dev, res);
+ if (IS_ERR(reg_p))
+ return PTR_ERR(reg_p);
+ ks_pcie->va_reg_pciid = reg_p;
+
+ pp->dev = dev;
+ platform_set_drvdata(pdev, ks_pcie);
+ ks_pcie->clk = devm_clk_get(dev, "pcie");
+ if (IS_ERR(ks_pcie->clk)) {
+ dev_err(dev, "Failed to get pcie rc clock\n");
+ return PTR_ERR(ks_pcie->clk);
+ }
+ ret = clk_prepare_enable(ks_pcie->clk);
+ if (ret)
+ return ret;
+
+ ret = ks_add_pcie_port(ks_pcie, pdev);
+ if (ret < 0)
+ goto fail_clk;
+
+ return 0;
+fail_clk:
+ clk_disable_unprepare(ks_pcie->clk);
+
+ return ret;
+}
+
+static struct platform_driver ks_pcie_driver __refdata = {
+ .probe = ks_pcie_probe,
+ .remove = __exit_p(ks_pcie_remove),
+ .driver = {
+ .name = "keystone-pcie",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ks_pcie_of_match),
+ },
+};
+
+module_platform_driver(ks_pcie_driver);
+
+MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
+MODULE_DESCRIPTION("Keystone PCIe host controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h
new file mode 100644
index 0000000..729ea7d
--- /dev/null
+++ b/drivers/pci/host/pci-keystone.h
@@ -0,0 +1,58 @@
+/*
+ * Keystone PCI Controller's common includes
+ *
+ * Copyright (C) 2013-2014 Texas Instruments., Ltd.
+ * http://www.ti.com
+ *
+ * Author: Murali Karicheri <m-karicheri2@ti.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define MAX_LEGACY_IRQS 4
+#define MAX_MSI_HOST_IRQS 8
+#define MAX_LEGACY_HOST_IRQS 4
+
+struct keystone_pcie {
+ struct clk *clk;
+ struct pcie_port pp;
+ void __iomem *va_reg_pciid;
+
+ int num_legacy_host_irqs;
+ int legacy_host_irqs[MAX_LEGACY_HOST_IRQS];
+ struct device_node *legacy_intc_np;
+
+ int num_msi_host_irqs;
+ int msi_host_irqs[MAX_MSI_HOST_IRQS];
+ struct device_node *msi_intc_np;
+ struct irq_domain *legacy_irq_domain;
+
+ /* Application register space */
+ void __iomem *va_app_base;
+ struct resource app;
+};
+
+/* Keystone DW specific MSI controller APIs/definitions */
+void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset);
+u32 ks_dw_pcie_get_msi_data(struct pcie_port *pp);
+
+/* Keystone specific PCI controller APIs */
+void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
+void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
+int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
+ struct device_node *msi_intc_np);
+int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 val);
+int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val);
+void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
+int ks_dw_pcie_link_up(struct pcie_port *pp);
+void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
+void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
+void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
+void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
+int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
+ struct msi_chip *chip);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v7 3/5] PCI: designware: enhance dw_pcie_host_init() to support v3.65 DW hardware
From: Murali Karicheri @ 2014-07-21 16:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405961925-27248-1-git-send-email-m-karicheri2@ti.com>
keystone PCI controller is based on v3.65 designware hardware. This
version differs from newer versions of the hardware in few functional
areas discussed below that makes it necessary to change dw_pcie_host_init()
to support v3.65 based PCI controller.
1. No support for ATU port. So any ATU specific resource handling code
is to be bypassed for v3.65 h/w.
2. MSI controller uses Application space to implement MSI and 32 MSI
interrupts are multiplexed over 8 IRQs to the host. Hence the code
to process MSI IRQ needs to be different. This patch allows platform
driver to provide its own irq_domain_ops ptr to irq_domain_add_linear()
through an API callback from the designware core driver.
3. MSI interrupt generation requires EP to write to the RC's application
register. So enhance the driver to allow setup of inbound access to
MSI irq register as a post scan bus API callback.
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Reviewed-by: Pratyush Anand <pratyush.anand@st.com>
Acked-by: Mohit KUMAR <mohit.kumar@st.com>
CC: Santosh Shilimkar <santosh.shilimkar@ti.com>
CC: Russell King <linux@arm.linux.org.uk>
CC: Grant Likely <grant.likely@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Jingoo Han <jg1.han@samsung.com>
CC: Bjorn Helgaas <bhelgaas@google.com>
CC: Richard Zhu <r65037@freescale.com>
CC: Kishon Vijay Abraham I <kishon@ti.com>
CC: Marek Vasut <marex@denx.de>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Randy Dunlap <rdunlap@infradead.org>
CC: Grant Likely <grant.likely@linaro.org>
---
drivers/pci/host/pcie-designware.c | 54 +++++++++++++++++++++++-------------
drivers/pci/host/pcie-designware.h | 2 ++
2 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 905941c..35bb4af 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -420,8 +420,8 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
struct device_node *np = pp->dev->of_node;
struct of_pci_range range;
struct of_pci_range_parser parser;
+ int i, ret;
u32 val;
- int i;
if (of_pci_range_parser_init(&parser, np)) {
dev_err(pp->dev, "missing ranges property\n");
@@ -467,21 +467,26 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
}
}
- pp->cfg0_base = pp->cfg.start;
- pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
pp->mem_base = pp->mem.start;
- pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
- pp->config.cfg0_size);
if (!pp->va_cfg0_base) {
- dev_err(pp->dev, "error with ioremap in function\n");
- return -ENOMEM;
+ pp->cfg0_base = pp->cfg.start;
+ pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
+ pp->config.cfg0_size);
+ if (!pp->va_cfg0_base) {
+ dev_err(pp->dev, "error with ioremap in function\n");
+ return -ENOMEM;
+ }
}
- pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
- pp->config.cfg1_size);
+
if (!pp->va_cfg1_base) {
- dev_err(pp->dev, "error with ioremap\n");
- return -ENOMEM;
+ pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
+ pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
+ pp->config.cfg1_size);
+ if (!pp->va_cfg1_base) {
+ dev_err(pp->dev, "error with ioremap\n");
+ return -ENOMEM;
+ }
}
if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
@@ -490,16 +495,22 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
}
if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
- MAX_MSI_IRQS, &msi_domain_ops,
- &dw_pcie_msi_chip);
- if (!pp->irq_domain) {
- dev_err(pp->dev, "irq domain init failed\n");
- return -ENXIO;
- }
+ if (!pp->ops->msi_host_init) {
+ pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
+ MAX_MSI_IRQS, &msi_domain_ops,
+ &dw_pcie_msi_chip);
+ if (!pp->irq_domain) {
+ dev_err(pp->dev, "irq domain init failed\n");
+ return -ENXIO;
+ }
- for (i = 0; i < MAX_MSI_IRQS; i++)
- irq_create_mapping(pp->irq_domain, i);
+ for (i = 0; i < MAX_MSI_IRQS; i++)
+ irq_create_mapping(pp->irq_domain, i);
+ } else {
+ ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
+ if (ret < 0)
+ return ret;
+ }
}
if (pp->ops->host_init)
@@ -759,6 +770,9 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
BUG();
}
+ if (bus && pp->ops->scan_bus)
+ pp->ops->scan_bus(pp);
+
return bus;
}
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index 387f69e..080c649 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -70,6 +70,8 @@ struct pcie_host_ops {
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
u32 (*get_msi_data)(struct pcie_port *pp);
+ void (*scan_bus)(struct pcie_port *pp);
+ int (*msi_host_init)(struct pcie_port *pp, struct msi_chip *chip);
};
int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox