xref: /openbmc/linux/drivers/clocksource/ingenic-sysost.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
15ecafc12S周琰杰 (Zhou Yanjie) // SPDX-License-Identifier: GPL-2.0
25ecafc12S周琰杰 (Zhou Yanjie) /*
35ecafc12S周琰杰 (Zhou Yanjie)  * Ingenic XBurst SoCs SYSOST clocks driver
45ecafc12S周琰杰 (Zhou Yanjie)  * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
55ecafc12S周琰杰 (Zhou Yanjie)  */
65ecafc12S周琰杰 (Zhou Yanjie) 
7*3b87265dS周琰杰 (Zhou Yanjie) #include <linux/bitfield.h>
85ecafc12S周琰杰 (Zhou Yanjie) #include <linux/bitops.h>
95ecafc12S周琰杰 (Zhou Yanjie) #include <linux/clk.h>
105ecafc12S周琰杰 (Zhou Yanjie) #include <linux/clk-provider.h>
115ecafc12S周琰杰 (Zhou Yanjie) #include <linux/clockchips.h>
125ecafc12S周琰杰 (Zhou Yanjie) #include <linux/clocksource.h>
135ecafc12S周琰杰 (Zhou Yanjie) #include <linux/interrupt.h>
145ecafc12S周琰杰 (Zhou Yanjie) #include <linux/mfd/syscon.h>
155ecafc12S周琰杰 (Zhou Yanjie) #include <linux/of_address.h>
165ecafc12S周琰杰 (Zhou Yanjie) #include <linux/of_irq.h>
175ecafc12S周琰杰 (Zhou Yanjie) #include <linux/sched_clock.h>
185ecafc12S周琰杰 (Zhou Yanjie) #include <linux/slab.h>
195ecafc12S周琰杰 (Zhou Yanjie) #include <linux/syscore_ops.h>
205ecafc12S周琰杰 (Zhou Yanjie) 
215ecafc12S周琰杰 (Zhou Yanjie) #include <dt-bindings/clock/ingenic,sysost.h>
225ecafc12S周琰杰 (Zhou Yanjie) 
235ecafc12S周琰杰 (Zhou Yanjie) /* OST register offsets */
245ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTCCR			0x00
255ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTCR			0x08
265ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTFR			0x0c
275ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTMR			0x10
285ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OST1DFR			0x14
295ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OST1CNT			0x18
305ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OST2CNTL		0x20
315ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTCNT2HBUF		0x24
325ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTESR			0x34
335ecafc12S周琰杰 (Zhou Yanjie) #define OST_REG_OSTECR			0x38
345ecafc12S周琰杰 (Zhou Yanjie) 
355ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTCCR register */
365ecafc12S周琰杰 (Zhou Yanjie) #define OSTCCR_PRESCALE1_MASK	0x3
375ecafc12S周琰杰 (Zhou Yanjie) #define OSTCCR_PRESCALE2_MASK	0xc
385ecafc12S周琰杰 (Zhou Yanjie) 
395ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTCR register */
405ecafc12S周琰杰 (Zhou Yanjie) #define OSTCR_OST1CLR			BIT(0)
415ecafc12S周琰杰 (Zhou Yanjie) #define OSTCR_OST2CLR			BIT(1)
425ecafc12S周琰杰 (Zhou Yanjie) 
435ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTFR register */
445ecafc12S周琰杰 (Zhou Yanjie) #define OSTFR_FFLAG				BIT(0)
455ecafc12S周琰杰 (Zhou Yanjie) 
465ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTMR register */
475ecafc12S周琰杰 (Zhou Yanjie) #define OSTMR_FMASK				BIT(0)
485ecafc12S周琰杰 (Zhou Yanjie) 
495ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTESR register */
505ecafc12S周琰杰 (Zhou Yanjie) #define OSTESR_OST1ENS			BIT(0)
515ecafc12S周琰杰 (Zhou Yanjie) #define OSTESR_OST2ENS			BIT(1)
525ecafc12S周琰杰 (Zhou Yanjie) 
535ecafc12S周琰杰 (Zhou Yanjie) /* bits within the OSTECR register */
545ecafc12S周琰杰 (Zhou Yanjie) #define OSTECR_OST1ENC			BIT(0)
555ecafc12S周琰杰 (Zhou Yanjie) #define OSTECR_OST2ENC			BIT(1)
565ecafc12S周琰杰 (Zhou Yanjie) 
575ecafc12S周琰杰 (Zhou Yanjie) struct ingenic_soc_info {
585ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int num_channels;
595ecafc12S周琰杰 (Zhou Yanjie) };
605ecafc12S周琰杰 (Zhou Yanjie) 
615ecafc12S周琰杰 (Zhou Yanjie) struct ingenic_ost_clk_info {
625ecafc12S周琰杰 (Zhou Yanjie) 	struct clk_init_data init_data;
635ecafc12S周琰杰 (Zhou Yanjie) 	u8 ostccr_reg;
645ecafc12S周琰杰 (Zhou Yanjie) };
655ecafc12S周琰杰 (Zhou Yanjie) 
665ecafc12S周琰杰 (Zhou Yanjie) struct ingenic_ost_clk {
675ecafc12S周琰杰 (Zhou Yanjie) 	struct clk_hw hw;
685ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int idx;
695ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost;
705ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_ost_clk_info *info;
715ecafc12S周琰杰 (Zhou Yanjie) };
725ecafc12S周琰杰 (Zhou Yanjie) 
735ecafc12S周琰杰 (Zhou Yanjie) struct ingenic_ost {
745ecafc12S周琰杰 (Zhou Yanjie) 	void __iomem *base;
755ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_soc_info *soc_info;
765ecafc12S周琰杰 (Zhou Yanjie) 	struct clk *clk, *percpu_timer_clk, *global_timer_clk;
775ecafc12S周琰杰 (Zhou Yanjie) 	struct clock_event_device cevt;
785ecafc12S周琰杰 (Zhou Yanjie) 	struct clocksource cs;
795ecafc12S周琰杰 (Zhou Yanjie) 	char name[20];
805ecafc12S周琰杰 (Zhou Yanjie) 
815ecafc12S周琰杰 (Zhou Yanjie) 	struct clk_hw_onecell_data *clocks;
825ecafc12S周琰杰 (Zhou Yanjie) };
835ecafc12S周琰杰 (Zhou Yanjie) 
845ecafc12S周琰杰 (Zhou Yanjie) static struct ingenic_ost *ingenic_ost;
855ecafc12S周琰杰 (Zhou Yanjie) 
to_ost_clk(struct clk_hw * hw)865ecafc12S周琰杰 (Zhou Yanjie) static inline struct ingenic_ost_clk *to_ost_clk(struct clk_hw *hw)
875ecafc12S周琰杰 (Zhou Yanjie) {
885ecafc12S周琰杰 (Zhou Yanjie) 	return container_of(hw, struct ingenic_ost_clk, hw);
895ecafc12S周琰杰 (Zhou Yanjie) }
905ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_percpu_timer_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)915ecafc12S周琰杰 (Zhou Yanjie) static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw *hw,
925ecafc12S周琰杰 (Zhou Yanjie) 		unsigned long parent_rate)
935ecafc12S周琰杰 (Zhou Yanjie) {
945ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
955ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_ost_clk_info *info = ost_clk->info;
965ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int prescale;
975ecafc12S周琰杰 (Zhou Yanjie) 
985ecafc12S周琰杰 (Zhou Yanjie) 	prescale = readl(ost_clk->ost->base + info->ostccr_reg);
995ecafc12S周琰杰 (Zhou Yanjie) 
100*3b87265dS周琰杰 (Zhou Yanjie) 	prescale = FIELD_GET(OSTCCR_PRESCALE1_MASK, prescale);
1015ecafc12S周琰杰 (Zhou Yanjie) 
1025ecafc12S周琰杰 (Zhou Yanjie) 	return parent_rate >> (prescale * 2);
1035ecafc12S周琰杰 (Zhou Yanjie) }
1045ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_global_timer_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)1055ecafc12S周琰杰 (Zhou Yanjie) static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw *hw,
1065ecafc12S周琰杰 (Zhou Yanjie) 		unsigned long parent_rate)
1075ecafc12S周琰杰 (Zhou Yanjie) {
1085ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
1095ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_ost_clk_info *info = ost_clk->info;
1105ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int prescale;
1115ecafc12S周琰杰 (Zhou Yanjie) 
1125ecafc12S周琰杰 (Zhou Yanjie) 	prescale = readl(ost_clk->ost->base + info->ostccr_reg);
1135ecafc12S周琰杰 (Zhou Yanjie) 
114*3b87265dS周琰杰 (Zhou Yanjie) 	prescale = FIELD_GET(OSTCCR_PRESCALE2_MASK, prescale);
1155ecafc12S周琰杰 (Zhou Yanjie) 
1165ecafc12S周琰杰 (Zhou Yanjie) 	return parent_rate >> (prescale * 2);
1175ecafc12S周琰杰 (Zhou Yanjie) }
1185ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_get_prescale(unsigned long rate,unsigned long req_rate)1195ecafc12S周琰杰 (Zhou Yanjie) static u8 ingenic_ost_get_prescale(unsigned long rate, unsigned long req_rate)
1205ecafc12S周琰杰 (Zhou Yanjie) {
1215ecafc12S周琰杰 (Zhou Yanjie) 	u8 prescale;
1225ecafc12S周琰杰 (Zhou Yanjie) 
1235ecafc12S周琰杰 (Zhou Yanjie) 	for (prescale = 0; prescale < 2; prescale++)
1245ecafc12S周琰杰 (Zhou Yanjie) 		if ((rate >> (prescale * 2)) <= req_rate)
1255ecafc12S周琰杰 (Zhou Yanjie) 			return prescale;
1265ecafc12S周琰杰 (Zhou Yanjie) 
1275ecafc12S周琰杰 (Zhou Yanjie) 	return 2; /* /16 divider */
1285ecafc12S周琰杰 (Zhou Yanjie) }
1295ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_round_rate(struct clk_hw * hw,unsigned long req_rate,unsigned long * parent_rate)1305ecafc12S周琰杰 (Zhou Yanjie) static long ingenic_ost_round_rate(struct clk_hw *hw, unsigned long req_rate,
1315ecafc12S周琰杰 (Zhou Yanjie) 		unsigned long *parent_rate)
1325ecafc12S周琰杰 (Zhou Yanjie) {
1335ecafc12S周琰杰 (Zhou Yanjie) 	unsigned long rate = *parent_rate;
1345ecafc12S周琰杰 (Zhou Yanjie) 	u8 prescale;
1355ecafc12S周琰杰 (Zhou Yanjie) 
1365ecafc12S周琰杰 (Zhou Yanjie) 	if (req_rate > rate)
1375ecafc12S周琰杰 (Zhou Yanjie) 		return rate;
1385ecafc12S周琰杰 (Zhou Yanjie) 
1395ecafc12S周琰杰 (Zhou Yanjie) 	prescale = ingenic_ost_get_prescale(rate, req_rate);
1405ecafc12S周琰杰 (Zhou Yanjie) 
1415ecafc12S周琰杰 (Zhou Yanjie) 	return rate >> (prescale * 2);
1425ecafc12S周琰杰 (Zhou Yanjie) }
1435ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_percpu_timer_set_rate(struct clk_hw * hw,unsigned long req_rate,unsigned long parent_rate)1445ecafc12S周琰杰 (Zhou Yanjie) static int ingenic_ost_percpu_timer_set_rate(struct clk_hw *hw, unsigned long req_rate,
1455ecafc12S周琰杰 (Zhou Yanjie) 		unsigned long parent_rate)
1465ecafc12S周琰杰 (Zhou Yanjie) {
1475ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
1485ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_ost_clk_info *info = ost_clk->info;
1495ecafc12S周琰杰 (Zhou Yanjie) 	u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate);
1505ecafc12S周琰杰 (Zhou Yanjie) 	int val;
1515ecafc12S周琰杰 (Zhou Yanjie) 
1525ecafc12S周琰杰 (Zhou Yanjie) 	val = readl(ost_clk->ost->base + info->ostccr_reg);
153*3b87265dS周琰杰 (Zhou Yanjie) 	val &= ~OSTCCR_PRESCALE1_MASK;
154*3b87265dS周琰杰 (Zhou Yanjie) 	val |= FIELD_PREP(OSTCCR_PRESCALE1_MASK, prescale);
1555ecafc12S周琰杰 (Zhou Yanjie) 	writel(val, ost_clk->ost->base + info->ostccr_reg);
1565ecafc12S周琰杰 (Zhou Yanjie) 
1575ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
1585ecafc12S周琰杰 (Zhou Yanjie) }
1595ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_global_timer_set_rate(struct clk_hw * hw,unsigned long req_rate,unsigned long parent_rate)1605ecafc12S周琰杰 (Zhou Yanjie) static int ingenic_ost_global_timer_set_rate(struct clk_hw *hw, unsigned long req_rate,
1615ecafc12S周琰杰 (Zhou Yanjie) 		unsigned long parent_rate)
1625ecafc12S周琰杰 (Zhou Yanjie) {
1635ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
1645ecafc12S周琰杰 (Zhou Yanjie) 	const struct ingenic_ost_clk_info *info = ost_clk->info;
1655ecafc12S周琰杰 (Zhou Yanjie) 	u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate);
1665ecafc12S周琰杰 (Zhou Yanjie) 	int val;
1675ecafc12S周琰杰 (Zhou Yanjie) 
1685ecafc12S周琰杰 (Zhou Yanjie) 	val = readl(ost_clk->ost->base + info->ostccr_reg);
169*3b87265dS周琰杰 (Zhou Yanjie) 	val &= ~OSTCCR_PRESCALE2_MASK;
170*3b87265dS周琰杰 (Zhou Yanjie) 	val |= FIELD_PREP(OSTCCR_PRESCALE2_MASK, prescale);
1715ecafc12S周琰杰 (Zhou Yanjie) 	writel(val, ost_clk->ost->base + info->ostccr_reg);
1725ecafc12S周琰杰 (Zhou Yanjie) 
1735ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
1745ecafc12S周琰杰 (Zhou Yanjie) }
1755ecafc12S周琰杰 (Zhou Yanjie) 
1765ecafc12S周琰杰 (Zhou Yanjie) static const struct clk_ops ingenic_ost_percpu_timer_ops = {
1775ecafc12S周琰杰 (Zhou Yanjie) 	.recalc_rate	= ingenic_ost_percpu_timer_recalc_rate,
1785ecafc12S周琰杰 (Zhou Yanjie) 	.round_rate		= ingenic_ost_round_rate,
1795ecafc12S周琰杰 (Zhou Yanjie) 	.set_rate		= ingenic_ost_percpu_timer_set_rate,
1805ecafc12S周琰杰 (Zhou Yanjie) };
1815ecafc12S周琰杰 (Zhou Yanjie) 
1825ecafc12S周琰杰 (Zhou Yanjie) static const struct clk_ops ingenic_ost_global_timer_ops = {
1835ecafc12S周琰杰 (Zhou Yanjie) 	.recalc_rate	= ingenic_ost_global_timer_recalc_rate,
1845ecafc12S周琰杰 (Zhou Yanjie) 	.round_rate		= ingenic_ost_round_rate,
1855ecafc12S周琰杰 (Zhou Yanjie) 	.set_rate		= ingenic_ost_global_timer_set_rate,
1865ecafc12S周琰杰 (Zhou Yanjie) };
1875ecafc12S周琰杰 (Zhou Yanjie) 
1885ecafc12S周琰杰 (Zhou Yanjie) static const char * const ingenic_ost_clk_parents[] = { "ext" };
1895ecafc12S周琰杰 (Zhou Yanjie) 
190870a6e15S周琰杰 (Zhou Yanjie) static const struct ingenic_ost_clk_info x1000_ost_clk_info[] = {
1915ecafc12S周琰杰 (Zhou Yanjie) 	[OST_CLK_PERCPU_TIMER] = {
1925ecafc12S周琰杰 (Zhou Yanjie) 		.init_data = {
1935ecafc12S周琰杰 (Zhou Yanjie) 			.name = "percpu timer",
1945ecafc12S周琰杰 (Zhou Yanjie) 			.parent_names = ingenic_ost_clk_parents,
1955ecafc12S周琰杰 (Zhou Yanjie) 			.num_parents = ARRAY_SIZE(ingenic_ost_clk_parents),
1965ecafc12S周琰杰 (Zhou Yanjie) 			.ops = &ingenic_ost_percpu_timer_ops,
1975ecafc12S周琰杰 (Zhou Yanjie) 			.flags = CLK_SET_RATE_UNGATE,
1985ecafc12S周琰杰 (Zhou Yanjie) 		},
1995ecafc12S周琰杰 (Zhou Yanjie) 		.ostccr_reg = OST_REG_OSTCCR,
2005ecafc12S周琰杰 (Zhou Yanjie) 	},
2015ecafc12S周琰杰 (Zhou Yanjie) 
2025ecafc12S周琰杰 (Zhou Yanjie) 	[OST_CLK_GLOBAL_TIMER] = {
2035ecafc12S周琰杰 (Zhou Yanjie) 		.init_data = {
2045ecafc12S周琰杰 (Zhou Yanjie) 			.name = "global timer",
2055ecafc12S周琰杰 (Zhou Yanjie) 			.parent_names = ingenic_ost_clk_parents,
2065ecafc12S周琰杰 (Zhou Yanjie) 			.num_parents = ARRAY_SIZE(ingenic_ost_clk_parents),
2075ecafc12S周琰杰 (Zhou Yanjie) 			.ops = &ingenic_ost_global_timer_ops,
2085ecafc12S周琰杰 (Zhou Yanjie) 			.flags = CLK_SET_RATE_UNGATE,
2095ecafc12S周琰杰 (Zhou Yanjie) 		},
2105ecafc12S周琰杰 (Zhou Yanjie) 		.ostccr_reg = OST_REG_OSTCCR,
2115ecafc12S周琰杰 (Zhou Yanjie) 	},
2125ecafc12S周琰杰 (Zhou Yanjie) };
2135ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_global_timer_read_cntl(void)2145ecafc12S周琰杰 (Zhou Yanjie) static u64 notrace ingenic_ost_global_timer_read_cntl(void)
2155ecafc12S周琰杰 (Zhou Yanjie) {
2165ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost = ingenic_ost;
2175ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int count;
2185ecafc12S周琰杰 (Zhou Yanjie) 
2195ecafc12S周琰杰 (Zhou Yanjie) 	count = readl(ost->base + OST_REG_OST2CNTL);
2205ecafc12S周琰杰 (Zhou Yanjie) 
2215ecafc12S周琰杰 (Zhou Yanjie) 	return count;
2225ecafc12S周琰杰 (Zhou Yanjie) }
2235ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_clocksource_read(struct clocksource * cs)2245ecafc12S周琰杰 (Zhou Yanjie) static u64 notrace ingenic_ost_clocksource_read(struct clocksource *cs)
2255ecafc12S周琰杰 (Zhou Yanjie) {
2265ecafc12S周琰杰 (Zhou Yanjie) 	return ingenic_ost_global_timer_read_cntl();
2275ecafc12S周琰杰 (Zhou Yanjie) }
2285ecafc12S周琰杰 (Zhou Yanjie) 
to_ingenic_ost(struct clock_event_device * evt)2295ecafc12S周琰杰 (Zhou Yanjie) static inline struct ingenic_ost *to_ingenic_ost(struct clock_event_device *evt)
2305ecafc12S周琰杰 (Zhou Yanjie) {
2315ecafc12S周琰杰 (Zhou Yanjie) 	return container_of(evt, struct ingenic_ost, cevt);
2325ecafc12S周琰杰 (Zhou Yanjie) }
2335ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_cevt_set_state_shutdown(struct clock_event_device * evt)2345ecafc12S周琰杰 (Zhou Yanjie) static int ingenic_ost_cevt_set_state_shutdown(struct clock_event_device *evt)
2355ecafc12S周琰杰 (Zhou Yanjie) {
2365ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost = to_ingenic_ost(evt);
2375ecafc12S周琰杰 (Zhou Yanjie) 
2385ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR);
2395ecafc12S周琰杰 (Zhou Yanjie) 
2405ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
2415ecafc12S周琰杰 (Zhou Yanjie) }
2425ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_cevt_set_next(unsigned long next,struct clock_event_device * evt)2435ecafc12S周琰杰 (Zhou Yanjie) static int ingenic_ost_cevt_set_next(unsigned long next,
2445ecafc12S周琰杰 (Zhou Yanjie) 				     struct clock_event_device *evt)
2455ecafc12S周琰杰 (Zhou Yanjie) {
2465ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost = to_ingenic_ost(evt);
2475ecafc12S周琰杰 (Zhou Yanjie) 
2485ecafc12S周琰杰 (Zhou Yanjie) 	writel((u32)~OSTFR_FFLAG, ost->base + OST_REG_OSTFR);
2495ecafc12S周琰杰 (Zhou Yanjie) 	writel(next, ost->base + OST_REG_OST1DFR);
2505ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTCR_OST1CLR, ost->base + OST_REG_OSTCR);
2515ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTESR_OST1ENS, ost->base + OST_REG_OSTESR);
2525ecafc12S周琰杰 (Zhou Yanjie) 	writel((u32)~OSTMR_FMASK, ost->base + OST_REG_OSTMR);
2535ecafc12S周琰杰 (Zhou Yanjie) 
2545ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
2555ecafc12S周琰杰 (Zhou Yanjie) }
2565ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_cevt_cb(int irq,void * dev_id)2575ecafc12S周琰杰 (Zhou Yanjie) static irqreturn_t ingenic_ost_cevt_cb(int irq, void *dev_id)
2585ecafc12S周琰杰 (Zhou Yanjie) {
2595ecafc12S周琰杰 (Zhou Yanjie) 	struct clock_event_device *evt = dev_id;
2605ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost = to_ingenic_ost(evt);
2615ecafc12S周琰杰 (Zhou Yanjie) 
2625ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR);
2635ecafc12S周琰杰 (Zhou Yanjie) 
2645ecafc12S周琰杰 (Zhou Yanjie) 	if (evt->event_handler)
2655ecafc12S周琰杰 (Zhou Yanjie) 		evt->event_handler(evt);
2665ecafc12S周琰杰 (Zhou Yanjie) 
2675ecafc12S周琰杰 (Zhou Yanjie) 	return IRQ_HANDLED;
2685ecafc12S周琰杰 (Zhou Yanjie) }
2695ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_register_clock(struct ingenic_ost * ost,unsigned int idx,const struct ingenic_ost_clk_info * info,struct clk_hw_onecell_data * clocks)2705ecafc12S周琰杰 (Zhou Yanjie) static int __init ingenic_ost_register_clock(struct ingenic_ost *ost,
2715ecafc12S周琰杰 (Zhou Yanjie) 			unsigned int idx, const struct ingenic_ost_clk_info *info,
2725ecafc12S周琰杰 (Zhou Yanjie) 			struct clk_hw_onecell_data *clocks)
2735ecafc12S周琰杰 (Zhou Yanjie) {
2745ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost_clk *ost_clk;
2755ecafc12S周琰杰 (Zhou Yanjie) 	int val, err;
2765ecafc12S周琰杰 (Zhou Yanjie) 
2775ecafc12S周琰杰 (Zhou Yanjie) 	ost_clk = kzalloc(sizeof(*ost_clk), GFP_KERNEL);
2785ecafc12S周琰杰 (Zhou Yanjie) 	if (!ost_clk)
2795ecafc12S周琰杰 (Zhou Yanjie) 		return -ENOMEM;
2805ecafc12S周琰杰 (Zhou Yanjie) 
2815ecafc12S周琰杰 (Zhou Yanjie) 	ost_clk->hw.init = &info->init_data;
2825ecafc12S周琰杰 (Zhou Yanjie) 	ost_clk->idx = idx;
2835ecafc12S周琰杰 (Zhou Yanjie) 	ost_clk->info = info;
2845ecafc12S周琰杰 (Zhou Yanjie) 	ost_clk->ost = ost;
2855ecafc12S周琰杰 (Zhou Yanjie) 
2865ecafc12S周琰杰 (Zhou Yanjie) 	/* Reset clock divider */
2875ecafc12S周琰杰 (Zhou Yanjie) 	val = readl(ost->base + info->ostccr_reg);
2885ecafc12S周琰杰 (Zhou Yanjie) 	val &= ~(OSTCCR_PRESCALE1_MASK | OSTCCR_PRESCALE2_MASK);
2895ecafc12S周琰杰 (Zhou Yanjie) 	writel(val, ost->base + info->ostccr_reg);
2905ecafc12S周琰杰 (Zhou Yanjie) 
2915ecafc12S周琰杰 (Zhou Yanjie) 	err = clk_hw_register(NULL, &ost_clk->hw);
2925ecafc12S周琰杰 (Zhou Yanjie) 	if (err) {
2935ecafc12S周琰杰 (Zhou Yanjie) 		kfree(ost_clk);
2945ecafc12S周琰杰 (Zhou Yanjie) 		return err;
2955ecafc12S周琰杰 (Zhou Yanjie) 	}
2965ecafc12S周琰杰 (Zhou Yanjie) 
2975ecafc12S周琰杰 (Zhou Yanjie) 	clocks->hws[idx] = &ost_clk->hw;
2985ecafc12S周琰杰 (Zhou Yanjie) 
2995ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
3005ecafc12S周琰杰 (Zhou Yanjie) }
3015ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_get_clock(struct device_node * np,int id)3025ecafc12S周琰杰 (Zhou Yanjie) static struct clk * __init ingenic_ost_get_clock(struct device_node *np, int id)
3035ecafc12S周琰杰 (Zhou Yanjie) {
3045ecafc12S周琰杰 (Zhou Yanjie) 	struct of_phandle_args args;
3055ecafc12S周琰杰 (Zhou Yanjie) 
3065ecafc12S周琰杰 (Zhou Yanjie) 	args.np = np;
3075ecafc12S周琰杰 (Zhou Yanjie) 	args.args_count = 1;
3085ecafc12S周琰杰 (Zhou Yanjie) 	args.args[0] = id;
3095ecafc12S周琰杰 (Zhou Yanjie) 
3105ecafc12S周琰杰 (Zhou Yanjie) 	return of_clk_get_from_provider(&args);
3115ecafc12S周琰杰 (Zhou Yanjie) }
3125ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_percpu_timer_init(struct device_node * np,struct ingenic_ost * ost)3135ecafc12S周琰杰 (Zhou Yanjie) static int __init ingenic_ost_percpu_timer_init(struct device_node *np,
3145ecafc12S周琰杰 (Zhou Yanjie) 					 struct ingenic_ost *ost)
3155ecafc12S周琰杰 (Zhou Yanjie) {
3165ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int timer_virq, channel = OST_CLK_PERCPU_TIMER;
3175ecafc12S周琰杰 (Zhou Yanjie) 	unsigned long rate;
3185ecafc12S周琰杰 (Zhou Yanjie) 	int err;
3195ecafc12S周琰杰 (Zhou Yanjie) 
3205ecafc12S周琰杰 (Zhou Yanjie) 	ost->percpu_timer_clk = ingenic_ost_get_clock(np, channel);
3215ecafc12S周琰杰 (Zhou Yanjie) 	if (IS_ERR(ost->percpu_timer_clk))
3225ecafc12S周琰杰 (Zhou Yanjie) 		return PTR_ERR(ost->percpu_timer_clk);
3235ecafc12S周琰杰 (Zhou Yanjie) 
3245ecafc12S周琰杰 (Zhou Yanjie) 	err = clk_prepare_enable(ost->percpu_timer_clk);
3255ecafc12S周琰杰 (Zhou Yanjie) 	if (err)
3265ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_put;
3275ecafc12S周琰杰 (Zhou Yanjie) 
3285ecafc12S周琰杰 (Zhou Yanjie) 	rate = clk_get_rate(ost->percpu_timer_clk);
3295ecafc12S周琰杰 (Zhou Yanjie) 	if (!rate) {
3305ecafc12S周琰杰 (Zhou Yanjie) 		err = -EINVAL;
3315ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_disable;
3325ecafc12S周琰杰 (Zhou Yanjie) 	}
3335ecafc12S周琰杰 (Zhou Yanjie) 
3345ecafc12S周琰杰 (Zhou Yanjie) 	timer_virq = of_irq_get(np, 0);
3355ecafc12S周琰杰 (Zhou Yanjie) 	if (!timer_virq) {
3365ecafc12S周琰杰 (Zhou Yanjie) 		err = -EINVAL;
3375ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_disable;
3385ecafc12S周琰杰 (Zhou Yanjie) 	}
3395ecafc12S周琰杰 (Zhou Yanjie) 
3405ecafc12S周琰杰 (Zhou Yanjie) 	snprintf(ost->name, sizeof(ost->name), "OST percpu timer");
3415ecafc12S周琰杰 (Zhou Yanjie) 
3425ecafc12S周琰杰 (Zhou Yanjie) 	err = request_irq(timer_virq, ingenic_ost_cevt_cb, IRQF_TIMER,
3435ecafc12S周琰杰 (Zhou Yanjie) 			  ost->name, &ost->cevt);
3445ecafc12S周琰杰 (Zhou Yanjie) 	if (err)
3455ecafc12S周琰杰 (Zhou Yanjie) 		goto err_irq_dispose_mapping;
3465ecafc12S周琰杰 (Zhou Yanjie) 
3475ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.cpumask = cpumask_of(smp_processor_id());
3485ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.features = CLOCK_EVT_FEAT_ONESHOT;
3495ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.name = ost->name;
3505ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.rating = 400;
3515ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.set_state_shutdown = ingenic_ost_cevt_set_state_shutdown;
3525ecafc12S周琰杰 (Zhou Yanjie) 	ost->cevt.set_next_event = ingenic_ost_cevt_set_next;
3535ecafc12S周琰杰 (Zhou Yanjie) 
3545ecafc12S周琰杰 (Zhou Yanjie) 	clockevents_config_and_register(&ost->cevt, rate, 4, 0xffffffff);
3555ecafc12S周琰杰 (Zhou Yanjie) 
3565ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
3575ecafc12S周琰杰 (Zhou Yanjie) 
3585ecafc12S周琰杰 (Zhou Yanjie) err_irq_dispose_mapping:
3595ecafc12S周琰杰 (Zhou Yanjie) 	irq_dispose_mapping(timer_virq);
3605ecafc12S周琰杰 (Zhou Yanjie) err_clk_disable:
3615ecafc12S周琰杰 (Zhou Yanjie) 	clk_disable_unprepare(ost->percpu_timer_clk);
3625ecafc12S周琰杰 (Zhou Yanjie) err_clk_put:
3635ecafc12S周琰杰 (Zhou Yanjie) 	clk_put(ost->percpu_timer_clk);
3645ecafc12S周琰杰 (Zhou Yanjie) 	return err;
3655ecafc12S周琰杰 (Zhou Yanjie) }
3665ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_global_timer_init(struct device_node * np,struct ingenic_ost * ost)3675ecafc12S周琰杰 (Zhou Yanjie) static int __init ingenic_ost_global_timer_init(struct device_node *np,
3685ecafc12S周琰杰 (Zhou Yanjie) 					       struct ingenic_ost *ost)
3695ecafc12S周琰杰 (Zhou Yanjie) {
3705ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int channel = OST_CLK_GLOBAL_TIMER;
3715ecafc12S周琰杰 (Zhou Yanjie) 	struct clocksource *cs = &ost->cs;
3725ecafc12S周琰杰 (Zhou Yanjie) 	unsigned long rate;
3735ecafc12S周琰杰 (Zhou Yanjie) 	int err;
3745ecafc12S周琰杰 (Zhou Yanjie) 
3755ecafc12S周琰杰 (Zhou Yanjie) 	ost->global_timer_clk = ingenic_ost_get_clock(np, channel);
3765ecafc12S周琰杰 (Zhou Yanjie) 	if (IS_ERR(ost->global_timer_clk))
3775ecafc12S周琰杰 (Zhou Yanjie) 		return PTR_ERR(ost->global_timer_clk);
3785ecafc12S周琰杰 (Zhou Yanjie) 
3795ecafc12S周琰杰 (Zhou Yanjie) 	err = clk_prepare_enable(ost->global_timer_clk);
3805ecafc12S周琰杰 (Zhou Yanjie) 	if (err)
3815ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_put;
3825ecafc12S周琰杰 (Zhou Yanjie) 
3835ecafc12S周琰杰 (Zhou Yanjie) 	rate = clk_get_rate(ost->global_timer_clk);
3845ecafc12S周琰杰 (Zhou Yanjie) 	if (!rate) {
3855ecafc12S周琰杰 (Zhou Yanjie) 		err = -EINVAL;
3865ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_disable;
3875ecafc12S周琰杰 (Zhou Yanjie) 	}
3885ecafc12S周琰杰 (Zhou Yanjie) 
3895ecafc12S周琰杰 (Zhou Yanjie) 	/* Clear counter CNT registers */
3905ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTCR_OST2CLR, ost->base + OST_REG_OSTCR);
3915ecafc12S周琰杰 (Zhou Yanjie) 
3925ecafc12S周琰杰 (Zhou Yanjie) 	/* Enable OST channel */
3935ecafc12S周琰杰 (Zhou Yanjie) 	writel(OSTESR_OST2ENS, ost->base + OST_REG_OSTESR);
3945ecafc12S周琰杰 (Zhou Yanjie) 
3955ecafc12S周琰杰 (Zhou Yanjie) 	cs->name = "ingenic-ost";
3965ecafc12S周琰杰 (Zhou Yanjie) 	cs->rating = 400;
3975ecafc12S周琰杰 (Zhou Yanjie) 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
3985ecafc12S周琰杰 (Zhou Yanjie) 	cs->mask = CLOCKSOURCE_MASK(32);
3995ecafc12S周琰杰 (Zhou Yanjie) 	cs->read = ingenic_ost_clocksource_read;
4005ecafc12S周琰杰 (Zhou Yanjie) 
4015ecafc12S周琰杰 (Zhou Yanjie) 	err = clocksource_register_hz(cs, rate);
4025ecafc12S周琰杰 (Zhou Yanjie) 	if (err)
4035ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_disable;
4045ecafc12S周琰杰 (Zhou Yanjie) 
4055ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
4065ecafc12S周琰杰 (Zhou Yanjie) 
4075ecafc12S周琰杰 (Zhou Yanjie) err_clk_disable:
4085ecafc12S周琰杰 (Zhou Yanjie) 	clk_disable_unprepare(ost->global_timer_clk);
4095ecafc12S周琰杰 (Zhou Yanjie) err_clk_put:
4105ecafc12S周琰杰 (Zhou Yanjie) 	clk_put(ost->global_timer_clk);
4115ecafc12S周琰杰 (Zhou Yanjie) 	return err;
4125ecafc12S周琰杰 (Zhou Yanjie) }
4135ecafc12S周琰杰 (Zhou Yanjie) 
4145ecafc12S周琰杰 (Zhou Yanjie) static const struct ingenic_soc_info x1000_soc_info = {
4155ecafc12S周琰杰 (Zhou Yanjie) 	.num_channels = 2,
4165ecafc12S周琰杰 (Zhou Yanjie) };
4175ecafc12S周琰杰 (Zhou Yanjie) 
418870a6e15S周琰杰 (Zhou Yanjie) static const struct of_device_id __maybe_unused ingenic_ost_of_matches[] __initconst = {
419870a6e15S周琰杰 (Zhou Yanjie) 	{ .compatible = "ingenic,x1000-ost", .data = &x1000_soc_info },
4205ecafc12S周琰杰 (Zhou Yanjie) 	{ /* sentinel */ }
4215ecafc12S周琰杰 (Zhou Yanjie) };
4225ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_probe(struct device_node * np)4235ecafc12S周琰杰 (Zhou Yanjie) static int __init ingenic_ost_probe(struct device_node *np)
4245ecafc12S周琰杰 (Zhou Yanjie) {
425870a6e15S周琰杰 (Zhou Yanjie) 	const struct of_device_id *id = of_match_node(ingenic_ost_of_matches, np);
4265ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost;
4275ecafc12S周琰杰 (Zhou Yanjie) 	unsigned int i;
4285ecafc12S周琰杰 (Zhou Yanjie) 	int ret;
4295ecafc12S周琰杰 (Zhou Yanjie) 
4305ecafc12S周琰杰 (Zhou Yanjie) 	ost = kzalloc(sizeof(*ost), GFP_KERNEL);
4315ecafc12S周琰杰 (Zhou Yanjie) 	if (!ost)
4325ecafc12S周琰杰 (Zhou Yanjie) 		return -ENOMEM;
4335ecafc12S周琰杰 (Zhou Yanjie) 
4345ecafc12S周琰杰 (Zhou Yanjie) 	ost->base = of_io_request_and_map(np, 0, of_node_full_name(np));
4355ecafc12S周琰杰 (Zhou Yanjie) 	if (IS_ERR(ost->base)) {
4365ecafc12S周琰杰 (Zhou Yanjie) 		pr_err("%s: Failed to map OST registers\n", __func__);
4375ecafc12S周琰杰 (Zhou Yanjie) 		ret = PTR_ERR(ost->base);
4385ecafc12S周琰杰 (Zhou Yanjie) 		goto err_free_ost;
4395ecafc12S周琰杰 (Zhou Yanjie) 	}
4405ecafc12S周琰杰 (Zhou Yanjie) 
4415ecafc12S周琰杰 (Zhou Yanjie) 	ost->clk = of_clk_get_by_name(np, "ost");
4425ecafc12S周琰杰 (Zhou Yanjie) 	if (IS_ERR(ost->clk)) {
4435ecafc12S周琰杰 (Zhou Yanjie) 		ret = PTR_ERR(ost->clk);
4445ecafc12S周琰杰 (Zhou Yanjie) 		pr_crit("%s: Cannot get OST clock\n", __func__);
4455ecafc12S周琰杰 (Zhou Yanjie) 		goto err_free_ost;
4465ecafc12S周琰杰 (Zhou Yanjie) 	}
4475ecafc12S周琰杰 (Zhou Yanjie) 
4485ecafc12S周琰杰 (Zhou Yanjie) 	ret = clk_prepare_enable(ost->clk);
4495ecafc12S周琰杰 (Zhou Yanjie) 	if (ret) {
4505ecafc12S周琰杰 (Zhou Yanjie) 		pr_crit("%s: Unable to enable OST clock\n", __func__);
4515ecafc12S周琰杰 (Zhou Yanjie) 		goto err_put_clk;
4525ecafc12S周琰杰 (Zhou Yanjie) 	}
4535ecafc12S周琰杰 (Zhou Yanjie) 
4545ecafc12S周琰杰 (Zhou Yanjie) 	ost->soc_info = id->data;
4555ecafc12S周琰杰 (Zhou Yanjie) 
4565ecafc12S周琰杰 (Zhou Yanjie) 	ost->clocks = kzalloc(struct_size(ost->clocks, hws, ost->soc_info->num_channels),
4575ecafc12S周琰杰 (Zhou Yanjie) 			      GFP_KERNEL);
4585ecafc12S周琰杰 (Zhou Yanjie) 	if (!ost->clocks) {
4595ecafc12S周琰杰 (Zhou Yanjie) 		ret = -ENOMEM;
4605ecafc12S周琰杰 (Zhou Yanjie) 		goto err_clk_disable;
4615ecafc12S周琰杰 (Zhou Yanjie) 	}
4625ecafc12S周琰杰 (Zhou Yanjie) 
4635ecafc12S周琰杰 (Zhou Yanjie) 	ost->clocks->num = ost->soc_info->num_channels;
4645ecafc12S周琰杰 (Zhou Yanjie) 
4655ecafc12S周琰杰 (Zhou Yanjie) 	for (i = 0; i < ost->clocks->num; i++) {
466870a6e15S周琰杰 (Zhou Yanjie) 		ret = ingenic_ost_register_clock(ost, i, &x1000_ost_clk_info[i], ost->clocks);
4675ecafc12S周琰杰 (Zhou Yanjie) 		if (ret) {
4685ecafc12S周琰杰 (Zhou Yanjie) 			pr_crit("%s: Cannot register clock %d\n", __func__, i);
4695ecafc12S周琰杰 (Zhou Yanjie) 			goto err_unregister_ost_clocks;
4705ecafc12S周琰杰 (Zhou Yanjie) 		}
4715ecafc12S周琰杰 (Zhou Yanjie) 	}
4725ecafc12S周琰杰 (Zhou Yanjie) 
4735ecafc12S周琰杰 (Zhou Yanjie) 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, ost->clocks);
4745ecafc12S周琰杰 (Zhou Yanjie) 	if (ret) {
4755ecafc12S周琰杰 (Zhou Yanjie) 		pr_crit("%s: Cannot add OF clock provider\n", __func__);
4765ecafc12S周琰杰 (Zhou Yanjie) 		goto err_unregister_ost_clocks;
4775ecafc12S周琰杰 (Zhou Yanjie) 	}
4785ecafc12S周琰杰 (Zhou Yanjie) 
4795ecafc12S周琰杰 (Zhou Yanjie) 	ingenic_ost = ost;
4805ecafc12S周琰杰 (Zhou Yanjie) 
4815ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
4825ecafc12S周琰杰 (Zhou Yanjie) 
4835ecafc12S周琰杰 (Zhou Yanjie) err_unregister_ost_clocks:
4845ecafc12S周琰杰 (Zhou Yanjie) 	for (i = 0; i < ost->clocks->num; i++)
4855ecafc12S周琰杰 (Zhou Yanjie) 		if (ost->clocks->hws[i])
4865ecafc12S周琰杰 (Zhou Yanjie) 			clk_hw_unregister(ost->clocks->hws[i]);
4875ecafc12S周琰杰 (Zhou Yanjie) 	kfree(ost->clocks);
4885ecafc12S周琰杰 (Zhou Yanjie) err_clk_disable:
4895ecafc12S周琰杰 (Zhou Yanjie) 	clk_disable_unprepare(ost->clk);
4905ecafc12S周琰杰 (Zhou Yanjie) err_put_clk:
4915ecafc12S周琰杰 (Zhou Yanjie) 	clk_put(ost->clk);
4925ecafc12S周琰杰 (Zhou Yanjie) err_free_ost:
4935ecafc12S周琰杰 (Zhou Yanjie) 	kfree(ost);
4945ecafc12S周琰杰 (Zhou Yanjie) 	return ret;
4955ecafc12S周琰杰 (Zhou Yanjie) }
4965ecafc12S周琰杰 (Zhou Yanjie) 
ingenic_ost_init(struct device_node * np)4975ecafc12S周琰杰 (Zhou Yanjie) static int __init ingenic_ost_init(struct device_node *np)
4985ecafc12S周琰杰 (Zhou Yanjie) {
4995ecafc12S周琰杰 (Zhou Yanjie) 	struct ingenic_ost *ost;
5005ecafc12S周琰杰 (Zhou Yanjie) 	unsigned long rate;
5015ecafc12S周琰杰 (Zhou Yanjie) 	int ret;
5025ecafc12S周琰杰 (Zhou Yanjie) 
5035ecafc12S周琰杰 (Zhou Yanjie) 	ret = ingenic_ost_probe(np);
5045ecafc12S周琰杰 (Zhou Yanjie) 	if (ret) {
5055ecafc12S周琰杰 (Zhou Yanjie) 		pr_crit("%s: Failed to initialize OST clocks: %d\n", __func__, ret);
5065ecafc12S周琰杰 (Zhou Yanjie) 		return ret;
5075ecafc12S周琰杰 (Zhou Yanjie) 	}
5085ecafc12S周琰杰 (Zhou Yanjie) 
5095ecafc12S周琰杰 (Zhou Yanjie) 	of_node_clear_flag(np, OF_POPULATED);
5105ecafc12S周琰杰 (Zhou Yanjie) 
5115ecafc12S周琰杰 (Zhou Yanjie) 	ost = ingenic_ost;
5125ecafc12S周琰杰 (Zhou Yanjie) 	if (IS_ERR(ost))
5135ecafc12S周琰杰 (Zhou Yanjie) 		return PTR_ERR(ost);
5145ecafc12S周琰杰 (Zhou Yanjie) 
5155ecafc12S周琰杰 (Zhou Yanjie) 	ret = ingenic_ost_global_timer_init(np, ost);
5165ecafc12S周琰杰 (Zhou Yanjie) 	if (ret) {
5175ecafc12S周琰杰 (Zhou Yanjie) 		pr_crit("%s: Unable to init global timer: %x\n", __func__, ret);
5185ecafc12S周琰杰 (Zhou Yanjie) 		goto err_free_ingenic_ost;
5195ecafc12S周琰杰 (Zhou Yanjie) 	}
5205ecafc12S周琰杰 (Zhou Yanjie) 
5215ecafc12S周琰杰 (Zhou Yanjie) 	ret = ingenic_ost_percpu_timer_init(np, ost);
5225ecafc12S周琰杰 (Zhou Yanjie) 	if (ret)
5235ecafc12S周琰杰 (Zhou Yanjie) 		goto err_ost_global_timer_cleanup;
5245ecafc12S周琰杰 (Zhou Yanjie) 
5255ecafc12S周琰杰 (Zhou Yanjie) 	/* Register the sched_clock at the end as there's no way to undo it */
5265ecafc12S周琰杰 (Zhou Yanjie) 	rate = clk_get_rate(ost->global_timer_clk);
5275ecafc12S周琰杰 (Zhou Yanjie) 	sched_clock_register(ingenic_ost_global_timer_read_cntl, 32, rate);
5285ecafc12S周琰杰 (Zhou Yanjie) 
5295ecafc12S周琰杰 (Zhou Yanjie) 	return 0;
5305ecafc12S周琰杰 (Zhou Yanjie) 
5315ecafc12S周琰杰 (Zhou Yanjie) err_ost_global_timer_cleanup:
5325ecafc12S周琰杰 (Zhou Yanjie) 	clocksource_unregister(&ost->cs);
5335ecafc12S周琰杰 (Zhou Yanjie) 	clk_disable_unprepare(ost->global_timer_clk);
5345ecafc12S周琰杰 (Zhou Yanjie) 	clk_put(ost->global_timer_clk);
5355ecafc12S周琰杰 (Zhou Yanjie) err_free_ingenic_ost:
5365ecafc12S周琰杰 (Zhou Yanjie) 	kfree(ost);
5375ecafc12S周琰杰 (Zhou Yanjie) 	return ret;
5385ecafc12S周琰杰 (Zhou Yanjie) }
5395ecafc12S周琰杰 (Zhou Yanjie) 
5405ecafc12S周琰杰 (Zhou Yanjie) TIMER_OF_DECLARE(x1000_ost,  "ingenic,x1000-ost",  ingenic_ost_init);
541