Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/3] dma-debug: unexport dma_debug_resize_entries and debug_dma_dump_mappings
From: Christoph Hellwig @ 2018-05-08 10:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bb5bb25f-24da-9729-a39b-3b88c65ef628@arm.com>

On Tue, May 08, 2018 at 11:05:20AM +0100, Robin Murphy wrote:
> On 24/04/18 15:02, Christoph Hellwig wrote:
>> Only used by the AMD GART driver, which must be built in.
>
> FWIW debug_dma_dump_mappings() is also called by the Intel VT-d driver, but 
> the same reasoning still applies.

I'll update the changelog.

> This does rather beg the question of 
> whether it's right to have bits of low-level dma-debug internals *only* 
> called by a couple of IOMMU drivers, but that can wait for another day.

My gut feeling is that it is wrong, but I didn't have time to look into
the details and history of how this happened.

^ permalink raw reply

* [PATCH v5 12/14] KVM: arm64: Remove redundant *exit_code changes in fpsimd_guest_exit()
From: Marc Zyngier @ 2018-05-08 10:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525449935-31424-13-git-send-email-Dave.Martin@arm.com>

On 04/05/18 17:05, Dave Martin wrote:
> In fixup_guest_exit(), there are a couple of cases where after
> checking what the exit code was, we assign it explicitly with the
> value it already had.
> 
> Assuming this is not indicative of a bug, these assignments are not
> needed.
> 
> This patch removes the redundant assignments simplifies some if-
> nesting that becomes trivial as a result.
> 
> No functional change.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v3 3/3] tty: implement led triggers
From: Uwe Kleine-König @ 2018-05-08 10:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508100851.GY2285@localhost>

On Tue, May 08, 2018 at 12:08:51PM +0200, Johan Hovold wrote:
> On Tue, May 08, 2018 at 12:05:43PM +0200, Uwe Kleine-K?nig wrote:
> > The rx trigger fires when data is pushed to the ldisc by the driver. This
> > is a bit later than the actual receiving of data but has the nice benefit
> > that it doesn't need adaption for each driver and isn't in the hot path.
> > 
> > Similarly the tx trigger fires when data was copied from userspace and is
> > given to the ldisc.
> > 
> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> > ---
> >  arch/arm/boot/dts/imx25-logitech-baby.dts | 192 ++++++++++++++++++++++
> 
> Looks like you included more than intended in this patch.

Right, this doesn't belong here. Feel free to assume I didn't include it
in the patch and comment the rest :-)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH v7 05/11] ARM: smp: Add initialization of CNTVOFF
From: Russell King - ARM Linux @ 2018-05-08 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180420211022.11759-6-mylene.josserand@bootlin.com>

On Fri, Apr 20, 2018 at 11:10:16PM +0200, Myl?ne Josserand wrote:
> The CNTVOFF register from arch timer is uninitialized.
> It should be done by the bootloader but it is currently not the case,
> even for boot CPU because this SoC is booting in secure mode.
> It leads to an random offset value meaning that each CPU will have a
> different time, which isn't working very well.
> 
> Add assembly code used for boot CPU and secondary CPU cores to make
> sure that the CNTVOFF register is initialized. Because this code can
> be used by different platforms, add this assembly file in ARM's common
> folder.
> 
> Signed-off-by: Myl?ne Josserand <mylene.josserand@bootlin.com>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
>  arch/arm/common/Makefile              |  1 +
>  arch/arm/common/secure_cntvoff.S      | 31 +++++++++++++++++++++++++++++++
>  arch/arm/include/asm/secure_cntvoff.h |  8 ++++++++
>  3 files changed, 40 insertions(+)
>  create mode 100644 arch/arm/common/secure_cntvoff.S
>  create mode 100644 arch/arm/include/asm/secure_cntvoff.h
> 
> diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
> index 70b4a14ed993..1e9f7af8f70f 100644
> --- a/arch/arm/common/Makefile
> +++ b/arch/arm/common/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
>  obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
>  obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
>  obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
> +obj-$(CONFIG_SMP)		+= secure_cntvoff.o
>  obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
>  obj-$(CONFIG_MCPM)		+= mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
>  CFLAGS_REMOVE_mcpm_entry.o	= -pg
> diff --git a/arch/arm/common/secure_cntvoff.S b/arch/arm/common/secure_cntvoff.S
> new file mode 100644
> index 000000000000..68a4a8344319
> --- /dev/null
> +++ b/arch/arm/common/secure_cntvoff.S
> @@ -0,0 +1,31 @@
> +/* SPDX-License-Identifier: GPL-2.0

For assembly files, the SPDX specifier is of this format:

/* SPDX-License-Identifier: <SPDX License Expression> */

