linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/14] enable HiP04 SoC
@ 2014-05-07 14:44 Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 01/14] ARM: debug: add HiP04 debug uart Haojian Zhuang
                   ` (13 more replies)
  0 siblings, 14 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Changelog:
v5:
  * Add ARCH_MULTI_V7_NONLPAE to avoid change too much things in Kconfig.
  * Use memreserve in DTS.
  * Remove L2 reset operation in mcpm implementation.
  * Re-use nr_lr field to cover HIP04 GICH_APR implementation.
  * Add more comments.

v4:
  * Add multi_v7_lpae_defconfig.
  * Select CONFIG_ARCH_MULTI_V7_LPAE if CONFIG_ARCH_MULTI_V7 is selected.
  * Only ARMADA_XP is ARCH_MULTI_V7_LPAE, other ARMADA chips are ARCH_MULTI_V7.
  * Remove gich_lr0 variable since we can calculate offset of GICH_LR0 from
    GICH_APR.
  * Cleanup GIC driver to support HiP04 GIC.
  * Cleanup HiP04 mcpm implementation.

v3:
  * Replace CONFIG_ARCH_MULTI_V7 by CONFIG_ARCH_MULTI_V7_LPAE in some SoC.
  * Update MCPM code based on Dave's patch.
  * Remove MCPM node in DTS file. Use sysctrl & fabric node instead.
  * Move hardcoding on bootwrapper into DTS file.
  * Append the CONFIG_MCPM_QUAD_CLUSTER for HiP04.
  * Fix the return value from gic_get_cpumask() if it's used in standard gic.
  * Add the vgic support on HiP04 GIC.
  * Add virtualization support in HiP04 defconfig.

v2:
  * Append ARCH_MULTI_V7_LPAE configuration. Define ARCH_MULTI_V7 to only
    support non-LPAE platform.
  * Append document of DT supporting.
  * Append ARCH_HISI in hi3xxx_defconfig.
  * Enable errata 798181 for HiP04 SoC.
  * Add PMU support.


Haojian Zhuang (12):
  ARM: debug: add HiP04 debug uart
  ARM: add V7_NONLPAE && V7_LPAE sub config
  ARM: config: append lpae configuration
  irq: gic: use mask field in GICC_IAR
  irq: gic: support hip04 gic
  ARM: mcpm: support 4 clusters
  ARM: hisi: add ARCH_HISI
  ARM: hisi: add hip04 SoC support
  ARM: dts: append hip04 dts
  ARM: config: append hip04_defconfig
  ARM: config: select ARCH_HISI in hi3xxx_defconfig
  virt: arm: support hip04 gic

Kefeng Wang (2):
  ARM: hisi: enable erratum 798181 of A15 on HiP04
  ARM: dts: Add PMU support in HiP04

 Documentation/devicetree/bindings/arm/gic.txt      |   1 +
 .../bindings/arm/hisilicon/hisilicon.txt           |  19 ++
 .../devicetree/bindings/clock/hip04-clock.txt      |  20 ++
 arch/arm/Kconfig                                   |  22 +-
 arch/arm/Kconfig.debug                             |  10 +
 arch/arm/Makefile                                  |   2 +-
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/hip04-d01.dts                    |  39 +++
 arch/arm/boot/dts/hip04.dtsi                       | 260 +++++++++++++++
 arch/arm/configs/hi3xxx_defconfig                  |   2 +
 arch/arm/configs/hip04_defconfig                   |  75 +++++
 arch/arm/configs/multi_v7_lpae_defconfig           | 349 +++++++++++++++++++++
 arch/arm/include/asm/mcpm.h                        |   5 +
 arch/arm/kvm/interrupts_head.S                     |  32 +-
 arch/arm/mach-hisi/Kconfig                         |  27 +-
 arch/arm/mach-hisi/Makefile                        |   1 +
 arch/arm/mach-hisi/core.h                          |   2 +
 arch/arm/mach-hisi/hisilicon.c                     |  12 +
 arch/arm/mach-hisi/platmcpm.c                      | 314 ++++++++++++++++++
 arch/arm/mm/Kconfig                                |   2 +-
 drivers/irqchip/irq-gic.c                          | 162 ++++++++--
 include/kvm/arm_vgic.h                             |   5 +-
 include/linux/irqchip/arm-gic.h                    |   8 +
 virt/kvm/arm/vgic.c                                |  47 ++-
 24 files changed, 1357 insertions(+), 60 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hip04-clock.txt
 create mode 100644 arch/arm/boot/dts/hip04-d01.dts
 create mode 100644 arch/arm/boot/dts/hip04.dtsi
 create mode 100644 arch/arm/configs/hip04_defconfig
 create mode 100644 arch/arm/configs/multi_v7_lpae_defconfig
 create mode 100644 arch/arm/mach-hisi/platmcpm.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 01/14] ARM: debug: add HiP04 debug uart
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config Haojian Zhuang
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Add the support of Hisilicon HiP04 debug uart.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig.debug | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 4a2fc0b..5a311af 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -223,6 +223,14 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on HI3716 UART.
 
+	config DEBUG_HIP04_UART
+		bool "Hisilicon HiP04 Debug UART"
+		depends on ARCH_HIP04
+		select DEBUG_UART_8250
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on HIP04 UART.
+
 	config DEBUG_HIGHBANK_UART
 		bool "Kernel low-level debugging messages via Highbank UART"
 		depends on ARCH_HIGHBANK
@@ -1044,6 +1052,7 @@ config DEBUG_UART_PHYS
 	default 0xd4017000 if DEBUG_MMP_UART2
 	default 0xd4018000 if DEBUG_MMP_UART3
 	default 0xe0000000 if ARCH_SPEAR13XX
+	default 0xe4007000 if DEBUG_HIP04_UART
 	default 0xf0000be0 if ARCH_EBSA110
 	default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
 	default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
@@ -1076,6 +1085,7 @@ config DEBUG_UART_VIRT
 	default 0xf4090000 if ARCH_LPC32XX
 	default 0xf4200000 if ARCH_GEMINI
 	default 0xf7fc9000 if DEBUG_BERLIN_UART
+	default 0xf8007000 if DEBUG_HIP04_UART
 	default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9
 	default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1
 	default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 01/14] ARM: debug: add HiP04 debug uart Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 16:46   ` Olof Johansson
  2014-05-07 14:44 ` [PATCH v5 03/14] ARM: config: append lpae configuration Haojian Zhuang
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Since CONFIG_ARM_LPAE could be set in ARM V7, add new two configurations
CONFIG_ARCH_MULTI_V7_NONLPAE & CONFIG_ARCH_MULTI_V7_LPAE.

If we want to enable CONFIG_ARM_LPAE configuration, we should enable
CONFIG_ARCH_MULTI_V7 & disable both CONFIG_ARCH_MULTI_V6 and
CONFIG_ARCH_MULTI_V7_NONLPAE.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig    | 13 ++++++++++++-
 arch/arm/mm/Kconfig |  2 +-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ab438cb..0e52a2c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -918,12 +918,23 @@ config ARCH_MULTI_V6
 	select CPU_V6K
 
 config ARCH_MULTI_V7
-	bool "ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)"
+	bool "ARMv7 based platforms"
 	default y
 	select ARCH_MULTI_V6_V7
 	select CPU_V7
 	select HAVE_SMP
 
+config ARCH_MULTI_V7_NONLPAE
+	bool "ARMv7 non-LPAE based platforms (Cortex-A5/A8/A9, PJ4, PJ4B, Scorpion)"
+	depends on ARCH_MULTI_V7
+	default y
+
+config ARCH_MULTI_V7_LPAE
+	bool "ARMv7 LPAE based platforms (Cortex-A7/A12/A15/A17, Brahma-B15, PJ4B-MP, Krait)"
+	depends on ARCH_MULTI_V7
+	default y
+	select ARM_LPAE if !(ARCH_MULTI_V6 || ARCH_MULTI_V7_NONLPAE)
+
 config ARCH_MULTI_V6_V7
 	bool
 	select MIGHT_HAVE_CACHE_L2X0
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index f5ad9ee..1c1576c 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -615,7 +615,7 @@ comment "Processor Features"
 config ARM_LPAE
 	bool "Support for the Large Physical Address Extension"
 	depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
-		!CPU_32v4 && !CPU_32v3
+		!CPU_32v4 && !CPU_32v3 && !ARCH_MULTI_V7_NONLPAE
 	help
 	  Say Y if you have an ARMv7 processor supporting the LPAE page
 	  table format and you would like to access memory beyond the
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 03/14] ARM: config: append lpae configuration
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 01/14] ARM: debug: add HiP04 debug uart Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 04/14] irq: gic: use mask field in GICC_IAR Haojian Zhuang
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Append multi_v7_lpae_config. In this default configuration,
CONFIG_ARCH_MULTI_V7_NONLPAE & CONFIG_ARCH_MULTI_V6 won't be selected.

CONFIG_ARM_LPAE configuration will be selected by default.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/configs/multi_v7_lpae_defconfig | 349 +++++++++++++++++++++++++++++++
 1 file changed, 349 insertions(+)
 create mode 100644 arch/arm/configs/multi_v7_lpae_defconfig

diff --git a/arch/arm/configs/multi_v7_lpae_defconfig b/arch/arm/configs/multi_v7_lpae_defconfig
new file mode 100644
index 0000000..fb03bad
--- /dev/null
+++ b/arch/arm/configs/multi_v7_lpae_defconfig
@@ -0,0 +1,349 @@
+CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+# CONFIG_ARCH_MULTI_V7_NONLPAE is not set
+CONFIG_ARCH_MULTI_V7_LPAE=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_375=y
+CONFIG_MACH_ARMADA_38X=y
+CONFIG_MACH_ARMADA_XP=y
+CONFIG_MACH_DOVE=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_5301X=y
+CONFIG_ARCH_BCM_MOBILE=y
+CONFIG_ARCH_BERLIN=y
+CONFIG_MACH_BERLIN_BG2=y
+CONFIG_MACH_BERLIN_BG2CD=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_KEYSTONE=y
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_VF610=y
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+CONFIG_SOC_OMAP5=y
+CONFIG_SOC_AM33XX=y
+CONFIG_SOC_DRA7XX=y
+CONFIG_SOC_AM43XX=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_ARCH_MSM8960=y
+CONFIG_ARCH_MSM8974=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_PLAT_SPEAR=y
+CONFIG_ARCH_SPEAR13XX=y
+CONFIG_MACH_SPEAR1310=y
+CONFIG_MACH_SPEAR1340=y
+CONFIG_ARCH_STI=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SIRF=y
+CONFIG_ARCH_TEGRA=y
+CONFIG_ARCH_TEGRA_2x_SOC=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_ARCH_TEGRA_114_SOC=y
+CONFIG_ARCH_TEGRA_124_SOC=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+CONFIG_ARCH_U8500=y
+CONFIG_MACH_HREFV60=y
+CONFIG_MACH_SNOWBALL=y
+CONFIG_MACH_UX500_DT=y
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CA9X4=y
+CONFIG_ARCH_VIRT=y
+CONFIG_ARCH_WM8850=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_NEON=y
+CONFIG_TRUSTED_FOUNDATIONS=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_PCI_TEGRA=y
+CONFIG_SMP=y
+CONFIG_HIGHPTE=y
+CONFIG_CMA=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_KEXEC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_ICS932S401=y
+CONFIG_APDS9802ALS=y
+CONFIG_ISL29003=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_HIGHBANK=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_SUN4I_EMAC=y
+CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MVNETA=y
+CONFIG_KS8851=y
+CONFIG_R8169=y
+CONFIG_SMSC911X=y
+CONFIG_STMMAC_ETH=y
+CONFIG_TI_CPSW=y
+CONFIG_AT803X_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_BRCMFMAC=m
+CONFIG_RT2X00=m
+CONFIG_RT2800USB=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_TEGRA=y
+CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_CROS_EC=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_SIRFSOC=y
+CONFIG_SERIAL_SIRFSOC_CONSOLE=y
+CONFIG_SERIAL_TEGRA=y
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_VT8500=y
+CONFIG_SERIAL_VT8500_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_I2C_SIRF=y
+CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_ORION=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SIRF=y
+CONFIG_SPI_TEGRA114=y
+CONFIG_SPI_TEGRA20_SFLASH=y
+CONFIG_SPI_TEGRA20_SLINK=y
+CONFIG_PINCTRL_AS3722=y
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_TPS6586X=y
+CONFIG_GPIO_TPS65910=y
+CONFIG_BATTERY_SBS=y
+CONFIG_CHARGER_TPS65090=y
+CONFIG_POWER_RESET_AS3722=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_SENSORS_LM90=y
+CONFIG_THERMAL=y
+CONFIG_DOVE_THERMAL=y
+CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_MFD_AS3722=y
+CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_MFD_MAX8907=y
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_TPS65090=y
+CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_AB8500=y
+CONFIG_REGULATOR_AS3722=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8907=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_TPS51632=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_REGULATOR_TPS6586X=y
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_VEXPRESS=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_GSPCA=y
+CONFIG_DRM=y
+CONFIG_DRM_TEGRA=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_WM8505=y
+CONFIG_FB_SIMPLE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_RT5640=y
+CONFIG_SND_SOC_TEGRA_WM8753=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_SND_SOC_TEGRA_ALC5632=y
+CONFIG_SND_SOC_TEGRA_MAX98090=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_AB8500_USB=y
+CONFIG_OMAP_USB3=y
+CONFIG_SAMSUNG_USB2PHY=y
+CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ISP1301=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_MMC_SDHCI_DOVE=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_HIGHBANK_MC=y
+CONFIG_EDAC_HIGHBANK_L2=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AS3722=y
+CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_PALMAS=y
+CONFIG_RTC_DRV_TWL4030=y
+CONFIG_RTC_DRV_TPS6586X=y
+CONFIG_RTC_DRV_TPS65910=y
+CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_RTC_DRV_VT8500=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_RTC_DRV_TEGRA=y
+CONFIG_DMADEVICES=y
+CONFIG_DW_DMAC=y
+CONFIG_MV_XOR=y
+CONFIG_TEGRA20_APB_DMA=y
+CONFIG_STE_DMA40=y
+CONFIG_SIRF_DMA=y
+CONFIG_TI_EDMA=y
+CONFIG_PL330_DMA=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+CONFIG_MXS_DMA=y
+CONFIG_DMA_OMAP=y
+CONFIG_STAGING=y
+CONFIG_SENSORS_ISL29018=y
+CONFIG_SENSORS_ISL29028=y
+CONFIG_MFD_NVEC=y
+CONFIG_KEYBOARD_NVEC=y
+CONFIG_SERIO_NVEC_PS2=y
+CONFIG_NVEC_POWER=y
+CONFIG_COMMON_CLK_QCOM=y
+CONFIG_MSM_GCC_8660=y
+CONFIG_MSM_MMCC_8960=y
+CONFIG_MSM_MMCC_8974=y
+CONFIG_TEGRA_IOMMU_GART=y
+CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_AK8975=y
+CONFIG_PWM=y
+CONFIG_PWM_TEGRA=y
+CONFIG_PWM_VT8500=y
+CONFIG_OMAP_USB2=y
+CONFIG_EXT4_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_CRYPTO_DEV_TEGRA_AES=y
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 04/14] irq: gic: use mask field in GICC_IAR
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (2 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 03/14] ARM: config: append lpae configuration Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 05/14] irq: gic: support hip04 gic Haojian Zhuang
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Bit[9:0] is interrupt ID field in GICC_IAR. Bit[12:10] is CPU ID field,
and others are reserved.

So we should use GICC_IAR_INT_ID_MASK to get interrupt ID. It's not a good way
to use ~0x1c00 (CPU ID field) to get interrupt ID.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/irqchip/irq-gic.c       | 2 +-
 include/linux/irqchip/arm-gic.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 4300b66..f711fb6 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -287,7 +287,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 
 	do {
 		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
-		irqnr = irqstat & ~0x1c00;
+		irqnr = irqstat & GICC_IAR_INT_ID_MASK;
 
 		if (likely(irqnr > 15 && irqnr < 1021)) {
 			irqnr = irq_find_mapping(gic->domain, irqnr);
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 7ed92d0..45e2d8c 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -21,6 +21,8 @@
 #define GIC_CPU_ACTIVEPRIO		0xd0
 #define GIC_CPU_IDENT			0xfc
 
+#define GICC_IAR_INT_ID_MASK		0x3ff
+
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
 #define GIC_DIST_IGROUP			0x080
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 05/14] irq: gic: support hip04 gic
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (3 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 04/14] irq: gic: use mask field in GICC_IAR Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 06/14] ARM: mcpm: support 4 clusters Haojian Zhuang
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

There's a little difference between ARM GIC and HiP04 GIC.

* HiP04 GIC could support 16 cores at most, and ARM GIC could support
8 cores at most. So the difination on GIC_DIST_TARGET registers are
different since CPU interfaces are increased from 8-bit to 16-bit.

* HiP04 GIC could support 510 interrupts at most, and ARM GIC could
support 1020 interrupts at most.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 Documentation/devicetree/bindings/arm/gic.txt |   1 +
 drivers/irqchip/irq-gic.c                     | 160 ++++++++++++++++++++------
 2 files changed, 129 insertions(+), 32 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 5573c08..150f7d6 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -16,6 +16,7 @@ Main node required properties:
 	"arm,cortex-a9-gic"
 	"arm,cortex-a7-gic"
 	"arm,arm11mp-gic"
+	"hisilicon,hip04-gic"
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
   interrupt source.  The type shall be a <u32> and the value shall be 3.
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index f711fb6..d1d1430 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -68,6 +68,7 @@ struct gic_chip_data {
 #ifdef CONFIG_GIC_NON_BANKED
 	void __iomem *(*get_base)(union gic_base *);
 #endif
+	u32 nr_cpu_if;
 };
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -76,9 +77,11 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
  * The GIC mapping of CPU interfaces does not necessarily match
  * the logical CPU numbering.  Let's use a mapping as returned
  * by the GIC itself.
+ *
+ * Hisilicon HiP04 extends the number of CPU interface from 8 to 16.
  */
-#define NR_GIC_CPU_IF 8
-static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
+#define NR_GIC_CPU_IF	16
+static u16 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
 
 /*
  * Supported arch specific GIC irq extension.
@@ -241,20 +244,64 @@ static int gic_retrigger(struct irq_data *d)
 	return 0;
 }
 
+static inline bool gic_is_standard(struct gic_chip_data *gic)
+{
+	return (gic->nr_cpu_if == 8);
+}
+
+static inline int gic_irqs_per_target_reg(struct gic_chip_data *gic)
+{
+	return 32 / gic->nr_cpu_if;
+}
+
 #ifdef CONFIG_SMP
+static inline u32 irq_to_target_reg(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+	unsigned int i = gic_irq(d);
+
+	if (gic_is_standard(gic_data))
+		i = i & ~3U;
+	else
+		i = (i << 1) & ~3U;
+	return (i + GIC_DIST_TARGET);
+}
+
+static inline u32 irq_to_core_shift(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+	unsigned int i = gic_irq(d);
+
+	if (gic_is_standard(gic_data))
+		return ((i % 4) << 3);
+	return ((i % 2) << 4);
+}
+
+static inline u32 irq_to_core_mask(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+	u32 mask;
+	/* ARM GIC, nr_cpu_if == 8; HiP04 GIC, nr_cpu_if == 16 */
+	mask = (1 << gic_data->nr_cpu_if) - 1;
+	return (mask << irq_to_core_shift(d));
+}
+
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
-	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (gic_irq(d) % 4) * 8;
+	void __iomem *reg;
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+	unsigned int shift = irq_to_core_shift(d);
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
-	if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
+	if (cpu >= gic_data->nr_cpu_if || cpu >= nr_cpu_ids)
 		return -EINVAL;
 
+	reg = gic_dist_base(d) + irq_to_target_reg(d);
+
 	raw_spin_lock(&irq_controller_lock);
-	mask = 0xff << shift;
+	mask = irq_to_core_mask(d);
 	bit = gic_cpu_map[cpu] << shift;
 	val = readl_relaxed(reg) & ~mask;
 	writel_relaxed(val | bit, reg);
@@ -354,15 +401,24 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static u8 gic_get_cpumask(struct gic_chip_data *gic)
+static u16 gic_get_cpumask(struct gic_chip_data *gic)
 {
 	void __iomem *base = gic_data_dist_base(gic);
 	u32 mask, i;
 
-	for (i = mask = 0; i < 32; i += 4) {
-		mask = readl_relaxed(base + GIC_DIST_TARGET + i);
-		mask |= mask >> 16;
-		mask |= mask >> 8;
+	/*
+	 * ARM GIC uses 8 registers for interrupt 0-31,
+	 * HiP04 GIC uses 16 registers for interrupt 0-31.
+	 */
+	for (i = mask = 0; i < 32; i += gic_irqs_per_target_reg(gic)) {
+		if (gic_is_standard(gic)) {
+			mask = readl_relaxed(base + GIC_DIST_TARGET + i);
+			mask |= mask >> 16;
+			mask |= mask >> 8;
+		} else {			/* HiP04 GIC */
+			mask = readl_relaxed(base + GIC_DIST_TARGET + i * 2);
+			mask |= mask >> 16;
+		}
 		if (mask)
 			break;
 	}
@@ -370,6 +426,10 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
 	if (!mask)
 		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
 
+	/* ARM GIC needs 8-bit cpu mask, HiP04 GIC needs 16-bit cpu mask. */
+	if (gic_is_standard(gic))
+		mask &= 0xff;
+
 	return mask;
 }
 
@@ -392,10 +452,17 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
 	 * Set all global interrupts to this CPU only.
 	 */
 	cpumask = gic_get_cpumask(gic);
-	cpumask |= cpumask << 8;
+	if (gic_is_standard(gic))
+		cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
-	for (i = 32; i < gic_irqs; i += 4)
-		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+	for (i = 32; i < gic_irqs; i += gic_irqs_per_target_reg(gic)) {
+		if (gic_is_standard(gic))
+			writel_relaxed(cpumask,
+				       base + GIC_DIST_TARGET + i / 4 * 4);
+		else
+			writel_relaxed(cpumask,
+				       base + GIC_DIST_TARGET + i / 2 * 4);
+	}
 
 	/*
 	 * Set priority on all global interrupts.
@@ -423,7 +490,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
 	/*
 	 * Get what the GIC says our CPU mask is.
 	 */
-	BUG_ON(cpu >= NR_GIC_CPU_IF);
+	BUG_ON(cpu >= gic->nr_cpu_if);
 	cpu_mask = gic_get_cpumask(gic);
 	gic_cpu_map[cpu] = cpu_mask;
 
@@ -431,7 +498,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
 	 * Clear our mask from the other map entries in case they're
 	 * still undefined.
 	 */
-	for (i = 0; i < NR_GIC_CPU_IF; i++)
+	for (i = 0; i < gic->nr_cpu_if; i++)
 		if (i != cpu)
 			gic_cpu_map[i] &= ~cpu_mask;
 
@@ -467,7 +534,7 @@ void gic_cpu_if_down(void)
  */
 static void gic_dist_save(unsigned int gic_nr)
 {
-	unsigned int gic_irqs;
+	unsigned int gic_irqs, nr_irq_per_target;
 	void __iomem *dist_base;
 	int i;
 
@@ -476,6 +543,7 @@ static void gic_dist_save(unsigned int gic_nr)
 
 	gic_irqs = gic_data[gic_nr].gic_irqs;
 	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+	nr_irq_per_target = gic_irqs_per_target_reg(&gic_data[gic_nr]);
 
 	if (!dist_base)
 		return;
@@ -484,7 +552,7 @@ static void gic_dist_save(unsigned int gic_nr)
 		gic_data[gic_nr].saved_spi_conf[i] =
 			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
 
-	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, nr_irq_per_target); i++)
 		gic_data[gic_nr].saved_spi_target[i] =
 			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
 
@@ -502,7 +570,7 @@ static void gic_dist_save(unsigned int gic_nr)
  */
 static void gic_dist_restore(unsigned int gic_nr)
 {
-	unsigned int gic_irqs;
+	unsigned int gic_irqs, nr_irq_per_target;
 	unsigned int i;
 	void __iomem *dist_base;
 
@@ -511,6 +579,7 @@ static void gic_dist_restore(unsigned int gic_nr)
 
 	gic_irqs = gic_data[gic_nr].gic_irqs;
 	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+	nr_irq_per_target = gic_irqs_per_target_reg(&gic_data[gic_nr]);
 
 	if (!dist_base)
 		return;
@@ -525,7 +594,7 @@ static void gic_dist_restore(unsigned int gic_nr)
 		writel_relaxed(0xa0a0a0a0,
 			dist_base + GIC_DIST_PRI + i * 4);
 
-	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+	for (i = 0; i < DIV_ROUND_UP(gic_irqs, nr_irq_per_target); i++)
 		writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
 			dist_base + GIC_DIST_TARGET + i * 4);
 
@@ -665,9 +734,19 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	 */
 	dmb(ishst);
 
-	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-
+	/*
+	 * CPUTargetList -- bit[23:16] in GIC_DIST_SOFTINT in ARM GIC.
+	 *                  bit[23:8] in GIC_DIST_SOFTINT in HiP04 GIC.
+	 * NSATT -- bit[15] in GIC_DIST_SOFTINT in ARM GIC.
+	 *          bit[7] in GIC_DIST_SOFTINT in HiP04 GIC.
+	 * this always happens on GIC0
+	 */
+	if (gic_is_standard(&gic_data[0]))
+		map = map << 16;
+	else
+		map = map << 8;
+	writel_relaxed(map | irq,
+		       gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 #endif
@@ -681,10 +760,15 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
  */
 void gic_send_sgi(unsigned int cpu_id, unsigned int irq)
 {
-	BUG_ON(cpu_id >= NR_GIC_CPU_IF);
+	BUG_ON(cpu_id >= gic_data[0].nr_cpu_if);
 	cpu_id = 1 << cpu_id;
 	/* this always happens on GIC0 */
-	writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+	if (gic_is_standard(&gic_data[0]))
+		cpu_id = cpu_id << 16;
+	else
+		cpu_id = cpu_id << 8;
+	writel_relaxed(cpu_id | irq,
+		       gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 }
 
 /*
@@ -700,7 +784,7 @@ int gic_get_cpu_id(unsigned int cpu)
 {
 	unsigned int cpu_bit;
 
-	if (cpu >= NR_GIC_CPU_IF)
+	if (cpu >= gic_data[0].nr_cpu_if)
 		return -1;
 	cpu_bit = gic_cpu_map[cpu];
 	if (cpu_bit & (cpu_bit - 1))
@@ -931,7 +1015,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
 	int gic_irqs, irq_base, i;
-	int nr_routable_irqs;
+	int nr_routable_irqs, max_nr_irq;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
@@ -967,12 +1051,22 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		gic_set_base_accessor(gic, gic_get_common_base);
 	}
 
+	if (of_device_is_compatible(node, "hisilicon,hip04-gic")) {
+		/* HiP04 GIC supports 16 CPUs at most */
+		gic->nr_cpu_if = 16;
+		max_nr_irq = 510;
+	} else {
+		/* ARM/Qualcomm GIC supports 8 CPUs at most */
+		gic->nr_cpu_if = 8;
+		max_nr_irq = 1020;
+	}
+
 	/*
 	 * Initialize the CPU interface map to all CPUs.
 	 * It will be refined as each CPU probes its ID.
 	 */
-	for (i = 0; i < NR_GIC_CPU_IF; i++)
-		gic_cpu_map[i] = 0xff;
+	for (i = 0; i < gic->nr_cpu_if; i++)
+		gic_cpu_map[i] = (1 << gic->nr_cpu_if) - 1;
 
 	/*
 	 * For primary GICs, skip over SGIs.
@@ -988,12 +1082,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 
 	/*
 	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
+	 * The ARM/Qualcomm GIC only supports up to 1020 interrupt sources.
+	 * The HiP04 GIC only supports up to 510 interrupt sources.
 	 */
 	gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
 	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
+	if (gic_irqs > max_nr_irq)
+		gic_irqs = max_nr_irq;
 	gic->gic_irqs = gic_irqs;
 
 	gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */
@@ -1069,6 +1164,7 @@ gic_of_init(struct device_node *node, struct device_node *parent)
 }
 IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
 IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
+IRQCHIP_DECLARE(hip04_gic, "hisilicon,hip04-gic", gic_of_init);
 IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 06/14] ARM: mcpm: support 4 clusters
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (4 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 05/14] irq: gic: support hip04 gic Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 16:48   ` Olof Johansson
  2014-05-07 16:59   ` Nicolas Pitre
  2014-05-07 14:44 ` [PATCH v5 07/14] ARM: hisi: add ARCH_HISI Haojian Zhuang
                   ` (7 subsequent siblings)
  13 siblings, 2 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
from 2 to 4.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig            | 9 +++++++++
 arch/arm/include/asm/mcpm.h | 5 +++++
 2 files changed, 14 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0e52a2c..624829f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1575,6 +1575,15 @@ config MCPM
 	  for (multi-)cluster based systems, such as big.LITTLE based
 	  systems.
 
+config MCPM_QUAD_CLUSTER
+	bool "Enable Quad clusters in MCPM"
+	depends on MCPM
+	help
+	  To avoid wasting resources unnecessarily, MCPM only supports up
+	  to 2 clusters by default.
+	  Platforms with 3 or 4 clusters that use MCPM must select this
+	  option to allow the additional clusters to be managed.
+
 config BIG_LITTLE
 	bool "big.LITTLE support (Experimental)"
 	depends on CPU_V7 && SMP
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index 608516e..fc8d70d 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -20,7 +20,12 @@
  * to consider dynamic allocation.
  */
 #define MAX_CPUS_PER_CLUSTER	4
+
+#ifdef CONFIG_MCPM_QUAD_CLUSTER
+#define MAX_NR_CLUSTERS		4
+#else
 #define MAX_NR_CLUSTERS		2
+#endif
 
 #ifndef __ASSEMBLY__
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 07/14] ARM: hisi: add ARCH_HISI
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (5 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 06/14] ARM: mcpm: support 4 clusters Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 08/14] ARM: hisi: add hip04 SoC support Haojian Zhuang
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Since multiple ARCH configuration will be appended into mach-hisi
directory, add ARCH_HISI as common configuration for different ARCH in
mach-hisi.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Makefile          |  2 +-
 arch/arm/mach-hisi/Kconfig | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 41c1931..4c2798a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -154,7 +154,7 @@ machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_GEMINI)		+= gemini
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
-machine-$(CONFIG_ARCH_HI3xxx)		+= hisi
+machine-$(CONFIG_ARCH_HISI)		+= hisi
 machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
 machine-$(CONFIG_ARCH_IOP32X)		+= iop32x
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index feee4db..da16efd 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -1,8 +1,16 @@
-config ARCH_HI3xxx
-	bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
+config ARCH_HISI
+	bool "Hisilicon SoC Support"
+	depends on ARCH_MULTIPLATFORM
 	select ARM_AMBA
 	select ARM_GIC
 	select ARM_TIMER_SP804
+
+if ARCH_HISI
+
+menu "Hisilicon platform type"
+
+config ARCH_HI3xxx
+	bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
 	select CACHE_L2X0
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
@@ -10,3 +18,7 @@ config ARCH_HI3xxx
 	select PINCTRL_SINGLE
 	help
 	  Support for Hisilicon Hi36xx/Hi37xx processor family
+
+endmenu
+
+endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (6 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 07/14] ARM: hisi: add ARCH_HISI Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 16:50   ` Olof Johansson
  2014-05-07 17:44   ` Nicolas Pitre
  2014-05-07 14:44 ` [PATCH v5 09/14] ARM: dts: append hip04 dts Haojian Zhuang
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hisilicon Hi3xxx is based on Cortex A9 Core. Now HiP04 SoC is based on
Cortex A15 Core. Since multiple clusters is used in HiP04 SoC, it could
be based on MCPM.

And HiP04 supports LPAE to support large memory.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |  19 ++
 .../devicetree/bindings/clock/hip04-clock.txt      |  20 ++
 arch/arm/mach-hisi/Kconfig                         |  10 +-
 arch/arm/mach-hisi/Makefile                        |   1 +
 arch/arm/mach-hisi/core.h                          |   2 +
 arch/arm/mach-hisi/hisilicon.c                     |  12 +
 arch/arm/mach-hisi/platmcpm.c                      | 314 +++++++++++++++++++++
 7 files changed, 377 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/hip04-clock.txt
 create mode 100644 arch/arm/mach-hisi/platmcpm.c

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index df0a452..20736b0 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -4,6 +4,10 @@ Hisilicon Platforms Device Tree Bindings
 Hi4511 Board
 Required root node properties:
 	- compatible = "hisilicon,hi3620-hi4511";
+HiP04 D01 Board
+Required root node properties:
+	- compatible = "hisilicon,hip04-d01";
+
 
 Hisilicon system controller
 
@@ -19,6 +23,13 @@ Optional properties:
 		If reg value is not zero, cpun exit wfi and go
 - resume-offset : offset in sysctrl for notifying cpu0 when resume
 - reboot-offset : offset in sysctrl for system reboot
+- relocation-entry : relocation address of secondary cpu boot code
+- relocation-size : relocation size of secondary cpu boot code
+- bootwrapper-phys : physical address of boot wrapper
+- bootwrapper-size : size of boot wrapper
+- bootwrapper-magic : magic number for secondary cpu in boot wrapper
+The memory area of [bootwrapper-phys : bootwrapper-phys+bootwrapper-size]
+should be reserved. This should be set in /memreserve/ node in DTS file.
 
 Example:
 
@@ -31,6 +42,7 @@ Example:
 		reboot-offset = <0x4>;
 	};
 
+
 PCTRL: Peripheral misc control register
 
 Required Properties:
@@ -44,3 +56,10 @@ Example:
 		compatible = "hisilicon,pctrl";
 		reg = <0xfca09000 0x1000>;
 	};
+
+
+Fabric:
+
+Required Properties:
+- compatible: "hisilicon,hip04-fabric";
+- reg: Address and size of Fabric
diff --git a/Documentation/devicetree/bindings/clock/hip04-clock.txt b/Documentation/devicetree/bindings/clock/hip04-clock.txt
new file mode 100644
index 0000000..4d31ae3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hip04-clock.txt
@@ -0,0 +1,20 @@
+* Hisilicon HiP04 Clock Controller
+
+The HiP04 clock controller generates and supplies clock to various
+controllers within the HiP04 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "hisilicon,hip04-clock" - controller compatible with HiP04 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hip04-clock.h>.
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index da16efd..17af1d2 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -17,7 +17,15 @@ config ARCH_HI3xxx
 	select PINCTRL
 	select PINCTRL_SINGLE
 	help
-	  Support for Hisilicon Hi36xx/Hi37xx processor family
+	  Support for Hisilicon Hi36xx/Hi37xx SoC family
+
+config ARCH_HIP04
+	bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7_LPAE
+	select HAVE_ARM_ARCH_TIMER
+	select MCPM if SMP
+	select MCPM_QUAD_CLUSTER if SMP
+	help
+	  Support for Hisilicon HiP04 SoC family
 
 endmenu
 
diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile
index 2ae1b59..e7a8640 100644
--- a/arch/arm/mach-hisi/Makefile
+++ b/arch/arm/mach-hisi/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-y	+= hisilicon.o
+obj-$(CONFIG_MCPM)		+= platmcpm.o
 obj-$(CONFIG_SMP)		+= platsmp.o hotplug.o
diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index af23ec2..1e60795 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -12,4 +12,6 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
 extern int hi3xxx_cpu_kill(unsigned int cpu);
 extern void hi3xxx_set_cpu(int cpu, bool enable);
 
+extern bool __init hip04_smp_init_ops(void);
+
 #endif
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index 741faf3..6489e57 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -88,3 +88,15 @@ DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
 	.smp		= smp_ops(hi3xxx_smp_ops),
 	.restart	= hi3xxx_restart,
 MACHINE_END
+
+#ifdef CONFIG_ARCH_HIP04
+static const char *hip04_compat[] __initconst = {
+	"hisilicon,hip04-d01",
+	NULL,
+};
+
+DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)")
+	.dt_compat	= hip04_compat,
+	.smp_init	= smp_init_ops(hip04_smp_init_ops),
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
new file mode 100644
index 0000000..e0d7afd
--- /dev/null
+++ b/arch/arm/mach-hisi/platmcpm.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2013-2014 Linaro Ltd.
+ * Copyright (c) 2013-2014 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+#include <linux/of_address.h>
+
+#include <asm/cputype.h>
+#include <asm/cp15.h>
+#include <asm/mcpm.h>
+
+#include "core.h"
+
+/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x]
+ * 1 -- unreset; 0 -- reset
+ */
+#define CORE_RESET_BIT(x)		(1 << x)
+#define NEON_RESET_BIT(x)		(1 << (x + 4))
+#define CORE_DEBUG_RESET_BIT(x)		(1 << (x + 9))
+#define CLUSTER_L2_RESET_BIT		(1 << 8)
+#define CLUSTER_DEBUG_RESET_BIT		(1 << 13)
+
+/*
+ * bits definition in SC_CPU_RESET_STATUS[x]
+ * 1 -- reset status; 0 -- unreset status
+ */
+#define CORE_RESET_STATUS(x)		(1 << x)
+#define NEON_RESET_STATUS(x)		(1 << (x + 4))
+#define CORE_DEBUG_RESET_STATUS(x)	(1 << (x + 9))
+#define CLUSTER_L2_RESET_STATUS		(1 << 8)
+#define CLUSTER_DEBUG_RESET_STATUS	(1 << 13)
+#define CORE_WFI_STATUS(x)		(1 << (x + 16))
+#define CORE_WFE_STATUS(x)		(1 << (x + 20))
+#define CORE_DEBUG_ACK(x)		(1 << (x + 24))
+
+#define SC_CPU_RESET_REQ(x)		(0x520 + (x << 3))	/* reset */
+#define SC_CPU_RESET_DREQ(x)		(0x524 + (x << 3))	/* unreset */
+#define SC_CPU_RESET_STATUS(x)		(0x1520 + (x << 3))
+
+#define FAB_SF_MODE			0x0c
+#define FAB_SF_INVLD			0x10
+
+/* bits definition in FB_SF_INVLD */
+#define FB_SF_INVLD_START		(1 << 8)
+
+#define HIP04_MAX_CLUSTERS		4
+#define HIP04_MAX_CPUS_PER_CLUSTER	4
+
+#define POLL_MSEC	10
+#define TIMEOUT_MSEC	1000
+
+struct hip04_secondary_cpu_data {
+	u32	bootwrapper_phys;
+	u32	bootwrapper_size;
+	u32	bootwrapper_magic;
+	u32	relocation_entry;
+	u32	relocation_size;
+};
+
+static void __iomem *relocation, *sysctrl, *fabric;
+static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER];
+static DEFINE_SPINLOCK(boot_lock);
+static struct hip04_secondary_cpu_data hip04_boot;
+
+static bool hip04_cluster_down(unsigned int cluster)
+{
+	int i;
+
+	for (i = 0; i < HIP04_MAX_CPUS_PER_CLUSTER; i++)
+		if (hip04_cpu_table[cluster][i])
+			return false;
+	return true;
+}
+
+static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
+{
+	unsigned long data;
+
+	if (!fabric)
+		return;
+	data = readl_relaxed(fabric + FAB_SF_MODE);
+	if (on)
+		data |= 1 << cluster;
+	else
+		data &= ~(1 << cluster);
+	writel_relaxed(data, fabric + FAB_SF_MODE);
+	while (1) {
+		if (data == readl_relaxed(fabric + FAB_SF_MODE))
+			break;
+	}
+}
+
+static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
+{
+	unsigned long data, mask;
+
+	if (!relocation || !sysctrl)
+		return -ENODEV;
+	if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
+		return -EINVAL;
+
+	spin_lock_irq(&boot_lock);
+	writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
+	writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
+	writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
+	writel_relaxed(0, relocation + 12);
+
+	if (hip04_cluster_down(cluster)) {
+		data = CLUSTER_DEBUG_RESET_BIT;
+		writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+		do {
+			mask = CLUSTER_DEBUG_RESET_STATUS;
+			data = readl_relaxed(sysctrl + \
+					     SC_CPU_RESET_STATUS(cluster));
+		} while (data & mask);
+		hip04_set_snoop_filter(cluster, 1);
+	}
+
+	hip04_cpu_table[cluster][cpu]++;
+
+	data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
+	       CORE_DEBUG_RESET_BIT(cpu);
+	writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+	spin_unlock_irq(&boot_lock);
+	msleep(POLL_MSEC);
+
+	return 0;
+}
+
+static void hip04_mcpm_power_down(void)
+{
+	unsigned int mpidr, cpu, cluster;
+	bool skip_wfi = false;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	__mcpm_cpu_going_down(cpu, cluster);
+
+	spin_lock(&boot_lock);
+	BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
+	hip04_cpu_table[cluster][cpu]--;
+	if (hip04_cpu_table[cluster][cpu] == 1) {
+		/* A power_up request went ahead of us. */
+		skip_wfi = true;
+	} else if (hip04_cpu_table[cluster][cpu] > 1) {
+		pr_err("Cluster %d CPU%d is still running\n", cluster, cpu);
+		BUG();
+	}
+
+	spin_unlock(&boot_lock);
+
+	v7_exit_coherency_flush(louis);
+
+	__mcpm_cpu_down(cpu, cluster);
+
+	isb();
+	dsb();
+
+	if (!skip_wfi)
+		wfi();
+}
+
+static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
+{
+	unsigned int data, tries;
+
+	BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
+	       cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
+
+	for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
+		data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
+		if (!(data & CORE_WFI_STATUS(cpu))) {
+			msleep(POLL_MSEC);
+			continue;
+		}
+		data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
+		       CORE_DEBUG_RESET_BIT(cpu);
+		writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
+		return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void hip04_mcpm_powered_up(void)
+{
+	if (!relocation)
+		return;
+	spin_lock(&boot_lock);
+	writel_relaxed(0, relocation);
+	writel_relaxed(0, relocation + 4);
+	writel_relaxed(0, relocation + 8);
+	writel_relaxed(0, relocation + 12);
+	spin_unlock(&boot_lock);
+}
+
+static const struct mcpm_platform_ops hip04_mcpm_ops = {
+	.power_up		= hip04_mcpm_power_up,
+	.power_down		= hip04_mcpm_power_down,
+	.wait_for_powerdown	= hip04_mcpm_wait_for_powerdown,
+	.powered_up		= hip04_mcpm_powered_up,
+};
+
+static bool __init hip04_cpu_table_init(void)
+{
+	unsigned int mpidr, cpu, cluster;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	if (cluster >= HIP04_MAX_CLUSTERS ||
+	    cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
+		pr_err("%s: boot CPU is out of bound!\n", __func__);
+		return false;
+	}
+	hip04_set_snoop_filter(cluster, 1);
+	hip04_cpu_table[cluster][cpu] = 1;
+	return true;
+}
+
+static int __init hip04_mcpm_init(void)
+{
+	struct device_node *np, *np_fab;
+	int ret = -ENODEV;
+
+	np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
+	if (!np)
+		goto err;
+	np_fab = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-fabric");
+	if (!np_fab)
+		goto err;
+
+	if (of_property_read_u32(np, "bootwrapper-phys",
+				 &hip04_boot.bootwrapper_phys)) {
+		pr_err("failed to get bootwrapper-phys\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	if (of_property_read_u32(np, "bootwrapper-size",
+				 &hip04_boot.bootwrapper_size)) {
+		pr_err("failed to get bootwrapper-size\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	if (of_property_read_u32(np, "bootwrapper-magic",
+				 &hip04_boot.bootwrapper_magic)) {
+		pr_err("failed to get bootwrapper-magic\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	if (of_property_read_u32(np, "relocation-entry",
+				 &hip04_boot.relocation_entry)) {
+		pr_err("failed to get relocation-entry\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	if (of_property_read_u32(np, "relocation-size",
+				 &hip04_boot.relocation_size)) {
+		pr_err("failed to get relocation-size\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	relocation = ioremap(hip04_boot.relocation_entry,
+			     hip04_boot.relocation_size);
+	if (!relocation) {
+		pr_err("failed to map relocation space\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	sysctrl = of_iomap(np, 0);
+	if (!sysctrl) {
+		pr_err("failed to get sysctrl base\n");
+		ret = -ENOMEM;
+		goto err_sysctrl;
+	}
+	fabric = of_iomap(np_fab, 0);
+	if (!fabric) {
+		pr_err("failed to get fabric base\n");
+		ret = -ENOMEM;
+		goto err_fabric;
+	}
+
+	if (!hip04_cpu_table_init())
+		return -EINVAL;
+	ret = mcpm_platform_register(&hip04_mcpm_ops);
+	if (!ret) {
+		mcpm_sync_init(NULL);
+		pr_info("HiP04 MCPM initialized\n");
+	}
+	return ret;
+err_fabric:
+	iounmap(sysctrl);
+err_sysctrl:
+	iounmap(relocation);
+err:
+	return ret;
+}
+early_initcall(hip04_mcpm_init);
+
+bool __init hip04_smp_init_ops(void)
+{
+	mcpm_smp_set_ops();
+	return true;
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 09/14] ARM: dts: append hip04 dts
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (7 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 08/14] ARM: hisi: add hip04 SoC support Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 10/14] ARM: config: append hip04_defconfig Haojian Zhuang
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Add hip04-d01.dts & hip04.dtsi for hip04 SoC platform.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/Makefile      |   1 +
 arch/arm/boot/dts/hip04-d01.dts |  39 +++++++
 arch/arm/boot/dts/hip04.dtsi    | 240 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+)
 create mode 100644 arch/arm/boot/dts/hip04-d01.dts
 create mode 100644 arch/arm/boot/dts/hip04.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f..7119bca 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -80,6 +80,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
 	ecx-2000.dtb
+dtb-$(CONFIG_ARCH_HIP04) += hip04-d01.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
 	integratorcp.dtb
 dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \
diff --git a/arch/arm/boot/dts/hip04-d01.dts b/arch/arm/boot/dts/hip04-d01.dts
new file mode 100644
index 0000000..661c8e5
--- /dev/null
+++ b/arch/arm/boot/dts/hip04-d01.dts
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (C) 2013-2014 Linaro Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+/* For bootwrapper */
+/memreserve/ 0x10c00000 0x00010000;
+
+#include "hip04.dtsi"
+
+/ {
+	/* memory bus is 64-bit */
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "Hisilicon D01 Development Board";
+	compatible = "hisilicon,hip04-d01";
+
+	memory at 00000000,10000000 {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000 0x00000000 0xc0000000>;
+	};
+
+	memory at 00000004,c0000000 {
+		device_type = "memory";
+		reg = <0x00000004 0xc0000000 0x00000003 0x40000000>;
+	};
+
+	soc {
+		uart0: uart at 4007000 {
+			status = "ok";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi
new file mode 100644
index 0000000..55a39ed
--- /dev/null
+++ b/arch/arm/boot/dts/hip04.dtsi
@@ -0,0 +1,240 @@
+/*
+ * Hisilicon Ltd. HiP01 SoC
+ *
+ * Copyright (C) 2013-2014 Hisilicon Ltd.
+ * Copyright (C) 2013-2014 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/hip04-clock.h>
+
+/ {
+	/* memory bus is 64-bit */
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+			cluster1 {
+				core0 {
+					cpu = <&CPU4>;
+				};
+				core1 {
+					cpu = <&CPU5>;
+				};
+				core2 {
+					cpu = <&CPU6>;
+				};
+				core3 {
+					cpu = <&CPU7>;
+				};
+			};
+			cluster2 {
+				core0 {
+					cpu = <&CPU8>;
+				};
+				core1 {
+					cpu = <&CPU9>;
+				};
+				core2 {
+					cpu = <&CPU10>;
+				};
+				core3 {
+					cpu = <&CPU11>;
+				};
+			};
+			cluster3 {
+				core0 {
+					cpu = <&CPU12>;
+				};
+				core1 {
+					cpu = <&CPU13>;
+				};
+				core2 {
+					cpu = <&CPU14>;
+				};
+				core3 {
+					cpu = <&CPU15>;
+				};
+			};
+		};
+		CPU0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+		};
+		CPU1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+		};
+		CPU2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+		};
+		CPU3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+		};
+		CPU4: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x100>;
+		};
+		CPU5: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x101>;
+		};
+		CPU6: cpu at 102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x102>;
+		};
+		CPU7: cpu at 103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x103>;
+		};
+		CPU8: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x200>;
+		};
+		CPU9: cpu at 201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x201>;
+		};
+		CPU10: cpu at 202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x202>;
+		};
+		CPU11: cpu at 203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x203>;
+		};
+		CPU12: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x300>;
+		};
+		CPU13: cpu at 301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x301>;
+		};
+		CPU14: cpu at 302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x302>;
+		};
+		CPU15: cpu at 303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x303>;
+		};
+	};
+
+	clock: clock {
+		compatible = "hisilicon,hip04-clock";
+		/* dummy register.
+		 * Don't need to access clock registers since they're
+		 * configured in firmware already.
+		 */
+		reg = <0 0 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+	};
+
+	soc {
+		/* It's a 32-bit SoC. */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges = <0 0 0xe0000000 0x10000000>;
+
+		gic: interrupt-controller at c01000 {
+			compatible = "hisilicon,hip04-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			interrupts = <1 9 0xf04>;
+
+			reg = <0xc01000 0x1000>, <0xc02000 0x1000>,
+			      <0xc04000 0x2000>, <0xc06000 0x2000>;
+		};
+
+		sysctrl: sysctrl {
+			compatible = "hisilicon,sysctrl";
+			reg = <0x3e00000 0x00100000>;
+			relocation-entry = <0xe0000100>;
+			relocation-size = <0x1000>;
+			bootwrapper-phys = <0x10c00000>;
+			bootwrapper-size = <0x10000>;
+			bootwrapper-magic = <0xa5a5a5a5>;
+		};
+
+		fabric: fabric {
+			compatible = "hisilicon,hip04-fabric";
+			reg = <0x302a000 0x1000>;
+		};
+
+		dual_timer0: dual_timer at 3000000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x3000000 0x1000>;
+			interrupts = <0 224 4>;
+			clocks = <&clock HIP04_CLK_50M>;
+			clock-names = "apb_pclk";
+		};
+
+		uart0: uart at 4007000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x4007000 0x1000>;
+			interrupts = <0 381 4>;
+			clocks = <&clock HIP04_CLK_168M>;
+			clock-names = "uartclk";
+			reg-shift = <2>;
+			status = "disabled";
+		};
+	};
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 10/14] ARM: config: append hip04_defconfig
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (8 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 09/14] ARM: dts: append hip04 dts Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 16:52   ` Olof Johansson
  2014-05-07 14:44 ` [PATCH v5 11/14] ARM: config: select ARCH_HISI in hi3xxx_defconfig Haojian Zhuang
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Select HiP04 SoC configuration by hip04_defconfig.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/configs/hip04_defconfig | 75 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 arch/arm/configs/hip04_defconfig

diff --git a/arch/arm/configs/hip04_defconfig b/arch/arm/configs/hip04_defconfig
new file mode 100644
index 0000000..96073b5
--- /dev/null
+++ b/arch/arm/configs/hip04_defconfig
@@ -0,0 +1,75 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_GZIP=y
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+# CONFIG_ARCH_MULTI_V7_NONLPAE is not set
+CONFIG_ARCH_MULTI_V7_LPAE=y
+CONFIG_ARCH_HISI=y
+CONFIG_ARCH_HIP04=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_MCPM=y
+CONFIG_MCPM_QUAD_CLUSTER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_HIGHMEM=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_DRM=y
+CONFIG_FB_SIMPLE=y
+CONFIG_RTC_CLASS=y
+CONFIG_EXT4_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_UART_8250=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEBUG_USER=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
+CONFIG_KVM_ARM_HOST=y
+CONFIG_KVM_ARM_MAX_VCPUS=4
+CONFIG_KVM_ARM_VGIC=y
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 11/14] ARM: config: select ARCH_HISI in hi3xxx_defconfig
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (9 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 10/14] ARM: config: append hip04_defconfig Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 12/14] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Since ARCH_HISI is added as common configuration of both ARCH_HI3xxx and
ARCH_HIP04, update it into hi3xxx_defconfig.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/configs/hi3xxx_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/hi3xxx_defconfig b/arch/arm/configs/hi3xxx_defconfig
index f186bdf..553e1b6 100644
--- a/arch/arm/configs/hi3xxx_defconfig
+++ b/arch/arm/configs/hi3xxx_defconfig
@@ -3,10 +3,12 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
+CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_NET=y
 CONFIG_UNIX=y
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 12/14] ARM: hisi: enable erratum 798181 of A15 on HiP04
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (10 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 11/14] ARM: config: select ARCH_HISI in hi3xxx_defconfig Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04 Haojian Zhuang
  2014-05-07 14:44 ` [PATCH v5 14/14] virt: arm: support hip04 gic Haojian Zhuang
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kefeng Wang <kefeng.wang@linaro.org>

The commit 93dc688 (ARM: 7684/1: errata: Workaround for Cortex-A15
erratum 798181 (TLBI/DSB operations)) introduced a workaround for
Cortex-A15 erratum 798181. Enable it for HIP04(Cortex-a15 r3p2).

Signed-off-by: Kefeng Wang <kefeng.wang@linaro.org>
Singed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/mach-hisi/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 17af1d2..5c0602d 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -21,6 +21,7 @@ config ARCH_HI3xxx
 
 config ARCH_HIP04
 	bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7_LPAE
+	select ARM_ERRATA_798181 if SMP
 	select HAVE_ARM_ARCH_TIMER
 	select MCPM if SMP
 	select MCPM_QUAD_CLUSTER if SMP
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (11 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 12/14] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  2014-05-07 16:53   ` Olof Johansson
  2014-05-07 14:44 ` [PATCH v5 14/14] virt: arm: support hip04 gic Haojian Zhuang
  13 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kefeng Wang <kefeng.wang@linaro.org>

ARM Performance Monitor Units are available on the HiP04.
So add the support in the dtsi.

Simply tested with perf.

Signed-off-by: Kefeng Wang <kefeng.wang@linaro.org>
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/boot/dts/hip04.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi
index 55a39ed..eee69e5 100644
--- a/arch/arm/boot/dts/hip04.dtsi
+++ b/arch/arm/boot/dts/hip04.dtsi
@@ -227,6 +227,26 @@
 			clock-names = "apb_pclk";
 		};
 
+		arm-pmu {
+			compatible = "arm,cortex-a15-pmu";
+			interrupts = <0 64 4>,
+				     <0 65 4>,
+				     <0 66 4>,
+				     <0 67 4>,
+				     <0 68 4>,
+				     <0 69 4>,
+				     <0 70 4>,
+				     <0 71 4>,
+				     <0 72 4>,
+				     <0 73 4>,
+				     <0 74 4>,
+				     <0 75 4>,
+				     <0 76 4>,
+				     <0 77 4>,
+				     <0 78 4>,
+				     <0 79 4>;
+		};
+
 		uart0: uart at 4007000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x4007000 0x1000>;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 14/14] virt: arm: support hip04 gic
  2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
                   ` (12 preceding siblings ...)
  2014-05-07 14:44 ` [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04 Haojian Zhuang
@ 2014-05-07 14:44 ` Haojian Zhuang
  13 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

