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

terastation_pro2-setup.c (9380B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Buffalo Terastation Pro II/Live Board Setup
      4 *
      5 * Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com>
      6 */
      7#include <linux/gpio.h>
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/platform_device.h>
     11#include <linux/pci.h>
     12#include <linux/irq.h>
     13#include <linux/delay.h>
     14#include <linux/mtd/physmap.h>
     15#include <linux/mv643xx_eth.h>
     16#include <linux/i2c.h>
     17#include <linux/serial_reg.h>
     18#include <asm/mach-types.h>
     19#include <asm/mach/arch.h>
     20#include <asm/mach/pci.h>
     21#include "common.h"
     22#include "mpp.h"
     23#include "orion5x.h"
     24
     25/*****************************************************************************
     26 * Terastation Pro 2/Live Info
     27 ****************************************************************************/
     28
     29/*
     30 * Terastation Pro 2 hardware :
     31 * - Marvell 88F5281-D0
     32 * - Marvell 88SX6042 SATA controller (PCI)
     33 * - Marvell 88E1118 Gigabit Ethernet PHY
     34 * - 256KB NOR flash
     35 * - 128MB of DDR RAM
     36 * - PCIe port (not equipped)
     37 */
     38
     39/*
     40 * 256K NOR flash Device bus boot chip select
     41 */
     42
     43#define TSP2_NOR_BOOT_BASE	0xf4000000
     44#define TSP2_NOR_BOOT_SIZE	SZ_256K
     45
     46/*****************************************************************************
     47 * 256KB NOR Flash on BOOT Device
     48 ****************************************************************************/
     49
     50static struct physmap_flash_data tsp2_nor_flash_data = {
     51	.width    = 1,
     52};
     53
     54static struct resource tsp2_nor_flash_resource = {
     55	.flags = IORESOURCE_MEM,
     56	.start = TSP2_NOR_BOOT_BASE,
     57	.end   = TSP2_NOR_BOOT_BASE + TSP2_NOR_BOOT_SIZE - 1,
     58};
     59
     60static struct platform_device tsp2_nor_flash = {
     61	.name          = "physmap-flash",
     62	.id            = 0,
     63	.dev           = {
     64		.platform_data	= &tsp2_nor_flash_data,
     65	},
     66	.num_resources = 1,
     67	.resource      = &tsp2_nor_flash_resource,
     68};
     69
     70/*****************************************************************************
     71 * PCI
     72 ****************************************************************************/
     73#define TSP2_PCI_SLOT0_OFFS		7
     74#define TSP2_PCI_SLOT0_IRQ_PIN		11
     75
     76static void __init tsp2_pci_preinit(void)
     77{
     78	int pin;
     79
     80	/*
     81	 * Configure PCI GPIO IRQ pins
     82	 */
     83	pin = TSP2_PCI_SLOT0_IRQ_PIN;
     84	if (gpio_request(pin, "PCI Int1") == 0) {
     85		if (gpio_direction_input(pin) == 0) {
     86			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
     87		} else {
     88			printk(KERN_ERR "tsp2_pci_preinit failed "
     89					"to set_irq_type pin %d\n", pin);
     90			gpio_free(pin);
     91		}
     92	} else {
     93		printk(KERN_ERR "tsp2_pci_preinit failed to "
     94				"gpio_request %d\n", pin);
     95	}
     96}
     97
     98static int __init tsp2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
     99{
    100	int irq;
    101
    102	/*
    103	 * Check for devices with hard-wired IRQs.
    104	 */
    105	irq = orion5x_pci_map_irq(dev, slot, pin);
    106	if (irq != -1)
    107		return irq;
    108
    109	/*
    110	 * PCI IRQs are connected via GPIOs.
    111	 */
    112	if (slot == TSP2_PCI_SLOT0_OFFS)
    113		return gpio_to_irq(TSP2_PCI_SLOT0_IRQ_PIN);
    114
    115	return -1;
    116}
    117
    118static struct hw_pci tsp2_pci __initdata = {
    119	.nr_controllers = 2,
    120	.preinit        = tsp2_pci_preinit,
    121	.setup          = orion5x_pci_sys_setup,
    122	.scan           = orion5x_pci_sys_scan_bus,
    123	.map_irq        = tsp2_pci_map_irq,
    124};
    125
    126static int __init tsp2_pci_init(void)
    127{
    128	if (machine_is_terastation_pro2())
    129		pci_common_init(&tsp2_pci);
    130
    131	return 0;
    132}
    133
    134subsys_initcall(tsp2_pci_init);
    135
    136/*****************************************************************************
    137 * Ethernet
    138 ****************************************************************************/
    139
    140static struct mv643xx_eth_platform_data tsp2_eth_data = {
    141	.phy_addr	= 0,
    142};
    143
    144/*****************************************************************************
    145 * RTC 5C372a on I2C bus
    146 ****************************************************************************/
    147
    148#define TSP2_RTC_GPIO	9
    149
    150static struct i2c_board_info __initdata tsp2_i2c_rtc = {
    151	I2C_BOARD_INFO("rs5c372a", 0x32),
    152};
    153
    154/*****************************************************************************
    155 * Terastation Pro II specific power off method via UART1-attached
    156 * microcontroller
    157 ****************************************************************************/
    158
    159#define UART1_REG(x)	(UART1_VIRT_BASE + ((UART_##x) << 2))
    160
    161static int tsp2_miconread(unsigned char *buf, int count)
    162{
    163	int i;
    164	int timeout;
    165
    166	for (i = 0; i < count; i++) {
    167		timeout = 10;
    168
    169		while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
    170			if (--timeout == 0)
    171				break;
    172			udelay(1000);
    173		}
    174
    175		if (timeout == 0)
    176			break;
    177		buf[i] = readl(UART1_REG(RX));
    178	}
    179
    180	/* return read bytes */
    181	return i;
    182}
    183
    184static int tsp2_miconwrite(const unsigned char *buf, int count)
    185{
    186	int i = 0;
    187
    188	while (count--) {
    189		while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
    190			barrier();
    191		writel(buf[i++], UART1_REG(TX));
    192	}
    193
    194	return 0;
    195}
    196
    197static int tsp2_miconsend(const unsigned char *data, int count)
    198{
    199	int i;
    200	unsigned char checksum = 0;
    201	unsigned char recv_buf[40];
    202	unsigned char send_buf[40];
    203	unsigned char correct_ack[3];
    204	int retry = 2;
    205
    206	/* Generate checksum */
    207	for (i = 0; i < count; i++)
    208		checksum -=  data[i];
    209
    210	do {
    211		/* Send data */
    212		tsp2_miconwrite(data, count);
    213
    214		/* send checksum */
    215		tsp2_miconwrite(&checksum, 1);
    216
    217		if (tsp2_miconread(recv_buf, sizeof(recv_buf)) <= 3) {
    218			printk(KERN_ERR ">%s: receive failed.\n", __func__);
    219
    220			/* send preamble to clear the receive buffer */
    221			memset(&send_buf, 0xff, sizeof(send_buf));
    222			tsp2_miconwrite(send_buf, sizeof(send_buf));
    223
    224			/* make dummy reads */
    225			mdelay(100);
    226			tsp2_miconread(recv_buf, sizeof(recv_buf));
    227		} else {
    228			/* Generate expected ack */
    229			correct_ack[0] = 0x01;
    230			correct_ack[1] = data[1];
    231			correct_ack[2] = 0x00;
    232
    233			/* checksum Check */
    234			if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
    235			     recv_buf[3]) & 0xFF) {
    236				printk(KERN_ERR ">%s: Checksum Error : "
    237					"Received data[%02x, %02x, %02x, %02x]"
    238					"\n", __func__, recv_buf[0],
    239					recv_buf[1], recv_buf[2], recv_buf[3]);
    240			} else {
    241				/* Check Received Data */
    242				if (correct_ack[0] == recv_buf[0] &&
    243				    correct_ack[1] == recv_buf[1] &&
    244				    correct_ack[2] == recv_buf[2]) {
    245					/* Interval for next command */
    246					mdelay(10);
    247
    248					/* Receive ACK */
    249					return 0;
    250				}
    251			}
    252			/* Received NAK or illegal Data */
    253			printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
    254					"Received\n", __func__);
    255		}
    256	} while (retry--);
    257
    258	/* Interval for next command */
    259	mdelay(10);
    260
    261	return -1;
    262}
    263
    264static void tsp2_power_off(void)
    265{
    266	const unsigned char watchdogkill[]	= {0x01, 0x35, 0x00};
    267	const unsigned char shutdownwait[]	= {0x00, 0x0c};
    268	const unsigned char poweroff[]		= {0x00, 0x06};
    269	/* 38400 baud divisor */
    270	const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400));
    271
    272	pr_info("%s: triggering power-off...\n", __func__);
    273
    274	/* hijack uart1 and reset into sane state (38400,8n1,even parity) */
    275	writel(0x83, UART1_REG(LCR));
    276	writel(divisor & 0xff, UART1_REG(DLL));
    277	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
    278	writel(0x1b, UART1_REG(LCR));
    279	writel(0x00, UART1_REG(IER));
    280	writel(0x07, UART1_REG(FCR));
    281	writel(0x00, UART1_REG(MCR));
    282
    283	/* Send the commands to shutdown the Terastation Pro II */
    284	tsp2_miconsend(watchdogkill, sizeof(watchdogkill)) ;
    285	tsp2_miconsend(shutdownwait, sizeof(shutdownwait)) ;
    286	tsp2_miconsend(poweroff, sizeof(poweroff));
    287}
    288
    289/*****************************************************************************
    290 * General Setup
    291 ****************************************************************************/
    292static unsigned int tsp2_mpp_modes[] __initdata = {
    293	MPP0_PCIE_RST_OUTn,
    294	MPP1_UNUSED,
    295	MPP2_UNUSED,
    296	MPP3_UNUSED,
    297	MPP4_NAND,		/* BOOT NAND Flash REn */
    298	MPP5_NAND,		/* BOOT NAND Flash WEn */
    299	MPP6_NAND,		/* BOOT NAND Flash HREn[0] */
    300	MPP7_NAND,		/* BOOT NAND Flash WEn[0] */
    301	MPP8_GPIO,		/* MICON int */
    302	MPP9_GPIO,		/* RTC int */
    303	MPP10_UNUSED,
    304	MPP11_GPIO,		/* PCI Int A */
    305	MPP12_UNUSED,
    306	MPP13_GPIO,		/* UPS on UART0 enable */
    307	MPP14_GPIO,		/* UPS low battery detection */
    308	MPP15_UNUSED,
    309	MPP16_UART,		/* UART1 RXD */
    310	MPP17_UART,		/* UART1 TXD */
    311	MPP18_UART,		/* UART1 CTSn */
    312	MPP19_UART,		/* UART1 RTSn */
    313	0,
    314};
    315
    316static void __init tsp2_init(void)
    317{
    318	/*
    319	 * Setup basic Orion functions. Need to be called early.
    320	 */
    321	orion5x_init();
    322
    323	orion5x_mpp_conf(tsp2_mpp_modes);
    324
    325	/*
    326	 * Configure peripherals.
    327	 */
    328	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
    329				    ORION_MBUS_DEVBUS_BOOT_ATTR,
    330				    TSP2_NOR_BOOT_BASE,
    331				    TSP2_NOR_BOOT_SIZE);
    332	platform_device_register(&tsp2_nor_flash);
    333
    334	orion5x_ehci0_init();
    335	orion5x_eth_init(&tsp2_eth_data);
    336	orion5x_i2c_init();
    337	orion5x_uart0_init();
    338	orion5x_uart1_init();
    339
    340	/* Get RTC IRQ and register the chip */
    341	if (gpio_request(TSP2_RTC_GPIO, "rtc") == 0) {
    342		if (gpio_direction_input(TSP2_RTC_GPIO) == 0)
    343			tsp2_i2c_rtc.irq = gpio_to_irq(TSP2_RTC_GPIO);
    344		else
    345			gpio_free(TSP2_RTC_GPIO);
    346	}
    347	if (tsp2_i2c_rtc.irq == 0)
    348		pr_warn("tsp2_init: failed to get RTC IRQ\n");
    349	i2c_register_board_info(0, &tsp2_i2c_rtc, 1);
    350
    351	/* register Terastation Pro II specific power-off method */
    352	pm_power_off = tsp2_power_off;
    353}
    354
    355MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
    356	/* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
    357	.atag_offset	= 0x100,
    358	.nr_irqs	= ORION5X_NR_IRQS,
    359	.init_machine	= tsp2_init,
    360	.map_io		= orion5x_map_io,
    361	.init_early	= orion5x_init_early,
    362	.init_irq	= orion5x_init_irq,
    363	.init_time	= orion5x_timer_init,
    364	.fixup		= tag_fixup_mem32,
    365	.restart	= orion5x_restart,
    366MACHINE_END