Procházet zdrojové kódy

waterDataStatisticsCrossAssociation rtuDataOperation.c 李欣儒 commit at 2021-01-28

李欣儒 před 4 roky
rodič
revize
a09768218e

+ 193 - 0
waterDataStatisticsCrossAssociation/databaseOperation/rtuDataOperation.c

@@ -321,3 +321,196 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 	clkev.errata = omap_dm_timer_get_errata();
 
 	/*
+	 * For clock-event timers we never read the timer counter and
+	 * so we are not impacted by errata i103 and i767. Therefore,
+	 * we can safely ignore this errata for clock-event timers.
+	 */
+	__omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
+
+	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
+				     OMAP_TIMER_POSTED);
+	BUG_ON(res);
+
+	omap2_gp_timer_irq.dev_id = &clkev;
+	setup_irq(clkev.irq, &omap2_gp_timer_irq);
+
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+
+	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
+				     clockevent_gpt.shift);
+	clockevent_gpt.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
+	clockevent_gpt.min_delta_ns =
+		clockevent_delta2ns(3, &clockevent_gpt);
+		/* Timer internal resynch latency. */
+
+	clockevent_gpt.cpumask = cpu_possible_mask;
+	clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
+	clockevents_register_device(&clockevent_gpt);
+
+	pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
+		gptimer_id, clkev.rate);
+}
+
+/* Clocksource code */
+static struct omap_dm_timer clksrc;
+static bool use_gptimer_clksrc;
+
+/*
+ * clocksource
+ */
+static cycle_t clocksource_read_cycles(struct clocksource *cs)
+{
+	return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
+						     OMAP_TIMER_NONPOSTED);
+}
+
+static struct clocksource clocksource_gpt = {
+	.name		= "gp_timer",
+	.rating		= 300,
+	.read		= clocksource_read_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 notrace dmtimer_read_sched_clock(void)
+{
+	if (clksrc.reserved)
+		return __omap_dm_timer_read_counter(&clksrc,
+						    OMAP_TIMER_NONPOSTED);
+
+	return 0;
+}
+
+static struct of_device_id omap_counter_match[] __initdata = {
+	{ .compatible = "ti,omap-counter32k", },
+	{ }
+};
+
+/* Setup free-running counter for clocksource */
+static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
+{
+	int ret;
+	struct device_node *np = NULL;
+	struct omap_hwmod *oh;
+	void __iomem *vbase;
+	const char *oh_name = "counter_32k";
+
+	/*
+	 * If device-tree is present, then search the DT blob
+	 * to see if the 32kHz counter is supported.
+	 */
+	if (of_have_populated_dt()) {
+		np = omap_get_timer_dt(omap_counter_match, NULL);
+		if (!np)
+			return -ENODEV;
+
+		of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
+		if (!oh_name)
+			return -ENODEV;
+	}
+
+	/*
+	 * First check hwmod data is available for sync32k counter
+	 */
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh || oh->slaves_cnt == 0)
+		return -ENODEV;
+
+	omap_hwmod_setup_one(oh_name);
+
+	if (np) {
+		vbase = of_iomap(np, 0);
+		of_node_put(np);
+	} else {
+		vbase = omap_hwmod_get_mpu_rt_va(oh);
+	}
+
+	if (!vbase) {
+		pr_warn("%s: failed to get counter_32k resource\n", __func__);
+		return -ENXIO;
+	}
+
+	ret = omap_hwmod_enable(oh);
+	if (ret) {
+		pr_warn("%s: failed to enable counter_32k module (%d)\n",
+							__func__, ret);
+		return ret;
+	}
+
+	ret = omap_init_clocksource_32k(vbase);
+	if (ret) {
+		pr_warn("%s: failed to initialize counter_32k as a clocksource (%d)\n",
+							__func__, ret);
+		omap_hwmod_idle(oh);
+	}
+
+	return ret;
+}
+
+static void __init omap2_gptimer_clocksource_init(int gptimer_id,
+						const char *fck_source)
+{
+	int res;
+
+	clksrc.errata = omap_dm_timer_get_errata();
+
+	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
+				     OMAP_TIMER_NONPOSTED);
+	BUG_ON(res);
+
+	__omap_dm_timer_load_start(&clksrc,
+				   OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
+				   OMAP_TIMER_NONPOSTED);
+	setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
+
+	if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
+		pr_err("Could not register clocksource %s\n",
+			clocksource_gpt.name);
+	else
+		pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
+			gptimer_id, clksrc.rate);
+}
+
+#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
+/*
+ * The realtime counter also called master counter, is a free-running
+ * counter, which is related to real time. It produces the count used
+ * by the CPU local timer peripherals in the MPU cluster. The timer counts
+ * at a rate of 6.144 MHz. Because the device operates on different clocks
+ * in different power modes, the master counter shifts operation between
+ * clocks, adjusting the increment per clock in hardware accordingly to
+ * maintain a constant count rate.
+ */
+static void __init realtime_counter_init(void)
+{
+	void __iomem *base;
+	static struct clk *sys_clk;
+	unsigned long rate;
+	unsigned int reg, num, den;
+
+	base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
+	if (!base) {
+		pr_err("%s: ioremap failed\n", __func__);
+		return;
+	}
+	sys_clk = clk_get(NULL, "sys_clkin_ck");
+	if (IS_ERR(sys_clk)) {
+		pr_err("%s: failed to get system clock handle\n", __func__);
+		iounmap(base);
+		return;
+	}
+
+	rate = clk_get_rate(sys_clk);
+	/* Numerator/denumerator values refer TRM Realtime Counter section */
+	switch (rate) {
+	case 1200000:
+		num = 64;
+		den = 125;
+		break;
+	case 1300000:
+		num = 768;
+		den = 1625;
+		break;
+	case 19200000:
+		num = 8;