In ARM standard GIC, GICH_APR offset is 0xf0 & GICH_LR0 offset is 0x100.
In HiP04 GIC, GICH_APR offset is 0x70 & GICH_LR0 offset is 0x80.

Now reuse the nr_lr field in struct vgic_cpu. Bit[31:16] is used to store
GICH_APR offset in HiP04, and bit[15:0] is used to store real nr_lr
variable. In ARM standard GIC, don't set bit[31:16]. So we could avoid
to change the VGIC implementation in arm64.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/kvm/interrupts_head.S  | 32 ++++++++++++++++++++++------
 include/kvm/arm_vgic.h          |  5 ++++-
 include/linux/irqchip/arm-gic.h |  6 ++++++
 virt/kvm/arm/vgic.c             | 47 +++++++++++++++++++++++++++++------------
 4 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index 76af9302..7aacaff 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -419,7 +419,10 @@ vcpu	.req	r0		@ vcpu pointer always in r0
 	ldr	r7, [r2, #GICH_EISR1]
 	ldr	r8, [r2, #GICH_ELRSR0]
 	ldr	r9, [r2, #GICH_ELRSR1]
-	ldr	r10, [r2, #GICH_APR]
+	ldr	r10, [r11, #VGIC_CPU_NR_LR]
+	movs	r10, r10, lsr #HWCFG_APR_SHIFT
+	ldrne	r10, [r2, r10]
+	ldreq	r10, [r2, #GICH_APR]
 
 	str	r3, [r11, #VGIC_CPU_HCR]
 	str	r4, [r11, #VGIC_CPU_VMCR]
@@ -435,9 +438,16 @@ vcpu	.req	r0		@ vcpu pointer always in r0
 	str	r5, [r2, #GICH_HCR]
 
 	/* Save list registers */
-	add	r2, r2, #GICH_LR0
-	add	r3, r11, #VGIC_CPU_LR
 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
+	addeq	r2, r2, #GICH_LR0
+	movne	r10, r4, lsr #HWCFG_APR_SHIFT
+	/* the offset between GICH_APR & GICH_LR0 is 0x10 */
+	addne	r10, r10, #0x10
+	addne	r2, r2, r10
+	add	r3, r11, #VGIC_CPU_LR
+	/* Get NR_LR from VGIC_CPU_NR_LR */
+	ldr	r6, =HWCFG_NR_LR_MASK
+	and	r4, r4, r6
 1:	ldr	r6, [r2], #4
 	str	r6, [r3], #4
 	subs	r4, r4, #1
@@ -469,12 +479,22 @@ vcpu	.req	r0		@ vcpu pointer always in r0
 
 	str	r3, [r2, #GICH_HCR]
 	str	r4, [r2, #GICH_VMCR]
-	str	r8, [r2, #GICH_APR]
+	ldr	r6, [r11, #VGIC_CPU_NR_LR]
+	movs	r6, r6, lsr #HWCFG_APR_SHIFT
+	strne	r8, [r2, r6]
+	streq	r8, [r2, #GICH_APR]
 
 	/* Restore list registers */
-	add	r2, r2, #GICH_LR0
-	add	r3, r11, #VGIC_CPU_LR
 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
+	addeq	r2, r2, #GICH_LR0
+	movne	r6, r4, lsr #HWCFG_APR_SHIFT
+	/* the offset between GICH_APR & GICH_LR0 is 0x10 */
+	addne	r6, r6, #0x10
+	addne	r2, r2, r6
+	/* Get NR_LR from VGIC_CPU_NR_LR */
+	add	r3, r11, #VGIC_CPU_LR
+	ldr	r6, =HWCFG_NR_LR_MASK
+	and	r4, r4, r6
 1:	ldr	r6, [r3], #4
 	str	r6, [r2], #4
 	subs	r4, r4, #1
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f27000f..089de25 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -122,7 +122,10 @@ struct vgic_cpu {
 	/* Bitmap of used/free list registers */
 	DECLARE_BITMAP(	lr_used, VGIC_MAX_LRS);
 
-	/* Number of list registers on this CPU */
+	/*
+	 * bit[31:16]: GICH_APR offset
+	 * bit[15:0]:  Number of list registers on this CPU
+	 */
 	int		nr_lr;
 
 	/* CPU vif control registers for world switch */
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 45e2d8c..5530388 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -49,6 +49,8 @@
 #define GICH_ELRSR1 			0x34
 #define GICH_APR			0xf0
 #define GICH_LR0			0x100
+#define HIP04_GICH_APR			0x70
+/* GICH_LR0 offset in HiP04 is 0x80 */
 
 #define GICH_HCR_EN			(1 << 0)
 #define GICH_HCR_UIE			(1 << 1)
@@ -73,6 +75,10 @@
 #define GICH_MISR_EOI			(1 << 0)
 #define GICH_MISR_U			(1 << 1)
 
+#define HWCFG_NR_LR_MASK	0xffff
+#define HWCFG_APR_MASK		0xffff
+#define HWCFG_APR_SHIFT		16
+
 #ifndef __ASSEMBLY__
 
 struct device_node;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 47b2983..e635b9b 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -97,7 +97,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu);
 static void vgic_update_state(struct kvm *kvm);
 static void vgic_kick_vcpus(struct kvm *kvm);
 static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg);
-static u32 vgic_nr_lr;
+static u32 vgic_hw_cfg;
 
 static unsigned int vgic_maint_irq;
 
@@ -624,9 +624,9 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	int vcpu_id = vcpu->vcpu_id;
 	int i, irq, source_cpu;
-	u32 *lr;
+	u32 *lr, nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
 
-	for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+	for_each_set_bit(i, vgic_cpu->lr_used, nr_lr) {
 		lr = &vgic_cpu->vgic_lr[i];
 		irq = LR_IRQID(*lr);
 		source_cpu = LR_CPUID(*lr);
@@ -1005,8 +1005,9 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
 {
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	int lr;
+	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
 
-	for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+	for_each_set_bit(lr, vgic_cpu->lr_used, nr_lr) {
 		int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
 
 		if (!vgic_irq_is_enabled(vcpu, irq)) {
@@ -1025,6 +1026,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 {
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	int lr;
+	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
 
 	/* Sanitize the input... */
 	BUG_ON(sgi_source_id & ~7);
@@ -1046,9 +1048,8 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 	}
 
 	/* Try to use another LR for this interrupt */
-	lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used,
-			       vgic_cpu->nr_lr);
-	if (lr >= vgic_cpu->nr_lr)
+	lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used, nr_lr);
+	if (lr >= nr_lr)
 		return false;
 
 	kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id);
@@ -1181,9 +1182,10 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 		 * active bit.
 		 */
 		int lr, irq;
+		int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
 
 		for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr,
-				 vgic_cpu->nr_lr) {
+				 nr_lr) {
 			irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
 
 			vgic_irq_clear_active(vcpu, irq);
@@ -1221,13 +1223,13 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	int lr, pending;
+	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
 	bool level_pending;
 
 	level_pending = vgic_process_maintenance(vcpu);
 
 	/* Clear mappings for empty LRs */
-	for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr,
-			 vgic_cpu->nr_lr) {
+	for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr, nr_lr) {
 		int irq;
 
 		if (!test_and_clear_bit(lr, vgic_cpu->lr_used))
@@ -1241,8 +1243,8 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 
 	/* Check if we still have something up our sleeve... */
 	pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_elrsr,
-				      vgic_cpu->nr_lr);
-	if (level_pending || pending < vgic_cpu->nr_lr)
+				      nr_lr);
+	if (level_pending || pending < nr_lr)
 		set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu);
 }
 
@@ -1438,7 +1440,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
 	 */
 	vgic_cpu->vgic_vmcr = 0;
 
-	vgic_cpu->nr_lr = vgic_nr_lr;
+	vgic_cpu->nr_lr = vgic_hw_cfg;
 	vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */
 
 	return 0;
@@ -1470,17 +1472,33 @@ static struct notifier_block vgic_cpu_nb = {
 	.notifier_call = vgic_cpu_notify,
 };
 
+static const struct of_device_id of_vgic_ids[] = {
+	{
+		.compatible = "arm,cortex-a15-gic",
+	}, {
+		.compatible = "hisilicon,hip04-gic",
+		.data = (void *)HIP04_GICH_APR,
+	}, {
+	},
+};
+
 int kvm_vgic_hyp_init(void)
 {
 	int ret;
 	struct resource vctrl_res;
 	struct resource vcpu_res;
+	const struct of_device_id *match;
+	u32 vgic_nr_lr;
 
-	vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
+	vgic_node = of_find_matching_node_and_match(NULL, of_vgic_ids, &match);
 	if (!vgic_node) {
 		kvm_err("error: no compatible vgic node in DT\n");
 		return -ENODEV;
 	}
+	/* If it's standard ARM GIC, high word in vgic_hw_cfg is 0.
+	 * Otherwise, it's the offset of non-standard GICH_APR (in HiP04).
+	 */
+	vgic_hw_cfg = (unsigned int)match->data << HWCFG_APR_SHIFT;
 
 	vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0);
 	if (!vgic_maint_irq) {
@@ -1517,6 +1535,7 @@ int kvm_vgic_hyp_init(void)
 
 	vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR);
 	vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1;
+	vgic_hw_cfg |= vgic_nr_lr;
 
 	ret = create_hyp_io_mappings(vgic_vctrl_base,
 				     vgic_vctrl_base + resource_size(&vctrl_res),
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config
  2014-05-07 14:44 ` [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config Haojian Zhuang
@ 2014-05-07 16:46   ` Olof Johansson
  2014-05-07 22:33     ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 16:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 07, 2014 at 10:44:36PM +0800, Haojian Zhuang wrote:
> Since CONFIG_ARM_LPAE could be set in ARM V7, add new two configurations
> CONFIG_ARCH_MULTI_V7_NONLPAE & CONFIG_ARCH_MULTI_V7_LPAE.
> 
> If we want to enable CONFIG_ARM_LPAE configuration, we should enable
> CONFIG_ARCH_MULTI_V7 & disable both CONFIG_ARCH_MULTI_V6 and
> CONFIG_ARCH_MULTI_V7_NONLPAE.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

I don't like this. Platforms should just depend on CONFIG_ARCH_MULTI_V7 &&
LPAE (or && !LPAE) instead.

Platforms that _can_ boot without LPAE should not require it, even if
they boot with less available memory.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 06/14] ARM: mcpm: support 4 clusters
  2014-05-07 14:44 ` [PATCH v5 06/14] ARM: mcpm: support 4 clusters Haojian Zhuang
@ 2014-05-07 16:48   ` Olof Johansson
  2014-05-07 18:00     ` Nicolas Pitre
  2014-05-07 16:59   ` Nicolas Pitre
  1 sibling, 1 reply; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 07, 2014 at 10:44:40PM +0800, Haojian Zhuang wrote:
> Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
> from 2 to 4.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  arch/arm/Kconfig            | 9 +++++++++
>  arch/arm/include/asm/mcpm.h | 5 +++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 0e52a2c..624829f 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1575,6 +1575,15 @@ config MCPM
>  	  for (multi-)cluster based systems, such as big.LITTLE based
>  	  systems.
>  
> +config MCPM_QUAD_CLUSTER
> +	bool "Enable Quad clusters in MCPM"
> +	depends on MCPM
> +	help
> +	  To avoid wasting resources unnecessarily, MCPM only supports up
> +	  to 2 clusters by default.
> +	  Platforms with 3 or 4 clusters that use MCPM must select this
> +	  option to allow the additional clusters to be managed.
> +

Why don't you add an integer config instead, i.e. MCPM_MAX_CLUSTERS, and let
that set MAX_NR_CLUSTERS?


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-07 14:44 ` [PATCH v5 08/14] ARM: hisi: add hip04 SoC support Haojian Zhuang
@ 2014-05-07 16:50   ` Olof Johansson
  2014-05-07 17:44   ` Nicolas Pitre
  1 sibling, 0 replies; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 16:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 07, 2014 at 10:44:42PM +0800, Haojian Zhuang wrote:
> Hisilicon Hi3xxx is based on Cortex A9 Core. Now HiP04 SoC is based on
> Cortex A15 Core. Since multiple clusters is used in HiP04 SoC, it could
> be based on MCPM.
> 
> And HiP04 supports LPAE to support large memory.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           |  19 ++
>  .../devicetree/bindings/clock/hip04-clock.txt      |  20 ++
>  arch/arm/mach-hisi/Kconfig                         |  10 +-
>  arch/arm/mach-hisi/Makefile                        |   1 +
>  arch/arm/mach-hisi/core.h                          |   2 +
>  arch/arm/mach-hisi/hisilicon.c                     |  12 +
>  arch/arm/mach-hisi/platmcpm.c                      | 314 +++++++++++++++++++++
>  7 files changed, 377 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hip04-clock.txt
>  create mode 100644 arch/arm/mach-hisi/platmcpm.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index df0a452..20736b0 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -4,6 +4,10 @@ Hisilicon Platforms Device Tree Bindings
>  Hi4511 Board
>  Required root node properties:
>  	- compatible = "hisilicon,hi3620-hi4511";
> +HiP04 D01 Board
> +Required root node properties:
> +	- compatible = "hisilicon,hip04-d01";
> +
>  
>  Hisilicon system controller
>  
> @@ -19,6 +23,13 @@ Optional properties:
>  		If reg value is not zero, cpun exit wfi and go
>  - resume-offset : offset in sysctrl for notifying cpu0 when resume
>  - reboot-offset : offset in sysctrl for system reboot
> +- relocation-entry : relocation address of secondary cpu boot code
> +- relocation-size : relocation size of secondary cpu boot code
> +- bootwrapper-phys : physical address of boot wrapper
> +- bootwrapper-size : size of boot wrapper
> +- bootwrapper-magic : magic number for secondary cpu in boot wrapper
> +The memory area of [bootwrapper-phys : bootwrapper-phys+bootwrapper-size]
> +should be reserved. This should be set in /memreserve/ node in DTS file.

This binding spec should be split up in separate files, it's hard to tell
from the patch what part of the binding this is appending to. Please do
that in a preceding patch, and then add new contents on top.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 10/14] ARM: config: append hip04_defconfig
  2014-05-07 14:44 ` [PATCH v5 10/14] ARM: config: append hip04_defconfig Haojian Zhuang
@ 2014-05-07 16:52   ` Olof Johansson
  2014-05-09  6:35     ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 07, 2014 at 10:44:44PM +0800, Haojian Zhuang wrote:
> Select HiP04 SoC configuration by hip04_defconfig.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

We're letting each vendor have one defconfig. This should coexist and/or add to
the hi3xxx defconfig instead of creating a new one.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04
  2014-05-07 14:44 ` [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04 Haojian Zhuang
@ 2014-05-07 16:53   ` Olof Johansson
  2014-05-09  6:36     ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 07, 2014 at 10:44:47PM +0800, Haojian Zhuang wrote:
> From: Kefeng Wang <kefeng.wang@linaro.org>
> 
> ARM Performance Monitor Units are available on the HiP04.
> So add the support in the dtsi.
> 
> Simply tested with perf.
> 
> Signed-off-by: Kefeng Wang <kefeng.wang@linaro.org>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

This should be squashed into the original dts introduction patch, no need
to add these separately.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 06/14] ARM: mcpm: support 4 clusters
  2014-05-07 14:44 ` [PATCH v5 06/14] ARM: mcpm: support 4 clusters Haojian Zhuang
  2014-05-07 16:48   ` Olof Johansson
@ 2014-05-07 16:59   ` Nicolas Pitre
  1 sibling, 0 replies; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-07 16:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 7 May 2014, Haojian Zhuang wrote:

> Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
> from 2 to 4.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  arch/arm/Kconfig            | 9 +++++++++
>  arch/arm/include/asm/mcpm.h | 5 +++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 0e52a2c..624829f 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1575,6 +1575,15 @@ config MCPM
>  	  for (multi-)cluster based systems, such as big.LITTLE based
>  	  systems.
>  
> +config MCPM_QUAD_CLUSTER
> +	bool "Enable Quad clusters in MCPM"

Please remove the prompt string, keeping only the bool alone.  This 
config option shouldn't be visible to users.  After that you may add:

Reviewed-by: Nicolas Pitre <nico@linaro.org>


> +	depends on MCPM
> +	help
> +	  To avoid wasting resources unnecessarily, MCPM only supports up
> +	  to 2 clusters by default.
> +	  Platforms with 3 or 4 clusters that use MCPM must select this
> +	  option to allow the additional clusters to be managed.
> +
>  config BIG_LITTLE
>  	bool "big.LITTLE support (Experimental)"
>  	depends on CPU_V7 && SMP
> diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
> index 608516e..fc8d70d 100644
> --- a/arch/arm/include/asm/mcpm.h
> +++ b/arch/arm/include/asm/mcpm.h
> @@ -20,7 +20,12 @@
>   * to consider dynamic allocation.
>   */
>  #define MAX_CPUS_PER_CLUSTER	4
> +
> +#ifdef CONFIG_MCPM_QUAD_CLUSTER
> +#define MAX_NR_CLUSTERS		4
> +#else
>  #define MAX_NR_CLUSTERS		2
> +#endif
>  
>  #ifndef __ASSEMBLY__
>  
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-07 14:44 ` [PATCH v5 08/14] ARM: hisi: add hip04 SoC support Haojian Zhuang
  2014-05-07 16:50   ` Olof Johansson
@ 2014-05-07 17:44   ` Nicolas Pitre
       [not found]     ` <CAD6h2NQU0NR1PO=x6pz62B4QWqkPz7F+Fp65YeQJ62vumF8_Aw@mail.gmail.com>
  1 sibling, 1 reply; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-07 17:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 7 May 2014, Haojian Zhuang wrote:

> Hisilicon Hi3xxx is based on Cortex A9 Core. Now HiP04 SoC is based on
> Cortex A15 Core. Since multiple clusters is used in HiP04 SoC, it could
> be based on MCPM.
> 
> And HiP04 supports LPAE to support large memory.

This makes for a large patch with multiple things mixed together (DT 
bindings, MCPM backend, etc.)  That might help reviewing if split into 
separate patches.

> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  .../bindings/arm/hisilicon/hisilicon.txt           |  19 ++
>  .../devicetree/bindings/clock/hip04-clock.txt      |  20 ++
>  arch/arm/mach-hisi/Kconfig                         |  10 +-
>  arch/arm/mach-hisi/Makefile                        |   1 +
>  arch/arm/mach-hisi/core.h                          |   2 +
>  arch/arm/mach-hisi/hisilicon.c                     |  12 +
>  arch/arm/mach-hisi/platmcpm.c                      | 314 +++++++++++++++++++++
>  7 files changed, 377 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/hip04-clock.txt
>  create mode 100644 arch/arm/mach-hisi/platmcpm.c

[...]

> diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
> new file mode 100644
> index 0000000..e0d7afd
> --- /dev/null
> +++ b/arch/arm/mach-hisi/platmcpm.c
> @@ -0,0 +1,314 @@
> +/*
> + * Copyright (c) 2013-2014 Linaro Ltd.
> + * Copyright (c) 2013-2014 Hisilicon Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/memblock.h>
> +#include <linux/of_address.h>
> +
> +#include <asm/cputype.h>
> +#include <asm/cp15.h>
> +#include <asm/mcpm.h>
> +
> +#include "core.h"
> +
> +/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x]
> + * 1 -- unreset; 0 -- reset
> + */
> +#define CORE_RESET_BIT(x)		(1 << x)
> +#define NEON_RESET_BIT(x)		(1 << (x + 4))
> +#define CORE_DEBUG_RESET_BIT(x)		(1 << (x + 9))
> +#define CLUSTER_L2_RESET_BIT		(1 << 8)
> +#define CLUSTER_DEBUG_RESET_BIT		(1 << 13)
> +
> +/*
> + * bits definition in SC_CPU_RESET_STATUS[x]
> + * 1 -- reset status; 0 -- unreset status
> + */
> +#define CORE_RESET_STATUS(x)		(1 << x)
> +#define NEON_RESET_STATUS(x)		(1 << (x + 4))
> +#define CORE_DEBUG_RESET_STATUS(x)	(1 << (x + 9))
> +#define CLUSTER_L2_RESET_STATUS		(1 << 8)
> +#define CLUSTER_DEBUG_RESET_STATUS	(1 << 13)
> +#define CORE_WFI_STATUS(x)		(1 << (x + 16))
> +#define CORE_WFE_STATUS(x)		(1 << (x + 20))
> +#define CORE_DEBUG_ACK(x)		(1 << (x + 24))
> +
> +#define SC_CPU_RESET_REQ(x)		(0x520 + (x << 3))	/* reset */
> +#define SC_CPU_RESET_DREQ(x)		(0x524 + (x << 3))	/* unreset */
> +#define SC_CPU_RESET_STATUS(x)		(0x1520 + (x << 3))
> +
> +#define FAB_SF_MODE			0x0c
> +#define FAB_SF_INVLD			0x10
> +
> +/* bits definition in FB_SF_INVLD */
> +#define FB_SF_INVLD_START		(1 << 8)
> +
> +#define HIP04_MAX_CLUSTERS		4
> +#define HIP04_MAX_CPUS_PER_CLUSTER	4
> +
> +#define POLL_MSEC	10
> +#define TIMEOUT_MSEC	1000
> +
> +struct hip04_secondary_cpu_data {
> +	u32	bootwrapper_phys;
> +	u32	bootwrapper_size;
> +	u32	bootwrapper_magic;
> +	u32	relocation_entry;
> +	u32	relocation_size;
> +};
> +
> +static void __iomem *relocation, *sysctrl, *fabric;
> +static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER];
> +static DEFINE_SPINLOCK(boot_lock);
> +static struct hip04_secondary_cpu_data hip04_boot;
> +
> +static bool hip04_cluster_down(unsigned int cluster)
> +{
> +	int i;
> +
> +	for (i = 0; i < HIP04_MAX_CPUS_PER_CLUSTER; i++)
> +		if (hip04_cpu_table[cluster][i])
> +			return false;
> +	return true;
> +}
> +
> +static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
> +{
> +	unsigned long data;
> +
> +	if (!fabric)
> +		return;
> +	data = readl_relaxed(fabric + FAB_SF_MODE);
> +	if (on)
> +		data |= 1 << cluster;
> +	else
> +		data &= ~(1 << cluster);
> +	writel_relaxed(data, fabric + FAB_SF_MODE);
> +	while (1) {
> +		if (data == readl_relaxed(fabric + FAB_SF_MODE))
> +			break;
> +	}
> +}
> +
> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
> +{
> +	unsigned long data, mask;
> +
> +	if (!relocation || !sysctrl)
> +		return -ENODEV;
> +	if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
> +		return -EINVAL;
> +
> +	spin_lock_irq(&boot_lock);
> +	writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
> +	writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
> +	writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
> +	writel_relaxed(0, relocation + 12);
> +
> +	if (hip04_cluster_down(cluster)) {
> +		data = CLUSTER_DEBUG_RESET_BIT;
> +		writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> +		do {
> +			mask = CLUSTER_DEBUG_RESET_STATUS;
> +			data = readl_relaxed(sysctrl + \
> +					     SC_CPU_RESET_STATUS(cluster));
> +		} while (data & mask);
> +		hip04_set_snoop_filter(cluster, 1);
> +	}

Isn't this racy?  What if the new CPU starts executing code before 
snoops are enabled for it?

Normally we solve this race by letting the waking-up CPU turn on its 
snoops by itself from an assembly code callback provided as argument to 
mcpm_sync_init().  This is also the only way to eventually support deep 
C-states with cpuidle.

> +
> +	hip04_cpu_table[cluster][cpu]++;
> +
> +	data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> +	       CORE_DEBUG_RESET_BIT(cpu);
> +	writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> +	spin_unlock_irq(&boot_lock);
> +	msleep(POLL_MSEC);

What is that msleep() for?

> +	return 0;
> +}
> +
> +static void hip04_mcpm_power_down(void)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +	bool skip_wfi = false;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	__mcpm_cpu_going_down(cpu, cluster);
> +
> +	spin_lock(&boot_lock);
> +	BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> +	hip04_cpu_table[cluster][cpu]--;
> +	if (hip04_cpu_table[cluster][cpu] == 1) {
> +		/* A power_up request went ahead of us. */
> +		skip_wfi = true;
> +	} else if (hip04_cpu_table[cluster][cpu] > 1) {
> +		pr_err("Cluster %d CPU%d is still running\n", cluster, cpu);
> +		BUG();
> +	}
> +
> +	spin_unlock(&boot_lock);
> +
> +	v7_exit_coherency_flush(louis);

Don't you have to turn off snoop filters in the case of a complete 
cluster down as well?

> +
> +	__mcpm_cpu_down(cpu, cluster);
> +
> +	isb();
> +	dsb();

Those isb/dsb are redundant here.  They're implicit from 
__mcpm_cpu_down().

> +
> +	if (!skip_wfi)
> +		wfi();
> +}
> +
> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
> +{
> +	unsigned int data, tries;
> +
> +	BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
> +	       cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
> +
> +	for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
> +		data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
> +		if (!(data & CORE_WFI_STATUS(cpu))) {
> +			msleep(POLL_MSEC);
> +			continue;
> +		}
> +		data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> +		       CORE_DEBUG_RESET_BIT(cpu);
> +		writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));

You are not supposed to perform any changes here.  This method is there 
only to wait for given CPU to be down.  It is not guaranteed it will be 
called.  Furthermore this can race with the power_up method.

Normally you should perform this reset business from 
hip04_mcpm_power_down() while the lock is held.  Now... this assumes 
that any power/reset would be effective only when the CPU executes a 
WFI.  Is this the case on this hardware?  If not then we'll have to 
think about a different strategy.

> +		return 0;
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void hip04_mcpm_powered_up(void)
> +{
> +	if (!relocation)
> +		return;
> +	spin_lock(&boot_lock);
> +	writel_relaxed(0, relocation);
> +	writel_relaxed(0, relocation + 4);
> +	writel_relaxed(0, relocation + 8);
> +	writel_relaxed(0, relocation + 12);
> +	spin_unlock(&boot_lock);
> +}
> +
> +static const struct mcpm_platform_ops hip04_mcpm_ops = {
> +	.power_up		= hip04_mcpm_power_up,
> +	.power_down		= hip04_mcpm_power_down,
> +	.wait_for_powerdown	= hip04_mcpm_wait_for_powerdown,
> +	.powered_up		= hip04_mcpm_powered_up,
> +};
> +
> +static bool __init hip04_cpu_table_init(void)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	if (cluster >= HIP04_MAX_CLUSTERS ||
> +	    cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
> +		pr_err("%s: boot CPU is out of bound!\n", __func__);
> +		return false;
> +	}
> +	hip04_set_snoop_filter(cluster, 1);
> +	hip04_cpu_table[cluster][cpu] = 1;
> +	return true;
> +}
> +
> +static int __init hip04_mcpm_init(void)
> +{
> +	struct device_node *np, *np_fab;
> +	int ret = -ENODEV;
> +
> +	np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
> +	if (!np)
> +		goto err;
> +	np_fab = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-fabric");
> +	if (!np_fab)
> +		goto err;
> +
> +	if (of_property_read_u32(np, "bootwrapper-phys",
> +				 &hip04_boot.bootwrapper_phys)) {
> +		pr_err("failed to get bootwrapper-phys\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	if (of_property_read_u32(np, "bootwrapper-size",
> +				 &hip04_boot.bootwrapper_size)) {
> +		pr_err("failed to get bootwrapper-size\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	if (of_property_read_u32(np, "bootwrapper-magic",
> +				 &hip04_boot.bootwrapper_magic)) {
> +		pr_err("failed to get bootwrapper-magic\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	if (of_property_read_u32(np, "relocation-entry",
> +				 &hip04_boot.relocation_entry)) {
> +		pr_err("failed to get relocation-entry\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	if (of_property_read_u32(np, "relocation-size",
> +				 &hip04_boot.relocation_size)) {
> +		pr_err("failed to get relocation-size\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	relocation = ioremap(hip04_boot.relocation_entry,
> +			     hip04_boot.relocation_size);
> +	if (!relocation) {
> +		pr_err("failed to map relocation space\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +	sysctrl = of_iomap(np, 0);
> +	if (!sysctrl) {
> +		pr_err("failed to get sysctrl base\n");
> +		ret = -ENOMEM;
> +		goto err_sysctrl;
> +	}
> +	fabric = of_iomap(np_fab, 0);
> +	if (!fabric) {
> +		pr_err("failed to get fabric base\n");
> +		ret = -ENOMEM;
> +		goto err_fabric;
> +	}
> +
> +	if (!hip04_cpu_table_init())
> +		return -EINVAL;
> +	ret = mcpm_platform_register(&hip04_mcpm_ops);
> +	if (!ret) {
> +		mcpm_sync_init(NULL);
> +		pr_info("HiP04 MCPM initialized\n");
> +	}
> +	return ret;
> +err_fabric:
> +	iounmap(sysctrl);
> +err_sysctrl:
> +	iounmap(relocation);
> +err:
> +	return ret;
> +}
> +early_initcall(hip04_mcpm_init);
> +
> +bool __init hip04_smp_init_ops(void)
> +{
> +	mcpm_smp_set_ops();
> +	return true;
> +}

You should be able to call mcpm_smp_set_ops() directly from 
hip04_mcpm_init(), and only if there was no errors.


Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 06/14] ARM: mcpm: support 4 clusters
  2014-05-07 16:48   ` Olof Johansson
@ 2014-05-07 18:00     ` Nicolas Pitre
  2014-05-07 18:03       ` Olof Johansson
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-07 18:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 7 May 2014, Olof Johansson wrote:

> On Wed, May 07, 2014 at 10:44:40PM +0800, Haojian Zhuang wrote:
> > Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
> > from 2 to 4.
> > 
> > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> > ---
> >  arch/arm/Kconfig            | 9 +++++++++
> >  arch/arm/include/asm/mcpm.h | 5 +++++
> >  2 files changed, 14 insertions(+)
> > 
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 0e52a2c..624829f 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -1575,6 +1575,15 @@ config MCPM
> >  	  for (multi-)cluster based systems, such as big.LITTLE based
> >  	  systems.
> >  
> > +config MCPM_QUAD_CLUSTER
> > +	bool "Enable Quad clusters in MCPM"
> > +	depends on MCPM
> > +	help
> > +	  To avoid wasting resources unnecessarily, MCPM only supports up
> > +	  to 2 clusters by default.
> > +	  Platforms with 3 or 4 clusters that use MCPM must select this
> > +	  option to allow the additional clusters to be managed.
> > +
> 
> Why don't you add an integer config instead, i.e. MCPM_MAX_CLUSTERS, and let
> that set MAX_NR_CLUSTERS?

I requested for this config symbol not to be visible to users (the 
prompt string should be removed) and be selected by those platforms that 
need it instead.  And there is no way to specify an actual value with 
'select'. And that wouldn't work in a multi-platform config where 
different platforms could fight over a different value anyway.

I also prefer to keep some control on the actual number that can be used 
here so not to let people go overboard with it.  If this grows too big 
we'll have to consider some dynamic allocation instead.

See previous discussion here:

http://article.gmane.org/gmane.linux.ports.arm.kernel/315228


Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 06/14] ARM: mcpm: support 4 clusters
  2014-05-07 18:00     ` Nicolas Pitre
@ 2014-05-07 18:03       ` Olof Johansson
  0 siblings, 0 replies; 36+ messages in thread
From: Olof Johansson @ 2014-05-07 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 7, 2014 at 11:00 AM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Wed, 7 May 2014, Olof Johansson wrote:
>
>> On Wed, May 07, 2014 at 10:44:40PM +0800, Haojian Zhuang wrote:
>> > Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
>> > from 2 to 4.
>> >
>> > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> > ---
>> >  arch/arm/Kconfig            | 9 +++++++++
>> >  arch/arm/include/asm/mcpm.h | 5 +++++
>> >  2 files changed, 14 insertions(+)
>> >
>> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>> > index 0e52a2c..624829f 100644
>> > --- a/arch/arm/Kconfig
>> > +++ b/arch/arm/Kconfig
>> > @@ -1575,6 +1575,15 @@ config MCPM
>> >       for (multi-)cluster based systems, such as big.LITTLE based
>> >       systems.
>> >
>> > +config MCPM_QUAD_CLUSTER
>> > +   bool "Enable Quad clusters in MCPM"
>> > +   depends on MCPM
>> > +   help
>> > +     To avoid wasting resources unnecessarily, MCPM only supports up
>> > +     to 2 clusters by default.
>> > +     Platforms with 3 or 4 clusters that use MCPM must select this
>> > +     option to allow the additional clusters to be managed.
>> > +
>>
>> Why don't you add an integer config instead, i.e. MCPM_MAX_CLUSTERS, and let
>> that set MAX_NR_CLUSTERS?
>
> I requested for this config symbol not to be visible to users (the
> prompt string should be removed) and be selected by those platforms that
> need it instead.  And there is no way to specify an actual value with
> 'select'. And that wouldn't work in a multi-platform config where
> different platforms could fight over a different value anyway.
>
> I also prefer to keep some control on the actual number that can be used
> here so not to let people go overboard with it.  If this grows too big
> we'll have to consider some dynamic allocation instead.
>
> See previous discussion here:
>
> http://article.gmane.org/gmane.linux.ports.arm.kernel/315228

Ok, fair enough.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config
  2014-05-07 16:46   ` Olof Johansson
@ 2014-05-07 22:33     ` Haojian Zhuang
  2014-05-20 18:18       ` Olof Johansson
  0 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-07 22:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 8 May 2014 00:46, Olof Johansson <olof@lixom.net> wrote:
> On Wed, May 07, 2014 at 10:44:36PM +0800, Haojian Zhuang wrote:
>> Since CONFIG_ARM_LPAE could be set in ARM V7, add new two configurations
>> CONFIG_ARCH_MULTI_V7_NONLPAE & CONFIG_ARCH_MULTI_V7_LPAE.
>>
>> If we want to enable CONFIG_ARM_LPAE configuration, we should enable
>> CONFIG_ARCH_MULTI_V7 & disable both CONFIG_ARCH_MULTI_V6 and
>> CONFIG_ARCH_MULTI_V7_NONLPAE.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> I don't like this. Platforms should just depend on CONFIG_ARCH_MULTI_V7 &&
> LPAE (or && !LPAE) instead.
>
> Platforms that _can_ boot without LPAE should not require it, even if
> they boot with less available memory.
>
>
> -Olof

Do you mean that I should remove CONFIG_ARCH_MULTI_V7_NONLPAE &
CONFIG_ARCH_MULTI_V7_LPAE & multi_v7_lpae_defconfig?

Regards
Haojian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 10/14] ARM: config: append hip04_defconfig
  2014-05-07 16:52   ` Olof Johansson
@ 2014-05-09  6:35     ` Haojian Zhuang
  0 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-09  6:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 8 May 2014 00:52, Olof Johansson <olof@lixom.net> wrote:
> On Wed, May 07, 2014 at 10:44:44PM +0800, Haojian Zhuang wrote:
>> Select HiP04 SoC configuration by hip04_defconfig.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> We're letting each vendor have one defconfig. This should coexist and/or add to
> the hi3xxx defconfig instead of creating a new one.
>
>
> -Olof

In HiP04, I need to enable 16 CPUs & LPAE.

16 CPU are specified by CONFIG_NR_CPUS. And Hi3xxx SoC don't need LPAE.

Regards
Haojian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04
  2014-05-07 16:53   ` Olof Johansson
@ 2014-05-09  6:36     ` Haojian Zhuang
  0 siblings, 0 replies; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-09  6:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 8 May 2014 00:53, Olof Johansson <olof@lixom.net> wrote:
> On Wed, May 07, 2014 at 10:44:47PM +0800, Haojian Zhuang wrote:
>> From: Kefeng Wang <kefeng.wang@linaro.org>
>>
>> ARM Performance Monitor Units are available on the HiP04.
>> So add the support in the dtsi.
>>
>> Simply tested with perf.
>>
>> Signed-off-by: Kefeng Wang <kefeng.wang@linaro.org>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> This should be squashed into the original dts introduction patch, no need
> to add these separately.
>
>
> -Olof

OK.

Regards
Haojian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
       [not found]     ` <CAD6h2NQU0NR1PO=x6pz62B4QWqkPz7F+Fp65YeQJ62vumF8_Aw@mail.gmail.com>
@ 2014-05-12  0:44       ` Haojian Zhuang
  2014-05-12 19:39         ` Nicolas Pitre
  0 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-12  0:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
>
>
> On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> On Wed, 7 May 2014, Haojian Zhuang wrote:
>>
>>> +
>>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
>>> +{
>>> +     unsigned long data, mask;
>>> +
>>> +     if (!relocation || !sysctrl)
>>> +             return -ENODEV;
>>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
>>> HIP04_MAX_CPUS_PER_CLUSTER)
>>> +             return -EINVAL;
>>> +
>>> +     spin_lock_irq(&boot_lock);
>>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
>>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
>>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
>>> +     writel_relaxed(0, relocation + 12);
>>> +
>>> +     if (hip04_cluster_down(cluster)) {
>>> +             data = CLUSTER_DEBUG_RESET_BIT;
>>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>>> +             do {
>>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
>>> +                     data = readl_relaxed(sysctrl + \
>>> +                                          SC_CPU_RESET_STATUS(cluster));
>>> +             } while (data & mask);
>>> +             hip04_set_snoop_filter(cluster, 1);
>>> +     }
>>
>> Isn't this racy?  What if the new CPU starts executing code before
>> snoops are enabled for it?
>>
>> Normally we solve this race by letting the waking-up CPU turn on its
>> snoops by itself from an assembly code callback provided as argument to
>> mcpm_sync_init().  This is also the only way to eventually support deep
>> C-states with cpuidle.
>>
>
> There's no race. At here, I enable snoop without unreset new CPU.
>
>>> +
>>> +     hip04_cpu_table[cluster][cpu]++;
>>> +
>>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>>> +            CORE_DEBUG_RESET_BIT(cpu);
>>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>
> At here, I make new CPU out of reset state.
>
>
>>> +     spin_unlock_irq(&boot_lock);
>>> +     msleep(POLL_MSEC);
>>
>> What is that msleep() for?
>>
> Without this delay, I'll meet hang.
>
> Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
> IPI at here. If I remove the msleep() here, it seems that IPI caused my
> system hang. So it's a workaround in my system.
>

I'm sorry that it's not hang. It results that new CPU cannot be online.

>>> +     return 0;
>>> +}
>>> +
>>> +static void hip04_mcpm_power_down(void)
>>> +{
>>> +     unsigned int mpidr, cpu, cluster;
>>> +     bool skip_wfi = false;
>>> +
>>> +     mpidr = read_cpuid_mpidr();
>>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>>> +
>>> +     __mcpm_cpu_going_down(cpu, cluster);
>>> +
>>> +     spin_lock(&boot_lock);
>>> +     BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
>>> +     hip04_cpu_table[cluster][cpu]--;
>>> +     if (hip04_cpu_table[cluster][cpu] == 1) {
>>> +             /* A power_up request went ahead of us. */
>>> +             skip_wfi = true;
>>> +     } else if (hip04_cpu_table[cluster][cpu] > 1) {
>>> +             pr_err("Cluster %d CPU%d is still running\n", cluster,
>>> cpu);
>>> +             BUG();
>>> +     }
>>> +
>>> +     spin_unlock(&boot_lock);
>>> +
>>> +     v7_exit_coherency_flush(louis);
>>
>> Don't you have to turn off snoop filters in the case of a complete
>> cluster down as well?
>>
>
> I still have some issue on disabling a whole cluster. So making it
> completely
> will be finished later in additional patch.
>
>
>>> +
>>> +     __mcpm_cpu_down(cpu, cluster);
>>> +
>>> +     isb();
>>> +     dsb();
>>
>> Those isb/dsb are redundant here.  They're implicit from
>> __mcpm_cpu_down().
>>
> OK. I'll remove it.
>
>
>>> +
>>> +     if (!skip_wfi)
>>> +             wfi();
>>> +}
>>> +
>>> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int
>>> cluster)
>>> +{
>>> +     unsigned int data, tries;
>>> +
>>> +     BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
>>> +            cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
>>> +
>>> +     for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
>>> +             data = readl_relaxed(sysctrl +
>>> SC_CPU_RESET_STATUS(cluster));
>>> +             if (!(data & CORE_WFI_STATUS(cpu))) {
>>> +                     msleep(POLL_MSEC);
>>> +                     continue;
>>> +             }
>>> +             data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>>> +                    CORE_DEBUG_RESET_BIT(cpu);
>>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
>>
>> You are not supposed to perform any changes here.  This method is there
>> only to wait for given CPU to be down.  It is not guaranteed it will be
>> called.  Furthermore this can race with the power_up method.
>>
>> Normally you should perform this reset business from
>> hip04_mcpm_power_down() while the lock is held.  Now... this assumes
>> that any power/reset would be effective only when the CPU executes a
>> WFI.  Is this the case on this hardware?  If not then we'll have to
>> think about a different strategy.
>>
> OK. I can move reset operation in hip04_mcpm_power_down().
>
>>> +             return 0;
>>> +     }
>>> +
>>> +     return -ETIMEDOUT;
>>> +}
>>> +
>>> +static void hip04_mcpm_powered_up(void)
>>> +{
>>> +     if (!relocation)
>>> +             return;
>>> +     spin_lock(&boot_lock);
>>> +     writel_relaxed(0, relocation);
>>> +     writel_relaxed(0, relocation + 4);
>>> +     writel_relaxed(0, relocation + 8);
>>> +     writel_relaxed(0, relocation + 12);
>>> +     spin_unlock(&boot_lock);
>>> +}
>>> +
>>> +static const struct mcpm_platform_ops hip04_mcpm_ops = {
>>> +     .power_up               = hip04_mcpm_power_up,
>>> +     .power_down             = hip04_mcpm_power_down,
>>> +     .wait_for_powerdown     = hip04_mcpm_wait_for_powerdown,
>>> +     .powered_up             = hip04_mcpm_powered_up,
>>> +};
>>> +
>>> +static bool __init hip04_cpu_table_init(void)
>>> +{
>>> +     unsigned int mpidr, cpu, cluster;
>>> +
>>> +     mpidr = read_cpuid_mpidr();
>>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>>> +
>>> +     if (cluster >= HIP04_MAX_CLUSTERS ||
>>> +         cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
>>> +             pr_err("%s: boot CPU is out of bound!\n", __func__);
>>> +             return false;
>>> +     }
>>> +     hip04_set_snoop_filter(cluster, 1);
>>> +     hip04_cpu_table[cluster][cpu] = 1;
>>> +     return true;
>>> +}
>>> +
>>> +static int __init hip04_mcpm_init(void)
>>> +{
>>> +     struct device_node *np, *np_fab;
>>> +     int ret = -ENODEV;
>>> +
>>> +     np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
>>> +     if (!np)
>>> +             goto err;
>>> +     np_fab = of_find_compatible_node(NULL, NULL,
>>> "hisilicon,hip04-fabric");
>>> +     if (!np_fab)
>>> +             goto err;
>>> +
>>> +     if (of_property_read_u32(np, "bootwrapper-phys",
>>> +                              &hip04_boot.bootwrapper_phys)) {
>>> +             pr_err("failed to get bootwrapper-phys\n");
>>> +             ret = -EINVAL;
>>> +             goto err;
>>> +     }
>>> +     if (of_property_read_u32(np, "bootwrapper-size",
>>> +                              &hip04_boot.bootwrapper_size)) {
>>> +             pr_err("failed to get bootwrapper-size\n");
>>> +             ret = -EINVAL;
>>> +             goto err;
>>> +     }
>>> +     if (of_property_read_u32(np, "bootwrapper-magic",
>>> +                              &hip04_boot.bootwrapper_magic)) {
>>> +             pr_err("failed to get bootwrapper-magic\n");
>>> +             ret = -EINVAL;
>>> +             goto err;
>>> +     }
>>> +     if (of_property_read_u32(np, "relocation-entry",
>>> +                              &hip04_boot.relocation_entry)) {
>>> +             pr_err("failed to get relocation-entry\n");
>>> +             ret = -EINVAL;
>>> +             goto err;
>>> +     }
>>> +     if (of_property_read_u32(np, "relocation-size",
>>> +                              &hip04_boot.relocation_size)) {
>>> +             pr_err("failed to get relocation-size\n");
>>> +             ret = -EINVAL;
>>> +             goto err;
>>> +     }
>>> +
>>> +     relocation = ioremap(hip04_boot.relocation_entry,
>>> +                          hip04_boot.relocation_size);
>>> +     if (!relocation) {
>>> +             pr_err("failed to map relocation space\n");
>>> +             ret = -ENOMEM;
>>> +             goto err;
>>> +     }
>>> +     sysctrl = of_iomap(np, 0);
>>> +     if (!sysctrl) {
>>> +             pr_err("failed to get sysctrl base\n");
>>> +             ret = -ENOMEM;
>>> +             goto err_sysctrl;
>>> +     }
>>> +     fabric = of_iomap(np_fab, 0);
>>> +     if (!fabric) {
>>> +             pr_err("failed to get fabric base\n");
>>> +             ret = -ENOMEM;
>>> +             goto err_fabric;
>>> +     }
>>> +
>>> +     if (!hip04_cpu_table_init())
>>> +             return -EINVAL;
>>> +     ret = mcpm_platform_register(&hip04_mcpm_ops);
>>> +     if (!ret) {
>>> +             mcpm_sync_init(NULL);
>>> +             pr_info("HiP04 MCPM initialized\n");
>>> +     }
>>> +     return ret;
>>> +err_fabric:
>>> +     iounmap(sysctrl);
>>> +err_sysctrl:
>>> +     iounmap(relocation);
>>> +err:
>>> +     return ret;
>>> +}
>>> +early_initcall(hip04_mcpm_init);
>>> +
>>> +bool __init hip04_smp_init_ops(void)
>>> +{
>>> +     mcpm_smp_set_ops();
>>> +     return true;
>>> +}
>>
>> You should be able to call mcpm_smp_set_ops() directly from
>> hip04_mcpm_init(), and only if there was no errors.
>>
> if (!mdesc->smp_init || !mdesc->smp_init()) {
>         if (psci_smp_available())
>                 smp_set_ops(&psci_smp_ops);
>         else if (mdesc->smp)
>                 smp_set_ops(mdesc->smp);
> }
>
> Since the above code checks the return value of mdesc->smp_init(),
> I think it's better to call mcpm_smp_set_ops() in mdesc->smp_init().
>
> Otherwise, my mdesc->smp_init() only return true without doing anything.
> It'll confuse others to understand the code.
>
>>
>> Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-12  0:44       ` Haojian Zhuang
@ 2014-05-12 19:39         ` Nicolas Pitre
  2014-05-13  9:57           ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-12 19:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 12 May 2014, Haojian Zhuang wrote:

> On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> >
> >
> > On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> On Wed, 7 May 2014, Haojian Zhuang wrote:
> >>
> >>> +
> >>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
> >>> +{
> >>> +     unsigned long data, mask;
> >>> +
> >>> +     if (!relocation || !sysctrl)
> >>> +             return -ENODEV;
> >>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
> >>> HIP04_MAX_CPUS_PER_CLUSTER)
> >>> +             return -EINVAL;
> >>> +
> >>> +     spin_lock_irq(&boot_lock);
> >>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
> >>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
> >>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
> >>> +     writel_relaxed(0, relocation + 12);
> >>> +
> >>> +     if (hip04_cluster_down(cluster)) {
> >>> +             data = CLUSTER_DEBUG_RESET_BIT;
> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >>> +             do {
> >>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
> >>> +                     data = readl_relaxed(sysctrl + \
> >>> +                                          SC_CPU_RESET_STATUS(cluster));
> >>> +             } while (data & mask);
> >>> +             hip04_set_snoop_filter(cluster, 1);
> >>> +     }
> >>
> >> Isn't this racy?  What if the new CPU starts executing code before
> >> snoops are enabled for it?
> >>
> >> Normally we solve this race by letting the waking-up CPU turn on its
> >> snoops by itself from an assembly code callback provided as argument to
> >> mcpm_sync_init().  This is also the only way to eventually support deep
> >> C-states with cpuidle.
> >>
> >
> > There's no race. At here, I enable snoop without unreset new CPU.
> >
> >>> +
> >>> +     hip04_cpu_table[cluster][cpu]++;
> >>> +
> >>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> >>> +            CORE_DEBUG_RESET_BIT(cpu);
> >>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >
> > At here, I make new CPU out of reset state.

That's my point.  At least on systems with the CCI, you risk hanging the 
system if you enable snoops for a CPU that is not yet running.

Yet you cannot enable the CPU and then turn on snoops as you have the 
opposite race in that case.

So the only way to be absolutely safe is to let the waking-up CPU turn 
on snoops for itself _before_ it starts using the cache.  That is what 
the power_up_setup callback provided to mcpm_sync_init() is all about.  

It must be written all in assembly as there is no stack available yet 
when it is called.  See arch/arm/mach-vexpress/dcscb_setup.S for an 
example skeleton where cci_enable_port_for_self is called when the 
affinity level is 1 (cluster level) and nothing special is done when the 
affinity level is 0 (CPU level).  All the synchronization and race 
avoidance is all handled for you in arch/arm/common/mcpm_head.S already.

> >
> >
> >>> +     spin_unlock_irq(&boot_lock);
> >>> +     msleep(POLL_MSEC);
> >>
> >> What is that msleep() for?
> >>
> > Without this delay, I'll meet hang.
> >
> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
> > system hang. So it's a workaround in my system.

Could you confirm that the IPI is actually what causes you trouble?

If so maybe you should make sure that the CPU is actually masking out 
IRQs at all times before they're unmasked by the kernel.

> >>> +     return 0;
> >>> +}
> >>> +
> >>> +static void hip04_mcpm_power_down(void)
> >>> +{
> >>> +     unsigned int mpidr, cpu, cluster;
> >>> +     bool skip_wfi = false;
> >>> +
> >>> +     mpidr = read_cpuid_mpidr();
> >>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> >>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> >>> +
> >>> +     __mcpm_cpu_going_down(cpu, cluster);
> >>> +
> >>> +     spin_lock(&boot_lock);
> >>> +     BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> >>> +     hip04_cpu_table[cluster][cpu]--;
> >>> +     if (hip04_cpu_table[cluster][cpu] == 1) {
> >>> +             /* A power_up request went ahead of us. */
> >>> +             skip_wfi = true;
> >>> +     } else if (hip04_cpu_table[cluster][cpu] > 1) {
> >>> +             pr_err("Cluster %d CPU%d is still running\n", cluster,
> >>> cpu);
> >>> +             BUG();
> >>> +     }
> >>> +
> >>> +     spin_unlock(&boot_lock);
> >>> +
> >>> +     v7_exit_coherency_flush(louis);
> >>
> >> Don't you have to turn off snoop filters in the case of a complete
> >> cluster down as well?
> >>
> >
> > I still have some issue on disabling a whole cluster. So making it
> > completely
> > will be finished later in additional patch.

Most likely related to my commentabove.

> >
> >
> >>> +
> >>> +     __mcpm_cpu_down(cpu, cluster);
> >>> +
> >>> +     isb();
> >>> +     dsb();
> >>
> >> Those isb/dsb are redundant here.  They're implicit from
> >> __mcpm_cpu_down().
> >>
> > OK. I'll remove it.
> >
> >
> >>> +
> >>> +     if (!skip_wfi)
> >>> +             wfi();
> >>> +}
> >>> +
> >>> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int
> >>> cluster)
> >>> +{
> >>> +     unsigned int data, tries;
> >>> +
> >>> +     BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
> >>> +            cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
> >>> +
> >>> +     for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
> >>> +             data = readl_relaxed(sysctrl +
> >>> SC_CPU_RESET_STATUS(cluster));
> >>> +             if (!(data & CORE_WFI_STATUS(cpu))) {
> >>> +                     msleep(POLL_MSEC);
> >>> +                     continue;
> >>> +             }
> >>> +             data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> >>> +                    CORE_DEBUG_RESET_BIT(cpu);
> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
> >>
> >> You are not supposed to perform any changes here.  This method is there
> >> only to wait for given CPU to be down.  It is not guaranteed it will be
> >> called.  Furthermore this can race with the power_up method.
> >>
> >> Normally you should perform this reset business from
> >> hip04_mcpm_power_down() while the lock is held.  Now... this assumes
> >> that any power/reset would be effective only when the CPU executes a
> >> WFI.  Is this the case on this hardware?  If not then we'll have to
> >> think about a different strategy.
> >>
> > OK. I can move reset operation in hip04_mcpm_power_down().
> >
> >>> +             return 0;
> >>> +     }
> >>> +
> >>> +     return -ETIMEDOUT;
> >>> +}
> >>> +
> >>> +static void hip04_mcpm_powered_up(void)
> >>> +{
> >>> +     if (!relocation)
> >>> +             return;
> >>> +     spin_lock(&boot_lock);
> >>> +     writel_relaxed(0, relocation);
> >>> +     writel_relaxed(0, relocation + 4);
> >>> +     writel_relaxed(0, relocation + 8);
> >>> +     writel_relaxed(0, relocation + 12);
> >>> +     spin_unlock(&boot_lock);
> >>> +}
> >>> +
> >>> +static const struct mcpm_platform_ops hip04_mcpm_ops = {
> >>> +     .power_up               = hip04_mcpm_power_up,
> >>> +     .power_down             = hip04_mcpm_power_down,
> >>> +     .wait_for_powerdown     = hip04_mcpm_wait_for_powerdown,
> >>> +     .powered_up             = hip04_mcpm_powered_up,
> >>> +};
> >>> +
> >>> +static bool __init hip04_cpu_table_init(void)
> >>> +{
> >>> +     unsigned int mpidr, cpu, cluster;
> >>> +
> >>> +     mpidr = read_cpuid_mpidr();
> >>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> >>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> >>> +
> >>> +     if (cluster >= HIP04_MAX_CLUSTERS ||
> >>> +         cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
> >>> +             pr_err("%s: boot CPU is out of bound!\n", __func__);
> >>> +             return false;
> >>> +     }
> >>> +     hip04_set_snoop_filter(cluster, 1);
> >>> +     hip04_cpu_table[cluster][cpu] = 1;
> >>> +     return true;
> >>> +}
> >>> +
> >>> +static int __init hip04_mcpm_init(void)
> >>> +{
> >>> +     struct device_node *np, *np_fab;
> >>> +     int ret = -ENODEV;
> >>> +
> >>> +     np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
> >>> +     if (!np)
> >>> +             goto err;
> >>> +     np_fab = of_find_compatible_node(NULL, NULL,
> >>> "hisilicon,hip04-fabric");
> >>> +     if (!np_fab)
> >>> +             goto err;
> >>> +
> >>> +     if (of_property_read_u32(np, "bootwrapper-phys",
> >>> +                              &hip04_boot.bootwrapper_phys)) {
> >>> +             pr_err("failed to get bootwrapper-phys\n");
> >>> +             ret = -EINVAL;
> >>> +             goto err;
> >>> +     }
> >>> +     if (of_property_read_u32(np, "bootwrapper-size",
> >>> +                              &hip04_boot.bootwrapper_size)) {
> >>> +             pr_err("failed to get bootwrapper-size\n");
> >>> +             ret = -EINVAL;
> >>> +             goto err;
> >>> +     }
> >>> +     if (of_property_read_u32(np, "bootwrapper-magic",
> >>> +                              &hip04_boot.bootwrapper_magic)) {
> >>> +             pr_err("failed to get bootwrapper-magic\n");
> >>> +             ret = -EINVAL;
> >>> +             goto err;
> >>> +     }
> >>> +     if (of_property_read_u32(np, "relocation-entry",
> >>> +                              &hip04_boot.relocation_entry)) {
> >>> +             pr_err("failed to get relocation-entry\n");
> >>> +             ret = -EINVAL;
> >>> +             goto err;
> >>> +     }
> >>> +     if (of_property_read_u32(np, "relocation-size",
> >>> +                              &hip04_boot.relocation_size)) {
> >>> +             pr_err("failed to get relocation-size\n");
> >>> +             ret = -EINVAL;
> >>> +             goto err;
> >>> +     }
> >>> +
> >>> +     relocation = ioremap(hip04_boot.relocation_entry,
> >>> +                          hip04_boot.relocation_size);
> >>> +     if (!relocation) {
> >>> +             pr_err("failed to map relocation space\n");
> >>> +             ret = -ENOMEM;
> >>> +             goto err;
> >>> +     }
> >>> +     sysctrl = of_iomap(np, 0);
> >>> +     if (!sysctrl) {
> >>> +             pr_err("failed to get sysctrl base\n");
> >>> +             ret = -ENOMEM;
> >>> +             goto err_sysctrl;
> >>> +     }
> >>> +     fabric = of_iomap(np_fab, 0);
> >>> +     if (!fabric) {
> >>> +             pr_err("failed to get fabric base\n");
> >>> +             ret = -ENOMEM;
> >>> +             goto err_fabric;
> >>> +     }
> >>> +
> >>> +     if (!hip04_cpu_table_init())
> >>> +             return -EINVAL;
> >>> +     ret = mcpm_platform_register(&hip04_mcpm_ops);
> >>> +     if (!ret) {
> >>> +             mcpm_sync_init(NULL);
> >>> +             pr_info("HiP04 MCPM initialized\n");
> >>> +     }
> >>> +     return ret;
> >>> +err_fabric:
> >>> +     iounmap(sysctrl);
> >>> +err_sysctrl:
> >>> +     iounmap(relocation);
> >>> +err:
> >>> +     return ret;
> >>> +}
> >>> +early_initcall(hip04_mcpm_init);
> >>> +
> >>> +bool __init hip04_smp_init_ops(void)
> >>> +{
> >>> +     mcpm_smp_set_ops();
> >>> +     return true;
> >>> +}
> >>
> >> You should be able to call mcpm_smp_set_ops() directly from
> >> hip04_mcpm_init(), and only if there was no errors.
> >>
> > if (!mdesc->smp_init || !mdesc->smp_init()) {
> >         if (psci_smp_available())
> >                 smp_set_ops(&psci_smp_ops);
> >         else if (mdesc->smp)
> >                 smp_set_ops(mdesc->smp);
> > }
> >
> > Since the above code checks the return value of mdesc->smp_init(),
> > I think it's better to call mcpm_smp_set_ops() in mdesc->smp_init().
> >
> > Otherwise, my mdesc->smp_init() only return true without doing anything.
> > It'll confuse others to understand the code.

Simply don't provide a mdesc->smp_init at all.  If you have a default 
value for mdesc->smp then it'll be replaced when hip04_mcpm_init() 
completes successfully.


Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-12 19:39         ` Nicolas Pitre
@ 2014-05-13  9:57           ` Haojian Zhuang
  2014-05-13 18:44             ` Nicolas Pitre
  0 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-13  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 May 2014 03:39, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Mon, 12 May 2014, Haojian Zhuang wrote:
>
>> On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
>> >
>> >
>> > On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >> On Wed, 7 May 2014, Haojian Zhuang wrote:
>> >>
>> >>> +
>> >>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
>> >>> +{
>> >>> +     unsigned long data, mask;
>> >>> +
>> >>> +     if (!relocation || !sysctrl)
>> >>> +             return -ENODEV;
>> >>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
>> >>> HIP04_MAX_CPUS_PER_CLUSTER)
>> >>> +             return -EINVAL;
>> >>> +
>> >>> +     spin_lock_irq(&boot_lock);
>> >>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
>> >>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
>> >>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
>> >>> +     writel_relaxed(0, relocation + 12);
>> >>> +
>> >>> +     if (hip04_cluster_down(cluster)) {
>> >>> +             data = CLUSTER_DEBUG_RESET_BIT;
>> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>> >>> +             do {
>> >>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
>> >>> +                     data = readl_relaxed(sysctrl + \
>> >>> +                                          SC_CPU_RESET_STATUS(cluster));
>> >>> +             } while (data & mask);
>> >>> +             hip04_set_snoop_filter(cluster, 1);
>> >>> +     }
>> >>
>> >> Isn't this racy?  What if the new CPU starts executing code before
>> >> snoops are enabled for it?
>> >>
>> >> Normally we solve this race by letting the waking-up CPU turn on its
>> >> snoops by itself from an assembly code callback provided as argument to
>> >> mcpm_sync_init().  This is also the only way to eventually support deep
>> >> C-states with cpuidle.
>> >>
>> >
>> > There's no race. At here, I enable snoop without unreset new CPU.
>> >
>> >>> +
>> >>> +     hip04_cpu_table[cluster][cpu]++;
>> >>> +
>> >>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> >>> +            CORE_DEBUG_RESET_BIT(cpu);
>> >>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>> >
>> > At here, I make new CPU out of reset state.
>
> That's my point.  At least on systems with the CCI, you risk hanging the
> system if you enable snoops for a CPU that is not yet running.
>
> Yet you cannot enable the CPU and then turn on snoops as you have the
> opposite race in that case.
>
> So the only way to be absolutely safe is to let the waking-up CPU turn
> on snoops for itself _before_ it starts using the cache.  That is what
> the power_up_setup callback provided to mcpm_sync_init() is all about.
>
> It must be written all in assembly as there is no stack available yet
> when it is called.  See arch/arm/mach-vexpress/dcscb_setup.S for an
> example skeleton where cci_enable_port_for_self is called when the
> affinity level is 1 (cluster level) and nothing special is done when the
> affinity level is 0 (CPU level).  All the synchronization and race
> avoidance is all handled for you in arch/arm/common/mcpm_head.S already.
>

There's no CCI in HiP04. Their own fabric is used instead.

>> >
>> >
>> >>> +     spin_unlock_irq(&boot_lock);
>> >>> +     msleep(POLL_MSEC);
>> >>
>> >> What is that msleep() for?
>> >>
>> > Without this delay, I'll meet hang.
>> >
>> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
>> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
>> > system hang. So it's a workaround in my system.
>
> Could you confirm that the IPI is actually what causes you trouble?
>
> If so maybe you should make sure that the CPU is actually masking out
> IRQs at all times before they're unmasked by the kernel.
>

I think so. But I don't have any hardware debugger to confirm it.

I think that unnecessary interrupt causes new CPU in interrupt mode,
then this CPU can't be online.

If I remove the code to send IPI, the new CPU could be online right.

>> >>> +     return 0;
>> >>> +}
>> >>> +
>> >>> +static void hip04_mcpm_power_down(void)
>> >>> +{
>> >>> +     unsigned int mpidr, cpu, cluster;
>> >>> +     bool skip_wfi = false;
>> >>> +
>> >>> +     mpidr = read_cpuid_mpidr();
>> >>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>> >>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>> >>> +
>> >>> +     __mcpm_cpu_going_down(cpu, cluster);
>> >>> +
>> >>> +     spin_lock(&boot_lock);
>> >>> +     BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
>> >>> +     hip04_cpu_table[cluster][cpu]--;
>> >>> +     if (hip04_cpu_table[cluster][cpu] == 1) {
>> >>> +             /* A power_up request went ahead of us. */
>> >>> +             skip_wfi = true;
>> >>> +     } else if (hip04_cpu_table[cluster][cpu] > 1) {
>> >>> +             pr_err("Cluster %d CPU%d is still running\n", cluster,
>> >>> cpu);
>> >>> +             BUG();
>> >>> +     }
>> >>> +
>> >>> +     spin_unlock(&boot_lock);
>> >>> +
>> >>> +     v7_exit_coherency_flush(louis);
>> >>
>> >> Don't you have to turn off snoop filters in the case of a complete
>> >> cluster down as well?
>> >>
>> >
>> > I still have some issue on disabling a whole cluster. So making it
>> > completely
>> > will be finished later in additional patch.
>
> Most likely related to my commentabove.
>
Maybe it's not. In my original code, I call hip04_set_snoop_filter() at here.
But it doesn't help me.

Before I root cause this issue, I don't plan to add
hip04_set_snoop_filter() here.

>> >> You should be able to call mcpm_smp_set_ops() directly from
>> >> hip04_mcpm_init(), and only if there was no errors.
>> >>
>> > if (!mdesc->smp_init || !mdesc->smp_init()) {
>> >         if (psci_smp_available())
>> >                 smp_set_ops(&psci_smp_ops);
>> >         else if (mdesc->smp)
>> >                 smp_set_ops(mdesc->smp);
>> > }
>> >
>> > Since the above code checks the return value of mdesc->smp_init(),
>> > I think it's better to call mcpm_smp_set_ops() in mdesc->smp_init().
>> >
>> > Otherwise, my mdesc->smp_init() only return true without doing anything.
>> > It'll confuse others to understand the code.
>
> Simply don't provide a mdesc->smp_init at all.  If you have a default
> value for mdesc->smp then it'll be replaced when hip04_mcpm_init()
> completes successfully.
>
>
> Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-13  9:57           ` Haojian Zhuang
@ 2014-05-13 18:44             ` Nicolas Pitre
  2014-05-15  6:28               ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-13 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 13 May 2014, Haojian Zhuang wrote:

> On 13 May 2014 03:39, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Mon, 12 May 2014, Haojian Zhuang wrote:
> >
> >> On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> >> >
> >> >
> >> > On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> >> On Wed, 7 May 2014, Haojian Zhuang wrote:
> >> >>
> >> >>> +
> >> >>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
> >> >>> +{
> >> >>> +     unsigned long data, mask;
> >> >>> +
> >> >>> +     if (!relocation || !sysctrl)
> >> >>> +             return -ENODEV;
> >> >>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
> >> >>> HIP04_MAX_CPUS_PER_CLUSTER)
> >> >>> +             return -EINVAL;
> >> >>> +
> >> >>> +     spin_lock_irq(&boot_lock);
> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
> >> >>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
> >> >>> +     writel_relaxed(0, relocation + 12);
> >> >>> +
> >> >>> +     if (hip04_cluster_down(cluster)) {
> >> >>> +             data = CLUSTER_DEBUG_RESET_BIT;
> >> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >> >>> +             do {
> >> >>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
> >> >>> +                     data = readl_relaxed(sysctrl + \
> >> >>> +                                          SC_CPU_RESET_STATUS(cluster));
> >> >>> +             } while (data & mask);
> >> >>> +             hip04_set_snoop_filter(cluster, 1);
> >> >>> +     }
> >> >>
> >> >> Isn't this racy?  What if the new CPU starts executing code before
> >> >> snoops are enabled for it?
> >> >>
> >> >> Normally we solve this race by letting the waking-up CPU turn on its
> >> >> snoops by itself from an assembly code callback provided as argument to
> >> >> mcpm_sync_init().  This is also the only way to eventually support deep
> >> >> C-states with cpuidle.
> >> >>
> >> >
> >> > There's no race. At here, I enable snoop without unreset new CPU.
> >> >
> >> >>> +
> >> >>> +     hip04_cpu_table[cluster][cpu]++;
> >> >>> +
> >> >>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> >> >>> +            CORE_DEBUG_RESET_BIT(cpu);
> >> >>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >> >
> >> > At here, I make new CPU out of reset state.
> >
> > That's my point.  At least on systems with the CCI, you risk hanging the
> > system if you enable snoops for a CPU that is not yet running.
> >
> > Yet you cannot enable the CPU and then turn on snoops as you have the
> > opposite race in that case.
> >
> > So the only way to be absolutely safe is to let the waking-up CPU turn
> > on snoops for itself _before_ it starts using the cache.  That is what
> > the power_up_setup callback provided to mcpm_sync_init() is all about.
> >
> > It must be written all in assembly as there is no stack available yet
> > when it is called.  See arch/arm/mach-vexpress/dcscb_setup.S for an
> > example skeleton where cci_enable_port_for_self is called when the
> > affinity level is 1 (cluster level) and nothing special is done when the
> > affinity level is 0 (CPU level).  All the synchronization and race
> > avoidance is all handled for you in arch/arm/common/mcpm_head.S already.
> >
> 
> There's no CCI in HiP04. Their own fabric is used instead.

OK.  Still, in order to support deep C-States with cpuidle, the 
waking-up of CPUs must happen asynchronously, and in that case the CPU 
being awaken must do snooping setup by itself.  So I'd be interested to 
see if that can be down that way as well for HiP04, at least to be 
similar in structure to other backend implementations, and possibly for 
being cpuidle ready as well.

> >> >
> >> >
> >> >>> +     spin_unlock_irq(&boot_lock);
> >> >>> +     msleep(POLL_MSEC);
> >> >>
> >> >> What is that msleep() for?
> >> >>
> >> > Without this delay, I'll meet hang.
> >> >
> >> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
> >> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
> >> > system hang. So it's a workaround in my system.
> >
> > Could you confirm that the IPI is actually what causes you trouble?
> >
> > If so maybe you should make sure that the CPU is actually masking out
> > IRQs at all times before they're unmasked by the kernel.
> >
> 
> I think so. But I don't have any hardware debugger to confirm it.
> 
> I think that unnecessary interrupt causes new CPU in interrupt mode,
> then this CPU can't be online.
> 
> If I remove the code to send IPI, the new CPU could be online right.

If so that's a bug in the firmware/bootloader/whatever code that needs 
to be fixed.  CPUs must never unmasq IRQs if they're not ready to cope 
with them.


Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-13 18:44             ` Nicolas Pitre
@ 2014-05-15  6:28               ` Haojian Zhuang
  2014-05-15 20:10                 ` Nicolas Pitre
  0 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-15  6:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 14 May 2014 02:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Tue, 13 May 2014, Haojian Zhuang wrote:
>
>> On 13 May 2014 03:39, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Mon, 12 May 2014, Haojian Zhuang wrote:
>> >
>> >> On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
>> >> >
>> >> >
>> >> > On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >> >> On Wed, 7 May 2014, Haojian Zhuang wrote:
>> >> >>
>> >> >>> +
>> >> >>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
>> >> >>> +{
>> >> >>> +     unsigned long data, mask;
>> >> >>> +
>> >> >>> +     if (!relocation || !sysctrl)
>> >> >>> +             return -ENODEV;
>> >> >>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
>> >> >>> HIP04_MAX_CPUS_PER_CLUSTER)
>> >> >>> +             return -EINVAL;
>> >> >>> +
>> >> >>> +     spin_lock_irq(&boot_lock);
>> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
>> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
>> >> >>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
>> >> >>> +     writel_relaxed(0, relocation + 12);
>> >> >>> +
>> >> >>> +     if (hip04_cluster_down(cluster)) {
>> >> >>> +             data = CLUSTER_DEBUG_RESET_BIT;
>> >> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>> >> >>> +             do {
>> >> >>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
>> >> >>> +                     data = readl_relaxed(sysctrl + \
>> >> >>> +                                          SC_CPU_RESET_STATUS(cluster));
>> >> >>> +             } while (data & mask);
>> >> >>> +             hip04_set_snoop_filter(cluster, 1);
>> >> >>> +     }
>> >> >>
>> >> >> Isn't this racy?  What if the new CPU starts executing code before
>> >> >> snoops are enabled for it?
>> >> >>
>> >> >> Normally we solve this race by letting the waking-up CPU turn on its
>> >> >> snoops by itself from an assembly code callback provided as argument to
>> >> >> mcpm_sync_init().  This is also the only way to eventually support deep
>> >> >> C-states with cpuidle.
>> >> >>
>> >> >
>> >> > There's no race. At here, I enable snoop without unreset new CPU.
>> >> >
>> >> >>> +
>> >> >>> +     hip04_cpu_table[cluster][cpu]++;
>> >> >>> +
>> >> >>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> >> >>> +            CORE_DEBUG_RESET_BIT(cpu);
>> >> >>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>> >> >
>> >> > At here, I make new CPU out of reset state.
>> >
>> > That's my point.  At least on systems with the CCI, you risk hanging the
>> > system if you enable snoops for a CPU that is not yet running.
>> >
>> > Yet you cannot enable the CPU and then turn on snoops as you have the
>> > opposite race in that case.
>> >
>> > So the only way to be absolutely safe is to let the waking-up CPU turn
>> > on snoops for itself _before_ it starts using the cache.  That is what
>> > the power_up_setup callback provided to mcpm_sync_init() is all about.
>> >
>> > It must be written all in assembly as there is no stack available yet
>> > when it is called.  See arch/arm/mach-vexpress/dcscb_setup.S for an
>> > example skeleton where cci_enable_port_for_self is called when the
>> > affinity level is 1 (cluster level) and nothing special is done when the
>> > affinity level is 0 (CPU level).  All the synchronization and race
>> > avoidance is all handled for you in arch/arm/common/mcpm_head.S already.
>> >
>>
>> There's no CCI in HiP04. Their own fabric is used instead.
>
> OK.  Still, in order to support deep C-States with cpuidle, the
> waking-up of CPUs must happen asynchronously, and in that case the CPU
> being awaken must do snooping setup by itself.  So I'd be interested to
> see if that can be down that way as well for HiP04, at least to be
> similar in structure to other backend implementations, and possibly for
> being cpuidle ready as well.
>

But it fails on my platform if I execute snooping setup on the new CPU.

>> >> >
>> >> >
>> >> >>> +     spin_unlock_irq(&boot_lock);
>> >> >>> +     msleep(POLL_MSEC);
>> >> >>
>> >> >> What is that msleep() for?
>> >> >>
>> >> > Without this delay, I'll meet hang.
>> >> >
>> >> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
>> >> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
>> >> > system hang. So it's a workaround in my system.
>> >
>> > Could you confirm that the IPI is actually what causes you trouble?
>> >
>> > If so maybe you should make sure that the CPU is actually masking out
>> > IRQs at all times before they're unmasked by the kernel.
>> >
>>
>> I think so. But I don't have any hardware debugger to confirm it.
>>
>> I think that unnecessary interrupt causes new CPU in interrupt mode,
>> then this CPU can't be online.
>>
>> If I remove the code to send IPI, the new CPU could be online right.
>
> If so that's a bug in the firmware/bootloader/whatever code that needs
> to be fixed.  CPUs must never unmasq IRQs if they're not ready to cope
> with them.
>

I agree that it should be fixed in firmware. But I need some time. So I
want to keep the workaround until the bug is fixed in firmware.

Regards
Haojian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-15  6:28               ` Haojian Zhuang
@ 2014-05-15 20:10                 ` Nicolas Pitre
  2014-05-20  4:53                   ` Haojian Zhuang
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Pitre @ 2014-05-15 20:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 15 May 2014, Haojian Zhuang wrote:

> On 14 May 2014 02:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Tue, 13 May 2014, Haojian Zhuang wrote:
> >
> >> On 13 May 2014 03:39, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> > On Mon, 12 May 2014, Haojian Zhuang wrote:
> >> >
> >> >> On 11 May 2014 16:02, Haojian Zhuang <haojian.zhuang@linaro.org> wrote:
> >> >> >
> >> >> >
> >> >> > On 8 May 2014 01:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> >> >> On Wed, 7 May 2014, Haojian Zhuang wrote:
> >> >> >>
> >> >> >>> +
> >> >> >>> +static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
> >> >> >>> +{
> >> >> >>> +     unsigned long data, mask;
> >> >> >>> +
> >> >> >>> +     if (!relocation || !sysctrl)
> >> >> >>> +             return -ENODEV;
> >> >> >>> +     if (cluster >= HIP04_MAX_CLUSTERS || cpu >=
> >> >> >>> HIP04_MAX_CPUS_PER_CLUSTER)
> >> >> >>> +             return -EINVAL;
> >> >> >>> +
> >> >> >>> +     spin_lock_irq(&boot_lock);
> >> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
> >> >> >>> +     writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
> >> >> >>> +     writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
> >> >> >>> +     writel_relaxed(0, relocation + 12);
> >> >> >>> +
> >> >> >>> +     if (hip04_cluster_down(cluster)) {
> >> >> >>> +             data = CLUSTER_DEBUG_RESET_BIT;
> >> >> >>> +             writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >> >> >>> +             do {
> >> >> >>> +                     mask = CLUSTER_DEBUG_RESET_STATUS;
> >> >> >>> +                     data = readl_relaxed(sysctrl + \
> >> >> >>> +                                          SC_CPU_RESET_STATUS(cluster));
> >> >> >>> +             } while (data & mask);
> >> >> >>> +             hip04_set_snoop_filter(cluster, 1);
> >> >> >>> +     }
> >> >> >>
> >> >> >> Isn't this racy?  What if the new CPU starts executing code before
> >> >> >> snoops are enabled for it?
> >> >> >>
> >> >> >> Normally we solve this race by letting the waking-up CPU turn on its
> >> >> >> snoops by itself from an assembly code callback provided as argument to
> >> >> >> mcpm_sync_init().  This is also the only way to eventually support deep
> >> >> >> C-states with cpuidle.
> >> >> >>
> >> >> >
> >> >> > There's no race. At here, I enable snoop without unreset new CPU.
> >> >> >
> >> >> >>> +
> >> >> >>> +     hip04_cpu_table[cluster][cpu]++;
> >> >> >>> +
> >> >> >>> +     data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> >> >> >>> +            CORE_DEBUG_RESET_BIT(cpu);
> >> >> >>> +     writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> >> >> >
> >> >> > At here, I make new CPU out of reset state.
> >> >
> >> > That's my point.  At least on systems with the CCI, you risk hanging the
> >> > system if you enable snoops for a CPU that is not yet running.
> >> >
> >> > Yet you cannot enable the CPU and then turn on snoops as you have the
> >> > opposite race in that case.
> >> >
> >> > So the only way to be absolutely safe is to let the waking-up CPU turn
> >> > on snoops for itself _before_ it starts using the cache.  That is what
> >> > the power_up_setup callback provided to mcpm_sync_init() is all about.
> >> >
> >> > It must be written all in assembly as there is no stack available yet
> >> > when it is called.  See arch/arm/mach-vexpress/dcscb_setup.S for an
> >> > example skeleton where cci_enable_port_for_self is called when the
> >> > affinity level is 1 (cluster level) and nothing special is done when the
> >> > affinity level is 0 (CPU level).  All the synchronization and race
> >> > avoidance is all handled for you in arch/arm/common/mcpm_head.S already.
> >> >
> >>
> >> There's no CCI in HiP04. Their own fabric is used instead.
> >
> > OK.  Still, in order to support deep C-States with cpuidle, the
> > waking-up of CPUs must happen asynchronously, and in that case the CPU
> > being awaken must do snooping setup by itself.  So I'd be interested to
> > see if that can be down that way as well for HiP04, at least to be
> > similar in structure to other backend implementations, and possibly for
> > being cpuidle ready as well.
> >
> 
> But it fails on my platform if I execute snooping setup on the new CPU.

It fails how?  I want to make sure if the problem is with the hardware 
design or the code.

> >> >> >
> >> >> >>> +     spin_unlock_irq(&boot_lock);
> >> >> >>> +     msleep(POLL_MSEC);
> >> >> >>
> >> >> >> What is that msleep() for?
> >> >> >>
> >> >> > Without this delay, I'll meet hang.
> >> >> >
> >> >> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
> >> >> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
> >> >> > system hang. So it's a workaround in my system.
> >> >
> >> > Could you confirm that the IPI is actually what causes you trouble?
> >> >
> >> > If so maybe you should make sure that the CPU is actually masking out
> >> > IRQs at all times before they're unmasked by the kernel.
> >> >
> >>
> >> I think so. But I don't have any hardware debugger to confirm it.
> >>
> >> I think that unnecessary interrupt causes new CPU in interrupt mode,
> >> then this CPU can't be online.
> >>
> >> If I remove the code to send IPI, the new CPU could be online right.
> >
> > If so that's a bug in the firmware/bootloader/whatever code that needs
> > to be fixed.  CPUs must never unmasq IRQs if they're not ready to cope
> > with them.
> >
> 
> I agree that it should be fixed in firmware. But I need some time. So I
> want to keep the workaround until the bug is fixed in firmware.

This is still a very bad workaround.  As an alternative, there might be 
a way to simply mask the IPI at the GIC level and unmask it from the 
powered_up method.

Also... if this is going to be fixed in the firmware, maybe not 
including such a workaround into the upstream submission will keep the 
incentive alive for having it actually fixed.


Nicolas

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-15 20:10                 ` Nicolas Pitre
@ 2014-05-20  4:53                   ` Haojian Zhuang
  2014-05-21  9:47                     ` Dave Martin
  0 siblings, 1 reply; 36+ messages in thread
From: Haojian Zhuang @ 2014-05-20  4:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 16 May 2014 04:10, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Thu, 15 May 2014, Haojian Zhuang wrote:
>
>> On 14 May 2014 02:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >>
>> >> There's no CCI in HiP04. Their own fabric is used instead.
>> >
>> > OK.  Still, in order to support deep C-States with cpuidle, the
>> > waking-up of CPUs must happen asynchronously, and in that case the CPU
>> > being awaken must do snooping setup by itself.  So I'd be interested to
>> > see if that can be down that way as well for HiP04, at least to be
>> > similar in structure to other backend implementations, and possibly for
>> > being cpuidle ready as well.
>> >
>>
>> But it fails on my platform if I execute snooping setup on the new CPU.
>
> It fails how?  I want to make sure if the problem is with the hardware
> design or the code.
>
The failure isn't caused by your assembly code. I even rewrite it.

It's caused by hardware design. Hisilicon guys said the snooping setup
should be set before new CPU on. I tried and got the same result.

>> >> >> >
>> >> >> >>> +     spin_unlock_irq(&boot_lock);
>> >> >> >>> +     msleep(POLL_MSEC);
>> >> >> >>
>> >> >> >> What is that msleep() for?
>> >> >> >>
>> >> >> > Without this delay, I'll meet hang.
>> >> >> >
>> >> >> > Since I'm using reset to wakeup CPU from wfi/wfe status, I don't need
>> >> >> > IPI at here. If I remove the msleep() here, it seems that IPI caused my
>> >> >> > system hang. So it's a workaround in my system.
>> >> >
>> >> > Could you confirm that the IPI is actually what causes you trouble?
>> >> >
>> >> > If so maybe you should make sure that the CPU is actually masking out
>> >> > IRQs at all times before they're unmasked by the kernel.
>> >> >
>> >>
>> >> I think so. But I don't have any hardware debugger to confirm it.
>> >>
>> >> I think that unnecessary interrupt causes new CPU in interrupt mode,
>> >> then this CPU can't be online.
>> >>
>> >> If I remove the code to send IPI, the new CPU could be online right.
>> >
>> > If so that's a bug in the firmware/bootloader/whatever code that needs
>> > to be fixed.  CPUs must never unmasq IRQs if they're not ready to cope
>> > with them.
>> >
>>
>> I agree that it should be fixed in firmware. But I need some time. So I
>> want to keep the workaround until the bug is fixed in firmware.
>
> This is still a very bad workaround.  As an alternative, there might be
> a way to simply mask the IPI at the GIC level and unmask it from the
> powered_up method.
>
> Also... if this is going to be fixed in the firmware, maybe not
> including such a workaround into the upstream submission will keep the
> incentive alive for having it actually fixed.
>


OK. Let me remove the workaround.

Regards
Haojian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config
  2014-05-07 22:33     ` Haojian Zhuang
@ 2014-05-20 18:18       ` Olof Johansson
  0 siblings, 0 replies; 36+ messages in thread
From: Olof Johansson @ 2014-05-20 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 7, 2014 at 3:33 PM, Haojian Zhuang
<haojian.zhuang@linaro.org> wrote:
> On 8 May 2014 00:46, Olof Johansson <olof@lixom.net> wrote:
>> On Wed, May 07, 2014 at 10:44:36PM +0800, Haojian Zhuang wrote:
>>> Since CONFIG_ARM_LPAE could be set in ARM V7, add new two configurations
>>> CONFIG_ARCH_MULTI_V7_NONLPAE & CONFIG_ARCH_MULTI_V7_LPAE.
>>>
>>> If we want to enable CONFIG_ARM_LPAE configuration, we should enable
>>> CONFIG_ARCH_MULTI_V7 & disable both CONFIG_ARCH_MULTI_V6 and
>>> CONFIG_ARCH_MULTI_V7_NONLPAE.
>>>
>>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>>
>> I don't like this. Platforms should just depend on CONFIG_ARCH_MULTI_V7 &&
>> LPAE (or && !LPAE) instead.
>>
>> Platforms that _can_ boot without LPAE should not require it, even if
>> they boot with less available memory.
>>
>>
>> -Olof
>
> Do you mean that I should remove CONFIG_ARCH_MULTI_V7_NONLPAE &
> CONFIG_ARCH_MULTI_V7_LPAE & multi_v7_lpae_defconfig?

Yes.

Once platforms have been flagged whether they support LPAE or not we
can easily create a lpae-enabled defconfig that doesn't enable a bunch
of extra platforms that it will never work on.


-Olof

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v5 08/14] ARM: hisi: add hip04 SoC support
  2014-05-20  4:53                   ` Haojian Zhuang
@ 2014-05-21  9:47                     ` Dave Martin
  0 siblings, 0 replies; 36+ messages in thread
From: Dave Martin @ 2014-05-21  9:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 20, 2014 at 12:53:31PM +0800, Haojian Zhuang wrote:
> On 16 May 2014 04:10, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Thu, 15 May 2014, Haojian Zhuang wrote:
> >
> >> On 14 May 2014 02:44, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> >>
> >> >> There's no CCI in HiP04. Their own fabric is used instead.
> >> >
> >> > OK.  Still, in order to support deep C-States with cpuidle, the
> >> > waking-up of CPUs must happen asynchronously, and in that case the CPU
> >> > being awaken must do snooping setup by itself.  So I'd be interested to
> >> > see if that can be down that way as well for HiP04, at least to be
> >> > similar in structure to other backend implementations, and possibly for
> >> > being cpuidle ready as well.
> >> >
> >>
> >> But it fails on my platform if I execute snooping setup on the new CPU.
> >
> > It fails how?  I want to make sure if the problem is with the hardware
> > design or the code.
> >
> The failure isn't caused by your assembly code. I even rewrite it.
> 
> It's caused by hardware design. Hisilicon guys said the snooping setup
> should be set before new CPU on. I tried and got the same result.

How does this design support cluster powerdown during idle, then ... or
is this just not intended to be supported?

Unless there is some extra logic in the hardware taking care of snoop
control races, it's not clear who interrupt-driven wakeup from a cluster
powerdown could work safely.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2014-05-21  9:47 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-07 14:44 [PATCH v5 00/14] enable HiP04 SoC Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 01/14] ARM: debug: add HiP04 debug uart Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 02/14] ARM: add V7_NONLPAE && V7_LPAE sub config Haojian Zhuang
2014-05-07 16:46   ` Olof Johansson
2014-05-07 22:33     ` Haojian Zhuang
2014-05-20 18:18       ` Olof Johansson
2014-05-07 14:44 ` [PATCH v5 03/14] ARM: config: append lpae configuration Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 04/14] irq: gic: use mask field in GICC_IAR Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 05/14] irq: gic: support hip04 gic Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 06/14] ARM: mcpm: support 4 clusters Haojian Zhuang
2014-05-07 16:48   ` Olof Johansson
2014-05-07 18:00     ` Nicolas Pitre
2014-05-07 18:03       ` Olof Johansson
2014-05-07 16:59   ` Nicolas Pitre
2014-05-07 14:44 ` [PATCH v5 07/14] ARM: hisi: add ARCH_HISI Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 08/14] ARM: hisi: add hip04 SoC support Haojian Zhuang
2014-05-07 16:50   ` Olof Johansson
2014-05-07 17:44   ` Nicolas Pitre
     [not found]     ` <CAD6h2NQU0NR1PO=x6pz62B4QWqkPz7F+Fp65YeQJ62vumF8_Aw@mail.gmail.com>
2014-05-12  0:44       ` Haojian Zhuang
2014-05-12 19:39         ` Nicolas Pitre
2014-05-13  9:57           ` Haojian Zhuang
2014-05-13 18:44             ` Nicolas Pitre
2014-05-15  6:28               ` Haojian Zhuang
2014-05-15 20:10                 ` Nicolas Pitre
2014-05-20  4:53                   ` Haojian Zhuang
2014-05-21  9:47                     ` Dave Martin
2014-05-07 14:44 ` [PATCH v5 09/14] ARM: dts: append hip04 dts Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 10/14] ARM: config: append hip04_defconfig Haojian Zhuang
2014-05-07 16:52   ` Olof Johansson
2014-05-09  6:35     ` Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 11/14] ARM: config: select ARCH_HISI in hi3xxx_defconfig Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 12/14] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 13/14] ARM: dts: Add PMU support in HiP04 Haojian Zhuang
2014-05-07 16:53   ` Olof Johansson
2014-05-09  6:36     ` Haojian Zhuang
2014-05-07 14:44 ` [PATCH v5 14/14] virt: arm: support hip04 gic Haojian Zhuang

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