Commit 22ba14f4 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'realview-base-armsoc-1-tag' of...

Merge tag 'realview-base-armsoc-1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into next/multiplatform

Merge "Realview multiplatform support" from Linus Walleij:

The board and infrastructure changes for RealView
multiplatform and extended DT support.

* tag 'realview-base-armsoc-1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator:
  ARM: realview: add an DT SMP boot method
  ARM: realview: select SP810 and ICST for the DT variant
  soc: versatile: add support for the PB11MPCore
  clk: versatile-icst: add device tree support
  clk: versatile-icst: refactor to allocate regmap separately
  clk: versatile-icst: convert to use regmap
  ARM: realview: remove private barrier implementation
  ARM: no longer force unbuffered DMA for realview
  clk/realview: stop using machine headers
  ARM: realview: don't map undefined PCI registers
  ARM: realview: remove sparsemem hack

Conflicts:
	drivers/clk/versatile/Kconfig
parents 7379d96b 5420b4b1
...@@ -190,6 +190,7 @@ nodes to be present and contain the properties described below. ...@@ -190,6 +190,7 @@ nodes to be present and contain the properties described below.
"allwinner,sun6i-a31" "allwinner,sun6i-a31"
"allwinner,sun8i-a23" "allwinner,sun8i-a23"
"arm,psci" "arm,psci"
"arm,realview-smp"
"brcm,brahma-b15" "brcm,brahma-b15"
"marvell,armada-375-smp" "marvell,armada-375-smp"
"marvell,armada-380-smp" "marvell,armada-380-smp"
......
...@@ -241,7 +241,6 @@ config ARM_PATCH_PHYS_VIRT ...@@ -241,7 +241,6 @@ config ARM_PATCH_PHYS_VIRT
bool "Patch physical to virtual translations at runtime" if EMBEDDED bool "Patch physical to virtual translations at runtime" if EMBEDDED
default y default y
depends on !XIP_KERNEL && MMU depends on !XIP_KERNEL && MMU
depends on !ARCH_REALVIEW || !SPARSEMEM
help help
Patch phys-to-virt and virt-to-phys translation functions at Patch phys-to-virt and virt-to-phys translation functions at
boot and module load time according to the position of the boot and module load time according to the position of the
...@@ -356,7 +355,6 @@ config ARCH_REALVIEW ...@@ -356,7 +355,6 @@ config ARCH_REALVIEW
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GPIO_PL061 if GPIOLIB select GPIO_PL061 if GPIOLIB
select ICST select ICST
select NEED_MACH_MEMORY_H
select PLAT_VERSATILE select PLAT_VERSATILE
select PLAT_VERSATILE_SCHED_CLOCK select PLAT_VERSATILE_SCHED_CLOCK
help help
......
...@@ -4,10 +4,14 @@ menu "RealView platform type" ...@@ -4,10 +4,14 @@ menu "RealView platform type"
config REALVIEW_DT config REALVIEW_DT
bool "Support RealView(R) Device Tree based boot" bool "Support RealView(R) Device Tree based boot"
select ARM_GIC select ARM_GIC
select CLK_SP810
select HAVE_SMP
select ICST
select MFD_SYSCON select MFD_SYSCON
select POWER_RESET select POWER_RESET
select POWER_RESET_VERSATILE select POWER_RESET_VERSATILE
select POWER_SUPPLY select POWER_SUPPLY
select SMP_ON_UP
select SOC_REALVIEW select SOC_REALVIEW
select USE_OF select USE_OF
help help
...@@ -36,7 +40,6 @@ config REALVIEW_EB_A9MP ...@@ -36,7 +40,6 @@ config REALVIEW_EB_A9MP
config REALVIEW_EB_ARM11MP config REALVIEW_EB_ARM11MP
bool "Support ARM11MPCore Tile" bool "Support ARM11MPCore Tile"
depends on MACH_REALVIEW_EB depends on MACH_REALVIEW_EB
select ARCH_HAS_BARRIERS if SMP
select CPU_V6K select CPU_V6K
select HAVE_ARM_SCU if SMP select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP select HAVE_ARM_TWD if SMP
...@@ -57,7 +60,6 @@ config REALVIEW_EB_ARM11MP_REVB ...@@ -57,7 +60,6 @@ config REALVIEW_EB_ARM11MP_REVB
config MACH_REALVIEW_PB11MP config MACH_REALVIEW_PB11MP
bool "Support RealView(R) Platform Baseboard for ARM11MPCore" bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
select ARCH_HAS_BARRIERS if SMP
select ARM_GIC select ARM_GIC
select CPU_V6K select CPU_V6K
select HAVE_ARM_SCU if SMP select HAVE_ARM_SCU if SMP
...@@ -102,14 +104,13 @@ config MACH_REALVIEW_PBA8 ...@@ -102,14 +104,13 @@ config MACH_REALVIEW_PBA8
config MACH_REALVIEW_PBX config MACH_REALVIEW_PBX
bool "Support RealView(R) Platform Baseboard Explore" bool "Support RealView(R) Platform Baseboard Explore"
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
select ARM_GIC select ARM_GIC
select HAVE_ARM_SCU if SMP select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP select HAVE_ARM_TWD if SMP
select HAVE_PATA_PLATFORM select HAVE_PATA_PLATFORM
select HAVE_SMP select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0 select MIGHT_HAVE_CACHE_L2X0
select ZONE_DMA if SPARSEMEM select ZONE_DMA
help help
Include support for the ARM(R) RealView(R) Platform Baseboard Include support for the ARM(R) RealView(R) Platform Baseboard
Explore. Explore.
...@@ -124,6 +125,6 @@ config REALVIEW_HIGH_PHYS_OFFSET ...@@ -124,6 +125,6 @@ config REALVIEW_HIGH_PHYS_OFFSET
the board supports 512MB of RAM, this option allows the the board supports 512MB of RAM, this option allows the
memory to be accessed contiguously at the high physical memory to be accessed contiguously at the high physical
offset. On the PBX board, disabling this option allows 1GB of offset. On the PBX board, disabling this option allows 1GB of
RAM to be used with SPARSEMEM. RAM to be used with HIGHMEM.
endmenu endmenu
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
obj-y := core.o obj-y := core.o
obj-$(CONFIG_REALVIEW_DT) += realview-dt.o obj-$(CONFIG_REALVIEW_DT) += realview-dt.o platsmp-dt.o
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
......
/*
* Barriers redefined for RealView ARM11MPCore platforms with L220 cache
* controller to work around hardware errata causing the outer_sync()
* operation to deadlock the system.
*/
#define mb() dsb()
#define rmb() dsb()
#define wmb() mb()
/*
* arch/arm/mach-realview/include/mach/memory.h
*
* Copyright (C) 2003 ARM Limited
*
* 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.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
#ifdef CONFIG_SPARSEMEM
/*
* Sparsemem definitions for RealView PBX.
*
* The RealView PBX board has another block of 512MB of RAM at 0x20000000,
* however only the block at 0x70000000 (or the 256MB mirror at 0x00000000)
* may be used for DMA.
*
* The macros below define a section size of 256MB and a non-linear virtual to
* physical mapping:
*
* 256MB @ 0x00000000 -> PAGE_OFFSET
* 512MB @ 0x20000000 -> PAGE_OFFSET + 0x10000000
* 256MB @ 0x80000000 -> PAGE_OFFSET + 0x30000000
*/
#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
#error "SPARSEMEM not available with REALVIEW_HIGH_PHYS_OFFSET"
#endif
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 28
/* bank page offsets */
#define PAGE_OFFSET1 (PAGE_OFFSET + 0x10000000)
#define PAGE_OFFSET2 (PAGE_OFFSET + 0x30000000)
#define PHYS_OFFSET PLAT_PHYS_OFFSET
#define __phys_to_virt(phys) \
((phys) >= 0x80000000 ? (phys) - 0x80000000 + PAGE_OFFSET2 : \
(phys) >= 0x20000000 ? (phys) - 0x20000000 + PAGE_OFFSET1 : \
(phys) + PAGE_OFFSET)
#define __virt_to_phys(virt) \
((virt) >= PAGE_OFFSET2 ? (virt) - PAGE_OFFSET2 + 0x80000000 : \
(virt) >= PAGE_OFFSET1 ? (virt) - PAGE_OFFSET1 + 0x20000000 : \
(virt) - PAGE_OFFSET)
#endif /* CONFIG_SPARSEMEM */
#endif
/*
* Copyright (C) 2015 Linus Walleij
*
* 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.
*/
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <plat/platsmp.h>
#include "core.h"
#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
static const struct of_device_id realview_scu_match[] = {
{ .compatible = "arm,arm11mp-scu", },
{ .compatible = "arm,cortex-a9-scu", },
{ .compatible = "arm,cortex-a5-scu", },
{ }
};
static const struct of_device_id realview_syscon_match[] = {
{ .compatible = "arm,core-module-integrator", },
{ .compatible = "arm,realview-eb-syscon", },
{ .compatible = "arm,realview-pb11mp-syscon", },
{ .compatible = "arm,realview-pbx-syscon", },
{ },
};
static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
{
struct device_node *np;
void __iomem *scu_base;
struct regmap *map;
unsigned int ncores;
int i;
np = of_find_matching_node(NULL, realview_scu_match);
if (!np) {
pr_err("PLATSMP: No SCU base address\n");
return;
}
scu_base = of_iomap(np, 0);
of_node_put(np);
if (!scu_base) {
pr_err("PLATSMP: No SCU remap\n");
return;
}
scu_enable(scu_base);
ncores = scu_get_core_count(scu_base);
pr_info("SCU: %d cores detected\n", ncores);
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
iounmap(scu_base);
/* The syscon contains the magic SMP start address registers */
np = of_find_matching_node(NULL, realview_syscon_match);
if (!np) {
pr_err("PLATSMP: No syscon match\n");
return;
}
map = syscon_node_to_regmap(np);
if (IS_ERR(map)) {
pr_err("PLATSMP: No syscon regmap\n");
return;
}
/* Put the boot address in this magic register */
regmap_write(map, REALVIEW_SYS_FLAGSSET_OFFSET,
virt_to_phys(versatile_secondary_startup));
}
struct smp_operations realview_dt_smp_ops __initdata = {
.smp_prepare_cpus = realview_smp_prepare_cpus,
.smp_secondary_init = versatile_secondary_init,
.smp_boot_secondary = versatile_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = realview_cpu_die,
#endif
};
CPU_METHOD_OF_DECLARE(realview_smp, "arm,realview-smp", &realview_dt_smp_ops);
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
#include <asm/smp_twd.h> #include <asm/smp_twd.h>
#include <asm/system_info.h> #include <asm/system_info.h>
#include <asm/outercache.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -450,6 +451,12 @@ static void __init realview_eb_init(void) ...@@ -450,6 +451,12 @@ static void __init realview_eb_init(void)
* Bits: .... ...0 0111 1001 0000 .... .... .... * Bits: .... ...0 0111 1001 0000 .... .... ....
*/ */
l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
/*
* due to a bug in the l220 cache controller, we must not call
* the sync function. stub it out here instead!
*/
outer_cache.sync = NULL;
#endif #endif
pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu"; pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu";
platform_device_register(&pmu_device); platform_device_register(&pmu_device);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <asm/outercache.h>
#include <mach/board-pb11mp.h> #include <mach/board-pb11mp.h>
#include <mach/irqs.h> #include <mach/irqs.h>
...@@ -345,6 +346,11 @@ static void __init realview_pb11mp_init(void) ...@@ -345,6 +346,11 @@ static void __init realview_pb11mp_init(void)
* Bits: .... ...0 0111 1001 0000 .... .... .... * Bits: .... ...0 0111 1001 0000 .... .... ....
*/ */
l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
/*
* due to a bug in the l220 cache controller, we must not call
* the sync function. stub it out here instead!
*/
outer_cache.sync = NULL;
#endif #endif
realview_flash_register(realview_pb11mp_flash_resource, realview_flash_register(realview_pb11mp_flash_resource,
......
...@@ -77,14 +77,6 @@ static struct map_desc realview_pba8_io_desc[] __initdata = { ...@@ -77,14 +77,6 @@ static struct map_desc realview_pba8_io_desc[] __initdata = {
.length = SZ_4K, .length = SZ_4K,
.type = MT_DEVICE, .type = MT_DEVICE,
}, },
#ifdef CONFIG_PCI
{
.virtual = PCIX_UNIT_BASE,
.pfn = __phys_to_pfn(REALVIEW_PBA8_PCI_BASE),
.length = REALVIEW_PBA8_PCI_BASE_SIZE,
.type = MT_DEVICE
},
#endif
#ifdef CONFIG_DEBUG_LL #ifdef CONFIG_DEBUG_LL
{ {
.virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE), .virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE),
......
...@@ -79,14 +79,6 @@ static struct map_desc realview_pbx_io_desc[] __initdata = { ...@@ -79,14 +79,6 @@ static struct map_desc realview_pbx_io_desc[] __initdata = {
.length = SZ_4K, .length = SZ_4K,
.type = MT_DEVICE, .type = MT_DEVICE,
}, },
#ifdef CONFIG_PCI
{
.virtual = PCIX_UNIT_BASE,
.pfn = __phys_to_pfn(REALVIEW_PBX_PCI_BASE),
.length = REALVIEW_PBX_PCI_BASE_SIZE,
.type = MT_DEVICE,
},
#endif
#ifdef CONFIG_DEBUG_LL #ifdef CONFIG_DEBUG_LL
{ {
.virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE), .virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE),
......
...@@ -1005,8 +1005,6 @@ config ARM_L1_CACHE_SHIFT ...@@ -1005,8 +1005,6 @@ config ARM_L1_CACHE_SHIFT
config ARM_DMA_MEM_BUFFERABLE config ARM_DMA_MEM_BUFFERABLE
bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7 bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7
depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \
MACH_REALVIEW_PB11MP)
default y if CPU_V6 || CPU_V6K || CPU_V7 default y if CPU_V6 || CPU_V6K || CPU_V7
help help
Historically, the kernel has used strongly ordered mappings to Historically, the kernel has used strongly ordered mappings to
......
...@@ -3,6 +3,7 @@ config COMMON_CLK_VERSATILE ...@@ -3,6 +3,7 @@ config COMMON_CLK_VERSATILE
depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \ ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \
COMPILE_TEST COMPILE_TEST
select REGMAP_MMIO
---help--- ---help---
Supports clocking on ARM Reference designs: Supports clocking on ARM Reference designs:
- Integrator/AP and Integrator/CP - Integrator/AP and Integrator/CP
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* We wrap the custom interface from <asm/hardware/icst.h> into the generic * We wrap the custom interface from <asm/hardware/icst.h> into the generic
* clock framework. * clock framework.
* *
* Copyright (C) 2012 Linus Walleij * Copyright (C) 2012-2015 Linus Walleij
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -19,9 +19,14 @@ ...@@ -19,9 +19,14 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include "clk-icst.h" #include "clk-icst.h"
/* Magic unlocking token used on all Versatile boards */
#define VERSATILE_LOCK_VAL 0xA05F
/** /**
* struct clk_icst - ICST VCO clock wrapper * struct clk_icst - ICST VCO clock wrapper
* @hw: corresponding clock hardware entry * @hw: corresponding clock hardware entry
...@@ -32,8 +37,9 @@ ...@@ -32,8 +37,9 @@
*/ */
struct clk_icst { struct clk_icst {
struct clk_hw hw; struct clk_hw hw;
void __iomem *vcoreg; struct regmap *map;
void __iomem *lockreg; u32 vcoreg_off;
u32 lockreg_off;
struct icst_params *params; struct icst_params *params;
unsigned long rate; unsigned long rate;
}; };
...@@ -41,53 +47,67 @@ struct clk_icst { ...@@ -41,53 +47,67 @@ struct clk_icst {
#define to_icst(_hw) container_of(_hw, struct clk_icst, hw) #define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
/** /**
* vco_get() - get ICST VCO settings from a certain register * vco_get() - get ICST VCO settings from a certain ICST
* @vcoreg: register containing the VCO settings * @icst: the ICST clock to get
* @vco: the VCO struct to return the value in
*/ */
static struct icst_vco vco_get(void __iomem *vcoreg) static int vco_get(struct clk_icst *icst, struct icst_vco *vco)
{ {
u32 val; u32 val;
struct icst_vco vco; int ret;
val = readl(vcoreg); ret = regmap_read(icst->map, icst->vcoreg_off, &val);
vco.v = val & 0x1ff; if (ret)
vco.r = (val >> 9) & 0x7f; return ret;
vco.s = (val >> 16) & 03; vco->v = val & 0x1ff;
return vco; vco->r = (val >> 9) & 0x7f;
vco->s = (val >> 16) & 03;
return 0;
} }
/** /**
* vco_set() - commit changes to an ICST VCO * vco_set() - commit changes to an ICST VCO
* @locreg: register to poke to unlock the VCO for writing * @icst: the ICST clock to set
* @vcoreg: register containing the VCO settings * @vco: the VCO struct to set the changes from
* @vco: ICST VCO parameters to commit
*/ */
static void vco_set(void __iomem *lockreg, static int vco_set(struct clk_icst *icst, struct icst_vco vco)
void __iomem *vcoreg,
struct icst_vco vco)
{ {
u32 val; u32 val;
int ret;
val = readl(vcoreg) & ~0x7ffff; ret = regmap_read(icst->map, icst->vcoreg_off, &val);
if (ret)
return ret;
val |= vco.v | (vco.r << 9) | (vco.s << 16); val |= vco.v | (vco.r << 9) | (vco.s << 16);
/* This magic unlocks the VCO so it can be controlled */ /* This magic unlocks the VCO so it can be controlled */
writel(0xa05f, lockreg); ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL);
writel(val, vcoreg); if (ret)
return ret;
ret = regmap_write(icst->map, icst->vcoreg_off, val);
if (ret)
return ret;
/* This locks the VCO again */ /* This locks the VCO again */
writel(0, lockreg); ret = regmap_write(icst->map, icst->lockreg_off, 0);
if (ret)
return ret;
return 0;
} }
static unsigned long icst_recalc_rate(struct clk_hw *hw, static unsigned long icst_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_icst *icst = to_icst(hw); struct clk_icst *icst = to_icst(hw);
struct icst_vco vco; struct icst_vco vco;
int ret;
if (parent_rate) if (parent_rate)
icst->params->ref = parent_rate; icst->params->ref = parent_rate;
vco = vco_get(icst->vcoreg); ret = vco_get(icst, &vco);
if (ret) {
pr_err("ICST: could not get VCO setting\n");
return 0;
}
icst->rate = icst_hz(icst->params, vco); icst->rate = icst_hz(icst->params, vco);
return icst->rate; return icst->rate;
} }
...@@ -112,8 +132,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -112,8 +132,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
icst->params->ref = parent_rate; icst->params->ref = parent_rate;
vco = icst_hz_to_vco(icst->params, rate); vco = icst_hz_to_vco(icst->params, rate);
icst->rate = icst_hz(icst->params, vco); icst->rate = icst_hz(icst->params, vco);
vco_set(icst->lockreg, icst->vcoreg, vco); return vco_set(icst, vco);
return 0;
} }
static const struct clk_ops icst_ops = { static const struct clk_ops icst_ops = {
...@@ -122,11 +141,11 @@ static const struct clk_ops icst_ops = { ...@@ -122,11 +141,11 @@ static const struct clk_ops icst_ops = {
.set_rate = icst_set_rate, .set_rate = icst_set_rate,
}; };
struct clk *icst_clk_register(struct device *dev, static struct clk *icst_clk_setup(struct device *dev,
const struct clk_icst_desc *desc, const struct clk_icst_desc *desc,
const char *name, const char *name,
const char *parent_name, const char *parent_name,
void __iomem *base) struct regmap *map)
{ {
struct clk *clk; struct clk *clk;
struct clk_icst *icst; struct clk_icst *icst;
...@@ -151,10 +170,11 @@ struct clk *icst_clk_register(struct device *dev, ...@@ -151,10 +170,11 @@ struct clk *icst_clk_register(struct device *dev,
init.flags = CLK_IS_ROOT; init.flags = CLK_IS_ROOT;
init.parent_names = (parent_name ? &parent_name : NULL); init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0); init.num_parents = (parent_name ? 1 : 0);
icst->map = map;
icst->hw.init = &init; icst->hw.init = &init;
icst->params = pclone; icst->params = pclone;
icst->vcoreg = base + desc->vco_offset; icst->vcoreg_off = desc->vco_offset;
icst->lockreg = base + desc->lock_offset; icst->lockreg_off = desc->lock_offset;
clk = clk_register(dev, &icst->hw); clk = clk_register(dev, &icst->hw);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
...@@ -164,4 +184,112 @@ struct clk *icst_clk_register(struct device *dev, ...@@ -164,4 +184,112 @@ struct clk *icst_clk_register(struct device *dev,
return clk; return clk;
} }
struct clk *icst_clk_register(struct device *dev,
const struct clk_icst_desc *desc,
const char *name,
const char *parent_name,
void __iomem *base)
{
struct regmap_config icst_regmap_conf = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
struct regmap *map;
map = regmap_init_mmio(dev, base, &icst_regmap_conf);
if (IS_ERR(map)) {
pr_err("could not initialize ICST regmap\n");
return ERR_CAST(map);
}
return icst_clk_setup(dev, desc, name, parent_name, map);
}
EXPORT_SYMBOL_GPL(icst_clk_register); EXPORT_SYMBOL_GPL(icst_clk_register);
#ifdef CONFIG_OF
/*
* In a device tree, an memory-mapped ICST clock appear as a child
* of a syscon node. Assume this and probe it only as a child of a
* syscon.
*/
static const struct icst_params icst525_params = {
.vco_max = ICST525_VCO_MAX_5V,
.vco_min = ICST525_VCO_MIN,
.vd_min = 8,
.vd_max = 263,
.rd_min = 3,
.rd_max = 65,
.s2div = icst525_s2div,
.idx2s = icst525_idx2s,
};
static const struct icst_params icst307_params = {
.vco_max = ICST307_VCO_MAX,
.vco_min = ICST307_VCO_MIN,
.vd_min = 4 + 8,
.vd_max = 511 + 8,
.rd_min = 1 + 2,
.rd_max = 127 + 2,
.s2div = icst307_s2div,
.idx2s = icst307_idx2s,
};
static void __init of_syscon_icst_setup(struct device_node *np)
{
struct device_node *parent;
struct regmap *map;
struct clk_icst_desc icst_desc;
const char *name = np->name;
const char *parent_name;
struct clk *regclk;
/* We do not release this reference, we are using it perpetually */
parent = of_get_parent(np);
if (!parent) {
pr_err("no parent node for syscon ICST clock\n");
return;
}
map = syscon_node_to_regmap(parent);
if (IS_ERR(map)) {
pr_err("no regmap for syscon ICST clock parent\n");
return;
}
if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) {
pr_err("no VCO register offset for ICST clock\n");
return;
}
if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) {
pr_err("no lock register offset for ICST clock\n");
return;
}
if (of_device_is_compatible(np, "arm,syscon-icst525"))
icst_desc.params = &icst525_params;
else if (of_device_is_compatible(np, "arm,syscon-icst307"))
icst_desc.params = &icst307_params;
else {
pr_err("unknown ICST clock %s\n", name);
return;
}
/* Parent clock name is not the same as node parent */
parent_name = of_clk_get_parent_name(np, 0);
regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map);
if (IS_ERR(regclk)) {
pr_err("error setting up syscon ICST clock %s\n", name);
return;
}
of_clk_add_provider(np, of_clk_src_simple_get, regclk);
pr_debug("registered syscon ICST clock %s\n", name);
}
CLK_OF_DECLARE(arm_syscon_icst525_clk,
"arm,syscon-icst525", of_syscon_icst_setup);
CLK_OF_DECLARE(arm_syscon_icst307_clk,
"arm,syscon-icst307", of_syscon_icst_setup);
#endif
...@@ -11,11 +11,15 @@ ...@@ -11,11 +11,15 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include "clk-icst.h" #include "clk-icst.h"
#define REALVIEW_SYS_OSC0_OFFSET 0x0C
#define REALVIEW_SYS_OSC1_OFFSET 0x10
#define REALVIEW_SYS_OSC2_OFFSET 0x14
#define REALVIEW_SYS_OSC3_OFFSET 0x18
#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */
#define REALVIEW_SYS_LOCK_OFFSET 0x20
/* /*
* Implementation of the ARM RealView clock trees. * Implementation of the ARM RealView clock trees.
*/ */
......
...@@ -36,6 +36,8 @@ static const char *realview_board_str(u32 id) ...@@ -36,6 +36,8 @@ static const char *realview_board_str(u32 id)
switch ((id >> 16) & 0xfff) { switch ((id >> 16) & 0xfff) {
case 0x0147: case 0x0147:
return "HBI-0147"; return "HBI-0147";
case 0x0159:
return "HBI-0159";
default: default:
return "Unknown"; return "Unknown";
} }
...@@ -44,6 +46,8 @@ static const char *realview_board_str(u32 id) ...@@ -44,6 +46,8 @@ static const char *realview_board_str(u32 id)
static const char *realview_arch_str(u32 id) static const char *realview_arch_str(u32 id)
{ {
switch ((id >> 8) & 0xf) { switch ((id >> 8) & 0xf) {
case 0x04:
return "AHB";
case 0x05: case 0x05:
return "Multi-layer AXI"; return "Multi-layer AXI";
default: default:
......
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