Re: [PATCH v2] drm: rcar-du: calculate DPLLCR to be more small jitter
Hi Morimoto-san, On Thursday, 14 December 2017 04:10:27 EET Kuninori Morimoto wrote: > Hi Laurent > > Thank you for your feedback > > >> + * NOTES > >> + * N = (n + 1), M = (m + 1), P = 2 > >> + * 2000 < fvco < 4096Mhz > > > > Are you sure that the fvco constraint is really 2kHz, and not 2GHz ? 2kHz > > - 4GHz would be a surprisingly large range. > > It is 2kHz. This is came from HW team, and indicated > on HW design sheet (?) OK, it's a surprising VCO, no issue with that :-) > >> + * Basically M=1 > > > > Why is this ? > > This is came from HW team, too. > They are assuming M=1, basically. > But yes confusable, let's remove it from comment. > m is started from 0 (= M=1), no need to explain. Sounds good to me. > >> + for (m = 0; m < 4; m++) { > >> + for (n = 119; n > 38; n--) { > >> + unsigned long long fvco = input * 2 * (n + 1) / (m + 1); > > > > This code runs for Gen3 only, so unsigned long would be enough. The rest > > of the function already relies on native support for 64-bit calculation. > > If you wanted to run this on a 32-bit CPU, you would likely need to > > do_div() for the division, and convert input to u64 to avoid integer > > overflows, otherwise the calculation will be performed on 32-bit before a > > final conversion to 64-bit. > > (snip) > > >> + if ((fvco < 2000) || > >> + (fvco > 409600ll)) > > > > No need for the inner parentheses, and you can write both conditions on a > > single line. Furthemore 4096 MHz will fit in a 32-bit number, so there's > > no need for the ll. > > Yes, but compiled by 32bit too, right ? > Without this "ll", 32bit compiler say > > warning: this decimal constant is unsigned only in ISO C90 That's right. How about 409600UL then, to force unsigned integer types ? Or possibly even better, 4096 * 1000 * 1000UL to make it more readable ? > # anyway, I will add this assumption (= used only by 64bit CPU) > # on comment to avoid future confusion > > > I think you can then drop the output >= 40 check inside the inner > > fdpll loop, as the output frequency can't be higher than 4GHz if the VCO > > frequency isn't. > > I think code has > > if (output >= 4) > > This is 400MHz, not 4GHz You're right, my bad. Maybe I should write it 400 * 1000 * 1000 :-) > >>for (fdpll = 1; fdpll < 32; fdpll++) { > >>unsigned long output; > > > > The output frequency on the line below can be calculated with > > > > output = fvco / 2 / (fdpll + 1) > > > > to avoid the multiplication by (n + 1) and division by (m + 1). > > It is nice idea to avoid extra calculation. > I will use this idea, and add extrate comment to avoid confusion Thank you. -- Regards, Laurent Pinchart
Re: [PATCH v2] drm: rcar-du: calculate DPLLCR to be more small jitter
Hi Laurent, On Thu, Dec 14, 2017 at 9:17 AM, Laurent Pinchart wrote: > On Thursday, 14 December 2017 04:10:27 EET Kuninori Morimoto wrote: >> >> + if ((fvco < 2000) || >> >> + (fvco > 409600ll)) >> > >> > No need for the inner parentheses, and you can write both conditions on a >> > single line. Furthemore 4096 MHz will fit in a 32-bit number, so there's >> > no need for the ll. >> >> Yes, but compiled by 32bit too, right ? >> Without this "ll", 32bit compiler say >> >> warning: this decimal constant is unsigned only in ISO C90 > > That's right. How about 409600UL then, to force unsigned integer types ? > Or possibly even better, 4096 * 1000 * 1000UL to make it more readable ? If it's just about making the number unsigned, and not about 64-bit arithmetic, a "U" suffix should be sufficient. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 4/4] kms++util: Add frame compare functionality
Hi Kieran, On Thu, Dec 14, 2017 at 12:10 AM, Kieran Bingham wrote: > From: Kieran Bingham > > Provide a means to compare two identically sized framebuffers. > > This basic implementation expects the two buffers to have the same > formats and sizes, and will return zero for identical frames, or a > positive float representing and average difference otherwise. an > --- a/kms++util/src/verification.cpp > +++ b/kms++util/src/verification.cpp > @@ -18,4 +18,35 @@ void save_raw_frame(IFramebuffer& fb, const char *filename) > os->write((char*)fb.map(i), fb.size(i)); > } > > +float compare_framebuffers(IFramebuffer& a, IFramebuffer& b) > +{ > + // This expects a frame to be identical, including non-visible data. > + for (i = 0; i < a.size(0) && i < b.size(0); i++) > + diff += abs(pa[i] - pb[i]); I think it's better to use "diff += abs(pa[i] - pb[i]) * abs(pa[i] - pb[i])", to penalize larger differences. See also https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio > + > + return diff / pixels; > +} Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH 0/3] Correct R-Car Gen2 critical CPU temperature
The current R-Car Gen2 device trees define the CPU critical temperature as 115°C. The R-Car hardware manuals state that Tc = –40°C to +105°C. The thermal sensor has an accuracy of ±5°C and there can be a temperature difference of 1 or 2 degrees between Tjmax and the thermal sensor due to the location of the latter. This means that 95°C is a safer value to use. This value should also apply to r8a7792 but thermal sensor support has not been added yet. Chris Paterson (3): ARM: dts: r8a7790: Correct critical CPU temperature ARM: dts: r8a7791: Correct critical CPU temperature ARM: dts: r8a7793: Correct critical CPU temperature arch/arm/boot/dts/r8a7790.dtsi | 2 +- arch/arm/boot/dts/r8a7791.dtsi | 2 +- arch/arm/boot/dts/r8a7793.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) -- 1.9.1
[PATCH 2/3] ARM: dts: r8a7791: Correct critical CPU temperature
The R-Car M2W hardware manual states that Tc = –40°C to +105°C. The thermal sensor has an accuracy of ±5°C and there can be a temperature difference of 1 or 2 degrees between Tjmax and the thermal sensor due to the location of the latter. This means that 95°C is a safer value to use. Fixes: cac68a56e34b9810 ("ARM: dts: r8a7791: enable to use thermal-zone") Signed-off-by: Chris Paterson --- arch/arm/boot/dts/r8a7791.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index dfc1c406179fbf3a..008a260f86a565c6 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -92,7 +92,7 @@ trips { cpu-crit { - temperature = <115000>; + temperature = <95000>; hysteresis = <0>; type= "critical"; }; -- 1.9.1
[PATCH 1/3] ARM: dts: r8a7790: Correct critical CPU temperature
The R-Car H2 hardware manual states that Tc = –40°C to +105°C. The thermal sensor has an accuracy of ±5°C and there can be a temperature difference of 1 or 2 degrees between Tjmax and the thermal sensor due to the location of the latter. This means that 95°C is a safer value to use. Fixes: a8b805f3606f7af7 ("ARM: dts: r8a7790: enable to use thermal-zone") Signed-off-by: Chris Paterson --- arch/arm/boot/dts/r8a7790.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 450bfc0e9796a557..ed9a68538a554001 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -168,7 +168,7 @@ trips { cpu-crit { - temperature = <115000>; + temperature = <95000>; hysteresis = <0>; type= "critical"; }; -- 1.9.1
[PATCH 3/3] ARM: dts: r8a7793: Correct critical CPU temperature
The R-Car M2N hardware manual states that Tc = –40°C to +105°C. The thermal sensor has an accuracy of ±5°C and there can be a temperature difference of 1 or 2 degrees between Tjmax and the thermal sensor due to the location of the latter. This means that 95°C is a safer value to use. Fixes: 57f9156bc620ac56 ("ARM: dts: r8a7793: enable to use thermal-zone") Signed-off-by: Chris Paterson --- arch/arm/boot/dts/r8a7793.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 61dd291d907da2f5..039b225175262e4b 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -89,7 +89,7 @@ trips { cpu-crit { - temperature = <115000>; + temperature = <95000>; hysteresis = <0>; type= "critical"; }; -- 1.9.1
RE: [PATCH 5/5] phy: renesas: rcar-gen3-usb2: add gpio handling
Hi Geert-san, > From: Geert Uytterhoeven, Sent: Wednesday, December 13, 2017 5:55 PM > > Hi Shimoda-san, > > On Wed, Dec 13, 2017 at 7:27 AM, Yoshihiro Shimoda > wrote: > > Some R-Car SoCs (e.g. R-Car D3) doesn't have dedicated pins of VBUS > > and ID. So, they may be connected to gpio pins. To handle the gpio > > pins, this patch adds the handling of VBUS and ID pins instead of > > dedicated pins. > > > > Signed-off-by: Yoshihiro Shimoda > > --- > > .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 2 + > > drivers/phy/renesas/phy-rcar-gen3-usb2.c | 77 > > -- > > 2 files changed, 72 insertions(+), 7 deletions(-) > > > > diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt > b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt > > index 99b651b..851582f 100644 > > --- a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt > > +++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt > > @@ -27,6 +27,8 @@ channel as USB OTG: > > - interrupts: interrupt specifier for the PHY. > > - vbus-supply: Phandle to a regulator that provides power to the VBUS. This > >regulator will be managed during the PHY power on/off > > sequence. > > +- renesas,vbus-gpios: use gpio to control vbus instead of dedicated pin. > > +- renesas,id-gpios: use gpio to detect id instead of dedicated pin. > > Documentation/devicetree/bindings/phy/brcm,ns2-drd-phy.txt already uses > "vbus-gpios" and "id-gpios" without vendor-specific prefixes, so perhaps > the "renesas," can be dropped? Thank you for the comments. I agree with you. So, I'll drop "renesas," in v2. Best regards, Yoshihiro Shimoda > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- > ge...@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like > that. > -- Linus Torvalds
RE: [PATCH 2/5] phy: renesas: rcar-gen3-usb2: unify OBINTEN handling
Hello! > From: Sergei Shtylyov, Sent: Wednesday, December 13, 2017 6:10 PM > > Hello! > > On 12/13/2017 9:27 AM, Yoshihiro Shimoda wrote: > > > This patch unifies the OBINTEN handling to clean-up the code. > > > > Signed-off-by: Yoshihiro Shimoda > > --- > > drivers/phy/renesas/phy-rcar-gen3-usb2.c | 23 +++ > > 1 file changed, 15 insertions(+), 8 deletions(-) > > > > diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c > > b/drivers/phy/renesas/phy-rcar-gen3-usb2.c > > index c22d65a..beeaa30 100644 > > --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c > > +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c > > @@ -147,6 +147,18 @@ static void rcar_gen3_enable_vbus_ctrl(struct > > rcar_gen3_chan *ch, int vbus) > > writel(val, usb2_base + USB2_ADPCTRL); > > } > > > > +static void rcar_gen3_enable_otg_irq(struct rcar_gen3_chan *ch, int enable) > > If it both enables and disables, rcar_gen3_control_otg_irq() would seem a > better name... Thank you for the comment! I think so. So, I'll change the name in v2. I'll also change the names of "enable_vbus_ctrl" and members of rcar_gen3_role_swap_ops in the patch 4 Best regards, Yoshihiro Shimoda > > +{ > > + void __iomem *usb2_base = ch->base; > > + u32 val = readl(usb2_base + USB2_OBINTEN); > > + > > + if (enable) > > + val |= USB2_OBINT_BITS; > > + else > > + val &= ~USB2_OBINT_BITS; > > + writel(val, usb2_base + USB2_OBINTEN); > > +} > > + > > static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) > > { > > rcar_gen3_set_linectrl(ch, 1, 1); > [...] > > MBR, Sergei
Re: [PATCH 1/3] ARM: dts: r8a7790: Correct critical CPU temperature
On Thu, Dec 14, 2017 at 10:08 AM, Chris Paterson wrote: > The R-Car H2 hardware manual states that Tc = –40°C to +105°C. The > thermal sensor has an accuracy of ±5°C and there can be a temperature > difference of 1 or 2 degrees between Tjmax and the thermal sensor due > to the location of the latter. > > This means that 95°C is a safer value to use. > > Fixes: a8b805f3606f7af7 ("ARM: dts: r8a7790: enable to use thermal-zone") > Signed-off-by: Chris Paterson Reviewed-by: Geert Uytterhoeven Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 2/3] ARM: dts: r8a7791: Correct critical CPU temperature
On Thu, Dec 14, 2017 at 10:08 AM, Chris Paterson wrote: > The R-Car M2W hardware manual states that Tc = –40°C to +105°C. The M2-W > thermal sensor has an accuracy of ±5°C and there can be a temperature > difference of 1 or 2 degrees between Tjmax and the thermal sensor due > to the location of the latter. > > This means that 95°C is a safer value to use. > > Fixes: cac68a56e34b9810 ("ARM: dts: r8a7791: enable to use thermal-zone") > Signed-off-by: Chris Paterson Reviewed-by: Geert Uytterhoeven Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 3/3] ARM: dts: r8a7793: Correct critical CPU temperature
On Thu, Dec 14, 2017 at 10:08 AM, Chris Paterson wrote: > The R-Car M2N hardware manual states that Tc = –40°C to +105°C. The M2-N > thermal sensor has an accuracy of ±5°C and there can be a temperature > difference of 1 or 2 degrees between Tjmax and the thermal sensor due > to the location of the latter. > > This means that 95°C is a safer value to use. > > Fixes: 57f9156bc620ac56 ("ARM: dts: r8a7793: enable to use thermal-zone") > Signed-off-by: Chris Paterson Reviewed-by: Geert Uytterhoeven Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 4/4] kms++util: Add frame compare functionality
Hi Geert, On 14/12/17 08:52, Geert Uytterhoeven wrote: > Hi Kieran, > > On Thu, Dec 14, 2017 at 12:10 AM, Kieran Bingham wrote: >> From: Kieran Bingham >> >> Provide a means to compare two identically sized framebuffers. >> >> This basic implementation expects the two buffers to have the same >> formats and sizes, and will return zero for identical frames, or a >> positive float representing and average difference otherwise. > > an > >> --- a/kms++util/src/verification.cpp >> +++ b/kms++util/src/verification.cpp >> @@ -18,4 +18,35 @@ void save_raw_frame(IFramebuffer& fb, const char >> *filename) >> os->write((char*)fb.map(i), fb.size(i)); >> } >> >> +float compare_framebuffers(IFramebuffer& a, IFramebuffer& b) >> +{ > >> + // This expects a frame to be identical, including non-visible data. >> + for (i = 0; i < a.size(0) && i < b.size(0); i++) >> + diff += abs(pa[i] - pb[i]); > > I think it's better to use "diff += abs(pa[i] - pb[i]) * abs(pa[i] - pb[i])", > to penalize larger differences. > > See also https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio Ah yes of course - an excellent suggestion! Thanks. >> + >> + return diff / pixels; >> +} > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- > ge...@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like > that. > -- Linus Torvalds > -- -- Kieran
Re: [PATCH v2 2/3] PM / core: Add IN_BAND_WAKEUP driver flag
Hi Ulf, On Mon, Dec 11, 2017 at 9:59 PM, Ulf Hansson wrote: > On 11 December 2017 at 11:48, Geert Uytterhoeven wrote: >> On Mon, Dec 11, 2017 at 11:24 AM, Ulf Hansson wrote: >>> On 10 December 2017 at 11:16, Geert Uytterhoeven >>> wrote: To complicate matters, some drivers may be used on SoCs where the device needs to be kept running (clock and/or power domain), and on SoCs where the device is always running. This difference is typically handled by genpd, and the device driver may not even be aware. Of course the driver can just set IN_BAND_WAKEUP regardless, (else it has to check for the presence of clocks and/or power-domains properties itself, duplicating genpd core/driver code). So what about if (IN_BAND_WAKEUP || (GENPD_FLAG_ACTIVE_WAKEUP && !OUT_BAND_WAKEUP)) { >>> >>> We don't want to suspend the device in case of IN_BAND_WAKEUP, right!? >>> ... suspend device... } >> >> Oops, inverted logic. I should not write technical emails on Sunday morning. >> >> Yes, the device must be kept awake if either IN_BAND_WAKEUP is set, or >> if GENPD_FLAG_ACTIVE_WAKEUP is set but OUT_BAND_WAKEUP isn't. > > Putting together the pieces of information received here, you have > convinced me that we should stick to use the current > GENPD_FLAG_ACTIVE_WAKEUP for now, which allows genpds to opt-in for > start dealing with in-band-wakeups. Thank you! So I'll move forward with "[PATCH v2 0/3] PM / Domain: renesas: Fix active wakeup behavior" (https://www.spinics.net/lists/linux-renesas-soc/msg19941.html) Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH 6/6] ARM: dts: r8a7743: Add TPU support
Add TPU support to SoC DT. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- arch/arm/boot/dts/r8a7743.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi index 6766c76..861e76d 100644 --- a/arch/arm/boot/dts/r8a7743.dtsi +++ b/arch/arm/boot/dts/r8a7743.dtsi @@ -1157,6 +1157,16 @@ status = "disabled"; }; + tpu: pwm@e60f { + compatible = "renesas,tpu-r8a7743", "renesas,tpu"; + reg = <0 0xe60f 0 0x148>; + clocks = <&cpg CPG_MOD 304>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 304>; + #pwm-cells = <3>; + status = "disabled"; + }; + sdhi0: sd@ee10 { compatible = "renesas,sdhi-r8a7743", "renesas,rcar-gen2-sdhi"; -- 2.7.4
[PATCH 5/6] pinctrl: sh-pfc: r8a7791: Add tpu groups and function
This patch adds tpu groups and function to r8a7743/r8a7791/r8a7793. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 42 ++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index c01ef02d..88eb8d3 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -3892,6 +3892,32 @@ static const unsigned int sdhi2_wp_mux[] = { SD2_WP_MARK, }; +/* - TPU */ +static const unsigned int tpu_to0_pins[] = { + RCAR_GP_PIN(6, 14), +}; +static const unsigned int tpu_to0_mux[] = { + TPU_TO0_MARK, +}; +static const unsigned int tpu_to1_pins[] = { + RCAR_GP_PIN(1, 17), +}; +static const unsigned int tpu_to1_mux[] = { + TPU_TO1_MARK, +}; +static const unsigned int tpu_to2_pins[] = { + RCAR_GP_PIN(1, 18), +}; +static const unsigned int tpu_to2_mux[] = { + TPU_TO2_MARK, +}; +static const unsigned int tpu_to3_pins[] = { + RCAR_GP_PIN(1, 24), +}; +static const unsigned int tpu_to3_mux[] = { + TPU_TO3_MARK, +}; + /* - SSI */ static const unsigned int ssi0_data_pins[] = { /* SDATA */ @@ -4431,7 +4457,7 @@ static const unsigned int vin2_clk_mux[] = { }; static const struct { - struct sh_pfc_pin_group common[342]; + struct sh_pfc_pin_group common[346]; struct sh_pfc_pin_group r8a779x[9]; } pinmux_groups = { .common = { @@ -4715,6 +4741,10 @@ static const struct { SH_PFC_PIN_GROUP(sdhi2_ctrl), SH_PFC_PIN_GROUP(sdhi2_cd), SH_PFC_PIN_GROUP(sdhi2_wp), + SH_PFC_PIN_GROUP(tpu_to0), + SH_PFC_PIN_GROUP(tpu_to1), + SH_PFC_PIN_GROUP(tpu_to2), + SH_PFC_PIN_GROUP(tpu_to3), SH_PFC_PIN_GROUP(ssi0_data), SH_PFC_PIN_GROUP(ssi0_data_b), SH_PFC_PIN_GROUP(ssi0129_ctrl), @@ -5247,6 +5277,13 @@ static const char * const sdhi2_groups[] = { "sdhi2_wp", }; +static const char * const tpu_groups[] = { + "tpu_to0", + "tpu_to1", + "tpu_to2", + "tpu_to3", +}; + static const char * const ssi_groups[] = { "ssi0_data", "ssi0_data_b", @@ -5327,7 +5364,7 @@ static const char * const vin2_groups[] = { }; static const struct { - struct sh_pfc_function common[57]; + struct sh_pfc_function common[58]; struct sh_pfc_function r8a779x[2]; } pinmux_functions = { .common = { @@ -5382,6 +5419,7 @@ static const struct { SH_PFC_FUNCTION(sdhi0), SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi2), + SH_PFC_FUNCTION(tpu), SH_PFC_FUNCTION(ssi), SH_PFC_FUNCTION(usb0), SH_PFC_FUNCTION(usb1), -- 2.7.4
[PATCH 1/6] ARM: shmobile: defconfig: Enable PWM
RZ/G1 and R-Car platforms have PWM timers. This patch enables PWM support by default. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- arch/arm/configs/shmobile_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index d60dbe1..578434c 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -208,6 +208,7 @@ CONFIG_STAGING_BOARD=y CONFIG_IIO=y CONFIG_AK8975=y CONFIG_PWM=y +CONFIG_PWM_RCAR=y CONFIG_PWM_RENESAS_TPU=y CONFIG_GENERIC_PHY=y CONFIG_PHY_RCAR_GEN2=y -- 2.7.4
[PATCH 0/6] Add PWM and TPU support to r8a7743
Dear All, this series includes all that is required to add PWM and TPU SoC specific support for the r8a7743. Thanks, Fabrizio Castro (6): ARM: shmobile: defconfig: Enable PWM dt-bindings: pwm: rcar: Document r8a774[35] PWM bindings ARM: dts: r8a7743: Add PWM SoC support dt-bindings: pwm: renesas-tpu: Document r8a774[35] support pinctrl: sh-pfc: r8a7791: Add tpu groups and function ARM: dts: r8a7743: Add TPU support .../devicetree/bindings/pwm/renesas,pwm-rcar.txt | 10 ++- .../devicetree/bindings/pwm/renesas,tpu-pwm.txt| 4 +- arch/arm/boot/dts/r8a7743.dtsi | 87 ++ arch/arm/configs/shmobile_defconfig| 1 + drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 42 ++- 5 files changed, 138 insertions(+), 6 deletions(-) -- 2.7.4
[PATCH 4/6] dt-bindings: pwm: renesas-tpu: Document r8a774[35] support
Document r8a774[35] specific compatible strings. No driver change is needed as the fallback compatible string "renesas,tpu" activates the right code in the driver. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index 1aadc80..16e5748 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -5,8 +5,10 @@ Required Properties: - compatible: should be one of the following. - "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller. - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. +- "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. +- "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. -- "renesas,tpu": for generic R-Car TPU PWM controller. +- "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller. - reg: Base address and length of each memory resource used by the PWM controller hardware module. -- 2.7.4
[PATCH 2/6] dt-bindings: pwm: rcar: Document r8a774[35] PWM bindings
This patch adds compatible strings specific to r8a774[35], no driver change is needed as the fallback compatible string will activate the right code. Also, this patch replaces the example with a DT snippet used for adding PWM0 support to an r8a7743 based platform. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- Dear All, the reason for replacing the example with one of a different SoC is that the new example refers to recent code from a real use case. I hope that's ok. Thanks, Fabrizio Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index 74c1180..f3bba59 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -2,6 +2,8 @@ Required Properties: - compatible: should be "renesas,pwm-rcar" and one of the following. + - "renesas,pwm-r8a7743": for RZ/G1M + - "renesas,pwm-r8a7745": for RZ/G1E - "renesas,pwm-r8a7778": for R-Car M1A - "renesas,pwm-r8a7779": for R-Car H1 - "renesas,pwm-r8a7790": for R-Car H2 @@ -17,13 +19,15 @@ Required Properties: - pinctrl-0: phandle, referring to a default pin configuration node. - pinctrl-names: Set to "default". -Example: R8A7790 (R-Car H2) PWM Timer node +Example: R8A7743 (RZ/G1M) PWM Timer node pwm0: pwm@e6e3 { - compatible = "renesas,pwm-r8a7790", "renesas,pwm-rcar"; + compatible = "renesas,pwm-r8a7743", "renesas,pwm-rcar"; reg = <0 0xe6e3 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; #pwm-cells = <2>; - clocks = <&mstp5_clks R8A7790_CLK_PWM>; pinctrl-0 = <&pwm0_pins>; pinctrl-names = "default"; }; -- 2.7.4
[PATCH 3/6] ARM: dts: r8a7743: Add PWM SoC support
Add the definitions for pwm[0123456] to the SoC .dtsi. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- arch/arm/boot/dts/r8a7743.dtsi | 77 ++ 1 file changed, 77 insertions(+) diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi index e056bc5..6766c76 100644 --- a/arch/arm/boot/dts/r8a7743.dtsi +++ b/arch/arm/boot/dts/r8a7743.dtsi @@ -1080,6 +1080,83 @@ status = "disabled"; }; + pwm0: pwm@e6e3 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e3 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm5: pwm@e6e35000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e35000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm6: pwm@e6e36000 { + compatible = "renesas,pwm-r8a7743", +"renesas,pwm-rcar"; + reg = <0 0xe6e36000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7743_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + sdhi0: sd@ee10 { compatible = "renesas,sdhi-r8a7743", "renesas,rcar-gen2-sdhi"; -- 2.7.4
[PATCH 2/4] ARM: dts: r8a7745: Add PWM SoC support
Add the definitions for pwm[0123456] to the SoC .dtsi. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- This patch depends on: * "dt-bindings: pwm: rcar: Document r8a774[35] PWM bindings" arch/arm/boot/dts/r8a7745.dtsi | 77 ++ 1 file changed, 77 insertions(+) diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi index 765a80d..b945300 100644 --- a/arch/arm/boot/dts/r8a7745.dtsi +++ b/arch/arm/boot/dts/r8a7745.dtsi @@ -966,6 +966,83 @@ status = "disabled"; }; + pwm0: pwm@e6e3 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e3 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm5: pwm@e6e35000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e35000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm6: pwm@e6e36000 { + compatible = "renesas,pwm-r8a7745", +"renesas,pwm-rcar"; + reg = <0 0xe6e36000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + sdhi0: sd@ee10 { compatible = "renesas,sdhi-r8a7745", "renesas,rcar-gen2-sdhi"; -- 2.7.4
[PATCH 0/4] Add PWM and TPU support to r8a7745
Dear All, this series includes all that is required to add PWM and TPU SoC specific support for the r8a7745. Thanks, Fabrizio Castro (4): pinctrl: sh-pfc: r8a7794: Add PWM[0123456] support ARM: dts: r8a7745: Add PWM SoC support pinctrl: sh-pfc: r8a7794: Add tpu groups and function ARM: dts: r8a7745: Add TPU support arch/arm/boot/dts/r8a7745.dtsi | 87 drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 266 +++ 2 files changed, 353 insertions(+) -- 2.7.4
[PATCH 1/4] pinctrl: sh-pfc: r8a7794: Add PWM[0123456] support
This patch adds PFC PWM[0123456] pin groups and functions, enabling PWM on the r8a7794 and r8a7745. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 165 +++ 1 file changed, 165 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c index c557bc8..dccc20a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c @@ -2546,6 +2546,109 @@ static const unsigned int msiof2_tx_b_pins[] = { static const unsigned int msiof2_tx_b_mux[] = { MSIOF2_TXD_B_MARK, }; +/* - PWM */ +static const unsigned int pwm0_pins[] = { + RCAR_GP_PIN(1, 14), +}; +static const unsigned int pwm0_mux[] = { + PWM0_MARK, +}; +static const unsigned int pwm0_b_pins[] = { + RCAR_GP_PIN(5, 3), +}; +static const unsigned int pwm0_b_mux[] = { + PWM0_B_MARK, +}; +static const unsigned int pwm1_pins[] = { + RCAR_GP_PIN(4, 5), +}; +static const unsigned int pwm1_mux[] = { + PWM1_MARK, +}; +static const unsigned int pwm1_b_pins[] = { + RCAR_GP_PIN(5, 10), +}; +static const unsigned int pwm1_b_mux[] = { + PWM1_B_MARK, +}; +static const unsigned int pwm1_c_pins[] = { + RCAR_GP_PIN(1, 18), +}; +static const unsigned int pwm1_c_mux[] = { + PWM1_C_MARK, +}; +static const unsigned int pwm2_pins[] = { + RCAR_GP_PIN(4, 10), +}; +static const unsigned int pwm2_mux[] = { + PWM2_MARK, +}; +static const unsigned int pwm2_b_pins[] = { + RCAR_GP_PIN(5, 17), +}; +static const unsigned int pwm2_b_mux[] = { + PWM2_B_MARK, +}; +static const unsigned int pwm2_c_pins[] = { + RCAR_GP_PIN(0, 13), +}; +static const unsigned int pwm2_c_mux[] = { + PWM2_C_MARK, +}; +static const unsigned int pwm3_pins[] = { + RCAR_GP_PIN(4, 13), +}; +static const unsigned int pwm3_mux[] = { + PWM3_MARK, +}; +static const unsigned int pwm3_b_pins[] = { + RCAR_GP_PIN(0, 16), +}; +static const unsigned int pwm3_b_mux[] = { + PWM3_B_MARK, +}; +static const unsigned int pwm4_pins[] = { + RCAR_GP_PIN(1, 3), +}; +static const unsigned int pwm4_mux[] = { + PWM4_MARK, +}; +static const unsigned int pwm4_b_pins[] = { + RCAR_GP_PIN(0, 21), +}; +static const unsigned int pwm4_b_mux[] = { + PWM4_B_MARK, +}; +static const unsigned int pwm5_pins[] = { + RCAR_GP_PIN(3, 30), +}; +static const unsigned int pwm5_mux[] = { + PWM5_MARK, +}; +static const unsigned int pwm5_b_pins[] = { + RCAR_GP_PIN(4, 0), +}; +static const unsigned int pwm5_b_mux[] = { + PWM5_B_MARK, +}; +static const unsigned int pwm5_c_pins[] = { + RCAR_GP_PIN(0, 10), +}; +static const unsigned int pwm5_c_mux[] = { + PWM5_C_MARK, +}; +static const unsigned int pwm6_pins[] = { + RCAR_GP_PIN(4, 8), +}; +static const unsigned int pwm6_mux[] = { + PWM6_MARK, +}; +static const unsigned int pwm6_b_pins[] = { + RCAR_GP_PIN(0, 7), +}; +static const unsigned int pwm6_b_mux[] = { + PWM6_B_MARK, +}; /* - QSPI --- */ static const unsigned int qspi_ctrl_pins[] = { /* SPCLK, SSL */ @@ -3689,6 +3792,23 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(msiof2_ss2_b), SH_PFC_PIN_GROUP(msiof2_rx_b), SH_PFC_PIN_GROUP(msiof2_tx_b), + SH_PFC_PIN_GROUP(pwm0), + SH_PFC_PIN_GROUP(pwm0_b), + SH_PFC_PIN_GROUP(pwm1), + SH_PFC_PIN_GROUP(pwm1_b), + SH_PFC_PIN_GROUP(pwm1_c), + SH_PFC_PIN_GROUP(pwm2), + SH_PFC_PIN_GROUP(pwm2_b), + SH_PFC_PIN_GROUP(pwm2_c), + SH_PFC_PIN_GROUP(pwm3), + SH_PFC_PIN_GROUP(pwm3_b), + SH_PFC_PIN_GROUP(pwm4), + SH_PFC_PIN_GROUP(pwm4_b), + SH_PFC_PIN_GROUP(pwm5), + SH_PFC_PIN_GROUP(pwm5_b), + SH_PFC_PIN_GROUP(pwm5_c), + SH_PFC_PIN_GROUP(pwm6), + SH_PFC_PIN_GROUP(pwm6_b), SH_PFC_PIN_GROUP(qspi_ctrl), SH_PFC_PIN_GROUP(qspi_data2), SH_PFC_PIN_GROUP(qspi_data4), @@ -4050,6 +4170,44 @@ static const char * const msiof2_groups[] = { "msiof2_tx_b", }; +static const char * const pwm0_groups[] = { + "pwm0", + "pwm0_b", +}; + +static const char * const pwm1_groups[] = { + "pwm1", + "pwm1_b", + "pwm1_c", +}; + +static const char * const pwm2_groups[] = { + "pwm2", + "pwm2_b", + "pwm2_c", +}; + +static const char * const pwm3_groups[] = { + "pwm3", + "pwm3_b", +}; + +static const char * const pwm4_groups[] = { + "pwm4", + "pwm4_b", +}; + +static const char * const pwm5_groups[] = { + "pwm5", + "pwm5_b", + "pwm5_c", +}; + +static const char * const pwm6_groups[] = { + "pwm6", + "pwm6_b", +}; + static const char * const qspi_groups[] = { "qspi_ctrl",
[PATCH 4/4] ARM: dts: r8a7745: Add TPU support
Add TPU support to SoC DT. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- This patch depends on: * "dt-bindings: pwm: renesas-tpu: Document r8a774[35]" arch/arm/boot/dts/r8a7745.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi index b945300..85f7875 100644 --- a/arch/arm/boot/dts/r8a7745.dtsi +++ b/arch/arm/boot/dts/r8a7745.dtsi @@ -1043,6 +1043,16 @@ status = "disabled"; }; + tpu: pwm@e60f { + compatible = "renesas,tpu-r8a7745", "renesas,tpu"; + reg = <0 0xe60f 0 0x148>; + clocks = <&cpg CPG_MOD 304>; + power-domains = <&sysc R8A7745_PD_ALWAYS_ON>; + resets = <&cpg 304>; + #pwm-cells = <3>; + status = "disabled"; + }; + sdhi0: sd@ee10 { compatible = "renesas,sdhi-r8a7745", "renesas,rcar-gen2-sdhi"; -- 2.7.4
[PATCH 3/4] pinctrl: sh-pfc: r8a7794: Add tpu groups and function
This patch adds tpu groups and function to r8a7745/r8a7794. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das --- drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 101 +++ 1 file changed, 101 insertions(+) diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c index dccc20a..455cb02 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c @@ -3254,6 +3254,79 @@ static const unsigned int sdhi2_wp_pins[] = { static const unsigned int sdhi2_wp_mux[] = { SD2_WP_MARK, }; +/* - TPU */ +static const unsigned int tpu_to0_pins[] = { + RCAR_GP_PIN(3, 31), +}; +static const unsigned int tpu_to0_mux[] = { + TPUTO0_MARK, +}; +static const unsigned int tpu_to0_b_pins[] = { + RCAR_GP_PIN(3, 30), +}; +static const unsigned int tpu_to0_b_mux[] = { + TPUTO0_B_MARK, +}; +static const unsigned int tpu_to0_c_pins[] = { + RCAR_GP_PIN(1, 18), +}; +static const unsigned int tpu_to0_c_mux[] = { + TPUTO0_C_MARK, +}; +static const unsigned int tpu_to1_pins[] = { + RCAR_GP_PIN(4, 9), +}; +static const unsigned int tpu_to1_mux[] = { + TPUTO1_MARK, +}; +static const unsigned int tpu_to1_b_pins[] = { + RCAR_GP_PIN(4, 0), +}; +static const unsigned int tpu_to1_b_mux[] = { + TPUTO1_B_MARK, +}; +static const unsigned int tpu_to1_c_pins[] = { + RCAR_GP_PIN(4, 4), +}; +static const unsigned int tpu_to1_c_mux[] = { + TPUTO1_C_MARK, +}; +static const unsigned int tpu_to2_pins[] = { + RCAR_GP_PIN(1, 3), +}; +static const unsigned int tpu_to2_mux[] = { + TPUTO2_MARK, +}; +static const unsigned int tpu_to2_b_pins[] = { + RCAR_GP_PIN(1, 0), +}; +static const unsigned int tpu_to2_b_mux[] = { + TPUTO2_B_MARK, +}; +static const unsigned int tpu_to2_c_pins[] = { + RCAR_GP_PIN(0, 22), +}; +static const unsigned int tpu_to2_c_mux[] = { + TPUTO2_C_MARK, +}; +static const unsigned int tpu_to3_pins[] = { + RCAR_GP_PIN(1, 14), +}; +static const unsigned int tpu_to3_mux[] = { + TPUTO3_MARK, +}; +static const unsigned int tpu_to3_b_pins[] = { + RCAR_GP_PIN(1, 13), +}; +static const unsigned int tpu_to3_b_mux[] = { + TPUTO3_B_MARK, +}; +static const unsigned int tpu_to3_c_pins[] = { + RCAR_GP_PIN(0, 21), +}; +static const unsigned int tpu_to3_c_mux[] = { + TPUTO3_C_MARK, +}; /* - SSI */ static const unsigned int ssi0_data_pins[] = { /* SDATA0 */ @@ -3892,6 +3965,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi2_ctrl), SH_PFC_PIN_GROUP(sdhi2_cd), SH_PFC_PIN_GROUP(sdhi2_wp), + SH_PFC_PIN_GROUP(tpu_to0), + SH_PFC_PIN_GROUP(tpu_to0_b), + SH_PFC_PIN_GROUP(tpu_to0_c), + SH_PFC_PIN_GROUP(tpu_to1), + SH_PFC_PIN_GROUP(tpu_to1_b), + SH_PFC_PIN_GROUP(tpu_to1_c), + SH_PFC_PIN_GROUP(tpu_to2), + SH_PFC_PIN_GROUP(tpu_to2_b), + SH_PFC_PIN_GROUP(tpu_to2_c), + SH_PFC_PIN_GROUP(tpu_to3), + SH_PFC_PIN_GROUP(tpu_to3_b), + SH_PFC_PIN_GROUP(tpu_to3_c), SH_PFC_PIN_GROUP(ssi0_data), SH_PFC_PIN_GROUP(ssi0129_ctrl), SH_PFC_PIN_GROUP(ssi1_data), @@ -4351,6 +4436,21 @@ static const char * const sdhi2_groups[] = { "sdhi2_wp", }; +static const char * const tpu_groups[] = { + "tpu_to0", + "tpu_to0_b", + "tpu_to0_c", + "tpu_to1", + "tpu_to1_b", + "tpu_to1_c", + "tpu_to2", + "tpu_to2_b", + "tpu_to2_c", + "tpu_to3", + "tpu_to3_b", + "tpu_to3_c", +}; + static const char * const ssi_groups[] = { "ssi0_data", "ssi0129_ctrl", @@ -4469,6 +4569,7 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(sdhi0), SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi2), + SH_PFC_FUNCTION(tpu), SH_PFC_FUNCTION(ssi), SH_PFC_FUNCTION(usb0), SH_PFC_FUNCTION(usb1), -- 2.7.4
Re: [PATCH 4/4] spi: sh-msiof: Document hardware limitations related to chip selects
On Wed, Dec 13, 2017 at 08:05:13PM +0100, Geert Uytterhoeven wrote: > + Hardware limitations related to chip selects: > +- Native chip selects are always deasserted in > + between transfers that are part of the same > + message. Use cs-gpios to work around this. Ideally the driver would be generating an error when it sees multi-transfer messages. signature.asc Description: PGP signature
Applied "spi: sh-msiof: Document hardware limitations related to chip selects" to the spi tree
The patch spi: sh-msiof: Document hardware limitations related to chip selects has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From c99182f73cce7926c623b5c1c0ff0b7954ac8d81 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Dec 2017 20:05:13 +0100 Subject: [PATCH] spi: sh-msiof: Document hardware limitations related to chip selects Guide users to maintain the proper balance between native and GPIO chip selects. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/sh-msiof.txt | 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt index bc8c16a6cfc8..80710f0f0448 100644 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt @@ -41,6 +41,16 @@ Optional properties: 0: MSIOF_SYNC 1: MSIOF_SS1 2: MSIOF_SS2 +Hardware limitations related to chip selects: + - Native chip selects are always deasserted in +between transfers that are part of the same +message. Use cs-gpios to work around this. + - All slaves using native chip selects must use the +same spi-cs-high configuration. Use cs-gpios to +work around this. + - When using GPIO chip selects, at least one native +chip select must be left unused, as it will be +driven anyway. - dmas : Must contain a list of two references to DMA specifiers, one for transmission, and one for reception. -- 2.15.1
Applied "spi: sh-msiof: Implement cs-gpios configuration" to the spi tree
The patch spi: sh-msiof: Implement cs-gpios configuration has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From b8761434bdec32fa46a644c26a12d16a9b0f58d8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Dec 2017 20:05:12 +0100 Subject: [PATCH] spi: sh-msiof: Implement cs-gpios configuration The current support for GPIO chip selects assumes the GPIOs have been configured by platform code or the boot loader. This includes pinmux setup and GPIO direction. Hence it does not work as expected when just described in DT using the "cs-gpios" property. Fix this by: 1. using devm_gpiod_get_index() to request the GPIO, and thus configure pinmux, if needed, 2. configuring the GPIO direction is the spi_master.setup() callback. Use gpio_is_valid() instead of a check on positive numbers. Note that when using GPIO chip selects, at least one native chip select must be left unused, as that native chip select will be driven anyway, and (global) native chip select polarity must be taken into account. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 66 +- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 9bdc292aa050..8aa5c7b910d9 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; + unsigned short unused_ss; bool native_cs_inited; bool native_cs_high; bool slave_aborted; @@ -547,8 +549,8 @@ static int sh_msiof_spi_setup(struct spi_device *spi) spi->cs_gpio = (uintptr_t)spi->controller_data; } - if (spi->cs_gpio >= 0) { - gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + if (gpio_is_valid(spi->cs_gpio)) { + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); return 0; } @@ -580,14 +582,20 @@ static int sh_msiof_prepare_message(struct spi_master *master, { struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); const struct spi_device *spi = msg->spi; + u32 ss, cs_high; /* Configure pins before asserting CS */ - sh_msiof_spi_set_pin_regs(p, spi->chip_select, - !!(spi->mode & SPI_CPOL), + if (gpio_is_valid(spi->cs_gpio)) { + ss = p->unused_ss; + cs_high = p->native_cs_high; + } else { + ss = spi->chip_select; + cs_high = !!(spi->mode & SPI_CS_HIGH); + } + sh_msiof_spi_set_pin_regs(p, ss, !!(spi->mode & SPI_CPOL), !!(spi->mode & SPI_CPHA), !!(spi->mode & SPI_3WIRE), - !!(spi->mode & SPI_LSB_FIRST), - !!(spi->mode & SPI_CS_HIGH)); + !!(spi->mode & SPI_LSB_FIRST), cs_high); return 0; } @@ -1091,6 +1099,45 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) } #endif +static int sh_msiof_get_cs_gpios(struct sh_msiof_spi_priv *p) +{ + struct device *dev = &p->pdev->dev; + unsigned int used_ss_mask = 0; + unsigned int cs_gpios = 0; + unsigned int num_cs, i; + int ret; + + ret = gpiod_count(dev, "cs"); + if (ret <= 0) + return 0; + + num_cs = max_t(unsigned int, ret, p->master->num_chipselect); + for (i = 0; i < num_cs; i++) { + struct gpio_desc *gpiod; + + gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS); + if (!IS_ERR(gpiod)) { + cs_gpios++; + continue; + } + + if (PTR_ERR(gpiod) != -ENOENT) + return PTR_ERR(gpiod); + + if (i >= MAX_SS) { +
Applied "spi: sh-msiof: Avoid writing to registers from spi_master.setup()" to the spi tree
The patch spi: sh-msiof: Avoid writing to registers from spi_master.setup() has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 7ff0b53c4051145d1cf992d2f60987e6447eed4f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Dec 2017 20:05:10 +0100 Subject: [PATCH] spi: sh-msiof: Avoid writing to registers from spi_master.setup() The spi_master.setup() callback must not change configuration registers, as that could corrupt I/O that is in progress for other SPI slaves. The only exception is the configuration of the native chip select polarity in SPI master mode, as a wrong chip select polarity will cause havoc during all future transfers to any other SPI slave. Hence stop writing to registers in sh_msiof_spi_setup(), unless it is the first call for a controller using a native chip select, or unless native chip select polarity has changed (note that you'll loose anyway if I/O is in progress). Even then, only do what is strictly necessary, instead of calling sh_msiof_spi_set_pin_regs(). Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 35 --- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 81a9144f5442..2704abb11ea4 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -55,6 +55,8 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; + bool native_cs_inited; + bool native_cs_high; bool slave_aborted; }; @@ -528,8 +530,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi) { struct device_node *np = spi->master->dev.of_node; struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); - - pm_runtime_get_sync(&p->pdev->dev); + u32 clr, set, tmp; if (!np) { /* @@ -539,19 +540,31 @@ static int sh_msiof_spi_setup(struct spi_device *spi) spi->cs_gpio = (uintptr_t)spi->controller_data; } - /* Configure pins before deasserting CS */ - sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), - !!(spi->mode & SPI_CPHA), - !!(spi->mode & SPI_3WIRE), - !!(spi->mode & SPI_LSB_FIRST), - !!(spi->mode & SPI_CS_HIGH)); - - if (spi->cs_gpio >= 0) + if (spi->cs_gpio >= 0) { gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + return 0; + } + if (spi_controller_is_slave(p->master)) + return 0; - pm_runtime_put(&p->pdev->dev); + if (p->native_cs_inited && + (p->native_cs_high == !!(spi->mode & SPI_CS_HIGH))) + return 0; + /* Configure native chip select mode/polarity early */ + clr = MDR1_SYNCMD_MASK; + set = MDR1_TRMD | TMDR1_PCON | MDR1_SYNCMD_SPI; + if (spi->mode & SPI_CS_HIGH) + clr |= BIT(MDR1_SYNCAC_SHIFT); + else + set |= BIT(MDR1_SYNCAC_SHIFT); + pm_runtime_get_sync(&p->pdev->dev); + tmp = sh_msiof_read(p, TMDR1) & ~clr; + sh_msiof_write(p, TMDR1, tmp | set); + pm_runtime_put(&p->pdev->dev); + p->native_cs_high = spi->mode & SPI_CS_HIGH; + p->native_cs_inited = true; return 0; } -- 2.15.1
Applied "spi: sh-msiof: Extend support to 3 native chip selects" to the spi tree
The patch spi: sh-msiof: Extend support to 3 native chip selects has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 9cce882bedd2768dc251b73f2ad86a9bfcfd9fc7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Dec 2017 20:05:11 +0100 Subject: [PATCH] spi: sh-msiof: Extend support to 3 native chip selects Currently only the MSIOF_SYNC signal can be used as a native chip select. Extend support to up to 3 native chipselects using the MSIOF_SS1 and MSIOF_SS2 signals. Inspired by a patch in the BSP by Hiromitsu Yamasaki. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/sh-msiof.txt | 6 +- drivers/spi/spi-sh-msiof.c | 18 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt index bdd83959019c..bc8c16a6cfc8 100644 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt @@ -36,7 +36,11 @@ Required properties: Optional properties: - clocks : Must contain a reference to the functional clock. -- num-cs : Total number of chip-selects (default is 1) +- num-cs : Total number of chip selects (default is 1). +Up to 3 native chip selects are supported: + 0: MSIOF_SYNC + 1: MSIOF_SS1 + 2: MSIOF_SS2 - dmas : Must contain a list of two references to DMA specifiers, one for transmission, and one for reception. diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 2704abb11ea4..9bdc292aa050 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -60,6 +60,8 @@ struct sh_msiof_spi_priv { bool slave_aborted; }; +#define MAX_SS 3 /* Maximum number of native chip selects */ + #define TMDR1 0x00/* Transmit Mode Register 1 */ #define TMDR2 0x04/* Transmit Mode Register 2 */ #define TMDR3 0x08/* Transmit Mode Register 3 */ @@ -93,6 +95,8 @@ struct sh_msiof_spi_priv { #define MDR1_XXSTP 0x0001 /* Transmission/Reception Stop on FIFO */ /* TMDR1 */ #define TMDR1_PCON 0x4000 /* Transfer Signal Connection */ +#define TMDR1_SYNCCH_MASK 0xc00 /* Synchronization Signal Channel Select */ +#define TMDR1_SYNCCH_SHIFT 26 /* 0=MSIOF_SYNC, 1=MSIOF_SS1, 2=MSIOF_SS2 */ /* TMDR2 and RMDR2 */ #define MDR2_BITLEN1(i)(((i) - 1) << 24) /* Data Size (8-32 bits) */ @@ -326,7 +330,7 @@ static u32 sh_msiof_spi_get_dtdl_and_syncdl(struct sh_msiof_spi_priv *p) return val; } -static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, +static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss, u32 cpol, u32 cpha, u32 tx_hi_z, u32 lsb_first, u32 cs_high) { @@ -344,10 +348,13 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); - if (spi_controller_is_slave(p->master)) + if (spi_controller_is_slave(p->master)) { sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); - else - sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); + } else { + sh_msiof_write(p, TMDR1, + tmp | MDR1_TRMD | TMDR1_PCON | + (ss < MAX_SS ? ss : 0) << TMDR1_SYNCCH_SHIFT); + } if (p->master->flags & SPI_MASTER_MUST_TX) { /* These bits are reserved if RX needs TX */ tmp &= ~0x; @@ -575,7 +582,8 @@ static int sh_msiof_prepare_message(struct spi_master *master, const struct spi_device *spi = msg->spi; /* Configure pins before asserting CS */ - sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL), +
Re: [PATCH/RFC 1/2] v4l: v4l2-dev: Add infrastructure to protect device unplug race
Hi Laurent, On Tue, Dec 12, 2017 at 04:42:23PM +0200, Laurent Pinchart wrote: ... > > > diff --git a/drivers/media/v4l2-core/v4l2-dev.c > > > b/drivers/media/v4l2-core/v4l2-dev.c index c647ba648805..c73c6d49e7cf > > > 100644 > > > --- a/drivers/media/v4l2-core/v4l2-dev.c > > > +++ b/drivers/media/v4l2-core/v4l2-dev.c > > > @@ -156,6 +156,52 @@ void video_device_release_empty(struct video_device > > > *vdev)> > > > } > > > EXPORT_SYMBOL(video_device_release_empty); > > > > > > +int video_device_enter(struct video_device *vdev) > > > +{ > > > + bool unplugged; > > > + > > > + spin_lock(&vdev->unplug_lock); > > > + unplugged = vdev->unplugged; > > > + if (!unplugged) > > > + vdev->access_refcount++; > > > + spin_unlock(&vdev->unplug_lock); > > > + > > > + return unplugged ? -ENODEV : 0; > > > +} > > > +EXPORT_SYMBOL_GPL(video_device_enter); > > > + > > > +void video_device_exit(struct video_device *vdev) > > > +{ > > > + bool wake_up; > > > + > > > + spin_lock(&vdev->unplug_lock); > > > + WARN_ON(--vdev->access_refcount < 0); > > > + wake_up = vdev->access_refcount == 0; > > > + spin_unlock(&vdev->unplug_lock); > > > + > > > + if (wake_up) > > > + wake_up(&vdev->unplug_wait); > > > +} > > > +EXPORT_SYMBOL_GPL(video_device_exit); > > > > Is there a need to export the two, i.e. wouldn't you only call them from > > the framework, or the same module? > > There could be a need to call these functions from entry points that are not > controlled by the V4L2 core, such as sysfs or debugfs. We could keep the > functions internal for now and only export them when the need arises, but if > we want to document how drivers need to handle race conditions between device > access and device unbind, we need to have them exported. Ack. > > > > + > > > +void video_device_unplug(struct video_device *vdev) > > > +{ > > > + bool unplug_blocked; > > > + > > > + spin_lock(&vdev->unplug_lock); > > > + unplug_blocked = vdev->access_refcount > 0; > > > + vdev->unplugged = true; > > > > Shouldn't this be set to false in video_register_device()? > > Yes it should. I currently rely on the fact that the memory is zeroed when > allocated, but I shouldn't. I'll fix that. > > > > + spin_unlock(&vdev->unplug_lock); > > > + > > > + if (!unplug_blocked) > > > + return; > > > > Not necessary, wait_event_timeout() handles this already. > > I'll fix this as well. > > > > + > > > + if (!wait_event_timeout(vdev->unplug_wait, !vdev->access_refcount, > > > + msecs_to_jiffies(15))) > > > + WARN(1, "Timeout waiting for device access to complete\n"); > > > > Why a timeout? Does this get somehow less problematic over time? :-) > > Not quite :-) This should never happen, but driver and/or core bugs could > cause a timeout. In that case I think proceeding after a timeout is a better > option than deadlocking forever. This also depends on the frame rate; you could have a very low frame rate configured on a sensor and the device could be actually in middle of a DMA operation while the timeout is hit. I'm not sure if there's a number that can be said to be safe here. Wouldn't it be better to kill the user space process using the device instead? Naturally the wait will have to be interruptible. ... > > > @@ -221,6 +228,12 @@ struct video_device > > > > > > u32 device_caps; > > > > > > + /* unplug handling */ > > > + bool unplugged; > > > + int access_refcount; > > > > Could you use refcount_t instead, to avoid integer overflow issues? > > I'd love to, but refcount_t has no provision for refcounts that start at 0. > > void refcount_inc(refcount_t *r) > { > WARN_ONCE(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use- > after-free.\n"); > } > EXPORT_SYMBOL(refcount_inc); Ah. I wonder if you could simply initialise in probe and decrement it again in remove? You could use refcount_inc_not_zero directly, too. > > > > + spinlock_t unplug_lock; > > > + wait_queue_head_t unplug_wait; > > > + > > > /* sysfs */ > > > struct device dev; > > > struct cdev *cdev; -- Kind regards, Sakari Ailus sakari.ai...@linux.intel.com
Re: [PATCH v2 1/3] clk: renesas: mstp: Keep wakeup sources active during system suspend
On 9 November 2017 at 14:27, Geert Uytterhoeven wrote: > If a device is part of the CPG/MSTP Clock Domain and to be used as a > wakeup source, it must be kept active during system suspend. > > Currently this is handled in device-specific drivers by explicitly > increasing the use count of the module clock when the device is > configured as a wakeup source. However, the proper way to prevent the > device from being stopped is to inform this requirement to the genpd > core, by setting the GENPD_FLAG_ACTIVE_WAKEUP flag. > > Note that this will only affect devices configured as wakeup sources. > > Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Kind regards Uffe > --- > v2: > - Integrate "clk: renesas: mstp: Use GENPD_FLAG_ACTIVE_WAKEUP", > --- > drivers/clk/renesas/clk-mstp.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c > index 500a9e4e03c48957..0b222197a4576fd7 100644 > --- a/drivers/clk/renesas/clk-mstp.c > +++ b/drivers/clk/renesas/clk-mstp.c > @@ -344,7 +344,7 @@ void __init cpg_mstp_add_clk_domain(struct device_node > *np) > return; > > pd->name = np->name; > - pd->flags = GENPD_FLAG_PM_CLK; > + pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; > pd->attach_dev = cpg_mstp_attach_dev; > pd->detach_dev = cpg_mstp_detach_dev; > pm_genpd_init(pd, &pm_domain_always_on_gov, false); > -- > 2.7.4 >
Re: [PATCH v2 2/3] clk: renesas: cpg-mssr: Keep wakeup sources active during system suspend
On 9 November 2017 at 14:27, Geert Uytterhoeven wrote: > If a device is part of the CPG/MSSR Clock Domain and to be used as a > wakeup source, it must be kept active during system suspend. > > Currently this is handled in device-specific drivers by explicitly > increasing the use count of the module clock when the device is > configured as a wakeup source. However, the proper way to prevent the > device from being stopped is to inform this requirement to the genpd > core, by setting the GENPD_FLAG_ACTIVE_WAKEUP flag. > > Note that this will only affect devices configured as wakeup sources. > > Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Kind regards Uffe > --- > v2: > - Integrate "clk: renesas: cpg-mssr: Use GENPD_FLAG_ACTIVE_WAKEUP", > --- > drivers/clk/renesas/renesas-cpg-mssr.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c > b/drivers/clk/renesas/renesas-cpg-mssr.c > index e580a5e6346c2533..99699b715d7cf2de 100644 > --- a/drivers/clk/renesas/renesas-cpg-mssr.c > +++ b/drivers/clk/renesas/renesas-cpg-mssr.c > @@ -500,7 +500,7 @@ static int __init cpg_mssr_add_clk_domain(struct device > *dev, > > genpd = &pd->genpd; > genpd->name = np->name; > - genpd->flags = GENPD_FLAG_PM_CLK; > + genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; > genpd->attach_dev = cpg_mssr_attach_dev; > genpd->detach_dev = cpg_mssr_detach_dev; > pm_genpd_init(genpd, &pm_domain_always_on_gov, false); > -- > 2.7.4 >
Re: [PATCH v2 3/3] soc: renesas: rcar-sysc: Keep wakeup sources active during system suspend
On 9 November 2017 at 14:27, Geert Uytterhoeven wrote: > If an R-Car SYSC slave device is part of the CPG/MSTP or CPG/MSSR Clock > Domain and to be used as a wakeup source, it must be kept active during > system suspend. > > Currently this is handled in device-specific drivers by explicitly > increasing the use count of the module clock when the device is > configured as a wakeup source. However, the proper way to prevent the > device from being stopped is to inform this requirement to the genpd > core, by setting the GENPD_FLAG_ACTIVE_WAKEUP flag. > > Note that this will only affect devices configured as wakeup sources. > > Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Kind regards Uffe > --- > v2: > - Integrate "soc: renesas: rcar-sysc: Use GENPD_FLAG_ACTIVE_WAKEUP", > --- > drivers/soc/renesas/rcar-sysc.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c > index c8406e81640f6560..ac4df1c43b2fbdbe 100644 > --- a/drivers/soc/renesas/rcar-sysc.c > +++ b/drivers/soc/renesas/rcar-sysc.c > @@ -224,7 +224,7 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd > *pd) > > if (!(pd->flags & (PD_CPU | PD_SCU))) { > /* Enable Clock Domain for I/O devices */ > - genpd->flags |= GENPD_FLAG_PM_CLK; > + genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; > if (has_cpg_mstp) { > genpd->attach_dev = cpg_mstp_attach_dev; > genpd->detach_dev = cpg_mstp_detach_dev; > -- > 2.7.4 >
Re: [PATCH v2 2/3] PM / core: Add IN_BAND_WAKEUP driver flag
On 14 December 2017 at 11:52, Geert Uytterhoeven wrote: > Hi Ulf, > > On Mon, Dec 11, 2017 at 9:59 PM, Ulf Hansson wrote: >> On 11 December 2017 at 11:48, Geert Uytterhoeven >> wrote: >>> On Mon, Dec 11, 2017 at 11:24 AM, Ulf Hansson >>> wrote: On 10 December 2017 at 11:16, Geert Uytterhoeven wrote: > To complicate matters, some drivers may be used on SoCs where the device > needs to be kept running (clock and/or power domain), and on SoCs where > the > device is always running. This difference is typically handled by genpd, > and the device driver may not even be aware. Of course the driver can just > set IN_BAND_WAKEUP regardless, (else it has to check for the presence of > clocks and/or power-domains properties itself, duplicating genpd > core/driver code). > > So what about > > if (IN_BAND_WAKEUP || > (GENPD_FLAG_ACTIVE_WAKEUP && !OUT_BAND_WAKEUP)) { We don't want to suspend the device in case of IN_BAND_WAKEUP, right!? > ... suspend device... > } >>> >>> Oops, inverted logic. I should not write technical emails on Sunday morning. >>> >>> Yes, the device must be kept awake if either IN_BAND_WAKEUP is set, or >>> if GENPD_FLAG_ACTIVE_WAKEUP is set but OUT_BAND_WAKEUP isn't. >> >> Putting together the pieces of information received here, you have >> convinced me that we should stick to use the current >> GENPD_FLAG_ACTIVE_WAKEUP for now, which allows genpds to opt-in for >> start dealing with in-band-wakeups. > > Thank you! > > So I'll move forward with "[PATCH v2 0/3] PM / Domain: renesas: Fix active > wakeup behavior" > (https://www.spinics.net/lists/linux-renesas-soc/msg19941.html) Yes! I just added my reviewed-by tag to these. Kind regards Uffe
Re: [PATCH v9 07/28] rcar-vin: change name of video device
On Fri, Dec 08, 2017 at 10:17:36AM +0200, Laurent Pinchart wrote: > Hi Niklas, > > (CC'ing Sakari) > > Thank you for the patch. > > On Friday, 8 December 2017 03:08:21 EET Niklas Söderlund wrote: > > The rcar-vin driver needs to be part of a media controller to support > > Gen3. Give each VIN instance a unique name so it can be referenced from > > userspace. > > > > Signed-off-by: Niklas Söderlund > > Reviewed-by: Kieran Bingham > > Reviewed-by: Hans Verkuil > > --- > > drivers/media/platform/rcar-vin/rcar-v4l2.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c > > b/drivers/media/platform/rcar-vin/rcar-v4l2.c index > > 59ec6d3d119590aa..19de99133f048960 100644 > > --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c > > +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c > > @@ -876,7 +876,8 @@ int rvin_v4l2_register(struct rvin_dev *vin) > > vdev->fops = &rvin_fops; > > vdev->v4l2_dev = &vin->v4l2_dev; > > vdev->queue = &vin->queue; > > - strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); > > + snprintf(vdev->name, sizeof(vdev->name), "%s %s", KBUILD_MODNAME, > > +dev_name(vin->dev)); > > Do we need the module name here ? How about calling them "%s output", > dev_name(vin->dev) to emphasize the fact that this is a video node and not a > VIN subdev ? This is what the omap3isp and vsp1 drivers do. > > We're suffering a bit from the fact that V4L2 has never standardized a naming > scheme for the devices. It wouldn't be fair to ask you to fix that as a > prerequisite to get the VIN driver merged, but we clearly have to work on > that > at some point. Agreed, this needs to be stable and I think aligning to what omap3isp or vsp1 do would be a good fix here. -- Sakari Ailus e-mail: sakari.ai...@iki.fi
Re: [PATCH v2 2/3] PM / core: Add IN_BAND_WAKEUP driver flag
Hi Ulf, On Thu, Dec 14, 2017 at 3:13 PM, Ulf Hansson wrote: > On 14 December 2017 at 11:52, Geert Uytterhoeven wrote: >> On Mon, Dec 11, 2017 at 9:59 PM, Ulf Hansson wrote: >>> On 11 December 2017 at 11:48, Geert Uytterhoeven >>> wrote: On Mon, Dec 11, 2017 at 11:24 AM, Ulf Hansson wrote: > On 10 December 2017 at 11:16, Geert Uytterhoeven > wrote: >> To complicate matters, some drivers may be used on SoCs where the device >> needs to be kept running (clock and/or power domain), and on SoCs where >> the >> device is always running. This difference is typically handled by genpd, >> and the device driver may not even be aware. Of course the driver can >> just >> set IN_BAND_WAKEUP regardless, (else it has to check for the presence of >> clocks and/or power-domains properties itself, duplicating genpd >> core/driver code). >> >> So what about >> >> if (IN_BAND_WAKEUP || >> (GENPD_FLAG_ACTIVE_WAKEUP && !OUT_BAND_WAKEUP)) { > > We don't want to suspend the device in case of IN_BAND_WAKEUP, right!? > >> ... suspend device... >> } Oops, inverted logic. I should not write technical emails on Sunday morning. Yes, the device must be kept awake if either IN_BAND_WAKEUP is set, or if GENPD_FLAG_ACTIVE_WAKEUP is set but OUT_BAND_WAKEUP isn't. >>> >>> Putting together the pieces of information received here, you have >>> convinced me that we should stick to use the current >>> GENPD_FLAG_ACTIVE_WAKEUP for now, which allows genpds to opt-in for >>> start dealing with in-band-wakeups. >> >> Thank you! >> >> So I'll move forward with "[PATCH v2 0/3] PM / Domain: renesas: Fix active >> wakeup behavior" >> (https://www.spinics.net/lists/linux-renesas-soc/msg19941.html) > > Yes! I just added my reviewed-by tag to these. Thanks a lot! Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: arm64: unhandled level 0 translation fault
Hi Catalin, Will, Dave, On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven wrote: > During userspace (Debian jessie NFS root) boot on arm64: > > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x0008, > esr 0x9204, in dash[adf77000+1a000] > CPU: 0 PID: 1083 Comm: rpcbind Not tainted > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51 > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ > (DT) This is a quad Cortex A57. > pstate: 8000 (Nzcv daif -PAN -UAO) > pc : 0xadf8a51c > lr : 0xadf8ac08 > sp : cffeac00 > x29: cffeac00 x28: adfa1000 > x27: cffebf7c x26: cffead20 > x25: cea1c5f0 x24: > x23: adfa1000 x22: adfa1000 > x21: x20: 0008 > x19: x18: cffeb500 > x17: a22babfc x16: adfa1ae8 > x15: a2363588 x14: > x13: 0020 x12: 0010 > x11: 0101010101010101 x10: adfa1000 > x9 : ff81 x8 : adfa2000 > x7 : x6 : > x5 : adfa2338 x4 : adfa2000 > x3 : adfa2338 x2 : > x1 : adfa28b0 x0 : adfa4c30 > > Sometimes it happens with other processes, but the main address, esr, and > pstate values are always the same. > > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers > releases, so the last time was two weeks ago), but never saw the issue > before until today, so probably v4.15-rc1 is OK. > Unfortunately it doesn't happen during every boot, which makes it > cumbersome to bisect. > > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that, > and even without today's arm64/for-next/core merged in, I still managed to > reproduce the issue, so I believe it was introduced in v4.15-rc2 or > v4.15-rc3. > > Once, when the kernel message above wasn't shown, I got an error from > userspace, which may be related: > *** Error in `/bin/sh': free(): invalid pointer: 0xdd970988 *** With more boots (10 instead of 6) to declare a kernel good, I bisected this to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD state after signals"). Reverting that commit on top of v4.15-rc3 fixed the issue for me. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: arm64: unhandled level 0 translation fault
Hi Geert, On Thu, Dec 14, 2017 at 03:34:50PM +0100, Geert Uytterhoeven wrote: > On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven > wrote: > > During userspace (Debian jessie NFS root) boot on arm64: > > > > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x0008, > > esr 0x9204, in dash[adf77000+1a000] > > CPU: 0 PID: 1083 Comm: rpcbind Not tainted > > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51 > > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ > > (DT) > > This is a quad Cortex A57. It's so bizarre that nobody else is running into this! > > pstate: 8000 (Nzcv daif -PAN -UAO) > > pc : 0xadf8a51c > > lr : 0xadf8ac08 > > sp : cffeac00 > > x29: cffeac00 x28: adfa1000 > > x27: cffebf7c x26: cffead20 > > x25: cea1c5f0 x24: > > x23: adfa1000 x22: adfa1000 > > x21: x20: 0008 > > x19: x18: cffeb500 > > x17: a22babfc x16: adfa1ae8 > > x15: a2363588 x14: > > x13: 0020 x12: 0010 > > x11: 0101010101010101 x10: adfa1000 > > x9 : ff81 x8 : adfa2000 > > x7 : x6 : > > x5 : adfa2338 x4 : adfa2000 > > x3 : adfa2338 x2 : > > x1 : adfa28b0 x0 : adfa4c30 > > > > Sometimes it happens with other processes, but the main address, esr, and > > pstate values are always the same. > > > > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers > > releases, so the last time was two weeks ago), but never saw the issue > > before until today, so probably v4.15-rc1 is OK. > > Unfortunately it doesn't happen during every boot, which makes it > > cumbersome to bisect. > > > > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that, > > and even without today's arm64/for-next/core merged in, I still managed to > > reproduce the issue, so I believe it was introduced in v4.15-rc2 or > > v4.15-rc3. > > > > Once, when the kernel message above wasn't shown, I got an error from > > userspace, which may be related: > > *** Error in `/bin/sh': free(): invalid pointer: 0xdd970988 *** > > With more boots (10 instead of 6) to declare a kernel good, I bisected this > to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD > state after signals"). > > Reverting that commit on top of v4.15-rc3 fixed the issue for me. Thanks for persevering with the bisect. We'll get this fixed ASAP, but we'll be relying on you to test the patch we come up with. Cheers, Will
Re: arm64: unhandled level 0 translation fault
On Thu, Dec 14, 2017 at 02:34:50PM +, Geert Uytterhoeven wrote: > Hi Catalin, Will, Dave, > > On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven > wrote: > > During userspace (Debian jessie NFS root) boot on arm64: > > > > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x0008, > > esr 0x9204, in dash[adf77000+1a000] > > CPU: 0 PID: 1083 Comm: rpcbind Not tainted > > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51 > > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ > > (DT) > > This is a quad Cortex A57. > > > pstate: 8000 (Nzcv daif -PAN -UAO) > > pc : 0xadf8a51c > > lr : 0xadf8ac08 > > sp : cffeac00 > > x29: cffeac00 x28: adfa1000 > > x27: cffebf7c x26: cffead20 > > x25: cea1c5f0 x24: > > x23: adfa1000 x22: adfa1000 > > x21: x20: 0008 > > x19: x18: cffeb500 > > x17: a22babfc x16: adfa1ae8 > > x15: a2363588 x14: > > x13: 0020 x12: 0010 > > x11: 0101010101010101 x10: adfa1000 > > x9 : ff81 x8 : adfa2000 > > x7 : x6 : > > x5 : adfa2338 x4 : adfa2000 > > x3 : adfa2338 x2 : > > x1 : adfa28b0 x0 : adfa4c30 > > > > Sometimes it happens with other processes, but the main address, esr, and > > pstate values are always the same. > > > > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers > > releases, so the last time was two weeks ago), but never saw the issue > > before until today, so probably v4.15-rc1 is OK. > > Unfortunately it doesn't happen during every boot, which makes it > > cumbersome to bisect. > > > > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that, > > and even without today's arm64/for-next/core merged in, I still managed to > > reproduce the issue, so I believe it was introduced in v4.15-rc2 or > > v4.15-rc3. > > > > Once, when the kernel message above wasn't shown, I got an error from > > userspace, which may be related: > > *** Error in `/bin/sh': free(): invalid pointer: 0xdd970988 *** > > With more boots (10 instead of 6) to declare a kernel good, I bisected this > to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD > state after signals"). > > Reverting that commit on top of v4.15-rc3 fixed the issue for me. Good work on the bisect -- I'll need to have a think about this... That patch fixes a genuine problem so we can't just revert it. What if you revert _just this function_ back to what it was in v4.14? Cheers ---Dave IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Re: [PATCH v2 1/3] clk: renesas: mstp: Keep wakeup sources active during system suspend
On Thu, Dec 14, 2017 at 3:10 PM, Ulf Hansson wrote: > On 9 November 2017 at 14:27, Geert Uytterhoeven > wrote: >> If a device is part of the CPG/MSTP Clock Domain and to be used as a >> wakeup source, it must be kept active during system suspend. >> >> Currently this is handled in device-specific drivers by explicitly >> increasing the use count of the module clock when the device is >> configured as a wakeup source. However, the proper way to prevent the >> device from being stopped is to inform this requirement to the genpd >> core, by setting the GENPD_FLAG_ACTIVE_WAKEUP flag. >> >> Note that this will only affect devices configured as wakeup sources. >> >> Signed-off-by: Geert Uytterhoeven > > Reviewed-by: Ulf Hansson Thank you, queued in clk-renesas-for-v4.16. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH v2 2/3] clk: renesas: cpg-mssr: Keep wakeup sources active during system suspend
On Thu, Dec 14, 2017 at 3:11 PM, Ulf Hansson wrote: > On 9 November 2017 at 14:27, Geert Uytterhoeven > wrote: >> If a device is part of the CPG/MSSR Clock Domain and to be used as a >> wakeup source, it must be kept active during system suspend. >> >> Currently this is handled in device-specific drivers by explicitly >> increasing the use count of the module clock when the device is >> configured as a wakeup source. However, the proper way to prevent the >> device from being stopped is to inform this requirement to the genpd >> core, by setting the GENPD_FLAG_ACTIVE_WAKEUP flag. >> >> Note that this will only affect devices configured as wakeup sources. >> >> Signed-off-by: Geert Uytterhoeven > > Reviewed-by: Ulf Hansson Thank you, queued in clk-renesas-for-v4.16. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH v9 07/28] rcar-vin: change name of video device
Hi Sakari, On Thursday, 14 December 2017 16:25:00 EET Sakari Ailus wrote: > On Fri, Dec 08, 2017 at 10:17:36AM +0200, Laurent Pinchart wrote: > > On Friday, 8 December 2017 03:08:21 EET Niklas Söderlund wrote: > > > The rcar-vin driver needs to be part of a media controller to support > > > Gen3. Give each VIN instance a unique name so it can be referenced from > > > userspace. > > > > > > Signed-off-by: Niklas Söderlund > > > Reviewed-by: Kieran Bingham > > > Reviewed-by: Hans Verkuil > > > --- > > > > > > drivers/media/platform/rcar-vin/rcar-v4l2.c | 3 ++- > > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c > > > b/drivers/media/platform/rcar-vin/rcar-v4l2.c index > > > 59ec6d3d119590aa..19de99133f048960 100644 > > > --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c > > > +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c > > > @@ -876,7 +876,8 @@ int rvin_v4l2_register(struct rvin_dev *vin) > > > > > > vdev->fops = &rvin_fops; > > > vdev->v4l2_dev = &vin->v4l2_dev; > > > vdev->queue = &vin->queue; > > > > > > - strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); > > > + snprintf(vdev->name, sizeof(vdev->name), "%s %s", KBUILD_MODNAME, > > > + dev_name(vin->dev)); > > > > Do we need the module name here ? How about calling them "%s output", > > dev_name(vin->dev) to emphasize the fact that this is a video node and not > > a VIN subdev ? This is what the omap3isp and vsp1 drivers do. > > > > We're suffering a bit from the fact that V4L2 has never standardized a > > naming scheme for the devices. It wouldn't be fair to ask you to fix that > > as a prerequisite to get the VIN driver merged, but we clearly have to > > work on that at some point. > > Agreed, this needs to be stable and I think aligning to what omap3isp or > vsp1 do would be a good fix here. Even omap3isp and vsp1 are not fully aligned, so I think we need to design a naming policy and document it. -- Regards, Laurent Pinchart
Re: arm64: unhandled level 0 translation fault
Hi Dave, On Thu, Dec 14, 2017 at 4:24 PM, Dave P Martin wrote: > On Thu, Dec 14, 2017 at 02:34:50PM +, Geert Uytterhoeven wrote: >> On Tue, Dec 12, 2017 at 11:20 AM, Geert Uytterhoeven >> wrote: >> > During userspace (Debian jessie NFS root) boot on arm64: >> > >> > rpcbind[1083]: unhandled level 0 translation fault (11) at 0x0008, >> > esr 0x9204, in dash[adf77000+1a000] >> > CPU: 0 PID: 1083 Comm: rpcbind Not tainted >> > 4.15.0-rc3-arm64-renesas-02176-g14f9a1826e48e355 #51 >> > Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 >> > ES2.0+ (DT) >> >> This is a quad Cortex A57. >> >> > pstate: 8000 (Nzcv daif -PAN -UAO) >> > pc : 0xadf8a51c >> > lr : 0xadf8ac08 >> > sp : cffeac00 >> > x29: cffeac00 x28: adfa1000 >> > x27: cffebf7c x26: cffead20 >> > x25: cea1c5f0 x24: >> > x23: adfa1000 x22: adfa1000 >> > x21: x20: 0008 >> > x19: x18: cffeb500 >> > x17: a22babfc x16: adfa1ae8 >> > x15: a2363588 x14: >> > x13: 0020 x12: 0010 >> > x11: 0101010101010101 x10: adfa1000 >> > x9 : ff81 x8 : adfa2000 >> > x7 : x6 : >> > x5 : adfa2338 x4 : adfa2000 >> > x3 : adfa2338 x2 : >> > x1 : adfa28b0 x0 : adfa4c30 >> > >> > Sometimes it happens with other processes, but the main address, esr, and >> > pstate values are always the same. >> > >> > I regularly run arm64/for-next/core (through bi-weekly renesas-drivers >> > releases, so the last time was two weeks ago), but never saw the issue >> > before until today, so probably v4.15-rc1 is OK. >> > Unfortunately it doesn't happen during every boot, which makes it >> > cumbersome to bisect. >> > >> > My first guess was UNMAP_KERNEL_AT_EL0, but even after disabling that, >> > and even without today's arm64/for-next/core merged in, I still managed to >> > reproduce the issue, so I believe it was introduced in v4.15-rc2 or >> > v4.15-rc3. >> > >> > Once, when the kernel message above wasn't shown, I got an error from >> > userspace, which may be related: >> > *** Error in `/bin/sh': free(): invalid pointer: 0xdd970988 *** >> >> With more boots (10 instead of 6) to declare a kernel good, I bisected this >> to commit 9de52a755cfb6da5 ("arm64: fpsimd: Fix failure to restore FPSIMD >> state after signals"). >> >> Reverting that commit on top of v4.15-rc3 fixed the issue for me. > > Good work on the bisect -- I'll need to have a think about this... > > That patch fixes a genuine problem so we can't just revert it. > > What if you revert _just this function_ back to what it was in v4.14? With fpsimd_update_current_state() reverted to v4.14, and - __this_cpu_write(fpsimd_last_state, st); + __this_cpu_write(fpsimd_last_state.st, st); to make it build, the problem seems to be fixed, too. Thanks! Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH/RFC v2 09/15] adv748x: csi2: add module param for virtual channel
The hardware can output on any of the 4 (0-3) Virtual Channels of the CSI-2 bus. Add a module parameter each for TXA and TXB to allow the user to specify which channel should be used. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-core.c | 10 ++ drivers/media/i2c/adv748x/adv748x-csi2.c | 2 +- drivers/media/i2c/adv748x/adv748x.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index fd92c9e4b519d2c5..3cad52532ead2e34 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -31,6 +31,9 @@ #include "adv748x.h" +static unsigned int txavc; +static unsigned int txbvc; + /* - * Register manipulation */ @@ -747,6 +750,7 @@ static int adv748x_probe(struct i2c_client *client, } /* Initialise TXA */ + state->txa.vc = txavc; ret = adv748x_csi2_init(state, &state->txa); if (ret) { adv_err(state, "Failed to probe TXA"); @@ -754,6 +758,7 @@ static int adv748x_probe(struct i2c_client *client, } /* Initialise TXB */ + state->txb.vc = txbvc; ret = adv748x_csi2_init(state, &state->txb); if (ret) { adv_err(state, "Failed to probe TXB"); @@ -824,6 +829,11 @@ static struct i2c_driver adv748x_driver = { module_i2c_driver(adv748x_driver); +module_param(txavc, uint, 0644); +MODULE_PARM_DESC(txavc, "Virtual Channel for TXA"); +module_param(txbvc, uint, 0644); +MODULE_PARM_DESC(txbvc, "Virtual Channel for TXB"); + MODULE_AUTHOR("Kieran Bingham "); MODULE_DESCRIPTION("ADV748X video decoder"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 820b44ed56a8679f..2a5dff8c571013bf 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -281,7 +281,7 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) } /* Initialise the virtual channel */ - adv748x_csi2_set_virtual_channel(tx, 0); + adv748x_csi2_set_virtual_channel(tx, tx->vc); adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, MEDIA_ENT_F_UNKNOWN, diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 6789e2f3bc8c2b49..f6e40ee3924e8f12 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -92,6 +92,7 @@ enum adv748x_csi2_pads { struct adv748x_csi2 { struct adv748x_state *state; + unsigned int vc; struct v4l2_mbus_framefmt format; unsigned int page; -- 2.15.1
[PATCH/RFC v2 15/15] adv748x: afe: add routing support
The adv748x afe have eight analog sink pads, currently one of them is chosen to be the active route based on device tree configuration. Whit the new routeing API it's possible to control which of the eight sink pads are routed to the source pad. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-afe.c | 66 + 1 file changed, 66 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c index 5188178588c9067d..5dda85c707f6efd7 100644 --- a/drivers/media/i2c/adv748x/adv748x-afe.c +++ b/drivers/media/i2c/adv748x/adv748x-afe.c @@ -43,6 +43,9 @@ #define ADV748X_AFE_STD_PAL_SECAM 0xe #define ADV748X_AFE_STD_PAL_SECAM_PED 0xf +#define ADV748X_AFE_ROUTES_MAX ((ADV748X_AFE_SINK_AIN7 - \ + ADV748X_AFE_SINK_AIN0) + 1) + static int adv748x_afe_read_ro_map(struct adv748x_state *state, u8 reg) { int ret; @@ -386,10 +389,73 @@ static int adv748x_afe_set_format(struct v4l2_subdev *sd, return 0; } + +static int adv748x_afe_get_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_routing *routing) +{ + struct adv748x_afe *afe = adv748x_sd_to_afe(sd); + struct v4l2_subdev_route *r = routing->routes; + unsigned int i; + + /* There are one possible route from each sink */ + if (routing->num_routes < ADV748X_AFE_ROUTES_MAX) { + routing->num_routes = ADV748X_AFE_ROUTES_MAX; + return -ENOSPC; + } + + routing->num_routes = ADV748X_AFE_ROUTES_MAX; + + for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) { + r->sink_pad = i; + r->sink_stream = 0; + r->source_pad = ADV748X_AFE_SOURCE; + r->source_stream = 0; + r->flags = afe->input == i ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0; + r++; + } + + return 0; +} + +static int adv748x_afe_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_routing *routing) +{ + struct adv748x_afe *afe = adv748x_sd_to_afe(sd); + struct v4l2_subdev_route *r = routing->routes; + int input = -1; + unsigned int i; + + if (routing->num_routes > ADV748X_AFE_ROUTES_MAX) + return -ENOSPC; + + for (i = 0; i < routing->num_routes; i++) { + if (r->sink_pad > ADV748X_AFE_SINK_AIN7 || + r->sink_stream != 0 || + r->source_pad != ADV748X_AFE_SOURCE || + r->source_stream != 0) + return -EINVAL; + + if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) { + if (input != -1) + return -EMLINK; + + input = r->sink_pad; + } + r++; + } + + if (input != -1) + afe->input = input; + + return 0; +} + static const struct v4l2_subdev_pad_ops adv748x_afe_pad_ops = { .enum_mbus_code = adv748x_afe_enum_mbus_code, .set_fmt = adv748x_afe_set_format, .get_fmt = adv748x_afe_get_format, + .get_routing = adv748x_afe_get_routing, + .set_routing = adv748x_afe_set_routing, }; /* - -- 2.15.1
[PATCH/RFC v2 01/15] v4l2-subdev.h: add pad and stream aware s_stream
To be able to start and stop individual streams of a multiplexed pad the s_stream operation needs to be both pad and stream aware. Add a new operation to pad ops to facilitate this. Signed-off-by: Niklas Söderlund --- include/media/v4l2-subdev.h | 5 + 1 file changed, 5 insertions(+) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a30a94fad8dbacde..7288209338a48fda 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -669,6 +669,9 @@ struct v4l2_subdev_pad_config { * * @set_frame_desc: set the low level media bus frame parameters, @fd array * may be adjusted by the subdev driver to device capabilities. + * + * @s_stream: used to notify the driver that a stream will start or has + * stopped. */ struct v4l2_subdev_pad_ops { int (*init_cfg)(struct v4l2_subdev *sd, @@ -713,6 +716,8 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_routing *route); int (*set_routing)(struct v4l2_subdev *sd, struct v4l2_subdev_routing *route); + int (*s_stream)(struct v4l2_subdev *sd, unsigned int pad, + unsigned int stream, int enable); }; /** -- 2.15.1
[PATCH/RFC v2 11/15] adv748x: csi2: implement get_frame_desc
Provide CSI-2 bus information for the multiplexed source pad using the frame descriptor. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-csi2.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index a2a6d93077204731..a43b251d0bc67a43 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -225,9 +225,37 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, return ret; } +static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); + struct v4l2_mbus_framefmt *mbusformat; + + memset(fd, 0, sizeof(*fd)); + + if (pad != ADV748X_CSI2_SOURCE) + return -EINVAL; + + mbusformat = adv748x_csi2_get_pad_format(sd, NULL, ADV748X_CSI2_SINK, +V4L2_SUBDEV_FORMAT_ACTIVE); + if (!mbusformat) + return -EINVAL; + + fd->entry->stream = 0; + fd->entry->bus.csi2.channel = tx->vc; + fd->entry->bus.csi2.data_type = + adv748x_csi2_code_to_datatype(mbusformat->code); + + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + fd->num_entries = 1; + + return 0; +} + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .get_fmt = adv748x_csi2_get_format, .set_fmt = adv748x_csi2_set_format, + .get_frame_desc = adv748x_csi2_get_frame_desc, }; /* - -- 2.15.1
[PATCH/RFC v2 02/15] rcar-vin: use pad as the starting point for a pipeline
The pipeline will be moved from the entity to the pads; reflect this in the media pipeline function API. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-dma.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 03a914361a33125c..cf30e5fceb1d493a 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1179,7 +1179,7 @@ static int rvin_set_stream(struct rvin_dev *vin, int on) return -EPIPE; if (!on) { - media_pipeline_stop(&vin->vdev.entity); + media_pipeline_stop(vin->vdev.entity.pads); return v4l2_subdev_call(sd, video, s_stream, 0); } @@ -1235,15 +1235,15 @@ static int rvin_set_stream(struct rvin_dev *vin, int on) fmt.format.height != vin->format.height) return -EPIPE; - pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe; - if (media_pipeline_start(&vin->vdev.entity, pipe)) + pipe = sd->entity.pads->pipe ? sd->entity.pads->pipe : &vin->vdev.pipe; + if (media_pipeline_start(vin->vdev.entity.pads, pipe)) return -EPIPE; ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret == -ENOIOCTLCMD) ret = 0; if (ret) - media_pipeline_stop(&vin->vdev.entity); + media_pipeline_stop(vin->vdev.entity.pads); return ret; } -- 2.15.1
[PATCH/RFC v2 08/15] rcar-csi2: add get_routing support
To support multiplexed streams the internal routing between the rcar-csi2 sink pad and its source pads needs to be described. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-csi2.c | 54 + 1 file changed, 54 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 2dd7d03d622d5510..fd1133e72482fc19 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -334,6 +334,14 @@ static int rcar_csi2_pad_to_vc(unsigned int pad) return pad - RCAR_CSI2_SOURCE_VC0; } +static int rcar_csi2_vc_to_pad(unsigned int vc) +{ + if (vc > 3) + return -EINVAL; + + return vc + RCAR_CSI2_SOURCE_VC0; +} + struct rcar_csi2_info { const struct phypll_hsfreqrange *hsfreqrange; const struct phtw_testdin_data *testdin_data; @@ -752,9 +760,55 @@ static int rcar_csi2_get_pad_format(struct v4l2_subdev *sd, return 0; } +static int rcar_csi2_get_routing(struct v4l2_subdev *sd, +struct v4l2_subdev_routing *routing) +{ + struct rcar_csi2 *priv = sd_to_csi2(sd); + struct v4l2_mbus_frame_desc fd; + struct v4l2_subdev_route *r = routing->routes; + struct v4l2_subdev *rsubdev; + unsigned int i, rpad; + int ret; + + /* Get information about multiplexed link */ + ret = rcar_csi2_get_source_info(priv, &rsubdev, &rpad, &fd); + if (ret) + return ret; + + if (routing->num_routes < fd.num_entries) { + routing->num_routes = fd.num_entries; + return -ENOSPC; + } + + routing->num_routes = fd.num_entries; + + for (i = 0; i < fd.num_entries; i++) { + struct v4l2_mbus_frame_desc_entry *entry = &fd.entry[i]; + int source_pad; + + source_pad = rcar_csi2_vc_to_pad(entry->bus.csi2.channel); + if (source_pad < 0) { + dev_err(priv->dev, "Virtual Channel out of range: %u\n", + entry->bus.csi2.channel); + return -ENOSPC; + } + + r->sink_pad = RCAR_CSI2_SINK; + r->sink_stream = entry->stream; + r->source_pad = source_pad; + r->source_stream = 0; + r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE | + V4L2_SUBDEV_ROUTE_FL_IMMUTABLE; + r++; + } + + return 0; +} + static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { .set_fmt = rcar_csi2_set_pad_format, .get_fmt = rcar_csi2_get_pad_format, + .get_routing = rcar_csi2_get_routing, .s_stream = rcar_csi2_s_stream, }; -- 2.15.1
[RFC 2/2] v4l2-ctl: add ROUTING get and set options
Signed-off-by: Niklas Söderlund --- utils/v4l2-ctl/Android.mk | 2 +- utils/v4l2-ctl/Makefile.am | 2 +- utils/v4l2-ctl/v4l2-ctl-routing.cpp | 154 utils/v4l2-ctl/v4l2-ctl.cpp | 10 +++ utils/v4l2-ctl/v4l2-ctl.h | 9 +++ 5 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 utils/v4l2-ctl/v4l2-ctl-routing.cpp diff --git a/utils/v4l2-ctl/Android.mk b/utils/v4l2-ctl/Android.mk index 707895026f88962d..f83347e04ff477c7 100644 --- a/utils/v4l2-ctl/Android.mk +++ b/utils/v4l2-ctl/Android.mk @@ -21,5 +21,5 @@ LOCAL_SRC_FILES := \ v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \ -v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c +v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-routing.cpp include $(BUILD_EXECUTABLE) diff --git a/utils/v4l2-ctl/Makefile.am b/utils/v4l2-ctl/Makefile.am index cae4e747a0afa047..69bf466e89bbf72e 100644 --- a/utils/v4l2-ctl/Makefile.am +++ b/utils/v4l2-ctl/Makefile.am @@ -6,7 +6,7 @@ v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cp v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \ v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \ v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \ - v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-meta.cpp + v4l2-tpg-colors.c v4l2-tpg-core.c v4l-stream.c v4l2-ctl-meta.cpp v4l2-ctl-routing.cpp v4l2_ctl_CPPFLAGS = -I$(top_srcdir)/utils/common if WITH_LIBV4L diff --git a/utils/v4l2-ctl/v4l2-ctl-routing.cpp b/utils/v4l2-ctl/v4l2-ctl-routing.cpp new file mode 100644 index ..55a2e44949785015 --- /dev/null +++ b/utils/v4l2-ctl/v4l2-ctl-routing.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "v4l2-ctl.h" + +#include + +/* + * The max value comes from a check in the kernel source code + * drivers/media/v4l2-core/v4l2-ioctl.c check_array_args() + */ +#define NUM_ROUTES_MAX 256 + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +struct v4l2_subdev_routing routing; +struct v4l2_subdev_route routes[NUM_ROUTES_MAX]; + +struct flag_name { + __u32 flag; + const char *name; +}; + +static void print_flags(const struct flag_name *flag_names, unsigned int num_entries, __u32 flags) +{ + bool first = true; + unsigned int i; + + for (i = 0; i < num_entries; i++) { + if (!(flags & flag_names[i].flag)) + continue; + if (!first) + printf(","); + printf("%s", flag_names[i].name); + flags &= ~flag_names[i].flag; + first = false; + } + + if (flags) { + if (!first) + printf(","); + printf("0x%x", flags); + } +} + +static void print_routes(const struct v4l2_subdev_routing *r) +{ + unsigned int i; + + static const struct flag_name route_flags[] = { + { V4L2_SUBDEV_ROUTE_FL_ACTIVE, "ENABLED" }, + { V4L2_SUBDEV_ROUTE_FL_IMMUTABLE, "IMMUTABLE" }, + }; + + for (i = 0; i < r->num_routes; i++) { + printf("%d/%d -> %d/%d [", + r->routes[i].sink_pad, r->routes[i].sink_stream, + r->routes[i].source_pad, r->routes[i].source_stream); + print_flags(route_flags, ARRAY_SIZE(route_flags), r->routes[i].flags); + printf("]\n"); + } +} + +void routing_usage(void) +{ + printf("\nRoute options:\n" + " --get-routing Print the route topology\n" + " --set-routing routes Comma-separated list of route descriptors to setup\n" + "\n" + "Routes are defined as\n" + "routes = route { ',' route } ;\n" + "route = sink '->' source '[' flags ']' ;\n" + "sink= sink-pad '/' sink-stream ;\n" + "source = source-pad '/' source-stream ;\n" + "\n" + "where the fields are\n" + "sink-pad= Pad numeric identifier for sink\n" + "sink-stream = Stream numeric identifier for sink\n" + "source-pad = Pad numeric identifier for source\n" + "source-stream = Stream numeric identifier for source\n" + "flags = Route flags (0: inactive, 1: active)\n" + ); +} + +/**/ + +void routing_c
[PATCH/RFC v2 00/15] Add multiplexed pad streaming support
Hi, This is the second attempt to add streaming support to multiplexed pads. The first attempt was not aware of Sakari's work. His work have now been taken into account and this series depends on his series together with the master of media-tree. git://linuxtv.org/sailus/media_tree.git#vc It also depends on the latest out-of-tree patches for R-Car VIN and CSI-2 as these drivers together with the in-tree driver adv748x have been used to prove functionality of this series. Test procedure includes changing which CSI-2 VC the adv7482 outputs on (using the module parameter introduced in this patch-set) and verify that the R-Car CSI-2 and VIN can receive that particular VC. A second hardware setup have also been used to verify functionality based on the MAX9286 chip, which in contrast to the outputs multiple CSI-2 virtual channels. Unfortunate the driver side for the MAX9286 and the sensors RDACM20 is still in a prototype stage so the patches to enable multiplexed pads on that setup is not included in this patch-set. The problem this patch-set is trying to solve is that there is no way in the v4l2 framework to describe and control links between subdevices which carry more then one video stream, for example a CSI-2 bus which can have 4 virtual channels carrying different video streams. The idea is that on both sides of the multiplexed media link there are one multiplexer subdevice and one demultiplexer subdevice. These two subdevices can't do any format conversions, there sole purpose is to (de)multiplex the CSI-2 link. If there is hardware which can do both CSI-2 multiplexing and format conversions they can be modeled as two subdevices from the same device driver. +--+ +--+ +---+ subdev 1 | | subdev 2 +---+ +--+ Pad 1 | | | | Pad 3 +---+ +--++ +-+---+ +---+-+ ++--+ || Muxed pad A +--+ Muxed pad B || +--++ +-+---+ +---+-+ ++--+ +--+ Pad 2 | | | | Pad 4 +---+ +---+ | | +---+ +--+ +--+ In the example above Pad 1 is routed to Pad 3 and Pad 2 to Pad 4, and the video data for both of them travels the link between pad A and B. The routing between the pads inside subdev 1 and subdev 2 are controlled and communicated to user-space using the [GS]_ROUTING subdev ioctls (from Sakari's patch-set). I have patches for v4l2-ctl which creates a user-space interface for these now ioctls which I will post in a separate thread. These routes are also used to perform format validation between pad 1-3 and pad 2-4, the format validation is also part of Sakari's patch-set. Obviously PATCH 01/15 is a RFC and if it is judged to be OK it should be split out to a separate patch and updated to move the .s_stream() operation from video ops to pad ops instead of adding a new one. I have posted a similar patch for this last year but it did not get much attention. For this RFC it's enough to add a new operation as to prove functionality. A big thanks to Laurent and Sakari for being really nice and taking time helping me grasp all the possibilities and issues with this problem, all cred to them and all blame to me for misunderstanding there guidance :-) Niklas Söderlund (15): v4l2-subdev.h: add pad and stream aware s_stream rcar-vin: use pad as the starting point for a pipeline rcar-vin: use the pad and stream aware s_stream rcar-csi2: switch to pad and stream aware s_stream rcar-csi2: count usage for each source pad rcar-csi2: use frame description information when propagating .s_stream() rcar-csi2: use frame description information to configure CSI-2 bus rcar-csi2: add get_routing support adv748x: csi2: add module param for virtual channel adv748x: csi2: add translation from pixelcode to CSI-2 datatype adv748x: csi2: implement get_frame_desc adv748x: csi2: switch to pad and stream aware s_stream adv748x: csi2: only allow formats on sink pads adv748x: csi2: add get_routing support adv748x: afe: add routing support drivers/media/i2c/adv748x/adv748x-afe.c | 66 +++ drivers/media/i2c/adv748x/adv748x-core.c| 10 ++ drivers/media/i2c/adv748x/adv748x-csi2.c| 96 +- drivers/media/i2c/adv748x/adv748x.h | 1 + drivers/media/platform/rcar-vin/rcar-csi2.c | 267 +++- drivers/media/platform/rcar-vin/rcar-dma.c | 14 +- include/media/v4l2-subdev.h | 5 + 7 files changed, 365 insertions(+), 94 deletions(-) -- 2.15.1
[PATCH/RFC v2 04/15] rcar-csi2: switch to pad and stream aware s_stream
Switch the driver to implement the pad and stream aware s_stream operation. This is needed to enable to support to start and stop individual streams on a multiplexed pad. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-csi2.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index d8751add48fc1322..8ce0bfeef1113f9c 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -625,12 +625,17 @@ static int rcar_csi2_sd_info(struct rcar_csi2 *priv, struct v4l2_subdev **sd) return 0; } -static int rcar_csi2_s_stream(struct v4l2_subdev *sd, int enable) +static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, + unsigned int stream, int enable) { struct rcar_csi2 *priv = sd_to_csi2(sd); struct v4l2_subdev *nextsd; int ret; + /* Only one stream on each source pad */ + if (stream != 0) + return -EINVAL; + mutex_lock(&priv->lock); ret = rcar_csi2_sd_info(priv, &nextsd); @@ -699,17 +704,13 @@ static int rcar_csi2_get_pad_format(struct v4l2_subdev *sd, return 0; } -static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { - .s_stream = rcar_csi2_s_stream, -}; - static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { .set_fmt = rcar_csi2_set_pad_format, .get_fmt = rcar_csi2_get_pad_format, + .s_stream = rcar_csi2_s_stream, }; static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { - .video = &rcar_csi2_video_ops, .pad= &rcar_csi2_pad_ops, }; -- 2.15.1
[RFC 1/2] Synchronize with the Kernel headers for routing operations
Signed-off-by: Niklas Söderlund --- include/linux/v4l2-subdev.h | 41 + 1 file changed, 41 insertions(+) diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index dbce2b554e026869..e19ee64075d6cbdf 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * V4L2 subdev userspace API * @@ -154,6 +155,44 @@ struct v4l2_subdev_selection { __u32 reserved[8]; }; +#define V4L2_SUBDEV_ROUTE_FL_ACTIVE(1 << 0) +#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE (1 << 1) + +/** + * struct v4l2_subdev_route - A signal route inside a subdev + * @sink_pad: the sink pad + * @sink_stream: the sink stream + * @source_pad: the source pad + * @source_stream: the source stream + * @flags: route flags: + * + * V4L2_SUBDEV_ROUTE_FL_ACTIVE: Is the stream in use or not? An + * active stream will start when streaming is enabled on a video + * node. Set by the user. + * + * V4L2_SUBDEV_ROUTE_FL_IMMUTABLE: Is the stream immutable, i.e. + * can it be activated and inactivated? Set by the driver. + */ +struct v4l2_subdev_route { + __u32 sink_pad; + __u32 sink_stream; + __u32 source_pad; + __u32 source_stream; + __u32 flags; + __u32 reserved[5]; +}; + +/** + * struct v4l2_subdev_routing - Routing information + * @routes: the routes array + * @num_routes: the total number of routes in the routes array + */ +struct v4l2_subdev_routing { + struct v4l2_subdev_route *routes; + __u32 num_routes; + __u32 reserved[5]; +}; + /* Backwards compatibility define --- to be removed */ #define v4l2_subdev_edid v4l2_edid @@ -176,5 +215,7 @@ struct v4l2_subdev_selection { #define VIDIOC_SUBDEV_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings) #define VIDIOC_SUBDEV_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) #define VIDIOC_SUBDEV_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) +#define VIDIOC_SUBDEV_G_ROUTING_IOWR('V', 38, struct v4l2_subdev_routing) +#define VIDIOC_SUBDEV_S_ROUTING_IOWR('V', 39, struct v4l2_subdev_routing) #endif -- 2.14.2
[PATCH/RFC v2 07/15] rcar-csi2: use frame description information to configure CSI-2 bus
The driver now have access to frame descriptor information, use it. Only enable the virtual channels which are described in the frame descriptor and calculate the link based on all enabled streams. With multiplexed stream support it's now possible to have different formats on the different source pads. Make source formats independent off each other and disallowing a format on the multiplexed sink. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-csi2.c | 112 ++-- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 6b607b2e31e26063..2dd7d03d622d5510 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -296,24 +296,22 @@ static const struct phtw_testdin_data testdin_data_v3m_e3[] = { #define CSI0CLKFREQRANGE(n)((n & 0x3f) << 16) struct rcar_csi2_format { - unsigned int code; unsigned int datatype; unsigned int bpp; }; static const struct rcar_csi2_format rcar_csi2_formats[] = { - { .code = MEDIA_BUS_FMT_RGB888_1X24,.datatype = 0x24, .bpp = 24 }, - { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 }, - { .code = MEDIA_BUS_FMT_UYVY8_2X8, .datatype = 0x1e, .bpp = 16 }, - { .code = MEDIA_BUS_FMT_YUYV10_2X10,.datatype = 0x1e, .bpp = 16 }, + { .datatype = 0x1e, .bpp = 16 }, + { .datatype = 0x24, .bpp = 24 }, }; -static const struct rcar_csi2_format *rcar_csi2_code_to_fmt(unsigned int code) +static const struct rcar_csi2_format +*rcar_csi2_datatype_to_fmt(unsigned int datatype) { unsigned int i; for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++) - if (rcar_csi2_formats[i].code == code) + if (rcar_csi2_formats[i].datatype == datatype) return rcar_csi2_formats + i; return NULL; @@ -355,7 +353,7 @@ struct rcar_csi2 { struct v4l2_async_notifier notifier; struct v4l2_async_subdev remote; - struct v4l2_mbus_framefmt mf; + struct v4l2_mbus_framefmt mf[4]; struct mutex lock; int stream_count[4]; @@ -411,25 +409,14 @@ static int rcar_csi2_wait_phy_start(struct rcar_csi2 *priv) return -ETIMEDOUT; } -static int rcar_csi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) +static int rcar_csi2_calc_mbps(struct rcar_csi2 *priv, + struct v4l2_subdev *source, + struct v4l2_mbus_frame_desc *fd) { - struct media_pad *pad, *source_pad; - struct v4l2_subdev *source = NULL; struct v4l2_ctrl *ctrl; + unsigned int i, bpp = 0; u64 mbps; - /* Get remote subdevice */ - pad = &priv->subdev.entity.pads[RCAR_CSI2_SINK]; - source_pad = media_entity_remote_pad(pad); - if (!source_pad) { - dev_err(priv->dev, "Could not find remote source pad\n"); - return -ENODEV; - } - source = media_entity_to_v4l2_subdev(source_pad->entity); - - dev_dbg(priv->dev, "Using source %s pad: %u\n", source->name, - source_pad->index); - /* Read the pixel rate control from remote */ ctrl = v4l2_ctrl_find(source->ctrl_handler, V4L2_CID_PIXEL_RATE); if (!ctrl) { @@ -438,6 +425,21 @@ static int rcar_csi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) return -EINVAL; } + /* Calculate total bpp */ + for (i = 0; i < fd->num_entries; i++) { + const struct rcar_csi2_format *format; + + format = rcar_csi2_datatype_to_fmt( + fd->entry[i].bus.csi2.data_type); + if (!format) { + dev_err(priv->dev, "Unknown data type: %d\n", + fd->entry[i].bus.csi2.data_type); + return -EINVAL; + } + + bpp += format->bpp; + } + /* Calculate the phypll */ mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; do_div(mbps, priv->lanes * 100); @@ -489,39 +491,33 @@ static int rcar_csi2_set_phtw(struct rcar_csi2 *priv, unsigned int mbps) return 0; } -static int rcar_csi2_start(struct rcar_csi2 *priv) +static int rcar_csi2_start(struct rcar_csi2 *priv, struct v4l2_subdev *source, + struct v4l2_mbus_frame_desc *fd) { - const struct rcar_csi2_format *format; - u32 phycnt, tmp; - u32 vcdt = 0, vcdt2 = 0; + u32 phycnt, vcdt = 0, vcdt2 = 0; unsigned int i; int mbps, ret; - dev_dbg(priv->dev, "Input size (%ux%u%c)\n", - priv->mf.width, priv->mf.height, - priv->mf.field == V4L2_FIELD_NONE ? 'p' : 'i'); - - /* Code is validated in set_ftm */ - format = rcar_csi2_code_to_fmt(priv
[PATCH/RFC v2 03/15] rcar-vin: use the pad and stream aware s_stream
To work with multiplexed streams the pad and stream aware s_stream operation needs to be used. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-dma.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index cf30e5fceb1d493a..8435491535060eae 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1180,7 +1180,7 @@ static int rvin_set_stream(struct rvin_dev *vin, int on) if (!on) { media_pipeline_stop(vin->vdev.entity.pads); - return v4l2_subdev_call(sd, video, s_stream, 0); + return v4l2_subdev_call(sd, pad, s_stream, pad->index, 0, 0); } fmt.pad = pad->index; @@ -1239,12 +1239,14 @@ static int rvin_set_stream(struct rvin_dev *vin, int on) if (media_pipeline_start(vin->vdev.entity.pads, pipe)) return -EPIPE; - ret = v4l2_subdev_call(sd, video, s_stream, 1); + ret = v4l2_subdev_call(sd, pad, s_stream, pad->index, 0, 1); if (ret == -ENOIOCTLCMD) ret = 0; if (ret) media_pipeline_stop(vin->vdev.entity.pads); + vin_dbg(vin, "pad: %u stream: 0 enable: %d\n", pad->index, on); + return ret; } -- 2.15.1
[PATCH/RFC v2 12/15] adv748x: csi2: switch to pad and stream aware s_stream
Switch the driver to implement the pad and stream aware s_stream operation. This is needed to enable to support to start and stop individual streams on a multiplexed pad. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-csi2.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index a43b251d0bc67a43..39f993282dd3bb5c 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -128,22 +128,26 @@ static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = { * v4l2_subdev_video_ops */ -static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, int enable) +static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, +unsigned int stream, int enable) { struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); + struct adv748x_state *state = tx->state; struct v4l2_subdev *src; + if (pad != ADV748X_CSI2_SOURCE || stream != 0) + return -EINVAL; + src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]); if (!src) return -EPIPE; + adv_dbg(state, "%s: pad: %u stream: %u enable: %d\n", sd->name, + pad, stream, enable); + return v4l2_subdev_call(src, video, s_stream, enable); } -static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { - .s_stream = adv748x_csi2_s_stream, -}; - /* - * v4l2_subdev_pad_ops * @@ -256,6 +260,7 @@ static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .get_fmt = adv748x_csi2_get_format, .set_fmt = adv748x_csi2_set_format, .get_frame_desc = adv748x_csi2_get_frame_desc, + .s_stream = adv748x_csi2_s_stream, }; /* - @@ -263,7 +268,6 @@ static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { */ static const struct v4l2_subdev_ops adv748x_csi2_ops = { - .video = &adv748x_csi2_video_ops, .pad = &adv748x_csi2_pad_ops, }; -- 2.15.1
[PATCH/RFC v2 14/15] adv748x: csi2: add get_routing support
To support multiplexed streams the internal routing between the adv748x sink pad and its source pad needs to be described. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-csi2.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 291b35bef49d41fb..dbefb53f5b8c414d 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -262,10 +262,32 @@ static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, return 0; } +static int adv748x_csi2_get_routing(struct v4l2_subdev *subdev, + struct v4l2_subdev_routing *routing) +{ + struct v4l2_subdev_route *r = routing->routes; + + if (routing->num_routes < 1) { + routing->num_routes = 1; + return -ENOSPC; + } + + routing->num_routes = 1; + + r->sink_pad = ADV748X_CSI2_SINK; + r->sink_stream = 0; + r->source_pad = ADV748X_CSI2_SOURCE; + r->source_stream = 0; + r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE | V4L2_SUBDEV_ROUTE_FL_IMMUTABLE; + + return 0; +} + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .get_fmt = adv748x_csi2_get_format, .set_fmt = adv748x_csi2_set_format, .get_frame_desc = adv748x_csi2_get_frame_desc, + .get_routing = adv748x_csi2_get_routing, .s_stream = adv748x_csi2_s_stream, }; -- 2.15.1
[PATCH/RFC v2 13/15] adv748x: csi2: only allow formats on sink pads
The driver is now pad and stream aware, only allow to get/set format on sink pads. Also record a different format for each sink pad since it's no longer true that they are all the same Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-csi2.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 39f993282dd3bb5c..291b35bef49d41fb 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -176,6 +176,9 @@ static int adv748x_csi2_get_format(struct v4l2_subdev *sd, struct adv748x_state *state = tx->state; struct v4l2_mbus_framefmt *mbusformat; + if (sdformat->pad != ADV748X_CSI2_SINK) + return -EINVAL; + mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, sdformat->which); if (!mbusformat) @@ -199,6 +202,9 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mbusformat; int ret = 0; + if (sdformat->pad != ADV748X_CSI2_SINK) + return -EINVAL; + mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, sdformat->which); if (!mbusformat) -- 2.15.1
[PATCH/RFC v2 05/15] rcar-csi2: count usage for each source pad
The R-Car CSI-2 hardware can output the same virtual channel simultaneously to more then one R-Car VIN. For this reason we need to move the usage counting from the global device to each source pad. If a source pads usage count go from 0 to 1 we need to signal that a new stream should start, likewise if it go from 1 to 0 we need to stop a stream. At the same time we only want to start or stop the R-Car CSI-2 device only on the first or last stream. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-csi2.c | 38 +++-- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 8ce0bfeef1113f9c..e0f56cc3d25179a9 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -328,6 +328,14 @@ enum rcar_csi2_pads { NR_OF_RCAR_CSI2_PAD, }; +static int rcar_csi2_pad_to_vc(unsigned int pad) +{ + if (pad < RCAR_CSI2_SOURCE_VC0 || pad > RCAR_CSI2_SOURCE_VC3) + return -EINVAL; + + return pad - RCAR_CSI2_SOURCE_VC0; +} + struct rcar_csi2_info { const struct phypll_hsfreqrange *hsfreqrange; const struct phtw_testdin_data *testdin_data; @@ -350,7 +358,7 @@ struct rcar_csi2 { struct v4l2_mbus_framefmt mf; struct mutex lock; - int stream_count; + int stream_count[4]; unsigned short lanes; unsigned char lane_swap[4]; @@ -630,7 +638,13 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, { struct rcar_csi2 *priv = sd_to_csi2(sd); struct v4l2_subdev *nextsd; - int ret; + unsigned int i, count = 0; + int ret, vc; + + /* Only allow stream control on source pads and valid vc */ + vc = rcar_csi2_pad_to_vc(pad); + if (vc < 0) + return vc; /* Only one stream on each source pad */ if (stream != 0) @@ -642,7 +656,10 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, if (ret) goto out; - if (enable && priv->stream_count == 0) { + for (i = 0; i < 4; i++) + count += priv->stream_count[i]; + + if (enable && count == 0) { pm_runtime_get_sync(priv->dev); ret = rcar_csi2_start(priv); @@ -650,20 +667,23 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, pm_runtime_put(priv->dev); goto out; } + } else if (!enable && count == 1) { + rcar_csi2_stop(priv); + pm_runtime_put(priv->dev); + } + if (enable && priv->stream_count[vc] == 0) { ret = v4l2_subdev_call(nextsd, video, s_stream, 1); if (ret) { rcar_csi2_stop(priv); pm_runtime_put(priv->dev); goto out; } - } else if (!enable && priv->stream_count == 1) { - rcar_csi2_stop(priv); + } else if (!enable && priv->stream_count[vc] == 1) { ret = v4l2_subdev_call(nextsd, video, s_stream, 0); - pm_runtime_put(priv->dev); } - priv->stream_count += enable ? 1 : -1; + priv->stream_count[vc] += enable ? 1 : -1; out: mutex_unlock(&priv->lock); @@ -919,7 +939,9 @@ static int rcar_csi2_probe(struct platform_device *pdev) priv->dev = &pdev->dev; mutex_init(&priv->lock); - priv->stream_count = 0; + + for (i = 0; i < 4; i++) + priv->stream_count[i] = 0; ret = rcar_csi2_probe_resources(priv, pdev); if (ret) { -- 2.15.1
[PATCH/RFC v2 06/15] rcar-csi2: use frame description information when propagating .s_stream()
Use the frame description from the remote subdevice of the rcar-csi2's sink pad to get the remote pad and stream pad needed to propagate the .s_stream() operation. The CSI-2 virtual channel which should be acted upon can be determined by looking at which of the rcar-csi2 source pad the .s_stream() was called on. This is because the rcar-csi2 acts as a demultiplexer for the CSI-2 link on the one sink pad and outputs each virtual channel on a distinct and known source pad. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-csi2.c | 58 - 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index e0f56cc3d25179a9..6b607b2e31e26063 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -614,20 +614,31 @@ static void rcar_csi2_stop(struct rcar_csi2 *priv) rcar_csi2_reset(priv); } -static int rcar_csi2_sd_info(struct rcar_csi2 *priv, struct v4l2_subdev **sd) +static int rcar_csi2_get_source_info(struct rcar_csi2 *priv, +struct v4l2_subdev **subdev, +unsigned int *pad, +struct v4l2_mbus_frame_desc *fd) { - struct media_pad *pad; + struct media_pad *remote_pad; - pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]); - if (!pad) { - dev_err(priv->dev, "Could not find remote pad\n"); + /* Get source subdevice and pad */ + remote_pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]); + if (!remote_pad) { + dev_err(priv->dev, "Could not find remote source pad\n"); return -ENODEV; } + *subdev = media_entity_to_v4l2_subdev(remote_pad->entity); + *pad = remote_pad->index; - *sd = media_entity_to_v4l2_subdev(pad->entity); - if (!*sd) { - dev_err(priv->dev, "Could not find remote subdevice\n"); - return -ENODEV; + /* Get frame descriptor */ + if (v4l2_subdev_call(*subdev, pad, get_frame_desc, *pad, fd)) { + dev_err(priv->dev, "Could not read frame desc\n"); + return -EINVAL; + } + + if (fd->type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { + dev_err(priv->dev, "Frame desc do not describe CSI-2 link"); + return -EINVAL; } return 0; @@ -637,9 +648,10 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, unsigned int stream, int enable) { struct rcar_csi2 *priv = sd_to_csi2(sd); + struct v4l2_mbus_frame_desc fd; struct v4l2_subdev *nextsd; - unsigned int i, count = 0; - int ret, vc; + unsigned int i, rpad, count = 0; + int ret, vc, rstream = -1; /* Only allow stream control on source pads and valid vc */ vc = rcar_csi2_pad_to_vc(pad); @@ -650,11 +662,23 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, if (stream != 0) return -EINVAL; - mutex_lock(&priv->lock); - - ret = rcar_csi2_sd_info(priv, &nextsd); + /* Get information about multiplexed link */ + ret = rcar_csi2_get_source_info(priv, &nextsd, &rpad, &fd); if (ret) - goto out; + return ret; + + /* Get stream on multiplexed link */ + for (i = 0; i < fd.num_entries; i++) + if (fd.entry[i].bus.csi2.channel == vc) + rstream = fd.entry[i].stream; + + if (rstream < 0) { + dev_err(priv->dev, "Could not find stream for vc %u\n", vc); + return -EINVAL; + } + + /* Start or stop the requested stream */ + mutex_lock(&priv->lock); for (i = 0; i < 4; i++) count += priv->stream_count[i]; @@ -673,14 +697,14 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, } if (enable && priv->stream_count[vc] == 0) { - ret = v4l2_subdev_call(nextsd, video, s_stream, 1); + ret = v4l2_subdev_call(nextsd, pad, s_stream, rpad, rstream, 1); if (ret) { rcar_csi2_stop(priv); pm_runtime_put(priv->dev); goto out; } } else if (!enable && priv->stream_count[vc] == 1) { - ret = v4l2_subdev_call(nextsd, video, s_stream, 0); + ret = v4l2_subdev_call(nextsd, pad, s_stream, rpad, rstream, 0); } priv->stream_count[vc] += enable ? 1 : -1; -- 2.15.1
[PATCH/RFC v2 10/15] adv748x: csi2: add translation from pixelcode to CSI-2 datatype
This will be needed to fill out the frame descriptor information correctly. Signed-off-by: Niklas Söderlund --- drivers/media/i2c/adv748x/adv748x-csi2.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 2a5dff8c571013bf..a2a6d93077204731 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -18,6 +18,28 @@ #include "adv748x.h" +struct adv748x_csi2_format { + unsigned int code; + unsigned int datatype; +}; + +static const struct adv748x_csi2_format adv748x_csi2_formats[] = { + { .code = MEDIA_BUS_FMT_RGB888_1X24,.datatype = 0x24, }, + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, }, + { .code = MEDIA_BUS_FMT_UYVY8_2X8, .datatype = 0x1e, }, + { .code = MEDIA_BUS_FMT_YUYV10_2X10,.datatype = 0x1e, }, +}; + +static unsigned int adv748x_csi2_code_to_datatype(unsigned int code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(adv748x_csi2_formats); i++) + if (adv748x_csi2_formats[i].code == code) + return adv748x_csi2_formats[i].datatype; + return 0; +} + static bool is_txa(struct adv748x_csi2 *tx) { return tx == &tx->state->txa; -- 2.15.1
[RFC 0/2] v4l2-ctl: add ROUTING get and set options
Hi, This small series adds support for the [GS]_ROUTING subdev ioctls introduced in Sakari's vc branch. git://linuxtv.org/sailus/media_tree.git#vc The use-case for this is to control the internal routing between pads inside a subdevice. Currently this is used on the ADV7482 to select which of it's 8 analog inputs are routed to the source pad. It is also used in the R-Car CSI-2, ADV7482 and MAX9286 drivers to deserve which pad is routed to which stream of the multiplexed link between the R-Car CSI-2 and either the ADV7482 or the MAX9286. Niklas Söderlund (2): Synchronize with the Kernel headers for routing operations v4l2-ctl: add ROUTING get and set options include/linux/v4l2-subdev.h | 41 ++ utils/v4l2-ctl/Android.mk | 2 +- utils/v4l2-ctl/Makefile.am | 2 +- utils/v4l2-ctl/v4l2-ctl-routing.cpp | 154 utils/v4l2-ctl/v4l2-ctl.cpp | 10 +++ utils/v4l2-ctl/v4l2-ctl.h | 9 +++ 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 utils/v4l2-ctl/v4l2-ctl-routing.cpp -- 2.14.2
[RFC PATCH renesas-drivers] of: overlay: overlay_changeset_release() can be static
Fixes: 11de0d24be47 ("of: overlay: kobjectify overlay objects") Signed-off-by: Fengguang Wu --- overlay.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index ef7e8a4..7f0255e 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -654,7 +654,7 @@ static inline struct overlay_changeset *kobj_to_ovcs(struct kobject *kobj) return container_of(kobj, struct overlay_changeset, kobj); } -void overlay_changeset_release(struct kobject *kobj) +static void overlay_changeset_release(struct kobject *kobj) { struct overlay_changeset *ovcs = kobj_to_ovcs(kobj);
[renesas-drivers:topic/renesas-overlays 10/92] drivers/of/overlay.c:657:6: sparse: symbol 'overlay_changeset_release' was not declared. Should it be static?
tree: https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git topic/renesas-overlays head: 47d433a558bb60587eb9f86a4d010ef74e03fa0d commit: 11de0d24be4742a41feceb95d9145b08843dc70a [10/92] of: overlay: kobjectify overlay objects reproduce: # apt-get install sparse git checkout 11de0d24be4742a41feceb95d9145b08843dc70a make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
[renesas-drivers:topic/renesas-overlays 23/92] drivers/of/dynamic.c:1141:13: sparse: incorrect type in assignment (different base types)
tree: https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git topic/renesas-overlays head: 47d433a558bb60587eb9f86a4d010ef74e03fa0d commit: e068b1eab7180587d15bbc55abdc5851b7f216dc [23/92] of: changesets: Introduce changeset helper methods reproduce: # apt-get install sparse git checkout e068b1eab7180587d15bbc55abdc5851b7f216dc make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) vim +1141 drivers/of/dynamic.c 1124 1125 /** 1126 * of_changeset_add_property_u32 - Create a new u32 property 1127 * 1128 * @ocs:changeset pointer 1129 * @np: device node pointer 1130 * @name: name of the property 1131 * @val:value in host endian format 1132 * 1133 * Adds a u32 property to the changeset. 1134 * 1135 * Returns zero on success, a negative error value otherwise. 1136 */ 1137 int of_changeset_add_property_u32(struct of_changeset *ocs, 1138 struct device_node *np, const char *name, u32 val) 1139 { 1140 /* in place */ > 1141 val = cpu_to_be32(val); 1142 return of_changeset_add_property_copy(ocs, np, name, &val, sizeof(val)); 1143 } 1144 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH/RFC v2 09/15] adv748x: csi2: add module param for virtual channel
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > The hardware can output on any of the 4 (0-3) Virtual Channels of the > CSI-2 bus. Add a module parameter each for TXA and TXB to allow the user > to specify which channel should be used. This patch only configures the channel at initialisation time, (which is a valid thing to do here at the moment I think) - but will we expect to provide functionality to change the virtual channel later ? Do we need to communicate the virtual channel in use across the media pad links somehow? (or does that already happen?) Perhaps the commit message could be clear on the fact that this only sets the channels initialisation value - and that modifying the module parameter after module load will have no effect? Regards Kieran > Signed-off-by: Niklas Söderlund > > --- > drivers/media/i2c/adv748x/adv748x-core.c | 10 ++ > drivers/media/i2c/adv748x/adv748x-csi2.c | 2 +- > drivers/media/i2c/adv748x/adv748x.h | 1 + > 3 files changed, 12 insertions(+), 1 deletion(-) > > diff --git a/drivers/media/i2c/adv748x/adv748x-core.c > b/drivers/media/i2c/adv748x/adv748x-core.c > index fd92c9e4b519d2c5..3cad52532ead2e34 100644 > --- a/drivers/media/i2c/adv748x/adv748x-core.c > +++ b/drivers/media/i2c/adv748x/adv748x-core.c > @@ -31,6 +31,9 @@ > > #include "adv748x.h" > > +static unsigned int txavc; > +static unsigned int txbvc; > + > /* > - > * Register manipulation > */ > @@ -747,6 +750,7 @@ static int adv748x_probe(struct i2c_client *client, > } > > /* Initialise TXA */ > + state->txa.vc = txavc; > ret = adv748x_csi2_init(state, &state->txa); > if (ret) { > adv_err(state, "Failed to probe TXA"); > @@ -754,6 +758,7 @@ static int adv748x_probe(struct i2c_client *client, > } > > /* Initialise TXB */ > + state->txb.vc = txbvc; > ret = adv748x_csi2_init(state, &state->txb); > if (ret) { > adv_err(state, "Failed to probe TXB"); > @@ -824,6 +829,11 @@ static struct i2c_driver adv748x_driver = { > > module_i2c_driver(adv748x_driver); > > +module_param(txavc, uint, 0644); > +MODULE_PARM_DESC(txavc, "Virtual Channel for TXA"); > +module_param(txbvc, uint, 0644); > +MODULE_PARM_DESC(txbvc, "Virtual Channel for TXB"); > + > MODULE_AUTHOR("Kieran Bingham "); > MODULE_DESCRIPTION("ADV748X video decoder"); > MODULE_LICENSE("GPL v2"); > diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c > b/drivers/media/i2c/adv748x/adv748x-csi2.c > index 820b44ed56a8679f..2a5dff8c571013bf 100644 > --- a/drivers/media/i2c/adv748x/adv748x-csi2.c > +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c > @@ -281,7 +281,7 @@ int adv748x_csi2_init(struct adv748x_state *state, struct > adv748x_csi2 *tx) > } > > /* Initialise the virtual channel */ > - adv748x_csi2_set_virtual_channel(tx, 0); > + adv748x_csi2_set_virtual_channel(tx, tx->vc); > > adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, > MEDIA_ENT_F_UNKNOWN, > diff --git a/drivers/media/i2c/adv748x/adv748x.h > b/drivers/media/i2c/adv748x/adv748x.h > index 6789e2f3bc8c2b49..f6e40ee3924e8f12 100644 > --- a/drivers/media/i2c/adv748x/adv748x.h > +++ b/drivers/media/i2c/adv748x/adv748x.h > @@ -92,6 +92,7 @@ enum adv748x_csi2_pads { > > struct adv748x_csi2 { > struct adv748x_state *state; > + unsigned int vc; > struct v4l2_mbus_framefmt format; > unsigned int page; > >
Re: [PATCH/RFC v2 10/15] adv748x: csi2: add translation from pixelcode to CSI-2 datatype
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > This will be needed to fill out the frame descriptor information > correctly. > > Signed-off-by: Niklas Söderlund > --- > drivers/media/i2c/adv748x/adv748x-csi2.c | 22 ++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c > b/drivers/media/i2c/adv748x/adv748x-csi2.c > index 2a5dff8c571013bf..a2a6d93077204731 100644 > --- a/drivers/media/i2c/adv748x/adv748x-csi2.c > +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c > @@ -18,6 +18,28 @@ > > #include "adv748x.h" > > +struct adv748x_csi2_format { > + unsigned int code; > + unsigned int datatype; > +}; > + > +static const struct adv748x_csi2_format adv748x_csi2_formats[] = { > + { .code = MEDIA_BUS_FMT_RGB888_1X24,.datatype = 0x24, }, > + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, }, > + { .code = MEDIA_BUS_FMT_UYVY8_2X8, .datatype = 0x1e, }, > + { .code = MEDIA_BUS_FMT_YUYV10_2X10,.datatype = 0x1e, }, > +}; Is the datatype mapping specific to the ADV748x here? or are these generic/common CSI2 mappings? What do those datatype magic numbers represent? -- Kieran > + > +static unsigned int adv748x_csi2_code_to_datatype(unsigned int code) > +{ > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE(adv748x_csi2_formats); i++) > + if (adv748x_csi2_formats[i].code == code) > + return adv748x_csi2_formats[i].datatype; > + return 0; > +} > + > static bool is_txa(struct adv748x_csi2 *tx) > { > return tx == &tx->state->txa; >
[PATCH 5/9] ARM: dts: porter: use demuxer for I2C2
Create a separate bus for HDMI related I2C2 and provide fallback to GPIO. Based on work for the r8a7790/lager by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, fixed aliases, switched to named GPIOs] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7791-porter.dts | 128 --- 1 file changed, 75 insertions(+), 53 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts index eb374956294f69..0a503a1ed95b44 100644 --- a/arch/arm/boot/dts/r8a7791-porter.dts +++ b/arch/arm/boot/dts/r8a7791-porter.dts @@ -29,6 +29,8 @@ aliases { serial0 = &scif0; + i2c9 = &gpioi2c2; + i2c10 = &i2chdmi; }; chosen { @@ -135,6 +137,78 @@ clocks = <&x14_clk>; }; }; + + gpioi2c2: i2c-9 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + + /* +* A fallback to GPIO is provided for I2C2. +*/ + i2chdmi: i2c-10 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c2>, <&gpioi2c2>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + ak4642: codec@12 { + compatible = "asahi-kasei,ak4642"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin0>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin0ep>; + }; + }; + }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio3>; + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; + }; }; &extal_clk { @@ -296,61 +370,9 @@ &i2c2 { pinctrl-0 = <&i2c2_pins>; - pinctrl-names = "default"; + pinctrl-names = "i2c-hdmi"; - status = "okay"; clock-frequency = <40>; - - ak4642: codec@12 { - compatible = "asahi-kasei,ak4642"; - #sound-dai-cells = <0>; - reg = <0x12>; - }; - - composite-in@20 { - compatible = "adi,adv7180"; - reg = <0x20>; - remote = <&vin0>; - - port { - adv7180: endpoint { - bus-width = <8>; - remote-endpoint = <&vin0ep>; - }; - }; - }; - - hdmi@39 { - compatible = "adi,adv7511w"; - reg = <0x39>; - interrupt-parent = <&gpio3>; - interrupts = <29 IRQ_TYPE_LEVEL_LOW>; - - adi,input-depth = <8>; - adi,input-colorspace = "rgb"; - adi,input-clock = "1x"; - adi,input-style = <1>; - adi,input-justification = "evenly"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - adv7511_in: endpoint { -
[PATCH 2/9] ARM: dts: lager: use demuxer for IIC3/I2C3
Create a separate bus for da9063 PMIC and da9210 regulator related I2C slaves. Based on similar work for HDMI by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, corrected chip name in commit msg, updated aliases] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7790-lager.dts | 84 +++-- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index e4050dae7e8e33..6f6e41c9fc4f6c 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -55,6 +55,7 @@ i2c10 = &i2cexio0; i2c11 = &i2cexio1; i2c12 = &i2chdmi; + i2c13 = &i2cpwr; }; chosen { @@ -410,6 +411,46 @@ }; }; }; + + /* +* IIC3 and I2C3 may be switched using pinmux. +* IIC3/I2C3 does not appear to support fallback to GPIO. +*/ + i2cpwr: i2c-13 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&iic3>, <&i2c3>; + i2c-bus-name = "i2c-pwr"; + #address-cells = <1>; + #size-cells = <0>; + + pmic@58 { + compatible = "dlg,da9063"; + reg = <0x58>; + interrupt-parent = <&irqc0>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + + rtc { + compatible = "dlg,da9063-rtc"; + }; + + wdt { + compatible = "dlg,da9063-watchdog"; + }; + }; + + vdd_dvfs: regulator@68 { + compatible = "dlg,da9210"; + reg = <0x68>; + interrupt-parent = <&irqc0>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + + regulator-min-microvolt = <100>; + regulator-max-microvolt = <100>; + regulator-boot-on; + regulator-always-on; + }; + }; }; &du { @@ -549,6 +590,11 @@ function = "iic2"; }; + i2c3_pins: i2c3 { + groups = "i2c3"; + function = "i2c3"; + }; + iic3_pins: iic3 { groups = "iic3"; function = "iic3"; @@ -764,38 +810,14 @@ clock-frequency = <10>; }; -&iic3 { - pinctrl-names = "default"; - pinctrl-0 = <&iic3_pins>; - status = "okay"; - - pmic@58 { - compatible = "dlg,da9063"; - reg = <0x58>; - interrupt-parent = <&irqc0>; - interrupts = <2 IRQ_TYPE_LEVEL_LOW>; - interrupt-controller; - - rtc { - compatible = "dlg,da9063-rtc"; - }; - - wdt { - compatible = "dlg,da9063-watchdog"; - }; - }; - - vdd_dvfs: regulator@68 { - compatible = "dlg,da9210"; - reg = <0x68>; - interrupt-parent = <&irqc0>; - interrupts = <2 IRQ_TYPE_LEVEL_LOW>; +&i2c3 { + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "i2c-pwr"; +}; - regulator-min-microvolt = <100>; - regulator-max-microvolt = <100>; - regulator-boot-on; - regulator-always-on; - }; +&iic3 { + pinctrl-0 = <&iic3_pins>; + pinctrl-names = "i2c-pwr"; }; &pci0 { -- 2.11.0
[PATCH 4/9] ARM: dts: koelsch: use demuxer for I2C4
Make it possible to fallback to GPIO for I2C4 on the EXIO-E connector. This is based on reference work for the I2C0 core of the lager/r8a7790 by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, fixed aliases, switched to named GPIOS] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7791-koelsch.dts | 34 ++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 4b20db197de629..8319eff0190ecd 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -52,8 +52,10 @@ serial1 = &scif1; i2c9 = &gpioi2c1; i2c10 = &gpioi2c2; + i2c11 = &gpioi2c4; i2c12 = &i2cexio1; i2c13 = &i2chdmi; + i2c14 = &i2cexio4; }; chosen { @@ -329,6 +331,16 @@ i2c-gpio,delay-us = <5>; }; + gpioi2c4: i2c-11 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio7 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio7 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + /* * I2C1 is routed to EXIO connector B, pins 64 (SCL) + 66 (SDA). * A fallback to GPIO is provided. @@ -437,6 +449,18 @@ pagesize = <16>; }; }; + + /* +* I2C4 is routed to EXIO connector E, pins 37 (SCL) + 39 (SDA). +* A fallback to GPIO is provided. +*/ + i2cexio4: i2c-14 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c4>, <&gpioi2c4>; + i2c-bus-name = "i2c-exio4"; + #address-cells = <1>; + #size-cells = <0>; + }; }; &du { @@ -480,6 +504,11 @@ function = "i2c2"; }; + i2c4_pins: i2c4 { + groups = "i2c4"; + function = "i2c4"; + }; + du_pins: du { groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; function = "du"; @@ -735,6 +764,11 @@ clock-frequency = <10>; }; +&i2c4 { + pinctrl-0 = <&i2c4_pins>; + pinctrl-names = "i2c-exio4"; +}; + &i2c6 { status = "okay"; clock-frequency = <10>; -- 2.11.0
[PATCH 8/9] ARM: dts: gose: use demuxer for I2C2
Create a separate bus for HDMI related I2C2 and provide fallback to GPIO. Based on work for the r8a7790/lager by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, corrected board name in subject, fixed aliases, switched to named GPIOs] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7793-gose.dts | 218 - 1 file changed, 121 insertions(+), 97 deletions(-) diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 51b3ffac8efaad..2b330ef71f4c17 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -48,6 +48,8 @@ aliases { serial0 = &scif0; serial1 = &scif1; + i2c9 = &gpioi2c2; + i2c11 = &i2chdmi; }; chosen { @@ -296,6 +298,124 @@ #clock-cells = <0>; clock-frequency = <14850>; }; + + gpioi2c2: i2c-9 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + + /* +* A fallback to GPIO is provided for I2C2. +*/ + i2chdmi: i2c-11 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c2>, <&gpioi2c2>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180cp"; + reg = <0x20>; + remote = <&vin1>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7180_in: endpoint { + remote-endpoint = <&composite_con_in>; + }; + }; + + port@3 { + reg = <3>; + adv7180_out: endpoint { + bus-width = <8>; + remote-endpoint = <&vin1ep>; + }; + }; + }; + }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio3>; + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; + + hdmi-in@4c { + compatible = "adi,adv7612"; + reg = <0x4c>; + interrupt-parent = <&gpio4>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + default-input = <0>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7612_in: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; + }; + + port@2 { +
[PATCH 0/9] ARM: dts: gen2: add IP core switcher for all busses
Here is the updated series to add the I2C IP core switcher to all busses of Gen2 boards where some kind of switching is possible (mostly to/from GPIO). These patches were tested locally on Lager and Alt, and remotely on Koelsch and Gose. Access to Porter did not work yet and will be investigated. We have no Silk board available but the patch follows the same style as the other patches. In addition, these patches have been double-checked by vimdiff-comparing the i2c-bus blobs before and after this patchset. As discussed previously: the tested boards boot fine. No regression encountered there. However, changing masters at runtime for HDMI-named busses and PWR-named busses will likely cause kernel warnings and maybe OOPSes. This is due to the rebind-issues in the V4L and regulator subsystems. For the former, fixing is WIP. For the latter, it is unknown how to deal with rebinding in general (but I'd need to look at this issue again if this is desired). It was decided that we consider those follow-up problems which should not hold back these patches anymore. The EXIO named busses seemed to work fine as far as this could be remotely tested. Changes since last time (long ago!) include: * rebased (include all the updates to the I2C busses since back then) * converted to named-gpios * fixed some aliases * minor stuff like sorting the {scl|sda}-gpios entries properly The branch can be found here: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/topc/ip-switch-rework-2017 It is based on v4.15-rc1 + renesas/dt-for-v4.16 merged in. Please review, comment... Thanks, Wolfram Wolfram Sang (9): ARM: dts: lager: use demuxer for IIC2/I2C2 ARM: dts: lager: use demuxer for IIC3/I2C3 ARM: dts: koelsch: use demuxer for I2C2 ARM: dts: koelsch: use demuxer for I2C4 ARM: dts: porter: use demuxer for I2C2 ARM: dts: alt: use demuxer for I2C1 ARM: dts: silk: use demuxer for I2C1 ARM: dts: gose: use demuxer for I2C2 ARM: dts: gose: use demuxer for I2C4 arch/arm/boot/dts/r8a7790-lager.dts | 279 -- arch/arm/boot/dts/r8a7791-koelsch.dts | 232 +--- arch/arm/boot/dts/r8a7791-porter.dts | 128 +--- arch/arm/boot/dts/r8a7793-gose.dts| 252 ++ arch/arm/boot/dts/r8a7794-alt.dts | 53 +-- arch/arm/boot/dts/r8a7794-silk.dts| 128 +--- 6 files changed, 654 insertions(+), 418 deletions(-) -- 2.11.0
[PATCH 3/9] ARM: dts: koelsch: use demuxer for I2C2
Create a separate bus for HDMI related I2C2 and provide fallback to GPIO. Based on work for the r8a7790/lager by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, fixed aliases, switched to named GPIOs, sorted by SCL pins] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7791-koelsch.dts | 200 +++--- 1 file changed, 111 insertions(+), 89 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index a50924d12b6f37..4b20db197de629 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -51,7 +51,9 @@ serial0 = &scif0; serial1 = &scif1; i2c9 = &gpioi2c1; + i2c10 = &gpioi2c2; i2c12 = &i2cexio1; + i2c13 = &i2chdmi; }; chosen { @@ -312,8 +314,18 @@ #size-cells = <0>; compatible = "i2c-gpio"; status = "disabled"; - sda-gpios = <&gpio7 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; scl-gpios = <&gpio7 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio7 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + + gpioi2c2: i2c-10 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-gpio,delay-us = <5>; }; @@ -328,6 +340,103 @@ #address-cells = <1>; #size-cells = <0>; }; + + /* +* A fallback to GPIO is provided for I2C2. +*/ + i2chdmi: i2c-13 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c2>, <&gpioi2c2>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin1>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin1ep>; + }; + }; + }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio3>; + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; + clocks = <&cec_clock>; + clock-names = "cec"; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; + + hdmi-in@4c { + compatible = "adi,adv7612"; + reg = <0x4c>; + interrupt-parent = <&gpio4>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + default-input = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7612_in: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; + }; + + port@2 { + re
[PATCH 7/9] ARM: dts: silk: use demuxer for I2C1
Create a separate bus for HDMI related I2C1 and provide fallback to GPIO. Based on work for the r8a7790/lager by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, fixed aliases, switched to named GPIOs] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7794-silk.dts | 128 ++--- 1 file changed, 75 insertions(+), 53 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index edfad0e5ac53a0..f1afe2dda13a36 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -31,6 +31,8 @@ aliases { serial0 = &scif2; + i2c9 = &gpioi2c1; + i2c10 = &i2chdmi; }; chosen { @@ -153,6 +155,78 @@ clocks = <&x9_clk>; }; }; + + gpioi2c1: i2c-9 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio4 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + + /* +* A fallback to GPIO is provided for I2C1. +*/ + i2chdmi: i2c-10 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c1>, <&gpioi2c1>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin0>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin0ep>; + }; + }; + }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio5>; + interrupts = <23 IRQ_TYPE_LEVEL_LOW>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&du_out_rgb0>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; + }; }; &extal_clk { @@ -268,61 +342,9 @@ &i2c1 { pinctrl-0 = <&i2c1_pins>; - pinctrl-names = "default"; + pinctrl-names = "i2c-hdmi"; - status = "okay"; clock-frequency = <40>; - - ak4643: codec@12 { - compatible = "asahi-kasei,ak4643"; - #sound-dai-cells = <0>; - reg = <0x12>; - }; - - composite-in@20 { - compatible = "adi,adv7180"; - reg = <0x20>; - remote = <&vin0>; - - port { - adv7180: endpoint { - bus-width = <8>; - remote-endpoint = <&vin0ep>; - }; - }; - }; - - hdmi@39 { - compatible = "adi,adv7511w"; - reg = <0x39>; - interrupt-parent = <&gpio5>; - interrupts = <23 IRQ_TYPE_LEVEL_LOW>; - - adi,input-depth = <8>; - adi,input-colorspace = "rgb"; - adi,input-clock = "1x"; - adi,input-style = <1>; - adi,input-justification = "evenly"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - adv7511_in: endpoint { - remo
[PATCH 6/9] ARM: dts: alt: use demuxer for I2C1
Create a separate bus for HDMI related I2C1 and provide fallback to GPIO. Based on work for the r8a7790/lager by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, fixed aliases, switched to named GPIOs] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7794-alt.dts | 53 +++ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts index 60c6515c499660..26a883484ea814 100644 --- a/arch/arm/boot/dts/r8a7794-alt.dts +++ b/arch/arm/boot/dts/r8a7794-alt.dts @@ -18,7 +18,9 @@ aliases { serial0 = &scif2; + i2c9 = &gpioi2c1; i2c10 = &gpioi2c4; + i2c11 = &i2chdmi; i2c12 = &i2cexio4; }; @@ -138,17 +140,50 @@ clock-frequency = <14850>; }; + gpioi2c1: i2c-9 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio4 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + }; + gpioi2c4: i2c-10 { #address-cells = <1>; #size-cells = <0>; compatible = "i2c-gpio"; status = "disabled"; - sda-gpios = <&gpio4 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; scl-gpios = <&gpio4 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-gpio,delay-us = <5>; }; /* +* A fallback to GPIO is provided for I2C1. +*/ + i2chdmi: i2c-11 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c1>, <&gpioi2c1>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin0>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin0ep>; + }; + }; + }; + }; + + /* * I2C4 is routed to EXIO connector B, pins 73 (SCL) + 74 (SDA). * A fallback to GPIO is provided. */ @@ -324,23 +359,9 @@ &i2c1 { pinctrl-0 = <&i2c1_pins>; - pinctrl-names = "default"; + pinctrl-names = "i2c-hdmi"; - status = "okay"; clock-frequency = <40>; - - composite-in@20 { - compatible = "adi,adv7180"; - reg = <0x20>; - remote = <&vin0>; - - port { - adv7180: endpoint { - bus-width = <8>; - remote-endpoint = <&vin0ep>; - }; - }; - }; }; &i2c4 { -- 2.11.0
[PATCH 1/9] ARM: dts: lager: use demuxer for IIC2/I2C2
Create a separate bus for HDMI related I2C slaves. Based on work by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, removed typo in comment, fixed aliases, switched to named GPIOS, sort SCL pins first] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7790-lager.dts | 197 +--- 1 file changed, 116 insertions(+), 81 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index f2ea632381e7d1..e4050dae7e8e33 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -51,8 +51,10 @@ serial0 = &scif0; serial1 = &scifa1; i2c8 = &gpioi2c1; + i2c9 = &gpioi2c2; i2c10 = &i2cexio0; i2c11 = &i2cexio1; + i2c12 = &i2chdmi; }; chosen { @@ -272,8 +274,18 @@ #size-cells = <0>; compatible = "i2c-gpio"; status = "disabled"; - sda-gpios = <&gpio1 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; scl-gpios = <&gpio1 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + + gpioi2c2: i2c-9 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio5 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-gpio,delay-us = <5>; }; @@ -308,6 +320,96 @@ #address-cells = <1>; #size-cells = <0>; }; + +/* + * IIC2 and I2C2 may be switched using pinmux. + * A fallback to GPIO is also provided. + */ + i2chdmi: i2c-12 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&iic2>, <&i2c2>, <&gpioi2c2>; + i2c-bus-name = "i2c-hdmi"; + #address-cells = <1>; + #size-cells = <0>; + + ak4643: codec@12 { + compatible = "asahi-kasei,ak4643"; + #sound-dai-cells = <0>; + reg = <0x12>; + }; + + composite-in@20 { + compatible = "adi,adv7180"; + reg = <0x20>; + remote = <&vin1>; + + port { + adv7180: endpoint { + bus-width = <8>; + remote-endpoint = <&vin1ep0>; + }; + }; + }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <15 IRQ_TYPE_LEVEL_LOW>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&du_out_lvds0>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; + + hdmi-in@4c { + compatible = "adi,adv7612"; + reg = <0x4c>; + interrupt-parent = <&gpio1>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + default-input = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7612_in: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; + }; + + port@2 { + reg = <2>; +
[PATCH 9/9] ARM: dts: gose: use demuxer for I2C4
Make it possible to fallback to GPIO for I2C4 on the EXIO-E connector. This is based on reference work for the I2C0 core of the lager/r8a7790 by Wolfram Sang. Signed-off-by: Simon Horman [wsa: rebased, corrected board name in subject, fixed aliases, switched to named GPIOs] Signed-off-by: Wolfram Sang --- arch/arm/boot/dts/r8a7793-gose.dts | 34 ++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 2b330ef71f4c17..c2f6a0fd767527 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -49,7 +49,9 @@ serial0 = &scif0; serial1 = &scif1; i2c9 = &gpioi2c2; + i2c10 = &gpioi2c4; i2c11 = &i2chdmi; + i2c12 = &i2cexio4; }; chosen { @@ -309,6 +311,16 @@ i2c-gpio,delay-us = <5>; }; + gpioi2c4: i2c-10 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + scl-gpios = <&gpio7 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio7 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <5>; + }; + /* * A fallback to GPIO is provided for I2C2. */ @@ -416,6 +428,18 @@ pagesize = <16>; }; }; + + /* +* I2C4 is routed to EXIO connector E, pins 37 (SCL) + 39 (SDA). +* A fallback to GPIO is provided. +*/ + i2cexio4: i2c-12 { + compatible = "i2c-demux-pinctrl"; + i2c-parent = <&i2c4>, <&gpioi2c4>; + i2c-bus-name = "i2c-exio4"; + #address-cells = <1>; + #size-cells = <0>; + }; }; &du { @@ -454,6 +478,11 @@ function = "i2c2"; }; + i2c4_pins: i2c4 { + groups = "i2c4"; + function = "i2c4"; + }; + du_pins: du { groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; function = "du"; @@ -692,6 +721,11 @@ }; }; +&i2c4 { + pinctrl-0 = <&i2c4_pins>; + pinctrl-names = "i2c-exio4"; +}; + &rcar_sound { pinctrl-0 = <&sound_pins &sound_clk_pins>; pinctrl-names = "default"; -- 2.11.0
Re: [PATCH/RFC v2 15/15] adv748x: afe: add routing support
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > The adv748x afe have eight analog sink pads, currently one of them is s/have/has/ > chosen to be the active route based on device tree configuration. Whit s/Whit/With/ > the new routeing API it's possible to control which of the eight sink > pads are routed to the source pad. > Signed-off-by: Niklas Söderlund Aha, I had been wondering how we would handle this... Other than the minor nits, this is otherwise looking good Reviewed-by: Kieran Bingham > --- > drivers/media/i2c/adv748x/adv748x-afe.c | 66 > + > 1 file changed, 66 insertions(+) > > diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c > b/drivers/media/i2c/adv748x/adv748x-afe.c > index 5188178588c9067d..5dda85c707f6efd7 100644 > --- a/drivers/media/i2c/adv748x/adv748x-afe.c > +++ b/drivers/media/i2c/adv748x/adv748x-afe.c > @@ -43,6 +43,9 @@ > #define ADV748X_AFE_STD_PAL_SECAM0xe > #define ADV748X_AFE_STD_PAL_SECAM_PED0xf > > +#define ADV748X_AFE_ROUTES_MAX ((ADV748X_AFE_SINK_AIN7 - \ > + ADV748X_AFE_SINK_AIN0) + 1) > + > static int adv748x_afe_read_ro_map(struct adv748x_state *state, u8 reg) > { > int ret; > @@ -386,10 +389,73 @@ static int adv748x_afe_set_format(struct v4l2_subdev > *sd, > return 0; > } > > + No need for that extra line.. > +static int adv748x_afe_get_routing(struct v4l2_subdev *sd, > +struct v4l2_subdev_routing *routing) > +{ > + struct adv748x_afe *afe = adv748x_sd_to_afe(sd); > + struct v4l2_subdev_route *r = routing->routes; > + unsigned int i; > + > + /* There are one possible route from each sink */ There is one possible ... > + if (routing->num_routes < ADV748X_AFE_ROUTES_MAX) { > + routing->num_routes = ADV748X_AFE_ROUTES_MAX; > + return -ENOSPC; > + } > + > + routing->num_routes = ADV748X_AFE_ROUTES_MAX; > + > + for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) { > + r->sink_pad = i; > + r->sink_stream = 0; > + r->source_pad = ADV748X_AFE_SOURCE; > + r->source_stream = 0; > + r->flags = afe->input == i ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0; > + r++; > + } > + > + return 0; > +} > + > +static int adv748x_afe_set_routing(struct v4l2_subdev *sd, > +struct v4l2_subdev_routing *routing) > +{ > + struct adv748x_afe *afe = adv748x_sd_to_afe(sd); > + struct v4l2_subdev_route *r = routing->routes; > + int input = -1; > + unsigned int i; > + > + if (routing->num_routes > ADV748X_AFE_ROUTES_MAX) > + return -ENOSPC; > + > + for (i = 0; i < routing->num_routes; i++) { > + if (r->sink_pad > ADV748X_AFE_SINK_AIN7 || > + r->sink_stream != 0 || > + r->source_pad != ADV748X_AFE_SOURCE || > + r->source_stream != 0) > + return -EINVAL; > + > + if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) { > + if (input != -1) > + return -EMLINK; > + > + input = r->sink_pad; > + } > + r++; > + } > + > + if (input != -1) > + afe->input = input;> + > + return 0; > +} > + > static const struct v4l2_subdev_pad_ops adv748x_afe_pad_ops = { > .enum_mbus_code = adv748x_afe_enum_mbus_code, > .set_fmt = adv748x_afe_set_format, > .get_fmt = adv748x_afe_get_format, > + .get_routing = adv748x_afe_get_routing, > + .set_routing = adv748x_afe_set_routing, > }; > > /* > - >
Re: [PATCH/RFC v2 15/15] adv748x: afe: add routing support
One more ... On 14/12/17 22:56, Kieran Bingham wrote: > Hi Niklas, > > On 14/12/17 19:08, Niklas Söderlund wrote: >> The adv748x afe have eight analog sink pads, currently one of them is > > s/have/has/ > >> chosen to be the active route based on device tree configuration. Whit > > s/Whit/With/ > >> the new routeing API it's possible to control which of the eight sink While routeing is correctly spelt, it is used as routing everywhere else... s/routeing/routing/ >> pads are routed to the source pad. > >> Signed-off-by: Niklas Söderlund > > Aha, I had been wondering how we would handle this... > > Other than the minor nits, this is otherwise looking good > > Reviewed-by: Kieran Bingham > >> --- >> drivers/media/i2c/adv748x/adv748x-afe.c | 66 >> + >> 1 file changed, 66 insertions(+) >> >> diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c >> b/drivers/media/i2c/adv748x/adv748x-afe.c >> index 5188178588c9067d..5dda85c707f6efd7 100644 >> --- a/drivers/media/i2c/adv748x/adv748x-afe.c >> +++ b/drivers/media/i2c/adv748x/adv748x-afe.c >> @@ -43,6 +43,9 @@ >> #define ADV748X_AFE_STD_PAL_SECAM 0xe >> #define ADV748X_AFE_STD_PAL_SECAM_PED 0xf >> >> +#define ADV748X_AFE_ROUTES_MAX ((ADV748X_AFE_SINK_AIN7 - \ >> +ADV748X_AFE_SINK_AIN0) + 1) >> + >> static int adv748x_afe_read_ro_map(struct adv748x_state *state, u8 reg) >> { >> int ret; >> @@ -386,10 +389,73 @@ static int adv748x_afe_set_format(struct v4l2_subdev >> *sd, >> return 0; >> } >> >> + > > No need for that extra line.. > >> +static int adv748x_afe_get_routing(struct v4l2_subdev *sd, >> + struct v4l2_subdev_routing *routing) >> +{ >> +struct adv748x_afe *afe = adv748x_sd_to_afe(sd); >> +struct v4l2_subdev_route *r = routing->routes; >> +unsigned int i; >> + >> +/* There are one possible route from each sink */ > > There is one possible ... > >> +if (routing->num_routes < ADV748X_AFE_ROUTES_MAX) { >> +routing->num_routes = ADV748X_AFE_ROUTES_MAX; >> +return -ENOSPC; >> +} >> + >> +routing->num_routes = ADV748X_AFE_ROUTES_MAX; >> + >> +for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) { >> +r->sink_pad = i; >> +r->sink_stream = 0; >> +r->source_pad = ADV748X_AFE_SOURCE; >> +r->source_stream = 0; >> +r->flags = afe->input == i ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0; >> +r++; >> +} >> + >> +return 0; >> +} >> + >> +static int adv748x_afe_set_routing(struct v4l2_subdev *sd, >> + struct v4l2_subdev_routing *routing) >> +{ >> +struct adv748x_afe *afe = adv748x_sd_to_afe(sd); >> +struct v4l2_subdev_route *r = routing->routes; >> +int input = -1; >> +unsigned int i; >> + >> +if (routing->num_routes > ADV748X_AFE_ROUTES_MAX) >> +return -ENOSPC; >> + >> +for (i = 0; i < routing->num_routes; i++) { >> +if (r->sink_pad > ADV748X_AFE_SINK_AIN7 || >> +r->sink_stream != 0 || >> +r->source_pad != ADV748X_AFE_SOURCE || >> +r->source_stream != 0) >> +return -EINVAL; >> + >> +if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) { >> +if (input != -1) >> +return -EMLINK; >> + >> +input = r->sink_pad; >> +} >> +r++; >> +} >> + >> +if (input != -1) >> +afe->input = input;> + >> +return 0; >> +} >> + >> static const struct v4l2_subdev_pad_ops adv748x_afe_pad_ops = { >> .enum_mbus_code = adv748x_afe_enum_mbus_code, >> .set_fmt = adv748x_afe_set_format, >> .get_fmt = adv748x_afe_get_format, >> +.get_routing = adv748x_afe_get_routing, >> +.set_routing = adv748x_afe_set_routing, >> }; >> >> /* >> - >>
Re: [PATCH/RFC v2 12/15] adv748x: csi2: switch to pad and stream aware s_stream
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > Switch the driver to implement the pad and stream aware s_stream > operation. This is needed to enable to support to start and stop > individual streams on a multiplexed pad "This is needed to enable support for starting and stopping individual streams on a multiplexed pad." > Signed-off-by: Niklas Söderlund Otherwise, Reviewed-by: Kieran Bingham > --- > drivers/media/i2c/adv748x/adv748x-csi2.c | 16 ++-- > 1 file changed, 10 insertions(+), 6 deletions(-) > > diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c > b/drivers/media/i2c/adv748x/adv748x-csi2.c > index a43b251d0bc67a43..39f993282dd3bb5c 100644 > --- a/drivers/media/i2c/adv748x/adv748x-csi2.c > +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c > @@ -128,22 +128,26 @@ static const struct v4l2_subdev_internal_ops > adv748x_csi2_internal_ops = { > * v4l2_subdev_video_ops > */ > > -static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, int enable) > +static int adv748x_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad, > + unsigned int stream, int enable) > { > struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); > + struct adv748x_state *state = tx->state; > struct v4l2_subdev *src; > > + if (pad != ADV748X_CSI2_SOURCE || stream != 0) > + return -EINVAL; > + > src = adv748x_get_remote_sd(&tx->pads[ADV748X_CSI2_SINK]); > if (!src) > return -EPIPE; > > + adv_dbg(state, "%s: pad: %u stream: %u enable: %d\n", sd->name, > + pad, stream, enable); > + > return v4l2_subdev_call(src, video, s_stream, enable); > } > > -static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { > - .s_stream = adv748x_csi2_s_stream, > -}; > - > /* > - > * v4l2_subdev_pad_ops > * > @@ -256,6 +260,7 @@ static const struct v4l2_subdev_pad_ops > adv748x_csi2_pad_ops = { > .get_fmt = adv748x_csi2_get_format, > .set_fmt = adv748x_csi2_set_format, > .get_frame_desc = adv748x_csi2_get_frame_desc, > + .s_stream = adv748x_csi2_s_stream, > }; > > /* > - > @@ -263,7 +268,6 @@ static const struct v4l2_subdev_pad_ops > adv748x_csi2_pad_ops = { > */ > > static const struct v4l2_subdev_ops adv748x_csi2_ops = { > - .video = &adv748x_csi2_video_ops, > .pad = &adv748x_csi2_pad_ops, > }; > >
Re: [PATCH/RFC v2 13/15] adv748x: csi2: only allow formats on sink pads
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > The driver is now pad and stream aware, only allow to get/set format on > sink pads. Ok - I can see the patch is doing this ... > Also record a different format for each sink pad since it's > no longer true that they are all the same But I can't see how the patch is doing this ^ ? What have I missed? -- Kieran > Signed-off-by: Niklas Söderlund > --- > drivers/media/i2c/adv748x/adv748x-csi2.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c > b/drivers/media/i2c/adv748x/adv748x-csi2.c > index 39f993282dd3bb5c..291b35bef49d41fb 100644 > --- a/drivers/media/i2c/adv748x/adv748x-csi2.c > +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c > @@ -176,6 +176,9 @@ static int adv748x_csi2_get_format(struct v4l2_subdev *sd, > struct adv748x_state *state = tx->state; > struct v4l2_mbus_framefmt *mbusformat; > > + if (sdformat->pad != ADV748X_CSI2_SINK) > + return -EINVAL; > + > mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, >sdformat->which); > if (!mbusformat) > @@ -199,6 +202,9 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, > struct v4l2_mbus_framefmt *mbusformat; > int ret = 0; > > + if (sdformat->pad != ADV748X_CSI2_SINK) > + return -EINVAL; > + > mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad, >sdformat->which); > if (!mbusformat) >
Re: [PATCH/RFC v2 14/15] adv748x: csi2: add get_routing support
Hi Niklas, On 14/12/17 19:08, Niklas Söderlund wrote: > To support multiplexed streams the internal routing between the > adv748x sink pad and its source pad needs to be described. The adv748x has quite a few sink and source pads... I presume here you mean the adv748x csi2 sink and source pad :D > > Signed-off-by: Niklas Söderlund > --- > drivers/media/i2c/adv748x/adv748x-csi2.c | 22 ++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c > b/drivers/media/i2c/adv748x/adv748x-csi2.c > index 291b35bef49d41fb..dbefb53f5b8c414d 100644 > --- a/drivers/media/i2c/adv748x/adv748x-csi2.c > +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c > @@ -262,10 +262,32 @@ static int adv748x_csi2_get_frame_desc(struct > v4l2_subdev *sd, unsigned int pad, > return 0; > } > > +static int adv748x_csi2_get_routing(struct v4l2_subdev *subdev, > + struct v4l2_subdev_routing *routing) > +{ > + struct v4l2_subdev_route *r = routing->routes; > + > + if (routing->num_routes < 1) { > + routing->num_routes = 1; > + return -ENOSPC; > + } > + > + routing->num_routes = 1; > + > + r->sink_pad = ADV748X_CSI2_SINK; > + r->sink_stream = 0; > + r->source_pad = ADV748X_CSI2_SOURCE; > + r->source_stream = 0; > + r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE | V4L2_SUBDEV_ROUTE_FL_IMMUTABLE; > + > + return 0; > +} > + So - I think this is fine - but it seems a lot of code to define a static default route which describes a single link between it's sink pad - and its source pad ... I suspect this should/could be wrapped by some helpers in core for cases like this, as it's the simple case - but as we don't currently have that I guess we have to put this in here for now ? Maybe we should have a helper to make this return v4l2_subdev_single_route(subdev, routing, ADV748X_CS2_SINK, 0, ADV748X_CSI2_SOURCE, 0, V4L2_SUBDEV_ROUTE_FL_ACTIVE | V4L2_SUBDEV_ROUTE_FL_IMMUTABLE); Or maybe even define these static routes in a struct somehow? > static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { > .get_fmt = adv748x_csi2_get_format, > .set_fmt = adv748x_csi2_set_format, > .get_frame_desc = adv748x_csi2_get_frame_desc, > + .get_routing = adv748x_csi2_get_routing, > .s_stream = adv748x_csi2_s_stream, > }; > >
[renesas-drivers:topic/renesas-overlays 30/92] drivers/of/base.c:1571:1: sparse: symbol 'dead_aliases_lookup' was not declared. Should it be static?
tree: https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git topic/renesas-overlays head: 47d433a558bb60587eb9f86a4d010ef74e03fa0d commit: 19e0da502da117244914b018be929c1ba0761d14 [30/92] [RFC] of: Add of_alias_destroy() reproduce: # apt-get install sparse git checkout 19e0da502da117244914b018be929c1ba0761d14 make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
[RFC PATCH renesas-drivers] [RFC] of: dead_aliases_lookup can be static
Fixes: 19e0da502da1 ("[RFC] of: Add of_alias_destroy()") Signed-off-by: Fengguang Wu --- base.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 5d3a0ad..1f3f84c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1568,7 +1568,7 @@ void of_alias_create(struct property *pp, } #ifdef CONFIG_OF_DYNAMIC -LIST_HEAD(dead_aliases_lookup); +static LIST_HEAD(dead_aliases_lookup); void of_alias_destroy(const char *name) {
Re: [PATCH v2] drm: rcar-du: calculate DPLLCR to be more small jitter
Hi Geert, Laurent > >> Yes, but compiled by 32bit too, right ? > >> Without this "ll", 32bit compiler say > >> > >> warning: this decimal constant is unsigned only in ISO C90 > > > > That's right. How about 409600UL then, to force unsigned integer types ? > > Or possibly even better, 4096 * 1000 * 1000UL to make it more readable ? > > If it's just about making the number unsigned, and not about 64-bit > arithmetic, > a "U" suffix should be sufficient. Thanks. Will try Best regards --- Kuninori Morimoto
[PATCH v3 0/2] drm: rcar-du: calculate DPLLCR to be more small jitter
Hi Laurent, David These are v3 of DPLLCR patch for rcar-du. [1/2] is added Kuninori Morimoto (2): drm: rcar-du: use 1000 to avoid misunderstanding in rcar_du_dpll_divider() drm: rcar-du: calculate DPLLCR to be more small jitter drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 60 +++--- 1 file changed, 55 insertions(+), 5 deletions(-) -- 1.9.1
[PATCH v3 1/2] drm: rcar-du: use 1000 to avoid misunderstanding in rcar_du_dpll_divider()
From: Kuninori Morimoto It is difficult to understand its scale if number has many 0s. This patch uses "* 1000" to avoid it in rcar_du_dpll_divider(). Signed-off-by: Kuninori Morimoto --- v2 -> v3 - new patch drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 5685d5a..6820461f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -132,7 +132,7 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc, output = input * (n + 1) / (m + 1) / (fdpll + 1); - if (output >= 4) + if (output >= 400 * 1000 * 1000) continue; diff = abs((long)output - (long)target); -- 1.9.1
[PATCH v3 2/2] drm: rcar-du: calculate DPLLCR to be more small jitter
From: Kuninori Morimoto In general, PLL has VCO (= Voltage controlled oscillator), one of the very important electronic feature called as "jitter" is related to this VCO. In academic generalism, VCO should be maximum to be more small jitter. In high frequency clock, jitter will be large impact. Thus, selecting Hi VCO is general theory. fin fvcofout fclkout in --> [1/M] --> |PD| -> [LPF] -> [VCO] -> [1/P] -+-> [1/FDPLL] -> out +-> | | | || +-[1/N]<-+ fclkout = fvco / P / FDPLL -- (1) In PD, it will loop until fin/M = fvco/P/N fvco = fin * P * N / M -- (2) (1) + (2) indicates fclkout = fin * N / M / FDPLL In this device, N = (n + 1), M = (m + 1), P = 2, FDPLL = (fdpll + 1). fclkout = fin * (n + 1) / (m + 1) / (fdpll + 1) This is the datasheet formula. One note here is that it should be 2000 < fvco < 4096MHz To be smaller jitter, fvco should be maximum, in other words, N as large as possible, M as small as possible driver should select. Here, basically M=1. This patch do it. Reported-by: HIROSHI INOSE Signed-off-by: Kuninori Morimoto --- v2 -> v3 - uses "* 1000" for number - uses "xx000U" for number - uses finnm to avoid duplicate calculation drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 58 +++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 6820461f..bb5ead6 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -125,13 +125,63 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc, unsigned int m; unsigned int n; - for (n = 39; n < 120; n++) { - for (m = 0; m < 4; m++) { + /* +* fin fvcofout fclkout +* in --> [1/M] --> |PD| -> [LPF] -> [VCO] -> [1/P] -+-> [1/FDPLL] -> out +* +-> | | | +* || +* +-[1/N]<-+ +* +* fclkout = fvco / P / FDPLL -- (1) +* +* fin/M = fvco/P/N +* +* fvco = fin * P * N / M -- (2) +* +* (1) + (2) indicates +* +* fclkout = fin * N / M / FDPLL +* +* NOTES +* N : (n + 1) +* M : (m + 1) +* FDPLL : (fdpll + 1) +* P : 2 +* 2000 < fvco < 4096Mhz +* +* To be small jitter, +* N : as large as possible +* M : as small as possible +*/ + for (m = 0; m < 4; m++) { + for (n = 119; n > 38; n--) { + /* +* NOTE: +* +* This code is assuming "used" from 64bit CPU only, +* not from 32bit CPU. But both can compile correctly +*/ + + /* +* fvco= fin * P * N / M +* fclkout = fin * N / M / FDPLL +* +* To avoid duplicate calculation, let's use below +* +* finnm = fin * N / M +* fvco= finnm * P +* fclkout = finnm / FDPLL +*/ + unsigned long finnm = input * (n + 1) / (m + 1); + unsigned long fvco = finnm * 2; + + if (fvco < 2000 || fvco > 4096 * 1000 * 1000U) + continue; + for (fdpll = 1; fdpll < 32; fdpll++) { unsigned long output; - output = input * (n + 1) / (m + 1) - / (fdpll + 1); + output = finnm / (fdpll + 1); if (output >= 400 * 1000 * 1000) continue; -- 1.9.1
[PATCH v2 1/6] phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway
In the future, the work struct will be used by non-irq related code. So, this patch moves the INIT_WORK() timing. Signed-off-by: Yoshihiro Shimoda --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 9c90e7d..c22d65a 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -431,10 +431,11 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) if (IS_ERR(channel->base)) return PTR_ERR(channel->base); + INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); + /* call request_irq for OTG */ irq = platform_get_irq(pdev, 0); if (irq >= 0) { - INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, IRQF_SHARED, dev_name(dev), channel); if (irq < 0) -- 1.9.1
[PATCH v2 2/6] phy: renesas: rcar-gen3-usb2: unify OBINTEN handling
This patch unifies the OBINTEN handling to clean-up the code. Signed-off-by: Yoshihiro Shimoda --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 23 +++ 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index c22d65a..480f912 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -147,6 +147,18 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) writel(val, usb2_base + USB2_ADPCTRL); } +static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) +{ + void __iomem *usb2_base = ch->base; + u32 val = readl(usb2_base + USB2_OBINTEN); + + if (enable) + val |= USB2_OBINT_BITS; + else + val &= ~USB2_OBINT_BITS; + writel(val, usb2_base + USB2_OBINTEN); +} + static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) { rcar_gen3_set_linectrl(ch, 1, 1); @@ -192,16 +204,12 @@ static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch) static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) { - void __iomem *usb2_base = ch->base; - u32 val; - - val = readl(usb2_base + USB2_OBINTEN); - writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); + rcar_gen3_control_otg_irq(ch, 0); rcar_gen3_enable_vbus_ctrl(ch, 0); rcar_gen3_init_for_host(ch); - writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); + rcar_gen3_control_otg_irq(ch, 1); } static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) @@ -291,8 +299,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) val = readl(usb2_base + USB2_VBCTRL); writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); - val = readl(usb2_base + USB2_OBINTEN); - writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); + rcar_gen3_control_otg_irq(ch, 1); val = readl(usb2_base + USB2_ADPCTRL); writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); val = readl(usb2_base + USB2_LINECTRL1); -- 1.9.1
[PATCH v2 3/6] phy: renesas: rcar-gen3-usb2: change the function name to set_vbus_ctrl()
This patch changes the function name from rcar_gen3_enable_vbus_ctrl() to rcar_gen3_set_vbus_ctrl() because the fucntion both enables and disables. Signed-off-by: Yoshihiro Shimoda --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 480f912..bca6162 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -134,13 +134,13 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) writel(val, usb2_base + USB2_LINECTRL1); } -static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) +static void rcar_gen3_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) { void __iomem *usb2_base = ch->base; u32 val = readl(usb2_base + USB2_ADPCTRL); - dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus); - if (vbus) + dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, enable); + if (enable) val |= USB2_ADPCTRL_DRVVBUS; else val &= ~USB2_ADPCTRL_DRVVBUS; @@ -163,7 +163,7 @@ static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) { rcar_gen3_set_linectrl(ch, 1, 1); rcar_gen3_set_host_mode(ch, 1); - rcar_gen3_enable_vbus_ctrl(ch, 1); + rcar_gen3_set_vbus_ctrl(ch, 1); ch->extcon_host = true; schedule_work(&ch->work); @@ -173,7 +173,7 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) { rcar_gen3_set_linectrl(ch, 0, 1); rcar_gen3_set_host_mode(ch, 0); - rcar_gen3_enable_vbus_ctrl(ch, 0); + rcar_gen3_set_vbus_ctrl(ch, 0); ch->extcon_host = false; schedule_work(&ch->work); @@ -189,7 +189,7 @@ static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch) rcar_gen3_set_linectrl(ch, 1, 1); rcar_gen3_set_host_mode(ch, 1); - rcar_gen3_enable_vbus_ctrl(ch, 0); + rcar_gen3_set_vbus_ctrl(ch, 0); val = readl(usb2_base + USB2_LINECTRL1); writel(val & ~USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1); @@ -199,14 +199,14 @@ static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch) { rcar_gen3_set_linectrl(ch, 0, 1); rcar_gen3_set_host_mode(ch, 0); - rcar_gen3_enable_vbus_ctrl(ch, 1); + rcar_gen3_set_vbus_ctrl(ch, 1); } static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) { rcar_gen3_control_otg_irq(ch, 0); - rcar_gen3_enable_vbus_ctrl(ch, 0); + rcar_gen3_set_vbus_ctrl(ch, 0); rcar_gen3_init_for_host(ch); rcar_gen3_control_otg_irq(ch, 1); -- 1.9.1
[PATCH v2 0/6] phy: renesas: rcar-gen3-usb2: add gpio handling for R-Car D3
This patch set is based on the latest linux-phy / next branch (commit id = 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323). This new feature will be used by the renesas_usbhs driver on R-Car D3. Changes from v1: - Drop "renesas," from the names of gpio property. - Change function names of "enable_" to "control_" or "set_" that will enable/disable irq or vbus. Yoshihiro Shimoda (6): phy: renesas: rcar-gen3-usb2: call INIT_WORK() anyway phy: renesas: rcar-gen3-usb2: unify OBINTEN handling phy: renesas: rcar-gen3-usb2: change the function name to set_vbus_ctrl() phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated pins handling phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops phy: renesas: rcar-gen3-usb2: add gpio handling .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 2 + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 276 - 2 files changed, 213 insertions(+), 65 deletions(-) -- 1.9.1
[PATCH v2 6/6] phy: renesas: rcar-gen3-usb2: add gpio handling
Some R-Car SoCs (e.g. R-Car D3) doesn't have dedicated pins of VBUS and ID. So, they may be connected to gpio pins. To handle the gpio pins, this patch adds the handling of VBUS and ID pins instead of dedicated pins. Signed-off-by: Yoshihiro Shimoda --- .../devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 2 + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 77 -- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt index 99b651b..999a6ef 100644 --- a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt +++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt @@ -27,6 +27,8 @@ channel as USB OTG: - interrupts: interrupt specifier for the PHY. - vbus-supply: Phandle to a regulator that provides power to the VBUS. This regulator will be managed during the PHY power on/off sequence. +- vbus-gpios: use gpio to control vbus instead of dedicated pin. +- id-gpios: use gpio to detect id instead of dedicated pin. Example (R-Car H3): diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index f470fb3..ea76973 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -100,9 +101,12 @@ struct rcar_gen3_chan { struct phy *phy; struct regulator *vbus; const struct rcar_gen3_role_swap_ops *rs_ops; + struct gpio_desc *gpio_vbus; + struct gpio_desc *gpio_id; struct work_struct work; bool extcon_host; bool has_otg_pins; + bool has_gpio; }; static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) @@ -199,6 +203,36 @@ static void has_otg_pins_init(struct rcar_gen3_chan *ch) usb2_base + USB2_LINECTRL1); } +static void gpio_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) +{ + gpiod_set_value(ch->gpio_vbus, enable); +} + +static bool gpio_check_id(struct rcar_gen3_chan *ch) +{ + return gpiod_get_value(ch->gpio_id); +} + +static void gpio_set_host(struct rcar_gen3_chan *ch, int host) +{ + /* In gpio ops, this driver will modify the extcon_host by sysfs */ + if (ch->extcon_host != !!host) { + ch->extcon_host = !!host; + schedule_work(&ch->work); + } +} + +static bool gpio_is_host(struct rcar_gen3_chan *ch) +{ + return ch->extcon_host; +} + +static irqreturn_t gpio_irq_handler(struct rcar_gen3_chan *ch) +{ + /* Nop because the driver will get gpio value after exited */ + return IRQ_HANDLED; +} + static void rcar_gen3_phy_usb2_work(struct work_struct *work) { struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan, @@ -323,7 +357,7 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr, bool is_b_device; enum phy_mode cur_mode, new_mode; - if (!ch->has_otg_pins || !ch->phy->init_count) + if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count) return -EIO; if (!strncmp(buf, "host", strlen("host"))) @@ -361,7 +395,7 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr, { struct rcar_gen3_chan *ch = dev_get_drvdata(dev); - if (!ch->has_otg_pins || !ch->phy->init_count) + if (!(ch->has_otg_pins || ch->has_gpio) || !ch->phy->init_count) return -EIO; return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" : @@ -388,7 +422,7 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); /* Initialize otg part */ - if (channel->has_otg_pins) + if (channel->has_otg_pins || channel->has_gpio) rcar_gen3_init_otg(channel); return 0; @@ -489,6 +523,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) .irq_handler= has_otg_pins_irq_handler, }; +static const struct rcar_gen3_role_swap_ops gpio_ops = { + .set_host = gpio_set_host, + .is_host= gpio_is_host, + .set_vbus_ctrl = gpio_set_vbus_ctrl, + .check_id = gpio_check_id, + .irq_handler= gpio_irq_handler, +}; + static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -513,9 +555,30 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); - /* call request_irq for OTG */ + channel->gpio_vbus = devm_gpiod_get(dev, "vbus", GPIOD_OUT_LOW); + if (IS_ERR(channel->gpio_vbus) && + PTR_ERR(channel->gpio_vbus) == -EPROBE_DEFER) + return PTR_ERR(channel->gpio_vbus); + + channel->gpio_id = devm_gpiod_get
[PATCH v2 5/6] phy: renesas: rcar-gen3-usb2: add rcar_gen3_role_swap_ops
This patch add rcar_gen3_role_swap_ops to support other feature (e.g. gpio handling) easily. Signed-off-by: Yoshihiro Shimoda --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 51 +++- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index b121f07..f470fb3 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -83,11 +83,23 @@ #define RCAR_GEN3_PHY_HAS_DEDICATED_PINS 1 +struct rcar_gen3_chan; +struct rcar_gen3_role_swap_ops { + void (*init)(struct rcar_gen3_chan *ch); + void (*set_host)(struct rcar_gen3_chan *ch, int host); + bool (*is_host)(struct rcar_gen3_chan *ch); + void (*set_vbus_ctrl)(struct rcar_gen3_chan *ch, int enable); + bool (*check_id)(struct rcar_gen3_chan *ch); + void (*control_irq)(struct rcar_gen3_chan *ch, int enable); + irqreturn_t (*irq_handler)(struct rcar_gen3_chan *ch); +}; + struct rcar_gen3_chan { void __iomem *base; struct extcon_dev *extcon; struct phy *phy; struct regulator *vbus; + const struct rcar_gen3_role_swap_ops *rs_ops; struct work_struct work; bool extcon_host; bool has_otg_pins; @@ -203,17 +215,20 @@ static void rcar_gen3_phy_usb2_work(struct work_struct *work) static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) { - has_otg_pins_set_host(ch, host); + if (ch->rs_ops && ch->rs_ops->set_host) + ch->rs_ops->set_host(ch, host); } static void rcar_gen3_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) { - has_otg_pins_set_vbus_ctrl(ch, enable); + if (ch->rs_ops && ch->rs_ops->set_vbus_ctrl) + ch->rs_ops->set_vbus_ctrl(ch, enable); } static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) { - has_otg_pins_control_irq(ch, enable); + if (ch->rs_ops && ch->rs_ops->control_irq) + ch->rs_ops->control_irq(ch, enable); } static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) @@ -271,7 +286,10 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) { - return has_otg_pins_check_id(ch); + if (ch->rs_ops && ch->rs_ops->check_id) + return ch->rs_ops->check_id(ch); + + return false; } static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) @@ -284,7 +302,10 @@ static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch) { - return has_otg_pins_is_host(ch); + if (ch->rs_ops && ch->rs_ops->is_host) + return ch->rs_ops->is_host(ch); + + return false; } static enum phy_mode rcar_gen3_get_phy_mode(struct rcar_gen3_chan *ch) @@ -350,7 +371,8 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr, static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) { - has_otg_pins_init(ch); + if (ch->rs_ops && ch->rs_ops->init) + ch->rs_ops->init(ch); rcar_gen3_device_recognition(ch); } @@ -425,9 +447,10 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) { struct rcar_gen3_chan *ch = _ch; - irqreturn_t ret; + irqreturn_t ret = IRQ_NONE; - ret = has_otg_pins_irq_handler(ch); + if (ch->rs_ops && ch->rs_ops->irq_handler) + ret = ch->rs_ops->irq_handler(ch); if (ret == IRQ_HANDLED) rcar_gen3_device_recognition(ch); @@ -456,6 +479,16 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) EXTCON_NONE, }; +static const struct rcar_gen3_role_swap_ops has_otg_pins_ops = { + .init = has_otg_pins_init, + .set_host = has_otg_pins_set_host, + .is_host= has_otg_pins_is_host, + .set_vbus_ctrl = has_otg_pins_set_vbus_ctrl, + .check_id = has_otg_pins_check_id, + .control_irq= has_otg_pins_control_irq, + .irq_handler= has_otg_pins_irq_handler, +}; + static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -493,6 +526,8 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) int ret; channel->has_otg_pins = (uintptr_t)of_device_get_match_data(dev); + if (channel->has_otg_pins) + channel->rs_ops = &has_otg_pins_ops; channel->extcon = devm_extcon_dev_allocate(dev, rcar_gen3_phy_cable); if (IS_ERR(channel->extcon)) -- 1.9.1
[PATCH v2 4/6] phy: renesas: rcar-gen3-usb2: use prefix "has_otg_pins_" for dedicated pins handling
To support gpio handling in the future, this patch clean-ups the code to use prefix "has_otg_pins_" functions. Signed-off-by: Yoshihiro Shimoda --- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 130 --- 1 file changed, 85 insertions(+), 45 deletions(-) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index bca6162..b121f07 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -93,21 +93,21 @@ struct rcar_gen3_chan { bool has_otg_pins; }; -static void rcar_gen3_phy_usb2_work(struct work_struct *work) +static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) { - struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan, -work); + void __iomem *usb2_base = ch->base; + u32 val = readl(usb2_base + USB2_LINECTRL1); - if (ch->extcon_host) { - extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true); - extcon_set_state_sync(ch->extcon, EXTCON_USB, false); - } else { - extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false); - extcon_set_state_sync(ch->extcon, EXTCON_USB, true); - } + dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); + val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); + if (dp) + val |= USB2_LINECTRL1_DP_RPD; + if (dm) + val |= USB2_LINECTRL1_DM_RPD; + writel(val, usb2_base + USB2_LINECTRL1); } -static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) +static void has_otg_pins_set_host(struct rcar_gen3_chan *ch, int host) { void __iomem *usb2_base = ch->base; u32 val = readl(usb2_base + USB2_COMMCTRL); @@ -120,21 +120,27 @@ static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) writel(val, usb2_base + USB2_COMMCTRL); } -static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) +static bool has_otg_pins_is_host(struct rcar_gen3_chan *ch) +{ + return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); +} + +static irqreturn_t has_otg_pins_irq_handler(struct rcar_gen3_chan *ch) { void __iomem *usb2_base = ch->base; - u32 val = readl(usb2_base + USB2_LINECTRL1); + u32 status = readl(usb2_base + USB2_OBINTSTA); + irqreturn_t ret = IRQ_NONE; - dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); - val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); - if (dp) - val |= USB2_LINECTRL1_DP_RPD; - if (dm) - val |= USB2_LINECTRL1_DM_RPD; - writel(val, usb2_base + USB2_LINECTRL1); + if (status & USB2_OBINT_BITS) { + dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status); + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); + ret = IRQ_HANDLED; + } + + return ret; } -static void rcar_gen3_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) +static void has_otg_pins_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) { void __iomem *usb2_base = ch->base; u32 val = readl(usb2_base + USB2_ADPCTRL); @@ -147,7 +153,7 @@ static void rcar_gen3_set_vbus_ctrl(struct rcar_gen3_chan *ch, int enable) writel(val, usb2_base + USB2_ADPCTRL); } -static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) +static void has_otg_pins_control_irq(struct rcar_gen3_chan *ch, int enable) { void __iomem *usb2_base = ch->base; u32 val = readl(usb2_base + USB2_OBINTEN); @@ -159,6 +165,57 @@ static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable) writel(val, usb2_base + USB2_OBINTEN); } +static bool has_otg_pins_check_id(struct rcar_gen3_chan *ch) +{ + return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); +} + +static void has_otg_pins_init(struct rcar_gen3_chan *ch) +{ + void __iomem *usb2_base = ch->base; + u32 val; + + val = readl(usb2_base + USB2_VBCTRL); + writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); + has_otg_pins_control_irq(ch, 1); + val = readl(usb2_base + USB2_ADPCTRL); + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); + val = readl(usb2_base + USB2_LINECTRL1); + rcar_gen3_set_linectrl(ch, 0, 0); + writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN, + usb2_base + USB2_LINECTRL1); +} + +static void rcar_gen3_phy_usb2_work(struct work_struct *work) +{ + struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan, +work); + + if (ch->extcon_host) { + extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, tr