[U-Boot] [PATCH 2/2] sun7i: Add PSCI v0.2 support

Hans de Goede hdegoede at redhat.com
Mon Dec 15 12:44:34 CET 2014


Hi,

On 15-12-14 12:37, Jan Kiszka wrote:
> This extends the PSCI support for the A20 to a dual v0.2 and v0.1
> interface. Recent OSes will prefer v0.2, olders will still find the
> original interface, just at v0.2 service IDs.
>
> In addition to the existing services, v0.2 requires us to implement both
> system off and reset. At least Linux will make use of them in favor of
> its own implementations and, thus, fail if they do not work.

Ugh, that may be a problem, as at least power off is highly SoC specific
(different pmics, and newer pmics have a different bus) and somewhat board
specific.

I think we may avoid adding any board specific stuff for now, since we
only want PSCI support on A20 and later and the only boards I know
of which are not using the standard axp pmics are all A10 / A13 boards,
but this might come back to bite us in the future.

Can't we just return -ENOTSUPPORTED or some such ?

Regards,

Hans


>
> Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
> ---
>   arch/arm/cpu/armv7/psci.S             |  35 +++++++++-
>   arch/arm/cpu/armv7/sunxi/psci.S       | 117 ++++++++++++++++++++++++++++++++++
>   arch/arm/cpu/armv7/virt-dt.c          |   5 +-
>   arch/arm/include/asm/arch-sunxi/cpu.h |   2 +
>   arch/arm/include/asm/psci.h           |  24 +++++--
>   5 files changed, 173 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S
> index bf11a34..e2a38ca 100644
> --- a/arch/arm/cpu/armv7/psci.S
> +++ b/arch/arm/cpu/armv7/psci.S
> @@ -49,8 +49,18 @@ ENTRY(psci_cpu_suspend)
>   ENTRY(psci_cpu_off)
>   ENTRY(psci_cpu_on)
>   ENTRY(psci_migrate)
> +ENTRY(psci_affinity_info)
> +ENTRY(psci_migrate_info_type)
> +ENTRY(psci_migrate_info_up_cpu)
> +ENTRY(psci_system_off)
> +ENTRY(psci_system_reset)
>   	mov	r0, #ARM_PSCI_RET_NI	@ Return -1 (Not Implemented)
>   	mov	pc, lr
> +ENDPROC(psci_system_reset)
> +ENDPROC(psci_system_off)
> +ENDPROC(psci_migrate_info_up_cpu)
> +ENDPROC(psci_migrate_info_type)
> +ENDPROC(psci_affinity_info)
>   ENDPROC(psci_migrate)
>   ENDPROC(psci_cpu_on)
>   ENDPROC(psci_cpu_off)
> @@ -59,16 +69,33 @@ ENDPROC(psci_cpu_suspend)
>   .weak psci_cpu_off
>   .weak psci_cpu_on
>   .weak psci_migrate
> +.weak psci_affinity_info
> +.weak psci_migrate_info_type
> +.weak psci_migrate_info_up_cpu
> +.weak psci_system_off
> +.weak psci_system_reset
>
>   _psci_table:
> +	.word	ARM_PSCI_FN_PSCI_VERSION
> +	.word	psci_version
>   	.word	ARM_PSCI_FN_CPU_SUSPEND
>   	.word	psci_cpu_suspend
>   	.word	ARM_PSCI_FN_CPU_OFF
>   	.word	psci_cpu_off
>   	.word	ARM_PSCI_FN_CPU_ON
>   	.word	psci_cpu_on
> +	.word	ARM_PSCI_FN_AFFINITY_INFO
> +	.word	psci_affinity_info
>   	.word	ARM_PSCI_FN_MIGRATE
>   	.word	psci_migrate
> +	.word	ARM_PSCI_FN_MIGRATE_INFO_TYPE
> +	.word	psci_migrate_info_type
> +	.word	ARM_PSCI_FN_MIGRATE_INFO_UP_CPU
> +	.word	psci_migrate_info_up_cpu
> +	.word	ARM_PSCI_FN_SYSTEM_OFF
> +	.word	psci_system_off
> +	.word	ARM_PSCI_FN_SYSTEM_RESET
> +	.word	psci_system_reset
>   	.word	0
>   	.word	0
>
> @@ -86,7 +113,7 @@ _smc_psci:
>   	ldr	r6, [r4, #4]		@ Load target PC
>   	cmp	r5, #0			@ If reach the end, bail out
>   	moveq	r0, #ARM_PSCI_RET_INVAL	@ Return -2 (Invalid)
> -	beq	2f
> +	beq	return
>   	cmp	r0, r5			@ If not matching, try next entry
>   	addne	r4, r4, #8
>   	bne	1b
> @@ -94,9 +121,13 @@ _smc_psci:
>   	blx	r6			@ Execute PSCI function
>
>   	@ Switch back to non-secure
> -2:	mcr	p15, 0, r7, c1, c1, 0
> +return:	mcr	p15, 0, r7, c1, c1, 0
>
>   	pop	{r4-r7, lr}
>   	movs	pc, lr			@ Return to the kernel
>
> +psci_version:
> +	mov	r0, #0x00000002		@ Version 0.2
> +	b	return
> +
>   	.popsection
> diff --git a/arch/arm/cpu/armv7/sunxi/psci.S b/arch/arm/cpu/armv7/sunxi/psci.S
> index 0aa4007..bba1894 100644
> --- a/arch/arm/cpu/armv7/sunxi/psci.S
> +++ b/arch/arm/cpu/armv7/sunxi/psci.S
> @@ -2,6 +2,9 @@
>    * Copyright (C) 2013 - ARM Ltd
>    * Author: Marc Zyngier <marc.zyngier at arm.com>
>    *
> + * Copyright (C) Siemens AG, 2014
> + * Author: Jan Kiszka <jan.kiszka at siemens.com>
> + *
>    * Based on code by Carl van Schaik <carl at ok-labs.com>.
>    *
>    * This program is free software; you can redistribute it and/or modify
> @@ -42,6 +45,35 @@
>   #define	GICD_BASE		0x1c81000
>   #define	GICC_BASE		0x1c82000
>
> +#define	TWI_DATA		0x0008
> +#define	TWI_CNTR		0x000c
> +#define	TWI_STAT		0x0010
> +#define	TWI_CCR			0x0014
> +#define	TWI_SRST		0x0018
> +
> +#define	TWI_CNTR_STOP		(1 << 4)
> +#define	TWI_CNTR_START		(1 << 5)
> +#define	TWI_CNTR_BUSEN		(1 << 6)
> +
> +#define	TWI_STAT_START_SENT	0x08
> +#define	TWI_STAT_ADDR_ACK	0x18
> +#define	TWI_STAT_DATA_ACK	0x28
> +
> +#define	TWI_CCR_100KHZ		((11 << 3) | 2)
> +
> +#define	AXP209_ADDR		0x34
> +#define	AXP209_REG_SHUTDOWN	0x32
> +#define	AXP209_SHUTDOWN_CTRL	0x80
> +
> +#define	WDOG_CTL		0x00
> +#define	WDOG_MODE		0x04
> +
> +#define	WDOG_CTL_RSTART		(1 << 0)
> +
> +#define	WDOG_MODE_EN		(1 << 0)
> +#define	WDOG_MODE_RSTEN		(1 << 1)
> +#define	WDOG_MODE_0_5_S		(0x0 << 3)
> +
>   .macro	timer_wait	reg, ticks
>   	@ Program CNTP_TVAL
>   	movw	\reg, #(\ticks & 0xffff)
> @@ -175,10 +207,13 @@ out:	mcr	p15, 0, r7, c1, c1, 0
>
>   	@ r1 = target CPU
>   	@ r2 = target PC
> +	@ r3 = context (v0.2 only)
>   .globl	psci_cpu_on
>   psci_cpu_on:
>   	adr	r0, _target_pc
>   	str	r2, [r0]
> +	adr	r0, _context
> +	str	r3, [r0]
>   	dsb
>
>   	movw	r0, #(SUN7I_CPUCFG_BASE & 0xffff)
> @@ -237,6 +272,8 @@ psci_cpu_on:
>
>   _target_pc:
>   	.word	0
> +_context:
> +	.word	0
>
>   /* Imported from Linux kernel */
>   v7_flush_dcache_all:
> @@ -297,6 +334,8 @@ _sunxi_cpu_entry:
>
>   	adr	r0, _target_pc
>   	ldr	r0, [r0]
> +	adr	r1, _context
> +	ldr	r1, [r1]
>   	b	_do_nonsec_entry
>
>   .globl	psci_cpu_off
> @@ -328,5 +367,83 @@ psci_cpu_off:
>   1:	wfi
>   	b	1b
>
> +/*
> + * r0: TWI base address
> + * r1: state to wait for
> + */
> +twi_wait:
> +1:	ldr	r2, [r0, #TWI_STAT]		@ Read state
> +	and	r2, r2, #0xff			@ Mask out state bits
> +	cmp	r2, r1				@ State reached?
> +	bne	1b
> +
> +	bx	lr
> +
> +/*
> + * r0: TWI base address
> + * r1: data value to be sent
> + */
> +twi_send:
> +	str	r1, [r0, #TWI_DATA]		@ Write outgoing data value
> +	mov	r1, #(TWI_CNTR_BUSEN)		@ Trigger transmission
> +	str	r1, [r0, #TWI_CNTR]
> +
> +	bx	lr
> +
> +.globl	psci_system_off
> +psci_system_off:
> +	movw	r0, #(SUNXI_TWI0_BASE & 0xffff)
> +	movt	r0, #(SUNXI_TWI0_BASE >> 16)
> +
> +	@ Perform soft-reset
> +	mov	r1, #0
> +	str	r1, [r0, #TWI_SRST]
> +
> +	@ Configure speed
> +	mov	r1, #TWI_CCR_100KHZ
> +	str	r1, [r0, #TWI_CCR]
> +
> +	@ Send STOP (just in case), then transmit START condition
> +	mov	r1, #(TWI_CNTR_BUSEN | TWI_CNTR_START | TWI_CNTR_STOP)
> +	str	r1, [r0, #TWI_CNTR]
> +	mov	r1, #TWI_STAT_START_SENT
> +	bl	twi_wait
> +
> +	@ Send AXP209 address
> +	mov	r1, #(AXP209_ADDR << 1)
> +	bl	twi_send
> +	mov	r1, #TWI_STAT_ADDR_ACK
> +	bl	twi_wait
> +
> +	@ Select AXP209 register
> +	mov	r1, #AXP209_REG_SHUTDOWN
> +	bl	twi_send
> +	mov	r1, #TWI_STAT_DATA_ACK
> +	bl	twi_wait
> +
> +	@ Request shutdown
> +	mov	r1, #AXP209_SHUTDOWN_CTRL
> +	bl	twi_send
> +	mov	r1, #TWI_STAT_DATA_ACK
> +	bl	twi_wait
> +
> +	@ Complete the transmission with a STOP condition
> +	mov	r1, #TWI_CNTR_STOP
> +	str	r1, [r0, #TWI_CNTR]
> +
> +1:	b	1b
> +
> +.globl	psci_system_reset
> +psci_system_reset:
> +	movw	r0, #(SUNXI_WDOG_CTL & 0xffff)
> +	movt	r0, #(SUNXI_WDOG_CTL >> 16)
> +
> +	mov	r1, #(WDOG_MODE_RSTEN | WDOG_MODE_EN | WDOG_MODE_0_5_S)
> +	str	r1, [r0, #WDOG_MODE]
> +
> +	mov	r1, #WDOG_CTL_RSTART
> +	str	r1, [r0, #WDOG_CTL]
> +1:	b	1b
> +
>   text_end:
>   	.popsection
> diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c
> index 0b0d6a7..f529d51 100644
> --- a/arch/arm/cpu/armv7/virt-dt.c
> +++ b/arch/arm/cpu/armv7/virt-dt.c
> @@ -66,7 +66,10 @@ static int fdt_psci(void *fdt)
>   			return nodeoff;
>   	}
>
> -	tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci");
> +	tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci-0.2");
> +	if (tmp)
> +		return tmp;
> +	tmp = fdt_appendprop_string(fdt, nodeoff, "compatible", "arm,psci");
>   	if (tmp)
>   		return tmp;
>   	tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
> index 2c92b5c..e887e96 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
> @@ -137,6 +137,8 @@
>
>   #define SUNXI_BROM_BASE			0xffff0000	/* 32 kiB */
>
> +#define SUNXI_WDOG_CTL			(SUNXI_TIMER_BASE + 0x90)
> +
>   #define SUNXI_CPU_CFG			(SUNXI_TIMER_BASE + 0x13c)
>
>   #ifndef __ASSEMBLY__
> diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
> index 704b4b0..234475a 100644
> --- a/arch/arm/include/asm/psci.h
> +++ b/arch/arm/include/asm/psci.h
> @@ -18,18 +18,28 @@
>   #ifndef __ARM_PSCI_H__
>   #define __ARM_PSCI_H__
>
> -/* PSCI interface */
> -#define ARM_PSCI_FN_BASE		0x95c1ba5e
> -#define ARM_PSCI_FN(n)			(ARM_PSCI_FN_BASE + (n))
> +#define ARM_PSCI_FN32_BASE		0x84000000
> +#define ARM_PSCI_FN(n)			(ARM_PSCI_FN32_BASE + (n))
>
> -#define ARM_PSCI_FN_CPU_SUSPEND		ARM_PSCI_FN(0)
> -#define ARM_PSCI_FN_CPU_OFF		ARM_PSCI_FN(1)
> -#define ARM_PSCI_FN_CPU_ON		ARM_PSCI_FN(2)
> -#define ARM_PSCI_FN_MIGRATE		ARM_PSCI_FN(3)
> +#define ARM_PSCI_FN_PSCI_VERSION	ARM_PSCI_FN(0)
> +#define ARM_PSCI_FN_CPU_SUSPEND		ARM_PSCI_FN(1)
> +#define ARM_PSCI_FN_CPU_OFF		ARM_PSCI_FN(2)
> +#define ARM_PSCI_FN_CPU_ON		ARM_PSCI_FN(3)
> +#define ARM_PSCI_FN_AFFINITY_INFO	ARM_PSCI_FN(4)
> +#define ARM_PSCI_FN_MIGRATE		ARM_PSCI_FN(5)
> +#define ARM_PSCI_FN_MIGRATE_INFO_TYPE	ARM_PSCI_FN(6)
> +#define ARM_PSCI_FN_MIGRATE_INFO_UP_CPU	ARM_PSCI_FN(7)
> +#define ARM_PSCI_FN_SYSTEM_OFF		ARM_PSCI_FN(8)
> +#define ARM_PSCI_FN_SYSTEM_RESET	ARM_PSCI_FN(9)
>
>   #define ARM_PSCI_RET_SUCCESS		0
>   #define ARM_PSCI_RET_NI			(-1)
>   #define ARM_PSCI_RET_INVAL		(-2)
>   #define ARM_PSCI_RET_DENIED		(-3)
> +#define ARM_PSCI_RET_ALREADY_ON		(-4)
> +#define ARM_PSCI_RET_ON_PENDING		(-5)
> +#define ARM_PSCI_RET_INTERNAL_FAILURE	(-6)
> +#define ARM_PSCI_RET_NOT_PRESENT	(-7)
> +#define ARM_PSCI_RET_DISABLED		(-8)
>
>   #endif /* __ARM_PSCI_H__ */
>


More information about the U-Boot mailing list