Commit 56e04649 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC platform updates from Olof Johansson:
 "New and/or improved SoC support for this release:

  Marvell Berlin:
     - Enable standard DT-based cpufreq
     - Add CPU hotplug support

  Freescale:
     - Ethernet init for i.MX7D
     - Suspend/resume support for i.MX6UL

  Allwinner:
     - Support for R8 chipset (used on NTC's $9 C.H.I.P board)

  Mediatek:
     - SMP support for some platforms

  Uniphier:
     - L2 support
     - Cleaned up SMP support, etc.

  plus a handful of other patches around above functionality, and a few
  other smaller changes"

* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (42 commits)
  ARM: uniphier: rework SMP operations to use trampoline code
  ARM: uniphier: add outer cache support
  Documentation: EXYNOS: Update bootloader interface on exynos542x
  ARM: mvebu: add broken-idle option
  ARM: orion5x: use mac_pton() helper
  ARM: at91: pm: at91_pm_suspend_in_sram() must be 8-byte aligned
  ARM: sunxi: Add R8 support
  ARM: digicolor: select pinctrl/gpio driver
  arm: berlin: add CPU hotplug support
  arm: berlin: use non-self-cleared reset register to reset cpu
  ARM: mediatek: add smp bringup code
  ARM: mediatek: enable gpt6 on boot up to make arch timer working
  soc: mediatek: Fix random hang up issue while kernel init
  soc: ti: qmss: make acc queue support optional in the driver
  soc: ti: add firmware file name as part of the driver
  Documentation: dt: soc: Add description for knav qmss driver
  ARM: S3C64XX: Use PWM lookup table for mach-smartq
  ARM: S3C64XX: Use PWM lookup table for mach-hmt
  ARM: S3C64XX: Use PWM lookup table for mach-crag6410
  ARM: S3C64XX: Use PWM lookup table for smdk6410
  ...
parents a5e1d715 b1e4006a
...@@ -19,7 +19,7 @@ executing kernel. ...@@ -19,7 +19,7 @@ executing kernel.
Address: sysram_ns_base_addr Address: sysram_ns_base_addr
Offset Value Purpose Offset Value Purpose
============================================================================= =============================================================================
0x08 exynos_cpu_resume_ns System suspend 0x08 exynos_cpu_resume_ns, mcpm_entry_point System suspend
0x0c 0x00000bad (Magic cookie) System suspend 0x0c 0x00000bad (Magic cookie) System suspend
0x1c exynos4_secondary_startup Secondary CPU boot 0x1c exynos4_secondary_startup Secondary CPU boot
0x1c + 4*cpu exynos4_secondary_startup (Exynos4412) Secondary CPU boot 0x1c + 4*cpu exynos4_secondary_startup (Exynos4412) Secondary CPU boot
...@@ -56,7 +56,8 @@ Offset Value Purpose ...@@ -56,7 +56,8 @@ Offset Value Purpose
Address: pmu_base_addr Address: pmu_base_addr
Offset Value Purpose Offset Value Purpose
============================================================================= =============================================================================
0x0908 Non-zero (only Exynos3250) Secondary CPU boot up indicator 0x0908 Non-zero Secondary CPU boot up indicator
on Exynos3250 and Exynos542x
4. Glossary 4. Glossary
......
* Texas Instruments Keystone Navigator Queue Management SubSystem driver
Driver source code path
drivers/soc/ti/knav_qmss.c
drivers/soc/ti/knav_qmss_acc.c
The QMSS (Queue Manager Sub System) found on Keystone SOCs is one of
the main hardware sub system which forms the backbone of the Keystone
multi-core Navigator. QMSS consist of queue managers, packed-data structure
processors(PDSP), linking RAM, descriptor pools and infrastructure
Packet DMA.
The Queue Manager is a hardware module that is responsible for accelerating
management of the packet queues. Packets are queued/de-queued by writing or
reading descriptor address to a particular memory mapped location. The PDSPs
perform QMSS related functions like accumulation, QoS, or event management.
Linking RAM registers are used to link the descriptors which are stored in
descriptor RAM. Descriptor RAM is configurable as internal or external memory.
The QMSS driver manages the PDSP setups, linking RAM regions,
queue pool management (allocation, push, pop and notify) and descriptor
pool management.
knav qmss driver provides a set of APIs to drivers to open/close qmss queues,
allocate descriptor pools, map the descriptors, push/pop to queues etc. For
details of the available APIs, please refers to include/linux/soc/ti/knav_qmss.h
DT documentation is available at
Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
Accumulator QMSS queues using PDSP firmware
============================================
The QMSS PDSP firmware support accumulator channel that can monitor a single
queue or multiple contiguous queues. drivers/soc/ti/knav_qmss_acc.c is the
driver that interface with the accumulator PDSP. This configures
accumulator channels defined in DTS (example in DT documentation) to monitor
1 or 32 queues per channel. More description on the firmware is available in
CPPI/QMSS Low Level Driver document (docs/CPPI_QMSS_LLD_SDS.pdf) at
git://git.ti.com/keystone-rtos/qmss-lld.git
k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports upto 48 accumulator
channels. This firmware is available under ti-keystone folder of
firmware.git at
git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
To use copy the firmware image to lib/firmware folder of the initramfs or
ubifs file system and provide a sym link to k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin
in the file system and boot up the kernel. User would see
"firmware file ks2_qmss_pdsp_acc48.bin downloaded for PDSP"
in the boot up log if loading of firmware to PDSP is successful.
Use of accumulated queues requires the firmware image to be present in the
file system. The driver doesn't acc queues to the supported queue range if
PDSP is not running in the SoC. The API call fails if there is a queue open
request to an acc queue and PDSP is not running. So make sure to copy firmware
to file system before using these queue types.
...@@ -25,7 +25,7 @@ SunXi family ...@@ -25,7 +25,7 @@ SunXi family
+ Datasheet + Datasheet
http://dl.linux-sunxi.org/A10s/A10s%20Datasheet%20-%20v1.20%20%282012-03-27%29.pdf http://dl.linux-sunxi.org/A10s/A10s%20Datasheet%20-%20v1.20%20%282012-03-27%29.pdf
- Allwinner A13 (sun5i) - Allwinner A13 / R8 (sun5i)
+ Datasheet + Datasheet
http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
+ User Manual + User Manual
......
...@@ -27,6 +27,11 @@ Required properties: ...@@ -27,6 +27,11 @@ Required properties:
* For "marvell,armada-380-coherency-fabric", only one pair is needed * For "marvell,armada-380-coherency-fabric", only one pair is needed
for the per-CPU fabric registers. for the per-CPU fabric registers.
Optional properties:
- broken-idle: boolean to set when the Idle mode is not supported by the
hardware.
Examples: Examples:
coherency-fabric@d0020200 { coherency-fabric@d0020200 {
......
MVEBU CPU Config registers
--------------------------
MVEBU (Marvell SOCs: Armada 370/XP)
Required properties:
- compatible: one of:
- "marvell,armada-370-cpu-config"
- "marvell,armada-xp-cpu-config"
- reg: Should contain CPU config registers location and length, in
their per-CPU variant
Example:
cpu-config@21000 {
compatible = "marvell,armada-xp-cpu-config";
reg = <0x21000 0x8>;
};
...@@ -6,6 +6,7 @@ using one of the following compatible strings: ...@@ -6,6 +6,7 @@ using one of the following compatible strings:
allwinner,sun4i-a10 allwinner,sun4i-a10
allwinner,sun5i-a10s allwinner,sun5i-a10s
allwinner,sun5i-a13 allwinner,sun5i-a13
allwinner,sun5i-r8
allwinner,sun6i-a31 allwinner,sun6i-a31
allwinner,sun7i-a20 allwinner,sun7i-a20
allwinner,sun8i-a23 allwinner,sun8i-a23
......
UniPhier outer cache controller
UniPhier SoCs are integrated with a full-custom outer cache controller system.
All of them have a level 2 cache controller, and some have a level 3 cache
controller as well.
Required properties:
- compatible: should be "socionext,uniphier-system-cache"
- reg: offsets and lengths of the register sets for the device. It should
contain 3 regions: control register, revision register, operation register,
in this order.
- cache-unified: specifies the cache is a unified cache.
- cache-size: specifies the size in bytes of the cache
- cache-sets: specifies the number of associativity sets of the cache
- cache-line-size: specifies the line size in bytes
- cache-level: specifies the level in the cache hierarchy. The value should
be 2 for L2 cache, 3 for L3 cache, etc.
Optional properties:
- next-level-cache: phandle to the next level cache if present. The next level
cache should be also compatible with "socionext,uniphier-system-cache".
The L2 cache must exist to use the L3 cache; the cache hierarchy must be
indicated correctly with "next-level-cache" properties.
Example 1 (system with L2):
l2: l2-cache@500c0000 {
compatible = "socionext,uniphier-system-cache";
reg = <0x500c0000 0x2000>, <0x503c0100 0x4>,
<0x506c0000 0x400>;
cache-unified;
cache-size = <0x80000>;
cache-sets = <256>;
cache-line-size = <128>;
cache-level = <2>;
};
Example 2 (system with L2 and L3):
l2: l2-cache@500c0000 {
compatible = "socionext,uniphier-system-cache";
reg = <0x500c0000 0x2000>, <0x503c0100 0x8>,
<0x506c0000 0x400>;
cache-unified;
cache-size = <0x200000>;
cache-sets = <512>;
cache-line-size = <128>;
cache-level = <2>;
next-level-cache = <&l3>;
};
l3: l3-cache@500c8000 {
compatible = "socionext,uniphier-system-cache";
reg = <0x500c8000 0x2000>, <0x503c8100 0x8>,
<0x506c8000 0x400>;
cache-unified;
cache-size = <0x400000>;
cache-sets = <512>;
cache-line-size = <256>;
cache-level = <3>;
};
...@@ -221,7 +221,6 @@ qmss: qmss@2a40000 { ...@@ -221,7 +221,6 @@ qmss: qmss@2a40000 {
#size-cells = <1>; #size-cells = <1>;
ranges; ranges;
pdsp0@0x2a10000 { pdsp0@0x2a10000 {
firmware = "keystone/qmss_pdsp_acc48_k2_le_1_0_0_8.fw";
reg = <0x2a10000 0x1000>, reg = <0x2a10000 0x1000>,
<0x2a0f000 0x100>, <0x2a0f000 0x100>,
<0x2a0c000 0x3c8>, <0x2a0c000 0x3c8>,
......
...@@ -920,7 +920,7 @@ M: Tsahee Zidenberg <tsahee@annapurnalabs.com> ...@@ -920,7 +920,7 @@ M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
S: Maintained S: Maintained
F: arch/arm/mach-alpine/ F: arch/arm/mach-alpine/
ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
M: Nicolas Ferre <nicolas.ferre@atmel.com> M: Nicolas Ferre <nicolas.ferre@atmel.com>
M: Alexandre Belloni <alexandre.belloni@free-electrons.com> M: Alexandre Belloni <alexandre.belloni@free-electrons.com>
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com> M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
...@@ -1630,7 +1630,9 @@ M: Masahiro Yamada <yamada.masahiro@socionext.com> ...@@ -1630,7 +1630,9 @@ M: Masahiro Yamada <yamada.masahiro@socionext.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/boot/dts/uniphier* F: arch/arm/boot/dts/uniphier*
F: arch/arm/include/asm/hardware/cache-uniphier.h
F: arch/arm/mach-uniphier/ F: arch/arm/mach-uniphier/
F: arch/arm/mm/cache-uniphier.c
F: drivers/i2c/busses/i2c-uniphier* F: drivers/i2c/busses/i2c-uniphier*
F: drivers/pinctrl/uniphier/ F: drivers/pinctrl/uniphier/
F: drivers/tty/serial/8250/8250_uniphier.c F: drivers/tty/serial/8250/8250_uniphier.c
......
...@@ -123,29 +123,23 @@ choice ...@@ -123,29 +123,23 @@ choice
0x80020000 | 0xf0020000 | UART8 0x80020000 | 0xf0020000 | UART8
0x80024000 | 0xf0024000 | UART9 0x80024000 | 0xf0024000 | UART9
config AT91_DEBUG_LL_DBGU0 config DEBUG_AT91_UART
bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10, 9rl, 9x5, 9n12" bool "Kernel low-level debugging on Atmel SoCs"
select DEBUG_AT91_UART
depends on ARCH_AT91 depends on ARCH_AT91
depends on SOC_AT91RM9200 || SOC_AT91SAM9 help
Say Y here if you want the debug print routines to direct
config AT91_DEBUG_LL_DBGU1 their output to the serial port on atmel devices.
bool "Kernel low-level debugging on 9263, 9g45 and sama5d3"
select DEBUG_AT91_UART
depends on ARCH_AT91
depends on SOC_AT91SAM9 || SOC_SAMA5
config AT91_DEBUG_LL_DBGU2 SOC DEBUG_UART_PHYS DEBUG_UART_VIRT PORT
bool "Kernel low-level debugging on sama5d4" rm9200, 9260/9g20, 0xfffff200 0xfefff200 DBGU
select DEBUG_AT91_UART 9261/9g10, 9rl
depends on ARCH_AT91 9263, 9g45, sama5d3 0xffffee00 0xfeffee00 DBGU
depends on SOC_SAMA5 sama5d4 0xfc00c000 0xfb00c000 USART3
sama5d4 0xfc069000 0xfb069000 DBGU
sama5d2 0xf8020000 0xf7020000 UART1
config AT91_DEBUG_LL_DBGU3 Please adjust DEBUG_UART_PHYS configuration options based on
bool "Kernel low-level debugging on sama5d2" your needs.
select DEBUG_AT91_UART
depends on ARCH_AT91
depends on SOC_SAMA5
config DEBUG_BCM2835 config DEBUG_BCM2835
bool "Kernel low-level debugging on BCM2835 PL011 UART" bool "Kernel low-level debugging on BCM2835 PL011 UART"
...@@ -1249,10 +1243,6 @@ choice ...@@ -1249,10 +1243,6 @@ choice
endchoice endchoice
config DEBUG_AT91_UART
bool
depends on ARCH_AT91
config DEBUG_EXYNOS_UART config DEBUG_EXYNOS_UART
bool bool
...@@ -1485,7 +1475,8 @@ config DEBUG_UART_PHYS ...@@ -1485,7 +1475,8 @@ config DEBUG_UART_PHYS
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \ DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \ DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
DEBUG_AT91_UART
config DEBUG_UART_VIRT config DEBUG_UART_VIRT
hex "Virtual base address of debug UART" hex "Virtual base address of debug UART"
......
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __CACHE_UNIPHIER_H
#define __CACHE_UNIPHIER_H
#include <linux/types.h>
#ifdef CONFIG_CACHE_UNIPHIER
int uniphier_cache_init(void);
int uniphier_cache_l2_is_enabled(void);
void uniphier_cache_l2_touch_range(unsigned long start, unsigned long end);
void uniphier_cache_l2_set_locked_ways(u32 way_mask);
#else
static inline int uniphier_cache_init(void)
{
return -ENODEV;
}
static inline int uniphier_cache_l2_is_enabled(void)
{
return 0;
}
static inline void uniphier_cache_l2_touch_range(unsigned long start,
unsigned long end)
{
}
static inline void uniphier_cache_l2_set_locked_ways(u32 way_mask)
{
}
#endif
#endif /* __CACHE_UNIPHIER_H */
...@@ -9,32 +9,22 @@ ...@@ -9,32 +9,22 @@
* *
*/ */
#if defined(CONFIG_AT91_DEBUG_LL_DBGU0)
#define AT91_DBGU 0xfffff200 /* AT91_BASE_DBGU0 */
#elif defined(CONFIG_AT91_DEBUG_LL_DBGU1)
#define AT91_DBGU 0xffffee00 /* AT91_BASE_DBGU1 */
#elif defined(CONFIG_AT91_DEBUG_LL_DBGU2)
/* On sama5d4, use USART3 as low level serial console */
#define AT91_DBGU 0xfc00c000 /* SAMA5D4_BASE_USART3 */
#else
/* On sama5d2, use UART1 as low level serial console */
#define AT91_DBGU 0xf8020000
#endif
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
#define AT91_IO_P2V(x) ((x) - 0x01000000) #define AT91_IO_P2V(x) ((x) - 0x01000000)
#else #else
#define AT91_IO_P2V(x) (x) #define AT91_IO_P2V(x) (x)
#endif #endif
#define CONFIG_DEBUG_UART_VIRT AT91_IO_P2V(CONFIG_DEBUG_UART_PHYS)
#define AT91_DBGU_SR (0x14) /* Status Register */ #define AT91_DBGU_SR (0x14) /* Status Register */
#define AT91_DBGU_THR (0x1c) /* Transmitter Holding Register */ #define AT91_DBGU_THR (0x1c) /* Transmitter Holding Register */
#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */ #define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */
#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */ #define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */
.macro addruart, rp, rv, tmp .macro addruart, rp, rv, tmp
ldr \rp, =AT91_DBGU @ System peripherals (phys address) ldr \rp, =CONFIG_DEBUG_UART_PHYS @ System peripherals (phys address)
ldr \rv, =AT91_IO_P2V(AT91_DBGU) @ System peripherals (virt address) ldr \rv, =CONFIG_DEBUG_UART_VIRT @ System peripherals (virt address)
.endm .endm
.macro senduart,rd,rx .macro senduart,rd,rx
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/cache-uniphier.h>
#include <asm/outercache.h> #include <asm/outercache.h>
#include <asm/exception.h> #include <asm/exception.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -97,6 +98,8 @@ void __init init_IRQ(void) ...@@ -97,6 +98,8 @@ void __init init_IRQ(void)
if (ret) if (ret)
pr_err("L2C: failed to init: %d\n", ret); pr_err("L2C: failed to init: %d\n", ret);
} }
uniphier_cache_init();
} }
#ifdef CONFIG_MULTI_IRQ_HANDLER #ifdef CONFIG_MULTI_IRQ_HANDLER
......
...@@ -80,6 +80,8 @@ tmp2 .req r5 ...@@ -80,6 +80,8 @@ tmp2 .req r5
* @r2: base address of second SDRAM Controller or 0 if not present * @r2: base address of second SDRAM Controller or 0 if not present
* @r3: pm information * @r3: pm information
*/ */
/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
.align 3
ENTRY(at91_pm_suspend_in_sram) ENTRY(at91_pm_suspend_in_sram)
/* Save registers on stack */ /* Save registers on stack */
stmfd sp!, {r4 - r12, lr} stmfd sp!, {r4 - r12, lr}
......
...@@ -35,6 +35,20 @@ config ARCH_BCM_CYGNUS ...@@ -35,6 +35,20 @@ config ARCH_BCM_CYGNUS
BCM11300, BCM11320, BCM11350, BCM11360, BCM11300, BCM11320, BCM11350, BCM11360,
BCM58300, BCM58302, BCM58303, BCM58305. BCM58300, BCM58302, BCM58303, BCM58305.
config ARCH_BCM_NSP
bool "Broadcom Northstar Plus SoC Support" if ARCH_MULTI_V7
select ARCH_BCM_IPROC
select ARM_ERRATA_754322
select ARM_ERRATA_775420
help
Support for Broadcom Northstar Plus SoC.
Broadcom Northstar Plus family of SoCs are used for switching control
and management applications as well as residential router/gateway
applications. The SoC features dual core Cortex A9 ARM CPUs,
integrating several peripheral interfaces including multiple Gigabit
Ethernet PHYs, DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and
NAND flash, SATA and several other IO controllers.
config ARCH_BCM_5301X config ARCH_BCM_5301X
bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
select ARCH_BCM_IPROC select ARCH_BCM_IPROC
...@@ -147,6 +161,7 @@ config ARCH_BRCMSTB ...@@ -147,6 +161,7 @@ config ARCH_BRCMSTB
select BCM7120_L2_IRQ select BCM7120_L2_IRQ
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
help help
Say Y if you intend to run the kernel on a Broadcom ARM-based STB Say Y if you intend to run the kernel on a Broadcom ARM-based STB
chipset. chipset.
......
# #
# Copyright (C) 2012-2014 Broadcom Corporation # Copyright (C) 2012-2015 Broadcom Corporation
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as # modify it under the terms of the GNU General Public License as
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
# Cygnus # Cygnus
obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o
# Northstar Plus
obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o
# BCM281XX # BCM281XX
obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o
......
/*
* Copyright (C) 2015 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* 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 <asm/mach/arch.h>
static const char *const bcm_nsp_dt_compat[] __initconst = {
"brcm,nsp",
NULL,
};
DT_MACHINE_START(NSP_DT, "Broadcom Northstar Plus SoC")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.dt_compat = bcm_nsp_dt_compat,
MACHINE_END
...@@ -12,11 +12,19 @@ ...@@ -12,11 +12,19 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/irqchip.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/soc/brcmstb/brcmstb.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
static void __init brcmstb_init_irq(void)
{
irqchip_init();
brcmstb_biuctrl_init();
}
static const char *const brcmstb_match[] __initconst = { static const char *const brcmstb_match[] __initconst = {
"brcm,bcm7445", "brcm,bcm7445",
"brcm,brcmstb", "brcm,brcmstb",
...@@ -25,4 +33,5 @@ static const char *const brcmstb_match[] __initconst = { ...@@ -25,4 +33,5 @@ static const char *const brcmstb_match[] __initconst = {
DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)") DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
.dt_compat = brcmstb_match, .dt_compat = brcmstb_match,
.init_irq = brcmstb_init_irq,
MACHINE_END MACHINE_END
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
static void __init berlin_init_late(void)
{
platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
}
static const char * const berlin_dt_compat[] = { static const char * const berlin_dt_compat[] = {
"marvell,berlin", "marvell,berlin",
NULL, NULL,
...@@ -25,6 +30,7 @@ static const char * const berlin_dt_compat[] = { ...@@ -25,6 +30,7 @@ static const char * const berlin_dt_compat[] = {
DT_MACHINE_START(BERLIN_DT, "Marvell Berlin") DT_MACHINE_START(BERLIN_DT, "Marvell Berlin")
.dt_compat = berlin_dt_compat, .dt_compat = berlin_dt_compat,
.init_late = berlin_init_late,
/* /*
* with DT probing for L2CCs, berlin_init_machine can be removed. * with DT probing for L2CCs, berlin_init_machine can be removed.
* Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc
......
...@@ -14,10 +14,16 @@ ...@@ -14,10 +14,16 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#define CPU_RESET 0x00 /*
* There are two reset registers, one with self-clearing (SC)
* reset and one with non-self-clearing reset (NON_SC).
*/
#define CPU_RESET_SC 0x00
#define CPU_RESET_NON_SC 0x20
#define RESET_VECT 0x00 #define RESET_VECT 0x00
#define SW_RESET_ADDR 0x94 #define SW_RESET_ADDR 0x94
...@@ -30,9 +36,11 @@ static inline void berlin_perform_reset_cpu(unsigned int cpu) ...@@ -30,9 +36,11 @@ static inline void berlin_perform_reset_cpu(unsigned int cpu)
{ {
u32 val; u32 val;
val = readl(cpu_ctrl + CPU_RESET); val = readl(cpu_ctrl + CPU_RESET_NON_SC);
val &= ~BIT(cpu_logical_map(cpu));
writel(val, cpu_ctrl + CPU_RESET_NON_SC);
val |= BIT(cpu_logical_map(cpu)); val |= BIT(cpu_logical_map(cpu));
writel(val, cpu_ctrl + CPU_RESET); writel(val, cpu_ctrl + CPU_RESET_NON_SC);
} }
static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle) static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
...@@ -91,8 +99,32 @@ static void __init berlin_smp_prepare_cpus(unsigned int max_cpus) ...@@ -91,8 +99,32 @@ static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
iounmap(scu_base); iounmap(scu_base);
} }
#ifdef CONFIG_HOTPLUG_CPU
static void berlin_cpu_die(unsigned int cpu)
{
v7_exit_coherency_flush(louis);
while (1)
cpu_do_idle();
}
static int berlin_cpu_kill(unsigned int cpu)
{
u32 val;
val = readl(cpu_ctrl + CPU_RESET_NON_SC);
val &= ~BIT(cpu_logical_map(cpu));
writel(val, cpu_ctrl + CPU_RESET_NON_SC);
return 1;
}
#endif
static struct smp_operations berlin_smp_ops __initdata = { static struct smp_operations berlin_smp_ops __initdata = {
.smp_prepare_cpus = berlin_smp_prepare_cpus, .smp_prepare_cpus = berlin_smp_prepare_cpus,
.smp_boot_secondary = berlin_boot_secondary, .smp_boot_secondary = berlin_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = berlin_cpu_die,
.cpu_kill = berlin_cpu_kill,
#endif
}; };
CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops); CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);
config ARCH_DIGICOLOR config ARCH_DIGICOLOR
bool "Conexant Digicolor SoC Support" bool "Conexant Digicolor SoC Support"
depends on ARCH_MULTI_V7 depends on ARCH_MULTI_V7
select ARCH_REQUIRE_GPIOLIB
select CLKSRC_MMIO select CLKSRC_MMIO
select DIGICOLOR_TIMER select DIGICOLOR_TIMER
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
select MFD_SYSCON select MFD_SYSCON
select PINCTRL
select PINCTRL_DIGICOLOR
...@@ -131,6 +131,7 @@ void imx6q_pm_init(void); ...@@ -131,6 +131,7 @@ void imx6q_pm_init(void);
void imx6dl_pm_init(void); void imx6dl_pm_init(void);
void imx6sl_pm_init(void); void imx6sl_pm_init(void);
void imx6sx_pm_init(void); void imx6sx_pm_init(void);
void imx6ul_pm_init(void);
#ifdef CONFIG_PM #ifdef CONFIG_PM
void imx51_pm_init(void); void imx51_pm_init(void);
......
...@@ -67,6 +67,7 @@ static void __init imx6ul_init_machine(void) ...@@ -67,6 +67,7 @@ static void __init imx6ul_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
imx6ul_enet_init(); imx6ul_enet_init();
imx_anatop_init(); imx_anatop_init();
imx6ul_pm_init();
} }
static void __init imx6ul_init_irq(void) static void __init imx6ul_init_irq(void)
...@@ -74,6 +75,13 @@ static void __init imx6ul_init_irq(void) ...@@ -74,6 +75,13 @@ static void __init imx6ul_init_irq(void)
imx_init_revision_from_anatop(); imx_init_revision_from_anatop();
imx_src_init(); imx_src_init();
irqchip_init(); irqchip_init();
imx6_pm_ccm_init("fsl,imx6ul-ccm");
}
static void __init imx6ul_init_late(void)
{
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
} }
static const char *imx6ul_dt_compat[] __initconst = { static const char *imx6ul_dt_compat[] __initconst = {
...@@ -84,5 +92,6 @@ static const char *imx6ul_dt_compat[] __initconst = { ...@@ -84,5 +92,6 @@ static const char *imx6ul_dt_compat[] __initconst = {
DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)") DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
.init_irq = imx6ul_init_irq, .init_irq = imx6ul_init_irq,
.init_machine = imx6ul_init_machine, .init_machine = imx6ul_init_machine,
.init_late = imx6ul_init_late,
.dt_compat = imx6ul_dt_compat, .dt_compat = imx6ul_dt_compat,
MACHINE_END MACHINE_END
...@@ -6,12 +6,85 @@ ...@@ -6,12 +6,85 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/irqchip.h> #include <linux/irqchip.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/phy.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include "common.h" #include "common.h"
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
/* Set RGMII IO voltage to 1.8V */
phy_write(dev, 0x1d, 0x1f);
phy_write(dev, 0x1e, 0x8);
/* disable phy AR8031 SmartEEE function. */
phy_write(dev, 0xd, 0x3);
phy_write(dev, 0xe, 0x805d);
phy_write(dev, 0xd, 0x4003);
val = phy_read(dev, 0xe);
val &= ~(0x1 << 8);
phy_write(dev, 0xe, val);
/* introduce tx clock delay */
phy_write(dev, 0x1d, 0x5);
val = phy_read(dev, 0x1e);
val |= 0x0100;
phy_write(dev, 0x1e, val);
return 0;
}
static int bcm54220_phy_fixup(struct phy_device *dev)
{
/* enable RXC skew select RGMII copper mode */
phy_write(dev, 0x1e, 0x21);
phy_write(dev, 0x1f, 0x7ea8);
phy_write(dev, 0x1e, 0x2f);
phy_write(dev, 0x1f, 0x71b7);
return 0;
}
#define PHY_ID_AR8031 0x004dd074
#define PHY_ID_BCM54220 0x600d8589
static void __init imx7d_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff,
bcm54220_phy_fixup);
}
}
static void __init imx7d_enet_clk_sel(void)
{
struct regmap *gpr;
gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");
if (!IS_ERR(gpr)) {
regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0);
regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, 0);
} else {
pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n");
}
}
static inline void imx7d_enet_init(void)
{
imx7d_enet_phy_init();
imx7d_enet_clk_sel();
}
static void __init imx7d_init_machine(void) static void __init imx7d_init_machine(void)
{ {
struct device *parent; struct device *parent;
...@@ -22,6 +95,7 @@ static void __init imx7d_init_machine(void) ...@@ -22,6 +95,7 @@ static void __init imx7d_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
imx_anatop_init(); imx_anatop_init();
imx7d_enet_init();
} }
static void __init imx7d_init_irq(void) static void __init imx7d_init_irq(void)
......
...@@ -93,6 +93,7 @@ struct imx6_pm_socdata { ...@@ -93,6 +93,7 @@ struct imx6_pm_socdata {
const char *src_compat; const char *src_compat;
const char *iomuxc_compat; const char *iomuxc_compat;
const char *gpc_compat; const char *gpc_compat;
const char *pl310_compat;
const u32 mmdc_io_num; const u32 mmdc_io_num;
const u32 *mmdc_io_offset; const u32 *mmdc_io_offset;
}; };
...@@ -137,11 +138,19 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = { ...@@ -137,11 +138,19 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */ 0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
}; };
static const u32 imx6ul_mmdc_io_offset[] __initconst = {
0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */
0x494, 0x4b0, /* MODE_CTL, MODE, */
};
static const struct imx6_pm_socdata imx6q_pm_data __initconst = { static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.mmdc_compat = "fsl,imx6q-mmdc", .mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src", .src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6q-iomuxc", .iomuxc_compat = "fsl,imx6q-iomuxc",
.gpc_compat = "fsl,imx6q-gpc", .gpc_compat = "fsl,imx6q-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset), .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
.mmdc_io_offset = imx6q_mmdc_io_offset, .mmdc_io_offset = imx6q_mmdc_io_offset,
}; };
...@@ -151,6 +160,7 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = { ...@@ -151,6 +160,7 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
.src_compat = "fsl,imx6q-src", .src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6dl-iomuxc", .iomuxc_compat = "fsl,imx6dl-iomuxc",
.gpc_compat = "fsl,imx6q-gpc", .gpc_compat = "fsl,imx6q-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset), .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
.mmdc_io_offset = imx6dl_mmdc_io_offset, .mmdc_io_offset = imx6dl_mmdc_io_offset,
}; };
...@@ -160,6 +170,7 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = { ...@@ -160,6 +170,7 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
.src_compat = "fsl,imx6sl-src", .src_compat = "fsl,imx6sl-src",
.iomuxc_compat = "fsl,imx6sl-iomuxc", .iomuxc_compat = "fsl,imx6sl-iomuxc",
.gpc_compat = "fsl,imx6sl-gpc", .gpc_compat = "fsl,imx6sl-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset), .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
.mmdc_io_offset = imx6sl_mmdc_io_offset, .mmdc_io_offset = imx6sl_mmdc_io_offset,
}; };
...@@ -169,10 +180,21 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = { ...@@ -169,10 +180,21 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
.src_compat = "fsl,imx6sx-src", .src_compat = "fsl,imx6sx-src",
.iomuxc_compat = "fsl,imx6sx-iomuxc", .iomuxc_compat = "fsl,imx6sx-iomuxc",
.gpc_compat = "fsl,imx6sx-gpc", .gpc_compat = "fsl,imx6sx-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset), .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
.mmdc_io_offset = imx6sx_mmdc_io_offset, .mmdc_io_offset = imx6sx_mmdc_io_offset,
}; };
static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
.mmdc_compat = "fsl,imx6ul-mmdc",
.src_compat = "fsl,imx6ul-src",
.iomuxc_compat = "fsl,imx6ul-iomuxc",
.gpc_compat = "fsl,imx6ul-gpc",
.pl310_compat = NULL,
.mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
.mmdc_io_offset = imx6ul_mmdc_io_offset,
};
/* /*
* This structure is for passing necessary data for low level ocram * This structure is for passing necessary data for low level ocram
* suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
...@@ -290,7 +312,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) ...@@ -290,7 +312,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= BM_CLPCR_SBYOS; val |= BM_CLPCR_SBYOS;
if (cpu_is_imx6sl()) if (cpu_is_imx6sl())
val |= BM_CLPCR_BYPASS_PMIC_READY; val |= BM_CLPCR_BYPASS_PMIC_READY;
if (cpu_is_imx6sl() || cpu_is_imx6sx()) if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
else else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
...@@ -330,6 +352,10 @@ static int imx6q_suspend_finish(unsigned long val) ...@@ -330,6 +352,10 @@ static int imx6q_suspend_finish(unsigned long val)
* as we need to float DDR IO. * as we need to float DDR IO.
*/ */
local_flush_tlb_all(); local_flush_tlb_all();
/* check if need to flush internal L2 cache */
if (!((struct imx6_cpu_pm_info *)
suspend_ocram_base)->l2_base.vbase)
flush_cache_all();
imx6_suspend_in_ocram_fn(suspend_ocram_base); imx6_suspend_in_ocram_fn(suspend_ocram_base);
} }
...@@ -470,6 +496,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) ...@@ -470,6 +496,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
suspend_ocram_base = __arm_ioremap_exec(ocram_pbase, suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
MX6Q_SUSPEND_OCRAM_SIZE, false); MX6Q_SUSPEND_OCRAM_SIZE, false);
memset(suspend_ocram_base, 0, sizeof(*pm_info));
pm_info = suspend_ocram_base; pm_info = suspend_ocram_base;
pm_info->pbase = ocram_pbase; pm_info->pbase = ocram_pbase;
pm_info->resume_addr = virt_to_phys(v7_cpu_resume); pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
...@@ -505,12 +532,14 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) ...@@ -505,12 +532,14 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
goto gpc_map_failed; goto gpc_map_failed;
} }
ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache"); if (socdata->pl310_compat) {
ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
if (ret) { if (ret) {
pr_warn("%s: failed to get pl310-cache base %d!\n", pr_warn("%s: failed to get pl310-cache base %d!\n",
__func__, ret); __func__, ret);
goto pl310_cache_map_failed; goto pl310_cache_map_failed;
} }
}
pm_info->ddr_type = imx_mmdc_get_ddr_type(); pm_info->ddr_type = imx_mmdc_get_ddr_type();
pm_info->mmdc_io_num = socdata->mmdc_io_num; pm_info->mmdc_io_num = socdata->mmdc_io_num;
...@@ -610,3 +639,8 @@ void __init imx6sx_pm_init(void) ...@@ -610,3 +639,8 @@ void __init imx6sx_pm_init(void)
{ {
imx6_pm_common_init(&imx6sx_pm_data); imx6_pm_common_init(&imx6sx_pm_data);
} }
void __init imx6ul_pm_init(void)
{
imx6_pm_common_init(&imx6ul_pm_data);
}
...@@ -79,12 +79,15 @@ ...@@ -79,12 +79,15 @@
/* sync L2 cache to drain L2's buffers to DRAM. */ /* sync L2 cache to drain L2's buffers to DRAM. */
#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_CACHE_L2X0
ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET] ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
teq r11, #0
beq 6f
mov r6, #0x0 mov r6, #0x0
str r6, [r11, #L2X0_CACHE_SYNC] str r6, [r11, #L2X0_CACHE_SYNC]
1: 1:
ldr r6, [r11, #L2X0_CACHE_SYNC] ldr r6, [r11, #L2X0_CACHE_SYNC]
ands r6, r6, #0x1 ands r6, r6, #0x1
bne 1b bne 1b
6:
#endif #endif
.endm .endm
......
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
endif
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
...@@ -16,6 +16,32 @@ ...@@ -16,6 +16,32 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <linux/of.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#define GPT6_CON_MT65xx 0x10008060
#define GPT_ENABLE 0x31
static void __init mediatek_timer_init(void)
{
void __iomem *gpt_base;
if (of_machine_is_compatible("mediatek,mt6589") ||
of_machine_is_compatible("mediatek,mt8135") ||
of_machine_is_compatible("mediatek,mt8127")) {
/* turn on GPT6 which ungates arch timer clocks */
gpt_base = ioremap(GPT6_CON_MT65xx, 0x04);
/* enable clock and set to free-run */
writel(GPT_ENABLE, gpt_base);
iounmap(gpt_base);
}
of_clk_init(NULL);
clocksource_probe();
};
static const char * const mediatek_board_dt_compat[] = { static const char * const mediatek_board_dt_compat[] = {
"mediatek,mt6589", "mediatek,mt6589",
...@@ -27,4 +53,5 @@ static const char * const mediatek_board_dt_compat[] = { ...@@ -27,4 +53,5 @@ static const char * const mediatek_board_dt_compat[] = {
DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)") DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
.dt_compat = mediatek_board_dt_compat, .dt_compat = mediatek_board_dt_compat,
.init_time = mediatek_timer_init,
MACHINE_END MACHINE_END
/*
* arch/arm/mach-mediatek/platsmp.c
*
* Copyright (c) 2014 Mediatek Inc.
* Author: Shunli Wang <shunli.wang@mediatek.com>
* Yingjoe Chen <yingjoe.chen@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/string.h>
#include <linux/threads.h>
#define MTK_MAX_CPU 8
#define MTK_SMP_REG_SIZE 0x1000
struct mtk_smp_boot_info {
unsigned long smp_base;
unsigned int jump_reg;
unsigned int core_keys[MTK_MAX_CPU - 1];
unsigned int core_regs[MTK_MAX_CPU - 1];
};
static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
0x80002000, 0x3fc,
{ 0x534c4131, 0x4c415332, 0x41534c33 },
{ 0x3f8, 0x3f8, 0x3f8 },
};
static const struct mtk_smp_boot_info mtk_mt6589_boot = {
0x10002000, 0x34,
{ 0x534c4131, 0x4c415332, 0x41534c33 },
{ 0x38, 0x3c, 0x40 },
};
static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
{ .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
{ .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
};
static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
{ .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
};
static void __iomem *mtk_smp_base;
static const struct mtk_smp_boot_info *mtk_smp_info;
static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
if (!mtk_smp_base)
return -EINVAL;
if (!mtk_smp_info->core_keys[cpu-1])
return -EINVAL;
writel_relaxed(mtk_smp_info->core_keys[cpu-1],
mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
return 0;
}
static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
{
int i, num;
const struct of_device_id *infos;
if (trustzone) {
num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
infos = mtk_tz_smp_boot_infos;
} else {
num = ARRAY_SIZE(mtk_smp_boot_infos);
infos = mtk_smp_boot_infos;
}
/* Find smp boot info for this SoC */
for (i = 0; i < num; i++) {
if (of_machine_is_compatible(infos[i].compatible)) {
mtk_smp_info = infos[i].data;
break;
}
}
if (!mtk_smp_info) {
pr_err("%s: Device is not supported\n", __func__);
return;
}
if (trustzone) {
/* smp_base(trustzone-bootinfo) is reserved by device tree */
mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
} else {
mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
if (!mtk_smp_base) {
pr_err("%s: Can't remap %lx\n", __func__,
mtk_smp_info->smp_base);
return;
}
}
/*
* write the address of slave startup address into the system-wide
* jump register
*/
writel_relaxed(virt_to_phys(secondary_startup_arm),
mtk_smp_base + mtk_smp_info->jump_reg);
}
static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
{
__mtk_smp_prepare_cpus(max_cpus, 1);
}
static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
{
__mtk_smp_prepare_cpus(max_cpus, 0);
}
static struct smp_operations mt81xx_tz_smp_ops __initdata = {
.smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
.smp_boot_secondary = mtk_boot_secondary,
};
CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
static struct smp_operations mt6589_smp_ops __initdata = {
.smp_prepare_cpus = mtk_smp_prepare_cpus,
.smp_boot_secondary = mtk_boot_secondary,
};
CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops);
...@@ -19,4 +19,9 @@ config MACH_MESON8 ...@@ -19,4 +19,9 @@ config MACH_MESON8
default ARCH_MESON default ARCH_MESON
select MESON6_TIMER select MESON6_TIMER
config MACH_MESON8B
bool "Amlogic Meson8b SoCs support"
default ARCH_MESON
select MESON6_TIMER
endif endif
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
static const char * const meson_common_board_compat[] = { static const char * const meson_common_board_compat[] = {
"amlogic,meson6", "amlogic,meson6",
"amlogic,meson8", "amlogic,meson8",
"amlogic,meson8b",
NULL, NULL,
}; };
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
unsigned long coherency_phys_base; unsigned long coherency_phys_base;
void __iomem *coherency_base; void __iomem *coherency_base;
static void __iomem *coherency_cpu_base; static void __iomem *coherency_cpu_base;
static void __iomem *cpu_config_base;
/* Coherency fabric registers */ /* Coherency fabric registers */
#define IO_SYNC_BARRIER_CTL_OFFSET 0x0 #define IO_SYNC_BARRIER_CTL_OFFSET 0x0
...@@ -65,6 +66,31 @@ static const struct of_device_id of_coherency_table[] = { ...@@ -65,6 +66,31 @@ static const struct of_device_id of_coherency_table[] = {
int ll_enable_coherency(void); int ll_enable_coherency(void);
void ll_add_cpu_to_smp_group(void); void ll_add_cpu_to_smp_group(void);
#define CPU_CONFIG_SHARED_L2 BIT(16)
/*
* Disable the "Shared L2 Present" bit in CPU Configuration register
* on Armada XP.
*
* The "Shared L2 Present" bit affects the "level of coherence" value
* in the clidr CP15 register. Cache operation functions such as
* "flush all" and "invalidate all" operate on all the cache levels
* that included in the defined level of coherence. When HW I/O
* coherency is used, this bit causes unnecessary flushes of the L2
* cache.
*/
static void armada_xp_clear_shared_l2(void)
{
u32 reg;
if (!cpu_config_base)
return;
reg = readl(cpu_config_base);
reg &= ~CPU_CONFIG_SHARED_L2;
writel(reg, cpu_config_base);
}
static int mvebu_hwcc_notifier(struct notifier_block *nb, static int mvebu_hwcc_notifier(struct notifier_block *nb,
unsigned long event, void *__dev) unsigned long event, void *__dev)
{ {
...@@ -85,9 +111,24 @@ static struct notifier_block mvebu_hwcc_pci_nb = { ...@@ -85,9 +111,24 @@ static struct notifier_block mvebu_hwcc_pci_nb = {
.notifier_call = mvebu_hwcc_notifier, .notifier_call = mvebu_hwcc_notifier,
}; };
static int armada_xp_clear_shared_l2_notifier_func(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
armada_xp_clear_shared_l2();
return NOTIFY_OK;
}
static struct notifier_block armada_xp_clear_shared_l2_notifier = {
.notifier_call = armada_xp_clear_shared_l2_notifier_func,
.priority = 100,
};
static void __init armada_370_coherency_init(struct device_node *np) static void __init armada_370_coherency_init(struct device_node *np)
{ {
struct resource res; struct resource res;
struct device_node *cpu_config_np;
of_address_to_resource(np, 0, &res); of_address_to_resource(np, 0, &res);
coherency_phys_base = res.start; coherency_phys_base = res.start;
...@@ -100,6 +141,23 @@ static void __init armada_370_coherency_init(struct device_node *np) ...@@ -100,6 +141,23 @@ static void __init armada_370_coherency_init(struct device_node *np)
sync_cache_w(&coherency_phys_base); sync_cache_w(&coherency_phys_base);
coherency_base = of_iomap(np, 0); coherency_base = of_iomap(np, 0);
coherency_cpu_base = of_iomap(np, 1); coherency_cpu_base = of_iomap(np, 1);
cpu_config_np = of_find_compatible_node(NULL, NULL,
"marvell,armada-xp-cpu-config");
if (!cpu_config_np)
goto exit;
cpu_config_base = of_iomap(cpu_config_np, 0);
if (!cpu_config_base) {
of_node_put(cpu_config_np);
goto exit;
}
of_node_put(cpu_config_np);
register_cpu_notifier(&armada_xp_clear_shared_l2_notifier);
exit:
set_cpu_coherent(); set_cpu_coherent();
} }
...@@ -204,6 +262,8 @@ int set_cpu_coherent(void) ...@@ -204,6 +262,8 @@ int set_cpu_coherent(void)
pr_warn("Coherency fabric is not initialized\n"); pr_warn("Coherency fabric is not initialized\n");
return 1; return 1;
} }
armada_xp_clear_shared_l2();
ll_add_cpu_to_smp_group(); ll_add_cpu_to_smp_group();
return ll_enable_coherency(); return ll_enable_coherency();
} }
......
...@@ -379,6 +379,16 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = { ...@@ -379,6 +379,16 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = {
static struct platform_device mvebu_v7_cpuidle_device; static struct platform_device mvebu_v7_cpuidle_device;
static int broken_idle(struct device_node *np)
{
if (of_property_read_bool(np, "broken-idle")) {
pr_warn("CPU idle is currently broken: disabling\n");
return 1;
}
return 0;
}
static __init int armada_370_cpuidle_init(void) static __init int armada_370_cpuidle_init(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -387,7 +397,9 @@ static __init int armada_370_cpuidle_init(void) ...@@ -387,7 +397,9 @@ static __init int armada_370_cpuidle_init(void)
np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
if (!np) if (!np)
return -ENODEV; return -ENODEV;
of_node_put(np);
if (broken_idle(np))
goto end;
/* /*
* On Armada 370, there is "a slow exit process from the deep * On Armada 370, there is "a slow exit process from the deep
...@@ -406,6 +418,8 @@ static __init int armada_370_cpuidle_init(void) ...@@ -406,6 +418,8 @@ static __init int armada_370_cpuidle_init(void)
mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend; mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
mvebu_v7_cpuidle_device.name = "cpuidle-armada-370"; mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
end:
of_node_put(np);
return 0; return 0;
} }
...@@ -422,6 +436,10 @@ static __init int armada_38x_cpuidle_init(void) ...@@ -422,6 +436,10 @@ static __init int armada_38x_cpuidle_init(void)
"marvell,armada-380-coherency-fabric"); "marvell,armada-380-coherency-fabric");
if (!np) if (!np)
return -ENODEV; return -ENODEV;
if (broken_idle(np))
goto end;
of_node_put(np); of_node_put(np);
np = of_find_compatible_node(NULL, NULL, np = of_find_compatible_node(NULL, NULL,
...@@ -430,7 +448,6 @@ static __init int armada_38x_cpuidle_init(void) ...@@ -430,7 +448,6 @@ static __init int armada_38x_cpuidle_init(void)
return -ENODEV; return -ENODEV;
mpsoc_base = of_iomap(np, 0); mpsoc_base = of_iomap(np, 0);
BUG_ON(!mpsoc_base); BUG_ON(!mpsoc_base);
of_node_put(np);
/* Set up reset mask when powering down the cpus */ /* Set up reset mask when powering down the cpus */
reg = readl(mpsoc_base + MPCORE_RESET_CTL); reg = readl(mpsoc_base + MPCORE_RESET_CTL);
...@@ -450,6 +467,8 @@ static __init int armada_38x_cpuidle_init(void) ...@@ -450,6 +467,8 @@ static __init int armada_38x_cpuidle_init(void)
mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend; mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend;
mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x"; mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x";
end:
of_node_put(np);
return 0; return 0;
} }
...@@ -460,12 +479,16 @@ static __init int armada_xp_cpuidle_init(void) ...@@ -460,12 +479,16 @@ static __init int armada_xp_cpuidle_init(void)
np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
if (!np) if (!np)
return -ENODEV; return -ENODEV;
of_node_put(np);
if (broken_idle(np))
goto end;
mvebu_cpu_resume = armada_370_xp_cpu_resume; mvebu_cpu_resume = armada_370_xp_cpu_resume;
mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend; mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp"; mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
end:
of_node_put(np);
return 0; return 0;
} }
......
...@@ -45,6 +45,7 @@ config MACH_KUROBOX_PRO ...@@ -45,6 +45,7 @@ config MACH_KUROBOX_PRO
config MACH_DNS323 config MACH_DNS323
bool "D-Link DNS-323" bool "D-Link DNS-323"
select GENERIC_NET_UTILS
select I2C_BOARDINFO select I2C_BOARDINFO
help help
Say 'Y' here if you want your kernel to support the Say 'Y' here if you want your kernel to support the
...@@ -52,6 +53,7 @@ config MACH_DNS323 ...@@ -52,6 +53,7 @@ config MACH_DNS323
config MACH_TS209 config MACH_TS209
bool "QNAP TS-109/TS-209" bool "QNAP TS-109/TS-209"
select GENERIC_NET_UTILS
help help
Say 'Y' here if you want your kernel to support the Say 'Y' here if you want your kernel to support the
QNAP TS-109/TS-209 platform. QNAP TS-109/TS-209 platform.
...@@ -93,6 +95,7 @@ config MACH_LINKSTATION_LS_HGL ...@@ -93,6 +95,7 @@ config MACH_LINKSTATION_LS_HGL
config MACH_TS409 config MACH_TS409
bool "QNAP TS-409" bool "QNAP TS-409"
select GENERIC_NET_UTILS
help help
Say 'Y' here if you want your kernel to support the Say 'Y' here if you want your kernel to support the
QNAP TS-409 platform. QNAP TS-409 platform.
......
...@@ -173,42 +173,10 @@ static struct mv643xx_eth_platform_data dns323_eth_data = { ...@@ -173,42 +173,10 @@ static struct mv643xx_eth_platform_data dns323_eth_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8), .phy_addr = MV643XX_ETH_PHY_ADDR(8),
}; };
/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these
* functions be kept somewhere?
*/
static int __init dns323_parse_hex_nibble(char n)
{
if (n >= '0' && n <= '9')
return n - '0';
if (n >= 'A' && n <= 'F')
return n - 'A' + 10;
if (n >= 'a' && n <= 'f')
return n - 'a' + 10;
return -1;
}
static int __init dns323_parse_hex_byte(const char *b)
{
int hi;
int lo;
hi = dns323_parse_hex_nibble(b[0]);
lo = dns323_parse_hex_nibble(b[1]);
if (hi < 0 || lo < 0)
return -1;
return (hi << 4) | lo;
}
static int __init dns323_read_mac_addr(void) static int __init dns323_read_mac_addr(void)
{ {
u_int8_t addr[6]; u_int8_t addr[6];
int i; void __iomem *mac_page;
char *mac_page;
/* MAC address is stored as a regular ol' string in /dev/mtdblock4 /* MAC address is stored as a regular ol' string in /dev/mtdblock4
* (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80). * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
...@@ -217,23 +185,8 @@ static int __init dns323_read_mac_addr(void) ...@@ -217,23 +185,8 @@ static int __init dns323_read_mac_addr(void)
if (!mac_page) if (!mac_page)
return -ENOMEM; return -ENOMEM;
/* Sanity check the string we're looking at */ if (!mac_pton((__force const char *) mac_page, addr))
for (i = 0; i < 5; i++) {
if (*(mac_page + (i * 3) + 2) != ':') {
goto error_fail; goto error_fail;
}
}
for (i = 0; i < 6; i++) {
int byte;
byte = dns323_parse_hex_byte(mac_page + (i * 3));
if (byte < 0) {
goto error_fail;
}
addr[i] = byte;
}
iounmap(mac_page); iounmap(mac_page);
printk("DNS-323: Found ethernet MAC address: %pM\n", addr); printk("DNS-323: Found ethernet MAC address: %pM\n", addr);
......
...@@ -53,53 +53,12 @@ struct mv643xx_eth_platform_data qnap_tsx09_eth_data = { ...@@ -53,53 +53,12 @@ struct mv643xx_eth_platform_data qnap_tsx09_eth_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR(8), .phy_addr = MV643XX_ETH_PHY_ADDR(8),
}; };
static int __init qnap_tsx09_parse_hex_nibble(char n)
{
if (n >= '0' && n <= '9')
return n - '0';
if (n >= 'A' && n <= 'F')
return n - 'A' + 10;
if (n >= 'a' && n <= 'f')
return n - 'a' + 10;
return -1;
}
static int __init qnap_tsx09_parse_hex_byte(const char *b)
{
int hi;
int lo;
hi = qnap_tsx09_parse_hex_nibble(b[0]);
lo = qnap_tsx09_parse_hex_nibble(b[1]);
if (hi < 0 || lo < 0)
return -1;
return (hi << 4) | lo;
}
static int __init qnap_tsx09_check_mac_addr(const char *addr_str) static int __init qnap_tsx09_check_mac_addr(const char *addr_str)
{ {
u_int8_t addr[6]; u_int8_t addr[6];
int i;
for (i = 0; i < 6; i++) {
int byte;
/* if (!mac_pton(addr_str, addr))
* Enforce "xx:xx:xx:xx:xx:xx\n" format.
*/
if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n'))
return -1;
byte = qnap_tsx09_parse_hex_byte(addr_str + (i * 3));
if (byte < 0)
return -1; return -1;
addr[i] = byte;
}
printk(KERN_INFO "tsx09: found ethernet mac address %pM\n", addr); printk(KERN_INFO "tsx09: found ethernet mac address %pM\n", addr);
...@@ -118,12 +77,12 @@ void __init qnap_tsx09_find_mac_addr(u32 mem_base, u32 size) ...@@ -118,12 +77,12 @@ void __init qnap_tsx09_find_mac_addr(u32 mem_base, u32 size)
unsigned long addr; unsigned long addr;
for (addr = mem_base; addr < (mem_base + size); addr += 1024) { for (addr = mem_base; addr < (mem_base + size); addr += 1024) {
char *nor_page; void __iomem *nor_page;
int ret = 0; int ret = 0;
nor_page = ioremap(addr, 1024); nor_page = ioremap(addr, 1024);
if (nor_page != NULL) { if (nor_page != NULL) {
ret = qnap_tsx09_check_mac_addr(nor_page); ret = qnap_tsx09_check_mac_addr((__force const char *)nor_page);
iounmap(nor_page); iounmap(nor_page);
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/leds.h> #include <linux/leds.h>
...@@ -469,6 +470,11 @@ static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = { ...@@ -469,6 +470,11 @@ static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
.ocr_avail = MMC_VDD_32_33, .ocr_avail = MMC_VDD_32_33,
}; };
static struct pwm_lookup h1940_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 36296,
PWM_POLARITY_NORMAL),
};
static int h1940_backlight_init(struct device *dev) static int h1940_backlight_init(struct device *dev)
{ {
gpio_request(S3C2410_GPB(0), "Backlight"); gpio_request(S3C2410_GPB(0), "Backlight");
...@@ -503,11 +509,8 @@ static void h1940_backlight_exit(struct device *dev) ...@@ -503,11 +509,8 @@ static void h1940_backlight_exit(struct device *dev)
static struct platform_pwm_backlight_data backlight_data = { static struct platform_pwm_backlight_data backlight_data = {
.pwm_id = 0,
.max_brightness = 100, .max_brightness = 100,
.dft_brightness = 50, .dft_brightness = 50,
/* tcnt = 0x31 */
.pwm_period_ns = 36296,
.enable_gpio = -1, .enable_gpio = -1,
.init = h1940_backlight_init, .init = h1940_backlight_init,
.notify = h1940_backlight_notify, .notify = h1940_backlight_notify,
...@@ -725,6 +728,7 @@ static void __init h1940_init(void) ...@@ -725,6 +728,7 @@ static void __init h1940_init(void)
gpio_request(H1940_LATCH_SD_POWER, "SD power"); gpio_request(H1940_LATCH_SD_POWER, "SD power");
gpio_direction_output(H1940_LATCH_SD_POWER, 0); gpio_direction_output(H1940_LATCH_SD_POWER, 0);
pwm_add_table(h1940_pwm_lookup, ARRAY_SIZE(h1940_pwm_lookup));
platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
gpio_request(S3C2410_GPA(1), "Red LED blink"); gpio_request(S3C2410_GPA(1), "Red LED blink");
......
...@@ -375,6 +375,11 @@ static struct s3c2410fb_mach_info rx1950_lcd_cfg = { ...@@ -375,6 +375,11 @@ static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
}; };
static struct pwm_lookup rx1950_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight.0", NULL, 48000,
PWM_POLARITY_NORMAL),
};
static struct pwm_device *lcd_pwm; static struct pwm_device *lcd_pwm;
static void rx1950_lcd_power(int enable) static void rx1950_lcd_power(int enable)
...@@ -520,10 +525,8 @@ static int rx1950_backlight_notify(struct device *dev, int brightness) ...@@ -520,10 +525,8 @@ static int rx1950_backlight_notify(struct device *dev, int brightness)
} }
static struct platform_pwm_backlight_data rx1950_backlight_data = { static struct platform_pwm_backlight_data rx1950_backlight_data = {
.pwm_id = 0,
.max_brightness = 24, .max_brightness = 24,
.dft_brightness = 4, .dft_brightness = 4,
.pwm_period_ns = 48000,
.enable_gpio = -1, .enable_gpio = -1,
.init = rx1950_backlight_init, .init = rx1950_backlight_init,
.notify = rx1950_backlight_notify, .notify = rx1950_backlight_notify,
...@@ -792,6 +795,7 @@ static void __init rx1950_init_machine(void) ...@@ -792,6 +795,7 @@ static void __init rx1950_init_machine(void)
gpio_direction_output(S3C2410_GPA(4), 0); gpio_direction_output(S3C2410_GPA(4), 0);
gpio_direction_output(S3C2410_GPJ(6), 0); gpio_direction_output(S3C2410_GPJ(6), 0);
pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup));
platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices)); platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
i2c_register_board_info(0, rx1950_i2c_devices, i2c_register_board_info(0, rx1950_i2c_devices,
......
...@@ -69,7 +69,6 @@ static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = { ...@@ -69,7 +69,6 @@ static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = {
.plat_data = { .plat_data = {
.max_brightness = 255, .max_brightness = 255,
.dft_brightness = 255, .dft_brightness = 255,
.pwm_period_ns = 78770,
.enable_gpio = -1, .enable_gpio = -1,
.init = samsung_bl_init, .init = samsung_bl_init,
.exit = samsung_bl_exit, .exit = samsung_bl_exit,
...@@ -111,7 +110,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, ...@@ -111,7 +110,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
samsung_bl_data = &samsung_bl_drvdata->plat_data; samsung_bl_data = &samsung_bl_drvdata->plat_data;
/* Copy board specific data provided by user */ /* Copy board specific data provided by user */
samsung_bl_data->pwm_id = bl_data->pwm_id;
samsung_bl_device->dev.parent = &samsung_device_pwm.dev; samsung_bl_device->dev.parent = &samsung_device_pwm.dev;
if (bl_data->max_brightness) if (bl_data->max_brightness)
...@@ -120,8 +118,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info, ...@@ -120,8 +118,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
samsung_bl_data->dft_brightness = bl_data->dft_brightness; samsung_bl_data->dft_brightness = bl_data->dft_brightness;
if (bl_data->lth_brightness) if (bl_data->lth_brightness)
samsung_bl_data->lth_brightness = bl_data->lth_brightness; samsung_bl_data->lth_brightness = bl_data->lth_brightness;
if (bl_data->pwm_period_ns)
samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
if (bl_data->enable_gpio >= 0) if (bl_data->enable_gpio >= 0)
samsung_bl_data->enable_gpio = bl_data->enable_gpio; samsung_bl_data->enable_gpio = bl_data->enable_gpio;
if (bl_data->init) if (bl_data->init)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/dm9000.h> #include <linux/dm9000.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
...@@ -108,11 +109,14 @@ static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = { ...@@ -108,11 +109,14 @@ static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
}, },
}; };
static struct pwm_lookup crag6410_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 100000,
PWM_POLARITY_NORMAL),
};
static struct platform_pwm_backlight_data crag6410_backlight_data = { static struct platform_pwm_backlight_data crag6410_backlight_data = {
.pwm_id = 0,
.max_brightness = 1000, .max_brightness = 1000,
.dft_brightness = 600, .dft_brightness = 600,
.pwm_period_ns = 100000, /* about 1kHz */
.enable_gpio = -1, .enable_gpio = -1,
}; };
...@@ -843,6 +847,7 @@ static void __init crag6410_machine_init(void) ...@@ -843,6 +847,7 @@ static void __init crag6410_machine_init(void)
samsung_keypad_set_platdata(&crag6410_keypad_data); samsung_keypad_set_platdata(&crag6410_keypad_data);
s3c64xx_spi0_set_platdata(NULL, 0, 2); s3c64xx_spi0_set_platdata(NULL, 0, 2);
pwm_add_table(crag6410_pwm_lookup, ARRAY_SIZE(crag6410_pwm_lookup));
platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices)); platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
gpio_led_register_device(-1, &gpio_leds_pdata); gpio_led_register_device(-1, &gpio_leds_pdata);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
...@@ -73,6 +74,11 @@ static struct s3c2410_uartcfg hmt_uartcfgs[] __initdata = { ...@@ -73,6 +74,11 @@ static struct s3c2410_uartcfg hmt_uartcfgs[] __initdata = {
}, },
}; };
static struct pwm_lookup hmt_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
1000000000 / (100 * 256 * 20), PWM_POLARITY_NORMAL),
};
static int hmt_bl_init(struct device *dev) static int hmt_bl_init(struct device *dev)
{ {
int ret; int ret;
...@@ -110,10 +116,8 @@ static void hmt_bl_exit(struct device *dev) ...@@ -110,10 +116,8 @@ static void hmt_bl_exit(struct device *dev)
} }
static struct platform_pwm_backlight_data hmt_backlight_data = { static struct platform_pwm_backlight_data hmt_backlight_data = {
.pwm_id = 1,
.max_brightness = 100 * 256, .max_brightness = 100 * 256,
.dft_brightness = 40 * 256, .dft_brightness = 40 * 256,
.pwm_period_ns = 1000000000 / (100 * 256 * 20),
.enable_gpio = -1, .enable_gpio = -1,
.init = hmt_bl_init, .init = hmt_bl_init,
.notify = hmt_bl_notify, .notify = hmt_bl_notify,
...@@ -268,6 +272,7 @@ static void __init hmt_machine_init(void) ...@@ -268,6 +272,7 @@ static void __init hmt_machine_init(void)
gpio_request(S3C64XX_GPF(13), "usb power"); gpio_request(S3C64XX_GPF(13), "usb power");
gpio_direction_output(S3C64XX_GPF(13), 1); gpio_direction_output(S3C64XX_GPF(13), 1);
pwm_add_table(hmt_pwm_lookup, ARRAY_SIZE(hmt_pwm_lookup));
platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices)); platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices));
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_s3c.h> #include <linux/serial_s3c.h>
...@@ -139,6 +140,11 @@ static struct platform_device smartq_usb_otg_vbus_dev = { ...@@ -139,6 +140,11 @@ static struct platform_device smartq_usb_otg_vbus_dev = {
.dev.platform_data = &smartq_usb_otg_vbus_pdata, .dev.platform_data = &smartq_usb_otg_vbus_pdata,
}; };
static struct pwm_lookup smartq_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
1000000000 / (1000 * 20), PWM_POLARITY_NORMAL),
};
static int smartq_bl_init(struct device *dev) static int smartq_bl_init(struct device *dev)
{ {
s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
...@@ -147,10 +153,8 @@ static int smartq_bl_init(struct device *dev) ...@@ -147,10 +153,8 @@ static int smartq_bl_init(struct device *dev)
} }
static struct platform_pwm_backlight_data smartq_backlight_data = { static struct platform_pwm_backlight_data smartq_backlight_data = {
.pwm_id = 1,
.max_brightness = 1000, .max_brightness = 1000,
.dft_brightness = 600, .dft_brightness = 600,
.pwm_period_ns = 1000000000 / (1000 * 20),
.enable_gpio = -1, .enable_gpio = -1,
.init = smartq_bl_init, .init = smartq_bl_init,
}; };
...@@ -396,5 +400,6 @@ void __init smartq_machine_init(void) ...@@ -396,5 +400,6 @@ void __init smartq_machine_init(void)
WARN_ON(smartq_usb_host_init()); WARN_ON(smartq_usb_host_init());
WARN_ON(smartq_wifi_init()); WARN_ON(smartq_wifi_init());
pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup));
platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices)); platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
} }
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/smsc911x.h> #include <linux/smsc911x.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h> #include <linux/pwm_backlight.h>
#include <linux/platform_data/s3c-hsotg.h> #include <linux/platform_data/s3c-hsotg.h>
...@@ -623,8 +624,12 @@ static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = { ...@@ -623,8 +624,12 @@ static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
.func = S3C_GPIO_SFN(2), .func = S3C_GPIO_SFN(2),
}; };
static struct pwm_lookup smdk6410_pwm_lookup[] = {
PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL, 78770,
PWM_POLARITY_NORMAL),
};
static struct platform_pwm_backlight_data smdk6410_bl_data = { static struct platform_pwm_backlight_data smdk6410_bl_data = {
.pwm_id = 1,
.enable_gpio = -1, .enable_gpio = -1,
}; };
...@@ -695,6 +700,7 @@ static void __init smdk6410_machine_init(void) ...@@ -695,6 +700,7 @@ static void __init smdk6410_machine_init(void)
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
pwm_add_table(smdk6410_pwm_lookup, ARRAY_SIZE(smdk6410_pwm_lookup));
samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data); samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data);
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#include <linux/clk/shmobile.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -124,36 +125,6 @@ static bool rmobile_pd_active_wakeup(struct device *dev) ...@@ -124,36 +125,6 @@ static bool rmobile_pd_active_wakeup(struct device *dev)
return true; return true;
} }
static int rmobile_pd_attach_dev(struct generic_pm_domain *domain,
struct device *dev)
{
int error;
error = pm_clk_create(dev);
if (error) {
dev_err(dev, "pm_clk_create failed %d\n", error);
return error;
}
error = pm_clk_add(dev, NULL);
if (error) {
dev_err(dev, "pm_clk_add failed %d\n", error);
goto fail;
}
return 0;
fail:
pm_clk_destroy(dev);
return error;
}
static void rmobile_pd_detach_dev(struct generic_pm_domain *domain,
struct device *dev)
{
pm_clk_destroy(dev);
}
static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
{ {
struct generic_pm_domain *genpd = &rmobile_pd->genpd; struct generic_pm_domain *genpd = &rmobile_pd->genpd;
...@@ -164,8 +135,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) ...@@ -164,8 +135,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
genpd->power_off = rmobile_pd_power_down; genpd->power_off = rmobile_pd_power_down;
genpd->power_on = rmobile_pd_power_up; genpd->power_on = rmobile_pd_power_up;
genpd->attach_dev = rmobile_pd_attach_dev; genpd->attach_dev = cpg_mstp_attach_dev;
genpd->detach_dev = rmobile_pd_detach_dev; genpd->detach_dev = cpg_mstp_detach_dev;
__rmobile_pd_power_up(rmobile_pd, false); __rmobile_pd_power_up(rmobile_pd, false);
} }
......
...@@ -26,10 +26,11 @@ static const char * const sunxi_board_dt_compat[] = { ...@@ -26,10 +26,11 @@ static const char * const sunxi_board_dt_compat[] = {
"allwinner,sun4i-a10", "allwinner,sun4i-a10",
"allwinner,sun5i-a10s", "allwinner,sun5i-a10s",
"allwinner,sun5i-a13", "allwinner,sun5i-a13",
"allwinner,sun5i-r8",
NULL, NULL,
}; };
DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") DT_MACHINE_START(SUNXI_DT, "Allwinner sun4i/sun5i Families")
.dt_compat = sunxi_board_dt_compat, .dt_compat = sunxi_board_dt_compat,
.init_late = sunxi_dt_cpufreq_init, .init_late = sunxi_dt_cpufreq_init,
MACHINE_END MACHINE_END
......
...@@ -39,8 +39,8 @@ static struct platform_device wifi_rfkill_device = { ...@@ -39,8 +39,8 @@ static struct platform_device wifi_rfkill_device = {
static struct gpiod_lookup_table wifi_gpio_lookup = { static struct gpiod_lookup_table wifi_gpio_lookup = {
.dev_id = "rfkill_gpio", .dev_id = "rfkill_gpio",
.table = { .table = {
GPIO_LOOKUP_IDX("tegra-gpio", 25, NULL, 0, 0), GPIO_LOOKUP("tegra-gpio", 25, "reset", 0),
GPIO_LOOKUP_IDX("tegra-gpio", 85, NULL, 1, 0), GPIO_LOOKUP("tegra-gpio", 85, "shutdown", 0),
{ }, { },
}, },
}; };
......
obj-y := uniphier.o obj-y := uniphier.o
obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o
/*
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/cp15.h>
ENTRY(uniphier_smp_trampoline)
ARM_BE8(setend be) @ ensure we are in BE8 mode
mrc p15, 0, r0, c0, c0, 5 @ MPIDR (Multiprocessor Affinity Reg)
and r2, r0, #0x3 @ CPU ID
ldr r1, uniphier_smp_trampoline_jump
ldr r3, uniphier_smp_trampoline_poll_addr
mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register)
orr r0, r0, #CR_I @ Enable ICache
bic r0, r0, #(CR_C | CR_M) @ Disable MMU and Dcache
mcr p15, 0, r0, c1, c0, 0
b 1f @ cache the following 5 instructions
0: wfe
1: ldr r0, [r3]
cmp r0, r2
bxeq r1 @ branch to secondary_startup
b 0b
.globl uniphier_smp_trampoline_jump
uniphier_smp_trampoline_jump:
.word 0 @ set virt_to_phys(secondary_startup)
.globl uniphier_smp_trampoline_poll_addr
uniphier_smp_trampoline_poll_addr:
.word 0 @ set CPU ID to be kicked to this reg
.globl uniphier_smp_trampoline_end
uniphier_smp_trampoline_end:
ENDPROC(uniphier_smp_trampoline)
...@@ -12,73 +12,198 @@ ...@@ -12,73 +12,198 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/sizes.h> #define pr_fmt(fmt) "uniphier: " fmt
#include <linux/compiler.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/regmap.h> #include <linux/ioport.h>
#include <linux/mfd/syscon.h> #include <linux/of.h>
#include <linux/of_address.h>
#include <linux/sizes.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-uniphier.h>
#include <asm/pgtable.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
static struct regmap *sbcm_regmap; /*
* The secondary CPUs check this register from the boot ROM for the jump
* destination. After that, it can be reused as a scratch register.
*/
#define UNIPHIER_SBC_ROM_BOOT_RSV2 0x1208
static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus) static void __iomem *uniphier_smp_rom_boot_rsv2;
static unsigned int uniphier_smp_max_cpus;
extern char uniphier_smp_trampoline;
extern char uniphier_smp_trampoline_jump;
extern char uniphier_smp_trampoline_poll_addr;
extern char uniphier_smp_trampoline_end;
/*
* Copy trampoline code to the tail of the 1st section of the page table used
* in the boot ROM. This area is directly accessible by the secondary CPUs
* for all the UniPhier SoCs.
*/
static const phys_addr_t uniphier_smp_trampoline_dest_end = SECTION_SIZE;
static phys_addr_t uniphier_smp_trampoline_dest;
static int __init uniphier_smp_copy_trampoline(phys_addr_t poll_addr)
{ {
static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; size_t trmp_size;
unsigned long scu_base_phys = 0; static void __iomem *trmp_base;
void __iomem *scu_base;
sbcm_regmap = syscon_regmap_lookup_by_compatible( if (!uniphier_cache_l2_is_enabled()) {
"socionext,uniphier-system-bus-controller-misc"); pr_warn("outer cache is needed for SMP, but not enabled\n");
if (IS_ERR(sbcm_regmap)) { return -ENODEV;
pr_err("failed to regmap system-bus-controller-misc\n"); }
goto err;
uniphier_cache_l2_set_locked_ways(1);
outer_flush_all();
trmp_size = &uniphier_smp_trampoline_end - &uniphier_smp_trampoline;
uniphier_smp_trampoline_dest = uniphier_smp_trampoline_dest_end -
trmp_size;
uniphier_cache_l2_touch_range(uniphier_smp_trampoline_dest,
uniphier_smp_trampoline_dest_end);
trmp_base = ioremap_cache(uniphier_smp_trampoline_dest, trmp_size);
if (!trmp_base) {
pr_err("failed to map trampoline destination area\n");
return -ENOMEM;
}
memcpy(trmp_base, &uniphier_smp_trampoline, trmp_size);
writel(virt_to_phys(secondary_startup),
trmp_base + (&uniphier_smp_trampoline_jump -
&uniphier_smp_trampoline));
writel(poll_addr, trmp_base + (&uniphier_smp_trampoline_poll_addr -
&uniphier_smp_trampoline));
flush_cache_all(); /* flush out trampoline code to outer cache */
iounmap(trmp_base);
return 0;
}
static int __init uniphier_smp_prepare_trampoline(unsigned int max_cpus)
{
struct device_node *np;
struct resource res;
phys_addr_t rom_rsv2_phys;
int ret;
np = of_find_compatible_node(NULL, NULL,
"socionext,uniphier-system-bus-controller");
ret = of_address_to_resource(np, 1, &res);
if (ret) {
pr_err("failed to get resource of system-bus-controller\n");
return ret;
}
rom_rsv2_phys = res.start + UNIPHIER_SBC_ROM_BOOT_RSV2;
ret = uniphier_smp_copy_trampoline(rom_rsv2_phys);
if (ret)
return ret;
uniphier_smp_rom_boot_rsv2 = ioremap(rom_rsv2_phys, sizeof(SZ_4));
if (!uniphier_smp_rom_boot_rsv2) {
pr_err("failed to map ROM_BOOT_RSV2 register\n");
return -ENOMEM;
} }
writel(uniphier_smp_trampoline_dest, uniphier_smp_rom_boot_rsv2);
asm("sev"); /* Bring up all secondary CPUs to the trampoline code */
uniphier_smp_max_cpus = max_cpus; /* save for later use */
return 0;
}
static void __init uniphier_smp_unprepare_trampoline(void)
{
iounmap(uniphier_smp_rom_boot_rsv2);
if (uniphier_smp_trampoline_dest)
outer_inv_range(uniphier_smp_trampoline_dest,
uniphier_smp_trampoline_dest_end);
uniphier_cache_l2_set_locked_ways(0);
}
static int __init uniphier_smp_enable_scu(void)
{
unsigned long scu_base_phys = 0;
void __iomem *scu_base;
if (scu_a9_has_base()) if (scu_a9_has_base())
scu_base_phys = scu_a9_get_base(); scu_base_phys = scu_a9_get_base();
if (!scu_base_phys) { if (!scu_base_phys) {
pr_err("failed to get scu base\n"); pr_err("failed to get scu base\n");
goto err; return -ENODEV;
} }
scu_base = ioremap(scu_base_phys, SZ_128); scu_base = ioremap(scu_base_phys, SZ_128);
if (!scu_base) { if (!scu_base) {
pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys); pr_err("failed to map scu base\n");
goto err; return -ENOMEM;
} }
scu_enable(scu_base); scu_enable(scu_base);
iounmap(scu_base); iounmap(scu_base);
return 0;
}
static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
{
static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
int ret;
ret = uniphier_smp_prepare_trampoline(max_cpus);
if (ret)
goto err;
ret = uniphier_smp_enable_scu();
if (ret)
goto err;
return; return;
err: err:
pr_warn("disabling SMP\n"); pr_warn("disabling SMP\n");
init_cpu_present(&only_cpu_0); init_cpu_present(&only_cpu_0);
sbcm_regmap = NULL; uniphier_smp_unprepare_trampoline();
} }
static int uniphier_boot_secondary(unsigned int cpu, static int __init uniphier_smp_boot_secondary(unsigned int cpu,
struct task_struct *idle) struct task_struct *idle)
{ {
int ret; if (WARN_ON_ONCE(!uniphier_smp_rom_boot_rsv2))
return -EFAULT;
if (!sbcm_regmap) writel(cpu, uniphier_smp_rom_boot_rsv2);
return -ENODEV; readl(uniphier_smp_rom_boot_rsv2); /* relax */
ret = regmap_write(sbcm_regmap, 0x1208, asm("sev"); /* wake up secondary CPUs sleeping in the trampoline */
virt_to_phys(secondary_startup));
if (!ret)
asm("sev"); /* wake up secondary CPU */
return ret; if (cpu == uniphier_smp_max_cpus - 1) {
/* clean up resources if this is the last CPU */
uniphier_smp_unprepare_trampoline();
}
return 0;
} }
struct smp_operations uniphier_smp_ops __initdata = { static struct smp_operations uniphier_smp_ops __initdata = {
.smp_prepare_cpus = uniphier_smp_prepare_cpus, .smp_prepare_cpus = uniphier_smp_prepare_cpus,
.smp_boot_secondary = uniphier_boot_secondary, .smp_boot_secondary = uniphier_smp_boot_secondary,
}; };
CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp", CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
&uniphier_smp_ops); &uniphier_smp_ops);
...@@ -974,6 +974,16 @@ config CACHE_TAUROS2 ...@@ -974,6 +974,16 @@ config CACHE_TAUROS2
This option enables the Tauros2 L2 cache controller (as This option enables the Tauros2 L2 cache controller (as
found on PJ1/PJ4). found on PJ1/PJ4).
config CACHE_UNIPHIER
bool "Enable the UniPhier outer cache controller"
depends on ARCH_UNIPHIER
default y
select OUTER_CACHE
select OUTER_CACHE_SYNC
help
This option enables the UniPhier outer cache (system cache)
controller.
config CACHE_XSC3L2 config CACHE_XSC3L2
bool "Enable the L2 cache on XScale3" bool "Enable the L2 cache on XScale3"
depends on CPU_XSC3 depends on CPU_XSC3
......
...@@ -103,3 +103,4 @@ obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o ...@@ -103,3 +103,4 @@ obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o
obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o
This diff is collapsed.
...@@ -7,6 +7,7 @@ config ARCH_BCM_IPROC ...@@ -7,6 +7,7 @@ config ARCH_BCM_IPROC
config ARCH_BERLIN config ARCH_BERLIN
bool "Marvell Berlin SoC Family" bool "Marvell Berlin SoC Family"
select ARCH_REQUIRE_GPIOLIB
select DW_APB_ICTL select DW_APB_ICTL
help help
This enables support for Marvell Berlin SoC Family This enables support for Marvell Berlin SoC Family
......
...@@ -259,6 +259,10 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) ...@@ -259,6 +259,10 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
"renesas,cpg-mstp-clocks")) "renesas,cpg-mstp-clocks"))
goto found; goto found;
/* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */
if (!strcmp(clkspec.np->name, "zb_clk"))
goto found;
of_node_put(clkspec.np); of_node_put(clkspec.np);
i++; i++;
} }
......
...@@ -1196,6 +1196,7 @@ static void __init sun5i_init_clocks(struct device_node *node) ...@@ -1196,6 +1196,7 @@ static void __init sun5i_init_clocks(struct device_node *node)
} }
CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks); CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks); CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
CLK_OF_DECLARE(sun5i_r8_clk_init, "allwinner,sun5i-r8", sun5i_init_clocks);
CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks); CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
static const char *sun6i_critical_clocks[] __initdata = { static const char *sun6i_critical_clocks[] __initdata = {
......
menu "SOC (System On Chip) specific Drivers" menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/brcmstb/Kconfig"
source "drivers/soc/mediatek/Kconfig" source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig" source "drivers/soc/qcom/Kconfig"
source "drivers/soc/sunxi/Kconfig" source "drivers/soc/sunxi/Kconfig"
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Makefile for the Linux Kernel SOC specific device drivers. # Makefile for the Linux Kernel SOC specific device drivers.
# #
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
obj-$(CONFIG_MACH_DOVE) += dove/ obj-$(CONFIG_MACH_DOVE) += dove/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/ obj-$(CONFIG_ARCH_QCOM) += qcom/
......
menuconfig SOC_BRCMSTB
bool "Broadcom STB SoC drivers"
depends on ARM
help
Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
This option alone enables only some support code, while the drivers
can be enabled individually within this menu.
If unsure, say N.
obj-y += common.o biuctrl.o
/*
* Broadcom STB SoCs Bus Unit Interface controls
*
* Copyright (C) 2015, Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "brcmstb: " KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#define CPU_CREDIT_REG_OFFSET 0x184
#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
static void __iomem *cpubiuctrl_base;
static bool mcp_wr_pairing_en;
static int __init mcp_write_pairing_set(void)
{
u32 creds = 0;
if (!cpubiuctrl_base)
return -1;
creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
if (mcp_wr_pairing_en) {
pr_info("MCP: Enabling write pairing\n");
writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
} else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
pr_info("MCP: Disabling write pairing\n");
writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
} else {
pr_info("MCP: Write pairing already disabled\n");
}
return 0;
}
static int __init setup_hifcpubiuctrl_regs(void)
{
struct device_node *np;
int ret = 0;
np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
if (!np) {
pr_err("missing BIU control node\n");
return -ENODEV;
}
cpubiuctrl_base = of_iomap(np, 0);
if (!cpubiuctrl_base) {
pr_err("failed to remap BIU control base\n");
ret = -ENOMEM;
goto out;
}
mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
out:
of_node_put(np);
return ret;
}
#ifdef CONFIG_PM_SLEEP
static u32 cpu_credit_reg_dump; /* for save/restore */
static int brcmstb_cpu_credit_reg_suspend(void)
{
if (cpubiuctrl_base)
cpu_credit_reg_dump =
readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
return 0;
}
static void brcmstb_cpu_credit_reg_resume(void)
{
if (cpubiuctrl_base)
writel_relaxed(cpu_credit_reg_dump,
cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
}
static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
.suspend = brcmstb_cpu_credit_reg_suspend,
.resume = brcmstb_cpu_credit_reg_resume,
};
#endif
void __init brcmstb_biuctrl_init(void)
{
int ret;
setup_hifcpubiuctrl_regs();
ret = mcp_write_pairing_set();
if (ret) {
pr_err("MCP: Unable to disable write pairing!\n");
return;
}
#ifdef CONFIG_PM_SLEEP
register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
#endif
}
/*
* Copyright © 2014 NVIDIA Corporation
* Copyright © 2015 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/of.h>
#include <soc/brcmstb/common.h>
static const struct of_device_id brcmstb_machine_match[] = {
{ .compatible = "brcm,brcmstb", },
{ }
};
bool soc_is_brcmstb(void)
{
struct device_node *root;
root = of_find_node_by_path("/");
if (!root)
return false;
return of_match_node(brcmstb_machine_match, root) != NULL;
}
...@@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp) ...@@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
if (pwrap_is_mt8135(wrp)) { if (pwrap_is_mt8135(wrp)) {
/* enable pwrap events and pwrap bridge in AP side */ /* enable pwrap events and pwrap bridge in AP side */
...@@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev) ...@@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* Initialize watchdog, may not be done by the bootloader */
pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp); "mt-pmic-pwrap", wrp);
......
...@@ -54,12 +54,16 @@ ...@@ -54,12 +54,16 @@
#define PWR_STATUS_USB BIT(25) #define PWR_STATUS_USB BIT(25)
enum clk_id { enum clk_id {
MT8173_CLK_NONE,
MT8173_CLK_MM, MT8173_CLK_MM,
MT8173_CLK_MFG, MT8173_CLK_MFG,
MT8173_CLK_NONE, MT8173_CLK_VENC,
MT8173_CLK_MAX = MT8173_CLK_NONE, MT8173_CLK_VENC_LT,
MT8173_CLK_MAX,
}; };
#define MAX_CLKS 2
struct scp_domain_data { struct scp_domain_data {
const char *name; const char *name;
u32 sta_mask; u32 sta_mask;
...@@ -67,7 +71,8 @@ struct scp_domain_data { ...@@ -67,7 +71,8 @@ struct scp_domain_data {
u32 sram_pdn_bits; u32 sram_pdn_bits;
u32 sram_pdn_ack_bits; u32 sram_pdn_ack_bits;
u32 bus_prot_mask; u32 bus_prot_mask;
enum clk_id clk_id; enum clk_id clk_id[MAX_CLKS];
bool active_wakeup;
}; };
static const struct scp_domain_data scp_domain_data[] __initconst = { static const struct scp_domain_data scp_domain_data[] __initconst = {
...@@ -77,7 +82,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -77,7 +82,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VDE_PWR_CON, .ctl_offs = SPM_VDE_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12), .sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = MT8173_CLK_MM, .clk_id = {MT8173_CLK_MM},
}, },
[MT8173_POWER_DOMAIN_VENC] = { [MT8173_POWER_DOMAIN_VENC] = {
.name = "venc", .name = "venc",
...@@ -85,7 +90,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -85,7 +90,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN_PWR_CON, .ctl_offs = SPM_VEN_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12), .sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_MM, .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
}, },
[MT8173_POWER_DOMAIN_ISP] = { [MT8173_POWER_DOMAIN_ISP] = {
.name = "isp", .name = "isp",
...@@ -93,7 +98,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -93,7 +98,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_ISP_PWR_CON, .ctl_offs = SPM_ISP_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12), .sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = MT8173_CLK_MM, .clk_id = {MT8173_CLK_MM},
}, },
[MT8173_POWER_DOMAIN_MM] = { [MT8173_POWER_DOMAIN_MM] = {
.name = "mm", .name = "mm",
...@@ -101,7 +106,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -101,7 +106,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_DIS_PWR_CON, .ctl_offs = SPM_DIS_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12), .sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = MT8173_CLK_MM, .clk_id = {MT8173_CLK_MM},
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
MT8173_TOP_AXI_PROT_EN_MM_M1, MT8173_TOP_AXI_PROT_EN_MM_M1,
}, },
...@@ -111,7 +116,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -111,7 +116,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN2_PWR_CON, .ctl_offs = SPM_VEN2_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12), .sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_MM, .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
}, },
[MT8173_POWER_DOMAIN_AUDIO] = { [MT8173_POWER_DOMAIN_AUDIO] = {
.name = "audio", .name = "audio",
...@@ -119,7 +124,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -119,7 +124,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_AUDIO_PWR_CON, .ctl_offs = SPM_AUDIO_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12), .sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_NONE, .clk_id = {MT8173_CLK_NONE},
}, },
[MT8173_POWER_DOMAIN_USB] = { [MT8173_POWER_DOMAIN_USB] = {
.name = "usb", .name = "usb",
...@@ -127,7 +132,8 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -127,7 +132,8 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_USB_PWR_CON, .ctl_offs = SPM_USB_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12), .sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_NONE, .clk_id = {MT8173_CLK_NONE},
.active_wakeup = true,
}, },
[MT8173_POWER_DOMAIN_MFG_ASYNC] = { [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
.name = "mfg_async", .name = "mfg_async",
...@@ -135,7 +141,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -135,7 +141,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_ASYNC_PWR_CON, .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0, .sram_pdn_ack_bits = 0,
.clk_id = MT8173_CLK_MFG, .clk_id = {MT8173_CLK_MFG},
}, },
[MT8173_POWER_DOMAIN_MFG_2D] = { [MT8173_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d", .name = "mfg_2d",
...@@ -143,7 +149,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -143,7 +149,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_2D_PWR_CON, .ctl_offs = SPM_MFG_2D_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8), .sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12), .sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = MT8173_CLK_NONE, .clk_id = {MT8173_CLK_NONE},
}, },
[MT8173_POWER_DOMAIN_MFG] = { [MT8173_POWER_DOMAIN_MFG] = {
.name = "mfg", .name = "mfg",
...@@ -151,7 +157,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = { ...@@ -151,7 +157,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_PWR_CON, .ctl_offs = SPM_MFG_PWR_CON,
.sram_pdn_bits = GENMASK(13, 8), .sram_pdn_bits = GENMASK(13, 8),
.sram_pdn_ack_bits = GENMASK(21, 16), .sram_pdn_ack_bits = GENMASK(21, 16),
.clk_id = MT8173_CLK_NONE, .clk_id = {MT8173_CLK_NONE},
.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
MT8173_TOP_AXI_PROT_EN_MFG_M0 | MT8173_TOP_AXI_PROT_EN_MFG_M0 |
MT8173_TOP_AXI_PROT_EN_MFG_M1 | MT8173_TOP_AXI_PROT_EN_MFG_M1 |
...@@ -166,12 +172,13 @@ struct scp; ...@@ -166,12 +172,13 @@ struct scp;
struct scp_domain { struct scp_domain {
struct generic_pm_domain genpd; struct generic_pm_domain genpd;
struct scp *scp; struct scp *scp;
struct clk *clk; struct clk *clk[MAX_CLKS];
u32 sta_mask; u32 sta_mask;
void __iomem *ctl_addr; void __iomem *ctl_addr;
u32 sram_pdn_bits; u32 sram_pdn_bits;
u32 sram_pdn_ack_bits; u32 sram_pdn_ack_bits;
u32 bus_prot_mask; u32 bus_prot_mask;
bool active_wakeup;
}; };
struct scp { struct scp {
...@@ -212,12 +219,17 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) ...@@ -212,12 +219,17 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
u32 sram_pdn_ack = scpd->sram_pdn_ack_bits; u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
u32 val; u32 val;
int ret; int ret;
int i;
for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
ret = clk_prepare_enable(scpd->clk[i]);
if (ret) {
for (--i; i >= 0; i--)
clk_disable_unprepare(scpd->clk[i]);
if (scpd->clk) {
ret = clk_prepare_enable(scpd->clk);
if (ret)
goto err_clk; goto err_clk;
} }
}
val = readl(ctl_addr); val = readl(ctl_addr);
val |= PWR_ON_BIT; val |= PWR_ON_BIT;
...@@ -282,7 +294,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) ...@@ -282,7 +294,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
return 0; return 0;
err_pwr_ack: err_pwr_ack:
clk_disable_unprepare(scpd->clk); for (i = MAX_CLKS - 1; i >= 0; i--) {
if (scpd->clk[i])
clk_disable_unprepare(scpd->clk[i]);
}
err_clk: err_clk:
dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
...@@ -299,6 +314,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) ...@@ -299,6 +314,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
u32 pdn_ack = scpd->sram_pdn_ack_bits; u32 pdn_ack = scpd->sram_pdn_ack_bits;
u32 val; u32 val;
int ret; int ret;
int i;
if (scpd->bus_prot_mask) { if (scpd->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg, ret = mtk_infracfg_set_bus_protection(scp->infracfg,
...@@ -360,8 +376,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) ...@@ -360,8 +376,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
expired = true; expired = true;
} }
if (scpd->clk) for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
clk_disable_unprepare(scpd->clk); clk_disable_unprepare(scpd->clk[i]);
return 0; return 0;
...@@ -371,11 +387,22 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) ...@@ -371,11 +387,22 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
return ret; return ret;
} }
static bool scpsys_active_wakeup(struct device *dev)
{
struct generic_pm_domain *genpd;
struct scp_domain *scpd;
genpd = pd_to_genpd(dev->pm_domain);
scpd = container_of(genpd, struct scp_domain, genpd);
return scpd->active_wakeup;
}
static int __init scpsys_probe(struct platform_device *pdev) static int __init scpsys_probe(struct platform_device *pdev)
{ {
struct genpd_onecell_data *pd_data; struct genpd_onecell_data *pd_data;
struct resource *res; struct resource *res;
int i, ret; int i, j, ret;
struct scp *scp; struct scp *scp;
struct clk *clk[MT8173_CLK_MAX]; struct clk *clk[MT8173_CLK_MAX];
...@@ -405,6 +432,14 @@ static int __init scpsys_probe(struct platform_device *pdev) ...@@ -405,6 +432,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
if (IS_ERR(clk[MT8173_CLK_MFG])) if (IS_ERR(clk[MT8173_CLK_MFG]))
return PTR_ERR(clk[MT8173_CLK_MFG]); return PTR_ERR(clk[MT8173_CLK_MFG]);
clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
if (IS_ERR(clk[MT8173_CLK_VENC]))
return PTR_ERR(clk[MT8173_CLK_VENC]);
clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"infracfg"); "infracfg");
if (IS_ERR(scp->infracfg)) { if (IS_ERR(scp->infracfg)) {
...@@ -428,12 +463,14 @@ static int __init scpsys_probe(struct platform_device *pdev) ...@@ -428,12 +463,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
scpd->sram_pdn_bits = data->sram_pdn_bits; scpd->sram_pdn_bits = data->sram_pdn_bits;
scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
scpd->bus_prot_mask = data->bus_prot_mask; scpd->bus_prot_mask = data->bus_prot_mask;
if (data->clk_id != MT8173_CLK_NONE) scpd->active_wakeup = data->active_wakeup;
scpd->clk = clk[data->clk_id]; for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
scpd->clk[j] = clk[data->clk_id[j]];
genpd->name = data->name; genpd->name = data->name;
genpd->power_off = scpsys_power_off; genpd->power_off = scpsys_power_off;
genpd->power_on = scpsys_power_on; genpd->power_on = scpsys_power_on;
genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
/* /*
* Initially turn on all domains to make the domains usable * Initially turn on all domains to make the domains usable
......
...@@ -135,9 +135,10 @@ struct knav_pdsp_info { ...@@ -135,9 +135,10 @@ struct knav_pdsp_info {
}; };
void __iomem *intd; void __iomem *intd;
u32 __iomem *iram; u32 __iomem *iram;
const char *firmware;
u32 id; u32 id;
struct list_head list; struct list_head list;
bool loaded;
bool started;
}; };
struct knav_qmgr_info { struct knav_qmgr_info {
......
...@@ -530,6 +530,12 @@ int knav_init_acc_range(struct knav_device *kdev, ...@@ -530,6 +530,12 @@ int knav_init_acc_range(struct knav_device *kdev,
return -EINVAL; return -EINVAL;
} }
if (!pdsp->started) {
dev_err(kdev->dev, "pdsp id %d not started for range %s\n",
info->pdsp_id, range->name);
return -ENODEV;
}
info->pdsp = pdsp; info->pdsp = pdsp;
channels = range->num_queues; channels = range->num_queues;
if (of_get_property(node, "multi-queue", NULL)) { if (of_get_property(node, "multi-queue", NULL)) {
......
...@@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock); ...@@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock);
idx < (kdev)->num_queues_in_use; \ idx < (kdev)->num_queues_in_use; \
idx++, inst = knav_queue_idx_to_inst(kdev, idx)) idx++, inst = knav_queue_idx_to_inst(kdev, idx))
/* All firmware file names end up here. List the firmware file names below.
* Newest followed by older ones. Search is done from start of the array
* until a firmware file is found.
*/
const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"};
/** /**
* knav_queue_notify: qmss queue notfier call * knav_queue_notify: qmss queue notfier call
* *
...@@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, ...@@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
struct device *dev = kdev->dev; struct device *dev = kdev->dev;
struct knav_pdsp_info *pdsp; struct knav_pdsp_info *pdsp;
struct device_node *child; struct device_node *child;
int ret;
for_each_child_of_node(pdsps, child) { for_each_child_of_node(pdsps, child) {
pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
...@@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, ...@@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
return -ENOMEM; return -ENOMEM;
} }
pdsp->name = knav_queue_find_name(child); pdsp->name = knav_queue_find_name(child);
ret = of_property_read_string(child, "firmware",
&pdsp->firmware);
if (ret < 0 || !pdsp->firmware) {
dev_err(dev, "unknown firmware for pdsp %s\n",
pdsp->name);
devm_kfree(dev, pdsp);
continue;
}
dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name,
pdsp->firmware);
pdsp->iram = pdsp->iram =
knav_queue_map_reg(kdev, child, knav_queue_map_reg(kdev, child,
KNAV_QUEUE_PDSP_IRAM_REG_INDEX); KNAV_QUEUE_PDSP_IRAM_REG_INDEX);
...@@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, ...@@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
} }
of_property_read_u32(child, "id", &pdsp->id); of_property_read_u32(child, "id", &pdsp->id);
list_add_tail(&pdsp->list, &kdev->pdsps); list_add_tail(&pdsp->list, &kdev->pdsps);
dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n", dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n",
pdsp->name, pdsp->command, pdsp->iram, pdsp->regs, pdsp->name, pdsp->command, pdsp->iram, pdsp->regs,
pdsp->intd, pdsp->firmware); pdsp->intd);
} }
return 0; return 0;
} }
...@@ -1510,6 +1504,8 @@ static int knav_queue_stop_pdsp(struct knav_device *kdev, ...@@ -1510,6 +1504,8 @@ static int knav_queue_stop_pdsp(struct knav_device *kdev,
dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name); dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name);
return ret; return ret;
} }
pdsp->loaded = false;
pdsp->started = false;
return 0; return 0;
} }
...@@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev, ...@@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev,
{ {
int i, ret, fwlen; int i, ret, fwlen;
const struct firmware *fw; const struct firmware *fw;
bool found = false;
u32 *fwdata; u32 *fwdata;
ret = request_firmware(&fw, pdsp->firmware, kdev->dev); for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
if (ret) { if (knav_acc_firmwares[i]) {
dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n", ret = request_firmware(&fw,
pdsp->firmware, pdsp->name); knav_acc_firmwares[i],
return ret; kdev->dev);
if (!ret) {
found = true;
break;
} }
}
}
if (!found) {
dev_err(kdev->dev, "failed to get firmware for pdsp\n");
return -ENODEV;
}
dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n",
knav_acc_firmwares[i]);
writel_relaxed(pdsp->id + 1, pdsp->command + 0x18); writel_relaxed(pdsp->id + 1, pdsp->command + 0x18);
/* download the firmware */ /* download the firmware */
fwdata = (u32 *)fw->data; fwdata = (u32 *)fw->data;
...@@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev) ...@@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
int ret; int ret;
knav_queue_stop_pdsps(kdev); knav_queue_stop_pdsps(kdev);
/* now load them all */ /* now load them all. We return success even if pdsp
* is not loaded as acc channels are optional on having
* firmware availability in the system. We set the loaded
* and stated flag and when initialize the acc range, check
* it and init the range only if pdsp is started.
*/
for_each_pdsp(kdev, pdsp) { for_each_pdsp(kdev, pdsp) {
ret = knav_queue_load_pdsp(kdev, pdsp); ret = knav_queue_load_pdsp(kdev, pdsp);
if (ret < 0) if (!ret)
return ret; pdsp->loaded = true;
} }
for_each_pdsp(kdev, pdsp) { for_each_pdsp(kdev, pdsp) {
if (pdsp->loaded) {
ret = knav_queue_start_pdsp(kdev, pdsp); ret = knav_queue_start_pdsp(kdev, pdsp);
WARN_ON(ret); if (!ret)
pdsp->started = true;
}
} }
return 0; return 0;
} }
......
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_IMX7_IOMUXC_GPR_H
#define __LINUX_IMX7_IOMUXC_GPR_H
#define IOMUXC_GPR0 0x00
#define IOMUXC_GPR1 0x04
#define IOMUXC_GPR2 0x08
#define IOMUXC_GPR3 0x0c
#define IOMUXC_GPR4 0x10
#define IOMUXC_GPR5 0x14
#define IOMUXC_GPR6 0x18
#define IOMUXC_GPR7 0x1c
#define IOMUXC_GPR8 0x20
#define IOMUXC_GPR9 0x24
#define IOMUXC_GPR10 0x28
#define IOMUXC_GPR11 0x2c
#define IOMUXC_GPR12 0x30
#define IOMUXC_GPR13 0x34
#define IOMUXC_GPR14 0x38
#define IOMUXC_GPR15 0x3c
#define IOMUXC_GPR16 0x40
#define IOMUXC_GPR17 0x44
#define IOMUXC_GPR18 0x48
#define IOMUXC_GPR19 0x4c
#define IOMUXC_GPR20 0x50
#define IOMUXC_GPR21 0x54
#define IOMUXC_GPR22 0x58
/* For imx7d iomux gpr register field define */
#define IMX7D_GPR1_IRQ_MASK (0x1 << 12)
#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK (0x1 << 13)
#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK (0x1 << 14)
#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13)
#define IMX7D_GPR1_ENET1_CLK_DIR_MASK (0x1 << 17)
#define IMX7D_GPR1_ENET2_CLK_DIR_MASK (0x1 << 18)
#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17)
#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI (0x1 << 4)
#endif /* __LINUX_IMX7_IOMUXC_GPR_H */
...@@ -9,15 +9,7 @@ ...@@ -9,15 +9,7 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/leds.h>
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
#include <linux/atmel-mci.h>
#include <sound/atmel-ac97c.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/platform_data/macb.h>
/* Compact Flash */ /* Compact Flash */
struct at91_cf_data { struct at91_cf_data {
......
#ifndef __BRCMSTB_SOC_H
#define __BRCMSTB_SOC_H
/*
* Bus Interface Unit control register setup, must happen early during boot,
* before SMP is brought up, called by machine entry point.
*/
void brcmstb_biuctrl_init(void);
#endif /* __BRCMSTB_SOC_H */
/*
* Copyright © 2014 NVIDIA Corporation
* Copyright © 2015 Broadcom Corporation
*
* 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.
*/
#ifndef __SOC_BRCMSTB_COMMON_H__
#define __SOC_BRCMSTB_COMMON_H__
bool soc_is_brcmstb(void);
#endif /* __SOC_BRCMSTB_COMMON_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment