summaryrefslogtreecommitdiffstats
path: root/arch/m68k/platform/coldfire/nettel.c
blob: ddc48ec1b800300d6496479c8e4d4a1cd5090102 (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
151
152
153
/***************************************************************************/

/*
 *	nettel.c -- startup code support for the NETtel boards
 *
 *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
 */

/***************************************************************************/

#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/nettel.h>

/***************************************************************************/

/*
 * Define the IO and interrupt resources of the 2 SMC9196 interfaces.
 */
#define	NETTEL_SMC0_ADDR	0x30600300
#define	NETTEL_SMC0_IRQ		29

#define	NETTEL_SMC1_ADDR	0x30600000
#define	NETTEL_SMC1_IRQ		27

/*
 * We need some access into the SMC9196 registers. Define those registers
 * we will need here (including the smc91x.h doesn't seem to give us these
 * in a simple form).
 */
#define	SMC91xx_BANKSELECT	14
#define	SMC91xx_BASEADDR	2
#define	SMC91xx_BASEMAC		4

/***************************************************************************/

static struct resource nettel_smc91x_0_resources[] = {
	{
		.start		= NETTEL_SMC0_ADDR,
		.end		= NETTEL_SMC0_ADDR + 0x20,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= NETTEL_SMC0_IRQ,
		.end		= NETTEL_SMC0_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct resource nettel_smc91x_1_resources[] = {
	{
		.start		= NETTEL_SMC1_ADDR,
		.end		= NETTEL_SMC1_ADDR + 0x20,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= NETTEL_SMC1_IRQ,
		.end		= NETTEL_SMC1_IRQ,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct platform_device nettel_smc91x[] = {
	{
		.name			= "smc91x",
		.id			= 0,
		.num_resources		= ARRAY_SIZE(nettel_smc91x_0_resources),
		.resource		= nettel_smc91x_0_resources,
	},
	{
		.name			= "smc91x",
		.id			= 1,
		.num_resources		= ARRAY_SIZE(nettel_smc91x_1_resources),
		.resource		= nettel_smc91x_1_resources,
	},
};

static struct platform_device *nettel_devices[] __initdata = {
	&nettel_smc91x[0],
	&nettel_smc91x[1],
};

/***************************************************************************/

static u8 nettel_macdefault[] __initdata = {
	0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01,
};

/*
 * Set flash contained MAC address into SMC9196 core. Make sure the flash
 * MAC address is sane, and not an empty flash. If no good use the Moreton
 * Bay default MAC address instead.
 */

static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flashaddr)
{
	u16 *macp;

	macp = (u16 *) flashaddr;
	if ((macp[0] == 0xffff) && (macp[1] == 0xffff) && (macp[2] == 0xffff))
		macp = (u16 *) &nettel_macdefault[0];

	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
	writew(macp[0], ioaddr + SMC91xx_BASEMAC);
	writew(macp[1], ioaddr + SMC91xx_BASEMAC + 2);
	writew(macp[2], ioaddr + SMC91xx_BASEMAC + 4);
}

/***************************************************************************/

/*
 * Re-map the address space of at least one of the SMC ethernet
 * parts. Both parts power up decoding the same address, so we
 * need to move one of them first, before doing anything else.
 */

static void __init nettel_smc91x_init(void)
{
	writew(0x00ec, MCFSIM_PADDR);
	mcf_setppdata(0, 0x0080);
	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
	writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
	mcf_setppdata(0x0080, 0);

	/* Set correct chip select timing for SMC9196 accesses */
	writew(0x1180, MCFSIM_CSCR3);

	/* Set the SMC interrupts to be auto-vectored */
	mcf_autovector(NETTEL_SMC0_IRQ);
	mcf_autovector(NETTEL_SMC1_IRQ);

	/* Set MAC addresses from flash for both interfaces */
	nettel_smc91x_setmac(NETTEL_SMC0_ADDR, 0xf0006000);
	nettel_smc91x_setmac(NETTEL_SMC1_ADDR, 0xf0006006);
}

/***************************************************************************/

static int __init init_nettel(void)
{
	nettel_smc91x_init();
	platform_add_devices(nettel_devices, ARRAY_SIZE(nettel_devices));
	return 0;
}

arch_initcall(init_nettel);

/***************************************************************************/