
Pull ARM SoC cleanups from Arnd Bergmann: "A large number of cleanups, all over the platforms. This is dominated largely by the Samsung platforms (s3c, s5p, exynos) and a few of the others moving code out of arch/arm into more appropriate subsystems. The clocksource and irqchip drivers are now abstracted to the point where platforms that are already cleaned up do not need to even specify the driver they use, it can all get configured from the device tree as we do for normal device drivers. The clocksource changes basically touch every single platform in the process. We further clean up the use of platform specific header files here, with the goal of turning more of the platforms over to being "multiplatform" enabled, which implies that they cannot expose their headers to architecture independent code any more. It is expected that no functional changes are part of the cleanup. The overall reduction in total code lines is mostly the result of removing broken and obsolete code." * tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (133 commits) ARM: mvebu: correct gated clock documentation ARM: kirkwood: add missing include for nsa310 ARM: exynos: move exynos4210-combiner to drivers/irqchip mfd: db8500-prcmu: update resource passing drivers/db8500-cpufreq: delete dangling include ARM: at91: remove NEOCORE 926 board sunxi: Cleanup the reset code and add meaningful registers defines ARM: S3C24XX: header mach/regs-mem.h local ARM: S3C24XX: header mach/regs-power.h local ARM: S3C24XX: header mach/regs-s3c2412-mem.h local ARM: S3C24XX: Remove plat-s3c24xx directory in arch/arm/ ARM: S3C24XX: transform s3c2443 subirqs into new structure ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs ARM: S3C24XX: move s3c2443 irq code to irq.c ARM: S3C24XX: transform s3c2416 irqs into new structure ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs ARM: S3C24XX: move s3c2416 irq init to common irq code ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property ARM: S3C24XX: Move irq syscore-ops to irq-pm clocksource: always define CLOCKSOURCE_OF_DECLARE ...
154 lines
3.8 KiB
C
154 lines
3.8 KiB
C
/*
|
|
* 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/db8500-prcmu.h>
|
|
#include <linux/clksrc-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/irq.h>
|
|
#include <linux/irqchip.h>
|
|
#include <linux/irqchip/arm-gic.h>
|
|
#include <linux/platform_data/clk-ux500.h>
|
|
|
|
#include <asm/mach/map.h>
|
|
|
|
#include <mach/hardware.h>
|
|
#include <mach/setup.h>
|
|
#include <mach/devices.h>
|
|
|
|
#include "board-mop500.h"
|
|
#include "id.h"
|
|
|
|
void __iomem *_PRCMU_BASE;
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
void __iomem *dist_base;
|
|
void __iomem *cpu_base;
|
|
|
|
gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
|
|
|
|
if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
|
|
dist_base = __io_address(U8500_GIC_DIST_BASE);
|
|
cpu_base = __io_address(U8500_GIC_CPU_BASE);
|
|
} else
|
|
ux500_unknown_soc();
|
|
|
|
#ifdef CONFIG_OF
|
|
if (of_have_populated_dt())
|
|
irqchip_init();
|
|
else
|
|
#endif
|
|
gic_init(0, 29, dist_base, cpu_base);
|
|
|
|
/*
|
|
* Init clocks here so that they are available for system timer
|
|
* initialization.
|
|
*/
|
|
if (cpu_is_u8500_family() || cpu_is_u9540())
|
|
db8500_prcmu_early_init();
|
|
|
|
if (cpu_is_u8500_family() || cpu_is_u9540())
|
|
u8500_clk_init();
|
|
else if (cpu_is_u8540())
|
|
u8540_clk_init();
|
|
}
|
|
|
|
void __init ux500_init_late(void)
|
|
{
|
|
mop500_uib_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();
|
|
}
|
|
|
|
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_OR_NULL(soc_dev)) {
|
|
kfree(soc_dev_attr);
|
|
return NULL;
|
|
}
|
|
|
|
parent = soc_device_to_device(soc_dev);
|
|
if (!IS_ERR_OR_NULL(parent))
|
|
device_create_file(parent, &ux500_soc_attr);
|
|
|
|
return parent;
|
|
}
|