mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
75
arch/arm/mach-ux500/Kconfig
Normal file
75
arch/arm/mach-ux500/Kconfig
Normal file
|
@ -0,0 +1,75 @@
|
|||
menuconfig ARCH_U8500
|
||||
bool "ST-Ericsson U8500 Series" if ARCH_MULTI_V7
|
||||
depends on MMU
|
||||
select AB8500_CORE
|
||||
select ABX500_CORE
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_AMBA
|
||||
select ARM_ERRATA_754322
|
||||
select ARM_ERRATA_764369 if SMP
|
||||
select ARM_GIC
|
||||
select CACHE_L2X0
|
||||
select CLKSRC_NOMADIK_MTU
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select PINCTRL
|
||||
select PINCTRL_ABX500
|
||||
select PINCTRL_NOMADIK
|
||||
select PL310_ERRATA_753970 if CACHE_L2X0
|
||||
help
|
||||
Support for ST-Ericsson's Ux500 architecture
|
||||
|
||||
if ARCH_U8500
|
||||
|
||||
config UX500_SOC_DB8500
|
||||
bool
|
||||
select MFD_DB8500_PRCMU
|
||||
select PINCTRL_DB8500
|
||||
select PINCTRL_DB8540
|
||||
select PINCTRL_AB8500
|
||||
select PINCTRL_AB8505
|
||||
select PINCTRL_AB9540
|
||||
select PINCTRL_AB8540
|
||||
select REGULATOR
|
||||
select REGULATOR_DB8500_PRCMU
|
||||
|
||||
config MACH_MOP500
|
||||
bool "U8500 Development platform, MOP500 versions"
|
||||
select I2C
|
||||
select I2C_NOMADIK
|
||||
select REGULATOR
|
||||
select REGULATOR_FIXED_VOLTAGE
|
||||
select SOC_BUS
|
||||
select UX500_SOC_DB8500
|
||||
help
|
||||
Include support for the MOP500 development platform.
|
||||
|
||||
config MACH_HREFV60
|
||||
bool "U8500 Development platform, HREFv60 version"
|
||||
select MACH_MOP500
|
||||
help
|
||||
Include support for the HREFv60 new development platform.
|
||||
Includes HREFv70, v71 etc.
|
||||
|
||||
config MACH_SNOWBALL
|
||||
bool "U8500 Snowball platform"
|
||||
select MACH_MOP500
|
||||
help
|
||||
Include support for the snowball development platform.
|
||||
|
||||
config UX500_AUTO_PLATFORM
|
||||
def_bool y
|
||||
select MACH_MOP500
|
||||
help
|
||||
At least one platform needs to be selected in order to build
|
||||
a working kernel. If everything else is disabled, this
|
||||
automatically enables MACH_MOP500.
|
||||
|
||||
config UX500_DEBUG_UART
|
||||
int "Ux500 UART to use for low-level debug"
|
||||
default 2
|
||||
help
|
||||
Choose the UART on which kernel low-level debug messages should be
|
||||
output.
|
||||
|
||||
endif
|
13
arch/arm/mach-ux500/Makefile
Normal file
13
arch/arm/mach-ux500/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Makefile for the linux kernel, U8500 machine.
|
||||
#
|
||||
|
||||
obj-y := cpu.o id.o timer.o pm.o
|
||||
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
|
||||
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
|
||||
obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \
|
||||
board-mop500-audio.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
|
||||
CFLAGS_hotplug.o += -march=armv7-a
|
3
arch/arm/mach-ux500/Makefile.boot
Normal file
3
arch/arm/mach-ux500/Makefile.boot
Normal file
|
@ -0,0 +1,3 @@
|
|||
zreladdr-y += 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
77
arch/arm/mach-ux500/board-mop500-audio.c
Normal file
77
arch/arm/mach-ux500/board-mop500-audio.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_data/dma-ste-dma40.h>
|
||||
|
||||
#include <linux/platform_data/asoc-ux500-msp.h>
|
||||
|
||||
#include "ste-dma40-db8500.h"
|
||||
#include "board-mop500.h"
|
||||
|
||||
static struct stedma40_chan_cfg msp0_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp0_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp0_platform_data = {
|
||||
.id = 0,
|
||||
.msp_i2s_dma_rx = &msp0_dma_rx,
|
||||
.msp_i2s_dma_tx = &msp0_dma_tx,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp1_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV30_MSP3,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp1_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV30_MSP1,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp1_platform_data = {
|
||||
.id = 1,
|
||||
.msp_i2s_dma_rx = NULL,
|
||||
.msp_i2s_dma_tx = &msp1_dma_tx,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp2_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV14_MSP2,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp2_dma_tx = {
|
||||
.high_priority = true,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV14_MSP2,
|
||||
.use_fixed_channel = true,
|
||||
.phy_channel = 1,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp2_platform_data = {
|
||||
.id = 2,
|
||||
.msp_i2s_dma_rx = &msp2_dma_rx,
|
||||
.msp_i2s_dma_tx = &msp2_dma_tx,
|
||||
};
|
||||
|
||||
struct msp_i2s_platform_data msp3_platform_data = {
|
||||
.id = 3,
|
||||
.msp_i2s_dma_rx = &msp1_dma_rx,
|
||||
.msp_i2s_dma_tx = NULL,
|
||||
};
|
1065
arch/arm/mach-ux500/board-mop500-regulators.c
Normal file
1065
arch/arm/mach-ux500/board-mop500-regulators.c
Normal file
File diff suppressed because it is too large
Load diff
24
arch/arm/mach-ux500/board-mop500-regulators.h
Normal file
24
arch/arm/mach-ux500/board-mop500-regulators.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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
|
17
arch/arm/mach-ux500/board-mop500.h
Normal file
17
arch/arm/mach-ux500/board-mop500.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_MOP500_H
|
||||
#define __BOARD_MOP500_H
|
||||
|
||||
#include <linux/platform_data/asoc-ux500-msp.h>
|
||||
|
||||
extern struct msp_i2s_platform_data msp0_platform_data;
|
||||
extern struct msp_i2s_platform_data msp1_platform_data;
|
||||
extern struct msp_i2s_platform_data msp2_platform_data;
|
||||
extern struct msp_i2s_platform_data msp3_platform_data;
|
||||
|
||||
#endif
|
57
arch/arm/mach-ux500/cache-l2x0.c
Normal file
57
arch/arm/mach-ux500/cache-l2x0.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2011
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "id.h"
|
||||
|
||||
static int __init ux500_l2x0_unlock(void)
|
||||
{
|
||||
int i;
|
||||
void __iomem *l2x0_base = __io_address(U8500_L2CC_BASE);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
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);
|
212
arch/arm/mach-ux500/cpu-db8500.c
Normal file
212
arch/arm/mach-ux500/cpu-db8500.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 ST-Ericsson SA
|
||||
*
|
||||
* Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.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/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.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_platform.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <asm/pmu.h>
|
||||
#include <asm/mach/map.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 struct prcmu_pdata db8500_prcmu_pdata = {
|
||||
.ab_platdata = &ab8500_platdata,
|
||||
.version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
|
||||
.legacy_offset = DB8500_PRCMU_LEGACY_OFFSET,
|
||||
};
|
||||
|
||||
/* minimum static i/o mapping required to boot U8500 platforms */
|
||||
static struct map_desc u8500_uart_io_desc[] __initdata = {
|
||||
__IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
|
||||
};
|
||||
/* U8500 and U9540 common io_desc */
|
||||
static struct map_desc u8500_common_io_desc[] __initdata = {
|
||||
/* SCU base also covers GIC CPU BASE and TWD with its 4K page */
|
||||
__IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K),
|
||||
|
||||
__IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K),
|
||||
|
||||
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
|
||||
};
|
||||
|
||||
/* U8500 IO map specific description */
|
||||
static struct map_desc u8500_io_desc[] __initdata = {
|
||||
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
|
||||
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
|
||||
|
||||
};
|
||||
|
||||
/* U9540 IO map specific description */
|
||||
static struct map_desc u9540_io_desc[] __initdata = {
|
||||
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K),
|
||||
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K),
|
||||
};
|
||||
|
||||
static void __init u8500_map_io(void)
|
||||
{
|
||||
/*
|
||||
* Map the UARTs early so that the DEBUG_LL stuff continues to work.
|
||||
*/
|
||||
iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc));
|
||||
|
||||
ux500_map_io();
|
||||
|
||||
iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc));
|
||||
|
||||
if (cpu_is_ux540_family())
|
||||
iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc));
|
||||
else
|
||||
iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
|
||||
}
|
||||
|
||||
/*
|
||||
* The PMU IRQ lines of two cores are wired together into a single interrupt.
|
||||
* Bounce the interrupt to the other core if it's not ours.
|
||||
*/
|
||||
static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
|
||||
{
|
||||
irqreturn_t ret = handler(irq, dev);
|
||||
int other = !smp_processor_id();
|
||||
|
||||
if (ret == IRQ_NONE && cpu_online(other))
|
||||
irq_set_affinity(irq, cpumask_of(other));
|
||||
|
||||
/*
|
||||
* We should be able to get away with the amount of IRQ_NONEs we give,
|
||||
* while still having the spurious IRQ detection code kick in if the
|
||||
* interrupt really starts hitting spuriously.
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct arm_pmu_platdata db8500_pmu_platdata = {
|
||||
.handle_irq = db8500_pmu_handler,
|
||||
};
|
||||
|
||||
static const char *db8500_read_soc_id(void)
|
||||
{
|
||||
void __iomem *uid = __io_address(U8500_BB_UID_BASE);
|
||||
|
||||
/* Throw these device-specific numbers into the entropy pool */
|
||||
add_device_randomness(uid, 0x14);
|
||||
return 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));
|
||||
}
|
||||
|
||||
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),
|
||||
/* Requires DMA bindings. */
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
|
||||
"ux500-msp-i2s.0", &msp0_platform_data),
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
|
||||
"ux500-msp-i2s.1", &msp1_platform_data),
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
|
||||
"ux500-msp-i2s.2", &msp2_platform_data),
|
||||
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,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",
|
||||
NULL),
|
||||
{},
|
||||
};
|
||||
|
||||
static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
|
||||
&db8500_prcmu_pdata),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct of_device_id u8500_local_bus_nodes[] = {
|
||||
/* only create devices below soc node */
|
||||
{ .compatible = "stericsson,db8500", },
|
||||
{ .compatible = "stericsson,db8500-prcmu", },
|
||||
{ .compatible = "simple-bus"},
|
||||
{ },
|
||||
};
|
||||
|
||||
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);
|
||||
else
|
||||
of_platform_populate(NULL, u8500_local_bus_nodes,
|
||||
u8500_auxdata_lookup, parent);
|
||||
}
|
||||
|
||||
static const char * stericsson_dt_platform_compat[] = {
|
||||
"st-ericsson,u8500",
|
||||
"st-ericsson,u8540",
|
||||
"st-ericsson,u9500",
|
||||
"st-ericsson,u9540",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
|
||||
.smp = smp_ops(ux500_smp_ops),
|
||||
.map_io = u8500_map_io,
|
||||
.init_irq = ux500_init_irq,
|
||||
/* we re-use nomadik timer here */
|
||||
.init_time = ux500_timer_init,
|
||||
.init_machine = u8500_init_machine,
|
||||
.init_late = NULL,
|
||||
.dt_compat = stericsson_dt_platform_compat,
|
||||
.restart = ux500_restart,
|
||||
MACHINE_END
|
153
arch/arm/mach-ux500/cpu.c
Normal file
153
arch/arm/mach-ux500/cpu.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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/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 <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)
|
||||
{
|
||||
gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
|
||||
irqchip_init();
|
||||
|
||||
/*
|
||||
* Init clocks here so that they are available for system timer
|
||||
* initialization.
|
||||
*/
|
||||
if (cpu_is_u8500_family()) {
|
||||
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||
|
||||
u8500_of_clk_init(U8500_CLKRST1_BASE,
|
||||
U8500_CLKRST2_BASE,
|
||||
U8500_CLKRST3_BASE,
|
||||
U8500_CLKRST5_BASE,
|
||||
U8500_CLKRST6_BASE);
|
||||
} else if (cpu_is_u9540()) {
|
||||
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||
u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
|
||||
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
|
||||
U8500_CLKRST6_BASE);
|
||||
} else if (cpu_is_u8540()) {
|
||||
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
||||
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
||||
u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
|
||||
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
|
||||
U8500_CLKRST6_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
200
arch/arm/mach-ux500/db8500-regs.h
Normal file
200
arch/arm/mach-ux500/db8500-regs.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#ifndef __MACH_DB8500_REGS_H
|
||||
#define __MACH_DB8500_REGS_H
|
||||
|
||||
/* Base address and bank offsets for ESRAM */
|
||||
#define U8500_ESRAM_BASE 0x40000000
|
||||
#define U8500_ESRAM_BANK_SIZE 0x00020000
|
||||
#define U8500_ESRAM_BANK0 U8500_ESRAM_BASE
|
||||
#define U8500_ESRAM_BANK1 (U8500_ESRAM_BASE + U8500_ESRAM_BANK_SIZE)
|
||||
#define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE)
|
||||
#define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE)
|
||||
#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
|
||||
/*
|
||||
* on V1 DMA uses 4KB for logical parameters position is right after the 64KB
|
||||
* reserved for security
|
||||
*/
|
||||
#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000
|
||||
|
||||
#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET)
|
||||
|
||||
/* This address fulfills the 256k alignment requirement of the lcla base */
|
||||
#define U8500_DMA_LCLA_BASE U8500_ESRAM_BANK4
|
||||
|
||||
#define U8500_PER3_BASE 0x80000000
|
||||
#define U8500_STM_BASE 0x80100000
|
||||
#define U8500_STM_REG_BASE (U8500_STM_BASE + 0xF000)
|
||||
#define U8500_PER2_BASE 0x80110000
|
||||
#define U8500_PER1_BASE 0x80120000
|
||||
#define U8500_B2R2_BASE 0x80130000
|
||||
#define U8500_HSEM_BASE 0x80140000
|
||||
#define U8500_PER4_BASE 0x80150000
|
||||
#define U8500_TPIU_BASE 0x80190000
|
||||
#define U8500_ICN_BASE 0x81000000
|
||||
|
||||
#define U8500_BOOT_ROM_BASE 0x90000000
|
||||
/* ASIC ID is at 0xbf4 offset within this region */
|
||||
#define U8500_ASIC_ID_BASE 0x9001D000
|
||||
|
||||
#define U9540_BOOT_ROM_BASE 0xFFFE0000
|
||||
/* ASIC ID is at 0xbf4 offset within this region */
|
||||
#define U9540_ASIC_ID_BASE 0xFFFFD000
|
||||
|
||||
#define U8500_PER6_BASE 0xa03c0000
|
||||
#define U8500_PER7_BASE 0xa03d0000
|
||||
#define U8500_PER5_BASE 0xa03e0000
|
||||
|
||||
#define U8500_SVA_BASE 0xa0100000
|
||||
#define U8500_SIA_BASE 0xa0200000
|
||||
|
||||
#define U8500_SGA_BASE 0xa0300000
|
||||
#define U8500_MCDE_BASE 0xa0350000
|
||||
#define U8500_DMA_BASE 0x801C0000 /* v1 */
|
||||
|
||||
#define U8500_SBAG_BASE 0xa0390000
|
||||
|
||||
#define U8500_SCU_BASE 0xa0410000
|
||||
#define U8500_GIC_CPU_BASE 0xa0410100
|
||||
#define U8500_TWD_BASE 0xa0410600
|
||||
#define U8500_GIC_DIST_BASE 0xa0411000
|
||||
#define U8500_L2CC_BASE 0xa0412000
|
||||
|
||||
#define U8500_MODEM_I2C 0xb7e02000
|
||||
|
||||
#define U8500_GPIO0_BASE (U8500_PER1_BASE + 0xE000)
|
||||
#define U8500_GPIO1_BASE (U8500_PER3_BASE + 0xE000)
|
||||
#define U8500_GPIO2_BASE (U8500_PER2_BASE + 0xE000)
|
||||
#define U8500_GPIO3_BASE (U8500_PER5_BASE + 0x1E000)
|
||||
|
||||
#define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000)
|
||||
#define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000)
|
||||
|
||||
/* per6 base addresses */
|
||||
#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000)
|
||||
#define U8500_HASH0_BASE (U8500_PER6_BASE + 0x1000)
|
||||
#define U8500_HASH1_BASE (U8500_PER6_BASE + 0x2000)
|
||||
#define U8500_PKA_BASE (U8500_PER6_BASE + 0x4000)
|
||||
#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x5100)
|
||||
#define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */
|
||||
#define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */
|
||||
#define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */
|
||||
#define U8500_CRYP0_BASE (U8500_PER6_BASE + 0xa000)
|
||||
#define U8500_CRYP1_BASE (U8500_PER6_BASE + 0xb000)
|
||||
#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000)
|
||||
|
||||
/* per5 base addresses */
|
||||
#define U8500_USBOTG_BASE (U8500_PER5_BASE + 0x00000)
|
||||
#define U8500_CLKRST5_BASE (U8500_PER5_BASE + 0x1f000)
|
||||
|
||||
/* per4 base addresses */
|
||||
#define U8500_BACKUPRAM0_BASE (U8500_PER4_BASE + 0x00000)
|
||||
#define U8500_BACKUPRAM1_BASE (U8500_PER4_BASE + 0x01000)
|
||||
#define U8500_RTT0_BASE (U8500_PER4_BASE + 0x02000)
|
||||
#define U8500_RTT1_BASE (U8500_PER4_BASE + 0x03000)
|
||||
#define U8500_RTC_BASE (U8500_PER4_BASE + 0x04000)
|
||||
#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
|
||||
#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
|
||||
#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
|
||||
#define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000)
|
||||
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
|
||||
#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
|
||||
#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
|
||||
#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
|
||||
|
||||
/* per3 base addresses */
|
||||
#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
|
||||
#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000)
|
||||
#define U8500_SSP1_BASE (U8500_PER3_BASE + 0x3000)
|
||||
#define U8500_I2C0_BASE (U8500_PER3_BASE + 0x4000)
|
||||
#define U8500_SDI2_BASE (U8500_PER3_BASE + 0x5000)
|
||||
#define U8500_SKE_BASE (U8500_PER3_BASE + 0x6000)
|
||||
#define U8500_UART2_BASE (U8500_PER3_BASE + 0x7000)
|
||||
#define U8500_SDI5_BASE (U8500_PER3_BASE + 0x8000)
|
||||
#define U8500_CLKRST3_BASE (U8500_PER3_BASE + 0xf000)
|
||||
|
||||
/* per2 base addresses */
|
||||
#define U8500_I2C3_BASE (U8500_PER2_BASE + 0x0000)
|
||||
#define U8500_SPI2_BASE (U8500_PER2_BASE + 0x1000)
|
||||
#define U8500_SPI1_BASE (U8500_PER2_BASE + 0x2000)
|
||||
#define U8500_PWL_BASE (U8500_PER2_BASE + 0x3000)
|
||||
#define U8500_SDI4_BASE (U8500_PER2_BASE + 0x4000)
|
||||
#define U8500_MSP2_BASE (U8500_PER2_BASE + 0x7000)
|
||||
#define U8500_SDI1_BASE (U8500_PER2_BASE + 0x8000)
|
||||
#define U8500_SDI3_BASE (U8500_PER2_BASE + 0x9000)
|
||||
#define U8500_SPI0_BASE (U8500_PER2_BASE + 0xa000)
|
||||
#define U8500_HSIR_BASE (U8500_PER2_BASE + 0xb000)
|
||||
#define U8500_HSIT_BASE (U8500_PER2_BASE + 0xc000)
|
||||
#define U8500_CLKRST2_BASE (U8500_PER2_BASE + 0xf000)
|
||||
|
||||
/* per1 base addresses */
|
||||
#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000)
|
||||
#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000)
|
||||
#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000)
|
||||
#define U8500_MSP3_BASE (U8500_PER1_BASE + 0x5000)
|
||||
#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000)
|
||||
#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000)
|
||||
#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000)
|
||||
#define U8500_I2C4_BASE (U8500_PER1_BASE + 0xa000)
|
||||
#define U8500_SLIM0_BASE (U8500_PER1_BASE + 0xb000)
|
||||
#define U8500_CLKRST1_BASE (U8500_PER1_BASE + 0xf000)
|
||||
|
||||
#define U8500_SHRM_GOP_INTERRUPT_BASE 0xB7C00040
|
||||
|
||||
#define U8500_GPIOBANK0_BASE U8500_GPIO0_BASE
|
||||
#define U8500_GPIOBANK1_BASE (U8500_GPIO0_BASE + 0x80)
|
||||
#define U8500_GPIOBANK2_BASE U8500_GPIO1_BASE
|
||||
#define U8500_GPIOBANK3_BASE (U8500_GPIO1_BASE + 0x80)
|
||||
#define U8500_GPIOBANK4_BASE (U8500_GPIO1_BASE + 0x100)
|
||||
#define U8500_GPIOBANK5_BASE (U8500_GPIO1_BASE + 0x180)
|
||||
#define U8500_GPIOBANK6_BASE U8500_GPIO2_BASE
|
||||
#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80)
|
||||
#define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE
|
||||
|
||||
#define U8500_MCDE_SIZE 0x1000
|
||||
#define U8500_DSI_LINK_SIZE 0x1000
|
||||
#define U8500_DSI_LINK1_BASE (U8500_MCDE_BASE + U8500_MCDE_SIZE)
|
||||
#define U8500_DSI_LINK2_BASE (U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE)
|
||||
#define U8500_DSI_LINK3_BASE (U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE)
|
||||
#define U8500_DSI_LINK_COUNT 0x3
|
||||
|
||||
/* Modem and APE physical addresses */
|
||||
#define U8500_MODEM_BASE 0xe000000
|
||||
#define U8500_APE_BASE 0x6000000
|
||||
|
||||
/* SoC identification number information */
|
||||
#define U8500_BB_UID_BASE (U8500_BACKUPRAM1_BASE + 0xFC0)
|
||||
|
||||
/* Offsets to specific addresses in some IP blocks for DMA */
|
||||
#define MSP_TX_RX_REG_OFFSET 0
|
||||
#define CRYP1_RX_REG_OFFSET 0x10
|
||||
#define CRYP1_TX_REG_OFFSET 0x8
|
||||
#define HASH1_TX_REG_OFFSET 0x4
|
||||
|
||||
/*
|
||||
* Macros to get at IO space when running virtually
|
||||
* We dont map all the peripherals, let ioremap do
|
||||
* this for us. We map only very basic peripherals here.
|
||||
*/
|
||||
#define U8500_IO_VIRTUAL 0xf0000000
|
||||
#define U8500_IO_PHYSICAL 0xa0000000
|
||||
/* This is where we map in the ROM to check ASIC IDs */
|
||||
#define UX500_VIRT_ROM IOMEM(0xf0000000)
|
||||
|
||||
/* This macro is used in assembly, so no cast */
|
||||
#define IO_ADDRESS(x) \
|
||||
(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + U8500_IO_VIRTUAL)
|
||||
|
||||
/* typesafe io address */
|
||||
#define __io_address(n) IOMEM(IO_ADDRESS(n))
|
||||
|
||||
/* Used by some plat-nomadik code */
|
||||
#define io_p2v(n) __io_address(n)
|
||||
|
||||
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
|
||||
|
||||
#endif
|
37
arch/arm/mach-ux500/headsmp.S
Normal file
37
arch/arm/mach-ux500/headsmp.S
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2009 ST-Ericsson
|
||||
* This file is based ARM Realview platform
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
/*
|
||||
* U8500 specific entry point for secondary CPUs.
|
||||
*/
|
||||
ENTRY(u8500_secondary_startup)
|
||||
mrc p15, 0, r0, c0, c0, 5
|
||||
and r0, r0, #15
|
||||
adr r4, 1f
|
||||
ldmia r4, {r5, r6}
|
||||
sub r4, r4, r5
|
||||
add r6, r6, r4
|
||||
pen: ldr r7, [r6]
|
||||
cmp r7, r0
|
||||
bne pen
|
||||
|
||||
/*
|
||||
* we've been released from the holding pen: secondary_stack
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(u8500_secondary_startup)
|
||||
|
||||
.align 2
|
||||
1: .long .
|
||||
.long pen_release
|
37
arch/arm/mach-ux500/hotplug.c
Normal file
37
arch/arm/mach-ux500/hotplug.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (C) STMicroelectronics 2009
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* License Terms: GNU General Public License v2
|
||||
* Based on ARM realview platform
|
||||
*
|
||||
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
void __ref ux500_cpu_die(unsigned int cpu)
|
||||
{
|
||||
/* directly enter low power state, skipping secure registers */
|
||||
for (;;) {
|
||||
__asm__ __volatile__("dsb\n\t" "wfi\n\t"
|
||||
: : : "memory");
|
||||
if (pen_release == cpu_logical_map(cpu)) {
|
||||
/*
|
||||
* OK, proper wakeup, we're done
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
116
arch/arm/mach-ux500/id.c
Normal file
116
arch/arm/mach-ux500/id.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "id.h"
|
||||
|
||||
struct dbx500_asic_id dbx500_id;
|
||||
|
||||
static unsigned int __init ux500_read_asicid(phys_addr_t addr)
|
||||
{
|
||||
phys_addr_t base = addr & ~0xfff;
|
||||
struct map_desc desc = {
|
||||
.virtual = (unsigned long)UX500_VIRT_ROM,
|
||||
.pfn = __phys_to_pfn(base),
|
||||
.length = SZ_16K,
|
||||
.type = MT_DEVICE,
|
||||
};
|
||||
|
||||
iotable_init(&desc, 1);
|
||||
|
||||
/* As in devicemaps_init() */
|
||||
local_flush_tlb_all();
|
||||
flush_cache_all();
|
||||
|
||||
return readl(UX500_VIRT_ROM + (addr & 0xfff));
|
||||
}
|
||||
|
||||
static void ux500_print_soc_info(unsigned int asicid)
|
||||
{
|
||||
unsigned int rev = dbx500_revision();
|
||||
|
||||
pr_info("DB%4x ", dbx500_partnumber());
|
||||
|
||||
if (rev == 0x01)
|
||||
pr_cont("Early Drop");
|
||||
else if (rev >= 0xA0)
|
||||
pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf);
|
||||
else
|
||||
pr_cont("Unknown");
|
||||
|
||||
pr_cont(" [%#010x]\n", asicid);
|
||||
}
|
||||
|
||||
static unsigned int partnumber(unsigned int asicid)
|
||||
{
|
||||
return (asicid >> 8) & 0xffff;
|
||||
}
|
||||
|
||||
/*
|
||||
* SOC MIDR ASICID ADDRESS ASICID VALUE
|
||||
* DB8500ed 0x410fc090 0x9001FFF4 0x00850001
|
||||
* DB8500v1 0x411fc091 0x9001FFF4 0x008500A0
|
||||
* DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1
|
||||
* DB8500v2 0x412fc091 0x9001DBF4 0x008500B0
|
||||
* DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2
|
||||
* DB5500v1 0x412fc091 0x9001FFF4 0x005500A0
|
||||
* DB9540 0x413fc090 0xFFFFDBF4 0x009540xx
|
||||
*/
|
||||
|
||||
void __init ux500_map_io(void)
|
||||
{
|
||||
unsigned int cpuid = read_cpuid_id();
|
||||
unsigned int asicid = 0;
|
||||
phys_addr_t addr = 0;
|
||||
|
||||
switch (cpuid) {
|
||||
case 0x410fc090: /* DB8500ed */
|
||||
case 0x411fc091: /* DB8500v1 */
|
||||
addr = 0x9001FFF4;
|
||||
break;
|
||||
|
||||
case 0x412fc091: /* DB8520 / DB8500v2 / DB5500v1 */
|
||||
asicid = ux500_read_asicid(0x9001DBF4);
|
||||
if (partnumber(asicid) == 0x8500 ||
|
||||
partnumber(asicid) == 0x8520)
|
||||
/* DB8500v2 */
|
||||
break;
|
||||
|
||||
/* DB5500v1 */
|
||||
addr = 0x9001FFF4;
|
||||
break;
|
||||
|
||||
case 0x413fc090: /* DB9540 */
|
||||
addr = 0xFFFFDBF4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
asicid = ux500_read_asicid(addr);
|
||||
|
||||
if (!asicid) {
|
||||
pr_err("Unable to identify SoC\n");
|
||||
ux500_unknown_soc();
|
||||
}
|
||||
|
||||
dbx500_id.process = asicid >> 24;
|
||||
dbx500_id.partnumber = partnumber(asicid);
|
||||
dbx500_id.revision = asicid & 0xff;
|
||||
|
||||
ux500_print_soc_info(asicid);
|
||||
}
|
144
arch/arm/mach-ux500/id.h
Normal file
144
arch/arm/mach-ux500/id.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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
|
169
arch/arm/mach-ux500/platsmp.c
Normal file
169
arch/arm/mach-ux500/platsmp.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* Copyright (C) 2008 STMicroelctronics.
|
||||
* Copyright (C) 2009 ST-Ericsson.
|
||||
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
||||
*
|
||||
* This file is based on arm realview platform
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "id.h"
|
||||
|
||||
/* This is called from headsmp.S to wakeup the secondary core */
|
||||
extern void u8500_secondary_startup(void);
|
||||
|
||||
/*
|
||||
* Write pen_release in a way that is guaranteed to be visible to all
|
||||
* observers, irrespective of whether they're taking part in coherency
|
||||
* or not. This is necessary for the hotplug code to work reliably.
|
||||
*/
|
||||
static void write_pen_release(int val)
|
||||
{
|
||||
pen_release = val;
|
||||
smp_wmb();
|
||||
sync_cache_w(&pen_release);
|
||||
}
|
||||
|
||||
static void __iomem *scu_base_addr(void)
|
||||
{
|
||||
if (cpu_is_u8500_family() || cpu_is_ux540_family())
|
||||
return __io_address(U8500_SCU_BASE);
|
||||
else
|
||||
ux500_unknown_soc();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
static void ux500_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
write_pen_release(-1);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
/*
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
* the holding pen - release it, then wait for it to flag
|
||||
* that it has been released by resetting pen_release.
|
||||
*/
|
||||
write_pen_release(cpu_logical_map(cpu));
|
||||
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
|
||||
static void __init wakeup_secondary(void)
|
||||
{
|
||||
void __iomem *backupram;
|
||||
|
||||
if (cpu_is_u8500_family() || cpu_is_ux540_family())
|
||||
backupram = __io_address(U8500_BACKUPRAM0_BASE);
|
||||
else
|
||||
ux500_unknown_soc();
|
||||
|
||||
/*
|
||||
* write the address of secondary startup into the backup ram register
|
||||
* at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
|
||||
* backup ram register at offset 0x1FF0, which is what boot rom code
|
||||
* is waiting for. This would wake up the secondary core from WFE
|
||||
*/
|
||||
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
|
||||
__raw_writel(virt_to_phys(u8500_secondary_startup),
|
||||
backupram + UX500_CPU1_JUMPADDR_OFFSET);
|
||||
|
||||
#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
|
||||
__raw_writel(0xA1FEED01,
|
||||
backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
|
||||
|
||||
/* make sure write buffer is drained */
|
||||
mb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
static void __init ux500_smp_init_cpus(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
unsigned int i, ncores;
|
||||
|
||||
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores > nr_cpu_ids) {
|
||||
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
|
||||
ncores, nr_cpu_ids);
|
||||
ncores = nr_cpu_ids;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
|
||||
scu_enable(scu_base_addr());
|
||||
wakeup_secondary();
|
||||
}
|
||||
|
||||
struct smp_operations ux500_smp_ops __initdata = {
|
||||
.smp_init_cpus = ux500_smp_init_cpus,
|
||||
.smp_prepare_cpus = ux500_smp_prepare_cpus,
|
||||
.smp_secondary_init = ux500_secondary_init,
|
||||
.smp_boot_secondary = ux500_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = ux500_cpu_die,
|
||||
#endif
|
||||
};
|
194
arch/arm/mach-ux500/pm.c
Normal file
194
arch/arm/mach-ux500/pm.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010-2013
|
||||
* Author: Rickard Andersson <rickard.andersson@stericsson.com> for
|
||||
* ST-Ericsson.
|
||||
* Author: Daniel Lezcano <daniel.lezcano@linaro.org> for Linaro.
|
||||
* Author: Ulf Hansson <ulf.hansson@linaro.org> for Linaro.
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/platform_data/arm-ux500-pm.h>
|
||||
|
||||
#include "db8500-regs.h"
|
||||
|
||||
/* ARM WFI Standby signal register */
|
||||
#define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130)
|
||||
#define PRCM_ARM_WFI_STANDBY_WFI0 0x08
|
||||
#define PRCM_ARM_WFI_STANDBY_WFI1 0x10
|
||||
#define PRCM_IOCR (prcmu_base + 0x310)
|
||||
#define PRCM_IOCR_IOFORCE 0x1
|
||||
|
||||
/* Dual A9 core interrupt management unit registers */
|
||||
#define PRCM_A9_MASK_REQ (prcmu_base + 0x328)
|
||||
#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1
|
||||
|
||||
#define PRCM_A9_MASK_ACK (prcmu_base + 0x32c)
|
||||
#define PRCM_ARMITMSK31TO0 (prcmu_base + 0x11c)
|
||||
#define PRCM_ARMITMSK63TO32 (prcmu_base + 0x120)
|
||||
#define PRCM_ARMITMSK95TO64 (prcmu_base + 0x124)
|
||||
#define PRCM_ARMITMSK127TO96 (prcmu_base + 0x128)
|
||||
#define PRCM_POWER_STATE_VAL (prcmu_base + 0x25C)
|
||||
#define PRCM_ARMITVAL31TO0 (prcmu_base + 0x260)
|
||||
#define PRCM_ARMITVAL63TO32 (prcmu_base + 0x264)
|
||||
#define PRCM_ARMITVAL95TO64 (prcmu_base + 0x268)
|
||||
#define PRCM_ARMITVAL127TO96 (prcmu_base + 0x26C)
|
||||
|
||||
static void __iomem *prcmu_base;
|
||||
|
||||
/* This function decouple the gic from the prcmu */
|
||||
int prcmu_gic_decouple(void)
|
||||
{
|
||||
u32 val = readl(PRCM_A9_MASK_REQ);
|
||||
|
||||
/* Set bit 0 register value to 1 */
|
||||
writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ,
|
||||
PRCM_A9_MASK_REQ);
|
||||
|
||||
/* Make sure the register is updated */
|
||||
readl(PRCM_A9_MASK_REQ);
|
||||
|
||||
/* Wait a few cycles for the gic mask completion */
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function recouple the gic with the prcmu */
|
||||
int prcmu_gic_recouple(void)
|
||||
{
|
||||
u32 val = readl(PRCM_A9_MASK_REQ);
|
||||
|
||||
/* Set bit 0 register value to 0 */
|
||||
writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PRCMU_GIC_NUMBER_REGS 5
|
||||
|
||||
/*
|
||||
* This function checks if there are pending irq on the gic. It only
|
||||
* makes sense if the gic has been decoupled before with the
|
||||
* db8500_prcmu_gic_decouple function. Disabling an interrupt only
|
||||
* disables the forwarding of the interrupt to any CPU interface. It
|
||||
* does not prevent the interrupt from changing state, for example
|
||||
* becoming pending, or active and pending if it is already
|
||||
* active. Hence, we have to check the interrupt is pending *and* is
|
||||
* active.
|
||||
*/
|
||||
bool prcmu_gic_pending_irq(void)
|
||||
{
|
||||
u32 pr; /* Pending register */
|
||||
u32 er; /* Enable register */
|
||||
void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
|
||||
int i;
|
||||
|
||||
/* 5 registers. STI & PPI not skipped */
|
||||
for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
|
||||
|
||||
pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
|
||||
er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||
|
||||
if (pr & er)
|
||||
return true; /* There is a pending interrupt */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if there are pending interrupt on the
|
||||
* prcmu which has been delegated to monitor the irqs with the
|
||||
* db8500_prcmu_copy_gic_settings function.
|
||||
*/
|
||||
bool prcmu_pending_irq(void)
|
||||
{
|
||||
u32 it, im;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
|
||||
it = readl(PRCM_ARMITVAL31TO0 + i * 4);
|
||||
im = readl(PRCM_ARMITMSK31TO0 + i * 4);
|
||||
if (it & im)
|
||||
return true; /* There is a pending interrupt */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if the specified cpu is in in WFI. It's usage
|
||||
* makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple
|
||||
* function. Of course passing smp_processor_id() to this function will
|
||||
* always return false...
|
||||
*/
|
||||
bool prcmu_is_cpu_in_wfi(int cpu)
|
||||
{
|
||||
return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
|
||||
PRCM_ARM_WFI_STANDBY_WFI0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function copies the gic SPI settings to the prcmu in order to
|
||||
* monitor them and abort/finish the retention/off sequence or state.
|
||||
*/
|
||||
int prcmu_copy_gic_settings(void)
|
||||
{
|
||||
u32 er; /* Enable register */
|
||||
void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
|
||||
int i;
|
||||
|
||||
/* We skip the STI and PPI */
|
||||
for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
|
||||
er = readl_relaxed(dist_base +
|
||||
GIC_DIST_ENABLE_SET + (i + 1) * 4);
|
||||
writel(er, PRCM_ARMITMSK31TO0 + i * 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
static int ux500_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
cpu_do_idle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ux500_suspend_valid(suspend_state_t state)
|
||||
{
|
||||
return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops ux500_suspend_ops = {
|
||||
.enter = ux500_suspend_enter,
|
||||
.valid = ux500_suspend_valid,
|
||||
};
|
||||
#define UX500_SUSPEND_OPS (&ux500_suspend_ops)
|
||||
#else
|
||||
#define UX500_SUSPEND_OPS NULL
|
||||
#endif
|
||||
|
||||
void __init ux500_pm_init(u32 phy_base, u32 size)
|
||||
{
|
||||
prcmu_base = ioremap(phy_base, size);
|
||||
if (!prcmu_base) {
|
||||
pr_err("could not remap PRCMU for PM functions\n");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* On watchdog reboot the GIC is in some cases decoupled.
|
||||
* This will make sure that the GIC is correctly configured.
|
||||
*/
|
||||
prcmu_gic_recouple();
|
||||
|
||||
/* Set up ux500 suspend callbacks. */
|
||||
suspend_set_ops(UX500_SUSPEND_OPS);
|
||||
}
|
46
arch/arm/mach-ux500/setup.h
Normal file
46
arch/arm/mach-ux500/setup.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2009 ST-Ericsson.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* These symbols are needed for board-specific files to call their
|
||||
* own cpu-specific files
|
||||
*/
|
||||
#ifndef __ASM_ARCH_SETUP_H
|
||||
#define __ASM_ARCH_SETUP_H
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
|
||||
void ux500_restart(enum reboot_mode mode, const char *cmd);
|
||||
|
||||
void __init ux500_map_io(void);
|
||||
|
||||
extern void __init ux500_init_irq(void);
|
||||
|
||||
extern struct device *ux500_soc_device_init(const char *soc_id);
|
||||
|
||||
extern void ux500_timer_init(void);
|
||||
|
||||
#define __IO_DEV_DESC(x, sz) { \
|
||||
.virtual = IO_ADDRESS(x), \
|
||||
.pfn = __phys_to_pfn(x), \
|
||||
.length = sz, \
|
||||
.type = MT_DEVICE, \
|
||||
}
|
||||
|
||||
#define __MEM_DEV_DESC(x, sz) { \
|
||||
.virtual = IO_ADDRESS(x), \
|
||||
.pfn = __phys_to_pfn(x), \
|
||||
.length = sz, \
|
||||
.type = MT_MEMORY_RWX, \
|
||||
}
|
||||
|
||||
extern struct smp_operations ux500_smp_ops;
|
||||
extern void ux500_cpu_die(unsigned int cpu);
|
||||
|
||||
#endif /* __ASM_ARCH_SETUP_H */
|
85
arch/arm/mach-ux500/ste-dma40-db8500.h
Normal file
85
arch/arm/mach-ux500/ste-dma40-db8500.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* arch/arm/mach-ux500/ste_dma40_db8500.h
|
||||
* DB8500-SoC-specific configuration for DMA40
|
||||
*
|
||||
* Copyright (C) ST-Ericsson 2007-2010
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
* Author: Per Friden <per.friden@stericsson.com>
|
||||
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
|
||||
*/
|
||||
#ifndef STE_DMA40_DB8500_H
|
||||
#define STE_DMA40_DB8500_H
|
||||
|
||||
#define DB8500_DMA_NR_DEV 64
|
||||
|
||||
/*
|
||||
* Unless otherwise specified, all channels numbers are used for
|
||||
* TX & RX, and can be used for either source or destination
|
||||
* channels.
|
||||
*/
|
||||
enum dma_dev_type {
|
||||
DB8500_DMA_DEV0_SPI0 = 0,
|
||||
DB8500_DMA_DEV1_SD_MMC0 = 1,
|
||||
DB8500_DMA_DEV2_SD_MMC1 = 2,
|
||||
DB8500_DMA_DEV3_SD_MMC2 = 3,
|
||||
DB8500_DMA_DEV4_I2C1 = 4,
|
||||
DB8500_DMA_DEV5_I2C3 = 5,
|
||||
DB8500_DMA_DEV6_I2C2 = 6,
|
||||
DB8500_DMA_DEV7_I2C4 = 7, /* Only on V1 and later */
|
||||
DB8500_DMA_DEV8_SSP0 = 8,
|
||||
DB8500_DMA_DEV9_SSP1 = 9,
|
||||
DB8500_DMA_DEV10_MCDE_RX = 10, /* RX only */
|
||||
DB8500_DMA_DEV11_UART2 = 11,
|
||||
DB8500_DMA_DEV12_UART1 = 12,
|
||||
DB8500_DMA_DEV13_UART0 = 13,
|
||||
DB8500_DMA_DEV14_MSP2 = 14,
|
||||
DB8500_DMA_DEV15_I2C0 = 15,
|
||||
DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15 = 16,
|
||||
DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14 = 17,
|
||||
DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13 = 18,
|
||||
DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12 = 19,
|
||||
DB8500_DMA_DEV20_SLIM0_CH0_HSI_CH0 = 20,
|
||||
DB8500_DMA_DEV21_SLIM0_CH1_HSI_CH1 = 21,
|
||||
DB8500_DMA_DEV22_SLIM0_CH2_HSI_CH2 = 22,
|
||||
DB8500_DMA_DEV23_SLIM0_CH3_HSI_CH3 = 23,
|
||||
DB8500_DMA_DEV24_SXA0 = 24,
|
||||
DB8500_DMA_DEV25_SXA1 = 25,
|
||||
DB8500_DMA_DEV26_SXA2 = 26,
|
||||
DB8500_DMA_DEV27_SXA3 = 27,
|
||||
DB8500_DMA_DEV28_SD_MM2 = 28,
|
||||
DB8500_DMA_DEV29_SD_MM0 = 29,
|
||||
DB8500_DMA_DEV30_MSP1 = 30,
|
||||
/* On DB8500v2, MSP3 RX replaces MSP1 RX */
|
||||
DB8500_DMA_DEV30_MSP3 = 30,
|
||||
DB8500_DMA_DEV31_MSP0_SLIM0_CH0 = 31,
|
||||
DB8500_DMA_DEV32_SD_MM1 = 32,
|
||||
DB8500_DMA_DEV33_SPI2 = 33,
|
||||
DB8500_DMA_DEV34_I2C3_RX2_TX2 = 34,
|
||||
DB8500_DMA_DEV35_SPI1 = 35,
|
||||
DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11 = 36,
|
||||
DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10 = 37,
|
||||
DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9 = 38,
|
||||
DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8 = 39,
|
||||
DB8500_DMA_DEV40_SPI3 = 40,
|
||||
DB8500_DMA_DEV41_SD_MM3 = 41,
|
||||
DB8500_DMA_DEV42_SD_MM4 = 42,
|
||||
DB8500_DMA_DEV43_SD_MM5 = 43,
|
||||
DB8500_DMA_DEV44_SXA4 = 44,
|
||||
DB8500_DMA_DEV45_SXA5 = 45,
|
||||
DB8500_DMA_DEV46_SLIM0_CH8_SRC_SXA6 = 46,
|
||||
DB8500_DMA_DEV47_SLIM0_CH9_SRC_SXA7 = 47,
|
||||
DB8500_DMA_DEV48_CAC1 = 48,
|
||||
DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49, /* TX only */
|
||||
DB8500_DMA_DEV50_HAC1_TX = 50, /* TX only */
|
||||
DB8500_DMA_MEMCPY_TX_0 = 51, /* TX only */
|
||||
DB8500_DMA_DEV52_SLIM0_CH4_HSI_CH4 = 52,
|
||||
DB8500_DMA_DEV53_SLIM0_CH5_HSI_CH5 = 53,
|
||||
DB8500_DMA_DEV54_SLIM0_CH6_HSI_CH6 = 54,
|
||||
DB8500_DMA_DEV55_SLIM0_CH7_HSI_CH7 = 55,
|
||||
/* 56 -> 60 are channels reserved for memcpy only */
|
||||
DB8500_DMA_DEV61_CAC0 = 61,
|
||||
DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62, /* TX only */
|
||||
DB8500_DMA_DEV63_HAC0_TX = 63, /* TX only */
|
||||
};
|
||||
|
||||
#endif
|
48
arch/arm/mach-ux500/timer.c
Normal file
48
arch/arm/mach-ux500/timer.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2011
|
||||
*
|
||||
* License Terms: GNU General Public License v2
|
||||
* Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
|
||||
*/
|
||||
#include <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clksrc-dbx500-prcmu.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "id.h"
|
||||
|
||||
static const struct of_device_id prcmu_timer_of_match[] __initconst = {
|
||||
{ .compatible = "stericsson,db8500-prcmu-timer-4", },
|
||||
{ },
|
||||
};
|
||||
|
||||
void __init ux500_timer_init(void)
|
||||
{
|
||||
void __iomem *prcmu_timer_base;
|
||||
void __iomem *tmp_base;
|
||||
struct device_node *np;
|
||||
|
||||
if (cpu_is_u8500_family() || cpu_is_ux540_family())
|
||||
prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
|
||||
else
|
||||
ux500_unknown_soc();
|
||||
|
||||
np = of_find_matching_node(NULL, prcmu_timer_of_match);
|
||||
if (!np)
|
||||
goto dt_fail;
|
||||
|
||||
tmp_base = of_iomap(np, 0);
|
||||
if (!tmp_base)
|
||||
goto dt_fail;
|
||||
|
||||
prcmu_timer_base = tmp_base;
|
||||
|
||||
dt_fail:
|
||||
clksrc_dbx500_prcmu_init(prcmu_timer_base);
|
||||
clocksource_of_init();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue