* Re: [PATCH v7 3/4] arm64: dts: marvell: Add I2C definitions for the Armada 3700
From: Gregory CLEMENT @ 2017-01-03 15:20 UTC (permalink / raw)
To: Romain Perier
Cc: Mark Rutland, devicetree, Yahuda Yitschak, Omri Itach,
Jason Cooper, Pawel Moll, Ian Campbell, Igal Liberman, Hanna Hawa,
Wolfram Sang, Neta Zur Hershkovits, Nadav Haklai, Rob Herring,
Andrew Lunn, linux-i2c, Kumar Gala, Shadi Ammouri, Marcin Wojtas,
Thomas Petazzoni, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20161201110440.27530-4-romain.perier@free-electrons.com>
Hi Romain,
On jeu., déc. 01 2016, Romain Perier <romain.perier@free-electrons.com> wrote:
> The Armada 3700 has two i2c bus interface units, this commit adds the
> definitions of the corresponding device nodes. It also enables the node
> on the development board for this SoC.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Applied on mvebu/dt64
Thanks,
Gregory
> ---
> arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
> arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++++
> 2 files changed, 22 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> index 1372e9a6..16d84af 100644
> --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
> @@ -62,6 +62,10 @@
> };
> };
>
> +&i2c0 {
> + status = "okay";
> +};
> +
> /* CON3 */
> &sata {
> status = "okay";
> diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
> index e9bd587..1b0fd21 100644
> --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
> @@ -98,6 +98,24 @@
> /* 32M internal register @ 0xd000_0000 */
> ranges = <0x0 0x0 0xd0000000 0x2000000>;
>
> + i2c0: i2c@11000 {
> + compatible = "marvell,armada-3700-i2c";
> + reg = <0x11000 0x24>;
> + clocks = <&nb_periph_clk 10>;
> + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
> + mrvl,i2c-fast-mode;
> + status = "disabled";
> + };
> +
> + i2c1: i2c@11080 {
> + compatible = "marvell,armada-3700-i2c";
> + reg = <0x11080 0x24>;
> + clocks = <&nb_periph_clk 9>;
> + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
> + mrvl,i2c-fast-mode;
> + status = "disabled";
> + };
> +
> uart0: serial@12000 {
> compatible = "marvell,armada-3700-uart";
> reg = <0x12000 0x400>;
> --
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH v2 6/7] dt-bindings: media: Add Renesas R-Car DRIF binding
From: Ramesh Shanmugasundaram @ 2017-01-03 15:20 UTC (permalink / raw)
To: Geert Uytterhoeven, Laurent Pinchart
Cc: Rob Herring, Mark Rutland, Mauro Carvalho Chehab, Hans Verkuil,
Sakari Ailus, Antti Palosaari, Chris Paterson, Geert Uytterhoeven,
Linux Media Mailing List, devicetree@vger.kernel.org,
Linux-Renesas
In-Reply-To: <CAMuHMdXj-xBrnBXfYu6BeXr7Gfv4wogH4z610Ddq-BSyVS=-8Q@mail.gmail.com>
Hi Laurent, Geert,
Thanks for the review comments.
> > On Wednesday 21 Dec 2016 08:10:37 Ramesh Shanmugasundaram wrote:
> >> Add binding documentation for Renesas R-Car Digital Radio Interface
> >> (DRIF) controller.
> >>
> >> Signed-off-by: Ramesh Shanmugasundaram
> >> <ramesh.shanmugasundaram@bp.renesas.com> ---
> >> .../devicetree/bindings/media/renesas,drif.txt | 202
> ++++++++++++++++++
> >> 1 file changed, 202 insertions(+)
> >> create mode 100644
> >> Documentation/devicetree/bindings/media/renesas,drif.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/media/renesas,drif.txt
> >> b/Documentation/devicetree/bindings/media/renesas,drif.txt new file
> >> mode
> >> 100644
> >> index 0000000..1f3feaf
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/media/renesas,drif.txt
>
> >> +Optional properties of an internal channel when:
> >> + - It is the only enabled channel of the bond (or)
> >> + - If it acts as primary among enabled bonds
> >> +--------------------------------------------------------
> >> +- renesas,syncmd : sync mode
> >> + 0 (Frame start sync pulse mode. 1-bit width
> pulse
> >> + indicates start of a frame)
> >> + 1 (L/R sync or I2S mode) (default)
> >> +- renesas,lsb-first : empty property indicates lsb bit is received
> >> first.
> >> + When not defined msb bit is received first
> >> +(default)
> >> +- renesas,syncac-active: Indicates sync signal polarity, 0/1 for
> low/high
> >> + respectively. The default is 1 (active high)
> >> +- renesas,dtdl : delay between sync signal and start of
> reception.
> >> + The possible values are represented in 0.5 clock
> >> + cycle units and the range is 0 to 4. The default
> >> + value is 2 (i.e.) 1 clock cycle delay.
> >> +- renesas,syncdl : delay between end of reception and sync
> signal
> >> edge.
> >> + The possible values are represented in 0.5 clock
> >> + cycle units and the range is 0 to 4 & 6. The
> default
> >> + value is 0 (i.e.) no delay.
> >
> > Most of these properties are pretty similar to the video bus
> > properties defined at the endpoint level in
> > Documentation/devicetree/bindings/media/video-interfaces.txt. I
> > believe it would make sense to use OF graph and try to standardize
> > these properties similarly.
>
> Note that the last two properties match the those in
> Documentation/devicetree/bindings/spi/sh-msiof.txt.
> We may want to use one DRIF channel as a plain SPI slave with the
> (modified) MSIOF driver in the future.
Should I leave it as it is or modify these as in video-interfaces.txt? Shall we conclude on this please?
Thanks,
Ramesh
^ permalink raw reply
* Re: [PATCH 1/3] dt: pwm: lpc32xx: add description of clocks and #pwm-cells properties
From: Sylvain Lemieux @ 2017-01-03 15:22 UTC (permalink / raw)
To: Vladimir Zapolskiy
Cc: Rob Herring, devicetree, Thierry Reding, linux-arm-kernel,
linux-pwm
In-Reply-To: <5a865e27-e673-2f45-6c71-ca1e7d92a346@mleia.com>
Hi Rob,
On Wed, 2016-12-21 at 05:30 +0200, Vladimir Zapolskiy wrote:
> On 12/10/2016 01:51 AM, Vladimir Zapolskiy wrote:
> > Hi Rob,
> >
> > On 12/09/2016 11:41 PM, Rob Herring wrote:
> >> On Mon, Dec 05, 2016 at 03:42:37AM +0200, Vladimir Zapolskiy wrote:
> >>> NXP LPC32xx SoCs have two simple independent PWM controllers with a single
> >>> output each, in this case there is no need to specify PWM channel argument
> >>> on client side, one cell for setting PWM output frequency is sufficient.
> >>>
> >>> Another added to the description property 'clocks' has a standard meaning
> >>> of a controller supply clock, in the LPC32xx User's Manual the clock is
> >>> denoted as PWM1_CLK or PWM2_CLK clock.
> >>>
> >>> Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
> >>> ---
> >>> Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt | 7 +++++++
> >>> 1 file changed, 7 insertions(+)
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
> >>> index 74b5bc5..523d796 100644
> >>> --- a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
> >>> +++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
> >>> @@ -3,15 +3,22 @@ LPC32XX PWM controller
> >>> Required properties:
> >>> - compatible: should be "nxp,lpc3220-pwm"
> >>> - reg: physical base address and length of the controller's registers
> >>> +- clocks: clock phandle and clock specifier pair
> >>> +- #pwm-cells: should be 1, the cell is used to specify the period in
> >>> + nanoseconds.
> >>
> >> This use of the cell is a bit odd as the period is s/w config and this
> >> would typically be a channel selection or such.
> >
> > this is a classic PWM channel configuration property for PWM consumers
> > described in DT, for instance PWM frequency for display panel backlight
> > on boot.
> >
> > I think >90% of PWM controllers with device tree bindings have this
> > argument in #pwm-cells, from bindings/pwm/pwm.txt :
> >
> > pwm-specifier typically encodes the chip-relative PWM number and
> > the PWM period in nanoseconds.
> >
> > You also may skim through phandle arguments of 'pwms' property,
> > commonly the second argument is the requested frequency.
> >
> > In this particular case I just drop PWM channel number, because
> > the LPC32xx PWM controller has a single output channel.
> >
> >> What if I want user specified/changed periods?
> >>
> >
> > The preset period still can be changed over sysfs in runtime.
>
> Rob, have I managed to answer your questions?
>
> If you accept my clarification, could you please ack the change?
>
> --
> With best wishes,
> Vladimir
>
ping
Sylvain
^ permalink raw reply
* Re: [PATCH v1 2/3] dt-bindings: add binding for rk3328 power domains
From: Rob Herring @ 2017-01-03 15:24 UTC (permalink / raw)
To: Elaine Zhang
Cc: mark.rutland, devicetree, huangtao, heiko, tomeu.vizoso, xf,
khilman, xxx, linux-kernel, linux-rockchip, cl, linux-arm-kernel,
wxt
In-Reply-To: <1482464872-12954-3-git-send-email-zhangqing@rock-chips.com>
On Fri, Dec 23, 2016 at 11:47:51AM +0800, Elaine Zhang wrote:
> Add binding documentation for the power domains
> found on Rockchip RK3328 SoCs.
> But RK3328 SoC just support idle, not support pd.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
> Documentation/devicetree/bindings/soc/rockchip/power_domain.txt | 3 +++
> 1 file changed, 3 insertions(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH 1/2] input: touchscreen: add driver for Zeitec ZET6223
From: Rob Herring @ 2017-01-03 15:24 UTC (permalink / raw)
To: Jelle van der Waa
Cc: Dmitry Torokhov, linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161223163214.7716-1-jelle-oJJ1AqDjjO4@public.gmane.org>
On Fri, Dec 23, 2016 at 05:32:13PM +0100, Jelle van der Waa wrote:
> This is a basic driver for the Zeitec ZET6223 I2C touchscreen
> controllers. The driver does not support firmware loading, which is not
> required for all tablets which contain this chip.
>
> Signed-off-by: Jelle van der Waa <jelle-oJJ1AqDjjO4@public.gmane.org>
> ---
> .../bindings/input/touchscreen/zet6223.txt | 29 +++
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> drivers/input/touchscreen/Kconfig | 11 ++
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/zet6223.c | 198 +++++++++++++++++++++
> 4 files changed, 239 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/zet6223.txt
> create mode 100644 drivers/input/touchscreen/zet6223.c
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/2] devicetree: add vendor prefix for Zeitec
From: Rob Herring @ 2017-01-03 15:25 UTC (permalink / raw)
To: Jelle van der Waa; +Cc: Dmitry Torokhov, linux-input, devicetree
In-Reply-To: <20161223163214.7716-2-jelle@vdwaa.nl>
On Fri, Dec 23, 2016 at 05:32:14PM +0100, Jelle van der Waa wrote:
> Signed-off-by: Jelle van der Waa <jelle@vdwaa.nl>
> ---
> Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 0/4] Add support for the USB OTG function of Allwinner V3s
From: Icenowy Zheng @ 2017-01-03 15:25 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Kishon Vijay Abraham I, Bin Liu
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Icenowy Zheng
Allwinner V3s SoC come with a USB OTG controller, which is a bind of a Mentor
Graphics MUSB Dual-role controller and a private USB PHY.
Both the MUSB and the USB PHY slightly changed. (The MUSB is similar to the
one in the popular SBC SoC H3).
Add support for them.
The device tree patches depends on my preivous patchset, but the phy and musb
patches are independent (the device tree patches depend on them).
The MUSB patch may be picked for use on H3.
The clock of the USB part seems to need some hack in the U-Boot, they are at
my WIP u-boot repo:
https://github.com/Icenowy/u-boot-1/tree/v3s .
Icenowy Zheng (4):
phy: sun4i-usb: add support for V3s USB PHY
musb: sunxi: add support for the variant in H3/V3s SoC
ARM: dts: sunxi: add usb_otg and usbphy node for V3s SoC
ARM: dts: sun8i: add OTG function to Lichee Pi Zero
.../devicetree/bindings/phy/sun4i-usb-phy.txt | 1 +
.../bindings/usb/allwinner,sun4i-a10-musb.txt | 4 +--
arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 10 +++++++
arch/arm/boot/dts/sun8i-v3s.dtsi | 27 +++++++++++++++++
drivers/phy/phy-sun4i-usb.c | 14 ++++++++-
drivers/usb/musb/sunxi.c | 35 ++++++++++++++++++++--
6 files changed, 86 insertions(+), 5 deletions(-)
--
2.11.0
^ permalink raw reply
* [PATCH 1/4] phy: sun4i-usb: add support for V3s USB PHY
From: Icenowy Zheng @ 2017-01-03 15:25 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Kishon Vijay Abraham I, Bin Liu
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Icenowy Zheng
In-Reply-To: <20170103152534.20118-1-icenowy@aosc.xyz>
Allwinner V3s come with a USB PHY controller slightly different to other
SoCs, with only one PHY.
Add support for it.
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | 1 +
drivers/phy/phy-sun4i-usb.c | 14 +++++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index 287150db6db4..e42334258185 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -10,6 +10,7 @@ Required properties:
* allwinner,sun8i-a23-usb-phy
* allwinner,sun8i-a33-usb-phy
* allwinner,sun8i-h3-usb-phy
+ * allwinner,sun8i-v3s-usb-phy
* allwinner,sun50i-a64-usb-phy
- reg : a list of offset + length pairs
- reg-names :
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index bf28a0fdd569..4102841a8ad2 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -99,6 +99,7 @@ enum sun4i_usb_phy_type {
sun6i_a31_phy,
sun8i_a33_phy,
sun8i_h3_phy,
+ sun8i_v3s_phy,
sun50i_a64_phy,
};
@@ -188,7 +189,8 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
spin_lock_irqsave(&phy_data->reg_lock, flags);
if (phy_data->cfg->type == sun8i_a33_phy ||
- phy_data->cfg->type == sun50i_a64_phy) {
+ phy_data->cfg->type == sun50i_a64_phy ||
+ phy_data->cfg->type == sun8i_v3s_phy) {
/* A33 or A64 needs us to set phyctl to 0 explicitly */
writel(0, phyctl);
}
@@ -825,6 +827,15 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.enable_pmu_unk1 = true,
};
+static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
+ .num_phys = 1,
+ .type = sun8i_v3s_phy,
+ .disc_thresh = 3,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .enable_pmu_unk1 = true,
+};
+
static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.num_phys = 2,
.type = sun50i_a64_phy,
@@ -842,6 +853,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
+ { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
{ },
--
2.11.0
^ permalink raw reply related
* [PATCH 2/4] musb: sunxi: add support for the variant in H3/V3s SoC
From: Icenowy Zheng @ 2017-01-03 15:25 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Kishon Vijay Abraham I, Bin Liu
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Icenowy Zheng
In-Reply-To: <20170103152534.20118-1-icenowy@aosc.xyz>
Allwinner H3/V3s features a variant of MUSB controller, which lacks one
endpoint.
Add support for it.
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
.../bindings/usb/allwinner,sun4i-a10-musb.txt | 4 +--
drivers/usb/musb/sunxi.c | 35 ++++++++++++++++++++--
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
index 862cd7c79805..d9b42da016f3 100644
--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
@@ -2,8 +2,8 @@ Allwinner sun4i A10 musb DRC/OTG controller
-------------------------------------------
Required properties:
- - compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb"
- or "allwinner,sun8i-a33-musb"
+ - compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb",
+ "allwinner,sun8i-a33-musb" or "allwinner,sun8i-h3-musb"
- reg : mmio address range of the musb controller
- clocks : clock specifier for the musb controller ahb gate clock
- reset : reset specifier for the ahb reset (A31 and newer only)
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index d0be0eadd0d9..48ecb1580817 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -645,6 +645,20 @@ static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
};
+/* H3/V3s OTG supports only 4 endpoints */
+#define SUNXI_MUSB_MAX_EP_NUM_H3 5
+
+static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = {
+ MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
+};
+
static struct musb_hdrc_config sunxi_musb_hdrc_config = {
.fifo_cfg = sunxi_musb_mode_cfg,
.fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg),
@@ -656,6 +670,18 @@ static struct musb_hdrc_config sunxi_musb_hdrc_config = {
.dma = 0,
};
+static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = {
+ .fifo_cfg = sunxi_musb_mode_cfg_h3,
+ .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3),
+ .multipoint = true,
+ .dyn_fifo = true,
+ .soft_con = true,
+ .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3,
+ .ram_bits = SUNXI_MUSB_RAM_BITS,
+ .dma = 0,
+};
+
+
static int sunxi_musb_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data pdata;
@@ -698,7 +724,10 @@ static int sunxi_musb_probe(struct platform_device *pdev)
return -EINVAL;
}
pdata.platform_ops = &sunxi_musb_ops;
- pdata.config = &sunxi_musb_hdrc_config;
+ if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb"))
+ pdata.config = &sunxi_musb_hdrc_config;
+ else
+ pdata.config = &sunxi_musb_hdrc_config_h3;
glue->dev = &pdev->dev;
INIT_WORK(&glue->work, sunxi_musb_work);
@@ -710,7 +739,8 @@ static int sunxi_musb_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
- if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb")) {
+ if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
+ of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) {
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
}
@@ -804,6 +834,7 @@ static const struct of_device_id sunxi_musb_match[] = {
{ .compatible = "allwinner,sun4i-a10-musb", },
{ .compatible = "allwinner,sun6i-a31-musb", },
{ .compatible = "allwinner,sun8i-a33-musb", },
+ { .compatible = "allwinner,sun8i-h3-musb", },
{}
};
MODULE_DEVICE_TABLE(of, sunxi_musb_match);
--
2.11.0
^ permalink raw reply related
* [PATCH 3/4] ARM: dts: sunxi: add usb_otg and usbphy node for V3s SoC
From: Icenowy Zheng @ 2017-01-03 15:25 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Kishon Vijay Abraham I, Bin Liu
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Icenowy Zheng
In-Reply-To: <20170103152534.20118-1-icenowy@aosc.xyz>
V3s SoC features a USB PHY controller and a MUSB OTG controller.
Add device nodes for them.
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
arch/arm/boot/dts/sun8i-v3s.dtsi | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 084da7474afb..ebefc0fefef2 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -153,6 +153,33 @@
#size-cells = <0>;
};
+ usb_otg: usb@01c19000 {
+ compatible = "allwinner,sun8i-h3-musb";
+ reg = <0x01c19000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ status = "disabled";
+ };
+
+ usbphy: phy@01c19400 {
+ compatible = "allwinner,sun8i-v3s-usb-phy";
+ reg = <0x01c19400 0x2c>,
+ <0x01c1a800 0x4>;
+ reg-names = "phy_ctrl",
+ "pmu0";
+ clocks = <&ccu CLK_USB_PHY0>;
+ clock-names = "usb0_phy";
+ resets = <&ccu RST_USB_PHY0>;
+ reset-names = "usb0_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
ccu: clock@01c20000 {
compatible = "allwinner,sun8i-v3s-ccu";
reg = <0x01c20000 0x400>;
--
2.11.0
^ permalink raw reply related
* [PATCH 4/4] ARM: dts: sun8i: add OTG function to Lichee Pi Zero
From: Icenowy Zheng @ 2017-01-03 15:25 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Kishon Vijay Abraham I, Bin Liu
Cc: devicetree, linux-usb, linux-kernel, linux-arm-kernel,
Icenowy Zheng
In-Reply-To: <20170103152534.20118-1-icenowy@aosc.xyz>
Lichee Pi Zero features a USB OTG port.
Add support for it.
Note: in order to use the Host mode, the board must be powered via the
+5V and GND pins.
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 0099affc6ce3..3d9168cbaeca 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -71,3 +71,13 @@
pinctrl-names = "default";
status = "okay";
};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpio = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
--
2.11.0
^ permalink raw reply related
* Re: [RFC PATCH v2 1/4] devicetree: hwmon: Add bindings for ADC128D818
From: Rob Herring @ 2017-01-03 15:28 UTC (permalink / raw)
To: Alexander Koch
Cc: linux-kernel, linux-hwmon, devicetree, Mark Rutland, Jean Delvare,
Guenter Roeck, Jiri Kosina
In-Reply-To: <20161223221205.8825-2-mail@alexanderkoch.net>
On Fri, Dec 23, 2016 at 11:12:02PM +0100, Alexander Koch wrote:
> Add bindings documentation for the ADC128D818 driver, featuring default I2C
> properties along with the optional 'mode' property for chip operation mode
> selection (see datasheet, sec. 8.4.1).
>
> Signed-off-by: Alexander Koch <mail@alexanderkoch.net>
> ---
> .../devicetree/bindings/hwmon/adc128d818.txt | 39 ++++++++++++++++++++++
> 1 file changed, 39 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/hwmon/adc128d818.txt
>
> diff --git a/Documentation/devicetree/bindings/hwmon/adc128d818.txt b/Documentation/devicetree/bindings/hwmon/adc128d818.txt
> new file mode 100644
> index 000000000000..5e14aa36a696
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/adc128d818.txt
> @@ -0,0 +1,39 @@
> +TI ADC128D818 ADC System Monitor With Temperature Sensor
> +--------------------------------------------------------
> +
> +Operation modes:
> +
> + - Mode 0: 7 single-ended voltage readings (IN0-IN6),
> + 1 temperature reading (internal)
> + - Mode 1: 8 single-ended voltage readings (IN0-IN7),
> + no temperature
> + - Mode 2: 4 pseudo-differential voltage readings
> + (IN0-IN1, IN3-IN2, IN4-IN5, IN7-IN6),
> + 1 temperature reading (internal)
> + - Mode 3: 4 single-ended voltage readings (IN0-IN3),
> + 2 pseudo-differential voltage readings
> + (IN4-IN5, IN7-IN6),
> + 1 temperature reading (internal)
> +
> +If no operation mode is configured via device tree, the driver defaults
> +to Mode 0.
> +
> +
> +Required node properties:
> +
> + - compatible: must be set to "ti,adc128d818"
> + - reg: I2C address of the device
> +
> +Optional node properties:
> +
> + - mode: Operation mode (see above).
Needs a vendor prefix.
> +
> +
> +Example (operation mode 2):
> +
> + adc128d818@1d {
> + compatible = "ti,adc128d818";
> + reg = <0x1d>;
> + mode = /bits/ 8 <2>;
Need to specify above this is an 8-bit value. Or just drop the size
here as there's little gain to use a byte here.
> + };
> +
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: exynos: make tm2 and tm2e independent from each other
From: Chanwoo Choi @ 2017-01-03 15:29 UTC (permalink / raw)
To: Andi Shyti
Cc: Mark Rutland, devicetree, linux-samsung-soc, Kukjin Kim,
Chanwoo Choi, Catalin Marinas, Jaechul Lee, Dmitry Torokhov,
Will Deacon, linux-kernel, Andi Shyti, Javier Martinez Canillas,
Rob Herring, Krzysztof Kozlowski, linux-input, galaxyra,
beomho.seo, linux-arm-kernel
In-Reply-To: <20170103144056.4ft2ohmhgmezeney@jack.zhora.eu>
Hi Andi,
2017-01-03 23:40 GMT+09:00 Andi Shyti <andi@etezian.org>:
> Hi,
>
>> FWIW, I also agree with Chanwoo that the difference is too small to
>> need a common .dtsi file.
>
> in principle I don't like "switching on and off" properties by
> overwriting them with "status = disable", unless it's really
> necessary (and this case is not). Even for small differences. It
> makes the DTS harder to read and duplicates nodes with different
> values throughout the DTS include chain.
>
> In my opinion this approach should be discouraged.
>
> Besides, there are other overwritten differences in tm2e.dts that
> I think should be separated as well. The "common" file approach is
> widely used in arm/boot/dts/exynos* files.
>
> The "status = disable" looks to me more like a temporary hack
> rather than a permanent solution.
>
> In any case, still up to you :)
>
> Andi
I think that "status=disabled" of hsi2c_9 is not hack. The overwrite
is possible for Device-tree. But, there is just difference how to
support them with some method.
Except for touchkey, all peripheral device are same on both tm2 and
tm2e. There are only small difference for a few property value.
To understand the difference between tm2 and tm2e, I made the patch
(it is not complete version). If we implement the following patch, we
support both tm2 and tm2e. So, I think that it is not complex to
understand the h/w difference between tm2 and tm2e.
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
index 1db4e7f..09b6935 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
@@ -18,6 +18,17 @@
compatible = "samsung,tm2e", "samsung,exynos5433";
};
+&display_timings {
+ clock-frequency = <16523724>;
+ hactive = <1600>;
+};
+
+&hsi2c_9 {
+ /* TM2E don't use the separate touchkey device. Instead, touchscreen
+ * device support the touchkey device.*/
+ status = "disabled";
+};
+
&ldo23_reg {
regulator-name = "CAM_SEN_CORE_1.025V_AP";
regulator-max-microvolt = <1050000>;
@@ -39,3 +50,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
+
+&touchscreen {
+ x-size = "1599";
+};
--
Best Regards,
Chanwoo Choi
^ permalink raw reply related
* Re: [PATCH] adc: add adc driver for Hisilicon BVT SOCs
From: Rob Herring @ 2017-01-03 15:30 UTC (permalink / raw)
To: Allen Liu
Cc: jic23, knaack.h, lars, pmeerw, mark.rutland, akinobu.mita,
ludovic.desroches, krzk, vilhelm.gray, ksenija.stanojevic,
zhiyong.tao, daniel.baluta, leonard.crestez, ray.jui,
raveendra.padasalagi, mranostay, amsfield22, linux-iio,
devicetree, linux-kernel, xuejiancheng, kevin.lixu
In-Reply-To: <1482544497-136656-1-git-send-email-liurenzhong@hisilicon.com>
On Sat, Dec 24, 2016 at 09:54:57AM +0800, Allen Liu wrote:
> Add ADC driver for the ADC controller found on HiSilicon BVT SOCs, like Hi3516CV300, etc.
> The ADC controller is primarily in charge of detecting voltage.
>
> Reviewed-by: Jiancheng Xue <xuejiancheng@hisilicon.com>
> Signed-off-by: Allen Liu <liurenzhong@hisilicon.com>
> ---
> .../devicetree/bindings/iio/adc/hibvt-lsadc.txt | 26 ++
> drivers/iio/adc/Kconfig | 10 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/hibvt_lsadc.c | 344 +++++++++++++++++++++
> 4 files changed, 381 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
> create mode 100644 drivers/iio/adc/hibvt_lsadc.c
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt b/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
> new file mode 100644
> index 0000000..63de46e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
> @@ -0,0 +1,26 @@
> +Hisilicon BVT Low Speed (LS) A/D Converter bindings
> +
> +Required properties:
> +- compatible: should be "hisilicon,<name>-lsadc"
> + - "hisilicon,hibvt-lsadc": for hi3516cv300
Use the SoC name in the compatible string.
> +
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +- interrupts: The interrupt number to the cpu. The interrupt specifier format
> + depends on the interrupt controller.
> +- #io-channel-cells: Should be 1, see ../iio-bindings.txt
> +
> +Optional properties:
> +- resets: Must contain an entry for each entry in reset-names if need support
> + this option. See ../reset/reset.txt for details.
> +- reset-names: Must include the name "saradc-apb".
> +
> +Example:
> + lsadc: hibvt-lsadc@120e0000 {
Just "adc@..."
> + compatible = "hisilicon,hibvt-lsadc";
> + reg = <0x120e0000 0x1000>;
> + interrupts = <19>;
> + resets = <&crg 0x7c 3>;
> + reset-names = "lsadc-crg";
> + status = "disabled";
> + };
^ permalink raw reply
* Re: [PATCH 2/5] mfd: twl: remove useless header
From: Lee Jones @ 2017-01-03 15:30 UTC (permalink / raw)
To: Nicolae Rosia
Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel
In-Reply-To: <20161126181326.14951-3-Nicolae_Rosia@mentor.com>
On Sat, 26 Nov 2016, Nicolae Rosia wrote:
> This header has one user, twl-core.c .
> Remove it before it gets more users.
The header is not useless. It prevents us from having to place
external prototypes into C files.
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
> drivers/mfd/twl-core.c | 8 ++++++--
> drivers/mfd/twl-core.h | 10 ----------
> drivers/mfd/twl4030-irq.c | 2 --
> drivers/mfd/twl6030-irq.c | 2 --
> 4 files changed, 6 insertions(+), 16 deletions(-)
> delete mode 100644 drivers/mfd/twl-core.h
>
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 48b0668..e16084e 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -52,8 +52,6 @@
> /* Register descriptions for audio */
> #include <linux/mfd/twl4030-audio.h>
>
> -#include "twl-core.h"
> -
> /*
> * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
> * Management and System Companion Device" chips originally designed for
> @@ -150,6 +148,12 @@
>
> /*----------------------------------------------------------------------*/
>
> +int twl6030_init_irq(struct device *dev, int irq_num);
> +int twl6030_exit_irq(void);
> +int twl4030_init_irq(struct device *dev, int irq_num);
> +int twl4030_exit_irq(void);
> +int twl4030_init_chip_irq(const char *chip);
> +
> /* Structure for each TWL4030/TWL6030 Slave */
> struct twl_client {
> struct i2c_client *client;
> diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
> deleted file mode 100644
> index 6ff99dc..0000000
> --- a/drivers/mfd/twl-core.h
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -#ifndef __TWL_CORE_H__
> -#define __TWL_CORE_H__
> -
> -extern int twl6030_init_irq(struct device *dev, int irq_num);
> -extern int twl6030_exit_irq(void);
> -extern int twl4030_init_irq(struct device *dev, int irq_num);
> -extern int twl4030_exit_irq(void);
> -extern int twl4030_init_chip_irq(const char *chip);
> -
> -#endif /* __TWL_CORE_H__ */
> diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
> index b46c0cf..000c231 100644
> --- a/drivers/mfd/twl4030-irq.c
> +++ b/drivers/mfd/twl4030-irq.c
> @@ -35,8 +35,6 @@
> #include <linux/irqdomain.h>
> #include <linux/i2c/twl.h>
>
> -#include "twl-core.h"
> -
> /*
> * TWL4030 IRQ handling has two stages in hardware, and thus in software.
> * The Primary Interrupt Handler (PIH) stage exposes status bits saying
> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
> index 5357450..63eca76 100644
> --- a/drivers/mfd/twl6030-irq.c
> +++ b/drivers/mfd/twl6030-irq.c
> @@ -42,8 +42,6 @@
> #include <linux/irqdomain.h>
> #include <linux/of_device.h>
>
> -#include "twl-core.h"
> -
> /*
> * TWL6030 (unlike its predecessors, which had two level interrupt handling)
> * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
From: Marc Kleine-Budde @ 2017-01-03 15:31 UTC (permalink / raw)
To: Akshay Bhat, wg, robh+dt
Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
Akshay Bhat
In-Reply-To: <1479146144-29143-2-git-send-email-akshay.bhat@timesys.com>
[-- Attachment #1.1: Type: text/plain, Size: 34565 bytes --]
On 11/14/2016 06:55 PM, Akshay Bhat wrote:
> This patch adds support for the Holt HI-311x CAN controller. The HI311x
> CAN controller is capable of transmitting and receiving standard data
> frames, extended data frames and remote frames. The HI311x interfaces
> with the host over SPI.
Don't use uint8_t and similar in the kernel, please use u8 instead.
>
> Datasheet: www.holtic.com/documents/371-hi-3110_v-rev-jpdf.do
>
> Signed-off-by: Akshay Bhat <nodeax@gmail.com>
> ---
> drivers/net/can/spi/Kconfig | 6 +
> drivers/net/can/spi/Makefile | 1 +
> drivers/net/can/spi/hi311x.c | 1071 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1078 insertions(+)
> create mode 100644 drivers/net/can/spi/hi311x.c
>
> diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig
> index 148cae5..9eb1bb1 100644
> --- a/drivers/net/can/spi/Kconfig
> +++ b/drivers/net/can/spi/Kconfig
> @@ -7,4 +7,10 @@ config CAN_MCP251X
> ---help---
> Driver for the Microchip MCP251x SPI CAN controllers.
>
> +config CAN_HI311X
> + tristate "Holt HI311x SPI CAN controllers"
> + depends on CAN_DEV && SPI && HAS_DMA
> + ---help---
> + Driver for the Holt HI311x SPI CAN controllers.
> +
> endmenu
> diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
> index 0e86040..eac7c3a 100644
> --- a/drivers/net/can/spi/Makefile
> +++ b/drivers/net/can/spi/Makefile
> @@ -4,3 +4,4 @@
>
>
> obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
> +obj-$(CONFIG_CAN_HI311X) += hi311x.o
Please keep sorted alphabetically. Same for the Kconfig.
> diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
> new file mode 100644
> index 0000000..1020166
> --- /dev/null
> +++ b/drivers/net/can/spi/hi311x.c
> @@ -0,0 +1,1071 @@
> +/* CAN bus driver for Holt HI3110 CAN Controller with SPI Interface
> + *
> + * Based on Microchip 251x CAN Controller (mcp251x) Linux kernel driver
You might want to add the copyright of the mcp authors.
> + *
> + * Copyright(C) Timesys Corporation 2016
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/can/core.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/led.h>
> +#include <linux/clk.h>
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/freezer.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/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <linux/spi/spi.h>
> +#include <linux/uaccess.h>
> +
Please use just a single space after each macro.
VVVVVVVV
> +#define HI3110_MASTER_RESET 0x56
> +#define HI3110_READ_CTRL0 0xD2
> +#define HI3110_READ_CTRL1 0xD4
> +#define HI3110_READ_STATF 0xE2
> +#define HI3110_WRITE_CTRL0 0x14
> +#define HI3110_WRITE_CTRL1 0x16
> +#define HI3110_WRITE_INTE 0x1C
> +#define HI3110_WRITE_BTR0 0x18
> +#define HI3110_WRITE_BTR1 0x1A
> +#define HI3110_READ_BTR0 0xD6
> +#define HI3110_READ_BTR1 0xD8
> +#define HI3110_READ_INTF 0xDE
> +#define HI3110_READ_ERR 0xDC
> +#define HI3110_READ_FIFO_WOTIME 0x48
> +#define HI3110_WRITE_FIFO 0x12
> +#define HI3110_READ_MESSTAT 0xDA
> +#define HI3110_READ_TEC 0xEC
> +
> +#define HI3110_CTRL0_MODE_MASK (7 << 5)
> +#define HI3110_CTRL0_NORMAL_MODE (0 << 5)
> +#define HI3110_CTRL0_LOOPBACK_MODE (1 << 5)
> +#define HI3110_CTRL0_MONITOR_MODE (2 << 5)
> +#define HI3110_CTRL0_SLEEP_MODE (3 << 5)
> +#define HI3110_CTRL0_INIT_MODE (4 << 5)
> +
> +#define HI3110_CTRL1_TXEN BIT(7)
> +
> +#define HI3110_INT_RXTMP BIT(7)
> +#define HI3110_INT_RXFIFO BIT(6)
> +#define HI3110_INT_TXCPLT BIT(5)
> +#define HI3110_INT_BUSERR BIT(4)
> +#define HI3110_INT_MCHG BIT(3)
> +#define HI3110_INT_WAKEUP BIT(2)
> +#define HI3110_INT_F1MESS BIT(1)
> +#define HI3110_INT_F0MESS BIT(0)
> +
> +#define HI3110_ERR_BUSOFF BIT(7)
> +#define HI3110_ERR_TXERRP BIT(6)
> +#define HI3110_ERR_RXERRP BIT(5)
> +#define HI3110_ERR_BITERR BIT(4)
> +#define HI3110_ERR_FRMERR BIT(3)
> +#define HI3110_ERR_CRCERR BIT(2)
> +#define HI3110_ERR_ACKERR BIT(1)
> +#define HI3110_ERR_STUFERR BIT(0)
> +#define HI3110_ERR_PROTOCOL_MASK (0x1F)
> +
> +#define HI3110_STAT_RXFMTY BIT(1)
> +
> +#define HI3110_BTR0_SJW_SHIFT 6
> +#define HI3110_BTR0_BRP_SHIFT 0
> +
> +#define HI3110_BTR1_SAMP_3PERBIT (1 << 7)
> +#define HI3110_BTR1_SAMP_1PERBIT (0 << 7)
> +#define HI3110_BTR1_TSEG2_SHIFT 4
> +#define HI3110_BTR1_TSEG1_SHIFT 0
> +
> +#define HI3110_FIFO_WOTIME_TAG_OFF 0
> +#define HI3110_FIFO_WOTIME_ID_OFF 1
> +#define HI3110_FIFO_WOTIME_DLC_OFF 5
> +#define HI3110_FIFO_WOTIME_DAT_OFF 6
> +
> +#define HI3110_FIFO_WOTIME_TAG_IDE BIT(7)
> +#define HI3110_FIFO_WOTIME_ID_RTR BIT(0)
> +
> +#define HI3110_FIFO_TAG_OFF 0
> +#define HI3110_FIFO_ID_OFF 1
> +#define HI3110_FIFO_STD_DLC_OFF 3
> +#define HI3110_FIFO_STD_DATA_OFF 4
> +#define HI3110_FIFO_EXT_DLC_OFF 5
> +#define HI3110_FIFO_EXT_DATA_OFF 6
> +
Please add the already used HI3110_ namespace to these defines, too.
> +#define CAN_FRAME_MAX_DATA_LEN 8
> +#define RX_BUF_LEN 15
> +#define TX_STD_BUF_LEN 12
> +#define TX_EXT_BUF_LEN 14
> +#define CAN_FRAME_MAX_BITS 128
> +
> +#define TX_ECHO_SKB_MAX 1
> +
> +#define HI3110_OST_DELAY_MS (10)
> +
> +#define DEVICE_NAME "hi3110"
> +
> +static int hi3110_enable_dma = 1; /* Enable SPI DMA. Default: 1 (On) */
> +module_param(hi3110_enable_dma, int, 0444);
> +MODULE_PARM_DESC(hi3110_enable_dma, "Enable SPI DMA. Default: 1 (On)");
> +
> +static const struct can_bittiming_const hi3110_bittiming_const = {
> + .name = DEVICE_NAME,
> + .tseg1_min = 2,
> + .tseg1_max = 16,
> + .tseg2_min = 2,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 64,
> + .brp_inc = 1,
> +};
> +
> +enum hi3110_model {
> + CAN_HI3110_HI3110 = 0x3110,
^^^^^^^
single space here, too
> +};
> +
> +struct hi3110_priv {
> + struct can_priv can;
^^^^
here too
> + struct net_device *net;
> + struct spi_device *spi;
> + enum hi3110_model model;
> +
> + struct mutex hi3110_lock; /* SPI device lock */
> +
> + u8 *spi_tx_buf;
> + u8 *spi_rx_buf;
> + dma_addr_t spi_tx_dma;
> + dma_addr_t spi_rx_dma;
> +
> + struct sk_buff *tx_skb;
> + int tx_len;
> +
> + struct workqueue_struct *wq;
> + struct work_struct tx_work;
> + struct work_struct restart_work;
> +
> + int force_quit;
> + int after_suspend;
Please add the already used HI3110_ namespace to these defines, too.
> +#define AFTER_SUSPEND_UP 1
> +#define AFTER_SUSPEND_DOWN 2
> +#define AFTER_SUSPEND_POWER 4
> +#define AFTER_SUSPEND_RESTART 8
> + int restart_tx;
> + struct regulator *power;
> + struct regulator *transceiver;
> + struct clk *clk;
> +};
> +
> +static void hi3110_clean(struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> +
> + if (priv->tx_skb || priv->tx_len)
> + net->stats.tx_errors++;
> + if (priv->tx_skb)
> + dev_kfree_skb(priv->tx_skb);
> + if (priv->tx_len)
> + can_free_echo_skb(priv->net, 0);
> + priv->tx_skb = NULL;
> + priv->tx_len = 0;
> +}
> +
> +/* Note about handling of error return of hi3110_spi_trans: accessing
> + * registers via SPI is not really different conceptually than using
> + * normal I/O assembler instructions, although it's much more
> + * complicated from a practical POV. So it's not advisable to always
> + * check the return value of this function. Imagine that every
> + * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
> + * error();", it would be a great mess (well there are some situation
> + * when exception handling C++ like could be useful after all). So we
> + * just check that transfers are OK at the beginning of our
> + * conversation with the chip and to avoid doing really nasty things
> + * (like injecting bogus packets in the network stack).
> + */
> +static int hi3110_spi_trans(struct spi_device *spi, int len)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + struct spi_transfer t = {
> + .tx_buf = priv->spi_tx_buf,
> + .rx_buf = priv->spi_rx_buf,
> + .len = len,
> + .cs_change = 0,
> + };
> + struct spi_message m;
> + int ret;
> +
> + spi_message_init(&m);
> +
> + if (hi3110_enable_dma) {
> + t.tx_dma = priv->spi_tx_dma;
> + t.rx_dma = priv->spi_rx_dma;
> + m.is_dma_mapped = 1;
> + }
> +
> + spi_message_add_tail(&t, &m);
> +
> + ret = spi_sync(spi, &m);
> +
> + if (ret)
> + dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret);
> + return ret;
> +}
> +
> +static u8 hi3110_cmd(struct spi_device *spi, uint8_t command)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> +
> + priv->spi_tx_buf[0] = command;
> + dev_dbg(&spi->dev, "hi3110_cmd: %02X\n", command);
> +
> + return hi3110_spi_trans(spi, 1);
> +}
> +
> +static u8 hi3110_read(struct spi_device *spi, uint8_t command)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + u8 val = 0;
> +
> + priv->spi_tx_buf[0] = command;
> + hi3110_spi_trans(spi, 2);
> + val = priv->spi_rx_buf[1];
> + dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
> +
> + return val;
> +}
> +
> +static void hi3110_write(struct spi_device *spi, u8 reg, uint8_t val)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> +
> + priv->spi_tx_buf[0] = reg;
> + priv->spi_tx_buf[1] = val;
> + dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
> +
> + hi3110_spi_trans(spi, 2);
> +}
> +
> +static void hi3110_hw_tx_frame(struct spi_device *spi, u8 *buf, int len)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> +
> + priv->spi_tx_buf[0] = HI3110_WRITE_FIFO;
> + memcpy(priv->spi_tx_buf + 1, buf, len);
> + hi3110_spi_trans(spi, len + 1);
> +}
> +
> +static void hi3110_hw_tx(struct spi_device *spi, struct can_frame *frame)
> +{
> + u8 buf[TX_EXT_BUF_LEN];
> +
> + buf[HI3110_FIFO_TAG_OFF] = 0;
> +
> + if (frame->can_id & CAN_EFF_FLAG) {
> + /* Extended frame */
> + buf[HI3110_FIFO_ID_OFF] = (frame->can_id & CAN_EFF_MASK) >> 21;
> + buf[HI3110_FIFO_ID_OFF + 1] =
> + ((((frame->can_id & CAN_EFF_MASK) >> 18) & 0x07) << 5) |
Why do you first shift down then up?
> + 0x18 | /* Recessive SRR and IDE */
Can you add a define for the 0x18?
> + (((frame->can_id & CAN_EFF_MASK) >> 15) & 0x07);
> + buf[HI3110_FIFO_ID_OFF + 2] =
> + (frame->can_id & CAN_EFF_MASK) >> 7;
> + buf[HI3110_FIFO_ID_OFF + 3] =
> + ((frame->can_id & CAN_EFF_MASK) << 1) |
> + ((frame->can_id & CAN_RTR_FLAG) ? 1 : 0);
> +
> + buf[HI3110_FIFO_EXT_DLC_OFF] = frame->can_dlc;
> +
> + memcpy(buf + HI3110_FIFO_EXT_DATA_OFF,
> + frame->data, frame->can_dlc);
> +
> + hi3110_hw_tx_frame(spi, buf, TX_EXT_BUF_LEN -
> + (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
> + } else {
> + /* Standard frame */
> + buf[HI3110_FIFO_ID_OFF] = (frame->can_id & CAN_SFF_MASK) >> 3;
> + buf[HI3110_FIFO_ID_OFF + 1] =
> + ((frame->can_id & CAN_SFF_MASK) << 5) |
> + ((frame->can_id & CAN_RTR_FLAG) ? (1 << 4) : 0);
> +
> + buf[HI3110_FIFO_STD_DLC_OFF] = frame->can_dlc;
> +
> + memcpy(buf + HI3110_FIFO_STD_DATA_OFF,
> + frame->data, frame->can_dlc);
> +
> + hi3110_hw_tx_frame(spi, buf, TX_STD_BUF_LEN -
> + (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
> + }
> +}
> +
> +static void hi3110_hw_rx_frame(struct spi_device *spi, u8 *buf)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> +
> + priv->spi_tx_buf[0] = HI3110_READ_FIFO_WOTIME;
> + hi3110_spi_trans(spi, RX_BUF_LEN);
> + memcpy(buf, priv->spi_rx_buf + 1, RX_BUF_LEN - 1);
> +}
> +
> +static void hi3110_hw_rx(struct spi_device *spi)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + struct sk_buff *skb;
> + struct can_frame *frame;
> + u8 buf[RX_BUF_LEN - 1];
> +
> + skb = alloc_can_skb(priv->net, &frame);
> + if (!skb) {
> + dev_err(&spi->dev, "cannot allocate RX skb\n");
> + priv->net->stats.rx_dropped++;
> + return;
> + }
> +
> + hi3110_hw_rx_frame(spi, buf);
> + if (buf[HI3110_FIFO_WOTIME_TAG_OFF] & HI3110_FIFO_WOTIME_TAG_IDE) {
> + /* IDE is recessive (1), indicating extended 29-bit frame */
> + frame->can_id = CAN_EFF_FLAG;
> + frame->can_id |=
> + (buf[HI3110_FIFO_WOTIME_ID_OFF] << 21) |
> + (((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5) << 18) |
> + ((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0x07) << 15) |
> + (buf[HI3110_FIFO_WOTIME_ID_OFF + 2] << 7) |
> + (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] >> 1);
> + } else {
> + /* IDE is dominant (0), frame indicating standard 11-bit */
> + frame->can_id =
> + (buf[HI3110_FIFO_WOTIME_ID_OFF] << 3) |
> + ((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5);
> + }
> +
> + if (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] & HI3110_FIFO_WOTIME_ID_RTR) {
> + /* RTR is recessive (1), indicating remote request frame */
> + frame->can_id |= CAN_RTR_FLAG;
> + }
> +
> + /* Data length */
> + frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] & 0x0F);
> + memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF, frame->can_dlc);
> +
> + priv->net->stats.rx_packets++;
> + priv->net->stats.rx_bytes += frame->can_dlc;
> +
> + can_led_event(priv->net, CAN_LED_EVENT_RX);
> +
> + netif_rx_ni(skb);
> +}
> +
> +static void hi3110_hw_sleep(struct spi_device *spi)
> +{
> + hi3110_write(spi, HI3110_WRITE_CTRL0, HI3110_CTRL0_SLEEP_MODE);
> +}
> +
> +static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
> + struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> + struct spi_device *spi = priv->spi;
> +
> + if (priv->tx_skb || priv->tx_len) {
> + dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
> + return NETDEV_TX_BUSY;
> + }
> +
> + if (can_dropped_invalid_skb(net, skb))
> + return NETDEV_TX_OK;
> +
> + netif_stop_queue(net);
> + priv->tx_skb = skb;
> + queue_work(priv->wq, &priv->tx_work);
> +
> + return NETDEV_TX_OK;
> +}
> +
> +static int hi3110_do_set_mode(struct net_device *net, enum can_mode mode)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> +
> + switch (mode) {
> + case CAN_MODE_START:
> + hi3110_clean(net);
> + /* We have to delay work since SPI I/O may sleep */
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> + priv->restart_tx = 1;
> + if (priv->can.restart_ms == 0)
> + priv->after_suspend = AFTER_SUSPEND_RESTART;
> + queue_work(priv->wq, &priv->restart_work);
> + break;
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +static int hi3110_set_normal_mode(struct spi_device *spi)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + u8 reg;
> +
> + hi3110_write(spi, HI3110_WRITE_INTE, HI3110_INT_BUSERR |
> + HI3110_INT_RXFIFO | HI3110_INT_TXCPLT);
> +
> + /* Enable TX */
> + hi3110_write(spi, HI3110_WRITE_CTRL1, HI3110_CTRL1_TXEN);
> +
> + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
> + /* Put device into loopback mode */
> + hi3110_write(spi, HI3110_WRITE_CTRL0,
> + HI3110_CTRL0_LOOPBACK_MODE);
> + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
> + /* Put device into listen-only mode */
> + hi3110_write(spi, HI3110_WRITE_CTRL0,
> + HI3110_CTRL0_MONITOR_MODE);
> + } else {
> + /* Put device into normal mode */
> + hi3110_write(spi, HI3110_WRITE_CTRL0,
> + HI3110_CTRL0_NORMAL_MODE);
> +
> + /* Wait for the device to enter normal mode */
> + mdelay(HI3110_OST_DELAY_MS);
> + reg = hi3110_read(spi, HI3110_READ_CTRL0);
> + if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
> + return -EBUSY;
> + }
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> + return 0;
> +}
> +
> +static int hi3110_do_set_bittiming(struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> + struct can_bittiming *bt = &priv->can.bittiming;
> + struct spi_device *spi = priv->spi;
> +
> + hi3110_write(spi, HI3110_WRITE_BTR0,
> + ((bt->sjw - 1) << HI3110_BTR0_SJW_SHIFT) |
> + ((bt->brp - 1) << HI3110_BTR0_BRP_SHIFT));
> +
> + hi3110_write(spi, HI3110_WRITE_BTR1,
> + (priv->can.ctrlmode &
> + CAN_CTRLMODE_3_SAMPLES ?
> + HI3110_BTR1_SAMP_3PERBIT : HI3110_BTR1_SAMP_1PERBIT) |
> + ((bt->phase_seg1 + bt->prop_seg - 1)
> + << HI3110_BTR1_TSEG1_SHIFT) |
> + ((bt->phase_seg2 - 1) << HI3110_BTR1_TSEG2_SHIFT));
> +
> + dev_dbg(&spi->dev, "BT: 0x%02x 0x%02x\n",
> + hi3110_read(spi, HI3110_READ_BTR0),
> + hi3110_read(spi, HI3110_READ_BTR1));
> +
> + return 0;
> +}
> +
> +static int hi3110_setup(struct net_device *net, struct hi3110_priv *priv,
> + struct spi_device *spi)
onlt the first parameter is used.
> +{
> + hi3110_do_set_bittiming(net);
> + return 0;
> +}
> +
> +static int hi3110_hw_reset(struct spi_device *spi)
> +{
> + u8 reg;
> + int ret;
> +
> + /* Wait for oscillator startup timer after power up */
> + mdelay(HI3110_OST_DELAY_MS);
> +
> + ret = hi3110_cmd(spi, HI3110_MASTER_RESET);
> + if (ret)
> + return ret;
> +
> + /* Wait for oscillator startup timer after reset */
> + mdelay(HI3110_OST_DELAY_MS);
> +
> + reg = hi3110_read(spi, HI3110_READ_CTRL0);
> + if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_INIT_MODE)
> + return -ENODEV;
> +
> + /* As per the datasheet it appears the error flags are
> + * not cleared on reset. Explicitly clear them by performing a read
> + */
> + hi3110_read(spi, HI3110_READ_ERR);
> +
> + return 0;
> +}
> +
> +static int hi3110_hw_probe(struct spi_device *spi)
> +{
> + u8 statf;
> +
> + hi3110_hw_reset(spi);
> +
> + /* Confirm correct operation by checking against reset values
> + * in datasheet
> + */
> + statf = hi3110_read(spi, HI3110_READ_STATF);
> +
> + dev_dbg(&spi->dev, "statf: %02X\n", statf);
> +
> + if (statf != 0x82)
> + return -ENODEV;
> +
> + return 0;
> +}
> +
> +static int hi3110_power_enable(struct regulator *reg, int enable)
> +{
> + if (IS_ERR_OR_NULL(reg))
> + return 0;
> +
> + if (enable)
> + return regulator_enable(reg);
> + else
> + return regulator_disable(reg);
> +}
> +
> +static void hi3110_open_clean(struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> + struct spi_device *spi = priv->spi;
> +
> + free_irq(spi->irq, priv);
> + hi3110_hw_sleep(spi);
> + hi3110_power_enable(priv->transceiver, 0);
> + close_candev(net);
> +}
> +
> +static int hi3110_stop(struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> + struct spi_device *spi = priv->spi;
> +
> + close_candev(net);
> +
> + priv->force_quit = 1;
> + free_irq(spi->irq, priv);
> + destroy_workqueue(priv->wq);
> + priv->wq = NULL;
> +
> + mutex_lock(&priv->hi3110_lock);
> +
> + /* Disable transmit, interrupts and clear flags */
> + hi3110_write(spi, HI3110_WRITE_CTRL1, 0x0);
> + hi3110_write(spi, HI3110_WRITE_INTE, 0x0);
> + hi3110_read(spi, HI3110_READ_INTF);
> +
> + hi3110_clean(net);
> +
> + hi3110_hw_sleep(spi);
> +
> + hi3110_power_enable(priv->transceiver, 0);
> +
> + priv->can.state = CAN_STATE_STOPPED;
> +
> + mutex_unlock(&priv->hi3110_lock);
> +
> + can_led_event(net, CAN_LED_EVENT_STOP);
> +
> + return 0;
> +}
> +
> +static void hi3110_error_skb(struct net_device *net, int can_id,
> + int data1, int data2)
> +{
> + struct sk_buff *skb;
> + struct can_frame *frame;
> +
> + skb = alloc_can_err_skb(net, &frame);
> + if (skb) {
> + frame->can_id |= can_id;
> + frame->data[1] = data1;
> + frame->data[2] = data2;
> + netif_rx_ni(skb);
> + } else {
> + netdev_err(net, "cannot allocate error skb\n");
> + }
> +}
> +
> +static void hi3110_tx_work_handler(struct work_struct *ws)
> +{
> + struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
> + tx_work);
> + struct spi_device *spi = priv->spi;
> + struct net_device *net = priv->net;
> + struct can_frame *frame;
> +
> + mutex_lock(&priv->hi3110_lock);
> + if (priv->tx_skb) {
> + if (priv->can.state == CAN_STATE_BUS_OFF) {
> + hi3110_clean(net);
> + } else {
> + frame = (struct can_frame *)priv->tx_skb->data;
> +
> + if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
> + frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
this has already been checked
> + hi3110_hw_tx(spi, frame);
> + priv->tx_len = 1 + frame->can_dlc;
> + can_put_echo_skb(priv->tx_skb, net, 0);
> + priv->tx_skb = NULL;
> + }
> + }
> + mutex_unlock(&priv->hi3110_lock);
> +}
> +
> +static void hi3110_restart_work_handler(struct work_struct *ws)
> +{
> + struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
> + restart_work);
> + struct spi_device *spi = priv->spi;
> + struct net_device *net = priv->net;
> +
> + mutex_lock(&priv->hi3110_lock);
> + if (priv->after_suspend) {
> + hi3110_hw_reset(spi);
> + hi3110_setup(net, priv, spi);
> + if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
> + hi3110_set_normal_mode(spi);
> + } else if (priv->after_suspend & AFTER_SUSPEND_UP) {
> + netif_device_attach(net);
> + hi3110_clean(net);
> + hi3110_set_normal_mode(spi);
> + netif_wake_queue(net);
> + } else {
> + hi3110_hw_sleep(spi);
> + }
> + priv->after_suspend = 0;
> + priv->force_quit = 0;
> + }
> +
> + if (priv->restart_tx) {
> + priv->restart_tx = 0;
> + hi3110_clean(net);
> + netif_wake_queue(net);
> + hi3110_error_skb(net, CAN_ERR_RESTARTED, 0, 0);
> + }
> + mutex_unlock(&priv->hi3110_lock);
> +}
> +
> +static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
> +{
> + struct hi3110_priv *priv = dev_id;
> + struct spi_device *spi = priv->spi;
> + struct net_device *net = priv->net;
> +
> + mutex_lock(&priv->hi3110_lock);
> +
> + while (!priv->force_quit) {
> + enum can_state new_state;
> + u8 intf;
> + u8 eflag;
> + int can_id = 0, data1 = 0, data2 = 0;
> +
> + while (!(HI3110_STAT_RXFMTY &
> + hi3110_read(spi, HI3110_READ_STATF))) {
> + hi3110_hw_rx(spi);
> + };
> +
> + intf = hi3110_read(spi, HI3110_READ_INTF);
> + eflag = hi3110_read(spi, HI3110_READ_ERR);
does the hardware supports multiple reads with a single transfer? If so
make use of it, for performance reasons.
> + /* Update can state */
> + if (eflag & HI3110_ERR_BUSOFF) {
> + new_state = CAN_STATE_BUS_OFF;
> + can_id |= CAN_ERR_BUSOFF;
> + } else if (eflag & HI3110_ERR_TXERRP) {
> + new_state = CAN_STATE_ERROR_PASSIVE;
> + can_id |= CAN_ERR_CRTL;
> + data1 |= CAN_ERR_CRTL_TX_PASSIVE;
> + } else if (eflag & HI3110_ERR_RXERRP) {
> + new_state = CAN_STATE_ERROR_PASSIVE;
> + can_id |= CAN_ERR_CRTL;
> + data1 |= CAN_ERR_CRTL_RX_PASSIVE;
> + } else {
> + new_state = CAN_STATE_ERROR_ACTIVE;
> + }
> +
> + /* Check for protocol errors */
> + if (eflag & HI3110_ERR_PROTOCOL_MASK) {
> + can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> + priv->can.can_stats.bus_error++;
> + priv->net->stats.rx_errors++;
> + if (eflag & HI3110_ERR_BITERR)
> + data2 |= CAN_ERR_PROT_BIT;
> + else if (eflag & HI3110_ERR_FRMERR)
> + data2 |= CAN_ERR_PROT_FORM;
> + else if (eflag & HI3110_ERR_STUFERR)
> + data2 |= CAN_ERR_PROT_STUFF;
> + else
> + data2 |= CAN_ERR_PROT_UNSPEC;
> + }
> +
> + /* Update can state statistics */
> + switch (priv->can.state) {
> + case CAN_STATE_ERROR_ACTIVE:
> + if (new_state >= CAN_STATE_ERROR_WARNING &&
> + new_state <= CAN_STATE_BUS_OFF)
> + priv->can.can_stats.error_warning++;
> + /* fallthrough */
> + case CAN_STATE_ERROR_WARNING:
> + if (new_state >= CAN_STATE_ERROR_PASSIVE &&
> + new_state <= CAN_STATE_BUS_OFF)
> + priv->can.can_stats.error_passive++;
> + break;
> + default:
> + break;
> + }
> + priv->can.state = new_state;
> +
> + if (intf & HI3110_INT_BUSERR) {
> + /* Note: HI3110 Does report overflow errors */
> + hi3110_error_skb(net, can_id, data1, data2);
> + }
> +
> + if (priv->can.state == CAN_STATE_BUS_OFF) {
> + if (priv->can.restart_ms == 0) {
> + priv->force_quit = 1;
> + priv->can.can_stats.bus_off++;
> + can_bus_off(net);
> + hi3110_hw_sleep(spi);
> + break;
> + }
> + }
> +
> + if (intf == 0)
> + break;
> +
> + if (intf & HI3110_INT_TXCPLT) {
> + net->stats.tx_packets++;
> + net->stats.tx_bytes += priv->tx_len - 1;
> + can_led_event(net, CAN_LED_EVENT_TX);
> + if (priv->tx_len) {
> + can_get_echo_skb(net, 0);
> + priv->tx_len = 0;
> + }
> + netif_wake_queue(net);
> + }
> + }
> + mutex_unlock(&priv->hi3110_lock);
> + return IRQ_HANDLED;
> +}
> +
> +static int hi3110_open(struct net_device *net)
> +{
> + struct hi3110_priv *priv = netdev_priv(net);
> + struct spi_device *spi = priv->spi;
> + unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
> + int ret;
> +
> + ret = open_candev(net);
> + if (ret) {
> + dev_err(&spi->dev, "unable to set initial baudrate!\n");
> + return ret;
> + }
> +
> + mutex_lock(&priv->hi3110_lock);
> + hi3110_power_enable(priv->transceiver, 1);
> +
> + priv->force_quit = 0;
> + priv->tx_skb = NULL;
> + priv->tx_len = 0;
> +
> + ret = request_threaded_irq(spi->irq, NULL, hi3110_can_ist,
> + flags, DEVICE_NAME, priv);
> + if (ret) {
> + dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
add propoer goto targets at the and of this function, for easier error
handling cleanup. This mean basically get rid of hi3110_open_clean(net).
> + hi3110_power_enable(priv->transceiver, 0);
> + close_candev(net);
> + goto open_unlock;
> + }
> +
> + priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
> + 0);
> + INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
> + INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
> +
> + ret = hi3110_hw_reset(spi);
> + if (ret) {
> + hi3110_open_clean(net);
> + goto open_unlock;
> + }
> + ret = hi3110_setup(net, priv, spi);
> + if (ret) {
> + hi3110_open_clean(net);
> + goto open_unlock;
> + }
> + ret = hi3110_set_normal_mode(spi);
> + if (ret) {
> + hi3110_open_clean(net);
> + goto open_unlock;
> + }
> + can_led_event(net, CAN_LED_EVENT_OPEN);
> + netif_wake_queue(net);
> +
> +open_unlock:
> + mutex_unlock(&priv->hi3110_lock);
> + return ret;
> +}
> +
> +static const struct net_device_ops hi3110_netdev_ops = {
> + .ndo_open = hi3110_open,
> + .ndo_stop = hi3110_stop,
> + .ndo_start_xmit = hi3110_hard_start_xmit,
> +};
> +
> +static const struct of_device_id hi3110_of_match[] = {
> + {
> + .compatible = "holt,hi3110",
> + .data = (void *)CAN_HI3110_HI3110,
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, hi3110_of_match);
> +
> +static const struct spi_device_id hi3110_id_table[] = {
> + {
> + .name = "hi3110",
> + .driver_data = (kernel_ulong_t)CAN_HI3110_HI3110,
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, hi3110_id_table);
> +
> +static int hi3110_can_probe(struct spi_device *spi)
> +{
> + const struct of_device_id *of_id = of_match_device(hi3110_of_match,
> + &spi->dev);
> + struct net_device *net;
> + struct hi3110_priv *priv;
> + struct clk *clk;
> + int freq, ret;
> +
> + clk = devm_clk_get(&spi->dev, NULL);
> + if (IS_ERR(clk)) {
> + dev_err(&spi->dev, "no CAN clock source defined\n");
> + return PTR_ERR(clk);
> + }
> + freq = clk_get_rate(clk);
> +
> + /* Sanity check */
> + if (freq > 40000000)
> + return -ERANGE;
> +
> + /* Allocate can/net device */
> + net = alloc_candev(sizeof(struct hi3110_priv), TX_ECHO_SKB_MAX);
> + if (!net)
> + return -ENOMEM;
> +
> + if (!IS_ERR(clk)) {
> + ret = clk_prepare_enable(clk);
> + if (ret)
> + goto out_free;
> + }
> +
> + net->netdev_ops = &hi3110_netdev_ops;
> + net->flags |= IFF_ECHO;
> +
> + priv = netdev_priv(net);
> + priv->can.bittiming_const = &hi3110_bittiming_const;
> + priv->can.do_set_mode = hi3110_do_set_mode;
> + priv->can.clock.freq = freq / 2;
> + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
> + CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
> + if (of_id)
> + priv->model = (enum hi3110_model)of_id->data;
> + else
> + priv->model = spi_get_device_id(spi)->driver_data;
> + priv->net = net;
> + priv->clk = clk;
> +
> + spi_set_drvdata(spi, priv);
> +
> + /* Configure the SPI bus */
> + spi->bits_per_word = 8;
> + ret = spi_setup(spi);
> + if (ret)
> + goto out_clk;
> +
> + priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
> + priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
> + if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
> + (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
> + ret = -EPROBE_DEFER;
> + goto out_clk;
> + }
> +
> + ret = hi3110_power_enable(priv->power, 1);
> + if (ret)
> + goto out_clk;
> +
> + priv->spi = spi;
> + mutex_init(&priv->hi3110_lock);
> +
> + /* If requested, allocate DMA buffers */
> + if (hi3110_enable_dma) {
> + spi->dev.coherent_dma_mask = ~0;
> +
> + /* Minimum coherent DMA allocation is PAGE_SIZE, so allocate
> + * that much and share it between Tx and Rx DMA buffers.
> + */
> + priv->spi_tx_buf = dmam_alloc_coherent(&spi->dev,
> + PAGE_SIZE,
> + &priv->spi_tx_dma,
> + GFP_DMA);
> +
> + if (priv->spi_tx_buf) {
> + priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
> + priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
> + (PAGE_SIZE / 2));
> + } else {
> + /* Fall back to non-DMA */
> + hi3110_enable_dma = 0;
> + }
> + }
> +
> + /* Allocate non-DMA buffers */
> + if (!hi3110_enable_dma) {
> + priv->spi_tx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
> + GFP_KERNEL);
> + if (!priv->spi_tx_buf) {
> + ret = -ENOMEM;
> + goto error_probe;
> + }
> + priv->spi_rx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
> + GFP_KERNEL);
> +
> + if (!priv->spi_rx_buf) {
> + ret = -ENOMEM;
> + goto error_probe;
> + }
> + }
> +
> + SET_NETDEV_DEV(net, &spi->dev);
> +
> + ret = hi3110_hw_probe(spi);
> + if (ret) {
> + if (ret == -ENODEV)
> + dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n",
> + priv->model);
> + goto error_probe;
> + }
> + hi3110_hw_sleep(spi);
> +
> + ret = register_candev(net);
> + if (ret)
> + goto error_probe;
> +
> + devm_can_led_init(net);
> + netdev_info(net, "%x successfully initialized.\n", priv->model);
> +
> + return 0;
> +
> +error_probe:
> + hi3110_power_enable(priv->power, 0);
> +
> +out_clk:
> + if (!IS_ERR(clk))
> + clk_disable_unprepare(clk);
> +
> +out_free:
> + free_candev(net);
> +
> + dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
> + return ret;
> +}
> +
> +static int hi3110_can_remove(struct spi_device *spi)
> +{
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + struct net_device *net = priv->net;
> +
> + unregister_candev(net);
> +
> + hi3110_power_enable(priv->power, 0);
> +
> + if (!IS_ERR(priv->clk))
> + clk_disable_unprepare(priv->clk);
> +
> + free_candev(net);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused hi3110_can_suspend(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> + struct net_device *net = priv->net;
> +
> + priv->force_quit = 1;
> + disable_irq(spi->irq);
> +
> + /* Note: at this point neither IST nor workqueues are running.
> + * open/stop cannot be called anyway so locking is not needed
> + */
> + if (netif_running(net)) {
> + netif_device_detach(net);
> +
> + hi3110_hw_sleep(spi);
> + hi3110_power_enable(priv->transceiver, 0);
> + priv->after_suspend = AFTER_SUSPEND_UP;
> + } else {
> + priv->after_suspend = AFTER_SUSPEND_DOWN;
> + }
> +
> + if (!IS_ERR_OR_NULL(priv->power)) {
> + regulator_disable(priv->power);
> + priv->after_suspend |= AFTER_SUSPEND_POWER;
> + }
> +
> + return 0;
> +}
> +
> +static int __maybe_unused hi3110_can_resume(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct hi3110_priv *priv = spi_get_drvdata(spi);
> +
> + if (priv->after_suspend & AFTER_SUSPEND_POWER)
> + hi3110_power_enable(priv->power, 1);
> +
> + if (priv->after_suspend & AFTER_SUSPEND_UP) {
> + hi3110_power_enable(priv->transceiver, 1);
> + queue_work(priv->wq, &priv->restart_work);
> + } else {
> + priv->after_suspend = 0;
> + }
> +
> + priv->force_quit = 0;
> + enable_irq(spi->irq);
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend,
> + hi3110_can_resume);
> +
> +static struct spi_driver hi3110_can_driver = {
> + .driver = {
> + .name = DEVICE_NAME,
> + .of_match_table = hi3110_of_match,
> + .pm = &hi3110_can_pm_ops,
> + },
> + .id_table = hi3110_id_table,
> + .probe = hi3110_can_probe,
> + .remove = hi3110_can_remove,
> +};
> +
> +module_spi_driver(hi3110_can_driver);
> +
> +MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
> +MODULE_AUTHOR("Casey Fitzpatrick <casey.fitzpatrick@timesys.com>");
> +MODULE_DESCRIPTION("Holt HI-3110 CAN driver");
> +MODULE_LICENSE("GPL v2");
>
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH 3/5] mfd: twl: move structure definitions to a public header
From: Lee Jones @ 2017-01-03 15:40 UTC (permalink / raw)
To: Nicolae Rosia
Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel
In-Reply-To: <20161126181326.14951-4-Nicolae_Rosia@mentor.com>
On Sat, 26 Nov 2016, Nicolae Rosia wrote:
> We want to get rid of exported symbols and have
> the child devices use structure members directly.
> Move the structure definitions to header and set
> drvdata so child devices can access it.
< Please use all 75 chars allocated to the commitlog before line wrapping >
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
> drivers/mfd/twl-core.c | 27 ++++-----------------------
> include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
> 2 files changed, 39 insertions(+), 23 deletions(-)
> create mode 100644 include/linux/mfd/twl-core.h
>
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index e16084e..409b836 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -48,6 +48,7 @@
>
> #include <linux/i2c.h>
> #include <linux/i2c/twl.h>
> +#include <linux/mfd/twl-core.h>
>
> /* Register descriptions for audio */
> #include <linux/mfd/twl4030-audio.h>
> @@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
> int twl4030_exit_irq(void);
> int twl4030_init_chip_irq(const char *chip);
>
> -/* Structure for each TWL4030/TWL6030 Slave */
> -struct twl_client {
> - struct i2c_client *client;
> - struct regmap *regmap;
> -};
> -
> -/* mapping the module id to slave id and base address */
> -struct twl_mapping {
> - unsigned char sid; /* Slave ID */
> - unsigned char base; /* base address */
> -};
> -
> -struct twl_private {
> - bool ready; /* The core driver is ready to be used */
> - u32 twl_idcode; /* TWL IDCODE Register value */
> - unsigned int twl_id;
> -
> - struct twl_mapping *twl_map;
> - struct twl_client *twl_modules;
> -};
> -
> -static struct twl_private *twl_priv;
> +static struct twlcore *twl_priv;
I'm guessing when you remove the exported functions, you can remove this?
> static struct twl_mapping twl4030_map[] = {
> /*
> @@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
> goto free;
> }
>
> - twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
> + twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
> GFP_KERNEL);
> if (!twl_priv) {
> status = -ENOMEM;
> @@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
> }
>
> twl_priv->ready = true;
> + dev_set_drvdata(&client->dev, twl_priv);
>
> /* setup clock framework */
> clocks_init(&pdev->dev);
> diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
> new file mode 100644
> index 0000000..d1c01b3
> --- /dev/null
> +++ b/include/linux/mfd/twl-core.h
> @@ -0,0 +1,35 @@
> +/*
> + * MFD core driver for the Texas Instruments TWL PMIC family
> + *
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
Your sign-off and SoB are different? Why?
> + * 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.
> + */
> +
> +#ifndef __TWL_CORE_H__
> +#define __TWL_CORE_H__
_MFD_
> +/* Structure for each TWL4030/TWL6030 Slave */
> +struct twl_client {
> + struct i2c_client *client;
> + struct regmap *regmap;
> +};
> +
> +/* mapping the module id to slave id and base address */
> +struct twl_mapping {
> + unsigned char sid; /* Slave ID */
> + unsigned char base; /* base address */
> +};
> +
> +struct twlcore {
> + bool ready; /* The core driver is ready to be used */
> + u32 twl_idcode; /* TWL IDCODE Register value */
> + unsigned int twl_id;
> +
> + struct twl_mapping *twl_map;
> + struct twl_client *twl_modules;
> +};
> +
> +#endif
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
From: Lee Jones @ 2017-01-03 15:46 UTC (permalink / raw)
To: Nicolae Rosia
Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel
In-Reply-To: <20161126181326.14951-6-Nicolae_Rosia@mentor.com>
On Sat, 26 Nov 2016, Nicolae Rosia wrote:
> TWL6032 regulator driver uses the drvdata twl_priv pointer.
> In order to avoid accessing an invalid drvdata
> when the driver gets unbinded, make sure we remove the
> child devices before deleting the drvdata.
This doesn't really describe the change.
Surely we're really just registering the regulator driver?
The fact that we then remove the device during .remove() is
incidental.
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
> drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 409b836..1e94364 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -43,6 +43,7 @@
> #include <linux/of_platform.h>
> #include <linux/irq.h>
> #include <linux/irqdomain.h>
> +#include <linux/mfd/core.h>
>
> #include <linux/regulator/machine.h>
>
> @@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
> int twl4030_exit_irq(void);
> int twl4030_init_chip_irq(const char *chip);
>
> +
?
> static struct twlcore *twl_priv;
>
> +static struct mfd_cell twl6032_devs[] = {
> + {
> + .name = "twl6032-regulator",
> + .of_compatible = "ti,twl6032-regulator",
> + },
> +};
> +
> static struct twl_mapping twl4030_map[] = {
> /*
> * NOTE: don't change this table without updating the
> @@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
> unsigned i, num_slaves;
> int status;
>
> + mfd_remove_devices(&client->dev);
> +
> if (twl_class_is_4030())
> status = twl4030_exit_irq();
> else
> @@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
> TWL4030_DCDC_GLOBAL_CFG);
> }
>
> + if (id->driver_data & TWL6032_SUBCLASS) {
> + status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> + twl6032_devs, ARRAY_SIZE(twl6032_devs),
> + NULL, 0, NULL);
> + if (status != 0) {
> + dev_err(&client->dev, "failed to add mfd devices: %d\n",
> + status);
> + goto fail;
> + }
> + }
> +
> fail:
> if (status < 0)
> twl_remove(client);
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/8] ARM: dts: armada-38x: Utilize new DSA binding
From: Gregory CLEMENT @ 2017-01-03 16:14 UTC (permalink / raw)
To: Florian Fainelli
Cc: Mark Rutland, Andrew Lunn, Jason Cooper, vivien.didelot,
Russell King, open list,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Rob Herring, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20170102022249.10657-3-f.fainelli@gmail.com>
Hi Florian,
You should use the board name in the topic, ie:
"ARM: dts: armada-385-linksys: Utilize new DSA binding"
Thanks,
Gregory
On lun., janv. 02 2017, Florian Fainelli <f.fainelli@gmail.com> wrote:
> Utilize the new DSA binding, introduced with commit 8c5ad1d6179d ("net: dsa:
> Document new binding"). The legacy binding node is kept included, but is marked
> disabled.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> arch/arm/boot/dts/armada-385-linksys.dtsi | 52 ++++++++++++++++++++++++++++++-
> 1 file changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi
> index 8f0e508f64ae..20d5e8b00f2d 100644
> --- a/arch/arm/boot/dts/armada-385-linksys.dtsi
> +++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
> @@ -103,8 +103,56 @@
> };
> };
>
> - mdio {
> + mdio@72004 {
> status = "okay";
> +
> + switch@0 {
> + compatible = "marvell,mv88e6095";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + label = "lan4";
> + };
> +
> + port@1 {
> + reg = <1>;
> + label = "lan3";
> + };
> +
> + port@2 {
> + reg = <2>;
> + label = "lan2";
> + };
> +
> + port@3 {
> + reg = <3>;
> + label = "lan1";
> + };
> +
> + port@4 {
> + reg = <4>;
> + label = "wan";
> + };
> +
> + port@5 {
> + reg = <5>;
> + label = "cpu";
> + ethernet = <ð2>;
> +
> + fixed-link {
> + speed = <1000>;
> + full-duplex;
> + };
> + };
> + };
> + };
> };
>
> sata@a8000 {
> @@ -261,6 +309,8 @@
> };
>
> dsa@0 {
> + status = "disabled";
> +
> compatible = "marvell,dsa";
> #address-cells = <2>;
> #size-cells = <0>;
> --
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 0/8] ARM: dts: Switch to new DSA binding
From: Gregory CLEMENT @ 2017-01-03 16:19 UTC (permalink / raw)
To: Florian Fainelli
Cc: Mark Rutland, Andrew Lunn, Jason Cooper, vivien.didelot,
Russell King, open list,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Rob Herring, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20170102022249.10657-1-f.fainelli@gmail.com>
Hi Florian,
On lun., janv. 02 2017, Florian Fainelli <f.fainelli@gmail.com> wrote:
> Hi all,
>
> This patch series converts the in-tree users to utilize the new (relatively)
> DSA binding that was introduced with commit 8c5ad1d6179d ("net: dsa: Document
> new binding"). The legacy binding node is kept included, but is marked
> disabled.
>
> In about 2-3 releases we may consider removing the old DSA binding entirely
> from the kernel.
The series looks OK. However I would like to have a reviewed by from
Andrew who know well the mvebu platform and the DSA subsystem.
Also there's few fixes needed for the v2.
Thanks,
Gregory
>
> Thank you!
>
> Florian Fainelli (8):
> ARM: dts: armada-370-rd: Utilize new DSA binding
> ARM: dts: armada-38x: Utilize new DSA binding
> ARM: dts: armada-388-clearfog: Utilize new DSA binding
> ARM: dts: armada-xp-linksys-mamba: Utilize new DSA binding
> ARM: dts: kirkwood-dir665: Utilize new DSA binding
> ARM: dts: kirkwood-linksys-viper: Utilize new DSA binding
> ARM: dts: kirkwood-mv88f6281gtw-ge: Utilize new DSA binding
> ARM: dts: kirkwood-rd88f6281: Utilize new DSA binding
>
> arch/arm/boot/dts/armada-370-rd.dts | 44 +++++++++++++++++
> arch/arm/boot/dts/armada-385-linksys.dtsi | 52 ++++++++++++++++++++-
> arch/arm/boot/dts/armada-388-clearfog.dts | 65 ++++++++++++++++++++++++++
> arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 53 +++++++++++++++++++++
> arch/arm/boot/dts/kirkwood-dir665.dts | 49 +++++++++++++++++++
> arch/arm/boot/dts/kirkwood-linksys-viper.dts | 49 +++++++++++++++++++
> arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 49 +++++++++++++++++++
> arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts | 11 +++++
> arch/arm/boot/dts/kirkwood-rd88f6281.dtsi | 44 +++++++++++++++++
> 9 files changed, 415 insertions(+), 1 deletion(-)
>
> --
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: exynos: make tm2 and tm2e independent from each other
From: Krzysztof Kozlowski @ 2017-01-03 16:31 UTC (permalink / raw)
To: Chanwoo Choi
Cc: Mark Rutland, devicetree, linux-samsung-soc, Kukjin Kim,
Chanwoo Choi, Catalin Marinas, Jaechul Lee, Dmitry Torokhov,
Will Deacon, linux-kernel, Andi Shyti, Javier Martinez Canillas,
Rob Herring, Krzysztof Kozlowski, Andi Shyti, linux-input,
galaxyra, beomho.seo, linux-arm-kernel
In-Reply-To: <CAGTfZH0tnjkqF_7DChLSvzs3C369mkb_HZmyrf3cc0T-UcBZ4A@mail.gmail.com>
On Wed, Jan 04, 2017 at 12:29:23AM +0900, Chanwoo Choi wrote:
> Hi Andi,
>
> 2017-01-03 23:40 GMT+09:00 Andi Shyti <andi@etezian.org>:
> > Hi,
> >
> >> FWIW, I also agree with Chanwoo that the difference is too small to
> >> need a common .dtsi file.
> >
> > in principle I don't like "switching on and off" properties by
> > overwriting them with "status = disable", unless it's really
> > necessary (and this case is not). Even for small differences. It
> > makes the DTS harder to read and duplicates nodes with different
> > values throughout the DTS include chain.
I agree.
> >
> > In my opinion this approach should be discouraged.
> >
> > Besides, there are other overwritten differences in tm2e.dts that
> > I think should be separated as well. The "common" file approach is
> > widely used in arm/boot/dts/exynos* files.
I agree. Mostly we use:
1. Common DTSI and final addons/customizations in DTS.
2. Several common DTSI for specific parts (like sound).
> > The "status = disable" looks to me more like a temporary hack
> > rather than a permanent solution.
> >
> > In any case, still up to you :)
> >
> > Andi
>
> I think that "status=disabled" of hsi2c_9 is not hack. The overwrite
> is possible for Device-tree. But, there is just difference how to
> support them with some method.
>
> Except for touchkey, all peripheral device are same on both tm2 and
> tm2e. There are only small difference for a few property value.
>
> To understand the difference between tm2 and tm2e, I made the patch
> (it is not complete version). If we implement the following patch, we
> support both tm2 and tm2e. So, I think that it is not complex to
> understand the h/w difference between tm2 and tm2e.
The difference below (I removed it from the quote) is indeed very small,
thanks Chanwoo for pointing this. However having common DTSI should not
end with much bigger final diff between files. I mean that it should be
the same amount of lines in total...
Actually, after applying this patch, the final exynos5433-tm2e.dts is
exactly the same as before. To me, this is a indication that a common
file is a good approach.
>From a separate Javier's mail:
> On 01/03/2017 11:40 AM, Andi Shyti wrote:
> > Hi,
> >
> >> FWIW, I also agree with Chanwoo that the difference is too small to
> >> need a common .dtsi file.
> >
> > in principle I don't like "switching on and off" properties by
> > overwriting them with "status = disable", unless it's really
>
> This is a very good point. It would had been different if it was the
> opposite and tm2e had to enable the device node, but disabling it is
> indeed more confusing.
> On 01/03/2017 11:40 AM, Andi Shyti wrote:
> > Hi,
> >
> >> FWIW, I also agree with Chanwoo that the difference is too small to
> >> need a common .dtsi file.
> >
> > in principle I don't like "switching on and off" properties by
> > overwriting them with "status = disable", unless it's really
>
> This is a very good point. It would had been different if it was the
> opposite and tm2e had to enable the device node, but disabling it is
> indeed more confusing.
I agree, 'status = disable' in final DTS is not a common pattern and
to me when reading, it makes me wonder what was the author's intention.
Also including a DTS in DTS is not a common pattern, neither. It appears
(git grep include arch/arm/boot/dts | grep 'dts"') in few places but it
is not obvious. At least to me.
Overall, I prefer the common approach.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 0/8] ARM: dts: Switch to new DSA binding
From: Andrew Lunn @ 2017-01-03 16:32 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Florian Fainelli, Jason Cooper, vivien.didelot, Russell King,
open list, Rob Herring, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <87eg0kf75m.fsf@free-electrons.com>
> The series looks OK. However I would like to have a reviewed by from
> Andrew who know well the mvebu platform and the DSA subsystem.
Hi Gregory
Yes, i was planning on reviewing, and testing on at least three of
these platforms.
Since this is mvebu/arm-soc and not netdev, i may take a week or so
before i get around to it. netdev is too fast some times.
Andrew
^ permalink raw reply
* Re: [PATCH v3 3/3] nfc: trf7970a: Prevent repeated polling from crashing the kernel
From: Mark Greer @ 2017-01-03 16:33 UTC (permalink / raw)
To: Geoff Lansberry
Cc: linux-wireless, Lauro Ramos Venancio, Aloisio Almeida Jr,
Samuel Ortiz, robh+dt, mark.rutland, netdev, devicetree,
linux-kernel, Justin Bronder, Jaret Cantu
In-Reply-To: <CAO7Z3WJa0goJ-VXc7dvyz8imZtqby6QsC0QNH+uRAE8LhxqU2w@mail.gmail.com>
[Please stop top-posting. Bottom-post only to these lists.]
Hi Geoff & happy new year.
On Tue, Dec 27, 2016 at 09:18:32AM -0500, Geoff Lansberry wrote:
> Mark - I will split this off soon.
OK
> In the meantime - here is some more info about how we use it.
>
> We do use NFC structures. I did find an interesting clue in that
> there are certain bottles that cause neard to segfault, I'm not sure
> what is different about them. We write a string, like
> "coppola_chardonnay_2015" to the bottles.
Off the top of my head, it could be the length of the text.
It would be useful to compare the data that works to the data
that doesn't work. Can you install NXP's 'TagInfo' app on a
smartphone and scan tags with working & non-working data?
You can email the data from the app to yourself, edit out
the cruft, and share here.
> Come to think of it, I
> haven't done anything special to make that an ndef record, just
> assumed that it would happen by default, I'll look into this further.
If you wrote the data using neard, it will be NDEF formatted.
Since it is working this well, it is virtually guaranteed that
the data is NDEF formatted.
> Also, I've been running neard with --plugin nfctype2. Just in case
> the problem was happening due to cycling through other tag types. It
> didn't seem to make any difference, but I have not gone back to
> default.
Good to know, thanks.
Mark
--
^ permalink raw reply
* Re: [PATCHv3] mfd: cpcap: Add minimal support
From: Lee Jones @ 2017-01-03 16:35 UTC (permalink / raw)
To: Tony Lindgren
Cc: Samuel Ortiz, linux-kernel, linux-omap, devicetree, Marcel Partap,
Mark Rutland, Michael Scott
In-Reply-To: <20161206004856.11996-1-tony@atomide.com>
On Mon, 05 Dec 2016, Tony Lindgren wrote:
> Many Motorola phones like droid 4 are using a custom PMIC called CPCAP
> or 6556002. We can support it's core features quite easily with regmap_spi
> and regmap_irq.
>
> The children of cpcap, such as regulators, ADC and USB, can be just regular
> device drivers and defined in the dts file. They get probed as we call
> of_platform_populate() at the end of our probe, and then the children
> can just call dev_get_regmap(dev.parent, NULL) to get the regmap.
>
> Cc: devicetree@vger.kernel.org
> Cc: Marcel Partap <mpartap@gmx.net>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Michael Scott <michael.scott@linaro.org>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>
> Changes from v2:
>
> - Fix typos in binding documentation for #size-cells and spi-cs-high
> - Add ack from Rob
>
> ---
> .../devicetree/bindings/mfd/motorola-cpcap.txt | 31 +++
> drivers/mfd/Kconfig | 11 +
> drivers/mfd/Makefile | 1 +
> drivers/mfd/motorola-cpcap.c | 244 +++++++++++++++++
> include/linux/mfd/motorola-cpcap.h | 289 +++++++++++++++++++++
> 5 files changed, 576 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> create mode 100644 drivers/mfd/motorola-cpcap.c
> create mode 100644 include/linux/mfd/motorola-cpcap.h
>
> diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> @@ -0,0 +1,31 @@
> +Motorola CPCAP PMIC device tree binding
> +
> +Required properties:
> +- compatible : One or both of "motorola,cpcap" or "ste,6556002"
> +- reg : SPI chip select
> +- interrupt-parent : The parent interrupt controller
> +- interrupts : The interrupt line the device is connected to
> +- interrupt-controller : Marks the device node as an interrupt controller
> +- #interrupt-cells : The number of cells to describe an IRQ, should be 2
> +- #address-cells : Child device offset number of cells, should be 1
> +- #size-cells : Child device size number of cells, should be 0
> +- spi-max-frequency : Typically set to 3000000
> +- spi-cs-high : SPI chip select direction
> +
> +Example:
> +
> +&mcspi1 {
> + cpcap: pmic@0 {
> + compatible = "motorola,cpcap", "ste,6556002";
> + reg = <0>; /* cs0 */
> + interrupt-parent = <&gpio1>;
> + interrupts = <7 IRQ_TYPE_EDGE_RISING>;
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + spi-max-frequency = <3000000>;
> + spi-cs-high;
> + };
> +};
> +
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -714,6 +714,17 @@ config EZX_PCAP
> This enables the PCAP ASIC present on EZX Phones. This is
> needed for MMC, TouchScreen, Sound, USB, etc..
>
> +config MFD_CPCAP
> + tristate "Support for Motorola CPCAP"
> + depends on SPI
> + depends on OF || COMPILE_TEST
> + select REGMAP_SPI
> + select REGMAP_IRQ
> + help
> + Say yes here if you want to include driver for CPCAP.
> + It is used on many Motorola phones and tablets as a PMIC.
> + At least Motorola Droid 4 is known to use CPCAP.
> +
> config MFD_VIPERBOARD
> tristate "Nano River Technologies Viperboard"
> select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -97,6 +97,7 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
> obj-$(CONFIG_MFD_CORE) += mfd-core.o
>
> obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
> +obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o
>
> obj-$(CONFIG_MCP) += mcp-core.o
> obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
> diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/mfd/motorola-cpcap.c
> @@ -0,0 +1,244 @@
> +/*
> + * Motorola CPCAP PMIC core driver
> + *
> + * Copyright (C) 2016 Tony Lindgren <tony@atomide.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +#include <linux/sysfs.h>
> +
> +#include <linux/mfd/motorola-cpcap.h>
> +#include <linux/spi/spi.h>
> +
> +#define CPCAP_NR_IRQ_REG_BANKS 6
> +#define CPCAP_NR_IRQ_CHIPS 3
> +
> +struct cpcap_ddata {
> + struct spi_device *spi;
> + struct regmap_irq *irqs;
> + struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
> + const struct regmap_config *regmap_conf;
> + struct regmap *regmap;
> +};
> +
> +static int cpcap_check_revision(struct cpcap_ddata *cpcap)
> +{
> + u16 vendor, rev;
> + int ret;
> +
> + ret = cpcap_get_vendor(&cpcap->spi->dev, cpcap->regmap, &vendor);
> + if (ret)
> + return ret;
> +
> + ret = cpcap_get_revision(&cpcap->spi->dev, cpcap->regmap, &rev);
> + if (ret)
> + return ret;
> +
> + dev_info(&cpcap->spi->dev, "CPCAP vendor: %s rev: %i.%i (%x)\n",
> + vendor == CPCAP_VENDOR_ST ? "ST" : "TI",
> + CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev),
> + rev);
> +
> + if (rev < CPCAP_REVISION_2_1) {
> + dev_info(&cpcap->spi->dev,
> + "Please add old CPCAP revision support as needed\n");
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * First two irq chips are the two private macro interrupt chips, the third
> + * irq chip is for register banks 1 - 4 and is available for drivers to use.
> + */
> +static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
> + {
> + .name = "cpcap-m2",
> + .num_regs = 1,
> + .status_base = CPCAP_REG_MI1,
> + .ack_base = CPCAP_REG_MI1,
> + .mask_base = CPCAP_REG_MIM1,
> + .use_ack = true,
> + },
> + {
> + .name = "cpcap-m2",
> + .num_regs = 1,
> + .status_base = CPCAP_REG_MI2,
> + .ack_base = CPCAP_REG_MI2,
> + .mask_base = CPCAP_REG_MIM2,
> + .use_ack = true,
> + },
> + {
> + .name = "cpcap1-4",
> + .num_regs = 4,
> + .status_base = CPCAP_REG_INT1,
> + .ack_base = CPCAP_REG_INT1,
> + .mask_base = CPCAP_REG_INTM1,
> + .type_base = CPCAP_REG_INTS1,
> + .use_ack = true,
> + },
> +};
> +
> +static int cpcap_init_irq_chip(struct cpcap_ddata *cpcap, int irq_chip,
> + int irq_start, int nr_irqs)
> +{
> + struct regmap_irq_chip *chip = &cpcap_irq_chip[irq_chip];
> + int i, ret;
> +
> + for (i = irq_start; i < irq_start + nr_irqs; i++) {
> + struct regmap_irq *cpcap_irq = &cpcap->irqs[i];
> +
> + cpcap_irq->reg_offset =
> + ((i - irq_start) / cpcap->regmap_conf->val_bits) *
> + cpcap->regmap_conf->reg_stride;
> + cpcap_irq->mask = BIT(i % cpcap->regmap_conf->val_bits);
If a code segment takes more than a few seconds to work out, it's
either too cluttered (break it down), too complex (simplify it) or if
neither of the first two approaches are possible, then a comment is
required.
> + }
> + chip->irqs = &cpcap->irqs[irq_start];
> + chip->num_irqs = nr_irqs;
> + chip->irq_drv_data = cpcap;
> +
> + ret = devm_regmap_add_irq_chip(&cpcap->spi->dev, cpcap->regmap,
> + cpcap->spi->irq,
> + IRQF_TRIGGER_RISING |
> + IRQF_SHARED, -1,
> + chip, &cpcap->irqdata[irq_chip]);
> + if (ret) {
> + dev_err(&cpcap->spi->dev, "could not add irq chip %i: %i\n",
> + irq_chip, ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int cpcap_init_irq(struct cpcap_ddata *cpcap)
> +{
> + int ret;
> +
> + cpcap->irqs = devm_kzalloc(&cpcap->spi->dev,
> + sizeof(*cpcap->irqs) *
> + CPCAP_NR_IRQ_REG_BANKS *
> + cpcap->regmap_conf->val_bits,
> + GFP_KERNEL);
> + if (!cpcap->irqs)
> + return -ENOMEM;
> +
> + ret = cpcap_init_irq_chip(cpcap, 0, 0, 16);
> + if (ret)
> + return ret;
> +
> + ret = cpcap_init_irq_chip(cpcap, 1, 16, 16);
> + if (ret)
> + return ret;
> +
> + ret = cpcap_init_irq_chip(cpcap, 2, 32, 64);
> + if (ret)
> + return ret;
> +
> + enable_irq_wake(cpcap->spi->irq);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id cpcap_of_match[] = {
> + { .compatible = "motorola,cpcap", },
> + { .compatible = "st,6556002", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, cpcap_of_match);
> +
> +static const struct regmap_config cpcap_regmap_config = {
> + .reg_bits = 16,
> + .reg_stride = 4,
> + .pad_bits = 0,
> + .val_bits = 16,
> + .write_flag_mask = 0x8000,
> + .max_register = CPCAP_REG_ST_TEST2,
> + .cache_type = REGCACHE_NONE,
> + .reg_format_endian = REGMAP_ENDIAN_LITTLE,
> + .val_format_endian = REGMAP_ENDIAN_LITTLE,
> +};
> +
> +static int cpcap_probe(struct spi_device *spi)
> +{
> + const struct of_device_id *match;
> + int ret = -EINVAL;
What is the purpose of initialising ret?
> + struct cpcap_ddata *cpcap;
> +
> + match = of_match_device(of_match_ptr(cpcap_of_match), &spi->dev);
> + if (!match)
> + return -ENODEV;
> +
> + cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
> + if (!cpcap)
> + return -ENOMEM;
> +
> + cpcap->spi = spi;
> + spi_set_drvdata(spi, cpcap);
> +
> + spi->bits_per_word = 16;
> + spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
> +
> + ret = spi_setup(spi);
> + if (ret < 0)
> + return ret;
Is it possible for spi_setup() to return >0?
If not, then "if (!ret)" will do.
> + cpcap->regmap_conf = &cpcap_regmap_config;
> + cpcap->regmap = devm_regmap_init_spi(spi, &cpcap_regmap_config);
> + if (IS_ERR(cpcap->regmap)) {
> + ret = PTR_ERR(cpcap->regmap);
> + dev_err(&cpcap->spi->dev, "Failed to initialize regmap: %d\n",
> + ret);
> +
> + return ret;
> + }
> +
> + ret = cpcap_check_revision(cpcap);
> + if (ret) {
> + dev_err(&cpcap->spi->dev, "Failed to detect CPCAP: %i\n", ret);
> + return ret;
> + }
> +
> + ret = cpcap_init_irq(cpcap);
> + if (ret)
> + return ret;
> +
> + return of_platform_populate(spi->dev.of_node, NULL, NULL,
> + &cpcap->spi->dev);
> +}
> +
> +static int cpcap_remove(struct spi_device *pdev)
> +{
> + struct cpcap_ddata *cpcap = spi_get_drvdata(pdev);
> +
> + of_platform_depopulate(&cpcap->spi->dev);
> +
> + return 0;
> +}
> +
> +static struct spi_driver cpcap_driver = {
> + .driver = {
> + .name = "cpcap-core",
> + .of_match_table = cpcap_of_match,
of_match_ptr() ?
> + },
> + .probe = cpcap_probe,
> + .remove = cpcap_remove,
> +};
> +module_spi_driver(cpcap_driver);
> +
> +MODULE_ALIAS("platform:cpcap");
> +MODULE_DESCRIPTION("CPCAP driver");
> +MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
> new file mode 100644
> --- /dev/null
> +++ b/include/linux/mfd/motorola-cpcap.h
> @@ -0,0 +1,289 @@
> +/*
> + * 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.
> + *
> + * Note that the register defines are based on earlier cpcap.h in
> + * Motorola Linux kernel tree Copyright (C) 2007-2009 Motorola, Inc.
> + *
> + * Rewritten for the real register offsets instead of enumeration
> + * to make the defines usable with Linux kernel regmap support
'\n'
> + * Copyright (C) 2016 Tony Lindgren <tony@atomide.com>.
Actually, it's more traditional to place the CR at the top.
> + */
> +
> +#define CPCAP_VENDOR_ST 0
> +#define CPCAP_VENDOR_TI 1
> +
> +#define CPCAP_REVISION_MAJOR(r) (((r) >> 4) + 1)
> +#define CPCAP_REVISION_MINOR(r) ((r) & 0xf)
> +
> +#define CPCAP_REVISION_1_0 0x08
> +#define CPCAP_REVISION_1_1 0x09
> +#define CPCAP_REVISION_2_0 0x10
> +#define CPCAP_REVISION_2_1 0x11
> +
> +/* CPCAP registers */
> +#define CPCAP_REG_INT1 0x0000 /* Interrupt 1 */
> +#define CPCAP_REG_INT2 0x0004 /* Interrupt 2 */
> +#define CPCAP_REG_INT3 0x0008 /* Interrupt 3 */
> +#define CPCAP_REG_INT4 0x000c /* Interrupt 4 */
> +#define CPCAP_REG_INTM1 0x0010 /* Interrupt Mask 1 */
> +#define CPCAP_REG_INTM2 0x0014 /* Interrupt Mask 2 */
> +#define CPCAP_REG_INTM3 0x0018 /* Interrupt Mask 3 */
> +#define CPCAP_REG_INTM4 0x001c /* Interrupt Mask 4 */
> +#define CPCAP_REG_INTS1 0x0020 /* Interrupt Sense 1 */
> +#define CPCAP_REG_INTS2 0x0024 /* Interrupt Sense 2 */
> +#define CPCAP_REG_INTS3 0x0028 /* Interrupt Sense 3 */
> +#define CPCAP_REG_INTS4 0x002c /* Interrupt Sense 4 */
> +#define CPCAP_REG_ASSIGN1 0x0030 /* Resource Assignment 1 */
> +#define CPCAP_REG_ASSIGN2 0x0034 /* Resource Assignment 2 */
> +#define CPCAP_REG_ASSIGN3 0x0038 /* Resource Assignment 3 */
> +#define CPCAP_REG_ASSIGN4 0x003c /* Resource Assignment 4 */
> +#define CPCAP_REG_ASSIGN5 0x0040 /* Resource Assignment 5 */
> +#define CPCAP_REG_ASSIGN6 0x0044 /* Resource Assignment 6 */
> +#define CPCAP_REG_VERSC1 0x0048 /* Version Control 1 */
> +#define CPCAP_REG_VERSC2 0x004c /* Version Control 2 */
> +
> +#define CPCAP_REG_MI1 0x0200 /* Macro Interrupt 1 */
> +#define CPCAP_REG_MIM1 0x0204 /* Macro Interrupt Mask 1 */
> +#define CPCAP_REG_MI2 0x0208 /* Macro Interrupt 2 */
> +#define CPCAP_REG_MIM2 0x020c /* Macro Interrupt Mask 2 */
> +#define CPCAP_REG_UCC1 0x0210 /* UC Control 1 */
> +#define CPCAP_REG_UCC2 0x0214 /* UC Control 2 */
> +
> +#define CPCAP_REG_PC1 0x021c /* Power Cut 1 */
> +#define CPCAP_REG_PC2 0x0220 /* Power Cut 2 */
> +#define CPCAP_REG_BPEOL 0x0224 /* BP and EOL */
> +#define CPCAP_REG_PGC 0x0228 /* Power Gate and Control */
> +#define CPCAP_REG_MT1 0x022c /* Memory Transfer 1 */
> +#define CPCAP_REG_MT2 0x0230 /* Memory Transfer 2 */
> +#define CPCAP_REG_MT3 0x0234 /* Memory Transfer 3 */
> +#define CPCAP_REG_PF 0x0238 /* Print Format */
> +
> +#define CPCAP_REG_SCC 0x0400 /* System Clock Control */
> +#define CPCAP_REG_SW1 0x0404 /* Stop Watch 1 */
> +#define CPCAP_REG_SW2 0x0408 /* Stop Watch 2 */
> +#define CPCAP_REG_UCTM 0x040c /* UC Turbo Mode */
> +#define CPCAP_REG_TOD1 0x0410 /* Time of Day 1 */
> +#define CPCAP_REG_TOD2 0x0414 /* Time of Day 2 */
> +#define CPCAP_REG_TODA1 0x0418 /* Time of Day Alarm 1 */
> +#define CPCAP_REG_TODA2 0x041c /* Time of Day Alarm 2 */
> +#define CPCAP_REG_DAY 0x0420 /* Day */
> +#define CPCAP_REG_DAYA 0x0424 /* Day Alarm */
> +#define CPCAP_REG_VAL1 0x0428 /* Validity 1 */
> +#define CPCAP_REG_VAL2 0x042c /* Validity 2 */
> +
> +#define CPCAP_REG_SDVSPLL 0x0600 /* Switcher DVS and PLL */
> +#define CPCAP_REG_SI2CC1 0x0604 /* Switcher I2C Control 1 */
> +#define CPCAP_REG_Si2CC2 0x0608 /* Switcher I2C Control 2 */
> +#define CPCAP_REG_S1C1 0x060c /* Switcher 1 Control 1 */
> +#define CPCAP_REG_S1C2 0x0610 /* Switcher 1 Control 2 */
> +#define CPCAP_REG_S2C1 0x0614 /* Switcher 2 Control 1 */
> +#define CPCAP_REG_S2C2 0x0618 /* Switcher 2 Control 2 */
> +#define CPCAP_REG_S3C 0x061c /* Switcher 3 Control */
> +#define CPCAP_REG_S4C1 0x0620 /* Switcher 4 Control 1 */
> +#define CPCAP_REG_S4C2 0x0624 /* Switcher 4 Control 2 */
> +#define CPCAP_REG_S5C 0x0628 /* Switcher 5 Control */
> +#define CPCAP_REG_S6C 0x062c /* Switcher 6 Control */
> +#define CPCAP_REG_VCAMC 0x0630 /* VCAM Control */
> +#define CPCAP_REG_VCSIC 0x0634 /* VCSI Control */
> +#define CPCAP_REG_VDACC 0x0638 /* VDAC Control */
> +#define CPCAP_REG_VDIGC 0x063c /* VDIG Control */
> +#define CPCAP_REG_VFUSEC 0x0640 /* VFUSE Control */
> +#define CPCAP_REG_VHVIOC 0x0644 /* VHVIO Control */
> +#define CPCAP_REG_VSDIOC 0x0648 /* VSDIO Control */
> +#define CPCAP_REG_VPLLC 0x064c /* VPLL Control */
> +#define CPCAP_REG_VRF1C 0x0650 /* VRF1 Control */
> +#define CPCAP_REG_VRF2C 0x0654 /* VRF2 Control */
> +#define CPCAP_REG_VRFREFC 0x0658 /* VRFREF Control */
> +#define CPCAP_REG_VWLAN1C 0x065c /* VWLAN1 Control */
> +#define CPCAP_REG_VWLAN2C 0x0660 /* VWLAN2 Control */
> +#define CPCAP_REG_VSIMC 0x0664 /* VSIM Control */
> +#define CPCAP_REG_VVIBC 0x0668 /* VVIB Control */
> +#define CPCAP_REG_VUSBC 0x066c /* VUSB Control */
> +#define CPCAP_REG_VUSBINT1C 0x0670 /* VUSBINT1 Control */
> +#define CPCAP_REG_VUSBINT2C 0x0674 /* VUSBINT2 Control */
> +#define CPCAP_REG_URT 0x0678 /* Useroff Regulator Trigger */
> +#define CPCAP_REG_URM1 0x067c /* Useroff Regulator Mask 1 */
> +#define CPCAP_REG_URM2 0x0680 /* Useroff Regulator Mask 2 */
> +
> +#define CPCAP_REG_VAUDIOC 0x0800 /* VAUDIO Control */
> +#define CPCAP_REG_CC 0x0804 /* Codec Control */
> +#define CPCAP_REG_CDI 0x0808 /* Codec Digital Interface */
> +#define CPCAP_REG_SDAC 0x080c /* Stereo DAC */
> +#define CPCAP_REG_SDACDI 0x0810 /* Stereo DAC Digital Interface */
> +#define CPCAP_REG_TXI 0x0814 /* TX Inputs */
> +#define CPCAP_REG_TXMP 0x0818 /* TX MIC PGA's */
> +#define CPCAP_REG_RXOA 0x081c /* RX Output Amplifiers */
> +#define CPCAP_REG_RXVC 0x0820 /* RX Volume Control */
> +#define CPCAP_REG_RXCOA 0x0824 /* RX Codec to Output Amps */
> +#define CPCAP_REG_RXSDOA 0x0828 /* RX Stereo DAC to Output Amps */
> +#define CPCAP_REG_RXEPOA 0x082c /* RX External PGA to Output Amps */
> +#define CPCAP_REG_RXLL 0x0830 /* RX Low Latency */
> +#define CPCAP_REG_A2LA 0x0834 /* A2 Loudspeaker Amplifier */
> +#define CPCAP_REG_MIPIS1 0x0838 /* MIPI Slimbus 1 */
> +#define CPCAP_REG_MIPIS2 0x083c /* MIPI Slimbus 2 */
> +#define CPCAP_REG_MIPIS3 0x0840 /* MIPI Slimbus 3. */
> +#define CPCAP_REG_LVAB 0x0844 /* LMR Volume and A4 Balanced. */
> +
> +#define CPCAP_REG_CCC1 0x0a00 /* Coulomb Counter Control 1 */
> +#define CPCAP_REG_CRM 0x0a04 /* Charger and Reverse Mode */
> +#define CPCAP_REG_CCCC2 0x0a08 /* Coincell and Coulomb Ctr Ctrl 2 */
> +#define CPCAP_REG_CCS1 0x0a0c /* Coulomb Counter Sample 1 */
> +#define CPCAP_REG_CCS2 0x0a10 /* Coulomb Counter Sample 2 */
> +#define CPCAP_REG_CCA1 0x0a14 /* Coulomb Counter Accumulator 1 */
> +#define CPCAP_REG_CCA2 0x0a18 /* Coulomb Counter Accumulator 2 */
> +#define CPCAP_REG_CCM 0x0a1c /* Coulomb Counter Mode */
> +#define CPCAP_REG_CCO 0x0a20 /* Coulomb Counter Offset */
> +#define CPCAP_REG_CCI 0x0a24 /* Coulomb Counter Integrator */
> +
> +#define CPCAP_REG_ADCC1 0x0c00 /* A/D Converter Configuration 1 */
> +#define CPCAP_REG_ADCC2 0x0c04 /* A/D Converter Configuration 2 */
> +#define CPCAP_REG_ADCD0 0x0c08 /* A/D Converter Data 0 */
> +#define CPCAP_REG_ADCD1 0x0c0c /* A/D Converter Data 1 */
> +#define CPCAP_REG_ADCD2 0x0c10 /* A/D Converter Data 2 */
> +#define CPCAP_REG_ADCD3 0x0c14 /* A/D Converter Data 3 */
> +#define CPCAP_REG_ADCD4 0x0c18 /* A/D Converter Data 4 */
> +#define CPCAP_REG_ADCD5 0x0c1c /* A/D Converter Data 5 */
> +#define CPCAP_REG_ADCD6 0x0c20 /* A/D Converter Data 6 */
> +#define CPCAP_REG_ADCD7 0x0c24 /* A/D Converter Data 7 */
> +#define CPCAP_REG_ADCAL1 0x0c28 /* A/D Converter Calibration 1 */
> +#define CPCAP_REG_ADCAL2 0x0c2c /* A/D Converter Calibration 2 */
> +
> +#define CPCAP_REG_USBC1 0x0e00 /* USB Control 1 */
> +#define CPCAP_REG_USBC2 0x0e04 /* USB Control 2 */
> +#define CPCAP_REG_USBC3 0x0e08 /* USB Control 3 */
> +#define CPCAP_REG_UVIDL 0x0e0c /* ULPI Vendor ID Low */
> +#define CPCAP_REG_UVIDH 0x0e10 /* ULPI Vendor ID High */
> +#define CPCAP_REG_UPIDL 0x0e14 /* ULPI Product ID Low */
> +#define CPCAP_REG_UPIDH 0x0e18 /* ULPI Product ID High */
> +#define CPCAP_REG_UFC1 0x0e1c /* ULPI Function Control 1 */
> +#define CPCAP_REG_UFC2 0x0e20 /* ULPI Function Control 2 */
> +#define CPCAP_REG_UFC3 0x0e24 /* ULPI Function Control 3 */
> +#define CPCAP_REG_UIC1 0x0e28 /* ULPI Interface Control 1 */
> +#define CPCAP_REG_UIC2 0x0e2c /* ULPI Interface Control 2 */
> +#define CPCAP_REG_UIC3 0x0e30 /* ULPI Interface Control 3 */
> +#define CPCAP_REG_USBOTG1 0x0e34 /* USB OTG Control 1 */
> +#define CPCAP_REG_USBOTG2 0x0e38 /* USB OTG Control 2 */
> +#define CPCAP_REG_USBOTG3 0x0e3c /* USB OTG Control 3 */
> +#define CPCAP_REG_UIER1 0x0e40 /* USB Interrupt Enable Rising 1 */
> +#define CPCAP_REG_UIER2 0x0e44 /* USB Interrupt Enable Rising 2 */
> +#define CPCAP_REG_UIER3 0x0e48 /* USB Interrupt Enable Rising 3 */
> +#define CPCAP_REG_UIEF1 0x0e4c /* USB Interrupt Enable Falling 1 */
> +#define CPCAP_REG_UIEF2 0x0e50 /* USB Interrupt Enable Falling 1 */
> +#define CPCAP_REG_UIEF3 0x0e54 /* USB Interrupt Enable Falling 1 */
> +#define CPCAP_REG_UIS 0x0e58 /* USB Interrupt Status */
> +#define CPCAP_REG_UIL 0x0e5c /* USB Interrupt Latch */
> +#define CPCAP_REG_USBD 0x0e60 /* USB Debug */
> +#define CPCAP_REG_SCR1 0x0e64 /* Scratch 1 */
> +#define CPCAP_REG_SCR2 0x0e68 /* Scratch 2 */
> +#define CPCAP_REG_SCR3 0x0e6c /* Scratch 3 */
> +
> +#define CPCAP_REG_VMC 0x0eac /* Video Mux Control */
> +#define CPCAP_REG_OWDC 0x0eb0 /* One Wire Device Control */
> +#define CPCAP_REG_GPIO0 0x0eb4 /* GPIO 0 Control */
> +
> +#define CPCAP_REG_GPIO1 0x0ebc /* GPIO 1 Control */
> +
> +#define CPCAP_REG_GPIO2 0x0ec4 /* GPIO 2 Control */
> +
> +#define CPCAP_REG_GPIO3 0x0ecc /* GPIO 3 Control */
> +
> +#define CPCAP_REG_GPIO4 0x0ed4 /* GPIO 4 Control */
> +
> +#define CPCAP_REG_GPIO5 0x0edc /* GPIO 5 Control */
> +
> +#define CPCAP_REG_GPIO6 0x0ee4 /* GPIO 6 Control */
> +
> +#define CPCAP_REG_MDLC 0x1000 /* Main Display Lighting Control */
> +#define CPCAP_REG_KLC 0x1004 /* Keypad Lighting Control */
> +#define CPCAP_REG_ADLC 0x1008 /* Aux Display Lighting Control */
> +#define CPCAP_REG_REDC 0x100c /* Red Triode Control */
> +#define CPCAP_REG_GREENC 0x1010 /* Green Triode Control */
> +#define CPCAP_REG_BLUEC 0x1014 /* Blue Triode Control */
> +#define CPCAP_REG_CFC 0x1018 /* Camera Flash Control */
> +#define CPCAP_REG_ABC 0x101c /* Adaptive Boost Control */
> +#define CPCAP_REG_BLEDC 0x1020 /* Bluetooth LED Control */
> +#define CPCAP_REG_CLEDC 0x1024 /* Camera Privacy LED Control */
> +
> +#define CPCAP_REG_OW1C 0x1200 /* One Wire 1 Command */
> +#define CPCAP_REG_OW1D 0x1204 /* One Wire 1 Data */
> +#define CPCAP_REG_OW1I 0x1208 /* One Wire 1 Interrupt */
> +#define CPCAP_REG_OW1IE 0x120c /* One Wire 1 Interrupt Enable */
> +
> +#define CPCAP_REG_OW1 0x1214 /* One Wire 1 Control */
> +
> +#define CPCAP_REG_OW2C 0x1220 /* One Wire 2 Command */
> +#define CPCAP_REG_OW2D 0x1224 /* One Wire 2 Data */
> +#define CPCAP_REG_OW2I 0x1228 /* One Wire 2 Interrupt */
> +#define CPCAP_REG_OW2IE 0x122c /* One Wire 2 Interrupt Enable */
> +
> +#define CPCAP_REG_OW2 0x1234 /* One Wire 2 Control */
> +
> +#define CPCAP_REG_OW3C 0x1240 /* One Wire 3 Command */
> +#define CPCAP_REG_OW3D 0x1244 /* One Wire 3 Data */
> +#define CPCAP_REG_OW3I 0x1248 /* One Wire 3 Interrupt */
> +#define CPCAP_REG_OW3IE 0x124c /* One Wire 3 Interrupt Enable */
> +
> +#define CPCAP_REG_OW3 0x1254 /* One Wire 3 Control */
> +#define CPCAP_REG_GCAIC 0x1258 /* GCAI Clock Control */
> +#define CPCAP_REG_GCAIM 0x125c /* GCAI GPIO Mode */
> +#define CPCAP_REG_LGDIR 0x1260 /* LMR GCAI GPIO Direction */
> +#define CPCAP_REG_LGPU 0x1264 /* LMR GCAI GPIO Pull-up */
> +#define CPCAP_REG_LGPIN 0x1268 /* LMR GCAI GPIO Pin */
> +#define CPCAP_REG_LGMASK 0x126c /* LMR GCAI GPIO Mask */
> +#define CPCAP_REG_LDEB 0x1270 /* LMR Debounce Settings */
> +#define CPCAP_REG_LGDET 0x1274 /* LMR GCAI Detach Detect */
> +#define CPCAP_REG_LMISC 0x1278 /* LMR Misc Bits */
> +#define CPCAP_REG_LMACE 0x127c /* LMR Mace IC Support */
> +
> +#define CPCAP_REG_TEST 0x7c00 /* Test */
> +
> +#define CPCAP_REG_ST_TEST1 0x7d08 /* ST Test1 */
> +
> +#define CPCAP_REG_ST_TEST2 0x7d18 /* ST Test2 */
> +
> +/*
> + * Helpers for child devices to check the revision and vendor.
> + *
> + * REVISIT: No documentation for the bits below, please update
> + * to use proper names for defines when available.
> + */
> +
> +static inline int cpcap_get_revision(struct device *dev,
> + struct regmap *regmap,
> + u16 *revision)
> +{
> + unsigned int val;
> + int ret;
> +
> + ret = regmap_read(regmap, CPCAP_REG_VERSC1, &val);
> + if (ret) {
> + dev_err(dev, "Could not read revision\n");
> +
> + return ret;
> + }
> +
> + *revision = ((val >> 3) & 0x7) | ((val << 3) & 0x38);
> +
> + return 0;
> +}
> +
> +static inline int cpcap_get_vendor(struct device *dev,
> + struct regmap *regmap,
> + u16 *vendor)
> +{
> + unsigned int val;
> + int ret;
> +
> + ret = regmap_read(regmap, CPCAP_REG_VERSC1, &val);
> + if (ret) {
> + dev_err(dev, "Could not read vendor\n");
> +
> + return ret;
> + }
> +
> + *vendor = (val >> 6) & 0x7;
> +
> + return 0;
> +}
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH 1/8] ARM: dts: armada-370-rd: Utilize new DSA binding
From: Andrew Lunn @ 2017-01-03 16:36 UTC (permalink / raw)
To: Florian Fainelli
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Jason Cooper, vivien.didelot, Russell King, open list,
Rob Herring, Gregory Clement, linux-arm-kernel,
Sebastian Hesselbarth
In-Reply-To: <20170102022249.10657-2-f.fainelli@gmail.com>
> +
> + switch: switch@10 {
> + compatible = "marvell,mv88e6085";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <16>;
Hummm, a device tree question. switch@10, reg = <16>. Is there an
implicit understanding that the 10 is hex?
Andrew
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox