xref: /openbmc/linux/arch/mips/bcm47xx/setup.c (revision 2aa088d6fd8a6c6e6020ea46b70141f0b7ccf5d2)
11c0c13ebSAurelien Jarno /*
21c0c13ebSAurelien Jarno  *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
31c0c13ebSAurelien Jarno  *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
41c0c13ebSAurelien Jarno  *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
5121915c4SWaldemar Brodkorb  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
61c0c13ebSAurelien Jarno  *
71c0c13ebSAurelien Jarno  *  This program is free software; you can redistribute  it and/or modify it
81c0c13ebSAurelien Jarno  *  under  the terms of  the GNU General  Public License as published by the
91c0c13ebSAurelien Jarno  *  Free Software Foundation;  either version 2 of the  License, or (at your
101c0c13ebSAurelien Jarno  *  option) any later version.
111c0c13ebSAurelien Jarno  *
121c0c13ebSAurelien Jarno  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
131c0c13ebSAurelien Jarno  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
141c0c13ebSAurelien Jarno  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
151c0c13ebSAurelien Jarno  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
161c0c13ebSAurelien Jarno  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
171c0c13ebSAurelien Jarno  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
181c0c13ebSAurelien Jarno  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
191c0c13ebSAurelien Jarno  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
201c0c13ebSAurelien Jarno  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
211c0c13ebSAurelien Jarno  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
221c0c13ebSAurelien Jarno  *
231c0c13ebSAurelien Jarno  *  You should have received a copy of the  GNU General Public License along
241c0c13ebSAurelien Jarno  *  with this program; if not, write  to the Free Software Foundation, Inc.,
251c0c13ebSAurelien Jarno  *  675 Mass Ave, Cambridge, MA 02139, USA.
261c0c13ebSAurelien Jarno  */
271c0c13ebSAurelien Jarno 
281c0c13ebSAurelien Jarno #include <linux/types.h>
291c0c13ebSAurelien Jarno #include <linux/ssb/ssb.h>
30b06f3e19SAurelien Jarno #include <linux/ssb/ssb_embedded.h>
3125e5fb97SAurelien Jarno #include <asm/bootinfo.h>
321c0c13ebSAurelien Jarno #include <asm/reboot.h>
331c0c13ebSAurelien Jarno #include <asm/time.h>
341c0c13ebSAurelien Jarno #include <bcm47xx.h>
35121915c4SWaldemar Brodkorb #include <asm/mach-bcm47xx/nvram.h>
361c0c13ebSAurelien Jarno 
371c0c13ebSAurelien Jarno struct ssb_bus ssb_bcm47xx;
381c0c13ebSAurelien Jarno EXPORT_SYMBOL(ssb_bcm47xx);
391c0c13ebSAurelien Jarno 
401c0c13ebSAurelien Jarno static void bcm47xx_machine_restart(char *command)
411c0c13ebSAurelien Jarno {
421c0c13ebSAurelien Jarno 	printk(KERN_ALERT "Please stand by while rebooting the system...\n");
431c0c13ebSAurelien Jarno 	local_irq_disable();
441c0c13ebSAurelien Jarno 	/* Set the watchdog timer to reset immediately */
45b06f3e19SAurelien Jarno 	ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
461c0c13ebSAurelien Jarno 	while (1)
471c0c13ebSAurelien Jarno 		cpu_relax();
481c0c13ebSAurelien Jarno }
491c0c13ebSAurelien Jarno 
501c0c13ebSAurelien Jarno static void bcm47xx_machine_halt(void)
511c0c13ebSAurelien Jarno {
521c0c13ebSAurelien Jarno 	/* Disable interrupts and watchdog and spin forever */
531c0c13ebSAurelien Jarno 	local_irq_disable();
54b06f3e19SAurelien Jarno 	ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
551c0c13ebSAurelien Jarno 	while (1)
561c0c13ebSAurelien Jarno 		cpu_relax();
571c0c13ebSAurelien Jarno }
581c0c13ebSAurelien Jarno 
5925e5fb97SAurelien Jarno static void str2eaddr(char *str, char *dest)
6025e5fb97SAurelien Jarno {
6125e5fb97SAurelien Jarno 	int i = 0;
6225e5fb97SAurelien Jarno 
6325e5fb97SAurelien Jarno 	if (str == NULL) {
6425e5fb97SAurelien Jarno 		memset(dest, 0, 6);
6525e5fb97SAurelien Jarno 		return;
6625e5fb97SAurelien Jarno 	}
6725e5fb97SAurelien Jarno 
6825e5fb97SAurelien Jarno 	for (;;) {
6925e5fb97SAurelien Jarno 		dest[i++] = (char) simple_strtoul(str, NULL, 16);
7025e5fb97SAurelien Jarno 		str += 2;
7125e5fb97SAurelien Jarno 		if (!*str++ || i == 6)
7225e5fb97SAurelien Jarno 			break;
7325e5fb97SAurelien Jarno 	}
7425e5fb97SAurelien Jarno }
7525e5fb97SAurelien Jarno 
76*2aa088d6SHauke Mehrtens #define READ_FROM_NVRAM(_outvar, name, buf) \
77*2aa088d6SHauke Mehrtens 	if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
78*2aa088d6SHauke Mehrtens 		sprom->_outvar = simple_strtoul(buf, NULL, 0);
79*2aa088d6SHauke Mehrtens 
80*2aa088d6SHauke Mehrtens static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
81*2aa088d6SHauke Mehrtens {
82*2aa088d6SHauke Mehrtens 	char buf[100];
83*2aa088d6SHauke Mehrtens 	u32 boardflags;
84*2aa088d6SHauke Mehrtens 
85*2aa088d6SHauke Mehrtens 	memset(sprom, 0, sizeof(struct ssb_sprom));
86*2aa088d6SHauke Mehrtens 
87*2aa088d6SHauke Mehrtens 	sprom->revision = 1; /* Fallback: Old hardware does not define this. */
88*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(revision, "sromrev", buf);
89*2aa088d6SHauke Mehrtens 	if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
90*2aa088d6SHauke Mehrtens 		str2eaddr(buf, sprom->il0mac);
91*2aa088d6SHauke Mehrtens 	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
92*2aa088d6SHauke Mehrtens 		str2eaddr(buf, sprom->et0mac);
93*2aa088d6SHauke Mehrtens 	if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
94*2aa088d6SHauke Mehrtens 		str2eaddr(buf, sprom->et1mac);
95*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
96*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
97*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
98*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
99*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(board_rev, "boardrev", buf);
100*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(country_code, "ccode", buf);
101*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
102*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
103*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
104*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
105*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
106*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
107*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
108*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
109*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
110*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
111*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
112*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
113*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
114*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
115*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
116*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
117*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
118*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
119*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
120*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
121*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
122*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
123*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
124*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
125*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(tri2g, "tri2g", buf);
126*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
127*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(tri5g, "tri5g", buf);
128*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
129*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
130*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
131*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
132*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
133*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
134*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
135*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
136*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
137*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
138*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
139*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
140*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
141*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
142*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
143*2aa088d6SHauke Mehrtens 	READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
144*2aa088d6SHauke Mehrtens 
145*2aa088d6SHauke Mehrtens 	if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
146*2aa088d6SHauke Mehrtens 		boardflags = simple_strtoul(buf, NULL, 0);
147*2aa088d6SHauke Mehrtens 		if (boardflags) {
148*2aa088d6SHauke Mehrtens 			sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
149*2aa088d6SHauke Mehrtens 			sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
150*2aa088d6SHauke Mehrtens 		}
151*2aa088d6SHauke Mehrtens 	}
152*2aa088d6SHauke Mehrtens 	if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
153*2aa088d6SHauke Mehrtens 		boardflags = simple_strtoul(buf, NULL, 0);
154*2aa088d6SHauke Mehrtens 		if (boardflags) {
155*2aa088d6SHauke Mehrtens 			sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
156*2aa088d6SHauke Mehrtens 			sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
157*2aa088d6SHauke Mehrtens 		}
158*2aa088d6SHauke Mehrtens 	}
159*2aa088d6SHauke Mehrtens }
160*2aa088d6SHauke Mehrtens 
1611c0c13ebSAurelien Jarno static int bcm47xx_get_invariants(struct ssb_bus *bus,
1621c0c13ebSAurelien Jarno 				   struct ssb_init_invariants *iv)
1631c0c13ebSAurelien Jarno {
164*2aa088d6SHauke Mehrtens 	char buf[20];
16525e5fb97SAurelien Jarno 
16625e5fb97SAurelien Jarno 	/* Fill boardinfo structure */
16725e5fb97SAurelien Jarno 	memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
16825e5fb97SAurelien Jarno 
16982571084SHauke Mehrtens 	if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
170*2aa088d6SHauke Mehrtens 		iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
171*2aa088d6SHauke Mehrtens 	else
172*2aa088d6SHauke Mehrtens 		iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
17382571084SHauke Mehrtens 	if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
17425e5fb97SAurelien Jarno 		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
17582571084SHauke Mehrtens 	if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
17625e5fb97SAurelien Jarno 		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
17725e5fb97SAurelien Jarno 
178*2aa088d6SHauke Mehrtens 	bcm47xx_fill_sprom(&iv->sprom);
17925e5fb97SAurelien Jarno 
180*2aa088d6SHauke Mehrtens 	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
181*2aa088d6SHauke Mehrtens 		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
18225e5fb97SAurelien Jarno 
1831c0c13ebSAurelien Jarno 	return 0;
1841c0c13ebSAurelien Jarno }
1851c0c13ebSAurelien Jarno 
1861c0c13ebSAurelien Jarno void __init plat_mem_setup(void)
1871c0c13ebSAurelien Jarno {
1881c0c13ebSAurelien Jarno 	int err;
1891c0c13ebSAurelien Jarno 
1901c0c13ebSAurelien Jarno 	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
1911c0c13ebSAurelien Jarno 				      bcm47xx_get_invariants);
1921c0c13ebSAurelien Jarno 	if (err)
1931c0c13ebSAurelien Jarno 		panic("Failed to initialize SSB bus (err %d)\n", err);
1941c0c13ebSAurelien Jarno 
1951c0c13ebSAurelien Jarno 	_machine_restart = bcm47xx_machine_restart;
1961c0c13ebSAurelien Jarno 	_machine_halt = bcm47xx_machine_halt;
1971c0c13ebSAurelien Jarno 	pm_power_off = bcm47xx_machine_halt;
1981c0c13ebSAurelien Jarno }
199