static void __init vexpress_sp810_init(void __iomem *base) { int i; if (WARN_ON(!base)) return; for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) { char name[12]; const char *parents[] = { "v2m:refclk32khz", /* REFCLK */ "v2m:refclk1mhz" /* TIMCLK */ }; snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name, parents, 2, 0, base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1, 0, &vexpress_sp810_lock); if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i]))) break; } }
static u8 clk_sp810_timerclken_get_parent(struct clk_hw *hw) { struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); u32 val = readl(timerclken->sp810->base + SCCTRL); return !!(val & (1 << SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel))); }
static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index) { struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); struct clk_sp810 *sp810 = timerclken->sp810; u32 val, shift = SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel); unsigned long flags = 0; if (WARN_ON(index > 1)) return -EINVAL; spin_lock_irqsave(&sp810->lock, flags); val = readl(sp810->base + SCCTRL); val &= ~(1 << shift); val |= index << shift; writel(val, sp810->base + SCCTRL); spin_unlock_irqrestore(&sp810->lock, flags); return 0; }