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

ts78xx-setup.c (14171B)


      1/*
      2 * arch/arm/mach-orion5x/ts78xx-setup.c
      3 *
      4 * Maintainer: Alexander Clouter <alex@digriz.org.uk>
      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
     11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     12
     13#include <linux/kernel.h>
     14#include <linux/init.h>
     15#include <linux/sysfs.h>
     16#include <linux/platform_device.h>
     17#include <linux/mv643xx_eth.h>
     18#include <linux/ata_platform.h>
     19#include <linux/mtd/platnand.h>
     20#include <linux/timeriomem-rng.h>
     21#include <asm/mach-types.h>
     22#include <asm/mach/arch.h>
     23#include <asm/mach/map.h>
     24#include "common.h"
     25#include "mpp.h"
     26#include "orion5x.h"
     27#include "ts78xx-fpga.h"
     28
     29/*****************************************************************************
     30 * TS-78xx Info
     31 ****************************************************************************/
     32
     33/*
     34 * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE
     35 */
     36#define TS78XX_FPGA_REGS_PHYS_BASE	0xe8000000
     37#define TS78XX_FPGA_REGS_VIRT_BASE	IOMEM(0xff900000)
     38#define TS78XX_FPGA_REGS_SIZE		SZ_1M
     39
     40static struct ts78xx_fpga_data ts78xx_fpga = {
     41	.id		= 0,
     42	.state		= 1,
     43/*	.supports	= ... - populated by ts78xx_fpga_supports() */
     44};
     45
     46/*****************************************************************************
     47 * I/O Address Mapping
     48 ****************************************************************************/
     49static struct map_desc ts78xx_io_desc[] __initdata = {
     50	{
     51		.virtual	= (unsigned long)TS78XX_FPGA_REGS_VIRT_BASE,
     52		.pfn		= __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE),
     53		.length		= TS78XX_FPGA_REGS_SIZE,
     54		.type		= MT_DEVICE,
     55	},
     56};
     57
     58static void __init ts78xx_map_io(void)
     59{
     60	orion5x_map_io();
     61	iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc));
     62}
     63
     64/*****************************************************************************
     65 * Ethernet
     66 ****************************************************************************/
     67static struct mv643xx_eth_platform_data ts78xx_eth_data = {
     68	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
     69};
     70
     71/*****************************************************************************
     72 * SATA
     73 ****************************************************************************/
     74static struct mv_sata_platform_data ts78xx_sata_data = {
     75	.n_ports	= 2,
     76};
     77
     78/*****************************************************************************
     79 * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
     80 ****************************************************************************/
     81#define TS_RTC_CTRL	(TS78XX_FPGA_REGS_PHYS_BASE + 0x808)
     82#define TS_RTC_DATA	(TS78XX_FPGA_REGS_PHYS_BASE + 0x80c)
     83
     84static struct resource ts78xx_ts_rtc_resources[] = {
     85	DEFINE_RES_MEM(TS_RTC_CTRL, 0x01),
     86	DEFINE_RES_MEM(TS_RTC_DATA, 0x01),
     87};
     88
     89static struct platform_device ts78xx_ts_rtc_device = {
     90	.name		= "rtc-m48t86",
     91	.id		= -1,
     92	.resource	= ts78xx_ts_rtc_resources,
     93	.num_resources 	= ARRAY_SIZE(ts78xx_ts_rtc_resources),
     94};
     95
     96static int ts78xx_ts_rtc_load(void)
     97{
     98	int rc;
     99
    100	if (ts78xx_fpga.supports.ts_rtc.init == 0) {
    101		rc = platform_device_register(&ts78xx_ts_rtc_device);
    102		if (!rc)
    103			ts78xx_fpga.supports.ts_rtc.init = 1;
    104	} else {
    105		rc = platform_device_add(&ts78xx_ts_rtc_device);
    106	}
    107
    108	if (rc)
    109		pr_info("RTC could not be registered: %d\n", rc);
    110
    111	return rc;
    112}
    113
    114static void ts78xx_ts_rtc_unload(void)
    115{
    116	platform_device_del(&ts78xx_ts_rtc_device);
    117}
    118
    119/*****************************************************************************
    120 * NAND Flash
    121 ****************************************************************************/
    122#define TS_NAND_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE + 0x800)	/* VIRT */
    123#define TS_NAND_DATA	(TS78XX_FPGA_REGS_PHYS_BASE + 0x804)	/* PHYS */
    124
    125/*
    126 * hardware specific access to control-lines
    127 *
    128 * ctrl:
    129 * NAND_NCE: bit 0 -> bit 2
    130 * NAND_CLE: bit 1 -> bit 1
    131 * NAND_ALE: bit 2 -> bit 0
    132 */
    133static void ts78xx_ts_nand_cmd_ctrl(struct nand_chip *this, int cmd,
    134				    unsigned int ctrl)
    135{
    136	if (ctrl & NAND_CTRL_CHANGE) {
    137		unsigned char bits;
    138
    139		bits = (ctrl & NAND_NCE) << 2;
    140		bits |= ctrl & NAND_CLE;
    141		bits |= (ctrl & NAND_ALE) >> 2;
    142
    143		writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL);
    144	}
    145
    146	if (cmd != NAND_CMD_NONE)
    147		writeb(cmd, this->legacy.IO_ADDR_W);
    148}
    149
    150static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip)
    151{
    152	return readb(TS_NAND_CTRL) & 0x20;
    153}
    154
    155static void ts78xx_ts_nand_write_buf(struct nand_chip *chip,
    156				     const uint8_t *buf, int len)
    157{
    158	void __iomem *io_base = chip->legacy.IO_ADDR_W;
    159	unsigned long off = ((unsigned long)buf & 3);
    160	int sz;
    161
    162	if (off) {
    163		sz = min_t(int, 4 - off, len);
    164		writesb(io_base, buf, sz);
    165		buf += sz;
    166		len -= sz;
    167	}
    168
    169	sz = len >> 2;
    170	if (sz) {
    171		u32 *buf32 = (u32 *)buf;
    172		writesl(io_base, buf32, sz);
    173		buf += sz << 2;
    174		len -= sz << 2;
    175	}
    176
    177	if (len)
    178		writesb(io_base, buf, len);
    179}
    180
    181static void ts78xx_ts_nand_read_buf(struct nand_chip *chip,
    182				    uint8_t *buf, int len)
    183{
    184	void __iomem *io_base = chip->legacy.IO_ADDR_R;
    185	unsigned long off = ((unsigned long)buf & 3);
    186	int sz;
    187
    188	if (off) {
    189		sz = min_t(int, 4 - off, len);
    190		readsb(io_base, buf, sz);
    191		buf += sz;
    192		len -= sz;
    193	}
    194
    195	sz = len >> 2;
    196	if (sz) {
    197		u32 *buf32 = (u32 *)buf;
    198		readsl(io_base, buf32, sz);
    199		buf += sz << 2;
    200		len -= sz << 2;
    201	}
    202
    203	if (len)
    204		readsb(io_base, buf, len);
    205}
    206
    207static struct mtd_partition ts78xx_ts_nand_parts[] = {
    208	{
    209		.name		= "mbr",
    210		.offset		= 0,
    211		.size		= SZ_128K,
    212		.mask_flags	= MTD_WRITEABLE,
    213	}, {
    214		.name		= "kernel",
    215		.offset		= MTDPART_OFS_APPEND,
    216		.size		= SZ_4M,
    217	}, {
    218		.name		= "initrd",
    219		.offset		= MTDPART_OFS_APPEND,
    220		.size		= SZ_4M,
    221	}, {
    222		.name		= "rootfs",
    223		.offset		= MTDPART_OFS_APPEND,
    224		.size		= MTDPART_SIZ_FULL,
    225	}
    226};
    227
    228static struct platform_nand_data ts78xx_ts_nand_data = {
    229	.chip	= {
    230		.nr_chips		= 1,
    231		.partitions		= ts78xx_ts_nand_parts,
    232		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
    233		.chip_delay		= 15,
    234		.bbt_options		= NAND_BBT_USE_FLASH,
    235	},
    236	.ctrl	= {
    237		/*
    238		 * The HW ECC offloading functions, used to give about a 9%
    239		 * performance increase for 'dd if=/dev/mtdblockX' and 5% for
    240		 * nanddump.  This all however was changed by git commit
    241		 * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is
    242		 * no performance advantage to be had so we no longer bother
    243		 */
    244		.cmd_ctrl		= ts78xx_ts_nand_cmd_ctrl,
    245		.dev_ready		= ts78xx_ts_nand_dev_ready,
    246		.write_buf		= ts78xx_ts_nand_write_buf,
    247		.read_buf		= ts78xx_ts_nand_read_buf,
    248	},
    249};
    250
    251static struct resource ts78xx_ts_nand_resources
    252			= DEFINE_RES_MEM(TS_NAND_DATA, 4);
    253
    254static struct platform_device ts78xx_ts_nand_device = {
    255	.name		= "gen_nand",
    256	.id		= -1,
    257	.dev		= {
    258		.platform_data	= &ts78xx_ts_nand_data,
    259	},
    260	.resource	= &ts78xx_ts_nand_resources,
    261	.num_resources	= 1,
    262};
    263
    264static int ts78xx_ts_nand_load(void)
    265{
    266	int rc;
    267
    268	if (ts78xx_fpga.supports.ts_nand.init == 0) {
    269		rc = platform_device_register(&ts78xx_ts_nand_device);
    270		if (!rc)
    271			ts78xx_fpga.supports.ts_nand.init = 1;
    272	} else
    273		rc = platform_device_add(&ts78xx_ts_nand_device);
    274
    275	if (rc)
    276		pr_info("NAND could not be registered: %d\n", rc);
    277	return rc;
    278};
    279
    280static void ts78xx_ts_nand_unload(void)
    281{
    282	platform_device_del(&ts78xx_ts_nand_device);
    283}
    284
    285/*****************************************************************************
    286 * HW RNG
    287 ****************************************************************************/
    288#define TS_RNG_DATA	(TS78XX_FPGA_REGS_PHYS_BASE | 0x044)
    289
    290static struct resource ts78xx_ts_rng_resource
    291			= DEFINE_RES_MEM(TS_RNG_DATA, 4);
    292
    293static struct timeriomem_rng_data ts78xx_ts_rng_data = {
    294	.period		= 1000000, /* one second */
    295};
    296
    297static struct platform_device ts78xx_ts_rng_device = {
    298	.name		= "timeriomem_rng",
    299	.id		= -1,
    300	.dev		= {
    301		.platform_data	= &ts78xx_ts_rng_data,
    302	},
    303	.resource	= &ts78xx_ts_rng_resource,
    304	.num_resources	= 1,
    305};
    306
    307static int ts78xx_ts_rng_load(void)
    308{
    309	int rc;
    310
    311	if (ts78xx_fpga.supports.ts_rng.init == 0) {
    312		rc = platform_device_register(&ts78xx_ts_rng_device);
    313		if (!rc)
    314			ts78xx_fpga.supports.ts_rng.init = 1;
    315	} else
    316		rc = platform_device_add(&ts78xx_ts_rng_device);
    317
    318	if (rc)
    319		pr_info("RNG could not be registered: %d\n", rc);
    320	return rc;
    321};
    322
    323static void ts78xx_ts_rng_unload(void)
    324{
    325	platform_device_del(&ts78xx_ts_rng_device);
    326}
    327
    328/*****************************************************************************
    329 * FPGA 'hotplug' support code
    330 ****************************************************************************/
    331static void ts78xx_fpga_devices_zero_init(void)
    332{
    333	ts78xx_fpga.supports.ts_rtc.init = 0;
    334	ts78xx_fpga.supports.ts_nand.init = 0;
    335	ts78xx_fpga.supports.ts_rng.init = 0;
    336}
    337
    338static void ts78xx_fpga_supports(void)
    339{
    340	/* TODO: put this 'table' into ts78xx-fpga.h */
    341	switch (ts78xx_fpga.id) {
    342	case TS7800_REV_1:
    343	case TS7800_REV_2:
    344	case TS7800_REV_3:
    345	case TS7800_REV_4:
    346	case TS7800_REV_5:
    347	case TS7800_REV_6:
    348	case TS7800_REV_7:
    349	case TS7800_REV_8:
    350	case TS7800_REV_9:
    351		ts78xx_fpga.supports.ts_rtc.present = 1;
    352		ts78xx_fpga.supports.ts_nand.present = 1;
    353		ts78xx_fpga.supports.ts_rng.present = 1;
    354		break;
    355	default:
    356		/* enable devices if magic matches */
    357		switch ((ts78xx_fpga.id >> 8) & 0xffffff) {
    358		case TS7800_FPGA_MAGIC:
    359			pr_warn("unrecognised FPGA revision 0x%.2x\n",
    360				ts78xx_fpga.id & 0xff);
    361			ts78xx_fpga.supports.ts_rtc.present = 1;
    362			ts78xx_fpga.supports.ts_nand.present = 1;
    363			ts78xx_fpga.supports.ts_rng.present = 1;
    364			break;
    365		default:
    366			ts78xx_fpga.supports.ts_rtc.present = 0;
    367			ts78xx_fpga.supports.ts_nand.present = 0;
    368			ts78xx_fpga.supports.ts_rng.present = 0;
    369		}
    370	}
    371}
    372
    373static int ts78xx_fpga_load_devices(void)
    374{
    375	int tmp, ret = 0;
    376
    377	if (ts78xx_fpga.supports.ts_rtc.present == 1) {
    378		tmp = ts78xx_ts_rtc_load();
    379		if (tmp)
    380			ts78xx_fpga.supports.ts_rtc.present = 0;
    381		ret |= tmp;
    382	}
    383	if (ts78xx_fpga.supports.ts_nand.present == 1) {
    384		tmp = ts78xx_ts_nand_load();
    385		if (tmp)
    386			ts78xx_fpga.supports.ts_nand.present = 0;
    387		ret |= tmp;
    388	}
    389	if (ts78xx_fpga.supports.ts_rng.present == 1) {
    390		tmp = ts78xx_ts_rng_load();
    391		if (tmp)
    392			ts78xx_fpga.supports.ts_rng.present = 0;
    393		ret |= tmp;
    394	}
    395
    396	return ret;
    397}
    398
    399static int ts78xx_fpga_unload_devices(void)
    400{
    401
    402	if (ts78xx_fpga.supports.ts_rtc.present == 1)
    403		ts78xx_ts_rtc_unload();
    404	if (ts78xx_fpga.supports.ts_nand.present == 1)
    405		ts78xx_ts_nand_unload();
    406	if (ts78xx_fpga.supports.ts_rng.present == 1)
    407		ts78xx_ts_rng_unload();
    408
    409	return 0;
    410}
    411
    412static int ts78xx_fpga_load(void)
    413{
    414	ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
    415
    416	pr_info("FPGA magic=0x%.6x, rev=0x%.2x\n",
    417			(ts78xx_fpga.id >> 8) & 0xffffff,
    418			ts78xx_fpga.id & 0xff);
    419
    420	ts78xx_fpga_supports();
    421
    422	if (ts78xx_fpga_load_devices()) {
    423		ts78xx_fpga.state = -1;
    424		return -EBUSY;
    425	}
    426
    427	return 0;
    428};
    429
    430static int ts78xx_fpga_unload(void)
    431{
    432	unsigned int fpga_id;
    433
    434	fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
    435
    436	/*
    437	 * There does not seem to be a feasible way to block access to the GPIO
    438	 * pins from userspace (/dev/mem).  This if clause should hopefully warn
    439	 * those foolish enough not to follow 'policy' :)
    440	 *
    441	 * UrJTAG SVN since r1381 can be used to reprogram the FPGA
    442	 */
    443	if (ts78xx_fpga.id != fpga_id) {
    444		pr_err("FPGA magic/rev mismatch\n"
    445			"TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n",
    446			(ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff,
    447			(fpga_id >> 8) & 0xffffff, fpga_id & 0xff);
    448		ts78xx_fpga.state = -1;
    449		return -EBUSY;
    450	}
    451
    452	if (ts78xx_fpga_unload_devices()) {
    453		ts78xx_fpga.state = -1;
    454		return -EBUSY;
    455	}
    456
    457	return 0;
    458};
    459
    460static ssize_t ts78xx_fpga_show(struct kobject *kobj,
    461			struct kobj_attribute *attr, char *buf)
    462{
    463	if (ts78xx_fpga.state < 0)
    464		return sprintf(buf, "borked\n");
    465
    466	return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline");
    467}
    468
    469static ssize_t ts78xx_fpga_store(struct kobject *kobj,
    470			struct kobj_attribute *attr, const char *buf, size_t n)
    471{
    472	int value, ret;
    473
    474	if (ts78xx_fpga.state < 0) {
    475		pr_err("FPGA borked, you must powercycle ASAP\n");
    476		return -EBUSY;
    477	}
    478
    479	if (strncmp(buf, "online", sizeof("online") - 1) == 0)
    480		value = 1;
    481	else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
    482		value = 0;
    483	else
    484		return -EINVAL;
    485
    486	if (ts78xx_fpga.state == value)
    487		return n;
    488
    489	ret = (ts78xx_fpga.state == 0)
    490		? ts78xx_fpga_load()
    491		: ts78xx_fpga_unload();
    492
    493	if (!(ret < 0))
    494		ts78xx_fpga.state = value;
    495
    496	return n;
    497}
    498
    499static struct kobj_attribute ts78xx_fpga_attr =
    500	__ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store);
    501
    502/*****************************************************************************
    503 * General Setup
    504 ****************************************************************************/
    505static unsigned int ts78xx_mpp_modes[] __initdata = {
    506	MPP0_UNUSED,
    507	MPP1_GPIO,		/* JTAG Clock */
    508	MPP2_GPIO,		/* JTAG Data In */
    509	MPP3_GPIO,		/* Lat ECP2 256 FPGA - PB2B */
    510	MPP4_GPIO,		/* JTAG Data Out */
    511	MPP5_GPIO,		/* JTAG TMS */
    512	MPP6_GPIO,		/* Lat ECP2 256 FPGA - PB31A_CLK4+ */
    513	MPP7_GPIO,		/* Lat ECP2 256 FPGA - PB22B */
    514	MPP8_UNUSED,
    515	MPP9_UNUSED,
    516	MPP10_UNUSED,
    517	MPP11_UNUSED,
    518	MPP12_UNUSED,
    519	MPP13_UNUSED,
    520	MPP14_UNUSED,
    521	MPP15_UNUSED,
    522	MPP16_UART,
    523	MPP17_UART,
    524	MPP18_UART,
    525	MPP19_UART,
    526	/*
    527	 * MPP[20] PCI Clock Out 1
    528	 * MPP[21] PCI Clock Out 0
    529	 * MPP[22] Unused
    530	 * MPP[23] Unused
    531	 * MPP[24] Unused
    532	 * MPP[25] Unused
    533	 */
    534	0,
    535};
    536
    537static void __init ts78xx_init(void)
    538{
    539	int ret;
    540
    541	/*
    542	 * Setup basic Orion functions. Need to be called early.
    543	 */
    544	orion5x_init();
    545
    546	orion5x_mpp_conf(ts78xx_mpp_modes);
    547
    548	/*
    549	 * Configure peripherals.
    550	 */
    551	orion5x_ehci0_init();
    552	orion5x_ehci1_init();
    553	orion5x_eth_init(&ts78xx_eth_data);
    554	orion5x_sata_init(&ts78xx_sata_data);
    555	orion5x_uart0_init();
    556	orion5x_uart1_init();
    557	orion5x_xor_init();
    558
    559	/* FPGA init */
    560	ts78xx_fpga_devices_zero_init();
    561	ret = ts78xx_fpga_load();
    562	ret = sysfs_create_file(firmware_kobj, &ts78xx_fpga_attr.attr);
    563	if (ret)
    564		pr_err("sysfs_create_file failed: %d\n", ret);
    565}
    566
    567MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
    568	/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
    569	.atag_offset	= 0x100,
    570	.nr_irqs	= ORION5X_NR_IRQS,
    571	.init_machine	= ts78xx_init,
    572	.map_io		= ts78xx_map_io,
    573	.init_early	= orion5x_init_early,
    574	.init_irq	= orion5x_init_irq,
    575	.init_time	= orion5x_timer_init,
    576	.restart	= orion5x_restart,
    577MACHINE_END