Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH] ARM: dts: qcom: Add RNG device tree node
From: Stanimir Varbanov @ 2014-02-12  9:28 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: devicetree, linux-arm-kernel, linux-arm-msm, Kumar Gala,
	Mark Rutland, Rob Herring, Pawel Moll, Ian Campbell, David Brown
In-Reply-To: <20140208033740.GD10784@codeaurora.org>

Hi, Stephen

On 02/08/2014 05:37 AM, Stephen Boyd wrote:
> On 02/07, Stanimir Varbanov wrote:
>> Add the necessary DT node to probe the rng driver on
>> msm8974 platforms.
>>
> 
> Looks good. We should add it to msm8960-cdp and enable the driver
> in the defconfig as well.

Sure, I can prepare a patch. Unfortunately I haven't msm8960 CDP to test it.

> 
>> Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
> 
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
> 

Thanks!

regards,
Stan

^ permalink raw reply

* Re: [PATCH v2 01/02] ARM: shmobile: Add SDHI devices to r8a7791 DTSI
From: Geert Uytterhoeven @ 2014-02-12  9:27 UTC (permalink / raw)
  To: Magnus Damm
  Cc: Linux-sh list, Simon Horman, Kuninori Morimoto,
	devicetree@vger.kernel.org
In-Reply-To: <CANqRtoQ8uYZcMQC5EQ6DLHGb3noOFsnTvtFTvPaMQarOdkD5Aw@mail.gmail.com>

On Wed, Feb 12, 2014 at 9:51 AM, Magnus Damm <magnus.damm@gmail.com> wrote:
>>>>>  - add r8a7790 suffix as fall back in case r8a7791 is missing from the driver

>>>>> +       sdhi0: sd@ee100000 {
>>>>> +               compatible = "renesas,sdhi-r8a7791", "renesas,sdhi-r8a7790";

>>>> I'm afraid that's not such a good idea: what if r8a7791 SDHI turns out to have a
>>>> slight incompatibility with r8a7790 SDHI later?
>>>
>>> It's a fallback so later we will simply use r8a7791 instead. r8a7790
>>> is currently used with the v3.14-rc version of the SDHI driver. Future
>>> ones always include r8a7791. How does that introduce any issues?
>>
>> Bummer, yes, it prefers the first compatible entry.
>>
>> Will refrain from sending more emails until my coffee has been digested ;-)
>
> Heheh. But I think you raise a valid point:
>
> Using the wrong SoC in the compatible string is pretty darn ugly.
>
> What is the best practise here?

(adding devicetree)

It should be a reference to the hardware block.

Before the advent of SoCs, a hardware block was an IC, with a part number
(e.g. de21040), and sometimes a name (e.g. tulip). Further evolutions of the
hardware block got (usually, but not always) different part numbers.

With SoCs, the part numbers of the hardware blocks were lost. Only the SoC
still carries a part number. The hardware blocks (now called "IP cores") still
have names (e.g. RSPI), but they're more abstract, and it's difficult to know
what exact version of the hardware block they're referring to[*].

Using "<manufacturer>,<name>-<soc>" is future-proof, but cumbersome.
Having a more generic fallback name to group SoCs with the same IP core
is convenient.

So we have to "invent" generic fallback names with versioning ourselves?

  - SoC family name? But there's no guarantee a new SoC from the same
    family will be 100% compatible.
  - "-v1", "-v2" suffixes? The new SoC may have something in between
    v1 and v2
  - ???

[*] With OpenRISC it's easier, as we have the hardware source files, but
    it's still cumbersome to find good version naming.
    The OpenCores-mandated "<name>-rtlsvn<version>" is not such a good
    match for todays distributed development, with IP cores being imported
    into git repositories and modified there.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v2] [media] of: move graph helpers from drivers/media/v4l2-core to drivers/media
From: Philipp Zabel @ 2014-02-12  9:25 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Russell King - ARM Linux, Mauro Carvalho Chehab, Grant Likely,
	Rob Herring, Sylwester Nawrocki, Laurent Pinchart, Kyungmin Park,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-media-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Guennadi Liakhovetski,
	Philipp Zabel
In-Reply-To: <52FB1FA8.2070903-l0cyMroinI0@public.gmane.org>

Hi Tomi,

Am Mittwoch, den 12.02.2014, 09:15 +0200 schrieb Tomi Valkeinen:
> Hi,
> 
> On 11/02/14 23:41, Philipp Zabel wrote:
> > From: Philipp Zabel <philipp.zabel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > 
> > This patch moves the parsing helpers used to parse connected graphs
> > in the device tree, like the video interface bindings documented in
> > Documentation/devicetree/bindings/media/video-interfaces.txt, from
> > drivers/media/v4l2-core to drivers/media.
> > 
> > This allows to reuse the same parser code from outside the V4L2
> > framework, most importantly from display drivers.
> > The functions v4l2_of_get_next_endpoint, v4l2_of_get_remote_port,
> > and v4l2_of_get_remote_port_parent are moved. They are renamed to
> > of_graph_get_next_endpoint, of_graph_get_remote_port, and
> > of_graph_get_remote_port_parent, respectively.
> > Since there are not that many current users, switch all of them
> > to the new functions right away.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > Acked-by: Mauro Carvalho Chehab <m.chehab-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> > Acked-by: Guennadi Liakhovetski <g.liakhovetski-Mmb7MZpHnFY@public.gmane.org>
> 
> I don't think the graphs or the parsing code has anything video
> specific. It could well be used for anything, whenever there's need to
> describe connections between devices which are not handled by the normal
> child-parent relationships. So the code could well reside in some
> generic place, in my opinion.
> 
> Also, I have no problem with having it in drivers/media, but
> drivers/video should work also. We already have other, generic, video
> related things there like hdmi infoframes and display timings.

I agree. In case anybody wants to use this for audio in the future,
media already sounds more generic than video.

> And last, it's fine to move the funcs as-is in the first place, but I
> think they should be improved a bit before non-v4l2 users use them.

The get_remote_port(_parent) are fine, I think.

> There are a couple of things I tried to accomplish with the omapdss
> specific versions in
> https://www.mail-archive.com/linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg100761.html:
>
> - Iterating ports and endpoints separately. If a node has multiple
> ports, I would think that the driver needs to know which port and
> endpoint combination is the current one during iteration. It's not
> enough to just get the endpoint.

Yes, I'd already have a use-case for that in enumerating the
encoders/panels connected to a single display interface (port).

On the other hand if you just want to enumerate components from the
device tree, iterating over all endpoints of all ports is useful, too.

> - Simplify cases when there's just one port and one endpoint, in which
> case the port node can be omitted from the DT data.

Also, I'd like to drop the prev reference in get_next_endpoint, then a
for_each_endpoint macro could be made from that.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/3] of: functions to count number of elements and convert regulators
From: Mark Rutland @ 2014-02-12  9:25 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: grant.likely@linaro.org, robh+dt@kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Liam Girdwood, Mark Brown
In-Reply-To: <2573561.oCYNnnL0gm@phil>

Hi Heiko,

On Tue, Feb 11, 2014 at 11:59:25PM +0000, Heiko Stübner wrote:
> In a different thread [0] Mark Rutland suggested that drivers should not
> repeatedly open-code the counting of array elements in a property as well
> as handling the format and endianes of the DTB, as these should be limited
> to the of_ helper functions.
> 
> Therefore the first patch introduces a set of helper functions for counting
> the number of u8,...,u64 elements in a property.
> 
> The second and third patch convert the two regulator drivers that use this
> pattern to instead use both of_property_count_u32_elemens as well as
> of_property_read_u32_index.
> 
> gpio-regulator change tested on a s3c2416-based device, ti-abb-regulator
> compile-tested only.

Cheers for this. All the patches look fine to me, so for the series:

Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks,
Mark.

^ permalink raw reply

* Re: [PATCH] ARM: dts: imx6qdl-sabresd: Do not place regulator nodes under simple-bus
From: Shawn Guo @ 2014-02-12  9:22 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: mark.rutland-5wv7dgnIgG8,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Fabio Estevam
In-Reply-To: <1392165078-25794-1-git-send-email-festevam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Tue, Feb 11, 2014 at 10:31:18PM -0200, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> 
> According to Documentation/devicetree/bindings/regulator/regulator.txt 
> regulator nodes should not be placed under 'simple-bus'.

I failed to read that statement from the binding doc.  Can you quote the
doc specifically on that statement?

> 
> Mark Rutland also explains about it at:
> http://www.spinics.net/lists/linux-usb/msg101497.html 
>  
> Signed-off-by: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> ---
> Shawn,
> 
> I can convert other dts files if you are fine with this approach.

I take it as an unnecessary churn, unless I see the consensus from most
of DT maintainers and arm-soc folks that we should make this change.
And see comment below ...

> 
>  arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 51 ++++++++++++++--------------------
>  1 file changed, 21 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> index 0d816d3..d7df5b2 100644
> --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> @@ -18,38 +18,29 @@
>  		reg = <0x10000000 0x40000000>;
>  	};
>  
> -	regulators {
> -		compatible = "simple-bus";
> -		#address-cells = <1>;
> -		#size-cells = <0>;
> -
> -		reg_usb_otg_vbus: regulator@0 {
> -			compatible = "regulator-fixed";
> -			reg = <0>;
> -			regulator-name = "usb_otg_vbus";
> -			regulator-min-microvolt = <5000000>;
> -			regulator-max-microvolt = <5000000>;
> -			gpio = <&gpio3 22 0>;
> -			enable-active-high;
> -		};
> +	reg_usb_otg_vbus: regulator@0 {

nodename@num should only be used for nodes that have 'reg' property.
Why are you dropping 'reg' property here?  Right, it does not compile if
you do not drop it.  You can take it as a reason of why I endorse
simple-bus regulators container.

Shawn

> +		compatible = "regulator-fixed";
> +		regulator-name = "usb_otg_vbus";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +		gpio = <&gpio3 22 0>;
> +		enable-active-high;
> +	};
>  
> -		reg_usb_h1_vbus: regulator@1 {
> -			compatible = "regulator-fixed";
> -			reg = <1>;
> -			regulator-name = "usb_h1_vbus";
> -			regulator-min-microvolt = <5000000>;
> -			regulator-max-microvolt = <5000000>;
> -			gpio = <&gpio1 29 0>;
> -			enable-active-high;
> -		};
> +	reg_usb_h1_vbus: regulator@1 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "usb_h1_vbus";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +		gpio = <&gpio1 29 0>;
> +		enable-active-high;
> +	};
>  
> -		reg_audio: regulator@2 {
> -			compatible = "regulator-fixed";
> -			reg = <2>;
> -			regulator-name = "wm8962-supply";
> -			gpio = <&gpio4 10 0>;
> -			enable-active-high;
> -		};
> +	reg_audio: regulator@2 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "wm8962-supply";
> +		gpio = <&gpio4 10 0>;
> +		enable-active-high;
>  	};
>  
>  	gpio-keys {
> -- 
> 1.8.1.2
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Cash Awaiting Pick Up..
From: 2014 Heritage Foundation Board @ 2014-02-12  9:13 UTC (permalink / raw)




This is to re-notify you that you have $500,000.00 waiting for pick-up at Money Gram, Contact 
Mrs Hillary Florence via email : heritdept-kGM0oXzJM5p02iOg2JU2CQ@public.gmane.org for claims.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2] [media] of: move graph helpers from drivers/media/v4l2-core to drivers/media
From: Philipp Zabel @ 2014-02-12  9:11 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Russell King - ARM Linux, Grant Likely, Rob Herring,
	Sylwester Nawrocki, Laurent Pinchart, Tomi Valkeinen,
	Kyungmin Park, linux-kernel, linux-media, devicetree,
	Guennadi Liakhovetski, Philipp Zabel
In-Reply-To: <20140212065306.36a03e82.m.chehab@samsung.com>

Hi Mauro,

Am Mittwoch, den 12.02.2014, 06:53 +0900 schrieb Mauro Carvalho Chehab:
[...]
> > diff --git a/include/media/of_graph.h b/include/media/of_graph.h
> > new file mode 100644
> > index 0000000..3bbeb60
> > --- /dev/null
> > +++ b/include/media/of_graph.h
> > @@ -0,0 +1,46 @@
> > +/*
> > + * OF graph binding parsing helpers
> > + *
> > + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
> > + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > + *
> > + * Copyright (C) 2012 Renesas Electronics Corp.
> > + * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of version 2 of the GNU General Public License as
> > + * published by the Free Software Foundation.
> > + */
> > +#ifndef __LINUX_OF_GRAPH_H
> > +#define __LINUX_OF_GRAPH_H
> > +
> > +#ifdef CONFIG_OF
> 
> As a matter of consistency, it would be better to test here for
> CONFIG_OF_GRAPH instead, to reflect the same symbol that enables such
> functions as used on Kconfig/Makefile.

Maybe I'm trying to be too clever for my own good, but my reasoning was
as follows:

Suppose I newly use the of_graph_ helpers in a subsystem that does not
yet select OF_GRAPH. In that case I'd rather get linking errors earlier
rather than stubbed out functions that silently fail to parse the DT
later.

Since there is
config VIDEO_DEV
	select OF_GRAPH if OF
already and the same should be added for other users of device tree
graphs, I think stubbing out the functions only if OF is disabled should
be enough.

regards
Philipp

^ permalink raw reply

* Re: [PATCH V3] net/dt: Add support for overriding phy configuration from device tree
From: Gerlando Falauto @ 2014-02-12  8:57 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Matthew Garrett, netdev, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Kishon Vijay Abraham I
In-Reply-To: <CAGVrzca7CV1SM0PfV2o=02Zd8z-65002kq6e-fhG6gWdkCadGA@mail.gmail.com>

Hi Florian,

On 02/11/2014 06:43 PM, Florian Fainelli wrote:
> Hi Gerlando,
>
> 2014-02-11 1:09 GMT-08:00 Gerlando Falauto <gerlando.falauto@keymile.com>:
>> Hi Florian,
>>
>> first of all, thank you for your answer.
>>
>>
>> On 02/10/2014 06:09 PM, Florian Fainelli wrote:
>>>
>>> Hi Gerlando,
>>>
>>> Le lundi 10 février 2014, 17:14:59 Gerlando Falauto a écrit :
>>>>
>>>> Hi,
>>>>
>>>> I'm currently trying to fix an issue for which this patch provides a
>>>> partial solution, so apologies in advance for jumping into the
>>>> discussion for my own purposes...
>>>>
>>>> On 02/04/2014 09:39 PM, Florian Fainelli wrote:> 2014-01-17 Matthew
>>>>
>>>> Garrett <matthew.garrett@nebula.com>:
>>>>    >> Some hardware may be broken in interesting and board-specific ways,
>>>> such
>>>>    >> that various bits of functionality don't work. This patch provides a
>>>>    >> mechanism for overriding mii registers during init based on the
>>>>
>>>> contents of
>>>>
>>>>    >> the device tree data, allowing board-specific fixups without having
>>>> to
>>>>    >> pollute generic code.
>>>>    >
>>>>    > It would be good to explain exactly how your hardware is broken
>>>>    > exactly. I really do not think that such a fine-grained setting where
>>>>    > you could disable, e.g: 100BaseT_Full, but allow 100BaseT_Half to
>>>>    > remain usable makes that much sense. In general, Gigabit might be
>>>>    > badly broken, but 100 and 10Mbits/sec should work fine. How about the
>>>>    > MASTER-SLAVE bit, is overriding it really required?
>>>>    >
>>>>    > Is not a PHY fixup registered for a specific OUI the solution you are
>>>>    > looking for? I am also concerned that this creates PHY
>>>> troubleshooting
>>>>    > issues much harder to debug than before as we may have no idea about
>>>>    > how much information has been put in Device Tree to override that.
>>>>    >
>>>>    > Finally, how about making this more general just like the BCM87xx PHY
>>>>    > driver, which is supplied value/reg pairs directly? There are 16
>>>>    > common MII registers, and 16 others for vendor specific registers,
>>>>    > this is just covering for about 2% of the possible changes.
>>>>
>>>> Good point. That would easily help me with my current issue, which
>>>> requires autoneg to be disabled to begin with (by clearing BMCR_ANENABLE
>>>> from register 0).
>>>
>>>
>>> Is there a point in time (e.g: after some specific initial configuration
>>> has
>>> been made) where BMCR_ANENABLE can be used?
>>
>>
>> What do you mean? In my case, for some HW-related reason (due to the PHY
>> counterpart I guess) autoneg needs to be disabled.
>> This is currently done by the bootloader code (which clears the bit).
>> What I'm looking for is some way for the kernel to either reinforce this
>> setting, or just take that into account and skip autoneg.
>> On top of that, there's a HW errata about that particular PHY, which
>> requires certain operations to be performed on the PHY as a workaround *WHEN
>> AUTONEG IS DISABLED*. That I'd implement on a PHY-specif driver.
>
> Ok.
>
>>
>>
>>>> This would not however fix it entirely (I tried a quick hardwired
>>>> implementation), as the whole PHY machinery would not take that into
>>>> account and would re-enable autoneg anyway.
>>>> I also tried changing the patch so that phydev->support gets updated
>>>
>>>
>>> There are multiple things that you could try doing here:
>>>
>>> - override the PHY state machine in your read_status callback to make sure
>>> that you always set phydev->autoneg set to AUTONEG_ENABLE
>>
>>
>> [you mean AUTONEG_DISABLE, right?]
>
> Right, I fat fingered here.
>
>> Uhm, but I don't want to implement a driver for that PHY that always
>> disables autoneg. I only want to disable autoneg for that particular board.
>> I figure I might register a fixup for that board, but that kindof makes
>> everything more complicated and less clear. Plus, what should be the
>> criterion to determine whether we're running on that particular hardware?
>
> of_machine_is_compatible() plus reading the specific PHY OUI should
> provide you with with an unique machine + PHY tuple. If your machine
> name is too generic.

Uhm, actually, my machine name ("model") is specific, but the compatible 
string is indeed generic so this would mean adding an extra string 
there. Not that it's a big issue, but it just seems too complicated and 
hard to follow. After all, we wanted device tree in the first place to 
get rid of board-sepcific files. To me, filtering by machine name looks 
like a big step backwards, especially if it's all about a "pretty 
standard feature" like disabling autoneg.

>
>>
>>
>>> - clear the SUPPORTED_Autoneg bits from phydev->supported right after PHY
>>> registration and before the call to phy_start()
>>
>>
>> I actually tried clearing it by tweaking the patch on this thread, but the
>> end result is that it does not produce any effect (see further comments
>> below). Only thing that seems to play a role here is explictly setting
>> phydev->autoneg = AUTONEG_DISABLE.
>>
>>
>>> - set the PHY_HAS_MAGICANEG bit in your PHY driver flag
>>
>>
>> Again, this seems to play no role whatsoever here:
>>
>>                          } else if (0 == phydev->link_timeout--) {
>>                                  needs_aneg = 1;
>>                                  /* If we have the magic_aneg bit,
>>                                   * we try again */
>>                                  if (phydev->drv->flags & PHY_HAS_MAGICANEG)
>>                                          break;
>>                          }
>>                          break;
>>                  case PHY_NOLINK:
>>
>> This code might have made sense when it was written in 2006 -- back then,
>> the break statement was skipping some fallback code. But now it seems to do
>> nothing.
>>
>>
>>>
>>>>
>>>> (instead of phydev->advertising):
>>>>    >> +               if (!of_property_read_u32(np, override->prop, &tmp))
>>>> {
>>>>    >> +                       if (tmp) {
>>>>    >> +                               *val |= override->value;
>>>>    >> +                               phydev->advertising |=
>>>>
>>>> override->supported;
>>>>
>>>>    >> +                       } else {
>>>>    >> +                               phydev->advertising &=
>>>>
>>>> ~(override->supported);
>>>>
>>>>    >> +                       }
>>>>    >> +
>>>>    >> +                       *mask |= override->value;
>>>>
>>>> What I find weird is that the only way phydev->autoneg could ever be set
>>>> to disabled is from here (phy.c):
>>>>
>>>> static void phy_sanitize_settings(struct phy_device *phydev)
>>>> {
>>>>          u32 features = phydev->supported;
>>>>          int idx;
>>>>
>>>>          /* Sanitize settings based on PHY capabilities */
>>>>          if ((features & SUPPORTED_Autoneg) == 0)
>>>>                  phydev->autoneg = AUTONEG_DISABLE;
>>>>
>>>> which is in turn only called when phydev->autoneg is set to
>>>> AUTONEG_DISABLE to begin with:
>>>>
>>>> int phy_start_aneg(struct phy_device *phydev)
>>>> {
>>>>          int err;
>>>>
>>>>          mutex_lock(&phydev->lock);
>>>>
>>>>          if (AUTONEG_DISABLE == phydev->autoneg)
>>>>                  phy_sanitize_settings(phydev);
>>>>
>>>> So could someone please help me figure out what I'm missing here?
>>>
>>>
>>> At first glance it looks like the PHY driver should be reading the phydev-
>>>>
>>>> autoneg value when the PHY driver config_aneg() callback is called to be
>>>
>>> allowed to set the forced speed and settings.
>>>
>>> The way phy_sanitize_settings() is coded does not make it return a mask of
>>> features, but only the forced supported speed and duplex. Then when the
>>> link
>>> is forced but we are having some issues getting a link status, libphy
>>> tries
>>> lower speeds and this function is used again to provide the next
>>> speed/duplex
>>> pair to try.
>>>
>>
>> What I was trying to say is that phy_sanitize_settings() is only called when
>> phydev->autoneg == AUTONEG_DISABLE, and in turn it's the only generic
>> function setting phydev->autoneg = AUTONEG_DISABLE.
>> So perhaps the condition should read:
>>
>> -       if (AUTONEG_DISABLE == phydev->autoneg)
>> +       if ((features & SUPPORTED_Autoneg) == 0)
>>                  phy_sanitize_settings(phydev);
>>
>> Or else, some other parts of the generic code should take care of setting it
>> to AUTONEG_DISABLE, depending on whether the feature is supported or not.
>> What I found weird is explicitly setting a value (phydev->autoneg =
>> AUTONEG_DISABLE), from a static function which is only called when that
>> condition is already true.
>
> I do not think that this change is correct either, let me cook a patch
> for you to allow disabling autoneg from the start.

Oh, OK, that would be great, thank you!
FWIW, I've already spent quite some time trying to overcome this -- my 
understanding is that you somehow need to set phydev->autoneg to 
AUTONEG_DISABLE at a very early stage (and that could of course be done 
as a consequence of SUPPORTED_Autoneg being unset), otherwise the whole 
software phy state machine and speed-matching algorithms will get confused.

>>
>> BTW, I feel like disabling autoneg from the start has never been a use case
>> before, am I right?
>
> Not really no, and that is because most hardware does not need quirks
> to work correctly.

To be honest with you, I'm not long experienced on MII/PHY, but I've 
already seen two completely unrelated cases where autoneg needs to be 
disabled in order for the hardware to work correctly. Of course I'm only 
talking about in-board connections (e.g. not PHYs connected to an RJ-45 
jack), still...
In this particular hardware configuration, not only does autoneg need to 
be disabled in the first place (otherwise link won't work at all), but 
the phy HW is also buggy so that when autoneg is disabled, it may still 
occasionally not work (like 0.1% of the times).

Thank you so much!
Gerlando

^ permalink raw reply

* Re: [PATCH] phy-core: Don't allow building phy-core as a module
From: Roger Quadros @ 2014-02-12  8:46 UTC (permalink / raw)
  To: Hans de Goede, Kishon Vijay Abraham I
  Cc: Greg Kroah-Hartman, Maxime Ripard,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <1392134631-32030-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On 02/11/2014 06:03 PM, Hans de Goede wrote:
> include/phy/phy.h has stub code in there for when building without the
> phy-core enabled. This is useful for generic drivers such as ahci-platform,
> ehci-platoform and ohci-platform which have support for driving an optional
> phy passed to them through the devicetree.
> 
> Since on some boards this phy functionality is not needed, being able to
> disable the phy subsystem without needing a lot of #ifdef magic in the
> driver using it is quite useful.
> 
> However this breaks when the module using the phy subsystem is build-in and
> the phy-core is not, which leads to the build failing with missing symbol
> errors in the linking stage of the zImage.
> 
> Which leads to gems such as this being added to the Kconfig for achi_platform:
> 
> 	depends on GENERIC_PHY || !GENERIC_PHY
> 
> Rather then duplicating this code in a lot of places using the phy-core,
> I believe it is better to simply not allow the phy-core to be built as a
> module. The phy core is quite small and has no external dependencies, so
> always building it in when enabling it should not be an issue.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Acked-by: Roger Quadros <rogerq-l0cyMroinI0@public.gmane.org>

--
cheers,
-roger

> ---
>  drivers/phy/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 6070c99..6e336b4 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -5,7 +5,7 @@
>  menu "PHY Subsystem"
>  
>  config GENERIC_PHY
> -	tristate "PHY Core"
> +	bool "PHY Core"
>  	help
>  	  Generic PHY support.
>  
> 

^ permalink raw reply

* Re: [PATCH v2 1/2] ohci-platform: Change compatible string from usb-ohci to generic-ohci
From: Roger Quadros @ 2014-02-12  8:45 UTC (permalink / raw)
  To: Hans de Goede, Greg Kroah-Hartman
  Cc: Alan Stern, Tony Prisk, Florian Fainelli, Maxime Ripard,
	Arnd Bergmann, linux-usb, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
In-Reply-To: <1392136529-5060-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On 02/11/2014 06:35 PM, Hans de Goede wrote:
> The initial versions of the devicetree enablement patches for ohci-platform
> used "ohci-platform" as compatible string. However this was disliked by various
> reviewers because the platform bus is a Linux invention and devicetree is
> supposed to be OS agnostic. After much discussion I gave up and went with
> the generic usb-ohci as requested.
> 
> In retro-spect I should have chosen something different, the dts files for many
> existing boards already claim to be compatible with "usb-ohci", ie they have:
> 
> 	compatible = "ti,ohci-omap3", "usb-ohci";
> 
> In theory this should not be a problem since the "ti,ohci-omap3" entry takes
> presedence, but in practice using a conflicting compatible string is an issue,
> because it makes which driver gets used depend on driver registration order.
> 
> This patch changes the compatible string claimed by ohci-platform to
> "generic-ohci", avoiding the driver registration / module loading ordering
> problems.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/usb/usb-ohci.txt | 4 ++--
>  drivers/usb/host/ohci-platform.c                   | 2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
> index 6933b0c..45f67d9 100644
> --- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
> +++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
> @@ -1,7 +1,7 @@
>  USB OHCI controllers
>  
>  Required properties:
> -- compatible : "usb-ohci"
> +- compatible : "generic-ohci"
>  - reg : ohci controller register range (address and length)
>  - interrupts : ohci controller interrupt
>  
> @@ -16,7 +16,7 @@ Optional properties:
>  Example:
>  
>  	ohci0: usb@01c14400 {
> -		compatible = "allwinner,sun4i-a10-ohci", "usb-ohci";
> +		compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
>  		reg = <0x01c14400 0x100>;
>  		interrupts = <64>;
>  		clocks = <&usb_clk 6>, <&ahb_gates 2>;
> diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
> index e2c28fd..b6ca0b2 100644
> --- a/drivers/usb/host/ohci-platform.c
> +++ b/drivers/usb/host/ohci-platform.c
> @@ -319,7 +319,7 @@ static int ohci_platform_resume(struct device *dev)
>  #endif /* CONFIG_PM */
>  
>  static const struct of_device_id ohci_platform_ids[] = {
> -	{ .compatible = "usb-ohci", },
> +	{ .compatible = "generic-ohci", },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(of, ohci_platform_ids);
> 
both v2 patches

Acked-by: Roger Quadros <rogerq-l0cyMroinI0@public.gmane.org>

^ permalink raw reply

* Re: Linux-3.14-rc2: Order of serial node compatibles in DTS files.
From: Sebastian Hesselbarth @ 2014-02-12  8:30 UTC (permalink / raw)
  To: Kevin Hao, Stephen N Chivers
  Cc: Chris Proctor, Arnd Bergmann, devicetree, Scott Wood,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <20140212052816.GA15434-2Y/eJ/Q4tBKYoDLmhA0N63T7OC0tnCxdQQ4Iyu8u01E@public.gmane.org>

On 02/12/2014 06:28 AM, Kevin Hao wrote:
> On Wed, Feb 12, 2014 at 10:21:58AM +1000, Stephen N Chivers wrote:
>> But, the Interrupt Controller (MPIC)
>> goes AWOL and it is down hill from there.
>>
>> The MPIC is specified in the DTS as:
>>
>>          mpic: pic@40000 {
>>                          interrupt-controller;
>>                          #address-cells = <0>;
>>                          #interrupt-cells = <2>;
>>                          reg = <0x40000 0x40000>;
>>                          compatible = "chrp,open-pic";
>>                          device_type = "open-pic";
>>                          big-endian;
>>                  };
>>
>> The board support file has the standard mechanism for allocating
>> the PIC:
>>
>>          struct mpic *mpic;
>>
>>          mpic = mpic_alloc(NULL, 0, 0, 0, 256, " OpenPIC  ");
>>          BUG_ON(mpic == NULL);
>>
>>          mpic_init(mpic);
>>
>> I checked for damage in applying the patch and it has applied
>> correctly.
>
> How about the following fix?
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index ff85450d5683..ca91984d3c4b 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -730,32 +730,40 @@ out:
>   }
>   EXPORT_SYMBOL(of_find_node_with_property);
>
> +static int of_match_type_name(const struct device_node *node,
> +				const struct of_device_id *m)

I am fine with having a sub-function here, but it should rather be
named of_match_type_or_name.

> +{
> +	int match = 1;
> +
> +	if (m->name[0])
> +		match &= node->name && !strcmp(m->name, node->name);
> +
> +	if (m->type[0])
> +		match &= node->type && !strcmp(m->type, node->type);
> +
> +	return match;
> +}
[...]
> +	/* Check against matches without compatible string */
> +	m = matches;
> +	while (!m->compatible[0] && (m->name[0] || m->type[0])) {

We shouldn't check for anything else than the sentinel here.
Although I guess yours will not quit early as mine did but that
way we don't have to worry about it.

Sebastian

> +		match = of_match_type_name(node, m);
> +		if (match)
> +			return m;
> +		m++;
> +	}
> +
>   	return NULL;
>   }
>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Linux-3.14-rc2: Order of serial node compatibles in DTS files.
From: Sebastian Hesselbarth @ 2014-02-12  8:25 UTC (permalink / raw)
  To: Stephen N Chivers
  Cc: Arnd Bergmann, Chris Proctor, devicetree, Kumar Gala,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Scott Wood
In-Reply-To: <OF9BA019D5.46DA1E29-ONCA257C7D.000089EA-CA257C7D.00020333-SmukeSwxQOQ@public.gmane.org>

On 02/12/2014 01:21 AM, Stephen N Chivers wrote:
> Sebastian Hesselbarth <sebastian.hesselbarth-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote on
> 02/12/2014 10:46:36 AM:
>
>> From: Sebastian Hesselbarth <sebastian.hesselbarth-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> To: Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>> Cc: Kumar Gala <galak-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>, Stephen N Chivers
>> <schivers-znpAAEhiOVUQrrorzV6ljw@public.gmane.org>, Chris Proctor <cproctor-znpAAEhiOVUQrrorzV6ljw@public.gmane.org>,
>> linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
>> devicetree <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
>> Date: 02/12/2014 11:04 AM
>> Subject: Re: Linux-3.14-rc2: Order of serial node compatibles in DTS
> files.
>>
>> On 02/12/2014 12:41 AM, Scott Wood wrote:
>>>
>>> Regardless of whether .type = "serial" gets removed, it seems wrong for
>>> of_match_node() to accept a .type-only match (or .name, or anything else
>>> that doesn't involve .compatible) before it accepts a compatible match
>>> other than the first in the compatible property.
>>
>> Right, I thought about it and came to the same conclusion. I sent a
>> patch a second ago to prefer .compatible != NULL matches over those
>> with .compatible == NULL.
>>
>> Would be great if Stephen can re-test that. If it solves the issue, I
>> can send a patch tomorrow.
> Done.
>
> But, the Interrupt Controller (MPIC)
> goes AWOL and it is down hill from there.
>
> The MPIC is specified in the DTS as:
>
>          mpic: pic@40000 {
>                          interrupt-controller;
>                          #address-cells = <0>;
>                          #interrupt-cells = <2>;
>                          reg = <0x40000 0x40000>;
>                          compatible = "chrp,open-pic";
>                          device_type = "open-pic";
>                          big-endian;
>                  };
>
> The board support file has the standard mechanism for allocating
> the PIC:
>
>          struct mpic *mpic;
>
>          mpic = mpic_alloc(NULL, 0, 0, 0, 256, " OpenPIC  ");
>          BUG_ON(mpic == NULL);
>
>          mpic_init(mpic);
>
> I checked for damage in applying the patch and it has applied
> correctly.

Hmm, I did a mistake in the patch:

-	while (m->name[0] || m->type[0]) {
+	while (m->compatible[0] || m->name[0] || m->type[0]) {

for the second added match. Otherwise, the matches are not
evaluated down to the sentinel but the loop quits on the first
match table entry without .name and .type set.

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 07/11] watchdog: xilinx: Use of_property_read_u32
From: Michal Simek @ 2014-02-12  8:13 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Michal Simek, linux-kernel, Wim Van Sebroeck, Grant Likely,
	Rob Herring, linux-watchdog, linux-arm-kernel, devicetree
In-Reply-To: <20140211202038.GC11798@roeck-us.net>

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

On 02/11/2014 09:20 PM, Guenter Roeck wrote:
> On Tue, Feb 11, 2014 at 07:55:50AM +0100, Michal Simek wrote:
>> Use of_property_read_u32 functions to clean probe function.
>>
>> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
>> ---
>>
> [ ... ]
> 
>> +
>> +	if (enable_once)
>>  		watchdog_set_nowayout(xilinx_wdt_wdd, true);
>> -	}
> 
> 	watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
> 
> would probably do as well (the function checks the flag as well).
> 
> Nitpick, so
> 
> Reviewed-by: Guenter Roeck <linux@roeck-us.net>

I will change it and send v3.

Thanks,
Michal



-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

^ permalink raw reply

* Re: [RFC/PATCH 1/1] mtd: nand: Add a devicetree binding for ECC strength and ECC step size
From: Brian Norris @ 2014-02-12  8:00 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, David Woodhouse,
	Pekon Gupta, Thomas Petazzoni, Gregory Clement, Seif Mazareeb,
	Lior Amsalem
In-Reply-To: <1389960820-18696-2-git-send-email-ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Hi Ezequiel,

On Fri, Jan 17, 2014 at 09:13:40AM -0300, Ezequiel Garcia wrote:
> Some flashes can only be properly accessed when the ECC mode is
> specified, and a way to describe such mode is required.
> 
> Such ECC mode is completely driver-specific so instead of having one binding
> per compatible-string, let's add generic ECC strength and ECC step size.
> Driver's can choose the appropriate ECC mode, based on this specification.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/mtd/nand.txt | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt
> index 03855c8..683a310 100644
> --- a/Documentation/devicetree/bindings/mtd/nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/nand.txt
> @@ -3,5 +3,9 @@
>  - nand-ecc-mode : String, operation mode of the NAND ecc mode.
>    Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
>    "soft_bch".
> +- nand-ecc-strength : integer ECC required strength.
> +- nand-ecc-size : integer step size associated to the ECC strength.

Probably should be nand-ecc-step-size, to be clearer.

> +  The exact meaning of the ECC strength and ECC size parameters is completely
> +  driver-specific.

I think we can be much more specific than this. We need to at least
describe how the strength and size are related, and we need to mention
how this represents the ECC scheme to use, rather than the minimum
requirement of the flash.

I'd say something like this. Feel free to improve it, but it covers the
gist of what I think we can say in a generic document:

 - nand-ecc-strength: integer representing the number of bits to correct
   per ECC step
 - nand-ecc-step-size: integer representing the number of data bytes
   that are covered by a single ECC step

   Together, the ECC strength and step size define the correction
   capability, so that we say we will correct "X bit errors per Y
   bytes". The interpretation of these parameters is
   implementation-defined, but they often have ramifications on the
   formation, interpretation, and placement of correction metadata on
   the flash. Not all implementations must support all possible
   combinations. Implementations are encouraged to further define the
   value(s) they support.

>  - nand-bus-width : 8 or 16 bus width if not present 8
>  - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false

Brian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 2/2] ARM: imx: add speed grading check for i.mx6 soc
From: Anson Huang @ 2014-02-12  7:56 UTC (permalink / raw)
  To: shawn.guo-QSEj5FYQhm4dnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1392191777-15703-1-git-send-email-b20788-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

The fuse map of speed_grading[1:0] defines the max speed
of ARM, see below the definition:

2b'11: 1200000000Hz;
2b'10: 996000000Hz;
2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
2b'00: 792000000Hz;

Need to remove all illegal setpoints according to fuse
map.

Signed-off-by: Anson Huang <b20788-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 arch/arm/mach-imx/mach-imx6q.c |   22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index f9cbbf9..ad9da1f 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -219,8 +219,10 @@ static void __init imx6q_init_machine(void)
 #define OCOTP_CFG3			0x440
 #define OCOTP_CFG3_SPEED_SHIFT		16
 #define OCOTP_CFG3_SPEED_1P2GHZ		0x3
+#define OCOTP_CFG3_SPEED_996MHZ		0x2
+#define OCOTP_CFG3_SPEED_852MHZ		0x1
 
-static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
+static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
 {
 	struct device_node *np;
 	void __iomem *base;
@@ -238,11 +240,27 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
 		goto put_node;
 	}
 
+	/*
+	 * SPEED_GRADING[1:0] defines the max speed of ARM:
+	 * 2b'11: 1200000000Hz;
+	 * 2b'10: 996000000Hz;
+	 * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+	 * 2b'00: 792000000Hz;
+	 * We need to set the max speed of ARM according to fuse map.
+	 */
 	val = readl_relaxed(base + OCOTP_CFG3);
 	val >>= OCOTP_CFG3_SPEED_SHIFT;
 	if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
 		if (dev_pm_opp_disable(cpu_dev, 1200000000))
 			pr_warn("failed to disable 1.2 GHz OPP\n");
+	if ((val & 0x3) < OCOTP_CFG3_SPEED_996MHZ)
+		if (dev_pm_opp_disable(cpu_dev, 996000000))
+			pr_warn("failed to disable 996 MHz OPP\n");
+	if (cpu_is_imx6q()) {
+		if ((val & 0x3) != OCOTP_CFG3_SPEED_852MHZ)
+			if (dev_pm_opp_disable(cpu_dev, 852000000))
+				pr_warn("failed to disable 852 MHz OPP\n");
+	}
 
 put_node:
 	of_node_put(np);
@@ -268,7 +286,7 @@ static void __init imx6q_opp_init(void)
 		goto put_node;
 	}
 
-	imx6q_opp_check_1p2ghz(cpu_dev);
+	imx6q_opp_check_speed_grading(cpu_dev);
 
 put_node:
 	of_node_put(np);
-- 
1.7.9.5


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/2] ARM: dts: imx6q: add 852MHz setpoint for CPU freq
From: Anson Huang @ 2014-02-12  7:56 UTC (permalink / raw)
  To: shawn.guo-QSEj5FYQhm4dnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

According to datasheet, i.MX6Q has setpoint of 852MHz
which is exclusive with 996MHz, the fuse map of speed_grading
defines the max speed of ARM, here we add this 852MHz
setpoint opp info, kernel will check the speed_grading
fuse and remove all illegal setpoints.

Signed-off-by: Anson Huang <b20788-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 arch/arm/boot/dts/imx6q.dtsi |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 422d169..fadf498 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -30,6 +30,7 @@
 				/* kHz    uV */
 				1200000 1275000
 				996000  1250000
+				852000  1250000
 				792000  1150000
 				396000  975000
 			>;
@@ -37,6 +38,7 @@
 				/* ARM kHz  SOC-PU uV */
 				1200000 1275000
 				996000	1250000
+				852000	1250000
 				792000	1175000
 				396000	1175000
 			>;
-- 
1.7.9.5


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH RESEND] leds-gpio: fix a typo in the documentation
From: Laszlo Papp @ 2014-02-12  7:54 UTC (permalink / raw)
  To: rob
  Cc: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
	devicetree, linux-doc, linux-kernel, Laszlo Papp

Signed-off-by: Laszlo Papp <lpapp@kde.org>
---
 Documentation/devicetree/bindings/leds/leds-gpio.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt
index df1b308..00e94fe 100644
--- a/Documentation/devicetree/bindings/leds/leds-gpio.txt
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt
@@ -16,7 +16,7 @@ LED sub-node properties:
   see Documentation/devicetree/bindings/leds/common.txt
 - default-state:  (optional) The initial state of the LED.  Valid
   values are "on", "off", and "keep".  If the LED is already on or off
-  and the default-state property is set the to same value, then no
+  and the default-state property is set to the same value, then no
   glitch should be produced where the LED momentarily turns off (or
   on).  The "keep" setting will keep the LED at whatever its current
   state is, without producing a glitch.  The default is off if this
-- 
1.8.5.4


^ permalink raw reply related

* Re: [RFC/PATCH 0/1] mtd: Add NAND ECC devicetree binding
From: Brian Norris @ 2014-02-12  7:44 UTC (permalink / raw)
  To: Gupta, Pekon
  Cc: Ezequiel Garcia, David Woodhouse, Thomas Petazzoni, Lior Amsalem,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Seif Mazareeb,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Gregory Clement
In-Reply-To: <20980858CB6D3A4BAE95CA194937D5E73EA67E79-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>

On Mon, Jan 20, 2014 at 06:21:35AM +0000, Pekon Gupta wrote:
> >From: Ezequiel Garcia 
> >I'm not implying we should deprecate the recently added "ti-nand-ecc-opt",
> >but just want to know it's eventually possible.
> >
> Yes, this is good approach for long-term, and it can replace "ti-nand-ecc-opt"
> "ti-nand-ecc-opt" is not new DT binding, it just got some new values added
> However, you have to convince DT Maintainers to get this in, and then deprecate
> other vendor specific bindings. It would be difficult to maintain backward
> compatibility to these bindings, if we move to 'nand-ecc-strength'.

I don't see why it would be difficult to support both the more generic
nand-ecc-strength and the OMAP-specific ti-nand-ecc-opt in the same
driver. OMAP NAND would just have to define a helper that translates
properties like "bch8" into a strength and sector size (8 and 512,
respectively). From then on, you can treat them identically.

> At some-point we need to get some concrete guidelines from DT Maintainers on
> how long we should support deprecated bindings in our code, And what is the
> age of DT binding. I think David Woodhouse should throw more light, as he had
> some discussions & ideas on about DT binding life, during a linux conference.

Barring some new direction from the DT folks, I believe DT is an eternal
ABI. We can and should maintain compatibility forever. And in this case,
I don't think it's that hard.

Brian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC PATCH 0/4] i.MX6 PU power domain support
From: Shawn Guo @ 2014-02-12  7:26 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Rob Herring, Mark Rutland, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392125231-28387-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Tue, Feb 11, 2014 at 02:27:07PM +0100, Philipp Zabel wrote:
> The i.MX6Q can gate off the CPU and PU (GPU/VPU) power domains using the
> Power Gating Controller (PGC) in the GPC register space. The CPU power
> domain is already handled by wait state code, but the PU power domain can
> be controlled using the generic power domain framework and power off the PU
> supply regulator if all devices in the power domain are (runtime) suspended.
> 
> This patchset adds a GPC platform device initialized at subsys_initcall time
> (after anatop regulators) that binds to the gpc device tree node and sets up
> the PU power domain:
> 
> 	gpc: gpc@020dc000 {
> 		#address-cells = <1>;
> 		#size-cells = <1>;
> 		compatible = "fsl,imx6q-gpc";
> 		reg = <0x020dc000 0x4000>;
> 		interrupts = <0 89 0x04 0 90 0x04>;
> 		pu-supply = <&reg_pu>;
> 
> 		pd_pu: power-domain@020dc260 {
> 			compatible = "fsl,power-domain";
> 			reg = <0x020dc260 0x10>;
> 		};
> 	};
> 
> It registers a platform bus notifier so that it can add GPU and VPU devices
> to the power domain when they are bound. If finds devices to be added to the
> power domain by scanning the device tree for nodes that contain a
> 	power-domain = <&pd_pu>;
> property.

I replied the individual patches with some small comments, but overall I
like it much.  Thanks for the work!

Shawn

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC PATCH 4/4] ARM: dts: imx6qdl: Add PU power-domain information to gpc node
From: Shawn Guo @ 2014-02-12  7:25 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Rob Herring, Mark Rutland, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392125231-28387-5-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Tue, Feb 11, 2014 at 02:27:11PM +0100, Philipp Zabel wrote:
> The PGC that is part of GPC controls isolation and power sequencing of the
> PU power domain. The power domain will be handled by the generic pm domain
> framework and needs a phandle to the PU regulator to turn off power when
> the domain is disabled.
> 
> Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
>  arch/arm/boot/dts/imx6qdl.dtsi | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> index 253d82c..595750d 100644
> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> @@ -598,9 +598,17 @@
>  			};
>  
>  			gpc: gpc@020dc000 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
>  				compatible = "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
>  				interrupts = <0 89 0x04 0 90 0x04>;
> +				pu-supply = <&reg_pu>;
> +
> +				pd_pu: power-domain@020dc260 {
> +					compatible = "fsl,power-domain";
> +					reg = <0x020dc260 0x10>;
> +				};

It's time to have a binding doc for gpc/pgc?  And I'm not sure
"fsl,power-domain" is a good compatible as it's so generic.

Shawn

>  			};
>  
>  			gpr: iomuxc-gpr@020e0000 {
> -- 
> 1.8.5.3
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC PATCH 1/4] ARM: imx6: gpc: Add PU power domain for GPU/VPU
From: Shawn Guo @ 2014-02-12  7:17 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Rob Herring, Mark Rutland, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1392125231-28387-2-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Tue, Feb 11, 2014 at 02:27:08PM +0100, Philipp Zabel wrote:
> When generic pm domain support is enabled, the PGC can be used
> to completely gate power to the PU power domain containing GPU3D,
> GPU2D, and VPU cores.
> This code triggers the PGC powerdown sequence to disable the GPU/VPU
> isolation cells and gate power and then disables the PU regulator.
> To reenable, the reverse powerup sequence is triggered after the PU
> regulaotor is enabled again.
> 
> Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
>  arch/arm/mach-imx/Kconfig |   2 +
>  arch/arm/mach-imx/gpc.c   | 169 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 171 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 33567aa..3c58f2e 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -808,6 +808,7 @@ config SOC_IMX6Q
>  	select PL310_ERRATA_727915 if CACHE_PL310
>  	select PL310_ERRATA_769419 if CACHE_PL310
>  	select PM_OPP if PM
> +	select PM_GENERIC_DOMAINS if PM
>  
>  	help
>  	  This enables support for Freescale i.MX6 Quad processor.
> @@ -827,6 +828,7 @@ config SOC_IMX6SL
>  	select PL310_ERRATA_588369 if CACHE_PL310
>  	select PL310_ERRATA_727915 if CACHE_PL310
>  	select PL310_ERRATA_769419 if CACHE_PL310
> +	select PM_GENERIC_DOMAINS if PM
>  
>  	help
>  	  This enables support for Freescale i.MX6 SoloLite processor.
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 586e017..c3ec2c5 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -10,19 +10,32 @@
>   * http://www.gnu.org/copyleft/gpl.html
>   */
>  
> +#include <linux/clk.h>
> +#include <linux/delay.h>
>  #include <linux/io.h>
>  #include <linux/irq.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
>  #include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/irqchip/arm-gic.h>
>  #include "common.h"
> +#include "hardware.h"
>  
> +#define GPC_CNTR		0x000
>  #define GPC_IMR1		0x008
> +#define GPC_PGC_GPU_PDN		0x260
> +#define GPC_PGC_GPU_PUPSCR	0x264
> +#define GPC_PGC_GPU_PDNSCR	0x268
>  #define GPC_PGC_CPU_PDN		0x2a0
>  
>  #define IMR_NUM			4
>  
> +#define GPU_VPU_PUP_REQ		BIT(1)
> +#define GPU_VPU_PDN_REQ		BIT(0)
> +
>  static void __iomem *gpc_base;
>  static u32 gpc_wake_irqs[IMR_NUM];
>  static u32 gpc_saved_imrs[IMR_NUM];
> @@ -138,3 +151,159 @@ void __init imx_gpc_init(void)
>  	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
>  	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
>  }
> +
> +static struct regulator *pu_reg;
> +
> +static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
> +{
> +	u32 val;
> +	int iso, iso2sw;
> +
> +	/* GPU3D, GPU2D, and VPU clocks should be disabled here */

The comment should be dropped?

> +
> +	/* Read ISO and ISO2SW power down delays */
> +	val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
> +	iso = val & 0x3f;
> +	iso2sw = (val >> 8) & 0x3f;
> +
> +	/* Gate off PU domain when GPU/VPU when powered down */
> +	writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
> +
> +	/* Request GPC to power down GPU/VPU */
> +	val = readl_relaxed(gpc_base + GPC_CNTR);
> +	val |= GPU_VPU_PDN_REQ;
> +	writel_relaxed(val, gpc_base + GPC_CNTR);
> +
> +	/* Wait ISO + ISO2SW IPG clock cycles */
> +	ndelay((iso + iso2sw) * 1000 / 66);
> +
> +	regulator_disable(pu_reg);
> +
> +	return 0;
> +}
> +
> +static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
> +{
> +	int ret;
> +	u32 val;
> +	int sw, sw2iso;
> +
> +	ret = regulator_enable(pu_reg);
> +	if (ret) {
> +		pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
> +		return ret;
> +	}
> +
> +	/* Gate off PU domain when GPU/VPU when powered down */
> +	writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
> +
> +	/* Read ISO and ISO2SW power down delays */
> +	val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
> +	sw = val & 0x3f;
> +	sw2iso = (val >> 8) & 0x3f;
> +
> +	/* Request GPC to power up GPU/VPU */
> +	val = readl_relaxed(gpc_base + GPC_CNTR);
> +	val |= GPU_VPU_PUP_REQ;
> +	writel_relaxed(val, gpc_base + GPC_CNTR);
> +
> +	/* Wait ISO + ISO2SW IPG clock cycles */
> +	ndelay((sw + sw2iso) * 1000 / 66);
> +
> +	return 0;
> +}
> +
> +static struct generic_pm_domain imx6q_pu_domain = {
> +	.name = "PU",
> +	.power_off = imx6q_pm_pu_power_off,
> +	.power_on = imx6q_pm_pu_power_on,
> +};
> +
> +static int imx6q_pm_notifier_call(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct generic_pm_domain *genpd;
> +	struct device *dev = data;
> +	struct device_node *np;
> +	int ret;
> +
> +	switch (event) {
> +	case BUS_NOTIFY_BIND_DRIVER:
> +		np = of_parse_phandle(dev->of_node, "power-domain", 0);
> +		if (!np)
> +			return NOTIFY_DONE;
> +
> +		ret = pm_genpd_of_add_device(np, dev);
> +		if (ret)
> +			dev_err(dev, "failed to add to power domain: %d\n",
> +				ret);
> +		break;
> +	case BUS_NOTIFY_UNBOUND_DRIVER:
> +		genpd = dev_to_genpd(dev);
> +		if (IS_ERR(genpd))
> +			return NOTIFY_DONE;
> +		ret = pm_genpd_remove_device(genpd, dev);
> +		if (ret)
> +			dev_err(dev, "failed to remove from power domain: %d\n",
> +				ret);
> +		break;
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block imx6q_platform_nb = {
> +	.notifier_call = imx6q_pm_notifier_call,
> +};
> +
> +static int imx_gpc_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np;
> +	int ret;
> +
> +	np = of_get_child_by_name(pdev->dev.of_node, "power-domain");
> +	if (!np) {
> +		dev_err(&pdev->dev, "missing power-domain node\n");
> +		return -EINVAL;
> +	}
> +
> +	pu_reg = devm_regulator_get(&pdev->dev, "pu");
> +	if (IS_ERR(pu_reg)) {
> +		ret = PTR_ERR(pu_reg);
> +		dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* The regulator is initially enabled */
> +	ret = regulator_enable(pu_reg);

That means the PU power domain will be always on when neither GPU nor
VPU is enabled?

Shawn

> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to enable pu regulator: %d\n", ret);
> +		return ret;
> +	}
> +
> +	imx6q_pu_domain.of_node = np;
> +	pm_genpd_init(&imx6q_pu_domain, NULL, false);
> +	bus_register_notifier(&platform_bus_type, &imx6q_platform_nb);
> +
> +	return 0;
> +}
> +
> +static struct of_device_id imx_gpc_dt_ids[] = {
> +	{ .compatible = "fsl,imx6q-gpc" },
> +	{ }
> +};
> +
> +static struct platform_driver imx_gpc_driver = {
> +	.driver = {
> +		.name = "imx-gpc",
> +		.owner = THIS_MODULE,
> +		.of_match_table = imx_gpc_dt_ids,
> +	},
> +	.probe = imx_gpc_probe,
> +};
> +
> +static int __init imx_pgc_init(void)
> +{
> +	return platform_driver_register(&imx_gpc_driver);
> +}
> +subsys_initcall(imx_pgc_init);
> -- 
> 1.8.5.3
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2] [media] of: move graph helpers from drivers/media/v4l2-core to drivers/media
From: Tomi Valkeinen @ 2014-02-12  7:15 UTC (permalink / raw)
  To: Philipp Zabel, Russell King - ARM Linux, Mauro Carvalho Chehab
  Cc: Grant Likely, Rob Herring, Sylwester Nawrocki, Laurent Pinchart,
	Kyungmin Park, linux-kernel, linux-media, devicetree,
	Guennadi Liakhovetski, Philipp Zabel
In-Reply-To: <1392154905-12007-1-git-send-email-p.zabel@pengutronix.de>

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

Hi,

On 11/02/14 23:41, Philipp Zabel wrote:
> From: Philipp Zabel <philipp.zabel@gmail.com>
> 
> This patch moves the parsing helpers used to parse connected graphs
> in the device tree, like the video interface bindings documented in
> Documentation/devicetree/bindings/media/video-interfaces.txt, from
> drivers/media/v4l2-core to drivers/media.
> 
> This allows to reuse the same parser code from outside the V4L2
> framework, most importantly from display drivers.
> The functions v4l2_of_get_next_endpoint, v4l2_of_get_remote_port,
> and v4l2_of_get_remote_port_parent are moved. They are renamed to
> of_graph_get_next_endpoint, of_graph_get_remote_port, and
> of_graph_get_remote_port_parent, respectively.
> Since there are not that many current users, switch all of them
> to the new functions right away.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Acked-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
> Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

I don't think the graphs or the parsing code has anything video
specific. It could well be used for anything, whenever there's need to
describe connections between devices which are not handled by the normal
child-parent relationships. So the code could well reside in some
generic place, in my opinion.

Also, I have no problem with having it in drivers/media, but
drivers/video should work also. We already have other, generic, video
related things there like hdmi infoframes and display timings.

And last, it's fine to move the funcs as-is in the first place, but I
think they should be improved a bit before non-v4l2 users use them.
There are a couple of things I tried to accomplish with the omapdss
specific versions in
https://www.mail-archive.com/linux-omap@vger.kernel.org/msg100761.html:

- Iterating ports and endpoints separately. If a node has multiple
ports, I would think that the driver needs to know which port and
endpoint combination is the current one during iteration. It's not
enough to just get the endpoint.

- Simplify cases when there's just one port and one endpoint, in which
case the port node can be omitted from the DT data.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply

* [PATCH v2] can: xilinx CAN controller support.
From: Kedareswara rao Appana @ 2014-02-12  7:10 UTC (permalink / raw)
  To: wg, mkl, michal.simek, grant.likely, robh+dt, linux-can
  Cc: netdev, linux-arm-kernel, linux-kernel, devicetree,
	Kedareswara rao Appana
In-Reply-To: <\>

This patch adds xilinx CAN controller support.
This driver supports both ZYNQ CANPS IP and
Soft IP AXI CAN controller.

Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
---
This patch is rebased on the 3.14 rc2 kernel.
Changes for v2:
- Updated with the review comments.
- Removed unnecessary debug prints.
- included tx,rx fifo depths in ZYNQ CANPS case also.
---
 .../devicetree/bindings/net/can/xilinx_can.txt     |   45 +
 drivers/net/can/Kconfig                            |    7 +
 drivers/net/can/Makefile                           |    1 +
 drivers/net/can/xilinx_can.c                       | 1153 ++++++++++++++++++++
 4 files changed, 1206 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/can/xilinx_can.txt
 create mode 100644 drivers/net/can/xilinx_can.c

diff --git a/Documentation/devicetree/bindings/net/can/xilinx_can.txt b/Documentation/devicetree/bindings/net/can/xilinx_can.txt
new file mode 100644
index 0000000..0e57103
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/xilinx_can.txt
@@ -0,0 +1,45 @@
+Xilinx Axi CAN/Zynq CANPS controller Device Tree Bindings
+---------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,zynq-can-1.00.a" for Zynq CAN
+			  controllers and "xlnx,axi-can-1.00.a" for Axi CAN
+			  controllers.
+- reg			: Physical base address and size of the Axi CAN/Zynq
+			  CANPS registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller
+- clock-names		: List of input clock names - "ref_clk", "aper_clk"
+			  (See clock bindings for details. Two clocks are
+			   required for Zynq CAN. For Axi CAN
+			   case it is one(ref_clk)).
+- clocks		: Clock phandles (see clock bindings for details).
+- tx-fifo-depth		: Can Tx fifo depth.
+- rx-fifo-depth		: Can Rx fifo depth.
+
+
+Example:
+
+For Zynq CANPS Dts file:
+	zynq_can_0: zynq-can@e0008000 {
+			compatible = "xlnx,zynq-can-1.00.a";
+			clocks = <&clkc 19>, <&clkc 36>;
+			clock-names = "ref_clk", "aper_clk";
+			reg = <0xe0008000 0x1000>;
+			interrupts = <0 28 4>;
+			interrupt-parent = <&intc>;
+			tx-fifo-depth = <0x40>;
+			rx-fifo-depth = <0x40>;
+		};
+For Axi CAN Dts file:
+	axi_can_0: axi-can@40000000 {
+			compatible = "xlnx,axi-can-1.00.a";
+			clocks = <&clkc 0>;
+			clock-names = "ref_clk" ;
+			reg = <0x40000000 0x10000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 59 1>;
+			tx-fifo-depth = <0x40>;
+			rx-fifo-depth = <0x40>;
+		};
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 9e7d95d..b180239 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -125,6 +125,13 @@ config CAN_GRCAN
 	  endian syntheses of the cores would need some modifications on
 	  the hardware level to work.
 
+config CAN_XILINXCAN
+	tristate "Xilinx CAN"
+	depends on ARCH_ZYNQ || MICROBLAZE
+	---help---
+	  Xilinx CAN driver. This driver supports both soft AXI CAN IP and
+	  Zynq CANPS IP.
+
 source "drivers/net/can/mscan/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index c744039..0b8e11e 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -25,5 +25,6 @@ obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
 obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o
 obj-$(CONFIG_PCH_CAN)		+= pch_can.o
 obj-$(CONFIG_CAN_GRCAN)		+= grcan.o
