mirror of https://gitee.com/openkylin/linux.git
bus: mvebu-mbus: provide a mechanism to save SDRAM window configuration
On Marvell EBU platforms, when doing suspend/resume, the SDRAM window configuration must be saved on suspend, and restored on resume. However, it needs to be restored on resume *before* re-entering the kernel, because the SDRAM window configuration defines the layout of the memory. For this reason, it cannot simply be done in the ->suspend() and ->resume() hooks of the mvebu-mbus driver. Instead, it needs to be restored by the bootloader "boot info" mechanism used when resuming. This mechanism allows the kernel to define a list of (address, value) pairs when suspending, that the bootloader will restore on resume before jumping back into the kernel. This commit therefore adds a new function to the mvebu-mbus driver, called mvebu_mbus_save_cpu_target(), which will be called by the platform code to make the mvebu-mbus driver save the SDRAM window configuration in a way that can be understood by the bootloader "boot info" mechanism. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Link: https://lkml.kernel.org/r/1416585613-2113-8-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
This commit is contained in:
parent
a0e89c02da
commit
4749c02b8d
|
@ -110,6 +110,8 @@ struct mvebu_mbus_soc_data {
|
||||||
bool has_mbus_bridge;
|
bool has_mbus_bridge;
|
||||||
unsigned int (*win_cfg_offset)(const int win);
|
unsigned int (*win_cfg_offset)(const int win);
|
||||||
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
|
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,
|
int (*show_cpu_target)(struct mvebu_mbus_state *s,
|
||||||
struct seq_file *seq, void *v);
|
struct seq_file *seq, void *v);
|
||||||
};
|
};
|
||||||
|
@ -128,6 +130,7 @@ struct mvebu_mbus_state {
|
||||||
void __iomem *mbuswins_base;
|
void __iomem *mbuswins_base;
|
||||||
void __iomem *sdramwins_base;
|
void __iomem *sdramwins_base;
|
||||||
void __iomem *mbusbridge_base;
|
void __iomem *mbusbridge_base;
|
||||||
|
phys_addr_t sdramwins_phys_base;
|
||||||
struct dentry *debugfs_root;
|
struct dentry *debugfs_root;
|
||||||
struct dentry *debugfs_sdram;
|
struct dentry *debugfs_sdram;
|
||||||
struct dentry *debugfs_devs;
|
struct dentry *debugfs_devs;
|
||||||
|
@ -541,6 +544,28 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||||
mvebu_mbus_dram_info.num_cs = cs;
|
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
|
static void __init
|
||||||
mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||||
{
|
{
|
||||||
|
@ -571,11 +596,35 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||||
mvebu_mbus_dram_info.num_cs = cs;
|
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 = {
|
static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
|
||||||
.num_wins = 20,
|
.num_wins = 20,
|
||||||
.num_remappable_wins = 8,
|
.num_remappable_wins = 8,
|
||||||
.has_mbus_bridge = true,
|
.has_mbus_bridge = true,
|
||||||
.win_cfg_offset = armada_370_xp_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||||
};
|
};
|
||||||
|
@ -584,6 +633,7 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
|
||||||
.num_wins = 8,
|
.num_wins = 8,
|
||||||
.num_remappable_wins = 4,
|
.num_remappable_wins = 4,
|
||||||
.win_cfg_offset = orion_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||||
};
|
};
|
||||||
|
@ -592,6 +642,7 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
|
||||||
.num_wins = 8,
|
.num_wins = 8,
|
||||||
.num_remappable_wins = 4,
|
.num_remappable_wins = 4,
|
||||||
.win_cfg_offset = orion_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_dove_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_dove,
|
.show_cpu_target = mvebu_sdram_debug_show_dove,
|
||||||
};
|
};
|
||||||
|
@ -604,6 +655,7 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
|
||||||
.num_wins = 8,
|
.num_wins = 8,
|
||||||
.num_remappable_wins = 4,
|
.num_remappable_wins = 4,
|
||||||
.win_cfg_offset = orion_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||||
};
|
};
|
||||||
|
@ -612,6 +664,7 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
|
||||||
.num_wins = 8,
|
.num_wins = 8,
|
||||||
.num_remappable_wins = 2,
|
.num_remappable_wins = 2,
|
||||||
.win_cfg_offset = orion_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||||
};
|
};
|
||||||
|
@ -620,6 +673,7 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
|
||||||
.num_wins = 14,
|
.num_wins = 14,
|
||||||
.num_remappable_wins = 8,
|
.num_remappable_wins = 8,
|
||||||
.win_cfg_offset = mv78xx0_mbus_win_offset,
|
.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,
|
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||||
};
|
};
|
||||||
|
@ -804,6 +858,8 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbus->sdramwins_phys_base = sdramwins_phys_base;
|
||||||
|
|
||||||
if (mbusbridge_phys_base) {
|
if (mbusbridge_phys_base) {
|
||||||
mbus->mbusbridge_base = ioremap(mbusbridge_phys_base,
|
mbus->mbusbridge_base = ioremap(mbusbridge_phys_base,
|
||||||
mbusbridge_size);
|
mbusbridge_size);
|
||||||
|
|
|
@ -61,6 +61,7 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int mvebu_mbus_save_cpu_target(u32 *store_addr);
|
||||||
void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
|
void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
|
||||||
void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
|
void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
|
||||||
int mvebu_mbus_add_window_remap_by_id(unsigned int target,
|
int mvebu_mbus_add_window_remap_by_id(unsigned int target,
|
||||||
|
|
Loading…
Reference in New Issue