The board and infrastructure changes for RealView
multiplatform and extended DT support. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWb9LqAAoJEEEQszewGV1z1I4QAIgylTG1hftD5xCtaKsgJv5X pcp+eVVCeYjeO3AbknrXzBlty0u3/rDOR6n9aUn7ci63qErGi2GeoZ5glo6y3aOU qKo2/M0LOoP3y6SGxMjaPTTpStjKsaj2XLjHLNrSHAKXsvoFB69vnAlQh2jU+ohX JEl9wvkugMWicGaiooWQfG7OAf2Gb6AFAKQUfYNVNNXBTD13oQcFRgLwBKDkNlc9 7N6yzPQDNQiauytr7Ji/49fbkiOLFSB5yllhecb37F/b56XprGvsXJTRwsQhPwbj ig28qu/g7LhfnkZUOTwhWH6WdyFarMlpA8oHHKrZBeGySgvdjXBVYH4IQAfhT2N9 WSh/he+w8T2+oMVj97gLSxKiP4ugUSsBR6daq5X8NESobxFVYzmFIYQxKxOwFif4 JDWvOKaQsRhx42iAq3CIMkh7yQsBC4tJjtyvVwHuGeC2zRlyODbBCnN4OGKDdYpJ +VY4kr48Yld5IxYm6J6fXOEWTcFw2n/hvEVsik5mmgw1rYivJsCcvcVxv04xZYCl 6d13eCaSh2TfeKYs/Qf2yy3hmps4dWFcd18/xWRyFdnkCs5qGRbtgLiAQtUnQAGm bpaI/rYeRnnF80af2dhpZT2i0zBL9uuur7FYZDB9xsQDOkqnCYxKvSW1CfNg5Gtc senI3dczeTC3NtwRp4eC =Zhx3 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
22ba14f41c
16 changed files with 285 additions and 134 deletions
|
@ -190,6 +190,7 @@ nodes to be present and contain the properties described below.
|
|||
"allwinner,sun6i-a31"
|
||||
"allwinner,sun8i-a23"
|
||||
"arm,psci"
|
||||
"arm,realview-smp"
|
||||
"brcm,brahma-b15"
|
||||
"marvell,armada-375-smp"
|
||||
"marvell,armada-380-smp"
|
||||
|
|
|
@ -241,7 +241,6 @@ config ARM_PATCH_PHYS_VIRT
|
|||
bool "Patch physical to virtual translations at runtime" if EMBEDDED
|
||||
default y
|
||||
depends on !XIP_KERNEL && MMU
|
||||
depends on !ARCH_REALVIEW || !SPARSEMEM
|
||||
help
|
||||
Patch phys-to-virt and virt-to-phys translation functions at
|
||||
boot and module load time according to the position of the
|
||||
|
@ -356,7 +355,6 @@ config ARCH_REALVIEW
|
|||
select GENERIC_CLOCKEVENTS
|
||||
select GPIO_PL061 if GPIOLIB
|
||||
select ICST
|
||||
select NEED_MACH_MEMORY_H
|
||||
select PLAT_VERSATILE
|
||||
select PLAT_VERSATILE_SCHED_CLOCK
|
||||
help
|
||||
|
|
|
@ -4,10 +4,14 @@ menu "RealView platform type"
|
|||
config REALVIEW_DT
|
||||
bool "Support RealView(R) Device Tree based boot"
|
||||
select ARM_GIC
|
||||
select CLK_SP810
|
||||
select HAVE_SMP
|
||||
select ICST
|
||||
select MFD_SYSCON
|
||||
select POWER_RESET
|
||||
select POWER_RESET_VERSATILE
|
||||
select POWER_SUPPLY
|
||||
select SMP_ON_UP
|
||||
select SOC_REALVIEW
|
||||
select USE_OF
|
||||
help
|
||||
|
@ -36,7 +40,6 @@ config REALVIEW_EB_A9MP
|
|||
config REALVIEW_EB_ARM11MP
|
||||
bool "Support ARM11MPCore Tile"
|
||||
depends on MACH_REALVIEW_EB
|
||||
select ARCH_HAS_BARRIERS if SMP
|
||||
select CPU_V6K
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
|
@ -57,7 +60,6 @@ config REALVIEW_EB_ARM11MP_REVB
|
|||
|
||||
config MACH_REALVIEW_PB11MP
|
||||
bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
|
||||
select ARCH_HAS_BARRIERS if SMP
|
||||
select ARM_GIC
|
||||
select CPU_V6K
|
||||
select HAVE_ARM_SCU if SMP
|
||||
|
@ -102,14 +104,13 @@ config MACH_REALVIEW_PBA8
|
|||
|
||||
config MACH_REALVIEW_PBX
|
||||
bool "Support RealView(R) Platform Baseboard Explore"
|
||||
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
|
||||
select ARM_GIC
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select HAVE_PATA_PLATFORM
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
select ZONE_DMA if SPARSEMEM
|
||||
select ZONE_DMA
|
||||
help
|
||||
Include support for the ARM(R) RealView(R) Platform Baseboard
|
||||
Explore.
|
||||
|
@ -124,6 +125,6 @@ config REALVIEW_HIGH_PHYS_OFFSET
|
|||
the board supports 512MB of RAM, this option allows the
|
||||
memory to be accessed contiguously at the high physical
|
||||
offset. On the PBX board, disabling this option allows 1GB of
|
||||
RAM to be used with SPARSEMEM.
|
||||
RAM to be used with HIGHMEM.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
|
||||
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_PB11MP) += realview_pb11mp.o
|
||||
obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/*
|
||||
* 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()
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* 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
|
91
arch/arm/mach-realview/platsmp-dt.c
Normal file
91
arch/arm/mach-realview/platsmp-dt.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 @@
|
|||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/system_info.h>
|
||||
#include <asm/outercache.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -450,6 +451,12 @@ static void __init realview_eb_init(void)
|
|||
* Bits: .... ...0 0111 1001 0000 .... .... ....
|
||||
*/
|
||||
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
|
||||
pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu";
|
||||
platform_device_register(&pmu_device);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/outercache.h>
|
||||
|
||||
#include <mach/board-pb11mp.h>
|
||||
#include <mach/irqs.h>
|
||||
|
@ -345,6 +346,11 @@ static void __init realview_pb11mp_init(void)
|
|||
* Bits: .... ...0 0111 1001 0000 .... .... ....
|
||||
*/
|
||||
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
|
||||
|
||||
realview_flash_register(realview_pb11mp_flash_resource,
|
||||
|
|
|
@ -77,14 +77,6 @@ static struct map_desc realview_pba8_io_desc[] __initdata = {
|
|||
.length = SZ_4K,
|
||||
.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
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_PBA8_UART0_BASE),
|
||||
|
|
|
@ -79,14 +79,6 @@ static struct map_desc realview_pbx_io_desc[] __initdata = {
|
|||
.length = SZ_4K,
|
||||
.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
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_PBX_UART0_BASE),
|
||||
|
|
|
@ -1005,8 +1005,6 @@ config ARM_L1_CACHE_SHIFT
|
|||
|
||||
config ARM_DMA_MEM_BUFFERABLE
|
||||
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
|
||||
help
|
||||
Historically, the kernel has used strongly ordered mappings to
|
||||
|
|
|
@ -3,6 +3,7 @@ config COMMON_CLK_VERSATILE
|
|||
depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
|
||||
ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \
|
||||
COMPILE_TEST
|
||||
select REGMAP_MMIO
|
||||
---help---
|
||||
Supports clocking on ARM Reference designs:
|
||||
- Integrator/AP and Integrator/CP
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* We wrap the custom interface from <asm/hardware/icst.h> into the generic
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -19,9 +19,14 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.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
|
||||
* @hw: corresponding clock hardware entry
|
||||
|
@ -32,8 +37,9 @@
|
|||
*/
|
||||
struct clk_icst {
|
||||
struct clk_hw hw;
|
||||
void __iomem *vcoreg;
|
||||
void __iomem *lockreg;
|
||||
struct regmap *map;
|
||||
u32 vcoreg_off;
|
||||
u32 lockreg_off;
|
||||
struct icst_params *params;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
@ -41,53 +47,67 @@ struct clk_icst {
|
|||
#define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
|
||||
|
||||
/**
|
||||
* vco_get() - get ICST VCO settings from a certain register
|
||||
* @vcoreg: register containing the VCO settings
|
||||
* vco_get() - get ICST VCO settings from a certain ICST
|
||||
* @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;
|
||||
struct icst_vco vco;
|
||||
int ret;
|
||||
|
||||
val = readl(vcoreg);
|
||||
vco.v = val & 0x1ff;
|
||||
vco.r = (val >> 9) & 0x7f;
|
||||
vco.s = (val >> 16) & 03;
|
||||
return vco;
|
||||
ret = regmap_read(icst->map, icst->vcoreg_off, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
vco->v = val & 0x1ff;
|
||||
vco->r = (val >> 9) & 0x7f;
|
||||
vco->s = (val >> 16) & 03;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vco_set() - commit changes to an ICST VCO
|
||||
* @locreg: register to poke to unlock the VCO for writing
|
||||
* @vcoreg: register containing the VCO settings
|
||||
* @vco: ICST VCO parameters to commit
|
||||
* @icst: the ICST clock to set
|
||||
* @vco: the VCO struct to set the changes from
|
||||
*/
|
||||
static void vco_set(void __iomem *lockreg,
|
||||
void __iomem *vcoreg,
|
||||
struct icst_vco vco)
|
||||
static int vco_set(struct clk_icst *icst, struct icst_vco vco)
|
||||
{
|
||||
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);
|
||||
|
||||
/* This magic unlocks the VCO so it can be controlled */
|
||||
writel(0xa05f, lockreg);
|
||||
writel(val, vcoreg);
|
||||
ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = regmap_write(icst->map, icst->vcoreg_off, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* 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,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_icst *icst = to_icst(hw);
|
||||
struct icst_vco vco;
|
||||
int ret;
|
||||
|
||||
if (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);
|
||||
return icst->rate;
|
||||
}
|
||||
|
@ -112,8 +132,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
icst->params->ref = parent_rate;
|
||||
vco = icst_hz_to_vco(icst->params, rate);
|
||||
icst->rate = icst_hz(icst->params, vco);
|
||||
vco_set(icst->lockreg, icst->vcoreg, vco);
|
||||
return 0;
|
||||
return vco_set(icst, vco);
|
||||
}
|
||||
|
||||
static const struct clk_ops icst_ops = {
|
||||
|
@ -122,11 +141,11 @@ static const struct clk_ops icst_ops = {
|
|||
.set_rate = icst_set_rate,
|
||||
};
|
||||
|
||||
struct clk *icst_clk_register(struct device *dev,
|
||||
const struct clk_icst_desc *desc,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *base)
|
||||
static struct clk *icst_clk_setup(struct device *dev,
|
||||
const struct clk_icst_desc *desc,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
struct regmap *map)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_icst *icst;
|
||||
|
@ -151,10 +170,11 @@ struct clk *icst_clk_register(struct device *dev,
|
|||
init.flags = CLK_IS_ROOT;
|
||||
init.parent_names = (parent_name ? &parent_name : NULL);
|
||||
init.num_parents = (parent_name ? 1 : 0);
|
||||
icst->map = map;
|
||||
icst->hw.init = &init;
|
||||
icst->params = pclone;
|
||||
icst->vcoreg = base + desc->vco_offset;
|
||||
icst->lockreg = base + desc->lock_offset;
|
||||
icst->vcoreg_off = desc->vco_offset;
|
||||
icst->lockreg_off = desc->lock_offset;
|
||||
|
||||
clk = clk_register(dev, &icst->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
|
@ -164,4 +184,112 @@ struct clk *icst_clk_register(struct device *dev,
|
|||
|
||||
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);
|
||||
|
||||
#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 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.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.
|
||||
*/
|
||||
|
|
|
@ -36,6 +36,8 @@ static const char *realview_board_str(u32 id)
|
|||
switch ((id >> 16) & 0xfff) {
|
||||
case 0x0147:
|
||||
return "HBI-0147";
|
||||
case 0x0159:
|
||||
return "HBI-0159";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -44,6 +46,8 @@ static const char *realview_board_str(u32 id)
|
|||
static const char *realview_arch_str(u32 id)
|
||||
{
|
||||
switch ((id >> 8) & 0xf) {
|
||||
case 0x04:
|
||||
return "AHB";
|
||||
case 0x05:
|
||||
return "Multi-layer AXI";
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue