Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 09/11] ARM: KVM: introduce per-vcpu HYP Configuration Register
From: Catalin Marinas @ 2014-02-06 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391630151-7875-10-git-send-email-marc.zyngier@arm.com>

On Wed, Feb 05, 2014 at 07:55:49PM +0000, Marc Zyngier wrote:
> So far, KVM/ARM used a fixed HCR configuration per guest, except for
> the VI/VF/VA bits to control the interrupt in absence of VGIC.
> 
> With the upcoming need to dynamically reconfigure trapping, it becomes
> necessary to allow the HCR to be changed on a per-vcpu basis.
> 
> The fix here is to mimic what KVM/arm64 already does: a per vcpu HCR
> field, initialized at setup time.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH 02/03] pinctrl: sh-pfc: r8a7790: Break out USB0 OVC/VBUS
From: Laurent Pinchart @ 2014-02-06 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANqRtoSubhvfgzn590k9oePLv04V00Z7aEuKw2Ofxi8FeCObbA@mail.gmail.com>

Hi Magnus,

On Friday 31 January 2014 12:10:05 Magnus Damm wrote:
> On Fri, Jan 31, 2014 at 10:17 AM, Laurent Pinchart wrote:
> > On Thursday 30 January 2014 08:10:19 Magnus Damm wrote:
> >> From: Magnus Damm <damm@opensource.se>
> >> 
> >> Create a new group for the USB0 OVC/VBUS pin by itself. This
> >> allows us to monitor PWEN as GPIO on the Lager board.
> >> 
> >> Signed-off-by: Magnus Damm <damm@opensource.se>
> >> ---
> >> 
> >>  drivers/pinctrl/sh-pfc/pfc-r8a7790.c |    9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >> 
> >> --- 0001/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> >> +++ work/drivers/pinctrl/sh-pfc/pfc-r8a7790.c 2014-01-24
> > 10:23:32.000000000
> >> +0900 @@ -3231,6 +3231,13 @@ static const unsigned int usb0_pins[] =
> >>  static const unsigned int usb0_mux[] = {
> >>       USB0_PWEN_MARK, USB0_OVC_VBUS_MARK,
> >>  };
> >> +static const unsigned int usb0_ovc_vbus_pins[] = {
> >> +     /* OVC/VBUS */
> >> +     RCAR_GP_PIN(5, 19),
> >> +};
> >> +static const unsigned int usb0_ovc_vbus_mux[] = {
> >> +     USB0_OVC_VBUS_MARK,
> >> +};
> > 
> > Another option would have been to split the existing usb0 group in
> > usb0_pwen and usb0_ovc. I'm not sure which is better though, I'd just
> > like to know if you had given it a thought.
> 
> I actually did just that in my first local attempt, but I decided not
> to since it will only cause potential breakage.

OK. I assume that using PWEN without OVC/VBUS doesn't make sense, right ?

> > Regardless, what about naming the new group usb0_ovc instead of
> > usb0_ovc_bus to keep names short ?
> 
> Is there any particular reason why you want shorter names?

When it doesn't reduce clarity I prefer to keep names short, as that makes the 
code easier to read and write, and (slightly) lowers the memory footprint.

> From my side, I prefer to keep the names in sync with the data sheet. In
> this particular case it is a shared pin so OVC is used for Host while VBUS
> is used for gadget, so if you're proposing to ditch VBUS then this feels
> somewhat inconsistent with the current gadget use case. =)

I thought the pin was used for over current detection only, but that doesn't 
make sense for function mode, you're right. Let's keep the name as-is then.

Provided PWEN without OVC/VBUS doesn't make sense and won't be needed,

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Will Deacon @ 2014-02-06 11:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140206105442.GB4993@e106497-lin.cambridge.arm.com>

On Thu, Feb 06, 2014 at 10:54:42AM +0000, Liviu Dudau wrote:
> On Thu, Feb 06, 2014 at 08:54:03AM +0000, Anup Patel wrote:
> > On Tue, Feb 4, 2014 at 10:23 PM, Will Deacon <will.deacon@arm.com> wrote:
> > > This patch adds support for an extremely simple virtual PCI host
> > > controller. The controller itself has no configuration registers, and
> > > has its address spaces described entirely by the device-tree (using the
> > > bindings described by ePAPR). This allows emulations, such as kvmtool,
> > > to provide a simple means for a guest Linux instance to make use of
> > > PCI devices.
> > >
> > > Corresponding documentation is added for the DT binding.
> > >
> > > Signed-off-by: Will Deacon <will.deacon@arm.com>
> > > ---
> > >  .../devicetree/bindings/pci/linux,pci-virt.txt     |  38 ++++
> > >  drivers/pci/host/Kconfig                           |   7 +
> > >  drivers/pci/host/Makefile                          |   1 +
> > >  drivers/pci/host/pci-virt.c                        | 200 +++++++++++++++++++++
> > >  4 files changed, 246 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > >  create mode 100644 drivers/pci/host/pci-virt.c
> > >
> > > diff --git a/Documentation/devicetree/bindings/pci/linux,pci-virt.txt b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > > new file mode 100644
> > > index 000000000000..54668a283498
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > > @@ -0,0 +1,38 @@
> > > +* ARM Basic Virtual PCI controller
> > > +
> > > +PCI emulations, such as the virtio-pci implementations found in kvmtool
> > > +and other para-virtualised systems, do not require driver support for
> > > +complexities such as regulator and clock management. In fact, the
> > > +controller may not even have a control interface visible to the
> > > +operating system, instead presenting a set of fixed windows describing a
> > > +subset of IO, Memory and Configuration spaces.
> > > +
> > > +Such a controller can be described purely in terms of the standardized
> > > +device tree bindings communicated in pci.txt:
> > > +
> > > +- compatible     : Must be "linux,pci-virt"
> > > +
> > > +- ranges         : As described in IEEE Std 1275-1994, but must provide
> > > +                   at least a definition of the Configuration Space plus
> > > +                   one or both of IO and Memory Space.
> > > +
> > > +- #address-cells : Must be 3
> > > +
> > > +- #size-cells    : Must be 2
> > > +
> > > +Configuration Space is assumed to be memory-mapped (as opposed to being
> > 
> > It would be great to have a flag to specify whether Configuration Space is over
> > ioports or memory mapped.
> 
> This is another reason why I prefer the reg property for specifying the configuration
> space address range. I don't see a straight way of making the distinction you
> need using the ranges property.

Well if we need to distinguish cam vs ecam, then adding ioport to the mix
should be (conceptually) easy and I don't think it would involve the "reg"
property.

However, I'm not planning to add ioport support myself.

Will

^ permalink raw reply

* [PATCH v3 2/2] ARM: dts: imx6sl-evk: Add audio support
From: Fabio Estevam @ 2014-02-06 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391684271-6621-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam@freescale.com>

imx6sl-evk has a wm8962 codec. Add support for it.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Chages since v2:
- Keep it sorted 

 arch/arm/boot/dts/imx6sl-evk.dts | 84 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 1899f85..3216ede 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -43,9 +43,49 @@
 			gpio = <&gpio4 2 0>;
 			enable-active-high;
 		};
+
+		reg_aud3v: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "wm8962-supply-3v15";
+			regulator-min-microvolt = <3150000>;
+			regulator-max-microvolt = <3150000>;
+			regulator-boot-on;
+		};
+
+		reg_aud4v: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "wm8962-supply-4v2";
+			regulator-min-microvolt = <4325000>;
+			regulator-max-microvolt = <4325000>;
+			regulator-boot-on;
+		};
+	};
+
+	sound {
+		compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962";
+		model = "wm8962-audio";
+		ssi-controller = <&ssi2>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"Ext Spk", "SPKOUTL",
+			"Ext Spk", "SPKOUTR",
+			"AMIC", "MICBIAS",
+			"IN3R", "AMIC";
+		mux-int-port = <2>;
+		mux-ext-port = <3>;
 	};
 };
 
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux3>;
+	status = "okay";
+};
+
 &ecspi1 {
 	fsl,spi-num-chipselects = <1>;
 	cs-gpios = <&gpio4 11 0>;
@@ -175,6 +215,27 @@
 	};
 };
 
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8962 at 1a {
+		compatible = "wlf,wm8962";
+		reg = <0x1a>;
+		clocks = <&clks IMX6SL_CLK_EXTERN_AUDIO>;
+		DCVDD-supply = <&vgen3_reg>;
+		DBVDD-supply = <&reg_aud3v>;
+		AVDD-supply = <&vgen3_reg>;
+		CPVDD-supply = <&vgen3_reg>;
+		MICVDD-supply = <&reg_aud3v>;
+		PLLVDD-supply = <&vgen3_reg>;
+		SPKVDD1-supply = <&reg_aud4v>;
+		SPKVDD2-supply = <&reg_aud4v>;
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -189,6 +250,16 @@
 				MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
 				MX6SL_PAD_KEY_COL4__GPIO4_IO00	0x80000000
 				MX6SL_PAD_KEY_COL5__GPIO4_IO02	0x80000000
+				MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0
+			>;
+		};
+
+		pinctrl_audmux3: audmux3grp {
+			fsl,pins = <
+				MX6SL_PAD_AUD_RXD__AUD3_RXD	  0x4130b0
+				MX6SL_PAD_AUD_TXC__AUD3_TXC	  0x4130b0
+				MX6SL_PAD_AUD_TXD__AUD3_TXD	  0x4110b0
+				MX6SL_PAD_AUD_TXFS__AUD3_TXFS	  0x4130b0
 			>;
 		};
 
@@ -221,6 +292,14 @@
 			>;
 		};
 
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C2_SCL__I2C2_SCL	0x4001b8b1
+				MX6SL_PAD_I2C2_SDA__I2C2_SDA	0x4001b8b1
+			>;
+		};
+
 		pinctrl_kpp: kppgrp {
 			fsl,pins = <
 				MX6SL_PAD_KEY_ROW0__KEY_ROW0    0x1b010
@@ -374,6 +453,11 @@
 	status = "okay";
 };
 
+&ssi2 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1>;
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH v3 1/2] ARM: dts: imx6sl-evk: Add PFUZE100 support
From: Fabio Estevam @ 2014-02-06 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Fabio Estevam <fabio.estevam@freescale.com>

imx6sl-evk board has Freescale PFUZE100 regulator, so add support for it.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Chages since v2:
- Keep it sorted 

 arch/arm/boot/dts/imx6sl-evk.dts | 113 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 0001804..1899f85 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -69,6 +69,112 @@
 	status = "okay";
 };
 
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: pfuze100 at 08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3b_reg: sw3b {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw4_reg: sw4 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vgen1 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vgen3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -108,6 +214,13 @@
 			>;
 		};
 
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6SL_PAD_I2C1_SCL__I2C1_SCL	0x4001b8b1
+				MX6SL_PAD_I2C1_SDA__I2C1_SDA	0x4001b8b1
+			>;
+		};
+
 		pinctrl_kpp: kppgrp {
 			fsl,pins = <
 				MX6SL_PAD_KEY_ROW0__KEY_ROW0    0x1b010
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 08/51] arm, hw-breakpoint: Fix CPU hotplug callback registration
From: Will Deacon @ 2014-02-06 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140205220603.19080.80971.stgit@srivatsabhat.in.ibm.com>

Hi Srivatsa,

On Wed, Feb 05, 2014 at 10:06:04PM +0000, Srivatsa S. Bhat wrote:
> Subsystems that want to register CPU hotplug callbacks, as well as perform
> initialization for the CPUs that are already online, often do it as shown
> below:
> 
> 	get_online_cpus();
> 
> 	for_each_online_cpu(cpu)
> 		init_cpu(cpu);
> 
> 	register_cpu_notifier(&foobar_cpu_notifier);
> 
> 	put_online_cpus();
> 
> This is wrong, since it is prone to ABBA deadlocks involving the
> cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
> with CPU hotplug operations).

Hmm, the code in question (for this patch) runs from an arch_initcall. How
can you generate CPU hotplug operations at that stage?

> Instead, the correct and race-free way of performing the callback
> registration is:
> 
> 	cpu_maps_update_begin();
> 
> 	for_each_online_cpu(cpu)
> 		init_cpu(cpu);
> 
> 	/* Note the use of the double underscored version of the API */
> 	__register_cpu_notifier(&foobar_cpu_notifier);
> 
> 	cpu_maps_update_done();
> 
> 
> Fix the hw-breakpoint code in arm by using this latter form of callback
> registration.

I guess you introduce __register_cpu_notifier somewhere earlier in the
series, so it's best if you take this all via your tree.

Will

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Liviu Dudau @ 2014-02-06 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAhSdy0X56UcMrp0bsH0na=GBkND=jqZVqbHxKsBampr8YM3cA@mail.gmail.com>

On Thu, Feb 06, 2014 at 08:54:03AM +0000, Anup Patel wrote:
> On Tue, Feb 4, 2014 at 10:23 PM, Will Deacon <will.deacon@arm.com> wrote:
> > This patch adds support for an extremely simple virtual PCI host
> > controller. The controller itself has no configuration registers, and
> > has its address spaces described entirely by the device-tree (using the
> > bindings described by ePAPR). This allows emulations, such as kvmtool,
> > to provide a simple means for a guest Linux instance to make use of
> > PCI devices.
> >
> > Corresponding documentation is added for the DT binding.
> >
> > Signed-off-by: Will Deacon <will.deacon@arm.com>
> > ---
> >  .../devicetree/bindings/pci/linux,pci-virt.txt     |  38 ++++
> >  drivers/pci/host/Kconfig                           |   7 +
> >  drivers/pci/host/Makefile                          |   1 +
> >  drivers/pci/host/pci-virt.c                        | 200 +++++++++++++++++++++
> >  4 files changed, 246 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> >  create mode 100644 drivers/pci/host/pci-virt.c
> >
> > diff --git a/Documentation/devicetree/bindings/pci/linux,pci-virt.txt b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > new file mode 100644
> > index 000000000000..54668a283498
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > @@ -0,0 +1,38 @@
> > +* ARM Basic Virtual PCI controller
> > +
> > +PCI emulations, such as the virtio-pci implementations found in kvmtool
> > +and other para-virtualised systems, do not require driver support for
> > +complexities such as regulator and clock management. In fact, the
> > +controller may not even have a control interface visible to the
> > +operating system, instead presenting a set of fixed windows describing a
> > +subset of IO, Memory and Configuration spaces.
> > +
> > +Such a controller can be described purely in terms of the standardized
> > +device tree bindings communicated in pci.txt:
> > +
> > +- compatible     : Must be "linux,pci-virt"
> > +
> > +- ranges         : As described in IEEE Std 1275-1994, but must provide
> > +                   at least a definition of the Configuration Space plus
> > +                   one or both of IO and Memory Space.
> > +
> > +- #address-cells : Must be 3
> > +
> > +- #size-cells    : Must be 2
> > +
> > +Configuration Space is assumed to be memory-mapped (as opposed to being
>
> It would be great to have a flag to specify whether Configuration Space is over
> ioports or memory mapped.

This is another reason why I prefer the reg property for specifying the configuration
space address range. I don't see a straight way of making the distinction you
need using the ranges property.

>
> Regards,
> Anup
>
> > +accessed via an ioport) and laid out with a direct correspondence to the
> > +geography of a PCI bus address, by concatenating the various components
> > +to form a 24-bit offset:
> > +
> > +        cfg_offset(bus, device, function, register) =
> > +                bus << 16 | device << 11 | function << 8 | register
> > +
> > +Interrupt mapping is exactly as described in `Open Firmware Recommended
> > +Practice: Interrupt Mapping' and requires the following properties:
> > +
> > +- #interrupt-cells   : Must be 1
> > +
> > +- interrupt-map      : <see aforementioned specification>
> > +
> > +- interrupt-map-mask : <see aforementioned specification>
> > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> > index 47d46c6d8468..fd4460573b81 100644
> > --- a/drivers/pci/host/Kconfig
> > +++ b/drivers/pci/host/Kconfig
> > @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2
> >           There are 3 internal PCI controllers available with a single
> >           built-in EHCI/OHCI host controller present on each one.
> >
> > +config PCI_VIRT_HOST
> > +       bool "Virtual PCI host controller"
> > +       depends on ARM && OF
> > +       help
> > +         Say Y here if you want to support a very simple virtual PCI
> > +         host controller, such as the one emulated by kvmtool.
> > +
> >  endmenu
> > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> > index 13fb3333aa05..9b6775d95d3b 100644
> > --- a/drivers/pci/host/Makefile
> > +++ b/drivers/pci/host/Makefile
> > @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
> >  obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> >  obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> >  obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> > +obj-$(CONFIG_PCI_VIRT_HOST) += pci-virt.o
> > diff --git a/drivers/pci/host/pci-virt.c b/drivers/pci/host/pci-virt.c
> > new file mode 100644
> > index 000000000000..ded01474453b
> > --- /dev/null
> > +++ b/drivers/pci/host/pci-virt.c
> > @@ -0,0 +1,200 @@
> > +/*
> > + * Very basic PCI host controller driver targetting virtual machines
> > + * (e.g. the PCI emulation provided by kvmtool).
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * 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/>.
> > + *
> > + * Copyright (C) 2014 ARM Limited
> > + *
> > + * Author: Will Deacon <will.deacon@arm.com>
> > + *
> > + * This driver currently supports (per instance):
> > + *     - A single controller
> > + *     - A single memory space and/or port space
> > + *     - A memory-mapped configuration space
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_pci.h>
> > +#include <linux/platform_device.h>
> > +
> > +struct virt_pci {
> > +       struct device   *dev;
> > +
> > +       struct resource cfg;
> > +       struct resource io;
> > +       struct resource mem;
> > +
> > +       void __iomem    *cfg_base;
> > +};
> > +
> > +static void __iomem *virt_pci_config_address(struct pci_bus *bus,
> > +                                            unsigned int devfn,
> > +                                            int where)
> > +{
> > +       struct pci_sys_data *sys = bus->sysdata;
> > +       struct virt_pci *pci = sys->private_data;
> > +       void __iomem *addr = pci->cfg_base;
> > +
> > +       /*
> > +        * We construct config space addresses by simply sandwiching
> > +        * together all of the PCI address components and using the
> > +        * result as an offset into a 16M region.
> > +        */
> > +       return addr + (((u32)bus->number << 16) | (devfn << 8) | where);
> > +}
> > +
> > +
> > +static int virt_pci_config_read(struct pci_bus *bus, unsigned int devfn,
> > +                               int where, int size, u32 *val)
> > +{
> > +       void __iomem *addr = virt_pci_config_address(bus, devfn, where);
> > +
> > +       switch (size) {
> > +       case 1:
> > +               *val = readb(addr);
> > +               break;
> > +       case 2:
> > +               *val = readw(addr);
> > +               break;
> > +       default:
> > +               *val = readl(addr);
> > +       }
> > +
> > +       return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int virt_pci_config_write(struct pci_bus *bus, unsigned int devfn,
> > +                                int where, int size, u32 val)
> > +{
> > +       void __iomem *addr = virt_pci_config_address(bus, devfn, where);
> > +
> > +       switch (size) {
> > +       case 1:
> > +               writeb(val, addr);
> > +               break;
> > +       case 2:
> > +               writew(val, addr);
> > +               break;
> > +       default:
> > +               writel(val, addr);
> > +       }
> > +
> > +       return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static struct pci_ops virt_pci_ops = {
> > +       .read   = virt_pci_config_read,
> > +       .write  = virt_pci_config_write,
> > +};
> > +
> > +static int virt_pci_setup(int nr, struct pci_sys_data *sys)
> > +{
> > +       struct virt_pci *pci = sys->private_data;
> > +
> > +       if (resource_type(&pci->io)) {
> > +               pci_add_resource(&sys->resources, &pci->io);
> > +               pci_ioremap_io(nr * resource_size(&pci->io), pci->io.start);
> > +       }
> > +
> > +       if (resource_type(&pci->mem))
> > +               pci_add_resource(&sys->resources, &pci->mem);
> > +
> > +       pci->cfg_base = devm_ioremap_resource(pci->dev, &pci->cfg);
> > +       return !IS_ERR(pci->cfg_base);
> > +}
> > +
> > +static const struct of_device_id virt_pci_of_match[] = {
> > +       { .compatible = "linux,pci-virt" },
> > +       { },
> > +};
> > +MODULE_DEVICE_TABLE(of, virt_pci_of_match);
> > +
> > +static int virt_pci_probe(struct platform_device *pdev)
> > +{
> > +       struct hw_pci hw;
> > +       struct of_pci_range range;
> > +       struct of_pci_range_parser parser;
> > +       struct virt_pci *pci;
> > +       struct device *dev = &pdev->dev;
> > +       struct device_node *np = dev->of_node;
> > +
> > +       if (of_pci_range_parser_init(&parser, np)) {
> > +               dev_err(dev, "missing \"ranges\" property\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
> > +       if (!pci)
> > +               return -ENOMEM;
> > +
> > +       pci->dev = dev;
> > +       for_each_of_pci_range(&parser, &range) {
> > +               u32 restype = range.flags & IORESOURCE_TYPE_BITS;
> > +
> > +               switch (restype) {
> > +               case IORESOURCE_IO:
> > +                       if (resource_type(&pci->io))
> > +                               dev_warn(dev,
> > +                                        "ignoring additional io resource\n");
> > +                       else
> > +                               of_pci_range_to_resource(&range, np, &pci->io);
> > +                       break;
> > +               case IORESOURCE_MEM:
> > +                       if (resource_type(&pci->mem))
> > +                               dev_warn(dev,
> > +                                        "ignoring additional mem resource\n");
> > +                       else
> > +                               of_pci_range_to_resource(&range, np, &pci->mem);
> > +                       break;
> > +               case 0: /* cfg */
> > +                       if (resource_type(&pci->cfg)) {
> > +                               dev_warn(dev,
> > +                                        "ignoring additional cfg resource\n");
> > +                       } else {
> > +                               of_pci_range_to_resource(&range, np, &pci->cfg);
> > +                               pci->cfg.flags |= IORESOURCE_MEM;
> > +                       }
> > +                       break;
> > +               default:
> > +                       dev_warn(dev,
> > +                               "ignoring unknown/unsupported resource type %x\n",
> > +                                restype);
> > +               }
> > +       }
> > +
> > +       memset(&hw, 0, sizeof(hw));
> > +       hw.nr_controllers       = 1;
> > +       hw.private_data         = (void **)&pci;
> > +       hw.setup                = virt_pci_setup;
> > +       hw.map_irq              = of_irq_parse_and_map_pci;
> > +       hw.ops                  = &virt_pci_ops;
> > +       pci_common_init_dev(dev, &hw);
> > +       return 0;
> > +}
> > +
> > +static struct platform_driver virt_pci_driver = {
> > +       .driver = {
> > +               .name = "pci-virt",
> > +               .owner = THIS_MODULE,
> > +               .of_match_table = virt_pci_of_match,
> > +       },
> > +       .probe = virt_pci_probe,
> > +};
> > +module_platform_driver(virt_pci_driver);
> > +
> > +MODULE_DESCRIPTION("Virtual PCI host driver");
> > +MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
> > +MODULE_LICENSE("GPLv2");
> > --
> > 1.8.2.2
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

--
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Anup Patel @ 2014-02-06 10:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2629498.fOknbqpyEP@wuerfel>

On Thu, Feb 6, 2014 at 3:56 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 06 February 2014 14:24:03 Anup Patel wrote:
>> > diff --git a/Documentation/devicetree/bindings/pci/linux,pci-virt.txt b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
>> > new file mode 100644
>> > index 000000000000..54668a283498
>> > +- compatible     : Must be "linux,pci-virt"
>> > +
>> > +- ranges         : As described in IEEE Std 1275-1994, but must provide
>> > +                   at least a definition of the Configuration Space plus
>> > +                   one or both of IO and Memory Space.
>> > +
>> > +- #address-cells : Must be 3
>> > +
>> > +- #size-cells    : Must be 2
>> > +
>> > +Configuration Space is assumed to be memory-mapped (as opposed to being
>>
>> It would be great to have a flag to specify whether Configuration Space is over
>> ioports or memory mapped.
>>
>
> I haven't seen config space access through ioport for a long
> time on non-x86. Do you have reason to believe that we will need
> that?

I suggested it to make "pci-virt" useful for x86-world too.

>
>         Arnd

--
Anup

^ permalink raw reply

* [PATCH v3 08/11] ARM: KVM: fix ordering of 64bit coprocessor accesses
From: Catalin Marinas @ 2014-02-06 10:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391630151-7875-9-git-send-email-marc.zyngier@arm.com>

On Wed, Feb 05, 2014 at 07:55:48PM +0000, Marc Zyngier wrote:
> Commit 240e99cbd00a (ARM: KVM: Fix 64-bit coprocessor handling)
> added an ordering dependency for the 64bit registers.
> 
> The order described is: CRn, CRm, Op1, Op2, 64bit-first.
> 
> Unfortunately, the implementation is: CRn, 64bit-first, CRm...
> 
> Move the 64bit test to be last in order to match the documentation.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH v3 07/11] ARM: KVM: fix handling of trapped 64bit coprocessor accesses
From: Catalin Marinas @ 2014-02-06 10:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391630151-7875-8-git-send-email-marc.zyngier@arm.com>

On Wed, Feb 05, 2014 at 07:55:47PM +0000, Marc Zyngier wrote:
> Commit 240e99cbd00a (ARM: KVM: Fix 64-bit coprocessor handling)
> changed the way we match the 64bit coprocessor access from
> user space, but didn't update the trap handler for the same
> set of registers.
> 
> The effect is that a trapped 64bit access is never matched, leading
> to a fault being injected into the guest. This went unnoticed as we
> didn't really trap any 64bit register so far.
> 
> Placing the CRm field of the access into the CRn field of the matching
> structure fixes the problem. Also update the debug feature to emit the
> expected string in case of failing match.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH v3 06/11] ARM: KVM: force cache clean on page fault when caches are off
From: Catalin Marinas @ 2014-02-06 10:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391630151-7875-7-git-send-email-marc.zyngier@arm.com>

On Wed, Feb 05, 2014 at 07:55:46PM +0000, Marc Zyngier wrote:
> In order for a guest with caches disabled to observe data written
> contained in a given page, we need to make sure that page is
> committed to memory, and not just hanging in the cache (as guest
> accesses are completely bypassing the cache until it decides to
> enable it).
> 
> For this purpose, hook into the coherent_cache_guest_page
> function and flush the region if the guest SCTLR
> register doesn't show the MMU and caches as being enabled.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH v3 05/11] ARM: LPAE: provide an IPA capable pmd_addr_end
From: Catalin Marinas @ 2014-02-06 10:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391630151-7875-6-git-send-email-marc.zyngier@arm.com>

On Wed, Feb 05, 2014 at 07:55:45PM +0000, Marc Zyngier wrote:
> The default pmd_addr_end macro uses an unsigned long to represent
> the VA. When used with KVM and stage-2 translation, the VA is
> actually an IPA, which is up to 40 bits. This also affect the
> SMMU driver, which also deals with stage-2 translation.
> 
> Instead, provide an implementation that can cope with larger VAs
> by using a u64 instead. This version will overload the default
> one provided in include/asm-generic/pgtable.h.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/include/asm/pgtable-3level.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
> index 03243f7..594867b 100644
> --- a/arch/arm/include/asm/pgtable-3level.h
> +++ b/arch/arm/include/asm/pgtable-3level.h
> @@ -262,6 +262,11 @@ static inline int has_transparent_hugepage(void)
>  	return 1;
>  }
>  
> +#define pmd_addr_end(addr, end)						\
> +({	u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK;		\
> +	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
> +})

I see why you need this but it affects all the other uses of
pmd_addr_end() with 32-bit VA. It would be slight performance, I don't
think it's noticeable.

A different approach could be something like (untested):

#define pmd_addr_end(addr, end)					\
({	__typeof__(addr) __boundary = ...
	...
})

What about the pgd_addr_end(), do we need this or it's not used by KVM?

-- 
Catalin

^ permalink raw reply

* [PATCH 00/11] ARM: shmobile: RSPI RZ and QSPI SoC and board integration
From: Magnus Damm @ 2014-02-06 10:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140205005631.GA7664@verge.net.au>

On Wed, Feb 5, 2014 at 9:56 AM, Simon Horman <horms@verge.net.au> wrote:
> Magnus, could you Ack these or otherwise?
>
> On Tue, Feb 04, 2014 at 04:23:54PM +0100, Geert Uytterhoeven wrote:
>>       Hi Simon, Magnus,
>>
>> This patch series contains SoC and board integration for
>>   1. RSPI in the r7s72100 aka RZ/A1H SoC on the Genmai reference board,
>>   2. QSPI in the r8a7791 aka R-Car M2 SoC on the Koelsch reference board.
>> It was rebased on top of renesas-devel-v3.14-rc1-20140204.
>>
>> It was tested on the r7s72100-based Genmai reference board using loopback
>> mode, and on the r8a7791-based Koelsch reference board using the Spansion
>> s25fl512s SPI FLASH.
>>
>>   - [v5 01/11] ARM: shmobile: r7s72100 clock: Add RSPI clocks
>>   - [v5 02/11] ARM: shmobile: genmai legacy: Add RSPI support
>>   - [v3 03/11] ARM: shmobile: genmai defconfig: Enable RSPI
>>   - [v3 04/11] ARM: shmobile: r7s72100 clock: Add RSPI clocks for DT
>>   - [v5 05/11] ARM: shmobile: r7s72100 dtsi: Add RSPI nodes
>>   - [v4 06/11] ARM: shmobile: r8a7791 clock: add QSPI clocks
>>   - [v4 07/11] ARM: shmobile: koelsch legacy: Add QSPI support
>>   - [v4 08/11] ARM: shmobile: koelsch defconfig: Enable RSPI and
>>   - [v3 09/11] ARM: shmobile: r8a7791 dtsi: Add QSPI node
>>   - [v3 10/11] ARM: shmobile: koelsch dts: Add QSPI nodes
>>   - [v2 11/11] ARM: shmobile: lager legacy: Switch QSPI to named IRQs
>
> Above I see v2, v3, v4 and v5 patches.
>
> While I can make sense of this it makes it cumbersome to refer to the
> series as a whole.
>
> Bob, can you take a look at '"[PATCH 00/11] ARM: shmobile: RSPI RZ and
> QSPI SoC and board", posted on Tuesday the 2nd, which includes v2, v3,
> v4 and v5 patches'?
>
> What would make my life easier would be if the entire series was v5 and
> all the patches contained in it were v5. Then I could just ask Bob to look
> at "[PATCH v5 00/11] ARM: shmobile: RSPI RZ and QSPI SoC and board"
>
> There is no Bob but I do ask people these kind of questions :)

Simon, Geert, Bob,

I've now gone through these patches and I think they look great. My
apologies for slow handling.

Acked-by: Magnus Damm <damm@opensource.se>

Thanks for your help.

Cheers,

/ magnus

^ permalink raw reply

* [PATCH] arm64: Change misleading function names in dma-mapping
From: Catalin Marinas @ 2014-02-06 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140206100909.GC26035@mudshark.cambridge.arm.com>

On Thu, Feb 06, 2014 at 10:09:09AM +0000, Will Deacon wrote:
> On Thu, Feb 06, 2014 at 06:28:22AM +0000, Ritesh Harjani wrote:
> > 
> > From: Ritesh Harjani <ritesh.harjani at gmail.com<mailto:ritesh.harjani@gmail.com>>
> > 
> > arm64_swiotlb_alloc/free_coherent name can be misleading
> > somtimes with CMA support being enabled after this
> > patch (c2104debc235b745265b64d610237a6833fd53)
> > 
> > Change this name to be more generic:
> > arm64_dma_alloc/free_coherent
> 
> I'm fine with this cosmetic change, but the (pre-existing) arm64 prefix looks
> a little odd for a static function.

Good point. I'm happy with a simpler __dma_alloc_coherent().

-- 
Catalin

^ permalink raw reply

* [PATCH] ARM: shmobile: r8a7790: Correct SYS DMAC clock defines
From: Laurent Pinchart @ 2014-02-06 10:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391646301-20197-1-git-send-email-horms+renesas@verge.net.au>

Hi Simon,

Thank you for the patch.

On Thursday 06 February 2014 09:25:01 Simon Horman wrote:
> This brings the implementation into line with the documentation.
> 
> This problem was introduced when SYS DMAC clock defines were added by
> ac991dce6498b5fc ("ARM: shmobile: r8a7790: Add clock index macros for DT
> sources") in v3.13-rc2. I do not believe this results in any problems as
> these defines do not appear to be used anywhere yet.
> 
> Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  include/dt-bindings/clock/r8a7790-clock.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/dt-bindings/clock/r8a7790-clock.h
> b/include/dt-bindings/clock/r8a7790-clock.h index 859e9be..6548a5f 100644
> --- a/include/dt-bindings/clock/r8a7790-clock.h
> +++ b/include/dt-bindings/clock/r8a7790-clock.h
> @@ -46,8 +46,8 @@
>  #define R8A7790_CLK_MSIOF1		8
>  #define R8A7790_CLK_MSIOF3		15
>  #define R8A7790_CLK_SCIFB2		16
> -#define R8A7790_CLK_SYS_DMAC0		18
> -#define R8A7790_CLK_SYS_DMAC1		19
> +#define R8A7790_CLK_SYS_DMAC1		18
> +#define R8A7790_CLK_SYS_DMAC0		19
> 
>  /* MSTP3 */
>  #define R8A7790_CLK_TPU0		4

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Arnd Bergmann @ 2014-02-06 10:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAhSdy0X56UcMrp0bsH0na=GBkND=jqZVqbHxKsBampr8YM3cA@mail.gmail.com>

On Thursday 06 February 2014 14:24:03 Anup Patel wrote:
> > diff --git a/Documentation/devicetree/bindings/pci/linux,pci-virt.txt b/Documentation/devicetree/bindings/pci/linux,pci-virt.txt
> > new file mode 100644
> > index 000000000000..54668a283498
> > +- compatible     : Must be "linux,pci-virt"
> > +
> > +- ranges         : As described in IEEE Std 1275-1994, but must provide
> > +                   at least a definition of the Configuration Space plus
> > +                   one or both of IO and Memory Space.
> > +
> > +- #address-cells : Must be 3
> > +
> > +- #size-cells    : Must be 2
> > +
> > +Configuration Space is assumed to be memory-mapped (as opposed to being
> 
> It would be great to have a flag to specify whether Configuration Space is over
> ioports or memory mapped.
> 

I haven't seen config space access through ioport for a long
time on non-x86. Do you have reason to believe that we will need
that?

	Arnd

^ permalink raw reply

* [PATCH v2] pwm: add CSR SiRFSoC PWM driver
From: Barry Song @ 2014-02-06 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401311623.56902.arnd@arndb.de>

2014-01-31 23:23 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Friday 31 January 2014, Barry Song wrote:
>> >
>> > Is SRC_OSC_RATE the rate of spwm->clk? If so, it would be nice to just call
>> > clk_get_rate() here, in case you ever have a chip with a different rate.
>> >
>>
>> SRC_OSC_RATE is the fixed frequency of crystal oscillator, but
>> spwm->clk comes from the IO bus. the design is a little strange, pwm
>> channels don't use the clock of PWM controller to generate
>> period/duty, but use other sources.
>
> How about modeling  that other source as a fixed-rate clock in DT
> then?

sirfsoc clock drivers have a clock node for OSC whose index is "1".
do you think the following is the right way to handle?

in dts, put both pwm controller clock and OSC
672                         pwm: pwm at b0130000 {
673                                 compatible = "sirf,prima2-pwm";
674                                 #pwm-cells = <2>;
675                                 reg = <0xb0130000 0x10000>;
676                                 clocks = <&clks 21>,  <&clks 1>;
677                                 clock-names = "pwmc", "osc";
678                         };

and in pwm-sirf.c driver, use
clk = clk_get(dev, "osc");
clk_get_rate(clk);

to get the rate in probe()?


>
>         Arnd

-barry

^ permalink raw reply

* [PATCH] can: xilinx CAN controller support.
From: Kedareswara rao Appana @ 2014-02-06 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

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 rc1 kernel.
---
 .../devicetree/bindings/net/can/xilinx_can.txt     |   43 +
 drivers/net/can/Kconfig                            |    8 +
 drivers/net/can/Makefile                           |    1 +
 drivers/net/can/xilinx_can.c                       | 1150 ++++++++++++++++++++
 4 files changed, 1202 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..34f9643
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/xilinx_can.txt
@@ -0,0 +1,43 @@
+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).
+- xlnx,can-tx-dpth	: Can Tx fifo depth (Required for Axi CAN).
+- xlnx,can-rx-dpth	: Can Rx fifo depth (Required for Axi CAN).
+
+
+Example:
+
+For Zynq CANPS Dts file:
+	zynq_can_0: zynq-can at 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>;
+		};
+For Axi CAN Dts file:
+	axi_can_0: axi-can at 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>;
+			xlnx,can-tx-dpth = <0x40>;
+			xlnx,can-rx-dpth = <0x40>;
+		};
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index d447b88..2344fb5 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -125,6 +125,14 @@ 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
+	default n
+	---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..c1b2b9d
--- /dev/null
+++ b/drivers/net/can/xilinx_can.c
@@ -0,0 +1,1150 @@
+/* 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_NAPI_WEIGHT		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 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;
+	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_OFFSET);
+
+	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;
+		}
+		schedule_timeout(1);
+	}
+
+	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;
+	}
+
+	netdev_dbg(ndev, "brp=%d,prop=%d,phase_seg1:%d,phase_reg2=%d,sjw=%d\n",
+			bt->brp, bt->prop_seg, bt->phase_seg1, bt->phase_seg2,
+			bt->sjw);
+
+	/* 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;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		netdev_info(ndev, "Doesn't support Triple Sampling\n");
+	netdev_dbg(ndev, "Setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
+
+	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 always
+ */
+static int xcan_start(struct net_device *ndev)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+
+	/* Check if it is in reset mode */
+	if (priv->can.state != CAN_STATE_STOPPED)
+		set_reset_mode(ndev);
+
+	/* 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;
+		if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+			while ((priv->read_reg(priv, XCAN_SR_OFFSET) &
+					XCAN_SR_LBACK_MASK) == 0)
+					;
+		} else {
+			while ((priv->read_reg(priv, XCAN_SR_OFFSET)
+					& XCAN_SR_NORMAL_MASK) == 0)
+					;
+		}
+		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)
+{
+	struct xcan_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	netdev_dbg(ndev, "Setting the mode of the driver%s\n", __func__);
+
+	if (!priv->open_time)
+		return -EINVAL;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		ret = xcan_start(ndev);
+		if (ret < 0)
+			netdev_err(ndev, "xcan_start failed!\n");
+
+		if (netif_queue_stopped(ndev))
+			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, tmp_dw1, tmp_dw2 = 0, data1, data2 = 0;
+	unsigned long 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;
+	}
+	/* Watch carefully on the bit sequence */
+	if ((cf->can_id & CAN_EFF_FLAG) == 0) {
+		/* 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;
+	} else {
+		/* 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;
+	}
+
+	dlc = (cf->can_dlc & 0xf) << XCAN_DLCR_DLC_SHIFT;
+
+	tmp_dw1 = le32_to_cpup((u32 *)(cf->data));
+	data1 = htonl(tmp_dw1);
+	if (dlc > 4) {
+		tmp_dw2 = le32_to_cpup((u32 *)(cf->data + 4));
+		data2 = htonl(tmp_dw2);
+	}
+
+	netdev_dbg(ndev, "tx:id=0x%08x,dlc=0x%08x,d1=0x%08x,d2=0x%08x\n",
+			id, dlc, data1, data2);
+
+	/* 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);
+	priv->write_reg(priv, XCAN_TXFIFO_DW1_OFFSET, data1);
+	priv->write_reg(priv, XCAN_TXFIFO_DW2_OFFSET, data2);
+	stats->tx_bytes += cf->can_dlc;
+	ndev->trans_start = jiffies;
+
+	can_put_echo_skb(skb, ndev, priv->ech_skb_next);
+
+	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);
+
+	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, data1, data2;
+
+	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;
+	data1 = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET);
+	data2 = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET);
+	netdev_dbg(ndev, "rx:id=0x%08x,dlc=0x%08x,d1=0x%08x,d2=0x%08x\n",
+		id_xcan, dlc, data1, data2);
+
+	/* 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;
+	} 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;
+	}
+
+	/* Change Xilinx CAN data format to socketCAN data format */
+	*(u32 *)(cf->data) = ntohl(data1);
+	if (cf->can_dlc > 4)
+		*(u32 *)(cf->data + 4) = ntohl(data2);
+	else
+		*(u32 *)(cf->data + 4) = 0;
+	stats->rx_bytes += cf->can_dlc;
+
+	can_led_event(ndev, CAN_LED_EVENT_RX);
+
+	netif_receive_skb(skb);
+
+	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;
+
+	if (priv->can.state == CAN_STATE_STOPPED)
+		return IRQ_NONE;
+
+	/* 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 err;
+
+	/* Set chip into reset mode */
+	err = set_reset_mode(ndev);
+	if (err < 0)
+		netdev_err(ndev, "mode resetting failed failed!\n");
+
+	/* Common open */
+	err = open_candev(ndev);
+	if (err)
+		return err;
+
+	err = xcan_start(ndev);
+	if (err < 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);
+	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;
+	priv->xcan_echo_skb_max_tx = XCAN_ECHO_SKB_MAX;
+	priv->xcan_echo_skb_max_rx = XCAN_NAPI_WEIGHT;
+
+	/* Get IRQ for the device */
+	ndev->irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, ndev->irq, &xcan_interrupt,
+				priv->irq_flags, dev_name(&pdev->dev),
+				(void *)ndev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Irq allocation for CAN failed\n");
+		goto err_free;
+	}
+
+	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;
+
+	/* 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 = of_property_read_u32(pdev->dev.of_node,
+				"xlnx,can-tx-dpth", &fifodep);
+		if (ret < 0)
+			goto err_free;
+		priv->xcan_echo_skb_max_tx = fifodep;
+		ret = of_property_read_u32(pdev->dev.of_node,
+				"xlnx,can-rx-dpth", &fifodep);
+		if (ret < 0)
+			goto err_free;
+		priv->xcan_echo_skb_max_rx = fifodep;
+	}
+
+	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

* [PATCH] pci: Add support for creating a generic host_bridge from device tree
From: Liviu Dudau @ 2014-02-06 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACoXjckKRQfR3CbC1JpgbhOumED+OqiMh1_Y73-h6q=ByMNanw@mail.gmail.com>

On Wed, Feb 05, 2014 at 10:26:27PM +0000, Tanmay Inamdar wrote:
> Hello Liviu,
>
> I did not get the first email of this particular patch on any of
> subscribed mailing lists (don't know why), hence replying here.

Strange, it shows in the MARC and GMANE archive for linux-pci, probably
a hickup on your receiving side?

>
> +struct pci_host_bridge *
> +pci_host_bridge_of_init(struct device *parent, int busno, struct pci_ops *ops,
> + void *host_data, struct list_head *resources)
> +{
> + struct pci_bus *root_bus;
> + struct pci_host_bridge *bridge;
> +
> + /* first parse the host bridge bus ranges */
> + if (pci_host_bridge_of_get_ranges(parent->of_node, resources))
> + return NULL;
> +
> + /* then create the root bus */
> + root_bus = pci_create_root_bus(parent, busno, ops, host_data, resources);
> + if (!root_bus)
> + return NULL;
> +
> + bridge = to_pci_host_bridge(root_bus->bridge);
> +
> + return bridge;
> +}
>
> You are keeping the domain_nr inside pci_host_bridge structure. In
> above API, domain_nr is required in 'pci_find_bus' function called
> from 'pci_create_root_bus'. Since the bridge is allocated after
> creating root bus, 'pci_find_bus' always gets domain_nr as 0. This
> will cause problem for scanning multiple domains.

Good catch. I was switching between creating a pci_controller in arch/arm64 and
adding the needed bits in pci_host_bridge. After internal review I've decided to
add the domain_nr to pci_host_bridge, but forgot to update the code everywhere.

Thanks for reviewing this, will fix in v2.

Do you find porting to the new API straight forward?

Best regards,
Liviu

>
>
> On Mon, Feb 3, 2014 at 10:46 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Monday 03 February 2014 18:33:48 Liviu Dudau wrote:
> >> +/**
> >> + * pci_host_bridge_of_get_ranges - Parse PCI host bridge resources from DT
> >> + * @dev: device node of the host bridge having the range property
> >> + * @resources: list where the range of resources will be added after DT parsing
> >> + *
> >> + * This function will parse the "ranges" property of a PCI host bridge device
> >> + * node and setup the resource mapping based on its content. It is expected
> >> + * that the property conforms with the Power ePAPR document.
> >> + *
> >> + * Each architecture will then apply their filtering based on the limitations
> >> + * of each platform. One general restriction seems to be the number of IO space
> >> + * ranges, the PCI framework makes intensive use of struct resource management,
> >> + * and for IORESOURCE_IO types they can only be requested if they are contained
> >> + * within the global ioport_resource, so that should be limited to one IO space
> >> + * range.
> >
> > Actually we have quite a different set of restrictions around I/O space on ARM32
> > at the moment: Each host bridge can have its own 64KB range in an arbitrary
> > location on MMIO space, and the total must not exceed 2MB of I/O space.
> >
> >> + */
> >> +static int pci_host_bridge_of_get_ranges(struct device_node *dev,
> >> +                                     struct list_head *resources)
> >> +{
> >> +     struct resource *res;
> >> +     struct of_pci_range range;
> >> +     struct of_pci_range_parser parser;
> >> +     int err;
> >> +
> >> +     pr_info("PCI host bridge %s ranges:\n", dev->full_name);
> >> +
> >> +     /* Check for ranges property */
> >> +     err = of_pci_range_parser_init(&parser, dev);
> >> +     if (err)
> >> +             return err;
> >> +
> >> +     pr_debug("Parsing ranges property...\n");
> >> +     for_each_of_pci_range(&parser, &range) {
> >> +             /* Read next ranges element */
> >> +             pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
> >> +                             range.pci_space, range.pci_addr);
> >> +             pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
> >> +                                     range.cpu_addr, range.size);
> >> +
> >> +             /* If we failed translation or got a zero-sized region
> >> +              * (some FW try to feed us with non sensical zero sized regions
> >> +              * such as power3 which look like some kind of attempt
> >> +              * at exposing the VGA memory hole) then skip this range
> >> +              */
> >> +             if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> >> +                     continue;
> >> +
> >> +             res = kzalloc(sizeof(struct resource), GFP_KERNEL);
> >> +             if (!res) {
> >> +                     err = -ENOMEM;
> >> +                     goto bridge_ranges_nomem;
> >> +             }
> >> +
> >> +             of_pci_range_to_resource(&range, dev, res);
> >> +
> >> +             pci_add_resource_offset(resources, res,
> >> +                             range.cpu_addr - range.pci_addr);
> >> +     }
> >
> > I believe of_pci_range_to_resource() will return the MMIO aperture for the
> > I/O space window here, which is not what you are supposed to pass into
> > pci_add_resource_offset.
> >
> >> +EXPORT_SYMBOL(pci_host_bridge_of_init);
> >
> > EXPORT_SYMBOL_GPL
> >
> >> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> >> index 6e34498..16febae 100644
> >> --- a/drivers/pci/probe.c
> >> +++ b/drivers/pci/probe.c
> >> @@ -1787,6 +1787,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> >>       list_for_each_entry_safe(window, n, resources, list) {
> >>               list_move_tail(&window->list, &bridge->windows);
> >>               res = window->res;
> >> +             /*
> >> +              * IO resources are stored in the kernel with a CPU start
> >> +              * address of zero. Adjust the data accordingly and remember
> >> +              * the offset
> >> +              */
> >> +             if (resource_type(res) == IORESOURCE_IO) {
> >> +                     bridge->io_offset = res->start;
> >> +                     res->end -= res->start;
> >> +                     window->offset -= res->start;
> >> +                     res->start = 0;
> >> +             }
> >>               offset = window->offset;
> >>               if (res->flags & IORESOURCE_BUS)
> >
> > Won't this break all existing host bridges?
> >
> >         Arnd
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

--
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782

^ permalink raw reply

* [PATCH] arm64: Change misleading function names in dma-mapping
From: Will Deacon @ 2014-02-06 10:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD15agZzJ4=RMbky+GymJbyktLz0PO+uZ-GOh1SbvH476k4hzA@mail.gmail.com>

On Thu, Feb 06, 2014 at 06:28:22AM +0000, Ritesh Harjani wrote:
> 
> From: Ritesh Harjani <ritesh.harjani at gmail.com<mailto:ritesh.harjani@gmail.com>>
> 
> arm64_swiotlb_alloc/free_coherent name can be misleading
> somtimes with CMA support being enabled after this
> patch (c2104debc235b745265b64d610237a6833fd53)
> 
> Change this name to be more generic:
> arm64_dma_alloc/free_coherent

I'm fine with this cosmetic change, but the (pre-existing) arm64 prefix looks
a little odd for a static function.

Will

> Signed-off-by: Ritesh Harjani <ritesh.harjani at gmail.com<mailto:ritesh.harjani@gmail.com>>
> ---
>  arch/arm64/mm/dma-mapping.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 45b5ab5..7517796 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -30,7 +30,7 @@
>  struct dma_map_ops *dma_ops;
>  EXPORT_SYMBOL(dma_ops);
> 
> -static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
> +static void *arm64_dma_alloc_coherent(struct device *dev, size_t size,
>                                           dma_addr_t *dma_handle, gfp_t flags,
>                                           struct dma_attrs *attrs)
>  {
> @@ -57,7 +57,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>         }
>  }
> 
> -static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
> +static void arm64_dma_free_coherent(struct device *dev, size_t size,
>                                         void *vaddr, dma_addr_t dma_handle,
>                                         struct dma_attrs *attrs)
>  {
> @@ -78,8 +78,8 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
>  }
> 
>  static struct dma_map_ops arm64_swiotlb_dma_ops = {
> -       .alloc = arm64_swiotlb_alloc_coherent,
> -       .free = arm64_swiotlb_free_coherent,
> +       .alloc = arm64_dma_alloc_coherent,
> +       .free = arm64_dma_free_coherent,
>         .map_page = swiotlb_map_page,
>         .unmap_page = swiotlb_unmap_page,
>         .map_sg = swiotlb_map_sg_attrs,
> --
> 1.8.1.3
> 
> 

^ permalink raw reply

* [GIT PULL] clk: socfpga: Clock updates for v3.15
From: Mike Turquette @ 2014-02-06 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391620344-16882-1-git-send-email-dinguyen@altera.com>

Quoting dinguyen at altera.com (2014-02-05 09:12:24)
> Hi Mike,
> 
> Please consider pull these patch for v3.15.

Taken into clk-next.

Thanks!
Mike

> 
> Thanks,
> Dinh
> 
> The following changes since commit 38dbfb59d1175ef458d006556061adeaa8751b72:
> 
>   Linus 3.14-rc1 (2014-02-02 16:42:13 -0800)
> 
> are available in the git repository at:
> 
>   git://git.rocketboards.org/linux-socfpga-next.git tags/socfpga-clk-for-3.15
> 
> for you to fetch changes up to 5d81b6fc5ee1d904f9e3faab3a80cee36d267136:
> 
>   clk: socfpga: Add a clk-phase property to the "altr,socfpga-gate-clk" (2014-02-05 11:05:09 -0600)
> 
> ----------------------------------------------------------------
> SOCFPGA clk updates for v3.15
> 
> ----------------------------------------------------------------
> Dinh Nguyen (4):
>       clk: socfpga: Map the clk manager base address in the clock driver
>       clk: socfpga: Look for the GPIO_DB_CLK by its offset
>       clk: socfpga: Remove socfpga_init_clocks
>       clk: socfpga: Add a clk-phase property to the "altr,socfpga-gate-clk"
> 
> Steffen Trumtrar (3):
>       clk: socfpga: remove unused field
>       clk: socfpga: fix define typo
>       clk: socfpga: split clk code
> 
>  .../devicetree/bindings/clock/altr_socfpga.txt     |    5 +
>  arch/arm/boot/dts/socfpga.dtsi                     |    1 +
>  arch/arm/mach-socfpga/socfpga.c                    |    5 -
>  drivers/clk/socfpga/Makefile                       |    3 +
>  drivers/clk/socfpga/clk-gate.c                     |  263 ++++++++++++++++
>  drivers/clk/socfpga/clk-periph.c                   |   94 ++++++
>  drivers/clk/socfpga/clk-pll.c                      |  111 +++++++
>  drivers/clk/socfpga/clk.c                          |  326 +-------------------
>  drivers/clk/socfpga/clk.h                          |   57 ++++
>  9 files changed, 546 insertions(+), 319 deletions(-)
>  create mode 100644 drivers/clk/socfpga/clk-gate.c
>  create mode 100644 drivers/clk/socfpga/clk-periph.c
>  create mode 100644 drivers/clk/socfpga/clk-pll.c
>  create mode 100644 drivers/clk/socfpga/clk.h

^ permalink raw reply

* IOMMU DMA-mapping API for arm64 ?
From: Will Deacon @ 2014-02-06 10:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD15agaA9c1+0svk_d97ZEcaOg6x_PGcbKVHM9dWAZ_t1T8FXw@mail.gmail.com>

On Thu, Feb 06, 2014 at 05:05:45AM +0000, Ritesh Harjani wrote:
> Hi everyone,
> 
> I tried looking for IOMMU support in ARM64 but what I was able to see is
> only swiotlb is currently supported.
> 
> Based on my understanding for IOMMU support, we need DMA-MAPPING API to
> have IOMMU ops field, similar to what is present in arm32.  I could see
> the iommu field added in dev_archdata in below mentioned patch
> (arch/arm64/include/asm/device.h), but there is no ops field in
> arch/arm64/mm/dma-mapping.c ?

Correct, there needs to be a way to plumb dma-mapping into the IOMMU layer.

> I also saw one mail discussion between you guys on what is the best place
> for adding iommu support in ARM64, but couldn't see any followed up
> patches for the same.
> 
> Please tell us the current status/updates on the same. Your feedback will
> be greatly appreciated.

There are a few related topics here:

  (1) Moving a bunch of the boilerplate IOMMU code into a common place
      (iommu-helper.c or similar). This is because we don't want to blindly
      duplicate common code across architectures.

  (2) Standardising at least part of a system topology description in
      device-tree, so that we can deal with different combinations of
      {coherent,nocoherent} device {with,without} a series of IOMMUs.

Once both of those are sorted, the actual plumbing should be fairly
straightforward.

Will

^ permalink raw reply

* mv64xxx: I2C bus locked when scanning absent devices on Armada XP
From: Gregory CLEMENT @ 2014-02-06 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

I write this email mainly to let you know that there are some issues
on i2c on the Armada XP (rev A0 and B0) based boards.

What we observed was that if the i2c driver try to access an address
where the device is absent, then the bus is locked. After the timeout
the driver give up, but if we have a lot of i2c client registered,
then the kernel spend a lot of time trying to scan all the
addresses. It is noticeable when using the multiv7_defconfig where
many i2c clients are registered, whereas with mvebu_defconfig we have
fewer i2c clients, and most of them are present on the boards.

Here is an extract of what you can see during a boot:

[    4.127648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[    4.137338] rtc-s35390a 1-0030: rtc core: registered rtc-s35390a as rtc0
[    6.137649] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[    8.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   10.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   12.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   14.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   16.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   18.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   20.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   22.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   24.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   26.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   28.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   30.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   32.137649] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   34.137648] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   36.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   38.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   40.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   42.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   44.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   46.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   48.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   50.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   52.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   54.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   56.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   58.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   60.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   62.137648] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0
[   62.144403] sdhci: Secure Digital Host Controller Interface driver

Then the kernel continue to boot. and except this very annoying delay,
everything else is working on i2c.

If anyone have an idea of the cause of this issue, I would be glad to
have any input.

I continue to investigate it, and for the record v3.12 was not
affected but v3.13 was. So now I am going to bisect.

Gregory
-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH v2 0/5] ARM: sun6i: Add support for the A31 I2C controller
From: Maxime Ripard @ 2014-02-06  9:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140127150312.GN3867@lukather>

On Mon, Jan 27, 2014 at 04:03:12PM +0100, Maxime Ripard wrote:
> Hi Wolfram,
> 
> On Mon, Jan 13, 2014 at 11:34:48AM +0100, Maxime Ripard wrote:
> > Hi everyone,
> > 
> > This patchset adds support the A31 i2c controller. This is mostly the
> > same controller as the one found in the other Allwinner SoCs, except
> > for the interrupts acking.
> > 
> > On the other SoCs using this driver, the interrupts are acked by
> > clearing the INT_FLAG bit in the control register, while on the A31,
> > the interrupt is acked by writing that bit into the control register.
> > 
> > The other difference is that the I2C IP is maintained in reset by a
> > reset controller, so we're adding optionnal support for the reset
> > framework in the driver to deassert the device from reset.
> 
> Do you have any comments on this?

Ping?

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140206/34c79c1b/attachment.sig>

^ permalink raw reply

* [PATCH v2 2/2] ARM: sunxi: dt: Convert to the new i2c compatibles
From: Maxime Ripard @ 2014-02-06  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391680285-16668-1-git-send-email-maxime.ripard@free-electrons.com>

Switch the device tree to the new compatibles introduced in the i2c drivers
to have a common pattern accross all Allwinner SoCs.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun4i-a10.dtsi  |  6 +++---
 arch/arm/boot/dts/sun5i-a10s.dtsi |  6 +++---
 arch/arm/boot/dts/sun5i-a13.dtsi  |  6 +++---
 arch/arm/boot/dts/sun7i-a20.dtsi  | 10 +++++-----
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 28273f9..ac65c8a 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -518,7 +518,7 @@
 		};
 
 		i2c0: i2c at 01c2ac00 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <7>;
 			clocks = <&apb1_gates 0>;
@@ -527,7 +527,7 @@
 		};
 
 		i2c1: i2c at 01c2b000 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <8>;
 			clocks = <&apb1_gates 1>;
@@ -536,7 +536,7 @@
 		};
 
 		i2c2: i2c at 01c2b400 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <9>;
 			clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 2318082..a2005c7 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -435,7 +435,7 @@
 		i2c0: i2c at 01c2ac00 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <7>;
 			clocks = <&apb1_gates 0>;
@@ -446,7 +446,7 @@
 		i2c1: i2c at 01c2b000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <8>;
 			clocks = <&apb1_gates 1>;
@@ -457,7 +457,7 @@
 		i2c2: i2c at 01c2b400 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <9>;
 			clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 6de40b6..537072c 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -377,7 +377,7 @@
 		};
 
 		i2c0: i2c at 01c2ac00 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <7>;
 			clocks = <&apb1_gates 0>;
@@ -386,7 +386,7 @@
 		};
 
 		i2c1: i2c at 01c2b000 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <8>;
 			clocks = <&apb1_gates 1>;
@@ -395,7 +395,7 @@
 		};
 
 		i2c2: i2c at 01c2b400 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <9>;
 			clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index bfb2cf2..ec4463f 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -564,7 +564,7 @@
 		};
 
 		i2c0: i2c at 01c2ac00 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <0 7 4>;
 			clocks = <&apb1_gates 0>;
@@ -573,7 +573,7 @@
 		};
 
 		i2c1: i2c at 01c2b000 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <0 8 4>;
 			clocks = <&apb1_gates 1>;
@@ -582,7 +582,7 @@
 		};
 
 		i2c2: i2c at 01c2b400 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <0 9 4>;
 			clocks = <&apb1_gates 2>;
@@ -591,7 +591,7 @@
 		};
 
 		i2c3: i2c at 01c2b800 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2b800 0x400>;
 			interrupts = <0 88 4>;
 			clocks = <&apb1_gates 3>;
@@ -600,7 +600,7 @@
 		};
 
 		i2c4: i2c at 01c2bc00 {
-			compatible = "allwinner,sun4i-i2c";
+			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2bc00 0x400>;
 			interrupts = <0 89 4>;
 			clocks = <&apb1_gates 15>;
-- 
1.8.4.2

^ permalink raw reply related


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