Commit 43a0a98a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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 ARM SoCs.

  A slew of changes this release cycle.  The reset driver tree, that we
  merge through arm-soc for historical reasons, is also sizable this
  time around.

  Among the changes:

   - clps711x: Treewide changes to compatible strings, merged here for simplicity.
   - Qualcomm: SCM firmware driver cleanups, move to platform driver
   - ux500: Major cleanups, removal of old mach-specific infrastructure.
   - Atmel external bus memory driver
   - Move of brcmstb platform to the rest of bcm
   - PMC driver updates for tegra, various fixes and improvements
   - Samsung platform driver updates to support 64-bit Exynos platforms
   - Reset controller cleanups moving to devm_reset_controller_register() APIs
   - Reset controller driver for Amlogic Meson
   - Reset controller driver for Hisilicon hi6220
   - ARM SCPI power domain support"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (100 commits)
  ARM: ux500: consolidate base platform files
  ARM: ux500: move soc_id driver to drivers/soc
  ARM: ux500: call ux500_setup_id later
  ARM: ux500: consolidate soc_device code in id.c
  ARM: ux500: remove cpu_is_u* helpers
  ARM: ux500: use CLK_OF_DECLARE()
  ARM: ux500: move l2x0 init to .init_irq
  mfd: db8500 stop passing around platform data
  ASoC: ab8500-codec: remove platform data based probe
  ARM: ux500: move ab8500_regulator_plat_data into driver
  ARM: ux500: remove unused regulator data
  soc: raspberrypi-power: add CONFIG_OF dependency
  firmware: scpi: add CONFIG_OF dependency
  video: clps711x-fb: Changing the compatibility string to match with the smallest supported chip
  input: clps711x-keypad: Changing the compatibility string to match with the smallest supported chip
  pwm: clps711x: Changing the compatibility string to match with the smallest supported chip
  serial: clps711x: Changing the compatibility string to match with the smallest supported chip
  irqchip: clps711x: Changing the compatibility string to match with the smallest supported chip
  clocksource: clps711x: Changing the compatibility string to match with the smallest supported chip
  clk: clps711x: Changing the compatibility string to match with the smallest supported chip
  ...
parents 6911a528 f8c6d88b
......@@ -2,11 +2,9 @@
# Makefile for the linux kernel, U8500 machine.
#
obj-y := cpu.o id.o pm.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
obj-y := pm.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \
board-mop500-audio.o
obj-$(CONFIG_MACH_MOP500) += board-mop500-audio.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
......
This diff is collapsed.
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
*
* MOP500 board specific initialization for regulators
*/
#ifndef __BOARD_MOP500_REGULATORS_H
#define __BOARD_MOP500_REGULATORS_H
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data;
extern struct ab8500_regulator_platform_data ab8505_regulator_plat_data;
extern struct regulator_init_data tps61052_regulator;
extern struct regulator_init_data gpio_en_3v3_regulator;
void mop500_regulator_init(void);
#endif
/*
* Copyright (C) ST-Ericsson SA 2011
*
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/outercache.h>
#include <asm/hardware/cache-l2x0.h>
#include "db8500-regs.h"
#include "id.h"
static int __init ux500_l2x0_unlock(void)
{
int i;
struct device_node *np;
void __iomem *l2x0_base;
np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
l2x0_base = of_iomap(np, 0);
of_node_put(np);
if (!l2x0_base)
return -ENODEV;
/*
* Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
* apparently locks both caches before jumping to the kernel. The
* l2x0 core will not touch the unlock registers if the l2x0 is
* already enabled, so we do it right here instead. The PL310 has
* 8 sets of registers, one per possible CPU.
*/
for (i = 0; i < 8; i++) {
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
i * L2X0_LOCKDOWN_STRIDE);
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
i * L2X0_LOCKDOWN_STRIDE);
}
iounmap(l2x0_base);
return 0;
}
static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)
{
/*
* We can't write to secure registers as we are in non-secure
* mode, until we have some SMI service available.
*/
}
static int __init ux500_l2x0_init(void)
{
/* Multiplatform guard */
if (!((cpu_is_u8500_family() || cpu_is_ux540_family())))
return -ENODEV;
/* Unlock before init */
ux500_l2x0_unlock();
outer_cache.write_sec = ux500_l2c310_write_sec;
l2x0_of_init(0, ~0);
return 0;
}
early_initcall(ux500_l2x0_init);
......@@ -12,41 +12,107 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/perf/arm_pmu.h>
#include <linux/regulator/machine.h>
#include <linux/random.h>
#include <asm/outercache.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include "setup.h"
#include "board-mop500-regulators.h"
#include "board-mop500.h"
#include "db8500-regs.h"
#include "id.h"
static struct ab8500_platform_data ab8500_platdata = {
.regulator = &ab8500_regulator_plat_data,
};
static int __init ux500_l2x0_unlock(void)
{
int i;
struct device_node *np;
void __iomem *l2x0_base;
static struct prcmu_pdata db8500_prcmu_pdata = {
.ab_platdata = &ab8500_platdata,
.version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
.legacy_offset = DB8500_PRCMU_LEGACY_OFFSET,
};
np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
l2x0_base = of_iomap(np, 0);
of_node_put(np);
if (!l2x0_base)
return -ENODEV;
/*
* Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
* apparently locks both caches before jumping to the kernel. The
* l2x0 core will not touch the unlock registers if the l2x0 is
* already enabled, so we do it right here instead. The PL310 has
* 8 sets of registers, one per possible CPU.
*/
for (i = 0; i < 8; i++) {
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
i * L2X0_LOCKDOWN_STRIDE);
writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
i * L2X0_LOCKDOWN_STRIDE);
}
iounmap(l2x0_base);
return 0;
}
static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)
{
/*
* We can't write to secure registers as we are in non-secure
* mode, until we have some SMI service available.
*/
}
static void __init u8500_map_io(void)
/*
* FIXME: Should we set up the GPIO domain here?
*
* The problem is that we cannot put the interrupt resources into the platform
* device until the irqdomain has been added. Right now, we set the GIC interrupt
* domain from init_irq(), then load the gpio driver from
* core_initcall(nmk_gpio_init) and add the platform devices from
* arch_initcall(customize_machine).
*
* This feels fragile because it depends on the gpio device getting probed
* _before_ any device uses the gpio interrupts.
*/
static void __init ux500_init_irq(void)
{
struct device_node *np;
struct resource r;
irqchip_init();
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
of_address_to_resource(np, 0, &r);
of_node_put(np);
if (!r.start) {
pr_err("could not find PRCMU base resource\n");
return;
}
prcmu_early_init(r.start, r.end-r.start);
ux500_pm_init(r.start, r.end-r.start);
/* Unlock before init */
ux500_l2x0_unlock();
outer_cache.write_sec = ux500_l2c310_write_sec;
}
static void ux500_restart(enum reboot_mode mode, const char *cmd)
{
debug_ll_io_init();
ux500_setup_id();
local_irq_disable();
local_fiq_disable();
prcmu_system_reset(0);
}
/*
......@@ -73,31 +139,6 @@ static struct arm_pmu_platdata db8500_pmu_platdata = {
.handle_irq = db8500_pmu_handler,
};
static const char *db8500_read_soc_id(void)
{
void __iomem *uid;
const char *retstr;
uid = ioremap(U8500_BB_UID_BASE, 0x20);
if (!uid)
return NULL;
/* Throw these device-specific numbers into the entropy pool */
add_device_randomness(uid, 0x14);
retstr = kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
readl((u32 *)uid+0),
readl((u32 *)uid+1), readl((u32 *)uid+2),
readl((u32 *)uid+3), readl((u32 *)uid+4));
iounmap(uid);
return retstr;
}
static struct device * __init db8500_soc_device_init(void)
{
const char *soc_id = db8500_read_soc_id();
return ux500_soc_device_init(soc_id);
}
static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
/* Requires call-back bindings. */
OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
......@@ -111,8 +152,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
"ux500-msp-i2s.3", &msp3_platform_data),
/* Requires non-DT:able platform data. */
OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
&db8500_prcmu_pdata),
OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL),
OF_DEV_AUXDATA("stericsson,ux500-cryp", 0xa03cb000, "cryp1", NULL),
OF_DEV_AUXDATA("stericsson,ux500-hash", 0xa03c2000, "hash1", NULL),
OF_DEV_AUXDATA("stericsson,snd-soc-mop500", 0, "snd-soc-mop500.0",
......@@ -121,8 +161,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
};
static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
&db8500_prcmu_pdata),
OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL),
{},
};
......@@ -136,15 +175,13 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
static void __init u8500_init_machine(void)
{
struct device *parent = db8500_soc_device_init();
/* automatically probe child nodes of dbx5x0 devices */
if (of_machine_is_compatible("st-ericsson,u8540"))
of_platform_populate(NULL, u8500_local_bus_nodes,
u8540_auxdata_lookup, parent);
u8540_auxdata_lookup, NULL);
else
of_platform_populate(NULL, u8500_local_bus_nodes,
u8500_auxdata_lookup, parent);
u8500_auxdata_lookup, NULL);
}
static const char * stericsson_dt_platform_compat[] = {
......@@ -156,10 +193,10 @@ static const char * stericsson_dt_platform_compat[] = {
};
DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
.map_io = u8500_map_io,
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.init_irq = ux500_init_irq,
.init_machine = u8500_init_machine,
.init_late = NULL,
.dt_compat = stericsson_dt_platform_compat,
.restart = ux500_restart,
MACHINE_END
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/sys_soc.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/platform_data/clk-ux500.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <asm/mach/map.h>
#include "setup.h"
#include "board-mop500.h"
#include "db8500-regs.h"
#include "id.h"
void ux500_restart(enum reboot_mode mode, const char *cmd)
{
local_irq_disable();
local_fiq_disable();
prcmu_system_reset(0);
}
/*
* FIXME: Should we set up the GPIO domain here?
*
* The problem is that we cannot put the interrupt resources into the platform
* device until the irqdomain has been added. Right now, we set the GIC interrupt
* domain from init_irq(), then load the gpio driver from
* core_initcall(nmk_gpio_init) and add the platform devices from
* arch_initcall(customize_machine).
*
* This feels fragile because it depends on the gpio device getting probed
* _before_ any device uses the gpio interrupts.
*/
void __init ux500_init_irq(void)
{
struct device_node *np;
struct resource r;
irqchip_init();
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
of_address_to_resource(np, 0, &r);
of_node_put(np);
if (!r.start) {
pr_err("could not find PRCMU base resource\n");
return;
}
prcmu_early_init(r.start, r.end-r.start);
ux500_pm_init(r.start, r.end-r.start);
/*
* Init clocks here so that they are available for system timer
* initialization.
*/
if (cpu_is_u8500_family())
u8500_clk_init();
else if (cpu_is_u9540())
u9540_clk_init();
else if (cpu_is_u8540())
u8540_clk_init();
}
static const char * __init ux500_get_machine(void)
{
return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber());
}
static const char * __init ux500_get_family(void)
{
return kasprintf(GFP_KERNEL, "ux500");
}
static const char * __init ux500_get_revision(void)
{
unsigned int rev = dbx500_revision();
if (rev == 0x01)
return kasprintf(GFP_KERNEL, "%s", "ED");
else if (rev >= 0xA0)
return kasprintf(GFP_KERNEL, "%d.%d",
(rev >> 4) - 0xA + 1, rev & 0xf);
return kasprintf(GFP_KERNEL, "%s", "Unknown");
}
static ssize_t ux500_get_process(struct device *dev,
struct device_attribute *attr,
char *buf)
{
if (dbx500_id.process == 0x00)
return sprintf(buf, "Standard\n");
return sprintf(buf, "%02xnm\n", dbx500_id.process);
}
static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
const char *soc_id)
{
soc_dev_attr->soc_id = soc_id;
soc_dev_attr->machine = ux500_get_machine();
soc_dev_attr->family = ux500_get_family();
soc_dev_attr->revision = ux500_get_revision();
}
static const struct device_attribute ux500_soc_attr =
__ATTR(process, S_IRUGO, ux500_get_process, NULL);
struct device * __init ux500_soc_device_init(const char *soc_id)
{
struct device *parent;
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return ERR_PTR(-ENOMEM);
soc_info_populate(soc_dev_attr, soc_id);
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr);
return NULL;
}
parent = soc_device_to_device(soc_dev);
device_create_file(parent, &ux500_soc_attr);
return parent;
}
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef __MACH_UX500_ID
#define __MACH_UX500_ID
/**
* struct dbx500_asic_id - fields of the ASIC ID
* @process: the manufacturing process, 0x40 is 40 nm 0x00 is "standard"
* @partnumber: hithereto 0x8500 for DB8500
* @revision: version code in the series
*/
struct dbx500_asic_id {
u16 partnumber;
u8 revision;
u8 process;
};
extern struct dbx500_asic_id dbx500_id;
static inline unsigned int __attribute_const__ dbx500_partnumber(void)
{
return dbx500_id.partnumber;
}
static inline unsigned int __attribute_const__ dbx500_revision(void)
{
return dbx500_id.revision;
}
/*
* SOCs
*/
static inline bool __attribute_const__ cpu_is_u8500(void)
{
return dbx500_partnumber() == 0x8500;
}
static inline bool __attribute_const__ cpu_is_u8520(void)
{
return dbx500_partnumber() == 0x8520;
}
static inline bool cpu_is_u8500_family(void)
{
return cpu_is_u8500() || cpu_is_u8520();
}
static inline bool __attribute_const__ cpu_is_u9540(void)
{
return dbx500_partnumber() == 0x9540;
}
static inline bool __attribute_const__ cpu_is_u8540(void)
{
return dbx500_partnumber() == 0x8540;
}
static inline bool __attribute_const__ cpu_is_u8580(void)
{
return dbx500_partnumber() == 0x8580;
}
static inline bool cpu_is_ux540_family(void)
{
return cpu_is_u9540() || cpu_is_u8540() || cpu_is_u8580();
}
/*
* 8500 revisions
*/
static inline bool __attribute_const__ cpu_is_u8500ed(void)
{
return cpu_is_u8500() && dbx500_revision() == 0x00;
}
static inline bool __attribute_const__ cpu_is_u8500v1(void)
{
return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0;
}
static inline bool __attribute_const__ cpu_is_u8500v10(void)
{
return cpu_is_u8500() && dbx500_revision() == 0xA0;
}
static inline bool __attribute_const__ cpu_is_u8500v11(void)
{
return cpu_is_u8500() && dbx500_revision() == 0xA1;
}
static inline bool __attribute_const__ cpu_is_u8500v2(void)
{
return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0);
}
static inline bool cpu_is_u8500v20(void)
{
return cpu_is_u8500() && (dbx500_revision() == 0xB0);
}
static inline bool cpu_is_u8500v21(void)
{
return cpu_is_u8500() && (dbx500_revision() == 0xB1);
}
static inline bool cpu_is_u8500v22(void)
{
return cpu_is_u8500() && (dbx500_revision() == 0xB2);
}
static inline bool cpu_is_u8500v20_or_later(void)
{
return (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11());
}
/*
* 8540 revisions
*/
static inline bool __attribute_const__ cpu_is_u8540v10(void)
{
return cpu_is_u8540() && dbx500_revision() == 0xA0;
}
static inline bool __attribute_const__ cpu_is_u8580v10(void)
{
return cpu_is_u8580() && dbx500_revision() == 0xA0;
}
static inline bool ux500_is_svp(void)
{
return false;
}
#define ux500_unknown_soc() BUG()
#endif
......@@ -26,7 +26,6 @@
#include "setup.h"
#include "db8500-regs.h"
#include "id.h"
/* Magic triggers in backup RAM */
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
......
......@@ -11,18 +11,6 @@
#ifndef __ASM_ARCH_SETUP_H
#define __ASM_ARCH_SETUP_H
#include <asm/mach/arch.h>
#include <linux/init.h>
#include <linux/mfd/abx500/ab8500.h>
void ux500_restart(enum reboot_mode mode, const char *cmd);
void __init ux500_setup_id(void);
extern void __init ux500_init_irq(void);
extern struct device *ux500_soc_device_init(const char *soc_id);
extern void ux500_cpu_die(unsigned int cpu);
#endif /* __ASM_ARCH_SETUP_H */
......@@ -5,6 +5,7 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/hisi,hi6220-resets.h>
#include <dt-bindings/clock/hi6220-clock.h>
#include <dt-bindings/pinctrl/hisi.h>
#include <dt-bindings/thermal/thermal.h>
......@@ -252,6 +253,7 @@
compatible = "hisilicon,hi6220-mediactrl", "syscon";
reg = <0x0 0xf4410000 0x0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
pm_ctrl: pm_ctrl@f7032000 {
......
......@@ -132,6 +132,19 @@ config SUNXI_RSB
with various RSB based devices, such as AXP223, AXP8XX PMICs,
and AC100/AC200 ICs.
# TODO: This uses pm_clk_*() symbols that aren't exported in v4.7 and hence
# the driver will fail to build as a module. However there are patches to
# address that queued for v4.8, so this can be turned into a tristate symbol
# after v4.8-rc1.
config TEGRA_ACONNECT
bool "Tegra ACONNECT Bus Driver"
depends on ARCH_TEGRA_210_SOC
depends on OF && PM
select PM_CLK
help
Driver for the Tegra ACONNECT bus which is used to interface with
the devices inside the Audio Processing Engine (APE) for Tegra210.
config UNIPHIER_SYSTEM_BUS
tristate "UniPhier System Bus driver"
depends on ARCH_UNIPHIER && OF
......
......@@ -17,5 +17,6 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
/*
* Tegra ACONNECT Bus Driver
*
* Copyright (C) 2016, NVIDIA CORPORATION. All rights reserved.
*
* 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/clk.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
static int tegra_aconnect_add_clock(struct device *dev, char *name)
{
struct clk *clk;
int ret;
clk = clk_get(dev, name);
if (IS_ERR(clk)) {
dev_err(dev, "%s clock not found\n", name);
return PTR_ERR(clk);
}
ret = pm_clk_add_clk(dev, clk);
if (ret)
clk_put(clk);
return ret;
}
static int tegra_aconnect_probe(struct platform_device *pdev)
{
int ret;
if (!pdev->dev.of_node)
return -EINVAL;
ret = pm_clk_create(&pdev->dev);
if (ret)
return ret;
ret = tegra_aconnect_add_clock(&pdev->dev, "ape");
if (ret)
goto clk_destroy;
ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape");
if (ret)
goto clk_destroy;
pm_runtime_enable(&pdev->dev);
of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
return 0;
clk_destroy:
pm_clk_destroy(&pdev->dev);
return ret;
}
static int tegra_aconnect_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
pm_clk_destroy(&pdev->dev);
return 0;
}
static int tegra_aconnect_runtime_resume(struct device *dev)
{
return pm_clk_resume(dev);
}
static int tegra_aconnect_runtime_suspend(struct device *dev)
{
return pm_clk_suspend(dev);
}
static const struct dev_pm_ops tegra_aconnect_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
tegra_aconnect_runtime_resume, NULL)
};
static const struct of_device_id tegra_aconnect_of_match[] = {
{ .compatible = "nvidia,tegra210-aconnect", },
{ }
};
MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
static struct platform_driver tegra_aconnect_driver = {
.probe = tegra_aconnect_probe,
.remove = tegra_aconnect_remove,
.driver = {
.name = "tegra-aconnect",
.of_match_table = tegra_aconnect_of_match,
.pm = &tegra_aconnect_pm_ops,
},
};
module_platform_driver(tegra_aconnect_driver);
MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver");
MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
MODULE_LICENSE("GPL v2");
......@@ -184,5 +184,5 @@ static void __init clps711x_clk_init_dt(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get,
&clps711x_clk->clk_data);
}
CLK_OF_DECLARE(clps711x, "cirrus,clps711x-clk", clps711x_clk_init_dt);
CLK_OF_DECLARE(clps711x, "cirrus,ep7209-clk", clps711x_clk_init_dt);
#endif
......@@ -11,7 +11,6 @@
#include <linux/of_address.h>
#include <linux/clk-provider.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/platform_data/clk-ux500.h>
#include "clk.h"
#define PRCC_NUM_PERIPH_CLUSTERS 6
......@@ -48,11 +47,6 @@ static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec,
return PRCC_SHOW(clk_data, base, bit);
}
static const struct of_device_id u8500_clk_of_match[] = {
{ .compatible = "stericsson,u8500-clks", },
{ },
};
/* CLKRST4 is missing making it hard to index things */
enum clkrst_index {
CLKRST1_INDEX = 0,
......@@ -63,22 +57,15 @@ enum clkrst_index {
CLKRST_MAX,
};
void u8500_clk_init(void)
static void u8500_clk_init(struct device_node *np)
{
struct prcmu_fw_version *fw_version;
struct device_node *np = NULL;
struct device_node *child = NULL;
const char *sgaclk_parent = NULL;
struct clk *clk, *rtc_clk, *twd_clk;
u32 bases[CLKRST_MAX];
int i;
if (of_have_populated_dt())
np = of_find_matching_node(NULL, u8500_clk_of_match);
if (!np) {
pr_err("Either DT or U8500 Clock node not found\n");
return;
}
for (i = 0; i < ARRAY_SIZE(bases); i++) {
struct resource r;
......@@ -573,3 +560,4 @@ void u8500_clk_init(void)
of_clk_add_provider(child, of_clk_src_simple_get, twd_clk);
}
}
CLK_OF_DECLARE(u8500_clks, "stericsson,u8500-clks", u8500_clk_init);
......@@ -12,14 +12,8 @@
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/platform_data/clk-ux500.h>
#include "clk.h"
static const struct of_device_id u8540_clk_of_match[] = {
{ .compatible = "stericsson,u8540-clks", },
{ }
};
/* CLKRST4 is missing making it hard to index things */
enum clkrst_index {
CLKRST1_INDEX = 0,
......@@ -30,19 +24,12 @@ enum clkrst_index {
CLKRST_MAX,
};
void u8540_clk_init(void)
static void u8540_clk_init(struct device_node *np)
{
struct clk *clk;
struct device_node *np = NULL;
u32 bases[CLKRST_MAX];
int i;
if (of_have_populated_dt())
np = of_find_matching_node(NULL, u8540_clk_of_match);
if (!np) {
pr_err("Either DT or U8540 Clock node not found\n");
return;
}
for (i = 0; i < ARRAY_SIZE(bases); i++) {
struct resource r;
......@@ -607,3 +594,4 @@ void u8540_clk_init(void)
bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
clk_register_clkdev(clk, NULL, "rng");
}
CLK_OF_DECLARE(u8540_clks, "stericsson,u8540-clks", u8540_clk_init);
......@@ -9,10 +9,10 @@
#include <linux/clk-provider.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/platform_data/clk-ux500.h>
#include "clk.h"
void u9540_clk_init(void)
static void u9540_clk_init(struct device_node *np)
{
/* register clocks here */
}
CLK_OF_DECLARE(u9540_clks, "stericsson,u9540-clks", u9540_clk_init);
......@@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np)
return -EINVAL;
}
}
CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init);
CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
#endif
......@@ -220,7 +220,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
tmp1 /= tmp;
__raw_writel(tmp1, reg);
writel_relaxed(tmp1, reg);
}
static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
......@@ -296,29 +296,29 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
* 1. Temporary Change divider for MFC and G3D
* SCLKA2M(200/1=200)->(200/4=50)Mhz
*/
reg = __raw_readl(S5P_CLK_DIV2);
reg = readl_relaxed(S5P_CLK_DIV2);
reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
(3 << S5P_CLKDIV2_MFC_SHIFT);
__raw_writel(reg, S5P_CLK_DIV2);
writel_relaxed(reg, S5P_CLK_DIV2);
/* For MFC, G3D dividing */
do {
reg = __raw_readl(S5P_CLKDIV_STAT0);
reg = readl_relaxed(S5P_CLKDIV_STAT0);
} while (reg & ((1 << 16) | (1 << 17)));
/*
* 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
* (200/4=50)->(667/4=166)Mhz
*/
reg = __raw_readl(S5P_CLK_SRC2);
reg = readl_relaxed(S5P_CLK_SRC2);
reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
(1 << S5P_CLKSRC2_MFC_SHIFT);
__raw_writel(reg, S5P_CLK_SRC2);
writel_relaxed(reg, S5P_CLK_SRC2);
do {
reg = __raw_readl(S5P_CLKMUX_STAT1);
reg = readl_relaxed(S5P_CLKMUX_STAT1);
} while (reg & ((1 << 7) | (1 << 3)));
/*
......@@ -330,19 +330,19 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
s5pv210_set_refresh(DMC1, 133000);
/* 4. SCLKAPLL -> SCLKMPLL */
reg = __raw_readl(S5P_CLK_SRC0);
reg = readl_relaxed(S5P_CLK_SRC0);
reg &= ~(S5P_CLKSRC0_MUX200_MASK);
reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
__raw_writel(reg, S5P_CLK_SRC0);
writel_relaxed(reg, S5P_CLK_SRC0);
do {
reg = __raw_readl(S5P_CLKMUX_STAT0);
reg = readl_relaxed(S5P_CLKMUX_STAT0);
} while (reg & (0x1 << 18));
}
/* Change divider */
reg = __raw_readl(S5P_CLK_DIV0);
reg = readl_relaxed(S5P_CLK_DIV0);
reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
......@@ -358,25 +358,25 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
(clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
(clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
__raw_writel(reg, S5P_CLK_DIV0);
writel_relaxed(reg, S5P_CLK_DIV0);
do {
reg = __raw_readl(S5P_CLKDIV_STAT0);
reg = readl_relaxed(S5P_CLKDIV_STAT0);
} while (reg & 0xff);
/* ARM MCS value changed */
reg = __raw_readl(S5P_ARM_MCS_CON);
reg = readl_relaxed(S5P_ARM_MCS_CON);
reg &= ~0x3;
if (index >= L3)
reg |= 0x3;
else
reg |= 0x1;
__raw_writel(reg, S5P_ARM_MCS_CON);
writel_relaxed(reg, S5P_ARM_MCS_CON);
if (pll_changing) {
/* 5. Set Lock time = 30us*24Mhz = 0x2cf */
__raw_writel(0x2cf, S5P_APLL_LOCK);
writel_relaxed(0x2cf, S5P_APLL_LOCK);
/*
* 6. Turn on APLL
......@@ -384,12 +384,12 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
* 6-2. Wait untile the PLL is locked
*/
if (index == L0)
__raw_writel(APLL_VAL_1000, S5P_APLL_CON);
writel_relaxed(APLL_VAL_1000, S5P_APLL_CON);
else
__raw_writel(APLL_VAL_800, S5P_APLL_CON);
writel_relaxed(APLL_VAL_800, S5P_APLL_CON);
do {
reg = __raw_readl(S5P_APLL_CON);
reg = readl_relaxed(S5P_APLL_CON);
} while (!(reg & (0x1 << 29)));
/*
......@@ -397,39 +397,39 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
* to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
* (667/4=166)->(200/4=50)Mhz
*/
reg = __raw_readl(S5P_CLK_SRC2);
reg = readl_relaxed(S5P_CLK_SRC2);
reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
(0 << S5P_CLKSRC2_MFC_SHIFT);
__raw_writel(reg, S5P_CLK_SRC2);
writel_relaxed(reg, S5P_CLK_SRC2);
do {
reg = __raw_readl(S5P_CLKMUX_STAT1);
reg = readl_relaxed(S5P_CLKMUX_STAT1);
} while (reg & ((1 << 7) | (1 << 3)));
/*
* 8. Change divider for MFC and G3D
* (200/4=50)->(200/1=200)Mhz
*/
reg = __raw_readl(S5P_CLK_DIV2);
reg = readl_relaxed(S5P_CLK_DIV2);
reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
(clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
__raw_writel(reg, S5P_CLK_DIV2);
writel_relaxed(reg, S5P_CLK_DIV2);
/* For MFC, G3D dividing */
do {
reg = __raw_readl(S5P_CLKDIV_STAT0);
reg = readl_relaxed(S5P_CLKDIV_STAT0);
} while (reg & ((1 << 16) | (1 << 17)));
/* 9. Change MPLL to APLL in MSYS_MUX */
reg = __raw_readl(S5P_CLK_SRC0);
reg = readl_relaxed(S5P_CLK_SRC0);
reg &= ~(S5P_CLKSRC0_MUX200_MASK);
reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
__raw_writel(reg, S5P_CLK_SRC0);
writel_relaxed(reg, S5P_CLK_SRC0);
do {
reg = __raw_readl(S5P_CLKMUX_STAT0);
reg = readl_relaxed(S5P_CLKMUX_STAT0);
} while (reg & (0x1 << 18));
/*
......@@ -446,13 +446,13 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
* and memory refresh parameter should be changed
*/
if (bus_speed_changing) {
reg = __raw_readl(S5P_CLK_DIV6);
reg = readl_relaxed(S5P_CLK_DIV6);
reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
__raw_writel(reg, S5P_CLK_DIV6);
writel_relaxed(reg, S5P_CLK_DIV6);
do {
reg = __raw_readl(S5P_CLKDIV_STAT1);
reg = readl_relaxed(S5P_CLKDIV_STAT1);
} while (reg & (1 << 15));
/* Reconfigure DRAM refresh counter value */
......@@ -492,7 +492,7 @@ static int check_mem_type(void __iomem *dmc_reg)
{
unsigned long val;
val = __raw_readl(dmc_reg + 0x4);
val = readl_relaxed(dmc_reg + 0x4);
val = (val & (0xf << 8));
return val >> 8;
......@@ -537,10 +537,10 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
}
/* Find current refresh counter and frequency each DMC */
s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000);
s5pv210_dram_conf[0].refresh = (readl_relaxed(dmc_base[0] + 0x30) * 1000);
s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000);
s5pv210_dram_conf[1].refresh = (readl_relaxed(dmc_base[1] + 0x30) * 1000);
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
policy->suspend_freq = SLEEP_FREQ;
......
......@@ -10,7 +10,7 @@ config ARM_PSCI_FW
config ARM_SCPI_PROTOCOL
tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
depends on ARM_MHU
depends on MAILBOX
help
System Control and Power Interface (SCPI) Message Protocol is
defined for the purpose of communication between the Application
......@@ -27,6 +27,15 @@ config ARM_SCPI_PROTOCOL
This protocol library provides interface for all the client drivers
making use of the features offered by the SCP.
config ARM_SCPI_POWER_DOMAIN
tristate "SCPI power domain driver"
depends on ARM_SCPI_PROTOCOL || (COMPILE_TEST && OF)
default y
select PM_GENERIC_DOMAINS if PM
help
This enables support for the SCPI power domains which can be
enabled or disabled via the SCP firmware
config EDD
tristate "BIOS Enhanced Disk Drive calls determine boot disk"
depends on X86
......@@ -184,6 +193,7 @@ config FW_CFG_SYSFS_CMDLINE
config QCOM_SCM
bool
depends on ARM || ARM64
select RESET_CONTROLLER
config QCOM_SCM_32
def_bool y
......
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