mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
ARM: SoC platform updates for v4.3
New or improved SoC support: - Addition of support for Atmel's SAMA5D2 SoC - Addition of Freescale i.MX6UL - Improved support of TI's DM814x platform - Misc fixes and improvements for RockChip platforms - Marvell MVEBU suspend/resume support A few driver changes that ideally would belong in the drivers branch are also here (acked by appropriate maintainers): - Power key input driver for Freescale platforms (svns) - RTC driver updates for Freescale platforms (svns/mxc) - Clk fixes for TI DM814/816X + a bunch of other changes for various platforms -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJV5Mo6AAoJEIwa5zzehBx3VnMP/28LFJVUjIbd2xjJBo2gbSwV jN7uGlTkKU+1kHjZqnUPuirlBxBzsXKgRfBvCoeu0cPOggwmFcaF915/HHPz7xuz vTP7k98+Y5nSXScIohWkWCdZTpKKjve4sn74rXmiNakTUiuaHf5lKut/m7ldVrWd hN1o9W4LN+5O1mOYbc9ZD98v3bkDb6eu+a22oK7qemXiEiQi+NIMoDx+IR2bd4pA FeDaW7sOFWTEYU/p+M5nZNvI3n53P0/mlB5rPRiAYRjhQf9DrWHm5G7HdnMkUkgo /s8/QlVjBkJwhkY0TqpwtHY23JjSSB6UtCnXzb1eVAkX1nJN6PJQpcpCz1zJhd9q +sJ2k1zEvrfomJCK7/iZ1ubQE09KlJLEeb8xi5xCwD0MBOBAYC31bovDVAswCitV 8NHnfltEG+wCMyX955eqqGkVxkcw8sJMJUK5A95aK6w+vKqjd7gUgLJjXFC1u4eN ECuVVUf1hVmUEmM799CDayTlfGDt4oGLmHGao+SiSCVc1XbG9HkWr7Lcgr6u9UHr lNv3RIe6Axb85xxIU0/9hqLHrtB85uEQjjlbnQx3o7u8RsSOeaiZvCz4BzcjP9E1 VGyD6zkRWhuDiMFlPVXiAX0qIH5xSjIWkC0wPNJNy8eWFH9tkfGL0mOlLbl09oGR gtuvOrjbF/BhILkPw38y =8T5Z -----END PGP SIGNATURE----- Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC platform updates from Olof Johansson: "New or improved SoC support: - add support for Atmel's SAMA5D2 SoC - add support for Freescale i.MX6UL - improved support for TI's DM814x platform - misc fixes and improvements for RockChip platforms - Marvell MVEBU suspend/resume support A few driver changes that ideally would belong in the drivers branch are also here (acked by appropriate maintainers): - power key input driver for Freescale platforms (svns) - RTC driver updates for Freescale platforms (svns/mxc) - clk fixes for TI DM814/816X + a bunch of other changes for various platforms" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (83 commits) ARM: rockchip: pm: Fix PTR_ERR() argument ARM: imx: mach-imx6ul: Fix allmodconfig build clk: ti: fix for definition movement ARM: uniphier: drop v7_invalidate_l1 call at secondary entry memory: kill off set_irq_flags usage rtc: snvs: select option REGMAP_MMIO ARM: brcmstb: select ARCH_DMA_ADDR_T_64BIT for LPAE ARM: BCM: Enable ARM erratum 798181 for BRCMSTB ARM: OMAP2+: Fix power domain operations regression caused by 81xx ARM: rockchip: enable PMU_GPIOINT_WAKEUP_EN when entering shallow suspend ARM: rockchip: set correct stabilization thresholds in suspend ARM: rockchip: rename osc_switch_to_32k variable ARM: imx6ul: add fec MAC refrence clock and phy fixup init ARM: imx6ul: add fec bits to GPR syscon definition rtc: mxc: add support of device tree dt-binding: document the binding for mxc rtc rtc: mxc: use a second rtc clock ARM: davinci: cp_intc: use IRQCHIP_SKIP_SET_WAKE instead of irq_set_wake callback soc: mediatek: Fix SCPSYS compilation ARM: at91/soc: add basic support for new sama5d2 SoC ...
This commit is contained in:
commit
50686e8a3a
@ -90,6 +90,11 @@ the Atmel website: http://www.atmel.com.
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11238-32-bit-Cortex-A5-Microcontroller-SAMA5D4_Datasheet.pdf
|
||||
|
||||
- sama5d2 family
|
||||
- sama5d27
|
||||
+ Datasheet
|
||||
Coming soon
|
||||
|
||||
|
||||
Linux kernel information
|
||||
------------------------
|
||||
|
@ -27,6 +27,8 @@ compatible: must be one of:
|
||||
o "atmel,at91sam9xe"
|
||||
* "atmel,sama5" for SoCs using a Cortex-A5, shall be extended with the specific
|
||||
SoC family:
|
||||
o "atmel,sama5d2" shall be extended with the specific SoC compatible:
|
||||
- "atmel,sama5d27"
|
||||
o "atmel,sama5d3" shall be extended with the specific SoC compatible:
|
||||
- "atmel,sama5d31"
|
||||
- "atmel,sama5d33"
|
||||
|
@ -305,12 +305,13 @@ Secure Non-Volatile Storage (SNVS) Node
|
||||
Node defines address range and the associated
|
||||
interrupt for the SNVS function. This function
|
||||
monitors security state information & reports
|
||||
security violations.
|
||||
security violations. This also included rtc,
|
||||
system power off and ON/OFF key.
|
||||
|
||||
- compatible
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Must include "fsl,sec-v4.0-mon".
|
||||
Definition: Must include "fsl,sec-v4.0-mon" and "syscon".
|
||||
|
||||
- reg
|
||||
Usage: required
|
||||
@ -341,7 +342,7 @@ Secure Non-Volatile Storage (SNVS) Node
|
||||
the child address, parent address, & length.
|
||||
|
||||
- interrupts
|
||||
Usage: required
|
||||
Usage: optional
|
||||
Value type: <prop_encoded-array>
|
||||
Definition: Specifies the interrupts generated by this
|
||||
device. The value of the interrupts property
|
||||
@ -358,7 +359,7 @@ Secure Non-Volatile Storage (SNVS) Node
|
||||
|
||||
EXAMPLE
|
||||
sec_mon@314000 {
|
||||
compatible = "fsl,sec-v4.0-mon";
|
||||
compatible = "fsl,sec-v4.0-mon", "syscon";
|
||||
reg = <0x314000 0x1000>;
|
||||
ranges = <0 0x314000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
@ -375,16 +376,72 @@ Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
|
||||
Value type: <string>
|
||||
Definition: Must include "fsl,sec-v4.0-mon-rtc-lp".
|
||||
|
||||
- reg
|
||||
- interrupts
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A standard property. Specifies the physical
|
||||
address and length of the SNVS LP configuration registers.
|
||||
Value type: <prop_encoded-array>
|
||||
Definition: Specifies the interrupts generated by this
|
||||
device. The value of the interrupts property
|
||||
consists of one interrupt specifier. The format
|
||||
of the specifier is defined by the binding document
|
||||
describing the node's interrupt parent.
|
||||
|
||||
- regmap
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: this is phandle to the register map node.
|
||||
|
||||
- offset
|
||||
Usage: option
|
||||
value type: <u32>
|
||||
Definition: LP register offset. default it is 0x34.
|
||||
|
||||
EXAMPLE
|
||||
sec_mon_rtc_lp@314000 {
|
||||
sec_mon_rtc_lp@1 {
|
||||
compatible = "fsl,sec-v4.0-mon-rtc-lp";
|
||||
reg = <0x34 0x58>;
|
||||
interrupts = <93 2>;
|
||||
regmap = <&snvs>;
|
||||
offset = <0x34>;
|
||||
};
|
||||
|
||||
=====================================================================
|
||||
System ON/OFF key driver
|
||||
|
||||
The snvs-pwrkey is designed to enable POWER key function which controlled
|
||||
by SNVS ONOFF, the driver can report the status of POWER key and wakeup
|
||||
system if pressed after system suspend.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Mush include "fsl,sec-v4.0-pwrkey".
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop_encoded-array>
|
||||
Definition: The SNVS ON/OFF interrupt number to the CPU(s).
|
||||
|
||||
- linux,keycode:
|
||||
Usage: option
|
||||
Value type: <int>
|
||||
Definition: Keycode to emit, KEY_POWER by default.
|
||||
|
||||
- wakeup-source:
|
||||
Usage: option
|
||||
Value type: <boo>
|
||||
Definition: Button can wake-up the system.
|
||||
|
||||
- regmap:
|
||||
Usage: required:
|
||||
Value type: <phandle>
|
||||
Definition: this is phandle to the register map node.
|
||||
|
||||
EXAMPLE:
|
||||
snvs-pwrkey@0x020cc000 {
|
||||
compatible = "fsl,sec-v4.0-pwrkey";
|
||||
regmap = <&snvs>;
|
||||
interrupts = <0 4 0x4>
|
||||
linux,keycode = <116>; /* KEY_POWER */
|
||||
wakeup;
|
||||
};
|
||||
|
||||
=====================================================================
|
||||
@ -460,12 +517,20 @@ FULL EXAMPLE
|
||||
compatible = "fsl,sec-v4.0-mon";
|
||||
reg = <0x314000 0x1000>;
|
||||
ranges = <0 0x314000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <93 2>;
|
||||
|
||||
sec_mon_rtc_lp@34 {
|
||||
compatible = "fsl,sec-v4.0-mon-rtc-lp";
|
||||
reg = <0x34 0x58>;
|
||||
regmap = <&sec_mon>;
|
||||
offset = <0x34>;
|
||||
interrupts = <93 2>;
|
||||
};
|
||||
|
||||
snvs-pwrkey@0x020cc000 {
|
||||
compatible = "fsl,sec-v4.0-pwrkey";
|
||||
regmap = <&sec_mon>;
|
||||
interrupts = <0 4 0x4>;
|
||||
linux,keycode = <116>; /* KEY_POWER */
|
||||
wakeup;
|
||||
};
|
||||
};
|
||||
|
||||
|
1
Documentation/devicetree/bindings/input/snvs-pwrkey.txt
Normal file
1
Documentation/devicetree/bindings/input/snvs-pwrkey.txt
Normal file
@ -0,0 +1 @@
|
||||
See Documentation/devicetree/bindings/crypto/fsl-sec4.txt
|
26
Documentation/devicetree/bindings/rtc/rtc-mxc.txt
Normal file
26
Documentation/devicetree/bindings/rtc/rtc-mxc.txt
Normal file
@ -0,0 +1,26 @@
|
||||
* Real Time Clock of the i.MX SoCs
|
||||
|
||||
RTC controller for the i.MX SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,imx1-rtc" or "fsl,imx21-rtc".
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: IRQ line for the RTC.
|
||||
- clocks: should contain two entries:
|
||||
* one for the input reference
|
||||
* one for the the SoC RTC
|
||||
- clock-names: should contain:
|
||||
* "ref" for the input reference clock
|
||||
* "ipg" for the SoC RTC clock
|
||||
|
||||
Example:
|
||||
|
||||
rtc@10007000 {
|
||||
compatible = "fsl,imx21-rtc";
|
||||
reg = <0x10007000 0x1000>;
|
||||
interrupts = <22>;
|
||||
clocks = <&clks IMX27_CLK_CKIL>,
|
||||
<&clks IMX27_CLK_RTC_IPG_GATE>;
|
||||
clock-names = "ref", "ipg";
|
||||
};
|
41
Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
Normal file
41
Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
Normal file
@ -0,0 +1,41 @@
|
||||
MediaTek SCPSYS
|
||||
===============
|
||||
|
||||
The System Control Processor System (SCPSYS) has several power management
|
||||
related tasks in the system. The tasks include thermal measurement, dynamic
|
||||
voltage frequency scaling (DVFS), interrupt filter and lowlevel sleep control.
|
||||
The System Power Manager (SPM) inside the SCPSYS is for the MTCMOS power
|
||||
domain control.
|
||||
|
||||
The driver implements the Generic PM domain bindings described in
|
||||
power/power_domain.txt. It provides the power domains defined in
|
||||
include/dt-bindings/power/mt8173-power.h.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "mediatek,mt8173-scpsys"
|
||||
- #power-domain-cells: Must be 1
|
||||
- reg: Address range of the SCPSYS unit
|
||||
- infracfg: must contain a phandle to the infracfg controller
|
||||
- clock, clock-names: clocks according to the common clock binding.
|
||||
The clocks needed "mm" and "mfg". These are the
|
||||
clocks which hardware needs to be enabled before
|
||||
enabling certain power domains.
|
||||
|
||||
Example:
|
||||
|
||||
scpsys: scpsys@10006000 {
|
||||
#power-domain-cells = <1>;
|
||||
compatible = "mediatek,mt8173-scpsys";
|
||||
reg = <0 0x10006000 0 0x1000>;
|
||||
infracfg = <&infracfg>;
|
||||
clocks = <&clk26m>,
|
||||
<&topckgen CLK_TOP_MM_SEL>;
|
||||
clock-names = "mfg", "mm";
|
||||
};
|
||||
|
||||
Example consumer:
|
||||
|
||||
afe: mt8173-afe-pcm@11220000 {
|
||||
compatible = "mediatek,mt8173-afe-pcm";
|
||||
power-domains = <&scpsys MT8173_POWER_DOMAIN_AUDIO>;
|
||||
};
|
@ -1583,7 +1583,10 @@ 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/boot/dts/uniphier*
|
||||
F: arch/arm/mach-uniphier/
|
||||
F: drivers/pinctrl/uniphier/
|
||||
F: drivers/tty/serial/8250/8250_uniphier.c
|
||||
N: uniphier
|
||||
|
||||
ARM/Ux500 ARM ARCHITECTURE
|
||||
@ -1678,7 +1681,7 @@ M: Michal Simek <michal.simek@xilinx.com>
|
||||
R: Sören Brinkmann <soren.brinkmann@xilinx.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
W: http://wiki.xilinx.com
|
||||
T: git git://git.xilinx.com/linux-xlnx.git
|
||||
T: git https://github.com/Xilinx/linux-xlnx.git
|
||||
S: Supported
|
||||
F: arch/arm/mach-zynq/
|
||||
F: drivers/cpuidle/cpuidle-zynq.c
|
||||
|
@ -141,6 +141,12 @@ choice
|
||||
depends on ARCH_AT91
|
||||
depends on SOC_SAMA5
|
||||
|
||||
config AT91_DEBUG_LL_DBGU3
|
||||
bool "Kernel low-level debugging on sama5d2"
|
||||
select DEBUG_AT91_UART
|
||||
depends on ARCH_AT91
|
||||
depends on SOC_SAMA5
|
||||
|
||||
config DEBUG_BCM2835
|
||||
bool "Kernel low-level debugging on BCM2835 PL011 UART"
|
||||
depends on ARCH_BCM2835
|
||||
@ -411,6 +417,13 @@ choice
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on i.MX6SX.
|
||||
|
||||
config DEBUG_IMX6UL_UART
|
||||
bool "i.MX6UL Debug UART"
|
||||
depends on SOC_IMX6UL
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on i.MX6UL.
|
||||
|
||||
config DEBUG_IMX7D_UART
|
||||
bool "i.MX7D Debug UART"
|
||||
depends on SOC_IMX7D
|
||||
@ -1269,6 +1282,7 @@ config DEBUG_IMX_UART_PORT
|
||||
DEBUG_IMX6Q_UART || \
|
||||
DEBUG_IMX6SL_UART || \
|
||||
DEBUG_IMX6SX_UART || \
|
||||
DEBUG_IMX6UL_UART || \
|
||||
DEBUG_IMX7D_UART
|
||||
default 1
|
||||
depends on ARCH_MXC
|
||||
@ -1320,6 +1334,7 @@ config DEBUG_LL_INCLUDE
|
||||
DEBUG_IMX6Q_UART || \
|
||||
DEBUG_IMX6SL_UART || \
|
||||
DEBUG_IMX6SX_UART || \
|
||||
DEBUG_IMX6UL_UART || \
|
||||
DEBUG_IMX7D_UART
|
||||
default "debug/ks8695.S" if DEBUG_KS8695_UART
|
||||
default "debug/msm.S" if DEBUG_QCOM_UARTDM
|
||||
|
@ -86,6 +86,7 @@
|
||||
prcm: prcm@1f0000 {
|
||||
compatible = "ti,am4-prcm";
|
||||
reg = <0x1f0000 0x11000>;
|
||||
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
prcm_clocks: clocks {
|
||||
#address-cells = <1>;
|
||||
|
@ -13,9 +13,12 @@
|
||||
#define AT91_DBGU 0xfffff200 /* AT91_BASE_DBGU0 */
|
||||
#elif defined(CONFIG_AT91_DEBUG_LL_DBGU1)
|
||||
#define AT91_DBGU 0xffffee00 /* AT91_BASE_DBGU1 */
|
||||
#else
|
||||
#elif defined(CONFIG_AT91_DEBUG_LL_DBGU2)
|
||||
/* On sama5d4, use USART3 as low level serial console */
|
||||
#define AT91_DBGU 0xfc00c000 /* SAMA5D4_BASE_USART3 */
|
||||
#else
|
||||
/* On sama5d2, use UART1 as low level serial console */
|
||||
#define AT91_DBGU 0xf8020000
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
@ -90,6 +90,17 @@
|
||||
#define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR
|
||||
#define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n)
|
||||
|
||||
#define IMX6UL_UART1_BASE_ADDR 0x02020000
|
||||
#define IMX6UL_UART2_BASE_ADDR 0x021e8000
|
||||
#define IMX6UL_UART3_BASE_ADDR 0x021ec000
|
||||
#define IMX6UL_UART4_BASE_ADDR 0x021f0000
|
||||
#define IMX6UL_UART5_BASE_ADDR 0x021f4000
|
||||
#define IMX6UL_UART6_BASE_ADDR 0x021fc000
|
||||
#define IMX6UL_UART7_BASE_ADDR 0x02018000
|
||||
#define IMX6UL_UART8_BASE_ADDR 0x02024000
|
||||
#define IMX6UL_UART_BASE_ADDR(n) IMX6UL_UART##n##_BASE_ADDR
|
||||
#define IMX6UL_UART_BASE(n) IMX6UL_UART_BASE_ADDR(n)
|
||||
|
||||
#define IMX7D_UART1_BASE_ADDR 0x30860000
|
||||
#define IMX7D_UART2_BASE_ADDR 0x30890000
|
||||
#define IMX7D_UART3_BASE_ADDR 0x30880000
|
||||
@ -124,6 +135,8 @@
|
||||
#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_IMX6UL_UART)
|
||||
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6UL)
|
||||
#elif defined(CONFIG_DEBUG_IMX7D_UART)
|
||||
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D)
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
.endm
|
||||
|
||||
.macro senduart,rd,rx
|
||||
str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
|
||||
strb \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
|
||||
.endm
|
||||
|
||||
.macro waituart,rd,rx
|
||||
|
@ -8,6 +8,18 @@ menuconfig ARCH_AT91
|
||||
select SOC_BUS
|
||||
|
||||
if ARCH_AT91
|
||||
config SOC_SAMA5D2
|
||||
bool "SAMA5D2 family" if ARCH_MULTI_V7
|
||||
select SOC_SAMA5
|
||||
select CACHE_L2X0
|
||||
select HAVE_FB_ATMEL
|
||||
select HAVE_AT91_UTMI
|
||||
select HAVE_AT91_USB_CLK
|
||||
select HAVE_AT91_H32MX
|
||||
select HAVE_AT91_GENERATED_CLK
|
||||
help
|
||||
Select this if ou are using one of Atmel's SAMA5D2 family SoC.
|
||||
|
||||
config SOC_SAMA5D3
|
||||
bool "SAMA5D3 family" if ARCH_MULTI_V7
|
||||
select SOC_SAMA5
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "soc.h"
|
||||
|
||||
static const struct at91_soc sama5_socs[] = {
|
||||
AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27_EXID_MATCH,
|
||||
"sama5d27", "sama5d2"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
|
||||
"sama5d31", "sama5d3"),
|
||||
AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
|
||||
@ -64,6 +66,7 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5")
|
||||
MACHINE_END
|
||||
|
||||
static const char *const sama5_alt_dt_board_compat[] __initconst = {
|
||||
"atmel,sama5d2",
|
||||
"atmel,sama5d4",
|
||||
NULL
|
||||
};
|
||||
|
@ -62,6 +62,9 @@ at91_soc_init(const struct at91_soc *socs);
|
||||
#define AT91SAM9XE256_CIDR_MATCH 0x329a93a0
|
||||
#define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0
|
||||
|
||||
#define SAMA5D2_CIDR_MATCH 0x0a5c08c0
|
||||
#define SAMA5D27_EXID_MATCH 0x00000021
|
||||
|
||||
#define SAMA5D3_CIDR_MATCH 0x0a5c07c0
|
||||
#define SAMA5D31_EXID_MATCH 0x00444300
|
||||
#define SAMA5D33_EXID_MATCH 0x00414300
|
||||
|
@ -140,10 +140,12 @@ config ARCH_BCM_63XX
|
||||
config ARCH_BRCMSTB
|
||||
bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
|
||||
select ARM_GIC
|
||||
select ARM_ERRATA_798181 if SMP
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select BRCMSTB_GISB_ARB
|
||||
select BRCMSTB_L2_IRQ
|
||||
select BCM7120_L2_IRQ
|
||||
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
help
|
||||
Say Y if you intend to run the kernel on a Broadcom ARM-based STB
|
||||
|
@ -85,23 +85,13 @@ static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Faking this allows us to to work with suspend functions of
|
||||
* generic drivers which call {enable|disable}_irq_wake for
|
||||
* wake up interrupt sources (eg RTC on DA850).
|
||||
*/
|
||||
static int cp_intc_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip cp_intc_irq_chip = {
|
||||
.name = "cp_intc",
|
||||
.irq_ack = cp_intc_ack_irq,
|
||||
.irq_mask = cp_intc_mask_irq,
|
||||
.irq_unmask = cp_intc_unmask_irq,
|
||||
.irq_set_type = cp_intc_set_irq_type,
|
||||
.irq_set_wake = cp_intc_set_wake,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
static struct irq_domain *cp_intc_domain;
|
||||
|
@ -548,6 +548,14 @@ config SOC_IMX6SX
|
||||
help
|
||||
This enables support for Freescale i.MX6 SoloX processor.
|
||||
|
||||
config SOC_IMX6UL
|
||||
bool "i.MX6 UltraLite support"
|
||||
select PINCTRL_IMX6UL
|
||||
select SOC_IMX6
|
||||
|
||||
help
|
||||
This enables support for Freescale i.MX6 UltraLite processor.
|
||||
|
||||
config SOC_IMX7D
|
||||
bool "i.MX7 Dual support"
|
||||
select PINCTRL_IMX7D
|
||||
|
@ -83,6 +83,7 @@ endif
|
||||
obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
|
||||
obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
|
||||
obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
|
||||
obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
|
||||
obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
|
||||
|
||||
ifeq ($(CONFIG_SUSPEND),y)
|
||||
|
@ -130,6 +130,9 @@ struct device * __init imx_soc_device_init(void)
|
||||
case MXC_CPU_IMX6Q:
|
||||
soc_id = "i.MX6Q";
|
||||
break;
|
||||
case MXC_CPU_IMX6UL:
|
||||
soc_id = "i.MX6UL";
|
||||
break;
|
||||
case MXC_CPU_IMX7D:
|
||||
soc_id = "i.MX7D";
|
||||
break;
|
||||
|
88
arch/arm/mach-imx/mach-imx6ul.c
Normal file
88
arch/arm/mach-imx/mach-imx6ul.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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/mfd/syscon.h>
|
||||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/micrel_phy.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void __init imx6ul_enet_clk_init(void)
|
||||
{
|
||||
struct regmap *gpr;
|
||||
|
||||
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
|
||||
if (!IS_ERR(gpr))
|
||||
regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_ENET_CLK_DIR,
|
||||
IMX6UL_GPR1_ENET_CLK_OUTPUT);
|
||||
else
|
||||
pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
|
||||
|
||||
}
|
||||
|
||||
static int ksz8081_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
if (dev && dev->interface == PHY_INTERFACE_MODE_MII) {
|
||||
phy_write(dev, 0x1f, 0x8110);
|
||||
phy_write(dev, 0x16, 0x201);
|
||||
} else if (dev && dev->interface == PHY_INTERFACE_MODE_RMII) {
|
||||
phy_write(dev, 0x1f, 0x8190);
|
||||
phy_write(dev, 0x16, 0x202);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init imx6ul_enet_phy_init(void)
|
||||
{
|
||||
if (IS_BUILTIN(CONFIG_PHYLIB))
|
||||
phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
|
||||
ksz8081_phy_fixup);
|
||||
}
|
||||
|
||||
static inline void imx6ul_enet_init(void)
|
||||
{
|
||||
imx6ul_enet_clk_init();
|
||||
imx6ul_enet_phy_init();
|
||||
}
|
||||
|
||||
static void __init imx6ul_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);
|
||||
imx6ul_enet_init();
|
||||
imx_anatop_init();
|
||||
}
|
||||
|
||||
static void __init imx6ul_init_irq(void)
|
||||
{
|
||||
imx_init_revision_from_anatop();
|
||||
imx_src_init();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
static const char *imx6ul_dt_compat[] __initconst = {
|
||||
"fsl,imx6ul",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
|
||||
.init_irq = imx6ul_init_irq,
|
||||
.init_machine = imx6ul_init_machine,
|
||||
.dt_compat = imx6ul_dt_compat,
|
||||
MACHINE_END
|
@ -38,6 +38,7 @@
|
||||
#define MXC_CPU_IMX6DL 0x61
|
||||
#define MXC_CPU_IMX6SX 0x62
|
||||
#define MXC_CPU_IMX6Q 0x63
|
||||
#define MXC_CPU_IMX6UL 0x64
|
||||
#define MXC_CPU_IMX7D 0x72
|
||||
|
||||
#define IMX_DDR_TYPE_LPDDR2 1
|
||||
@ -165,6 +166,11 @@ static inline bool cpu_is_imx6sx(void)
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6SX;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6ul(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6UL;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6q(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6Q;
|
||||
|
@ -3,6 +3,7 @@ menuconfig ARCH_MEDIATEK
|
||||
select ARM_GIC
|
||||
select PINCTRL
|
||||
select MTK_TIMER
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Support for Mediatek MT65xx & MT81xx SoCs
|
||||
|
||||
|
@ -65,18 +65,6 @@ static const struct of_device_id of_coherency_table[] = {
|
||||
int ll_enable_coherency(void);
|
||||
void ll_add_cpu_to_smp_group(void);
|
||||
|
||||
int set_cpu_coherent(void)
|
||||
{
|
||||
if (!coherency_base) {
|
||||
pr_warn("Can't make current CPU cache coherent.\n");
|
||||
pr_warn("Coherency fabric is not initialized\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ll_add_cpu_to_smp_group();
|
||||
return ll_enable_coherency();
|
||||
}
|
||||
|
||||
static int mvebu_hwcc_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *__dev)
|
||||
{
|
||||
@ -206,6 +194,23 @@ static int coherency_type(void)
|
||||
return type;
|
||||
}
|
||||
|
||||
int set_cpu_coherent(void)
|
||||
{
|
||||
int type = coherency_type();
|
||||
|
||||
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) {
|
||||
if (!coherency_base) {
|
||||
pr_warn("Can't make current CPU cache coherent.\n");
|
||||
pr_warn("Coherency fabric is not initialized\n");
|
||||
return 1;
|
||||
}
|
||||
ll_add_cpu_to_smp_group();
|
||||
return ll_enable_coherency();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int coherency_available(void)
|
||||
{
|
||||
return coherency_type() != COHERENCY_FABRIC_TYPE_NONE;
|
||||
|
@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
|
||||
|
||||
void __iomem *mvebu_get_scu_base(void);
|
||||
|
||||
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd));
|
||||
|
||||
int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
|
||||
u32 srcmd));
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Board-level suspend/resume support.
|
||||
*
|
||||
* Copyright (C) 2014 Marvell
|
||||
* Copyright (C) 2014-2015 Marvell
|
||||
*
|
||||
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
*
|
||||
@ -20,27 +20,27 @@
|
||||
#include <linux/slab.h>
|
||||
#include "common.h"
|
||||
|
||||
#define ARMADA_XP_GP_PIC_NR_GPIOS 3
|
||||
#define ARMADA_PIC_NR_GPIOS 3
|
||||
|
||||
static void __iomem *gpio_ctrl;
|
||||
static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
|
||||
static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
|
||||
static int pic_gpios[ARMADA_PIC_NR_GPIOS];
|
||||
static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS];
|
||||
|
||||
static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
|
||||
static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd)
|
||||
{
|
||||
u32 reg, ackcmd;
|
||||
int i;
|
||||
|
||||
/* Put 001 as value on the GPIOs */
|
||||
reg = readl(gpio_ctrl);
|
||||
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
|
||||
for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
|
||||
reg &= ~BIT(pic_raw_gpios[i]);
|
||||
reg |= BIT(pic_raw_gpios[0]);
|
||||
writel(reg, gpio_ctrl);
|
||||
|
||||
/* Prepare writing 111 to the GPIOs */
|
||||
ackcmd = readl(gpio_ctrl);
|
||||
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
|
||||
for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
|
||||
ackcmd |= BIT(pic_raw_gpios[i]);
|
||||
|
||||
srcmd = cpu_to_le32(srcmd);
|
||||
@ -76,7 +76,7 @@ static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
|
||||
[ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
|
||||
}
|
||||
|
||||
static int mvebu_armada_xp_gp_pm_init(void)
|
||||
static int __init mvebu_armada_pm_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct device_node *gpio_ctrl_np;
|
||||
@ -89,7 +89,7 @@ static int mvebu_armada_xp_gp_pm_init(void)
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) {
|
||||
for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) {
|
||||
char *name;
|
||||
struct of_phandle_args args;
|
||||
|
||||
@ -134,11 +134,19 @@ static int mvebu_armada_xp_gp_pm_init(void)
|
||||
if (!gpio_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
mvebu_pm_init(mvebu_armada_xp_gp_pm_enter);
|
||||
mvebu_pm_suspend_init(mvebu_armada_pm_enter);
|
||||
|
||||
out:
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
late_initcall(mvebu_armada_xp_gp_pm_init);
|
||||
/*
|
||||
* Registering the mvebu_board_pm_enter callback must be done before
|
||||
* the platform_suspend_ops will be registered. In the same time we
|
||||
* also need to have the gpio devices registered. That's why we use a
|
||||
* device_initcall_sync which is called after all the device_initcall
|
||||
* (used by the gpio device) but before the late_initcall (used to
|
||||
* register the platform_suspend_ops)
|
||||
*/
|
||||
device_initcall_sync(mvebu_armada_pm_init);
|
||||
|
@ -105,12 +105,10 @@ static phys_addr_t mvebu_internal_reg_base(void)
|
||||
return of_translate_address(np, in_addr);
|
||||
}
|
||||
|
||||
static void mvebu_pm_store_bootinfo(void)
|
||||
static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr)
|
||||
{
|
||||
u32 *store_addr;
|
||||
phys_addr_t resume_pc;
|
||||
|
||||
store_addr = phys_to_virt(BOOT_INFO_ADDR);
|
||||
resume_pc = virt_to_phys(armada_370_xp_cpu_resume);
|
||||
|
||||
/*
|
||||
@ -151,14 +149,30 @@ static void mvebu_pm_store_bootinfo(void)
|
||||
writel(BOOT_MAGIC_LIST_END, store_addr);
|
||||
}
|
||||
|
||||
static int mvebu_pm_enter(suspend_state_t state)
|
||||
static int mvebu_pm_store_bootinfo(void)
|
||||
{
|
||||
if (state != PM_SUSPEND_MEM)
|
||||
return -EINVAL;
|
||||
u32 *store_addr;
|
||||
|
||||
store_addr = phys_to_virt(BOOT_INFO_ADDR);
|
||||
|
||||
if (of_machine_is_compatible("marvell,armadaxp"))
|
||||
mvebu_pm_store_armadaxp_bootinfo(store_addr);
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_enter_suspend(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mvebu_pm_store_bootinfo();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cpu_pm_enter();
|
||||
|
||||
mvebu_pm_store_bootinfo();
|
||||
cpu_suspend(0, mvebu_pm_powerdown);
|
||||
|
||||
outer_resume();
|
||||
@ -168,23 +182,62 @@ static int mvebu_pm_enter(suspend_state_t state)
|
||||
set_cpu_coherent();
|
||||
|
||||
cpu_pm_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
cpu_do_idle();
|
||||
break;
|
||||
case PM_SUSPEND_MEM:
|
||||
pr_warn("Entering suspend to RAM. Only special wake-up sources will resume the system\n");
|
||||
return mvebu_enter_suspend();
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_pm_valid(suspend_state_t state)
|
||||
{
|
||||
if (state == PM_SUSPEND_STANDBY)
|
||||
return 1;
|
||||
|
||||
if (state == PM_SUSPEND_MEM && mvebu_board_pm_enter != NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops mvebu_pm_ops = {
|
||||
.enter = mvebu_pm_enter,
|
||||
.valid = suspend_valid_only_mem,
|
||||
.valid = mvebu_pm_valid,
|
||||
};
|
||||
|
||||
int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
|
||||
static int __init mvebu_pm_init(void)
|
||||
{
|
||||
if (!of_machine_is_compatible("marvell,armadaxp") &&
|
||||
!of_machine_is_compatible("marvell,armada370") &&
|
||||
!of_machine_is_compatible("marvell,armada380") &&
|
||||
!of_machine_is_compatible("marvell,armada390"))
|
||||
return -ENODEV;
|
||||
|
||||
suspend_set_ops(&mvebu_pm_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
late_initcall(mvebu_pm_init);
|
||||
|
||||
int __init mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg,
|
||||
u32 srcmd))
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
|
||||
if (!of_machine_is_compatible("marvell,armadaxp"))
|
||||
return -ENODEV;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL,
|
||||
"marvell,armada-xp-sdram-controller");
|
||||
if (!np)
|
||||
@ -212,7 +265,5 @@ int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
|
||||
|
||||
mvebu_board_pm_enter = board_pm_enter;
|
||||
|
||||
suspend_set_ops(&mvebu_pm_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -226,8 +226,7 @@ obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o
|
||||
# EMU peripherals
|
||||
obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
|
||||
|
||||
iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
|
||||
obj-y += $(iommu-m) $(iommu-y)
|
||||
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
|
||||
|
||||
# OMAP2420 MSDI controller integration support ("MMC")
|
||||
obj-$(CONFIG_SOC_OMAP2420) += msdi.o
|
||||
|
@ -169,7 +169,7 @@ static const char *const ti814x_boards_compat[] __initconst = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(TI81XX_DT, "Generic ti814x (Flattened Device Tree)")
|
||||
DT_MACHINE_START(TI814X_DT, "Generic ti814x (Flattened Device Tree)")
|
||||
.reserve = omap_reserve,
|
||||
.map_io = ti81xx_map_io,
|
||||
.init_early = ti814x_init_early,
|
||||
@ -297,7 +297,7 @@ static const char *const dra74x_boards_compat[] __initconst = {
|
||||
DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
|
||||
.reserve = omap_reserve,
|
||||
.smp = smp_ops(omap4_smp_ops),
|
||||
.map_io = omap5_map_io,
|
||||
.map_io = dra7xx_map_io,
|
||||
.init_early = dra7xx_init_early,
|
||||
.init_late = dra7xx_init_late,
|
||||
.init_irq = omap_gic_of_init,
|
||||
@ -316,7 +316,7 @@ static const char *const dra72x_boards_compat[] __initconst = {
|
||||
|
||||
DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)")
|
||||
.reserve = omap_reserve,
|
||||
.map_io = omap5_map_io,
|
||||
.map_io = dra7xx_map_io,
|
||||
.init_early = dra7xx_init_early,
|
||||
.init_late = dra7xx_init_late,
|
||||
.init_irq = omap_gic_of_init,
|
||||
|
@ -216,7 +216,8 @@ extern void __init omap242x_clockdomains_init(void);
|
||||
extern void __init omap243x_clockdomains_init(void);
|
||||
extern void __init omap3xxx_clockdomains_init(void);
|
||||
extern void __init am33xx_clockdomains_init(void);
|
||||
extern void __init ti81xx_clockdomains_init(void);
|
||||
extern void __init ti814x_clockdomains_init(void);
|
||||
extern void __init ti816x_clockdomains_init(void);
|
||||
extern void __init omap44xx_clockdomains_init(void);
|
||||
extern void __init omap54xx_clockdomains_init(void);
|
||||
extern void __init dra7xx_clockdomains_init(void);
|
||||
|
@ -331,7 +331,7 @@ static struct clockdomain l4per2_7xx_clkdm = {
|
||||
.dep_bit = DRA7XX_L4PER2_STATDEP_SHIFT,
|
||||
.wkdep_srcs = l4per2_wkup_sleep_deps,
|
||||
.sleepdep_srcs = l4per2_wkup_sleep_deps,
|
||||
.flags = CLKDM_CAN_HWSUP_SWSUP,
|
||||
.flags = CLKDM_CAN_SWSUP,
|
||||
};
|
||||
|
||||
static struct clockdomain mpu0_7xx_clkdm = {
|
||||
|
@ -165,7 +165,24 @@ static struct clockdomain default_l3_slow_816x_clkdm = {
|
||||
.flags = CLKDM_CAN_SWSUP,
|
||||
};
|
||||
|
||||
static struct clockdomain *clockdomains_ti81xx[] __initdata = {
|
||||
static struct clockdomain *clockdomains_ti814x[] __initdata = {
|
||||
&alwon_l3_slow_81xx_clkdm,
|
||||
&alwon_l3_med_81xx_clkdm,
|
||||
&alwon_l3_fast_81xx_clkdm,
|
||||
&alwon_ethernet_81xx_clkdm,
|
||||
&mmu_81xx_clkdm,
|
||||
&mmu_cfg_81xx_clkdm,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void __init ti814x_clockdomains_init(void)
|
||||
{
|
||||
clkdm_register_platform_funcs(&am33xx_clkdm_operations);
|
||||
clkdm_register_clkdms(clockdomains_ti814x);
|
||||
clkdm_complete_init();
|
||||
}
|
||||
|
||||
static struct clockdomain *clockdomains_ti816x[] __initdata = {
|
||||
&alwon_mpu_816x_clkdm,
|
||||
&alwon_l3_slow_81xx_clkdm,
|
||||
&alwon_l3_med_81xx_clkdm,
|
||||
@ -185,10 +202,10 @@ static struct clockdomain *clockdomains_ti81xx[] __initdata = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
void __init ti81xx_clockdomains_init(void)
|
||||
void __init ti816x_clockdomains_init(void)
|
||||
{
|
||||
clkdm_register_platform_funcs(&am33xx_clkdm_operations);
|
||||
clkdm_register_clkdms(clockdomains_ti81xx);
|
||||
clkdm_register_clkdms(clockdomains_ti816x);
|
||||
clkdm_complete_init();
|
||||
}
|
||||
#endif
|
||||
|
@ -198,6 +198,7 @@ void __init omap3_map_io(void);
|
||||
void __init am33xx_map_io(void);
|
||||
void __init omap4_map_io(void);
|
||||
void __init omap5_map_io(void);
|
||||
void __init dra7xx_map_io(void);
|
||||
void __init ti81xx_map_io(void);
|
||||
|
||||
/**
|
||||
|
@ -652,6 +652,7 @@ static const struct of_device_id omap_scrm_dt_match_table[] = {
|
||||
{ .compatible = "ti,am4-scm", .data = &ctrl_data },
|
||||
{ .compatible = "ti,omap2-scm", .data = &omap2_ctrl_data },
|
||||
{ .compatible = "ti,omap3-scm", .data = &omap2_ctrl_data },
|
||||
{ .compatible = "ti,dm814-scm", .data = &ctrl_data },
|
||||
{ .compatible = "ti,dm816-scrm", .data = &ctrl_data },
|
||||
{ .compatible = "ti,omap4-scm-core", .data = &ctrl_data },
|
||||
{ .compatible = "ti,omap5-scm-core", .data = &ctrl_data },
|
||||
|
@ -235,7 +235,7 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
|
||||
#ifdef CONFIG_SOC_OMAP5
|
||||
static struct map_desc omap54xx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = L3_54XX_VIRT,
|
||||
@ -264,6 +264,53 @@ static struct map_desc omap54xx_io_desc[] __initdata = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_DRA7XX
|
||||
static struct map_desc dra7xx_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = L4_CFG_MPU_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_CFG_MPU_DRA7XX_PHYS),
|
||||
.length = L4_CFG_MPU_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L3_MAIN_SN_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L3_MAIN_SN_DRA7XX_PHYS),
|
||||
.length = L3_MAIN_SN_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L4_PER1_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_PER1_DRA7XX_PHYS),
|
||||
.length = L4_PER1_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L4_PER2_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_PER2_DRA7XX_PHYS),
|
||||
.length = L4_PER2_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L4_PER3_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_PER3_DRA7XX_PHYS),
|
||||
.length = L4_PER3_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L4_CFG_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_CFG_DRA7XX_PHYS),
|
||||
.length = L4_CFG_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = L4_WKUP_DRA7XX_VIRT,
|
||||
.pfn = __phys_to_pfn(L4_WKUP_DRA7XX_PHYS),
|
||||
.length = L4_WKUP_DRA7XX_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_OMAP2420
|
||||
void __init omap242x_map_io(void)
|
||||
{
|
||||
@ -308,12 +355,19 @@ void __init omap4_map_io(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
|
||||
#ifdef CONFIG_SOC_OMAP5
|
||||
void __init omap5_map_io(void)
|
||||
{
|
||||
iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_DRA7XX
|
||||
void __init dra7xx_map_io(void)
|
||||
{
|
||||
iotable_init(dra7xx_io_desc, ARRAY_SIZE(dra7xx_io_desc));
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
|
||||
*
|
||||
@ -553,11 +607,11 @@ void __init ti814x_init_early(void)
|
||||
omap2_prcm_base_init();
|
||||
omap3xxx_voltagedomains_init();
|
||||
omap3xxx_powerdomains_init();
|
||||
ti81xx_clockdomains_init();
|
||||
ti81xx_hwmod_init();
|
||||
ti814x_clockdomains_init();
|
||||
dm814x_hwmod_init();
|
||||
omap_hwmod_init_postsetup();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = ti81xx_dt_clk_init;
|
||||
omap_clk_soc_init = dm814x_dt_clk_init;
|
||||
}
|
||||
|
||||
void __init ti816x_init_early(void)
|
||||
@ -570,11 +624,11 @@ void __init ti816x_init_early(void)
|
||||
omap2_prcm_base_init();
|
||||
omap3xxx_voltagedomains_init();
|
||||
omap3xxx_powerdomains_init();
|
||||
ti81xx_clockdomains_init();
|
||||
ti81xx_hwmod_init();
|
||||
ti816x_clockdomains_init();
|
||||
dm816x_hwmod_init();
|
||||
omap_hwmod_init_postsetup();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = ti81xx_dt_clk_init;
|
||||
omap_clk_soc_init = dm816x_dt_clk_init;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -194,3 +194,66 @@
|
||||
#define L4_PER_54XX_PHYS L4_PER_54XX_BASE /* 0x48000000 --> 0xfa000000 */
|
||||
#define L4_PER_54XX_VIRT (L4_PER_54XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_PER_54XX_SIZE SZ_4M
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* DRA7xx specific IO mapping
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* L3_MAIN_SN_DRA7XX_PHYS 0x44000000 --> 0xf8000000
|
||||
* The overall space is 24MiB (0x4400_0000<->0x457F_FFFF), but mapping
|
||||
* everything is just inefficient, since, there are too many address holes.
|
||||
*/
|
||||
#define L3_MAIN_SN_DRA7XX_PHYS L3_MAIN_SN_DRA7XX_BASE
|
||||
#define L3_MAIN_SN_DRA7XX_VIRT (L3_MAIN_SN_DRA7XX_PHYS + OMAP4_L3_IO_OFFSET)
|
||||
#define L3_MAIN_SN_DRA7XX_SIZE SZ_1M
|
||||
|
||||
/*
|
||||
* L4_PER1_DRA7XX_PHYS (0x4800_000<>0x480D_2FFF) -> 0.82MiB (alloc 1MiB)
|
||||
* (0x48000000<->0x48100000) <=> (0xFA000000<->0xFA100000)
|
||||
*/
|
||||
#define L4_PER1_DRA7XX_PHYS L4_PER1_DRA7XX_BASE
|
||||
#define L4_PER1_DRA7XX_VIRT (L4_PER1_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_PER1_DRA7XX_SIZE SZ_1M
|
||||
|
||||
/*
|
||||
* L4_CFG_MPU_DRA7XX_PHYS (0x48210000<>0x482A_F2FF) -> 0.62MiB (alloc 1MiB)
|
||||
* (0x48210000<->0x48310000) <=> (0xFA210000<->0xFA310000)
|
||||
* NOTE: This is a bit of an orphan memory map sitting isolated in TRM
|
||||
*/
|
||||
#define L4_CFG_MPU_DRA7XX_PHYS L4_CFG_MPU_DRA7XX_BASE
|
||||
#define L4_CFG_MPU_DRA7XX_VIRT (L4_CFG_MPU_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_CFG_MPU_DRA7XX_SIZE SZ_1M
|
||||
|
||||
/*
|
||||
* L4_PER2_DRA7XX_PHYS (0x4840_0000<>0x4848_8FFF) -> .53MiB (alloc 1MiB)
|
||||
* (0x48400000<->0x48500000) <=> (0xFA400000<->0xFA500000)
|
||||
*/
|
||||
#define L4_PER2_DRA7XX_PHYS L4_PER2_DRA7XX_BASE
|
||||
#define L4_PER2_DRA7XX_VIRT (L4_PER2_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_PER2_DRA7XX_SIZE SZ_1M
|
||||
|
||||
/*
|
||||
* L4_PER3_DRA7XX_PHYS (0x4880_0000<>0x489E_0FFF) -> 1.87MiB (alloc 2MiB)
|
||||
* (0x48800000<->0x48A00000) <=> (0xFA800000<->0xFAA00000)
|
||||
*/
|
||||
#define L4_PER3_DRA7XX_PHYS L4_PER3_DRA7XX_BASE
|
||||
#define L4_PER3_DRA7XX_VIRT (L4_PER3_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_PER3_DRA7XX_SIZE SZ_2M
|
||||
|
||||
/*
|
||||
* L4_CFG_DRA7XX_PHYS (0x4A00_0000<>0x4A22_BFFF) ->2.17MiB (alloc 3MiB)?
|
||||
* (0x4A000000<->0x4A300000) <=> (0xFC000000<->0xFC300000)
|
||||
*/
|
||||
#define L4_CFG_DRA7XX_PHYS L4_CFG_DRA7XX_BASE
|
||||
#define L4_CFG_DRA7XX_VIRT (L4_CFG_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_CFG_DRA7XX_SIZE (SZ_1M + SZ_2M)
|
||||
|
||||
/*
|
||||
* L4_WKUP_DRA7XX_PHYS (0x4AE0_0000<>0x4AE3_EFFF) -> .24 mb (alloc 1MiB)?
|
||||
* (0x4AE00000<->4AF00000) <=> (0xFCE00000<->0xFCF00000)
|
||||
*/
|
||||
#define L4_WKUP_DRA7XX_PHYS L4_WKUP_DRA7XX_BASE
|
||||
#define L4_WKUP_DRA7XX_VIRT (L4_WKUP_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET)
|
||||
#define L4_WKUP_DRA7XX_SIZE SZ_1M
|
||||
|
@ -11,7 +11,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
@ -63,15 +62,5 @@ static int __init omap_iommu_init(void)
|
||||
|
||||
return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL);
|
||||
}
|
||||
/* must be ready before omap3isp is probed */
|
||||
omap_subsys_initcall(omap_iommu_init);
|
||||
|
||||
static void __exit omap_iommu_exit(void)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
module_exit(omap_iommu_exit);
|
||||
|
||||
MODULE_AUTHOR("Hiroshi DOYU");
|
||||
MODULE_DESCRIPTION("omap iommu: omap device registration");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
/* must be ready before omap3isp is probed */
|
||||
|
@ -105,7 +105,7 @@ static void dummy_cpu_resume(void)
|
||||
static void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state)
|
||||
{}
|
||||
|
||||
struct cpu_pm_ops omap_pm_ops = {
|
||||
static struct cpu_pm_ops omap_pm_ops = {
|
||||
.finish_suspend = default_finish_suspend,
|
||||
.resume = dummy_cpu_resume,
|
||||
.scu_prepare = dummy_scu_prepare,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "control.h"
|
||||
#include "prm.h"
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/reboot.h>
|
||||
#include "common.h"
|
||||
#include "prm.h"
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,14 @@
|
||||
#define OMAP54XX_CTRL_BASE 0x4a002800
|
||||
#define OMAP54XX_SAR_RAM_BASE 0x4ae26000
|
||||
|
||||
/* DRA7 specific base addresses */
|
||||
#define L3_MAIN_SN_DRA7XX_BASE 0x44000000
|
||||
#define L4_PER1_DRA7XX_BASE 0x48000000
|
||||
#define L4_CFG_MPU_DRA7XX_BASE 0x48210000
|
||||
#define L4_PER2_DRA7XX_BASE 0x48400000
|
||||
#define L4_PER3_DRA7XX_BASE 0x48800000
|
||||
#define L4_CFG_DRA7XX_BASE 0x4A000000
|
||||
#define L4_WKUP_DRA7XX_BASE 0x4ae00000
|
||||
#define DRA7XX_CM_CORE_AON_BASE 0x4a005000
|
||||
#define DRA7XX_CTRL_BASE 0x4a003400
|
||||
#define DRA7XX_TAP_BASE 0x4ae0c000
|
||||
|
@ -300,7 +300,20 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
|
||||
|
||||
/* Module might have lost context, always update cache and register */
|
||||
oh->_sysc_cache = v;
|
||||
|
||||
/*
|
||||
* Some IP blocks (such as RTC) require unlocking of IP before
|
||||
* accessing its registers. If a function pointer is present
|
||||
* to unlock, then call it before accessing sysconfig and
|
||||
* call lock after writing sysconfig.
|
||||
*/
|
||||
if (oh->class->unlock)
|
||||
oh->class->unlock(oh);
|
||||
|
||||
omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
|
||||
|
||||
if (oh->class->lock)
|
||||
oh->class->lock(oh);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3887,7 +3900,8 @@ void __init omap_hwmod_init(void)
|
||||
soc_ops.init_clkdm = _init_clkdm;
|
||||
soc_ops.update_context_lost = _omap4_update_context_lost;
|
||||
soc_ops.get_context_lost = _omap4_get_context_lost;
|
||||
} else if (cpu_is_ti816x() || soc_is_am33xx() || soc_is_am43xx()) {
|
||||
} else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() ||
|
||||
soc_is_am43xx()) {
|
||||
soc_ops.enable_module = _omap4_enable_module;
|
||||
soc_ops.disable_module = _omap4_disable_module;
|
||||
soc_ops.wait_target_ready = _omap4_wait_target_ready;
|
||||
|
@ -576,6 +576,8 @@ struct omap_hwmod_omap4_prcm {
|
||||
* @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
|
||||
* @reset: ptr to fn to be executed in place of the standard hwmod reset fn
|
||||
* @enable_preprogram: ptr to fn to be executed during device enable
|
||||
* @lock: ptr to fn to be executed to lock IP registers
|
||||
* @unlock: ptr to fn to be executed to unlock IP registers
|
||||
*
|
||||
* Represent the class of a OMAP hardware "modules" (e.g. timer,
|
||||
* smartreflex, gpio, uart...)
|
||||
@ -600,6 +602,8 @@ struct omap_hwmod_class {
|
||||
int (*pre_shutdown)(struct omap_hwmod *oh);
|
||||
int (*reset)(struct omap_hwmod *oh);
|
||||
int (*enable_preprogram)(struct omap_hwmod *oh);
|
||||
void (*lock)(struct omap_hwmod *oh);
|
||||
void (*unlock)(struct omap_hwmod *oh);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -755,7 +759,8 @@ extern int omap3xxx_hwmod_init(void);
|
||||
extern int omap44xx_hwmod_init(void);
|
||||
extern int omap54xx_hwmod_init(void);
|
||||
extern int am33xx_hwmod_init(void);
|
||||
extern int ti81xx_hwmod_init(void);
|
||||
extern int dm814x_hwmod_init(void);
|
||||
extern int dm816x_hwmod_init(void);
|
||||
extern int dra7xx_hwmod_init(void);
|
||||
int am43xx_hwmod_init(void);
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "prm-regbits-24xx.h"
|
||||
#include "wd_timer.h"
|
||||
|
||||
struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
|
||||
static struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
|
||||
{ .name = "dispc", .dma_req = 5 },
|
||||
{ .dma_req = -1, },
|
||||
};
|
||||
|
@ -480,7 +480,7 @@ static struct omap_hwmod am43xx_dss_core_hwmod = {
|
||||
|
||||
/* dispc */
|
||||
|
||||
struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = {
|
||||
static struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = {
|
||||
.manager_count = 1,
|
||||
.has_framedonetv_irq = 0
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ struct pdata_init {
|
||||
void (*fn)(void);
|
||||
};
|
||||
|
||||
struct of_dev_auxdata omap_auxdata_lookup[];
|
||||
static struct of_dev_auxdata omap_auxdata_lookup[];
|
||||
static struct twl4030_gpio_platform_data twl_gpio_auxdata;
|
||||
|
||||
#ifdef CONFIG_MACH_NOKIA_N8X0
|
||||
@ -128,7 +128,7 @@ static void __init omap3_sbc_t3530_legacy_init(void)
|
||||
omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub");
|
||||
}
|
||||
|
||||
struct ti_st_plat_data wilink_pdata = {
|
||||
static struct ti_st_plat_data wilink_pdata = {
|
||||
.nshutdown_gpio = 137,
|
||||
.dev_name = "/dev/ttyO1",
|
||||
.flow_cntrl = 1,
|
||||
@ -323,7 +323,7 @@ static struct pdata_init auxdata_quirks[] __initdata = {
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
|
||||
static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
|
||||
#ifdef CONFIG_MACH_NOKIA_N8X0
|
||||
OF_DEV_AUXDATA("ti,omap2420-mmc", 0x4809c000, "mmci-omap.0", NULL),
|
||||
OF_DEV_AUXDATA("menelaus", 0x72, "1-0072", &n8x0_menelaus_platform_data),
|
||||
|
@ -349,6 +349,41 @@ static struct powerdomain device_81xx_pwrdm = {
|
||||
.voltdm = { .name = "core" },
|
||||
};
|
||||
|
||||
static struct powerdomain gem_814x_pwrdm = {
|
||||
.name = "gem_pwrdm",
|
||||
.prcm_offs = TI814X_PRM_DSP_MOD,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.voltdm = { .name = "dsp" },
|
||||
};
|
||||
|
||||
static struct powerdomain ivahd_814x_pwrdm = {
|
||||
.name = "ivahd_pwrdm",
|
||||
.prcm_offs = TI814X_PRM_HDVICP_MOD,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.voltdm = { .name = "iva" },
|
||||
};
|
||||
|
||||
static struct powerdomain hdvpss_814x_pwrdm = {
|
||||
.name = "hdvpss_pwrdm",
|
||||
.prcm_offs = TI814X_PRM_HDVPSS_MOD,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.voltdm = { .name = "dsp" },
|
||||
};
|
||||
|
||||
static struct powerdomain sgx_814x_pwrdm = {
|
||||
.name = "sgx_pwrdm",
|
||||
.prcm_offs = TI814X_PRM_GFX_MOD,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.voltdm = { .name = "core" },
|
||||
};
|
||||
|
||||
static struct powerdomain isp_814x_pwrdm = {
|
||||
.name = "isp_pwrdm",
|
||||
.prcm_offs = TI814X_PRM_ISP_MOD,
|
||||
.pwrsts = PWRSTS_OFF_ON,
|
||||
.voltdm = { .name = "core" },
|
||||
};
|
||||
|
||||
static struct powerdomain active_816x_pwrdm = {
|
||||
.name = "active_pwrdm",
|
||||
.prcm_offs = TI816X_PRM_ACTIVE_MOD,
|
||||
@ -448,7 +483,18 @@ static struct powerdomain *powerdomains_am35x[] __initdata = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct powerdomain *powerdomains_ti81xx[] __initdata = {
|
||||
static struct powerdomain *powerdomains_ti814x[] __initdata = {
|
||||
&alwon_81xx_pwrdm,
|
||||
&device_81xx_pwrdm,
|
||||
&gem_814x_pwrdm,
|
||||
&ivahd_814x_pwrdm,
|
||||
&hdvpss_814x_pwrdm,
|
||||
&sgx_814x_pwrdm,
|
||||
&isp_814x_pwrdm,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct powerdomain *powerdomains_ti816x[] __initdata = {
|
||||
&alwon_81xx_pwrdm,
|
||||
&device_81xx_pwrdm,
|
||||
&active_816x_pwrdm,
|
||||
@ -460,6 +506,73 @@ static struct powerdomain *powerdomains_ti81xx[] __initdata = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/* TI81XX specific ops */
|
||||
#define TI81XX_PM_PWSTCTRL 0x0000
|
||||
#define TI81XX_RM_RSTCTRL 0x0010
|
||||
#define TI81XX_PM_PWSTST 0x0004
|
||||
|
||||
static int ti81xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
||||
{
|
||||
omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
|
||||
(pwrst << OMAP_POWERSTATE_SHIFT),
|
||||
pwrdm->prcm_offs, TI81XX_PM_PWSTCTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti81xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
||||
{
|
||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||
TI81XX_PM_PWSTCTRL,
|
||||
OMAP_POWERSTATE_MASK);
|
||||
}
|
||||
|
||||
static int ti81xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
||||
{
|
||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||
(pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL :
|
||||
TI81XX_PM_PWSTST,
|
||||
OMAP_POWERSTATEST_MASK);
|
||||
}
|
||||
|
||||
static int ti81xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
||||
{
|
||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||
(pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL :
|
||||
TI81XX_PM_PWSTST,
|
||||
OMAP3430_LOGICSTATEST_MASK);
|
||||
}
|
||||
|
||||
static int ti81xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||
{
|
||||
u32 c = 0;
|
||||
|
||||
while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs,
|
||||
(pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL :
|
||||
TI81XX_PM_PWSTST) &
|
||||
OMAP_INTRANSITION_MASK) &&
|
||||
(c++ < PWRDM_TRANSITION_BAILOUT))
|
||||
udelay(1);
|
||||
|
||||
if (c > PWRDM_TRANSITION_BAILOUT) {
|
||||
pr_err("powerdomain: %s timeout waiting for transition\n",
|
||||
pwrdm->name);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For dm814x we need to fix up fix GFX pwstst and rstctrl reg offsets */
|
||||
static struct pwrdm_ops ti81xx_pwrdm_operations = {
|
||||
.pwrdm_set_next_pwrst = ti81xx_pwrdm_set_next_pwrst,
|
||||
.pwrdm_read_next_pwrst = ti81xx_pwrdm_read_next_pwrst,
|
||||
.pwrdm_read_pwrst = ti81xx_pwrdm_read_pwrst,
|
||||
.pwrdm_read_logic_pwrst = ti81xx_pwrdm_read_logic_pwrst,
|
||||
.pwrdm_wait_transition = ti81xx_pwrdm_wait_transition,
|
||||
};
|
||||
|
||||
void __init omap3xxx_powerdomains_init(void)
|
||||
{
|
||||
unsigned int rev;
|
||||
@ -467,15 +580,22 @@ void __init omap3xxx_powerdomains_init(void)
|
||||
if (!cpu_is_omap34xx() && !cpu_is_ti81xx())
|
||||
return;
|
||||
|
||||
pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
|
||||
/* Only 81xx needs custom pwrdm_operations */
|
||||
if (!cpu_is_ti81xx())
|
||||
pwrdm_register_platform_funcs(&omap3_pwrdm_operations);;
|
||||
|
||||
rev = omap_rev();
|
||||
|
||||
if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
|
||||
pwrdm_register_pwrdms(powerdomains_am35x);
|
||||
} else if (rev == TI8148_REV_ES1_0 || rev == TI8148_REV_ES2_0 ||
|
||||
rev == TI8148_REV_ES2_1) {
|
||||
pwrdm_register_platform_funcs(&ti81xx_pwrdm_operations);
|
||||
pwrdm_register_pwrdms(powerdomains_ti814x);
|
||||
} else if (rev == TI8168_REV_ES1_0 || rev == TI8168_REV_ES1_1
|
||||
|| rev == TI8168_REV_ES2_0 || rev == TI8168_REV_ES2_1) {
|
||||
pwrdm_register_pwrdms(powerdomains_ti81xx);
|
||||
pwrdm_register_platform_funcs(&ti81xx_pwrdm_operations);
|
||||
pwrdm_register_pwrdms(powerdomains_ti816x);
|
||||
} else {
|
||||
pwrdm_register_pwrdms(powerdomains_omap3430_common);
|
||||
|
||||
|
@ -51,6 +51,12 @@
|
||||
/*
|
||||
* TI81XX PRM module offsets
|
||||
*/
|
||||
#define TI814X_PRM_DSP_MOD 0x0a00
|
||||
#define TI814X_PRM_HDVICP_MOD 0x0c00
|
||||
#define TI814X_PRM_ISP_MOD 0x0d00
|
||||
#define TI814X_PRM_HDVPSS_MOD 0x0e00
|
||||
#define TI814X_PRM_GFX_MOD 0x0f00
|
||||
|
||||
#define TI81XX_PRM_DEVICE_MOD 0x0000
|
||||
#define TI816X_PRM_ACTIVE_MOD 0x0a00
|
||||
#define TI81XX_PRM_DEFAULT_MOD 0x0b00
|
||||
@ -472,6 +478,7 @@ struct omap_prcm_irq {
|
||||
* struct omap_prcm_irq_setup - PRCM interrupt controller details
|
||||
* @ack: PRM register offset for the first PRM_IRQSTATUS_MPU register
|
||||
* @mask: PRM register offset for the first PRM_IRQENABLE_MPU register
|
||||
* @pm_ctrl: PRM register offset for the PRM_IO_PMCTRL register
|
||||
* @nr_regs: number of PRM_IRQ{STATUS,ENABLE}_MPU* registers
|
||||
* @nr_irqs: number of entries in the @irqs array
|
||||
* @irqs: ptr to an array of PRCM interrupt bits (see @nr_irqs)
|
||||
@ -494,6 +501,7 @@ struct omap_prcm_irq {
|
||||
struct omap_prcm_irq_setup {
|
||||
u16 ack;
|
||||
u16 mask;
|
||||
u16 pm_ctrl;
|
||||
u8 nr_regs;
|
||||
u8 nr_irqs;
|
||||
const struct omap_prcm_irq *irqs;
|
||||
|
@ -25,6 +25,13 @@
|
||||
#define AM43XX_PRM_WKUP_INST 0x2000
|
||||
#define AM43XX_PRM_DEVICE_INST 0x4000
|
||||
|
||||
/* PRM_IRQ offsets */
|
||||
#define AM43XX_PRM_IRQSTATUS_MPU_OFFSET 0x0004
|
||||
#define AM43XX_PRM_IRQENABLE_MPU_OFFSET 0x0008
|
||||
|
||||
/* Other PRM offsets */
|
||||
#define AM43XX_PRM_IO_PMCTRL_OFFSET 0x0024
|
||||
|
||||
/* RM RSTCTRL offsets */
|
||||
#define AM43XX_RM_PER_RSTCTRL_OFFSET 0x0010
|
||||
#define AM43XX_RM_GFX_RSTCTRL_OFFSET 0x0010
|
||||
|
@ -18,13 +18,14 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
#include "vp.h"
|
||||
#include "prm44xx.h"
|
||||
#include "prcm43xx.h"
|
||||
#include "prm-regbits-44xx.h"
|
||||
#include "prcm44xx.h"
|
||||
#include "prminst44xx.h"
|
||||
@ -45,6 +46,7 @@ static const struct omap_prcm_irq omap4_prcm_irqs[] = {
|
||||
static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
|
||||
.ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
|
||||
.mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET,
|
||||
.pm_ctrl = OMAP4_PRM_IO_PMCTRL_OFFSET,
|
||||
.nr_regs = 2,
|
||||
.irqs = omap4_prcm_irqs,
|
||||
.nr_irqs = ARRAY_SIZE(omap4_prcm_irqs),
|
||||
@ -216,11 +218,11 @@ static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
|
||||
*/
|
||||
static void omap44xx_prm_read_pending_irqs(unsigned long *events)
|
||||
{
|
||||
events[0] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_OFFSET,
|
||||
OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
|
||||
int i;
|
||||
|
||||
events[1] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_2_OFFSET,
|
||||
OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
|
||||
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
|
||||
events[i] = _read_pending_irq_reg(omap4_prcm_irq_setup.mask +
|
||||
i * 4, omap4_prcm_irq_setup.ack + i * 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,17 +252,17 @@ static void omap44xx_prm_ocp_barrier(void)
|
||||
*/
|
||||
static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
|
||||
{
|
||||
saved_mask[0] =
|
||||
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
|
||||
saved_mask[1] =
|
||||
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
|
||||
int i;
|
||||
u16 reg;
|
||||
|
||||
omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
|
||||
omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
|
||||
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) {
|
||||
reg = omap4_prcm_irq_setup.mask + i * 4;
|
||||
|
||||
saved_mask[i] =
|
||||
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
reg);
|
||||
omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, reg);
|
||||
}
|
||||
|
||||
/* OCP barrier */
|
||||
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
@ -279,10 +281,12 @@ static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
|
||||
*/
|
||||
static void omap44xx_prm_restore_irqen(u32 *saved_mask)
|
||||
{
|
||||
omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
|
||||
omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
|
||||
omap4_prm_write_inst_reg(saved_mask[i],
|
||||
OMAP4430_PRM_OCP_SOCKET_INST,
|
||||
omap4_prcm_irq_setup.mask + i * 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,10 +310,10 @@ static void omap44xx_prm_reconfigure_io_chain(void)
|
||||
omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
|
||||
OMAP4430_WUCLK_CTRL_MASK,
|
||||
inst,
|
||||
OMAP4_PRM_IO_PMCTRL_OFFSET);
|
||||
omap4_prcm_irq_setup.pm_ctrl);
|
||||
omap_test_timeout(
|
||||
(((omap4_prm_read_inst_reg(inst,
|
||||
OMAP4_PRM_IO_PMCTRL_OFFSET) &
|
||||
omap4_prcm_irq_setup.pm_ctrl) &
|
||||
OMAP4430_WUCLK_STATUS_MASK) >>
|
||||
OMAP4430_WUCLK_STATUS_SHIFT) == 1),
|
||||
MAX_IOPAD_LATCH_TIME, i);
|
||||
@ -319,10 +323,10 @@ static void omap44xx_prm_reconfigure_io_chain(void)
|
||||
/* Trigger WUCLKIN disable */
|
||||
omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
|
||||
inst,
|
||||
OMAP4_PRM_IO_PMCTRL_OFFSET);
|
||||
omap4_prcm_irq_setup.pm_ctrl);
|
||||
omap_test_timeout(
|
||||
(((omap4_prm_read_inst_reg(inst,
|
||||
OMAP4_PRM_IO_PMCTRL_OFFSET) &
|
||||
omap4_prcm_irq_setup.pm_ctrl) &
|
||||
OMAP4430_WUCLK_STATUS_MASK) >>
|
||||
OMAP4430_WUCLK_STATUS_SHIFT) == 0),
|
||||
MAX_IOPAD_LATCH_TIME, i);
|
||||
@ -350,7 +354,7 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
|
||||
omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
|
||||
OMAP4430_GLOBAL_WUEN_MASK,
|
||||
inst,
|
||||
OMAP4_PRM_IO_PMCTRL_OFFSET);
|
||||
omap4_prcm_irq_setup.pm_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -719,6 +723,15 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
|
||||
|
||||
omap4_prminst_set_prm_dev_inst(data->device_inst_offset);
|
||||
|
||||
/* Add AM437X specific differences */
|
||||
if (of_device_is_compatible(data->np, "ti,am4-prcm")) {
|
||||
omap4_prcm_irq_setup.nr_irqs = 1;
|
||||
omap4_prcm_irq_setup.nr_regs = 1;
|
||||
omap4_prcm_irq_setup.pm_ctrl = AM43XX_PRM_IO_PMCTRL_OFFSET;
|
||||
omap4_prcm_irq_setup.ack = AM43XX_PRM_IRQSTATUS_MPU_OFFSET;
|
||||
omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET;
|
||||
}
|
||||
|
||||
return prm_register(&omap44xx_prm_ll_data);
|
||||
}
|
||||
|
||||
|
@ -696,6 +696,7 @@ static struct omap_prcm_init_data am4_prm_data __initdata = {
|
||||
.index = TI_CLKM_PRM,
|
||||
.init = omap44xx_prm_init,
|
||||
.device_inst_offset = AM43XX_PRM_DEVICE_INST,
|
||||
.flags = PRM_HAS_IO_WAKEUP,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -208,7 +208,6 @@ static void __init omap_dmtimer_init(void)
|
||||
/* If we are a secure device, remove any secure timer nodes */
|
||||
if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
|
||||
np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
|
||||
if (np)
|
||||
of_node_put(np);
|
||||
}
|
||||
}
|
||||
@ -649,23 +648,10 @@ static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP4
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
|
||||
void __init omap4_local_timer_init(void)
|
||||
{
|
||||
omap4_sync32k_timer_init();
|
||||
/* Local timers are not supprted on OMAP4430 ES1.0 */
|
||||
if (omap_rev() != OMAP4430_REV_ES1_0) {
|
||||
int err;
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
clocksource_of_init();
|
||||
return;
|
||||
}
|
||||
|
||||
err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void __init omap4_local_timer_init(void)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/platform_data/camera-pxa.h>
|
||||
#include <mach/audio.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/platform_data/mmp_dma.h>
|
||||
#include <linux/platform_data/mtd-nand-pxa3xx.h>
|
||||
|
||||
#include "devices.h"
|
||||
@ -1193,3 +1194,39 @@ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info)
|
||||
pd->dev.platform_data = info;
|
||||
platform_device_add(pd);
|
||||
}
|
||||
|
||||
static struct mmp_dma_platdata pxa_dma_pdata = {
|
||||
.dma_channels = 0,
|
||||
};
|
||||
|
||||
static struct resource pxa_dma_resource[] = {
|
||||
[0] = {
|
||||
.start = 0x40000000,
|
||||
.end = 0x4000ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_DMA,
|
||||
.end = IRQ_DMA,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 pxadma_dmamask = 0xffffffffUL;
|
||||
|
||||
static struct platform_device pxa2xx_pxa_dma = {
|
||||
.name = "pxa-dma",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &pxadma_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(pxa_dma_resource),
|
||||
.resource = pxa_dma_resource,
|
||||
};
|
||||
|
||||
void __init pxa2xx_set_dmac_info(int nb_channels)
|
||||
{
|
||||
pxa_dma_pdata.dma_channels = nb_channels;
|
||||
pxa_register_device(&pxa2xx_pxa_dma, &pxa_dma_pdata);
|
||||
}
|
||||
|
@ -206,6 +206,7 @@ static int __init pxa25x_init(void)
|
||||
register_syscore_ops(&pxa_irq_syscore_ops);
|
||||
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
|
||||
|
||||
pxa2xx_set_dmac_info(16);
|
||||
pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info);
|
||||
ret = platform_add_devices(pxa25x_devices,
|
||||
ARRAY_SIZE(pxa25x_devices));
|
||||
|
@ -310,6 +310,7 @@ static int __init pxa27x_init(void)
|
||||
if (!of_have_populated_dt()) {
|
||||
pxa_register_device(&pxa27x_device_gpio,
|
||||
&pxa27x_gpio_info);
|
||||
pxa2xx_set_dmac_info(32);
|
||||
ret = platform_add_devices(devices,
|
||||
ARRAY_SIZE(devices));
|
||||
}
|
||||
|
@ -431,6 +431,7 @@ static int __init pxa3xx_init(void)
|
||||
if (of_have_populated_dt())
|
||||
return 0;
|
||||
|
||||
pxa2xx_set_dmac_info(32);
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -841,11 +841,9 @@ static int sharpsl_pm_probe(struct platform_device *pdev)
|
||||
sharpsl_pm.charge_mode = CHRG_OFF;
|
||||
sharpsl_pm.flags = 0;
|
||||
|
||||
init_timer(&sharpsl_pm.ac_timer);
|
||||
sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
|
||||
setup_timer(&sharpsl_pm.ac_timer, sharpsl_ac_timer, 0UL);
|
||||
|
||||
init_timer(&sharpsl_pm.chrg_full_timer);
|
||||
sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
|
||||
setup_timer(&sharpsl_pm.chrg_full_timer, sharpsl_chrg_full_timer, 0UL);
|
||||
|
||||
led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
|
||||
|
||||
|
@ -131,17 +131,4 @@ static struct platform_driver tosa_bt_driver = {
|
||||
.name = "tosa-bt",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int __init tosa_bt_init(void)
|
||||
{
|
||||
return platform_driver_register(&tosa_bt_driver);
|
||||
}
|
||||
|
||||
static void __exit tosa_bt_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tosa_bt_driver);
|
||||
}
|
||||
|
||||
module_init(tosa_bt_init);
|
||||
module_exit(tosa_bt_exit);
|
||||
module_platform_driver(tosa_bt_driver);
|
||||
|
@ -72,30 +72,23 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
|
||||
static int pmu_set_power_domain(int pd, bool on)
|
||||
{
|
||||
u32 val = (on) ? 0 : BIT(pd);
|
||||
struct reset_control *rstc = rockchip_get_core_reset(pd);
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
|
||||
pr_err("%s: could not get reset control for core %d\n",
|
||||
__func__, pd);
|
||||
return PTR_ERR(rstc);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to soft reset the cpu when we turn off the cpu power domain,
|
||||
* or else the active processors might be stalled when the individual
|
||||
* processor is powered down.
|
||||
*/
|
||||
if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
|
||||
struct reset_control *rstc = rockchip_get_core_reset(pd);
|
||||
|
||||
if (IS_ERR(rstc)) {
|
||||
pr_err("%s: could not get reset control for core %d\n",
|
||||
__func__, pd);
|
||||
return PTR_ERR(rstc);
|
||||
}
|
||||
|
||||
if (on)
|
||||
reset_control_deassert(rstc);
|
||||
else
|
||||
if (!IS_ERR(rstc) && !on)
|
||||
reset_control_assert(rstc);
|
||||
|
||||
reset_control_put(rstc);
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: could not update power domain\n", __func__);
|
||||
@ -112,6 +105,12 @@ static int pmu_set_power_domain(int pd, bool on)
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR(rstc)) {
|
||||
if (on)
|
||||
reset_control_deassert(rstc);
|
||||
reset_control_put(rstc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -140,14 +139,19 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
return ret;
|
||||
|
||||
if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
|
||||
/* We communicate with the bootrom to active the cpus other
|
||||
/*
|
||||
* We communicate with the bootrom to active the cpus other
|
||||
* than cpu0, after a blob of initialize code, they will
|
||||
* stay at wfe state, once they are actived, they will check
|
||||
* the mailbox:
|
||||
* sram_base_addr + 4: 0xdeadbeaf
|
||||
* sram_base_addr + 8: start address for pc
|
||||
* */
|
||||
udelay(10);
|
||||
* The cpu0 need to wait the other cpus other than cpu0 entering
|
||||
* the wfe state.The wait time is affected by many aspects.
|
||||
* (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
|
||||
*/
|
||||
mdelay(1); /* ensure the cpus other than cpu0 to startup */
|
||||
|
||||
writel(virt_to_phys(secondary_startup), sram_base_addr + 8);
|
||||
writel(0xDEADBEAF, sram_base_addr + 4);
|
||||
dsb_sev();
|
||||
@ -317,6 +321,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int rockchip_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* We need a delay here to ensure that the dying CPU can finish
|
||||
* executing v7_coherency_exit() and reach the WFI/WFE state
|
||||
* prior to having the power domain disabled.
|
||||
*/
|
||||
mdelay(1);
|
||||
|
||||
pmu_set_power_domain(0 + cpu, false);
|
||||
return 1;
|
||||
}
|
||||
@ -337,4 +348,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
|
||||
.cpu_die = rockchip_cpu_die,
|
||||
#endif
|
||||
};
|
||||
|
||||
CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
|
||||
|
@ -45,9 +45,11 @@ static phys_addr_t rk3288_bootram_phy;
|
||||
|
||||
static struct regmap *pmu_regmap;
|
||||
static struct regmap *sgrf_regmap;
|
||||
static struct regmap *grf_regmap;
|
||||
|
||||
static u32 rk3288_pmu_pwr_mode_con;
|
||||
static u32 rk3288_sgrf_soc_con0;
|
||||
static u32 rk3288_sgrf_cpu_con0;
|
||||
|
||||
static inline u32 rk3288_l2_config(void)
|
||||
{
|
||||
@ -66,10 +68,37 @@ static void rk3288_config_bootdata(void)
|
||||
rkpm_bootdata_l2ctlr = rk3288_l2_config();
|
||||
}
|
||||
|
||||
#define GRF_UOC0_CON0 0x320
|
||||
#define GRF_UOC1_CON0 0x334
|
||||
#define GRF_UOC2_CON0 0x348
|
||||
#define GRF_SIDDQ BIT(13)
|
||||
|
||||
static bool rk3288_slp_disable_osc(void)
|
||||
{
|
||||
static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
|
||||
GRF_UOC2_CON0 };
|
||||
u32 reg, i;
|
||||
|
||||
/*
|
||||
* if any usb phy is still on(GRF_SIDDQ==0), that means we need the
|
||||
* function of usb wakeup, so do not switch to 32khz, since the usb phy
|
||||
* clk does not connect to 32khz osc
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
|
||||
regmap_read(grf_regmap, reg_offset[i], ®);
|
||||
if (!(reg & GRF_SIDDQ))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rk3288_slp_mode_set(int level)
|
||||
{
|
||||
u32 mode_set, mode_set1;
|
||||
bool osc_disable = rk3288_slp_disable_osc();
|
||||
|
||||
regmap_read(sgrf_regmap, RK3288_SGRF_CPU_CON0, &rk3288_sgrf_cpu_con0);
|
||||
regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
|
||||
|
||||
regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON,
|
||||
@ -94,9 +123,6 @@ static void rk3288_slp_mode_set(int level)
|
||||
regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR,
|
||||
rk3288_bootram_phy);
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1,
|
||||
PMU_ARMINT_WAKEUP_EN);
|
||||
|
||||
mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) |
|
||||
BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) |
|
||||
BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) |
|
||||
@ -107,13 +133,31 @@ static void rk3288_slp_mode_set(int level)
|
||||
|
||||
if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
|
||||
/* arm off, logic deep sleep */
|
||||
mode_set |= BIT(PMU_BUS_PD_EN) |
|
||||
mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) |
|
||||
BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
|
||||
BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
|
||||
BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
|
||||
|
||||
if (osc_disable)
|
||||
mode_set |= BIT(PMU_OSC_24M_DIS);
|
||||
|
||||
mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
|
||||
BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1,
|
||||
PMU_ARMINT_WAKEUP_EN);
|
||||
|
||||
/*
|
||||
* In deep suspend we use PMU_PMU_USE_LF to let the rk3288
|
||||
* switch its main clock supply to the alternative 32kHz
|
||||
* source. Therefore set 30ms on a 32kHz clock for pmic
|
||||
* stabilization. Similar 30ms on 24MHz for the other
|
||||
* mode below.
|
||||
*/
|
||||
regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, 32 * 30);
|
||||
|
||||
/* only wait for stabilization, if we turned the osc off */
|
||||
regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT,
|
||||
osc_disable ? 32 * 30 : 0);
|
||||
} else {
|
||||
/*
|
||||
* arm off, logic normal
|
||||
@ -121,6 +165,15 @@ static void rk3288_slp_mode_set(int level)
|
||||
* wakeup will be error
|
||||
*/
|
||||
mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN);
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1,
|
||||
PMU_ARMINT_WAKEUP_EN | PMU_GPIOINT_WAKEUP_EN);
|
||||
|
||||
/* 30ms on a 24MHz clock for pmic stabilization */
|
||||
regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, 24000 * 30);
|
||||
|
||||
/* oscillator is still running, so no need to wait */
|
||||
regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, 0);
|
||||
}
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set);
|
||||
@ -129,6 +182,9 @@ static void rk3288_slp_mode_set(int level)
|
||||
|
||||
static void rk3288_slp_mode_set_resume(void)
|
||||
{
|
||||
regmap_write(sgrf_regmap, RK3288_SGRF_CPU_CON0,
|
||||
rk3288_sgrf_cpu_con0 | SGRF_DAPDEVICEEN_WRITE);
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON,
|
||||
rk3288_pmu_pwr_mode_con);
|
||||
|
||||
@ -190,7 +246,14 @@ static int rk3288_suspend_init(struct device_node *np)
|
||||
"rockchip,rk3288-sgrf");
|
||||
if (IS_ERR(sgrf_regmap)) {
|
||||
pr_err("%s: could not find sgrf regmap\n", __func__);
|
||||
return PTR_ERR(pmu_regmap);
|
||||
return PTR_ERR(sgrf_regmap);
|
||||
}
|
||||
|
||||
grf_regmap = syscon_regmap_lookup_by_compatible(
|
||||
"rockchip,rk3288-grf");
|
||||
if (IS_ERR(grf_regmap)) {
|
||||
pr_err("%s: could not find grf regmap\n", __func__);
|
||||
return PTR_ERR(grf_regmap);
|
||||
}
|
||||
|
||||
sram_np = of_find_compatible_node(NULL, NULL,
|
||||
@ -221,9 +284,6 @@ static int rk3288_suspend_init(struct device_node *np)
|
||||
memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
|
||||
rk3288_bootram_sz);
|
||||
|
||||
regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, OSC_STABL_CNT_THRESH);
|
||||
regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, PMU_STABL_CNT_THRESH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,19 +59,9 @@ static inline void rockchip_suspend_init(void)
|
||||
#define SGRF_DAPDEVICEEN BIT(0)
|
||||
#define SGRF_DAPDEVICEEN_WRITE BIT(16)
|
||||
|
||||
#define RK3288_CRU_MODE_CON 0x50
|
||||
#define RK3288_CRU_SEL0_CON 0x60
|
||||
#define RK3288_CRU_SEL1_CON 0x64
|
||||
#define RK3288_CRU_SEL10_CON 0x88
|
||||
#define RK3288_CRU_SEL33_CON 0xe4
|
||||
#define RK3288_CRU_SEL37_CON 0xf4
|
||||
|
||||
/* PMU_WAKEUP_CFG1 bits */
|
||||
#define PMU_ARMINT_WAKEUP_EN BIT(0)
|
||||
|
||||
/* wait 30ms for OSC stable and 30ms for pmic stable */
|
||||
#define OSC_STABL_CNT_THRESH (32 * 30)
|
||||
#define PMU_STABL_CNT_THRESH (32 * 30)
|
||||
#define PMU_GPIOINT_WAKEUP_EN BIT(3)
|
||||
|
||||
enum rk3288_pwr_mode_con {
|
||||
PMU_PWR_MODE_EN = 0,
|
||||
|
@ -80,6 +80,11 @@ config ARCH_R8A7791
|
||||
select ARCH_RCAR_GEN2
|
||||
select I2C
|
||||
|
||||
config ARCH_R8A7793
|
||||
bool "R-Car M2-N (R8A7793)"
|
||||
select ARCH_RCAR_GEN2
|
||||
select I2C
|
||||
|
||||
config ARCH_R8A7794
|
||||
bool "R-Car E2 (R8A77940)"
|
||||
select ARCH_RCAR_GEN2
|
||||
|
@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o pm-r8a7779.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += setup-r8a7793.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += setup-r8a7794.o
|
||||
obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o
|
||||
obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o
|
||||
@ -31,6 +32,7 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += setup-rcar-gen2.o platsmp-apmu.o $(cpu-y)
|
||||
CFLAGS_setup-rcar-gen2.o += -march=armv7-a
|
||||
obj-$(CONFIG_ARCH_R8A7790) += regulator-quirk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += regulator-quirk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += regulator-quirk-rcar-gen2.o
|
||||
|
||||
# SMP objects
|
||||
smp-y := $(cpu-y)
|
||||
|
@ -123,7 +123,8 @@ static int __init rcar_gen2_regulator_quirk(void)
|
||||
u32 mon;
|
||||
|
||||
if (!of_machine_is_compatible("renesas,koelsch") &&
|
||||
!of_machine_is_compatible("renesas,lager"))
|
||||
!of_machine_is_compatible("renesas,lager") &&
|
||||
!of_machine_is_compatible("renesas,gose"))
|
||||
return -ENODEV;
|
||||
|
||||
irqc = ioremap(IRQC_BASE, PAGE_SIZE);
|
||||
|
33
arch/arm/mach-shmobile/setup-r8a7793.c
Normal file
33
arch/arm/mach-shmobile/setup-r8a7793.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* r8a7793 processor support
|
||||
*
|
||||
* Copyright (C) 2015 Ulrich Hecht
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "rcar-gen2.h"
|
||||
|
||||
static const char *r8a7793_boards_compat_dt[] __initconst = {
|
||||
"renesas,r8a7793",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(R8A7793_DT, "Generic R8A7793 (Flattened Device Tree)")
|
||||
.init_early = shmobile_init_delay,
|
||||
.init_time = rcar_gen2_timer_init,
|
||||
.init_late = shmobile_init_late,
|
||||
.reserve = rcar_gen2_reserve,
|
||||
.dt_compat = r8a7793_boards_compat_dt,
|
||||
MACHINE_END
|
@ -25,6 +25,7 @@
|
||||
#define SOCFPGA_RSTMGR_MODPERRST 0x14
|
||||
#define SOCFPGA_RSTMGR_BRGMODRST 0x1c
|
||||
|
||||
#define SOCFPGA_A10_RSTMGR_CTRL 0xC
|
||||
#define SOCFPGA_A10_RSTMGR_MODMPURST 0x20
|
||||
|
||||
/* System Manager bits */
|
||||
|
@ -106,11 +106,23 @@ static void socfpga_cpu_die(unsigned int cpu)
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* We need a dummy function so that platform_can_cpu_hotplug() knows
|
||||
* we support CPU hotplug. However, the function does not need to do
|
||||
* anything, because CPUs going offline just do WFI. We could reset
|
||||
* the CPUs but it would increase power consumption.
|
||||
*/
|
||||
static int socfpga_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct smp_operations socfpga_smp_ops __initdata = {
|
||||
.smp_prepare_cpus = socfpga_smp_prepare_cpus,
|
||||
.smp_boot_secondary = socfpga_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = socfpga_cpu_die,
|
||||
.cpu_kill = socfpga_cpu_kill,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -119,6 +131,7 @@ static struct smp_operations socfpga_a10_smp_ops __initdata = {
|
||||
.smp_boot_secondary = socfpga_a10_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = socfpga_cpu_die,
|
||||
.cpu_kill = socfpga_cpu_kill,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -74,6 +74,19 @@ static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)
|
||||
writel(temp, rst_manager_base_addr + SOCFPGA_RSTMGR_CTRL);
|
||||
}
|
||||
|
||||
static void socfpga_arria10_restart(enum reboot_mode mode, const char *cmd)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
temp = readl(rst_manager_base_addr + SOCFPGA_A10_RSTMGR_CTRL);
|
||||
|
||||
if (mode == REBOOT_HARD)
|
||||
temp |= RSTMGR_CTRL_SWCOLDRSTREQ;
|
||||
else
|
||||
temp |= RSTMGR_CTRL_SWWARMRSTREQ;
|
||||
writel(temp, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_CTRL);
|
||||
}
|
||||
|
||||
static const char *altera_dt_match[] = {
|
||||
"altr,socfpga",
|
||||
NULL
|
||||
@ -86,3 +99,16 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
|
||||
.restart = socfpga_cyclone5_restart,
|
||||
.dt_compat = altera_dt_match,
|
||||
MACHINE_END
|
||||
|
||||
static const char *altera_a10_dt_match[] = {
|
||||
"altr,socfpga-arria10",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(SOCFPGA_A10, "Altera SOCFPGA Arria10")
|
||||
.l2c_aux_val = 0,
|
||||
.l2c_aux_mask = ~0,
|
||||
.init_irq = socfpga_init_irq,
|
||||
.restart = socfpga_arria10_restart,
|
||||
.dt_compat = altera_a10_dt_match,
|
||||
MACHINE_END
|
||||
|
@ -37,6 +37,7 @@ pen: ldr r7, [r6]
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(sti_secondary_startup)
|
||||
|
||||
1: .long .
|
||||
.long pen_release
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/memblock.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
@ -38,8 +39,6 @@ static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
static void sti_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
@ -99,14 +98,62 @@ static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
|
||||
static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
void __iomem *scu_base = NULL;
|
||||
struct device_node *np = of_find_compatible_node(
|
||||
NULL, NULL, "arm,cortex-a9-scu");
|
||||
struct device_node *np;
|
||||
void __iomem *scu_base;
|
||||
u32 __iomem *cpu_strt_ptr;
|
||||
u32 release_phys;
|
||||
int cpu;
|
||||
unsigned long entry_pa = virt_to_phys(sti_secondary_startup);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
|
||||
|
||||
if (np) {
|
||||
scu_base = of_iomap(np, 0);
|
||||
scu_enable(scu_base);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
if (max_cpus <= 1)
|
||||
return;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
||||
np = of_get_cpu_node(cpu, NULL);
|
||||
|
||||
if (!np)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32(np, "cpu-release-addr",
|
||||
&release_phys)) {
|
||||
pr_err("CPU %d: missing or invalid cpu-release-addr "
|
||||
"property\n", cpu);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* holding pen is usually configured in SBC DMEM but can also be
|
||||
* in RAM.
|
||||
*/
|
||||
|
||||
if (!memblock_is_memory(release_phys))
|
||||
cpu_strt_ptr =
|
||||
ioremap(release_phys, sizeof(release_phys));
|
||||
else
|
||||
cpu_strt_ptr =
|
||||
(u32 __iomem *)phys_to_virt(release_phys);
|
||||
|
||||
__raw_writel(entry_pa, cpu_strt_ptr);
|
||||
|
||||
/*
|
||||
* wmb so that data is actually written
|
||||
* before cache flush is done
|
||||
*/
|
||||
smp_wmb();
|
||||
sync_cache_w(cpu_strt_ptr);
|
||||
|
||||
if (!memblock_is_memory(release_phys))
|
||||
iounmap(cpu_strt_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
struct smp_operations __initdata sti_smp_ops = {
|
||||
|
@ -14,4 +14,6 @@
|
||||
|
||||
extern struct smp_operations sti_smp_ops;
|
||||
|
||||
void sti_secondary_startup(void);
|
||||
|
||||
#endif
|
||||
|
@ -60,12 +60,6 @@ err:
|
||||
sbcm_regmap = NULL;
|
||||
}
|
||||
|
||||
static void __naked uniphier_secondary_startup(void)
|
||||
{
|
||||
asm("bl v7_invalidate_l1\n"
|
||||
"b secondary_startup\n");
|
||||
};
|
||||
|
||||
static int uniphier_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle)
|
||||
{
|
||||
@ -75,7 +69,7 @@ static int uniphier_boot_secondary(unsigned int cpu,
|
||||
return -ENODEV;
|
||||
|
||||
ret = regmap_write(sbcm_regmap, 0x1208,
|
||||
virt_to_phys(uniphier_secondary_startup));
|
||||
virt_to_phys(secondary_startup));
|
||||
if (!ret)
|
||||
asm("sev"); /* wake up secondary CPU */
|
||||
|
||||
|
@ -13,6 +13,7 @@ config SOC_ZX296702
|
||||
select ARM_GLOBAL_TIMER
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select PM_GENERIC_DOMAINS
|
||||
help
|
||||
Support for ZTE ZX296702 SoC which is a dual core CortexA9MP
|
||||
endif
|
||||
|
@ -1,2 +1,2 @@
|
||||
obj-$(CONFIG_SOC_ZX296702) += zx296702.o
|
||||
obj-$(CONFIG_SOC_ZX296702) += zx296702.o zx296702-pm-domain.o
|
||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
|
202
arch/arm/mach-zx/zx296702-pm-domain.c
Normal file
202
arch/arm/mach-zx/zx296702-pm-domain.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Linaro Ltd.
|
||||
*
|
||||
* Author: Jun Nie <jun.nie@linaro.org>
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define PCU_DM_CLKEN 0x18
|
||||
#define PCU_DM_RSTEN 0x1C
|
||||
#define PCU_DM_ISOEN 0x20
|
||||
#define PCU_DM_PWRDN 0x24
|
||||
#define PCU_DM_ACK_SYNC 0x28
|
||||
|
||||
enum {
|
||||
PCU_DM_NEON0 = 0,
|
||||
PCU_DM_NEON1,
|
||||
PCU_DM_GPU,
|
||||
PCU_DM_DECPPU,
|
||||
PCU_DM_VOU,
|
||||
PCU_DM_R2D,
|
||||
PCU_DM_TOP,
|
||||
};
|
||||
|
||||
static void __iomem *pcubase;
|
||||
|
||||
struct zx_pm_domain {
|
||||
struct generic_pm_domain dm;
|
||||
unsigned int bit;
|
||||
};
|
||||
|
||||
static int normal_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
|
||||
unsigned long loop = 1000;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_CLKEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp, pcubase + PCU_DM_CLKEN);
|
||||
udelay(5);
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_ISOEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_ISOEN);
|
||||
udelay(5);
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_RSTEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp, pcubase + PCU_DM_RSTEN);
|
||||
udelay(5);
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_PWRDN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_PWRDN);
|
||||
do {
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
|
||||
} while (--loop && !tmp);
|
||||
|
||||
if (!loop) {
|
||||
pr_err("Error: %s %s fail\n", __func__, domain->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int normal_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
|
||||
unsigned long loop = 10000;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_PWRDN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp, pcubase + PCU_DM_PWRDN);
|
||||
do {
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
|
||||
} while (--loop && tmp);
|
||||
|
||||
if (!loop) {
|
||||
pr_err("Error: %s %s fail\n", __func__, domain->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_RSTEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_RSTEN);
|
||||
udelay(5);
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_ISOEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp, pcubase + PCU_DM_ISOEN);
|
||||
udelay(5);
|
||||
|
||||
tmp = readl_relaxed(pcubase + PCU_DM_CLKEN);
|
||||
tmp &= ~BIT(zpd->bit);
|
||||
writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_CLKEN);
|
||||
udelay(5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct zx_pm_domain gpu_domain = {
|
||||
.dm = {
|
||||
.name = "gpu_domain",
|
||||
.power_off = normal_power_off,
|
||||
.power_on = normal_power_on,
|
||||
},
|
||||
.bit = PCU_DM_GPU,
|
||||
};
|
||||
|
||||
static struct zx_pm_domain decppu_domain = {
|
||||
.dm = {
|
||||
.name = "decppu_domain",
|
||||
.power_off = normal_power_off,
|
||||
.power_on = normal_power_on,
|
||||
},
|
||||
.bit = PCU_DM_DECPPU,
|
||||
};
|
||||
|
||||
static struct zx_pm_domain vou_domain = {
|
||||
.dm = {
|
||||
.name = "vou_domain",
|
||||
.power_off = normal_power_off,
|
||||
.power_on = normal_power_on,
|
||||
},
|
||||
.bit = PCU_DM_VOU,
|
||||
};
|
||||
|
||||
static struct zx_pm_domain r2d_domain = {
|
||||
.dm = {
|
||||
.name = "r2d_domain",
|
||||
.power_off = normal_power_off,
|
||||
.power_on = normal_power_on,
|
||||
},
|
||||
.bit = PCU_DM_R2D,
|
||||
};
|
||||
|
||||
static struct generic_pm_domain *zx296702_pm_domains[] = {
|
||||
&vou_domain.dm,
|
||||
&gpu_domain.dm,
|
||||
&decppu_domain.dm,
|
||||
&r2d_domain.dm,
|
||||
};
|
||||
|
||||
static int zx296702_pd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct genpd_onecell_data *genpd_data;
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
|
||||
if (!genpd_data)
|
||||
return -ENOMEM;
|
||||
|
||||
genpd_data->domains = zx296702_pm_domains;
|
||||
genpd_data->num_domains = ARRAY_SIZE(zx296702_pm_domains);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no memory resource defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcubase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (!pcubase) {
|
||||
dev_err(&pdev->dev, "ioremap fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(zx296702_pm_domains); ++i)
|
||||
pm_genpd_init(zx296702_pm_domains[i], NULL, false);
|
||||
|
||||
of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id zx296702_pm_domain_matches[] __initconst = {
|
||||
{ .compatible = "zte,zx296702-pcu", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver zx296702_pd_driver __initdata = {
|
||||
.driver = {
|
||||
.name = "zx-powerdomain",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = zx296702_pm_domain_matches,
|
||||
},
|
||||
.probe = zx296702_pd_probe,
|
||||
};
|
||||
|
||||
static int __init zx296702_pd_init(void)
|
||||
{
|
||||
return platform_driver_register(&zx296702_pd_driver);
|
||||
}
|
||||
subsys_initcall(zx296702_pd_init);
|
@ -197,8 +197,8 @@ static const char * const zynq_dt_match[] = {
|
||||
|
||||
DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
|
||||
/* 64KB way size, 8-way associativity, parity disabled */
|
||||
.l2c_aux_val = 0x00000000,
|
||||
.l2c_aux_mask = 0xffffffff,
|
||||
.l2c_aux_val = 0x00400000,
|
||||
.l2c_aux_mask = 0xffbfffff,
|
||||
.smp = smp_ops(zynq_smp_ops),
|
||||
.map_io = zynq_map_io,
|
||||
.init_irq = zynq_irq_init,
|
||||
|
@ -18,7 +18,7 @@ ARM_BE8(rev r0, r0)
|
||||
.globl zynq_secondary_trampoline_jump
|
||||
zynq_secondary_trampoline_jump:
|
||||
/* Space for jumping address */
|
||||
.word /* cpu 1 */
|
||||
.word 0 /* cpu 1 */
|
||||
.globl zynq_secondary_trampoline_end
|
||||
zynq_secondary_trampoline_end:
|
||||
ENDPROC(zynq_secondary_trampoline)
|
||||
|
@ -289,7 +289,8 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
|
||||
/* try grabbing a DMA channel with the requested priority */
|
||||
for (i = 0; i < num_dma_channels; i++) {
|
||||
if ((dma_channels[i].prio == prio) &&
|
||||
!dma_channels[i].name) {
|
||||
!dma_channels[i].name &&
|
||||
!pxad_toggle_reserved_channel(i)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@ -326,13 +327,14 @@ void pxa_free_dma (int dma_ch)
|
||||
local_irq_save(flags);
|
||||
DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
|
||||
dma_channels[dma_ch].name = NULL;
|
||||
pxad_toggle_reserved_channel(dma_ch);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(pxa_free_dma);
|
||||
|
||||
static irqreturn_t dma_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
int i, dint = DINT;
|
||||
int i, dint = DINT, done = 0;
|
||||
struct dma_channel *channel;
|
||||
|
||||
while (dint) {
|
||||
@ -341,16 +343,13 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
|
||||
channel = &dma_channels[i];
|
||||
if (channel->name && channel->irq_handler) {
|
||||
channel->irq_handler(i, channel->data);
|
||||
} else {
|
||||
/*
|
||||
* IRQ for an unregistered DMA channel:
|
||||
* let's clear the interrupts and disable it.
|
||||
*/
|
||||
printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
|
||||
DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
|
||||
done++;
|
||||
}
|
||||
}
|
||||
if (done)
|
||||
return IRQ_HANDLED;
|
||||
else
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int __init pxa_init_dma(int irq, int num_ch)
|
||||
@ -372,7 +371,8 @@ int __init pxa_init_dma(int irq, int num_ch)
|
||||
spin_lock_init(&dma_channels[i].lock);
|
||||
}
|
||||
|
||||
ret = request_irq(irq, dma_irq_handler, 0, "DMA", NULL);
|
||||
ret = request_irq(irq, dma_irq_handler, IRQF_SHARED, "DMA",
|
||||
dma_channels);
|
||||
if (ret) {
|
||||
printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
|
||||
kfree(dma_channels);
|
||||
|
@ -82,4 +82,19 @@ int pxa_request_dma (char *name,
|
||||
|
||||
void pxa_free_dma (int dma_ch);
|
||||
|
||||
/*
|
||||
* Cooperation with pxa_dma + dmaengine while there remains at least one pxa
|
||||
* driver not converted to dmaengine.
|
||||
*/
|
||||
#if defined(CONFIG_PXA_DMA)
|
||||
extern int pxad_toggle_reserved_channel(int legacy_channel);
|
||||
#else
|
||||
static inline int pxad_toggle_reserved_channel(int legacy_channel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern void __init pxa2xx_set_dmac_info(int nb_channels);
|
||||
|
||||
#endif /* __PLAT_DMA_H */
|
||||
|
@ -3,7 +3,7 @@ clk-common = dpll.o composite.o divider.o gate.o \
|
||||
fixed-factor.o mux.o apll.o \
|
||||
clkt_dpll.o clkt_iclk.o clkt_dflt.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o
|
||||
obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o
|
||||
obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-814x.o clk-816x.o
|
||||
obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o \
|
||||
clk-3xxx.o dpll3xxx.o
|
||||
|
33
drivers/clk/ti/clk-814x.c
Normal file
33
drivers/clk/ti/clk-814x.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 version 2.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/ti.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
static struct ti_dt_clk dm814_clks[] = {
|
||||
DT_CLK(NULL, "devosc_ck", "devosc_ck"),
|
||||
DT_CLK(NULL, "mpu_ck", "mpu_ck"),
|
||||
DT_CLK(NULL, "sysclk4_ck", "sysclk4_ck"),
|
||||
DT_CLK(NULL, "sysclk6_ck", "sysclk6_ck"),
|
||||
DT_CLK(NULL, "sysclk10_ck", "sysclk10_ck"),
|
||||
DT_CLK(NULL, "sysclk18_ck", "sysclk18_ck"),
|
||||
DT_CLK(NULL, "timer_sys_ck", "devosc_ck"),
|
||||
DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"),
|
||||
DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"),
|
||||
{ .node_name = NULL },
|
||||
};
|
||||
|
||||
int __init dm814x_dt_clk_init(void)
|
||||
{
|
||||
ti_dt_clocks_register(dm814_clks);
|
||||
omap2_clk_disable_autoidle_all();
|
||||
omap2_clk_enable_init_clocks(NULL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
@ -44,7 +44,7 @@ static const char *enable_init_clks[] = {
|
||||
"ddr_pll_clk3",
|
||||
};
|
||||
|
||||
int __init ti81xx_dt_clk_init(void)
|
||||
int __init dm816x_dt_clk_init(void)
|
||||
{
|
||||
ti_dt_clocks_register(dm816x_clks);
|
||||
omap2_clk_disable_autoidle_all();
|
||||
|
@ -1,3 +1,3 @@
|
||||
# Zynq clock specific Makefile
|
||||
|
||||
obj-$(CONFIG_ARCH_ZYNQ) += clkc.o pll.o
|
||||
obj-y += clkc.o pll.o
|
||||
|
@ -401,6 +401,17 @@ config KEYBOARD_MPR121
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mpr121_touchkey.
|
||||
|
||||
config KEYBOARD_SNVS_PWRKEY
|
||||
tristate "IMX SNVS Power Key Driver"
|
||||
depends on SOC_IMX6SX
|
||||
depends on OF
|
||||
help
|
||||
This is the snvs powerkey driver for the Freescale i.MX application
|
||||
processors that are newer than i.MX6 SX.
|
||||
|
||||
To compile this driver as a module, choose M here; the
|
||||
module will be called snvs_pwrkey.
|
||||
|
||||
config KEYBOARD_IMX
|
||||
tristate "IMX keypad support"
|
||||
depends on ARCH_MXC
|
||||
|
@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o
|
||||
obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o
|
||||
obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
|
||||
obj-$(CONFIG_KEYBOARD_SNVS_PWRKEY) += snvs_pwrkey.o
|
||||
obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
|
||||
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
|
||||
|
227
drivers/input/keyboard/snvs_pwrkey.c
Normal file
227
drivers/input/keyboard/snvs_pwrkey.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Driver for the IMX SNVS ON/OFF Power Key
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define SNVS_LPSR_REG 0x4C /* LP Status Register */
|
||||
#define SNVS_LPCR_REG 0x38 /* LP Control Register */
|
||||
#define SNVS_HPSR_REG 0x14
|
||||
#define SNVS_HPSR_BTN BIT(6)
|
||||
#define SNVS_LPSR_SPO BIT(18)
|
||||
#define SNVS_LPCR_DEP_EN BIT(5)
|
||||
|
||||
#define DEBOUNCE_TIME 30
|
||||
#define REPEAT_INTERVAL 60
|
||||
|
||||
struct pwrkey_drv_data {
|
||||
struct regmap *snvs;
|
||||
int irq;
|
||||
int keycode;
|
||||
int keystate; /* 1:pressed */
|
||||
int wakeup;
|
||||
struct timer_list check_timer;
|
||||
struct input_dev *input;
|
||||
};
|
||||
|
||||
static void imx_imx_snvs_check_for_events(unsigned long data)
|
||||
{
|
||||
struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data;
|
||||
struct input_dev *input = pdata->input;
|
||||
u32 state;
|
||||
|
||||
regmap_read(pdata->snvs, SNVS_HPSR_REG, &state);
|
||||
state = state & SNVS_HPSR_BTN ? 1 : 0;
|
||||
|
||||
/* only report new event if status changed */
|
||||
if (state ^ pdata->keystate) {
|
||||
pdata->keystate = state;
|
||||
input_event(input, EV_KEY, pdata->keycode, state);
|
||||
input_sync(input);
|
||||
pm_relax(pdata->input->dev.parent);
|
||||
}
|
||||
|
||||
/* repeat check if pressed long */
|
||||
if (state) {
|
||||
mod_timer(&pdata->check_timer,
|
||||
jiffies + msecs_to_jiffies(REPEAT_INTERVAL));
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct platform_device *pdev = dev_id;
|
||||
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
|
||||
u32 lp_status;
|
||||
|
||||
pm_wakeup_event(pdata->input->dev.parent, 0);
|
||||
|
||||
regmap_read(pdata->snvs, SNVS_LPSR_REG, &lp_status);
|
||||
if (lp_status & SNVS_LPSR_SPO)
|
||||
mod_timer(&pdata->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
|
||||
|
||||
/* clear SPO status */
|
||||
regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void imx_snvs_pwrkey_act(void *pdata)
|
||||
{
|
||||
struct pwrkey_drv_data *pd = pdata;
|
||||
|
||||
del_timer_sync(&pd->check_timer);
|
||||
}
|
||||
|
||||
static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pwrkey_drv_data *pdata = NULL;
|
||||
struct input_dev *input = NULL;
|
||||
struct device_node *np;
|
||||
int error;
|
||||
|
||||
/* Get SNVS register Page */
|
||||
np = pdev->dev.of_node;
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");;
|
||||
|
||||
if (!pdata->snvs) {
|
||||
dev_err(&pdev->dev, "Can't get snvs syscon\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
|
||||
pdata->keycode = KEY_POWER;
|
||||
dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
|
||||
}
|
||||
|
||||
pdata->wakeup = of_property_read_bool(np, "wakeup-source");
|
||||
|
||||
pdata->irq = platform_get_irq(pdev, 0);
|
||||
if (pdata->irq < 0) {
|
||||
dev_err(&pdev->dev, "no irq defined in platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_DEP_EN, SNVS_LPCR_DEP_EN);
|
||||
|
||||
/* clear the unexpected interrupt before driver ready */
|
||||
regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO);
|
||||
|
||||
setup_timer(&pdata->check_timer,
|
||||
imx_imx_snvs_check_for_events, (unsigned long) pdata);
|
||||
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input) {
|
||||
dev_err(&pdev->dev, "failed to allocate the input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input->name = pdev->name;
|
||||
input->phys = "snvs-pwrkey/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
|
||||
input_set_capability(input, EV_KEY, pdata->keycode);
|
||||
|
||||
/* input customer action to cancel release timer */
|
||||
error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register remove action\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_irq(&pdev->dev, pdata->irq,
|
||||
imx_snvs_pwrkey_interrupt,
|
||||
0, pdev->name, pdev);
|
||||
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "interrupt not available.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error < 0) {
|
||||
dev_err(&pdev->dev, "failed to register input device\n");
|
||||
input_free_device(input);
|
||||
return error;
|
||||
}
|
||||
|
||||
pdata->input = input;
|
||||
platform_set_drvdata(pdev, pdata);
|
||||
|
||||
device_init_wakeup(&pdev->dev, pdata->wakeup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_snvs_pwrkey_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
enable_irq_wake(pdata->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_snvs_pwrkey_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
disable_irq_wake(pdata->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id imx_snvs_pwrkey_ids[] = {
|
||||
{ .compatible = "fsl,sec-v4.0-pwrkey" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids);
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend,
|
||||
imx_snvs_pwrkey_resume);
|
||||
|
||||
static struct platform_driver imx_snvs_pwrkey_driver = {
|
||||
.driver = {
|
||||
.name = "snvs_pwrkey",
|
||||
.pm = &imx_snvs_pwrkey_pm_ops,
|
||||
.of_match_table = imx_snvs_pwrkey_ids,
|
||||
},
|
||||
.probe = imx_snvs_pwrkey_probe,
|
||||
};
|
||||
module_platform_driver(imx_snvs_pwrkey_driver);
|
||||
|
||||
MODULE_AUTHOR("Freescale Semiconductor");
|
||||
MODULE_DESCRIPTION("i.MX snvs power key Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1176,8 +1176,8 @@ static int gpmc_setup_irq(void)
|
||||
gpmc_client_irq[i].irq = gpmc_irq_start + i;
|
||||
irq_set_chip_and_handler(gpmc_client_irq[i].irq,
|
||||
&gpmc_irq_chip, handle_simple_irq);
|
||||
set_irq_flags(gpmc_client_irq[i].irq,
|
||||
IRQF_VALID | IRQF_NOAUTOEN);
|
||||
irq_modify_status(gpmc_client_irq[i].irq, IRQ_NOREQUEST,
|
||||
IRQ_NOAUTOEN);
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
@ -1200,7 +1200,6 @@ static int gpmc_free_irq(void)
|
||||
for (i = 0; i < GPMC_NR_IRQ; i++) {
|
||||
irq_set_handler(gpmc_client_irq[i].irq, NULL);
|
||||
irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
|
||||
irq_modify_status(gpmc_client_irq[i].irq, 0, 0);
|
||||
}
|
||||
|
||||
irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ);
|
||||
|
@ -1523,6 +1523,7 @@ config RTC_DRV_MXC
|
||||
|
||||
config RTC_DRV_SNVS
|
||||
tristate "Freescale SNVS RTC support"
|
||||
select REGMAP_MMIO
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
help
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#define RTC_INPUT_CLK_32768HZ (0x00 << 5)
|
||||
#define RTC_INPUT_CLK_32000HZ (0x01 << 5)
|
||||
@ -79,7 +81,8 @@ struct rtc_plat_data {
|
||||
struct rtc_device *rtc;
|
||||
void __iomem *ioaddr;
|
||||
int irq;
|
||||
struct clk *clk;
|
||||
struct clk *clk_ref;
|
||||
struct clk *clk_ipg;
|
||||
struct rtc_time g_rtc_alarm;
|
||||
enum imx_rtc_type devtype;
|
||||
};
|
||||
@ -97,6 +100,15 @@ static const struct platform_device_id imx_rtc_devtype[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id imx_rtc_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx1-rtc", .data = (const void *)IMX1_RTC },
|
||||
{ .compatible = "fsl,imx21-rtc", .data = (const void *)IMX21_RTC },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_rtc_dt_ids);
|
||||
#endif
|
||||
|
||||
static inline int is_imx1_rtc(struct rtc_plat_data *data)
|
||||
{
|
||||
return data->devtype == IMX1_RTC;
|
||||
@ -361,11 +373,16 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
u32 reg;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
of_id = of_match_device(imx_rtc_dt_ids, &pdev->dev);
|
||||
if (of_id)
|
||||
pdata->devtype = (enum imx_rtc_type)of_id->data;
|
||||
else
|
||||
pdata->devtype = pdev->id_entry->driver_data;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@ -373,17 +390,28 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(pdata->ioaddr))
|
||||
return PTR_ERR(pdata->ioaddr);
|
||||
|
||||
pdata->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(pdata->clk)) {
|
||||
dev_err(&pdev->dev, "unable to get clock!\n");
|
||||
return PTR_ERR(pdata->clk);
|
||||
pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(pdata->clk_ipg)) {
|
||||
dev_err(&pdev->dev, "unable to get ipg clock!\n");
|
||||
return PTR_ERR(pdata->clk_ipg);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pdata->clk);
|
||||
ret = clk_prepare_enable(pdata->clk_ipg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rate = clk_get_rate(pdata->clk);
|
||||
pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
|
||||
if (IS_ERR(pdata->clk_ref)) {
|
||||
dev_err(&pdev->dev, "unable to get ref clock!\n");
|
||||
ret = PTR_ERR(pdata->clk_ref);
|
||||
goto exit_put_clk_ipg;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pdata->clk_ref);
|
||||
if (ret)
|
||||
goto exit_put_clk_ipg;
|
||||
|
||||
rate = clk_get_rate(pdata->clk_ref);
|
||||
|
||||
if (rate == 32768)
|
||||
reg = RTC_INPUT_CLK_32768HZ;
|
||||
@ -394,7 +422,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
else {
|
||||
dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate);
|
||||
ret = -EINVAL;
|
||||
goto exit_put_clk;
|
||||
goto exit_put_clk_ref;
|
||||
}
|
||||
|
||||
reg |= RTC_ENABLE_BIT;
|
||||
@ -402,7 +430,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) {
|
||||
dev_err(&pdev->dev, "hardware module can't be enabled!\n");
|
||||
ret = -EIO;
|
||||
goto exit_put_clk;
|
||||
goto exit_put_clk_ref;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pdata);
|
||||
@ -424,15 +452,17 @@ static int mxc_rtc_probe(struct platform_device *pdev)
|
||||
THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
ret = PTR_ERR(rtc);
|
||||
goto exit_put_clk;
|
||||
goto exit_put_clk_ref;
|
||||
}
|
||||
|
||||
pdata->rtc = rtc;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_put_clk:
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
exit_put_clk_ref:
|
||||
clk_disable_unprepare(pdata->clk_ref);
|
||||
exit_put_clk_ipg:
|
||||
clk_disable_unprepare(pdata->clk_ipg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -441,7 +471,8 @@ static int mxc_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
clk_disable_unprepare(pdata->clk_ref);
|
||||
clk_disable_unprepare(pdata->clk_ipg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -473,6 +504,7 @@ static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
|
||||
static struct platform_driver mxc_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "mxc_rtc",
|
||||
.of_match_table = of_match_ptr(imx_rtc_dt_ids),
|
||||
.pm = &mxc_rtc_pm_ops,
|
||||
},
|
||||
.id_table = imx_rtc_devtype,
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define SNVS_LPREGISTER_OFFSET 0x34
|
||||
|
||||
/* These register offsets are relative to LP (Low Power) range */
|
||||
#define SNVS_LPCR 0x04
|
||||
@ -37,31 +41,36 @@
|
||||
|
||||
struct snvs_rtc_data {
|
||||
struct rtc_device *rtc;
|
||||
void __iomem *ioaddr;
|
||||
struct regmap *regmap;
|
||||
int offset;
|
||||
int irq;
|
||||
spinlock_t lock;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static u32 rtc_read_lp_counter(void __iomem *ioaddr)
|
||||
static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
|
||||
{
|
||||
u64 read1, read2;
|
||||
u32 val;
|
||||
|
||||
do {
|
||||
read1 = readl(ioaddr + SNVS_LPSRTCMR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
|
||||
read1 = val;
|
||||
read1 <<= 32;
|
||||
read1 |= readl(ioaddr + SNVS_LPSRTCLR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
|
||||
read1 |= val;
|
||||
|
||||
read2 = readl(ioaddr + SNVS_LPSRTCMR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
|
||||
read2 = val;
|
||||
read2 <<= 32;
|
||||
read2 |= readl(ioaddr + SNVS_LPSRTCLR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
|
||||
read2 |= val;
|
||||
} while (read1 != read2);
|
||||
|
||||
/* Convert 47-bit counter to 32-bit raw second count */
|
||||
return (u32) (read1 >> CNTR_TO_SECS_SH);
|
||||
}
|
||||
|
||||
static void rtc_write_sync_lp(void __iomem *ioaddr)
|
||||
static void rtc_write_sync_lp(struct snvs_rtc_data *data)
|
||||
{
|
||||
u32 count1, count2, count3;
|
||||
int i;
|
||||
@ -69,15 +78,15 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
|
||||
/* Wait for 3 CKIL cycles */
|
||||
for (i = 0; i < 3; i++) {
|
||||
do {
|
||||
count1 = readl(ioaddr + SNVS_LPSRTCLR);
|
||||
count2 = readl(ioaddr + SNVS_LPSRTCLR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
|
||||
} while (count1 != count2);
|
||||
|
||||
/* Now wait until counter value changes */
|
||||
do {
|
||||
do {
|
||||
count2 = readl(ioaddr + SNVS_LPSRTCLR);
|
||||
count3 = readl(ioaddr + SNVS_LPSRTCLR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
|
||||
} while (count2 != count3);
|
||||
} while (count3 == count1);
|
||||
}
|
||||
@ -85,23 +94,14 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
|
||||
|
||||
static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
int timeout = 1000;
|
||||
u32 lpcr;
|
||||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
lpcr = readl(data->ioaddr + SNVS_LPCR);
|
||||
if (enable)
|
||||
lpcr |= SNVS_LPCR_SRTC_ENV;
|
||||
else
|
||||
lpcr &= ~SNVS_LPCR_SRTC_ENV;
|
||||
writel(lpcr, data->ioaddr + SNVS_LPCR);
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_SRTC_ENV,
|
||||
enable ? SNVS_LPCR_SRTC_ENV : 0);
|
||||
|
||||
while (--timeout) {
|
||||
lpcr = readl(data->ioaddr + SNVS_LPCR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPCR, &lpcr);
|
||||
|
||||
if (enable) {
|
||||
if (lpcr & SNVS_LPCR_SRTC_ENV)
|
||||
@ -121,7 +121,7 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
|
||||
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||
unsigned long time = rtc_read_lp_counter(data->ioaddr);
|
||||
unsigned long time = rtc_read_lp_counter(data);
|
||||
|
||||
rtc_time_to_tm(time, tm);
|
||||
|
||||
@ -139,8 +139,8 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
snvs_rtc_enable(data, false);
|
||||
|
||||
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
|
||||
writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR);
|
||||
writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
|
||||
|
||||
/* Enable RTC again */
|
||||
snvs_rtc_enable(data, true);
|
||||
@ -153,10 +153,10 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||
u32 lptar, lpsr;
|
||||
|
||||
lptar = readl(data->ioaddr + SNVS_LPTAR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
|
||||
rtc_time_to_tm(lptar, &alrm->time);
|
||||
|
||||
lpsr = readl(data->ioaddr + SNVS_LPSR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
|
||||
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
@ -165,21 +165,12 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
|
||||
{
|
||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||
u32 lpcr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
|
||||
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
|
||||
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
|
||||
|
||||
lpcr = readl(data->ioaddr + SNVS_LPCR);
|
||||
if (enable)
|
||||
lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
|
||||
else
|
||||
lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
|
||||
writel(lpcr, data->ioaddr + SNVS_LPCR);
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
rtc_write_sync_lp(data->ioaddr);
|
||||
rtc_write_sync_lp(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -189,24 +180,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||
struct rtc_time *alrm_tm = &alrm->time;
|
||||
unsigned long time;
|
||||
unsigned long flags;
|
||||
u32 lpcr;
|
||||
|
||||
rtc_tm_to_time(alrm_tm, &time);
|
||||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
/* Have to clear LPTA_EN before programming new alarm time in LPTAR */
|
||||
lpcr = readl(data->ioaddr + SNVS_LPCR);
|
||||
lpcr &= ~SNVS_LPCR_LPTA_EN;
|
||||
writel(lpcr, data->ioaddr + SNVS_LPCR);
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
writel(time, data->ioaddr + SNVS_LPTAR);
|
||||
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
|
||||
|
||||
/* Clear alarm interrupt status bit */
|
||||
writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
|
||||
|
||||
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
|
||||
}
|
||||
@ -226,7 +207,7 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
|
||||
u32 lpsr;
|
||||
u32 events = 0;
|
||||
|
||||
lpsr = readl(data->ioaddr + SNVS_LPSR);
|
||||
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
|
||||
|
||||
if (lpsr & SNVS_LPSR_LPTA) {
|
||||
events |= (RTC_AF | RTC_IRQF);
|
||||
@ -238,25 +219,48 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/* clear interrupt status */
|
||||
writel(lpsr, data->ioaddr + SNVS_LPSR);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
|
||||
|
||||
return events ? IRQ_HANDLED : IRQ_NONE;
|
||||
}
|
||||
|
||||
static const struct regmap_config snvs_rtc_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
};
|
||||
|
||||
static int snvs_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snvs_rtc_data *data;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
void __iomem *mmio;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
|
||||
|
||||
if (IS_ERR(data->regmap)) {
|
||||
dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it\n");
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->ioaddr = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->ioaddr))
|
||||
return PTR_ERR(data->ioaddr);
|
||||
|
||||
mmio = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(mmio))
|
||||
return PTR_ERR(mmio);
|
||||
|
||||
data->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, &snvs_rtc_config);
|
||||
} else {
|
||||
data->offset = SNVS_LPREGISTER_OFFSET;
|
||||
of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
|
||||
}
|
||||
|
||||
if (!data->regmap) {
|
||||
dev_err(&pdev->dev, "Can't find snvs syscon\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->irq = platform_get_irq(pdev, 0);
|
||||
if (data->irq < 0)
|
||||
@ -276,13 +280,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
spin_lock_init(&data->lock);
|
||||
|
||||
/* Initialize glitch detect */
|
||||
writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPPGDR, SNVS_LPPGDR_INIT);
|
||||
|
||||
/* Clear interrupt status */
|
||||
writel(0xffffffff, data->ioaddr + SNVS_LPSR);
|
||||
regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
|
||||
|
||||
/* Enable RTC */
|
||||
snvs_rtc_enable(data, true);
|
||||
|
@ -1,6 +1,15 @@
|
||||
#
|
||||
# MediaTek SoC drivers
|
||||
#
|
||||
config MTK_INFRACFG
|
||||
bool "MediaTek INFRACFG Support"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select REGMAP
|
||||
help
|
||||
Say yes here to add support for the MediaTek INFRACFG controller. The
|
||||
INFRACFG controller contains various infrastructure registers not
|
||||
directly associated to any device.
|
||||
|
||||
config MTK_PMIC_WRAP
|
||||
tristate "MediaTek PMIC Wrapper Support"
|
||||
depends on ARCH_MEDIATEK
|
||||
@ -10,3 +19,13 @@ config MTK_PMIC_WRAP
|
||||
Say yes here to add support for MediaTek PMIC Wrapper found
|
||||
on different MediaTek SoCs. The PMIC wrapper is a proprietary
|
||||
hardware to connect the PMIC.
|
||||
|
||||
config MTK_SCPSYS
|
||||
bool "MediaTek SCPSYS Support"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
select REGMAP
|
||||
select MTK_INFRACFG
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
Say yes here to add support for the MediaTek SCPSYS power domain
|
||||
driver.
|
||||
|
@ -1 +1,3 @@
|
||||
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
|
||||
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
|
||||
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
|
||||
|
91
drivers/soc/mediatek/mtk-infracfg.c
Normal file
91
drivers/soc/mediatek/mtk-infracfg.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Pengutronix, Sascha Hauer <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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soc/mediatek/infracfg.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define INFRA_TOPAXI_PROTECTEN 0x0220
|
||||
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
|
||||
|
||||
/**
|
||||
* mtk_infracfg_set_bus_protection - enable bus protection
|
||||
* @regmap: The infracfg regmap
|
||||
* @mask: The mask containing the protection bits to be enabled.
|
||||
*
|
||||
* This function enables the bus protection bits for disabled power
|
||||
* domains so that the system does not hang when some unit accesses the
|
||||
* bus while in power down.
|
||||
*/
|
||||
int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
|
||||
{
|
||||
unsigned long expired;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
|
||||
|
||||
expired = jiffies + HZ;
|
||||
|
||||
while (1) {
|
||||
ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((val & mask) == mask)
|
||||
break;
|
||||
|
||||
cpu_relax();
|
||||
if (time_after(jiffies, expired))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_infracfg_clear_bus_protection - disable bus protection
|
||||
* @regmap: The infracfg regmap
|
||||
* @mask: The mask containing the protection bits to be disabled.
|
||||
*
|
||||
* This function disables the bus protection bits previously enabled with
|
||||
* mtk_infracfg_set_bus_protection.
|
||||
*/
|
||||
int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
|
||||
{
|
||||
unsigned long expired;
|
||||
int ret;
|
||||
|
||||
regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
|
||||
|
||||
expired = jiffies + HZ;
|
||||
|
||||
while (1) {
|
||||
u32 val;
|
||||
|
||||
ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(val & mask))
|
||||
break;
|
||||
|
||||
cpu_relax();
|
||||
if (time_after(jiffies, expired))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -926,7 +926,6 @@ err_out1:
|
||||
static struct platform_driver pwrap_drv = {
|
||||
.driver = {
|
||||
.name = "mt-pmic-pwrap",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(of_pwrap_match_tbl),
|
||||
},
|
||||
.probe = pwrap_probe,
|
||||
|
488
drivers/soc/mediatek/mtk-scpsys.c
Normal file
488
drivers/soc/mediatek/mtk-scpsys.c
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Pengutronix, Sascha Hauer <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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soc/mediatek/infracfg.h>
|
||||
#include <dt-bindings/power/mt8173-power.h>
|
||||
|
||||
#define SPM_VDE_PWR_CON 0x0210
|
||||
#define SPM_MFG_PWR_CON 0x0214
|
||||
#define SPM_VEN_PWR_CON 0x0230
|
||||
#define SPM_ISP_PWR_CON 0x0238
|
||||
#define SPM_DIS_PWR_CON 0x023c
|
||||
#define SPM_VEN2_PWR_CON 0x0298
|
||||
#define SPM_AUDIO_PWR_CON 0x029c
|
||||
#define SPM_MFG_2D_PWR_CON 0x02c0
|
||||
#define SPM_MFG_ASYNC_PWR_CON 0x02c4
|
||||
#define SPM_USB_PWR_CON 0x02cc
|
||||
#define SPM_PWR_STATUS 0x060c
|
||||
#define SPM_PWR_STATUS_2ND 0x0610
|
||||
|
||||
#define PWR_RST_B_BIT BIT(0)
|
||||
#define PWR_ISO_BIT BIT(1)
|
||||
#define PWR_ON_BIT BIT(2)
|
||||
#define PWR_ON_2ND_BIT BIT(3)
|
||||
#define PWR_CLK_DIS_BIT BIT(4)
|
||||
|
||||
#define PWR_STATUS_DISP BIT(3)
|
||||
#define PWR_STATUS_MFG BIT(4)
|
||||
#define PWR_STATUS_ISP BIT(5)
|
||||
#define PWR_STATUS_VDEC BIT(7)
|
||||
#define PWR_STATUS_VENC_LT BIT(20)
|
||||
#define PWR_STATUS_VENC BIT(21)
|
||||
#define PWR_STATUS_MFG_2D BIT(22)
|
||||
#define PWR_STATUS_MFG_ASYNC BIT(23)
|
||||
#define PWR_STATUS_AUDIO BIT(24)
|
||||
#define PWR_STATUS_USB BIT(25)
|
||||
|
||||
enum clk_id {
|
||||
MT8173_CLK_MM,
|
||||
MT8173_CLK_MFG,
|
||||
MT8173_CLK_NONE,
|
||||
MT8173_CLK_MAX = MT8173_CLK_NONE,
|
||||
};
|
||||
|
||||
struct scp_domain_data {
|
||||
const char *name;
|
||||
u32 sta_mask;
|
||||
int ctl_offs;
|
||||
u32 sram_pdn_bits;
|
||||
u32 sram_pdn_ack_bits;
|
||||
u32 bus_prot_mask;
|
||||
enum clk_id clk_id;
|
||||
};
|
||||
|
||||
static const struct scp_domain_data scp_domain_data[] __initconst = {
|
||||
[MT8173_POWER_DOMAIN_VDEC] = {
|
||||
.name = "vdec",
|
||||
.sta_mask = PWR_STATUS_VDEC,
|
||||
.ctl_offs = SPM_VDE_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||
.clk_id = MT8173_CLK_MM,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_VENC] = {
|
||||
.name = "venc",
|
||||
.sta_mask = PWR_STATUS_VENC,
|
||||
.ctl_offs = SPM_VEN_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
.clk_id = MT8173_CLK_MM,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_ISP] = {
|
||||
.name = "isp",
|
||||
.sta_mask = PWR_STATUS_ISP,
|
||||
.ctl_offs = SPM_ISP_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(13, 12),
|
||||
.clk_id = MT8173_CLK_MM,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_MM] = {
|
||||
.name = "mm",
|
||||
.sta_mask = PWR_STATUS_DISP,
|
||||
.ctl_offs = SPM_DIS_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(12, 12),
|
||||
.clk_id = MT8173_CLK_MM,
|
||||
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
|
||||
MT8173_TOP_AXI_PROT_EN_MM_M1,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_VENC_LT] = {
|
||||
.name = "venc_lt",
|
||||
.sta_mask = PWR_STATUS_VENC_LT,
|
||||
.ctl_offs = SPM_VEN2_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
.clk_id = MT8173_CLK_MM,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_AUDIO] = {
|
||||
.name = "audio",
|
||||
.sta_mask = PWR_STATUS_AUDIO,
|
||||
.ctl_offs = SPM_AUDIO_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
.clk_id = MT8173_CLK_NONE,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_USB] = {
|
||||
.name = "usb",
|
||||
.sta_mask = PWR_STATUS_USB,
|
||||
.ctl_offs = SPM_USB_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(15, 12),
|
||||
.clk_id = MT8173_CLK_NONE,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
|
||||
.name = "mfg_async",
|
||||
.sta_mask = PWR_STATUS_MFG_ASYNC,
|
||||
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = 0,
|
||||
.clk_id = MT8173_CLK_MFG,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_MFG_2D] = {
|
||||
.name = "mfg_2d",
|
||||
.sta_mask = PWR_STATUS_MFG_2D,
|
||||
.ctl_offs = SPM_MFG_2D_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(11, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(13, 12),
|
||||
.clk_id = MT8173_CLK_NONE,
|
||||
},
|
||||
[MT8173_POWER_DOMAIN_MFG] = {
|
||||
.name = "mfg",
|
||||
.sta_mask = PWR_STATUS_MFG,
|
||||
.ctl_offs = SPM_MFG_PWR_CON,
|
||||
.sram_pdn_bits = GENMASK(13, 8),
|
||||
.sram_pdn_ack_bits = GENMASK(21, 16),
|
||||
.clk_id = MT8173_CLK_NONE,
|
||||
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
|
||||
MT8173_TOP_AXI_PROT_EN_MFG_M0 |
|
||||
MT8173_TOP_AXI_PROT_EN_MFG_M1 |
|
||||
MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data)
|
||||
|
||||
struct scp;
|
||||
|
||||
struct scp_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
struct scp *scp;
|
||||
struct clk *clk;
|
||||
u32 sta_mask;
|
||||
void __iomem *ctl_addr;
|
||||
u32 sram_pdn_bits;
|
||||
u32 sram_pdn_ack_bits;
|
||||
u32 bus_prot_mask;
|
||||
};
|
||||
|
||||
struct scp {
|
||||
struct scp_domain domains[NUM_DOMAINS];
|
||||
struct genpd_onecell_data pd_data;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct regmap *infracfg;
|
||||
};
|
||||
|
||||
static int scpsys_domain_is_on(struct scp_domain *scpd)
|
||||
{
|
||||
struct scp *scp = scpd->scp;
|
||||
|
||||
u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->sta_mask;
|
||||
u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & scpd->sta_mask;
|
||||
|
||||
/*
|
||||
* A domain is on when both status bits are set. If only one is set
|
||||
* return an error. This happens while powering up a domain
|
||||
*/
|
||||
|
||||
if (status && status2)
|
||||
return true;
|
||||
if (!status && !status2)
|
||||
return false;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int scpsys_power_on(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
|
||||
struct scp *scp = scpd->scp;
|
||||
unsigned long timeout;
|
||||
bool expired;
|
||||
void __iomem *ctl_addr = scpd->ctl_addr;
|
||||
u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (scpd->clk) {
|
||||
ret = clk_prepare_enable(scpd->clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
val = readl(ctl_addr);
|
||||
val |= PWR_ON_BIT;
|
||||
writel(val, ctl_addr);
|
||||
val |= PWR_ON_2ND_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
/* wait until PWR_ACK = 1 */
|
||||
timeout = jiffies + HZ;
|
||||
expired = false;
|
||||
while (1) {
|
||||
ret = scpsys_domain_is_on(scpd);
|
||||
if (ret > 0)
|
||||
break;
|
||||
|
||||
if (expired) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto err_pwr_ack;
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
expired = true;
|
||||
}
|
||||
|
||||
val &= ~PWR_CLK_DIS_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val &= ~PWR_ISO_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val |= PWR_RST_B_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val &= ~scpd->sram_pdn_bits;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
/* wait until SRAM_PDN_ACK all 0 */
|
||||
timeout = jiffies + HZ;
|
||||
expired = false;
|
||||
while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
|
||||
|
||||
if (expired) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto err_pwr_ack;
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
expired = true;
|
||||
}
|
||||
|
||||
if (scpd->bus_prot_mask) {
|
||||
ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
|
||||
scpd->bus_prot_mask);
|
||||
if (ret)
|
||||
goto err_pwr_ack;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pwr_ack:
|
||||
clk_disable_unprepare(scpd->clk);
|
||||
err_clk:
|
||||
dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int scpsys_power_off(struct generic_pm_domain *genpd)
|
||||
{
|
||||
struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
|
||||
struct scp *scp = scpd->scp;
|
||||
unsigned long timeout;
|
||||
bool expired;
|
||||
void __iomem *ctl_addr = scpd->ctl_addr;
|
||||
u32 pdn_ack = scpd->sram_pdn_ack_bits;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (scpd->bus_prot_mask) {
|
||||
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
|
||||
scpd->bus_prot_mask);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
val = readl(ctl_addr);
|
||||
val |= scpd->sram_pdn_bits;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
/* wait until SRAM_PDN_ACK all 1 */
|
||||
timeout = jiffies + HZ;
|
||||
expired = false;
|
||||
while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
|
||||
if (expired) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
expired = true;
|
||||
}
|
||||
|
||||
val |= PWR_ISO_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val &= ~PWR_RST_B_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val |= PWR_CLK_DIS_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val &= ~PWR_ON_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
val &= ~PWR_ON_2ND_BIT;
|
||||
writel(val, ctl_addr);
|
||||
|
||||
/* wait until PWR_ACK = 0 */
|
||||
timeout = jiffies + HZ;
|
||||
expired = false;
|
||||
while (1) {
|
||||
ret = scpsys_domain_is_on(scpd);
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
if (expired) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
expired = true;
|
||||
}
|
||||
|
||||
if (scpd->clk)
|
||||
clk_disable_unprepare(scpd->clk);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init scpsys_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct genpd_onecell_data *pd_data;
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
struct scp *scp;
|
||||
struct clk *clk[MT8173_CLK_MAX];
|
||||
|
||||
scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
|
||||
if (!scp)
|
||||
return -ENOMEM;
|
||||
|
||||
scp->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
scp->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(scp->base))
|
||||
return PTR_ERR(scp->base);
|
||||
|
||||
pd_data = &scp->pd_data;
|
||||
|
||||
pd_data->domains = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL);
|
||||
if (!pd_data->domains)
|
||||
return -ENOMEM;
|
||||
|
||||
clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm");
|
||||
if (IS_ERR(clk[MT8173_CLK_MM]))
|
||||
return PTR_ERR(clk[MT8173_CLK_MM]);
|
||||
|
||||
clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg");
|
||||
if (IS_ERR(clk[MT8173_CLK_MFG]))
|
||||
return PTR_ERR(clk[MT8173_CLK_MFG]);
|
||||
|
||||
scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
||||
"infracfg");
|
||||
if (IS_ERR(scp->infracfg)) {
|
||||
dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
|
||||
PTR_ERR(scp->infracfg));
|
||||
return PTR_ERR(scp->infracfg);
|
||||
}
|
||||
|
||||
pd_data->num_domains = NUM_DOMAINS;
|
||||
|
||||
for (i = 0; i < NUM_DOMAINS; i++) {
|
||||
struct scp_domain *scpd = &scp->domains[i];
|
||||
struct generic_pm_domain *genpd = &scpd->genpd;
|
||||
const struct scp_domain_data *data = &scp_domain_data[i];
|
||||
|
||||
pd_data->domains[i] = genpd;
|
||||
scpd->scp = scp;
|
||||
|
||||
scpd->sta_mask = data->sta_mask;
|
||||
scpd->ctl_addr = scp->base + data->ctl_offs;
|
||||
scpd->sram_pdn_bits = data->sram_pdn_bits;
|
||||
scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
|
||||
scpd->bus_prot_mask = data->bus_prot_mask;
|
||||
if (data->clk_id != MT8173_CLK_NONE)
|
||||
scpd->clk = clk[data->clk_id];
|
||||
|
||||
genpd->name = data->name;
|
||||
genpd->power_off = scpsys_power_off;
|
||||
genpd->power_on = scpsys_power_on;
|
||||
|
||||
/*
|
||||
* Initially turn on all domains to make the domains usable
|
||||
* with !CONFIG_PM and to get the hardware in sync with the
|
||||
* software. The unused domains will be switched off during
|
||||
* late_init time.
|
||||
*/
|
||||
genpd->power_on(genpd);
|
||||
|
||||
pm_genpd_init(genpd, NULL, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are not allowed to fail here since there is no way to unregister
|
||||
* a power domain. Once registered above we have to keep the domains
|
||||
* valid.
|
||||
*/
|
||||
|
||||
ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
|
||||
pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
|
||||
if (ret && IS_ENABLED(CONFIG_PM))
|
||||
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
|
||||
|
||||
ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D],
|
||||
pd_data->domains[MT8173_POWER_DOMAIN_MFG]);
|
||||
if (ret && IS_ENABLED(CONFIG_PM))
|
||||
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
|
||||
|
||||
ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_scpsys_match_tbl[] = {
|
||||
{
|
||||
.compatible = "mediatek,mt8173-scpsys",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_driver scpsys_drv = {
|
||||
.driver = {
|
||||
.name = "mtk-scpsys",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(of_scpsys_match_tbl),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(scpsys_drv, scpsys_probe);
|
15
include/dt-bindings/power/mt8173-power.h
Normal file
15
include/dt-bindings/power/mt8173-power.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
|
||||
#define _DT_BINDINGS_POWER_MT8183_POWER_H
|
||||
|
||||
#define MT8173_POWER_DOMAIN_VDEC 0
|
||||
#define MT8173_POWER_DOMAIN_VENC 1
|
||||
#define MT8173_POWER_DOMAIN_ISP 2
|
||||
#define MT8173_POWER_DOMAIN_MM 3
|
||||
#define MT8173_POWER_DOMAIN_VENC_LT 4
|
||||
#define MT8173_POWER_DOMAIN_AUDIO 5
|
||||
#define MT8173_POWER_DOMAIN_USB 6
|
||||
#define MT8173_POWER_DOMAIN_MFG_ASYNC 7
|
||||
#define MT8173_POWER_DOMAIN_MFG_2D 8
|
||||
#define MT8173_POWER_DOMAIN_MFG 9
|
||||
|
||||
#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */
|
@ -263,7 +263,8 @@ void omap2_clk_legacy_provider_init(int index, void __iomem *mem);
|
||||
int omap3430_dt_clk_init(void);
|
||||
int omap3630_dt_clk_init(void);
|
||||
int am35xx_dt_clk_init(void);
|
||||
int ti81xx_dt_clk_init(void);
|
||||
int dm814x_dt_clk_init(void);
|
||||
int dm816x_dt_clk_init(void);
|
||||
int omap4xxx_dt_clk_init(void);
|
||||
int omap5xxx_dt_clk_init(void);
|
||||
int dra7xx_dt_clk_init(void);
|
||||
|
@ -435,4 +435,12 @@
|
||||
#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1)
|
||||
#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1)
|
||||
|
||||
/* For imx6ul iomux gpr register field define */
|
||||
#define IMX6UL_GPR1_ENET1_CLK_DIR (0x1 << 17)
|
||||
#define IMX6UL_GPR1_ENET2_CLK_DIR (0x1 << 18)
|
||||
#define IMX6UL_GPR1_ENET1_CLK_OUTPUT (0x1 << 17)
|
||||
#define IMX6UL_GPR1_ENET2_CLK_OUTPUT (0x1 << 18)
|
||||
#define IMX6UL_GPR1_ENET_CLK_DIR (0x3 << 17)
|
||||
#define IMX6UL_GPR1_ENET_CLK_OUTPUT (0x3 << 17)
|
||||
|
||||
#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
|
||||
|
26
include/linux/soc/mediatek/infracfg.h
Normal file
26
include/linux/soc/mediatek/infracfg.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __SOC_MEDIATEK_INFRACFG_H
|
||||
#define __SOC_MEDIATEK_INFRACFG_H
|
||||
|
||||
#define MT8173_TOP_AXI_PROT_EN_MCI_M2 BIT(0)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MM_M0 BIT(1)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MM_M1 BIT(2)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MMAPB_S BIT(6)
|
||||
#define MT8173_TOP_AXI_PROT_EN_L2C_M2 BIT(9)
|
||||
#define MT8173_TOP_AXI_PROT_EN_L2SS_SMI BIT(11)
|
||||
#define MT8173_TOP_AXI_PROT_EN_L2SS_ADD BIT(12)
|
||||
#define MT8173_TOP_AXI_PROT_EN_CCI_M2 BIT(13)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MFG_S BIT(14)
|
||||
#define MT8173_TOP_AXI_PROT_EN_PERI_M0 BIT(15)
|
||||
#define MT8173_TOP_AXI_PROT_EN_PERI_M1 BIT(16)
|
||||
#define MT8173_TOP_AXI_PROT_EN_DEBUGSYS BIT(17)
|
||||
#define MT8173_TOP_AXI_PROT_EN_CQ_DMA BIT(18)
|
||||
#define MT8173_TOP_AXI_PROT_EN_GCPU BIT(19)
|
||||
#define MT8173_TOP_AXI_PROT_EN_IOMMU BIT(20)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MFG_M0 BIT(21)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MFG_M1 BIT(22)
|
||||
#define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT BIT(23)
|
||||
|
||||
int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
|
||||
int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
|
||||
|
||||
#endif /* __SOC_MEDIATEK_INFRACFG_H */
|
Loading…
Reference in New Issue
Block a user