* [RESEND PATCH v2] bus: arm-cci: use asm unreachable
From: Stefan Agner @ 2018-05-08 13:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9925be9a-2e24-7ab4-4d7e-cb8f62c422e7@arm.com>
On 08.05.2018 14:19, Robin Murphy wrote:
> On 08/05/18 12:32, Stefan Agner wrote:
>> Mixing asm and C code is not recommended in a naked function by
>> gcc and leads to an error when using clang:
>> drivers/bus/arm-cci.c:2107:2: error: non-ASM statement in naked
>> function is not supported
>> unreachable();
>> ^
>>
>> While the function is marked __naked it actually properly return
>> in asm. There is no need for the unreachable() call.
>
> The commit title is a bit out-of-date now (I guess it could just be
> something like "remove unnecessary unreachable()" now), but the rest
> looks OK to me - even GCC clearly doesn't expect anything beyond the
> asm to be reachable anyway since the lack of epilogue includes the
> lack of any compiler-generated return. I've checked that GCC 7.2
> generates identical object files before and after, other than (for
> obvious reasons) the line numbers generated by WANT_WARN_ON_SLOWPATH
> for all the WARN()s appearing later in the file.
Title: Oops, good catch! Will send a v3.
Thanks for checking gcc.
--
Stefan
>
> Reviewed-by: Robin Murphy <robin.murphy@arm.com>
>
>> Suggested-by: Russell King <linux@arm.linux.org.uk>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>> Acked-by: Nicolas Pitre <nico@linaro.org>
>> ---
>> drivers/bus/arm-cci.c | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
>> index 443e4c3fd357..b8184a903583 100644
>> --- a/drivers/bus/arm-cci.c
>> +++ b/drivers/bus/arm-cci.c
>> @@ -371,8 +371,6 @@ asmlinkage void __naked cci_enable_port_for_self(void)
>> [sizeof_struct_cpu_port] "i" (sizeof(struct cpu_port)),
>> [sizeof_struct_ace_port] "i" (sizeof(struct cci_ace_port)),
>> [offsetof_port_phys] "i" (offsetof(struct cci_ace_port, phys)) );
>> -
>> - unreachable();
>> }
>> /**
>>
^ permalink raw reply
* [PATCH] Kirin-PCIe: Add kirin pcie msi feature.
From: Bjorn Helgaas @ 2018-05-08 12:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1525763028-107417-1-git-send-email-chenyao11@huawei.com>
[+cc Stanimir, Jianguo, Shawn for qcom, histb comments below]
On Tue, May 08, 2018 at 03:03:48PM +0800, Yao Chen wrote:
> This patch adds kirin pcie msi feature.
Thanks for the patch! Please update your subject and changelog like this:
PCI: kirin: Add MSI support
Add support for MSI.
You can figure out what style to use for the subject by running:
git log --oneline drivers/pci/dwc/pcie-kirin.c
Then follow the existing style.
> Signed-off-by: Yao Chen <chenyao11@huawei.com>
> ---
> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 2 ++
> drivers/pci/dwc/pcie-kirin.c | 38 +++++++++++++++++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index ec3eb8e..4ef684f 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -872,6 +872,8 @@
> 0x0 0x02000000>;
> num-lanes = <1>;
> #interrupt-cells = <1>;
> + interrupts = <0 283 4>;
> + interrupts-names = "msi";
> interrupt-map-mask = <0xf800 0 0 7>;
> interrupt-map = <0x0 0 0 1
> &gic GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
> diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/dwc/pcie-kirin.c
> index d2970a0..2319c9c 100644
> --- a/drivers/pci/dwc/pcie-kirin.c
> +++ b/drivers/pci/dwc/pcie-kirin.c
> @@ -426,9 +426,28 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)
> return 0;
> }
>
> +static irqreturn_t kirin_pcie_msi_irq_handler(int irq, void *arg)
> +{
> + struct pcie_port *pp = arg;
> +
> + return dw_handle_msi_irq(pp);
> +}
> +
> +static void kirin_pcie_msi_init(struct pcie_port *pp)
> +{
> + dw_pcie_msi_init(pp);
> +}
> +
> +static void kirin_pcie_enable_interrupts(struct pcie_port *pp)
> +{
> + if (IS_ENABLED(CONFIG_PCI_MSI))
> + kirin_pcie_msi_init(pp);
> +}
> +
> static int kirin_pcie_host_init(struct pcie_port *pp)
> {
> kirin_pcie_establish_link(pp);
> + kirin_pcie_enable_interrupts(pp);
>
> return 0;
> }
> @@ -448,6 +467,25 @@ static int kirin_pcie_host_init(struct pcie_port *pp)
> static int __init kirin_add_pcie_port(struct dw_pcie *pci,
> struct platform_device *pdev)
> {
> + int ret;
> +
> + if (IS_ENABLED(CONFIG_PCI_MSI)) {
> + pci->pp.msi_irq = platform_get_irq(pdev, 0);
> + if (!pci->pp.msi_irq) {
> + dev_err(&pdev->dev, "failed to get msi irq\n");
s/msi irq/MSI IRQ/
> + return -ENODEV;
> + }
> + ret = devm_request_irq(&pdev->dev, pci->pp.msi_irq,
> + kirin_pcie_msi_irq_handler,
> + IRQF_SHARED | IRQF_NO_THREAD,
> + "kirin_pcie_msi", &pci->pp);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to request msi irq\n");
s/msi irq/MSI IRQ/
Also, please include the IRQ number (pci->pp.msi_irq) in the message.
> + return ret;
> + }
> + }
> +
> + pci->pp.root_bus_nr = -1;
Setting root_bus_nr looks like an unrelated change that should be in a
separate patch.
But I'm not sure why you need to set root_bus_nr at all, since
dw_pcie_host_init() always sets it.
Some other callers of dw_pcie_host_init() do set it:
exynos_add_pcie_port()
imx6_add_pcie_port()
armada8k_add_pcie_port()
artpec6_add_pcie_port()
dw_plat_add_pcie_port()
histb_pcie_probe()
qcom_pcie_probe()
spear13xx_add_pcie_port()
But I don't see *why* any of these need to set it. If they don't need to
set it, they shouldn't.
And it would be nice if histb and qcom followed the structure and naming
conventions of the other drivers, i.e., they should have
histb_add_pcie_port() and qcom_add_pcie_port().
> pci->pp.ops = &kirin_pcie_host_ops;
>
> return dw_pcie_host_init(&pci->pp);
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH net-next v2 03/13] net: phy: sfp: warn the user when no tx_disable pin is available
From: Russell King - ARM Linux @ 2018-05-08 12:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180505205242.GA2876@lunn.ch>
On Sat, May 05, 2018 at 10:52:42PM +0200, Andrew Lunn wrote:
> On Sat, May 05, 2018 at 01:38:31PM -0700, Florian Fainelli wrote:
> > On May 4, 2018 10:14:25 AM PDT, Andrew Lunn <andrew@lunn.ch> wrote:
> > >On Fri, May 04, 2018 at 10:07:53AM -0700, Florian Fainelli wrote:
> > >> On 05/04/2018 06:56 AM, Antoine Tenart wrote:
> > >> > In case no Tx disable pin is available the SFP modules will always
> > >be
> > >> > emitting. This could be an issue when using modules using laser as
> > >their
> > >> > light source as we would have no way to disable it when the fiber
> > >is
> > >> > removed. This patch adds a warning when registering an SFP cage
> > >which do
> > >> > not have its tx_disable pin wired or available.
> > >>
> > >> Is this something that was done in a possibly earlier revision of a
> > >> given board design and which was finally fixed? Nothing wrong with
> > >the
> > >> patch, but this seems like a pretty serious board design mistake,
> > >that
> > >> needs to be addressed.
> > >
> > >Hi Florian
> > >
> > >Zii Devel B is like this. Only the "Signal Detect" pin is wired to a
> > >GPIO.
> >
>
> > Good point, indeed. BTW what do you think about exposing the SFF's
> > EEPROM and diagnostics through the standard ethtool operations even
> > if we have to keep the description of the SFF as a fixed link in
> > Device Tree because of the unfortunate wiring?
>
> I believe in Antoine case, all the control plane is broken. He cannot
> read the EEPROM, nor any of the modules pins via GPIOs.
Correct.
> For Zii Devel B, the EEPROM is accessible, and so is the SD pin. What
> is missing is transmit disable. So i would expose it as an SFF module.
Agreed.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH] tty: pl011: Avoid spuriously stuck-off interrupts
From: Dave Martin @ 2018-05-08 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508110119.GA16141@n2100.armlinux.org.uk>
On Tue, May 08, 2018 at 12:01:19PM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 27, 2018 at 11:05:45AM +0100, Dave Martin wrote:
> > Commit 9b96fbacda34 ("serial: PL011: clear pending interrupts")
> > clears the RX and receive timeout interrupts on pl011 startup, to
> > avoid a screaming-interrupt scenario that can occur when the
> > firmware or bootloader leaves these interrupts asserted.
> >
> > This has been noted as an issue when running Linux on qemu [1].
> >
> > Unfortunately, the above fix seems to lead to potential
> > misbehaviour if the RX FIFO interrupt is asserted _non_ spuriously
> > on driver startup, if the RX FIFO is also already full to the
> > trigger level.
> >
> > Clearing the RX FIFO interrupt does not change the FIFO fill level.
> > In this scenario, because the interrupt is now clear and because
> > the FIFO is already full to the trigger level, no new assertion of
> > the RX FIFO interrupt can occur unless the FIFO is drained back
> > below the trigger level. This never occurs because the pl011
> > driver is waiting for an RX FIFO interrupt to tell it that there is
> > something to read, and does not read the FIFO at all until that
> > interrupt occurs.
> >
> > Thus, simply clearing "spurious" interrupts on startup may be
> > misguided, since there is no way to be sure that the interrupts are
> > truly spurious, and things can go wrong if they are not.
> >
> > This patch instead clears the interrupt condition by draining the
> > RX FIFO during UART startup, after clearing any potentially
> > spurious interrupt. This should ensure that an interrupt will
> > definitely be asserted if the RX FIFO subsequently becomes
> > sufficiently full.
> >
> > The drain is done at the point of enabling interrupts only. This
> > means that it will occur any time the UART is newly opened through
> > the tty layer. It will not apply to polled-mode use of the UART by
> > kgdboc: since that scenario cannot use interrupts by design, this
> > should not matter. kgdboc will interact badly with "normal" use of
> > the UART in any case: this patch makes no attempt to paper over
> > such issues.
> >
> > This patch does not attempt to address the case where the RX FIFO
> > fills faster than it can be drained: that is a pathological
> > hardware design problem that is beyond the scope of the driver to
> > work around.
> >
> > [1] [Qemu-devel] [Qemu-arm] [PATCH] pl011: do not put into fifo
> > before enabled the interruption
> > https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg06446.html
> >
> > Reported-by: Wei Xu <xuwei5@hisilicon.com>
> > Cc: Russell King <linux@armlinux.org.uk>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Peter Maydell <peter.maydell@linaro.org>
> > Fixes: 9b96fbacda34 ("serial: PL011: clear pending interrupts")
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > Tested-by: Andrew Jones <drjones@redhat.com>
> > Reviewed-by: Andrew Jones <drjones@redhat.com>
> > ---
> > drivers/tty/serial/amba-pl011.c | 10 ++++++++++
> > 1 file changed, 10 insertions(+)
> >
> > diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
> > index 4b40a5b..a6ccb85 100644
> > --- a/drivers/tty/serial/amba-pl011.c
> > +++ b/drivers/tty/serial/amba-pl011.c
> > @@ -1731,6 +1731,16 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
> >
> > /* Clear out any spuriously appearing RX interrupts */
> > pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
> > +
> > + /*
> > + * RXIS is asserted only when the RX FIFO transitions from below
> > + * to above the trigger threshold. If the RX FIFO is already
> > + * full to the threshold this can't happen and RXIS will now be
> > + * stuck off. Drain the RX FIFO explicitly to fix this:
> > + */
> > + while (!(pl011_read(uap, REG_FR) & UART01x_FR_RXFE))
> > + pl011_read(uap, REG_DR);
>
> You probably ought to limit this in case of a stuck receive not empty
> case, maybe to (eg) twice the depth of the FIFO?
My argument would have been that if the FIFO fills too fast to be
drained, then you have more serious problems... but it would be better
for this to show as character loss than a lockup.
So, I guess draining twice the FIFO depth before giving up is a
reasonable compromise.
I'll hack that in and repost.
Cheers
---Dave
^ permalink raw reply
* [PATCH v9 01/12] ARM: Allow this header to be included by assembly files
From: Russell King - ARM Linux @ 2018-05-08 12:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180504190545.5114-2-mylene.josserand@bootlin.com>
On Fri, May 04, 2018 at 09:05:34PM +0200, Myl?ne Josserand wrote:
> From: Doug Berger <opendmb@gmail.com>
>
> The constants defined in this file are equally useful in assembly and C
> source files. The arm64 architecture version of this file allows
> inclusion in both assembly and C source files, so this this commit adds
> that capability to the arm architecture version so that the constants
> don't need to be defined in multiple places.
>
> Signed-off-by: Doug Berger <opendmb@gmail.com>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Myl?ne Josserand <mylene.josserand@bootlin.com>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
Thanks.
> ---
> arch/arm/include/asm/cputype.h | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
> index cb546425da8a..e7632f536633 100644
> --- a/arch/arm/include/asm/cputype.h
> +++ b/arch/arm/include/asm/cputype.h
> @@ -2,9 +2,6 @@
> #ifndef __ASM_ARM_CPUTYPE_H
> #define __ASM_ARM_CPUTYPE_H
>
> -#include <linux/stringify.h>
> -#include <linux/kernel.h>
> -
> #define CPUID_ID 0
> #define CPUID_CACHETYPE 1
> #define CPUID_TCM 2
> @@ -98,6 +95,11 @@
> /* Qualcomm implemented cores */
> #define ARM_CPU_PART_SCORPION 0x510002d0
>
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/stringify.h>
> +#include <linux/kernel.h>
> +
> extern unsigned int processor_id;
>
> #ifdef CONFIG_CPU_CP15
> @@ -326,4 +328,6 @@ static inline int __attribute_const__ cpuid_feature_extract_field(u32 features,
> #define cpuid_feature_extract(reg, field) \
> cpuid_feature_extract_field(read_cpuid_ext(reg), field)
>
> +#endif /* __ASSEMBLY__ */
> +
> #endif
> --
> 2.11.0
>
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH v6 2/6] ARM: imx6: register pm_power_off handler if "fsl,pmic-stby-poweroff" is set
From: Russell King - ARM Linux @ 2018-05-08 12:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180305102524.5905-3-o.rempel@pengutronix.de>
On Mon, Mar 05, 2018 at 11:25:19AM +0100, Oleksij Rempel wrote:
> One of the Freescale recommended sequences for power off with external
> PMIC is the following:
> ...
> 3. SoC is programming PMIC for power off when standby is asserted.
> 4. In CCM STOP mode, Standby is asserted, PMIC gates SoC supplies.
>
> See:
> http://www.nxp.com/assets/documents/data/en/reference-manuals/IMX6DQRM.pdf
> page 5083
>
> This patch implements step 4. of this sequence.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> arch/arm/mach-imx/pm-imx6.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
> index ecdf071653d4..24689260a2a5 100644
> --- a/arch/arm/mach-imx/pm-imx6.c
> +++ b/arch/arm/mach-imx/pm-imx6.c
> @@ -604,6 +604,28 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
> IMX6Q_GPR1_GINT);
> }
>
> +static void imx6_pm_stby_poweroff(void)
> +{
> + imx6_set_lpm(STOP_POWER_OFF);
> + cpu_suspend(0, imx6q_suspend_finish);
Do you actually need to save the processor state etc here - the request
is after all to power down the system and not to suspend. Would calling
imx6q_suspend_finish() directly work (and hence simplify the code) ?
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH v5 10/14] KVM: arm64: Save host SVE context as appropriate
From: Dave Martin @ 2018-05-08 12:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ab34071f-1808-f33a-e9a0-3067afa815af@arm.com>
On Tue, May 08, 2018 at 12:57:56PM +0100, Marc Zyngier wrote:
> On 08/05/18 12:25, Dave Martin wrote:
> > On Tue, May 08, 2018 at 11:38:05AM +0100, Marc Zyngier wrote:
> >> On 04/05/18 17:05, Dave Martin wrote:
> >>> This patch adds SVE context saving to the hyp FPSIMD context switch
> >>> path. This means that it is no longer necessary to save the host
> >>> SVE state in advance of entering the guest, when in use.
> >>>
> >>> In order to avoid adding pointless complexity to the code, VHE is
> >>> assumed if SVE is in use. VHE is an architectural prerequisite for
> >>> SVE, so there is no good reason to turn CONFIG_ARM64_VHE off in
> >>> kernels that support both SVE and KVM.
> >>>
> >>> Historically, software models exist that can expose the
> >>> architecturally invalid configuration of SVE without VHE, so if
> >>> this situation is detected this patch warns and refuses to create a
> >>> VM. Doing this check at VM creation time avoids race issues
> >>> between KVM and SVE initialisation.
> >>>
> >>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> >>> Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
> >>> ---
> >>> arch/arm64/Kconfig | 7 +++++++
> >>> arch/arm64/kvm/fpsimd.c | 1 -
> >>> arch/arm64/kvm/hyp/switch.c | 21 +++++++++++++++++++--
> >>> virt/kvm/arm/arm.c | 18 ++++++++++++++++++
> >>> 4 files changed, 44 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> >>> index eb2cf49..b0d3820 100644
> >>> --- a/arch/arm64/Kconfig
> >>> +++ b/arch/arm64/Kconfig
> >>> @@ -1130,6 +1130,7 @@ endmenu
> >>> config ARM64_SVE
> >>> bool "ARM Scalable Vector Extension support"
> >>> default y
> >>> + depends on !KVM || ARM64_VHE
> >>
> >> In that case, should we consider making ARM64_VHE "default y" as well,
> >> as KVM is "default y" too?
> >
> > Surely ARM64_VHE has always been default y?
> >
> > 1f364c8c48a0 ("arm64: VHE: Add support for running Linux in EL2 mode")
>
> Hmmm. I have no idea who this Zyngier guy from 2014 is. Oh well.
>
> >> Otherwise, I fear we end-up regressing existing configurations. Also,
> >> you still have to check for the configuration at run time, so I'm not
> >> immediately getting the point of this particular change.
> >
> > We check for the configuration, but the penalty is severe (i.e., can't
> > create VMs) and it doesn't appear to make sense to put effort into
> > working around that: the user has an easy fix in the form of setting
> > ARM64_VHE=y.
> >
> > Is there some value to supporting this configuration that I'm missing?
> > SVE and VHE are both default y.
>
> I had the (obviously wrong) idea that VHE didn't default to y.
Fair enough.
[...]
> >>> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> >>> index 6cf499b..a7be7bf 100644
> >>> --- a/virt/kvm/arm/arm.c
> >>> +++ b/virt/kvm/arm/arm.c
> >>> @@ -16,6 +16,7 @@
> >>> * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> >>> */
> >>>
> >>> +#include <linux/bug.h>
> >>> #include <linux/cpu_pm.h>
> >>> #include <linux/errno.h>
> >>> #include <linux/err.h>
> >>> @@ -41,6 +42,7 @@
> >>> #include <asm/mman.h>
> >>> #include <asm/tlbflush.h>
> >>> #include <asm/cacheflush.h>
> >>> +#include <asm/cpufeature.h>
> >>> #include <asm/virt.h>
> >>> #include <asm/kvm_arm.h>
> >>> #include <asm/kvm_asm.h>
> >>> @@ -120,6 +122,22 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
> >>> if (type)
> >>> return -EINVAL;
> >>>
> >>> + /*
> >>> + * VHE is a prerequisite for SVE in the Arm architecture, and
> >>> + * Kconfig ensures that if system_supports_sve() here then
> >>> + * CONFIG_ARM64_VHE is enabled, so if VHE support wasn't already
> >>> + * detected and enabled, the CPU is architecturally
> >>> + * noncompliant.
> >>> + *
> >>> + * Just in case this mismatch is seen, detect it, warn and give
> >>> + * up. Supporting this forbidden configuration in Hyp would be
> >>> + * pointless.
> >>> + */
> >>> + if (system_supports_sve() && !has_vhe()) {
> >>> + kvm_pr_unimpl("Cannot create VMs on SVE system without VHE. Broken cpu?");
> >>> + return -ENXIO;
> >>> + }
> >>
> >> You might as well fail the boot KVM initialization altogether, and not
> >> wait for a VM to be created.
> >
> > I was concerned that the SVE and KVM initialisation might happen in
> > an unpredictable order.
> >
> > KVM is initialised via module_init(), which I'm guessing is later than
> > cpufeatures (?) If so then yes, kvm_arch_init() would be a reasonable
> > place to do this.
>
> CPU features are set in stone very early, right after we've booted all
> the CPUs that can be discovered before running userspace. KVM itself
> relies on that, so you should be able to move that check pretty early.
OK, I'll have a go.
> >> But I'm more concerned with the fact that we're now have a configuration
> >> that drops functionalities on the floor, one way or another.
> >
> > Is this still a problem if that configuration is forbidden by Kconfig?
> >
> > Can you describe a scenario in which the problem config (KVM=y, VHE=n,
> > SVE=y) would be wanted?
>
> Not really. I guess it is just me being paranoid and not realising we
> had VHE on by default already.
OK, I'll leave it as-is for now, but give me a shout if you have further
concerns.
Cheers
---Dave
^ permalink raw reply
* [PATCH net-next v2 06/13] phy: add 2.5G SGMII mode to the phy_mode enum
From: Russell King - ARM Linux @ 2018-05-08 12:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180504135643.23466-7-antoine.tenart@bootlin.com>
On Fri, May 04, 2018 at 03:56:36PM +0200, Antoine Tenart wrote:
> This patch adds one more generic PHY mode to the phy_mode enum, to allow
> configuring generic PHYs to the 2.5G SGMII mode by using the set_mode
> callback.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
> Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
Hi,
Would it be possible to get the 2.5G SGMII comphy support merged
ahead of the rest of this series please - I don't think there's been
any objections to it, and having it in mainline would then mean I can
drop the Marvell Comphy code from my tree and transition to the bootlin
Comphy code instead.
Of course, the perfect solution would be to get the whole series merged,
but I'm just thinking about the situation where we're still discussing
points when the next merge window opens.
Thanks.
> ---
> include/linux/phy/phy.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index c9d14eeee7f5..9713aebdd348 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -36,6 +36,7 @@ enum phy_mode {
> PHY_MODE_USB_DEVICE_SS,
> PHY_MODE_USB_OTG,
> PHY_MODE_SGMII,
> + PHY_MODE_2500SGMII,
> PHY_MODE_10GKR,
> PHY_MODE_UFS_HS_A,
> PHY_MODE_UFS_HS_B,
> --
> 2.17.0
>
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH v5 13/14] KVM: arm64: Fold redundant exit code checks out of fixup_guest_exit()
From: Dave Martin @ 2018-05-08 12:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5b9460e5-207d-befd-446c-b9c7ec2bcc35@arm.com>
On Tue, May 08, 2018 at 12:59:39PM +0100, Marc Zyngier wrote:
> On 08/05/18 12:30, Dave Martin wrote:
> > On Tue, May 08, 2018 at 11:59:25AM +0100, Marc Zyngier wrote:
> >> On 04/05/18 17:05, Dave Martin wrote:
[...]
> >>> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> >>> index 39e9166..be09c52 100644
> >>> --- a/arch/arm64/kvm/hyp/switch.c
> >>> +++ b/arch/arm64/kvm/hyp/switch.c
> >>> @@ -385,11 +385,13 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> >>> * same PC once the SError has been injected, and replay the
> >>> * trapping instruction.
> >>> */
> >>> - if (*exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
> >>> + if (*exit_code != ARM_EXCEPTION_TRAP)
> >>> + goto exit;
> >>> +
> >>> + if (!__populate_fault_info(vcpu))
> >>> return true;
> >>>
> >>> - if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
> >>> - *exit_code == ARM_EXCEPTION_TRAP) {
> >>> + if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
> >>> bool valid;
> >>>
> >>> valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW &&
> >>> @@ -414,12 +416,12 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> >>> if (!__skip_instr(vcpu))
> >>> *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
> >>> *exit_code = ARM_EXCEPTION_EL1_SERROR;
> >>> + goto exit;
> >>
> >> This goto...
> >>
> >>> }
> >>
> >> ... should be placed here. If this was a data abort, it cannot be a
> >> system register trap, and the below conditions cannot possibly apply.
> >
> > That sounds logically sensible, but to be clear, this would be a
> > semantic change to this function, right?
> >
> > (i.e., it forces skipping of the GICv3 handling code in a case where
> > it previously wasn't forced -- at least not within this function. The
> > arguments about whether vgic_v2_cpuif_trap and vgic_v3_cpuif_trap can
> > ever be true simultaneously still apply.)
>
> I agree that this is a slight semantic change, but one that makes sense,
> just like the one you've introduced in patch #12.
Agreed, just wanted to make sure I hadn't missed something in my
original refactoring.
Cheers
---Dave
^ permalink raw reply
* [PATCH 1/2] arm64: signal: Report signal frame size to userspace via auxv
From: Dave Martin @ 2018-05-08 12:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508122652.3zbgvpx7x2al5g5m@lakrids.cambridge.arm.com>
On Tue, May 08, 2018 at 01:26:52PM +0100, Mark Rutland wrote:
> On Tue, May 08, 2018 at 12:43:24PM +0100, Dave Martin wrote:
> > On Tue, May 08, 2018 at 12:30:44PM +0100, Mark Rutland wrote:
> > > On Tue, May 08, 2018 at 11:43:30AM +0100, Dave Martin wrote:
> > > > +/*
> > > > + * Determine the stack space required for guaranteed signal devliery.
> > > > + * This function is used to populate AT_MINSIGSTKSZ at process startup.
> > > > + */
> > > > +int get_minsigstksz(void)
> > > > +{
> > > > + static __read_mostly atomic_t minsigstksz;
> > > > +
> > > > + int ret;
> > > > + struct rt_sigframe_user_layout user;
> > > > +
> > > > + ret = atomic_read(&minsigstksz);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + init_user_layout(&user);
> > > > + ret = setup_sigframe_layout(&user, true);
> > > > +
> > > > + if (ret) {
> > > > + WARN_ON(1);
> > > > +
> > > > + ret = SIGSTKSZ;
> > > > + } else {
> > > > + ret = sigframe_size(&user) +
> > > > + round_up(sizeof(struct frame_record), 16) +
> > > > + 16; /* max alignment padding */
> > > > + }
> > > > +
> > > > + /*
> > > > + * The computed value (ret) is invariant, so its value can be
> > > > + * safely stored irrespective of whether some other racing
> > > > + * task got there first:
> > > > + */
> > > > + atomic_set(&minsigstksz, ret);
> > > > + return ret;
> > > > +}
> > >
> > > Can we set up minsigstksz at some initcall time? that way get_minstksz()
> > > can return minsigstksz with no conditionality at all.
> >
> > I would have preferred to do that, but I wasn't sure where to put it.
> >
> > Unless arch_initcall_sync() works for this, I don't know what to
> > suggest.
>
> Perhaps have a setup_minsigstksz(), and call that at the end of
> setup_cpu_features()?
That's probably reasonable. The places the computed value can change
are ... not well defined, if the dust hasn't settled by the time we get
to the end of the cpufeatures setup then we almost certainly have more
serious problems.
I'll have a go and see what it looks like.
Cheers
---Dave
^ permalink raw reply
* [PATCH 1/2] arm64: signal: Report signal frame size to userspace via auxv
From: Mark Rutland @ 2018-05-08 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114323.GG7753@e103592.cambridge.arm.com>
On Tue, May 08, 2018 at 12:43:24PM +0100, Dave Martin wrote:
> On Tue, May 08, 2018 at 12:30:44PM +0100, Mark Rutland wrote:
> > On Tue, May 08, 2018 at 11:43:30AM +0100, Dave Martin wrote:
> > > +/*
> > > + * Determine the stack space required for guaranteed signal devliery.
> > > + * This function is used to populate AT_MINSIGSTKSZ at process startup.
> > > + */
> > > +int get_minsigstksz(void)
> > > +{
> > > + static __read_mostly atomic_t minsigstksz;
> > > +
> > > + int ret;
> > > + struct rt_sigframe_user_layout user;
> > > +
> > > + ret = atomic_read(&minsigstksz);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + init_user_layout(&user);
> > > + ret = setup_sigframe_layout(&user, true);
> > > +
> > > + if (ret) {
> > > + WARN_ON(1);
> > > +
> > > + ret = SIGSTKSZ;
> > > + } else {
> > > + ret = sigframe_size(&user) +
> > > + round_up(sizeof(struct frame_record), 16) +
> > > + 16; /* max alignment padding */
> > > + }
> > > +
> > > + /*
> > > + * The computed value (ret) is invariant, so its value can be
> > > + * safely stored irrespective of whether some other racing
> > > + * task got there first:
> > > + */
> > > + atomic_set(&minsigstksz, ret);
> > > + return ret;
> > > +}
> >
> > Can we set up minsigstksz at some initcall time? that way get_minstksz()
> > can return minsigstksz with no conditionality at all.
>
> I would have preferred to do that, but I wasn't sure where to put it.
>
> Unless arch_initcall_sync() works for this, I don't know what to
> suggest.
Perhaps have a setup_minsigstksz(), and call that at the end of
setup_cpu_features()?
Thanks,
Mark.
^ permalink raw reply
* [RESEND PATCH v2] bus: arm-cci: use asm unreachable
From: Robin Murphy @ 2018-05-08 12:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508113211.7026-1-stefan@agner.ch>
On 08/05/18 12:32, Stefan Agner wrote:
> Mixing asm and C code is not recommended in a naked function by
> gcc and leads to an error when using clang:
> drivers/bus/arm-cci.c:2107:2: error: non-ASM statement in naked
> function is not supported
> unreachable();
> ^
>
> While the function is marked __naked it actually properly return
> in asm. There is no need for the unreachable() call.
The commit title is a bit out-of-date now (I guess it could just be
something like "remove unnecessary unreachable()" now), but the rest
looks OK to me - even GCC clearly doesn't expect anything beyond the asm
to be reachable anyway since the lack of epilogue includes the lack of
any compiler-generated return. I've checked that GCC 7.2 generates
identical object files before and after, other than (for obvious
reasons) the line numbers generated by WANT_WARN_ON_SLOWPATH for all the
WARN()s appearing later in the file.
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> Suggested-by: Russell King <linux@arm.linux.org.uk>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> drivers/bus/arm-cci.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
> index 443e4c3fd357..b8184a903583 100644
> --- a/drivers/bus/arm-cci.c
> +++ b/drivers/bus/arm-cci.c
> @@ -371,8 +371,6 @@ asmlinkage void __naked cci_enable_port_for_self(void)
> [sizeof_struct_cpu_port] "i" (sizeof(struct cpu_port)),
> [sizeof_struct_ace_port] "i" (sizeof(struct cci_ace_port)),
> [offsetof_port_phys] "i" (offsetof(struct cci_ace_port, phys)) );
> -
> - unreachable();
> }
>
> /**
>
^ permalink raw reply
* [PATCH v5 13/14] KVM: arm64: Fold redundant exit code checks out of fixup_guest_exit()
From: Marc Zyngier @ 2018-05-08 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508113039.GF7753@e103592.cambridge.arm.com>
On 08/05/18 12:30, Dave Martin wrote:
> On Tue, May 08, 2018 at 11:59:25AM +0100, Marc Zyngier wrote:
>> On 04/05/18 17:05, Dave Martin wrote:
>>> The entire tail of fixup_guest_exit() is contained in if statements
>>> of the form if (x && *exit_code == ARM_EXCEPTION_TRAP). As a result,
>>> we can check just once and bail out of the function early, allowing
>>> the remaining if conditions to be simplified.
>>>
>>> The only awkward case is where *exit_code is changed to
>>> ARM_EXCEPTION_EL1_SERROR in the case of an illegal GICv2 CPU
>>> interface access: in that case, the GICv3 trap handling code is
>>> skipped using a goto. This avoids pointlessly evaluating the
>>> static branch check for the GICv3 case, even though we can't have
>>> vgic_v2_cpuif_trap and vgic_v3_cpuif_trap true simultaneously
>>> unless we have a GICv3 and GICv2 on the host: that sounds stupid,
>>> but I haven't satisfied myself that it can't happen.
>>
>> Indeed, this cannot happen, unless we decided to trap access to the
>> memory-mapped interface of a GICv3 implementation. We don't do that.
>>
>> But I guess the goto also serves a visual clue that the two cases are
>> mutually exclusives. Small nit below though:
>>
>>>
>>> No functional change.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>> ---
>>> arch/arm64/kvm/hyp/switch.c | 11 +++++++----
>>> 1 file changed, 7 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
>>> index 39e9166..be09c52 100644
>>> --- a/arch/arm64/kvm/hyp/switch.c
>>> +++ b/arch/arm64/kvm/hyp/switch.c
>>> @@ -385,11 +385,13 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
>>> * same PC once the SError has been injected, and replay the
>>> * trapping instruction.
>>> */
>>> - if (*exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
>>> + if (*exit_code != ARM_EXCEPTION_TRAP)
>>> + goto exit;
>>> +
>>> + if (!__populate_fault_info(vcpu))
>>> return true;
>>>
>>> - if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
>>> - *exit_code == ARM_EXCEPTION_TRAP) {
>>> + if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
>>> bool valid;
>>>
>>> valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW &&
>>> @@ -414,12 +416,12 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
>>> if (!__skip_instr(vcpu))
>>> *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
>>> *exit_code = ARM_EXCEPTION_EL1_SERROR;
>>> + goto exit;
>>
>> This goto...
>>
>>> }
>>
>> ... should be placed here. If this was a data abort, it cannot be a
>> system register trap, and the below conditions cannot possibly apply.
>
> That sounds logically sensible, but to be clear, this would be a
> semantic change to this function, right?
>
> (i.e., it forces skipping of the GICv3 handling code in a case where
> it previously wasn't forced -- at least not within this function. The
> arguments about whether vgic_v2_cpuif_trap and vgic_v3_cpuif_trap can
> ever be true simultaneously still apply.)
I agree that this is a slight semantic change, but one that makes sense,
just like the one you've introduced in patch #12.
Thanks,
N,
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v5 10/14] KVM: arm64: Save host SVE context as appropriate
From: Marc Zyngier @ 2018-05-08 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508112514.GE7753@e103592.cambridge.arm.com>
On 08/05/18 12:25, Dave Martin wrote:
> On Tue, May 08, 2018 at 11:38:05AM +0100, Marc Zyngier wrote:
>> On 04/05/18 17:05, Dave Martin wrote:
>>> This patch adds SVE context saving to the hyp FPSIMD context switch
>>> path. This means that it is no longer necessary to save the host
>>> SVE state in advance of entering the guest, when in use.
>>>
>>> In order to avoid adding pointless complexity to the code, VHE is
>>> assumed if SVE is in use. VHE is an architectural prerequisite for
>>> SVE, so there is no good reason to turn CONFIG_ARM64_VHE off in
>>> kernels that support both SVE and KVM.
>>>
>>> Historically, software models exist that can expose the
>>> architecturally invalid configuration of SVE without VHE, so if
>>> this situation is detected this patch warns and refuses to create a
>>> VM. Doing this check at VM creation time avoids race issues
>>> between KVM and SVE initialisation.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>> Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
>>> ---
>>> arch/arm64/Kconfig | 7 +++++++
>>> arch/arm64/kvm/fpsimd.c | 1 -
>>> arch/arm64/kvm/hyp/switch.c | 21 +++++++++++++++++++--
>>> virt/kvm/arm/arm.c | 18 ++++++++++++++++++
>>> 4 files changed, 44 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index eb2cf49..b0d3820 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -1130,6 +1130,7 @@ endmenu
>>> config ARM64_SVE
>>> bool "ARM Scalable Vector Extension support"
>>> default y
>>> + depends on !KVM || ARM64_VHE
>>
>> In that case, should we consider making ARM64_VHE "default y" as well,
>> as KVM is "default y" too?
>
> Surely ARM64_VHE has always been default y?
>
> 1f364c8c48a0 ("arm64: VHE: Add support for running Linux in EL2 mode")
Hmmm. I have no idea who this Zyngier guy from 2014 is. Oh well.
>> Otherwise, I fear we end-up regressing existing configurations. Also,
>> you still have to check for the configuration at run time, so I'm not
>> immediately getting the point of this particular change.
>
> We check for the configuration, but the penalty is severe (i.e., can't
> create VMs) and it doesn't appear to make sense to put effort into
> working around that: the user has an easy fix in the form of setting
> ARM64_VHE=y.
>
> Is there some value to supporting this configuration that I'm missing?
> SVE and VHE are both default y.
I had the (obviously wrong) idea that VHE didn't default to y.
>
> [...]
>
>>> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
>>> index 6cf499b..a7be7bf 100644
>>> --- a/virt/kvm/arm/arm.c
>>> +++ b/virt/kvm/arm/arm.c
>>> @@ -16,6 +16,7 @@
>>> * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
>>> */
>>>
>>> +#include <linux/bug.h>
>>> #include <linux/cpu_pm.h>
>>> #include <linux/errno.h>
>>> #include <linux/err.h>
>>> @@ -41,6 +42,7 @@
>>> #include <asm/mman.h>
>>> #include <asm/tlbflush.h>
>>> #include <asm/cacheflush.h>
>>> +#include <asm/cpufeature.h>
>>> #include <asm/virt.h>
>>> #include <asm/kvm_arm.h>
>>> #include <asm/kvm_asm.h>
>>> @@ -120,6 +122,22 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>>> if (type)
>>> return -EINVAL;
>>>
>>> + /*
>>> + * VHE is a prerequisite for SVE in the Arm architecture, and
>>> + * Kconfig ensures that if system_supports_sve() here then
>>> + * CONFIG_ARM64_VHE is enabled, so if VHE support wasn't already
>>> + * detected and enabled, the CPU is architecturally
>>> + * noncompliant.
>>> + *
>>> + * Just in case this mismatch is seen, detect it, warn and give
>>> + * up. Supporting this forbidden configuration in Hyp would be
>>> + * pointless.
>>> + */
>>> + if (system_supports_sve() && !has_vhe()) {
>>> + kvm_pr_unimpl("Cannot create VMs on SVE system without VHE. Broken cpu?");
>>> + return -ENXIO;
>>> + }
>>
>> You might as well fail the boot KVM initialization altogether, and not
>> wait for a VM to be created.
>
> I was concerned that the SVE and KVM initialisation might happen in
> an unpredictable order.
>
> KVM is initialised via module_init(), which I'm guessing is later than
> cpufeatures (?) If so then yes, kvm_arch_init() would be a reasonable
> place to do this.
CPU features are set in stone very early, right after we've booted all
the CPUs that can be discovered before running userspace. KVM itself
relies on that, so you should be able to move that check pretty early.
>> But I'm more concerned with the fact that we're now have a configuration
>> that drops functionalities on the floor, one way or another.
>
> Is this still a problem if that configuration is forbidden by Kconfig?
>
> Can you describe a scenario in which the problem config (KVM=y, VHE=n,
> SVE=y) would be wanted?
Not really. I guess it is just me being paranoid and not realising we
had VHE on by default already.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v0 2/2] arm64: dts: rockchip: Add sdmmc UHS support for roc-rk3328-cc
From: Heiko Stuebner @ 2018-05-08 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1525747704-8537-3-git-send-email-djw@t-chip.com.cn>
Hi Levin,
Am Dienstag, 8. Mai 2018, 04:48:24 CEST schrieb djw at t-chip.com.cn:
> From: Levin Du <djw@t-chip.com.cn>
>
> In roc-rk3328-cc board, the signal voltage of sdmmc is supplied by
> the vcc_sdio regulator, which is a mux between 1.8V and 3.3V,
> controlled by a special output only gpio pin.
>
> However, this pin, not being a normal gpio in the rockchip pinctrl,
> is set by bit 1 of system register GRF_SOC_CON10. Therefore a new
> gpio controller using gpio-syscon driver is defined in order to use
> regulator-gpio.
>
> If the signal voltage changes, the io domain needs to change
> correspondingly.
>
> To use this feature, the following options are required in kernel config:
> - CONFIG_GPIO_SYSCON=y
> - CONFIG_POWER_AVS=y
> - CONFIG_ROCKCHIP_IODOMAIN=y
>
> Signed-off-by: Levin Du <djw@t-chip.com.cn>
>
> ---
>
> arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 36 ++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
> index 246c317..792cb04 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
> @@ -14,6 +14,12 @@
> stdout-path = "serial2:1500000n8";
> };
>
> + gpio_syscon10: gpio-syscon10 {
> + compatible = "rockchip,rk3328-gpio-syscon10";
> + gpio-controller;
> + #gpio-cells = <2>;
> + };
> +
please split this into a separate patch, move it to rk3328.dtsi and together
with the suggestions from patch 1/2 make it look like
grf: syscon at ff100000 {
compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
reg = <0x0 0xff100000 0x0 0x1000>;
...
gpio_mute: gpio-mute {
compatible = "rockchip,rk3328-gpio-mute";
gpio-controller;
#gpio-cells = <2>;
};
...
};
So making the gpio-controller a child of the grf node.
And as this definition is not specific to the roc-cc it should be in the
main devicetree file for the rk3328.
> gmac_clkin: external-gmac-clock {
> compatible = "fixed-clock";
> clock-frequency = <125000000>;
> @@ -41,6 +47,19 @@
> vin-supply = <&vcc_io>;
> };
>
> + vcc_sdio: sdmmcio-regulator {
> + compatible = "regulator-gpio";
> + gpios = <&gpio_syscon10 1 GPIO_ACTIVE_HIGH>;
> + states = <1800000 0x1
> + 3300000 0x0>;
> + regulator-name = "vcc_sdio";
> + regulator-type = "voltage";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-always-on;
> + vin-supply = <&vcc_sys>;
> + };
> +
> vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator {
> compatible = "regulator-fixed";
> enable-active-high;
> @@ -208,6 +227,18 @@
> };
> };
>
> +&io_domains {
> + status = "okay";
> +
> + vccio1-supply = <&vcc_io>;
> + vccio2-supply = <&vcc18_emmc>;
> + vccio3-supply = <&vcc_sdio>;
> + vccio4-supply = <&vcc_18>;
> + vccio5-supply = <&vcc_io>;
> + vccio6-supply = <&vcc_io>;
> + pmuio-supply = <&vcc_io>;
> +};
> +
Please split this into a separate patch about
"adding io-domain supplies for roc-cc"
> &pinctrl {
> pmic {
> pmic_int_l: pmic-int-l {
> @@ -227,10 +258,15 @@
> cap-mmc-highspeed;
> cap-sd-highspeed;
> disable-wp;
> + sd-uhs-sdr12;
> + sd-uhs-sdr25;
> + sd-uhs-sdr50;
> + sd-uhs-sdr104;
please sort properties alphabetically, so between pinctrl-0 and vmmc-supply
> max-frequency = <150000000>;
> pinctrl-names = "default";
> pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
> vmmc-supply = <&vcc_sd>;
> + vqmmc-supply = <&vcc_sdio>;
> status = "okay";
> };
Thanks
Heiko
^ permalink raw reply
* [PATCH net-next v2 03/13] net: phy: sfp: warn the user when no tx_disable pin is available
From: Russell King - ARM Linux @ 2018-05-08 11:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180504135643.23466-4-antoine.tenart@bootlin.com>
On Fri, May 04, 2018 at 03:56:33PM +0200, Antoine Tenart wrote:
> In case no Tx disable pin is available the SFP modules will always be
> emitting. This could be an issue when using modules using laser as their
> light source as we would have no way to disable it when the fiber is
> removed. This patch adds a warning when registering an SFP cage which do
> not have its tx_disable pin wired or available.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Looks fine, thanks.
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> drivers/net/phy/sfp.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> index 8e323a4b70da..d4f503b2e3e2 100644
> --- a/drivers/net/phy/sfp.c
> +++ b/drivers/net/phy/sfp.c
> @@ -1093,6 +1093,15 @@ static int sfp_probe(struct platform_device *pdev)
> if (!sfp->gpio[GPIO_MODDEF0] && !sfp->gpio[GPIO_LOS])
> sfp->sm_dev_state = SFP_DEV_UNKNOWN;
>
> + /* We could have an issue in cases no Tx disable pin is available or
> + * wired as modules using a laser as their light source will continue to
> + * be active when the fiber is removed. This could be a safety issue and
> + * we should at least warn the user about that.
> + */
> + if (!sfp->gpio[GPIO_TX_DISABLE])
> + dev_warn(sfp->dev,
> + "No tx_disable pin: SFP modules will always be emitting.\n");
> +
> return 0;
> }
>
> --
> 2.17.0
>
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH net-next v2 02/13] net: phy: sfp: handle non-wired SFP connectors
From: Russell King - ARM Linux @ 2018-05-08 11:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180504135643.23466-3-antoine.tenart@bootlin.com>
On Fri, May 04, 2018 at 03:56:32PM +0200, Antoine Tenart wrote:
> SFP connectors can be solder on a board without having any of their pins
> (LOS, i2c...) wired. In such cases the SFP link state cannot be guessed,
> and the overall link status reporting is left to other layers.
>
> In order to achieve this, a new SFP_DEV status is added, named UNKNOWN.
> This mode is set when it is not possible for the SFP code to get the
> link status and as a result the link status is reported to be always UP
> from the SFP point of view.
This looks weird to me. SFP_DEV_* states track the netdevice up/down
state and have little to do with whether LOS or MODDEF0 are implemented.
I think it would be better to have a new SFP_MOD_* and to force
sm_mod_state to that in this circumstance.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH REPOST] ARM: smp: Move clear_tasks_mm_cpumask() call to __cpu_die()
From: Russell King - ARM Linux @ 2018-05-08 11:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180504112939.25493-1-bigeasy@linutronix.de>
On Fri, May 04, 2018 at 01:29:39PM +0200, Sebastian Andrzej Siewior wrote:
> From: Grygorii Strashko <grygorii.strashko@ti.com>
>
> Suspending a CPU on a RT kernel results in the following backtrace:
>
> | Disabling non-boot CPUs ...
> | BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917
> | in_atomic(): 1, irqs_disabled(): 128, pid: 18, name: migration/1
> | INFO: lockdep is turned off.
> | irq event stamp: 122
> | hardirqs last enabled at (121): [<c06ac0ac>] _raw_spin_unlock_irqrestore+0x88/0x90
> | hardirqs last disabled at (122): [<c06abed0>] _raw_spin_lock_irq+0x28/0x5c
> | CPU: 1 PID: 18 Comm: migration/1 Tainted: G W 4.1.4-rt3-01046-g96ac8da #204
> | Hardware name: Generic DRA74X (Flattened Device Tree)
> | [<c0019134>] (unwind_backtrace) from [<c0014774>] (show_stack+0x20/0x24)
> | [<c0014774>] (show_stack) from [<c06a70f4>] (dump_stack+0x88/0xdc)
> | [<c06a70f4>] (dump_stack) from [<c006cab8>] (___might_sleep+0x198/0x2a8)
> | [<c006cab8>] (___might_sleep) from [<c06ac4dc>] (rt_spin_lock+0x30/0x70)
> | [<c06ac4dc>] (rt_spin_lock) from [<c013f790>] (find_lock_task_mm+0x9c/0x174)
> | [<c013f790>] (find_lock_task_mm) from [<c00409ac>] (clear_tasks_mm_cpumask+0xb4/0x1ac)
> | [<c00409ac>] (clear_tasks_mm_cpumask) from [<c00166a4>] (__cpu_disable+0x98/0xbc)
> | [<c00166a4>] (__cpu_disable) from [<c06a2e8c>] (take_cpu_down+0x1c/0x50)
> | [<c06a2e8c>] (take_cpu_down) from [<c00f2600>] (multi_cpu_stop+0x11c/0x158)
> | [<c00f2600>] (multi_cpu_stop) from [<c00f2a9c>] (cpu_stopper_thread+0xc4/0x184)
> | [<c00f2a9c>] (cpu_stopper_thread) from [<c0069058>] (smpboot_thread_fn+0x18c/0x324)
> | [<c0069058>] (smpboot_thread_fn) from [<c00649c4>] (kthread+0xe8/0x104)
> | [<c00649c4>] (kthread) from [<c0010058>] (ret_from_fork+0x14/0x3c)
> | CPU1: shutdown
>
> The root cause of above backtrace is task_lock() which takes a sleeping
> lock on -RT.
>
> To fix the issue, move clear_tasks_mm_cpumask() call from __cpu_disable()
> to __cpu_die() which is called on the thread which is asking for a target
> CPU to be shutdown. In addition, this change restores CPU hotplug
> functionality on ARM CPU1 can be unplugged/plugged many times.
This looks fine to me - all the paths that use the mm_cpumask() check
that the CPU is still marked online.
Please send to the patch system, thanks.
>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> Cc: <linux-arm-kernel@lists.infradead.org>
> Cc: Sekhar Nori <nsekhar@ti.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Link: http://lkml.kernel.org/r/1441995683-30817-1-git-send-email-grygorii.strashko at ti.com
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> [bigeasy: slighty edited the commit message]
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> arch/arm/kernel/smp.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -236,8 +236,6 @@ int __cpu_disable(void)
> flush_cache_louis();
> local_flush_tlb_all();
>
> - clear_tasks_mm_cpumask(cpu);
> -
> return 0;
> }
>
> @@ -255,6 +253,7 @@ void __cpu_die(unsigned int cpu)
> }
> pr_debug("CPU%u: shutdown\n", cpu);
>
> + clear_tasks_mm_cpumask(cpu);
> /*
> * platform_cpu_kill() is generally expected to do the powering off
> * and/or cutting of clocks to the dying CPU. Optionally, this may
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH 8/8] arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888
From: Mikko Perttunen @ 2018-05-08 11:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
The Tegra Combined UART is the proper primary serial port on P2888,
so use it.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
index 859ab5af17c1..95e2433984f7 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -10,7 +10,7 @@
aliases {
sdhci0 = "/cbb/sdhci at 3460000";
sdhci1 = "/cbb/sdhci at 3400000";
- serial0 = &uartb;
+ serial0 = &tcu;
i2c0 = "/bpmp/i2c";
i2c1 = "/cbb/i2c at 3160000";
i2c2 = "/cbb/i2c at c240000";
--
2.16.1
^ permalink raw reply related
* [PATCH 7/8] arm64: tegra: Add nodes for tcu on Tegra194
From: Mikko Perttunen @ 2018-05-08 11:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
Add nodes required for communication through the Tegra Combined UART.
This includes the AON HSP instance, addition of shared interrupts
for the TOP0 HSP instance, and finally the TCU node itself. Also
mark the HSP instances as compatible to tegra194-hsp, as the hardware
is not identical but is compatible to tegra186-hsp.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
arch/arm64/boot/dts/nvidia/tegra194.dtsi | 34 +++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index 6d699815a84f..d7f780b06fe2 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -217,10 +217,31 @@
};
hsp_top0: hsp at 3c00000 {
- compatible = "nvidia,tegra186-hsp";
+ compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
reg = <0x03c00000 0xa0000>;
- interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "doorbell";
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "doorbell", "shared0", "shared1", "shared2",
+ "shared3", "shared4", "shared5", "shared6",
+ "shared7";
+ #mbox-cells = <2>;
+ };
+
+ hsp_aon: hsp at c150000 {
+ compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
+ reg = <0x0c150000 0xa0000>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "shared0", "shared1", "shared2", "shared3";
#mbox-cells = <2>;
};
@@ -382,6 +403,13 @@
};
};
+ tcu: tcu {
+ compatible = "nvidia,tegra194-tcu";
+ mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
+ <&hsp_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
+ mbox-names = "rx", "tx";
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13
--
2.16.1
^ permalink raw reply related
* [PATCH 6/8] serial: Add Tegra Combined UART driver
From: Mikko Perttunen @ 2018-05-08 11:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.
Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/tty/serial/Kconfig | 9 ++
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/tegra-tcu.c | 302 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
4 files changed, 315 insertions(+)
create mode 100644 drivers/tty/serial/tegra-tcu.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index eca55187539a..494db7afe230 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -322,6 +322,15 @@ config SERIAL_TEGRA
are enabled). This driver uses the APB DMA to achieve higher baudrate
and better performance.
+config SERIAL_TEGRA_TCU
+ tristate "NVIDIA Tegra Combined UART"
+ depends on ARCH_TEGRA && MAILBOX
+ select SERIAL_CORE
+ help
+ Support for the mailbox-based TCU (Tegra Combined UART) serial port.
+ TCU is a virtual serial port that allows multiplexing multiple data
+ streams into a single hardware serial port.
+
config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index daac675612df..4ad82231ff8a 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
new file mode 100644
index 000000000000..8b46fe3a4b0c
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <linux/console.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+static struct uart_driver tegra_tcu_uart_driver;
+static struct uart_port tegra_tcu_uart_port;
+
+struct tegra_tcu {
+ struct mbox_client tx_client, rx_client;
+ struct mbox_chan *tx, *rx;
+};
+
+static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port)
+{
+ return TIOCSER_TEMT;
+}
+
+static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ (void)port;
+ (void)mctrl;
+}
+
+static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port)
+{
+ return 0;
+}
+
+static void tegra_tcu_uart_stop_tx(struct uart_port *port)
+{
+ (void)port;
+}
+
+static void tegra_tcu_write(const char *s, unsigned int count)
+{
+ struct tegra_tcu *tcu = tegra_tcu_uart_port.private_data;
+ unsigned int written = 0, i = 0;
+ bool insert_nl = false;
+ uint32_t value = 0;
+
+ while (i < count) {
+ if (insert_nl) {
+ value |= '\n' << (written++ * 8);
+ insert_nl = false;
+ i++;
+ } else if (s[i] == '\n') {
+ value |= '\r' << (written++ * 8);
+ insert_nl = true;
+ } else {
+ value |= s[i++] << (written++ * 8);
+ }
+
+ if (written == 3) {
+ value |= 3 << 24;
+ value |= BIT(26);
+ mbox_send_message(tcu->tx, &value);
+ value = 0;
+ written = 0;
+ }
+ }
+
+ if (written) {
+ value |= written << 24;
+ value |= BIT(26);
+ mbox_send_message(tcu->tx, &value);
+ }
+}
+
+static void tegra_tcu_uart_start_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned long count;
+
+ for (;;) {
+ count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ if (!count)
+ break;
+
+ tegra_tcu_write(&xmit->buf[xmit->tail], count);
+ xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+ }
+
+ uart_write_wakeup(port);
+}
+
+static void tegra_tcu_uart_stop_rx(struct uart_port *port)
+{
+ (void)port;
+}
+
+static void tegra_tcu_uart_break_ctl(struct uart_port *port, int ctl)
+{
+ (void)port;
+ (void)ctl;
+}
+
+static int tegra_tcu_uart_startup(struct uart_port *port)
+{
+ (void)port;
+
+ return 0;
+}
+
+static void tegra_tcu_uart_shutdown(struct uart_port *port)
+{
+ (void)port;
+}
+
+static void tegra_tcu_uart_set_termios(struct uart_port *port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+ (void)port;
+ (void)new;
+ (void)old;
+}
+
+static const struct uart_ops tegra_tcu_uart_ops = {
+ .tx_empty = tegra_tcu_uart_tx_empty,
+ .set_mctrl = tegra_tcu_uart_set_mctrl,
+ .get_mctrl = tegra_tcu_uart_get_mctrl,
+ .stop_tx = tegra_tcu_uart_stop_tx,
+ .start_tx = tegra_tcu_uart_start_tx,
+ .stop_rx = tegra_tcu_uart_stop_rx,
+ .break_ctl = tegra_tcu_uart_break_ctl,
+ .startup = tegra_tcu_uart_startup,
+ .shutdown = tegra_tcu_uart_shutdown,
+ .set_termios = tegra_tcu_uart_set_termios,
+};
+
+static void tegra_tcu_console_write(struct console *cons, const char *s,
+ unsigned int count)
+{
+ (void)cons;
+
+ tegra_tcu_write(s, count);
+}
+
+static int tegra_tcu_console_setup(struct console *cons, char *options)
+{
+ (void)options;
+
+ if (!tegra_tcu_uart_port.private_data)
+ return -ENODEV;
+
+ return uart_set_options(&tegra_tcu_uart_port, cons,
+ 115200, 'n', 8, 'n');
+}
+
+static struct console tegra_tcu_console = {
+ .name = "ttyTCU",
+ .device = uart_console_device,
+ .flags = CON_PRINTBUFFER | CON_ANYTIME,
+ .index = -1,
+ .write = tegra_tcu_console_write,
+ .setup = tegra_tcu_console_setup,
+ .data = &tegra_tcu_uart_driver,
+};
+
+static struct uart_driver tegra_tcu_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "tegra-tcu",
+ .dev_name = "ttyTCU",
+ .cons = &tegra_tcu_console,
+ .nr = 1,
+};
+
+static void tegra_tcu_receive(struct mbox_client *client, void *msg_p)
+{
+ struct tty_port *port = &tegra_tcu_uart_port.state->port;
+ uint32_t msg = *(uint32_t *)msg_p;
+ unsigned int num_bytes;
+ int i;
+
+ num_bytes = (msg >> 24) & 0x3;
+ for (i = 0; i < num_bytes; i++)
+ tty_insert_flip_char(port, (msg >> (i*8)) & 0xff, TTY_NORMAL);
+
+ tty_flip_buffer_push(port);
+}
+
+static int tegra_tcu_probe(struct platform_device *pdev)
+{
+ struct uart_port *port = &tegra_tcu_uart_port;
+ struct tegra_tcu *tcu;
+ int err;
+
+ tcu = devm_kzalloc(&pdev->dev, sizeof(*tcu), GFP_KERNEL);
+ if (!tcu)
+ return -ENOMEM;
+
+ tcu->tx_client.dev = &pdev->dev;
+ tcu->rx_client.dev = &pdev->dev;
+ tcu->rx_client.rx_callback = tegra_tcu_receive;
+
+ tcu->tx = mbox_request_channel_byname(&tcu->tx_client, "tx");
+ if (IS_ERR(tcu->tx)) {
+ err = PTR_ERR(tcu->tx);
+ dev_err(&pdev->dev, "failed to get tx mailbox: %d\n", err);
+ return err;
+ }
+
+ tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx");
+ if (IS_ERR(tcu->rx)) {
+ err = PTR_ERR(tcu->rx);
+ dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err);
+ goto free_tx;
+ }
+
+ err = uart_register_driver(&tegra_tcu_uart_driver);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register UART driver: %d\n",
+ err);
+ goto free_rx;
+ }
+
+ spin_lock_init(&port->lock);
+ port->dev = &pdev->dev;
+ port->type = PORT_TEGRA_TCU;
+ port->ops = &tegra_tcu_uart_ops;
+ port->fifosize = 1;
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->private_data = tcu;
+
+ err = uart_add_one_port(&tegra_tcu_uart_driver, port);
+ if (err) {
+ dev_err(&pdev->dev, "failed to add UART port: %d\n", err);
+ goto unregister_uart;
+ }
+
+ return 0;
+
+unregister_uart:
+ uart_unregister_driver(&tegra_tcu_uart_driver);
+free_rx:
+ mbox_free_channel(tcu->rx);
+free_tx:
+ mbox_free_channel(tcu->tx);
+
+ return err;
+}
+
+static int tegra_tcu_remove(struct platform_device *pdev)
+{
+ uart_remove_one_port(&tegra_tcu_uart_driver, &tegra_tcu_uart_port);
+ uart_unregister_driver(&tegra_tcu_uart_driver);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_tcu_match[] = {
+ { .compatible = "nvidia,tegra194-tcu" },
+ { }
+};
+
+static struct platform_driver tegra_tcu_driver = {
+ .driver = {
+ .name = "tegra-tcu",
+ .of_match_table = tegra_tcu_match,
+ },
+ .probe = tegra_tcu_probe,
+ .remove = tegra_tcu_remove,
+};
+
+static int __init tegra_tcu_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&tegra_tcu_driver);
+ if (err)
+ return err;
+
+ register_console(&tegra_tcu_console);
+
+ return 0;
+}
+module_init(tegra_tcu_init);
+
+static void __exit tegra_tcu_exit(void)
+{
+ unregister_console(&tegra_tcu_console);
+ platform_driver_unregister(&tegra_tcu_driver);
+}
+module_exit(tegra_tcu_exit);
+
+MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index dce5f9dae121..eaf3c303cba6 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -281,4 +281,7 @@
/* MediaTek BTIF */
#define PORT_MTK_BTIF 117
+/* NVIDIA Tegra Combined UART */
+#define PORT_TEGRA_TCU 118
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
2.16.1
^ permalink raw reply related
* [PATCH 5/8] mailbox: tegra-hsp: Add support for shared mailboxes
From: Mikko Perttunen @ 2018-05-08 11:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
The Tegra HSP block supports 'shared mailboxes' that are simple 32-bit
registers consisting of a FULL bit in MSB position and 31 bits of data.
The hardware can be configured to trigger interrupts when a mailbox
is empty or full. Add support for these shared mailboxes to the HSP
driver.
The initial use for the mailboxes is the Tegra Combined UART. For this
purpose, we use interrupts to receive data, and spinning to wait for
the transmit mailbox to be emptied to minimize unnecessary overhead.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/mailbox/tegra-hsp.c | 216 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 193 insertions(+), 23 deletions(-)
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 16eb970f2c9f..77bc8ed7ef15 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -21,6 +21,11 @@
#include <dt-bindings/mailbox/tegra186-hsp.h>
+#include "mailbox.h"
+
+#define HSP_INT0_IE 0x100
+#define HSP_INT_IR 0x304
+
#define HSP_INT_DIMENSIONING 0x380
#define HSP_nSM_SHIFT 0
#define HSP_nSS_SHIFT 4
@@ -34,6 +39,8 @@
#define HSP_DB_RAW 0x8
#define HSP_DB_PENDING 0xc
+#define HSP_SM_SHRD_MBOX 0x0
+
#define HSP_DB_CCPLEX 1
#define HSP_DB_BPMP 3
#define HSP_DB_MAX 7
@@ -68,6 +75,18 @@ struct tegra_hsp_db_map {
unsigned int index;
};
+struct tegra_hsp_mailbox {
+ struct tegra_hsp_channel channel;
+ unsigned int index;
+ bool sending;
+};
+
+static inline struct tegra_hsp_mailbox *
+channel_to_mailbox(struct tegra_hsp_channel *channel)
+{
+ return container_of(channel, struct tegra_hsp_mailbox, channel);
+}
+
struct tegra_hsp_soc {
const struct tegra_hsp_db_map *map;
};
@@ -77,6 +96,7 @@ struct tegra_hsp {
struct mbox_controller mbox;
void __iomem *regs;
unsigned int doorbell_irq;
+ unsigned int shared_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -85,6 +105,7 @@ struct tegra_hsp {
spinlock_t lock;
struct list_head doorbells;
+ struct tegra_hsp_mailbox *mailboxes;
};
static inline struct tegra_hsp *
@@ -189,6 +210,35 @@ static irqreturn_t tegra_hsp_doorbell_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t tegra_hsp_shared_irq(int irq, void *data)
+{
+ struct tegra_hsp_mailbox *mb;
+ struct tegra_hsp *hsp = data;
+ unsigned long bit, mask;
+ u32 value;
+
+ mask = tegra_hsp_readl(hsp, HSP_INT_IR);
+ /* Only interested in FULL interrupts */
+ mask &= 0xff << 8;
+
+ for_each_set_bit(bit, &mask, 16) {
+ unsigned int mb_i = bit % 8;
+
+ mb = &hsp->mailboxes[mb_i];
+
+ if (!mb->sending) {
+ value = tegra_hsp_channel_readl(&mb->channel,
+ HSP_SM_SHRD_MBOX);
+ value &= ~BIT(31);
+ mbox_chan_received_data(mb->channel.chan, &value);
+ tegra_hsp_channel_writel(&mb->channel, value,
+ HSP_SM_SHRD_MBOX);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
static struct tegra_hsp_channel *
tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
unsigned int master, unsigned int index)
@@ -277,15 +327,58 @@ static void tegra_hsp_doorbell_shutdown(struct tegra_hsp_doorbell *db)
spin_unlock_irqrestore(&hsp->lock, flags);
}
+static int tegra_hsp_mailbox_startup(struct tegra_hsp_mailbox *mb)
+{
+ struct tegra_hsp *hsp = mb->channel.hsp;
+ u32 value;
+
+ mb->channel.chan->txdone_method = TXDONE_BY_BLOCK;
+
+ /* Route FULL interrupt to external IRQ 0 */
+ value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+ value |= BIT(mb->index + 8);
+ tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+ return 0;
+}
+
+static int tegra_hsp_mailbox_shutdown(struct tegra_hsp_mailbox *mb)
+{
+ struct tegra_hsp *hsp = mb->channel.hsp;
+ u32 value;
+
+ value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+ value &= ~BIT(mb->index + 8);
+ tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+ return 0;
+}
+
static int tegra_hsp_send_data(struct mbox_chan *chan, void *data)
{
struct tegra_hsp_channel *channel = chan->con_priv;
- struct tegra_hsp_doorbell *db;
+ struct tegra_hsp_mailbox *mailbox;
+ uint32_t value;
switch (channel->type) {
case TEGRA_HSP_MBOX_TYPE_DB:
- db = channel_to_doorbell(channel);
- tegra_hsp_channel_writel(&db->channel, 1, HSP_DB_TRIGGER);
+ tegra_hsp_channel_writel(channel, 1, HSP_DB_TRIGGER);
+ return 0;
+ case TEGRA_HSP_MBOX_TYPE_SM:
+ mailbox = channel_to_mailbox(channel);
+ mailbox->sending = true;
+
+ value = *(uint32_t *)data;
+ /* Mark mailbox full */
+ value |= BIT(31);
+
+ tegra_hsp_channel_writel(channel, value, HSP_SM_SHRD_MBOX);
+
+ while (tegra_hsp_channel_readl(channel, HSP_SM_SHRD_MBOX)
+ & BIT(31))
+ cpu_relax();
+
+ return 0;
}
return -EINVAL;
@@ -298,6 +391,8 @@ static int tegra_hsp_startup(struct mbox_chan *chan)
switch (channel->type) {
case TEGRA_HSP_MBOX_TYPE_DB:
return tegra_hsp_doorbell_startup(channel_to_doorbell(channel));
+ case TEGRA_HSP_MBOX_TYPE_SM:
+ return tegra_hsp_mailbox_startup(channel_to_mailbox(channel));
}
return -EINVAL;
@@ -311,6 +406,9 @@ static void tegra_hsp_shutdown(struct mbox_chan *chan)
case TEGRA_HSP_MBOX_TYPE_DB:
tegra_hsp_doorbell_shutdown(channel_to_doorbell(channel));
break;
+ case TEGRA_HSP_MBOX_TYPE_SM:
+ tegra_hsp_mailbox_shutdown(channel_to_mailbox(channel));
+ break;
}
}
@@ -364,7 +462,16 @@ static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
switch (type) {
case TEGRA_HSP_MBOX_TYPE_DB:
- return tegra_hsp_doorbell_xlate(hsp, param);
+ if (hsp->doorbell_irq)
+ return tegra_hsp_doorbell_xlate(hsp, param);
+ else
+ return ERR_PTR(-EINVAL);
+
+ case TEGRA_HSP_MBOX_TYPE_SM:
+ if (hsp->shared_irq && param < hsp->num_sm)
+ return hsp->mailboxes[param].channel.chan;
+ else
+ return ERR_PTR(-EINVAL);
default:
return ERR_PTR(-EINVAL);
@@ -403,6 +510,31 @@ static int tegra_hsp_add_doorbells(struct tegra_hsp *hsp)
return 0;
}
+static int tegra_hsp_add_mailboxes(struct tegra_hsp *hsp, struct device *dev)
+{
+ int i;
+
+ hsp->mailboxes = devm_kcalloc(dev, hsp->num_sm, sizeof(*hsp->mailboxes),
+ GFP_KERNEL);
+ if (!hsp->mailboxes)
+ return -ENOMEM;
+
+ for (i = 0; i < hsp->num_sm; i++) {
+ struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
+
+ mb->index = i;
+ mb->sending = false;
+
+ mb->channel.hsp = hsp;
+ mb->channel.type = TEGRA_HSP_MBOX_TYPE_SM;
+ mb->channel.regs = hsp->regs + SZ_64K + i * SZ_32K;
+ mb->channel.chan = &hsp->mbox.chans[i];
+ mb->channel.chan->con_priv = &mb->channel;
+ }
+
+ return 0;
+}
+
static int tegra_hsp_probe(struct platform_device *pdev)
{
struct tegra_hsp *hsp;
@@ -431,14 +563,19 @@ static int tegra_hsp_probe(struct platform_device *pdev)
hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
err = platform_get_irq_byname(pdev, "doorbell");
- if (err < 0) {
- dev_err(&pdev->dev, "failed to get doorbell IRQ: %d\n", err);
- return err;
- }
+ if (err < 0)
+ hsp->doorbell_irq = 0;
+ else
+ hsp->doorbell_irq = err;
- hsp->doorbell_irq = err;
+ err = platform_get_irq_byname(pdev, "shared0");
+ if (err < 0)
+ hsp->shared_irq = 0;
+ else
+ hsp->shared_irq = err;
hsp->mbox.of_xlate = of_tegra_hsp_xlate;
+ /* First nSM are reserved for mailboxes */
hsp->mbox.num_chans = 32;
hsp->mbox.dev = &pdev->dev;
hsp->mbox.txdone_irq = false;
@@ -451,10 +588,22 @@ static int tegra_hsp_probe(struct platform_device *pdev)
if (!hsp->mbox.chans)
return -ENOMEM;
- err = tegra_hsp_add_doorbells(hsp);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to add doorbells: %d\n", err);
- return err;
+ if (hsp->doorbell_irq) {
+ err = tegra_hsp_add_doorbells(hsp);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to add doorbells: %d\n",
+ err);
+ return err;
+ }
+ }
+
+ if (hsp->shared_irq) {
+ err = tegra_hsp_add_mailboxes(hsp, &pdev->dev);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to add mailboxes: %d\n",
+ err);
+ goto remove_doorbells;
+ }
}
platform_set_drvdata(pdev, hsp);
@@ -462,20 +611,40 @@ static int tegra_hsp_probe(struct platform_device *pdev)
err = mbox_controller_register(&hsp->mbox);
if (err) {
dev_err(&pdev->dev, "failed to register mailbox: %d\n", err);
- tegra_hsp_remove_doorbells(hsp);
- return err;
+ goto remove_doorbells;
}
- err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
- tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
- dev_name(&pdev->dev), hsp);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to request doorbell IRQ#%u: %d\n",
- hsp->doorbell_irq, err);
- return err;
+ if (hsp->doorbell_irq) {
+ err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
+ tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
+ dev_name(&pdev->dev), hsp);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "failed to request doorbell IRQ#%u: %d\n",
+ hsp->doorbell_irq, err);
+ return err;
+ }
+ }
+
+ if (hsp->shared_irq) {
+ err = devm_request_irq(&pdev->dev, hsp->shared_irq,
+ tegra_hsp_shared_irq, 0,
+ dev_name(&pdev->dev), hsp);
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "failed to request shared0 IRQ%u: %d\n",
+ hsp->shared_irq, err);
+ return err;
+ }
}
return 0;
+
+remove_doorbells:
+ if (hsp->doorbell_irq)
+ tegra_hsp_remove_doorbells(hsp);
+
+ return err;
}
static int tegra_hsp_remove(struct platform_device *pdev)
@@ -483,7 +652,8 @@ static int tegra_hsp_remove(struct platform_device *pdev)
struct tegra_hsp *hsp = platform_get_drvdata(pdev);
mbox_controller_unregister(&hsp->mbox);
- tegra_hsp_remove_doorbells(hsp);
+ if (hsp->doorbell_irq)
+ tegra_hsp_remove_doorbells(hsp);
return 0;
}
--
2.16.1
^ permalink raw reply related
* [PATCH 4/8] mailbox: tegra-hsp: Refactor in preparation of mailboxes
From: Mikko Perttunen @ 2018-05-08 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
The HSP driver is currently in many places written with the assumption
of only supporting doorbells. Prepare for the addition of shared
mailbox support by removing these assumptions and cleaning up the code.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/mailbox/tegra-hsp.c | 124 +++++++++++++++++++++++++++++---------------
1 file changed, 82 insertions(+), 42 deletions(-)
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 0cde356c11ab..16eb970f2c9f 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -42,6 +42,7 @@ struct tegra_hsp_channel;
struct tegra_hsp;
struct tegra_hsp_channel {
+ unsigned int type;
struct tegra_hsp *hsp;
struct mbox_chan *chan;
void __iomem *regs;
@@ -55,6 +56,12 @@ struct tegra_hsp_doorbell {
unsigned int index;
};
+static inline struct tegra_hsp_doorbell *
+channel_to_doorbell(struct tegra_hsp_channel *channel)
+{
+ return container_of(channel, struct tegra_hsp_doorbell, channel);
+}
+
struct tegra_hsp_db_map {
const char *name;
unsigned int master;
@@ -69,7 +76,7 @@ struct tegra_hsp {
const struct tegra_hsp_soc *soc;
struct mbox_controller mbox;
void __iomem *regs;
- unsigned int irq;
+ unsigned int doorbell_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -194,7 +201,7 @@ tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
if (!db)
return ERR_PTR(-ENOMEM);
- offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
+ offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K;
offset += index * 0x100;
db->channel.regs = hsp->regs + offset;
@@ -218,18 +225,8 @@ static void __tegra_hsp_doorbell_destroy(struct tegra_hsp_doorbell *db)
kfree(db);
}
-static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
-{
- struct tegra_hsp_doorbell *db = chan->con_priv;
-
- tegra_hsp_channel_writel(&db->channel, 1, HSP_DB_TRIGGER);
-
- return 0;
-}
-
-static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
+static int tegra_hsp_doorbell_startup(struct tegra_hsp_doorbell *db)
{
- struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -260,9 +257,8 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
return 0;
}
-static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
+static void tegra_hsp_doorbell_shutdown(struct tegra_hsp_doorbell *db)
{
- struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -281,35 +277,61 @@ static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
spin_unlock_irqrestore(&hsp->lock, flags);
}
-static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
- .send_data = tegra_hsp_doorbell_send_data,
- .startup = tegra_hsp_doorbell_startup,
- .shutdown = tegra_hsp_doorbell_shutdown,
+static int tegra_hsp_send_data(struct mbox_chan *chan, void *data)
+{
+ struct tegra_hsp_channel *channel = chan->con_priv;
+ struct tegra_hsp_doorbell *db;
+
+ switch (channel->type) {
+ case TEGRA_HSP_MBOX_TYPE_DB:
+ db = channel_to_doorbell(channel);
+ tegra_hsp_channel_writel(&db->channel, 1, HSP_DB_TRIGGER);
+ }
+
+ return -EINVAL;
+}
+
+static int tegra_hsp_startup(struct mbox_chan *chan)
+{
+ struct tegra_hsp_channel *channel = chan->con_priv;
+
+ switch (channel->type) {
+ case TEGRA_HSP_MBOX_TYPE_DB:
+ return tegra_hsp_doorbell_startup(channel_to_doorbell(channel));
+ }
+
+ return -EINVAL;
+}
+
+static void tegra_hsp_shutdown(struct mbox_chan *chan)
+{
+ struct tegra_hsp_channel *channel = chan->con_priv;
+
+ switch (channel->type) {
+ case TEGRA_HSP_MBOX_TYPE_DB:
+ tegra_hsp_doorbell_shutdown(channel_to_doorbell(channel));
+ break;
+ }
+}
+
+static const struct mbox_chan_ops tegra_hsp_ops = {
+ .send_data = tegra_hsp_send_data,
+ .startup = tegra_hsp_startup,
+ .shutdown = tegra_hsp_shutdown,
};
-static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
- const struct of_phandle_args *args)
+static struct mbox_chan *tegra_hsp_doorbell_xlate(struct tegra_hsp *hsp,
+ unsigned int master)
{
struct tegra_hsp_channel *channel = ERR_PTR(-ENODEV);
- struct tegra_hsp *hsp = to_tegra_hsp(mbox);
- unsigned int type = args->args[0];
- unsigned int master = args->args[1];
struct tegra_hsp_doorbell *db;
struct mbox_chan *chan;
unsigned long flags;
unsigned int i;
- switch (type) {
- case TEGRA_HSP_MBOX_TYPE_DB:
- db = tegra_hsp_doorbell_get(hsp, master);
- if (db)
- channel = &db->channel;
-
- break;
-
- default:
- break;
- }
+ db = tegra_hsp_doorbell_get(hsp, master);
+ if (db)
+ channel = &db->channel;
if (IS_ERR(channel))
return ERR_CAST(channel);
@@ -321,6 +343,7 @@ static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
if (!chan->con_priv) {
chan->con_priv = channel;
channel->chan = chan;
+ channel->type = TEGRA_HSP_MBOX_TYPE_DB;
break;
}
@@ -332,6 +355,22 @@ static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
return chan ?: ERR_PTR(-EBUSY);
}
+static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *args)
+{
+ struct tegra_hsp *hsp = to_tegra_hsp(mbox);
+ unsigned int type = args->args[0];
+ unsigned int param = args->args[1];
+
+ switch (type) {
+ case TEGRA_HSP_MBOX_TYPE_DB:
+ return tegra_hsp_doorbell_xlate(hsp, param);
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+}
+
static void tegra_hsp_remove_doorbells(struct tegra_hsp *hsp)
{
struct tegra_hsp_doorbell *db, *tmp;
@@ -397,14 +436,14 @@ static int tegra_hsp_probe(struct platform_device *pdev)
return err;
}
- hsp->irq = err;
+ hsp->doorbell_irq = err;
hsp->mbox.of_xlate = of_tegra_hsp_xlate;
hsp->mbox.num_chans = 32;
hsp->mbox.dev = &pdev->dev;
hsp->mbox.txdone_irq = false;
hsp->mbox.txdone_poll = false;
- hsp->mbox.ops = &tegra_hsp_doorbell_ops;
+ hsp->mbox.ops = &tegra_hsp_ops;
hsp->mbox.chans = devm_kcalloc(&pdev->dev, hsp->mbox.num_chans,
sizeof(*hsp->mbox.chans),
@@ -427,11 +466,12 @@ static int tegra_hsp_probe(struct platform_device *pdev)
return err;
}
- err = devm_request_irq(&pdev->dev, hsp->irq, tegra_hsp_doorbell_irq,
- IRQF_NO_SUSPEND, dev_name(&pdev->dev), hsp);
+ err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
+ tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
+ dev_name(&pdev->dev), hsp);
if (err < 0) {
- dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
- hsp->irq, err);
+ dev_err(&pdev->dev, "failed to request doorbell IRQ#%u: %d\n",
+ hsp->doorbell_irq, err);
return err;
}
--
2.16.1
^ permalink raw reply related
* [PATCH 3/8] mailbox: Add transmit done by blocking option
From: Mikko Perttunen @ 2018-05-08 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/mailbox/mailbox.c | 30 +++++++++++++++++++++---------
drivers/mailbox/mailbox.h | 1 +
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 674b35f402f5..5c76b70e673c 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -53,6 +53,8 @@ static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
return idx;
}
+static void tx_tick(struct mbox_chan *chan, int r, bool submit_next);
+
static void msg_submit(struct mbox_chan *chan)
{
unsigned count, idx;
@@ -60,10 +62,13 @@ static void msg_submit(struct mbox_chan *chan)
void *data;
int err = -EBUSY;
+next:
spin_lock_irqsave(&chan->lock, flags);
- if (!chan->msg_count || chan->active_req)
- goto exit;
+ if (!chan->msg_count || chan->active_req) {
+ spin_unlock_irqrestore(&chan->lock, flags);
+ return;
+ }
count = chan->msg_count;
idx = chan->msg_free;
@@ -82,15 +87,21 @@ static void msg_submit(struct mbox_chan *chan)
chan->active_req = data;
chan->msg_count--;
}
-exit:
+
spin_unlock_irqrestore(&chan->lock, flags);
if (!err && (chan->txdone_method & TXDONE_BY_POLL))
/* kick start the timer immediately to avoid delays */
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
+
+ if (chan->txdone_method & TXDONE_BY_BLOCK) {
+ tx_tick(chan, err, false);
+ if (!err)
+ goto next;
+ }
}
-static void tx_tick(struct mbox_chan *chan, int r)
+static void tx_tick(struct mbox_chan *chan, int r, bool submit_next)
{
unsigned long flags;
void *mssg;
@@ -101,7 +112,8 @@ static void tx_tick(struct mbox_chan *chan, int r)
spin_unlock_irqrestore(&chan->lock, flags);
/* Submit next message */
- msg_submit(chan);
+ if (submit_next)
+ msg_submit(chan);
if (!mssg)
return;
@@ -127,7 +139,7 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
if (chan->active_req && chan->cl) {
txdone = chan->mbox->ops->last_tx_done(chan);
if (txdone)
- tx_tick(chan, 0);
+ tx_tick(chan, 0, true);
else
resched = true;
}
@@ -176,7 +188,7 @@ void mbox_chan_txdone(struct mbox_chan *chan, int r)
return;
}
- tx_tick(chan, r);
+ tx_tick(chan, r, true);
}
EXPORT_SYMBOL_GPL(mbox_chan_txdone);
@@ -196,7 +208,7 @@ void mbox_client_txdone(struct mbox_chan *chan, int r)
return;
}
- tx_tick(chan, r);
+ tx_tick(chan, r, true);
}
EXPORT_SYMBOL_GPL(mbox_client_txdone);
@@ -275,7 +287,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
ret = wait_for_completion_timeout(&chan->tx_complete, wait);
if (ret == 0) {
t = -ETIME;
- tx_tick(chan, t);
+ tx_tick(chan, t, true);
}
}
diff --git a/drivers/mailbox/mailbox.h b/drivers/mailbox/mailbox.h
index 456ba68513bb..ec68e2e28cd6 100644
--- a/drivers/mailbox/mailbox.h
+++ b/drivers/mailbox/mailbox.h
@@ -10,5 +10,6 @@
#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */
+#define TXDONE_BY_BLOCK BIT(3) /* mailbox driver send_data blocks until done */
#endif /* __MAILBOX_H */
--
2.16.1
^ permalink raw reply related
* [PATCH 2/8] dt-bindings: serial: Add bindings for nvidia, tegra194-tcu
From: Mikko Perttunen @ 2018-05-08 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>
Add bindings for the Tegra Combined UART device used to talk to the
UART console on Tegra194 systems.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
.../bindings/serial/nvidia,tegra194-tcu.txt | 35 ++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
new file mode 100644
index 000000000000..86763bc5d74f
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
@@ -0,0 +1,35 @@
+NVIDIA Tegra Combined UART (TCU)
+
+The TCU is a system for sharing a hardware UART instance among multiple
+systems withing the Tegra SoC. It is implemented through a mailbox-
+based protocol where each "virtual UART" has a pair of mailboxes, one
+for transmitting and one for receiving, that is used to communicate
+with the hardware implementing the TCU.
+
+Required properties:
+- name : Should be tcu
+- compatible
+ Array of strings
+ One of:
+ - "nvidia,tegra194-tcu"
+- mbox-names:
+ "rx" - Mailbox for receiving data from hardware UART
+ "tx" - Mailbox for transmitting data to hardware UART
+- mboxes: Mailboxes corresponding to the mbox-names.
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+Example bindings:
+-----------------
+
+tcu: tcu {
+ compatible = "nvidia,tegra194-tcu";
+ mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
+ <&hsp_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
+ mbox-names = "rx", "tx";
+};
--
2.16.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).