1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /***************************************************************************/
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun * nettel.c -- startup code support for the NETtel boards
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /***************************************************************************/
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/param.h>
14*4882a593Smuzhiyun #include <linux/init.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <asm/coldfire.h>
18*4882a593Smuzhiyun #include <asm/mcfsim.h>
19*4882a593Smuzhiyun #include <asm/nettel.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /***************************************************************************/
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /*
24*4882a593Smuzhiyun * Define the IO and interrupt resources of the 2 SMC9196 interfaces.
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun #define NETTEL_SMC0_ADDR 0x30600300
27*4882a593Smuzhiyun #define NETTEL_SMC0_IRQ 29
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define NETTEL_SMC1_ADDR 0x30600000
30*4882a593Smuzhiyun #define NETTEL_SMC1_IRQ 27
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun * We need some access into the SMC9196 registers. Define those registers
34*4882a593Smuzhiyun * we will need here (including the smc91x.h doesn't seem to give us these
35*4882a593Smuzhiyun * in a simple form).
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun #define SMC91xx_BANKSELECT 14
38*4882a593Smuzhiyun #define SMC91xx_BASEADDR 2
39*4882a593Smuzhiyun #define SMC91xx_BASEMAC 4
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /***************************************************************************/
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun static struct resource nettel_smc91x_0_resources[] = {
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun .start = NETTEL_SMC0_ADDR,
46*4882a593Smuzhiyun .end = NETTEL_SMC0_ADDR + 0x20,
47*4882a593Smuzhiyun .flags = IORESOURCE_MEM,
48*4882a593Smuzhiyun },
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun .start = NETTEL_SMC0_IRQ,
51*4882a593Smuzhiyun .end = NETTEL_SMC0_IRQ,
52*4882a593Smuzhiyun .flags = IORESOURCE_IRQ,
53*4882a593Smuzhiyun },
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun static struct resource nettel_smc91x_1_resources[] = {
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun .start = NETTEL_SMC1_ADDR,
59*4882a593Smuzhiyun .end = NETTEL_SMC1_ADDR + 0x20,
60*4882a593Smuzhiyun .flags = IORESOURCE_MEM,
61*4882a593Smuzhiyun },
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun .start = NETTEL_SMC1_IRQ,
64*4882a593Smuzhiyun .end = NETTEL_SMC1_IRQ,
65*4882a593Smuzhiyun .flags = IORESOURCE_IRQ,
66*4882a593Smuzhiyun },
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun static struct platform_device nettel_smc91x[] = {
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun .name = "smc91x",
72*4882a593Smuzhiyun .id = 0,
73*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(nettel_smc91x_0_resources),
74*4882a593Smuzhiyun .resource = nettel_smc91x_0_resources,
75*4882a593Smuzhiyun },
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun .name = "smc91x",
78*4882a593Smuzhiyun .id = 1,
79*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(nettel_smc91x_1_resources),
80*4882a593Smuzhiyun .resource = nettel_smc91x_1_resources,
81*4882a593Smuzhiyun },
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun static struct platform_device *nettel_devices[] __initdata = {
85*4882a593Smuzhiyun &nettel_smc91x[0],
86*4882a593Smuzhiyun &nettel_smc91x[1],
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /***************************************************************************/
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun static u8 nettel_macdefault[] __initdata = {
92*4882a593Smuzhiyun 0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01,
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * Set flash contained MAC address into SMC9196 core. Make sure the flash
97*4882a593Smuzhiyun * MAC address is sane, and not an empty flash. If no good use the Moreton
98*4882a593Smuzhiyun * Bay default MAC address instead.
99*4882a593Smuzhiyun */
100*4882a593Smuzhiyun
nettel_smc91x_setmac(unsigned int ioaddr,unsigned int flashaddr)101*4882a593Smuzhiyun static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flashaddr)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun u16 *macp;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun macp = (u16 *) flashaddr;
106*4882a593Smuzhiyun if ((macp[0] == 0xffff) && (macp[1] == 0xffff) && (macp[2] == 0xffff))
107*4882a593Smuzhiyun macp = (u16 *) &nettel_macdefault[0];
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
110*4882a593Smuzhiyun writew(macp[0], ioaddr + SMC91xx_BASEMAC);
111*4882a593Smuzhiyun writew(macp[1], ioaddr + SMC91xx_BASEMAC + 2);
112*4882a593Smuzhiyun writew(macp[2], ioaddr + SMC91xx_BASEMAC + 4);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /***************************************************************************/
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /*
118*4882a593Smuzhiyun * Re-map the address space of at least one of the SMC ethernet
119*4882a593Smuzhiyun * parts. Both parts power up decoding the same address, so we
120*4882a593Smuzhiyun * need to move one of them first, before doing anything else.
121*4882a593Smuzhiyun */
122*4882a593Smuzhiyun
nettel_smc91x_init(void)123*4882a593Smuzhiyun static void __init nettel_smc91x_init(void)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun writew(0x00ec, MCFSIM_PADDR);
126*4882a593Smuzhiyun mcf_setppdata(0, 0x0080);
127*4882a593Smuzhiyun writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
128*4882a593Smuzhiyun writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
129*4882a593Smuzhiyun mcf_setppdata(0x0080, 0);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* Set correct chip select timing for SMC9196 accesses */
132*4882a593Smuzhiyun writew(0x1180, MCFSIM_CSCR3);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* Set the SMC interrupts to be auto-vectored */
135*4882a593Smuzhiyun mcf_autovector(NETTEL_SMC0_IRQ);
136*4882a593Smuzhiyun mcf_autovector(NETTEL_SMC1_IRQ);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /* Set MAC addresses from flash for both interfaces */
139*4882a593Smuzhiyun nettel_smc91x_setmac(NETTEL_SMC0_ADDR, 0xf0006000);
140*4882a593Smuzhiyun nettel_smc91x_setmac(NETTEL_SMC1_ADDR, 0xf0006006);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /***************************************************************************/
144*4882a593Smuzhiyun
init_nettel(void)145*4882a593Smuzhiyun static int __init init_nettel(void)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun nettel_smc91x_init();
148*4882a593Smuzhiyun platform_add_devices(nettel_devices, ARRAY_SIZE(nettel_devices));
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun arch_initcall(init_nettel);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /***************************************************************************/
155