ARM: SoC platform updates for v4.4

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.
 
 + A handful of other patches around above functionality, and a few other
 smaller changes.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWQCmaAAoJEIwa5zzehBx3F/0QAKIYmvmJM3sUanNEEwhRilx+
 3xhSgld7e25suLGwrNapTkd8VzVB4b8GnJhNShNk+l5WqfqICHCB4Aru2NmJHY8V
 yPj5vBrgJTVMnIiH7CRDPz9IlwAkWM4MmWi4PgFuhrk1T/0wPKPNMc40OWOloTeD
 gA5YmbbX1hNOqKoI/z+DK7CEdp1lHrEjeYIbnQ0SldFzkY9NKhrI784gtcz3si6E
 19pFQ9LA7EtEv7aRcFOA0sazeooa2wiJ9P9L31Mn5APZBJj5H8HjyKdvOmJ8neQn
 +b77Tya11Q70U57uDq69l0rl58fpy650uTwYaLNGWmUdTgOiGMWN05lvIVNrQd/R
 gP+VEQDGsTH6kqOCy9gyLCmn9q9I7l0t9lwcu5TP52Xy9vqVq9rb388MkcPcsWk8
 cYPvD8RcSaywZUV3YJgbYozBfVuf5rLVus6D54pMXe3N12KGaNBt8kk4co4jBwvh
 b//1urA82cdlEAZ/kiqHXjRMq/ht+dxtb6sSVOJ9frxPLuc7g1z4ORC+Z0PTS5WC
 zB0hMzPnTwXeqHcYpV4wP/vGtgZGpLevBkK7pKVdqKZykV8BS4FiT4HFp6Rghxs3
 dxAz7JjQUle6KOX7YfuHdpLnyZFWQvLYyTn946xGKpw2QH/iWLwECpet2I87QzVs
 QkEkGygPhK4QcGccxz9N
 =h5xk
 -----END PGP SIGNATURE-----

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

Pull ARM SoC platform updates from Olof Johansson:
 "New 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
  ...
This commit is contained in:
Linus Torvalds 2015-11-10 14:56:23 -08:00
commit 56e0464980
70 changed files with 1888 additions and 296 deletions

View File

@ -19,7 +19,7 @@ executing kernel.
Address: sysram_ns_base_addr
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
0x1c exynos4_secondary_startup Secondary CPU boot
0x1c + 4*cpu exynos4_secondary_startup (Exynos4412) Secondary CPU boot
@ -56,7 +56,8 @@ Offset Value Purpose
Address: pmu_base_addr
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

View File

@ -0,0 +1,56 @@
* 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.

View File

@ -25,7 +25,7 @@ SunXi family
+ Datasheet
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
http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
+ User Manual

View File

@ -27,6 +27,11 @@ Required properties:
* For "marvell,armada-380-coherency-fabric", only one pair is needed
for the per-CPU fabric registers.
Optional properties:
- broken-idle: boolean to set when the Idle mode is not supported by the
hardware.
Examples:
coherency-fabric@d0020200 {

View File

@ -0,0 +1,20 @@
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>;
};

View File

@ -6,6 +6,7 @@ using one of the following compatible strings:
allwinner,sun4i-a10
allwinner,sun5i-a10s
allwinner,sun5i-a13
allwinner,sun5i-r8
allwinner,sun6i-a31
allwinner,sun7i-a20
allwinner,sun8i-a23

View File

@ -0,0 +1,60 @@
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>;
};

View File

@ -221,7 +221,6 @@ qmss: qmss@2a40000 {
#size-cells = <1>;
ranges;
pdsp0@0x2a10000 {
firmware = "keystone/qmss_pdsp_acc48_k2_le_1_0_0_8.fw";
reg = <0x2a10000 0x1000>,
<0x2a0f000 0x100>,
<0x2a0c000 0x3c8>,

View File

@ -920,7 +920,7 @@ M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
S: Maintained
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: Alexandre Belloni <alexandre.belloni@free-electrons.com>
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
@ -1630,7 +1630,9 @@ M: Masahiro Yamada <yamada.masahiro@socionext.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/boot/dts/uniphier*
F: arch/arm/include/asm/hardware/cache-uniphier.h
F: arch/arm/mach-uniphier/
F: arch/arm/mm/cache-uniphier.c
F: drivers/i2c/busses/i2c-uniphier*
F: drivers/pinctrl/uniphier/
F: drivers/tty/serial/8250/8250_uniphier.c

View File

@ -123,29 +123,23 @@ choice
0x80020000 | 0xf0020000 | UART8
0x80024000 | 0xf0024000 | UART9
config AT91_DEBUG_LL_DBGU0
bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10, 9rl, 9x5, 9n12"
select DEBUG_AT91_UART
config DEBUG_AT91_UART
bool "Kernel low-level debugging on Atmel SoCs"
depends on ARCH_AT91
depends on SOC_AT91RM9200 || SOC_AT91SAM9
help
Say Y here if you want the debug print routines to direct
their output to the serial port on atmel devices.
config AT91_DEBUG_LL_DBGU1
bool "Kernel low-level debugging on 9263, 9g45 and sama5d3"
select DEBUG_AT91_UART
depends on ARCH_AT91
depends on SOC_AT91SAM9 || SOC_SAMA5
SOC DEBUG_UART_PHYS DEBUG_UART_VIRT PORT
rm9200, 9260/9g20, 0xfffff200 0xfefff200 DBGU
9261/9g10, 9rl
9263, 9g45, sama5d3 0xffffee00 0xfeffee00 DBGU
sama5d4 0xfc00c000 0xfb00c000 USART3
sama5d4 0xfc069000 0xfb069000 DBGU
sama5d2 0xf8020000 0xf7020000 UART1
config AT91_DEBUG_LL_DBGU2
bool "Kernel low-level debugging on sama5d4"
select DEBUG_AT91_UART
depends on ARCH_AT91
depends on SOC_SAMA5
config AT91_DEBUG_LL_DBGU3
bool "Kernel low-level debugging on sama5d2"
select DEBUG_AT91_UART
depends on ARCH_AT91
depends on SOC_SAMA5
Please adjust DEBUG_UART_PHYS configuration options based on
your needs.
config DEBUG_BCM2835
bool "Kernel low-level debugging on BCM2835 PL011 UART"
@ -1249,10 +1243,6 @@ choice
endchoice
config DEBUG_AT91_UART
bool
depends on ARCH_AT91
config DEBUG_EXYNOS_UART
bool
@ -1485,7 +1475,8 @@ config DEBUG_UART_PHYS
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_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
hex "Virtual base address of debug UART"

View File

@ -0,0 +1,46 @@
/*
* 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 */

View File

@ -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
#define AT91_IO_P2V(x) ((x) - 0x01000000)
#else
#define AT91_IO_P2V(x) (x)
#endif
#define CONFIG_DEBUG_UART_VIRT AT91_IO_P2V(CONFIG_DEBUG_UART_PHYS)
#define AT91_DBGU_SR (0x14) /* Status Register */
#define AT91_DBGU_THR (0x1c) /* Transmitter Holding Register */
#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */
#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */
.macro addruart, rp, rv, tmp
ldr \rp, =AT91_DBGU @ System peripherals (phys address)
ldr \rv, =AT91_IO_P2V(AT91_DBGU) @ System peripherals (virt address)
ldr \rp, =CONFIG_DEBUG_UART_PHYS @ System peripherals (phys address)
ldr \rv, =CONFIG_DEBUG_UART_VIRT @ System peripherals (virt address)
.endm
.macro senduart,rd,rx

View File

@ -39,6 +39,7 @@
#include <linux/export.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/cache-uniphier.h>
#include <asm/outercache.h>
#include <asm/exception.h>
#include <asm/mach/arch.h>
@ -97,6 +98,8 @@ void __init init_IRQ(void)
if (ret)
pr_err("L2C: failed to init: %d\n", ret);
}
uniphier_cache_init();
}
#ifdef CONFIG_MULTI_IRQ_HANDLER

View File

@ -80,6 +80,8 @@ tmp2 .req r5
* @r2: base address of second SDRAM Controller or 0 if not present
* @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)
/* Save registers on stack */
stmfd sp!, {r4 - r12, lr}

View File

@ -35,6 +35,20 @@ config ARCH_BCM_CYGNUS
BCM11300, BCM11320, BCM11350, BCM11360,
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
bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
select ARCH_BCM_IPROC
@ -147,6 +161,7 @@ config ARCH_BRCMSTB
select BCM7120_L2_IRQ
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_WANT_OPTIONAL_GPIOLIB
select SOC_BRCMSTB
help
Say Y if you intend to run the kernel on a Broadcom ARM-based STB
chipset.

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2012-2014 Broadcom Corporation
# Copyright (C) 2012-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
@ -13,6 +13,9 @@
# Cygnus
obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o
# Northstar Plus
obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o
# BCM281XX
obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o

View File

@ -0,0 +1,25 @@
/*
* 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

View File

@ -12,11 +12,19 @@
*/
#include <linux/init.h>
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/soc/brcmstb/brcmstb.h>
#include <asm/mach-types.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 = {
"brcm,bcm7445",
"brcm,brcmstb",
@ -25,4 +33,5 @@ static const char *const brcmstb_match[] __initconst = {
DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
.dt_compat = brcmstb_match,
.init_irq = brcmstb_init_irq,
MACHINE_END

View File

@ -18,6 +18,11 @@
#include <asm/hardware/cache-l2x0.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[] = {
"marvell,berlin",
NULL,
@ -25,6 +30,7 @@ static const char * const berlin_dt_compat[] = {
DT_MACHINE_START(BERLIN_DT, "Marvell Berlin")
.dt_compat = berlin_dt_compat,
.init_late = berlin_init_late,
/*
* with DT probing for L2CCs, berlin_init_machine can be removed.
* Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc

View File

@ -14,10 +14,16 @@
#include <linux/of_address.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.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 SW_RESET_ADDR 0x94
@ -30,9 +36,11 @@ static inline void berlin_perform_reset_cpu(unsigned int cpu)
{
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));
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)
@ -91,8 +99,32 @@ unmap_scu:
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 = {
.smp_prepare_cpus = berlin_smp_prepare_cpus,
.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);

View File

@ -1,7 +1,10 @@
config ARCH_DIGICOLOR
bool "Conexant Digicolor SoC Support"
depends on ARCH_MULTI_V7
select ARCH_REQUIRE_GPIOLIB
select CLKSRC_MMIO
select DIGICOLOR_TIMER
select GENERIC_IRQ_CHIP
select MFD_SYSCON
select PINCTRL
select PINCTRL_DIGICOLOR

View File

@ -131,6 +131,7 @@ void imx6q_pm_init(void);
void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6ul_pm_init(void);
#ifdef CONFIG_PM
void imx51_pm_init(void);

View File

@ -67,6 +67,7 @@ static void __init imx6ul_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
imx6ul_enet_init();
imx_anatop_init();
imx6ul_pm_init();
}
static void __init imx6ul_init_irq(void)
@ -74,6 +75,13 @@ static void __init imx6ul_init_irq(void)
imx_init_revision_from_anatop();
imx_src_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 = {
@ -84,5 +92,6 @@ static const char *imx6ul_dt_compat[] __initconst = {
DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
.init_irq = imx6ul_init_irq,
.init_machine = imx6ul_init_machine,
.init_late = imx6ul_init_late,
.dt_compat = imx6ul_dt_compat,
MACHINE_END

View File

@ -6,12 +6,85 @@
* published by the Free Software Foundation.
*/
#include <linux/irqchip.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
static 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)
{
struct device *parent;
@ -22,6 +95,7 @@ static void __init imx7d_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
imx_anatop_init();
imx7d_enet_init();
}
static void __init imx7d_init_irq(void)

View File

@ -93,6 +93,7 @@ struct imx6_pm_socdata {
const char *src_compat;
const char *iomuxc_compat;
const char *gpc_compat;
const char *pl310_compat;
const u32 mmdc_io_num;
const u32 *mmdc_io_offset;
};
@ -137,11 +138,19 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
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 = {
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6q-iomuxc",
.gpc_compat = "fsl,imx6q-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(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 = {
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6dl-iomuxc",
.gpc_compat = "fsl,imx6q-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(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 = {
.src_compat = "fsl,imx6sl-src",
.iomuxc_compat = "fsl,imx6sl-iomuxc",
.gpc_compat = "fsl,imx6sl-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(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 = {
.src_compat = "fsl,imx6sx-src",
.iomuxc_compat = "fsl,imx6sx-iomuxc",
.gpc_compat = "fsl,imx6sx-gpc",
.pl310_compat = "arm,pl310-cache",
.mmdc_io_num = ARRAY_SIZE(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
* 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)
val |= BM_CLPCR_SBYOS;
if (cpu_is_imx6sl())
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;
else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@ -330,6 +352,10 @@ static int imx6q_suspend_finish(unsigned long val)
* as we need to float DDR IO.
*/
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);
}
@ -470,6 +496,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
MX6Q_SUSPEND_OCRAM_SIZE, false);
memset(suspend_ocram_base, 0, sizeof(*pm_info));
pm_info = suspend_ocram_base;
pm_info->pbase = ocram_pbase;
pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
@ -505,11 +532,13 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
goto gpc_map_failed;
}
ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
if (ret) {
pr_warn("%s: failed to get pl310-cache base %d!\n",
__func__, ret);
goto pl310_cache_map_failed;
if (socdata->pl310_compat) {
ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
if (ret) {
pr_warn("%s: failed to get pl310-cache base %d!\n",
__func__, ret);
goto pl310_cache_map_failed;
}
}
pm_info->ddr_type = imx_mmdc_get_ddr_type();
@ -610,3 +639,8 @@ void __init imx6sx_pm_init(void)
{
imx6_pm_common_init(&imx6sx_pm_data);
}
void __init imx6ul_pm_init(void)
{
imx6_pm_common_init(&imx6ul_pm_data);
}

View File

@ -79,12 +79,15 @@
/* sync L2 cache to drain L2's buffers to DRAM. */
#ifdef CONFIG_CACHE_L2X0
ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
teq r11, #0
beq 6f
mov r6, #0x0
str r6, [r11, #L2X0_CACHE_SYNC]
1:
ldr r6, [r11, #L2X0_CACHE_SYNC]
ands r6, r6, #0x1
bne 1b
6:
#endif
.endm

View File

@ -1 +1,4 @@
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
endif
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o

View File

@ -16,6 +16,32 @@
*/
#include <linux/init.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[] = {
"mediatek,mt6589",
@ -27,4 +53,5 @@ static const char * const mediatek_board_dt_compat[] = {
DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
.dt_compat = mediatek_board_dt_compat,
.init_time = mediatek_timer_init,
MACHINE_END

View File

@ -0,0 +1,141 @@
/*
* 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);

View File

@ -19,4 +19,9 @@ config MACH_MESON8
default ARCH_MESON
select MESON6_TIMER
config MACH_MESON8B
bool "Amlogic Meson8b SoCs support"
default ARCH_MESON
select MESON6_TIMER
endif

View File

@ -19,6 +19,7 @@
static const char * const meson_common_board_compat[] = {
"amlogic,meson6",
"amlogic,meson8",
"amlogic,meson8b",
NULL,
};

View File

@ -40,6 +40,7 @@
unsigned long coherency_phys_base;
void __iomem *coherency_base;
static void __iomem *coherency_cpu_base;
static void __iomem *cpu_config_base;
/* Coherency fabric registers */
#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
@ -65,6 +66,31 @@ static const struct of_device_id of_coherency_table[] = {
int ll_enable_coherency(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,
unsigned long event, void *__dev)
{
@ -85,9 +111,24 @@ static struct notifier_block mvebu_hwcc_pci_nb = {
.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)
{
struct resource res;
struct device_node *cpu_config_np;
of_address_to_resource(np, 0, &res);
coherency_phys_base = res.start;
@ -100,6 +141,23 @@ static void __init armada_370_coherency_init(struct device_node *np)
sync_cache_w(&coherency_phys_base);
coherency_base = of_iomap(np, 0);
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();
}
@ -204,6 +262,8 @@ int set_cpu_coherent(void)
pr_warn("Coherency fabric is not initialized\n");
return 1;
}
armada_xp_clear_shared_l2();
ll_add_cpu_to_smp_group();
return ll_enable_coherency();
}

View File

@ -379,6 +379,16 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = {
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)
{
struct device_node *np;
@ -387,7 +397,9 @@ static __init int armada_370_cpuidle_init(void)
np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
if (!np)
return -ENODEV;
of_node_put(np);
if (broken_idle(np))
goto end;
/*
* On Armada 370, there is "a slow exit process from the deep
@ -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.name = "cpuidle-armada-370";
end:
of_node_put(np);
return 0;
}
@ -422,6 +436,10 @@ static __init int armada_38x_cpuidle_init(void)
"marvell,armada-380-coherency-fabric");
if (!np)
return -ENODEV;
if (broken_idle(np))
goto end;
of_node_put(np);
np = of_find_compatible_node(NULL, NULL,
@ -430,7 +448,6 @@ static __init int armada_38x_cpuidle_init(void)
return -ENODEV;
mpsoc_base = of_iomap(np, 0);
BUG_ON(!mpsoc_base);
of_node_put(np);
/* Set up reset mask when powering down the cpus */
reg = readl(mpsoc_base + MPCORE_RESET_CTL);
@ -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.name = "cpuidle-armada-38x";
end:
of_node_put(np);
return 0;
}
@ -460,12 +479,16 @@ static __init int armada_xp_cpuidle_init(void)
np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
if (!np)
return -ENODEV;
of_node_put(np);
if (broken_idle(np))
goto end;
mvebu_cpu_resume = armada_370_xp_cpu_resume;
mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
end:
of_node_put(np);
return 0;
}

View File

@ -45,6 +45,7 @@ config MACH_KUROBOX_PRO
config MACH_DNS323
bool "D-Link DNS-323"
select GENERIC_NET_UTILS
select I2C_BOARDINFO
help
Say 'Y' here if you want your kernel to support the
@ -52,6 +53,7 @@ config MACH_DNS323
config MACH_TS209
bool "QNAP TS-109/TS-209"
select GENERIC_NET_UTILS
help
Say 'Y' here if you want your kernel to support the
QNAP TS-109/TS-209 platform.
@ -93,6 +95,7 @@ config MACH_LINKSTATION_LS_HGL
config MACH_TS409
bool "QNAP TS-409"
select GENERIC_NET_UTILS
help
Say 'Y' here if you want your kernel to support the
QNAP TS-409 platform.

View File

@ -173,42 +173,10 @@ static struct mv643xx_eth_platform_data dns323_eth_data = {
.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)
{
u_int8_t addr[6];
int i;
char *mac_page;
void __iomem *mac_page;
/* MAC address is stored as a regular ol' string in /dev/mtdblock4
* (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
@ -217,23 +185,8 @@ static int __init dns323_read_mac_addr(void)
if (!mac_page)
return -ENOMEM;
/* Sanity check the string we're looking at */
for (i = 0; i < 5; i++) {
if (*(mac_page + (i * 3) + 2) != ':') {
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;
}
if (!mac_pton((__force const char *) mac_page, addr))
goto error_fail;
iounmap(mac_page);
printk("DNS-323: Found ethernet MAC address: %pM\n", addr);

View File

@ -53,53 +53,12 @@ struct mv643xx_eth_platform_data qnap_tsx09_eth_data = {
.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)
{
u_int8_t addr[6];
int i;
for (i = 0; i < 6; i++) {
int byte;
/*
* 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;
addr[i] = byte;
}
if (!mac_pton(addr_str, addr))
return -1;
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)
unsigned long addr;
for (addr = mem_base; addr < (mem_base + size); addr += 1024) {
char *nor_page;
void __iomem *nor_page;
int ret = 0;
nor_page = ioremap(addr, 1024);
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);
}

View File

@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/i2c.h>
#include <linux/leds.h>
@ -469,6 +470,11 @@ static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
.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)
{
gpio_request(S3C2410_GPB(0), "Backlight");
@ -503,11 +509,8 @@ static void h1940_backlight_exit(struct device *dev)
static struct platform_pwm_backlight_data backlight_data = {
.pwm_id = 0,
.max_brightness = 100,
.dft_brightness = 50,
/* tcnt = 0x31 */
.pwm_period_ns = 36296,
.enable_gpio = -1,
.init = h1940_backlight_init,
.notify = h1940_backlight_notify,
@ -725,6 +728,7 @@ static void __init h1940_init(void)
gpio_request(H1940_LATCH_SD_POWER, "SD power");
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));
gpio_request(S3C2410_GPA(1), "Red LED blink");

View File

@ -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 void rx1950_lcd_power(int enable)
@ -520,10 +525,8 @@ static int rx1950_backlight_notify(struct device *dev, int brightness)
}
static struct platform_pwm_backlight_data rx1950_backlight_data = {
.pwm_id = 0,
.max_brightness = 24,
.dft_brightness = 4,
.pwm_period_ns = 48000,
.enable_gpio = -1,
.init = rx1950_backlight_init,
.notify = rx1950_backlight_notify,
@ -792,6 +795,7 @@ static void __init rx1950_init_machine(void)
gpio_direction_output(S3C2410_GPA(4), 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));
i2c_register_board_info(0, rx1950_i2c_devices,

View File

@ -69,7 +69,6 @@ static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = {
.plat_data = {
.max_brightness = 255,
.dft_brightness = 255,
.pwm_period_ns = 78770,
.enable_gpio = -1,
.init = samsung_bl_init,
.exit = samsung_bl_exit,
@ -111,7 +110,6 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
samsung_bl_data = &samsung_bl_drvdata->plat_data;
/* 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;
if (bl_data->max_brightness)
@ -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;
if (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)
samsung_bl_data->enable_gpio = bl_data->enable_gpio;
if (bl_data->init)

View File

@ -25,6 +25,7 @@
#include <linux/mmc/host.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/dm9000.h>
#include <linux/gpio_keys.h>
@ -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 = {
.pwm_id = 0,
.max_brightness = 1000,
.dft_brightness = 600,
.pwm_period_ns = 100000, /* about 1kHz */
.enable_gpio = -1,
};
@ -843,6 +847,7 @@ static void __init crag6410_machine_init(void)
samsung_keypad_set_platdata(&crag6410_keypad_data);
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));
gpio_led_register_device(-1, &gpio_leds_pdata);

View File

@ -19,6 +19,7 @@
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/leds.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@ -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)
{
int ret;
@ -110,10 +116,8 @@ static void hmt_bl_exit(struct device *dev)
}
static struct platform_pwm_backlight_data hmt_backlight_data = {
.pwm_id = 1,
.max_brightness = 100 * 256,
.dft_brightness = 40 * 256,
.pwm_period_ns = 1000000000 / (100 * 256 * 20),
.enable_gpio = -1,
.init = hmt_bl_init,
.notify = hmt_bl_notify,
@ -268,6 +272,7 @@ static void __init hmt_machine_init(void)
gpio_request(S3C64XX_GPF(13), "usb power");
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));
}

View File

@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
@ -139,6 +140,11 @@ static struct platform_device smartq_usb_otg_vbus_dev = {
.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)
{
s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
@ -147,10 +153,8 @@ static int smartq_bl_init(struct device *dev)
}
static struct platform_pwm_backlight_data smartq_backlight_data = {
.pwm_id = 1,
.max_brightness = 1000,
.dft_brightness = 600,
.pwm_period_ns = 1000000000 / (1000 * 20),
.enable_gpio = -1,
.init = smartq_bl_init,
};
@ -396,5 +400,6 @@ void __init smartq_machine_init(void)
WARN_ON(smartq_usb_host_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));
}

View File

@ -30,6 +30,7 @@
#include <linux/smsc911x.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/platform_data/s3c-hsotg.h>
@ -623,8 +624,12 @@ static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
.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 = {
.pwm_id = 1,
.enable_gpio = -1,
};
@ -695,6 +700,7 @@ static void __init smdk6410_machine_init(void)
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);
}

View File

@ -12,6 +12,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/clk/shmobile.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/of.h>
@ -124,36 +125,6 @@ static bool rmobile_pd_active_wakeup(struct device *dev)
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)
{
struct generic_pm_domain *genpd = &rmobile_pd->genpd;
@ -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->power_off = rmobile_pd_power_down;
genpd->power_on = rmobile_pd_power_up;
genpd->attach_dev = rmobile_pd_attach_dev;
genpd->detach_dev = rmobile_pd_detach_dev;
genpd->attach_dev = cpg_mstp_attach_dev;
genpd->detach_dev = cpg_mstp_detach_dev;
__rmobile_pd_power_up(rmobile_pd, false);
}

View File

@ -26,10 +26,11 @@ static const char * const sunxi_board_dt_compat[] = {
"allwinner,sun4i-a10",
"allwinner,sun5i-a10s",
"allwinner,sun5i-a13",
"allwinner,sun5i-r8",
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,
.init_late = sunxi_dt_cpufreq_init,
MACHINE_END

View File

@ -39,8 +39,8 @@ static struct platform_device wifi_rfkill_device = {
static struct gpiod_lookup_table wifi_gpio_lookup = {
.dev_id = "rfkill_gpio",
.table = {
GPIO_LOOKUP_IDX("tegra-gpio", 25, NULL, 0, 0),
GPIO_LOOKUP_IDX("tegra-gpio", 85, NULL, 1, 0),
GPIO_LOOKUP("tegra-gpio", 25, "reset", 0),
GPIO_LOOKUP("tegra-gpio", 85, "shutdown", 0),
{ },
},
};

View File

@ -1,2 +1,2 @@
obj-y := uniphier.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o

View File

@ -0,0 +1,43 @@
/*
* 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)

View File

@ -12,73 +12,198 @@
* GNU General Public License for more details.
*/
#include <linux/sizes.h>
#include <linux/compiler.h>
#define pr_fmt(fmt) "uniphier: " fmt
#include <linux/init.h>
#include <linux/io.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/ioport.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_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)
{
size_t trmp_size;
static void __iomem *trmp_base;
if (!uniphier_cache_l2_is_enabled()) {
pr_warn("outer cache is needed for SMP, but not enabled\n");
return -ENODEV;
}
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)
{
static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
unsigned long scu_base_phys = 0;
void __iomem *scu_base;
sbcm_regmap = syscon_regmap_lookup_by_compatible(
"socionext,uniphier-system-bus-controller-misc");
if (IS_ERR(sbcm_regmap)) {
pr_err("failed to regmap system-bus-controller-misc\n");
goto err;
}
if (scu_a9_has_base())
scu_base_phys = scu_a9_get_base();
if (!scu_base_phys) {
pr_err("failed to get scu base\n");
goto err;
return -ENODEV;
}
scu_base = ioremap(scu_base_phys, SZ_128);
if (!scu_base) {
pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys);
goto err;
pr_err("failed to map scu base\n");
return -ENOMEM;
}
scu_enable(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;
err:
pr_warn("disabling SMP\n");
init_cpu_present(&only_cpu_0);
sbcm_regmap = NULL;
uniphier_smp_unprepare_trampoline();
}
static int uniphier_boot_secondary(unsigned int cpu,
struct task_struct *idle)
static int __init uniphier_smp_boot_secondary(unsigned int cpu,
struct task_struct *idle)
{
int ret;
if (WARN_ON_ONCE(!uniphier_smp_rom_boot_rsv2))
return -EFAULT;
if (!sbcm_regmap)
return -ENODEV;
writel(cpu, uniphier_smp_rom_boot_rsv2);
readl(uniphier_smp_rom_boot_rsv2); /* relax */
ret = regmap_write(sbcm_regmap, 0x1208,
virt_to_phys(secondary_startup));
if (!ret)
asm("sev"); /* wake up secondary CPU */
asm("sev"); /* wake up secondary CPUs sleeping in the trampoline */
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_boot_secondary = uniphier_boot_secondary,
.smp_boot_secondary = uniphier_smp_boot_secondary,
};
CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
&uniphier_smp_ops);

View File

@ -974,6 +974,16 @@ config CACHE_TAUROS2
This option enables the Tauros2 L2 cache controller (as
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
bool "Enable the L2 cache on XScale3"
depends on CPU_XSC3

View File

@ -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_XSC3L2) += cache-xsc3l2.o
obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o

View File

@ -0,0 +1,555 @@
/*
* 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.
*/
#define pr_fmt(fmt) "uniphier: " fmt
#include <linux/init.h>
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <asm/hardware/cache-uniphier.h>
#include <asm/outercache.h>
/* control registers */
#define UNIPHIER_SSCC 0x0 /* Control Register */
#define UNIPHIER_SSCC_BST BIT(20) /* UCWG burst read */
#define UNIPHIER_SSCC_ACT BIT(19) /* Inst-Data separate */
#define UNIPHIER_SSCC_WTG BIT(18) /* WT gathering on */
#define UNIPHIER_SSCC_PRD BIT(17) /* enable pre-fetch */
#define UNIPHIER_SSCC_ON BIT(0) /* enable cache */
#define UNIPHIER_SSCLPDAWCR 0x30 /* Unified/Data Active Way Control */
#define UNIPHIER_SSCLPIAWCR 0x34 /* Instruction Active Way Control */
/* revision registers */
#define UNIPHIER_SSCID 0x0 /* ID Register */
/* operation registers */
#define UNIPHIER_SSCOPE 0x244 /* Cache Operation Primitive Entry */
#define UNIPHIER_SSCOPE_CM_INV 0x0 /* invalidate */
#define UNIPHIER_SSCOPE_CM_CLEAN 0x1 /* clean */
#define UNIPHIER_SSCOPE_CM_FLUSH 0x2 /* flush */
#define UNIPHIER_SSCOPE_CM_SYNC 0x8 /* sync (drain bufs) */
#define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */
#define UNIPHIER_SSCOQM 0x248 /* Cache Operation Queue Mode */
#define UNIPHIER_SSCOQM_TID_MASK (0x3 << 21)
#define UNIPHIER_SSCOQM_TID_LRU_DATA (0x0 << 21)
#define UNIPHIER_SSCOQM_TID_LRU_INST (0x1 << 21)
#define UNIPHIER_SSCOQM_TID_WAY (0x2 << 21)
#define UNIPHIER_SSCOQM_S_MASK (0x3 << 17)
#define UNIPHIER_SSCOQM_S_RANGE (0x0 << 17)
#define UNIPHIER_SSCOQM_S_ALL (0x1 << 17)
#define UNIPHIER_SSCOQM_S_WAY (0x2 << 17)
#define UNIPHIER_SSCOQM_CE BIT(15) /* notify completion */
#define UNIPHIER_SSCOQM_CM_INV 0x0 /* invalidate */
#define UNIPHIER_SSCOQM_CM_CLEAN 0x1 /* clean */
#define UNIPHIER_SSCOQM_CM_FLUSH 0x2 /* flush */
#define UNIPHIER_SSCOQM_CM_PREFETCH 0x3 /* prefetch to cache */
#define UNIPHIER_SSCOQM_CM_PREFETCH_BUF 0x4 /* prefetch to pf-buf */
#define UNIPHIER_SSCOQM_CM_TOUCH 0x5 /* touch */
#define UNIPHIER_SSCOQM_CM_TOUCH_ZERO 0x6 /* touch to zero */
#define UNIPHIER_SSCOQM_CM_TOUCH_DIRTY 0x7 /* touch with dirty */
#define UNIPHIER_SSCOQAD 0x24c /* Cache Operation Queue Address */
#define UNIPHIER_SSCOQSZ 0x250 /* Cache Operation Queue Size */
#define UNIPHIER_SSCOQMASK 0x254 /* Cache Operation Queue Address Mask */
#define UNIPHIER_SSCOQWN 0x258 /* Cache Operation Queue Way Number */
#define UNIPHIER_SSCOPPQSEF 0x25c /* Cache Operation Queue Set Complete*/
#define UNIPHIER_SSCOPPQSEF_FE BIT(1)
#define UNIPHIER_SSCOPPQSEF_OE BIT(0)
#define UNIPHIER_SSCOLPQS 0x260 /* Cache Operation Queue Status */
#define UNIPHIER_SSCOLPQS_EF BIT(2)
#define UNIPHIER_SSCOLPQS_EST BIT(1)
#define UNIPHIER_SSCOLPQS_QST BIT(0)
/* Is the touch/pre-fetch destination specified by ways? */
#define UNIPHIER_SSCOQM_TID_IS_WAY(op) \
((op & UNIPHIER_SSCOQM_TID_MASK) == UNIPHIER_SSCOQM_TID_WAY)
/* Is the operation region specified by address range? */
#define UNIPHIER_SSCOQM_S_IS_RANGE(op) \
((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
/**
* uniphier_cache_data - UniPhier outer cache specific data
*
* @ctrl_base: virtual base address of control registers
* @rev_base: virtual base address of revision registers
* @op_base: virtual base address of operation registers
* @way_present_mask: each bit specifies if the way is present
* @way_locked_mask: each bit specifies if the way is locked
* @nsets: number of associativity sets
* @line_size: line size in bytes
* @range_op_max_size: max size that can be handled by a single range operation
* @list: list node to include this level in the whole cache hierarchy
*/
struct uniphier_cache_data {
void __iomem *ctrl_base;
void __iomem *rev_base;
void __iomem *op_base;
u32 way_present_mask;
u32 way_locked_mask;
u32 nsets;
u32 line_size;
u32 range_op_max_size;
struct list_head list;
};
/*
* List of the whole outer cache hierarchy. This list is only modified during
* the early boot stage, so no mutex is taken for the access to the list.
*/
static LIST_HEAD(uniphier_cache_list);
/**
* __uniphier_cache_sync - perform a sync point for a particular cache level
*
* @data: cache controller specific data
*/
static void __uniphier_cache_sync(struct uniphier_cache_data *data)
{
/* This sequence need not be atomic. Do not disable IRQ. */
writel_relaxed(UNIPHIER_SSCOPE_CM_SYNC,
data->op_base + UNIPHIER_SSCOPE);
/* need a read back to confirm */
readl_relaxed(data->op_base + UNIPHIER_SSCOPE);
}
/**
* __uniphier_cache_maint_common - run a queue operation for a particular level
*
* @data: cache controller specific data
* @start: start address of range operation (don't care for "all" operation)
* @size: data size of range operation (don't care for "all" operation)
* @operation: flags to specify the desired cache operation
*/
static void __uniphier_cache_maint_common(struct uniphier_cache_data *data,
unsigned long start,
unsigned long size,
u32 operation)
{
unsigned long flags;
/*
* No spin lock is necessary here because:
*
* [1] This outer cache controller is able to accept maintenance
* operations from multiple CPUs at a time in an SMP system; if a
* maintenance operation is under way and another operation is issued,
* the new one is stored in the queue. The controller performs one
* operation after another. If the queue is full, the status register,
* UNIPHIER_SSCOPPQSEF, indicates that the queue registration has
* failed. The status registers, UNIPHIER_{SSCOPPQSEF, SSCOLPQS}, have
* different instances for each CPU, i.e. each CPU can track the status
* of the maintenance operations triggered by itself.
*
* [2] The cache command registers, UNIPHIER_{SSCOQM, SSCOQAD, SSCOQSZ,
* SSCOQWN}, are shared between multiple CPUs, but the hardware still
* guarantees the registration sequence is atomic; the write access to
* them are arbitrated by the hardware. The first accessor to the
* register, UNIPHIER_SSCOQM, holds the access right and it is released
* by reading the status register, UNIPHIER_SSCOPPQSEF. While one CPU
* is holding the access right, other CPUs fail to register operations.
* One CPU should not hold the access right for a long time, so local
* IRQs should be disabled while the following sequence.
*/
local_irq_save(flags);
/* clear the complete notification flag */
writel_relaxed(UNIPHIER_SSCOLPQS_EF, data->op_base + UNIPHIER_SSCOLPQS);
do {
/* set cache operation */
writel_relaxed(UNIPHIER_SSCOQM_CE | operation,
data->op_base + UNIPHIER_SSCOQM);
/* set address range if needed */
if (likely(UNIPHIER_SSCOQM_S_IS_RANGE(operation))) {
writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD);
writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ);
}
/* set target ways if needed */
if (unlikely(UNIPHIER_SSCOQM_TID_IS_WAY(operation)))
writel_relaxed(data->way_locked_mask,
data->op_base + UNIPHIER_SSCOQWN);
} while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) &
(UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)));
/* wait until the operation is completed */
while (likely(readl_relaxed(data->op_base + UNIPHIER_SSCOLPQS) !=
UNIPHIER_SSCOLPQS_EF))
cpu_relax();
local_irq_restore(flags);
}
static void __uniphier_cache_maint_all(struct uniphier_cache_data *data,
u32 operation)
{
__uniphier_cache_maint_common(data, 0, 0,
UNIPHIER_SSCOQM_S_ALL | operation);
__uniphier_cache_sync(data);
}
static void __uniphier_cache_maint_range(struct uniphier_cache_data *data,
unsigned long start, unsigned long end,
u32 operation)
{
unsigned long size;
/*
* If the start address is not aligned,
* perform a cache operation for the first cache-line
*/
start = start & ~(data->line_size - 1);
size = end - start;
if (unlikely(size >= (unsigned long)(-data->line_size))) {
/* this means cache operation for all range */
__uniphier_cache_maint_all(data, operation);
return;
}
/*
* If the end address is not aligned,
* perform a cache operation for the last cache-line
*/
size = ALIGN(size, data->line_size);
while (size) {
unsigned long chunk_size = min_t(unsigned long, size,
data->range_op_max_size);
__uniphier_cache_maint_common(data, start, chunk_size,
UNIPHIER_SSCOQM_S_RANGE | operation);
start += chunk_size;
size -= chunk_size;
}
__uniphier_cache_sync(data);
}
static void __uniphier_cache_enable(struct uniphier_cache_data *data, bool on)
{
u32 val = 0;
if (on)
val = UNIPHIER_SSCC_WTG | UNIPHIER_SSCC_PRD | UNIPHIER_SSCC_ON;
writel_relaxed(val, data->ctrl_base + UNIPHIER_SSCC);
}
static void __init __uniphier_cache_set_locked_ways(
struct uniphier_cache_data *data,
u32 way_mask)
{
data->way_locked_mask = way_mask & data->way_present_mask;
writel_relaxed(~data->way_locked_mask & data->way_present_mask,
data->ctrl_base + UNIPHIER_SSCLPDAWCR);
}
static void uniphier_cache_maint_range(unsigned long start, unsigned long end,
u32 operation)
{
struct uniphier_cache_data *data;
list_for_each_entry(data, &uniphier_cache_list, list)
__uniphier_cache_maint_range(data, start, end, operation);
}
static void uniphier_cache_maint_all(u32 operation)
{
struct uniphier_cache_data *data;
list_for_each_entry(data, &uniphier_cache_list, list)
__uniphier_cache_maint_all(data, operation);
}
static void uniphier_cache_inv_range(unsigned long start, unsigned long end)
{
uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_INV);
}
static void uniphier_cache_clean_range(unsigned long start, unsigned long end)
{
uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_CLEAN);
}
static void uniphier_cache_flush_range(unsigned long start, unsigned long end)
{
uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_FLUSH);
}
static void __init uniphier_cache_inv_all(void)
{
uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV);
}
static void uniphier_cache_flush_all(void)
{
uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH);
}
static void uniphier_cache_disable(void)
{
struct uniphier_cache_data *data;
list_for_each_entry_reverse(data, &uniphier_cache_list, list)
__uniphier_cache_enable(data, false);
uniphier_cache_flush_all();
}
static void __init uniphier_cache_enable(void)
{
struct uniphier_cache_data *data;
uniphier_cache_inv_all();
list_for_each_entry(data, &uniphier_cache_list, list) {
__uniphier_cache_enable(data, true);
__uniphier_cache_set_locked_ways(data, 0);
}
}
static void uniphier_cache_sync(void)
{
struct uniphier_cache_data *data;
list_for_each_entry(data, &uniphier_cache_list, list)
__uniphier_cache_sync(data);
}
int __init uniphier_cache_l2_is_enabled(void)
{
struct uniphier_cache_data *data;
data = list_first_entry_or_null(&uniphier_cache_list,
struct uniphier_cache_data, list);
if (!data)
return 0;
return !!(readl_relaxed(data->ctrl_base + UNIPHIER_SSCC) &
UNIPHIER_SSCC_ON);
}
void __init uniphier_cache_l2_touch_range(unsigned long start,
unsigned long end)
{
struct uniphier_cache_data *data;
data = list_first_entry_or_null(&uniphier_cache_list,
struct uniphier_cache_data, list);
if (data)
__uniphier_cache_maint_range(data, start, end,
UNIPHIER_SSCOQM_TID_WAY |
UNIPHIER_SSCOQM_CM_TOUCH);
}
void __init uniphier_cache_l2_set_locked_ways(u32 way_mask)
{
struct uniphier_cache_data *data;
data = list_first_entry_or_null(&uniphier_cache_list,
struct uniphier_cache_data, list);
if (data)
__uniphier_cache_set_locked_ways(data, way_mask);
}
static const struct of_device_id uniphier_cache_match[] __initconst = {
{
.compatible = "socionext,uniphier-system-cache",
},
{ /* sentinel */ }
};
static struct device_node * __init uniphier_cache_get_next_level_node(
struct device_node *np)
{
u32 phandle;
if (of_property_read_u32(np, "next-level-cache", &phandle))
return NULL;
return of_find_node_by_phandle(phandle);
}
static int __init __uniphier_cache_init(struct device_node *np,
unsigned int *cache_level)
{
struct uniphier_cache_data *data;
u32 level, cache_size;
struct device_node *next_np;
int ret = 0;
if (!of_match_node(uniphier_cache_match, np)) {
pr_err("L%d: not compatible with uniphier cache\n",
*cache_level);
return -EINVAL;
}
if (of_property_read_u32(np, "cache-level", &level)) {
pr_err("L%d: cache-level is not specified\n", *cache_level);
return -EINVAL;
}
if (level != *cache_level) {
pr_err("L%d: cache-level is unexpected value %d\n",
*cache_level, level);
return -EINVAL;
}
if (!of_property_read_bool(np, "cache-unified")) {
pr_err("L%d: cache-unified is not specified\n", *cache_level);
return -EINVAL;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
if (of_property_read_u32(np, "cache-line-size", &data->line_size) ||
!is_power_of_2(data->line_size)) {
pr_err("L%d: cache-line-size is unspecified or invalid\n",
*cache_level);
ret = -EINVAL;
goto err;
}
if (of_property_read_u32(np, "cache-sets", &data->nsets) ||
!is_power_of_2(data->nsets)) {
pr_err("L%d: cache-sets is unspecified or invalid\n",
*cache_level);
ret = -EINVAL;
goto err;
}
if (of_property_read_u32(np, "cache-size", &cache_size) ||
cache_size == 0 || cache_size % (data->nsets * data->line_size)) {
pr_err("L%d: cache-size is unspecified or invalid\n",
*cache_level);
ret = -EINVAL;
goto err;
}
data->way_present_mask =
((u32)1 << cache_size / data->nsets / data->line_size) - 1;
data->ctrl_base = of_iomap(np, 0);
if (!data->ctrl_base) {
pr_err("L%d: failed to map control register\n", *cache_level);
ret = -ENOMEM;
goto err;
}
data->rev_base = of_iomap(np, 1);
if (!data->rev_base) {
pr_err("L%d: failed to map revision register\n", *cache_level);
ret = -ENOMEM;
goto err;
}
data->op_base = of_iomap(np, 2);
if (!data->op_base) {
pr_err("L%d: failed to map operation register\n", *cache_level);
ret = -ENOMEM;
goto err;
}
if (*cache_level == 2) {
u32 revision = readl(data->rev_base + UNIPHIER_SSCID);
/*
* The size of range operation is limited to (1 << 22) or less
* for PH-sLD8 or older SoCs.
*/
if (revision <= 0x16)
data->range_op_max_size = (u32)1 << 22;
}
data->range_op_max_size -= data->line_size;
INIT_LIST_HEAD(&data->list);
list_add_tail(&data->list, &uniphier_cache_list); /* no mutex */
/*
* OK, this level has been successfully initialized. Look for the next
* level cache. Do not roll back even if the initialization of the
* next level cache fails because we want to continue with available
* cache levels.
*/
next_np = uniphier_cache_get_next_level_node(np);
if (next_np) {
(*cache_level)++;
ret = __uniphier_cache_init(next_np, cache_level);
}
of_node_put(next_np);
return ret;
err:
iounmap(data->op_base);
iounmap(data->rev_base);
iounmap(data->ctrl_base);
kfree(data);
return ret;
}
int __init uniphier_cache_init(void)
{
struct device_node *np = NULL;
unsigned int cache_level;
int ret = 0;
/* look for level 2 cache */
while ((np = of_find_matching_node(np, uniphier_cache_match)))
if (!of_property_read_u32(np, "cache-level", &cache_level) &&
cache_level == 2)
break;
if (!np)
return -ENODEV;
ret = __uniphier_cache_init(np, &cache_level);
of_node_put(np);
if (ret) {
/*
* Error out iif L2 initialization fails. Continue with any
* error on L3 or outer because they are optional.
*/
if (cache_level == 2) {
pr_err("failed to initialize L2 cache\n");
return ret;
}
cache_level--;
ret = 0;
}
outer_cache.inv_range = uniphier_cache_inv_range;
outer_cache.clean_range = uniphier_cache_clean_range;
outer_cache.flush_range = uniphier_cache_flush_range;
outer_cache.flush_all = uniphier_cache_flush_all;
outer_cache.disable = uniphier_cache_disable;
outer_cache.sync = uniphier_cache_sync;
uniphier_cache_enable();
pr_info("enabled outer cache (cache level: %d)\n", cache_level);
return ret;
}

View File

@ -7,6 +7,7 @@ config ARCH_BCM_IPROC
config ARCH_BERLIN
bool "Marvell Berlin SoC Family"
select ARCH_REQUIRE_GPIOLIB
select DW_APB_ICTL
help
This enables support for Marvell Berlin SoC Family

View File

@ -259,6 +259,10 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
"renesas,cpg-mstp-clocks"))
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);
i++;
}

View File

@ -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_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);
static const char *sun6i_critical_clocks[] __initdata = {

View File

@ -1,5 +1,6 @@
menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/brcmstb/Kconfig"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/sunxi/Kconfig"

View File

@ -2,6 +2,7 @@
# Makefile for the Linux Kernel SOC specific device drivers.
#
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
obj-$(CONFIG_MACH_DOVE) += dove/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/

View File

@ -0,0 +1,9 @@
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.

View File

@ -0,0 +1 @@
obj-y += common.o biuctrl.o

View File

@ -0,0 +1,116 @@
/*
* 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
}

View File

@ -0,0 +1,33 @@
/*
* 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;
}

View File

@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
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)) {
/* enable pwrap events and pwrap bridge in AP side */
@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev)
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);
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp);

View File

@ -54,12 +54,16 @@
#define PWR_STATUS_USB BIT(25)
enum clk_id {
MT8173_CLK_NONE,
MT8173_CLK_MM,
MT8173_CLK_MFG,
MT8173_CLK_NONE,
MT8173_CLK_MAX = MT8173_CLK_NONE,
MT8173_CLK_VENC,
MT8173_CLK_VENC_LT,
MT8173_CLK_MAX,
};
#define MAX_CLKS 2
struct scp_domain_data {
const char *name;
u32 sta_mask;
@ -67,7 +71,8 @@ struct scp_domain_data {
u32 sram_pdn_bits;
u32 sram_pdn_ack_bits;
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 = {
@ -77,7 +82,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VDE_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = MT8173_CLK_MM,
.clk_id = {MT8173_CLK_MM},
},
[MT8173_POWER_DOMAIN_VENC] = {
.name = "venc",
@ -85,7 +90,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_MM,
.clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
},
[MT8173_POWER_DOMAIN_ISP] = {
.name = "isp",
@ -93,7 +98,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_ISP_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = MT8173_CLK_MM,
.clk_id = {MT8173_CLK_MM},
},
[MT8173_POWER_DOMAIN_MM] = {
.name = "mm",
@ -101,7 +106,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_DIS_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.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 |
MT8173_TOP_AXI_PROT_EN_MM_M1,
},
@ -111,7 +116,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_VEN2_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.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] = {
.name = "audio",
@ -119,7 +124,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_AUDIO_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = MT8173_CLK_NONE,
.clk_id = {MT8173_CLK_NONE},
},
[MT8173_POWER_DOMAIN_USB] = {
.name = "usb",
@ -127,7 +132,8 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_USB_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.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] = {
.name = "mfg_async",
@ -135,7 +141,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0,
.clk_id = MT8173_CLK_MFG,
.clk_id = {MT8173_CLK_MFG},
},
[MT8173_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
@ -143,7 +149,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_2D_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = MT8173_CLK_NONE,
.clk_id = {MT8173_CLK_NONE},
},
[MT8173_POWER_DOMAIN_MFG] = {
.name = "mfg",
@ -151,7 +157,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
.ctl_offs = SPM_MFG_PWR_CON,
.sram_pdn_bits = GENMASK(13, 8),
.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 |
MT8173_TOP_AXI_PROT_EN_MFG_M0 |
MT8173_TOP_AXI_PROT_EN_MFG_M1 |
@ -166,12 +172,13 @@ struct scp;
struct scp_domain {
struct generic_pm_domain genpd;
struct scp *scp;
struct clk *clk;
struct clk *clk[MAX_CLKS];
u32 sta_mask;
void __iomem *ctl_addr;
u32 sram_pdn_bits;
u32 sram_pdn_ack_bits;
u32 bus_prot_mask;
bool active_wakeup;
};
struct scp {
@ -212,11 +219,16 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
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;
}
}
val = readl(ctl_addr);
@ -282,7 +294,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
return 0;
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:
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)
u32 pdn_ack = scpd->sram_pdn_ack_bits;
u32 val;
int ret;
int i;
if (scpd->bus_prot_mask) {
ret = mtk_infracfg_set_bus_protection(scp->infracfg,
@ -360,8 +376,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
expired = true;
}
if (scpd->clk)
clk_disable_unprepare(scpd->clk);
for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
clk_disable_unprepare(scpd->clk[i]);
return 0;
@ -371,11 +387,22 @@ out:
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)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
int i, ret;
int i, j, ret;
struct scp *scp;
struct clk *clk[MT8173_CLK_MAX];
@ -405,6 +432,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
if (IS_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,
"infracfg");
if (IS_ERR(scp->infracfg)) {
@ -428,12 +463,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
scpd->sram_pdn_bits = data->sram_pdn_bits;
scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
scpd->bus_prot_mask = data->bus_prot_mask;
if (data->clk_id != MT8173_CLK_NONE)
scpd->clk = clk[data->clk_id];
scpd->active_wakeup = data->active_wakeup;
for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
scpd->clk[j] = clk[data->clk_id[j]];
genpd->name = data->name;
genpd->power_off = scpsys_power_off;
genpd->power_on = scpsys_power_on;
genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
/*
* Initially turn on all domains to make the domains usable

View File

@ -135,9 +135,10 @@ struct knav_pdsp_info {
};
void __iomem *intd;
u32 __iomem *iram;
const char *firmware;
u32 id;
struct list_head list;
bool loaded;
bool started;
};
struct knav_qmgr_info {

View File

@ -486,8 +486,8 @@ struct knav_range_ops knav_acc_range_ops = {
* Return 0 on success or error
*/
int knav_init_acc_range(struct knav_device *kdev,
struct device_node *node,
struct knav_range_info *range)
struct device_node *node,
struct knav_range_info *range)
{
struct knav_acc_channel *acc;
struct knav_pdsp_info *pdsp;
@ -530,6 +530,12 @@ int knav_init_acc_range(struct knav_device *kdev,
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;
channels = range->num_queues;
if (of_get_property(node, "multi-queue", NULL)) {

View File

@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock);
idx < (kdev)->num_queues_in_use; \
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
*
@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
struct device *dev = kdev->dev;
struct knav_pdsp_info *pdsp;
struct device_node *child;
int ret;
for_each_child_of_node(pdsps, child) {
pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
return -ENOMEM;
}
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 =
knav_queue_map_reg(kdev, child,
KNAV_QUEUE_PDSP_IRAM_REG_INDEX);
@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
}
of_property_read_u32(child, "id", &pdsp->id);
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->intd, pdsp->firmware);
pdsp->intd);
}
return 0;
}
@ -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);
return ret;
}
pdsp->loaded = false;
pdsp->started = false;
return 0;
}
@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev,
{
int i, ret, fwlen;
const struct firmware *fw;
bool found = false;
u32 *fwdata;
ret = request_firmware(&fw, pdsp->firmware, kdev->dev);
if (ret) {
dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n",
pdsp->firmware, pdsp->name);
return ret;
for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
if (knav_acc_firmwares[i]) {
ret = request_firmware(&fw,
knav_acc_firmwares[i],
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);
/* download the firmware */
fwdata = (u32 *)fw->data;
@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
int ret;
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) {
ret = knav_queue_load_pdsp(kdev, pdsp);
if (ret < 0)
return ret;
if (!ret)
pdsp->loaded = true;
}
for_each_pdsp(kdev, pdsp) {
ret = knav_queue_start_pdsp(kdev, pdsp);
WARN_ON(ret);
if (pdsp->loaded) {
ret = knav_queue_start_pdsp(kdev, pdsp);
if (!ret)
pdsp->started = true;
}
}
return 0;
}

View File

@ -0,0 +1,47 @@
/*
* 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 */

View File

@ -9,15 +9,7 @@
#include <linux/mtd/nand.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/platform_data/macb.h>
/* Compact Flash */
struct at91_cf_data {

View File

@ -0,0 +1,10 @@
#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 */

View File

@ -0,0 +1,15 @@
/*
* 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__ */