Please see Documentation/process/license-rules.rst for more
information, and fix your specifier to conform to the requirements.
Thanks.

> + *
> + * Copyright (C) 2014 Renesas Electronics Corporation
> + *
> + * Initialization of CNTVOFF register from secure mode
> + *
> + */
> +
> +#include <linux/linkage.h>
> +#include <asm/assembler.h>
> +
> +ENTRY(secure_cntvoff_init)
> +	.arch	armv7-a
> +	/*
> +	 * CNTVOFF has to be initialized either from non-secure Hypervisor
> +	 * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled
> +	 * then it should be handled by the secure code

This should also state that this code must not be executed if
virtualisation extensions are not present (which should be obvious)
as the mcrr instruction becomes unpredictable in that case.

> +	 */
> +	cps	#MON_MODE
> +	mrc	p15, 0, r1, c1, c1, 0		/* Get Secure Config */
> +	orr	r0, r1, #1
> +	mcr	p15, 0, r0, c1, c1, 0		/* Set Non Secure bit */
> +	isb
> +	mov	r0, #0
> +	mcrr	p15, 4, r0, r0, c14		/* CNTVOFF = 0 */
> +	isb
> +	mcr	p15, 0, r1, c1, c1, 0		/* Set Secure bit */
> +	isb
> +	cps	#SVC_MODE
> +	ret	lr
> +ENDPROC(secure_cntvoff_init)
> diff --git a/arch/arm/include/asm/secure_cntvoff.h b/arch/arm/include/asm/secure_cntvoff.h
> new file mode 100644
> index 000000000000..1f93aee1f630
> --- /dev/null
> +++ b/arch/arm/include/asm/secure_cntvoff.h
> @@ -0,0 +1,8 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

This one conforms.

> +
> +#ifndef __ASMARM_ARCH_CNTVOFF_H
> +#define __ASMARM_ARCH_CNTVOFF_H
> +
> +extern void secure_cntvoff_init(void);
> +
> +#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 00/13] drm/kms/mode: using helper func drm_display_mode_to/from_videomode for calculating timing parameters
From: Satendra Singh Thakur @ 2018-05-08 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180507134602.GH12521@phenom.ffwll.local>

On Thu, May 07, 2018 at 15:46:02 +0200, Daniel Vetter wrote:
> On Thu, May 03, 2018 at 01:53:55PM +0530, Satendra Singh Thakur wrote:
> > 1.There is a function in drm-core to calculate display timing parameters:
> > horizontal front porch, back porch, sync length,
> > vertical front porch, back porch, sync length and
> > clock in Hz.
> > However, some drivers are still calculating these parameters themselves.
> > Therefore, there is a duplication of the code.
> > This patch series replaces this redundant code with the function
> > drm_display_mode_to_videomode.
> > This removes nearly 100 redundant lines from the related drivers.
> > 2.For some drivers (sun4i) the reverse helper
> > drm_display_mode_from_videomode is used.
> > 3.For some drivers it replaces arithmatic operators (*, /) with shifting
> > operators (>>, <<).
> > 4.For some drivers DRM_MODE_FLAG_* are replaced with DISPLAY_FLAGS_* flags.
> > 5.These changes apply to following crtc and encoder drivers:
> > atmel-hlcdc
> > bridge-tc358767
> > exynos-dsi
> > fsl-dcu
> > gma500-mdfld_dsi_dpi
> > hisilicon-kirin_dsi, ade
> > meson-encoder
> > pl111-display
> > sun4i-tv
> > ti lcdc
> > tegra dc
> > mediatek dpi dsi
> > bridge-adv7533
> 
> The drm_mode_to_videomode helper is meant for interop between drm and v4l,
> which have different internal structures to represent modes.
> 
> For drivers that only use drm I think the better option would be to add
> these fields to struct drm_display_mode as another set of crtc_* values
> (the computed values are stored in crtc_ prefixed members). And compute
> front/back porch in drm_mode_set_crtcinfo.
> 
> Then we can use these new drm_display_mode->crtc_h|vfront|back_porch
> fields in all the drivers you're changing. This way you avoid having to
> change all the drm drivers to use v4l #defines.
> 
> Thanks,
> Daniel

Hi Daniel,
Thanks for the comments.
I will look into it.

Thanks
-Satendra

^ 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 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525449935-31424-14-git-send-email-Dave.Martin@arm.com>

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.

>  		}
>  	}
>  
>  	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
> -	    *exit_code == ARM_EXCEPTION_TRAP &&
>  	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
>  	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
>  		int ret = __vgic_v3_perform_cpuif_access(vcpu);
> @@ -428,6 +430,7 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
>  			return true;
>  	}
>  
> +exit:
>  	/* Return to the host kernel and handle the exit */
>  	return false;
>  }
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH] tty: pl011: Avoid spuriously stuck-off interrupts
From: Russell King - ARM Linux @ 2018-05-08 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1524823545-11309-2-git-send-email-Dave.Martin@arm.com>

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?

-- 
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 14/14] KVM: arm64: Invoke FPSIMD context switch trap from C
From: Marc Zyngier @ 2018-05-08 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525449935-31424-15-git-send-email-Dave.Martin@arm.com>

On 04/05/18 17:05, Dave Martin wrote:
> The conversion of the FPSIMD context switch trap code to C has added
> some overhead to calling it, due to the need to save registers that
> the procedure call standard defines as caller-saved.
> 
> So, perhaps it is no longer worth invoking this trap handler quite
> so early.
> 
> Instead, we can invoke it from fixup_guest_exit(), with little
> likelihood of increasing the overhead much further.
> 
> As a convenience, this patch gives __hyp_switch_fpsimd() the same
> return semantics fixup_guest_exit().  For now there is no
> possibility of a spurious FPSIMD trap, so the function always
> returns true, but this allows it to be tail-called with a single
> return statement.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v3 2/3] can: simplify LED trigger handling
From: Marc Kleine-Budde @ 2018-05-08 11:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508100543.12559-3-u.kleine-koenig@pengutronix.de>

On 05/08/2018 12:05 PM, Uwe Kleine-K?nig wrote:
> The new function led_trigger_register_format allows one to simplify LED
> trigger handling considerably.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>

Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180508/dd8e18c4/attachment.sig>

^ permalink raw reply

* [PATCH v2 11/17] kvm: arm64: Configure VTCR per VM
From: Suzuki K Poulose @ 2018-05-08 11:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1175bc06-14b1-63e4-7b99-55c22db1c451@arm.com>

On 03/05/18 15:39, James Morse wrote:
> Hi Suzuki,
> 
> On 27/03/18 14:15, Suzuki K Poulose wrote:
>> We set VTCR_EL2 very early during the stage2 init and don't
>> touch it ever. This is fine as we had a fixed IPA size. This
>> patch changes the behavior to set the VTCR for a given VM,
>> depending on its stage2 table. The common configuration for
>> VTCR is still performed during the early init as we have to
>> retain the hardware access flag update bits (VTCR_EL2_HA)
>> per CPU (as they are only set for the CPUs which are capabile).
>> The bits defining the number of levels in the page table (SL0)
>> and and the size of the Input address to the translation (T0SZ)
>> are programmed for each VM upon entry to the guest.
> 
> 
>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>> index 596f8e4..9f3c8b8 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -392,10 +392,12 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>>   
>>   static inline void __cpu_init_stage2(void)
>>   {
>> -	u32 parange = kvm_call_hyp(__init_stage2_translation);
>> +	u32 ps;
>>   
>> -	WARN_ONCE(parange < 40,
>> -		  "PARange is %d bits, unsupported configuration!", parange);
>> +	kvm_call_hyp(__init_stage2_translation);
>> +	ps = id_aa64mmfr0_parange_to_phys_shift(read_sysreg(id_aa64mmfr0_el1));
> 
> Doesn't id_aa64mmfr0_parange_to_phys_shift() expect you do to the mask and shift
> for it? This will always hit the default case.

Good catch ! The error case was not hit on the system I tested, as it was
indeed having 48bit PA. I should have done more testing with Juno where it
is 40bit PA (which doesn't really allow different phys-shift ranges).

I will change the helper to extract the parange and the convert it.
Also, rename it to :

id_aa64mmfr0_phys_shift()

Cheers
Suzuki

> 
> 
>> +	WARN_ONCE(ps < 40,
>> +		  "PARange is %d bits, unsupported configuration!", ps);
>>   }
> 
> 
> 
> Thanks,
> 
> James
> 

^ permalink raw reply

* [PATCH v1 6/7] Bluetooth: hci_mediatek: Add protocol support for MediaTek serial devices
From: Marcel Holtmann @ 2018-05-08 11:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525767775.18877.22.camel@mtkswgap22>

Hi Sean,

>>>>> +
>>>>> +static int mtk_wmt_cmd_sync(struct hci_uart *hu, u8 opcode, u8 flag, u16 plen,
>>>>> +			    const void *param)
>>>>> +{
>>>>> +	struct mtk_bt_dev *btdev = hu->priv;
>>>>> +	struct hci_command_hdr *hhdr;
>>>>> +	struct hci_acl_hdr *ahdr;
>>>>> +	struct mtk_wmt_hdr *whdr;
>>>>> +	struct sk_buff *skb;
>>>>> +	int ret = 0;
>>>>> +
>>>>> +	init_completion(&btdev->wmt_cmd);
>>>>> +
>>>>> +	skb = bt_skb_alloc(plen + MTK_WMT_CMD_SIZE, GFP_KERNEL);
>>>>> +	if (!skb)
>>>>> +		return -ENOMEM;
>>>>> +
>>>>> +	/*
>>>>> +	 * WMT data is carried in either ACL or HCI format with op code as
>>>>> +	 * 0xfc6f and followed by a WMT header and its actual payload.
>>>>> +	 */
>>>> 
>>>> Please use net subsystem comment style.
>>>> 
>>>>> +	switch (opcode) {
>>>>> +	case MTK_WMT_PATCH_DWNLD:
>>>>> +		ahdr = skb_put(skb, HCI_ACL_HDR_SIZE);
>>>>> +		ahdr->handle = cpu_to_le16(0xfc6f);
>>>>> +		ahdr->dlen   = cpu_to_le16(plen + MTK_WMT_HDR_SIZE);
>>>>> +		break;
>>>>> +	default:
>>>>> +		hhdr = skb_put(skb, HCI_COMMAND_HDR_SIZE);
>>>>> +		hhdr->opcode = cpu_to_le16(0xfc6f);
>>>>> +		hhdr->plen = plen + MTK_WMT_HDR_SIZE;
>>>>> +		break;
>>>>> +	}
>>>>> +
>>>>> +	hci_skb_pkt_type(skb) = opcode == MTK_WMT_PATCH_DWNLD ?
>>>>> +				HCI_ACLDATA_PKT : HCI_COMMAND_PKT;
>>>> 
>>>> Why not move that into the switch statement above.
>>>> 
>>>>> +
>>>>> +	/* Start to build a WMT header and its actual payload. */
>>>>> +	whdr = skb_put(skb, MTK_WMT_HDR_SIZE);
>>>>> +	whdr->dir = 1;
>>>>> +	whdr->op = opcode;
>>>>> +	whdr->dlen = cpu_to_le16(plen + 1);
>>>>> +	whdr->flag = flag;
>>>>> +	skb_put_data(skb, param, plen);
>>>>> +
>>>>> +	mtk_enqueue(hu, skb);
>>>>> +	hci_uart_tx_wakeup(hu);
>>>>> +
>>>>> +	/*
>>>>> +	 * Waiting a WMT event response, while we must take care in case of
>>>>> +	 * failures for the wait.
>>>>> +	 */
>>>>> +	ret = wait_for_completion_interruptible_timeout(&btdev->wmt_cmd, HZ);
>>>>> +
>>>>> +	return ret > 0 ? 0 : ret < 0 ? ret : -ETIMEDOUT;
>>>>> +}
>>>> 
>>>> All in all I am not convinced that this is super clean. I get that we need something special for having this in the ACL data packets, but for the standard HCI command I prefer that __hci_cmd_sync is used. I addition, it seems that patch download is the only special case and that happens before at the setup stage. So we could make things special for that. I need to understand this a bit better. Can I get a btmon -w trace.log file from the whole init procedure.
>>>> 
>>> 
>>> While i was trying to rewrite the driver based on btuart.c. you posted
>>> on RFC, I used __hci_cmd_sync_ev to replace such kinds of SoC specific
>>> hci command sending which I've done previously with mtk_wmt_cmd_sync.
>>> 
>>> However, eventually, I got a cmd_timer timeout whose message printed
>>> on console as "Bluetooth: hci0: command 0xfc6f tx timeout".
>>> 
>>> The mtk soc specific cmd/event I posted below, I dumped directly in
>>> driver, always uses cmd as opcode 0xfc6f, and its event id as 0xe4.
>>> 
>>> It appears to the event id is not standard and thus it cannot cancel the
>>> cmd timer when the special hci event is being handled. This way can we
>>> can still use __hci_cmd_sync api ?
>>> 
>>> [    4.896200] hci tx: 00000000: 01 6f fc 05 01 07 01 00 04    
>>> [    4.904671] hci rx: 00000000: e4 05 02 07 01 00
>>> 00                             
>>> [    4.912859] Bluetooth: hci0 event 0xe4
>>> 
>>> 
>>> buildroot login: [    6.914509] Bluetooth: hci0: command 0xfc6f tx
>>> timeout
>>> [    6.919831] hci tx: 00000000: 01 6f fc 06 01 06 02 00 00
>>> 01                    .o........
>>> [    7.006631] hci rx: 00000000: e4 05 02 06 01 00
>>> 00                             .......
>>> [    7.014821] Bluetooth: hci0 event 0xe4
>> 
>> can you just start btmon before loading the module / driver? It makes it a lot easier since it will actually decode the basics for us. If there is a bug within __hci_cmd_sync_ev, then we are going to fix it.
>> 
> 
> I'm happy to do with btmon. just the environment with buildroot the BT
> running on seems there's a missing support for btmon. I can start to use
> btmon once I change the environment to Debian.
> 
>> So all the MTK vendor commands respond with a vendor event? Or are there some that do the standard command status/complete handling?
>> 
> 
> yes, mtk controller after mt7622 (included), its MTK vendors command
> (opcode 0xfc6f) always respond with a vendor event id 0xe4. And they
> don't do any standard status/complete handling.

then we need to figure out where the __hci_cmd_sync_ev causes a problem. Since normally that should just work for you.

> BTW, mtk controller before mt7622, such as mt7623, its MTK vendor
> command always go with completely specific format, not with hci format.

What does that mean? Do you have an example?

Regards

Marcel

^ permalink raw reply

* [BUGFIX PATCH v3 0/4] arm: kprobes: Fix to prohibit probing on unsafe functions
From: Russell King - ARM Linux @ 2018-05-08 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152540727123.29650.13679359124038587629.stgit@devbox>

On Fri, May 04, 2018 at 01:14:31PM +0900, Masami Hiramatsu wrote:
> Hi,
> 
> This is the 3rd version of bugfix series for kprobes on arm.
> This series fixes 4 different issues which I found.
> 
>  - Fix to use smp_processor_id() after disabling preemption.
>  - Prohibit probing on optimized_callback() for avoiding
>    recursive probe.
>  - Prohibit kprobes on do_undefinstr() by same reason.
>  - Prohibit kprobes on get_user() by same reason.
> 
> >From v2, I included another 2 bugfixes (1/4 and 2/4)
> which are not merged yet, and added "Cc: stable at vger.kernel.org",
> since there are obvious bugs.

Please submit them to the patch system, thanks.

> 
> Thanks,
> 
> ---
> 
> Masami Hiramatsu (4):
>       arm: kprobes: Fix to use get_kprobe_ctlblk after irq-disabed
>       arm: kprobes: Prohibit probing on optimized_callback
>       arm: kprobes: Prohibit kprobes on do_undefinstr
>       arm: kprobes: Prohibit kprobes on get_user functions
> 
> 
>  arch/arm/include/asm/assembler.h  |   10 ++++++++++
>  arch/arm/kernel/traps.c           |    5 ++++-
>  arch/arm/lib/getuser.S            |   10 ++++++++++
>  arch/arm/probes/kprobes/opt-arm.c |    4 +++-
>  4 files changed, 27 insertions(+), 2 deletions(-)
> 
> --
> Masami Hiramatsu (Linaro) <mhiramat@kernel.org>

-- 
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 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0c616c43-3bff-1c93-0463-fae1c53c0e51@arm.com>

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")

> 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.


[...]

> > 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.

> 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?

Cheers
---Dave

^ 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 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <eddc101f-6f6c-a37b-ae48-e80a24f60815@arm.com>

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.)


Cheers
---Dave

^ permalink raw reply

* [PATCH 1/2] arm64: signal: Report signal frame size to userspace via auxv
From: Mark Rutland @ 2018-05-08 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1525776211-28169-2-git-send-email-Dave.Martin@arm.com>

On Tue, May 08, 2018 at 11:43:30AM +0100, Dave Martin wrote:
> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index fac1c4d..771c7a8 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -24,6 +24,10 @@
>  #include <asm/ptrace.h>
>  #include <asm/user.h>
>  
> +#ifndef __ASSEMBLY__
> +#include <asm/processor.h> /* for get_minsigstksz(), used by ARCH_DLINFO */
> +#endif

This can live under the existing ifndef __ASSEMBLY__ block, where
ARCH_DLINFO lives.

[...]

> +/*
> + * 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.

Thanks,
Mark.

^ permalink raw reply

* [RESEND PATCH v2] bus: arm-cci: use asm unreachable
From: Stefan Agner @ 2018-05-08 11:32 UTC (permalink / raw)
  To: linux-arm-kernel

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.

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();
 }
 
 /**
-- 
2.17.0

^ permalink raw reply related

* [PATCH 1/2] arm64: signal: Report signal frame size to userspace via auxv
From: Dave Martin @ 2018-05-08 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508113043.elgvfz3dud2amcif@lakrids.cambridge.arm.com>

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:
> > diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> > index fac1c4d..771c7a8 100644
> > --- a/arch/arm64/include/asm/elf.h
> > +++ b/arch/arm64/include/asm/elf.h
> > @@ -24,6 +24,10 @@
> >  #include <asm/ptrace.h>
> >  #include <asm/user.h>
> >  
> > +#ifndef __ASSEMBLY__
> > +#include <asm/processor.h> /* for get_minsigstksz(), used by ARCH_DLINFO */
> > +#endif
> 
> This can live under the existing ifndef __ASSEMBLY__ block, where
> ARCH_DLINFO lives.

Can do.  I don't usually like mixing #includes with the code unless absolutely necessary, but this looks like a pretty trivial case, with just some #defines before the #ifndef __ASSEMBLY__ block.

So I guess this can be moved harmlessly.

> 
> [...]
> 
> > +/*
> > + * 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.

Cheers
---Dave

^ permalink raw reply

* [PATCH 0/8] Tegra Combined UART driver
From: Mikko Perttunen @ 2018-05-08 11:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

on Tegra194, the primary console UART is the "Tegra Combined UART",
or TCU. This is a "virtual UART", where each consumer communicates
with a central implementation over mailboxes. The central
implementation then multiplexes the streams and arbitrates use of
a hardware serial port. This driver implements the consumer portion
to allow using the primary console.

The series is split into the following parts:
* patches 1 and 2 add the device tree bindings for mailbox and tcu
  itself.
* patch 3 adds a blocking transmission option to the mailbox
  framework.
* patches 4 and 5 add support for the "shared mailbox" primitive
  to the Tegra HSP driver.
* patch 6 adds the TCU driver itself
* patches 7 and 8 do the necessary device tree changes.

The series has been tested on the Tegra194 P2972 board.

Thanks,
Mikko

Mikko Perttunen (8):
  dt-bindings: tegra186-hsp: Add shared interrupts
  dt-bindings: serial: Add bindings for nvidia,tegra194-tcu
  mailbox: Add transmit done by blocking option
  mailbox: tegra-hsp: Refactor in preparation of mailboxes
  mailbox: tegra-hsp: Add support for shared mailboxes
  serial: Add Tegra Combined UART driver
  arm64: tegra: Add nodes for tcu on Tegra194
  arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888

 .../bindings/mailbox/nvidia,tegra186-hsp.txt       |   2 +
 .../bindings/serial/nvidia,tegra194-tcu.txt        |  35 +++
 arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi     |   2 +-
 arch/arm64/boot/dts/nvidia/tegra194.dtsi           |  34 ++-
 drivers/mailbox/mailbox.c                          |  30 +-
 drivers/mailbox/mailbox.h                          |   1 +
 drivers/mailbox/tegra-hsp.c                        | 320 +++++++++++++++++----
 drivers/tty/serial/Kconfig                         |   9 +
 drivers/tty/serial/Makefile                        |   1 +
 drivers/tty/serial/tegra-tcu.c                     | 302 +++++++++++++++++++
 include/uapi/linux/serial_core.h                   |   3 +
 11 files changed, 671 insertions(+), 68 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
 create mode 100644 drivers/tty/serial/tegra-tcu.c

-- 
2.16.1

^ permalink raw reply

* [PATCH 1/8] dt-bindings: tegra186-hsp: Add shared interrupts
From: Mikko Perttunen @ 2018-05-08 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180508114403.14499-1-mperttunen@nvidia.com>

Non-doorbell interrupts are routed through "shared interrupts". These
interrupts can be mapped to various internal interrupt lines. Add
interrupt properties for shared interrupts to the tegra186-hsp device
tree bindings.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
index b99d25fc2f26..9edcdf82d719 100644
--- a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
@@ -21,6 +21,8 @@ Required properties:
     Contains a list of names for the interrupts described by the interrupt
     property. May contain the following entries, in any order:
     - "doorbell"
+    - "sharedN", where 'N' is a number from zero up to the number of
+      external interrupts supported by the HSP instance minus one.
     Users of this binding MUST look up entries in the interrupt property
     by name, using this interrupt-names property to do so.
 - interrupts
-- 
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

* [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 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 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 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 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


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