Commit d2919c65 authored by Olof Johansson's avatar Olof Johansson

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
parents e396dbd4 e994d5eb
...@@ -365,23 +365,13 @@ static struct platform_device mipidsi0_device = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment