Commit 7d2b6ef1 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull ARM SoC driver updates from Olof Johansson:
 "Driver updates for v4.1.  Some of these are for drivers/soc, where we
  find more and more SoC-specific drivers these days.  Some are for
  other driver subsystems where we have received acks from the
  appropriate maintainers.

  The larger parts of this branch are:

   - MediaTek support for their PMIC wrapper interface, a high-level
     interface for talking to the system PMIC over a dedicated I2C
     interface.

   - Qualcomm SCM driver has been moved to drivers/firmware.  It's used
     for CPU up/down and needs to be in a shared location for arm/arm64
     common code.

   - cleanup of ARM-CCI PMU code.

   - another set of cleanusp to the OMAP GPMC code"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (43 commits)
  soc/mediatek: Remove unused variables
  clocksource: atmel-st: select MFD_SYSCON
  soc: mediatek: Add PMIC wrapper for MT8135 and MT8173 SoCs
  arm-cci: Fix CCI PMU event validation
  arm-cci: Split the code for PMU vs driver support
  arm-cci: Get rid of secure transactions for PMU driver
  arm-cci: Abstract the CCI400 PMU specific definitions
  arm-cci: Rearrange code for splitting PMU vs driver code
  drivers: cci: reject groups spanning multiple HW PMUs
  ARM: at91: remove useless include
  clocksource: atmel-st: remove mach/hardware dependency
  clocksource: atmel-st: use syscon/regmap
  ARM: at91: time: move the system timer driver to drivers/clocksource
  ARM: at91: properly initialize timer
  ARM: at91: at91rm9200: remove deprecated arm_pm_restart
  watchdog: at91rm9200: implement restart handler
  watchdog: at91rm9200: use the system timer syscon
  mfd: syscon: Add atmel system timer registers definition
  ARM: at91/dt: declare atmel,at91rm9200-st as a syscon
  soc: qcom: gsbi: Add support for ADM CRCI muxing
  ...
parents 5c73cc4b 7415d97e
......@@ -46,10 +46,12 @@ PIT Timer required properties:
shared across all System Controller members.
System Timer (ST) required properties:
- compatible: Should be "atmel,at91rm9200-st"
- compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd"
- reg: Should contain registers location and length
- interrupts: Should contain interrupt for the ST which is the IRQ line
shared across all System Controller members.
Its subnodes can be:
- watchdog: compatible should be "atmel,at91rm9200-wdt"
TC/TCLIB Timer required properties:
- compatible: Should be "atmel,<chip>-tcb".
......
......@@ -94,8 +94,11 @@ specific to ARM.
- compatible
Usage: required
Value type: <string>
Definition: must be "arm,cci-400-pmu"
Definition: Must contain one of:
"arm,cci-400-pmu,r0"
"arm,cci-400-pmu,r1"
"arm,cci-400-pmu" - DEPRECATED, permitted only where OS has
secure acces to CCI registers
- reg:
Usage: required
Value type: Integer cells. A register entry, expressed
......
Renesas Bus State Controller (BSC)
==================================
The Renesas Bus State Controller (BSC, sometimes called "LBSC within Bus
Bridge", or "External Bus Interface") can be found in several Renesas ARM SoCs.
It provides an external bus for connecting multiple external devices to the
SoC, driving several chip select lines, for e.g. NOR FLASH, Ethernet and USB.
While the BSC is a fairly simple memory-mapped bus, it may be part of a PM
domain, and may have a gateable functional clock.
Before a device connected to the BSC can be accessed, the PM domain
containing the BSC must be powered on, and the functional clock
driving the BSC must be enabled.
The bindings for the BSC extend the bindings for "simple-pm-bus".
Required properties
- compatible: Must contain an SoC-specific value, and "renesas,bsc" and
"simple-pm-bus" as fallbacks.
SoC-specific values can be:
"renesas,bsc-r8a73a4" for R-Mobile APE6 (r8a73a4)
"renesas,bsc-sh73a0" for SH-Mobile AG5 (sh73a0)
- #address-cells, #size-cells, ranges: Must describe the mapping between
parent address and child address spaces.
- reg: Must contain the base address and length to access the bus controller.
Optional properties:
- interrupts: Must contain a reference to the BSC interrupt, if available.
- clocks: Must contain a reference to the functional clock, if available.
- power-domains: Must contain a reference to the PM domain, if available.
Example:
bsc: bus@fec10000 {
compatible = "renesas,bsc-sh73a0", "renesas,bsc",
"simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0x20000000>;
reg = <0xfec10000 0x400>;
interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&zb_clk>;
power-domains = <&pd_a4s>;
};
Simple Power-Managed Bus
========================
A Simple Power-Managed Bus is a transparent bus that doesn't need a real
driver, as it's typically initialized by the boot loader.
However, its bus controller is part of a PM domain, or under the control of a
functional clock. Hence, the bus controller's PM domain and/or clock must be
enabled for child devices connected to the bus (either on-SoC or externally)
to function.
While "simple-pm-bus" follows the "simple-bus" set of properties, as specified
in ePAPR, it is not an extension of "simple-bus".
Required properties:
- compatible: Must contain at least "simple-pm-bus".
Must not contain "simple-bus".
It's recommended to let this be preceded by one or more
vendor-specific compatible values.
- #address-cells, #size-cells, ranges: Must describe the mapping between
parent address and child address spaces.
Optional platform-specific properties for clock or PM domain control (at least
one of them is required):
- clocks: Must contain a reference to the functional clock(s),
- power-domains: Must contain a reference to the PM domain.
Please refer to the binding documentation for the clock and/or PM domain
providers for more details.
Example:
bsc: bus@fec10000 {
compatible = "renesas,bsc-sh73a0", "renesas,bsc",
"simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0x20000000>;
reg = <0xfec10000 0x400>;
interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&zb_clk>;
power-domains = <&pd_a4s>;
};
......@@ -6,7 +6,8 @@ configuration settings. The mode setting will govern the input/output mode of
the 4 GSBI IOs.
Required properties:
- compatible: must contain "qcom,gsbi-v1.0.0" for APQ8064/IPQ8064
- compatible: Should contain "qcom,gsbi-v1.0.0"
- cell-index: Should contain the GSBI index
- reg: Address range for GSBI registers
- clocks: required clock
- clock-names: must contain "iface" entry
......@@ -16,6 +17,8 @@ Required properties:
Optional properties:
- qcom,crci : indicates CRCI MUX value for QUP CRCI ports. Please reference
dt-bindings/soc/qcom,gsbi.h for valid CRCI mux values.
- syscon-tcsr: indicates phandle of TCSR syscon node. Required if child uses
dma.
Required properties if child node exists:
- #address-cells: Must be 1
......@@ -39,6 +42,7 @@ Example for APQ8064:
gsbi4@16300000 {
compatible = "qcom,gsbi-v1.0.0";
cell-index = <4>;
reg = <0x16300000 0x100>;
clocks = <&gcc GSBI4_H_CLK>;
clock-names = "iface";
......@@ -48,22 +52,24 @@ Example for APQ8064:
qcom,mode = <GSBI_PROT_I2C_UART>;
qcom,crci = <GSBI_CRCI_QUP>;
syscon-tcsr = <&tcsr>;
/* child nodes go under here */
i2c_qup4: i2c@16380000 {
compatible = "qcom,i2c-qup-v1.1.1";
reg = <0x16380000 0x1000>;
interrupts = <0 153 0>;
compatible = "qcom,i2c-qup-v1.1.1";
reg = <0x16380000 0x1000>;
interrupts = <0 153 0>;
clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
clock-names = "core", "iface";
clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
clock-names = "core", "iface";
clock-frequency = <200000>;
clock-frequency = <200000>;
#address-cells = <1>;
#size-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
};
};
uart4: serial@16340000 {
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
......@@ -76,3 +82,7 @@ Example for APQ8064:
};
};
tcsr: syscon@1a400000 {
compatible = "qcom,apq8064-tcsr", "syscon";
reg = <0x1a400000 0x100>;
};
......@@ -1327,6 +1327,7 @@ F: drivers/tty/serial/msm_serial.h
F: drivers/tty/serial/msm_serial.c
F: drivers/*/pm8???-*
F: drivers/mfd/ssbi.c
F: drivers/firmware/qcom_scm.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
ARM/RADISYS ENP2611 MACHINE SUPPORT
......
......@@ -2146,6 +2146,8 @@ source "net/Kconfig"
source "drivers/Kconfig"
source "drivers/firmware/Kconfig"
source "fs/Kconfig"
source "arch/arm/Kconfig.debug"
......
......@@ -356,9 +356,13 @@ macb0_clk: macb0_clk {
};
st: timer@fffffd00 {
compatible = "atmel,at91rm9200-st";
compatible = "atmel,at91rm9200-st", "syscon", "simple-mfd";
reg = <0xfffffd00 0x100>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
watchdog {
compatible = "atmel,at91rm9200-wdt";
};
};
rtc: rtc@fffffe00 {
......
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
/*
* arch/arm/include/asm/arm-cci.h
*
* Copyright (C) 2015 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
* 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
......@@ -10,30 +13,30 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/slab.h>
#ifndef __ASM_ARM_CCI_H
#define __ASM_ARM_CCI_H
#include "scm.h"
#include "scm-boot.h"
#ifdef CONFIG_MCPM
#include <asm/mcpm.h>
/*
* Set the cold/warm boot address for one of the CPU cores.
* We don't have a reliable way of detecting whether,
* if we have access to secure-only registers, unless
* mcpm is registered.
*/
int scm_set_boot_addr(u32 addr, int flags)
static inline bool platform_has_secure_cci_access(void)
{
struct {
__le32 flags;
__le32 addr;
} cmd;
return mcpm_is_available();
}
cmd.addr = cpu_to_le32(addr);
cmd.flags = cpu_to_le32(flags);
return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
&cmd, sizeof(cmd), NULL, 0);
#else
static inline bool platform_has_secure_cci_access(void)
{
return false;
}
EXPORT_SYMBOL(scm_set_boot_addr);
#endif
#endif
......@@ -77,6 +77,7 @@ if SOC_SAM_V4_V5
config SOC_AT91RM9200
bool "AT91RM9200"
select ATMEL_AIC_IRQ
select ATMEL_ST
select COMMON_CLK_AT91
select CPU_ARM920T
select GENERIC_CLOCKEVENTS
......
......@@ -7,7 +7,7 @@ obj-y := soc.o
obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o
# CPU-specific support
obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o at91rm9200_time.o
obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
obj-$(CONFIG_SOC_SAMA5) += sama5.o
......
......@@ -15,8 +15,6 @@
#include <asm/mach/arch.h>
#include <asm/system_misc.h>
#include <mach/at91_st.h>
#include "generic.h"
#include "soc.h"
......@@ -25,21 +23,6 @@ static const struct at91_soc rm9200_socs[] = {
{ /* sentinel */ },
};
static void at91rm9200_restart(enum reboot_mode reboot_mode, const char *cmd)
{
/*
* Perform a hardware reset with the use of the Watchdog timer.
*/
at91_st_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
}
static void __init at91rm9200_dt_timer_init(void)
{
of_clk_init(NULL);
at91rm9200_timer_init();
}
static void __init at91rm9200_dt_device_init(void)
{
struct soc_device *soc;
......@@ -52,7 +35,6 @@ static void __init at91rm9200_dt_device_init(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
arm_pm_idle = at91rm9200_idle;
arm_pm_restart = at91rm9200_restart;
at91rm9200_pm_init();
}
......@@ -62,7 +44,6 @@ static const char *at91rm9200_dt_board_compat[] __initconst = {
};
DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200")
.init_time = at91rm9200_dt_timer_init,
.init_machine = at91rm9200_dt_device_init,
.dt_compat = at91rm9200_dt_board_compat,
MACHINE_END
......@@ -18,9 +18,6 @@
extern void __init at91_map_io(void);
extern void __init at91_alt_map_io(void);
/* Timer */
extern void at91rm9200_timer_init(void);
/* idle */
extern void at91rm9200_idle(void);
extern void at91sam9_idle(void);
......
/*
* arch/arm/mach-at91/include/mach/at91_st.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* System Timer (ST) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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.
*/
#ifndef AT91_ST_H
#define AT91_ST_H
#ifndef __ASSEMBLY__
extern void __iomem *at91_st_base;
#define at91_st_read(field) \
__raw_readl(at91_st_base + field)
#define at91_st_write(field, value) \
__raw_writel(value, at91_st_base + field)
#else
.extern at91_st_base
#endif
#define AT91_ST_CR 0x00 /* Control Register */
#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */
#define AT91_ST_PIMR 0x04 /* Period Interval Mode Register */
#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */
#define AT91_ST_WDMR 0x08 /* Watchdog Mode Register */
#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */
#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */
#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */
#define AT91_ST_RTMR 0x0c /* Real-time Mode Register */
#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */
#define AT91_ST_SR 0x10 /* Status Register */
#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */
#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */
#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */
#define AT91_ST_ALMS (1 << 3) /* Alarm Status */
#define AT91_ST_IER 0x14 /* Interrupt Enable Register */
#define AT91_ST_IDR 0x18 /* Interrupt Disable Register */
#define AT91_ST_IMR 0x1c /* Interrupt Mask Register */
#define AT91_ST_RTAR 0x20 /* Real-time Alarm Register */
#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */
#define AT91_ST_CRTR 0x24 /* Current Real-time Register */
#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */
#endif
......@@ -123,7 +123,7 @@ config SOC_EXYNOS5800
config EXYNOS5420_MCPM
bool "Exynos5420 Multi-Cluster PM support"
depends on MCPM && SOC_EXYNOS5420
select ARM_CCI
select ARM_CCI400_PORT_CTRL
select ARM_CPU_SUSPEND
help
This is needed to provide CPU and cluster power management
......
menuconfig ARCH_MEDIATEK
bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
select ARM_GIC
select PINCTRL
select MTK_TIMER
help
Support for Mediatek MT65xx & MT81xx SoCs
......
......@@ -96,14 +96,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
if (gpmc_t) {
err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
if (err < 0) {
pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
return err;
}
}
memset(&s, 0, sizeof(struct gpmc_settings));
if (gpmc_nand_data->of_node)
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
......@@ -111,6 +103,16 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
gpmc_set_legacy(gpmc_nand_data, &s);
s.device_nand = true;
if (gpmc_t) {
err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t, &s);
if (err < 0) {
pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n",
err);
return err;
}
}
err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
if (err < 0)
goto out_free_cs;
......
......@@ -293,7 +293,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
if (ret < 0)
return ret;
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t, &onenand_async);
if (ret < 0)
return ret;
......@@ -331,7 +331,7 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
if (ret < 0)
return ret;
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t, &onenand_sync);
if (ret < 0)
return ret;
......
......@@ -71,7 +71,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
gpmc_calc_timings(&t, &tusb_async, &dev_t);
return gpmc_cs_set_timings(async_cs, &t);
return gpmc_cs_set_timings(async_cs, &t, &tusb_async);
}
static int tusb_set_sync_mode(unsigned sysclk_ps)
......@@ -98,7 +98,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
gpmc_calc_timings(&t, &tusb_sync, &dev_t);
return gpmc_cs_set_timings(sync_cs, &t);
return gpmc_cs_set_timings(sync_cs, &t, &tusb_sync);
}
/* tusb driver calls this when it changes the chip's clocking */
......
......@@ -22,7 +22,4 @@ config ARCH_MSM8974
bool "Enable support for MSM8974"
select HAVE_ARM_ARCH_TIMER
config QCOM_SCM
bool
endif
obj-y := board.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
......@@ -17,10 +17,10 @@
#include <linux/of_address.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/qcom_scm.h>
#include <asm/smp_plat.h>
#include "scm-boot.h"
#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0
#define SCSS_CPU1CORE_RESET 0x2d80
......@@ -319,25 +319,10 @@ static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
{
int cpu, map;
unsigned int flags = 0;
static const int cold_boot_flags[] = {
0,
SCM_FLAG_COLDBOOT_CPU1,
SCM_FLAG_COLDBOOT_CPU2,
SCM_FLAG_COLDBOOT_CPU3,
};
for_each_present_cpu(cpu) {
map = cpu_logical_map(cpu);
if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
set_cpu_present(cpu, false);
continue;
}
flags |= cold_boot_flags[map];
}
int cpu;
if (scm_set_boot_addr(virt_to_phys(secondary_startup_arm), flags)) {
if (qcom_scm_set_cold_boot_addr(secondary_startup_arm,
cpu_present_mask)) {
for_each_present_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
......
......@@ -54,7 +54,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
config ARCH_VEXPRESS_DCSCB
bool "Dual Cluster System Control Block (DCSCB) support"
depends on MCPM
select ARM_CCI
select ARM_CCI400_PORT_CTRL
help
Support for the Dual Cluster System Configuration Block (DCSCB).
This is needed to provide CPU and cluster power management
......@@ -72,7 +72,7 @@ config ARCH_VEXPRESS_SPC
config ARCH_VEXPRESS_TC2_PM
bool "Versatile Express TC2 power management"
depends on MCPM
select ARM_CCI
select ARM_CCI400_PORT_CTRL
select ARCH_VEXPRESS_SPC
select ARM_CPU_SUSPEND
help
......
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
/*
* arch/arm64/include/asm/arm-cci.h
*
* Copyright (C) 2015 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __MACH_SCM_H
#define __MACH_SCM_H
#define SCM_SVC_BOOT 0x1
#define SCM_SVC_PIL 0x2
extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
void *resp_buf, size_t resp_len);
#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
#ifndef __ASM_ARM_CCI_H
#define __ASM_ARM_CCI_H
extern u32 scm_get_version(void);
static inline bool platform_has_secure_cci_access(void)
{
return false;
}
#endif
......@@ -4,6 +4,41 @@
menu "Bus devices"
config ARM_CCI
bool
config ARM_CCI400_COMMON
bool
select ARM_CCI
config ARM_CCI400_PMU
bool "ARM CCI400 PMU support"
default y
depends on ARM || ARM64
depends on HW_PERF_EVENTS
select ARM_CCI400_COMMON
help
Support for PMU events monitoring on the ARM CCI cache coherent
interconnect.
If unsure, say Y
config ARM_CCI400_PORT_CTRL
bool
depends on ARM && OF && CPU_V7
select ARM_CCI400_COMMON
help
Low level power management driver for CCI400 cache coherent
interconnect for ARM platforms.
config ARM_CCN
bool "ARM CCN driver support"
depends on ARM || ARM64
depends on PERF_EVENTS
help
PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
interconnect.
config BRCMSTB_GISB_ARB
bool "Broadcom STB GISB bus arbiter"
depends on ARM || MIPS
......@@ -40,15 +75,6 @@ config MVEBU_MBUS
Driver needed for the MBus configuration on Marvell EBU SoCs
(Kirkwood, Dove, Orion5x, MV78XX0 and Armada 370/XP).
config OMAP_OCP2SCP
tristate "OMAP OCP2SCP DRIVER"
depends on ARCH_OMAP2PLUS
help
Driver to enable ocp2scp module which transforms ocp interface
protocol to scp protocol. In OMAP4, USB PHY is connected via
OCP2SCP and in OMAP5, both USB PHY and SATA PHY is connected via
OCP2SCP.
config OMAP_INTERCONNECT
tristate "OMAP INTERCONNECT DRIVER"
depends on ARCH_OMAP2PLUS
......@@ -56,20 +82,27 @@ config OMAP_INTERCONNECT
help
Driver to enable OMAP interconnect error handling driver.
config ARM_CCI
bool "ARM CCI driver support"
depends on ARM && OF && CPU_V7
config OMAP_OCP2SCP
tristate "OMAP OCP2SCP DRIVER"
depends on ARCH_OMAP2PLUS
help
Driver supporting the CCI cache coherent interconnect for ARM
platforms.
Driver to enable ocp2scp module which transforms ocp interface
protocol to scp protocol. In OMAP4, USB PHY is connected via
OCP2SCP and in OMAP5, both USB PHY and SATA PHY is connected via
OCP2SCP.
config ARM_CCN
bool "ARM CCN driver support"
depends on ARM || ARM64
depends on PERF_EVENTS
config SIMPLE_PM_BUS
bool "Simple Power-Managed Bus Driver"
depends on OF && PM
depends on ARCH_SHMOBILE || COMPILE_TEST
help
PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
interconnect.
Driver for transparent busses that don't need a real driver, but
where the bus controller is part of a PM domain, or under the control
of a functional clock, and thus relies on runtime PM for managing
this PM domain and/or clock.
An example of such a bus controller is the Renesas Bus State
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
config VEXPRESS_CONFIG
bool "Versatile Express configuration bus"
......
......@@ -2,17 +2,18 @@
# Makefile for the bus drivers.
#
# Interconnect bus drivers for ARM platforms
obj-$(CONFIG_ARM_CCI) += arm-cci.o
obj-$(CONFIG_ARM_CCN) += arm-ccn.o
obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
# Interconnect bus driver for OMAP SoCs.
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
# Interconnect bus drivers for ARM platforms
obj-$(CONFIG_ARM_CCI) += arm-cci.o
obj-$(CONFIG_ARM_CCN) += arm-ccn.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
This diff is collapsed.
/*
* Simple Power-Managed Bus Driver
*
* Copyright (C) 2014-2015 Glider bvba
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
static int simple_pm_bus_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
dev_dbg(&pdev->dev, "%s\n", __func__);
pm_runtime_enable(&pdev->dev);
if (np)
of_platform_populate(np, NULL, NULL, &pdev->dev);
return 0;
}
static int simple_pm_bus_remove(struct platform_device *pdev)
{
dev_dbg(&pdev->dev, "%s\n", __func__);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id simple_pm_bus_of_match[] = {
{ .compatible = "simple-pm-bus", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);
static struct platform_driver simple_pm_bus_driver = {
.probe = simple_pm_bus_probe,
.remove = simple_pm_bus_remove,
.driver = {
.name = "simple-pm-bus",
.of_match_table = simple_pm_bus_of_match,
},
};
module_platform_driver(simple_pm_bus_driver);
MODULE_DESCRIPTION("Simple Power-Managed Bus Driver");
MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
MODULE_LICENSE("GPL v2");
......@@ -143,6 +143,11 @@ config ATMEL_PIT
select CLKSRC_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
config ATMEL_ST
bool
select CLKSRC_OF
select MFD_SYSCON
config CLKSRC_METAG_GENERIC
def_bool y if METAG
help
......
obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
......
......@@ -24,19 +24,17 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/export.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/atmel-st.h>
#include <linux/of_irq.h>
#include <asm/mach/time.h>
#include <mach/at91_st.h>
#include <mach/hardware.h>
#include <linux/regmap.h>
static unsigned long last_crtr;
static u32 irqmask;
static struct clock_event_device clkevt;
static struct regmap *regmap_st;
#define AT91_SLOW_CLOCK 32768
#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
/*
......@@ -46,11 +44,11 @@ static struct clock_event_device clkevt;
*/
static inline unsigned long read_CRTR(void)
{
unsigned long x1, x2;
unsigned int x1, x2;
x1 = at91_st_read(AT91_ST_CRTR);
regmap_read(regmap_st, AT91_ST_CRTR, &x1);
do {
x2 = at91_st_read(AT91_ST_CRTR);
regmap_read(regmap_st, AT91_ST_CRTR, &x2);
if (x1 == x2)
break;
x1 = x2;
......@@ -63,7 +61,10 @@ static inline unsigned long read_CRTR(void)
*/
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
{
u32 sr = at91_st_read(AT91_ST_SR) & irqmask;
u32 sr;
regmap_read(regmap_st, AT91_ST_SR, &sr);
sr &= irqmask;
/*
* irqs should be disabled here, but as the irq is shared they are only
......@@ -92,13 +93,6 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
static struct irqaction at91rm9200_timer_irq = {
.name = "at91_tick",
.flags = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = at91rm9200_timer_interrupt,
.irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
static cycle_t read_clk32k(struct clocksource *cs)
{
return read_CRTR();
......@@ -115,23 +109,25 @@ static struct clocksource clk32k = {
static void
clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
unsigned int val;
/* Disable and flush pending timer interrupts */
at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
at91_st_read(AT91_ST_SR);
regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
regmap_read(regmap_st, AT91_ST_SR, &val);
last_crtr = read_CRTR();
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
/* PIT for periodic irqs; fixed rate of 1/HZ */
irqmask = AT91_ST_PITS;
at91_st_write(AT91_ST_PIMR, RM9200_TIMER_LATCH);
regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* ALM for oneshot irqs, set by next_event()
* before 32 seconds have passed
*/
irqmask = AT91_ST_ALMS;
at91_st_write(AT91_ST_RTAR, last_crtr);
regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
......@@ -139,7 +135,7 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
irqmask = 0;
break;
}
at91_st_write(AT91_ST_IER, irqmask);
regmap_write(regmap_st, AT91_ST_IER, irqmask);
}
static int
......@@ -147,6 +143,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
{
u32 alm;
int status = 0;
unsigned int val;
BUG_ON(delta < 2);
......@@ -162,12 +159,12 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
alm = read_CRTR();
/* Cancel any pending alarm; flush any pending IRQ */
at91_st_write(AT91_ST_RTAR, alm);
at91_st_read(AT91_ST_SR);
regmap_write(regmap_st, AT91_ST_RTAR, alm);
regmap_read(regmap_st, AT91_ST_SR, &val);
/* Schedule alarm by writing RTAR. */
alm += delta;
at91_st_write(AT91_ST_RTAR, alm);
regmap_write(regmap_st, AT91_ST_RTAR, alm);
return status;
}
......@@ -180,66 +177,40 @@ static struct clock_event_device clkevt = {
.set_mode = clkevt32k_mode,
};
void __iomem *at91_st_base;
EXPORT_SYMBOL_GPL(at91_st_base);
static const struct of_device_id at91rm9200_st_timer_ids[] = {
{ .compatible = "atmel,at91rm9200-st" },
{ /* sentinel */ }
};
static int __init of_at91rm9200_st_init(void)
{
struct device_node *np;
int ret;
np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
if (!np)
goto err;
at91_st_base = of_iomap(np, 0);
if (!at91_st_base)
goto node_err;
/* Get the interrupts property */
ret = irq_of_parse_and_map(np, 0);
if (!ret)
goto ioremap_err;
at91rm9200_timer_irq.irq = ret;
of_node_put(np);
return 0;
ioremap_err:
iounmap(at91_st_base);
node_err:
of_node_put(np);
err:
return -EINVAL;
}
/*
* ST (system timer) module supports both clockevents and clocksource.
*/
void __init at91rm9200_timer_init(void)
static void __init atmel_st_timer_init(struct device_node *node)
{
/* For device tree enabled device: initialize here */
of_at91rm9200_st_init();
unsigned int val;
int irq, ret;
regmap_st = syscon_node_to_regmap(node);
if (IS_ERR(regmap_st))
panic(pr_fmt("Unable to get regmap\n"));
/* Disable all timer interrupts, and clear any pending ones */
at91_st_write(AT91_ST_IDR,
regmap_write(regmap_st, AT91_ST_IDR,
AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
at91_st_read(AT91_ST_SR);
regmap_read(regmap_st, AT91_ST_SR, &val);
/* Get the interrupts property */
irq = irq_of_parse_and_map(node, 0);
if (!irq)
panic(pr_fmt("Unable to get IRQ from DT\n"));
/* Make IRQs happen for the system timer */
setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
ret = request_irq(irq, at91rm9200_timer_interrupt,
IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
"at91_tick", regmap_st);
if (ret)
panic(pr_fmt("Unable to setup IRQ\n"));
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
* its prescaler from the 1 Hz default.
*/
at91_st_write(AT91_ST_RTMR, 1);
regmap_write(regmap_st, AT91_ST_RTMR, 1);
/* Setup timer clockevent, with minimum of two ticks (important!!) */
clkevt.cpumask = cpumask_of(0);
......@@ -249,3 +220,5 @@ void __init at91rm9200_timer_init(void)
/* register clocksource */
clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
}
CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
atmel_st_timer_init);
......@@ -132,6 +132,10 @@ config ISCSI_IBFT
detect iSCSI boot parameters dynamically during system boot, say Y.
Otherwise, say N.
config QCOM_SCM
bool
depends on ARM || ARM64
source "drivers/firmware/google/Kconfig"
source "drivers/firmware/efi/Kconfig"
......
......@@ -11,6 +11,8 @@ obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
obj-$(CONFIG_EFI) += efi/
......
This diff is collapsed.
menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/ti/Kconfig"
source "drivers/soc/versatile/Kconfig"
......
......@@ -2,6 +2,7 @@
# Makefile for the Linux Kernel SOC specific device drivers.
#
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
......
#
# MediaTek SoC drivers
#
config MTK_PMIC_WRAP
tristate "MediaTek PMIC Wrapper Support"
depends on ARCH_MEDIATEK
select REGMAP
help
Say yes here to add support for MediaTek PMIC Wrapper found
on different MediaTek SoCs. The PMIC wrapper is a proprietary
hardware to connect the PMIC.
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
This diff is collapsed.
......@@ -4,6 +4,7 @@
config QCOM_GSBI
tristate "QCOM General Serial Bus Interface"
depends on ARCH_QCOM
select MFD_SYSCON
help
Say y here to enable GSBI support. The GSBI provides control
functions for connecting the underlying serial UART, SPI, and I2C
......
......@@ -18,22 +18,129 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <dt-bindings/soc/qcom,gsbi.h>
#define GSBI_CTRL_REG 0x0000
#define GSBI_PROTOCOL_SHIFT 4
#define MAX_GSBI 12
#define TCSR_ADM_CRCI_BASE 0x70
struct crci_config {
u32 num_rows;
const u32 (*array)[MAX_GSBI];
};
static const u32 crci_ipq8064[][MAX_GSBI] = {
{
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
{
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
};
static const struct crci_config config_ipq8064 = {
.num_rows = ARRAY_SIZE(crci_ipq8064),
.array = crci_ipq8064,
};
static const unsigned int crci_apq8064[][MAX_GSBI] = {
{
0x001800, 0x006000, 0x000030, 0x0000c0,
0x000300, 0x000400, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000
},
{
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000020, 0x0000c0, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000
},
};
static const struct crci_config config_apq8064 = {
.num_rows = ARRAY_SIZE(crci_apq8064),
.array = crci_apq8064,
};
static const unsigned int crci_msm8960[][MAX_GSBI] = {
{
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000400, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000
},
{
0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000020, 0x0000c0, 0x000300,
0x001800, 0x006000, 0x000000, 0x000000
},
};
static const struct crci_config config_msm8960 = {
.num_rows = ARRAY_SIZE(crci_msm8960),
.array = crci_msm8960,
};
static const unsigned int crci_msm8660[][MAX_GSBI] = {
{ /* ADM 0 - B */
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
{ /* ADM 0 - B */
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
{ /* ADM 1 - A */
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
{ /* ADM 1 - B */
0x000003, 0x00000c, 0x000030, 0x0000c0,
0x000300, 0x000c00, 0x003000, 0x00c000,
0x030000, 0x0c0000, 0x300000, 0xc00000
},
};
static const struct crci_config config_msm8660 = {
.num_rows = ARRAY_SIZE(crci_msm8660),
.array = crci_msm8660,
};
struct gsbi_info {
struct clk *hclk;
u32 mode;
u32 crci;
struct regmap *tcsr;
};
static const struct of_device_id tcsr_dt_match[] = {
{ .compatible = "qcom,tcsr-ipq8064", .data = &config_ipq8064},
{ .compatible = "qcom,tcsr-apq8064", .data = &config_apq8064},
{ .compatible = "qcom,tcsr-msm8960", .data = &config_msm8960},
{ .compatible = "qcom,tcsr-msm8660", .data = &config_msm8660},
{ },
};
static int gsbi_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device_node *tcsr_node;
const struct of_device_id *match;
struct resource *res;
void __iomem *base;
struct gsbi_info *gsbi;
int i;
u32 mask, gsbi_num;
const struct crci_config *config = NULL;
gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
......@@ -45,6 +152,32 @@ static int gsbi_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
/* get the tcsr node and setup the config and regmap */
gsbi->tcsr = syscon_regmap_lookup_by_phandle(node, "syscon-tcsr");
if (!IS_ERR(gsbi->tcsr)) {
tcsr_node = of_parse_phandle(node, "syscon-tcsr", 0);
if (tcsr_node) {
match = of_match_node(tcsr_dt_match, tcsr_node);
if (match)
config = match->data;
else
dev_warn(&pdev->dev, "no matching TCSR\n");
of_node_put(tcsr_node);
}
}
if (of_property_read_u32(node, "cell-index", &gsbi_num)) {
dev_err(&pdev->dev, "missing cell-index\n");
return -EINVAL;
}
if (gsbi_num < 1 || gsbi_num > MAX_GSBI) {
dev_err(&pdev->dev, "invalid cell-index\n");
return -EINVAL;
}
if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
dev_err(&pdev->dev, "missing mode configuration\n");
return -EINVAL;
......@@ -64,6 +197,25 @@ static int gsbi_probe(struct platform_device *pdev)
writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
base + GSBI_CTRL_REG);
/*
* modify tcsr to reflect mode and ADM CRCI mux
* Each gsbi contains a pair of bits, one for RX and one for TX
* SPI mode requires both bits cleared, otherwise they are set
*/
if (config) {
for (i = 0; i < config->num_rows; i++) {
mask = config->array[i][gsbi_num - 1];
if (gsbi->mode == GSBI_PROT_SPI)
regmap_update_bits(gsbi->tcsr,
TCSR_ADM_CRCI_BASE + 4 * i, mask, 0);
else
regmap_update_bits(gsbi->tcsr,
TCSR_ADM_CRCI_BASE + 4 * i, mask, mask);
}
}
/* make sure the gsbi control write is not reordered */
wmb();
......
......@@ -154,7 +154,7 @@ config ARM_SP805_WATCHDOG
config AT91RM9200_WATCHDOG
tristate "AT91RM9200 watchdog"
depends on SOC_AT91RM9200
depends on SOC_AT91RM9200 && MFD_SYSCON
help
Watchdog timer embedded into AT91RM9200 chips. This will reboot your
system when the timeout is reached.
......
......@@ -12,27 +12,32 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/atmel-st.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <mach/at91_st.h>
#define WDT_DEFAULT_TIME 5 /* seconds */
#define WDT_MAX_TIME 256 /* seconds */
static int wdt_time = WDT_DEFAULT_TIME;
static bool nowayout = WATCHDOG_NOWAYOUT;
static struct regmap *regmap_st;
module_param(wdt_time, int, 0);
MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
......@@ -50,12 +55,33 @@ static unsigned long at91wdt_busy;
/* ......................................................................... */
static int at91rm9200_restart(struct notifier_block *this,
unsigned long mode, void *cmd)
{
/*
* Perform a hardware reset with the use of the Watchdog timer.
*/
regmap_write(regmap_st, AT91_ST_WDMR,
AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
mdelay(2000);
pr_emerg("Unable to restart system\n");
return NOTIFY_DONE;
}
static struct notifier_block at91rm9200_restart_nb = {
.notifier_call = at91rm9200_restart,
.priority = 192,
};
/*
* Disable the watchdog.
*/
static inline void at91_wdt_stop(void)
{
at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN);
regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN);
}
/*
......@@ -63,9 +89,9 @@ static inline void at91_wdt_stop(void)
*/
static inline void at91_wdt_start(void)
{
at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
(((65536 * wdt_time) >> 8) & AT91_ST_WDV));
at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
}
/*
......@@ -73,7 +99,7 @@ static inline void at91_wdt_start(void)
*/
static inline void at91_wdt_reload(void)
{
at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
}
/* ......................................................................... */
......@@ -203,16 +229,32 @@ static struct miscdevice at91wdt_miscdev = {
static int at91wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent;
int res;
if (at91wdt_miscdev.parent)
return -EBUSY;
at91wdt_miscdev.parent = &pdev->dev;
parent = dev->parent;
if (!parent) {
dev_err(dev, "no parent\n");
return -ENODEV;
}
regmap_st = syscon_node_to_regmap(parent->of_node);
if (!regmap_st)
return -ENODEV;
res = misc_register(&at91wdt_miscdev);
if (res)
return res;
res = register_restart_handler(&at91rm9200_restart_nb);
if (res)
dev_warn(dev, "failed to register restart handler\n");
pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
wdt_time, nowayout ? ", nowayout" : "");
return 0;
......@@ -220,8 +262,13 @@ static int at91wdt_probe(struct platform_device *pdev)
static int at91wdt_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int res;
res = unregister_restart_handler(&at91rm9200_restart_nb);
if (res)
dev_warn(dev, "failed to unregister restart handler\n");
res = misc_deregister(&at91wdt_miscdev);
if (!res)
at91wdt_miscdev.parent = NULL;
......@@ -267,7 +314,7 @@ static struct platform_driver at91wdt_driver = {
.suspend = at91wdt_suspend,
.resume = at91wdt_resume,
.driver = {
.name = "at91_wdt",
.name = "atmel_st_watchdog",
.of_match_table = at91_wdt_dt_ids,
},
};
......@@ -296,4 +343,4 @@ module_exit(at91_wdt_exit);
MODULE_AUTHOR("Andrew Victor");
MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:at91_wdt");
MODULE_ALIAS("platform:atmel_st_watchdog");
......@@ -24,16 +24,22 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <asm/arm-cci.h>
struct device_node;
#ifdef CONFIG_ARM_CCI
extern bool cci_probed(void);
#else
static inline bool cci_probed(void) { return false; }
#endif
#ifdef CONFIG_ARM_CCI400_PORT_CTRL
extern int cci_ace_get_port(struct device_node *dn);
extern int cci_disable_port_by_cpu(u64 mpidr);
extern int __cci_control_port_by_device(struct device_node *dn, bool enable);
extern int __cci_control_port_by_index(u32 port, bool enable);
#else
static inline bool cci_probed(void) { return false; }
static inline int cci_ace_get_port(struct device_node *dn)
{
return -ENODEV;
......@@ -49,6 +55,7 @@ static inline int __cci_control_port_by_index(u32 port, bool enable)
return -ENODEV;
}
#endif
#define cci_disable_port_by_device(dev) \
__cci_control_port_by_device(dev, false)
#define cci_enable_port_by_device(dev) \
......
/*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* System Timer (ST) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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.
*/
#ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H
#define _LINUX_MFD_SYSCON_ATMEL_ST_H
#include <linux/bitops.h>
#define AT91_ST_CR 0x00 /* Control Register */
#define AT91_ST_WDRST BIT(0) /* Watchdog Timer Restart */
#define AT91_ST_PIMR 0x04 /* Period Interval Mode Register */
#define AT91_ST_PIV 0xffff /* Period Interval Value */
#define AT91_ST_WDMR 0x08 /* Watchdog Mode Register */
#define AT91_ST_WDV 0xffff /* Watchdog Counter Value */
#define AT91_ST_RSTEN BIT(16) /* Reset Enable */
#define AT91_ST_EXTEN BIT(17) /* External Signal Assertion Enable */
#define AT91_ST_RTMR 0x0c /* Real-time Mode Register */
#define AT91_ST_RTPRES 0xffff /* Real-time Prescalar Value */
#define AT91_ST_SR 0x10 /* Status Register */
#define AT91_ST_PITS BIT(0) /* Period Interval Timer Status */
#define AT91_ST_WDOVF BIT(1) /* Watchdog Overflow */
#define AT91_ST_RTTINC BIT(2) /* Real-time Timer Increment */
#define AT91_ST_ALMS BIT(3) /* Alarm Status */
#define AT91_ST_IER 0x14 /* Interrupt Enable Register */
#define AT91_ST_IDR 0x18 /* Interrupt Disable Register */
#define AT91_ST_IMR 0x1c /* Interrupt Mask Register */
#define AT91_ST_RTAR 0x20 /* Real-time Alarm Register */
#define AT91_ST_ALMV 0xfffff /* Alarm Value */
#define AT91_ST_CRTR 0x24 /* Current Real-time Register */
#define AT91_ST_CRTV 0xfffff /* Current Real-Time Value */
#endif /* _LINUX_MFD_SYSCON_ATMEL_ST_H */
......@@ -163,7 +163,8 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
extern int gpmc_calc_divider(unsigned int sync_clk);
extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
const struct gpmc_settings *s);
extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
extern void gpmc_cs_free(int cs);
......
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
* Copyright (C) 2015 Linaro Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
......@@ -9,18 +10,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MACH_SCM_BOOT_H
#define __MACH_SCM_BOOT_H
#ifndef __QCOM_SCM_H
#define __QCOM_SCM_H
#define SCM_BOOT_ADDR 0x1
#define SCM_FLAG_COLDBOOT_CPU1 0x01
#define SCM_FLAG_COLDBOOT_CPU2 0x08
#define SCM_FLAG_COLDBOOT_CPU3 0x20
#define SCM_FLAG_WARMBOOT_CPU0 0x04
#define SCM_FLAG_WARMBOOT_CPU1 0x02
#define SCM_FLAG_WARMBOOT_CPU2 0x10
#define SCM_FLAG_WARMBOOT_CPU3 0x40
extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
int scm_set_boot_addr(u32 addr, int flags);
#define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0
#define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1
extern void qcom_scm_cpu_power_down(u32 flags);
#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
extern u32 qcom_scm_get_version(void);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment