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

kurobox_pro-setup.c (10832B)


      1/*
      2 * arch/arm/mach-orion5x/kurobox_pro-setup.c
      3 *
      4 * Maintainer: Ronen Shitrit <rshitrit@marvell.com>
      5 *
      6 * This file is licensed under the terms of the GNU General Public
      7 * License version 2.  This program is licensed "as is" without any
      8 * warranty of any kind, whether express or implied.
      9 */
     10#include <linux/gpio.h>
     11#include <linux/kernel.h>
     12#include <linux/init.h>
     13#include <linux/platform_device.h>
     14#include <linux/pci.h>
     15#include <linux/irq.h>
     16#include <linux/delay.h>
     17#include <linux/mtd/physmap.h>
     18#include <linux/mtd/rawnand.h>
     19#include <linux/mv643xx_eth.h>
     20#include <linux/i2c.h>
     21#include <linux/serial_reg.h>
     22#include <linux/ata_platform.h>
     23#include <asm/mach-types.h>
     24#include <asm/mach/arch.h>
     25#include <asm/mach/pci.h>
     26#include <linux/platform_data/mtd-orion_nand.h>
     27#include "common.h"
     28#include "mpp.h"
     29#include "orion5x.h"
     30
     31/*****************************************************************************
     32 * KUROBOX-PRO Info
     33 ****************************************************************************/
     34
     35/*
     36 * 256K NOR flash Device bus boot chip select
     37 */
     38
     39#define KUROBOX_PRO_NOR_BOOT_BASE	0xf4000000
     40#define KUROBOX_PRO_NOR_BOOT_SIZE	SZ_256K
     41
     42/*
     43 * 256M NAND flash on Device bus chip select 1
     44 */
     45
     46#define KUROBOX_PRO_NAND_BASE		0xfc000000
     47#define KUROBOX_PRO_NAND_SIZE		SZ_2M
     48
     49/*****************************************************************************
     50 * 256MB NAND Flash on Device bus CS0
     51 ****************************************************************************/
     52
     53static struct mtd_partition kurobox_pro_nand_parts[] = {
     54	{
     55		.name	= "uImage",
     56		.offset	= 0,
     57		.size	= SZ_4M,
     58	}, {
     59		.name	= "rootfs",
     60		.offset	= SZ_4M,
     61		.size	= SZ_64M,
     62	}, {
     63		.name	= "extra",
     64		.offset	= SZ_4M + SZ_64M,
     65		.size	= SZ_256M - (SZ_4M + SZ_64M),
     66	},
     67};
     68
     69static struct resource kurobox_pro_nand_resource = {
     70	.flags		= IORESOURCE_MEM,
     71	.start		= KUROBOX_PRO_NAND_BASE,
     72	.end		= KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
     73};
     74
     75static struct orion_nand_data kurobox_pro_nand_data = {
     76	.parts		= kurobox_pro_nand_parts,
     77	.nr_parts	= ARRAY_SIZE(kurobox_pro_nand_parts),
     78	.cle		= 0,
     79	.ale		= 1,
     80	.width		= 8,
     81};
     82
     83static struct platform_device kurobox_pro_nand_flash = {
     84	.name		= "orion_nand",
     85	.id		= -1,
     86	.dev		= {
     87		.platform_data	= &kurobox_pro_nand_data,
     88	},
     89	.resource	= &kurobox_pro_nand_resource,
     90	.num_resources	= 1,
     91};
     92
     93/*****************************************************************************
     94 * 256KB NOR Flash on BOOT Device
     95 ****************************************************************************/
     96
     97static struct physmap_flash_data kurobox_pro_nor_flash_data = {
     98	.width		= 1,
     99};
    100
    101static struct resource kurobox_pro_nor_flash_resource = {
    102	.flags			= IORESOURCE_MEM,
    103	.start			= KUROBOX_PRO_NOR_BOOT_BASE,
    104	.end			= KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
    105};
    106
    107static struct platform_device kurobox_pro_nor_flash = {
    108	.name			= "physmap-flash",
    109	.id			= 0,
    110	.dev		= {
    111		.platform_data	= &kurobox_pro_nor_flash_data,
    112	},
    113	.num_resources		= 1,
    114	.resource		= &kurobox_pro_nor_flash_resource,
    115};
    116
    117/*****************************************************************************
    118 * PCI
    119 ****************************************************************************/
    120
    121static int __init kurobox_pro_pci_map_irq(const struct pci_dev *dev, u8 slot,
    122	u8 pin)
    123{
    124	int irq;
    125
    126	/*
    127	 * Check for devices with hard-wired IRQs.
    128	 */
    129	irq = orion5x_pci_map_irq(dev, slot, pin);
    130	if (irq != -1)
    131		return irq;
    132
    133	/*
    134	 * PCI isn't used on the Kuro
    135	 */
    136	return -1;
    137}
    138
    139static struct hw_pci kurobox_pro_pci __initdata = {
    140	.nr_controllers	= 2,
    141	.setup		= orion5x_pci_sys_setup,
    142	.scan		= orion5x_pci_sys_scan_bus,
    143	.map_irq	= kurobox_pro_pci_map_irq,
    144};
    145
    146static int __init kurobox_pro_pci_init(void)
    147{
    148	if (machine_is_kurobox_pro()) {
    149		orion5x_pci_disable();
    150		pci_common_init(&kurobox_pro_pci);
    151	}
    152
    153	return 0;
    154}
    155
    156subsys_initcall(kurobox_pro_pci_init);
    157
    158/*****************************************************************************
    159 * Ethernet
    160 ****************************************************************************/
    161
    162static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
    163	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
    164};
    165
    166/*****************************************************************************
    167 * RTC 5C372a on I2C bus
    168 ****************************************************************************/
    169static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
    170	I2C_BOARD_INFO("rs5c372a", 0x32),
    171};
    172
    173/*****************************************************************************
    174 * SATA
    175 ****************************************************************************/
    176static struct mv_sata_platform_data kurobox_pro_sata_data = {
    177	.n_ports	= 2,
    178};
    179
    180/*****************************************************************************
    181 * Kurobox Pro specific power off method via UART1-attached microcontroller
    182 ****************************************************************************/
    183
    184#define UART1_REG(x)	(UART1_VIRT_BASE + ((UART_##x) << 2))
    185
    186static int kurobox_pro_miconread(unsigned char *buf, int count)
    187{
    188	int i;
    189	int timeout;
    190
    191	for (i = 0; i < count; i++) {
    192		timeout = 10;
    193
    194		while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
    195			if (--timeout == 0)
    196				break;
    197			udelay(1000);
    198		}
    199
    200		if (timeout == 0)
    201			break;
    202		buf[i] = readl(UART1_REG(RX));
    203	}
    204
    205	/* return read bytes */
    206	return i;
    207}
    208
    209static int kurobox_pro_miconwrite(const unsigned char *buf, int count)
    210{
    211	int i = 0;
    212
    213	while (count--) {
    214		while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
    215			barrier();
    216		writel(buf[i++], UART1_REG(TX));
    217	}
    218
    219	return 0;
    220}
    221
    222static int kurobox_pro_miconsend(const unsigned char *data, int count)
    223{
    224	int i;
    225	unsigned char checksum = 0;
    226	unsigned char recv_buf[40];
    227	unsigned char send_buf[40];
    228	unsigned char correct_ack[3];
    229	int retry = 2;
    230
    231	/* Generate checksum */
    232	for (i = 0; i < count; i++)
    233		checksum -=  data[i];
    234
    235	do {
    236		/* Send data */
    237		kurobox_pro_miconwrite(data, count);
    238
    239		/* send checksum */
    240		kurobox_pro_miconwrite(&checksum, 1);
    241
    242		if (kurobox_pro_miconread(recv_buf, sizeof(recv_buf)) <= 3) {
    243			printk(KERN_ERR ">%s: receive failed.\n", __func__);
    244
    245			/* send preamble to clear the receive buffer */
    246			memset(&send_buf, 0xff, sizeof(send_buf));
    247			kurobox_pro_miconwrite(send_buf, sizeof(send_buf));
    248
    249			/* make dummy reads */
    250			mdelay(100);
    251			kurobox_pro_miconread(recv_buf, sizeof(recv_buf));
    252		} else {
    253			/* Generate expected ack */
    254			correct_ack[0] = 0x01;
    255			correct_ack[1] = data[1];
    256			correct_ack[2] = 0x00;
    257
    258			/* checksum Check */
    259			if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
    260			     recv_buf[3]) & 0xFF) {
    261				printk(KERN_ERR ">%s: Checksum Error : "
    262					"Received data[%02x, %02x, %02x, %02x]"
    263					"\n", __func__, recv_buf[0],
    264					recv_buf[1], recv_buf[2], recv_buf[3]);
    265			} else {
    266				/* Check Received Data */
    267				if (correct_ack[0] == recv_buf[0] &&
    268				    correct_ack[1] == recv_buf[1] &&
    269				    correct_ack[2] == recv_buf[2]) {
    270					/* Interval for next command */
    271					mdelay(10);
    272
    273					/* Receive ACK */
    274					return 0;
    275				}
    276			}
    277			/* Received NAK or illegal Data */
    278			printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
    279					"Received\n", __func__);
    280		}
    281	} while (retry--);
    282
    283	/* Interval for next command */
    284	mdelay(10);
    285
    286	return -1;
    287}
    288
    289static void kurobox_pro_power_off(void)
    290{
    291	const unsigned char watchdogkill[]	= {0x01, 0x35, 0x00};
    292	const unsigned char shutdownwait[]	= {0x00, 0x0c};
    293	const unsigned char poweroff[]		= {0x00, 0x06};
    294	/* 38400 baud divisor */
    295	const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400));
    296
    297	pr_info("%s: triggering power-off...\n", __func__);
    298
    299	/* hijack uart1 and reset into sane state (38400,8n1,even parity) */
    300	writel(0x83, UART1_REG(LCR));
    301	writel(divisor & 0xff, UART1_REG(DLL));
    302	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
    303	writel(0x1b, UART1_REG(LCR));
    304	writel(0x00, UART1_REG(IER));
    305	writel(0x07, UART1_REG(FCR));
    306	writel(0x00, UART1_REG(MCR));
    307
    308	/* Send the commands to shutdown the Kurobox Pro */
    309	kurobox_pro_miconsend(watchdogkill, sizeof(watchdogkill)) ;
    310	kurobox_pro_miconsend(shutdownwait, sizeof(shutdownwait)) ;
    311	kurobox_pro_miconsend(poweroff, sizeof(poweroff));
    312}
    313
    314/*****************************************************************************
    315 * General Setup
    316 ****************************************************************************/
    317static unsigned int kurobox_pro_mpp_modes[] __initdata = {
    318	MPP0_UNUSED,
    319	MPP1_UNUSED,
    320	MPP2_GPIO,		/* GPIO Micon */
    321	MPP3_GPIO,		/* GPIO Rtc */
    322	MPP4_UNUSED,
    323	MPP5_UNUSED,
    324	MPP6_NAND,		/* NAND Flash REn */
    325	MPP7_NAND,		/* NAND Flash WEn */
    326	MPP8_UNUSED,
    327	MPP9_UNUSED,
    328	MPP10_UNUSED,
    329	MPP11_UNUSED,
    330	MPP12_SATA_LED,		/* SATA 0 presence */
    331	MPP13_SATA_LED,		/* SATA 1 presence */
    332	MPP14_SATA_LED,		/* SATA 0 active */
    333	MPP15_SATA_LED,		/* SATA 1 active */
    334	MPP16_UART,		/* UART1 RXD */
    335	MPP17_UART,		/* UART1 TXD */
    336	MPP18_UART,		/* UART1 CTSn */
    337	MPP19_UART,		/* UART1 RTSn */
    338	0,
    339};
    340
    341static void __init kurobox_pro_init(void)
    342{
    343	/*
    344	 * Setup basic Orion functions. Need to be called early.
    345	 */
    346	orion5x_init();
    347
    348	orion5x_mpp_conf(kurobox_pro_mpp_modes);
    349
    350	/*
    351	 * Configure peripherals.
    352	 */
    353	orion5x_ehci0_init();
    354	orion5x_ehci1_init();
    355	orion5x_eth_init(&kurobox_pro_eth_data);
    356	orion5x_i2c_init();
    357	orion5x_sata_init(&kurobox_pro_sata_data);
    358	orion5x_uart0_init();
    359	orion5x_uart1_init();
    360	orion5x_xor_init();
    361
    362	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
    363				    ORION_MBUS_DEVBUS_BOOT_ATTR,
    364				    KUROBOX_PRO_NOR_BOOT_BASE,
    365				    KUROBOX_PRO_NOR_BOOT_SIZE);
    366	platform_device_register(&kurobox_pro_nor_flash);
    367
    368	if (machine_is_kurobox_pro()) {
    369		mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(0),
    370					    ORION_MBUS_DEVBUS_ATTR(0),
    371					    KUROBOX_PRO_NAND_BASE,
    372					    KUROBOX_PRO_NAND_SIZE);
    373		platform_device_register(&kurobox_pro_nand_flash);
    374	}
    375
    376	i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
    377
    378	/* register Kurobox Pro specific power-off method */
    379	pm_power_off = kurobox_pro_power_off;
    380}
    381
    382#ifdef CONFIG_MACH_KUROBOX_PRO
    383MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
    384	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
    385	.atag_offset	= 0x100,
    386	.nr_irqs	= ORION5X_NR_IRQS,
    387	.init_machine	= kurobox_pro_init,
    388	.map_io		= orion5x_map_io,
    389	.init_early	= orion5x_init_early,
    390	.init_irq	= orion5x_init_irq,
    391	.init_time	= orion5x_timer_init,
    392	.fixup		= tag_fixup_mem32,
    393	.restart	= orion5x_restart,
    394MACHINE_END
    395#endif
    396
    397#ifdef CONFIG_MACH_LINKSTATION_PRO
    398MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
    399	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
    400	.atag_offset	= 0x100,
    401	.nr_irqs	= ORION5X_NR_IRQS,
    402	.init_machine	= kurobox_pro_init,
    403	.map_io		= orion5x_map_io,
    404	.init_early	= orion5x_init_early,
    405	.init_irq	= orion5x_init_irq,
    406	.init_time	= orion5x_timer_init,
    407	.fixup		= tag_fixup_mem32,
    408	.restart	= orion5x_restart,
    409MACHINE_END
    410#endif