summaryrefslogtreecommitdiff
path: root/sys/arch/arm/ti/am3_platform.c
blob: 4763e13bba76e8e472aad9308bbc29f7c1f2b8d3 (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
139
140
141
142
143
144
145
146
147
148
149
150
/* $NetBSD: am3_platform.c,v 1.4 2023/04/07 08:55:30 skrll Exp $ */

#include "opt_console.h"

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: am3_platform.c,v 1.4 2023/04/07 08:55:30 skrll Exp $");

#include <sys/param.h>

#include <dev/fdt/fdtvar.h>

#include <arm/fdt/arm_fdtvar.h>

#include <uvm/uvm_extern.h>

#include <dev/ic/comreg.h>

#include <machine/vmparam.h>
#include <arch/evbarm/fdt/platform.h>

extern struct bus_space armv7_generic_bs_tag;
extern struct arm32_bus_dma_tag arm_generic_dma_tag;

void am33xx_platform_early_putchar(char);

void __noasan
am33xx_platform_early_putchar(char c)
{
#ifdef CONSADDR
#define CONSADDR_VA ((CONSADDR - 0x44c00000) + (KERNEL_IO_VBASE | 0x04c00000))
	volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
	    (volatile uint32_t *)CONSADDR_VA :
	    (volatile uint32_t *)CONSADDR;

	while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0)
		;

	uartaddr[com_data] = htole32(c);
#endif
}


static const struct pmap_devmap *
am33xx_platform_devmap(void)
{
	static const struct pmap_devmap devmap[] = {
		DEVMAP_ENTRY(KERNEL_IO_VBASE | 0x04c00000, 0x44c00000, 0x00400000),
		DEVMAP_ENTRY(KERNEL_IO_VBASE | 0x08000000, 0x48000000, 0x01000000),
		DEVMAP_ENTRY(KERNEL_IO_VBASE | 0x0a000000, 0x4a000000, 0x01000000),
		DEVMAP_ENTRY_END
	};

	return devmap;
}

static void
am33xx_platform_init_attach_args(struct fdt_attach_args *faa)
{
	faa->faa_bst = &armv7_generic_bs_tag;
	faa->faa_dmat = &arm_generic_dma_tag;
}

static void
wdelay(bus_space_tag_t bst, bus_space_handle_t bsh)
{
	while (bus_space_read_4(bst, bsh, 0x34) != 0)
		delay(10);
}

static void
am33xx_platform_bootstrap(void)
{
	static bus_space_tag_t bst = &armv7_generic_bs_tag;
	static bus_space_handle_t bsh;

	bus_space_map(bst, 0x44e00000, 0x1000, 0, &bsh);
	bus_space_write_4(bst, bsh, 0x508, 0x1); /* CLKSEL_TIMER2_CLK: CLK_M_OSC */
	bus_space_write_4(bst, bsh, 0x50c, 0x1); /* CLKSEL_TIMER3_CLK: CLK_M_OSC */
	bus_space_write_4(bst, bsh, 0x80, 0x2); /* CM_PER_TIMER2_CLKCTRL: MODULEMODE: ENABLE */
	bus_space_write_4(bst, bsh, 0x84, 0x2); /* CM_PER_TIMER3_CLKCTRL: MODULEMODE: ENABLE */
	bus_space_unmap(bst, bsh, 0x1000);

	bus_space_map(bst, 0x48040000, 0x1000, 0, &bsh); /* TIMER2 for delay() */

	bus_space_write_4(bst, bsh, 0x40, 0); /* Load */
	bus_space_write_4(bst, bsh, 0x3c, 0); /* Counter */
	bus_space_write_4(bst, bsh, 0x38, 3); /* Control */

	bus_space_unmap(bst, bsh, 0x1000);

	bus_space_map(bst, 0x44e35000, 0x1000, 0, &bsh);
	wdelay(bst, bsh);
	bus_space_write_4(bst, bsh, 0x48, 0xAAAA);
	wdelay(bst, bsh);
	bus_space_write_4(bst, bsh, 0x48, 0x5555);
	wdelay(bst, bsh);
	bus_space_unmap(bst, bsh, 0x1000);

	bus_space_map(bst, 0x44e00000, 0x1000, 0, &bsh);
	bus_space_write_4(bst, bsh, 0x4d4, 0); /* suspend watch dog */
	bus_space_unmap(bst, bsh, 0x1000);
}

static u_int
am33xx_platform_uart_freq(void)
{
	return 48000000;
}

static void
am33xx_platform_delay(u_int n)
{
	static bus_space_tag_t bst = &armv7_generic_bs_tag;
	static bus_space_handle_t bsh = 0;

	uint32_t cur, prev;
	long ticks = n * 24;

	if (bsh == 0)
		bus_space_map(bst, 0x48040000, 0x1000, 0, &bsh); /* TIMER2 */

	prev = bus_space_read_4(bst, bsh, 0x3c);
	while (ticks > 0) {
		cur = bus_space_read_4(bst, bsh, 0x3c);
		if (cur >= prev)
			ticks -= (cur - prev);
		else
			ticks -= (UINT32_MAX - cur + prev);
		prev = cur;
	}
}

static void
am33xx_platform_reset(void)
{
	volatile uint32_t *resetaddr = (volatile uint32_t *)(KERNEL_IO_VBASE | 0x04e00f00);

	*resetaddr = 1;
}

static const struct fdt_platform am33xx_platform = {
	.fp_devmap = am33xx_platform_devmap,
	.fp_init_attach_args = am33xx_platform_init_attach_args,
	.fp_bootstrap = am33xx_platform_bootstrap,
	.fp_uart_freq = am33xx_platform_uart_freq,
	.fp_delay = am33xx_platform_delay,
	.fp_reset = am33xx_platform_reset,
};

FDT_PLATFORM(am33xx, "ti,am33xx", &am33xx_platform);