summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@libc.org>2016-07-31 03:32:21 +0000
committerRich Felker <dalias@libc.org>2016-07-31 03:32:21 +0000
commit4c425eac1153ff79929e922f8ebd9abd4108b9f7 (patch)
tree33f24c77396de148428af093683e29b92fe5cc63
parent88f7680d4a371ff2d78d3edb34cf1ef9ce4b8145 (diff)
downloadlinux-sh-devel-20160730.tar.gz
wip updates to jcore pitdevel-20160730
-rw-r--r--drivers/clocksource/jcore-pit.c181
-rw-r--r--include/linux/cpuhotplug.h1
2 files changed, 70 insertions, 112 deletions
diff --git a/drivers/clocksource/jcore-pit.c b/drivers/clocksource/jcore-pit.c
index 4a2f7803624b..b54d313df069 100644
--- a/drivers/clocksource/jcore-pit.c
+++ b/drivers/clocksource/jcore-pit.c
@@ -15,65 +15,54 @@
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
#include <linux/cpu.h>
+#include <linux/cpuhotplug.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#define PIT_IRQ_SHIFT 12
-#define PIT_PRIO_SHIFT 20
-#define PIT_ENABLE_SHIFT 26
-#define PIT_IRQ_MASK 0x3f
-#define PIT_PRIO_MASK 0xf
-
-#define REG_PITEN 0x00
-#define REG_THROT 0x10
-#define REG_COUNT 0x14
-#define REG_BUSPD 0x18
-#define REG_SECHI 0x20
-#define REG_SECLO 0x24
-#define REG_NSEC 0x28
-
-struct jcore_clocksource {
- struct clocksource cs;
- __iomem void *base;
-};
+#define PIT_IRQ_SHIFT 12
+#define PIT_PRIO_SHIFT 20
+#define PIT_ENABLE_SHIFT 26
+#define PIT_IRQ_MASK 0x3f
+#define PIT_PRIO_MASK 0xf
-struct jcore_pit {
- struct clock_event_device ced;
- __iomem void *base;
- unsigned long periodic_delta;
- unsigned cpu;
- u32 enable_val;
-};
+#define REG_PITEN 0x00
+#define REG_THROT 0x10
+#define REG_COUNT 0x14
+#define REG_BUSPD 0x18
+#define REG_SECHI 0x20
+#define REG_SECLO 0x24
+#define REG_NSEC 0x28
-struct jcore_pit_nb {
- struct notifier_block nb;
- struct jcore_pit __percpu *pit_percpu;
+struct jcore_pit {
+ struct clock_event_device ced;
+ __iomem void *base;
+ unsigned long periodic_delta;
+ unsigned cpu;
+ u32 enable_val;
};
-static struct clocksource *jcore_cs;
+static __iomem void *jcore_pit_base;
+static struct clocksource jcore_cs;
+struct jcore_pit __percpu *jcore_pit_percpu;
-static cycle_t jcore_clocksource_read(struct clocksource *cs)
+static notrace u64 jcore_sched_clock_read(void)
{
- __iomem void *base =
- container_of(cs, struct jcore_clocksource, cs)->base;
- u32 sechi, seclo, nsec, sechi0, seclo0;
+ u32 seclo, nsec, seclo0;
+ __iomem void *base = jcore_pit_base;
- sechi = __raw_readl(base + REG_SECHI);
seclo = __raw_readl(base + REG_SECLO);
do {
- sechi0 = sechi;
seclo0 = seclo;
nsec = __raw_readl(base + REG_NSEC);
- sechi = __raw_readl(base + REG_SECHI);
seclo = __raw_readl(base + REG_SECLO);
- } while (sechi0 != sechi || seclo0 != seclo);
+ } while (seclo0 != seclo);
- return ((u64)sechi << 32 | seclo) * NSEC_PER_SEC + nsec;
+ return seclo * NSEC_PER_SEC + nsec;
}
-static notrace u64 jcore_sched_clock_read(void)
+static cycle_t jcore_clocksource_read(struct clocksource *cs)
{
- return jcore_clocksource_read(jcore_cs);
+ return jcore_sched_clock_read();
}
static int jcore_pit_disable(struct jcore_pit *pit)
@@ -93,18 +82,21 @@ static int jcore_pit_set(unsigned long delta, struct jcore_pit *pit)
static int jcore_pit_set_state_shutdown(struct clock_event_device *ced)
{
struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
return jcore_pit_disable(pit);
}
static int jcore_pit_set_state_oneshot(struct clock_event_device *ced)
{
struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
return jcore_pit_disable(pit);
}
static int jcore_pit_set_state_periodic(struct clock_event_device *ced)
{
struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
return jcore_pit_set(pit->periodic_delta, pit);
}
@@ -112,11 +104,13 @@ static int jcore_pit_set_next_event(unsigned long delta,
struct clock_event_device *ced)
{
struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
return jcore_pit_set(delta, pit);
}
-static int jcore_pit_local_init(struct jcore_pit *pit)
+static int jcore_pit_local_init(unsigned cpu)
{
+ struct jcore_pit *pit = this_cpu_ptr(jcore_pit_percpu);
unsigned buspd, freq;
pr_info("Local J-Core PIT init on cpu %u\n", pit->cpu);
@@ -130,16 +124,9 @@ static int jcore_pit_local_init(struct jcore_pit *pit)
return 0;
}
-static int jcore_pit_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static int jcore_pit_local_shutdown(unsigned cpu)
{
- struct jcore_pit_nb *nb = container_of(self, struct jcore_pit_nb, nb);
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_STARTING:
- jcore_pit_local_init(this_cpu_ptr(nb->pit_percpu));
- break;
- }
- return NOTIFY_OK;
+ return 0;
}
static irqreturn_t jcore_timer_interrupt(int irq, void *dev_id)
@@ -157,83 +144,53 @@ static irqreturn_t jcore_timer_interrupt(int irq, void *dev_id)
static int __init jcore_pit_init(struct device_node *node)
{
int err;
- __iomem void *pit_base;
- unsigned pit_irq;
- unsigned cpu;
- struct jcore_pit_nb *nb = 0;
- struct jcore_clocksource *cs = 0;
- struct jcore_pit __percpu *pit_percpu = 0;
+ unsigned pit_irq, cpu;
unsigned long hwirq;
u32 irqprio, enable_val;
- pit_base = of_iomap(node, 0);
- if (!pit_base) {
+ jcore_pit_base = of_iomap(node, 0);
+ if (!jcore_pit_base) {
pr_err("Error: Cannot map base address for J-Core PIT\n");
- err = -ENXIO;
- goto out;
+ return -ENXIO;
}
pit_irq = irq_of_parse_and_map(node, 0);
if (!pit_irq) {
pr_err("Error: J-Core PIT has no IRQ\n");
- err = -ENXIO;
- goto out;
+ return -ENXIO;
}
- pr_info("Initializing J-Core PIT at %p IRQ %d\n", pit_base, pit_irq);
+ pr_info("Initializing J-Core PIT at %p IRQ %d\n",
+ jcore_pit_base, pit_irq);
- cs = kzalloc(sizeof *cs, GFP_KERNEL);
- if (!cs) {
- pr_err("Failed to allocate memory for clocksource\n");
- err = ENOMEM;
- goto out;
- }
- jcore_cs = &cs->cs;
-
- cs->base = pit_base;
- cs->cs.name = "jcore_pit_cs";
- cs->cs.rating = 400;
- cs->cs.read = jcore_clocksource_read;
- cs->cs.mult = 1;
- cs->cs.shift = 0;
- cs->cs.mask = CLOCKSOURCE_MASK(64);
- cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-
- err = clocksource_register_hz(&cs->cs, NSEC_PER_SEC);
+ jcore_cs.name = "jcore_pit_cs";
+ jcore_cs.rating = 400;
+ jcore_cs.read = jcore_clocksource_read;
+ jcore_cs.mult = 1;
+ jcore_cs.shift = 0;
+ jcore_cs.mask = CLOCKSOURCE_MASK(32);
+ jcore_cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ err = clocksource_register_hz(&jcore_cs, NSEC_PER_SEC);
if (err) {
pr_err("Error registering clocksource device: %d\n", err);
- goto out;
+ return err;
}
- sched_clock_register(jcore_sched_clock_read, 64, NSEC_PER_SEC);
+ sched_clock_register(jcore_sched_clock_read, 32, NSEC_PER_SEC);
- pit_percpu = alloc_percpu(struct jcore_pit);
- if (!pit_percpu) {
+ jcore_pit_percpu = alloc_percpu(struct jcore_pit);
+ if (!jcore_pit_percpu) {
pr_err("Failed to allocate memory for clock event device\n");
- err = ENOMEM;
- goto out;
- }
-
- nb = kzalloc(sizeof *nb, GFP_KERNEL);
- if (!nb) {
- pr_err("Failed to allocate memory for J-Core PIT notifier\n");
- err = ENOMEM;
- goto out;
- }
-
- nb->pit_percpu = pit_percpu;
- nb->nb.notifier_call = jcore_pit_cpu_notify;
- err = register_cpu_notifier(&nb->nb);
- if (err) {
- pr_err("Error registering J-Core PIT notifier: %d\n", err);
- goto out;
+ return -ENOMEM;
}
err = request_irq(pit_irq, jcore_timer_interrupt,
- IRQF_TIMER | IRQF_PERCPU, "jcore_pit", pit_percpu);
+ IRQF_TIMER | IRQF_PERCPU,
+ "jcore_pit", jcore_pit_percpu);
if (err) {
pr_err("pit irq request failed: %d\n", err);
- goto out;
+ return err;
}
/* The J-Core PIT is not hard-wired to a particular IRQ, but
@@ -248,12 +205,14 @@ static int __init jcore_pit_init(struct device_node *node)
| (hwirq << PIT_IRQ_SHIFT)
| (irqprio << PIT_PRIO_SHIFT);
- for_each_possible_cpu(cpu) {
- struct jcore_pit *pit = per_cpu_ptr(pit_percpu, cpu);
+ for_each_present_cpu(cpu) {
+ struct jcore_pit *pit = per_cpu_ptr(jcore_pit_percpu, cpu);
pit->base = of_iomap(node, cpu);
- if (!pit->base)
+ if (!pit->base) {
+ pr_err("Unable to map PIT for cpu %u\n", cpu);
continue;
+ }
pit->ced.name = "jcore_pit";
pit->ced.features = CLOCK_EVT_FEAT_PERIODIC
@@ -271,13 +230,11 @@ static int __init jcore_pit_init(struct device_node *node)
pit->enable_val = enable_val;
}
- jcore_pit_local_init(this_cpu_ptr(pit_percpu));
+ cpuhp_setup_state(CPUHP_AP_JCORE_TIMER_STARTING,
+ "AP_JCORE_TIMER_STARTING",
+ jcore_pit_local_init, jcore_pit_local_shutdown);
return 0;
-
-out:
- pr_err("Could not initialize J-Core PIT driver\n");
- return err;
}
CLOCKSOURCE_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 386374d19987..b885c4fafb55 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -9,6 +9,7 @@ enum cpuhp_state {
CPUHP_AP_IDLE_DEAD,
CPUHP_AP_OFFLINE,
CPUHP_AP_SCHED_STARTING,
+ CPUHP_AP_JCORE_TIMER_STARTING,
CPUHP_AP_NOTIFY_STARTING,
CPUHP_AP_ONLINE,
CPUHP_TEARDOWN_CPU,