Skip to content
Snippets Groups Projects
Commit 58591dae authored by leichuan's avatar leichuan Committed by Kenneth Johansson
Browse files

GPTC WDT dt parsing support

parent fd61d14a
No related branches found
No related tags found
No related merge requests found
...@@ -100,6 +100,7 @@ struct gptc_timer { ...@@ -100,6 +100,7 @@ struct gptc_timer {
u32 irq; u32 irq;
#define CLK_SRC_FLAG 0x01 #define CLK_SRC_FLAG 0x01
#define CLK_EVT_FLAG 0x02 #define CLK_EVT_FLAG 0x02
#define CLK_WDT_FLAG 0x04
u32 flags; u32 flags;
u32 frequency; u32 frequency;
enum gptc_cnt_dir dir; enum gptc_cnt_dir dir;
...@@ -335,6 +336,19 @@ static void gptc_per_timer_init(struct gptc_timer *timer) ...@@ -335,6 +336,19 @@ static void gptc_per_timer_init(struct gptc_timer *timer)
gptc_reload_and_run(timer); gptc_reload_and_run(timer);
} }
static const char *const gptc_flag_to_str(u32 flags)
{
if (flags & CLK_SRC_FLAG)
return "src";
if (flags & CLK_EVT_FLAG)
return "event";
if (flags & CLK_WDT_FLAG)
return "wdt";
return "none";
}
static void gptc_print_config(void) static void gptc_print_config(void)
{ {
int i; int i;
...@@ -346,7 +360,7 @@ static void gptc_print_config(void) ...@@ -346,7 +360,7 @@ static void gptc_print_config(void)
pr_debug("timer%d base %p gptcid %d freq %d tid %d cpuid %d irq %d clk %s %s\n", pr_debug("timer%d base %p gptcid %d freq %d tid %d cpuid %d irq %d clk %s %s\n",
i, timer->base, timer->gptcid, timer->frequency, i, timer->base, timer->gptcid, timer->frequency,
timer->tid, timer->cpuid, timer->irq, timer->tid, timer->cpuid, timer->irq,
(timer->flags & CLK_SRC_FLAG) ? "src" : "event", gptc_flag_to_str(timer->flags),
timer->used ? "used" : "unused"); timer->used ? "used" : "unused");
} }
} }
...@@ -355,7 +369,10 @@ static int gptc_timer_of_init(struct device_node *np) ...@@ -355,7 +369,10 @@ static int gptc_timer_of_init(struct device_node *np)
{ {
int i, ret; int i, ret;
u32 prop; u32 prop;
u32 gptcid, nr_evts; u32 gptcid;
u32 nr_evts = 0;
u32 nr_wdts = 0;
u32 nr_srcs = 0;
struct resource res; struct resource res;
void __iomem *base; void __iomem *base;
struct gptc_timer *timer; struct gptc_timer *timer;
...@@ -395,16 +412,17 @@ static int gptc_timer_of_init(struct device_node *np) ...@@ -395,16 +412,17 @@ static int gptc_timer_of_init(struct device_node *np)
clk_prepare(fpiclk); clk_prepare(fpiclk);
freq = clk_get_rate(fpiclk); freq = clk_get_rate(fpiclk);
base = of_iomap(np, 0);
if (!base) {
pr_err("Can't map GPTC registers\n");
goto err_iomap;
}
if (!of_property_read_bool(np, "intel,clksrc") && if (!of_property_read_bool(np, "intel,clksrc") &&
!of_property_read_bool(np, "intel,clkevt")) { !of_property_read_bool(np, "intel,clkevt") &&
!of_property_read_bool(np, "intel,clkwdt")) {
ret = -EEXIST; ret = -EEXIST;
goto err; goto err_fpipre;
}
base = of_iomap(np, 0);
if (!base) {
pr_err("Can't map GPTC base address\n");
goto err_fpipre;
} }
if (!of_property_read_u32(np, "intel,clksrc", &prop)) { if (!of_property_read_u32(np, "intel,clksrc", &prop)) {
...@@ -421,52 +439,91 @@ static int gptc_timer_of_init(struct device_node *np) ...@@ -421,52 +439,91 @@ static int gptc_timer_of_init(struct device_node *np)
timer->dir = GPTC_COUNT_UP; timer->dir = GPTC_COUNT_UP;
timer->used = false; timer->used = false;
gptc_timer_count++; gptc_timer_count++;
nr_srcs++;
} }
/* Parse clock event list */
nr_evts = of_property_count_u32_elems(np, "intel,clkevt"); nr_evts = of_property_count_u32_elems(np, "intel,clkevt");
if (nr_evts == 0 || nr_evts > TIMER_PER_GPTC) { if ((nr_evts > 0) && (nr_evts <= TIMER_PER_GPTC)) {
pr_warn("GPTC%d doesn't provide valid clock events\n", gptcid); ret = of_property_read_u32_array(np, "intel,clkevt",
ret = -EINVAL; tid, nr_evts);
goto err; if (ret) {
} pr_err("GPTC%d failed to get clock event timer list\n",
gptcid);
goto err;
}
ret = of_property_read_u32_array(np, "intel,clkevt", tid, nr_evts); ret = of_property_read_u32_array(np, "intel,cpuid",
if (ret) { cpuid, nr_evts);
pr_err("GPTC%d failed to get clock event timer id list\n", if (ret) {
gptcid); pr_err("GPTC%d failed to get cpu id list\n", gptcid);
goto err; goto err;
} }
ret = of_property_read_u32_array(np, "intel,cpuid", cpuid, nr_evts); for (i = 0; i < nr_evts; i++) {
if (ret) { timer = &gptc_timer_info[gptc_timer_count];
pr_err("GPTC%d failed to get cpu id list\n", gptcid); timer->base = base;
goto err; timer->phy_base = res.start;
timer->gptcid = gptcid;
timer->tid = tid[i];
WARN_ON(timer->tid >= TIMER_PER_GPTC);
timer->cpuid = cpuid[i];
timer->flags |= CLK_EVT_FLAG;
/* Timer ID as index to get irq */
timer->irq = irq_of_parse_and_map(np, timer->tid);
WARN_ON(timer->irq == 0);
timer->frequency = freq;
timer->dir = GPTC_COUNT_DOWN;
timer->used = false;
gptc_timer_count++;
}
} }
for (i = 0; i < nr_evts; i++) { /* Parse watchdog timer list */
timer = &gptc_timer_info[gptc_timer_count]; nr_wdts = of_property_count_u32_elems(np, "intel,clkwdt");
timer->base = base; if ((nr_wdts > 0) && (nr_wdts <= TIMER_PER_GPTC)) {
timer->phy_base = res.start; ret = of_property_read_u32_array(np, "intel,clkwdt",
timer->gptcid = gptcid; tid, nr_wdts);
timer->tid = tid[i]; if (ret) {
WARN_ON(timer->tid >= TIMER_PER_GPTC); pr_err("GPTC%d failed to get wdt timer list\n", gptcid);
timer->cpuid = cpuid[i]; goto err;
timer->flags |= CLK_EVT_FLAG; }
/* Timer ID as index to get irq */
timer->irq = irq_of_parse_and_map(np, timer->tid); ret = of_property_read_u32_array(np, "intel,wdtid",
WARN_ON(timer->irq == 0); cpuid, nr_wdts);
timer->frequency = freq; if (ret) {
timer->dir = GPTC_COUNT_DOWN; pr_err("GPTC%d failed to get wdt cpu id list\n",
timer->used = false; gptcid);
gptc_timer_count++; goto err;
}
for (i = 0; i < nr_wdts; i++) {
timer = &gptc_timer_info[gptc_timer_count];
timer->base = base;
timer->phy_base = res.start;
timer->gptcid = gptcid;
timer->tid = tid[i];
WARN_ON(timer->tid >= TIMER_PER_GPTC);
timer->cpuid = cpuid[i];
timer->flags |= CLK_WDT_FLAG;
/* Timer ID as index to get irq */
timer->irq = irq_of_parse_and_map(np, timer->tid);
WARN_ON(timer->irq == 0);
timer->frequency = freq;
timer->dir = GPTC_COUNT_DOWN;
timer->used = false;
gptc_timer_count++;
}
} }
pr_debug("GPTC%d nr_srcs %d nr_evts %d nr_wdts %d\n",
gptcid, nr_srcs, nr_evts, nr_wdts);
/* GPTC level initialization */ /* GPTC level initialization */
gptc_global_init(base); gptc_global_init(base);
return 0; return 0;
err: err:
iounmap(base); iounmap(base);
err_iomap: err_fpipre:
clk_unprepare(fpiclk); clk_unprepare(fpiclk);
clk_put(fpiclk); clk_put(fpiclk);
err_fpiclk: err_fpiclk:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment