mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
mvebu SoC suspend changes for v3.19
- Armada 370/XP suspend/resume support
- mvebu SoC driver suspend/resume support
- irqchip
- clocksource
- mbus
- clk
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQIcBAABAgAGBQJUe0lIAAoJEP45WPkGe8Zn/IgP/jOO8c7t7dohRbAe3axzIcaC
DLL7d7j0AScZGXLx1/xJrFFY/P3gn3dlLR7HnT0t4K7vcW0kP4orMGo6FcGicSOZ
VzQf88cOkunKf9NTM1Y0LOXVWTHGuACiXAnxook5A6k+l0xQ1t+uewgEKrg/33VK
6WQ6woe2eYFwghkFwL3ybjttOPM5nxPef6v3TZ3LfwSUBsnSm70F1XiO8xZJH+LM
fL83P409LGWgohwSaXYRdPJcNM0U7QMNo6i/If9NNBhIkdKb6llhQ/DvI+aXUvqB
aD9/4t+Q75yki0mXIin6irltjspWsR8OFbaKZOM5IBFp/XrsKvNU+wy++7z9se9z
qfG1QYmKk3ddI0isoksuIJpfbrlbQqFKCGlNkn8HVi4xCYCijNgb5bUrHQ27Aa4U
GGisAOhqs9Ktpz96WeNKjvNQBSJZ3ESd6tlLrwCei8DwEdT0Z73jr1aEnulurpPG
A3kiUhVpRIU+w0cth5Kix2bZj7JGsykzu1x5xORLE+MN8RSgmoveGyY5CBp2MHrl
NxR/u98SD9I/rWT3DwQIKxM5ZqF4AAnyj4SaSWR/f40kWMU+A+eMEfo8VUeO88fl
ygeeHTghSf58gbdgganRfDyY8OaQHeYNNKbWK6c7vxyMX98vwHOtOb5JS3nn0p7q
Fugy/6qf+ZqYHT4nczJO
=uX+e
-----END PGP SIGNATURE-----
Merge tag 'mvebu-soc-suspend-3.19' of git://git.infradead.org/linux-mvebu into next/soc
Pull "mvebu SoC suspend changes for v3.19" from Jason Cooper:
- Armada 370/XP suspend/resume support
- mvebu SoC driver suspend/resume support
- irqchip
- clocksource
- mbus
- clk
* tag 'mvebu-soc-suspend-3.19' of git://git.infradead.org/linux-mvebu:
ARM: mvebu: add SDRAM controller description for Armada XP
ARM: mvebu: adjust mbus controller description on Armada 370/XP
ARM: mvebu: add suspend/resume DT information for Armada XP GP
ARM: mvebu: synchronize secondary CPU clocks on resume
ARM: mvebu: make sure MMU is disabled in armada_370_xp_cpu_resume
ARM: mvebu: Armada XP GP specific suspend/resume code
ARM: mvebu: reserve the first 10 KB of each memory bank for suspend/resume
ARM: mvebu: implement suspend/resume support for Armada XP
clk: mvebu: add suspend/resume for gatable clocks
bus: mvebu-mbus: provide a mechanism to save SDRAM window configuration
bus: mvebu-mbus: suspend/resume support
clocksource: time-armada-370-xp: add suspend/resume support
irqchip: armada-370-xp: Add suspend/resume support
Documentation: dt-bindings: minimal documentation for MVEBU SDRAM controller
Signed-off-by: Arnd Bergmann <[email protected]>
This commit is contained in:
commit
ab64920c37
18 changed files with 777 additions and 32 deletions
|
|
@ -57,6 +57,7 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
/*
|
||||
* DDR target is the same on all platforms.
|
||||
|
|
@ -94,20 +95,42 @@
|
|||
|
||||
#define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
|
||||
|
||||
/* Relative to mbusbridge_base */
|
||||
#define MBUS_BRIDGE_CTRL_OFF 0x0
|
||||
#define MBUS_BRIDGE_BASE_OFF 0x4
|
||||
|
||||
/* Maximum number of windows, for all known platforms */
|
||||
#define MBUS_WINS_MAX 20
|
||||
|
||||
struct mvebu_mbus_state;
|
||||
|
||||
struct mvebu_mbus_soc_data {
|
||||
unsigned int num_wins;
|
||||
unsigned int num_remappable_wins;
|
||||
bool has_mbus_bridge;
|
||||
unsigned int (*win_cfg_offset)(const int win);
|
||||
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
|
||||
int (*save_cpu_target)(struct mvebu_mbus_state *s,
|
||||
u32 *store_addr);
|
||||
int (*show_cpu_target)(struct mvebu_mbus_state *s,
|
||||
struct seq_file *seq, void *v);
|
||||
};
|
||||
|
||||
/*
|
||||
* Used to store the state of one MBus window accross suspend/resume.
|
||||
*/
|
||||
struct mvebu_mbus_win_data {
|
||||
u32 ctrl;
|
||||
u32 base;
|
||||
u32 remap_lo;
|
||||
u32 remap_hi;
|
||||
};
|
||||
|
||||
struct mvebu_mbus_state {
|
||||
void __iomem *mbuswins_base;
|
||||
void __iomem *sdramwins_base;
|
||||
void __iomem *mbusbridge_base;
|
||||
phys_addr_t sdramwins_phys_base;
|
||||
struct dentry *debugfs_root;
|
||||
struct dentry *debugfs_sdram;
|
||||
struct dentry *debugfs_devs;
|
||||
|
|
@ -115,6 +138,11 @@ struct mvebu_mbus_state {
|
|||
struct resource pcie_io_aperture;
|
||||
const struct mvebu_mbus_soc_data *soc;
|
||||
int hw_io_coherency;
|
||||
|
||||
/* Used during suspend/resume */
|
||||
u32 mbus_bridge_ctrl;
|
||||
u32 mbus_bridge_base;
|
||||
struct mvebu_mbus_win_data wins[MBUS_WINS_MAX];
|
||||
};
|
||||
|
||||
static struct mvebu_mbus_state mbus_state;
|
||||
|
|
@ -516,6 +544,28 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
|||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
||||
static int
|
||||
mvebu_mbus_default_save_cpu_target(struct mvebu_mbus_state *mbus,
|
||||
u32 *store_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
writel(mbus->sdramwins_phys_base + DDR_BASE_CS_OFF(i),
|
||||
store_addr++);
|
||||
writel(base, store_addr++);
|
||||
writel(mbus->sdramwins_phys_base + DDR_SIZE_CS_OFF(i),
|
||||
store_addr++);
|
||||
writel(size, store_addr++);
|
||||
}
|
||||
|
||||
/* We've written 16 words to the store address */
|
||||
return 16;
|
||||
}
|
||||
|
||||
static void __init
|
||||
mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
|
|
@ -546,10 +596,35 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
|||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
||||
static int
|
||||
mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus,
|
||||
u32 *store_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
|
||||
|
||||
writel(mbus->sdramwins_phys_base + DOVE_DDR_BASE_CS_OFF(i),
|
||||
store_addr++);
|
||||
writel(map, store_addr++);
|
||||
}
|
||||
|
||||
/* We've written 4 words to the store address */
|
||||
return 4;
|
||||
}
|
||||
|
||||
int mvebu_mbus_save_cpu_target(u32 *store_addr)
|
||||
{
|
||||
return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
|
||||
}
|
||||
|
||||
static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
|
||||
.num_wins = 20,
|
||||
.num_remappable_wins = 8,
|
||||
.has_mbus_bridge = true,
|
||||
.win_cfg_offset = armada_370_xp_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
};
|
||||
|
|
@ -558,6 +633,7 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
|
|||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
};
|
||||
|
|
@ -566,6 +642,7 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
|
|||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_dove_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_dove_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_dove,
|
||||
};
|
||||
|
|
@ -578,6 +655,7 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
|
|||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
};
|
||||
|
|
@ -586,6 +664,7 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
|
|||
.num_wins = 8,
|
||||
.num_remappable_wins = 2,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
};
|
||||
|
|
@ -594,6 +673,7 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
|
|||
.num_wins = 14,
|
||||
.num_remappable_wins = 8,
|
||||
.win_cfg_offset = mv78xx0_mbus_win_offset,
|
||||
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
};
|
||||
|
|
@ -698,11 +778,73 @@ static __init int mvebu_mbus_debugfs_init(void)
|
|||
}
|
||||
fs_initcall(mvebu_mbus_debugfs_init);
|
||||
|
||||
static int mvebu_mbus_suspend(void)
|
||||
{
|
||||
struct mvebu_mbus_state *s = &mbus_state;
|
||||
int win;
|
||||
|
||||
if (!s->mbusbridge_base)
|
||||
return -ENODEV;
|
||||
|
||||
for (win = 0; win < s->soc->num_wins; win++) {
|
||||
void __iomem *addr = s->mbuswins_base +
|
||||
s->soc->win_cfg_offset(win);
|
||||
|
||||
s->wins[win].base = readl(addr + WIN_BASE_OFF);
|
||||
s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF);
|
||||
|
||||
if (win >= s->soc->num_remappable_wins)
|
||||
continue;
|
||||
|
||||
s->wins[win].remap_lo = readl(addr + WIN_REMAP_LO_OFF);
|
||||
s->wins[win].remap_hi = readl(addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
|
||||
s->mbus_bridge_ctrl = readl(s->mbusbridge_base +
|
||||
MBUS_BRIDGE_CTRL_OFF);
|
||||
s->mbus_bridge_base = readl(s->mbusbridge_base +
|
||||
MBUS_BRIDGE_BASE_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mvebu_mbus_resume(void)
|
||||
{
|
||||
struct mvebu_mbus_state *s = &mbus_state;
|
||||
int win;
|
||||
|
||||
writel(s->mbus_bridge_ctrl,
|
||||
s->mbusbridge_base + MBUS_BRIDGE_CTRL_OFF);
|
||||
writel(s->mbus_bridge_base,
|
||||
s->mbusbridge_base + MBUS_BRIDGE_BASE_OFF);
|
||||
|
||||
for (win = 0; win < s->soc->num_wins; win++) {
|
||||
void __iomem *addr = s->mbuswins_base +
|
||||
s->soc->win_cfg_offset(win);
|
||||
|
||||
writel(s->wins[win].base, addr + WIN_BASE_OFF);
|
||||
writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF);
|
||||
|
||||
if (win >= s->soc->num_remappable_wins)
|
||||
continue;
|
||||
|
||||
writel(s->wins[win].remap_lo, addr + WIN_REMAP_LO_OFF);
|
||||
writel(s->wins[win].remap_hi, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
struct syscore_ops mvebu_mbus_syscore_ops = {
|
||||
.suspend = mvebu_mbus_suspend,
|
||||
.resume = mvebu_mbus_resume,
|
||||
};
|
||||
|
||||
static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t mbuswins_phys_base,
|
||||
size_t mbuswins_size,
|
||||
phys_addr_t sdramwins_phys_base,
|
||||
size_t sdramwins_size)
|
||||
size_t sdramwins_size,
|
||||
phys_addr_t mbusbridge_phys_base,
|
||||
size_t mbusbridge_size)
|
||||
{
|
||||
int win;
|
||||
|
||||
|
|
@ -716,11 +858,26 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mbus->sdramwins_phys_base = sdramwins_phys_base;
|
||||
|
||||
if (mbusbridge_phys_base) {
|
||||
mbus->mbusbridge_base = ioremap(mbusbridge_phys_base,
|
||||
mbusbridge_size);
|
||||
if (!mbus->mbusbridge_base) {
|
||||
iounmap(mbus->sdramwins_base);
|
||||
iounmap(mbus->mbuswins_base);
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else
|
||||
mbus->mbusbridge_base = NULL;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++)
|
||||
mvebu_mbus_disable_window(mbus, win);
|
||||
|
||||
mbus->soc->setup_cpu_target(mbus);
|
||||
|
||||
register_syscore_ops(&mvebu_mbus_syscore_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -746,7 +903,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
|
|||
mbuswins_phys_base,
|
||||
mbuswins_size,
|
||||
sdramwins_phys_base,
|
||||
sdramwins_size);
|
||||
sdramwins_size, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
@ -887,7 +1044,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
|
|||
|
||||
int __init mvebu_mbus_dt_init(bool is_coherent)
|
||||
{
|
||||
struct resource mbuswins_res, sdramwins_res;
|
||||
struct resource mbuswins_res, sdramwins_res, mbusbridge_res;
|
||||
struct device_node *np, *controller;
|
||||
const struct of_device_id *of_id;
|
||||
const __be32 *prop;
|
||||
|
|
@ -923,6 +1080,19 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the resource to 0 so that it can be left unmapped by
|
||||
* mvebu_mbus_common_init() if the DT doesn't carry the
|
||||
* necessary information. This is needed to preserve backward
|
||||
* compatibility.
|
||||
*/
|
||||
memset(&mbusbridge_res, 0, sizeof(mbusbridge_res));
|
||||
|
||||
if (mbus_state.soc->has_mbus_bridge) {
|
||||
if (of_address_to_resource(controller, 2, &mbusbridge_res))
|
||||
pr_warn(FW_WARN "deprecated mbus-mvebu Device Tree, suspend/resume will not work\n");
|
||||
}
|
||||
|
||||
mbus_state.hw_io_coherency = is_coherent;
|
||||
|
||||
/* Get optional pcie-{mem,io}-aperture properties */
|
||||
|
|
@ -933,7 +1103,9 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
|
|||
mbuswins_res.start,
|
||||
resource_size(&mbuswins_res),
|
||||
sdramwins_res.start,
|
||||
resource_size(&sdramwins_res));
|
||||
resource_size(&sdramwins_res),
|
||||
mbusbridge_res.start,
|
||||
resource_size(&mbusbridge_res));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue