cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

setup.c (7656B)


      1/*
      2 *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
      3 *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
      4 *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
      5 *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
      6 *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
      7 *
      8 *  This program is free software; you can redistribute  it and/or modify it
      9 *  under  the terms of  the GNU General  Public License as published by the
     10 *  Free Software Foundation;  either version 2 of the  License, or (at your
     11 *  option) any later version.
     12 *
     13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
     14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
     15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
     16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
     17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
     19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
     21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 *
     24 *  You should have received a copy of the  GNU General Public License along
     25 *  with this program; if not, write  to the Free Software Foundation, Inc.,
     26 *  675 Mass Ave, Cambridge, MA 02139, USA.
     27 */
     28
     29#include "bcm47xx_private.h"
     30
     31#include <linux/bcm47xx_sprom.h>
     32#include <linux/export.h>
     33#include <linux/types.h>
     34#include <linux/ethtool.h>
     35#include <linux/phy.h>
     36#include <linux/phy_fixed.h>
     37#include <linux/ssb/ssb.h>
     38#include <linux/ssb/ssb_embedded.h>
     39#include <linux/bcma/bcma_soc.h>
     40#include <asm/bootinfo.h>
     41#include <asm/idle.h>
     42#include <asm/prom.h>
     43#include <asm/reboot.h>
     44#include <asm/time.h>
     45#include <bcm47xx.h>
     46#include <bcm47xx_board.h>
     47
     48union bcm47xx_bus bcm47xx_bus;
     49EXPORT_SYMBOL(bcm47xx_bus);
     50
     51enum bcm47xx_bus_type bcm47xx_bus_type;
     52EXPORT_SYMBOL(bcm47xx_bus_type);
     53
     54static void bcm47xx_machine_restart(char *command)
     55{
     56	pr_alert("Please stand by while rebooting the system...\n");
     57	local_irq_disable();
     58	/* Set the watchdog timer to reset immediately */
     59	switch (bcm47xx_bus_type) {
     60#ifdef CONFIG_BCM47XX_SSB
     61	case BCM47XX_BUS_TYPE_SSB:
     62		if (bcm47xx_bus.ssb.chip_id == 0x4785)
     63			write_c0_diag4(1 << 22);
     64		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
     65		if (bcm47xx_bus.ssb.chip_id == 0x4785) {
     66			__asm__ __volatile__(
     67				".set\tmips3\n\t"
     68				"sync\n\t"
     69				"wait\n\t"
     70				".set\tmips0");
     71		}
     72		break;
     73#endif
     74#ifdef CONFIG_BCM47XX_BCMA
     75	case BCM47XX_BUS_TYPE_BCMA:
     76		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
     77		break;
     78#endif
     79	}
     80	while (1)
     81		cpu_relax();
     82}
     83
     84static void bcm47xx_machine_halt(void)
     85{
     86	/* Disable interrupts and watchdog and spin forever */
     87	local_irq_disable();
     88	switch (bcm47xx_bus_type) {
     89#ifdef CONFIG_BCM47XX_SSB
     90	case BCM47XX_BUS_TYPE_SSB:
     91		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
     92		break;
     93#endif
     94#ifdef CONFIG_BCM47XX_BCMA
     95	case BCM47XX_BUS_TYPE_BCMA:
     96		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
     97		break;
     98#endif
     99	}
    100	while (1)
    101		cpu_relax();
    102}
    103
    104#ifdef CONFIG_BCM47XX_SSB
    105static void __init bcm47xx_register_ssb(void)
    106{
    107	int err;
    108	char buf[100];
    109	struct ssb_mipscore *mcore;
    110
    111	err = ssb_bus_host_soc_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE);
    112	if (err)
    113		panic("Failed to initialize SSB bus (err %d)", err);
    114
    115	mcore = &bcm47xx_bus.ssb.mipscore;
    116	if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
    117		if (strstr(buf, "console=ttyS1")) {
    118			struct ssb_serial_port port;
    119
    120			pr_debug("Swapping serial ports!\n");
    121			/* swap serial ports */
    122			memcpy(&port, &mcore->serial_ports[0], sizeof(port));
    123			memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
    124			       sizeof(port));
    125			memcpy(&mcore->serial_ports[1], &port, sizeof(port));
    126		}
    127	}
    128}
    129#endif
    130
    131#ifdef CONFIG_BCM47XX_BCMA
    132static void __init bcm47xx_register_bcma(void)
    133{
    134	int err;
    135
    136	err = bcma_host_soc_register(&bcm47xx_bus.bcma);
    137	if (err)
    138		panic("Failed to register BCMA bus (err %d)", err);
    139}
    140#endif
    141
    142/*
    143 * Memory setup is done in the early part of MIPS's arch_mem_init. It's supposed
    144 * to detect memory and record it with memblock_add.
    145 * Any extra initializaion performed here must not use kmalloc or bootmem.
    146 */
    147void __init plat_mem_setup(void)
    148{
    149	struct cpuinfo_mips *c = &current_cpu_data;
    150
    151	if (c->cputype == CPU_74K) {
    152		pr_info("Using bcma bus\n");
    153#ifdef CONFIG_BCM47XX_BCMA
    154		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
    155		bcm47xx_register_bcma();
    156		bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
    157#ifdef CONFIG_HIGHMEM
    158		bcm47xx_prom_highmem_init();
    159#endif
    160#endif
    161	} else {
    162		pr_info("Using ssb bus\n");
    163#ifdef CONFIG_BCM47XX_SSB
    164		bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
    165		bcm47xx_sprom_register_fallbacks();
    166		bcm47xx_register_ssb();
    167		bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id);
    168#endif
    169	}
    170
    171	_machine_restart = bcm47xx_machine_restart;
    172	_machine_halt = bcm47xx_machine_halt;
    173	pm_power_off = bcm47xx_machine_halt;
    174}
    175
    176#ifdef CONFIG_BCM47XX_BCMA
    177static struct device * __init bcm47xx_setup_device(void)
    178{
    179	struct device *dev;
    180	int err;
    181
    182	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    183	if (!dev)
    184		return NULL;
    185
    186	err = dev_set_name(dev, "bcm47xx_soc");
    187	if (err) {
    188		pr_err("Failed to set SoC device name: %d\n", err);
    189		kfree(dev);
    190		return NULL;
    191	}
    192
    193	err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
    194	if (err)
    195		pr_err("Failed to set SoC DMA mask: %d\n", err);
    196
    197	return dev;
    198}
    199#endif
    200
    201/*
    202 * This finishes bus initialization doing things that were not possible without
    203 * kmalloc. Make sure to call it late enough (after mm_init).
    204 */
    205void __init bcm47xx_bus_setup(void)
    206{
    207#ifdef CONFIG_BCM47XX_BCMA
    208	if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
    209		int err;
    210
    211		bcm47xx_bus.bcma.dev = bcm47xx_setup_device();
    212		if (!bcm47xx_bus.bcma.dev)
    213			panic("Failed to setup SoC device\n");
    214
    215		err = bcma_host_soc_init(&bcm47xx_bus.bcma);
    216		if (err)
    217			panic("Failed to initialize BCMA bus (err %d)", err);
    218	}
    219#endif
    220
    221	/* With bus initialized we can access NVRAM and detect the board */
    222	bcm47xx_board_detect();
    223	mips_set_machine_name(bcm47xx_board_get_name());
    224}
    225
    226static int __init bcm47xx_cpu_fixes(void)
    227{
    228	switch (bcm47xx_bus_type) {
    229#ifdef CONFIG_BCM47XX_SSB
    230	case BCM47XX_BUS_TYPE_SSB:
    231		/* Nothing to do */
    232		break;
    233#endif
    234#ifdef CONFIG_BCM47XX_BCMA
    235	case BCM47XX_BUS_TYPE_BCMA:
    236		/* The BCM4706 has a problem with the CPU wait instruction.
    237		 * When r4k_wait or r4k_wait_irqoff is used will just hang and
    238		 * not return from a msleep(). Removing the cpu_wait
    239		 * functionality is a workaround for this problem. The BCM4716
    240		 * does not have this problem.
    241		 */
    242		if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
    243			cpu_wait = NULL;
    244		break;
    245#endif
    246	}
    247	return 0;
    248}
    249arch_initcall(bcm47xx_cpu_fixes);
    250
    251static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = {
    252	.link	= 1,
    253	.speed	= SPEED_100,
    254	.duplex	= DUPLEX_FULL,
    255};
    256
    257static int __init bcm47xx_register_bus_complete(void)
    258{
    259	switch (bcm47xx_bus_type) {
    260#ifdef CONFIG_BCM47XX_SSB
    261	case BCM47XX_BUS_TYPE_SSB:
    262		/* Nothing to do */
    263		break;
    264#endif
    265#ifdef CONFIG_BCM47XX_BCMA
    266	case BCM47XX_BUS_TYPE_BCMA:
    267		if (device_register(bcm47xx_bus.bcma.dev))
    268			pr_err("Failed to register SoC device\n");
    269		bcma_bus_register(&bcm47xx_bus.bcma.bus);
    270		break;
    271#endif
    272	}
    273	bcm47xx_buttons_register();
    274	bcm47xx_leds_register();
    275	bcm47xx_workarounds();
    276
    277	fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
    278	return 0;
    279}
    280device_initcall(bcm47xx_register_bus_complete);