+obj-$(CONFIG_CAN_XILINXCAN)	+= xilinx_can.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
new file mode 100644
index 0000000..642e6b4
--- /dev/null
+++ b/drivers/net/can/xilinx_can.c
@@ -0,0 +1,1153 @@
+/* Xilinx CAN device driver
+ *
+ * Copyright (C) 2012 - 2014 Xilinx, Inc.
+ * Copyright (C) 2009 PetaLogix. All rights reserved.
+ *
+ * Description:
+ * This driver is developed for Axi CAN IP and for Zynq CANPS Controller.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/led.h>
+
+#define DRIVER_NAME	"XILINX_CAN"
+
+/* CAN registers set */
+#define XCAN_SRR_OFFSET			0x00 /* Software reset */
+#define XCAN_MSR_OFFSET			0x04 /* Mode select */
+#define XCAN_BRPR_OFFSET		0x08 /* Baud rate prescaler */
+#define XCAN_BTR_OFFSET			0x0C /* Bit timing */
+#define XCAN_ECR_OFFSET			0x10 /* Error counter */
+#define XCAN_ESR_OFFSET			0x14 /* Error status */
+#define XCAN_SR_OFFSET			0x18 /* Status */
+#define XCAN_ISR_OFFSET			0x1C /* Interrupt status */
+#define XCAN_IER_OFFSET			0x20 /* Interrupt enable */
+#define XCAN_ICR_OFFSET			0x24 /* Interrupt clear */
+#define XCAN_TXFIFO_ID_OFFSET		0x30 /* TX FIFO ID */
+#define XCAN_TXFIFO_DLC_OFFSET		0x34 /* TX FIFO DLC */
+#define XCAN_TXFIFO_DW1_OFFSET		0x38 /* TX FIFO Data Word 1 */
+#define XCAN_TXFIFO_DW2_OFFSET		0x3C /* TX FIFO Data Word 2 */
+#define XCAN_RXFIFO_ID_OFFSET		0x50 /* RX FIFO ID */
+#define XCAN_RXFIFO_DLC_OFFSET		0x54 /* RX FIFO DLC */
+#define XCAN_RXFIFO_DW1_OFFSET		0x58 /* RX FIFO Data Word 1 */
+#define XCAN_RXFIFO_DW2_OFFSET		0x5C /* RX FIFO Data Word 2 */
+
+/* CAN register bit masks - XCAN_<REG>_<BIT>_MASK */
+#define XCAN_SRR_CEN_MASK		0x00000002 /* CAN enable */
+#define XCAN_SRR_RESET_MASK		0x00000001 /* Soft Reset the CAN core */
+#define XCAN_MSR_LBACK_MASK		0x00000002 /* Loop back mode select */
+#define XCAN_MSR_SLEEP_MASK		0x00000001 /* Sleep mode select */
+#define XCAN_BRPR_BRP_MASK		0x000000FF /* Baud rate prescaler */
+#define XCAN_BTR_SJW_MASK		0x00000180 /* Synchronous jump width */
+#define XCAN_BTR_TS2_MASK		0x00000070 /* Time segment 2 */
+#define XCAN_BTR_TS1_MASK		0x0000000F /* Time segment 1 */
+#define XCAN_ECR_REC_MASK		0x0000FF00 /* Receive error counter */
+#define XCAN_ECR_TEC_MASK		0x000000FF /* Transmit error counter */
+#define XCAN_ESR_ACKER_MASK		0x00000010 /* ACK error */
+#define XCAN_ESR_BERR_MASK		0x00000008 /* Bit error */
+#define XCAN_ESR_STER_MASK		0x00000004 /* Stuff error */
+#define XCAN_ESR_FMER_MASK		0x00000002 /* Form error */
+#define XCAN_ESR_CRCER_MASK		0x00000001 /* CRC error */
+#define XCAN_SR_TXFLL_MASK		0x00000400 /* TX FIFO is full */
+#define XCAN_SR_ESTAT_MASK		0x00000180 /* Error status */
+#define XCAN_SR_ERRWRN_MASK		0x00000040 /* Error warning */
+#define XCAN_SR_NORMAL_MASK		0x00000008 /* Normal mode */
+#define XCAN_SR_LBACK_MASK		0x00000002 /* Loop back mode */
+#define XCAN_SR_CONFIG_MASK		0x00000001 /* Configuration mode */
+#define XCAN_IXR_TXFEMP_MASK		0x00004000 /* TX FIFO Empty */
+#define XCAN_IXR_WKUP_MASK		0x00000800 /* Wake up interrupt */
+#define XCAN_IXR_SLP_MASK		0x00000400 /* Sleep interrupt */
+#define XCAN_IXR_BSOFF_MASK		0x00000200 /* Bus off interrupt */
+#define XCAN_IXR_ERROR_MASK		0x00000100 /* Error interrupt */
+#define XCAN_IXR_RXNEMP_MASK		0x00000080 /* RX FIFO NotEmpty intr */
+#define XCAN_IXR_RXOFLW_MASK		0x00000040 /* RX FIFO Overflow intr */
+#define XCAN_IXR_RXOK_MASK		0x00000010 /* Message received intr */
+#define XCAN_IXR_TXOK_MASK		0x00000002 /* TX successful intr */
+#define XCAN_IXR_ARBLST_MASK		0x00000001 /* Arbitration lost intr */
+#define XCAN_IDR_ID1_MASK		0xFFE00000 /* Standard msg identifier */
+#define XCAN_IDR_SRR_MASK		0x00100000 /* Substitute remote TXreq */
+#define XCAN_IDR_IDE_MASK		0x00080000 /* Identifier extension */
+#define XCAN_IDR_ID2_MASK		0x0007FFFE /* Extended message ident */
+#define XCAN_IDR_RTR_MASK		0x00000001 /* Remote TX request */
+#define XCAN_DLCR_DLC_MASK		0xF0000000 /* Data length code */
+
+#define XCAN_INTR_ALL		(XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\
+				 XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \
+				 XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \
+				 XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK)
+
+/* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */
+#define XCAN_BTR_SJW_SHIFT		7  /* Synchronous jump width */
+#define XCAN_BTR_TS2_SHIFT		4  /* Time segment 2 */
+#define XCAN_IDR_ID1_SHIFT		21 /* Standard Messg Identifier */
+#define XCAN_IDR_ID2_SHIFT		1  /* Extended Message Identifier */
+#define XCAN_DLCR_DLC_SHIFT		28 /* Data length code */
+#define XCAN_ESR_REC_SHIFT		8  /* Rx Error Count */
+
+/* CAN frame length constants */
+#define XCAN_ECHO_SKB_MAX		64
+#define XCAN_FRAME_MAX_DATA_LEN		8
+#define XCAN_TIMEOUT			(50 * HZ)
+
+/**
+ * struct xcan_priv - This definition define CAN driver instance
+ * @can:			CAN private data structure.
+ * @open_time:			For holding timeout values
+ * @waiting_ech_skb_index:	Pointer for skb
+ * @ech_skb_next:		This tell the next packet in the queue
+ * @waiting_ech_skb_num:	Gives the number of packets waiting
+ * @xcan_echo_skb_max_tx:	Maximum number packets the driver can send
+ * @xcan_echo_skb_max_rx:	Maximum number packets the driver can receive
+ * @napi:			NAPI structure
+ * @ech_skb_lock:		For spinlock purpose
+ * @read_reg:			For reading data from CAN registers
+ * @write_reg:			For writing data to CAN registers
+ * @dev:			Network device data structure
+ * @reg_base:			Ioremapped address to registers
+ * @irq_flags:			For request_irq()
+ * @aperclk:			Pointer to struct clk
+ * @devclk:			Pointer to struct clk
+ */
+struct xcan_priv {
+	struct can_priv can;
+	int open_time;
+	int waiting_ech_skb_index;
+	int ech_skb_next;
+	int waiting_ech_skb_num;
+	int xcan_echo_skb_max_tx;
+	int xcan_echo_skb_max_rx;
+	struct napi_struct napi;
+	spinlock_t ech_skb_lock;
+	u32 (*read_reg)(const struct xcan_priv *priv, int reg);
+	void (*write_reg)(const struct xcan_priv *priv, int reg, u32 val);
+	struct net_device *dev;
+	void __iomem *reg_base;
+	unsigned long irq_flags;
+	struct clk *aperclk;
+	struct clk *devclk;
+};
+
+/* CAN Bittiming constants as per Xilinx CAN specs */
+static const struct can_bittiming_const xcan_bittiming_const = {
+	.name = DRIVER_NAME,
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 256,
+	.brp_inc = 1,
+};
+
+/**
+ * xcan_write_reg - Write a value to the device register
+ * @priv:	Driver private data structure
+ * @reg:	Register offset
+ * @val:	Value to write at the Register offset
+ *
+ * Write data to the paricular CAN register
+ */
+static void xcan_write_reg(const struct xcan_priv *priv, int reg, u32 val)
+{
+	writel(val, priv->reg_base + reg);
+}
+
+/**
+ * xcan_read_reg - Read a value from the device register
+ * @priv:	Driver private data structure
+ * @reg:	Register offset
+ *
+ * Read data from the particular CAN register
+ * Return: value read from the CAN register
+ */
+static u32 xcan_read_reg(const struct xcan_priv *priv, int reg)
+{
+	return readl(priv->reg_base + reg);
+}
+
+/**
+ * set_reset_mode - Resets the CAN device mode
+ * @ndev:	Pointer to net_device structure
+ *
+ * This is the driver reset mode routine.The driver
+ * enters into configuration mode.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int set_reset_mode(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	unsigned long timeout;
+
+	priv->can.state = CAN_STATE_STOPPED;
+
+	timeout = jiffies + XCAN_TIMEOUT;
+	while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & XCAN_SR_CONFIG_MASK)) {
+		if (time_after(jiffies, timeout)) {
+			netdev_warn(ndev, "timedout waiting for config mode\n");
+			return -ETIMEDOUT;
+		}
+		usleep_range(500, 10000);
+	}
+
+	return 0;
+}
+
+/**
+ * xcan_set_bittiming - CAN set bit timing routine
+ * @ndev:	Pointer to net_device structure
+ *
+ * This is the driver set bittiming  routine.
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_set_bittiming(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	u32 btr0, btr1;
+	u32 is_config_mode;
+
+	/* Check whether Xilinx CAN is in configuration mode.
+	 * It cannot set bit timing if Xilinx CAN is not in configuration mode.
+	 */
+	is_config_mode = priv->read_reg(priv, XCAN_SR_OFFSET) &
+				XCAN_SR_CONFIG_MASK;
+	if (!is_config_mode) {
+		netdev_alert(ndev,
+			"Cannot set bittiming can is not in config mode\n");
+		return -EPERM;
+	}
+
+	/* Setting Baud Rate prescalar value in BRPR Register */
+	btr0 = (bt->brp - 1) & XCAN_BRPR_BRP_MASK;
+
+	/* Setting Time Segment 1 in BTR Register */
+	btr1 = (bt->prop_seg + bt->phase_seg1 - 1) & XCAN_BTR_TS1_MASK;
+
+	/* Setting Time Segment 2 in BTR Register */
+	btr1 |= ((bt->phase_seg2 - 1) << XCAN_BTR_TS2_SHIFT) &
+		XCAN_BTR_TS2_MASK;
+
+	/* Setting Synchronous jump width in BTR Register */
+	btr1 |= ((bt->sjw - 1) << XCAN_BTR_SJW_SHIFT) & XCAN_BTR_SJW_MASK;
+
+	priv->write_reg(priv, XCAN_BRPR_OFFSET, btr0);
+	priv->write_reg(priv, XCAN_BTR_OFFSET, btr1);
+
+	netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n",
+			priv->read_reg(priv, XCAN_BRPR_OFFSET),
+			priv->read_reg(priv, XCAN_BTR_OFFSET));
+
+	return 0;
+}
+
+/**
+ * xcan_start - This the drivers start routine
+ * @ndev:	Pointer to net_device structure
+ *
+ * This is the drivers start routine.
+ * Based on the State of the CAN device it puts
+ * the CAN device into a proper mode.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_start(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	u32 err;
+	unsigned long timeout;
+
+	/* Check if it is in reset mode */
+	if (priv->can.state != CAN_STATE_STOPPED)
+		err = set_reset_mode(ndev);
+		if (err < 0)
+			return err;
+
+	/* Enable interrupts */
+	priv->write_reg(priv, XCAN_IER_OFFSET, XCAN_INTR_ALL);
+
+	/* Check whether it is loopback mode or normal mode  */
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+		/* Put device into loopback mode */
+		priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_LBACK_MASK);
+	else
+		/* The device is in normal mode */
+		priv->write_reg(priv, XCAN_MSR_OFFSET, 0);
+
+	if (priv->can.state == CAN_STATE_STOPPED) {
+		/* Enable Xilinx CAN */
+		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK);
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		timeout = jiffies + XCAN_TIMEOUT;
+		if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+			while ((priv->read_reg(priv, XCAN_SR_OFFSET)
+					& XCAN_SR_LBACK_MASK) == 0) {
+				if (time_after(jiffies, timeout)) {
+					netdev_warn(ndev,
+						"timedout for loopback mode\n");
+					return -ETIMEDOUT;
+				}
+				usleep_range(500, 10000);
+			}
+		} else {
+			while ((priv->read_reg(priv, XCAN_SR_OFFSET)
+					& XCAN_SR_NORMAL_MASK) == 0) {
+				if (time_after(jiffies, timeout)) {
+					netdev_warn(ndev,
+						"timedout for normal mode\n");
+					return -ETIMEDOUT;
+				}
+				usleep_range(500, 10000);
+			}
+		}
+		netdev_dbg(ndev, "status:#x%08x\n",
+				priv->read_reg(priv, XCAN_SR_OFFSET));
+	}
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	return 0;
+}
+
+/**
+ * xcan_do_set_mode - This sets the mode of the driver
+ * @ndev:	Pointer to net_device structure
+ * @mode:	Tells the mode of the driver
+ *
+ * This check the drivers state and calls the
+ * the corresponding modes to set.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_do_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		ret = xcan_start(ndev);
+		if (ret < 0)
+			netdev_err(ndev, "xcan_start failed!\n");
+		netif_wake_queue(ndev);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * xcan_start_xmit - Starts the transmission
+ * @skb:	sk_buff pointer that contains data to be Txed
+ * @ndev:	Pointer to net_device structure
+ *
+ * This function is invoked from upper layers to initiate transmission. This
+ * function uses the next available free txbuff and populates their fields to
+ * start the transmission.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	u32 id, dlc, data[2] = {0, 0}, rtr = 0;
+	unsigned long flags;
+
+	if (can_dropped_invalid_skb(ndev, skb))
+		return NETDEV_TX_OK;
+
+	/* Watch carefully on the bit sequence */
+	if (cf->can_id & CAN_EFF_FLAG) {
+		/* Extended CAN ID format */
+		id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) &
+			XCAN_IDR_ID2_MASK;
+		id |= (((cf->can_id & CAN_EFF_MASK) >>
+			(CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) <<
+			XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK;
+
+		/* The substibute remote TX request bit should be "1"
+		 * for extended frames as in the Xilinx CAN datasheet
+		 */
+		id |= XCAN_IDR_IDE_MASK | XCAN_IDR_SRR_MASK;
+
+		if (cf->can_id & CAN_RTR_FLAG) {
+			/* Extended frames remote TX request */
+			id |= XCAN_IDR_RTR_MASK;
+			rtr = 1;
+		}
+	} else {
+		/* Standard CAN ID format */
+		id = ((cf->can_id & CAN_SFF_MASK) << XCAN_IDR_ID1_SHIFT) &
+			XCAN_IDR_ID1_MASK;
+
+		if (cf->can_id & CAN_RTR_FLAG) {
+			/* Extended frames remote TX request */
+			id |= XCAN_IDR_SRR_MASK;
+			rtr = 1;
+		}
+	}
+
+	dlc = (cf->can_dlc & 0xf) << XCAN_DLCR_DLC_SHIFT;
+
+	if (dlc > 0)
+		data[0] = be32_to_cpup((__be32 *)(cf->data + 0));
+	if (dlc > 4)
+		data[1] = be32_to_cpup((__be32 *)(cf->data + 4));
+
+	can_put_echo_skb(skb, ndev, priv->ech_skb_next);
+
+	/* Write the Frame to Xilinx CAN TX FIFO */
+	priv->write_reg(priv, XCAN_TXFIFO_ID_OFFSET, id);
+	priv->write_reg(priv, XCAN_TXFIFO_DLC_OFFSET, dlc);
+	if (!rtr) {
+		priv->write_reg(priv, XCAN_TXFIFO_DW1_OFFSET, data[0]);
+		priv->write_reg(priv, XCAN_TXFIFO_DW2_OFFSET, data[1]);
+		stats->tx_bytes += cf->can_dlc;
+	}
+
+	priv->ech_skb_next = (priv->ech_skb_next + 1) %
+					priv->xcan_echo_skb_max_tx;
+
+	spin_lock_irqsave(&priv->ech_skb_lock, flags);
+	priv->waiting_ech_skb_num++;
+	spin_unlock_irqrestore(&priv->ech_skb_lock, flags);
+
+	/* Check if the TX buffer is full */
+	if (priv->read_reg(priv, XCAN_SR_OFFSET) & XCAN_SR_TXFLL_MASK) {
+		netif_stop_queue(ndev);
+		netdev_err(ndev, "TX register is still full!\n");
+		return NETDEV_TX_BUSY;
+	} else if (priv->waiting_ech_skb_num == priv->xcan_echo_skb_max_tx) {
+		netif_stop_queue(ndev);
+		netdev_err(ndev, "waiting:0x%08x, max:0x%08x\n",
+			priv->waiting_ech_skb_num, priv->xcan_echo_skb_max_tx);
+		return NETDEV_TX_BUSY;
+	}
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * xcan_rx -  Is called from CAN isr to complete the received
+ *		frame  processing
+ * @ndev:	Pointer to net_device structure
+ *
+ * This function is invoked from the CAN isr(poll) to process the Rx frames. It
+ * does minimal processing and invokes "netif_receive_skb" to complete further
+ * processing.
+ * Return: 0 on success and negative error value on error
+ */
+static int xcan_rx(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u32 id_xcan, dlc, data[2] = {0, 0}, rtr = 0;
+
+	skb = alloc_can_skb(ndev, &cf);
+	if (!skb)
+		return -ENOMEM;
+
+	/* Read a frame from Xilinx zynq CANPS */
+	id_xcan = priv->read_reg(priv, XCAN_RXFIFO_ID_OFFSET);
+	dlc = priv->read_reg(priv, XCAN_RXFIFO_DLC_OFFSET) & XCAN_DLCR_DLC_MASK;
+
+	/* Change Xilinx CAN data length format to socketCAN data format */
+	cf->can_dlc = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >>
+				XCAN_DLCR_DLC_SHIFT);
+
+	/* Change Xilinx CAN ID format to socketCAN ID format */
+	if (id_xcan & XCAN_IDR_IDE_MASK) {
+		/* The received frame is an Extended format frame */
+		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3;
+		cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >>
+				XCAN_IDR_ID2_SHIFT;
+		cf->can_id |= CAN_EFF_FLAG;
+		if (id_xcan & XCAN_IDR_RTR_MASK) {
+			cf->can_id |= CAN_RTR_FLAG;
+			rtr = 1;
+		}
+	} else {
+		/* The received frame is a standard format frame */
+		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >>
+				XCAN_IDR_ID1_SHIFT;
+		if (id_xcan & XCAN_IDR_RTR_MASK) {
+			cf->can_id |= CAN_RTR_FLAG;
+			rtr = 1;
+		}
+	}
+
+	if (!rtr) {
+		data[0] = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET);
+		data[1] = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET);
+
+		/* Change Xilinx CAN data format to socketCAN data format */
+		*(__be32 *)(cf->data) = cpu_to_be32(data[0]);
+		if (cf->can_dlc > 4)
+			*(__be32 *)(cf->data + 4) = cpu_to_be32(data[1]);
+	}
+	can_led_event(ndev, CAN_LED_EVENT_RX);
+
+	netif_receive_skb(skb);
+
+	stats->rx_bytes += cf->can_dlc;
+	stats->rx_packets++;
+	return 0;
+}
+
+/**
+ * xcan_err_interrupt - error frame Isr
+ * @ndev:	net_device pointer
+ * @isr:	interrupt status register value
+ *
+ * This is the CAN error interrupt and it will
+ * check the the type of error and forward the error
+ * frame to upper layers.
+ */
+static void xcan_err_interrupt(struct net_device *ndev, u32 isr)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u32 err_status, status;
+
+	skb = alloc_can_err_skb(ndev, &cf);
+	if (!skb) {
+		netdev_err(ndev, "alloc_can_err_skb() failed!\n");
+		return;
+	}
+
+	err_status = priv->read_reg(priv, XCAN_ESR_OFFSET);
+	priv->write_reg(priv, XCAN_ESR_OFFSET, err_status);
+	status = priv->read_reg(priv, XCAN_SR_OFFSET);
+
+	if (isr & XCAN_IXR_BSOFF_MASK) {
+		priv->can.state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		priv->can.can_stats.bus_off++;
+		/* Leave device in Config Mode in bus-off state */
+		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
+		can_bus_off(ndev);
+	} else if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) {
+		cf->can_id |= CAN_ERR_CRTL;
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		priv->can.can_stats.error_passive++;
+		cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE |
+					CAN_ERR_CRTL_TX_PASSIVE;
+	} else if (status & XCAN_SR_ERRWRN_MASK) {
+		cf->can_id |= CAN_ERR_CRTL;
+		priv->can.state = CAN_STATE_ERROR_WARNING;
+		priv->can.can_stats.error_warning++;
+		cf->data[1] |= CAN_ERR_CRTL_RX_WARNING |
+					CAN_ERR_CRTL_TX_WARNING;
+	}
+
+	/* Check for Arbitration lost interrupt */
+	if (isr & XCAN_IXR_ARBLST_MASK) {
+		cf->can_id |= CAN_ERR_LOSTARB;
+		cf->data[0] = CAN_ERR_LOSTARB_UNSPEC;
+		priv->can.can_stats.arbitration_lost++;
+	}
+
+	/* Check for RX FIFO Overflow interrupt */
+	if (isr & XCAN_IXR_RXOFLW_MASK) {
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
+	}
+
+	/* Check for error interrupt */
+	if (isr & XCAN_IXR_ERROR_MASK) {
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+
+		/* Check for Ack error interrupt */
+		if (err_status & XCAN_ESR_ACKER_MASK) {
+			cf->can_id |= CAN_ERR_ACK;
+			cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
+			stats->tx_errors++;
+		}
+
+		/* Check for Bit error interrupt */
+		if (err_status & XCAN_ESR_BERR_MASK) {
+			cf->can_id |= CAN_ERR_PROT;
+			cf->data[2] = CAN_ERR_PROT_BIT;
+			stats->tx_errors++;
+		}
+
+		/* Check for Stuff error interrupt */
+		if (err_status & XCAN_ESR_STER_MASK) {
+			cf->can_id |= CAN_ERR_PROT;
+			cf->data[2] = CAN_ERR_PROT_STUFF;
+			stats->rx_errors++;
+		}
+
+		/* Check for Form error interrupt */
+		if (err_status & XCAN_ESR_FMER_MASK) {
+			cf->can_id |= CAN_ERR_PROT;
+			cf->data[2] = CAN_ERR_PROT_FORM;
+			stats->rx_errors++;
+		}
+
+		/* Check for CRC error interrupt */
+		if (err_status & XCAN_ESR_CRCER_MASK) {
+			cf->can_id |= CAN_ERR_PROT;
+			cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ |
+					CAN_ERR_PROT_LOC_CRC_DEL;
+			stats->rx_errors++;
+		}
+			priv->can.can_stats.bus_error++;
+	}
+
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	netdev_dbg(ndev, "%s: error status register:0x%x\n",
+			__func__, priv->read_reg(priv, XCAN_ESR_OFFSET));
+}
+
+/**
+ * xcan_state_interrupt - It will check the state of the CAN device
+ * @ndev:	net_device pointer
+ * @isr:	interrupt status register value
+ *
+ * This will checks the state of the CAN device
+ * and puts the device into appropriate state.
+ */
+static void xcan_state_interrupt(struct net_device *ndev, u32 isr)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	/* Check for Sleep interrupt if set put CAN device in sleep state */
+	if (isr & XCAN_IXR_SLP_MASK)
+		priv->can.state = CAN_STATE_SLEEPING;
+
+	/* Check for Wake up interrupt if set put CAN device in Active state */
+	if (isr & XCAN_IXR_WKUP_MASK)
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+}
+
+/**
+ * xcan_rx_poll - Poll routine for rx packets (NAPI)
+ * @napi:	napi structure pointer
+ * @quota:	Max number of rx packets to be processed.
+ *
+ * This is the poll routine for rx part.
+ * It will process the packets maximux quota value.
+ *
+ * Return: number of packets received
+ */
+static int xcan_rx_poll(struct napi_struct *napi, int quota)
+{
+	struct net_device *ndev = napi->dev;
+	struct xcan_priv *priv = netdev_priv(ndev);
+	u32 isr, ier;
+	int work_done = 0;
+
+	isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+	while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) {
+		if (isr & XCAN_IXR_RXOK_MASK) {
+			priv->write_reg(priv, XCAN_ICR_OFFSET,
+				XCAN_IXR_RXOK_MASK);
+			if (xcan_rx(ndev) < 0)
+				return work_done;
+			work_done++;
+		} else {
+			priv->write_reg(priv, XCAN_ICR_OFFSET,
+				XCAN_IXR_RXNEMP_MASK);
+			break;
+		}
+		priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK);
+		isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+	}
+
+	if (work_done < quota) {
+		napi_complete(napi);
+		ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+		ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK);
+		priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+	}
+	return work_done;
+}
+
+/**
+ * xcan_tx_interrupt - Tx Done Isr
+ * @ndev:	net_device pointer
+ */
+static void xcan_tx_interrupt(struct net_device *ndev)
+{
+	unsigned long flags;
+	struct xcan_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	u32 processed = 0, txpackets;
+
+	stats->tx_packets++;
+	netdev_dbg(ndev, "%s: waiting total:%d,current:%d\n", __func__,
+			priv->waiting_ech_skb_num, priv->waiting_ech_skb_index);
+
+	txpackets = priv->waiting_ech_skb_num;
+
+	if (txpackets) {
+		can_get_echo_skb(ndev, priv->waiting_ech_skb_index);
+		priv->waiting_ech_skb_index =
+			(priv->waiting_ech_skb_index + 1) %
+			priv->xcan_echo_skb_max_tx;
+		processed++;
+		txpackets--;
+	}
+
+	spin_lock_irqsave(&priv->ech_skb_lock, flags);
+	priv->waiting_ech_skb_num -= processed;
+	spin_unlock_irqrestore(&priv->ech_skb_lock, flags);
+
+	netdev_dbg(ndev, "%s: waiting total:%d,current:%d\n", __func__,
+			priv->waiting_ech_skb_num, priv->waiting_ech_skb_index);
+
+	netif_wake_queue(ndev);
+
+	can_led_event(ndev, CAN_LED_EVENT_TX);
+}
+
+/**
+ * xcan_interrupt - CAN Isr
+ * @irq:	irq number
+ * @dev_id:	device id poniter
+ *
+ * This is the xilinx CAN Isr. It checks for the type of interrupt
+ * and invokes the corresponding ISR.
+ *
+ * Return:
+ * IRQ_NONE - If CAN device is in sleep mode, IRQ_HANDLED otherwise
+ */
+static irqreturn_t xcan_interrupt(int irq, void *dev_id)
+{
+	struct net_device *ndev = (struct net_device *)dev_id;
+	struct xcan_priv *priv = netdev_priv(ndev);
+	u32 isr, ier;
+
+	/* Get the interrupt status from Xilinx CAN */
+	isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+	if (!isr)
+		return IRQ_NONE;
+
+	netdev_dbg(ndev, "%s: isr:#x%08x, err:#x%08x\n", __func__,
+			isr, priv->read_reg(priv, XCAN_ESR_OFFSET));
+
+	/* Check for the type of interrupt and Processing it */
+	if (isr & (XCAN_IXR_SLP_MASK | XCAN_IXR_WKUP_MASK)) {
+		priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_SLP_MASK |
+				XCAN_IXR_WKUP_MASK));
+		xcan_state_interrupt(ndev, isr);
+	}
+
+	/* Check for Tx interrupt and Processing it */
+	if (isr & XCAN_IXR_TXOK_MASK) {
+		priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
+		xcan_tx_interrupt(ndev);
+	}
+
+	/* Check for the type of error interrupt and Processing it */
+	if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
+			XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) {
+		priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK |
+				XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK |
+				XCAN_IXR_ARBLST_MASK));
+		xcan_err_interrupt(ndev, isr);
+	}
+
+	/* Check for the type of receive interrupt and Processing it */
+	if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) {
+		ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+		ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK);
+		priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+		napi_schedule(&priv->napi);
+	}
+	return IRQ_HANDLED;
+}
+
+/**
+ * xcan_stop - Driver stop routine
+ * @ndev:	Pointer to net_device structure
+ *
+ * This is the drivers stop routine. It will disable the
+ * interrupts and put the device into configuration mode.
+ */
+static void xcan_stop(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	u32 ier;
+
+	/* Disable interrupts and leave the can in configuration mode */
+	ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+	ier &= ~XCAN_INTR_ALL;
+	priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
+	priv->can.state = CAN_STATE_STOPPED;
+}
+
+/**
+ * xcan_open - Driver open routine
+ * @ndev:	Pointer to net_device structure
+ *
+ * This is the driver open routine.
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_open(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags,
+			ndev->name, (void *)ndev);
+	if (ret < 0) {
+		netdev_err(ndev, "Irq allocation for CAN failed\n");
+		return ret;
+	}
+
+	/* Set chip into reset mode */
+	ret = set_reset_mode(ndev);
+	if (ret < 0)
+		netdev_err(ndev, "mode resetting failed failed!\n");
+
+	/* Common open */
+	ret = open_candev(ndev);
+	if (ret)
+		return ret;
+
+	ret = xcan_start(ndev);
+	if (ret < 0)
+		netdev_err(ndev, "xcan_start failed!\n");
+
+
+	can_led_event(ndev, CAN_LED_EVENT_OPEN);
+	napi_enable(&priv->napi);
+	netif_start_queue(ndev);
+
+	return 0;
+}
+
+/**
+ * xcan_close - Driver close routine
+ * @ndev:	Pointer to net_device structure
+ *
+ * Return: 0 always
+ */
+static int xcan_close(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	netif_stop_queue(ndev);
+	napi_disable(&priv->napi);
+	xcan_stop(ndev);
+	free_irq(ndev->irq, ndev);
+	close_candev(ndev);
+
+	can_led_event(ndev, CAN_LED_EVENT_STOP);
+
+	return 0;
+}
+
+/**
+ * xcan_get_berr_counter - error counter routine
+ * @ndev:	Pointer to net_device structure
+ * @bec:	Pointer to can_berr_counter structure
+ *
+ * This is the driver error counter routine.
+ * Return: 0 always
+ */
+static int xcan_get_berr_counter(const struct net_device *ndev,
+					struct can_berr_counter *bec)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK;
+	bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) &
+			XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT);
+	return 0;
+}
+
+static const struct net_device_ops xcan_netdev_ops = {
+	.ndo_open	= xcan_open,
+	.ndo_stop	= xcan_close,
+	.ndo_start_xmit	= xcan_start_xmit,
+};
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * xcan_suspend - Suspend method for the driver
+ * @_dev:	Address of the platform_device structure
+ *
+ * Put the driver into low power mode.
+ * Return: 0 always
+ */
+static int xcan_suspend(struct device *_dev)
+{
+	struct platform_device *pdev = container_of(_dev,
+			struct platform_device, dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	if (netif_running(ndev)) {
+		netif_stop_queue(ndev);
+		netif_device_detach(ndev);
+	}
+
+	priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK);
+	priv->can.state = CAN_STATE_SLEEPING;
+
+	clk_disable(priv->aperclk);
+	clk_disable(priv->devclk);
+
+	return 0;
+}
+
+/**
+ * xcan_resume - Resume from suspend
+ * @dev:	Address of the platformdevice structure
+ *
+ * Resume operation after suspend.
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_resume(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev,
+			struct platform_device, dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct xcan_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	ret = clk_enable(priv->aperclk);
+	if (ret) {
+		dev_err(dev, "Cannot enable clock.\n");
+		return ret;
+	}
+	ret = clk_enable(priv->devclk);
+	if (ret) {
+		dev_err(dev, "Cannot enable clock.\n");
+		return ret;
+	}
+
+	priv->write_reg(priv, XCAN_MSR_OFFSET, 0);
+	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK);
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	if (netif_running(ndev)) {
+		netif_device_attach(ndev);
+		netif_start_queue(ndev);
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume);
+
+/**
+ * xcan_probe - Platform registration call
+ * @pdev:	Handle to the platform device structure
+ *
+ * This function does all the memory allocation and registration for the CAN
+ * device.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xcan_probe(struct platform_device *pdev)
+{
+	struct resource *res; /* IO mem resources */
+	struct net_device *ndev;
+	struct xcan_priv *priv;
+	int ret, fifodep;
+
+	/* Create a CAN device instance */
+	ndev = alloc_candev(sizeof(struct xcan_priv), XCAN_ECHO_SKB_MAX);
+	if (!ndev)
+		return -ENOMEM;
+
+	priv = netdev_priv(ndev);
+	priv->dev = ndev;
+	priv->can.bittiming_const = &xcan_bittiming_const;
+	priv->can.do_set_bittiming = xcan_set_bittiming;
+	priv->can.do_set_mode = xcan_do_set_mode;
+	priv->can.do_get_berr_counter = xcan_get_berr_counter;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
+					CAN_CTRLMODE_BERR_REPORTING;
+
+	/* Get IRQ for the device */
+	ndev->irq = platform_get_irq(pdev, 0);
+
+	spin_lock_init(&priv->ech_skb_lock);
+	ndev->flags |= IFF_ECHO;	/* We support local echo */
+
+	platform_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ndev->netdev_ops = &xcan_netdev_ops;
+
+	/* Get the virtual base address for the device */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->reg_base)) {
+		ret = PTR_ERR(priv->reg_base);
+		goto err_free;
+	}
+	ndev->mem_start = res->start;
+	ndev->mem_end = res->end;
+
+	priv->write_reg = xcan_write_reg;
+	priv->read_reg = xcan_read_reg;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth",
+				&fifodep);
+	if (ret < 0)
+		goto err_free;
+	priv->xcan_echo_skb_max_tx = fifodep;
+
+	ret = of_property_read_u32(pdev->dev.of_node, "rx-fifo-depth",
+				&fifodep);
+	if (ret < 0)
+		goto err_free;
+	priv->xcan_echo_skb_max_rx = fifodep;
+
+	/* Getting the CAN devclk info */
+	priv->devclk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(priv->devclk)) {
+		dev_err(&pdev->dev, "Device clock not found.\n");
+		ret = PTR_ERR(priv->devclk);
+		goto err_free;
+	}
+
+	/* Check for type of CAN device */
+	if (of_device_is_compatible(pdev->dev.of_node,
+				    "xlnx,zynq-can-1.00.a")) {
+		priv->aperclk = devm_clk_get(&pdev->dev, "aper_clk");
+		if (IS_ERR(priv->aperclk)) {
+			dev_err(&pdev->dev, "aper clock not found\n");
+			ret = PTR_ERR(priv->aperclk);
+			goto err_free;
+		}
+	} else {
+		priv->aperclk = priv->devclk;
+	}
+
+	ret = clk_prepare_enable(priv->devclk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable device clock\n");
+		goto err_free;
+	}
+
+	ret = clk_prepare_enable(priv->aperclk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable aper clock\n");
+		goto err_unprepar_disabledev;
+	}
+
+	priv->can.clock.freq = clk_get_rate(priv->devclk);
+
+	netif_napi_add(ndev, &priv->napi, xcan_rx_poll,
+				priv->xcan_echo_skb_max_rx);
+	ret = register_candev(ndev);
+	if (ret) {
+		dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret);
+		goto err_unprepar_disableaper;
+	}
+
+	devm_can_led_init(ndev);
+	dev_info(&pdev->dev,
+			"reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n",
+			priv->reg_base, ndev->irq, priv->can.clock.freq,
+			priv->xcan_echo_skb_max_tx);
+
+	return 0;
+
+err_unprepar_disableaper:
+	clk_disable_unprepare(priv->aperclk);
+err_unprepar_disabledev:
+	clk_disable_unprepare(priv->devclk);
+err_free:
+	free_candev(ndev);
+
+	return ret;
+}
+
+/**
+ * xcan_remove - Unregister the device after releasing the resources
+ * @pdev:	Handle to the platform device structure
+ *
+ * This function frees all the resources allocated to the device.
+ * Return: 0 always
+ */
+static int xcan_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	if (set_reset_mode(ndev) < 0)
+		netdev_err(ndev, "mode resetting failed!\n");
+
+	unregister_candev(ndev);
+	netif_napi_del(&priv->napi);
+	clk_disable_unprepare(priv->aperclk);
+	clk_disable_unprepare(priv->devclk);
+
+	free_candev(ndev);
+
+	return 0;
+}
+
+/* Match table for OF platform binding */
+static struct of_device_id xcan_of_match[] = {
+	{ .compatible = "xlnx,zynq-can-1.00.a", },
+	{ .compatible = "xlnx,axi-can-1.00.a", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, xcan_of_match);
+
+static struct platform_driver xcan_driver = {
+	.probe = xcan_probe,
+	.remove	= xcan_remove,
+	.driver	= {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+		.pm = &xcan_dev_pm_ops,
+		.of_match_table	= xcan_of_match,
+	},
+};
+
+module_platform_driver(xcan_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Xilinx Inc");
+MODULE_DESCRIPTION("Xilinx CAN interface");
-- 
1.7.4

^ permalink raw reply related

* Re: Linux-3.14-rc2: Order of serial node compatibles in DTS files.
From: Kevin Hao @ 2014-02-12  5:28 UTC (permalink / raw)
  To: Stephen N Chivers
  Cc: Sebastian Hesselbarth, Chris Proctor, Arnd Bergmann, devicetree,
	Scott Wood, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <OF9BA019D5.46DA1E29-ONCA257C7D.000089EA-CA257C7D.00020333-SmukeSwxQOQ@public.gmane.org>

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

On Wed, Feb 12, 2014 at 10:21:58AM +1000, Stephen N Chivers wrote:
> But, the Interrupt Controller (MPIC)
> goes AWOL and it is down hill from there.
> 
> The MPIC is specified in the DTS as:
> 
>         mpic: pic@40000 {
>                         interrupt-controller;
>                         #address-cells = <0>;
>                         #interrupt-cells = <2>;
>                         reg = <0x40000 0x40000>;
>                         compatible = "chrp,open-pic";
>                         device_type = "open-pic";
>                         big-endian;
>                 };
> 
> The board support file has the standard mechanism for allocating
> the PIC:
> 
>         struct mpic *mpic;
> 
>         mpic = mpic_alloc(NULL, 0, 0, 0, 256, " OpenPIC  ");
>         BUG_ON(mpic == NULL);
> 
>         mpic_init(mpic);
> 
> I checked for damage in applying the patch and it has applied
> correctly.

How about the following fix?

diff --git a/drivers/of/base.c b/drivers/of/base.c
index ff85450d5683..ca91984d3c4b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -730,32 +730,40 @@ out:
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
+static int of_match_type_name(const struct device_node *node,
+				const struct of_device_id *m)
+{
+	int match = 1;
+
+	if (m->name[0])
+		match &= node->name && !strcmp(m->name, node->name);
+
+	if (m->type[0])
+		match &= node->type && !strcmp(m->type, node->type);
+
+	return match;
+}
+
 static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
 					   const struct device_node *node)
 {
 	const char *cp;
 	int cplen, l;
+	const struct of_device_id *m;
+	int match;
 
 	if (!matches)
 		return NULL;
 
 	cp = __of_get_property(node, "compatible", &cplen);
 	do {
-		const struct of_device_id *m = matches;
+		m = matches;
 
 		/* Check against matches with current compatible string */
-		while (m->name[0] || m->type[0] || m->compatible[0]) {
-			int match = 1;
-			if (m->name[0])
-				match &= node->name
-					&& !strcmp(m->name, node->name);
-			if (m->type[0])
-				match &= node->type
-					&& !strcmp(m->type, node->type);
-			if (m->compatible[0])
-				match &= cp
-					&& !of_compat_cmp(m->compatible, cp,
+		while (m->compatible[0]) {
+			match = of_match_type_name(node, m);
+			match &= cp && !of_compat_cmp(m->compatible, cp,
 							strlen(m->compatible));
 			if (match)
 				return m;
@@ -770,6 +778,15 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
 		}
 	} while (cp && (cplen > 0));
 
+	/* Check against matches without compatible string */
+	m = matches;
+	while (!m->compatible[0] && (m->name[0] || m->type[0])) {
+		match = of_match_type_name(node, m);
+		if (match)
+			return m;
+		m++;
+	}
+
 	return NULL;
 }


Thanks,
Kevin
> 
> Stephen Chivers,
> CSC Australia Pty. Ltd.
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

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

^ permalink raw reply related

* Re: [PATCH 1/2] BCM2835: Add dmaengine driver to device tree
From: Stephen Warren @ 2014-02-12  5:05 UTC (permalink / raw)
  To: Florian Meier
  Cc: linux-rpi-kernel, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree
In-Reply-To: <52D3C9EF.1030901@koalo.de>

On 01/13/2014 04:11 AM, Florian Meier wrote:
> This adds the definitions for the BCM2835 dmaengine driver
> to the device tree. The dma-channel-mask is currently
> fixed. Later it should be set via the firmware.

I've applied patch 1, and the part of patch 2 which touches bcm2835.dtsi
to bcm2835's for-3.15/dt branch, with minor fixes.

^ permalink raw reply


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