summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mach-mcfv4e/mcf_clocksource.c
blob: 926a592158cee6c0a66a260533735afb07b56c00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
 * See file CREDITS for list of people who contributed to this project.
 *
 * This file is part of U-Boot V2.
 *
 * U-Boot V2 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * U-Boot V2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with U-Boot V2.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 *  Implements the clocksource for Coldfire V4E
 */
#include <common.h>
#include <init.h>
#include <clock.h>
#include <mach/mcf54xx-regs.h>
#include <mach/clocks.h>
#include <proc/processor.h> //FIXME - move to other file

#ifdef CONFIG_USE_IRQ

static uint32_t mcf_sltirq_hits; // FIXME: test code

static int slt_timer_default_isr(void *not_used, void *t)
{
	struct mcf5xxx_slt *slt = MCF_SLT_Address(0);
	if ( MCF_INTC_IPRH | MCF_INTC_IPRH_INT54 )
	{
		if (slt->SSR & MCF_SLT_SSR_ST)
		{
			slt->SSR = 0UL
				| MCF_SLT_SSR_ST;
		}
		mcf_sltirq_hits++;
		return 1;
	}
	return 0;
}
#endif


static uint64_t mcf_clocksource_read(void)
{
	struct mcf5xxx_slt *slt = MCF_SLT_Address(0);
	uint32_t sltcnt;
	uint64_t rc = 0;

	if (slt->SSR & MCF_SLT_SSR_ST)
	{
#ifndef CONFIG_USE_IRQ
		slt->SSR = 0UL
			| MCF_SLT_SSR_ST;
#endif

		rc = 0xffffffffULL + 1;
	}

	sltcnt = 0xffffffffUL - slt->SCNT;

	rc += sltcnt;

	return rc;
}


static struct clocksource cs = {
	.read	= mcf_clocksource_read,
	.mask	= 0xffffffff,
	.mult   = 1,
	.shift	= 0,
};

static int clocksource_init (void)
{
	struct mcf5xxx_slt *slt = MCF_SLT_Address(0);
	uint32_t sltclk = mcfv4e_get_bus_clk() * 1000000;

	/* Setup a slice timer terminal count */
	slt->STCNT = 0xffffffff;

	/* Reset status bits */
        slt->SSR = 0UL
		| MCF_SLT_SSR_ST
		| MCF_SLT_SSR_BE;

        /* Start timer to run continously */
	slt->SCR   = 0UL
		| MCF_SLT_SCR_TEN
		| MCF_SLT_SCR_RUN
		| MCF_SLT_SCR_IEN;	// FIXME - add irq handler

        /* Setup up multiplier */
	cs.mult = clocksource_hz2mult(sltclk, cs.shift);

	/*
	* Register the timer interrupt handler
	*/
	init_clock(&cs);

	return 0;
}

core_initcall(clocksource_init);

#ifdef CONFIG_USE_IRQ

static int clocksource_irq_init(void)
{
	if (!mcf_interrupts_register_handler(
	     118, // FIXME!
	     (int (*)(void*,void*))slt_timer_default_isr,
	     NULL,
	     NULL)
	              )
	{
		return 1;
	}
	// Setup ICR
	MCF_INTC_ICR54 = MCF_INTC_ICRn_IL(1) | MCF_INTC_ICRn_IP(0);
	// Enable IRQ source
	MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK54;
	return 0;
}

postcore_initcall(clocksource_irq_init);

#endif