Commit c5d431e8 authored by Russell King's avatar Russell King Committed by Gregory CLEMENT

ARM: dove: convert legacy dove to PMU support

Since Dove has non-DT support for various facilities in the PMU, convert
the legacy support to use the new PMU driver.
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarGregory CLEMENT <gregory.clement@free-electrons.com>
parent 67098119
......@@ -516,6 +516,7 @@ config ARCH_DOVE
select PINCTRL_DOVE
select PLAT_ORION_LEGACY
select SPARSE_IRQ
select PM_GENERIC_DOMAINS if PM
help
Support for the Marvell Dove SoC 88AP510
......
......@@ -16,6 +16,7 @@
#include <linux/platform_data/dma-mv_xor.h>
#include <linux/platform_data/usb-ehci-orion.h>
#include <linux/platform_device.h>
#include <linux/soc/dove/pmu.h>
#include <asm/hardware/cache-tauros2.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -392,6 +393,30 @@ static void __init __maybe_unused orion_wdt_init(void)
platform_device_register(&orion_wdt_device);
}
static const struct dove_pmu_domain_initdata pmu_domains[] __initconst = {
{
.pwr_mask = PMU_PWR_VPU_PWR_DWN_MASK,
.rst_mask = PMU_SW_RST_VIDEO_MASK,
.iso_mask = PMU_ISO_VIDEO_MASK,
.name = "vpu-domain",
}, {
.pwr_mask = PMU_PWR_GPU_PWR_DWN_MASK,
.rst_mask = PMU_SW_RST_GPU_MASK,
.iso_mask = PMU_ISO_GPU_MASK,
.name = "gpu-domain",
}, {
/* sentinel */
},
};
static const struct dove_pmu_initdata pmu_data __initconst = {
.pmc_base = DOVE_PMU_VIRT_BASE,
.pmu_base = DOVE_PMU_VIRT_BASE + 0x8000,
.irq = IRQ_DOVE_PMU,
.irq_domain_start = IRQ_DOVE_PMU_START,
.domains = pmu_domains,
};
void __init dove_init(void)
{
pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
......@@ -406,6 +431,7 @@ void __init dove_init(void)
dove_clk_init();
/* internal devices that every board has */
dove_init_pmu_legacy(&pmu_data);
dove_rtc_init();
dove_xor0_init();
dove_xor1_init();
......
......@@ -51,22 +51,14 @@
#define CLOCK_GATING_GIGA_PHY_MASK (1 << CLOCK_GATING_BIT_GIGA_PHY)
#define PMU_INTERRUPT_CAUSE (DOVE_PMU_VIRT_BASE + 0x50)
#define PMU_INTERRUPT_MASK (DOVE_PMU_VIRT_BASE + 0x54)
static inline int pmu_to_irq(int pin)
{
if (pin < NR_PMU_IRQS)
return pin + IRQ_DOVE_PMU_START;
#define PMU_SW_RST_VIDEO_MASK BIT(16)
#define PMU_SW_RST_GPU_MASK BIT(18)
return -EINVAL;
}
#define PMU_PWR_GPU_PWR_DWN_MASK BIT(2)
#define PMU_PWR_VPU_PWR_DWN_MASK BIT(3)
static inline int irq_to_pmu(int irq)
{
if (IRQ_DOVE_PMU_START <= irq && irq < DOVE_NR_IRQS)
return irq - IRQ_DOVE_PMU_START;
return -EINVAL;
}
#define PMU_ISO_VIDEO_MASK BIT(0)
#define PMU_ISO_GPU_MASK BIT(1)
#endif
......@@ -7,88 +7,15 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <asm/exception.h>
#include <asm/mach/arch.h>
#include <plat/irq.h>
#include <asm/mach/irq.h>
#include <mach/pm.h>
#include <mach/bridge-regs.h>
#include <plat/orion-gpio.h>
#include "common.h"
static void pmu_irq_mask(struct irq_data *d)
{
int pin = irq_to_pmu(d->irq);
u32 u;
u = readl(PMU_INTERRUPT_MASK);
u &= ~(1 << (pin & 31));
writel(u, PMU_INTERRUPT_MASK);
}
static void pmu_irq_unmask(struct irq_data *d)
{
int pin = irq_to_pmu(d->irq);
u32 u;
u = readl(PMU_INTERRUPT_MASK);
u |= 1 << (pin & 31);
writel(u, PMU_INTERRUPT_MASK);
}
static void pmu_irq_ack(struct irq_data *d)
{
int pin = irq_to_pmu(d->irq);
u32 u;
/*
* The PMU mask register is not RW0C: it is RW. This means that
* the bits take whatever value is written to them; if you write
* a '1', you will set the interrupt.
*
* Unfortunately this means there is NO race free way to clear
* these interrupts.
*
* So, let's structure the code so that the window is as small as
* possible.
*/
u = ~(1 << (pin & 31));
u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
writel_relaxed(u, PMU_INTERRUPT_CAUSE);
}
static struct irq_chip pmu_irq_chip = {
.name = "pmu_irq",
.irq_mask = pmu_irq_mask,
.irq_unmask = pmu_irq_unmask,
.irq_ack = pmu_irq_ack,
};
static void pmu_irq_handler(struct irq_desc *desc)
{
unsigned long cause = readl(PMU_INTERRUPT_CAUSE);
unsigned int irq;
cause &= readl(PMU_INTERRUPT_MASK);
if (cause == 0) {
do_bad_IRQ(desc);
return;
}
for (irq = 0; irq < NR_PMU_IRQS; irq++) {
if (!(cause & (1 << irq)))
continue;
irq = pmu_to_irq(irq);
generic_handle_irq(irq);
}
}
static int __initdata gpio0_irqs[4] = {
IRQ_DOVE_GPIO_0_7,
IRQ_DOVE_GPIO_8_15,
......@@ -135,8 +62,6 @@ __exception_irq_entry dove_legacy_handle_irq(struct pt_regs *regs)
void __init dove_init_irq(void)
{
int i;
orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
......@@ -153,17 +78,4 @@ void __init dove_init_irq(void)
orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
/*
* Mask and clear PMU interrupts
*/
writel(0, PMU_INTERRUPT_MASK);
writel(0, PMU_INTERRUPT_CAUSE);
for (i = IRQ_DOVE_PMU_START; i < DOVE_NR_IRQS; i++) {
irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq);
irq_set_status_flags(i, IRQ_LEVEL);
irq_clear_status_flags(i, IRQ_NOREQUEST);
}
irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
}
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