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*25e5fb97SAurelien Jarno #include <asm/bootinfo.h> 311c0c13ebSAurelien Jarno #include <asm/reboot.h> 321c0c13ebSAurelien Jarno #include <asm/time.h> 331c0c13ebSAurelien Jarno #include <bcm47xx.h> 34*25e5fb97SAurelien Jarno #include <asm/fw/cfe/cfe_api.h> 351c0c13ebSAurelien Jarno 361c0c13ebSAurelien Jarno struct ssb_bus ssb_bcm47xx; 371c0c13ebSAurelien Jarno EXPORT_SYMBOL(ssb_bcm47xx); 381c0c13ebSAurelien Jarno 391c0c13ebSAurelien Jarno static void bcm47xx_machine_restart(char *command) 401c0c13ebSAurelien Jarno { 411c0c13ebSAurelien Jarno printk(KERN_ALERT "Please stand by while rebooting the system...\n"); 421c0c13ebSAurelien Jarno local_irq_disable(); 431c0c13ebSAurelien Jarno /* Set the watchdog timer to reset immediately */ 441c0c13ebSAurelien Jarno ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 1); 451c0c13ebSAurelien Jarno while (1) 461c0c13ebSAurelien Jarno cpu_relax(); 471c0c13ebSAurelien Jarno } 481c0c13ebSAurelien Jarno 491c0c13ebSAurelien Jarno static void bcm47xx_machine_halt(void) 501c0c13ebSAurelien Jarno { 511c0c13ebSAurelien Jarno /* Disable interrupts and watchdog and spin forever */ 521c0c13ebSAurelien Jarno local_irq_disable(); 531c0c13ebSAurelien Jarno ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 0); 541c0c13ebSAurelien Jarno while (1) 551c0c13ebSAurelien Jarno cpu_relax(); 561c0c13ebSAurelien Jarno } 571c0c13ebSAurelien Jarno 58*25e5fb97SAurelien Jarno static void str2eaddr(char *str, char *dest) 59*25e5fb97SAurelien Jarno { 60*25e5fb97SAurelien Jarno int i = 0; 61*25e5fb97SAurelien Jarno 62*25e5fb97SAurelien Jarno if (str == NULL) { 63*25e5fb97SAurelien Jarno memset(dest, 0, 6); 64*25e5fb97SAurelien Jarno return; 65*25e5fb97SAurelien Jarno } 66*25e5fb97SAurelien Jarno 67*25e5fb97SAurelien Jarno for (;;) { 68*25e5fb97SAurelien Jarno dest[i++] = (char) simple_strtoul(str, NULL, 16); 69*25e5fb97SAurelien Jarno str += 2; 70*25e5fb97SAurelien Jarno if (!*str++ || i == 6) 71*25e5fb97SAurelien Jarno break; 72*25e5fb97SAurelien Jarno } 73*25e5fb97SAurelien Jarno } 74*25e5fb97SAurelien Jarno 751c0c13ebSAurelien Jarno static int bcm47xx_get_invariants(struct ssb_bus *bus, 761c0c13ebSAurelien Jarno struct ssb_init_invariants *iv) 771c0c13ebSAurelien Jarno { 78*25e5fb97SAurelien Jarno char buf[100]; 79*25e5fb97SAurelien Jarno 80*25e5fb97SAurelien Jarno /* Fill boardinfo structure */ 81*25e5fb97SAurelien Jarno memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); 82*25e5fb97SAurelien Jarno 83*25e5fb97SAurelien Jarno if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0) 84*25e5fb97SAurelien Jarno iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 85*25e5fb97SAurelien Jarno if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) 86*25e5fb97SAurelien Jarno iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 87*25e5fb97SAurelien Jarno if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) 88*25e5fb97SAurelien Jarno iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); 89*25e5fb97SAurelien Jarno 90*25e5fb97SAurelien Jarno /* Fill sprom structure */ 91*25e5fb97SAurelien Jarno memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); 92*25e5fb97SAurelien Jarno iv->sprom.revision = 3; 93*25e5fb97SAurelien Jarno 94*25e5fb97SAurelien Jarno if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) 95*25e5fb97SAurelien Jarno str2eaddr(buf, iv->sprom.r1.et0mac); 96*25e5fb97SAurelien Jarno if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) 97*25e5fb97SAurelien Jarno str2eaddr(buf, iv->sprom.r1.et1mac); 98*25e5fb97SAurelien Jarno if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) 99*25e5fb97SAurelien Jarno iv->sprom.r1.et0phyaddr = simple_strtoul(buf, NULL, 10); 100*25e5fb97SAurelien Jarno if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) 101*25e5fb97SAurelien Jarno iv->sprom.r1.et1phyaddr = simple_strtoul(buf, NULL, 10); 102*25e5fb97SAurelien Jarno if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) 103*25e5fb97SAurelien Jarno iv->sprom.r1.et0mdcport = simple_strtoul(buf, NULL, 10); 104*25e5fb97SAurelien Jarno if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) 105*25e5fb97SAurelien Jarno iv->sprom.r1.et1mdcport = simple_strtoul(buf, NULL, 10); 106*25e5fb97SAurelien Jarno 1071c0c13ebSAurelien Jarno return 0; 1081c0c13ebSAurelien Jarno } 1091c0c13ebSAurelien Jarno 1101c0c13ebSAurelien Jarno void __init plat_mem_setup(void) 1111c0c13ebSAurelien Jarno { 1121c0c13ebSAurelien Jarno int err; 1131c0c13ebSAurelien Jarno 1141c0c13ebSAurelien Jarno err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, 1151c0c13ebSAurelien Jarno bcm47xx_get_invariants); 1161c0c13ebSAurelien Jarno if (err) 1171c0c13ebSAurelien Jarno panic("Failed to initialize SSB bus (err %d)\n", err); 1181c0c13ebSAurelien Jarno 1191c0c13ebSAurelien Jarno _machine_restart = bcm47xx_machine_restart; 1201c0c13ebSAurelien Jarno _machine_halt = bcm47xx_machine_halt; 1211c0c13ebSAurelien Jarno pm_power_off = bcm47xx_machine_halt; 1221c0c13ebSAurelien Jarno board_time_init = bcm47xx_time_init; 1231c0c13ebSAurelien Jarno } 1241c0c13ebSAurelien Jarno 125