ARM: SoC: platform support for v4.2
Our SoC branch usually contains expanded support for new SoCs and other core platform code. Some highlights from this round: - sunxi: SMP support for A23 SoC - socpga: big-endian support - pxa: conversion to common clock framework - bcm: SMP support for BCM63138 - imx: support new I.MX7D SoC - zte: basic support for ZX296702 SoC Conflicts: arch/arm/mach-socfpga/core.h Trivial remove/remove conflict with our cleanup branch. Resolution: remove both sides -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVi4RMAAoJEFk3GJrT+8Zl6/kP/1Rv9O++1Kxua6R54Og6AF1J 0miFr2fnUrUWUYg/NVbseRH5bBe6N6ir3SQMfde8W2/QibEjOoEwSwrle+mC/eiq CE0x0gtyRvXMrMU/FWkOvbmmw9uv5oz1z3IHZV6AiecNuSMLUBPfamryikQ8C+d1 O/QZtX543tJQJDOBihO5cuhoVVM37UX0unNmqGsyswlyqTPF8FxcIJAYVNtnxjmj AFaOB0nDJKLKFTiX2Ype2wOxxJX1lrLatNo4W4T+YaaK+i1uCOhgTdSN+n49K7YA KNDFEgZFQqT8VMJyG+eJVeYF+cI7yWQ7lBzIftPUjPk/7+dIHBjWPz2QdjVz3U38 kxncf4S9xGAF5G2rcKe4mFrfT3Y8QLWQpA/jFs06yLwW1O3Hlfq3DzMdGNcF7hth 17LOP8namn9+NepZEp/vAlFzRRypxWWtbkPNBIItkImC6zn0IiGjBy50DE1io27W hmQcnMb7d+0wWl2Y8OmR2lZSB97JiRZkRYMCVHVt+0zGJzp4prLvl9wbjh1VXkPv ERCDJ9nCmZsl7ZVmIXMI7KNXYuPNp7R/QAzCvuSUueswF0qxTAQ0VSSBwRMqvQsQ UUNC6p63VnjUeMUdn2EBsUQZ0Uqw3t2U5TtvooHNt9FkiGsSpwjWrvVD+LItaPoJ GPeeJrJaYQsDvTrO8wjU =ZtPK -----END PGP SIGNATURE----- Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC platform support updates from Kevin Hilman: "Our SoC branch usually contains expanded support for new SoCs and other core platform code. Some highlights from this round: - sunxi: SMP support for A23 SoC - socpga: big-endian support - pxa: conversion to common clock framework - bcm: SMP support for BCM63138 - imx: support new I.MX7D SoC - zte: basic support for ZX296702 SoC" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (134 commits) ARM: zx: Add basic defconfig support for ZX296702 ARM: dts: zx: add an initial zx296702 dts and doc clk: zx: add clock support to zx296702 dt-bindings: Add #defines for ZTE ZX296702 clocks ARM: socfpga: fix build error due to secondary_startup MAINTAINERS: ARM64: EXYNOS: Extend entry for ARM64 DTS ARM: ep93xx: simone: support for SPI-based MMC/SD cards MAINTAINERS: update Shawn's email to use kernel.org one ARM: socfpga: support suspend to ram ARM: socfpga: add CPU_METHOD_OF_DECLARE for Arria 10 ARM: socfpga: use CPU_METHOD_OF_DECLARE for socfpga_cyclone5 ARM: EXYNOS: register power domain driver from core_initcall ARM: EXYNOS: use PS_HOLD based poweroff for all supported SoCs ARM: SAMSUNG: Constify platform_device_id ARM: EXYNOS: Constify irq_domain_ops ARM: EXYNOS: add coupled cpuidle support for Exynos3250 ARM: EXYNOS: add exynos_get_boot_addr() helper ARM: EXYNOS: add exynos_set_boot_addr() helper ARM: EXYNOS: make exynos_core_restart() less verbose ARM: EXYNOS: fix exynos_boot_secondary() return value on timeout ...
This commit is contained in:
commit
4aa705b18b
|
@ -0,0 +1,32 @@
|
|||
STM32 ARM Linux Overview
|
||||
========================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The STMicroelectronics family of Cortex-M based MCUs are supported by the
|
||||
'STM32' platform of ARM Linux. Currently only the STM32F429 is supported.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
A generic configuration is provided for STM32 family, and can be used as the
|
||||
default by
|
||||
make stm32_defconfig
|
||||
|
||||
Layout
|
||||
------
|
||||
|
||||
All the files for multiple machine families are located in the platform code
|
||||
contained in arch/arm/mach-stm32
|
||||
|
||||
There is a generic board board-dt.c in the mach folder which support
|
||||
Flattened Device Tree, which means, it works with any compatible board with
|
||||
Device Trees.
|
||||
|
||||
|
||||
Document Author
|
||||
---------------
|
||||
|
||||
Maxime Coquelin <mcoquelin.stm32@gmail.com>
|
|
@ -0,0 +1,22 @@
|
|||
STM32F429 Overview
|
||||
==================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
The STM32F429 is a Cortex-M4 MCU aimed at various applications.
|
||||
It features:
|
||||
- ARM Cortex-M4 up to 180MHz with FPU
|
||||
- 2MB internal Flash Memory
|
||||
- External memory support through FMC controller (PSRAM, SDRAM, NOR, NAND)
|
||||
- I2C, SPI, SAI, CAN, USB OTG, Ethernet controllers
|
||||
- LCD controller & Camera interface
|
||||
- Cryptographic processor
|
||||
|
||||
Resources
|
||||
---------
|
||||
Datasheet and reference manual are publicly available on ST website:
|
||||
- http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN1806?ecmp=stm32f429-439_pron_pr-ces2014_nov2013
|
||||
|
||||
Document Author
|
||||
---------------
|
||||
Maxime Coquelin <mcoquelin.stm32@gmail.com>
|
|
@ -188,6 +188,7 @@ nodes to be present and contain the properties described below.
|
|||
# On ARM 32-bit systems this property is optional and
|
||||
can be one of:
|
||||
"allwinner,sun6i-a31"
|
||||
"allwinner,sun8i-a23"
|
||||
"arm,psci"
|
||||
"brcm,brahma-b15"
|
||||
"marvell,armada-375-smp"
|
||||
|
|
|
@ -19,9 +19,10 @@ Optional Properties:
|
|||
domains.
|
||||
- clock-names: The following clocks can be specified:
|
||||
- oscclk: Oscillator clock.
|
||||
- pclkN, clkN: Pairs of parent of input clock and input clock to the
|
||||
devices in this power domain. Maximum of 4 pairs (N = 0 to 3)
|
||||
are supported currently.
|
||||
- clkN: Input clocks to the devices in this power domain. These clocks
|
||||
will be reparented to oscclk before swithing power domain off.
|
||||
Their original parent will be brought back after turning on
|
||||
the domain. Maximum of 4 clocks (N = 0 to 3) are supported.
|
||||
- asbN: Clocks required by asynchronous bridges (ASB) present in
|
||||
the power domain. These clock should be enabled during power
|
||||
domain on/off operations.
|
||||
|
|
|
@ -81,12 +81,15 @@ Freescale Vybrid Platform Device Tree Bindings
|
|||
For the Vybrid SoC familiy all variants with DDR controller are supported,
|
||||
which is the VF5xx and VF6xx series. Out of historical reasons, in most
|
||||
places the kernel uses vf610 to refer to the whole familiy.
|
||||
The compatible string "fsl,vf610m4" is used for the secondary Cortex-M4
|
||||
core support.
|
||||
|
||||
Required root node compatible property (one of them):
|
||||
- compatible = "fsl,vf500";
|
||||
- compatible = "fsl,vf510";
|
||||
- compatible = "fsl,vf600";
|
||||
- compatible = "fsl,vf610";
|
||||
- compatible = "fsl,vf610m4";
|
||||
|
||||
Freescale LS1021A Platform Device Tree Bindings
|
||||
------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
ZTE platforms device tree bindings
|
||||
---------------------------------------
|
||||
|
||||
- ZX296702 board:
|
||||
Required root node properties:
|
||||
- compatible = "zte,zx296702-ad1", "zte,zx296702"
|
||||
|
||||
System management required properties:
|
||||
- compatible = "zte,sysctrl"
|
||||
|
||||
Low power management required properties:
|
||||
- compatible = "zte,zx296702-pcu"
|
||||
|
||||
Bus matrix required properties:
|
||||
- compatible = "zte,zx-bus-matrix"
|
|
@ -0,0 +1,35 @@
|
|||
Device Tree Clock bindings for ZTE zx296702
|
||||
|
||||
This binding uses the common clock binding[1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"zte,zx296702-topcrm-clk":
|
||||
zx296702 top clock selection, divider and gating
|
||||
|
||||
"zte,zx296702-lsp0crpm-clk" and
|
||||
"zte,zx296702-lsp1crpm-clk":
|
||||
zx296702 device level clock selection and gating
|
||||
|
||||
- reg: Address and length of the register set
|
||||
|
||||
The clock consumer should specify the desired clock by having the clock
|
||||
ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296702-clock.h
|
||||
for the full list of zx296702 clock IDs.
|
||||
|
||||
|
||||
topclk: topcrm@0x09800000 {
|
||||
compatible = "zte,zx296702-topcrm-clk";
|
||||
reg = <0x09800000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
uart0: serial@0x09405000 {
|
||||
compatible = "zte,zx296702-uart";
|
||||
reg = <0x09405000 0x1000>;
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&lsp1clk ZX296702_UART0_PCLK>;
|
||||
status = "disabled";
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
* ARM AMBA Primecell PL011 serial UART
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "arm,primecell", "arm,pl011"
|
||||
- compatible: must be "arm,primecell", "arm,pl011", "zte,zx296702-uart"
|
||||
- reg: exactly one register range with length 0x1000
|
||||
- interrupts: exactly one interrupt specifier
|
||||
|
||||
|
|
|
@ -214,3 +214,4 @@ xillybus Xillybus Ltd.
|
|||
xlnx Xilinx
|
||||
zyxel ZyXEL Communications Corp.
|
||||
zarlink Zarlink Semiconductor
|
||||
zte ZTE Corp.
|
||||
|
|
38
MAINTAINERS
38
MAINTAINERS
|
@ -1043,7 +1043,7 @@ F: arch/arm/include/asm/hardware/dec21285.h
|
|||
F: arch/arm/mach-footbridge/
|
||||
|
||||
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
M: Shawn Guo <shawnguo@kernel.org>
|
||||
M: Sascha Hauer <kernel@pengutronix.de>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
|
@ -1052,9 +1052,11 @@ F: arch/arm/mach-imx/
|
|||
F: arch/arm/mach-mxs/
|
||||
F: arch/arm/boot/dts/imx*
|
||||
F: arch/arm/configs/imx*_defconfig
|
||||
F: drivers/clk/imx/
|
||||
F: include/soc/imx/
|
||||
|
||||
ARM/FREESCALE VYBRID ARM ARCHITECTURE
|
||||
M: Shawn Guo <shawn.guo@linaro.org>
|
||||
M: Shawn Guo <shawnguo@kernel.org>
|
||||
M: Sascha Hauer <kernel@pengutronix.de>
|
||||
R: Stefan Agner <stefan@agner.ch>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -1197,6 +1199,12 @@ M: Lennert Buytenhek <kernel@wantstofly.org>
|
|||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
|
||||
ARM/LPC18XX ARCHITECTURE
|
||||
M: Joachim Eastwood <manabian@gmail.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
N: lpc18xx
|
||||
|
||||
ARM/MAGICIAN MACHINE SUPPORT
|
||||
M: Philipp Zabel <philipp.zabel@gmail.com>
|
||||
S: Maintained
|
||||
|
@ -1400,6 +1408,7 @@ L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: arch/arm/boot/dts/s3c*
|
||||
F: arch/arm/boot/dts/exynos*
|
||||
F: arch/arm64/boot/dts/exynos/
|
||||
F: arch/arm/plat-samsung/
|
||||
F: arch/arm/mach-s3c24*/
|
||||
F: arch/arm/mach-s3c64xx/
|
||||
|
@ -1511,6 +1520,14 @@ F: drivers/usb/host/ohci-st.c
|
|||
F: drivers/watchdog/st_lpc_wdt.c
|
||||
F: drivers/ata/ahci_st.c
|
||||
|
||||
ARM/STM32 ARCHITECTURE
|
||||
M: Maxime Coquelin <mcoquelin.stm32@gmail.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcoquelin/stm32.git
|
||||
N: stm32
|
||||
F: drivers/clocksource/armv7m_systick.c
|
||||
|
||||
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
|
||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -1557,6 +1574,13 @@ F: drivers/rtc/rtc-ab3100.c
|
|||
F: drivers/rtc/rtc-coh901331.c
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
|
||||
|
||||
ARM/UNIPHIER ARCHITECTURE
|
||||
M: Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-uniphier/
|
||||
N: uniphier
|
||||
|
||||
ARM/Ux500 ARM ARCHITECTURE
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -1634,6 +1658,15 @@ S: Maintained
|
|||
F: arch/arm/mach-pxa/z2.c
|
||||
F: arch/arm/mach-pxa/include/mach/z2.h
|
||||
|
||||
ARM/ZTE ARCHITECTURE
|
||||
M: Jun Nie <jun.nie@linaro.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-zx/
|
||||
F: drivers/clk/zte/
|
||||
F: Documentation/devicetree/bindings/arm/zte.txt
|
||||
F: Documentation/devicetree/bindings/clock/zx296702-clk.txt
|
||||
|
||||
ARM/ZYNQ ARCHITECTURE
|
||||
M: Michal Simek <michal.simek@xilinx.com>
|
||||
R: Sören Brinkmann <soren.brinkmann@xilinx.com>
|
||||
|
@ -2228,6 +2261,7 @@ S: Maintained
|
|||
F: arch/arm/mach-bcm/*brcmstb*
|
||||
F: arch/arm/boot/dts/bcm7*.dts*
|
||||
F: drivers/bus/brcmstb_gisb.c
|
||||
N: brcmstb
|
||||
|
||||
BROADCOM BMIPS MIPS ARCHITECTURE
|
||||
M: Kevin Cernekee <cernekee@gmail.com>
|
||||
|
|
|
@ -331,6 +331,20 @@ config ARCH_MULTIPLATFORM
|
|||
select SPARSE_IRQ
|
||||
select USE_OF
|
||||
|
||||
config ARM_SINGLE_ARMV7M
|
||||
bool "ARMv7-M based platforms (Cortex-M0/M3/M4)"
|
||||
depends on !MMU
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select ARM_NVIC
|
||||
select AUTO_ZRELADDR
|
||||
select CLKSRC_OF
|
||||
select COMMON_CLK
|
||||
select CPU_V7M
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select NO_IOPORT_MAP
|
||||
select SPARSE_IRQ
|
||||
select USE_OF
|
||||
|
||||
config ARCH_REALVIEW
|
||||
bool "ARM Ltd. RealView family"
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
|
@ -400,24 +414,6 @@ config ARCH_EBSA110
|
|||
Ethernet interface, two PCMCIA sockets, two serial ports and a
|
||||
parallel port.
|
||||
|
||||
config ARCH_EFM32
|
||||
bool "Energy Micro efm32"
|
||||
depends on !MMU
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_NVIC
|
||||
select AUTO_ZRELADDR
|
||||
select CLKSRC_OF
|
||||
select COMMON_CLK
|
||||
select CPU_V7M
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select NO_DMA
|
||||
select NO_IOPORT_MAP
|
||||
select SPARSE_IRQ
|
||||
select USE_OF
|
||||
help
|
||||
Support for Energy Micro's (now Silicon Labs) efm32 Giant Gecko
|
||||
processors.
|
||||
|
||||
config ARCH_EP93XX
|
||||
bool "EP93xx-based"
|
||||
select ARCH_HAS_HOLES_MEMORYMODEL
|
||||
|
@ -608,6 +604,7 @@ config ARCH_PXA
|
|||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_CPU_SUSPEND if PM
|
||||
select AUTO_ZRELADDR
|
||||
select COMMON_CLK
|
||||
select CLKDEV_LOOKUP
|
||||
select CLKSRC_MMIO
|
||||
select CLKSRC_OF
|
||||
|
@ -754,8 +751,10 @@ config ARCH_OMAP1
|
|||
select GENERIC_IRQ_CHIP
|
||||
select HAVE_IDE
|
||||
select IRQ_DOMAIN
|
||||
select MULTI_IRQ_HANDLER
|
||||
select NEED_MACH_IO_H if PCCARD
|
||||
select NEED_MACH_MEMORY_H
|
||||
select SPARSE_IRQ
|
||||
help
|
||||
Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx)
|
||||
|
||||
|
@ -939,6 +938,8 @@ source "arch/arm/mach-tegra/Kconfig"
|
|||
|
||||
source "arch/arm/mach-u300/Kconfig"
|
||||
|
||||
source "arch/arm/mach-uniphier/Kconfig"
|
||||
|
||||
source "arch/arm/mach-ux500/Kconfig"
|
||||
|
||||
source "arch/arm/mach-versatile/Kconfig"
|
||||
|
@ -950,8 +951,40 @@ source "arch/arm/mach-vt8500/Kconfig"
|
|||
|
||||
source "arch/arm/mach-w90x900/Kconfig"
|
||||
|
||||
source "arch/arm/mach-zx/Kconfig"
|
||||
|
||||
source "arch/arm/mach-zynq/Kconfig"
|
||||
|
||||
# ARMv7-M architecture
|
||||
config ARCH_EFM32
|
||||
bool "Energy Micro efm32"
|
||||
depends on ARM_SINGLE_ARMV7M
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
Support for Energy Micro's (now Silicon Labs) efm32 Giant Gecko
|
||||
processors.
|
||||
|
||||
config ARCH_LPC18XX
|
||||
bool "NXP LPC18xx/LPC43xx"
|
||||
depends on ARM_SINGLE_ARMV7M
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select ARM_AMBA
|
||||
select CLKSRC_LPC32XX
|
||||
select PINCTRL
|
||||
help
|
||||
Support for NXP's LPC18xx Cortex-M3 and LPC43xx Cortex-M4
|
||||
high performance microcontrollers.
|
||||
|
||||
config ARCH_STM32
|
||||
bool "STMicrolectronics STM32"
|
||||
depends on ARM_SINGLE_ARMV7M
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select ARMV7M_SYSTICK
|
||||
select CLKSRC_STM32
|
||||
select RESET_CONTROLLER
|
||||
help
|
||||
Support for STMicroelectronics STM32 processors.
|
||||
|
||||
# Definitions to make life easier
|
||||
config ARCH_ACORN
|
||||
bool
|
||||
|
@ -1479,7 +1512,8 @@ config ARM_PSCI
|
|||
# selected platforms.
|
||||
config ARCH_NR_GPIO
|
||||
int
|
||||
default 1024 if ARCH_SHMOBILE || ARCH_TEGRA || ARCH_ZYNQ
|
||||
default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \
|
||||
ARCH_ZYNQ
|
||||
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
|
||||
SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
|
||||
default 416 if ARCH_SUNXI
|
||||
|
|
|
@ -410,6 +410,13 @@ choice
|
|||
Say Y here if you want kernel low-level debugging support
|
||||
on i.MX6SX.
|
||||
|
||||
config DEBUG_IMX7D_UART
|
||||
bool "i.MX7D Debug UART"
|
||||
depends on SOC_IMX7D
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on i.MX7D.
|
||||
|
||||
config DEBUG_KEYSTONE_UART0
|
||||
bool "Kernel low-level debugging on KEYSTONE2 using UART0"
|
||||
depends on ARCH_KEYSTONE
|
||||
|
@ -433,6 +440,14 @@ choice
|
|||
Say Y here if you want kernel low-level debugging support
|
||||
on KS8695.
|
||||
|
||||
config DEBUG_LPC18XX_UART0
|
||||
bool "Kernel low-level debugging via LPC18xx/43xx UART0"
|
||||
depends on ARCH_LPC18XX
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on NXP LPC18xx/43xx UART0.
|
||||
|
||||
config DEBUG_MESON_UARTAO
|
||||
bool "Kernel low-level debugging via Meson6 UARTAO"
|
||||
depends on ARCH_MESON
|
||||
|
@ -908,13 +923,22 @@ choice
|
|||
on SA-11x0 UART ports. The kernel will check for the first
|
||||
enabled UART in a sequence 3-1-2.
|
||||
|
||||
config DEBUG_SOCFPGA_UART
|
||||
config DEBUG_SOCFPGA_UART0
|
||||
depends on ARCH_SOCFPGA
|
||||
bool "Use SOCFPGA UART for low-level debug"
|
||||
bool "Use SOCFPGA UART0 for low-level debug"
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on SOCFPGA based platforms.
|
||||
on SOCFPGA(Cyclone 5 and Arria 5) based platforms.
|
||||
|
||||
config DEBUG_SOCFPGA_UART1
|
||||
depends on ARCH_SOCFPGA
|
||||
bool "Use SOCFPGA UART1 for low-level debug"
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on SOCFPGA(Arria 10) based platforms.
|
||||
|
||||
|
||||
config DEBUG_SUN9I_UART0
|
||||
bool "Kernel low-level debugging messages via sun9i UART0"
|
||||
|
@ -1157,6 +1181,18 @@ choice
|
|||
For more details about semihosting, please see
|
||||
chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
|
||||
|
||||
config DEBUG_ZTE_ZX
|
||||
bool "Use ZTE ZX UART"
|
||||
select DEBUG_UART_PL01X
|
||||
depends on ARCH_ZX
|
||||
help
|
||||
Say Y here if you are enabling ZTE ZX296702 SOC and need
|
||||
debug uart support.
|
||||
|
||||
This option is preferred over the platform specific
|
||||
options; the platform specific options are deprecated
|
||||
and will be soon removed.
|
||||
|
||||
config DEBUG_LL_UART_8250
|
||||
bool "Kernel low-level debugging via 8250 UART"
|
||||
help
|
||||
|
@ -1231,7 +1267,8 @@ config DEBUG_IMX_UART_PORT
|
|||
DEBUG_IMX53_UART || \
|
||||
DEBUG_IMX6Q_UART || \
|
||||
DEBUG_IMX6SL_UART || \
|
||||
DEBUG_IMX6SX_UART
|
||||
DEBUG_IMX6SX_UART || \
|
||||
DEBUG_IMX7D_UART
|
||||
default 1
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
|
@ -1281,7 +1318,8 @@ config DEBUG_LL_INCLUDE
|
|||
DEBUG_IMX53_UART ||\
|
||||
DEBUG_IMX6Q_UART || \
|
||||
DEBUG_IMX6SL_UART || \
|
||||
DEBUG_IMX6SX_UART
|
||||
DEBUG_IMX6SX_UART || \
|
||||
DEBUG_IMX7D_UART
|
||||
default "debug/ks8695.S" if DEBUG_KS8695_UART
|
||||
default "debug/msm.S" if DEBUG_QCOM_UARTDM
|
||||
default "debug/netx.S" if DEBUG_NETX_UART
|
||||
|
@ -1337,6 +1375,7 @@ config DEBUG_UART_PHYS
|
|||
default 0x02531000 if DEBUG_KEYSTONE_UART1
|
||||
default 0x03010fe0 if ARCH_RPC
|
||||
default 0x07000000 if DEBUG_SUN9I_UART0
|
||||
default 0x09405000 if DEBUG_ZTE_ZX
|
||||
default 0x10009000 if DEBUG_REALVIEW_STD_PORT || \
|
||||
DEBUG_VEXPRESS_UART0_CA9
|
||||
default 0x1010c000 if DEBUG_REALVIEW_PB1176_PORT
|
||||
|
@ -1359,6 +1398,7 @@ config DEBUG_UART_PHYS
|
|||
default 0x20201000 if DEBUG_BCM2835
|
||||
default 0x3e000000 if DEBUG_BCM_KONA_UART
|
||||
default 0x4000e400 if DEBUG_LL_UART_EFM32
|
||||
default 0x40081000 if DEBUG_LPC18XX_UART0
|
||||
default 0x40090000 if ARCH_LPC32XX
|
||||
default 0x40100000 if DEBUG_PXA_UART1
|
||||
default 0x42000000 if ARCH_GEMINI
|
||||
|
@ -1407,7 +1447,8 @@ config DEBUG_UART_PHYS
|
|||
default 0xfd883000 if DEBUG_ALPINE_UART0
|
||||
default 0xfe800000 if ARCH_IOP32X
|
||||
default 0xff690000 if DEBUG_RK32_UART2
|
||||
default 0xffc02000 if DEBUG_SOCFPGA_UART
|
||||
default 0xffc02000 if DEBUG_SOCFPGA_UART0
|
||||
default 0xffc02100 if DEBUG_SOCFPGA_UART1
|
||||
default 0xffd82340 if ARCH_IOP13XX
|
||||
default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0
|
||||
default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2
|
||||
|
@ -1466,6 +1507,7 @@ config DEBUG_UART_VIRT
|
|||
default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
|
||||
default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
|
||||
default 0xfc40ab00 if DEBUG_BRCMSTB_UART
|
||||
default 0xfc705000 if DEBUG_ZTE_ZX
|
||||
default 0xfcfe8600 if DEBUG_UART_BCM63XX
|
||||
default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
|
||||
default 0xfd000000 if ARCH_SPEAR13XX
|
||||
|
@ -1485,7 +1527,8 @@ config DEBUG_UART_VIRT
|
|||
default 0xfeb26000 if DEBUG_RK3X_UART1
|
||||
default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
|
||||
default 0xfeb31000 if DEBUG_KEYSTONE_UART1
|
||||
default 0xfec02000 if DEBUG_SOCFPGA_UART
|
||||
default 0xfec02000 if DEBUG_SOCFPGA_UART0
|
||||
default 0xfec02100 if DEBUG_SOCFPGA_UART1
|
||||
default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE
|
||||
default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE
|
||||
default 0xfec10000 if DEBUG_SIRFATLAS7_UART0
|
||||
|
@ -1530,8 +1573,9 @@ config DEBUG_UART_8250_WORD
|
|||
bool "Use 32-bit accesses for 8250 UART"
|
||||
depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
|
||||
depends on DEBUG_UART_8250_SHIFT >= 2
|
||||
default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \
|
||||
ARCH_KEYSTONE || DEBUG_ALPINE_UART0 || \
|
||||
default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART0 || \
|
||||
DEBUG_SOCFPGA_UART1 || ARCH_KEYSTONE || \
|
||||
DEBUG_ALPINE_UART0 || \
|
||||
DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
|
||||
DEBUG_DAVINCI_DA8XX_UART2 || \
|
||||
DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 || \
|
||||
|
@ -1544,7 +1588,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
|
|||
|
||||
config DEBUG_UNCOMPRESS
|
||||
bool
|
||||
depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG
|
||||
depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
|
||||
default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
|
||||
(!DEBUG_TEGRA_UART || !ZBOOT_ROM)
|
||||
help
|
||||
|
@ -1561,7 +1605,7 @@ config DEBUG_UNCOMPRESS
|
|||
config UNCOMPRESS_INCLUDE
|
||||
string
|
||||
default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
|
||||
PLAT_SAMSUNG || ARCH_EFM32 || \
|
||||
PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || \
|
||||
ARCH_SHMOBILE_LEGACY
|
||||
default "mach/uncompress.h"
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ machine-$(CONFIG_ARCH_IOP33X) += iop33x
|
|||
machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx
|
||||
machine-$(CONFIG_ARCH_KEYSTONE) += keystone
|
||||
machine-$(CONFIG_ARCH_KS8695) += ks8695
|
||||
machine-$(CONFIG_ARCH_LPC18XX) += lpc18xx
|
||||
machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx
|
||||
machine-$(CONFIG_ARCH_MESON) += meson
|
||||
machine-$(CONFIG_ARCH_MMP) += mmp
|
||||
|
@ -196,14 +197,17 @@ machine-$(CONFIG_ARCH_SHMOBILE) += shmobile
|
|||
machine-$(CONFIG_ARCH_SIRF) += prima2
|
||||
machine-$(CONFIG_ARCH_SOCFPGA) += socfpga
|
||||
machine-$(CONFIG_ARCH_STI) += sti
|
||||
machine-$(CONFIG_ARCH_STM32) += stm32
|
||||
machine-$(CONFIG_ARCH_SUNXI) += sunxi
|
||||
machine-$(CONFIG_ARCH_TEGRA) += tegra
|
||||
machine-$(CONFIG_ARCH_U300) += u300
|
||||
machine-$(CONFIG_ARCH_U8500) += ux500
|
||||
machine-$(CONFIG_ARCH_UNIPHIER) += uniphier
|
||||
machine-$(CONFIG_ARCH_VERSATILE) += versatile
|
||||
machine-$(CONFIG_ARCH_VEXPRESS) += vexpress
|
||||
machine-$(CONFIG_ARCH_VT8500) += vt8500
|
||||
machine-$(CONFIG_ARCH_W90X900) += w90x900
|
||||
machine-$(CONFIG_ARCH_ZX) += zx
|
||||
machine-$(CONFIG_ARCH_ZYNQ) += zynq
|
||||
machine-$(CONFIG_PLAT_SPEAR) += spear
|
||||
|
||||
|
|
|
@ -660,6 +660,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
|
|||
mt6592-evb.dtb \
|
||||
mt8127-moose.dtb \
|
||||
mt8135-evbp1.dtb
|
||||
dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
|
||||
endif
|
||||
|
||||
always := $(dtb-y)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
/dts-v1/;
|
||||
|
||||
#include "zx296702.dtsi"
|
||||
|
||||
/ {
|
||||
model = "ZTE ZX296702 AD1 Board";
|
||||
compatible = "zte,zx296702-ad1", "zte,zx296702";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = <0x50000000 0x20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
num-slots = <1>;
|
||||
supports-highspeed;
|
||||
non-removable;
|
||||
disable-wp;
|
||||
status = "okay";
|
||||
|
||||
slot@0 {
|
||||
reg = <0>;
|
||||
bus-width = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
&mmc1 {
|
||||
num-slots = <1>;
|
||||
supports-highspeed;
|
||||
non-removable;
|
||||
disable-wp;
|
||||
status = "okay";
|
||||
|
||||
slot@0 {
|
||||
reg = <0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
#include "skeleton.dtsi"
|
||||
#include <dt-bindings/clock/zx296702-clock.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
enable-method = "zte,zx296702-smp";
|
||||
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a9";
|
||||
device_type = "cpu";
|
||||
next-level-cache = <&l2cc>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "arm,cortex-a9";
|
||||
device_type = "cpu";
|
||||
next-level-cache = <&l2cc>;
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
interrupt-parent = <&intc>;
|
||||
ranges;
|
||||
|
||||
matrix: bus-matrix@400000 {
|
||||
compatible = "zte,zx-bus-matrix";
|
||||
reg = <0x00400000 0x1000>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@00801000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-controller;
|
||||
reg = <0x00801000 0x1000>,
|
||||
<0x00800100 0x100>;
|
||||
};
|
||||
|
||||
global_timer: timer@008000200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0x00800200 0x20>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&intc>;
|
||||
clocks = <&topclk ZX296702_A9_PERIPHCLK>;
|
||||
};
|
||||
|
||||
l2cc: l2-cache-controller@0x00c00000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0x00c00000 0x1000>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
arm,data-latency = <1 1 1>;
|
||||
arm,tag-latency = <1 1 1>;
|
||||
arm,double-linefill = <1>;
|
||||
arm,double-linefill-incr = <0>;
|
||||
};
|
||||
|
||||
pcu: pcu@0xa0008000 {
|
||||
compatible = "zte,zx296702-pcu";
|
||||
reg = <0xa0008000 0x1000>;
|
||||
};
|
||||
|
||||
topclk: topclk@0x09800000 {
|
||||
compatible = "zte,zx296702-topcrm-clk";
|
||||
reg = <0x09800000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
lsp1clk: lsp1clk@0x09400000 {
|
||||
compatible = "zte,zx296702-lsp1crpm-clk";
|
||||
reg = <0x09400000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
lsp0clk: lsp0clk@0x0b000000 {
|
||||
compatible = "zte,zx296702-lsp0crpm-clk";
|
||||
reg = <0x0b000000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
uart0: serial@0x09405000 {
|
||||
compatible = "zte,zx296702-uart";
|
||||
reg = <0x09405000 0x1000>;
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&lsp1clk ZX296702_UART0_WCLK>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart1: serial@0x09406000 {
|
||||
compatible = "zte,zx296702-uart";
|
||||
reg = <0x09406000 0x1000>;
|
||||
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&lsp1clk ZX296702_UART1_WCLK>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mmc0: mmc@0x09408000 {
|
||||
compatible = "snps,dw-mshc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x09408000 0x1000>;
|
||||
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
|
||||
fifo-depth = <32>;
|
||||
clocks = <&lsp1clk ZX296702_SDMMC0_PCLK>,
|
||||
<&lsp1clk ZX296702_SDMMC0_WCLK>;
|
||||
clock-names = "biu", "ciu";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mmc1: mmc@0x0b003000 {
|
||||
compatible = "snps,dw-mshc";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x0b003000 0x1000>;
|
||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
fifo-depth = <32>;
|
||||
clocks = <&lsp0clk ZX296702_SDMMC1_PCLK>,
|
||||
<&lsp0clk ZX296702_SDMMC1_WCLK>;
|
||||
clock-names = "biu", "ciu";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sysctrl: sysctrl@0xa0007000 {
|
||||
compatible = "zte,sysctrl", "syscon";
|
||||
reg = <0xa0007000 0x1000>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -16,6 +16,7 @@ CONFIG_EMBEDDED=y
|
|||
# CONFIG_IOSCHED_DEADLINE is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
# CONFIG_MMU is not set
|
||||
CONFIG_ARM_SINGLE_ARMV7M=y
|
||||
CONFIG_ARCH_EFM32=y
|
||||
CONFIG_SET_MEM_PARAM=y
|
||||
CONFIG_DRAM_BASE=0x88000000
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_RESOURCE_COUNTERS=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_SYSCTL_SYSCALL=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
CONFIG_SLAB=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_IOSCHED_CFQ is not set
|
||||
CONFIG_ARCH_ZX=y
|
||||
CONFIG_SOC_ZX296702=y
|
||||
# CONFIG_SWP_EMULATE is not set
|
||||
CONFIG_ARM_ERRATA_754322=y
|
||||
CONFIG_ARM_ERRATA_775420=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_VMSPLIT_2G=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_KSM=y
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_VFP=y
|
||||
CONFIG_NEON=y
|
||||
CONFIG_KERNEL_MODE_NEON=y
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
CONFIG_HIBERNATION=y
|
||||
CONFIG_PM_RUNTIME=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_SUSPEND_TIME=y
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_CMDLINE="console=ttyAMA0,115200 debug earlyprintk root=/dev/ram rw rootwait"
|
||||
#CONFIG_NET is not set
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_DMA_CMA=y
|
||||
CONFIG_CMA_SIZE_MBYTES=192
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=1
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_UID_STAT=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_CHR_DEV_SCH=y
|
||||
CONFIG_SCSI_MULTI_LUN=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=y
|
||||
CONFIG_DM_UEVENT=y
|
||||
CONFIG_DM_VERITY=y
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_SERIO=y
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_CONSOLE_POLL=y
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_UNSAFE_RESUME=y
|
||||
CONFIG_MMC_BLOCK_MINORS=16
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_IDMAC=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_EXT4_DEBUG=y
|
||||
CONFIG_FUSE_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=936
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
#CONFIG_NFS_FS is not set
|
||||
CONFIG_NLS_CODEPAGE_936=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_FRAME_WARN=4096
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
CONFIG_PANIC_TIMEOUT=5
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_TIMER_STATS=y
|
||||
CONFIG_DEBUG_RT_MUTEXES=y
|
||||
CONFIG_DEBUG_SPINLOCK=y
|
||||
CONFIG_DEBUG_MUTEXES=y
|
||||
CONFIG_RCU_CPU_STALL_TIMEOUT=60
|
||||
# CONFIG_FTRACE is not set
|
||||
CONFIG_KGDB=y
|
||||
CONFIG_KGDB_KDB=y
|
||||
# CONFIG_ARM_UNWIND is not set
|
||||
CONFIG_DEBUG_PREEMPT=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_DEBUG_LL=y
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_STACKTRACE=y
|
||||
CONFIG_DEBUG_ZTE_ZX=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_CRYPTO_LZO=y
|
||||
CONFIG_GPIOLIB=y
|
|
@ -33,6 +33,10 @@ struct firmware_ops {
|
|||
* Sets boot address of specified physical CPU
|
||||
*/
|
||||
int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
|
||||
/*
|
||||
* Gets boot address of specified physical CPU
|
||||
*/
|
||||
int (*get_cpu_boot_addr)(int cpu, unsigned long *boot_addr);
|
||||
/*
|
||||
* Boots specified physical CPU
|
||||
*/
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
* First, the standard VFP set.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_VFP_H
|
||||
#define __ASM_VFP_H
|
||||
|
||||
#define FPSID cr0
|
||||
#define FPSCR cr1
|
||||
#define MVFR1 cr6
|
||||
|
@ -87,3 +90,9 @@
|
|||
#define VFPOPDESC_UNUSED_BIT (24)
|
||||
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
|
||||
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
void vfp_disable(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_VFP_H */
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
|
||||
#ifdef CONFIG_DEBUG_UART_8250_WORD
|
||||
.macro store, rd, rx:vararg
|
||||
ARM_BE8(rev \rd, \rd)
|
||||
str \rd, \rx
|
||||
ARM_BE8(rev \rd, \rd)
|
||||
.endm
|
||||
|
||||
.macro load, rd, rx:vararg
|
||||
ldr \rd, \rx
|
||||
ARM_BE8(rev \rd, \rd)
|
||||
.endm
|
||||
#else
|
||||
.macro store, rd, rx:vararg
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define UARTn_TXDATA 0x0034
|
||||
|
||||
.macro addruart, rx, tmp
|
||||
.macro addruart, rx, tmp, tmp2
|
||||
ldr \rx, =(CONFIG_DEBUG_UART_PHYS)
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -90,6 +90,16 @@
|
|||
#define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR
|
||||
#define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n)
|
||||
|
||||
#define IMX7D_UART1_BASE_ADDR 0x30860000
|
||||
#define IMX7D_UART2_BASE_ADDR 0x30890000
|
||||
#define IMX7D_UART3_BASE_ADDR 0x30880000
|
||||
#define IMX7D_UART4_BASE_ADDR 0x30a60000
|
||||
#define IMX7D_UART5_BASE_ADDR 0x30a70000
|
||||
#define IMX7D_UART6_BASE_ADDR 0x30a80000
|
||||
#define IMX7D_UART7_BASE_ADDR 0x30a90000
|
||||
#define IMX7D_UART_BASE_ADDR(n) IMX7D_UART##n##_BASE_ADDR
|
||||
#define IMX7D_UART_BASE(n) IMX7D_UART_BASE_ADDR(n)
|
||||
|
||||
#define IMX_DEBUG_UART_BASE(soc) soc##_UART_BASE(CONFIG_DEBUG_IMX_UART_PORT)
|
||||
|
||||
#ifdef CONFIG_DEBUG_IMX1_UART
|
||||
|
@ -114,6 +124,9 @@
|
|||
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL)
|
||||
#elif defined(CONFIG_DEBUG_IMX6SX_UART)
|
||||
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX)
|
||||
#elif defined(CONFIG_DEBUG_IMX7D_UART)
|
||||
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __DEBUG_IMX_UART_H */
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
*/
|
||||
#include <linux/amba/serial.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_ZTE_ZX
|
||||
#undef UART01x_DR
|
||||
#undef UART01x_FR
|
||||
#define UART01x_DR 0x04
|
||||
#define UART01x_FR 0x14
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_PHYS
|
||||
.macro addruart, rp, rv, tmp
|
||||
ldr \rp, =CONFIG_DEBUG_UART_PHYS
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#else /* !CONFIG_MMU */
|
||||
.macro addruart_current, rx, tmp1, tmp2
|
||||
addruart \rx, \tmp1
|
||||
addruart \rx, \tmp1, \tmp2
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
|
|
@ -19,6 +19,7 @@ config ARCH_BCM_IPROC
|
|||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_AMBA
|
||||
select PINCTRL
|
||||
select MTD_NAND_BRCMNAND
|
||||
help
|
||||
This enables support for systems based on Broadcom IPROC architected SoCs.
|
||||
The IPROC complex contains one or more ARM CPUs along with common
|
||||
|
@ -144,6 +145,7 @@ config ARCH_BRCMSTB
|
|||
select BRCMSTB_GISB_ARB
|
||||
select BRCMSTB_L2_IRQ
|
||||
select BCM7120_L2_IRQ
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
help
|
||||
Say Y if you intend to run the kernel on a Broadcom ARM-based STB
|
||||
chipset.
|
||||
|
|
|
@ -38,7 +38,12 @@ obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o
|
|||
obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o
|
||||
|
||||
# BCM63XXx
|
||||
obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o
|
||||
ifeq ($(CONFIG_ARCH_BCM_63XX),y)
|
||||
CFLAGS_bcm63xx_headsmp.o += -march=armv7-a
|
||||
obj-y += bcm63xx.o
|
||||
obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_headsmp.o \
|
||||
bcm63xx_pmb.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_BRCMSTB),y)
|
||||
CFLAGS_platsmp-brcmstb.o += -march=armv7-a
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Broadcom Corporation
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
ENTRY(bcm63138_secondary_startup)
|
||||
ARM_BE8(setend be)
|
||||
/*
|
||||
* L1 cache does have unpredictable contents at power-up clean its
|
||||
* contents without flushing
|
||||
*/
|
||||
bl v7_invalidate_l1
|
||||
nop
|
||||
|
||||
b secondary_startup
|
||||
ENDPROC(bcm63138_secondary_startup)
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Broadcom BCM63138 PMB initialization for secondary CPU(s)
|
||||
*
|
||||
* Copyright (C) 2015 Broadcom Corporation
|
||||
* Author: Florian Fainelli <f.fainelli@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/reset/bcm63xx_pmb.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "bcm63xx_smp.h"
|
||||
|
||||
/* ARM Control register definitions */
|
||||
#define CORE_PWR_CTRL_SHIFT 0
|
||||
#define CORE_PWR_CTRL_MASK 0x3
|
||||
#define PLL_PWR_ON BIT(8)
|
||||
#define PLL_LDO_PWR_ON BIT(9)
|
||||
#define PLL_CLAMP_ON BIT(10)
|
||||
#define CPU_RESET_N(x) BIT(13 + (x))
|
||||
#define NEON_RESET_N BIT(15)
|
||||
#define PWR_CTRL_STATUS_SHIFT 28
|
||||
#define PWR_CTRL_STATUS_MASK 0x3
|
||||
#define PWR_DOWN_SHIFT 30
|
||||
#define PWR_DOWN_MASK 0x3
|
||||
|
||||
/* CPU Power control register definitions */
|
||||
#define MEM_PWR_OK BIT(0)
|
||||
#define MEM_PWR_ON BIT(1)
|
||||
#define MEM_CLAMP_ON BIT(2)
|
||||
#define MEM_PWR_OK_STATUS BIT(4)
|
||||
#define MEM_PWR_ON_STATUS BIT(5)
|
||||
#define MEM_PDA_SHIFT 8
|
||||
#define MEM_PDA_MASK 0xf
|
||||
#define MEM_PDA_CPU_MASK 0x1
|
||||
#define MEM_PDA_NEON_MASK 0xf
|
||||
#define CLAMP_ON BIT(15)
|
||||
#define PWR_OK_SHIFT 16
|
||||
#define PWR_OK_MASK 0xf
|
||||
#define PWR_ON_SHIFT 20
|
||||
#define PWR_CPU_MASK 0x03
|
||||
#define PWR_NEON_MASK 0x01
|
||||
#define PWR_ON_MASK 0xf
|
||||
#define PWR_OK_STATUS_SHIFT 24
|
||||
#define PWR_OK_STATUS_MASK 0xf
|
||||
#define PWR_ON_STATUS_SHIFT 28
|
||||
#define PWR_ON_STATUS_MASK 0xf
|
||||
|
||||
#define ARM_CONTROL 0x30
|
||||
#define ARM_PWR_CONTROL_BASE 0x34
|
||||
#define ARM_PWR_CONTROL(x) (ARM_PWR_CONTROL_BASE + (x) * 0x4)
|
||||
#define ARM_NEON_L2 0x3c
|
||||
|
||||
/* Perform a value write, then spin until the value shifted by
|
||||
* shift is seen, masked with mask and is different from cond.
|
||||
*/
|
||||
static int bpcm_wr_rd_mask(void __iomem *master,
|
||||
unsigned int addr, u32 off, u32 *val,
|
||||
u32 shift, u32 mask, u32 cond)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bpcm_wr(master, addr, off, *val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
do {
|
||||
ret = bpcm_rd(master, addr, off, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cpu_relax();
|
||||
} while (((*val >> shift) & mask) != cond);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Global lock to serialize accesses to the PMB registers while we
|
||||
* are bringing up the secondary CPU
|
||||
*/
|
||||
static DEFINE_SPINLOCK(pmb_lock);
|
||||
|
||||
static int bcm63xx_pmb_get_resources(struct device_node *dn,
|
||||
void __iomem **base,
|
||||
unsigned int *cpu,
|
||||
unsigned int *addr)
|
||||
{
|
||||
struct device_node *pmb_dn;
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32(dn, "reg", cpu);
|
||||
if (ret) {
|
||||
pr_err("CPU is missing a reg node\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_parse_phandle_with_args(dn, "resets", "#reset-cells",
|
||||
0, &args);
|
||||
if (ret) {
|
||||
pr_err("CPU is missing a resets phandle\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmb_dn = args.np;
|
||||
if (args.args_count != 2) {
|
||||
pr_err("reset-controller does not conform to reset-cells\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*base = of_iomap(args.np, 0);
|
||||
if (!*base) {
|
||||
pr_err("failed remapping PMB register\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* We do not need the number of zones */
|
||||
*addr = args.args[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bcm63xx_pmb_power_on_cpu(struct device_node *dn)
|
||||
{
|
||||
void __iomem *base;
|
||||
unsigned int cpu, addr;
|
||||
unsigned long flags;
|
||||
u32 val, ctrl;
|
||||
int ret;
|
||||
|
||||
ret = bcm63xx_pmb_get_resources(dn, &base, &cpu, &addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* We would not know how to enable a third and greater CPU */
|
||||
WARN_ON(cpu > 1);
|
||||
|
||||
spin_lock_irqsave(&pmb_lock, flags);
|
||||
|
||||
/* Check if the CPU is already on and save the ARM_CONTROL register
|
||||
* value since we will use it later for CPU de-assert once done with
|
||||
* the CPU-specific power sequence
|
||||
*/
|
||||
ret = bpcm_rd(base, addr, ARM_CONTROL, &ctrl);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (ctrl & CPU_RESET_N(cpu)) {
|
||||
pr_info("PMB: CPU%d is already powered on\n", cpu);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Power on PLL */
|
||||
ret = bpcm_rd(base, addr, ARM_PWR_CONTROL(cpu), &val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val |= (PWR_CPU_MASK << PWR_ON_SHIFT);
|
||||
|
||||
ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
|
||||
PWR_ON_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val |= (PWR_CPU_MASK << PWR_OK_SHIFT);
|
||||
|
||||
ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
|
||||
PWR_OK_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val &= ~CLAMP_ON;
|
||||
|
||||
ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Power on CPU<N> RAM */
|
||||
val &= ~(MEM_PDA_MASK << MEM_PDA_SHIFT);
|
||||
|
||||
ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val |= MEM_PWR_ON;
|
||||
|
||||
ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
|
||||
0, MEM_PWR_ON_STATUS, MEM_PWR_ON_STATUS);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val |= MEM_PWR_OK;
|
||||
|
||||
ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
|
||||
0, MEM_PWR_OK_STATUS, MEM_PWR_OK_STATUS);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
val &= ~MEM_CLAMP_ON;
|
||||
|
||||
ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* De-assert CPU reset */
|
||||
ctrl |= CPU_RESET_N(cpu);
|
||||
|
||||
ret = bpcm_wr(base, addr, ARM_CONTROL, ctrl);
|
||||
out:
|
||||
spin_unlock_irqrestore(&pmb_lock, flags);
|
||||
iounmap(base);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Broadcom BCM63138 DSL SoCs SMP support code
|
||||
*
|
||||
* Copyright (C) 2015, Broadcom Corporation
|
||||
*
|
||||
* Licensed under the terms of the GPLv2
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/vfp.h>
|
||||
|
||||
#include "bcm63xx_smp.h"
|
||||
|
||||
/* Size of mapped Cortex A9 SCU address space */
|
||||
#define CORTEX_A9_SCU_SIZE 0x58
|
||||
|
||||
/*
|
||||
* Enable the Cortex A9 Snoop Control Unit
|
||||
*
|
||||
* By the time this is called we already know there are multiple
|
||||
* cores present. We assume we're running on a Cortex A9 processor,
|
||||
* so any trouble getting the base address register or getting the
|
||||
* SCU base is a problem.
|
||||
*
|
||||
* Return 0 if successful or an error code otherwise.
|
||||
*/
|
||||
static int __init scu_a9_enable(void)
|
||||
{
|
||||
unsigned long config_base;
|
||||
void __iomem *scu_base;
|
||||
unsigned int i, ncores;
|
||||
|
||||
if (!scu_a9_has_base()) {
|
||||
pr_err("no configuration base address register!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Config base address register value is zero for uniprocessor */
|
||||
config_base = scu_a9_get_base();
|
||||
if (!config_base) {
|
||||
pr_err("hardware reports only one core\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
|
||||
if (!scu_base) {
|
||||
pr_err("failed to remap config base (%lu/%u) for SCU\n",
|
||||
config_base, CORTEX_A9_SCU_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
scu_enable(scu_base);
|
||||
|
||||
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
|
||||
if (ncores > nr_cpu_ids) {
|
||||
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
|
||||
ncores, nr_cpu_ids);
|
||||
ncores = nr_cpu_ids;
|
||||
}
|
||||
|
||||
/* The BCM63138 SoC has two Cortex-A9 CPUs, CPU0 features a complete
|
||||
* and fully functional VFP unit that can be used, but CPU1 does not.
|
||||
* Since we will not be able to trap kernel-mode NEON to force
|
||||
* migration to CPU0, just do not advertise VFP support at all.
|
||||
*
|
||||
* This will make vfp_init bail out and do not attempt to use VFP at
|
||||
* all, for kernel-mode NEON, we do not want to introduce any
|
||||
* conditionals in hot-paths, so we just restrict the system to UP.
|
||||
*/
|
||||
#ifdef CONFIG_VFP
|
||||
if (ncores > 1) {
|
||||
pr_warn("SMP: secondary CPUs lack VFP unit, disabling VFP\n");
|
||||
vfp_disable();
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
WARN(1, "SMP: kernel-mode NEON enabled, restricting to UP\n");
|
||||
ncores = 1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
|
||||
iounmap(scu_base); /* That's the last we'll need of this */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm63138_bootlut_ids[] = {
|
||||
{ .compatible = "brcm,bcm63138-bootlut", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
#define BOOTLUT_RESET_VECT 0x20
|
||||
|
||||
static int bcm63138_smp_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle)
|
||||
{
|
||||
void __iomem *bootlut_base;
|
||||
struct device_node *dn;
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
|
||||
dn = of_find_matching_node(NULL, bcm63138_bootlut_ids);
|
||||
if (!dn) {
|
||||
pr_err("SMP: unable to find bcm63138 boot LUT node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bootlut_base = of_iomap(dn, 0);
|
||||
of_node_put(dn);
|
||||
|
||||
if (!bootlut_base) {
|
||||
pr_err("SMP: unable to remap boot LUT base register\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Locate the secondary CPU node */
|
||||
dn = of_get_cpu_node(cpu_logical_map(cpu), NULL);
|
||||
if (!dn) {
|
||||
pr_err("SMP: failed to locate secondary CPU%d node\n", cpu);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Write the secondary init routine to the BootLUT reset vector */
|
||||
val = virt_to_phys(bcm63138_secondary_startup);
|
||||
writel_relaxed(val, bootlut_base + BOOTLUT_RESET_VECT);
|
||||
|
||||
/* Power up the core, will jump straight to its reset vector when we
|
||||
* return
|
||||
*/
|
||||
ret = bcm63xx_pmb_power_on_cpu(dn);
|
||||
if (ret)
|
||||
goto out;
|
||||
out:
|
||||
iounmap(bootlut_base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __init bcm63138_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = scu_a9_enable();
|
||||
if (ret) {
|
||||
pr_warn("SMP: Cortex-A9 SCU setup failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct smp_operations bcm63138_smp_ops __initdata = {
|
||||
.smp_prepare_cpus = bcm63138_smp_prepare_cpus,
|
||||
.smp_boot_secondary = bcm63138_smp_boot_secondary,
|
||||
};
|
||||
|
||||
CPU_METHOD_OF_DECLARE(bcm63138_smp, "brcm,bcm63138", &bcm63138_smp_ops);
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef __BCM63XX_SMP_H
|
||||
#define __BCM63XX_SMP_H
|
||||
|
||||
struct device_node;
|
||||
|
||||
extern void bcm63138_secondary_startup(void);
|
||||
extern int bcm63xx_pmb_power_on_cpu(struct device_node *dn);
|
||||
|
||||
#endif /* __BCM63XX_SMP_H */
|
|
@ -18,15 +18,16 @@ static bool first_fault = true;
|
|||
static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (fsr == 0x1c06 && first_fault) {
|
||||
if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) {
|
||||
first_fault = false;
|
||||
|
||||
/*
|
||||
* These faults with code 0x1c06 happens for no good reason,
|
||||
* possibly left over from the CFE boot loader.
|
||||
* These faults with codes 0x1406 (BCM4709) or 0x1c06 happens
|
||||
* for no good reason, possibly left over from the CFE boot
|
||||
* loader.
|
||||
*/
|
||||
pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n",
|
||||
addr, fsr);
|
||||
addr, fsr);
|
||||
|
||||
/* Returning non-zero causes fault display and panic */
|
||||
return 0;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/of_address.h>
|
||||
|
@ -22,97 +21,10 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#define PM_RSTC 0x1c
|
||||
#define PM_RSTS 0x20
|
||||
#define PM_WDOG 0x24
|
||||
|
||||
#define PM_PASSWORD 0x5a000000
|
||||
#define PM_RSTC_WRCFG_MASK 0x00000030
|
||||
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
|
||||
#define PM_RSTS_HADWRH_SET 0x00000040
|
||||
|
||||
#define BCM2835_PERIPH_PHYS 0x20000000
|
||||
#define BCM2835_PERIPH_VIRT 0xf0000000
|
||||
#define BCM2835_PERIPH_SIZE SZ_16M
|
||||
|
||||
static void __iomem *wdt_regs;
|
||||
|
||||
/*
|
||||
* The machine restart method can be called from an atomic context so we won't
|
||||
* be able to ioremap the regs then.
|
||||
*/
|
||||
static void bcm2835_setup_restart(void)
|
||||
{
|
||||
struct device_node *np = of_find_compatible_node(NULL, NULL,
|
||||
"brcm,bcm2835-pm-wdt");
|
||||
if (WARN(!np, "unable to setup watchdog restart"))
|
||||
return;
|
||||
|
||||
wdt_regs = of_iomap(np, 0);
|
||||
WARN(!wdt_regs, "failed to remap watchdog regs");
|
||||
}
|
||||
|
||||
static void bcm2835_restart(enum reboot_mode mode, const char *cmd)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (!wdt_regs)
|
||||
return;
|
||||
|
||||
/* use a timeout of 10 ticks (~150us) */
|
||||
writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
|
||||
val = readl_relaxed(wdt_regs + PM_RSTC);
|
||||
val &= ~PM_RSTC_WRCFG_MASK;
|
||||
val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
|
||||
writel_relaxed(val, wdt_regs + PM_RSTC);
|
||||
|
||||
/* No sleeping, possibly atomic. */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't really power off, but if we do the normal reset scheme, and
|
||||
* indicate to bootcode.bin not to reboot, then most of the chip will be
|
||||
* powered off.
|
||||
*/
|
||||
static void bcm2835_power_off(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* We set the watchdog hard reset bit here to distinguish this reset
|
||||
* from the normal (full) reset. bootcode.bin will not reboot after a
|
||||
* hard reset.
|
||||
*/
|
||||
val = readl_relaxed(wdt_regs + PM_RSTS);
|
||||
val &= ~PM_RSTC_WRCFG_MASK;
|
||||
val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
|
||||
writel_relaxed(val, wdt_regs + PM_RSTS);
|
||||
|
||||
/* Continue with normal reset mechanism */
|
||||
bcm2835_restart(REBOOT_HARD, "");
|
||||
}
|
||||
|
||||
static struct map_desc io_map __initdata = {
|
||||
.virtual = BCM2835_PERIPH_VIRT,
|
||||
.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
|
||||
.length = BCM2835_PERIPH_SIZE,
|
||||
.type = MT_DEVICE
|
||||
};
|
||||
|
||||
static void __init bcm2835_map_io(void)
|
||||
{
|
||||
iotable_init(&io_map, 1);
|
||||
}
|
||||
|
||||
static void __init bcm2835_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bcm2835_setup_restart();
|
||||
if (wdt_regs)
|
||||
pm_power_off = bcm2835_power_off;
|
||||
|
||||
bcm2835_init_clocks();
|
||||
|
||||
ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
|
||||
|
@ -129,9 +41,6 @@ static const char * const bcm2835_compat[] = {
|
|||
};
|
||||
|
||||
DT_MACHINE_START(BCM2835, "BCM2835")
|
||||
.map_io = bcm2835_map_io,
|
||||
.init_irq = irqchip_init,
|
||||
.init_machine = bcm2835_init,
|
||||
.restart = bcm2835_restart,
|
||||
.dt_compat = bcm2835_compat
|
||||
MACHINE_END
|
||||
|
|
|
@ -20,9 +20,14 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <linux/platform_data/spi-ep93xx.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/platform_data/video-ep93xx.h>
|
||||
#include <mach/gpio-ep93xx.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -40,6 +45,132 @@ static struct ep93xxfb_mach_info __initdata simone_fb_info = {
|
|||
.flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO lines used for MMC card detection.
|
||||
*/
|
||||
#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0
|
||||
|
||||
/*
|
||||
* Up to v1.3, the Sim.One used SFRMOUT as SD card chip select, but this goes
|
||||
* low between multi-message command blocks. From v1.4, it uses a GPIO instead.
|
||||
* v1.3 parts will still work, since the signal on SFRMOUT is automatic.
|
||||
*/
|
||||
#define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO1
|
||||
|
||||
/*
|
||||
* MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal,
|
||||
* you can leave these empty and pass NULL as .controller_data.
|
||||
*/
|
||||
|
||||
static int simone_mmc_spi_setup(struct spi_device *spi)
|
||||
{
|
||||
unsigned int gpio = MMC_CHIP_SELECT_GPIO;
|
||||
int err;
|
||||
|
||||
err = gpio_request(gpio, spi->modalias);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gpio_direction_output(gpio, 1);
|
||||
if (err) {
|
||||
gpio_free(gpio);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void simone_mmc_spi_cleanup(struct spi_device *spi)
|
||||
{
|
||||
unsigned int gpio = MMC_CHIP_SELECT_GPIO;
|
||||
|
||||
gpio_set_value(gpio, 1);
|
||||
gpio_direction_input(gpio);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
static void simone_mmc_spi_cs_control(struct spi_device *spi, int value)
|
||||
{
|
||||
gpio_set_value(MMC_CHIP_SELECT_GPIO, value);
|
||||
}
|
||||
|
||||
static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = {
|
||||
.setup = simone_mmc_spi_setup,
|
||||
.cleanup = simone_mmc_spi_cleanup,
|
||||
.cs_control = simone_mmc_spi_cs_control,
|
||||
};
|
||||
|
||||
/*
|
||||
* MMC card detection GPIO setup.
|
||||
*/
|
||||
|
||||
static int simone_mmc_spi_init(struct device *dev,
|
||||
irqreturn_t (*irq_handler)(int, void *), void *mmc)
|
||||
{
|
||||
unsigned int gpio = MMC_CARD_DETECT_GPIO;
|
||||
int irq, err;
|
||||
|
||||
err = gpio_request(gpio, dev_name(dev));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gpio_direction_input(gpio);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
irq = gpio_to_irq(gpio);
|
||||
if (irq < 0)
|
||||
goto fail;
|
||||
|
||||
err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING,
|
||||
"MMC card detect", mmc);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
printk(KERN_INFO "%s: using irq %d for MMC card detection\n",
|
||||
dev_name(dev), irq);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
gpio_free(gpio);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void simone_mmc_spi_exit(struct device *dev, void *mmc)
|
||||
{
|
||||
unsigned int gpio = MMC_CARD_DETECT_GPIO;
|
||||
|
||||
free_irq(gpio_to_irq(gpio), mmc);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data simone_mmc_spi_data = {
|
||||
.init = simone_mmc_spi_init,
|
||||
.exit = simone_mmc_spi_exit,
|
||||
.detect_delay = 500,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
};
|
||||
|
||||
static struct spi_board_info simone_spi_devices[] __initdata = {
|
||||
{
|
||||
.modalias = "mmc_spi",
|
||||
.controller_data = &simone_mmc_spi_ops,
|
||||
.platform_data = &simone_mmc_spi_data,
|
||||
/*
|
||||
* We use 10 MHz even though the maximum is 3.7 MHz. The driver
|
||||
* will limit it automatically to max. frequency.
|
||||
*/
|
||||
.max_speed_hz = 10 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_spi_info simone_spi_info __initdata = {
|
||||
.num_chipselect = ARRAY_SIZE(simone_spi_devices),
|
||||
};
|
||||
|
||||
static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
|
||||
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
|
||||
.sda_is_open_drain = 0,
|
||||
|
@ -74,6 +205,8 @@ static void __init simone_init_machine(void)
|
|||
ep93xx_register_fb(&simone_fb_info);
|
||||
ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
|
||||
ARRAY_SIZE(simone_i2c_board_info));
|
||||
ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
|
||||
ARRAY_SIZE(simone_spi_devices));
|
||||
simone_register_audio();
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,9 @@ extern void exynos_set_delayed_reset_assertion(bool enable);
|
|||
|
||||
extern void s5p_init_cpu(void __iomem *cpuid_addr);
|
||||
extern unsigned int samsung_rev(void);
|
||||
extern void __iomem *cpu_boot_reg_base(void);
|
||||
extern void exynos_core_restart(u32 core_id);
|
||||
extern int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr);
|
||||
extern int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr);
|
||||
|
||||
static inline void pmu_raw_writel(u32 val, u32 offset)
|
||||
{
|
||||
|
|
|
@ -234,7 +234,8 @@ static void __init exynos_dt_machine_init(void)
|
|||
exynos_sysram_init();
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
|
||||
if (of_machine_is_compatible("samsung,exynos4210"))
|
||||
if (of_machine_is_compatible("samsung,exynos4210") ||
|
||||
of_machine_is_compatible("samsung,exynos3250"))
|
||||
exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
|
||||
#endif
|
||||
if (of_machine_is_compatible("samsung,exynos4210") ||
|
||||
|
|
|
@ -49,6 +49,7 @@ static int exynos_do_idle(unsigned long mode)
|
|||
sysram_ns_base_addr + 0x24);
|
||||
__raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
|
||||
if (soc_is_exynos3250()) {
|
||||
flush_cache_all();
|
||||
exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
|
||||
SMC_POWERSTATE_IDLE, 0);
|
||||
exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER,
|
||||
|
@ -104,6 +105,22 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_get_cpu_boot_addr(int cpu, unsigned long *boot_addr)
|
||||
{
|
||||
void __iomem *boot_reg;
|
||||
|
||||
if (!sysram_ns_base_addr)
|
||||
return -ENODEV;
|
||||
|
||||
boot_reg = sysram_ns_base_addr + 0x1c;
|
||||
|
||||
if (soc_is_exynos4412())
|
||||
boot_reg += 4 * cpu;
|
||||
|
||||
*boot_addr = __raw_readl(boot_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_cpu_suspend(unsigned long arg)
|
||||
{
|
||||
flush_cache_all();
|
||||
|
@ -138,6 +155,7 @@ static int exynos_resume(void)
|
|||
static const struct firmware_ops exynos_firmware_ops = {
|
||||
.do_idle = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL,
|
||||
.set_cpu_boot_addr = exynos_set_cpu_boot_addr,
|
||||
.get_cpu_boot_addr = exynos_get_cpu_boot_addr,
|
||||
.cpu_boot = exynos_cpu_boot,
|
||||
.suspend = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL,
|
||||
.resume = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
|
||||
|
|
|
@ -169,7 +169,7 @@ int exynos_cluster_power_state(int cluster)
|
|||
S5P_CORE_LOCAL_PWR_EN);
|
||||
}
|
||||
|
||||
void __iomem *cpu_boot_reg_base(void)
|
||||
static void __iomem *cpu_boot_reg_base(void)
|
||||
{
|
||||
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
|
||||
return pmu_base_addr + S5P_INFORM5;
|
||||
|
@ -195,7 +195,7 @@ static inline void __iomem *cpu_boot_reg(int cpu)
|
|||
*
|
||||
* Currently this is needed only when booting secondary CPU on Exynos3250.
|
||||
*/
|
||||
static void exynos_core_restart(u32 core_id)
|
||||
void exynos_core_restart(u32 core_id)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
|
@ -210,7 +210,6 @@ static void exynos_core_restart(u32 core_id)
|
|||
val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
|
||||
pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
|
||||
|
||||
pr_info("CPU%u: Software reset\n", core_id);
|
||||
pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET);
|
||||
}
|
||||
|
||||
|
@ -248,6 +247,56 @@ static void exynos_secondary_init(unsigned int cpu)
|
|||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Try to set boot address using firmware first
|
||||
* and fall back to boot register if it fails.
|
||||
*/
|
||||
ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
goto fail;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg)) {
|
||||
ret = PTR_ERR(boot_reg);
|
||||
goto fail;
|
||||
}
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
ret = 0;
|
||||
}
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Try to get boot address using firmware first
|
||||
* and fall back to boot register if it fails.
|
||||
*/
|
||||
ret = call_firmware_op(get_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
goto fail;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg)) {
|
||||
ret = PTR_ERR(boot_reg);
|
||||
goto fail;
|
||||
}
|
||||
*boot_addr = __raw_readl(boot_reg);
|
||||
ret = 0;
|
||||
}
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
@ -307,22 +356,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
|
||||
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
||||
|
||||
/*
|
||||
* Try to set boot address using firmware first
|
||||
* and fall back to boot register if it fails.
|
||||
*/
|
||||
ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
ret = exynos_set_boot_addr(core_id, boot_addr);
|
||||
if (ret)
|
||||
goto fail;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg)) {
|
||||
ret = PTR_ERR(boot_reg);
|
||||
goto fail;
|
||||
}
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
}
|
||||
|
||||
call_firmware_op(cpu_boot, core_id);
|
||||
|
||||
|
@ -337,6 +373,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
udelay(10);
|
||||
}
|
||||
|
||||
if (pen_release != -1)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
|
@ -407,16 +446,9 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
|
|||
core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
||||
|
||||
ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
|
||||
if (ret && ret != -ENOSYS)
|
||||
ret = exynos_set_boot_addr(core_id, boot_addr);
|
||||
if (ret)
|
||||
break;
|
||||
if (ret == -ENOSYS) {
|
||||
void __iomem *boot_reg = cpu_boot_reg(core_id);
|
||||
|
||||
if (IS_ERR(boot_reg))
|
||||
break;
|
||||
__raw_writel(boot_addr, boot_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <asm/firmware.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
|
@ -209,6 +210,8 @@ static int exynos_cpu0_enter_aftr(void)
|
|||
* sequence, let's wait for one of these to happen
|
||||
*/
|
||||
while (exynos_cpu_power_state(1)) {
|
||||
unsigned long boot_addr;
|
||||
|
||||
/*
|
||||
* The other cpu may skip idle and boot back
|
||||
* up again
|
||||
|
@ -221,7 +224,11 @@ static int exynos_cpu0_enter_aftr(void)
|
|||
* boot back up again, getting stuck in the
|
||||
* boot rom code
|
||||
*/
|
||||
if (__raw_readl(cpu_boot_reg_base()) == 0)
|
||||
ret = exynos_get_boot_addr(1, &boot_addr);
|
||||
if (ret)
|
||||
goto fail;
|
||||
ret = -1;
|
||||
if (boot_addr == 0)
|
||||
goto abort;
|
||||
|
||||
cpu_relax();
|
||||
|
@ -233,11 +240,14 @@ static int exynos_cpu0_enter_aftr(void)
|
|||
|
||||
abort:
|
||||
if (cpu_online(1)) {
|
||||
unsigned long boot_addr = virt_to_phys(exynos_cpu_resume);
|
||||
|
||||
/*
|
||||
* Set the boot vector to something non-zero
|
||||
*/
|
||||
__raw_writel(virt_to_phys(exynos_cpu_resume),
|
||||
cpu_boot_reg_base());
|
||||
ret = exynos_set_boot_addr(1, boot_addr);
|
||||
if (ret)
|
||||
goto fail;
|
||||
dsb();
|
||||
|
||||
/*
|
||||
|
@ -247,22 +257,42 @@ abort:
|
|||
while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN)
|
||||
cpu_relax();
|
||||
|
||||
if (soc_is_exynos3250()) {
|
||||
while (!pmu_raw_readl(S5P_PMU_SPARE2) &&
|
||||
!atomic_read(&cpu1_wakeup))
|
||||
cpu_relax();
|
||||
|
||||
if (!atomic_read(&cpu1_wakeup))
|
||||
exynos_core_restart(1);
|
||||
}
|
||||
|
||||
while (!atomic_read(&cpu1_wakeup)) {
|
||||
smp_rmb();
|
||||
|
||||
/*
|
||||
* Poke cpu1 out of the boot rom
|
||||
*/
|
||||
__raw_writel(virt_to_phys(exynos_cpu_resume),
|
||||
cpu_boot_reg_base());
|
||||
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(1));
|
||||
ret = exynos_set_boot_addr(1, boot_addr);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
call_firmware_op(cpu_boot, 1);
|
||||
|
||||
if (soc_is_exynos3250())
|
||||
dsb_sev();
|
||||
else
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(1));
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_wfi_finisher(unsigned long flags)
|
||||
{
|
||||
if (soc_is_exynos3250())
|
||||
flush_cache_all();
|
||||
cpu_do_idle();
|
||||
|
||||
return -1;
|
||||
|
@ -283,6 +313,9 @@ static int exynos_cpu1_powerdown(void)
|
|||
*/
|
||||
exynos_cpu_power_down(1);
|
||||
|
||||
if (soc_is_exynos3250())
|
||||
pmu_raw_writel(0, S5P_PMU_SPARE2);
|
||||
|
||||
ret = cpu_suspend(0, exynos_wfi_finisher);
|
||||
|
||||
cpu_pm_exit();
|
||||
|
@ -299,7 +332,9 @@ cpu1_aborted:
|
|||
|
||||
static void exynos_pre_enter_aftr(void)
|
||||
{
|
||||
__raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base());
|
||||
unsigned long boot_addr = virt_to_phys(exynos_cpu_resume);
|
||||
|
||||
(void)exynos_set_boot_addr(1, boot_addr);
|
||||
}
|
||||
|
||||
static void exynos_post_enter_aftr(void)
|
||||
|
|
|
@ -62,6 +62,7 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
pd->pclk[i] = clk_get_parent(pd->clk[i]);
|
||||
if (clk_set_parent(pd->clk[i], pd->oscclk))
|
||||
pr_err("%s: error setting oscclk as parent to clock %d\n",
|
||||
pd->name, i);
|
||||
|
@ -90,6 +91,9 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
continue; /* Skip on first power up */
|
||||
if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
||||
pr_err("%s: error setting parent to clock%d\n",
|
||||
pd->name, i);
|
||||
|
@ -117,27 +121,37 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
|
|||
|
||||
static __init int exynos4_pm_init_power_domain(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct device_node *np;
|
||||
|
||||
for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
|
||||
struct exynos_pm_domain *pd;
|
||||
int on, i;
|
||||
struct device *dev;
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
dev = &pdev->dev;
|
||||
|
||||
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
pr_err("%s: failed to allocate memory for domain\n",
|
||||
__func__);
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
pd->pd.name = kstrdup_const(strrchr(np->full_name, '/') + 1,
|
||||
GFP_KERNEL);
|
||||
if (!pd->pd.name) {
|
||||
kfree(pd);
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->pd.name = kstrdup(dev_name(dev), GFP_KERNEL);
|
||||
pd->name = pd->pd.name;
|
||||
pd->base = of_iomap(np, 0);
|
||||
if (!pd->base) {
|
||||
pr_warn("%s: failed to map memory\n", __func__);
|
||||
kfree(pd->pd.name);
|
||||
kfree(pd);
|
||||
of_node_put(np);
|
||||
continue;
|
||||
}
|
||||
|
||||
pd->pd.power_off = exynos_pd_power_off;
|
||||
pd->pd.power_on = exynos_pd_power_on;
|
||||
|
||||
|
@ -145,12 +159,12 @@ static __init int exynos4_pm_init_power_domain(void)
|
|||
char clk_name[8];
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "asb%d", i);
|
||||
pd->asb_clk[i] = clk_get(dev, clk_name);
|
||||
pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
|
||||
if (IS_ERR(pd->asb_clk[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
pd->oscclk = clk_get(dev, "oscclk");
|
||||
pd->oscclk = of_clk_get_by_name(np, "oscclk");
|
||||
if (IS_ERR(pd->oscclk))
|
||||
goto no_clk;
|
||||
|
||||
|
@ -158,16 +172,14 @@ static __init int exynos4_pm_init_power_domain(void)
|
|||
char clk_name[8];
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "clk%d", i);
|
||||
pd->clk[i] = clk_get(dev, clk_name);
|
||||
pd->clk[i] = of_clk_get_by_name(np, clk_name);
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
snprintf(clk_name, sizeof(clk_name), "pclk%d", i);
|
||||
pd->pclk[i] = clk_get(dev, clk_name);
|
||||
if (IS_ERR(pd->pclk[i])) {
|
||||
clk_put(pd->clk[i]);
|
||||
pd->clk[i] = ERR_PTR(-EINVAL);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Skip setting parent on first power up.
|
||||
* The parent at this time may not be useful at all.
|
||||
*/
|
||||
pd->pclk[i] = ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (IS_ERR(pd->clk[0]))
|
||||
|
@ -189,15 +201,15 @@ no_clk:
|
|||
args.args_count = 0;
|
||||
child_domain = of_genpd_get_from_provider(&args);
|
||||
if (IS_ERR(child_domain))
|
||||
continue;
|
||||
goto next_pd;
|
||||
|
||||
if (of_parse_phandle_with_args(np, "power-domains",
|
||||
"#power-domain-cells", 0, &args) != 0)
|
||||
continue;
|
||||
goto next_pd;
|
||||
|
||||
parent_domain = of_genpd_get_from_provider(&args);
|
||||
if (IS_ERR(parent_domain))
|
||||
continue;
|
||||
goto next_pd;
|
||||
|
||||
if (pm_genpd_add_subdomain(parent_domain, child_domain))
|
||||
pr_warn("%s failed to add subdomain: %s\n",
|
||||
|
@ -205,9 +217,10 @@ no_clk:
|
|||
else
|
||||
pr_info("%s has as child subdomain: %s.\n",
|
||||
parent_domain->name, child_domain->name);
|
||||
next_pd:
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(exynos4_pm_init_power_domain);
|
||||
core_initcall(exynos4_pm_init_power_domain);
|
||||
|
|
|
@ -681,7 +681,7 @@ static unsigned int const exynos5420_list_disable_pmu_reg[] = {
|
|||
EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,
|
||||
};
|
||||
|
||||
static void exynos5_power_off(void)
|
||||
static void exynos_power_off(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
|
@ -872,8 +872,6 @@ static void exynos5420_pmu_init(void)
|
|||
EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);
|
||||
|
||||
pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
|
||||
|
||||
pm_power_off = exynos5_power_off;
|
||||
pr_info("EXYNOS5420 PMU initialized\n");
|
||||
}
|
||||
|
||||
|
@ -984,6 +982,8 @@ static int exynos_pmu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
dev_warn(dev, "can't register restart handler err=%d\n", ret);
|
||||
|
||||
pm_power_off = exynos_power_off;
|
||||
|
||||
dev_dbg(dev, "Exynos PMU Driver probe done\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ static int exynos_pmu_domain_alloc(struct irq_domain *domain,
|
|||
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops exynos_pmu_domain_ops = {
|
||||
static const struct irq_domain_ops exynos_pmu_domain_ops = {
|
||||
.xlate = exynos_pmu_domain_xlate,
|
||||
.alloc = exynos_pmu_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
menuconfig ARCH_MXC
|
||||
bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
|
||||
bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 || ARM_SINGLE_ARMV7M
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_CPU_SUSPEND if PM
|
||||
select CLKSRC_MMIO
|
||||
select CLKSRC_IMX_GPT
|
||||
select GENERIC_IRQ_CHIP
|
||||
select PINCTRL
|
||||
select PM_OPP if PM
|
||||
|
@ -462,10 +462,10 @@ config MACH_VPR200
|
|||
|
||||
endif
|
||||
|
||||
if ARCH_MULTI_V5
|
||||
|
||||
comment "Device tree only"
|
||||
|
||||
if ARCH_MULTI_V5
|
||||
|
||||
config SOC_IMX25
|
||||
bool "i.MX25 support"
|
||||
select ARCH_MXC_IOMUX_V3
|
||||
|
@ -478,7 +478,7 @@ endif
|
|||
|
||||
if ARCH_MULTI_V7
|
||||
|
||||
comment "Device tree only"
|
||||
comment "Cortex-A platforms"
|
||||
|
||||
config SOC_IMX5
|
||||
bool
|
||||
|
@ -548,10 +548,33 @@ config SOC_IMX6SX
|
|||
help
|
||||
This enables support for Freescale i.MX6 SoloX processor.
|
||||
|
||||
config SOC_IMX7D
|
||||
bool "i.MX7 Dual support"
|
||||
select PINCTRL_IMX7D
|
||||
select ARM_GIC
|
||||
select HAVE_IMX_ANATOP
|
||||
select HAVE_IMX_MMDC
|
||||
help
|
||||
This enables support for Freescale i.MX7 Dual processor.
|
||||
|
||||
config SOC_LS1021A
|
||||
bool "Freescale LS1021A support"
|
||||
select ARM_GIC
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select PCI_DOMAINS if PCI
|
||||
select ZONE_DMA if ARM_LPAE
|
||||
help
|
||||
This enables support for Freescale LS1021A processor.
|
||||
|
||||
endif
|
||||
|
||||
comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms"
|
||||
|
||||
if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
|
||||
|
||||
config SOC_VF610
|
||||
bool "Vybrid Family VF610 support"
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select ARM_GIC
|
||||
select ARM_GIC if ARCH_MULTI_V7
|
||||
select PINCTRL_VF610
|
||||
select PL310_ERRATA_769419 if CACHE_L2X0
|
||||
select SMP_ON_UP if SMP
|
||||
|
@ -565,7 +588,7 @@ choice
|
|||
default VF_USE_ARM_GLOBAL_TIMER
|
||||
|
||||
config VF_USE_ARM_GLOBAL_TIMER
|
||||
bool "Use ARM Global Timer"
|
||||
bool "Use ARM Global Timer" if ARCH_MULTI_V7
|
||||
select ARM_GLOBAL_TIMER
|
||||
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
|
||||
help
|
||||
|
@ -579,16 +602,6 @@ choice
|
|||
|
||||
endchoice
|
||||
|
||||
config SOC_LS1021A
|
||||
bool "Freescale LS1021A support"
|
||||
select ARM_GIC
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select PCI_DOMAINS if PCI
|
||||
select ZONE_DMA if ARM_LPAE
|
||||
|
||||
help
|
||||
This enables support for Freescale LS1021A processor.
|
||||
|
||||
endif
|
||||
|
||||
source "arch/arm/mach-imx/devices/Kconfig"
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
obj-y := time.o cpu.o system.o irq-common.o
|
||||
obj-y := cpu.o system.o irq-common.o
|
||||
|
||||
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
|
||||
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
|
||||
obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
|
||||
obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
|
||||
|
||||
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o cpu-imx25.o mach-imx25.o
|
||||
obj-$(CONFIG_SOC_IMX25) += cpu-imx25.o mach-imx25.o
|
||||
|
||||
obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
|
||||
obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
|
||||
obj-$(CONFIG_SOC_IMX27) += mm-imx27.o ehci-imx27.o
|
||||
|
||||
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
|
||||
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
|
||||
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
|
||||
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o ehci-imx35.o pm-imx3.o
|
||||
|
||||
imx5-pm-$(CONFIG_PM) += pm-imx5.o
|
||||
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
|
||||
clk-pfd.o clk-busy.o clk.o \
|
||||
clk-fixup-div.o clk-fixup-mux.o \
|
||||
clk-gate-exclusive.o
|
||||
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o $(imx5-pm-y)
|
||||
|
||||
obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
|
||||
obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
|
||||
|
@ -85,13 +80,15 @@ AFLAGS_headsmp.o :=-Wa,-march=armv7-a
|
|||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
endif
|
||||
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
|
||||
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
|
||||
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o
|
||||
obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
|
||||
obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
|
||||
obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
|
||||
obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
|
||||
|
||||
ifeq ($(CONFIG_SUSPEND),y)
|
||||
AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
|
||||
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
|
||||
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
|
||||
endif
|
||||
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
|
||||
|
||||
|
@ -99,7 +96,7 @@ obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
|
|||
obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
|
||||
obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
|
||||
|
||||
obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
|
||||
obj-$(CONFIG_SOC_VF610) += mach-vf610.o
|
||||
|
||||
obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
|
@ -28,6 +28,7 @@
|
|||
#define ANADIG_USB2_CHRG_DETECT 0x210
|
||||
#define ANADIG_DIGPROG 0x260
|
||||
#define ANADIG_DIGPROG_IMX6SL 0x280
|
||||
#define ANADIG_DIGPROG_IMX7D 0x800
|
||||
|
||||
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
|
||||
#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8
|
||||
|
@ -121,6 +122,8 @@ void __init imx_init_revision_from_anatop(void)
|
|||
WARN_ON(!anatop_base);
|
||||
if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
|
||||
offset = ANADIG_DIGPROG_IMX6SL;
|
||||
if (of_device_is_compatible(np, "fsl,imx7d-anatop"))
|
||||
offset = ANADIG_DIGPROG_IMX7D;
|
||||
digprog = readl_relaxed(anatop_base + offset);
|
||||
iounmap(anatop_base);
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ void imx27_soc_init(void);
|
|||
void imx31_soc_init(void);
|
||||
void imx35_soc_init(void);
|
||||
void epit_timer_init(void __iomem *base, int irq);
|
||||
void mxc_timer_init(void __iomem *, int);
|
||||
int mx1_clocks_init(unsigned long fref);
|
||||
int mx21_clocks_init(unsigned long lref, unsigned long fref);
|
||||
int mx27_clocks_init(unsigned long fref);
|
||||
|
@ -56,13 +55,10 @@ struct platform_device *mxc_register_gpio(char *name, int id,
|
|||
void mxc_set_cpu_type(unsigned int type);
|
||||
void mxc_restart(enum reboot_mode, const char *);
|
||||
void mxc_arch_reset_init(void __iomem *);
|
||||
int mx51_revision(void);
|
||||
int mx53_revision(void);
|
||||
void imx_set_aips(void __iomem *);
|
||||
void imx_aips_allow_unprivileged_access(const char *compat);
|
||||
int mxc_device_init(void);
|
||||
void imx_set_soc_revision(unsigned int rev);
|
||||
unsigned int imx_get_soc_revision(void);
|
||||
void imx_init_revision_from_anatop(void);
|
||||
struct device *imx_soc_device_init(void);
|
||||
void imx6_enable_rbc(bool enable);
|
||||
|
@ -87,7 +83,6 @@ enum mx3_cpu_pwr_mode {
|
|||
};
|
||||
|
||||
void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
|
||||
void imx_print_silicon_rev(const char *cpu, int srev);
|
||||
|
||||
void imx_enable_cpu(int cpu, bool enable);
|
||||
void imx_set_cpu_jump(int cpu, void *jump_addr);
|
||||
|
@ -111,7 +106,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq);
|
|||
void imx_anatop_init(void);
|
||||
void imx_anatop_pre_suspend(void);
|
||||
void imx_anatop_post_resume(void);
|
||||
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
|
||||
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
|
||||
void imx6q_set_int_mem_clk_lpm(bool enable);
|
||||
void imx6sl_set_wait_clk(bool enter);
|
||||
int imx_mmdc_get_ddr_type(void);
|
||||
|
@ -121,26 +116,28 @@ int imx_cpu_kill(unsigned int cpu);
|
|||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
void v7_cpu_resume(void);
|
||||
void imx53_suspend(void __iomem *ocram_vbase);
|
||||
extern const u32 imx53_suspend_sz;
|
||||
void imx6_suspend(void __iomem *ocram_vbase);
|
||||
#else
|
||||
static inline void v7_cpu_resume(void) {}
|
||||
static inline void imx53_suspend(void __iomem *ocram_vbase) {}
|
||||
static const u32 imx53_suspend_sz;
|
||||
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
|
||||
#endif
|
||||
|
||||
void imx6_pm_ccm_init(const char *ccm_compat);
|
||||
void imx6q_pm_init(void);
|
||||
void imx6dl_pm_init(void);
|
||||
void imx6sl_pm_init(void);
|
||||
void imx6sx_pm_init(void);
|
||||
void imx6q_pm_set_ccm_base(void __iomem *base);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void imx51_pm_init(void);
|
||||
void imx53_pm_init(void);
|
||||
void imx5_pm_set_ccm_base(void __iomem *base);
|
||||
#else
|
||||
static inline void imx51_pm_init(void) {}
|
||||
static inline void imx53_pm_init(void) {}
|
||||
static inline void imx5_pm_set_ccm_base(void __iomem *base) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NEON
|
||||
|
|
|
@ -130,6 +130,9 @@ struct device * __init imx_soc_device_init(void)
|
|||
case MXC_CPU_IMX6Q:
|
||||
soc_id = "i.MX6Q";
|
||||
break;
|
||||
case MXC_CPU_IMX7D:
|
||||
soc_id = "i.MX7D";
|
||||
break;
|
||||
default:
|
||||
soc_id = "Unknown";
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ static int imx6q_enter_wait(struct cpuidle_device *dev,
|
|||
*/
|
||||
if (!spin_trylock(&master_lock))
|
||||
goto idle;
|
||||
imx6q_set_lpm(WAIT_UNCLOCKED);
|
||||
imx6_set_lpm(WAIT_UNCLOCKED);
|
||||
cpu_do_idle();
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
imx6_set_lpm(WAIT_CLOCKED);
|
||||
spin_unlock(&master_lock);
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
static int imx6sl_enter_wait(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index)
|
||||
{
|
||||
imx6q_set_lpm(WAIT_UNCLOCKED);
|
||||
imx6_set_lpm(WAIT_UNCLOCKED);
|
||||
/*
|
||||
* Software workaround for ERR005311, see function
|
||||
* description for details.
|
||||
|
@ -24,7 +24,7 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev,
|
|||
imx6sl_set_wait_clk(true);
|
||||
cpu_do_idle();
|
||||
imx6sl_set_wait_clk(false);
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
imx6_set_lpm(WAIT_CLOCKED);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ static int imx6sx_idle_finish(unsigned long val)
|
|||
static int imx6sx_enter_wait(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int index)
|
||||
{
|
||||
imx6q_set_lpm(WAIT_UNCLOCKED);
|
||||
imx6_set_lpm(WAIT_UNCLOCKED);
|
||||
|
||||
switch (index) {
|
||||
case 1:
|
||||
|
@ -50,7 +50,7 @@ static int imx6sx_enter_wait(struct cpuidle_device *dev,
|
|||
break;
|
||||
}
|
||||
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
imx6_set_lpm(WAIT_CLOCKED);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
|
|||
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops imx_gpc_domain_ops = {
|
||||
static const struct irq_domain_ops imx_gpc_domain_ops = {
|
||||
.xlate = imx_gpc_domain_xlate,
|
||||
.alloc = imx_gpc_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <asm/io.h>
|
||||
#include <soc/imx/revision.h>
|
||||
#endif
|
||||
#include <asm/sizes.h>
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(gpio_mux_lock);
|
|||
|
||||
#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
|
||||
|
||||
static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
|
||||
static DECLARE_BITMAP(mxc_pin_alloc_map, NB_PORTS * 32);
|
||||
/*
|
||||
* set the mode for a IOMUX pin.
|
||||
*/
|
||||
|
|
|
@ -393,6 +393,7 @@ static void __init imx6q_init_irq(void)
|
|||
imx_init_l2cache();
|
||||
imx_src_init();
|
||||
irqchip_init();
|
||||
imx6_pm_ccm_init("fsl,imx6q-ccm");
|
||||
}
|
||||
|
||||
static const char * const imx6q_dt_compat[] __initconst = {
|
||||
|
|
|
@ -66,6 +66,7 @@ static void __init imx6sl_init_irq(void)
|
|||
imx_init_l2cache();
|
||||
imx_src_init();
|
||||
irqchip_init();
|
||||
imx6_pm_ccm_init("fsl,imx6sl-ccm");
|
||||
}
|
||||
|
||||
static const char * const imx6sl_dt_compat[] __initconst = {
|
||||
|
|
|
@ -86,6 +86,7 @@ static void __init imx6sx_init_irq(void)
|
|||
imx_init_l2cache();
|
||||
imx_src_init();
|
||||
irqchip_init();
|
||||
imx6_pm_ccm_init("fsl,imx6sx-ccm");
|
||||
}
|
||||
|
||||
static void __init imx6sx_init_late(void)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void __init imx7d_init_machine(void)
|
||||
{
|
||||
struct device *parent;
|
||||
|
||||
parent = imx_soc_device_init();
|
||||
if (parent == NULL)
|
||||
pr_warn("failed to initialize soc device\n");
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
imx_anatop_init();
|
||||
}
|
||||
|
||||
static void __init imx7d_init_irq(void)
|
||||
{
|
||||
imx_init_revision_from_anatop();
|
||||
imx_src_init();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
static const char *imx7d_dt_compat[] __initconst = {
|
||||
"fsl,imx7d",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
|
||||
.init_irq = imx7d_init_irq,
|
||||
.init_machine = imx7d_init_machine,
|
||||
.dt_compat = imx7d_dt_compat,
|
||||
MACHINE_END
|
|
@ -17,6 +17,7 @@ static const char * const vf610_dt_compat[] __initconst = {
|
|||
"fsl,vf510",
|
||||
"fsl,vf600",
|
||||
"fsl,vf610",
|
||||
"fsl,vf610m4",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MMDC_MAPSR 0x404
|
||||
#define BP_MMDC_MAPSR_PSD 0
|
||||
#define BP_MMDC_MAPSR_PSS 4
|
||||
|
|
|
@ -231,8 +231,4 @@
|
|||
#define MX27_DMA_REQ_SDHC3 36
|
||||
#define MX27_DMA_REQ_NFC 37
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern int mx27_revision(void);
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __MACH_MX27_H__ */
|
||||
|
|
|
@ -185,11 +185,4 @@
|
|||
|
||||
#define MX3x_PROD_SIGNATURE 0x1 /* For MX31 */
|
||||
|
||||
/* Mandatory defines used globally */
|
||||
|
||||
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
|
||||
extern int mx35_revision(void);
|
||||
extern int mx31_revision(void);
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __MACH_MX3x_H__ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
* Copyright 2004-2007, 2010-2015 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -38,22 +38,7 @@
|
|||
#define MXC_CPU_IMX6DL 0x61
|
||||
#define MXC_CPU_IMX6SX 0x62
|
||||
#define MXC_CPU_IMX6Q 0x63
|
||||
|
||||
#define IMX_CHIP_REVISION_1_0 0x10
|
||||
#define IMX_CHIP_REVISION_1_1 0x11
|
||||
#define IMX_CHIP_REVISION_1_2 0x12
|
||||
#define IMX_CHIP_REVISION_1_3 0x13
|
||||
#define IMX_CHIP_REVISION_1_4 0x14
|
||||
#define IMX_CHIP_REVISION_1_5 0x15
|
||||
#define IMX_CHIP_REVISION_2_0 0x20
|
||||
#define IMX_CHIP_REVISION_2_1 0x21
|
||||
#define IMX_CHIP_REVISION_2_2 0x22
|
||||
#define IMX_CHIP_REVISION_2_3 0x23
|
||||
#define IMX_CHIP_REVISION_3_0 0x30
|
||||
#define IMX_CHIP_REVISION_3_1 0x31
|
||||
#define IMX_CHIP_REVISION_3_2 0x32
|
||||
#define IMX_CHIP_REVISION_3_3 0x33
|
||||
#define IMX_CHIP_REVISION_UNKNOWN 0xff
|
||||
#define MXC_CPU_IMX7D 0x72
|
||||
|
||||
#define IMX_DDR_TYPE_LPDDR2 1
|
||||
|
||||
|
@ -185,6 +170,11 @@ static inline bool cpu_is_imx6q(void)
|
|||
return __mxc_cpu_type == MXC_CPU_IMX6Q;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx7d(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX7D;
|
||||
}
|
||||
|
||||
struct cpu_op {
|
||||
u32 cpu_rate;
|
||||
};
|
||||
|
|
|
@ -13,7 +13,14 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/fncpy.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
|
@ -49,29 +56,91 @@
|
|||
*/
|
||||
#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
|
||||
|
||||
struct imx5_suspend_io_state {
|
||||
u32 offset;
|
||||
u32 clear;
|
||||
u32 set;
|
||||
u32 saved_value;
|
||||
};
|
||||
|
||||
struct imx5_pm_data {
|
||||
phys_addr_t ccm_addr;
|
||||
phys_addr_t cortex_addr;
|
||||
phys_addr_t gpc_addr;
|
||||
phys_addr_t m4if_addr;
|
||||
phys_addr_t iomuxc_addr;
|
||||
void (*suspend_asm)(void __iomem *ocram_vbase);
|
||||
const u32 *suspend_asm_sz;
|
||||
const struct imx5_suspend_io_state *suspend_io_config;
|
||||
int suspend_io_count;
|
||||
};
|
||||
|
||||
static const struct imx5_suspend_io_state imx53_suspend_io_config[] = {
|
||||
#define MX53_DSE_HIGHZ_MASK (0x7 << 19)
|
||||
{.offset = 0x584, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM0 */
|
||||
{.offset = 0x594, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM1 */
|
||||
{.offset = 0x560, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM2 */
|
||||
{.offset = 0x554, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM3 */
|
||||
{.offset = 0x574, .clear = MX53_DSE_HIGHZ_MASK}, /* CAS */
|
||||
{.offset = 0x588, .clear = MX53_DSE_HIGHZ_MASK}, /* RAS */
|
||||
{.offset = 0x578, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_0 */
|
||||
{.offset = 0x570, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_1 */
|
||||
|
||||
{.offset = 0x580, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT0 */
|
||||
{.offset = 0x564, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT1 */
|
||||
{.offset = 0x57c, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS0 */
|
||||
{.offset = 0x590, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS1 */
|
||||
{.offset = 0x568, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS2 */
|
||||
{.offset = 0x558, .clear = MX53_DSE_HIGHZ_MASK}, /* SDSQ3 */
|
||||
{.offset = 0x6f0, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_ADDS */
|
||||
{.offset = 0x718, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_BODS */
|
||||
{.offset = 0x71c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B1DS */
|
||||
{.offset = 0x728, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B2DS */
|
||||
{.offset = 0x72c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B3DS */
|
||||
|
||||
/* Controls the CKE signal which is required to leave self refresh */
|
||||
{.offset = 0x720, .clear = MX53_DSE_HIGHZ_MASK, .set = 1 << 19}, /* CTLDS */
|
||||
};
|
||||
|
||||
static const struct imx5_pm_data imx51_pm_data __initconst = {
|
||||
.ccm_addr = 0x73fd4000,
|
||||
.cortex_addr = 0x83fa0000,
|
||||
.gpc_addr = 0x73fd8000,
|
||||
};
|
||||
|
||||
static const struct imx5_pm_data imx53_pm_data __initconst = {
|
||||
.ccm_addr = 0x53fd4000,
|
||||
.cortex_addr = 0x63fa0000,
|
||||
.gpc_addr = 0x53fd8000,
|
||||
.m4if_addr = 0x63fd8000,
|
||||
.iomuxc_addr = 0x53fa8000,
|
||||
.suspend_asm = &imx53_suspend,
|
||||
.suspend_asm_sz = &imx53_suspend_sz,
|
||||
.suspend_io_config = imx53_suspend_io_config,
|
||||
.suspend_io_count = ARRAY_SIZE(imx53_suspend_io_config),
|
||||
};
|
||||
|
||||
#define MX5_MAX_SUSPEND_IOSTATE ARRAY_SIZE(imx53_suspend_io_config)
|
||||
|
||||
/*
|
||||
* This structure is for passing necessary data for low level ocram
|
||||
* suspend code(arch/arm/mach-imx/suspend-imx53.S), if this struct
|
||||
* definition is changed, the offset definition in that file
|
||||
* must be also changed accordingly otherwise, the suspend to ocram
|
||||
* function will be broken!
|
||||
*/
|
||||
struct imx5_cpu_suspend_info {
|
||||
void __iomem *m4if_base;
|
||||
void __iomem *iomuxc_base;
|
||||
u32 io_count;
|
||||
struct imx5_suspend_io_state io_state[MX5_MAX_SUSPEND_IOSTATE];
|
||||
} __aligned(8);
|
||||
|
||||
static void __iomem *ccm_base;
|
||||
static void __iomem *cortex_base;
|
||||
static void __iomem *gpc_base;
|
||||
|
||||
void __init imx5_pm_set_ccm_base(void __iomem *base)
|
||||
{
|
||||
ccm_base = base;
|
||||
}
|
||||
static void __iomem *suspend_ocram_base;
|
||||
static void (*imx5_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
|
||||
|
||||
/*
|
||||
* set cpu low power mode before WFI instruction. This function is called
|
||||
|
@ -161,8 +230,15 @@ static int mx5_suspend_enter(suspend_state_t state)
|
|||
/*clear the EMPGC0/1 bits */
|
||||
__raw_writel(0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
|
||||
__raw_writel(0, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
|
||||
|
||||
if (imx5_suspend_in_ocram_fn)
|
||||
imx5_suspend_in_ocram_fn(suspend_ocram_base);
|
||||
else
|
||||
cpu_do_idle();
|
||||
|
||||
} else {
|
||||
cpu_do_idle();
|
||||
}
|
||||
cpu_do_idle();
|
||||
|
||||
/* return registers to default idle state */
|
||||
mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
|
||||
|
@ -194,6 +270,111 @@ static void imx5_pm_idle(void)
|
|||
imx5_cpu_do_idle();
|
||||
}
|
||||
|
||||
static int __init imx_suspend_alloc_ocram(
|
||||
size_t size,
|
||||
void __iomem **virt_out,
|
||||
phys_addr_t *phys_out)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct platform_device *pdev;
|
||||
struct gen_pool *ocram_pool;
|
||||
unsigned long ocram_base;
|
||||
void __iomem *virt;
|
||||
phys_addr_t phys;
|
||||
int ret = 0;
|
||||
|
||||
/* Copied from imx6: TODO factorize */
|
||||
node = of_find_compatible_node(NULL, NULL, "mmio-sram");
|
||||
if (!node) {
|
||||
pr_warn("%s: failed to find ocram node!\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdev = of_find_device_by_node(node);
|
||||
if (!pdev) {
|
||||
pr_warn("%s: failed to find ocram device!\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto put_node;
|
||||
}
|
||||
|
||||
ocram_pool = dev_get_gen_pool(&pdev->dev);
|
||||
if (!ocram_pool) {
|
||||
pr_warn("%s: ocram pool unavailable!\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto put_node;
|
||||
}
|
||||
|
||||
ocram_base = gen_pool_alloc(ocram_pool, size);
|
||||
if (!ocram_base) {
|
||||
pr_warn("%s: unable to alloc ocram!\n", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto put_node;
|
||||
}
|
||||
|
||||
phys = gen_pool_virt_to_phys(ocram_pool, ocram_base);
|
||||
virt = __arm_ioremap_exec(phys, size, false);
|
||||
if (phys_out)
|
||||
*phys_out = phys;
|
||||
if (virt_out)
|
||||
*virt_out = virt;
|
||||
|
||||
put_node:
|
||||
of_node_put(node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init imx5_suspend_init(const struct imx5_pm_data *soc_data)
|
||||
{
|
||||
struct imx5_cpu_suspend_info *suspend_info;
|
||||
int ret;
|
||||
/* Need this to avoid compile error due to const typeof in fncpy.h */
|
||||
void (*suspend_asm)(void __iomem *) = soc_data->suspend_asm;
|
||||
|
||||
if (!suspend_asm)
|
||||
return 0;
|
||||
|
||||
if (!soc_data->suspend_asm_sz || !*soc_data->suspend_asm_sz)
|
||||
return -EINVAL;
|
||||
|
||||
ret = imx_suspend_alloc_ocram(
|
||||
*soc_data->suspend_asm_sz + sizeof(*suspend_info),
|
||||
&suspend_ocram_base, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
suspend_info = suspend_ocram_base;
|
||||
|
||||
suspend_info->io_count = soc_data->suspend_io_count;
|
||||
memcpy(suspend_info->io_state, soc_data->suspend_io_config,
|
||||
sizeof(*suspend_info->io_state) * soc_data->suspend_io_count);
|
||||
|
||||
suspend_info->m4if_base = ioremap(soc_data->m4if_addr, SZ_16K);
|
||||
if (!suspend_info->m4if_base) {
|
||||
ret = -ENOMEM;
|
||||
goto failed_map_m4if;
|
||||
}
|
||||
|
||||
suspend_info->iomuxc_base = ioremap(soc_data->iomuxc_addr, SZ_16K);
|
||||
if (!suspend_info->iomuxc_base) {
|
||||
ret = -ENOMEM;
|
||||
goto failed_map_iomuxc;
|
||||
}
|
||||
|
||||
imx5_suspend_in_ocram_fn = fncpy(
|
||||
suspend_ocram_base + sizeof(*suspend_info),
|
||||
suspend_asm,
|
||||
*soc_data->suspend_asm_sz);
|
||||
|
||||
return 0;
|
||||
|
||||
failed_map_iomuxc:
|
||||
iounmap(suspend_info->m4if_base);
|
||||
|
||||
failed_map_m4if:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
@ -208,6 +389,7 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
|
|||
|
||||
arm_pm_idle = imx5_pm_idle;
|
||||
|
||||
ccm_base = ioremap(data->ccm_addr, SZ_16K);
|
||||
cortex_base = ioremap(data->cortex_addr, SZ_16K);
|
||||
gpc_base = ioremap(data->gpc_addr, SZ_16K);
|
||||
WARN_ON(!ccm_base || !cortex_base || !gpc_base);
|
||||
|
@ -219,6 +401,11 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
|
|||
if (ret)
|
||||
pr_warn("%s: cpuidle init failed %d\n", __func__, ret);
|
||||
|
||||
ret = imx5_suspend_init(data);
|
||||
if (ret)
|
||||
pr_warn("%s: No DDR LPM support with suspend %d!\n",
|
||||
__func__, ret);
|
||||
|
||||
suspend_set_ops(&mx5_suspend_ops);
|
||||
|
||||
return 0;
|
||||
|
@ -226,10 +413,12 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
|
|||
|
||||
void __init imx51_pm_init(void)
|
||||
{
|
||||
imx5_pm_common_init(&imx51_pm_data);
|
||||
if (IS_ENABLED(CONFIG_SOC_IMX51))
|
||||
imx5_pm_common_init(&imx51_pm_data);
|
||||
}
|
||||
|
||||
void __init imx53_pm_init(void)
|
||||
{
|
||||
imx5_pm_common_init(&imx53_pm_data);
|
||||
if (IS_ENABLED(CONFIG_SOC_IMX53))
|
||||
imx5_pm_common_init(&imx53_pm_data);
|
||||
}
|
||||
|
|
|
@ -255,7 +255,7 @@ static void imx6q_enable_wb(bool enable)
|
|||
writel_relaxed(val, ccm_base + CCR);
|
||||
}
|
||||
|
||||
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
|
||||
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
|
||||
{
|
||||
u32 val = readl_relaxed(ccm_base + CLPCR);
|
||||
|
||||
|
@ -340,7 +340,7 @@ static int imx6q_pm_enter(suspend_state_t state)
|
|||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
imx6q_set_lpm(STOP_POWER_ON);
|
||||
imx6_set_lpm(STOP_POWER_ON);
|
||||
imx6q_set_int_mem_clk_lpm(true);
|
||||
imx_gpc_pre_suspend(false);
|
||||
if (cpu_is_imx6sl())
|
||||
|
@ -350,10 +350,10 @@ static int imx6q_pm_enter(suspend_state_t state)
|
|||
if (cpu_is_imx6sl())
|
||||
imx6sl_set_wait_clk(false);
|
||||
imx_gpc_post_resume();
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
imx6_set_lpm(WAIT_CLOCKED);
|
||||
break;
|
||||
case PM_SUSPEND_MEM:
|
||||
imx6q_set_lpm(STOP_POWER_OFF);
|
||||
imx6_set_lpm(STOP_POWER_OFF);
|
||||
imx6q_set_int_mem_clk_lpm(false);
|
||||
imx6q_enable_wb(true);
|
||||
/*
|
||||
|
@ -373,7 +373,7 @@ static int imx6q_pm_enter(suspend_state_t state)
|
|||
imx6_enable_rbc(false);
|
||||
imx6q_enable_wb(false);
|
||||
imx6q_set_int_mem_clk_lpm(true);
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
imx6_set_lpm(WAIT_CLOCKED);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -392,11 +392,6 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
|
|||
.valid = imx6q_pm_valid,
|
||||
};
|
||||
|
||||
void __init imx6q_pm_set_ccm_base(void __iomem *base)
|
||||
{
|
||||
ccm_base = base;
|
||||
}
|
||||
|
||||
static int __init imx6_pm_get_base(struct imx6_pm_base *base,
|
||||
const char *compat)
|
||||
{
|
||||
|
@ -482,8 +477,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
|
|||
|
||||
/*
|
||||
* ccm physical address is not used by asm code currently,
|
||||
* so get ccm virtual address directly, as we already have
|
||||
* it from ccm driver.
|
||||
* so get ccm virtual address directly.
|
||||
*/
|
||||
pm_info->ccm_base.vbase = ccm_base;
|
||||
|
||||
|
@ -568,7 +562,7 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
|
|||
|
||||
/*
|
||||
* This is for SW workaround step #1 of ERR007265, see comments
|
||||
* in imx6q_set_lpm for details of this errata.
|
||||
* in imx6_set_lpm for details of this errata.
|
||||
* Force IOMUXC irq pending, so that the interrupt to GPC can be
|
||||
* used to deassert dsm_request signal when the signal gets
|
||||
* asserted unexpectedly.
|
||||
|
@ -579,6 +573,24 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
|
|||
IMX6Q_GPR1_GINT);
|
||||
}
|
||||
|
||||
void __init imx6_pm_ccm_init(const char *ccm_compat)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 val;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, ccm_compat);
|
||||
ccm_base = of_iomap(np, 0);
|
||||
BUG_ON(!ccm_base);
|
||||
|
||||
/*
|
||||
* Initialize CCM_CLPCR_LPM into RUN mode to avoid ARM core
|
||||
* clock being shut down unexpectedly by WAIT mode.
|
||||
*/
|
||||
val = readl_relaxed(ccm_base + CLPCR);
|
||||
val &= ~BM_CLPCR_LPM;
|
||||
writel_relaxed(val, ccm_base + CLPCR);
|
||||
}
|
||||
|
||||
void __init imx6q_pm_init(void)
|
||||
{
|
||||
imx6_pm_common_init(&imx6q_pm_data);
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#define M4IF_MCR0_OFFSET (0x008C)
|
||||
#define M4IF_MCR0_FDVFS (0x1 << 11)
|
||||
#define M4IF_MCR0_FDVACK (0x1 << 27)
|
||||
|
||||
.align 3
|
||||
|
||||
/*
|
||||
* ==================== low level suspend ====================
|
||||
*
|
||||
* On entry
|
||||
* r0: pm_info structure address;
|
||||
*
|
||||
* suspend ocram space layout:
|
||||
* ======================== high address ======================
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* ^
|
||||
* ^
|
||||
* ^
|
||||
* imx53_suspend code
|
||||
* PM_INFO structure(imx53_suspend_info)
|
||||
* ======================== low address =======================
|
||||
*/
|
||||
|
||||
/* Offsets of members of struct imx53_suspend_info */
|
||||
#define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
|
||||
#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
|
||||
#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
|
||||
#define SUSPEND_INFO_MX53_IO_STATE_OFFSET 0xc
|
||||
|
||||
ENTRY(imx53_suspend)
|
||||
stmfd sp!, {r4,r5,r6,r7}
|
||||
|
||||
/* Save pad config */
|
||||
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
|
||||
cmp r1, #0
|
||||
beq skip_pad_conf_1
|
||||
|
||||
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
|
||||
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
|
||||
|
||||
1:
|
||||
ldr r5, [r2], #12 /* IOMUXC register offset */
|
||||
ldr r6, [r3, r5] /* current value */
|
||||
str r6, [r2], #4 /* save area */
|
||||
subs r1, r1, #1
|
||||
bne 1b
|
||||
|
||||
skip_pad_conf_1:
|
||||
/* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
|
||||
ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
|
||||
ldr r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
orr r2, r2, #M4IF_MCR0_FDVFS
|
||||
str r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
|
||||
/* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
|
||||
wait_sr_ack:
|
||||
ldr r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
ands r2, r2, #M4IF_MCR0_FDVACK
|
||||
beq wait_sr_ack
|
||||
|
||||
/* Set pad config */
|
||||
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
|
||||
cmp r1, #0
|
||||
beq skip_pad_conf_2
|
||||
|
||||
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
|
||||
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
|
||||
|
||||
2:
|
||||
ldr r5, [r2], #4 /* IOMUXC register offset */
|
||||
ldr r6, [r2], #4 /* clear */
|
||||
ldr r7, [r3, r5]
|
||||
bic r7, r7, r6
|
||||
ldr r6, [r2], #8 /* set */
|
||||
orr r7, r7, r6
|
||||
str r7, [r3, r5]
|
||||
subs r1, r1, #1
|
||||
bne 2b
|
||||
|
||||
skip_pad_conf_2:
|
||||
/* Zzz, enter stop mode */
|
||||
wfi
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Restore pad config */
|
||||
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
|
||||
cmp r1, #0
|
||||
beq skip_pad_conf_3
|
||||
|
||||
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
|
||||
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
|
||||
|
||||
3:
|
||||
ldr r5, [r2], #12 /* IOMUXC register offset */
|
||||
ldr r6, [r2], #4 /* saved value */
|
||||
str r6, [r3, r5]
|
||||
subs r1, r1, #1
|
||||
bne 3b
|
||||
|
||||
skip_pad_conf_3:
|
||||
/* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
|
||||
ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
|
||||
ldr r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
bic r2, r2, #M4IF_MCR0_FDVFS
|
||||
str r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
|
||||
/* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
|
||||
wait_ar_ack:
|
||||
ldr r2,[r1, #M4IF_MCR0_OFFSET]
|
||||
ands r2, r2, #M4IF_MCR0_FDVACK
|
||||
bne wait_ar_ack
|
||||
|
||||
/* Restore registers */
|
||||
ldmfd sp!, {r4,r5,r6,r7}
|
||||
mov pc, lr
|
||||
|
||||
ENDPROC(imx53_suspend)
|
||||
|
||||
ENTRY(imx53_suspend_sz)
|
||||
.word . - imx53_suspend
|
|
@ -1,385 +0,0 @@
|
|||
/*
|
||||
* linux/arch/arm/plat-mxc/time.c
|
||||
*
|
||||
* Copyright (C) 2000-2001 Deep Blue Solutions
|
||||
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
|
||||
* Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
|
||||
* Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "hardware.h"
|
||||
|
||||
/*
|
||||
* There are 2 versions of the timer hardware on Freescale MXC hardware.
|
||||
* Version 1: MX1/MXL, MX21, MX27.
|
||||
* Version 2: MX25, MX31, MX35, MX37, MX51
|
||||
*/
|
||||
|
||||
/* defines common for all i.MX */
|
||||
#define MXC_TCTL 0x00
|
||||
#define MXC_TCTL_TEN (1 << 0) /* Enable module */
|
||||
#define MXC_TPRER 0x04
|
||||
|
||||
/* MX1, MX21, MX27 */
|
||||
#define MX1_2_TCTL_CLK_PCLK1 (1 << 1)
|
||||
#define MX1_2_TCTL_IRQEN (1 << 4)
|
||||
#define MX1_2_TCTL_FRR (1 << 8)
|
||||
#define MX1_2_TCMP 0x08
|
||||
#define MX1_2_TCN 0x10
|
||||
#define MX1_2_TSTAT 0x14
|
||||
|
||||
/* MX21, MX27 */
|
||||
#define MX2_TSTAT_CAPT (1 << 1)
|
||||
#define MX2_TSTAT_COMP (1 << 0)
|
||||
|
||||
/* MX31, MX35, MX25, MX5, MX6 */
|
||||
#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */
|
||||
#define V2_TCTL_CLK_IPG (1 << 6)
|
||||
#define V2_TCTL_CLK_PER (2 << 6)
|
||||
#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
|
||||
#define V2_TCTL_FRR (1 << 9)
|
||||
#define V2_TCTL_24MEN (1 << 10)
|
||||
#define V2_TPRER_PRE24M 12
|
||||
#define V2_IR 0x0c
|
||||
#define V2_TSTAT 0x08
|
||||
#define V2_TSTAT_OF1 (1 << 0)
|
||||
#define V2_TCN 0x24
|
||||
#define V2_TCMP 0x10
|
||||
|
||||
#define V2_TIMER_RATE_OSC_DIV8 3000000
|
||||
|
||||
#define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
|
||||
#define timer_is_v2() (!timer_is_v1())
|
||||
|
||||
static struct clock_event_device clockevent_mxc;
|
||||
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
|
||||
|
||||
static void __iomem *timer_base;
|
||||
|
||||
static inline void gpt_irq_disable(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
if (timer_is_v2())
|
||||
__raw_writel(0, timer_base + V2_IR);
|
||||
else {
|
||||
tmp = __raw_readl(timer_base + MXC_TCTL);
|
||||
__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gpt_irq_enable(void)
|
||||
{
|
||||
if (timer_is_v2())
|
||||
__raw_writel(1<<0, timer_base + V2_IR);
|
||||
else {
|
||||
__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
|
||||
timer_base + MXC_TCTL);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpt_irq_acknowledge(void)
|
||||
{
|
||||
if (timer_is_v1()) {
|
||||
if (cpu_is_mx1())
|
||||
__raw_writel(0, timer_base + MX1_2_TSTAT);
|
||||
else
|
||||
__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
|
||||
timer_base + MX1_2_TSTAT);
|
||||
} else if (timer_is_v2())
|
||||
__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
|
||||
}
|
||||
|
||||
static void __iomem *sched_clock_reg;
|
||||
|
||||
static u64 notrace mxc_read_sched_clock(void)
|
||||
{
|
||||
return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
|
||||
}
|
||||
|
||||
static struct delay_timer imx_delay_timer;
|
||||
|
||||
static unsigned long imx_read_current_timer(void)
|
||||
{
|
||||
return __raw_readl(sched_clock_reg);
|
||||
}
|
||||
|
||||
static int __init mxc_clocksource_init(struct clk *timer_clk)
|
||||
{
|
||||
unsigned int c = clk_get_rate(timer_clk);
|
||||
void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
|
||||
|
||||
imx_delay_timer.read_current_timer = &imx_read_current_timer;
|
||||
imx_delay_timer.freq = c;
|
||||
register_current_timer_delay(&imx_delay_timer);
|
||||
|
||||
sched_clock_reg = reg;
|
||||
|
||||
sched_clock_register(mxc_read_sched_clock, 32, c);
|
||||
return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
|
||||
clocksource_mmio_readl_up);
|
||||
}
|
||||
|
||||
/* clock event */
|
||||
|
||||
static int mx1_2_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long tcmp;
|
||||
|
||||
tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
|
||||
|
||||
__raw_writel(tcmp, timer_base + MX1_2_TCMP);
|
||||
|
||||
return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
|
||||
-ETIME : 0;
|
||||
}
|
||||
|
||||
static int v2_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long tcmp;
|
||||
|
||||
tcmp = __raw_readl(timer_base + V2_TCN) + evt;
|
||||
|
||||
__raw_writel(tcmp, timer_base + V2_TCMP);
|
||||
|
||||
return evt < 0x7fffffff &&
|
||||
(int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
|
||||
-ETIME : 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *clock_event_mode_label[] = {
|
||||
[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
|
||||
[CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
|
||||
[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
|
||||
[CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED",
|
||||
[CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME",
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
static void mxc_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* The timer interrupt generation is disabled at least
|
||||
* for enough time to call mxc_set_next_event()
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Disable interrupt in GPT module */
|
||||
gpt_irq_disable();
|
||||
|
||||
if (mode != clockevent_mode) {
|
||||
/* Set event time into far-far future */
|
||||
if (timer_is_v2())
|
||||
__raw_writel(__raw_readl(timer_base + V2_TCN) - 3,
|
||||
timer_base + V2_TCMP);
|
||||
else
|
||||
__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
|
||||
timer_base + MX1_2_TCMP);
|
||||
|
||||
/* Clear pending interrupt */
|
||||
gpt_irq_acknowledge();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
|
||||
clock_event_mode_label[clockevent_mode],
|
||||
clock_event_mode_label[mode]);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Remember timer mode */
|
||||
clockevent_mode = mode;
|
||||
local_irq_restore(flags);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
|
||||
"supported for i.MX\n");
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/*
|
||||
* Do not put overhead of interrupt enable/disable into
|
||||
* mxc_set_next_event(), the core has about 4 minutes
|
||||
* to call mxc_set_next_event() or shutdown clock after
|
||||
* mode switching
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
gpt_irq_enable();
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
/* Left event sources disabled, no more interrupts appear */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handler for the timer
|
||||
*/
|
||||
static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *evt = &clockevent_mxc;
|
||||
uint32_t tstat;
|
||||
|
||||
if (timer_is_v2())
|
||||
tstat = __raw_readl(timer_base + V2_TSTAT);
|
||||
else
|
||||
tstat = __raw_readl(timer_base + MX1_2_TSTAT);
|
||||
|
||||
gpt_irq_acknowledge();
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction mxc_timer_irq = {
|
||||
.name = "i.MX Timer Tick",
|
||||
.flags = IRQF_TIMER | IRQF_IRQPOLL,
|
||||
.handler = mxc_timer_interrupt,
|
||||
};
|
||||
|
||||
static struct clock_event_device clockevent_mxc = {
|
||||
.name = "mxc_timer1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = mxc_set_mode,
|
||||
.set_next_event = mx1_2_set_next_event,
|
||||
.rating = 200,
|
||||
};
|
||||
|
||||
static int __init mxc_clockevent_init(struct clk *timer_clk)
|
||||
{
|
||||
if (timer_is_v2())
|
||||
clockevent_mxc.set_next_event = v2_set_next_event;
|
||||
|
||||
clockevent_mxc.cpumask = cpumask_of(0);
|
||||
clockevents_config_and_register(&clockevent_mxc,
|
||||
clk_get_rate(timer_clk),
|
||||
0xff, 0xfffffffe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init _mxc_timer_init(int irq,
|
||||
struct clk *clk_per, struct clk *clk_ipg)
|
||||
{
|
||||
uint32_t tctl_val;
|
||||
|
||||
if (IS_ERR(clk_per)) {
|
||||
pr_err("i.MX timer: unable to get clk\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IS_ERR(clk_ipg))
|
||||
clk_prepare_enable(clk_ipg);
|
||||
|
||||
clk_prepare_enable(clk_per);
|
||||
|
||||
/*
|
||||
* Initialise to a known state (all timers off, and timing reset)
|
||||
*/
|
||||
|
||||
__raw_writel(0, timer_base + MXC_TCTL);
|
||||
__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
|
||||
|
||||
if (timer_is_v2()) {
|
||||
tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
|
||||
if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) {
|
||||
tctl_val |= V2_TCTL_CLK_OSC_DIV8;
|
||||
if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
|
||||
/* 24 / 8 = 3 MHz */
|
||||
__raw_writel(7 << V2_TPRER_PRE24M,
|
||||
timer_base + MXC_TPRER);
|
||||
tctl_val |= V2_TCTL_24MEN;
|
||||
}
|
||||
} else {
|
||||
tctl_val |= V2_TCTL_CLK_PER;
|
||||
}
|
||||
} else {
|
||||
tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
|
||||
}
|
||||
|
||||
__raw_writel(tctl_val, timer_base + MXC_TCTL);
|
||||
|
||||
/* init and register the timer to the framework */
|
||||
mxc_clocksource_init(clk_per);
|
||||
mxc_clockevent_init(clk_per);
|
||||
|
||||
/* Make irqs happen */
|
||||
setup_irq(irq, &mxc_timer_irq);
|
||||
}
|
||||
|
||||
void __init mxc_timer_init(void __iomem *base, int irq)
|
||||
{
|
||||
struct clk *clk_per = clk_get_sys("imx-gpt.0", "per");
|
||||
struct clk *clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
|
||||
|
||||
timer_base = base;
|
||||
|
||||
_mxc_timer_init(irq, clk_per, clk_ipg);
|
||||
}
|
||||
|
||||
static void __init mxc_timer_init_dt(struct device_node *np)
|
||||
{
|
||||
struct clk *clk_per, *clk_ipg;
|
||||
int irq;
|
||||
|
||||
if (timer_base)
|
||||
return;
|
||||
|
||||
timer_base = of_iomap(np, 0);
|
||||
WARN_ON(!timer_base);
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
|
||||
clk_ipg = of_clk_get_by_name(np, "ipg");
|
||||
|
||||
/* Try osc_per first, and fall back to per otherwise */
|
||||
clk_per = of_clk_get_by_name(np, "osc_per");
|
||||
if (IS_ERR(clk_per))
|
||||
clk_per = of_clk_get_by_name(np, "per");
|
||||
|
||||
_mxc_timer_init(irq, clk_per, clk_ipg);
|
||||
}
|
||||
CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx50_timer, "fsl,imx50-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx51_timer, "fsl,imx51-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx53_timer, "fsl,imx53-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx6q_timer, "fsl,imx6q-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx6sl_timer, "fsl,imx6sl-gpt", mxc_timer_init_dt);
|
||||
CLOCKSOURCE_OF_DECLARE(mx6sx_timer, "fsl,imx6sx-gpt", mxc_timer_init_dt);
|
|
@ -0,0 +1 @@
|
|||
obj-y += board-dt.o
|
|
@ -0,0 +1,3 @@
|
|||
# Empty file waiting for deletion once Makefile.boot isn't needed any more.
|
||||
# Patch waits for application at
|
||||
# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Device Tree board file for NXP LPC18xx/43xx
|
||||
*
|
||||
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
static const char *const lpc18xx_43xx_compat[] __initconst = {
|
||||
"nxp,lpc1850",
|
||||
"nxp,lpc4350",
|
||||
"nxp,lpc4370",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(LPC18XXDT, "NXP LPC18xx/43xx (Device Tree)")
|
||||
.dt_compat = lpc18xx_43xx_compat,
|
||||
MACHINE_END
|
|
@ -17,11 +17,10 @@
|
|||
#include <asm/assembler.h>
|
||||
|
||||
#include <mach/board-ams-delta.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/ams-delta-fiq.h>
|
||||
|
||||
#include "iomap.h"
|
||||
#include "soc.h"
|
||||
|
||||
/*
|
||||
* GPIO related definitions, copied from arch/arm/plat-omap/gpio.c.
|
||||
|
|
|
@ -626,6 +626,7 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
|
|||
.map_io = ams_delta_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = ams_delta_init,
|
||||
.init_late = ams_delta_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -362,6 +362,7 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
|
|||
.map_io = omap_fsample_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_fsample_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -82,6 +82,7 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
|
|||
.map_io = omap16xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_generic_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -426,6 +426,7 @@ MACHINE_START(OMAP_H2, "TI-H2")
|
|||
.map_io = omap16xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = h2_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <linux/i2c/tps65010.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "board-h3.h"
|
||||
#include "mmc.h"
|
||||
|
||||
|
|
|
@ -452,6 +452,7 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
|
|||
.map_io = omap16xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = h3_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -601,6 +601,7 @@ MACHINE_START(HERALD, "HTC Herald")
|
|||
.map_io = htcherald_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = htcherald_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -456,6 +456,7 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
|
|||
.map_io = innovator_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = innovator_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -294,6 +294,7 @@ MACHINE_START(NOKIA770, "Nokia 770")
|
|||
.map_io = omap16xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_nokia770_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -610,6 +610,7 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
|
|||
.map_io = omap16xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = osk_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -235,6 +235,7 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
|
|||
.map_io = omap15xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_palmte_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -282,6 +282,7 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
|
|||
.map_io = omap15xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_palmtt_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -297,6 +297,7 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
|
|||
.map_io = omap15xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_palmz71_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -324,6 +324,7 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
|
|||
.map_io = omap_perseus2_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_perseus2_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -343,6 +343,7 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1")
|
|||
.map_io = omap15xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = omap_sx1_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -288,6 +288,7 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
|
|||
.map_io = omap15xx_map_io,
|
||||
.init_early = omap1_init_early,
|
||||
.init_irq = omap1_init_irq,
|
||||
.handle_irq = omap1_handle_irq,
|
||||
.init_machine = voiceblue_init,
|
||||
.init_late = omap1_init_late,
|
||||
.init_time = omap1_timer_init,
|
||||
|
|
|
@ -30,10 +30,14 @@
|
|||
#include <linux/i2c-omap.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
|
||||
#include <plat/i2c.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
|
||||
void omap7xx_map_io(void);
|
||||
#else
|
||||
|
@ -73,6 +77,7 @@ static inline int omap_serial_wakeup_init(void)
|
|||
|
||||
void omap1_init_early(void);
|
||||
void omap1_init_irq(void);
|
||||
void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs);
|
||||
void omap1_init_late(void);
|
||||
void omap1_restart(enum reboot_mode, const char *);
|
||||
|
||||
|
@ -91,8 +96,6 @@ static inline int __init omap_32k_timer_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
extern u32 omap_irq_flags;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP16XX
|
||||
extern int ocpi_enable(void);
|
||||
#else
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <linux/omap-dma.h>
|
||||
#include <mach/tc.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
#include "soc.h"
|
||||
|
||||
#define OMAP1_DMA_BASE (0xfffed800)
|
||||
#define OMAP1_LOGICAL_DMA_CH_COUNT 17
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
#define OMAP1610_GPIO1_BASE 0xfffbe400
|
||||
#define OMAP1610_GPIO2_BASE 0xfffbec00
|
||||
#define OMAP1610_GPIO3_BASE 0xfffbb400
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
#define OMAP7XX_GPIO1_BASE 0xfffbc000
|
||||
#define OMAP7XX_GPIO2_BASE 0xfffbc800
|
||||
#define OMAP7XX_GPIO3_BASE 0xfffbd000
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#define OMAP_I2C_SIZE 0x3f
|
||||
#define OMAP1_I2C_BASE 0xfffb3800
|
||||
#define OMAP1_INT_I2C (32 + 4)
|
||||
|
||||
static const char name[] = "omap_i2c";
|
||||
|
||||
|
@ -67,7 +66,7 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata,
|
|||
res[0].start = OMAP1_I2C_BASE;
|
||||
res[0].end = res[0].start + OMAP_I2C_SIZE;
|
||||
res[0].flags = IORESOURCE_MEM;
|
||||
res[1].start = OMAP1_INT_I2C;
|
||||
res[1].start = INT_I2C;
|
||||
res[1].flags = IORESOURCE_IRQ;
|
||||
pdev->resource = res;
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* arch/arm/mach-omap1/include/mach/entry-macro.S
|
||||
*
|
||||
* Low-level IRQ helper macros for OMAP-based platforms
|
||||
*
|
||||
* Copyright (C) 2009 Texas Instruments
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
ldr \base, =OMAP1_IO_ADDRESS(OMAP_IH1_BASE)
|
||||
ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
|
||||
ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET]
|
||||
mov \irqstat, #0xffffffff
|
||||
bic \tmp, \irqstat, \tmp
|
||||
tst \irqnr, \tmp
|
||||
beq 1510f
|
||||
|
||||
ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET]
|
||||
ldr \tmp, =omap_irq_flags @ irq flags address
|
||||
ldr \tmp, [\tmp, #0] @ irq flags value
|
||||
cmp \irqnr, #0
|
||||
ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
|
||||
cmpeq \irqnr, \tmp
|
||||
ldreq \base, =OMAP1_IO_ADDRESS(OMAP_IH2_BASE)
|
||||
ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
|
||||
addeqs \irqnr, \irqnr, #32
|
||||
1510:
|
||||
.endm
|
||||
|
|
@ -34,84 +34,84 @@
|
|||
* NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
|
||||
*
|
||||
*/
|
||||
#define INT_CAMERA 1
|
||||
#define INT_FIQ 3
|
||||
#define INT_RTDX 6
|
||||
#define INT_DSP_MMU_ABORT 7
|
||||
#define INT_HOST 8
|
||||
#define INT_ABORT 9
|
||||
#define INT_BRIDGE_PRIV 13
|
||||
#define INT_GPIO_BANK1 14
|
||||
#define INT_UART3 15
|
||||
#define INT_TIMER3 16
|
||||
#define INT_DMA_CH0_6 19
|
||||
#define INT_DMA_CH1_7 20
|
||||
#define INT_DMA_CH2_8 21
|
||||
#define INT_DMA_CH3 22
|
||||
#define INT_DMA_CH4 23
|
||||
#define INT_DMA_CH5 24
|
||||
#define INT_TIMER1 26
|
||||
#define INT_WD_TIMER 27
|
||||
#define INT_BRIDGE_PUB 28
|
||||
#define INT_TIMER2 30
|
||||
#define INT_LCD_CTRL 31
|
||||
#define INT_CAMERA (NR_IRQS_LEGACY + 1)
|
||||
#define INT_FIQ (NR_IRQS_LEGACY + 3)
|
||||
#define INT_RTDX (NR_IRQS_LEGACY + 6)
|
||||
#define INT_DSP_MMU_ABORT (NR_IRQS_LEGACY + 7)
|
||||
#define INT_HOST (NR_IRQS_LEGACY + 8)
|
||||
#define INT_ABORT (NR_IRQS_LEGACY + 9)
|
||||
#define INT_BRIDGE_PRIV (NR_IRQS_LEGACY + 13)
|
||||
#define INT_GPIO_BANK1 (NR_IRQS_LEGACY + 14)
|
||||
#define INT_UART3 (NR_IRQS_LEGACY + 15)
|
||||
#define INT_TIMER3 (NR_IRQS_LEGACY + 16)
|
||||
#define INT_DMA_CH0_6 (NR_IRQS_LEGACY + 19)
|
||||
#define INT_DMA_CH1_7 (NR_IRQS_LEGACY + 20)
|
||||
#define INT_DMA_CH2_8 (NR_IRQS_LEGACY + 21)
|
||||
#define INT_DMA_CH3 (NR_IRQS_LEGACY + 22)
|
||||
#define INT_DMA_CH4 (NR_IRQS_LEGACY + 23)
|
||||
#define INT_DMA_CH5 (NR_IRQS_LEGACY + 24)
|
||||
#define INT_TIMER1 (NR_IRQS_LEGACY + 26)
|
||||
#define INT_WD_TIMER (NR_IRQS_LEGACY + 27)
|
||||
#define INT_BRIDGE_PUB (NR_IRQS_LEGACY + 28)
|
||||
#define INT_TIMER2 (NR_IRQS_LEGACY + 30)
|
||||
#define INT_LCD_CTRL (NR_IRQS_LEGACY + 31)
|
||||
|
||||
/*
|
||||
* OMAP-1510 specific IRQ numbers for interrupt handler 1
|
||||
*/
|
||||
#define INT_1510_IH2_IRQ 0
|
||||
#define INT_1510_RES2 2
|
||||
#define INT_1510_SPI_TX 4
|
||||
#define INT_1510_SPI_RX 5
|
||||
#define INT_1510_DSP_MAILBOX1 10
|
||||
#define INT_1510_DSP_MAILBOX2 11
|
||||
#define INT_1510_RES12 12
|
||||
#define INT_1510_LB_MMU 17
|
||||
#define INT_1510_RES18 18
|
||||
#define INT_1510_LOCAL_BUS 29
|
||||
#define INT_1510_IH2_IRQ (NR_IRQS_LEGACY + 0)
|
||||
#define INT_1510_RES2 (NR_IRQS_LEGACY + 2)
|
||||
#define INT_1510_SPI_TX (NR_IRQS_LEGACY + 4)
|
||||
#define INT_1510_SPI_RX (NR_IRQS_LEGACY + 5)
|
||||
#define INT_1510_DSP_MAILBOX1 (NR_IRQS_LEGACY + 10)
|
||||
#define INT_1510_DSP_MAILBOX2 (NR_IRQS_LEGACY + 11)
|
||||
#define INT_1510_RES12 (NR_IRQS_LEGACY + 12)
|
||||
#define INT_1510_LB_MMU (NR_IRQS_LEGACY + 17)
|
||||
#define INT_1510_RES18 (NR_IRQS_LEGACY + 18)
|
||||
#define INT_1510_LOCAL_BUS (NR_IRQS_LEGACY + 29)
|
||||
|
||||
/*
|
||||
* OMAP-1610 specific IRQ numbers for interrupt handler 1
|
||||
*/
|
||||
#define INT_1610_IH2_IRQ INT_1510_IH2_IRQ
|
||||
#define INT_1610_IH2_FIQ 2
|
||||
#define INT_1610_McBSP2_TX 4
|
||||
#define INT_1610_McBSP2_RX 5
|
||||
#define INT_1610_DSP_MAILBOX1 10
|
||||
#define INT_1610_DSP_MAILBOX2 11
|
||||
#define INT_1610_LCD_LINE 12
|
||||
#define INT_1610_GPTIMER1 17
|
||||
#define INT_1610_GPTIMER2 18
|
||||
#define INT_1610_SSR_FIFO_0 29
|
||||
#define INT_1610_IH2_FIQ (NR_IRQS_LEGACY + 2)
|
||||
#define INT_1610_McBSP2_TX (NR_IRQS_LEGACY + 4)
|
||||
#define INT_1610_McBSP2_RX (NR_IRQS_LEGACY + 5)
|
||||
#define INT_1610_DSP_MAILBOX1 (NR_IRQS_LEGACY + 10)
|
||||
#define INT_1610_DSP_MAILBOX2 (NR_IRQS_LEGACY + 11)
|
||||
#define INT_1610_LCD_LINE (NR_IRQS_LEGACY + 12)
|
||||
#define INT_1610_GPTIMER1 (NR_IRQS_LEGACY + 17)
|
||||
#define INT_1610_GPTIMER2 (NR_IRQS_LEGACY + 18)
|
||||
#define INT_1610_SSR_FIFO_0 (NR_IRQS_LEGACY + 29)
|
||||
|
||||
/*
|
||||
* OMAP-7xx specific IRQ numbers for interrupt handler 1
|
||||
*/
|
||||
#define INT_7XX_IH2_FIQ 0
|
||||
#define INT_7XX_IH2_IRQ 1
|
||||
#define INT_7XX_USB_NON_ISO 2
|
||||
#define INT_7XX_USB_ISO 3
|
||||
#define INT_7XX_ICR 4
|
||||
#define INT_7XX_EAC 5
|
||||
#define INT_7XX_GPIO_BANK1 6
|
||||
#define INT_7XX_GPIO_BANK2 7
|
||||
#define INT_7XX_GPIO_BANK3 8
|
||||
#define INT_7XX_McBSP2TX 10
|
||||
#define INT_7XX_McBSP2RX 11
|
||||
#define INT_7XX_McBSP2RX_OVF 12
|
||||
#define INT_7XX_LCD_LINE 14
|
||||
#define INT_7XX_GSM_PROTECT 15
|
||||
#define INT_7XX_TIMER3 16
|
||||
#define INT_7XX_GPIO_BANK5 17
|
||||
#define INT_7XX_GPIO_BANK6 18
|
||||
#define INT_7XX_SPGIO_WR 29
|
||||
#define INT_7XX_IH2_FIQ (NR_IRQS_LEGACY + 0)
|
||||
#define INT_7XX_IH2_IRQ (NR_IRQS_LEGACY + 1)
|
||||
#define INT_7XX_USB_NON_ISO (NR_IRQS_LEGACY + 2)
|
||||
#define INT_7XX_USB_ISO (NR_IRQS_LEGACY + 3)
|
||||
#define INT_7XX_ICR (NR_IRQS_LEGACY + 4)
|
||||
#define INT_7XX_EAC (NR_IRQS_LEGACY + 5)
|
||||
#define INT_7XX_GPIO_BANK1 (NR_IRQS_LEGACY + 6)
|
||||
#define INT_7XX_GPIO_BANK2 (NR_IRQS_LEGACY + 7)
|
||||
#define INT_7XX_GPIO_BANK3 (NR_IRQS_LEGACY + 8)
|
||||
#define INT_7XX_McBSP2TX (NR_IRQS_LEGACY + 10)
|
||||
#define INT_7XX_McBSP2RX (NR_IRQS_LEGACY + 11)
|
||||
#define INT_7XX_McBSP2RX_OVF (NR_IRQS_LEGACY + 12)
|
||||
#define INT_7XX_LCD_LINE (NR_IRQS_LEGACY + 14)
|
||||
#define INT_7XX_GSM_PROTECT (NR_IRQS_LEGACY + 15)
|
||||
#define INT_7XX_TIMER3 (NR_IRQS_LEGACY + 16)
|
||||
#define INT_7XX_GPIO_BANK5 (NR_IRQS_LEGACY + 17)
|
||||
#define INT_7XX_GPIO_BANK6 (NR_IRQS_LEGACY + 18)
|
||||
#define INT_7XX_SPGIO_WR (NR_IRQS_LEGACY + 29)
|
||||
|
||||
/*
|
||||
* IRQ numbers for interrupt handler 2
|
||||
*
|
||||
* NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
|
||||
*/
|
||||
#define IH2_BASE 32
|
||||
#define IH2_BASE (NR_IRQS_LEGACY + 32)
|
||||
|
||||
#define INT_KEYBOARD (1 + IH2_BASE)
|
||||
#define INT_uWireTX (2 + IH2_BASE)
|
||||
|
@ -255,11 +255,7 @@
|
|||
#endif
|
||||
#define OMAP_FPGA_IRQ_END (OMAP_FPGA_IRQ_BASE + OMAP_FPGA_NR_IRQS)
|
||||
|
||||
#define NR_IRQS OMAP_FPGA_IRQ_END
|
||||
|
||||
#define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32))
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#define OMAP_IRQ_BIT(irq) (1 << ((irq - NR_IRQS_LEGACY) % 32))
|
||||
|
||||
#ifdef CONFIG_FIQ
|
||||
#define FIQ_START 1024
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#ifndef __ASM_ARCH_MEMORY_H
|
||||
#define __ASM_ARCH_MEMORY_H
|
||||
|
||||
/* REVISIT: omap1 legacy drivers still rely on this */
|
||||
#include <mach/soc.h>
|
||||
|
||||
/*
|
||||
* Bus address is physical address, except for OMAP-1510 Local Bus.
|
||||
* OMAP-1510 bus address is translated into a Local Bus address if the
|
||||
|
@ -14,7 +17,6 @@
|
|||
* because of the strncmp().
|
||||
*/
|
||||
#if defined(CONFIG_ARCH_OMAP15XX) && !defined(__ASSEMBLER__)
|
||||
#include <mach/soc.h>
|
||||
|
||||
/*
|
||||
* OMAP-1510 Local Bus address offset
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
*/
|
||||
#define OMAP_UART_INFO_OFS 0x3ffc
|
||||
|
||||
/* OMAP1 serial ports */
|
||||
#define OMAP1_UART1_BASE 0xfffb0000
|
||||
#define OMAP1_UART2_BASE 0xfffb0800
|
||||
#define OMAP1_UART3_BASE 0xfffb9800
|
||||
|
||||
#define OMAP_PORT_SHIFT 2
|
||||
#define OMAP7XX_PORT_SHIFT 0
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#ifndef __ASM_ARCH_OMAP_CPU_H
|
||||
#define __ASM_ARCH_OMAP_CPU_H
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <linux/io.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/exception.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
@ -56,66 +57,41 @@
|
|||
|
||||
struct omap_irq_bank {
|
||||
unsigned long base_reg;
|
||||
void __iomem *va;
|
||||
unsigned long trigger_map;
|
||||
unsigned long wake_enable;
|
||||
};
|
||||
|
||||
u32 omap_irq_flags;
|
||||
static u32 omap_l2_irq;
|
||||
static unsigned int irq_bank_count;
|
||||
static struct omap_irq_bank *irq_banks;
|
||||
static struct irq_domain *domain;
|
||||
|
||||
static inline unsigned int irq_bank_readl(int bank, int offset)
|
||||
{
|
||||
return readl_relaxed(irq_banks[bank].va + offset);
|
||||
}
|
||||
static inline void irq_bank_writel(unsigned long value, int bank, int offset)
|
||||
{
|
||||
omap_writel(value, irq_banks[bank].base_reg + offset);
|
||||
writel_relaxed(value, irq_banks[bank].va + offset);
|
||||
}
|
||||
|
||||
static void omap_ack_irq(struct irq_data *d)
|
||||
static void omap_ack_irq(int irq)
|
||||
{
|
||||
if (d->irq > 31)
|
||||
omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET);
|
||||
if (irq > 31)
|
||||
writel_relaxed(0x1, irq_banks[1].va + IRQ_CONTROL_REG_OFFSET);
|
||||
|
||||
omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET);
|
||||
}
|
||||
|
||||
static void omap_mask_irq(struct irq_data *d)
|
||||
{
|
||||
int bank = IRQ_BANK(d->irq);
|
||||
u32 l;
|
||||
|
||||
l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
|
||||
l |= 1 << IRQ_BIT(d->irq);
|
||||
omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
|
||||
}
|
||||
|
||||
static void omap_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
int bank = IRQ_BANK(d->irq);
|
||||
u32 l;
|
||||
|
||||
l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
|
||||
l &= ~(1 << IRQ_BIT(d->irq));
|
||||
omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
|
||||
writel_relaxed(0x1, irq_banks[0].va + IRQ_CONTROL_REG_OFFSET);
|
||||
}
|
||||
|
||||
static void omap_mask_ack_irq(struct irq_data *d)
|
||||
{
|
||||
omap_mask_irq(d);
|
||||
omap_ack_irq(d);
|
||||
struct irq_chip_type *ct = irq_data_get_chip_type(d);
|
||||
|
||||
ct->chip.irq_mask(d);
|
||||
omap_ack_irq(d->irq);
|
||||
}
|
||||
|
||||
static int omap_wake_irq(struct irq_data *d, unsigned int enable)
|
||||
{
|
||||
int bank = IRQ_BANK(d->irq);
|
||||
|
||||
if (enable)
|
||||
irq_banks[bank].wake_enable |= IRQ_BIT(d->irq);
|
||||
else
|
||||
irq_banks[bank].wake_enable &= ~IRQ_BIT(d->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allows tuning the IRQ type and priority
|
||||
*
|
||||
|
@ -165,46 +141,105 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static struct irq_chip omap_irq_chip = {
|
||||
.name = "MPU",
|
||||
.irq_ack = omap_mask_ack_irq,
|
||||
.irq_mask = omap_mask_irq,
|
||||
.irq_unmask = omap_unmask_irq,
|
||||
.irq_set_wake = omap_wake_irq,
|
||||
};
|
||||
asmlinkage void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
void __iomem *l1 = irq_banks[0].va;
|
||||
void __iomem *l2 = irq_banks[1].va;
|
||||
u32 irqnr;
|
||||
|
||||
do {
|
||||
irqnr = readl_relaxed(l1 + IRQ_ITR_REG_OFFSET);
|
||||
irqnr &= ~(readl_relaxed(l1 + IRQ_MIR_REG_OFFSET) & 0xffffffff);
|
||||
if (!irqnr)
|
||||
break;
|
||||
|
||||
irqnr = readl_relaxed(l1 + IRQ_SIR_FIQ_REG_OFFSET);
|
||||
if (irqnr)
|
||||
goto irq;
|
||||
|
||||
irqnr = readl_relaxed(l1 + IRQ_SIR_IRQ_REG_OFFSET);
|
||||
if (irqnr == omap_l2_irq) {
|
||||
irqnr = readl_relaxed(l2 + IRQ_SIR_IRQ_REG_OFFSET);
|
||||
if (irqnr)
|
||||
irqnr += 32;
|
||||
}
|
||||
irq:
|
||||
if (irqnr)
|
||||
handle_domain_irq(domain, irqnr, regs);
|
||||
else
|
||||
break;
|
||||
} while (irqnr);
|
||||
}
|
||||
|
||||
static __init void
|
||||
omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
|
||||
{
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
|
||||
gc = irq_alloc_generic_chip("MPU", 1, irq_start, base,
|
||||
handle_level_irq);
|
||||
ct = gc->chip_types;
|
||||
ct->chip.irq_ack = omap_mask_ack_irq;
|
||||
ct->chip.irq_mask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_set_wake = irq_gc_set_wake;
|
||||
ct->regs.mask = IRQ_MIR_REG_OFFSET;
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
|
||||
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
}
|
||||
|
||||
void __init omap1_init_irq(void)
|
||||
{
|
||||
int i, j;
|
||||
struct irq_chip_type *ct;
|
||||
struct irq_data *d = NULL;
|
||||
int i, j, irq_base;
|
||||
unsigned long nr_irqs;
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
|
||||
if (cpu_is_omap7xx()) {
|
||||
omap_irq_flags = INT_7XX_IH2_IRQ;
|
||||
irq_banks = omap7xx_irq_banks;
|
||||
irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_OMAP15XX
|
||||
if (cpu_is_omap1510()) {
|
||||
omap_irq_flags = INT_1510_IH2_IRQ;
|
||||
irq_banks = omap1510_irq_banks;
|
||||
irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
|
||||
}
|
||||
if (cpu_is_omap310()) {
|
||||
omap_irq_flags = INT_1510_IH2_IRQ;
|
||||
irq_banks = omap310_irq_banks;
|
||||
irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_OMAP16XX)
|
||||
if (cpu_is_omap16xx()) {
|
||||
omap_irq_flags = INT_1510_IH2_IRQ;
|
||||
irq_banks = omap1610_irq_banks;
|
||||
irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
|
||||
}
|
||||
#endif
|
||||
printk("Total of %i interrupts in %i interrupt banks\n",
|
||||
irq_bank_count * 32, irq_bank_count);
|
||||
|
||||
for (i = 0; i < irq_bank_count; i++) {
|
||||
irq_banks[i].va = ioremap(irq_banks[i].base_reg, 0xff);
|
||||
if (WARN_ON(!irq_banks[i].va))
|
||||
return;
|
||||
}
|
||||
|
||||
nr_irqs = irq_bank_count * 32;
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
|
||||
if (irq_base < 0) {
|
||||
pr_warn("Couldn't allocate IRQ numbers\n");
|
||||
irq_base = 0;
|
||||
}
|
||||
omap_l2_irq = cpu_is_omap7xx() ? irq_base + 1 : irq_base;
|
||||
omap_l2_irq -= NR_IRQS_LEGACY;
|
||||
|
||||
domain = irq_domain_add_legacy(NULL, nr_irqs, irq_base, 0,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
|
||||
pr_info("Total of %lu interrupts in %i interrupt banks\n",
|
||||
nr_irqs, irq_bank_count);
|
||||
|
||||
/* Mask and clear all interrupts */
|
||||
for (i = 0; i < irq_bank_count; i++) {
|
||||
|
@ -227,19 +262,15 @@ void __init omap1_init_irq(void)
|
|||
|
||||
irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
|
||||
omap_irq_set_cfg(j, 0, 0, irq_trigger);
|
||||
|
||||
irq_set_chip_and_handler(j, &omap_irq_chip,
|
||||
handle_level_irq);
|
||||
set_irq_flags(j, IRQF_VALID);
|
||||
}
|
||||
omap_alloc_gc(irq_banks[i].va, irq_base + i * 32, 32);
|
||||
}
|
||||
|
||||
/* Unmask level 2 handler */
|
||||
|
||||
if (cpu_is_omap7xx())
|
||||
omap_unmask_irq(irq_get_irq_data(INT_7XX_IH2_IRQ));
|
||||
else if (cpu_is_omap15xx())
|
||||
omap_unmask_irq(irq_get_irq_data(INT_1510_IH2_IRQ));
|
||||
else if (cpu_is_omap16xx())
|
||||
omap_unmask_irq(irq_get_irq_data(INT_1610_IH2_IRQ));
|
||||
d = irq_get_irq_data(irq_find_mapping(domain, omap_l2_irq));
|
||||
if (d) {
|
||||
ct = irq_data_get_chip_type(d);
|
||||
ct->chip.irq_unmask(d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
static struct omap_mux_cfg arch_mux_cfg;
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
|
||||
static struct pin_config __initdata_or_module omap7xx_pins[] = {
|
||||
static struct pin_config omap7xx_pins[] = {
|
||||
MUX_CFG_7XX("E2_7XX_KBR0", 12, 21, 0, 20, 1, 0)
|
||||
MUX_CFG_7XX("J7_7XX_KBR1", 12, 25, 0, 24, 1, 0)
|
||||
MUX_CFG_7XX("E1_7XX_KBR2", 12, 29, 0, 28, 1, 0)
|
||||
|
@ -82,7 +82,7 @@ MUX_CFG_7XX("UART_7XX_2", 8, 1, 6, 0, 0, 0)
|
|||
#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
|
||||
static struct pin_config __initdata_or_module omap1xxx_pins[] = {
|
||||
static struct pin_config omap1xxx_pins[] = {
|
||||
/*
|
||||
* description mux mode mux pull pull pull pu_pd pu dbg
|
||||
* reg offset mode reg bit ena reg
|
||||
|
@ -343,7 +343,7 @@ MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0)
|
|||
#define OMAP1XXX_PINS_SZ 0
|
||||
#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
|
||||
|
||||
static int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
|
||||
static int omap1_cfg_reg(const struct pin_config *cfg)
|
||||
{
|
||||
static DEFINE_SPINLOCK(mux_spin_lock);
|
||||
unsigned long flags;
|
||||
|
@ -469,7 +469,7 @@ int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg)
|
|||
/*
|
||||
* Sets the Omap MUX and PULL_DWN registers based on the table
|
||||
*/
|
||||
int __init_or_module omap_cfg_reg(const unsigned long index)
|
||||
int omap_cfg_reg(const unsigned long index)
|
||||
{
|
||||
struct pin_config *reg;
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "iomap.h"
|
||||
#include "clock.h"
|
||||
#include "pm.h"
|
||||
#include "soc.h"
|
||||
#include "sram.h"
|
||||
|
||||
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue