11c0c13ebSAurelien Jarno /* 21c0c13ebSAurelien Jarno * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> 31c0c13ebSAurelien Jarno * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org> 41c0c13ebSAurelien Jarno * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> 51c0c13ebSAurelien Jarno * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de> 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> 30*b06f3e19SAurelien 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> 3525e5fb97SAurelien Jarno #include <asm/fw/cfe/cfe_api.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 */ 45*b06f3e19SAurelien 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(); 54*b06f3e19SAurelien 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 761c0c13ebSAurelien Jarno static int bcm47xx_get_invariants(struct ssb_bus *bus, 771c0c13ebSAurelien Jarno struct ssb_init_invariants *iv) 781c0c13ebSAurelien Jarno { 7925e5fb97SAurelien Jarno char buf[100]; 8025e5fb97SAurelien Jarno 8125e5fb97SAurelien Jarno /* Fill boardinfo structure */ 8225e5fb97SAurelien Jarno memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); 8325e5fb97SAurelien Jarno 8425e5fb97SAurelien Jarno if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0) 8525e5fb97SAurelien Jarno iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 8625e5fb97SAurelien Jarno if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) 8725e5fb97SAurelien Jarno iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 8825e5fb97SAurelien Jarno if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) 8925e5fb97SAurelien Jarno iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); 9025e5fb97SAurelien Jarno 9125e5fb97SAurelien Jarno /* Fill sprom structure */ 9225e5fb97SAurelien Jarno memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); 9325e5fb97SAurelien Jarno iv->sprom.revision = 3; 9425e5fb97SAurelien Jarno 9525e5fb97SAurelien Jarno if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) 96cc2d6f70SAurelien Jarno str2eaddr(buf, iv->sprom.et0mac); 9725e5fb97SAurelien Jarno if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) 98cc2d6f70SAurelien Jarno str2eaddr(buf, iv->sprom.et1mac); 9925e5fb97SAurelien Jarno if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) 100cc2d6f70SAurelien Jarno iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10); 10125e5fb97SAurelien Jarno if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) 102cc2d6f70SAurelien Jarno iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10); 10325e5fb97SAurelien Jarno if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) 104cc2d6f70SAurelien Jarno iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); 10525e5fb97SAurelien Jarno if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) 106cc2d6f70SAurelien Jarno iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); 10725e5fb97SAurelien Jarno 1081c0c13ebSAurelien Jarno return 0; 1091c0c13ebSAurelien Jarno } 1101c0c13ebSAurelien Jarno 1111c0c13ebSAurelien Jarno void __init plat_mem_setup(void) 1121c0c13ebSAurelien Jarno { 1131c0c13ebSAurelien Jarno int err; 1141c0c13ebSAurelien Jarno 1151c0c13ebSAurelien Jarno err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, 1161c0c13ebSAurelien Jarno bcm47xx_get_invariants); 1171c0c13ebSAurelien Jarno if (err) 1181c0c13ebSAurelien Jarno panic("Failed to initialize SSB bus (err %d)\n", err); 1191c0c13ebSAurelien Jarno 1201c0c13ebSAurelien Jarno _machine_restart = bcm47xx_machine_restart; 1211c0c13ebSAurelien Jarno _machine_halt = bcm47xx_machine_halt; 1221c0c13ebSAurelien Jarno pm_power_off = bcm47xx_machine_halt; 1231c0c13ebSAurelien Jarno } 1241c0c13ebSAurelien Jarno 125