mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 15:31:14 +07:00
ARM: SoC platform updates
SoC platform changes (arch/arm/mach-*). This merge window, the bulk is for a few platforms: - Andres Färber adds initial support for the Actions Semi S500 (a.k.a. 'owl') platform, a close relative of the S900 platform he adds for arm64. - in mach-omap2, we remove more legacy code - Rockchips gains support for the RV1108 SoC designed for camera applications. - For Atmel, we gain support for MMU-less SoCs (SAME70/V71/S70/V70) - Minor updates for other platforms, including davinci, s3c64xx, prima2, stm32, broadcom nsp, amlogic, pxa, imx and renesas -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAWVo7+GCrR//JCVInAQKbMA//WeEPEDUt0boJCUfuzXfZ35S5ksBMBGQa NaOJvcW3T//7Tfa88YlBEB7h1w22u1Sv4/CfcistdSPbUwZLyYo6aUz53AwlUnLs bVHnd8+h1xN6qSDjzOPIEQQHg9OVIRBD49moBgJ1BkXzyqR/RI1jPPyyRl5vucSW MYRxhPkplmjFL5+6uvFoSOdd3Z/FLoEYRrkIk4iu+KgKtnNlj4P1FNSdm6Yb29dj yzmXoSpxEzbq0ahGlkjrekEJxTWvW1vOq9d+xTKwTbXoM7pbzXnBRzx4q2Fg9GAT BJseMx+uDEG/+eYrFZA7jX/HgpKB1fAlCGp+dK6GIcJoEM6lFKJRsJrP702KPzg0 PqOMM/htq/4hZ7Waz+Yj3lyVF2C+A6Dn/fXPaHJGdTLj4r0OLgZayhBXFHp1VX2G 9ERx1UCnfxeY91VBUM99qo21ECT7j0C/bZLln8MFjwX8tk3OATkElIAtnsEHxJ5d v4TEkI/AcpMW4lMj/u/hp1PJMCvhlSreWPGx1PRax6va+YB5Ov19DshVgyfoTTq9 kArUJWQdKo4aKqB+feg9NHNC01xSLw5ywKb+oIyYP3jZzMexzRyP5L7EAVOu6Cel iHeIRpo8VjX63gltE+9u4aZ/aEMREGVcgkzuwBTKqbVQ3ismrmGYe54VnFAushJS m+XSB250Vz8= =8F3w -----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 Arnd Bergmann: "SoC platform changes (arch/arm/mach-*). This merge window, the bulk is for a few platforms: - Andres Färber adds initial support for the Actions Semi S500 (aka 'owl') platform, a close relative of the S900 platform he adds for arm64. - in mach-omap2, we remove more legacy code - Rockchips gains support for the RV1108 SoC designed for camera applications. - For Atmel, we gain support for MMU-less SoCs (SAME70/V71/S70/V70) - Minor updates for other platforms, including davinci, s3c64xx, prima2, stm32, broadcom nsp, amlogic, pxa, imx and renesas" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (74 commits) ARM: owl: smp: Drop bogus holding pen ARM: owl: Drop custom machine ARM: owl: smp: Implement SPS power-gating for CPU2 and CPU3 soc: actions: owl-sps: Factor out owl_sps_set_pg() for power-gating soc: actions: Add Owl SPS dt-bindings: power: Add Owl SPS power domains MAINTAINERS: Update Actions Semi section with SPS ARM: owl: Implement CPU enable-method for S500 MAINTAINERS: Add Actions Semi Owl section ARM: Prepare Actions Semi S500 ARM: socfpga: Increase max number of GPIOs ARM: stm32: Introduce MACH_STM32F469 flag ARM: prima2: remove redundant select CPU_V7 ARM: davinci: fix const warnings ARM: shmobile: pm-rmobile: Use GENPD_FLAG_ALWAYS_ON ARM: OMAP4: hwmod_data: add SHAM crypto accelerator ARM: OMAP4: hwmod data: add des ARM: OMAP4: hwmod data: add aes2 ARM: OMAP4: hwmod data: add aes1 ARM: pxa: Delete an error message for a failed memory allocation in pxa3xx_u2d_probe() ...
This commit is contained in:
commit
8ca302e9c6
@ -16,7 +16,7 @@ git branches/tags and email subject always contain this "at91" sub-string.
|
||||
|
||||
AT91 SoCs
|
||||
---------
|
||||
Documentation and detailled datasheet for each product are available on
|
||||
Documentation and detailed datasheet for each product are available on
|
||||
the Atmel website: http://www.atmel.com.
|
||||
|
||||
Flavors:
|
||||
@ -101,6 +101,42 @@ the Atmel website: http://www.atmel.com.
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
|
||||
|
||||
* ARM Cortex-M7 MCUs
|
||||
- sams70 family
|
||||
- sams70j19
|
||||
- sams70j20
|
||||
- sams70j21
|
||||
- sams70n19
|
||||
- sams70n20
|
||||
- sams70n21
|
||||
- sams70q19
|
||||
- sams70q20
|
||||
- sams70q21
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11242-32-bit-Cortex-M7-Microcontroller-SAM-S70Q-SAM-S70N-SAM-S70J_Datasheet.pdf
|
||||
|
||||
- samv70 family
|
||||
- samv70j19
|
||||
- samv70j20
|
||||
- samv70n19
|
||||
- samv70n20
|
||||
- samv70q19
|
||||
- samv70q20
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11297-32-bit-Cortex-M7-Microcontroller-SAM-V70Q-SAM-V70N-SAM-V70J_Datasheet.pdf
|
||||
|
||||
- samv71 family
|
||||
- samv71j19
|
||||
- samv71j20
|
||||
- samv71j21
|
||||
- samv71n19
|
||||
- samv71n20
|
||||
- samv71n21
|
||||
- samv71q19
|
||||
- samv71q20
|
||||
- samv71q21
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-44003-32-bit-Cortex-M7-Microcontroller-SAM-V71Q-SAM-V71N-SAM-V71J_Datasheet.pdf
|
||||
|
||||
Linux kernel information
|
||||
------------------------
|
||||
|
@ -41,6 +41,36 @@ compatible: must be one of:
|
||||
- "atmel,sama5d43"
|
||||
- "atmel,sama5d44"
|
||||
|
||||
* "atmel,samv7" for MCUs using a Cortex-M7, shall be extended with the specific
|
||||
SoC family:
|
||||
o "atmel,sams70" shall be extended with the specific MCU compatible:
|
||||
- "atmel,sams70j19"
|
||||
- "atmel,sams70j20"
|
||||
- "atmel,sams70j21"
|
||||
- "atmel,sams70n19"
|
||||
- "atmel,sams70n20"
|
||||
- "atmel,sams70n21"
|
||||
- "atmel,sams70q19"
|
||||
- "atmel,sams70q20"
|
||||
- "atmel,sams70q21"
|
||||
o "atmel,samv70" shall be extended with the specific MCU compatible:
|
||||
- "atmel,samv70j19"
|
||||
- "atmel,samv70j20"
|
||||
- "atmel,samv70n19"
|
||||
- "atmel,samv70n20"
|
||||
- "atmel,samv70q19"
|
||||
- "atmel,samv70q20"
|
||||
o "atmel,samv71" shall be extended with the specific MCU compatible:
|
||||
- "atmel,samv71j19"
|
||||
- "atmel,samv71j20"
|
||||
- "atmel,samv71j21"
|
||||
- "atmel,samv71n19"
|
||||
- "atmel,samv71n20"
|
||||
- "atmel,samv71n21"
|
||||
- "atmel,samv71q19"
|
||||
- "atmel,samv71q20"
|
||||
- "atmel,samv71q21"
|
||||
|
||||
Chipid required properties:
|
||||
- compatible: Should be "atmel,sama5d2-chipid"
|
||||
- reg : Should contain registers location and length
|
||||
|
17
Documentation/devicetree/bindings/power/actions,owl-sps.txt
Normal file
17
Documentation/devicetree/bindings/power/actions,owl-sps.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Actions Semi Owl Smart Power System (SPS)
|
||||
|
||||
Required properties:
|
||||
- compatible : "actions,s500-sps" for S500
|
||||
- reg : Offset and length of the register set for the device.
|
||||
- #power-domain-cells : Must be 1.
|
||||
See macros in:
|
||||
include/dt-bindings/power/owl-s500-powergate.h for S500
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
sps: power-controller@b01b0100 {
|
||||
compatible = "actions,s500-sps";
|
||||
reg = <0xb01b0100 0x100>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
16
MAINTAINERS
16
MAINTAINERS
@ -1036,6 +1036,22 @@ S: Maintained
|
||||
F: drivers/amba/
|
||||
F: include/linux/amba/bus.h
|
||||
|
||||
ARM/ACTIONS SEMI ARCHITECTURE
|
||||
M: Andreas Färber <afaerber@suse.de>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
N: owl
|
||||
F: arch/arm/mach-actions/
|
||||
F: arch/arm/boot/dts/owl-*
|
||||
F: arch/arm64/boot/dts/actions/
|
||||
F: drivers/clocksource/owl-*
|
||||
F: drivers/soc/actions/
|
||||
F: include/dt-bindings/power/owl-*
|
||||
F: include/linux/soc/actions/
|
||||
F: Documentation/devicetree/bindings/arm/actions.txt
|
||||
F: Documentation/devicetree/bindings/power/actions,owl-sps.txt
|
||||
F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt
|
||||
|
||||
ARM/ADS SPHERE MACHINE SUPPORT
|
||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -712,6 +712,8 @@ config ARCH_VIRT
|
||||
#
|
||||
source "arch/arm/mach-mvebu/Kconfig"
|
||||
|
||||
source "arch/arm/mach-actions/Kconfig"
|
||||
|
||||
source "arch/arm/mach-alpine/Kconfig"
|
||||
|
||||
source "arch/arm/mach-artpec/Kconfig"
|
||||
@ -1462,6 +1464,7 @@ config ARM_PSCI
|
||||
# selected platforms.
|
||||
config ARCH_NR_GPIO
|
||||
int
|
||||
default 2048 if ARCH_SOCFPGA
|
||||
default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \
|
||||
ARCH_ZYNQ
|
||||
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
|
||||
|
@ -145,6 +145,15 @@ choice
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on the USART3 port of sama5d4.
|
||||
|
||||
config DEBUG_AT91_SAMV7_USART1
|
||||
bool "Kernel low-level debugging via SAMV7 USART1"
|
||||
select DEBUG_AT91_UART
|
||||
depends on SOC_SAMV7
|
||||
help
|
||||
Say Y here if you want the debug print routines to direct
|
||||
their output to the USART1 port on SAMV7 based
|
||||
machines.
|
||||
|
||||
config DEBUG_BCM2835
|
||||
bool "Kernel low-level debugging on BCM2835 PL011 UART"
|
||||
depends on ARCH_BCM2835 && ARCH_MULTI_V6
|
||||
@ -751,6 +760,7 @@ choice
|
||||
ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT
|
||||
APQ8064 0x16640000 0xf0040000
|
||||
APQ8084 0xf995e000 0xfa75e000
|
||||
IPQ4019 0x078af000 0xf78af000
|
||||
MSM8X60 0x19c40000 0xf0040000
|
||||
MSM8960 0x16440000 0xf0040000
|
||||
MSM8974 0xf991e000 0xfa71e000
|
||||
@ -776,6 +786,30 @@ choice
|
||||
their output to the standard serial port on the RealView
|
||||
PB1176 platform.
|
||||
|
||||
config DEBUG_RV1108_UART0
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART0"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RV1108_UART1
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART1"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RV1108_UART2
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART2"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RK29_UART0
|
||||
bool "Kernel low-level debugging messages via Rockchip RK29 UART0"
|
||||
depends on ARCH_ROCKCHIP
|
||||
@ -1465,6 +1499,9 @@ config DEBUG_UART_PHYS
|
||||
default 0x10126000 if DEBUG_RK3X_UART1
|
||||
default 0x101f1000 if DEBUG_VERSATILE
|
||||
default 0x101fb000 if DEBUG_NOMADIK_UART
|
||||
default 0x10210000 if DEBUG_RV1108_UART2
|
||||
default 0x10220000 if DEBUG_RV1108_UART1
|
||||
default 0x10230000 if DEBUG_RV1108_UART0
|
||||
default 0x11002000 if DEBUG_MT8127_UART0
|
||||
default 0x11006000 if DEBUG_MT6589_UART0
|
||||
default 0x11009000 if DEBUG_MT8135_UART3
|
||||
@ -1481,6 +1518,7 @@ config DEBUG_UART_PHYS
|
||||
default 0x3f201000 if DEBUG_BCM2836
|
||||
default 0x3e000000 if DEBUG_BCM_KONA_UART
|
||||
default 0x4000e400 if DEBUG_LL_UART_EFM32
|
||||
default 0x40028000 if DEBUG_AT91_SAMV7_USART1
|
||||
default 0x40081000 if DEBUG_LPC18XX_UART0
|
||||
default 0x40090000 if DEBUG_LPC32XX
|
||||
default 0x40100000 if DEBUG_PXA_UART1
|
||||
@ -1563,6 +1601,9 @@ config DEBUG_UART_PHYS
|
||||
|
||||
config DEBUG_UART_VIRT
|
||||
hex "Virtual base address of debug UART"
|
||||
default 0xc881f000 if DEBUG_RV1108_UART2
|
||||
default 0xc8821000 if DEBUG_RV1108_UART1
|
||||
default 0xc8912000 if DEBUG_RV1108_UART0
|
||||
default 0xe0000a00 if DEBUG_NETX_UART
|
||||
default 0xe0010fe0 if ARCH_RPC
|
||||
default 0xf0000be0 if ARCH_EBSA110
|
||||
|
@ -151,6 +151,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
|
||||
|
||||
# Machine directory name. This list is sorted alphanumerically
|
||||
# by CONFIG_* macro name.
|
||||
machine-$(CONFIG_ARCH_ACTIONS) += actions
|
||||
machine-$(CONFIG_ARCH_ALPINE) += alpine
|
||||
machine-$(CONFIG_ARCH_ARTPEC) += artpec
|
||||
machine-$(CONFIG_ARCH_AT91) += at91
|
||||
|
16
arch/arm/mach-actions/Kconfig
Normal file
16
arch/arm/mach-actions/Kconfig
Normal file
@ -0,0 +1,16 @@
|
||||
menuconfig ARCH_ACTIONS
|
||||
bool "Actions Semi SoCs"
|
||||
depends on ARCH_MULTI_V7
|
||||
select ARM_AMBA
|
||||
select ARM_GIC
|
||||
select ARM_GLOBAL_TIMER
|
||||
select CACHE_L2X0
|
||||
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
|
||||
select COMMON_CLK
|
||||
select GENERIC_IRQ_CHIP
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select OWL_PM_DOMAINS_HELPER
|
||||
select OWL_TIMER
|
||||
help
|
||||
This enables support for the Actions Semiconductor S500 SoC family.
|
3
arch/arm/mach-actions/Makefile
Normal file
3
arch/arm/mach-actions/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-${CONFIG_SMP} += platsmp.o headsmp.o
|
||||
|
||||
AFLAGS_headsmp.o := -Wa,-march=armv7-a
|
52
arch/arm/mach-actions/headsmp.S
Normal file
52
arch/arm/mach-actions/headsmp.S
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
ENTRY(owl_v7_invalidate_l1)
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 2, r0, c0, c0, 0
|
||||
mrc p15, 1, r0, c0, c0, 0
|
||||
|
||||
ldr r1, =0x7fff
|
||||
and r2, r1, r0, lsr #13
|
||||
|
||||
ldr r1, =0x3ff
|
||||
|
||||
and r3, r1, r0, lsr #3 @ NumWays - 1
|
||||
add r2, r2, #1 @ NumSets
|
||||
|
||||
and r0, r0, #0x7
|
||||
add r0, r0, #4 @ SetShift
|
||||
|
||||
clz r1, r3 @ WayShift
|
||||
add r4, r3, #1 @ NumWays
|
||||
1: sub r2, r2, #1 @ NumSets--
|
||||
mov r3, r4 @ Temp = NumWays
|
||||
2: subs r3, r3, #1 @ Temp--
|
||||
mov r5, r3, lsl r1
|
||||
mov r6, r2, lsl r0
|
||||
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
|
||||
mcr p15, 0, r5, c7, c6, 2
|
||||
bgt 2b
|
||||
cmp r2, #0
|
||||
bgt 1b
|
||||
dsb
|
||||
isb
|
||||
mov pc, lr
|
||||
ENDPROC(owl_v7_invalidate_l1)
|
||||
|
||||
ENTRY(owl_secondary_startup)
|
||||
bl owl_v7_invalidate_l1
|
||||
b secondary_startup
|
171
arch/arm/mach-actions/platsmp.c
Normal file
171
arch/arm/mach-actions/platsmp.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Actions Semi Leopard
|
||||
*
|
||||
* This file is based on arm realview smp platform.
|
||||
*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/soc/actions/owl-sps.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#define OWL_CPU1_ADDR 0x50
|
||||
#define OWL_CPU1_FLAG 0x5c
|
||||
|
||||
#define OWL_CPUx_FLAG_BOOT 0x55aa
|
||||
|
||||
#define OWL_SPS_PG_CTL_PWR_CPU2 BIT(5)
|
||||
#define OWL_SPS_PG_CTL_PWR_CPU3 BIT(6)
|
||||
#define OWL_SPS_PG_CTL_ACK_CPU2 BIT(21)
|
||||
#define OWL_SPS_PG_CTL_ACK_CPU3 BIT(22)
|
||||
|
||||
static void __iomem *scu_base_addr;
|
||||
static void __iomem *sps_base_addr;
|
||||
static void __iomem *timer_base_addr;
|
||||
static int ncores;
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void owl_secondary_startup(void);
|
||||
|
||||
static int s500_wakeup_secondary(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (cpu > 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* The generic PM domain driver is not available this early. */
|
||||
switch (cpu) {
|
||||
case 2:
|
||||
ret = owl_sps_set_pg(sps_base_addr,
|
||||
OWL_SPS_PG_CTL_PWR_CPU2,
|
||||
OWL_SPS_PG_CTL_ACK_CPU2, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case 3:
|
||||
ret = owl_sps_set_pg(sps_base_addr,
|
||||
OWL_SPS_PG_CTL_PWR_CPU3,
|
||||
OWL_SPS_PG_CTL_ACK_CPU3, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for CPUx to run to WFE instruction */
|
||||
udelay(200);
|
||||
|
||||
writel(virt_to_phys(owl_secondary_startup),
|
||||
timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4);
|
||||
writel(OWL_CPUx_FLAG_BOOT,
|
||||
timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4);
|
||||
|
||||
dsb_sev();
|
||||
mb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s500_smp_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
ret = s500_wakeup_secondary(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
udelay(10);
|
||||
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
smp_send_reschedule(cpu);
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
writel(0, timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4);
|
||||
writel(0, timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4);
|
||||
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init s500_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "actions,s500-timer");
|
||||
if (!node) {
|
||||
pr_err("%s: missing timer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
timer_base_addr = of_iomap(node, 0);
|
||||
if (!timer_base_addr) {
|
||||
pr_err("%s: could not map timer registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "actions,s500-sps");
|
||||
if (!node) {
|
||||
pr_err("%s: missing sps\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sps_base_addr = of_iomap(node, 0);
|
||||
if (!sps_base_addr) {
|
||||
pr_err("%s: could not map sps registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
||||
node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
|
||||
if (!node) {
|
||||
pr_err("%s: missing scu\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
scu_base_addr = of_iomap(node, 0);
|
||||
if (!scu_base_addr) {
|
||||
pr_err("%s: could not map scu registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* While the number of cpus is gathered from dt, also get the
|
||||
* number of cores from the scu to verify this value when
|
||||
* booting the cores.
|
||||
*/
|
||||
ncores = scu_get_core_count(scu_base_addr);
|
||||
pr_debug("%s: ncores %d\n", __func__, ncores);
|
||||
|
||||
scu_enable(scu_base_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct smp_operations s500_smp_ops __initconst = {
|
||||
.smp_prepare_cpus = s500_smp_prepare_cpus,
|
||||
.smp_boot_secondary = s500_smp_boot_secondary,
|
||||
};
|
||||
CPU_METHOD_OF_DECLARE(s500_smp, "actions,s500-smp", &s500_smp_ops);
|
@ -1,6 +1,6 @@
|
||||
menuconfig ARCH_AT91
|
||||
bool "Atmel SoCs"
|
||||
depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7
|
||||
depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
|
||||
select ARM_CPU_SUSPEND if PM
|
||||
select COMMON_CLK_AT91
|
||||
select GPIOLIB
|
||||
@ -8,6 +8,14 @@ menuconfig ARCH_AT91
|
||||
select SOC_BUS
|
||||
|
||||
if ARCH_AT91
|
||||
config SOC_SAMV7
|
||||
bool "SAM Cortex-M7 family" if ARM_SINGLE_ARMV7M
|
||||
select COMMON_CLK_AT91
|
||||
select PINCTRL_AT91
|
||||
help
|
||||
Select this if you are using an SoC from Atmel's SAME7, SAMS7 or SAMV7
|
||||
families.
|
||||
|
||||
config SOC_SAMA5D2
|
||||
bool "SAMA5D2 family"
|
||||
depends on ARCH_MULTI_V7
|
||||
@ -53,6 +61,7 @@ config SOC_AT91RM9200
|
||||
bool "AT91RM9200"
|
||||
depends on ARCH_MULTI_V4T
|
||||
select ATMEL_AIC_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_ST
|
||||
select CPU_ARM920T
|
||||
select HAVE_AT91_USB_CLK
|
||||
@ -66,6 +75,7 @@ config SOC_AT91SAM9
|
||||
bool "AT91SAM9"
|
||||
depends on ARCH_MULTI_V5
|
||||
select ATMEL_AIC_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select CPU_ARM926T
|
||||
select HAVE_AT91_SMD
|
||||
@ -124,9 +134,13 @@ config SOC_SAM_V7
|
||||
config SOC_SAMA5
|
||||
bool
|
||||
select ATMEL_AIC5_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select MEMORY
|
||||
select SOC_SAM_V7
|
||||
select SRAM if PM
|
||||
|
||||
config ATMEL_PM
|
||||
bool
|
||||
|
||||
endif
|
||||
|
@ -6,10 +6,10 @@
|
||||
obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
|
||||
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
|
||||
obj-$(CONFIG_SOC_SAMA5) += sama5.o
|
||||
obj-$(CONFIG_SOC_SAMV7) += samv7.o
|
||||
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o
|
||||
obj-$(CONFIG_PM) += pm_suspend.o
|
||||
obj-$(CONFIG_ATMEL_PM) += pm.o pm_suspend.o
|
||||
|
||||
ifeq ($(CONFIG_CPU_V7),y)
|
||||
AFLAGS_pm_suspend.o := -march=armv7-a
|
||||
|
3
arch/arm/mach-at91/Makefile.boot
Normal file
3
arch/arm/mach-at91/Makefile.boot
Normal file
@ -0,0 +1,3 @@
|
||||
# Empty file waiting for deletion once Makefile.boot isn't needed any more.
|
||||
# Patch waits for application at
|
||||
# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
|
@ -15,10 +15,12 @@
|
||||
extern void __init at91rm9200_pm_init(void);
|
||||
extern void __init at91sam9_pm_init(void);
|
||||
extern void __init sama5_pm_init(void);
|
||||
extern void __init sama5d2_pm_init(void);
|
||||
#else
|
||||
static inline void __init at91rm9200_pm_init(void) { }
|
||||
static inline void __init at91sam9_pm_init(void) { }
|
||||
static inline void __init sama5_pm_init(void) { }
|
||||
static inline void __init sama5d2_pm_init(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* _AT91_GENERIC_H */
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
@ -22,6 +23,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/fncpy.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "pm.h"
|
||||
@ -37,7 +39,17 @@ extern void at91_pinctrl_gpio_suspend(void);
|
||||
extern void at91_pinctrl_gpio_resume(void);
|
||||
#endif
|
||||
|
||||
static struct at91_pm_data pm_data;
|
||||
static const match_table_t pm_modes __initconst = {
|
||||
{ 0, "standby" },
|
||||
{ AT91_PM_SLOW_CLOCK, "ulp0" },
|
||||
{ AT91_PM_BACKUP, "backup" },
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
static struct at91_pm_data pm_data = {
|
||||
.standby_mode = 0,
|
||||
.suspend_mode = AT91_PM_SLOW_CLOCK,
|
||||
};
|
||||
|
||||
#define at91_ramc_read(id, field) \
|
||||
__raw_readl(pm_data.ramc[id] + field)
|
||||
@ -58,15 +70,33 @@ static int at91_pm_valid_state(suspend_state_t state)
|
||||
}
|
||||
}
|
||||
|
||||
static int canary = 0xA5A5A5A5;
|
||||
|
||||
static suspend_state_t target_state;
|
||||
static struct at91_pm_bu {
|
||||
int suspended;
|
||||
unsigned long reserved;
|
||||
phys_addr_t canary;
|
||||
phys_addr_t resume;
|
||||
} *pm_bu;
|
||||
|
||||
/*
|
||||
* Called after processes are frozen, but before we shutdown devices.
|
||||
*/
|
||||
static int at91_pm_begin(suspend_state_t state)
|
||||
{
|
||||
target_state = state;
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
pm_data.mode = pm_data.suspend_mode;
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_STANDBY:
|
||||
pm_data.mode = pm_data.standby_mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
pm_data.mode = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -115,7 +145,7 @@ static int at91_pm_verify_clocks(void)
|
||||
*/
|
||||
int at91_suspend_entering_slow_clock(void)
|
||||
{
|
||||
return (target_state == PM_SUSPEND_MEM);
|
||||
return (pm_data.mode >= AT91_PM_SLOW_CLOCK);
|
||||
}
|
||||
EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
|
||||
|
||||
@ -123,50 +153,65 @@ static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
|
||||
extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
|
||||
extern u32 at91_pm_suspend_in_sram_sz;
|
||||
|
||||
static void at91_pm_suspend(suspend_state_t state)
|
||||
static int at91_suspend_finish(unsigned long val)
|
||||
{
|
||||
pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0;
|
||||
|
||||
flush_cache_all();
|
||||
outer_disable();
|
||||
|
||||
at91_suspend_sram_fn(&pm_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at91_pm_suspend(suspend_state_t state)
|
||||
{
|
||||
if (pm_data.mode == AT91_PM_BACKUP) {
|
||||
pm_bu->suspended = 1;
|
||||
|
||||
cpu_suspend(0, at91_suspend_finish);
|
||||
|
||||
/* The SRAM is lost between suspend cycles */
|
||||
at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
|
||||
&at91_pm_suspend_in_sram,
|
||||
at91_pm_suspend_in_sram_sz);
|
||||
} else {
|
||||
at91_suspend_finish(0);
|
||||
}
|
||||
|
||||
outer_resume();
|
||||
}
|
||||
|
||||
/*
|
||||
* STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup'
|
||||
* event sources; and reduces DRAM power. But otherwise it's identical to
|
||||
* PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
|
||||
*
|
||||
* AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must
|
||||
* suspend more deeply, the master clock switches to the clk32k and turns off
|
||||
* the main oscillator
|
||||
*
|
||||
* AT91_PM_BACKUP turns off the whole SoC after placing the DDR in self refresh
|
||||
*/
|
||||
static int at91_pm_enter(suspend_state_t state)
|
||||
{
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
at91_pinctrl_gpio_suspend();
|
||||
#endif
|
||||
|
||||
switch (state) {
|
||||
/*
|
||||
* Suspend-to-RAM is like STANDBY plus slow clock mode, so
|
||||
* drivers must suspend more deeply, the master clock switches
|
||||
* to the clk32k and turns off the main oscillator
|
||||
*/
|
||||
case PM_SUSPEND_MEM:
|
||||
case PM_SUSPEND_STANDBY:
|
||||
/*
|
||||
* Ensure that clocks are in a valid state.
|
||||
*/
|
||||
if (!at91_pm_verify_clocks())
|
||||
if ((pm_data.mode >= AT91_PM_SLOW_CLOCK) &&
|
||||
!at91_pm_verify_clocks())
|
||||
goto error;
|
||||
|
||||
at91_pm_suspend(state);
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
* STANDBY mode has *all* drivers suspended; ignores irqs not
|
||||
* marked as 'wakeup' event sources; and reduces DRAM power.
|
||||
* But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
|
||||
* nothing fancy done with main or cpu clocks.
|
||||
*/
|
||||
case PM_SUSPEND_STANDBY:
|
||||
at91_pm_suspend(state);
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_ON:
|
||||
cpu_do_idle();
|
||||
break;
|
||||
@ -177,8 +222,6 @@ static int at91_pm_enter(suspend_state_t state)
|
||||
}
|
||||
|
||||
error:
|
||||
target_state = PM_SUSPEND_ON;
|
||||
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
at91_pinctrl_gpio_resume();
|
||||
#endif
|
||||
@ -190,7 +233,6 @@ static int at91_pm_enter(suspend_state_t state)
|
||||
*/
|
||||
static void at91_pm_end(void)
|
||||
{
|
||||
target_state = PM_SUSPEND_ON;
|
||||
}
|
||||
|
||||
|
||||
@ -436,6 +478,79 @@ static void __init at91_pm_sram_init(void)
|
||||
&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
|
||||
}
|
||||
|
||||
static void __init at91_pm_backup_init(void)
|
||||
{
|
||||
struct gen_pool *sram_pool;
|
||||
struct device_node *np;
|
||||
struct platform_device *pdev = NULL;
|
||||
|
||||
if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
|
||||
(pm_data.suspend_mode != AT91_PM_BACKUP))
|
||||
return;
|
||||
|
||||
pm_bu = NULL;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
|
||||
if (!np) {
|
||||
pr_warn("%s: failed to find shdwc!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pm_data.shdwc = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
|
||||
if (!np) {
|
||||
pr_warn("%s: failed to find sfrbu!\n", __func__);
|
||||
goto sfrbu_fail;
|
||||
}
|
||||
|
||||
pm_data.sfrbu = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
pm_bu = NULL;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
|
||||
if (!np)
|
||||
goto securam_fail;
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!pdev) {
|
||||
pr_warn("%s: failed to find securam device!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
sram_pool = gen_pool_get(&pdev->dev, NULL);
|
||||
if (!sram_pool) {
|
||||
pr_warn("%s: securam pool unavailable!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
|
||||
if (!pm_bu) {
|
||||
pr_warn("%s: unable to alloc securam!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
pm_bu->suspended = 0;
|
||||
pm_bu->canary = virt_to_phys(&canary);
|
||||
pm_bu->resume = virt_to_phys(cpu_resume);
|
||||
|
||||
return;
|
||||
|
||||
sfrbu_fail:
|
||||
iounmap(pm_data.shdwc);
|
||||
pm_data.shdwc = NULL;
|
||||
securam_fail:
|
||||
iounmap(pm_data.sfrbu);
|
||||
pm_data.sfrbu = NULL;
|
||||
|
||||
if (pm_data.standby_mode == AT91_PM_BACKUP)
|
||||
pm_data.standby_mode = AT91_PM_SLOW_CLOCK;
|
||||
if (pm_data.suspend_mode == AT91_PM_BACKUP)
|
||||
pm_data.suspend_mode = AT91_PM_SLOW_CLOCK;
|
||||
}
|
||||
|
||||
struct pmc_info {
|
||||
unsigned long uhp_udp_mask;
|
||||
};
|
||||
@ -481,10 +596,14 @@ static void __init at91_pm_init(void (*pm_idle)(void))
|
||||
|
||||
at91_pm_sram_init();
|
||||
|
||||
if (at91_suspend_sram_fn)
|
||||
if (at91_suspend_sram_fn) {
|
||||
suspend_set_ops(&at91_pm_ops);
|
||||
else
|
||||
pr_info("AT91: PM: standby: %s, suspend: %s\n",
|
||||
pm_modes[pm_data.standby_mode].pattern,
|
||||
pm_modes[pm_data.suspend_mode].pattern);
|
||||
} else {
|
||||
pr_info("AT91: PM not supported, due to no SRAM allocated\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __init at91rm9200_pm_init(void)
|
||||
@ -510,3 +629,34 @@ void __init sama5_pm_init(void)
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(NULL);
|
||||
}
|
||||
|
||||
void __init sama5d2_pm_init(void)
|
||||
{
|
||||
at91_pm_backup_init();
|
||||
sama5_pm_init();
|
||||
}
|
||||
|
||||
static int __init at91_pm_modes_select(char *str)
|
||||
{
|
||||
char *s;
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
int standby, suspend;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
s = strsep(&str, ",");
|
||||
standby = match_token(s, pm_modes, args);
|
||||
if (standby < 0)
|
||||
return 0;
|
||||
|
||||
suspend = match_token(str, pm_modes, args);
|
||||
if (suspend < 0)
|
||||
return 0;
|
||||
|
||||
pm_data.standby_mode = standby;
|
||||
pm_data.suspend_mode = suspend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("atmel.pm_modes", at91_pm_modes_select);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define AT91_MEMCTRL_DDRSDR 2
|
||||
|
||||
#define AT91_PM_SLOW_CLOCK 0x01
|
||||
#define AT91_PM_BACKUP 0x02
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct at91_pm_data {
|
||||
@ -30,6 +31,10 @@ struct at91_pm_data {
|
||||
unsigned long uhp_udp_mask;
|
||||
unsigned int memctrl;
|
||||
unsigned int mode;
|
||||
void __iomem *shdwc;
|
||||
void __iomem *sfrbu;
|
||||
unsigned int standby_mode;
|
||||
unsigned int suspend_mode;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -9,5 +9,8 @@ int main(void)
|
||||
DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1]));
|
||||
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
|
||||
DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode));
|
||||
DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc));
|
||||
DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -97,15 +97,61 @@ ENTRY(at91_pm_suspend_in_sram)
|
||||
str tmp1, .memtype
|
||||
ldr tmp1, [r0, #PM_DATA_MODE]
|
||||
str tmp1, .pm_mode
|
||||
/* Both ldrne below are here to preload their address in the TLB */
|
||||
ldr tmp1, [r0, #PM_DATA_SHDWC]
|
||||
str tmp1, .shdwc
|
||||
cmp tmp1, #0
|
||||
ldrne tmp2, [tmp1, #0]
|
||||
ldr tmp1, [r0, #PM_DATA_SFRBU]
|
||||
str tmp1, .sfr
|
||||
cmp tmp1, #0
|
||||
ldrne tmp2, [tmp1, #0x10]
|
||||
|
||||
/* Active the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_ACTIVE
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
ldr r0, .pm_mode
|
||||
tst r0, #AT91_PM_SLOW_CLOCK
|
||||
beq skip_disable_main_clock
|
||||
cmp r0, #AT91_PM_SLOW_CLOCK
|
||||
beq slow_clock
|
||||
cmp r0, #AT91_PM_BACKUP
|
||||
beq backup_mode
|
||||
|
||||
/* Wait for interrupt */
|
||||
ldr pmc, .pmc_base
|
||||
at91_cpu_idle
|
||||
b exit_suspend
|
||||
|
||||
slow_clock:
|
||||
bl at91_slowck_mode
|
||||
b exit_suspend
|
||||
backup_mode:
|
||||
bl at91_backup_mode
|
||||
b exit_suspend
|
||||
|
||||
exit_suspend:
|
||||
/* Exit the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_EXIT
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
/* Restore registers, and return */
|
||||
ldmfd sp!, {r4 - r12, pc}
|
||||
ENDPROC(at91_pm_suspend_in_sram)
|
||||
|
||||
ENTRY(at91_backup_mode)
|
||||
/*BUMEN*/
|
||||
ldr r0, .sfr
|
||||
mov tmp1, #0x1
|
||||
str tmp1, [r0, #0x10]
|
||||
|
||||
/* Shutdown */
|
||||
ldr r0, .shdwc
|
||||
mov tmp1, #0xA5000000
|
||||
add tmp1, tmp1, #0x1
|
||||
str tmp1, [r0, #0]
|
||||
ENDPROC(at91_backup_mode)
|
||||
|
||||
ENTRY(at91_slowck_mode)
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Save Master clock setting */
|
||||
@ -134,18 +180,9 @@ ENTRY(at91_pm_suspend_in_sram)
|
||||
orr tmp1, tmp1, #AT91_PMC_KEY
|
||||
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
|
||||
skip_disable_main_clock:
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Wait for interrupt */
|
||||
at91_cpu_idle
|
||||
|
||||
ldr r0, .pm_mode
|
||||
tst r0, #AT91_PM_SLOW_CLOCK
|
||||
beq skip_enable_main_clock
|
||||
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Turn on the main oscillator */
|
||||
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
orr tmp1, tmp1, #AT91_PMC_MOSCEN
|
||||
@ -174,14 +211,8 @@ skip_disable_main_clock:
|
||||
|
||||
wait_mckrdy
|
||||
|
||||
skip_enable_main_clock:
|
||||
/* Exit the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_EXIT
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
/* Restore registers, and return */
|
||||
ldmfd sp!, {r4 - r12, pc}
|
||||
ENDPROC(at91_pm_suspend_in_sram)
|
||||
mov pc, lr
|
||||
ENDPROC(at91_slowck_mode)
|
||||
|
||||
/*
|
||||
* void at91_sramc_self_refresh(unsigned int is_active)
|
||||
@ -314,6 +345,10 @@ ENDPROC(at91_sramc_self_refresh)
|
||||
.word 0
|
||||
.sramc1_base:
|
||||
.word 0
|
||||
.shdwc:
|
||||
.word 0
|
||||
.sfr:
|
||||
.word 0
|
||||
.memtype:
|
||||
.word 0
|
||||
.pm_mode:
|
||||
|
@ -34,7 +34,6 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5")
|
||||
MACHINE_END
|
||||
|
||||
static const char *const sama5_alt_dt_board_compat[] __initconst = {
|
||||
"atmel,sama5d2",
|
||||
"atmel,sama5d4",
|
||||
NULL
|
||||
};
|
||||
@ -45,3 +44,21 @@ DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5")
|
||||
.dt_compat = sama5_alt_dt_board_compat,
|
||||
.l2c_aux_mask = ~0UL,
|
||||
MACHINE_END
|
||||
|
||||
static void __init sama5d2_init(void)
|
||||
{
|
||||
of_platform_default_populate(NULL, NULL, NULL);
|
||||
sama5d2_pm_init();
|
||||
}
|
||||
|
||||
static const char *const sama5d2_compat[] __initconst = {
|
||||
"atmel,sama5d2",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(sama5d2, "Atmel SAMA5")
|
||||
/* Maintainer: Atmel */
|
||||
.init_machine = sama5d2_init,
|
||||
.dt_compat = sama5d2_compat,
|
||||
.l2c_aux_mask = ~0UL,
|
||||
MACHINE_END
|
||||
|
25
arch/arm/mach-at91/samv7.c
Normal file
25
arch/arm/mach-at91/samv7.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Setup code for SAMv7x
|
||||
*
|
||||
* Copyright (C) 2013 Atmel,
|
||||
* 2016 Andras Szemzo <szemzo.andras@gmail.com>
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include "generic.h"
|
||||
|
||||
static const char *const samv7_dt_board_compat[] __initconst = {
|
||||
"atmel,samv7",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(samv7_dt, "Atmel SAMV7")
|
||||
.dt_compat = samv7_dt_board_compat,
|
||||
MACHINE_END
|
@ -44,6 +44,8 @@ config ARCH_BCM_NSP
|
||||
select ARM_ERRATA_775420
|
||||
select ARM_ERRATA_764369 if SMP
|
||||
select HAVE_SMP
|
||||
select THERMAL
|
||||
select THERMAL_OF
|
||||
help
|
||||
Support for Broadcom Northstar Plus SoC.
|
||||
Broadcom Northstar Plus family of SoCs are used for switching control
|
||||
|
@ -641,7 +641,7 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vpif_input dm6467_ch0_inputs[] = {
|
||||
static struct vpif_input dm6467_ch0_inputs[] = {
|
||||
{
|
||||
.input = {
|
||||
.index = 0,
|
||||
@ -656,7 +656,7 @@ static const struct vpif_input dm6467_ch0_inputs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vpif_input dm6467_ch1_inputs[] = {
|
||||
static struct vpif_input dm6467_ch1_inputs[] = {
|
||||
{
|
||||
.input = {
|
||||
.index = 0,
|
||||
|
@ -789,15 +789,35 @@ int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
|
||||
|
||||
static struct resource da8xx_rproc_resources[] = {
|
||||
{ /* DSP boot address */
|
||||
.name = "host1cfg",
|
||||
.start = DA8XX_SYSCFG0_BASE + DA8XX_HOST1CFG_REG,
|
||||
.end = DA8XX_SYSCFG0_BASE + DA8XX_HOST1CFG_REG + 3,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{ /* DSP interrupt registers */
|
||||
.name = "chipsig",
|
||||
.start = DA8XX_SYSCFG0_BASE + DA8XX_CHIPSIG_REG,
|
||||
.end = DA8XX_SYSCFG0_BASE + DA8XX_CHIPSIG_REG + 7,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{ /* DSP L2 RAM */
|
||||
.name = "l2sram",
|
||||
.start = DA8XX_DSP_L2_RAM_BASE,
|
||||
.end = DA8XX_DSP_L2_RAM_BASE + SZ_256K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{ /* DSP L1P RAM */
|
||||
.name = "l1pram",
|
||||
.start = DA8XX_DSP_L1P_RAM_BASE,
|
||||
.end = DA8XX_DSP_L1P_RAM_BASE + SZ_32K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{ /* DSP L1D RAM */
|
||||
.name = "l1dram",
|
||||
.start = DA8XX_DSP_L1D_RAM_BASE,
|
||||
.end = DA8XX_DSP_L1D_RAM_BASE + SZ_32K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{ /* dsp irq */
|
||||
.start = IRQ_DA8XX_CHIPINT0,
|
||||
.end = IRQ_DA8XX_CHIPINT0,
|
||||
@ -814,6 +834,8 @@ static struct platform_device da8xx_dsp = {
|
||||
.resource = da8xx_rproc_resources,
|
||||
};
|
||||
|
||||
static bool rproc_mem_inited __initdata;
|
||||
|
||||
#if IS_ENABLED(CONFIG_DA8XX_REMOTEPROC)
|
||||
|
||||
static phys_addr_t rproc_base __initdata;
|
||||
@ -852,6 +874,8 @@ void __init da8xx_rproc_reserve_cma(void)
|
||||
ret = dma_declare_contiguous(&da8xx_dsp.dev, rproc_size, rproc_base, 0);
|
||||
if (ret)
|
||||
pr_err("%s: dma_declare_contiguous failed %d\n", __func__, ret);
|
||||
else
|
||||
rproc_mem_inited = true;
|
||||
}
|
||||
|
||||
#else
|
||||
@ -866,6 +890,12 @@ int __init da8xx_register_rproc(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!rproc_mem_inited) {
|
||||
pr_warn("%s: memory not reserved for DSP, not registering DSP device\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = platform_device_register(&da8xx_dsp);
|
||||
if (ret)
|
||||
pr_err("%s: can't register DSP device: %d\n", __func__, ret);
|
||||
|
@ -75,6 +75,11 @@ extern unsigned int da850_max_speed;
|
||||
#define DA8XX_VPIF_BASE 0x01e17000
|
||||
#define DA8XX_GPIO_BASE 0x01e26000
|
||||
#define DA8XX_PSC1_BASE 0x01e27000
|
||||
|
||||
#define DA8XX_DSP_L2_RAM_BASE 0x11800000
|
||||
#define DA8XX_DSP_L1P_RAM_BASE (DA8XX_DSP_L2_RAM_BASE + 0x600000)
|
||||
#define DA8XX_DSP_L1D_RAM_BASE (DA8XX_DSP_L2_RAM_BASE + 0x700000)
|
||||
|
||||
#define DA8XX_AEMIF_CS2_BASE 0x60000000
|
||||
#define DA8XX_AEMIF_CS3_BASE 0x62000000
|
||||
#define DA8XX_AEMIF_CTL_BASE 0x68000000
|
||||
|
@ -33,7 +33,7 @@ static struct tvp514x_platform_data tvp5146_pdata = {
|
||||
|
||||
#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
|
||||
|
||||
static const struct vpif_input da850_ch0_inputs[] = {
|
||||
static struct vpif_input da850_ch0_inputs[] = {
|
||||
{
|
||||
.input = {
|
||||
.index = 0,
|
||||
@ -48,7 +48,7 @@ static const struct vpif_input da850_ch0_inputs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vpif_input da850_ch1_inputs[] = {
|
||||
static struct vpif_input da850_ch1_inputs[] = {
|
||||
{
|
||||
.input = {
|
||||
.index = 0,
|
||||
|
@ -536,6 +536,7 @@ config SOC_IMX7D
|
||||
select HAVE_IMX_ANATOP
|
||||
select HAVE_IMX_MMDC
|
||||
select HAVE_IMX_SRC
|
||||
select IMX_GPCV2
|
||||
help
|
||||
This enables support for Freescale i.MX7 Dual processor.
|
||||
|
||||
|
@ -131,6 +131,9 @@ struct device * __init imx_soc_device_init(void)
|
||||
case MXC_CPU_IMX6UL:
|
||||
soc_id = "i.MX6UL";
|
||||
break;
|
||||
case MXC_CPU_IMX6ULL:
|
||||
soc_id = "i.MX6ULL";
|
||||
break;
|
||||
case MXC_CPU_IMX7D:
|
||||
soc_id = "i.MX7D";
|
||||
break;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define MXC_CPU_IMX6SX 0x62
|
||||
#define MXC_CPU_IMX6Q 0x63
|
||||
#define MXC_CPU_IMX6UL 0x64
|
||||
#define MXC_CPU_IMX6ULL 0x65
|
||||
#define MXC_CPU_IMX7D 0x72
|
||||
|
||||
#define IMX_DDR_TYPE_LPDDR2 1
|
||||
@ -73,6 +74,11 @@ static inline bool cpu_is_imx6ul(void)
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6UL;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6ull(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6ULL;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6q(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6Q;
|
||||
|
@ -295,7 +295,8 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
|
||||
val &= ~BM_CLPCR_SBYOS;
|
||||
if (cpu_is_imx6sl())
|
||||
val |= BM_CLPCR_BYPASS_PMIC_READY;
|
||||
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
|
||||
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
|
||||
cpu_is_imx6ull())
|
||||
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
|
||||
else
|
||||
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
|
||||
@ -312,7 +313,8 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
|
||||
val |= BM_CLPCR_SBYOS;
|
||||
if (cpu_is_imx6sl() || cpu_is_imx6sx())
|
||||
val |= BM_CLPCR_BYPASS_PMIC_READY;
|
||||
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
|
||||
if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
|
||||
cpu_is_imx6ull())
|
||||
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
|
||||
else
|
||||
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
|
||||
|
@ -21,6 +21,7 @@ config MACH_MESON8
|
||||
bool "Amlogic Meson8 SoCs support"
|
||||
default ARCH_MESON
|
||||
select MESON6_TIMER
|
||||
select COMMON_CLK_MESON8B
|
||||
|
||||
config MACH_MESON8B
|
||||
bool "Amlogic Meson8b SoCs support"
|
||||
|
@ -240,7 +240,6 @@ static void omap1_show_dma_caps(void)
|
||||
w |= 1 << 3;
|
||||
dma_write(w, GSCR, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned configure_dma_errata(void)
|
||||
@ -339,10 +338,8 @@ static int __init omap1_system_dma_init(void)
|
||||
goto exit_iounmap;
|
||||
}
|
||||
|
||||
d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d) {
|
||||
dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
|
||||
__func__, pdev->name);
|
||||
ret = -ENOMEM;
|
||||
goto exit_iounmap;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Contains first level initialization routines which internally
|
||||
* generates timer device information and registers with linux
|
||||
* device model. It also has low level function to chnage the timer
|
||||
* device model. It also has a low level function to change the timer
|
||||
* input clock source.
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
@ -134,8 +134,6 @@ static int __init omap1_dm_timer_init(void)
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
|
||||
__func__);
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pdata;
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o
|
||||
|
||||
# OPP table initialization
|
||||
ifeq ($(CONFIG_PM_OPP),y)
|
||||
obj-y += opp.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
|
||||
endif
|
||||
@ -220,9 +219,6 @@ obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o
|
||||
obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o
|
||||
obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o
|
||||
|
||||
# EMU peripherals
|
||||
obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
|
||||
|
||||
# OMAP2420 MSDI controller integration support ("MMC")
|
||||
obj-$(CONFIG_SOC_OMAP2420) += msdi.o
|
||||
|
||||
|
@ -53,14 +53,12 @@ static u32 board_caps;
|
||||
|
||||
static void board_check_revision(void)
|
||||
{
|
||||
if (of_have_populated_dt()) {
|
||||
if (of_machine_is_compatible("nokia,n800"))
|
||||
board_caps = NOKIA_N800;
|
||||
else if (of_machine_is_compatible("nokia,n810"))
|
||||
board_caps = NOKIA_N810;
|
||||
else if (of_machine_is_compatible("nokia,n810-wimax"))
|
||||
board_caps = NOKIA_N810_WIMAX;
|
||||
}
|
||||
if (of_machine_is_compatible("nokia,n800"))
|
||||
board_caps = NOKIA_N800;
|
||||
else if (of_machine_is_compatible("nokia,n810"))
|
||||
board_caps = NOKIA_N810;
|
||||
else if (of_machine_is_compatible("nokia,n810-wimax"))
|
||||
board_caps = NOKIA_N810_WIMAX;
|
||||
|
||||
if (!board_caps)
|
||||
pr_err("Unknown board\n");
|
||||
|
@ -1224,6 +1224,14 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 clkdm_xlate_address(struct clockdomain *clkdm)
|
||||
{
|
||||
if (arch_clkdm->clkdm_xlate_address)
|
||||
return arch_clkdm->clkdm_xlate_address(clkdm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
|
||||
* @clkdm: struct clockdomain *
|
||||
|
@ -175,6 +175,7 @@ struct clkdm_ops {
|
||||
void (*clkdm_deny_idle)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_enable)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
|
||||
u32 (*clkdm_xlate_address)(struct clockdomain *clkdm);
|
||||
};
|
||||
|
||||
int clkdm_register_platform_funcs(struct clkdm_ops *co);
|
||||
@ -213,6 +214,7 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
|
||||
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
|
||||
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
|
||||
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
|
||||
u32 clkdm_xlate_address(struct clockdomain *clkdm);
|
||||
|
||||
extern void __init omap242x_clockdomains_init(void);
|
||||
extern void __init omap243x_clockdomains_init(void);
|
||||
|
@ -24,8 +24,11 @@
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
#include <linux/clk/ti.h>
|
||||
extern void __iomem *cm_base;
|
||||
extern void __iomem *cm2_base;
|
||||
|
||||
#include "prcm-common.h"
|
||||
|
||||
extern struct omap_domain_base cm_base;
|
||||
extern struct omap_domain_base cm2_base;
|
||||
extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
|
||||
# endif
|
||||
|
||||
|
@ -52,12 +52,12 @@
|
||||
|
||||
static inline u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
|
||||
{
|
||||
return readl_relaxed(cm_base + module + idx);
|
||||
return readl_relaxed(cm_base.va + module + idx);
|
||||
}
|
||||
|
||||
static inline void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||
{
|
||||
writel_relaxed(val, cm_base + module + idx);
|
||||
writel_relaxed(val, cm_base.va + module + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in a CM module. Caller must lock */
|
||||
|
@ -50,13 +50,13 @@
|
||||
/* Read a register in a CM instance */
|
||||
static inline u32 am33xx_cm_read_reg(u16 inst, u16 idx)
|
||||
{
|
||||
return readl_relaxed(cm_base + inst + idx);
|
||||
return readl_relaxed(cm_base.va + inst + idx);
|
||||
}
|
||||
|
||||
/* Write into a register in a CM */
|
||||
static inline void am33xx_cm_write_reg(u32 val, u16 inst, u16 idx)
|
||||
{
|
||||
writel_relaxed(val, cm_base + inst + idx);
|
||||
writel_relaxed(val, cm_base.va + inst + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in CM */
|
||||
|
@ -669,7 +669,8 @@ static struct cm_ll_data omap3xxx_cm_ll_data = {
|
||||
|
||||
int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
|
||||
{
|
||||
omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base + OMAP3430_IVA2_MOD);
|
||||
omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base.va +
|
||||
OMAP3430_IVA2_MOD);
|
||||
return cm_register(&omap3xxx_cm_ll_data);
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,10 @@ static struct cm_ll_data null_cm_ll_data;
|
||||
static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
|
||||
|
||||
/* cm_base: base virtual address of the CM IP block */
|
||||
void __iomem *cm_base;
|
||||
struct omap_domain_base cm_base;
|
||||
|
||||
/* cm2_base: base virtual address of the CM2 IP block (OMAP44xx only) */
|
||||
void __iomem *cm2_base;
|
||||
struct omap_domain_base cm2_base;
|
||||
|
||||
#define CM_NO_CLOCKS 0x1
|
||||
#define CM_SINGLE_INSTANCE 0x2
|
||||
@ -49,8 +49,8 @@ void __iomem *cm2_base;
|
||||
*/
|
||||
void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2)
|
||||
{
|
||||
cm_base = cm;
|
||||
cm2_base = cm2;
|
||||
cm_base.va = cm;
|
||||
cm2_base.va = cm2;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,27 +315,34 @@ int __init omap2_cm_base_init(void)
|
||||
struct device_node *np;
|
||||
const struct of_device_id *match;
|
||||
struct omap_prcm_init_data *data;
|
||||
void __iomem *mem;
|
||||
struct resource res;
|
||||
int ret;
|
||||
struct omap_domain_base *mem = NULL;
|
||||
|
||||
for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
|
||||
data = (struct omap_prcm_init_data *)match->data;
|
||||
|
||||
mem = of_iomap(np, 0);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data->index == TI_CLKM_CM)
|
||||
cm_base = mem + data->offset;
|
||||
mem = &cm_base;
|
||||
|
||||
if (data->index == TI_CLKM_CM2)
|
||||
cm2_base = mem + data->offset;
|
||||
mem = &cm2_base;
|
||||
|
||||
data->mem = mem;
|
||||
data->mem = ioremap(res.start, resource_size(&res));
|
||||
|
||||
if (mem) {
|
||||
mem->pa = res.start + data->offset;
|
||||
mem->va = data->mem + data->offset;
|
||||
}
|
||||
|
||||
data->np = np;
|
||||
|
||||
if (data->init && (data->flags & CM_SINGLE_INSTANCE ||
|
||||
(cm_base && cm2_base)))
|
||||
(cm_base.va && cm2_base.va)))
|
||||
data->init(data);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
||||
#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
|
||||
#define CLKCTRL_IDLEST_DISABLED 0x3
|
||||
|
||||
static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
|
||||
static struct omap_domain_base _cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
|
||||
|
||||
/**
|
||||
* omap_cm_base_init - Populates the cm partitions
|
||||
@ -65,10 +65,11 @@ static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
|
||||
*/
|
||||
static void omap_cm_base_init(void)
|
||||
{
|
||||
_cm_bases[OMAP4430_PRM_PARTITION] = prm_base;
|
||||
_cm_bases[OMAP4430_CM1_PARTITION] = cm_base;
|
||||
_cm_bases[OMAP4430_CM2_PARTITION] = cm2_base;
|
||||
_cm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
|
||||
memcpy(&_cm_bases[OMAP4430_PRM_PARTITION], &prm_base, sizeof(prm_base));
|
||||
memcpy(&_cm_bases[OMAP4430_CM1_PARTITION], &cm_base, sizeof(cm_base));
|
||||
memcpy(&_cm_bases[OMAP4430_CM2_PARTITION], &cm2_base, sizeof(cm2_base));
|
||||
memcpy(&_cm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base,
|
||||
sizeof(prcm_mpu_base));
|
||||
}
|
||||
|
||||
/* Private functions */
|
||||
@ -116,8 +117,8 @@ static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
|
||||
{
|
||||
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
|
||||
part == OMAP4430_INVALID_PRCM_PARTITION ||
|
||||
!_cm_bases[part]);
|
||||
return readl_relaxed(_cm_bases[part] + inst + idx);
|
||||
!_cm_bases[part].va);
|
||||
return readl_relaxed(_cm_bases[part].va + inst + idx);
|
||||
}
|
||||
|
||||
/* Write into a register in a CM instance */
|
||||
@ -125,8 +126,8 @@ static void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
|
||||
{
|
||||
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
|
||||
part == OMAP4430_INVALID_PRCM_PARTITION ||
|
||||
!_cm_bases[part]);
|
||||
writel_relaxed(val, _cm_bases[part] + inst + idx);
|
||||
!_cm_bases[part].va);
|
||||
writel_relaxed(val, _cm_bases[part].va + inst + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in CM1. Caller must lock */
|
||||
@ -475,6 +476,14 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 omap4_clkdm_xlate_address(struct clockdomain *clkdm)
|
||||
{
|
||||
u32 addr = _cm_bases[clkdm->prcm_partition].pa + clkdm->cm_inst +
|
||||
clkdm->clkdm_offs;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct clkdm_ops omap4_clkdm_operations = {
|
||||
.clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
|
||||
.clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
|
||||
@ -490,6 +499,7 @@ struct clkdm_ops omap4_clkdm_operations = {
|
||||
.clkdm_deny_idle = omap4_clkdm_deny_idle,
|
||||
.clkdm_clk_enable = omap4_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap4_clkdm_clk_disable,
|
||||
.clkdm_xlate_address = omap4_clkdm_xlate_address,
|
||||
};
|
||||
|
||||
struct clkdm_ops am43xx_clkdm_operations = {
|
||||
@ -499,6 +509,7 @@ struct clkdm_ops am43xx_clkdm_operations = {
|
||||
.clkdm_deny_idle = omap4_clkdm_deny_idle,
|
||||
.clkdm_clk_enable = omap4_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap4_clkdm_clk_disable,
|
||||
.clkdm_xlate_address = omap4_clkdm_xlate_address,
|
||||
};
|
||||
|
||||
static struct cm_ll_data omap4xxx_cm_ll_data = {
|
||||
|
@ -36,130 +36,6 @@
|
||||
#define L3_MODULES_MAX_LEN 12
|
||||
#define L3_MODULES 3
|
||||
|
||||
static int __init omap3_l3_init(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
char oh_name[L3_MODULES_MAX_LEN];
|
||||
|
||||
/*
|
||||
* To avoid code running on other OMAPs in
|
||||
* multi-omap builds
|
||||
*/
|
||||
if (!(cpu_is_omap34xx()) || of_have_populated_dt())
|
||||
return -ENODEV;
|
||||
|
||||
snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
|
||||
|
||||
oh = omap_hwmod_lookup(oh_name);
|
||||
|
||||
if (!oh)
|
||||
pr_err("could not look up %s\n", oh_name);
|
||||
|
||||
pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0);
|
||||
|
||||
WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
|
||||
|
||||
return PTR_ERR_OR_ZERO(pdev);
|
||||
}
|
||||
omap_postcore_initcall(omap3_l3_init);
|
||||
|
||||
static inline void omap_init_sti(void) {}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SPI_OMAP24XX)
|
||||
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
static int __init omap_mcspi_init(struct omap_hwmod *oh, void *unused)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
char *name = "omap2_mcspi";
|
||||
struct omap2_mcspi_platform_config *pdata;
|
||||
static int spi_num;
|
||||
struct omap2_mcspi_dev_attr *mcspi_attrib = oh->dev_attr;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
pr_err("Memory allocation for McSPI device failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata->num_cs = mcspi_attrib->num_chipselect;
|
||||
switch (oh->class->rev) {
|
||||
case OMAP2_MCSPI_REV:
|
||||
case OMAP3_MCSPI_REV:
|
||||
pdata->regs_offset = 0;
|
||||
break;
|
||||
case OMAP4_MCSPI_REV:
|
||||
pdata->regs_offset = OMAP4_MCSPI_REG_OFFSET;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid McSPI Revision value\n");
|
||||
kfree(pdata);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spi_num++;
|
||||
pdev = omap_device_build(name, spi_num, oh, pdata, sizeof(*pdata));
|
||||
WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
|
||||
name, oh->name);
|
||||
kfree(pdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_init_mcspi(void)
|
||||
{
|
||||
omap_hwmod_for_each_by_class("mcspi", omap_mcspi_init, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void omap_init_mcspi(void) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* omap_init_rng - bind the RNG hwmod to the RNG omap_device
|
||||
*
|
||||
* Bind the RNG hwmod to the RNG omap_device. No return value.
|
||||
*/
|
||||
static void __init omap_init_rng(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
|
||||
oh = omap_hwmod_lookup("rng");
|
||||
if (!oh)
|
||||
return;
|
||||
|
||||
pdev = omap_device_build("omap_rng", -1, oh, NULL, 0);
|
||||
WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n");
|
||||
}
|
||||
|
||||
static void __init omap_init_sham(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
|
||||
oh = omap_hwmod_lookup("sham");
|
||||
if (!oh)
|
||||
return;
|
||||
|
||||
pdev = omap_device_build("omap-sham", -1, oh, NULL, 0);
|
||||
WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
|
||||
}
|
||||
|
||||
static void __init omap_init_aes(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
|
||||
oh = omap_hwmod_lookup("aes");
|
||||
if (!oh)
|
||||
return;
|
||||
|
||||
pdev = omap_device_build("omap-aes", -1, oh, NULL, 0);
|
||||
WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if IS_ENABLED(CONFIG_VIDEO_OMAP2_VOUT)
|
||||
@ -185,54 +61,3 @@ int __init omap_init_vout(void)
|
||||
#else
|
||||
int __init omap_init_vout(void) { return 0; }
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int __init omap2_init_devices(void)
|
||||
{
|
||||
/* Enable dummy states for those platforms without pinctrl support */
|
||||
if (!of_have_populated_dt())
|
||||
pinctrl_provide_dummies();
|
||||
|
||||
/* If dtb is there, the devices will be created dynamically */
|
||||
if (!of_have_populated_dt()) {
|
||||
/*
|
||||
* please keep these calls, and their implementations above,
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
omap_init_mcspi();
|
||||
omap_init_sham();
|
||||
omap_init_aes();
|
||||
omap_init_rng();
|
||||
}
|
||||
omap_init_sti();
|
||||
|
||||
return 0;
|
||||
}
|
||||
omap_arch_initcall(omap2_init_devices);
|
||||
|
||||
static int __init omap_gpmc_init(void)
|
||||
{
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
char *oh_name = "gpmc";
|
||||
|
||||
/*
|
||||
* if the board boots up with a populated DT, do not
|
||||
* manually add the device from this initcall
|
||||
*/
|
||||
if (of_have_populated_dt())
|
||||
return -ENODEV;
|
||||
|
||||
oh = omap_hwmod_lookup(oh_name);
|
||||
if (!oh) {
|
||||
pr_err("Could not look up %s\n", oh_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdev = omap_device_build("omap-gpmc", -1, oh, NULL, 0);
|
||||
WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
|
||||
|
||||
return PTR_ERR_OR_ZERO(pdev);
|
||||
}
|
||||
omap_postcore_initcall(omap_gpmc_init);
|
||||
|
@ -153,7 +153,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
|
||||
|
||||
hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL);
|
||||
if (!hc_name) {
|
||||
pr_err("Cannot allocate memory for controller slot name\n");
|
||||
kfree(hc_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -315,10 +314,8 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
|
||||
int res;
|
||||
|
||||
mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL);
|
||||
if (!mmc_data) {
|
||||
pr_err("Cannot allocate memory for mmc device!\n");
|
||||
if (!mmc_data)
|
||||
return;
|
||||
}
|
||||
|
||||
res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
|
||||
if (res < 0)
|
||||
|
@ -493,67 +493,39 @@ void __init omap3_init_early(void)
|
||||
omap2_set_globals_tap(OMAP343X_CLASS, OMAP2_L4_IO_ADDRESS(0x4830A000));
|
||||
omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
|
||||
OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE));
|
||||
/* XXX: remove these once OMAP3 is DT only */
|
||||
if (!of_have_populated_dt()) {
|
||||
omap2_set_globals_control(
|
||||
OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE));
|
||||
omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE));
|
||||
omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
|
||||
NULL);
|
||||
}
|
||||
omap2_control_base_init();
|
||||
omap3xxx_check_revision();
|
||||
omap3xxx_check_features();
|
||||
omap2_prcm_base_init();
|
||||
/* XXX: remove these once OMAP3 is DT only */
|
||||
if (!of_have_populated_dt()) {
|
||||
omap3xxx_prm_init(NULL);
|
||||
omap3xxx_cm_init(NULL);
|
||||
}
|
||||
omap3xxx_voltagedomains_init();
|
||||
omap3xxx_powerdomains_init();
|
||||
omap3xxx_clockdomains_init();
|
||||
omap3xxx_hwmod_init();
|
||||
omap_hwmod_init_postsetup();
|
||||
if (!of_have_populated_dt()) {
|
||||
omap3_control_legacy_iomap_init();
|
||||
if (soc_is_am35xx())
|
||||
omap_clk_soc_init = am35xx_clk_legacy_init;
|
||||
else if (cpu_is_omap3630())
|
||||
omap_clk_soc_init = omap36xx_clk_legacy_init;
|
||||
else if (omap_rev() == OMAP3430_REV_ES1_0)
|
||||
omap_clk_soc_init = omap3430es1_clk_legacy_init;
|
||||
else
|
||||
omap_clk_soc_init = omap3430_clk_legacy_init;
|
||||
}
|
||||
}
|
||||
|
||||
void __init omap3430_init_early(void)
|
||||
{
|
||||
omap3_init_early();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = omap3430_dt_clk_init;
|
||||
omap_clk_soc_init = omap3430_dt_clk_init;
|
||||
}
|
||||
|
||||
void __init omap35xx_init_early(void)
|
||||
{
|
||||
omap3_init_early();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = omap3430_dt_clk_init;
|
||||
omap_clk_soc_init = omap3430_dt_clk_init;
|
||||
}
|
||||
|
||||
void __init omap3630_init_early(void)
|
||||
{
|
||||
omap3_init_early();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = omap3630_dt_clk_init;
|
||||
omap_clk_soc_init = omap3630_dt_clk_init;
|
||||
}
|
||||
|
||||
void __init am35xx_init_early(void)
|
||||
{
|
||||
omap3_init_early();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = am35xx_dt_clk_init;
|
||||
omap_clk_soc_init = am35xx_dt_clk_init;
|
||||
}
|
||||
|
||||
void __init omap3_init_late(void)
|
||||
@ -628,8 +600,7 @@ void __init ti816x_init_early(void)
|
||||
ti816x_clockdomains_init();
|
||||
dm816x_hwmod_init();
|
||||
omap_hwmod_init_postsetup();
|
||||
if (of_have_populated_dt())
|
||||
omap_clk_soc_init = dm816x_dt_clk_init;
|
||||
omap_clk_soc_init = dm816x_dt_clk_init;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -785,21 +756,19 @@ int __init omap_clk_init(void)
|
||||
|
||||
omap2_clk_setup_ll_ops();
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
ret = omap_control_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = omap_control_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = omap_prcm_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = omap_prcm_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
of_clk_init(NULL);
|
||||
of_clk_init(NULL);
|
||||
|
||||
ti_dt_clk_init_retry_clks();
|
||||
ti_dt_clk_init_retry_clks();
|
||||
|
||||
ti_dt_clockdomains_setup();
|
||||
}
|
||||
ti_dt_clockdomains_setup();
|
||||
|
||||
ret = omap_clk_soc_init();
|
||||
|
||||
|
@ -53,73 +53,3 @@ void __init omap3_mcbsp_init_pdata_callback(
|
||||
|
||||
pdata->force_ick_on = omap3_mcbsp_force_ick_on;
|
||||
}
|
||||
|
||||
static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
|
||||
{
|
||||
int id, count = 1;
|
||||
char *name = "omap-mcbsp";
|
||||
struct omap_hwmod *oh_device[2];
|
||||
struct omap_mcbsp_platform_data *pdata = NULL;
|
||||
struct platform_device *pdev;
|
||||
|
||||
sscanf(oh->name, "mcbsp%d", &id);
|
||||
|
||||
pdata = kzalloc(sizeof(struct omap_mcbsp_platform_data), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
pr_err("%s: No memory for mcbsp\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata->reg_step = 4;
|
||||
if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
|
||||
pdata->reg_size = 2;
|
||||
} else {
|
||||
pdata->reg_size = 4;
|
||||
pdata->has_ccr = true;
|
||||
}
|
||||
|
||||
if (oh->class->rev == MCBSP_CONFIG_TYPE2) {
|
||||
/* The FIFO has 128 locations */
|
||||
pdata->buffer_size = 0x80;
|
||||
} else if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
|
||||
if (id == 2)
|
||||
/* The FIFO has 1024 + 256 locations */
|
||||
pdata->buffer_size = 0x500;
|
||||
else
|
||||
/* The FIFO has 128 locations */
|
||||
pdata->buffer_size = 0x80;
|
||||
} else if (oh->class->rev == MCBSP_CONFIG_TYPE4) {
|
||||
/* The FIFO has 128 locations for all instances */
|
||||
pdata->buffer_size = 0x80;
|
||||
}
|
||||
|
||||
if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
|
||||
pdata->has_wakeup = true;
|
||||
|
||||
oh_device[0] = oh;
|
||||
|
||||
if (oh->dev_attr) {
|
||||
oh_device[1] = omap_hwmod_lookup((
|
||||
(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
|
||||
pdata->force_ick_on = omap3_mcbsp_force_ick_on;
|
||||
count++;
|
||||
}
|
||||
pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
|
||||
sizeof(*pdata));
|
||||
kfree(pdata);
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
|
||||
name, oh->name);
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init omap2_mcbsp_init(void)
|
||||
{
|
||||
if (!of_have_populated_dt())
|
||||
omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
omap_arch_initcall(omap2_mcbsp_init);
|
||||
|
@ -58,6 +58,17 @@ static unsigned int irq_banks = DEFAULT_NR_REG_BANKS;
|
||||
static unsigned int max_irqs = DEFAULT_IRQS;
|
||||
static unsigned int omap_secure_apis;
|
||||
|
||||
#ifdef CONFIG_CPU_PM
|
||||
static unsigned int wakeupgen_context[MAX_NR_REG_BANKS];
|
||||
#endif
|
||||
|
||||
struct omap_wakeupgen_ops {
|
||||
void (*save_context)(void);
|
||||
void (*restore_context)(void);
|
||||
};
|
||||
|
||||
static struct omap_wakeupgen_ops *wakeupgen_ops;
|
||||
|
||||
/*
|
||||
* Static helper functions.
|
||||
*/
|
||||
@ -264,6 +275,16 @@ static inline void omap5_irq_save_context(void)
|
||||
|
||||
}
|
||||
|
||||
static inline void am43xx_irq_save_context(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < irq_banks; i++) {
|
||||
wakeupgen_context[i] = wakeupgen_readl(i, 0);
|
||||
wakeupgen_writel(0, i, CPU0_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save WakeupGen interrupt context in SAR BANK3. Restore is done by
|
||||
* ROM code. WakeupGen IP is integrated along with GIC to manage the
|
||||
@ -280,11 +301,8 @@ static void irq_save_context(void)
|
||||
|
||||
if (!sar_base)
|
||||
sar_base = omap4_get_sar_ram_base();
|
||||
|
||||
if (soc_is_omap54xx())
|
||||
omap5_irq_save_context();
|
||||
else
|
||||
omap4_irq_save_context();
|
||||
if (wakeupgen_ops && wakeupgen_ops->save_context)
|
||||
wakeupgen_ops->save_context();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -306,6 +324,20 @@ static void irq_sar_clear(void)
|
||||
writel_relaxed(val, sar_base + offset);
|
||||
}
|
||||
|
||||
static void am43xx_irq_restore_context(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < irq_banks; i++)
|
||||
wakeupgen_writel(wakeupgen_context[i], i, CPU0_ID);
|
||||
}
|
||||
|
||||
static void irq_restore_context(void)
|
||||
{
|
||||
if (wakeupgen_ops && wakeupgen_ops->restore_context)
|
||||
wakeupgen_ops->restore_context();
|
||||
}
|
||||
|
||||
/*
|
||||
* Save GIC and Wakeupgen interrupt context using secure API
|
||||
* for HS/EMU devices.
|
||||
@ -319,6 +351,26 @@ static void irq_save_secure_context(void)
|
||||
if (ret != API_HAL_RET_VALUE_OK)
|
||||
pr_err("GIC and Wakeupgen context save failed\n");
|
||||
}
|
||||
|
||||
/* Define ops for context save and restore for each SoC */
|
||||
static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {
|
||||
.save_context = omap4_irq_save_context,
|
||||
.restore_context = irq_sar_clear,
|
||||
};
|
||||
|
||||
static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {
|
||||
.save_context = omap5_irq_save_context,
|
||||
.restore_context = irq_sar_clear,
|
||||
};
|
||||
|
||||
static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {
|
||||
.save_context = am43xx_irq_save_context,
|
||||
.restore_context = am43xx_irq_restore_context,
|
||||
};
|
||||
#else
|
||||
static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {};
|
||||
static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {};
|
||||
static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
@ -359,7 +411,7 @@ static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
break;
|
||||
case CPU_CLUSTER_PM_EXIT:
|
||||
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
|
||||
irq_sar_clear();
|
||||
irq_restore_context();
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -494,9 +546,13 @@ static int __init wakeupgen_init(struct device_node *node,
|
||||
irq_banks = OMAP4_NR_BANKS;
|
||||
max_irqs = OMAP4_NR_IRQS;
|
||||
omap_secure_apis = 1;
|
||||
wakeupgen_ops = &omap4_wakeupgen_ops;
|
||||
} else if (soc_is_omap54xx()) {
|
||||
wakeupgen_ops = &omap5_wakeupgen_ops;
|
||||
} else if (soc_is_am43xx()) {
|
||||
irq_banks = AM43XX_NR_REG_BANKS;
|
||||
max_irqs = AM43XX_IRQS;
|
||||
wakeupgen_ops = &am43xx_wakeupgen_ops;
|
||||
}
|
||||
|
||||
domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
|
||||
|
@ -65,7 +65,7 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
|
||||
|
||||
r = clk_get_sys(NULL, clk_name);
|
||||
|
||||
if (IS_ERR(r) && of_have_populated_dt()) {
|
||||
if (IS_ERR(r)) {
|
||||
struct of_phandle_args clkspec;
|
||||
|
||||
clkspec.np = of_find_node_by_name(NULL, clk_name);
|
||||
@ -953,9 +953,6 @@ static int __init omap_device_late_init(void)
|
||||
{
|
||||
bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
|
||||
|
||||
WARN(!of_have_populated_dt(),
|
||||
"legacy booting deprecated, please update to boot with .dts\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
omap_late_initcall_sync(omap_device_late_init);
|
||||
|
@ -141,6 +141,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/system_misc.h>
|
||||
|
||||
@ -181,6 +182,24 @@
|
||||
*/
|
||||
#define MOD_CLK_MAX_NAME_LEN 32
|
||||
|
||||
/**
|
||||
* struct clkctrl_provider - clkctrl provider mapping data
|
||||
* @addr: base address for the provider
|
||||
* @offset: base offset for the provider
|
||||
* @clkdm: base clockdomain for provider
|
||||
* @node: device node associated with the provider
|
||||
* @link: list link
|
||||
*/
|
||||
struct clkctrl_provider {
|
||||
u32 addr;
|
||||
u16 offset;
|
||||
struct clockdomain *clkdm;
|
||||
struct device_node *node;
|
||||
struct list_head link;
|
||||
};
|
||||
|
||||
static LIST_HEAD(clkctrl_providers);
|
||||
|
||||
/**
|
||||
* struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
|
||||
* @enable_module: function to enable a module (via MODULEMODE)
|
||||
@ -204,6 +223,8 @@ struct omap_hwmod_soc_ops {
|
||||
void (*update_context_lost)(struct omap_hwmod *oh);
|
||||
int (*get_context_lost)(struct omap_hwmod *oh);
|
||||
int (*disable_direct_prcm)(struct omap_hwmod *oh);
|
||||
u32 (*xlate_clkctrl)(struct omap_hwmod *oh,
|
||||
struct clkctrl_provider *provider);
|
||||
};
|
||||
|
||||
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
|
||||
@ -690,6 +711,103 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
||||
return clkdm_del_sleepdep(clkdm, init_clkdm);
|
||||
}
|
||||
|
||||
static const struct of_device_id ti_clkctrl_match_table[] __initconst = {
|
||||
{ .compatible = "ti,clkctrl" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int _match_clkdm(struct clockdomain *clkdm, void *user)
|
||||
{
|
||||
struct clkctrl_provider *provider = user;
|
||||
|
||||
if (clkdm_xlate_address(clkdm) == provider->addr) {
|
||||
pr_debug("%s: Matched clkdm %s for addr %x (%s)\n", __func__,
|
||||
clkdm->name, provider->addr,
|
||||
provider->node->parent->name);
|
||||
provider->clkdm = clkdm;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _setup_clkctrl_provider(struct device_node *np)
|
||||
{
|
||||
const __be32 *addrp;
|
||||
struct clkctrl_provider *provider;
|
||||
|
||||
provider = memblock_virt_alloc(sizeof(*provider), 0);
|
||||
if (!provider)
|
||||
return -ENOMEM;
|
||||
|
||||
addrp = of_get_address(np, 0, NULL, NULL);
|
||||
provider->addr = (u32)of_translate_address(np, addrp);
|
||||
provider->offset = provider->addr & 0xff;
|
||||
provider->addr &= ~0xff;
|
||||
provider->node = np;
|
||||
|
||||
clkdm_for_each(_match_clkdm, provider);
|
||||
|
||||
if (!provider->clkdm) {
|
||||
pr_err("%s: nothing matched for node %s (%x)\n",
|
||||
__func__, np->parent->name, provider->addr);
|
||||
memblock_free_early(__pa(provider), sizeof(*provider));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_add(&provider->link, &clkctrl_providers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_clkctrl_providers(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int ret = 0;
|
||||
|
||||
for_each_matching_node(np, ti_clkctrl_match_table) {
|
||||
ret = _setup_clkctrl_provider(np);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 _omap4_xlate_clkctrl(struct omap_hwmod *oh,
|
||||
struct clkctrl_provider *provider)
|
||||
{
|
||||
return oh->prcm.omap4.clkctrl_offs -
|
||||
provider->offset - provider->clkdm->clkdm_offs;
|
||||
}
|
||||
|
||||
static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh)
|
||||
{
|
||||
struct clkctrl_provider *provider;
|
||||
struct clk *clk;
|
||||
|
||||
if (!soc_ops.xlate_clkctrl)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(provider, &clkctrl_providers, link) {
|
||||
if (provider->clkdm == oh->clkdm) {
|
||||
struct of_phandle_args clkspec;
|
||||
|
||||
clkspec.np = provider->node;
|
||||
clkspec.args_count = 2;
|
||||
clkspec.args[0] = soc_ops.xlate_clkctrl(oh, provider);
|
||||
clkspec.args[1] = 0;
|
||||
|
||||
clk = of_clk_get_from_provider(&clkspec);
|
||||
|
||||
return clk;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _init_main_clk - get a struct clk * for the the hwmod's main functional clk
|
||||
* @oh: struct omap_hwmod *
|
||||
@ -701,22 +819,16 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
|
||||
static int _init_main_clk(struct omap_hwmod *oh)
|
||||
{
|
||||
int ret = 0;
|
||||
char name[MOD_CLK_MAX_NAME_LEN];
|
||||
struct clk *clk;
|
||||
static const char modck[] = "_mod_ck";
|
||||
struct clk *clk = NULL;
|
||||
|
||||
if (strlen(oh->name) >= MOD_CLK_MAX_NAME_LEN - strlen(modck))
|
||||
pr_warn("%s: warning: cropping name for %s\n", __func__,
|
||||
oh->name);
|
||||
clk = _lookup_clkctrl_clk(oh);
|
||||
|
||||
strlcpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - strlen(modck));
|
||||
strlcat(name, modck, MOD_CLK_MAX_NAME_LEN);
|
||||
|
||||
clk = clk_get(NULL, name);
|
||||
if (!IS_ERR(clk)) {
|
||||
if (!IS_ERR_OR_NULL(clk)) {
|
||||
pr_debug("%s: mapped main_clk %s for %s\n", __func__,
|
||||
__clk_get_name(clk), oh->name);
|
||||
oh->main_clk = __clk_get_name(clk);
|
||||
oh->_clk = clk;
|
||||
soc_ops.disable_direct_prcm(oh);
|
||||
oh->main_clk = kstrdup(name, GFP_KERNEL);
|
||||
} else {
|
||||
if (!oh->main_clk)
|
||||
return 0;
|
||||
@ -1482,13 +1594,13 @@ static int _init_clkdm(struct omap_hwmod *oh)
|
||||
* _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as
|
||||
* well the clockdomain.
|
||||
* @oh: struct omap_hwmod *
|
||||
* @data: not used; pass NULL
|
||||
* @np: device_node mapped to this hwmod
|
||||
*
|
||||
* Called by omap_hwmod_setup_*() (after omap2_clk_init()).
|
||||
* Resolves all clock names embedded in the hwmod. Returns 0 on
|
||||
* success, or a negative error code on failure.
|
||||
*/
|
||||
static int _init_clocks(struct omap_hwmod *oh, void *data)
|
||||
static int _init_clocks(struct omap_hwmod *oh, struct device_node *np)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -2334,24 +2446,21 @@ static int __init _init(struct omap_hwmod *oh, void *data)
|
||||
{
|
||||
int r, index;
|
||||
struct device_node *np = NULL;
|
||||
struct device_node *bus;
|
||||
|
||||
if (oh->_state != _HWMOD_STATE_REGISTERED)
|
||||
return 0;
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
struct device_node *bus;
|
||||
bus = of_find_node_by_name(NULL, "ocp");
|
||||
if (!bus)
|
||||
return -ENODEV;
|
||||
|
||||
bus = of_find_node_by_name(NULL, "ocp");
|
||||
if (!bus)
|
||||
return -ENODEV;
|
||||
|
||||
r = of_dev_hwmod_lookup(bus, oh, &index, &np);
|
||||
if (r)
|
||||
pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
|
||||
else if (np && index)
|
||||
pr_warn("omap_hwmod: %s using broken dt data from %s\n",
|
||||
oh->name, np->name);
|
||||
}
|
||||
r = of_dev_hwmod_lookup(bus, oh, &index, &np);
|
||||
if (r)
|
||||
pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
|
||||
else if (np && index)
|
||||
pr_warn("omap_hwmod: %s using broken dt data from %s\n",
|
||||
oh->name, np->name);
|
||||
|
||||
r = _init_mpu_rt_base(oh, NULL, index, np);
|
||||
if (r < 0) {
|
||||
@ -2360,7 +2469,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = _init_clocks(oh, NULL);
|
||||
r = _init_clocks(oh, np);
|
||||
if (r < 0) {
|
||||
WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name);
|
||||
return -EINVAL;
|
||||
@ -3722,6 +3831,7 @@ void __init omap_hwmod_init(void)
|
||||
soc_ops.update_context_lost = _omap4_update_context_lost;
|
||||
soc_ops.get_context_lost = _omap4_get_context_lost;
|
||||
soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
|
||||
soc_ops.xlate_clkctrl = _omap4_xlate_clkctrl;
|
||||
} else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() ||
|
||||
soc_is_am43xx()) {
|
||||
soc_ops.enable_module = _omap4_enable_module;
|
||||
@ -3736,6 +3846,8 @@ void __init omap_hwmod_init(void)
|
||||
WARN(1, "omap_hwmod: unknown SoC type\n");
|
||||
}
|
||||
|
||||
_init_clkctrl_providers();
|
||||
|
||||
inited = true;
|
||||
}
|
||||
|
||||
|
@ -3204,8 +3204,7 @@ int __init omap3xxx_hwmod_init(void)
|
||||
* If DT information is missing, enable them only for GP devices.
|
||||
*/
|
||||
|
||||
if (of_have_populated_dt())
|
||||
bus = of_find_node_by_name(NULL, "ocp");
|
||||
bus = of_find_node_by_name(NULL, "ocp");
|
||||
|
||||
if (h_sham && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "sham")) {
|
||||
r = omap_hwmod_register_links(h_sham);
|
||||
|
@ -775,6 +775,7 @@ static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
|
||||
|
||||
static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = {
|
||||
{ .role = "sys_clk", .clk = "dss_sys_clk" },
|
||||
{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
|
||||
};
|
||||
|
||||
static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
|
||||
@ -785,7 +786,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
|
||||
* HDMI audio requires to use no-idle mode. Hence,
|
||||
* set idle mode by software.
|
||||
*/
|
||||
.flags = HWMOD_SWSUP_SIDLE,
|
||||
.flags = HWMOD_SWSUP_SIDLE | HWMOD_OPT_CLKS_NEEDED,
|
||||
.mpu_irqs = omap44xx_dss_hdmi_irqs,
|
||||
.xlate_irq = omap4_xlate_irq,
|
||||
.sdma_reqs = omap44xx_dss_hdmi_sdma_reqs,
|
||||
@ -858,11 +859,16 @@ static struct omap_hwmod_class omap44xx_venc_hwmod_class = {
|
||||
};
|
||||
|
||||
/* dss_venc */
|
||||
static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
|
||||
{ .role = "tv_clk", .clk = "dss_tv_clk" },
|
||||
};
|
||||
|
||||
static struct omap_hwmod omap44xx_dss_venc_hwmod = {
|
||||
.name = "dss_venc",
|
||||
.class = &omap44xx_venc_hwmod_class,
|
||||
.clkdm_name = "l3_dss_clkdm",
|
||||
.main_clk = "dss_tv_clk",
|
||||
.flags = HWMOD_OPT_CLKS_NEEDED,
|
||||
.prcm = {
|
||||
.omap4 = {
|
||||
.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
|
||||
@ -870,6 +876,35 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
|
||||
},
|
||||
},
|
||||
.parent_hwmod = &omap44xx_dss_hwmod,
|
||||
.opt_clks = dss_venc_opt_clks,
|
||||
.opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks),
|
||||
};
|
||||
|
||||
/* sha0 HIB2 (the 'P' (public) device) */
|
||||
static struct omap_hwmod_class_sysconfig omap44xx_sha0_sysc = {
|
||||
.rev_offs = 0x100,
|
||||
.sysc_offs = 0x110,
|
||||
.syss_offs = 0x114,
|
||||
.sysc_flags = SYSS_HAS_RESET_STATUS,
|
||||
};
|
||||
|
||||
static struct omap_hwmod_class omap44xx_sha0_hwmod_class = {
|
||||
.name = "sham",
|
||||
.sysc = &omap44xx_sha0_sysc,
|
||||
};
|
||||
|
||||
struct omap_hwmod omap44xx_sha0_hwmod = {
|
||||
.name = "sham",
|
||||
.class = &omap44xx_sha0_hwmod_class,
|
||||
.clkdm_name = "l4_secure_clkdm",
|
||||
.main_clk = "l3_div_ck",
|
||||
.prcm = {
|
||||
.omap4 = {
|
||||
.clkctrl_offs = OMAP4_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET,
|
||||
.context_offs = OMAP4_RM_L4SEC_SHA2MD51_CONTEXT_OFFSET,
|
||||
.modulemode = MODULEMODE_SWCTRL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
@ -952,6 +987,103 @@ static struct omap_hwmod omap44xx_emif2_hwmod = {
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
Crypto modules AES0/1 belong to:
|
||||
PD_L4_PER power domain
|
||||
CD_L4_SEC clock domain
|
||||
On the L3, the AES modules are mapped to
|
||||
L3_CLK2: Peripherals and multimedia sub clock domain
|
||||
*/
|
||||
static struct omap_hwmod_class_sysconfig omap44xx_aes_sysc = {
|
||||
.rev_offs = 0x80,
|
||||
.sysc_offs = 0x84,
|
||||
.syss_offs = 0x88,
|
||||
.sysc_flags = SYSS_HAS_RESET_STATUS,
|
||||
};
|
||||
|
||||
static struct omap_hwmod_class omap44xx_aes_hwmod_class = {
|
||||
.name = "aes",
|
||||
.sysc = &omap44xx_aes_sysc,
|
||||
};
|
||||
|
||||
static struct omap_hwmod omap44xx_aes1_hwmod = {
|
||||
.name = "aes1",
|
||||
.class = &omap44xx_aes_hwmod_class,
|
||||
.clkdm_name = "l4_secure_clkdm",
|
||||
.main_clk = "l3_div_ck",
|
||||
.prcm = {
|
||||
.omap4 = {
|
||||
.context_offs = OMAP4_RM_L4SEC_AES1_CONTEXT_OFFSET,
|
||||
.clkctrl_offs = OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET,
|
||||
.modulemode = MODULEMODE_SWCTRL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__aes1 = {
|
||||
.master = &omap44xx_l4_per_hwmod,
|
||||
.slave = &omap44xx_aes1_hwmod,
|
||||
.clk = "l3_div_ck",
|
||||
.user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
};
|
||||
|
||||
static struct omap_hwmod omap44xx_aes2_hwmod = {
|
||||
.name = "aes2",
|
||||
.class = &omap44xx_aes_hwmod_class,
|
||||
.clkdm_name = "l4_secure_clkdm",
|
||||
.main_clk = "l3_div_ck",
|
||||
.prcm = {
|
||||
.omap4 = {
|
||||
.context_offs = OMAP4_RM_L4SEC_AES2_CONTEXT_OFFSET,
|
||||
.clkctrl_offs = OMAP4_CM_L4SEC_AES2_CLKCTRL_OFFSET,
|
||||
.modulemode = MODULEMODE_SWCTRL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__aes2 = {
|
||||
.master = &omap44xx_l4_per_hwmod,
|
||||
.slave = &omap44xx_aes2_hwmod,
|
||||
.clk = "l3_div_ck",
|
||||
.user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
};
|
||||
|
||||
/*
|
||||
* 'des' class for DES3DES module
|
||||
*/
|
||||
static struct omap_hwmod_class_sysconfig omap44xx_des_sysc = {
|
||||
.rev_offs = 0x30,
|
||||
.sysc_offs = 0x34,
|
||||
.syss_offs = 0x38,
|
||||
.sysc_flags = SYSS_HAS_RESET_STATUS,
|
||||
};
|
||||
|
||||
static struct omap_hwmod_class omap44xx_des_hwmod_class = {
|
||||
.name = "des",
|
||||
.sysc = &omap44xx_des_sysc,
|
||||
};
|
||||
|
||||
static struct omap_hwmod omap44xx_des_hwmod = {
|
||||
.name = "des",
|
||||
.class = &omap44xx_des_hwmod_class,
|
||||
.clkdm_name = "l4_secure_clkdm",
|
||||
.main_clk = "l3_div_ck",
|
||||
.prcm = {
|
||||
.omap4 = {
|
||||
.context_offs = OMAP4_RM_L4SEC_DES3DES_CONTEXT_OFFSET,
|
||||
.clkctrl_offs = OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET,
|
||||
.modulemode = MODULEMODE_SWCTRL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct omap_hwmod_ocp_if omap44xx_l3_main_2__des = {
|
||||
.master = &omap44xx_l3_main_2_hwmod,
|
||||
.slave = &omap44xx_des_hwmod,
|
||||
.clk = "l3_div_ck",
|
||||
.user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
};
|
||||
|
||||
/*
|
||||
* 'fdif' class
|
||||
* face detection hw accelerator module
|
||||
@ -3882,6 +4014,14 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
|
||||
.user = OCP_USER_MPU,
|
||||
};
|
||||
|
||||
/* l3_main_2 -> sham */
|
||||
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sha0 = {
|
||||
.master = &omap44xx_l3_main_2_hwmod,
|
||||
.slave = &omap44xx_sha0_hwmod,
|
||||
.clk = "l3_div_ck",
|
||||
.user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
};
|
||||
|
||||
/* l4_per -> elm */
|
||||
static struct omap_hwmod_ocp_if omap44xx_l4_per__elm = {
|
||||
.master = &omap44xx_l4_per_hwmod,
|
||||
@ -4793,6 +4933,10 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
|
||||
&omap44xx_l4_abe__wd_timer3_dma,
|
||||
&omap44xx_mpu__emif1,
|
||||
&omap44xx_mpu__emif2,
|
||||
&omap44xx_l3_main_2__aes1,
|
||||
&omap44xx_l3_main_2__aes2,
|
||||
&omap44xx_l3_main_2__des,
|
||||
&omap44xx_l3_main_2__sha0,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* OMAP SoC specific OPP wrapper function
|
||||
*
|
||||
* Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
* Eduardo Valentin
|
||||
*
|
||||
* 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 "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include "omap_device.h"
|
||||
|
||||
#include "omap_opp_data.h"
|
||||
|
||||
/* Temp variable to allow multiple calls */
|
||||
static u8 __initdata omap_table_init;
|
||||
|
||||
/**
|
||||
* omap_init_opp_table() - Initialize opp table as per the CPU type
|
||||
* @opp_def: opp default list for this silicon
|
||||
* @opp_def_size: number of opp entries for this silicon
|
||||
*
|
||||
* Register the initial OPP table with the OPP library based on the CPU
|
||||
* type. This is meant to be used only by SoC specific registration.
|
||||
*/
|
||||
int __init omap_init_opp_table(struct omap_opp_def *opp_def,
|
||||
u32 opp_def_size)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (of_have_populated_dt())
|
||||
return -EINVAL;
|
||||
|
||||
if (!opp_def || !opp_def_size) {
|
||||
pr_err("%s: invalid params!\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize only if not already initialized even if the previous
|
||||
* call failed, because, no reason we'd succeed again.
|
||||
*/
|
||||
if (omap_table_init)
|
||||
return -EEXIST;
|
||||
omap_table_init = 1;
|
||||
|
||||
/* Lets now register with OPP library */
|
||||
for (i = 0; i < opp_def_size; i++, opp_def++) {
|
||||
struct omap_hwmod *oh;
|
||||
struct device *dev;
|
||||
|
||||
if (!opp_def->hwmod_name) {
|
||||
pr_err("%s: NULL name of omap_hwmod, failing [%d].\n",
|
||||
__func__, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strncmp(opp_def->hwmod_name, "mpu", 3)) {
|
||||
/*
|
||||
* All current OMAPs share voltage rail and
|
||||
* clock source, so CPU0 is used to represent
|
||||
* the MPU-SS.
|
||||
*/
|
||||
dev = get_cpu_device(0);
|
||||
} else {
|
||||
oh = omap_hwmod_lookup(opp_def->hwmod_name);
|
||||
if (!oh || !oh->od) {
|
||||
pr_debug("%s: no hwmod or odev for %s, [%d] cannot add OPPs.\n",
|
||||
__func__, opp_def->hwmod_name, i);
|
||||
continue;
|
||||
}
|
||||
dev = &oh->od->pdev->dev;
|
||||
}
|
||||
|
||||
r = dev_pm_opp_add(dev, opp_def->freq, opp_def->u_volt);
|
||||
if (r) {
|
||||
dev_err(dev, "%s: add OPP %ld failed for %s [%d] result=%d\n",
|
||||
__func__, opp_def->freq,
|
||||
opp_def->hwmod_name, i, r);
|
||||
} else {
|
||||
if (!opp_def->default_available)
|
||||
r = dev_pm_opp_disable(dev, opp_def->freq);
|
||||
if (r)
|
||||
dev_err(dev, "%s: disable %ld failed for %s [%d] result=%d\n",
|
||||
__func__, opp_def->freq,
|
||||
opp_def->hwmod_name, i, r);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -83,89 +83,3 @@ struct omap_volt_data omap36xx_vddcore_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
/* OPP data */
|
||||
|
||||
static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
|
||||
/* MPU OPP1 */
|
||||
OPP_INITIALIZER("mpu", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV),
|
||||
/* MPU OPP2 */
|
||||
OPP_INITIALIZER("mpu", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV),
|
||||
/* MPU OPP3 */
|
||||
OPP_INITIALIZER("mpu", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV),
|
||||
/* MPU OPP4 */
|
||||
OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV),
|
||||
/* MPU OPP5 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV),
|
||||
|
||||
/*
|
||||
* L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
|
||||
* almost the same than the one at 83MHz thus providing very little
|
||||
* gain for the power point of view. In term of energy it will even
|
||||
* increase the consumption due to the very negative performance
|
||||
* impact that frequency will do to the MPU and the whole system in
|
||||
* general.
|
||||
*/
|
||||
OPP_INITIALIZER("l3_main", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV),
|
||||
/* L3 OPP2 */
|
||||
OPP_INITIALIZER("l3_main", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV),
|
||||
/* L3 OPP3 */
|
||||
OPP_INITIALIZER("l3_main", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV),
|
||||
|
||||
/* DSP OPP1 */
|
||||
OPP_INITIALIZER("iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV),
|
||||
/* DSP OPP2 */
|
||||
OPP_INITIALIZER("iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV),
|
||||
/* DSP OPP3 */
|
||||
OPP_INITIALIZER("iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV),
|
||||
/* DSP OPP4 */
|
||||
OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV),
|
||||
/* DSP OPP5 */
|
||||
OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV),
|
||||
};
|
||||
|
||||
static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 300000000, OMAP3630_VDD_MPU_OPP50_UV),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, OMAP3630_VDD_MPU_OPP100_UV),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV),
|
||||
/* MPU OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV),
|
||||
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV),
|
||||
/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
|
||||
OPP_INITIALIZER("l3_main", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV),
|
||||
|
||||
/* DSP OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("iva", true, 260000000, OMAP3630_VDD_MPU_OPP50_UV),
|
||||
/* DSP OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("iva", true, 520000000, OMAP3630_VDD_MPU_OPP100_UV),
|
||||
/* DSP OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV),
|
||||
/* DSP OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV),
|
||||
};
|
||||
|
||||
/**
|
||||
* omap3_opp_init() - initialize omap3 opp table
|
||||
*/
|
||||
int __init omap3_opp_init(void)
|
||||
{
|
||||
int r = -ENODEV;
|
||||
|
||||
if (!cpu_is_omap34xx())
|
||||
return r;
|
||||
|
||||
if (cpu_is_omap3630())
|
||||
r = omap_init_opp_table(omap36xx_opp_def_list,
|
||||
ARRAY_SIZE(omap36xx_opp_def_list));
|
||||
else
|
||||
r = omap_init_opp_table(omap34xx_opp_def_list,
|
||||
ARRAY_SIZE(omap34xx_opp_def_list));
|
||||
|
||||
return r;
|
||||
}
|
||||
omap_device_initcall(omap3_opp_init);
|
||||
|
@ -63,29 +63,6 @@ struct omap_volt_data omap443x_vdd_core_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
|
||||
static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV),
|
||||
/* MPU OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV),
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV),
|
||||
/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
|
||||
OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV),
|
||||
/* IVA OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV),
|
||||
/* IVA OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV),
|
||||
/* IVA OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
|
||||
/* TODO: add DSP, aess, fdif, gpu */
|
||||
};
|
||||
|
||||
#define OMAP4460_VDD_MPU_OPP50_UV 1025000
|
||||
#define OMAP4460_VDD_MPU_OPP100_UV 1200000
|
||||
#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
|
||||
@ -122,59 +99,3 @@ struct omap_volt_data omap446x_vdd_core_volt_data[] = {
|
||||
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
|
||||
VOLT_DATA_DEFINE(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
|
||||
/*
|
||||
* MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
|
||||
* recommends TPS623631 - confirm and enable the opp in board file
|
||||
* XXX: May be we should enable these based on mpu capability and
|
||||
* Exception board files disable it...
|
||||
*/
|
||||
OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
|
||||
/* MPU OPP4 - OPP-Nitro SpeedBin */
|
||||
OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
|
||||
/* L3 OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
|
||||
/* IVA OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
|
||||
/* IVA OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
|
||||
/*
|
||||
* IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
|
||||
* recommends Phoenix VCORE2 which can supply only 600mA - so the ones
|
||||
* above this OPP frequency, even though OMAP is capable, should be
|
||||
* enabled by board file which is sure of the chip power capability
|
||||
*/
|
||||
OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
|
||||
/* IVA OPP4 - OPP-Nitro */
|
||||
OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
|
||||
/* IVA OPP5 - OPP-Nitro SpeedBin*/
|
||||
OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
|
||||
|
||||
/* TODO: add DSP, aess, fdif, gpu */
|
||||
};
|
||||
|
||||
/**
|
||||
* omap4_opp_init() - initialize omap4 opp table
|
||||
*/
|
||||
int __init omap4_opp_init(void)
|
||||
{
|
||||
int r = -ENODEV;
|
||||
|
||||
if (cpu_is_omap443x())
|
||||
r = omap_init_opp_table(omap443x_opp_def_list,
|
||||
ARRAY_SIZE(omap443x_opp_def_list));
|
||||
else if (cpu_is_omap446x())
|
||||
r = omap_init_opp_table(omap446x_opp_def_list,
|
||||
ARRAY_SIZE(omap446x_opp_def_list));
|
||||
return r;
|
||||
}
|
||||
omap_device_initcall(omap4_opp_init);
|
||||
|
@ -71,7 +71,7 @@ void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
|
||||
}
|
||||
#endif
|
||||
|
||||
int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
|
||||
int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
|
||||
{
|
||||
clkdm_allow_idle(clkdm);
|
||||
return 0;
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* OMAP2 ARM Performance Monitoring Unit (PMU) Support
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
*
|
||||
* Contacts:
|
||||
* Jon Hunter <jon-hunter@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/system_info.h>
|
||||
|
||||
#include "soc.h"
|
||||
#include "omap_hwmod.h"
|
||||
#include "omap_device.h"
|
||||
|
||||
static char *omap2_pmu_oh_names[] = {"mpu"};
|
||||
static char *omap3_pmu_oh_names[] = {"mpu", "debugss"};
|
||||
static char *omap4430_pmu_oh_names[] = {"l3_main_3", "l3_instr", "debugss"};
|
||||
static struct platform_device *omap_pmu_dev;
|
||||
|
||||
/**
|
||||
* omap2_init_pmu - creates and registers PMU platform device
|
||||
* @oh_num: Number of OMAP HWMODs required to create PMU device
|
||||
* @oh_names: Array of OMAP HWMODS names required to create PMU device
|
||||
*
|
||||
* Uses OMAP HWMOD framework to create and register an ARM PMU device
|
||||
* from a list of HWMOD names passed. Currently supports OMAP2, OMAP3
|
||||
* and OMAP4 devices.
|
||||
*/
|
||||
static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[])
|
||||
{
|
||||
int i;
|
||||
struct omap_hwmod *oh[3];
|
||||
char *dev_name = cpu_architecture() == CPU_ARCH_ARMv6 ?
|
||||
"armv6-pmu" : "armv7-pmu";
|
||||
|
||||
if ((!oh_num) || (oh_num > 3))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < oh_num; i++) {
|
||||
oh[i] = omap_hwmod_lookup(oh_names[i]);
|
||||
if (!oh[i]) {
|
||||
pr_err("Could not look up %s hwmod\n", oh_names[i]);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0);
|
||||
WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n",
|
||||
dev_name);
|
||||
|
||||
return PTR_ERR_OR_ZERO(omap_pmu_dev);
|
||||
}
|
||||
|
||||
static int __init omap_init_pmu(void)
|
||||
{
|
||||
unsigned oh_num;
|
||||
char **oh_names;
|
||||
|
||||
/* XXX Remove this check when the CTI driver is available */
|
||||
if (cpu_is_omap443x()) {
|
||||
pr_info("ARM PMU: not yet supported on OMAP4430 due to missing CTI driver\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_have_populated_dt())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* To create an ARM-PMU device the following HWMODs
|
||||
* are required for the various OMAP2+ devices.
|
||||
*
|
||||
* OMAP24xx: mpu
|
||||
* OMAP3xxx: mpu, debugss
|
||||
* OMAP4430: l3_main_3, l3_instr, debugss
|
||||
* OMAP4460/70: mpu, debugss
|
||||
*/
|
||||
if (cpu_is_omap443x()) {
|
||||
oh_num = ARRAY_SIZE(omap4430_pmu_oh_names);
|
||||
oh_names = omap4430_pmu_oh_names;
|
||||
} else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
|
||||
oh_num = ARRAY_SIZE(omap3_pmu_oh_names);
|
||||
oh_names = omap3_pmu_oh_names;
|
||||
} else {
|
||||
oh_num = ARRAY_SIZE(omap2_pmu_oh_names);
|
||||
oh_names = omap2_pmu_oh_names;
|
||||
}
|
||||
|
||||
return omap2_init_pmu(oh_num, oh_names);
|
||||
}
|
||||
omap_subsys_initcall(omap_init_pmu);
|
@ -526,10 +526,16 @@ struct omap_prcm_irq_setup {
|
||||
.priority = _priority \
|
||||
}
|
||||
|
||||
struct omap_domain_base {
|
||||
u32 pa;
|
||||
void __iomem *va;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct omap_prcm_init_data - PRCM driver init data
|
||||
* @index: clock memory mapping index to be used
|
||||
* @mem: IO mem pointer for this module
|
||||
* @phys: IO mem physical base address for this module
|
||||
* @offset: module base address offset from the IO base
|
||||
* @flags: PRCM module init flags
|
||||
* @device_inst_offset: device instance offset within the module address space
|
||||
@ -539,6 +545,7 @@ struct omap_prcm_irq_setup {
|
||||
struct omap_prcm_init_data {
|
||||
int index;
|
||||
void __iomem *mem;
|
||||
u32 phys;
|
||||
s16 offset;
|
||||
u16 flags;
|
||||
s32 device_inst_offset;
|
||||
|
@ -24,7 +24,7 @@
|
||||
* prcm_mpu_base: the virtual address of the start of the PRCM_MPU IP
|
||||
* block registers
|
||||
*/
|
||||
void __iomem *prcm_mpu_base;
|
||||
struct omap_domain_base prcm_mpu_base;
|
||||
|
||||
/* PRCM_MPU low-level functions */
|
||||
|
||||
@ -58,5 +58,5 @@ u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
|
||||
*/
|
||||
void __init omap2_set_globals_prcm_mpu(void __iomem *prcm_mpu)
|
||||
{
|
||||
prcm_mpu_base = prcm_mpu;
|
||||
prcm_mpu_base.va = prcm_mpu;
|
||||
}
|
||||
|
@ -24,7 +24,9 @@
|
||||
#define __ARCH_ARM_MACH_OMAP2_PRCM_MPU_44XX_54XX_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
extern void __iomem *prcm_mpu_base;
|
||||
#include "prcm-common.h"
|
||||
|
||||
extern struct omap_domain_base prcm_mpu_base;
|
||||
|
||||
extern u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 idx);
|
||||
extern void omap4_prcm_mpu_write_inst_reg(u32 val, s16 inst, u16 idx);
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "prcm-common.h"
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
extern void __iomem *prm_base;
|
||||
extern struct omap_domain_base prm_base;
|
||||
extern u16 prm_features;
|
||||
extern void omap2_set_globals_prm(void __iomem *prm);
|
||||
int omap_prcm_init(void);
|
||||
|
@ -55,12 +55,12 @@
|
||||
/* Power/reset management domain register get/set */
|
||||
static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
|
||||
{
|
||||
return readl_relaxed(prm_base + module + idx);
|
||||
return readl_relaxed(prm_base.va + module + idx);
|
||||
}
|
||||
|
||||
static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||
{
|
||||
writel_relaxed(val, prm_base + module + idx);
|
||||
writel_relaxed(val, prm_base.va + module + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in a PRM module. Caller must lock */
|
||||
|
@ -30,13 +30,13 @@
|
||||
/* Read a register in a PRM instance */
|
||||
static u32 am33xx_prm_read_reg(s16 inst, u16 idx)
|
||||
{
|
||||
return readl_relaxed(prm_base + inst + idx);
|
||||
return readl_relaxed(prm_base.va + inst + idx);
|
||||
}
|
||||
|
||||
/* Write into a register in a PRM instance */
|
||||
static void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
|
||||
{
|
||||
writel_relaxed(val, prm_base + inst + idx);
|
||||
writel_relaxed(val, prm_base.va + inst + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in PRM. Caller must lock */
|
||||
|
@ -676,7 +676,7 @@ static struct prm_ll_data omap3xxx_prm_ll_data = {
|
||||
int __init omap3xxx_prm_init(const struct omap_prcm_init_data *data)
|
||||
{
|
||||
omap2_clk_legacy_provider_init(TI_CLKM_PRM,
|
||||
prm_base + OMAP3430_IVA2_MOD);
|
||||
prm_base.va + OMAP3430_IVA2_MOD);
|
||||
if (omap3_has_io_wakeup())
|
||||
prm_features |= PRM_HAS_IO_WAKEUP;
|
||||
|
||||
@ -690,6 +690,8 @@ static const struct of_device_id omap3_prm_dt_match_table[] = {
|
||||
|
||||
static int omap3xxx_prm_late_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int irq_num;
|
||||
int ret;
|
||||
|
||||
if (!(prm_features & PRM_HAS_IO_WAKEUP))
|
||||
@ -702,16 +704,11 @@ static int omap3xxx_prm_late_init(void)
|
||||
omap3_prcm_irq_setup.reconfigure_io_chain =
|
||||
omap3430_pre_es3_1_reconfigure_io_chain;
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
struct device_node *np;
|
||||
int irq_num;
|
||||
|
||||
np = of_find_matching_node(NULL, omap3_prm_dt_match_table);
|
||||
if (np) {
|
||||
irq_num = of_irq_get(np, 0);
|
||||
if (irq_num >= 0)
|
||||
omap3_prcm_irq_setup.irq = irq_num;
|
||||
}
|
||||
np = of_find_matching_node(NULL, omap3_prm_dt_match_table);
|
||||
if (np) {
|
||||
irq_num = of_irq_get(np, 0);
|
||||
if (irq_num >= 0)
|
||||
omap3_prcm_irq_setup.irq = irq_num;
|
||||
}
|
||||
|
||||
omap3xxx_prm_enable_io_wakeup();
|
||||
|
@ -91,13 +91,13 @@ static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
|
||||
/* Read a register in a CM/PRM instance in the PRM module */
|
||||
static u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
|
||||
{
|
||||
return readl_relaxed(prm_base + inst + reg);
|
||||
return readl_relaxed(prm_base.va + inst + reg);
|
||||
}
|
||||
|
||||
/* Write into a register in a CM/PRM instance in the PRM module */
|
||||
static void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
|
||||
{
|
||||
writel_relaxed(val, prm_base + inst + reg);
|
||||
writel_relaxed(val, prm_base.va + inst + reg);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in a PRM module. Caller must lock */
|
||||
@ -336,27 +336,6 @@ static void omap44xx_prm_reconfigure_io_chain(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
||||
*
|
||||
* Activates the I/O wakeup event latches and allows events logged by
|
||||
* those latches to signal a wakeup event to the PRCM. For I/O wakeups
|
||||
* to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
|
||||
* omap44xx_prm_reconfigure_io_chain() must be called. No return value.
|
||||
*/
|
||||
static void __init omap44xx_prm_enable_io_wakeup(void)
|
||||
{
|
||||
s32 inst = omap4_prmst_get_prm_dev_inst();
|
||||
|
||||
if (inst == PRM_INSTANCE_UNKNOWN)
|
||||
return;
|
||||
|
||||
omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
|
||||
OMAP4430_GLOBAL_WUEN_MASK,
|
||||
inst,
|
||||
omap4_prcm_irq_setup.pm_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap44xx_prm_read_reset_sources - return the last SoC reset source
|
||||
*
|
||||
@ -689,8 +668,6 @@ struct pwrdm_ops omap4_pwrdm_operations = {
|
||||
.pwrdm_has_voltdm = omap4_check_vcvp,
|
||||
};
|
||||
|
||||
static int omap44xx_prm_late_init(void);
|
||||
|
||||
/*
|
||||
* XXX document
|
||||
*/
|
||||
@ -698,7 +675,6 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
|
||||
.read_reset_sources = &omap44xx_prm_read_reset_sources,
|
||||
.was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
|
||||
.clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
|
||||
.late_init = &omap44xx_prm_late_init,
|
||||
.assert_hardreset = omap4_prminst_assert_hardreset,
|
||||
.deassert_hardreset = omap4_prminst_deassert_hardreset,
|
||||
.is_hardreset_asserted = omap4_prminst_is_hardreset_asserted,
|
||||
@ -735,41 +711,6 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
|
||||
return prm_register(&omap44xx_prm_ll_data);
|
||||
}
|
||||
|
||||
static int omap44xx_prm_late_init(void)
|
||||
{
|
||||
int irq_num;
|
||||
|
||||
if (!(prm_features & PRM_HAS_IO_WAKEUP))
|
||||
return 0;
|
||||
|
||||
/* OMAP4+ is DT only now */
|
||||
if (!of_have_populated_dt())
|
||||
return 0;
|
||||
|
||||
irq_num = of_irq_get(prm_init_data->np, 0);
|
||||
/*
|
||||
* Already have OMAP4 IRQ num. For all other platforms, we need
|
||||
* IRQ numbers from DT
|
||||
*/
|
||||
if (irq_num < 0 && !(prm_init_data->flags & PRM_IRQ_DEFAULT)) {
|
||||
if (irq_num == -EPROBE_DEFER)
|
||||
return irq_num;
|
||||
|
||||
/* Have nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Once OMAP4 DT is filled as well */
|
||||
if (irq_num >= 0) {
|
||||
omap4_prcm_irq_setup.irq = irq_num;
|
||||
omap4_prcm_irq_setup.xlate_irq = NULL;
|
||||
}
|
||||
|
||||
omap44xx_prm_enable_io_wakeup();
|
||||
|
||||
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
|
||||
}
|
||||
|
||||
static void __exit omap44xx_prm_exit(void)
|
||||
{
|
||||
prm_unregister(&omap44xx_prm_ll_data);
|
||||
|
@ -66,7 +66,7 @@ static struct irq_chip_generic **prcm_irq_chips;
|
||||
static struct omap_prcm_irq_setup *prcm_irq_setup;
|
||||
|
||||
/* prm_base: base virtual address of the PRM IP block */
|
||||
void __iomem *prm_base;
|
||||
struct omap_domain_base prm_base;
|
||||
|
||||
u16 prm_features;
|
||||
|
||||
@ -267,10 +267,9 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
|
||||
{
|
||||
int nr_regs;
|
||||
u32 mask[OMAP_PRCM_MAX_NR_PENDING_REG];
|
||||
int offset, i;
|
||||
int offset, i, irq;
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
unsigned int irq;
|
||||
|
||||
if (!irq_setup)
|
||||
return -EINVAL;
|
||||
@ -325,7 +324,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
|
||||
|
||||
for (i = 0; i < irq_setup->nr_regs; i++) {
|
||||
gc = irq_alloc_generic_chip("PRCM", 1,
|
||||
irq_setup->base_irq + i * 32, prm_base,
|
||||
irq_setup->base_irq + i * 32, prm_base.va,
|
||||
handle_level_irq);
|
||||
|
||||
if (!gc) {
|
||||
@ -344,10 +343,8 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
|
||||
prcm_irq_chips[i] = gc;
|
||||
}
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
int irq = omap_prcm_event_to_irq("io");
|
||||
omap_pcs_legacy_init(irq, irq_setup->reconfigure_io_chain);
|
||||
}
|
||||
irq = omap_prcm_event_to_irq("io");
|
||||
omap_pcs_legacy_init(irq, irq_setup->reconfigure_io_chain);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -364,7 +361,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
|
||||
*/
|
||||
void __init omap2_set_globals_prm(void __iomem *prm)
|
||||
{
|
||||
prm_base = prm;
|
||||
prm_base.va = prm;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -755,19 +752,22 @@ int __init omap2_prm_base_init(void)
|
||||
struct device_node *np;
|
||||
const struct of_device_id *match;
|
||||
struct omap_prcm_init_data *data;
|
||||
void __iomem *mem;
|
||||
struct resource res;
|
||||
int ret;
|
||||
|
||||
for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) {
|
||||
data = (struct omap_prcm_init_data *)match->data;
|
||||
|
||||
mem = of_iomap(np, 0);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data->index == TI_CLKM_PRM)
|
||||
prm_base = mem + data->offset;
|
||||
data->mem = ioremap(res.start, resource_size(&res));
|
||||
|
||||
data->mem = mem;
|
||||
if (data->index == TI_CLKM_PRM) {
|
||||
prm_base.va = data->mem + data->offset;
|
||||
prm_base.pa = res.start + data->offset;
|
||||
}
|
||||
|
||||
data->np = np;
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "prcm_mpu44xx.h"
|
||||
#include "soc.h"
|
||||
|
||||
static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
|
||||
static struct omap_domain_base _prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
|
||||
|
||||
static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
|
||||
|
||||
@ -41,8 +41,10 @@ static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
|
||||
*/
|
||||
void omap_prm_base_init(void)
|
||||
{
|
||||
_prm_bases[OMAP4430_PRM_PARTITION] = prm_base;
|
||||
_prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
|
||||
memcpy(&_prm_bases[OMAP4430_PRM_PARTITION], &prm_base,
|
||||
sizeof(prm_base));
|
||||
memcpy(&_prm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base,
|
||||
sizeof(prcm_mpu_base));
|
||||
}
|
||||
|
||||
s32 omap4_prmst_get_prm_dev_inst(void)
|
||||
@ -60,8 +62,8 @@ u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
|
||||
{
|
||||
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
|
||||
part == OMAP4430_INVALID_PRCM_PARTITION ||
|
||||
!_prm_bases[part]);
|
||||
return readl_relaxed(_prm_bases[part] + inst + idx);
|
||||
!_prm_bases[part].va);
|
||||
return readl_relaxed(_prm_bases[part].va + inst + idx);
|
||||
}
|
||||
|
||||
/* Write into a register in a PRM instance */
|
||||
@ -69,8 +71,8 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
|
||||
{
|
||||
BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
|
||||
part == OMAP4430_INVALID_PRCM_PARTITION ||
|
||||
!_prm_bases[part]);
|
||||
writel_relaxed(val, _prm_bases[part] + inst + idx);
|
||||
!_prm_bases[part].va);
|
||||
writel_relaxed(val, _prm_bases[part].va + inst + idx);
|
||||
}
|
||||
|
||||
/* Read-modify-write a register in PRM. Caller must lock */
|
||||
|
@ -44,13 +44,9 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
|
||||
while (volt_data[count].volt_nominal)
|
||||
count++;
|
||||
|
||||
nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!nvalue_table) {
|
||||
pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
|
||||
nvalue_table = kcalloc(count, sizeof(*nvalue_table), GFP_KERNEL);
|
||||
if (!nvalue_table)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < count; i++) {
|
||||
u32 v;
|
||||
@ -102,12 +98,9 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
|
||||
char *name = "smartreflex";
|
||||
static int i;
|
||||
|
||||
sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
|
||||
if (!sr_data) {
|
||||
pr_err("%s: Unable to allocate memory for %s sr_data\n",
|
||||
__func__, oh->name);
|
||||
sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL);
|
||||
if (!sr_data)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr;
|
||||
if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) {
|
||||
|
@ -68,6 +68,9 @@
|
||||
static struct omap_dm_timer clkev;
|
||||
static struct clock_event_device clockevent_gpt;
|
||||
|
||||
/* Clockevent hwmod for am335x and am437x suspend */
|
||||
static struct omap_hwmod *clockevent_gpt_hwmod;
|
||||
|
||||
#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
|
||||
static unsigned long arch_timer_freq;
|
||||
|
||||
@ -125,6 +128,23 @@ static int omap2_gp_timer_set_periodic(struct clock_event_device *evt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_clkevt_idle(struct clock_event_device *unused)
|
||||
{
|
||||
if (!clockevent_gpt_hwmod)
|
||||
return;
|
||||
|
||||
omap_hwmod_idle(clockevent_gpt_hwmod);
|
||||
}
|
||||
|
||||
static void omap_clkevt_unidle(struct clock_event_device *unused)
|
||||
{
|
||||
if (!clockevent_gpt_hwmod)
|
||||
return;
|
||||
|
||||
omap_hwmod_enable(clockevent_gpt_hwmod);
|
||||
__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent_gpt = {
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
@ -232,37 +252,29 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
|
||||
const char **timer_name,
|
||||
int posted)
|
||||
{
|
||||
char name[10]; /* 10 = sizeof("gptXX_Xck0") */
|
||||
const char *oh_name = NULL;
|
||||
struct device_node *np;
|
||||
struct omap_hwmod *oh;
|
||||
struct resource irq, mem;
|
||||
struct clk *src;
|
||||
int r = 0;
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
np = omap_get_timer_dt(omap_timer_match, property);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
np = omap_get_timer_dt(omap_timer_match, property);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
|
||||
if (!oh_name)
|
||||
return -ENODEV;
|
||||
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
|
||||
if (!oh_name)
|
||||
return -ENODEV;
|
||||
|
||||
timer->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!timer->irq)
|
||||
return -ENXIO;
|
||||
timer->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!timer->irq)
|
||||
return -ENXIO;
|
||||
|
||||
timer->io_base = of_iomap(np, 0);
|
||||
timer->io_base = of_iomap(np, 0);
|
||||
|
||||
of_node_put(np);
|
||||
} else {
|
||||
if (omap_dm_timer_reserve_systimer(timer->id))
|
||||
return -ENODEV;
|
||||
timer->fclk = of_clk_get_by_name(np, "fck");
|
||||
|
||||
sprintf(name, "timer%d", timer->id);
|
||||
oh_name = name;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
oh = omap_hwmod_lookup(oh_name);
|
||||
if (!oh)
|
||||
@ -270,29 +282,14 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
|
||||
|
||||
*timer_name = oh->name;
|
||||
|
||||
if (!of_have_populated_dt()) {
|
||||
r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
|
||||
&irq);
|
||||
if (r)
|
||||
return -ENXIO;
|
||||
timer->irq = irq.start;
|
||||
|
||||
r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL,
|
||||
&mem);
|
||||
if (r)
|
||||
return -ENXIO;
|
||||
|
||||
/* Static mapping, never released */
|
||||
timer->io_base = ioremap(mem.start, mem.end - mem.start);
|
||||
}
|
||||
|
||||
if (!timer->io_base)
|
||||
return -ENXIO;
|
||||
|
||||
omap_hwmod_setup_one(oh_name);
|
||||
|
||||
/* After the dmtimer is using hwmod these clocks won't be needed */
|
||||
timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
|
||||
if (IS_ERR_OR_NULL(timer->fclk))
|
||||
timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
|
||||
if (IS_ERR(timer->fclk))
|
||||
return PTR_ERR(timer->fclk);
|
||||
|
||||
@ -358,6 +355,14 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
|
||||
3, /* Timer internal resynch latency */
|
||||
0xffffffff);
|
||||
|
||||
if (soc_is_am33xx() || soc_is_am43xx()) {
|
||||
clockevent_gpt.suspend = omap_clkevt_idle;
|
||||
clockevent_gpt.resume = omap_clkevt_unidle;
|
||||
|
||||
clockevent_gpt_hwmod =
|
||||
omap_hwmod_lookup(clockevent_gpt.name);
|
||||
}
|
||||
|
||||
pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
|
||||
clkev.rate);
|
||||
}
|
||||
@ -405,18 +410,15 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
|
||||
const char *oh_name = "counter_32k";
|
||||
|
||||
/*
|
||||
* If device-tree is present, then search the DT blob
|
||||
* to see if the 32kHz counter is supported.
|
||||
* See if the 32kHz counter is supported.
|
||||
*/
|
||||
if (of_have_populated_dt()) {
|
||||
np = omap_get_timer_dt(omap_counter_match, NULL);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
np = omap_get_timer_dt(omap_counter_match, NULL);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
|
||||
if (!oh_name)
|
||||
return -ENODEV;
|
||||
}
|
||||
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
|
||||
if (!oh_name)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* First check hwmod data is available for sync32k counter
|
||||
@ -434,18 +436,6 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!of_have_populated_dt()) {
|
||||
void __iomem *vbase;
|
||||
|
||||
vbase = omap_hwmod_get_mpu_rt_va(oh);
|
||||
|
||||
ret = omap_init_clocksource_32k(vbase);
|
||||
if (ret) {
|
||||
pr_warn("%s: failed to initialize counter_32k as a clocksource (%d)\n",
|
||||
__func__, ret);
|
||||
omap_hwmod_idle(oh);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -660,96 +650,6 @@ void __init omap5_realtime_timer_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SOC_OMAP5 || CONFIG_SOC_DRA7XX */
|
||||
|
||||
/**
|
||||
* omap_timer_init - build and register timer device with an
|
||||
* associated timer hwmod
|
||||
* @oh: timer hwmod pointer to be used to build timer device
|
||||
* @user: parameter that can be passed from calling hwmod API
|
||||
*
|
||||
* Called by omap_hwmod_for_each_by_class to register each of the timer
|
||||
* devices present in the system. The number of timer devices is known
|
||||
* by parsing through the hwmod database for a given class name. At the
|
||||
* end of function call memory is allocated for timer device and it is
|
||||
* registered to the framework ready to be proved by the driver.
|
||||
*/
|
||||
static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
|
||||
{
|
||||
int id;
|
||||
int ret = 0;
|
||||
char *name = "omap_timer";
|
||||
struct dmtimer_platform_data *pdata;
|
||||
struct platform_device *pdev;
|
||||
struct omap_timer_capability_dev_attr *timer_dev_attr;
|
||||
|
||||
pr_debug("%s: %s\n", __func__, oh->name);
|
||||
|
||||
/* on secure device, do not register secure timer */
|
||||
timer_dev_attr = oh->dev_attr;
|
||||
if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
|
||||
if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
|
||||
return ret;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
pr_err("%s: No memory for [%s]\n", __func__, oh->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the IDs from name field in hwmod database
|
||||
* and use the same for constructing ids' for the
|
||||
* timer devices. In a way, we are avoiding usage of
|
||||
* static variable witin the function to do the same.
|
||||
* CAUTION: We have to be careful and make sure the
|
||||
* name in hwmod database does not change in which case
|
||||
* we might either make corresponding change here or
|
||||
* switch back static variable mechanism.
|
||||
*/
|
||||
sscanf(oh->name, "timer%2d", &id);
|
||||
|
||||
if (timer_dev_attr)
|
||||
pdata->timer_capability = timer_dev_attr->timer_capability;
|
||||
|
||||
pdata->timer_errata = omap_dm_timer_get_errata();
|
||||
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
|
||||
|
||||
pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata));
|
||||
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("%s: Can't build omap_device for %s: %s.\n",
|
||||
__func__, name, oh->name);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
kfree(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap2_dm_timer_init - top level regular device initialization
|
||||
*
|
||||
* Uses dedicated hwmod api to parse through hwmod database for
|
||||
* given class name and then build and register the timer device.
|
||||
*/
|
||||
static int __init omap2_dm_timer_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* If dtb is there, the devices will be created dynamically */
|
||||
if (of_have_populated_dt())
|
||||
return -ENODEV;
|
||||
|
||||
ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
|
||||
if (unlikely(ret)) {
|
||||
pr_err("%s: device registration failed.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
omap_arch_initcall(omap2_dm_timer_init);
|
||||
|
||||
/**
|
||||
* omap2_override_clocksource - clocksource override with user configuration
|
||||
*
|
||||
|
@ -102,31 +102,3 @@ int omap2_wd_timer_reset(struct omap_hwmod *oh)
|
||||
return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
|
||||
omap2_wd_timer_disable(oh);
|
||||
}
|
||||
|
||||
static int __init omap_init_wdt(void)
|
||||
{
|
||||
int id = -1;
|
||||
struct platform_device *pdev;
|
||||
struct omap_hwmod *oh;
|
||||
char *oh_name = "wd_timer2";
|
||||
char *dev_name = "omap_wdt";
|
||||
struct omap_wd_timer_platform_data pdata;
|
||||
|
||||
if (!cpu_class_is_omap2() || of_have_populated_dt())
|
||||
return 0;
|
||||
|
||||
oh = omap_hwmod_lookup(oh_name);
|
||||
if (!oh) {
|
||||
pr_err("Could not look up wd_timer%d hwmod\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata.read_reset_sources = prm_read_reset_sources;
|
||||
|
||||
pdev = omap_device_build(dev_name, id, oh, &pdata,
|
||||
sizeof(struct omap_wd_timer_platform_data));
|
||||
WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
|
||||
dev_name, oh->name);
|
||||
return 0;
|
||||
}
|
||||
omap_subsys_initcall(omap_init_wdt);
|
||||
|
@ -27,7 +27,6 @@ config ARCH_ATLAS7
|
||||
bool "CSR SiRFSoC ATLAS7 ARM Cortex A7 Platform"
|
||||
default y
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select ATLAS7_TIMER
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_SMP
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define GPIO10_MAGICIAN_GSM_IRQ 10
|
||||
#define GPIO11_MAGICIAN_GSM_OUT1 11
|
||||
#define GPIO13_MAGICIAN_CPLD_IRQ 13
|
||||
#define GPIO14_MAGICIAN_TSC2046_CS 14
|
||||
#define GPIO18_MAGICIAN_UNKNOWN 18
|
||||
#define GPIO22_MAGICIAN_VIBRA_EN 22
|
||||
#define GPIO26_MAGICIAN_GSM_POWER 26
|
||||
|
@ -54,6 +54,10 @@
|
||||
#include "devices.h"
|
||||
#include "generic.h"
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/pxa2xx_spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
|
||||
static unsigned long magician_pin_config[] __initdata = {
|
||||
|
||||
/* SDRAM and Static Memory I/O Signals */
|
||||
@ -85,7 +89,7 @@ static unsigned long magician_pin_config[] __initdata = {
|
||||
|
||||
/* SSP 2 TSC2046 touchscreen */
|
||||
GPIO19_SSP2_SCLK,
|
||||
GPIO14_SSP2_SFRM,
|
||||
MFP_CFG_OUT(GPIO14, AF0, DRIVE_HIGH), /* frame as GPIO */
|
||||
GPIO89_SSP2_TXD,
|
||||
GPIO88_SSP2_RXD,
|
||||
|
||||
@ -674,6 +678,37 @@ static struct platform_device bq24022 = {
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* fixed regulator for ads7846
|
||||
*/
|
||||
|
||||
static struct regulator_consumer_supply ads7846_supply =
|
||||
REGULATOR_SUPPLY("vcc", "spi2.0");
|
||||
|
||||
static struct regulator_init_data vads7846_regulator = {
|
||||
.constraints = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = 1,
|
||||
.consumer_supplies = &ads7846_supply,
|
||||
};
|
||||
|
||||
static struct fixed_voltage_config vads7846 = {
|
||||
.supply_name = "vads7846",
|
||||
.microvolts = 3300000, /* probably */
|
||||
.gpio = -EINVAL,
|
||||
.startup_delay = 0,
|
||||
.init_data = &vads7846_regulator,
|
||||
};
|
||||
|
||||
static struct platform_device vads7846_device = {
|
||||
.name = "reg-fixed-voltage",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &vads7846,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Vcore regulator MAX1587A
|
||||
*/
|
||||
@ -851,6 +886,49 @@ static struct i2c_pxa_platform_data magician_i2c_power_info = {
|
||||
.fast_mode = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Touchscreen
|
||||
*/
|
||||
|
||||
static struct ads7846_platform_data ads7846_pdata = {
|
||||
.model = 7846,
|
||||
.x_plate_ohms = 317,
|
||||
.y_plate_ohms = 500,
|
||||
.pressure_max = 1023, /* with x plate ohms it will overflow 255 */
|
||||
.debounce_max = 3, /* first readout is always bad */
|
||||
.debounce_tol = 30,
|
||||
.debounce_rep = 0,
|
||||
.gpio_pendown = GPIO115_MAGICIAN_nPEN_IRQ,
|
||||
.keep_vref_on = 1,
|
||||
.wakeup = true,
|
||||
.vref_delay_usecs = 100,
|
||||
.penirq_recheck_delay_usecs = 100,
|
||||
};
|
||||
|
||||
struct pxa2xx_spi_chip tsc2046_chip_info = {
|
||||
.tx_threshold = 1,
|
||||
.rx_threshold = 2,
|
||||
.timeout = 64,
|
||||
/* NOTICE must be GPIO, incompatibility with hw PXA SPI framing */
|
||||
.gpio_cs = GPIO14_MAGICIAN_TSC2046_CS,
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_master magician_spi_info = {
|
||||
.num_chipselect = 1,
|
||||
.enable_dma = 1,
|
||||
};
|
||||
|
||||
static struct spi_board_info ads7846_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "ads7846",
|
||||
.bus_num = 2,
|
||||
.max_speed_hz = 2500000,
|
||||
.platform_data = &ads7846_pdata,
|
||||
.controller_data = &tsc2046_chip_info,
|
||||
.irq = PXA_GPIO_TO_IRQ(GPIO115_MAGICIAN_nPEN_IRQ),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Platform devices
|
||||
*/
|
||||
@ -865,6 +943,7 @@ static struct platform_device *devices[] __initdata = {
|
||||
&power_supply,
|
||||
&strataflash,
|
||||
&leds_gpio,
|
||||
&vads7846_device,
|
||||
};
|
||||
|
||||
static struct gpio magician_global_gpios[] = {
|
||||
@ -922,6 +1001,9 @@ static void __init magician_init(void)
|
||||
} else
|
||||
pr_err("LCD detection: CPLD mapping failed\n");
|
||||
|
||||
pxa2xx_set_spi_info(2, &magician_spi_info);
|
||||
spi_register_board_info(ARRAY_AND_SIZE(ads7846_spi_board_info));
|
||||
|
||||
regulator_register_always_on(0, "power", pwm_backlight_supply,
|
||||
ARRAY_SIZE(pwm_backlight_supply), 5000000);
|
||||
|
||||
|
@ -107,10 +107,8 @@ static int __init pxa_pm_init(void)
|
||||
sleep_save = kmalloc_array(pxa_cpu_pm_fns->save_count,
|
||||
sizeof(*sleep_save),
|
||||
GFP_KERNEL);
|
||||
if (!sleep_save) {
|
||||
printk(KERN_ERR "failed to alloc memory for pm save\n");
|
||||
if (!sleep_save)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
suspend_set_ops(&pxa_pm_ops);
|
||||
return 0;
|
||||
|
@ -286,11 +286,9 @@ static int pxa3xx_u2d_probe(struct platform_device *pdev)
|
||||
struct resource *r;
|
||||
int err;
|
||||
|
||||
u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL);
|
||||
if (!u2d) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory\n");
|
||||
u2d = kzalloc(sizeof(*u2d), GFP_KERNEL);
|
||||
if (!u2d)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
u2d->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(u2d->clk)) {
|
||||
|
@ -70,6 +70,7 @@ static const char * const rockchip_board_dt_compat[] = {
|
||||
"rockchip,rk3188",
|
||||
"rockchip,rk3228",
|
||||
"rockchip,rk3288",
|
||||
"rockchip,rv1108",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,6 @@ config CPU_S3C6410
|
||||
|
||||
config S3C64XX_PL080
|
||||
def_bool DMADEVICES
|
||||
select ARM_AMBA
|
||||
select AMBA_PL08X
|
||||
|
||||
config S3C64XX_SETUP_SDHCI
|
||||
|
@ -130,7 +130,7 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
|
||||
struct generic_pm_domain *genpd = &rmobile_pd->genpd;
|
||||
struct dev_power_governor *gov = rmobile_pd->gov;
|
||||
|
||||
genpd->flags = GENPD_FLAG_PM_CLK;
|
||||
genpd->flags |= GENPD_FLAG_PM_CLK;
|
||||
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
|
||||
genpd->power_off = rmobile_pd_power_down;
|
||||
genpd->power_on = rmobile_pd_power_up;
|
||||
@ -140,14 +140,6 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
|
||||
pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
|
||||
}
|
||||
|
||||
static int rmobile_pd_suspend_busy(void)
|
||||
{
|
||||
/*
|
||||
* This domain should not be turned off.
|
||||
*/
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int rmobile_pd_suspend_console(void)
|
||||
{
|
||||
/*
|
||||
@ -260,8 +252,7 @@ static void __init rmobile_setup_pm_domain(struct device_node *np,
|
||||
* only be turned off if the CPU is not in use.
|
||||
*/
|
||||
pr_debug("PM domain %s contains CPU\n", name);
|
||||
pd->gov = &pm_domain_always_on_gov;
|
||||
pd->suspend = rmobile_pd_suspend_busy;
|
||||
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
break;
|
||||
|
||||
case PD_CONSOLE:
|
||||
@ -277,8 +268,7 @@ static void __init rmobile_setup_pm_domain(struct device_node *np,
|
||||
* is not in use.
|
||||
*/
|
||||
pr_debug("PM domain %s contains Coresight-ETM\n", name);
|
||||
pd->gov = &pm_domain_always_on_gov;
|
||||
pd->suspend = rmobile_pd_suspend_busy;
|
||||
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
break;
|
||||
|
||||
case PD_MEMCTL:
|
||||
@ -287,8 +277,7 @@ static void __init rmobile_setup_pm_domain(struct device_node *np,
|
||||
* should only be turned off if memory is not in use.
|
||||
*/
|
||||
pr_debug("PM domain %s contains MEMCTL\n", name);
|
||||
pd->gov = &pm_domain_always_on_gov;
|
||||
pd->suspend = rmobile_pd_suspend_busy;
|
||||
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
break;
|
||||
|
||||
case PD_NORMAL:
|
||||
|
@ -15,6 +15,11 @@ config MACH_STM32F429
|
||||
depends on ARCH_STM32
|
||||
default y
|
||||
|
||||
config MACH_STM32F469
|
||||
bool "STMicrolectronics STM32F469"
|
||||
depends on ARCH_STM32
|
||||
default y
|
||||
|
||||
config MACH_STM32F746
|
||||
bool "STMicrolectronics STM32F746"
|
||||
depends on ARCH_STM32
|
||||
|
@ -1,5 +1,6 @@
|
||||
menu "SOC (System On Chip) specific Drivers"
|
||||
|
||||
source "drivers/soc/actions/Kconfig"
|
||||
source "drivers/soc/atmel/Kconfig"
|
||||
source "drivers/soc/bcm/Kconfig"
|
||||
source "drivers/soc/fsl/Kconfig"
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Makefile for the Linux Kernel SOC specific device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ARCH_ACTIONS) += actions/
|
||||
obj-$(CONFIG_ARCH_AT91) += atmel/
|
||||
obj-y += bcm/
|
||||
obj-$(CONFIG_ARCH_DOVE) += dove/
|
||||
|
16
drivers/soc/actions/Kconfig
Normal file
16
drivers/soc/actions/Kconfig
Normal file
@ -0,0 +1,16 @@
|
||||
if ARCH_ACTIONS || COMPILE_TEST
|
||||
|
||||
config OWL_PM_DOMAINS_HELPER
|
||||
bool
|
||||
|
||||
config OWL_PM_DOMAINS
|
||||
bool "Actions Semi SPS power domains"
|
||||
depends on PM
|
||||
select OWL_PM_DOMAINS_HELPER
|
||||
select PM_GENERIC_DOMAINS
|
||||
help
|
||||
Say 'y' here to enable support for Smart Power System (SPS)
|
||||
power-gating on Actions Semiconductor S500 SoC.
|
||||
If unsure, say 'n'.
|
||||
|
||||
endif
|
2
drivers/soc/actions/Makefile
Normal file
2
drivers/soc/actions/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o
|
||||
obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o
|
51
drivers/soc/actions/owl-sps-helper.c
Normal file
51
drivers/soc/actions/owl-sps-helper.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Actions Semi Owl Smart Power System (SPS) shared helpers
|
||||
*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define OWL_SPS_PG_CTL 0x0
|
||||
|
||||
int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable)
|
||||
{
|
||||
u32 val;
|
||||
bool ack;
|
||||
int timeout;
|
||||
|
||||
val = readl(base + OWL_SPS_PG_CTL);
|
||||
ack = val & ack_mask;
|
||||
if (ack == enable)
|
||||
return 0;
|
||||
|
||||
if (enable)
|
||||
val |= pwr_mask;
|
||||
else
|
||||
val &= ~pwr_mask;
|
||||
|
||||
writel(val, base + OWL_SPS_PG_CTL);
|
||||
|
||||
for (timeout = 5000; timeout > 0; timeout -= 50) {
|
||||
val = readl(base + OWL_SPS_PG_CTL);
|
||||
if ((val & ack_mask) == (enable ? ack_mask : 0))
|
||||
break;
|
||||
udelay(50);
|
||||
}
|
||||
if (timeout <= 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
udelay(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(owl_sps_set_pg);
|
224
drivers/soc/actions/owl-sps.c
Normal file
224
drivers/soc/actions/owl-sps.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Actions Semi Owl Smart Power System (SPS)
|
||||
*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/soc/actions/owl-sps.h>
|
||||
#include <dt-bindings/power/owl-s500-powergate.h>
|
||||
|
||||
struct owl_sps_domain_info {
|
||||
const char *name;
|
||||
int pwr_bit;
|
||||
int ack_bit;
|
||||
unsigned int genpd_flags;
|
||||
};
|
||||
|
||||
struct owl_sps_info {
|
||||
unsigned num_domains;
|
||||
const struct owl_sps_domain_info *domains;
|
||||
};
|
||||
|
||||
struct owl_sps {
|
||||
struct device *dev;
|
||||
const struct owl_sps_info *info;
|
||||
void __iomem *base;
|
||||
struct genpd_onecell_data genpd_data;
|
||||
struct generic_pm_domain *domains[];
|
||||
};
|
||||
|
||||
#define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
|
||||
|
||||
struct owl_sps_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
const struct owl_sps_domain_info *info;
|
||||
struct owl_sps *sps;
|
||||
};
|
||||
|
||||
static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
|
||||
{
|
||||
u32 pwr_mask, ack_mask;
|
||||
|
||||
ack_mask = BIT(pd->info->ack_bit);
|
||||
pwr_mask = BIT(pd->info->pwr_bit);
|
||||
|
||||
return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
|
||||
}
|
||||
|
||||
static int owl_sps_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct owl_sps_domain *pd = to_owl_pd(domain);
|
||||
|
||||
dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
|
||||
|
||||
return owl_sps_set_power(pd, true);
|
||||
}
|
||||
|
||||
static int owl_sps_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct owl_sps_domain *pd = to_owl_pd(domain);
|
||||
|
||||
dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
|
||||
|
||||
return owl_sps_set_power(pd, false);
|
||||
}
|
||||
|
||||
static int owl_sps_init_domain(struct owl_sps *sps, int index)
|
||||
{
|
||||
struct owl_sps_domain *pd;
|
||||
|
||||
pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd)
|
||||
return -ENOMEM;
|
||||
|
||||
pd->info = &sps->info->domains[index];
|
||||
pd->sps = sps;
|
||||
|
||||
pd->genpd.name = pd->info->name;
|
||||
pd->genpd.power_on = owl_sps_power_on;
|
||||
pd->genpd.power_off = owl_sps_power_off;
|
||||
pd->genpd.flags = pd->info->genpd_flags;
|
||||
pm_genpd_init(&pd->genpd, NULL, false);
|
||||
|
||||
sps->genpd_data.domains[index] = &pd->genpd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_sps_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
const struct owl_sps_info *sps_info;
|
||||
struct owl_sps *sps;
|
||||
int i, ret;
|
||||
|
||||
if (!pdev->dev.of_node) {
|
||||
dev_err(&pdev->dev, "no device node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
|
||||
if (!match || !match->data) {
|
||||
dev_err(&pdev->dev, "unknown compatible or missing data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sps_info = match->data;
|
||||
|
||||
sps = devm_kzalloc(&pdev->dev, sizeof(*sps) +
|
||||
sps_info->num_domains * sizeof(sps->domains[0]),
|
||||
GFP_KERNEL);
|
||||
if (!sps)
|
||||
return -ENOMEM;
|
||||
|
||||
sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
|
||||
if (IS_ERR(sps->base)) {
|
||||
dev_err(&pdev->dev, "failed to map sps registers\n");
|
||||
return PTR_ERR(sps->base);
|
||||
}
|
||||
|
||||
sps->dev = &pdev->dev;
|
||||
sps->info = sps_info;
|
||||
sps->genpd_data.domains = sps->domains;
|
||||
sps->genpd_data.num_domains = sps_info->num_domains;
|
||||
|
||||
for (i = 0; i < sps_info->num_domains; i++) {
|
||||
ret = owl_sps_init_domain(sps, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add provider (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct owl_sps_domain_info s500_sps_domains[] = {
|
||||
[S500_PD_VDE] = {
|
||||
.name = "VDE",
|
||||
.pwr_bit = 0,
|
||||
.ack_bit = 16,
|
||||
},
|
||||
[S500_PD_VCE_SI] = {
|
||||
.name = "VCE_SI",
|
||||
.pwr_bit = 1,
|
||||
.ack_bit = 17,
|
||||
},
|
||||
[S500_PD_USB2_1] = {
|
||||
.name = "USB2_1",
|
||||
.pwr_bit = 2,
|
||||
.ack_bit = 18,
|
||||
},
|
||||
[S500_PD_CPU2] = {
|
||||
.name = "CPU2",
|
||||
.pwr_bit = 5,
|
||||
.ack_bit = 21,
|
||||
.genpd_flags = GENPD_FLAG_ALWAYS_ON,
|
||||
},
|
||||
[S500_PD_CPU3] = {
|
||||
.name = "CPU3",
|
||||
.pwr_bit = 6,
|
||||
.ack_bit = 22,
|
||||
.genpd_flags = GENPD_FLAG_ALWAYS_ON,
|
||||
},
|
||||
[S500_PD_DMA] = {
|
||||
.name = "DMA",
|
||||
.pwr_bit = 8,
|
||||
.ack_bit = 12,
|
||||
},
|
||||
[S500_PD_DS] = {
|
||||
.name = "DS",
|
||||
.pwr_bit = 9,
|
||||
.ack_bit = 13,
|
||||
},
|
||||
[S500_PD_USB3] = {
|
||||
.name = "USB3",
|
||||
.pwr_bit = 10,
|
||||
.ack_bit = 14,
|
||||
},
|
||||
[S500_PD_USB2_0] = {
|
||||
.name = "USB2_0",
|
||||
.pwr_bit = 11,
|
||||
.ack_bit = 15,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct owl_sps_info s500_sps_info = {
|
||||
.num_domains = ARRAY_SIZE(s500_sps_domains),
|
||||
.domains = s500_sps_domains,
|
||||
};
|
||||
|
||||
static const struct of_device_id owl_sps_of_matches[] = {
|
||||
{ .compatible = "actions,s500-sps", .data = &s500_sps_info },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver owl_sps_platform_driver = {
|
||||
.probe = owl_sps_probe,
|
||||
.driver = {
|
||||
.name = "owl-sps",
|
||||
.of_match_table = owl_sps_of_matches,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init owl_sps_init(void)
|
||||
{
|
||||
return platform_driver_register(&owl_sps_platform_driver);
|
||||
}
|
||||
postcore_initcall(owl_sps_init);
|
@ -106,6 +106,30 @@ static const struct at91_soc __initconst socs[] = {
|
||||
"sama5d43", "sama5d4"),
|
||||
AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
|
||||
"sama5d44", "sama5d4"),
|
||||
#endif
|
||||
#ifdef CONFIG_SOC_SAMV7
|
||||
AT91_SOC(SAME70Q21_CIDR_MATCH, SAME70Q21_EXID_MATCH,
|
||||
"same70q21", "same7"),
|
||||
AT91_SOC(SAME70Q20_CIDR_MATCH, SAME70Q20_EXID_MATCH,
|
||||
"same70q20", "same7"),
|
||||
AT91_SOC(SAME70Q19_CIDR_MATCH, SAME70Q19_EXID_MATCH,
|
||||
"same70q19", "same7"),
|
||||
AT91_SOC(SAMS70Q21_CIDR_MATCH, SAMS70Q21_EXID_MATCH,
|
||||
"sams70q21", "sams7"),
|
||||
AT91_SOC(SAMS70Q20_CIDR_MATCH, SAMS70Q20_EXID_MATCH,
|
||||
"sams70q20", "sams7"),
|
||||
AT91_SOC(SAMS70Q19_CIDR_MATCH, SAMS70Q19_EXID_MATCH,
|
||||
"sams70q19", "sams7"),
|
||||
AT91_SOC(SAMV71Q21_CIDR_MATCH, SAMV71Q21_EXID_MATCH,
|
||||
"samv71q21", "samv7"),
|
||||
AT91_SOC(SAMV71Q20_CIDR_MATCH, SAMV71Q20_EXID_MATCH,
|
||||
"samv71q20", "samv7"),
|
||||
AT91_SOC(SAMV71Q19_CIDR_MATCH, SAMV71Q19_EXID_MATCH,
|
||||
"samv71q19", "samv7"),
|
||||
AT91_SOC(SAMV70Q20_CIDR_MATCH, SAMV70Q20_EXID_MATCH,
|
||||
"samv70q20", "samv7"),
|
||||
AT91_SOC(SAMV70Q19_CIDR_MATCH, SAMV70Q19_EXID_MATCH,
|
||||
"samv70q19", "samv7"),
|
||||
#endif
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
@ -88,4 +88,30 @@ at91_soc_init(const struct at91_soc *socs);
|
||||
#define SAMA5D43_EXID_MATCH 0x00000003
|
||||
#define SAMA5D44_EXID_MATCH 0x00000004
|
||||
|
||||
#define SAME70Q21_CIDR_MATCH 0x21020e00
|
||||
#define SAME70Q21_EXID_MATCH 0x00000002
|
||||
#define SAME70Q20_CIDR_MATCH 0x21020c00
|
||||
#define SAME70Q20_EXID_MATCH 0x00000002
|
||||
#define SAME70Q19_CIDR_MATCH 0x210d0a00
|
||||
#define SAME70Q19_EXID_MATCH 0x00000002
|
||||
|
||||
#define SAMS70Q21_CIDR_MATCH 0x21120e00
|
||||
#define SAMS70Q21_EXID_MATCH 0x00000002
|
||||
#define SAMS70Q20_CIDR_MATCH 0x21120c00
|
||||
#define SAMS70Q20_EXID_MATCH 0x00000002
|
||||
#define SAMS70Q19_CIDR_MATCH 0x211d0a00
|
||||
#define SAMS70Q19_EXID_MATCH 0x00000002
|
||||
|
||||
#define SAMV71Q21_CIDR_MATCH 0x21220e00
|
||||
#define SAMV71Q21_EXID_MATCH 0x00000002
|
||||
#define SAMV71Q20_CIDR_MATCH 0x21220c00
|
||||
#define SAMV71Q20_EXID_MATCH 0x00000002
|
||||
#define SAMV71Q19_CIDR_MATCH 0x212d0a00
|
||||
#define SAMV71Q19_EXID_MATCH 0x00000002
|
||||
|
||||
#define SAMV70Q20_CIDR_MATCH 0x21320c00
|
||||
#define SAMV70Q20_EXID_MATCH 0x00000002
|
||||
#define SAMV70Q19_CIDR_MATCH 0x213d0a00
|
||||
#define SAMV70Q19_EXID_MATCH 0x00000002
|
||||
|
||||
#endif /* __AT91_SOC_H */
|
||||
|
19
include/dt-bindings/power/owl-s500-powergate.h
Normal file
19
include/dt-bindings/power/owl-s500-powergate.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
*/
|
||||
#ifndef DT_BINDINGS_POWER_OWL_S500_POWERGATE_H
|
||||
#define DT_BINDINGS_POWER_OWL_S500_POWERGATE_H
|
||||
|
||||
#define S500_PD_VDE 0
|
||||
#define S500_PD_VCE_SI 1
|
||||
#define S500_PD_USB2_1 2
|
||||
#define S500_PD_CPU2 3
|
||||
#define S500_PD_CPU3 4
|
||||
#define S500_PD_DMA 5
|
||||
#define S500_PD_DS 6
|
||||
#define S500_PD_USB3 7
|
||||
#define S500_PD_USB2_0 8
|
||||
|
||||
#endif
|
@ -7,9 +7,6 @@
|
||||
#ifndef __ATMEL_H__
|
||||
#define __ATMEL_H__
|
||||
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
/* Compact Flash */
|
||||
struct at91_cf_data {
|
||||
int irq_pin; /* I/O IRQ */
|
||||
@ -22,26 +19,14 @@ struct at91_cf_data {
|
||||
#define AT91_IDE_SWAP_A0_A2 0x02
|
||||
};
|
||||
|
||||
/* NAND / SmartMedia */
|
||||
struct atmel_nand_data {
|
||||
int enable_pin; /* chip enable */
|
||||
int det_pin; /* card detect */
|
||||
int rdy_pin; /* ready/busy */
|
||||
u8 rdy_pin_active_low; /* rdy_pin value is inverted */
|
||||
u8 ale; /* address line number connected to ALE */
|
||||
u8 cle; /* address line number connected to CLE */
|
||||
u8 bus_width_16; /* buswidth is 16 bit */
|
||||
u8 ecc_mode; /* ecc mode */
|
||||
u8 on_flash_bbt; /* bbt on flash */
|
||||
struct mtd_partition *parts;
|
||||
unsigned int num_parts;
|
||||
bool has_dma; /* support dma transfer */
|
||||
|
||||
/* default is false, only for at32ap7000 chip is true */
|
||||
bool need_reset_workaround;
|
||||
};
|
||||
|
||||
/* FIXME: this needs a better location, but gets stuff building again */
|
||||
#ifdef CONFIG_ATMEL_PM
|
||||
extern int at91_suspend_entering_slow_clock(void);
|
||||
#else
|
||||
static inline int at91_suspend_entering_slow_clock(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ATMEL_H__ */
|
||||
|
11
include/linux/soc/actions/owl-sps.h
Normal file
11
include/linux/soc/actions/owl-sps.h
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#ifndef SOC_ACTIONS_OWL_SPS_H
|
||||
#define SOC_ACTIONS_OWL_SPS_H
|
||||
|
||||
int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user