Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/renesas into fixes
By Guennadi Liakhovetski (2) and others via Rafael J. Wysocki: "[...] urgent fixes for Renesas ARM-based platforms. Four of these commits are fixes of regressions new in 3.4-rc and the last one is necessary for SMP to work on those systems in general." * 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/renesas: ARM / mach-shmobile: Invalidate caches when booting secondary cores ARM / mach-shmobile: sh73a0 SMP TWD boot regression fix ARM / mach-shmobile: r8a7779 SMP TWD boot regression fix ARM: mach-shmobile: convert ag5evm to use the generic MMC GPIO hotplug helper ARM: mach-shmobile: convert mackerel to use the generic MMC GPIO hotplug helper
This commit is contained in:
commit
d2919c651e
9 changed files with 81 additions and 53 deletions
arch/arm/mach-shmobile
|
@ -365,23 +365,13 @@ static struct platform_device mipidsi0_device = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SDHI0 */
|
/* SDHI0 */
|
||||||
static irqreturn_t ag5evm_sdhi0_gpio_cd(int irq, void *arg)
|
|
||||||
{
|
|
||||||
struct device *dev = arg;
|
|
||||||
struct sh_mobile_sdhi_info *info = dev->platform_data;
|
|
||||||
struct tmio_mmc_data *pdata = info->pdata;
|
|
||||||
|
|
||||||
tmio_mmc_cd_wakeup(pdata);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct sh_mobile_sdhi_info sdhi0_info = {
|
static struct sh_mobile_sdhi_info sdhi0_info = {
|
||||||
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
||||||
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
||||||
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
|
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
|
||||||
.tmio_caps = MMC_CAP_SD_HIGHSPEED,
|
.tmio_caps = MMC_CAP_SD_HIGHSPEED,
|
||||||
.tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
|
.tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
|
||||||
|
.cd_gpio = GPIO_PORT251,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource sdhi0_resources[] = {
|
static struct resource sdhi0_resources[] = {
|
||||||
|
@ -557,7 +547,6 @@ static void __init ag5evm_init(void)
|
||||||
lcd_backlight_reset();
|
lcd_backlight_reset();
|
||||||
|
|
||||||
/* enable SDHI0 on CN15 [SD I/F] */
|
/* enable SDHI0 on CN15 [SD I/F] */
|
||||||
gpio_request(GPIO_FN_SDHICD0, NULL);
|
|
||||||
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
||||||
gpio_request(GPIO_FN_SDHICMD0, NULL);
|
gpio_request(GPIO_FN_SDHICMD0, NULL);
|
||||||
gpio_request(GPIO_FN_SDHICLK0, NULL);
|
gpio_request(GPIO_FN_SDHICLK0, NULL);
|
||||||
|
@ -566,13 +555,6 @@ static void __init ag5evm_init(void)
|
||||||
gpio_request(GPIO_FN_SDHID0_1, NULL);
|
gpio_request(GPIO_FN_SDHID0_1, NULL);
|
||||||
gpio_request(GPIO_FN_SDHID0_0, NULL);
|
gpio_request(GPIO_FN_SDHID0_0, NULL);
|
||||||
|
|
||||||
if (!request_irq(intcs_evt2irq(0x3c0), ag5evm_sdhi0_gpio_cd,
|
|
||||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
|
|
||||||
"sdhi0 cd", &sdhi0_device.dev))
|
|
||||||
sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
|
|
||||||
else
|
|
||||||
pr_warn("Unable to setup SDHI0 GPIO IRQ\n");
|
|
||||||
|
|
||||||
/* enable SDHI1 on CN4 [WLAN I/F] */
|
/* enable SDHI1 on CN4 [WLAN I/F] */
|
||||||
gpio_request(GPIO_FN_SDHICLK1, NULL);
|
gpio_request(GPIO_FN_SDHICLK1, NULL);
|
||||||
gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
|
gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
|
||||||
|
|
|
@ -1011,21 +1011,12 @@ static int slot_cn7_get_cd(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SDHI0 */
|
/* SDHI0 */
|
||||||
static irqreturn_t mackerel_sdhi0_gpio_cd(int irq, void *arg)
|
|
||||||
{
|
|
||||||
struct device *dev = arg;
|
|
||||||
struct sh_mobile_sdhi_info *info = dev->platform_data;
|
|
||||||
struct tmio_mmc_data *pdata = info->pdata;
|
|
||||||
|
|
||||||
tmio_mmc_cd_wakeup(pdata);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct sh_mobile_sdhi_info sdhi0_info = {
|
static struct sh_mobile_sdhi_info sdhi0_info = {
|
||||||
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
||||||
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
||||||
|
.tmio_flags = TMIO_MMC_USE_GPIO_CD,
|
||||||
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
|
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
|
||||||
|
.cd_gpio = GPIO_PORT172,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource sdhi0_resources[] = {
|
static struct resource sdhi0_resources[] = {
|
||||||
|
@ -1384,7 +1375,6 @@ static void __init mackerel_init(void)
|
||||||
{
|
{
|
||||||
u32 srcr4;
|
u32 srcr4;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* External clock source */
|
/* External clock source */
|
||||||
clk_set_rate(&sh7372_dv_clki_clk, 27000000);
|
clk_set_rate(&sh7372_dv_clki_clk, 27000000);
|
||||||
|
@ -1481,7 +1471,6 @@ static void __init mackerel_init(void)
|
||||||
irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
|
irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
|
||||||
|
|
||||||
/* enable SDHI0 */
|
/* enable SDHI0 */
|
||||||
gpio_request(GPIO_FN_SDHICD0, NULL);
|
|
||||||
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
||||||
gpio_request(GPIO_FN_SDHICMD0, NULL);
|
gpio_request(GPIO_FN_SDHICMD0, NULL);
|
||||||
gpio_request(GPIO_FN_SDHICLK0, NULL);
|
gpio_request(GPIO_FN_SDHICLK0, NULL);
|
||||||
|
@ -1490,13 +1479,6 @@ static void __init mackerel_init(void)
|
||||||
gpio_request(GPIO_FN_SDHID0_1, NULL);
|
gpio_request(GPIO_FN_SDHID0_1, NULL);
|
||||||
gpio_request(GPIO_FN_SDHID0_0, NULL);
|
gpio_request(GPIO_FN_SDHID0_0, NULL);
|
||||||
|
|
||||||
ret = request_irq(evt2irq(0x3340), mackerel_sdhi0_gpio_cd,
|
|
||||||
IRQF_TRIGGER_FALLING, "sdhi0 cd", &sdhi0_device.dev);
|
|
||||||
if (!ret)
|
|
||||||
sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
|
|
||||||
else
|
|
||||||
pr_err("Cannot get IRQ #%d: %d\n", evt2irq(0x3340), ret);
|
|
||||||
|
|
||||||
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
|
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
|
||||||
/* enable SDHI1 */
|
/* enable SDHI1 */
|
||||||
gpio_request(GPIO_FN_SDHICMD1, NULL);
|
gpio_request(GPIO_FN_SDHICMD1, NULL);
|
||||||
|
|
|
@ -16,6 +16,59 @@
|
||||||
|
|
||||||
__CPUINIT
|
__CPUINIT
|
||||||
|
|
||||||
|
/* Cache invalidation nicked from arch/arm/mach-imx/head-v7.S, thanks!
|
||||||
|
*
|
||||||
|
* The secondary kernel init calls v7_flush_dcache_all before it enables
|
||||||
|
* the L1; however, the L1 comes out of reset in an undefined state, so
|
||||||
|
* the clean + invalidate performed by v7_flush_dcache_all causes a bunch
|
||||||
|
* of cache lines with uninitialized data and uninitialized tags to get
|
||||||
|
* written out to memory, which does really unpleasant things to the main
|
||||||
|
* processor. We fix this by performing an invalidate, rather than a
|
||||||
|
* clean + invalidate, before jumping into the kernel.
|
||||||
|
*
|
||||||
|
* This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
|
||||||
|
* to be called for both secondary cores startup and primary core resume
|
||||||
|
* procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
|
||||||
|
*/
|
||||||
|
ENTRY(v7_invalidate_l1)
|
||||||
|
mov r0, #0
|
||||||
|
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
|
||||||
|
mcr p15, 2, r0, c0, c0, 0
|
||||||
|
mrc p15, 1, r0, c0, c0, 0
|
||||||
|
|
||||||
|
ldr r1, =0x7fff
|
||||||
|
and r2, r1, r0, lsr #13
|
||||||
|
|
||||||
|
ldr r1, =0x3ff
|
||||||
|
|
||||||
|
and r3, r1, r0, lsr #3 @ NumWays - 1
|
||||||
|
add r2, r2, #1 @ NumSets
|
||||||
|
|
||||||
|
and r0, r0, #0x7
|
||||||
|
add r0, r0, #4 @ SetShift
|
||||||
|
|
||||||
|
clz r1, r3 @ WayShift
|
||||||
|
add r4, r3, #1 @ NumWays
|
||||||
|
1: sub r2, r2, #1 @ NumSets--
|
||||||
|
mov r3, r4 @ Temp = NumWays
|
||||||
|
2: subs r3, r3, #1 @ Temp--
|
||||||
|
mov r5, r3, lsl r1
|
||||||
|
mov r6, r2, lsl r0
|
||||||
|
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
|
||||||
|
mcr p15, 0, r5, c7, c6, 2
|
||||||
|
bgt 2b
|
||||||
|
cmp r2, #0
|
||||||
|
bgt 1b
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
mov pc, lr
|
||||||
|
ENDPROC(v7_invalidate_l1)
|
||||||
|
|
||||||
|
ENTRY(shmobile_invalidate_start)
|
||||||
|
bl v7_invalidate_l1
|
||||||
|
b secondary_startup
|
||||||
|
ENDPROC(shmobile_invalidate_start)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset vector for secondary CPUs.
|
* Reset vector for secondary CPUs.
|
||||||
* This will be mapped at address 0 by SBAR register.
|
* This will be mapped at address 0 by SBAR register.
|
||||||
|
@ -24,4 +77,5 @@
|
||||||
.align 12
|
.align 12
|
||||||
ENTRY(shmobile_secondary_vector)
|
ENTRY(shmobile_secondary_vector)
|
||||||
ldr pc, 1f
|
ldr pc, 1f
|
||||||
1: .long secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET
|
1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
|
||||||
|
ENDPROC(shmobile_secondary_vector)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
extern void shmobile_earlytimer_init(void);
|
extern void shmobile_earlytimer_init(void);
|
||||||
extern struct sys_timer shmobile_timer;
|
extern struct sys_timer shmobile_timer;
|
||||||
struct twd_local_timer;
|
struct twd_local_timer;
|
||||||
void shmobile_twd_init(struct twd_local_timer *twd_local_timer);
|
|
||||||
extern void shmobile_setup_console(void);
|
extern void shmobile_setup_console(void);
|
||||||
extern void shmobile_secondary_vector(void);
|
extern void shmobile_secondary_vector(void);
|
||||||
extern int shmobile_platform_cpu_kill(unsigned int cpu);
|
extern int shmobile_platform_cpu_kill(unsigned int cpu);
|
||||||
|
@ -82,5 +81,6 @@ extern int r8a7779_platform_cpu_kill(unsigned int cpu);
|
||||||
extern void r8a7779_secondary_init(unsigned int cpu);
|
extern void r8a7779_secondary_init(unsigned int cpu);
|
||||||
extern int r8a7779_boot_secondary(unsigned int cpu);
|
extern int r8a7779_boot_secondary(unsigned int cpu);
|
||||||
extern void r8a7779_smp_prepare_cpus(void);
|
extern void r8a7779_smp_prepare_cpus(void);
|
||||||
|
extern void r8a7779_register_twd(void);
|
||||||
|
|
||||||
#endif /* __ARCH_MACH_COMMON_H */
|
#endif /* __ARCH_MACH_COMMON_H */
|
||||||
|
|
|
@ -262,10 +262,14 @@ void __init r8a7779_add_standard_devices(void)
|
||||||
ARRAY_SIZE(r8a7779_late_devices));
|
ARRAY_SIZE(r8a7779_late_devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
|
||||||
|
void __init __weak r8a7779_register_twd(void) { }
|
||||||
|
|
||||||
static void __init r8a7779_earlytimer_init(void)
|
static void __init r8a7779_earlytimer_init(void)
|
||||||
{
|
{
|
||||||
r8a7779_clock_init();
|
r8a7779_clock_init();
|
||||||
shmobile_earlytimer_init();
|
shmobile_earlytimer_init();
|
||||||
|
r8a7779_register_twd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init r8a7779_add_early_devices(void)
|
void __init r8a7779_add_early_devices(void)
|
||||||
|
|
|
@ -688,10 +688,14 @@ void __init sh73a0_add_standard_devices(void)
|
||||||
ARRAY_SIZE(sh73a0_late_devices));
|
ARRAY_SIZE(sh73a0_late_devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
|
||||||
|
void __init __weak sh73a0_register_twd(void) { }
|
||||||
|
|
||||||
static void __init sh73a0_earlytimer_init(void)
|
static void __init sh73a0_earlytimer_init(void)
|
||||||
{
|
{
|
||||||
sh73a0_clock_init();
|
sh73a0_clock_init();
|
||||||
shmobile_earlytimer_init();
|
shmobile_earlytimer_init();
|
||||||
|
sh73a0_register_twd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init sh73a0_add_early_devices(void)
|
void __init sh73a0_add_early_devices(void)
|
||||||
|
|
|
@ -64,8 +64,15 @@ static void __iomem *scu_base_addr(void)
|
||||||
static DEFINE_SPINLOCK(scu_lock);
|
static DEFINE_SPINLOCK(scu_lock);
|
||||||
static unsigned long tmp;
|
static unsigned long tmp;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARM_TWD
|
||||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||||
|
|
||||||
|
void __init r8a7779_register_twd(void)
|
||||||
|
{
|
||||||
|
twd_local_timer_register(&twd_local_timer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||||
{
|
{
|
||||||
void __iomem *scu_base = scu_base_addr();
|
void __iomem *scu_base = scu_base_addr();
|
||||||
|
@ -84,7 +91,6 @@ unsigned int __init r8a7779_get_core_count(void)
|
||||||
{
|
{
|
||||||
void __iomem *scu_base = scu_base_addr();
|
void __iomem *scu_base = scu_base_addr();
|
||||||
|
|
||||||
shmobile_twd_init(&twd_local_timer);
|
|
||||||
return scu_get_core_count(scu_base);
|
return scu_get_core_count(scu_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,13 @@ static void __iomem *scu_base_addr(void)
|
||||||
static DEFINE_SPINLOCK(scu_lock);
|
static DEFINE_SPINLOCK(scu_lock);
|
||||||
static unsigned long tmp;
|
static unsigned long tmp;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARM_TWD
|
||||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||||
|
void __init sh73a0_register_twd(void)
|
||||||
|
{
|
||||||
|
twd_local_timer_register(&twd_local_timer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||||
{
|
{
|
||||||
|
@ -62,7 +68,6 @@ unsigned int __init sh73a0_get_core_count(void)
|
||||||
{
|
{
|
||||||
void __iomem *scu_base = scu_base_addr();
|
void __iomem *scu_base = scu_base_addr();
|
||||||
|
|
||||||
shmobile_twd_init(&twd_local_timer);
|
|
||||||
return scu_get_core_count(scu_base);
|
return scu_get_core_count(scu_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,15 +46,6 @@ static void __init shmobile_timer_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init shmobile_twd_init(struct twd_local_timer *twd_local_timer)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_HAVE_ARM_TWD
|
|
||||||
int err = twd_local_timer_register(twd_local_timer);
|
|
||||||
if (err)
|
|
||||||
pr_err("twd_local_timer_register failed %d\n", err);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sys_timer shmobile_timer = {
|
struct sys_timer shmobile_timer = {
|
||||||
.init = shmobile_timer_init,
|
.init = shmobile_timer_init,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue