Skip to content

Commit

Permalink
Merge pull request #3 from sjoerd-ccu/endless
Browse files Browse the repository at this point in the history
Fix PMU for perf
  • Loading branch information
dsd committed Apr 22, 2014
2 parents 5ae16a2 + 31a4465 commit a7fa33c
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 18 deletions.
98 changes: 84 additions & 14 deletions arch/arm/mach-exynos/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <mach/regs-pmu.h>
#include <mach/regs-gpio.h>
#include <mach/pmu.h>
#include <mach/irqs.h>

#include <plat/cpu.h>
#include <plat/clock.h>
Expand Down Expand Up @@ -496,6 +497,7 @@ struct combiner_chip_data {
unsigned int irq_offset;
unsigned int irq_mask;
void __iomem *base;
unsigned int parent_irq;
};

static struct irq_domain *combiner_irq_domain;
Expand Down Expand Up @@ -552,35 +554,59 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
chained_irq_exit(chip, desc);
}

#ifdef CONFIG_SMP
static int combiner_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
{
struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d);
struct irq_chip *chip = irq_get_chip(chip_data->parent_irq);
struct irq_data *data = irq_get_irq_data(chip_data->parent_irq);

if (chip && chip->irq_set_affinity)
return chip->irq_set_affinity(data, mask_val, force);
else
return -EINVAL;
}
#endif

static struct irq_chip combiner_chip = {
.name = "COMBINER",
.irq_mask = combiner_mask_irq,
.irq_unmask = combiner_unmask_irq,
#ifdef CONFIG_SMP
.irq_set_affinity = combiner_set_affinity,
#endif
};

static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
static unsigned int max_combiner_nr(void)
{
unsigned int max_nr;

if (soc_is_exynos5250())
max_nr = EXYNOS5_MAX_COMBINER_NR;
return EXYNOS5_MAX_COMBINER_NR;
else if (soc_is_exynos4412())
return EXYNOS4412_MAX_COMBINER_NR;
else if (soc_is_exynos4212())
return EXYNOS4212_MAX_COMBINER_NR;
else
max_nr = EXYNOS4_MAX_COMBINER_NR;
return EXYNOS4210_MAX_COMBINER_NR;
}

if (combiner_nr >= max_nr)
static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
{
if (combiner_nr >= max_combiner_nr())
BUG();
if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
BUG();
irq_set_chained_handler(irq, combiner_handle_cascade_irq);
}

static void __init combiner_init_one(unsigned int combiner_nr,
void __iomem *base)
void __iomem *base, unsigned int irq)
{
combiner_data[combiner_nr].base = base;
combiner_data[combiner_nr].irq_offset = irq_find_mapping(
combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
combiner_data[combiner_nr].parent_irq = irq;

/* Disable all interrupts */
__raw_writel(combiner_data[combiner_nr].irq_mask,
Expand Down Expand Up @@ -631,22 +657,36 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
.map = combiner_irq_domain_map,
};

static unsigned int exynos4x12_combiner_extra_irq(int group)
{
switch (group) {
case 16:
return IRQ_SPI(107);
case 17:
return IRQ_SPI(108);
case 18:
return IRQ_SPI(48);
case 19:
return IRQ_SPI(42);
default:
return 0;
}
}

static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
unsigned int max_nr, nr_irq;

max_nr = max_combiner_nr();

if (np) {
if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
pr_warning("%s: number of combiners not specified, "
"setting default as %d.\n",
__func__, EXYNOS4_MAX_COMBINER_NR);
max_nr = EXYNOS4_MAX_COMBINER_NR;
__func__, max_nr);
}
} else {
max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
EXYNOS4_MAX_COMBINER_NR;
}
nr_irq = max_nr * MAX_IRQ_IN_COMBINER;

Expand All @@ -664,13 +704,16 @@ static void __init combiner_init(void __iomem *combiner_base,
}

for (i = 0; i < max_nr; i++) {
combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
irq = IRQ_SPI(i);
if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
irq = IRQ_SPI(i);
else
irq = exynos4x12_combiner_extra_irq(i);
#ifdef CONFIG_OF
if (np)
irq = irq_of_parse_and_map(np, i);
#endif
combiner_cascade_irq(i, irq);
combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq);
}
}

Expand Down Expand Up @@ -1143,3 +1186,30 @@ static int __init exynos_init_irq_eint(void)
return 0;
}
arch_initcall(exynos_init_irq_eint);

static struct resource exynos4_pmu_resource[] = {
DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU),
DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1),
#if defined(CONFIG_SOC_EXYNOS4412)
DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2),
DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3),
#endif
};

static struct platform_device exynos4_device_pmu = {
.name = "arm-pmu",
.num_resources = ARRAY_SIZE(exynos4_pmu_resource),
.resource = exynos4_pmu_resource,
};

static int __init exynos_armpmu_init(void)
{
if (!of_have_populated_dt()) {
if (soc_is_exynos4210() || soc_is_exynos4212())
exynos4_device_pmu.num_resources = 2;
platform_device_register(&exynos4_device_pmu);
}

return 0;
}
arch_initcall(exynos_armpmu_init);
14 changes: 11 additions & 3 deletions arch/arm/mach-exynos/include/mach/irqs.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
#define EXYNOS4_IRQ_ADC1 IRQ_SPI(107)
#define EXYNOS4_IRQ_PEN1 IRQ_SPI(108)
#define EXYNOS4_IRQ_KEYPAD IRQ_SPI(109)
#define EXYNOS4_IRQ_PMU IRQ_SPI(110)
#define EXYNOS4_IRQ_POWER_PMU IRQ_SPI(110)
#define EXYNOS4_IRQ_GPS IRQ_SPI(111)
#define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112)
#define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113)
Expand All @@ -137,6 +137,11 @@
#define EXYNOS4_IRQ_TSI IRQ_SPI(115)
#define EXYNOS4_IRQ_SATA IRQ_SPI(116)

#define EXYNOS4_IRQ_PMU COMBINER_IRQ(2, 2)
#define EXYNOS4_IRQ_PMU_CPU1 COMBINER_IRQ(3, 2)
#define EXYNOS4_IRQ_PMU_CPU2 COMBINER_IRQ(18, 2)
#define EXYNOS4_IRQ_PMU_CPU3 COMBINER_IRQ(19, 2)

#define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4)
#define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4)

Expand Down Expand Up @@ -169,7 +174,11 @@
#define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1)
#define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2)

#define EXYNOS4_MAX_COMBINER_NR 16
#define EXYNOS4210_MAX_COMBINER_NR 16
#define EXYNOS4212_MAX_COMBINER_NR 18
#define EXYNOS4412_MAX_COMBINER_NR 20
#define EXYNOS4_MAX_COMBINER_NR EXYNOS4412_MAX_COMBINER_NR


#define EXYNOS4_IRQ_GPIO1_NR_GROUPS 16
#define EXYNOS4_IRQ_GPIO2_NR_GROUPS 9
Expand Down Expand Up @@ -235,7 +244,6 @@
#define IRQ_TC EXYNOS4_IRQ_PEN0

#define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD
#define IRQ_PMU EXYNOS4_IRQ_PMU

#define IRQ_CEC EXYNOS4_IRQ_CEC

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/plat-samsung/devs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ struct platform_device s5p_device_onenand = {

/* PMU */

#ifdef CONFIG_PLAT_S5P
#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
static struct resource s5p_pmu_resource[] = {
DEFINE_RES_IRQ(IRQ_PMU)
};
Expand Down

0 comments on commit a7fa33c

Please sign in to comment.