mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-05 00:41:23 +00:00
a727eaf64f
SoC-near driver changes that we're merging through our tree. Mostly because they depend on other changes we have staged, but in some cases because the driver maintainers preferred that we did it this way. This contains a largeish cleanup series of the omap_l3_noc bus driver, cpuidle rework for Exynos, some reset driver conversions and a long branch of TI EDMA fixes and cleanups, with more to come next release. The TI EDMA cleanups is a shared branch with the dmaengine tree, with a handful of Davinci-specific fixes on top. After discussion at last year's KS (and some more on the mailing lists), we are here adding a drivers/soc directory. The purpose of this is to keep per-vendor shared code that's needed by different drivers but that doesn't fit into the MFD (nor drivers/platform) model. We expect to keep merging contents for this hierarchy through arm-soc so we can keep an eye on what the vendors keep adding here and not making it a free-for-all to shove in crazy stuff. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJTjOFiAAoJEIwa5zzehBx30RYP/0UE+R8ccdsodunmIDrmQ7QP qFWe1YTWlyXtGBDaPCNfdcU09UYatPKuCv5dJ2ToQCyyFI26PIIhFtnCNXmMuYz+ XPCuqAlJ9hZWx7+j2hXRlyhoZMAaJ5EVVxaK5tnVYXDIfy1Y3xG7i069HD/qGrQp xrV+XofFmpU2VAds6S+SpecFFfYD7n/pJ1bTSgzPfaUsEUyV882dJ3skgs1VpTzQ PnL/0Z2t4ePoP3+6p+F7EnJxemLF5IXrlL0c7hODxQKuMqlzoUluywh6SwOHfCQL u2cc5SFUbbKhExwlGOVibdQMiC0HUOXyRvyYFOIdbv+xNH+Zc/tcoQQ22PWm4Yy1 08qOm3Fr6yw5nH5IT+1wCIFCzJEC/ZHM5B2t+RISFybAMk6Bg1TDYJLmd570zkEL aTLtS5hdmy4h8Ad5FBtwKNyL//6FJJxhbHUu/m0qaE0phq94+78B2M6vbx6757xC kCFlpJsHoN0Tn5c9Q1hpTqI/BHxb4UR7Nf+b8Ox8Veuc9JrS35lzi/rWnGxB5WB0 +1KCA8eih9KXTtksxAte1TmSbMciqW559RUR7dNAPXAMPksY2mJV1I+rg0cRsY3i F90Lnc6LWUM5PYpc4VwiC0sUCLKzTFnpZUELqMOiws3PUblbb0StXuoNo6owbtsK mp1Juxi1n7VhoN9AFVpL =SC+e -----END PGP SIGNATURE----- Merge tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc into next Pull ARM SoC driver changes from Olof Johansson: "SoC-near driver changes that we're merging through our tree. Mostly because they depend on other changes we have staged, but in some cases because the driver maintainers preferred that we did it this way. This contains a largeish cleanup series of the omap_l3_noc bus driver, cpuidle rework for Exynos, some reset driver conversions and a long branch of TI EDMA fixes and cleanups, with more to come next release. The TI EDMA cleanups is a shared branch with the dmaengine tree, with a handful of Davinci-specific fixes on top. After discussion at last year's KS (and some more on the mailing lists), we are here adding a drivers/soc directory. The purpose of this is to keep per-vendor shared code that's needed by different drivers but that doesn't fit into the MFD (nor drivers/platform) model. We expect to keep merging contents for this hierarchy through arm-soc so we can keep an eye on what the vendors keep adding here and not making it a free-for-all to shove in crazy stuff" * tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (101 commits) cpufreq: exynos: Fix driver compilation with ARCH_MULTIPLATFORM tty: serial: msm: Remove direct access to GSBI power: reset: keystone-reset: introduce keystone reset driver Documentation: dt: add bindings for keystone pll control controller Documentation: dt: add bindings for keystone reset driver soc: qcom: fix of_device_id table ARM: EXYNOS: Fix kernel panic when unplugging CPU1 on exynos ARM: EXYNOS: Move the driver to drivers/cpuidle directory ARM: EXYNOS: Cleanup all unneeded headers from cpuidle.c ARM: EXYNOS: Pass the AFTR callback to the platform_data ARM: EXYNOS: Move S5P_CHECK_SLEEP into pm.c ARM: EXYNOS: Move the power sequence call in the cpu_pm notifier ARM: EXYNOS: Move the AFTR state function into pm.c ARM: EXYNOS: Encapsulate the AFTR code into a function ARM: EXYNOS: Disable cpuidle for exynos5440 ARM: EXYNOS: Encapsulate boot vector code into a function for cpuidle ARM: EXYNOS: Pass wakeup mask parameter to function for cpuidle ARM: EXYNOS: Remove ifdef for scu_enable in pm ARM: EXYNOS: Move scu_enable in the cpu_pm notifier ARM: EXYNOS: Use the cpu_pm notifier for pm ...
345 lines
8.1 KiB
C
345 lines
8.1 KiB
C
/*
|
|
* SAMSUNG EXYNOS Flattened Device Tree enabled machine
|
|
*
|
|
* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/serial_s3c.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_domain.h>
|
|
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/hardware/cache-l2x0.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/mach/map.h>
|
|
#include <asm/memory.h>
|
|
|
|
#include "common.h"
|
|
#include "mfc.h"
|
|
#include "regs-pmu.h"
|
|
|
|
#define L2_AUX_VAL 0x7C470001
|
|
#define L2_AUX_MASK 0xC200ffff
|
|
|
|
static struct map_desc exynos4_iodesc[] __initdata = {
|
|
{
|
|
.virtual = (unsigned long)S3C_VA_SYS,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S3C_VA_TIMER,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
|
|
.length = SZ_16K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S3C_VA_WATCHDOG,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_SROMC,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_SYSTIMER,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_PMU,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_GIC_CPU,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_GIC_DIST,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_CMU,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
|
|
.length = SZ_128K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_COREPERI_BASE,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
|
|
.length = SZ_8K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_L2CC,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_DMC0,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_DMC1,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S3C_VA_USB_HSPHY,
|
|
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
},
|
|
};
|
|
|
|
static struct map_desc exynos5_iodesc[] __initdata = {
|
|
{
|
|
.virtual = (unsigned long)S3C_VA_SYS,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S3C_VA_TIMER,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
|
|
.length = SZ_16K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S3C_VA_WATCHDOG,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_SROMC,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_CMU,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
|
|
.length = 144 * SZ_1K,
|
|
.type = MT_DEVICE,
|
|
}, {
|
|
.virtual = (unsigned long)S5P_VA_PMU,
|
|
.pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
|
|
.length = SZ_64K,
|
|
.type = MT_DEVICE,
|
|
},
|
|
};
|
|
|
|
void exynos_restart(enum reboot_mode mode, const char *cmd)
|
|
{
|
|
struct device_node *np;
|
|
u32 val = 0x1;
|
|
void __iomem *addr = EXYNOS_SWRESET;
|
|
|
|
if (of_machine_is_compatible("samsung,exynos5440")) {
|
|
u32 status;
|
|
np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
|
|
|
|
addr = of_iomap(np, 0) + 0xbc;
|
|
status = __raw_readl(addr);
|
|
|
|
addr = of_iomap(np, 0) + 0xcc;
|
|
val = __raw_readl(addr);
|
|
|
|
val = (val & 0xffff0000) | (status & 0xffff);
|
|
}
|
|
|
|
__raw_writel(val, addr);
|
|
}
|
|
|
|
static struct platform_device exynos_cpuidle = {
|
|
.name = "exynos_cpuidle",
|
|
.dev.platform_data = exynos_enter_aftr,
|
|
.id = -1,
|
|
};
|
|
|
|
void __init exynos_cpuidle_init(void)
|
|
{
|
|
if (soc_is_exynos5440())
|
|
return;
|
|
|
|
platform_device_register(&exynos_cpuidle);
|
|
}
|
|
|
|
void __init exynos_cpufreq_init(void)
|
|
{
|
|
platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
|
|
}
|
|
|
|
void __init exynos_init_late(void)
|
|
{
|
|
if (of_machine_is_compatible("samsung,exynos5440"))
|
|
/* to be supported later */
|
|
return;
|
|
|
|
pm_genpd_poweroff_unused();
|
|
exynos_pm_init();
|
|
}
|
|
|
|
static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
|
|
int depth, void *data)
|
|
{
|
|
struct map_desc iodesc;
|
|
__be32 *reg;
|
|
unsigned long len;
|
|
|
|
if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
|
|
!of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
|
|
return 0;
|
|
|
|
reg = of_get_flat_dt_prop(node, "reg", &len);
|
|
if (reg == NULL || len != (sizeof(unsigned long) * 2))
|
|
return 0;
|
|
|
|
iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
|
|
iodesc.length = be32_to_cpu(reg[1]) - 1;
|
|
iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
|
|
iodesc.type = MT_DEVICE;
|
|
iotable_init(&iodesc, 1);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* exynos_map_io
|
|
*
|
|
* register the standard cpu IO areas
|
|
*/
|
|
static void __init exynos_map_io(void)
|
|
{
|
|
if (soc_is_exynos4())
|
|
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
|
|
|
|
if (soc_is_exynos5())
|
|
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
|
|
}
|
|
|
|
void __init exynos_init_io(void)
|
|
{
|
|
debug_ll_io_init();
|
|
|
|
of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
|
|
|
|
/* detect cpu id and rev. */
|
|
s5p_init_cpu(S5P_VA_CHIPID);
|
|
|
|
exynos_map_io();
|
|
}
|
|
|
|
static int __init exynos4_l2x0_cache_init(void)
|
|
{
|
|
int ret;
|
|
|
|
if (!soc_is_exynos4())
|
|
return 0;
|
|
|
|
ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (IS_ENABLED(CONFIG_S5P_SLEEP)) {
|
|
l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
|
|
clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
|
|
}
|
|
return 0;
|
|
}
|
|
early_initcall(exynos4_l2x0_cache_init);
|
|
|
|
static void __init exynos_dt_machine_init(void)
|
|
{
|
|
struct device_node *i2c_np;
|
|
const char *i2c_compat = "samsung,s3c2440-i2c";
|
|
unsigned int tmp;
|
|
int id;
|
|
|
|
/*
|
|
* Exynos5's legacy i2c controller and new high speed i2c
|
|
* controller have muxed interrupt sources. By default the
|
|
* interrupts for 4-channel HS-I2C controller are enabled.
|
|
* If node for first four channels of legacy i2c controller
|
|
* are available then re-configure the interrupts via the
|
|
* system register.
|
|
*/
|
|
if (soc_is_exynos5()) {
|
|
for_each_compatible_node(i2c_np, NULL, i2c_compat) {
|
|
if (of_device_is_available(i2c_np)) {
|
|
id = of_alias_get_id(i2c_np, "i2c");
|
|
if (id < 4) {
|
|
tmp = readl(EXYNOS5_SYS_I2C_CFG);
|
|
writel(tmp & ~(0x1 << id),
|
|
EXYNOS5_SYS_I2C_CFG);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
exynos_cpuidle_init();
|
|
exynos_cpufreq_init();
|
|
|
|
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
|
}
|
|
|
|
static char const *exynos_dt_compat[] __initconst = {
|
|
"samsung,exynos3",
|
|
"samsung,exynos3250",
|
|
"samsung,exynos4",
|
|
"samsung,exynos4210",
|
|
"samsung,exynos4212",
|
|
"samsung,exynos4412",
|
|
"samsung,exynos5",
|
|
"samsung,exynos5250",
|
|
"samsung,exynos5260",
|
|
"samsung,exynos5420",
|
|
"samsung,exynos5440",
|
|
NULL
|
|
};
|
|
|
|
static void __init exynos_reserve(void)
|
|
{
|
|
#ifdef CONFIG_S5P_DEV_MFC
|
|
int i;
|
|
char *mfc_mem[] = {
|
|
"samsung,mfc-v5",
|
|
"samsung,mfc-v6",
|
|
"samsung,mfc-v7",
|
|
};
|
|
|
|
for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
|
|
if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
|
|
/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
|
|
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
|
|
.smp = smp_ops(exynos_smp_ops),
|
|
.map_io = exynos_init_io,
|
|
.init_early = exynos_firmware_init,
|
|
.init_machine = exynos_dt_machine_init,
|
|
.init_late = exynos_init_late,
|
|
.dt_compat = exynos_dt_compat,
|
|
.restart = exynos_restart,
|
|
.reserve = exynos_reserve,
|
|
MACHINE_END
|