17171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/* 27171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * arch/arm/mach-orion5x/ts78xx-setup.c 37171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * 47171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * Maintainer: Alexander Clouter <alex@digriz.org.uk> 57171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * 67171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * This file is licensed under the terms of the GNU General Public 77171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * License version 2. This program is licensed "as is" without any 87171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * warranty of any kind, whether express or implied. 97171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter */ 107171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 114d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 124d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter 137171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/kernel.h> 147171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/init.h> 1539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter#include <linux/sysfs.h> 167171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/platform_device.h> 177171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/mv643xx_eth.h> 187171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/ata_platform.h> 197171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <linux/m48t86.h> 2075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter#include <linux/mtd/nand.h> 2175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter#include <linux/mtd/partitions.h> 22a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter#include <linux/timeriomem-rng.h> 237171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <asm/mach-types.h> 247171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <asm/mach/arch.h> 257171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include <asm/mach/map.h> 26a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/orion5x.h> 277171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include "common.h" 287171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#include "mpp.h" 2939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter#include "ts78xx-fpga.h" 307171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 317171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 327171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * TS-78xx Info 337171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 347171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 357171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/* 367171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE 377171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter */ 387171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#define TS78XX_FPGA_REGS_PHYS_BASE 0xe8000000 39ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn#define TS78XX_FPGA_REGS_VIRT_BASE IOMEM(0xff900000) 407171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter#define TS78XX_FPGA_REGS_SIZE SZ_1M 417171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 4239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic struct ts78xx_fpga_data ts78xx_fpga = { 4339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .id = 0, 4439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .state = 1, 4539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter/* .supports = ... - populated by ts78xx_fpga_supports() */ 4639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter}; 477171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 487171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 497171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * I/O Address Mapping 507171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 517171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouterstatic struct map_desc ts78xx_io_desc[] __initdata = { 527171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter { 53ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn .virtual = (unsigned long)TS78XX_FPGA_REGS_VIRT_BASE, 547171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .pfn = __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE), 557171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .length = TS78XX_FPGA_REGS_SIZE, 567171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .type = MT_DEVICE, 577171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter }, 587171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 597171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 604236666688e9dbc38d0c7a98b7cfa16c8961f752Andrew Lunnstatic void __init ts78xx_map_io(void) 617171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter{ 627171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_map_io(); 637171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc)); 647171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter} 657171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 667171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 677171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * Ethernet 687171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 697171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouterstatic struct mv643xx_eth_platform_data ts78xx_eth_data = { 70ac840605f3b1d9b99e1e6629a54994f8e003ff91Lennert Buytenhek .phy_addr = MV643XX_ETH_PHY_ADDR(0), 717171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 727171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 737171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 7439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * SATA 7539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ****************************************************************************/ 7639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic struct mv_sata_platform_data ts78xx_sata_data = { 7739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .n_ports = 2, 7839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter}; 7939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 8039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter/***************************************************************************** 817171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c 827171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 83ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn#define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x808) 84ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn#define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE + 0x80c) 8539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 8639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) 877171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter{ 8839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter writeb(addr, TS_RTC_CTRL); 8939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return readb(TS_RTC_DATA); 907171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter} 917171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 9239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) 937171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter{ 9439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter writeb(addr, TS_RTC_CTRL); 9539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter writeb(value, TS_RTC_DATA); 967171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter} 977171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 9839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic struct m48t86_ops ts78xx_ts_rtc_ops = { 9939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .readbyte = ts78xx_ts_rtc_readbyte, 10039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .writebyte = ts78xx_ts_rtc_writebyte, 1017171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 1027171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 10339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic struct platform_device ts78xx_ts_rtc_device = { 1047171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .name = "rtc-m48t86", 1057171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .id = -1, 1067171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .dev = { 10739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter .platform_data = &ts78xx_ts_rtc_ops, 1087171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter }, 1097171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .num_resources = 0, 1107171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 1117171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 1127171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/* 1137171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * TS uses some of the user storage space on the RTC chip so see if it is 1147171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * present; as it's an optional feature at purchase time and not all boards 1157171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * will have it present 1167171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * 1177171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * I've used the method TS use in their rtc7800.c example for the detection 1187171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * 1197171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * TODO: track down a guinea pig without an RTC to see if we can work out a 1209f234997dac445a64f5d9672bf21649e6d745bb9Alexander Clouter * better RTC detection routine 1217171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter */ 12239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic int ts78xx_ts_rtc_load(void) 1237171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter{ 124f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter int rc; 1257171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter unsigned char tmp_rtc0, tmp_rtc1; 1267171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 12739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); 12839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); 12939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 13039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_writebyte(0x00, 126); 13139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_writebyte(0x55, 127); 13239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_ts_rtc_readbyte(127) == 0x55) { 13339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_writebyte(0xaa, 127); 13439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_ts_rtc_readbyte(127) == 0xaa 13539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter && ts78xx_ts_rtc_readbyte(126) == 0x00) { 13639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); 13739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); 138f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter 13939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.supports.ts_rtc.init == 0) { 140f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter rc = platform_device_register(&ts78xx_ts_rtc_device); 141f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter if (!rc) 142f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter ts78xx_fpga.supports.ts_rtc.init = 1; 14339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } else 144f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter rc = platform_device_add(&ts78xx_ts_rtc_device); 145f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter 1464d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (rc) 1474d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_info("RTC could not be registered: %d\n", 1484d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter rc); 149f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter return rc; 1507171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter } 1517171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter } 1527171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 1534d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_info("RTC not found\n"); 15439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -ENODEV; 1557171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 15639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 15739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic void ts78xx_ts_rtc_unload(void) 15839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 15939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter platform_device_del(&ts78xx_ts_rtc_device); 16039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 1617171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 1627171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 16375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * NAND Flash 16475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ****************************************************************************/ 165ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn#define TS_NAND_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x800) /* VIRT */ 166ac3524b7f5a6b9a744fb7ea19991355354c09afbAndrew Lunn#define TS_NAND_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x804) /* PHYS */ 16775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 16875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter/* 16975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * hardware specific access to control-lines 17075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * 17175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * ctrl: 17275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * NAND_NCE: bit 0 -> bit 2 17375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * NAND_CLE: bit 1 -> bit 1 17475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * NAND_ALE: bit 2 -> bit 0 17575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter */ 17675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, 17775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter unsigned int ctrl) 17875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter{ 17975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter struct nand_chip *this = mtd->priv; 18075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 18175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (ctrl & NAND_CTRL_CHANGE) { 18275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter unsigned char bits; 18375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 18475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter bits = (ctrl & NAND_NCE) << 2; 18575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter bits |= ctrl & NAND_CLE; 18675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter bits |= (ctrl & NAND_ALE) >> 2; 18775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 18875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL); 18975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter } 19075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 19175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (cmd != NAND_CMD_NONE) 19275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter writeb(cmd, this->IO_ADDR_W); 19375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter} 19475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 19575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd) 19675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter{ 19775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter return readb(TS_NAND_CTRL) & 0x20; 19875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter} 19975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 200e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouterstatic void ts78xx_ts_nand_write_buf(struct mtd_info *mtd, 201e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter const uint8_t *buf, int len) 202e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter{ 203e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter struct nand_chip *chip = mtd->priv; 204e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter void __iomem *io_base = chip->IO_ADDR_W; 205e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter unsigned long off = ((unsigned long)buf & 3); 206e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter int sz; 207e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 208e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (off) { 20953936c56dcaf1db818fe953ae05592a8b5e345b5Alexander Clouter sz = min_t(int, 4 - off, len); 210e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter writesb(io_base, buf, sz); 211e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter buf += sz; 212e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter len -= sz; 213e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter } 214e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 215e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter sz = len >> 2; 216e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (sz) { 217e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter u32 *buf32 = (u32 *)buf; 218e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter writesl(io_base, buf32, sz); 219e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter buf += sz << 2; 220e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter len -= sz << 2; 221e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter } 222e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 223e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (len) 224e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter writesb(io_base, buf, len); 225e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter} 226e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 227e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouterstatic void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, 228e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter uint8_t *buf, int len) 229e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter{ 230e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter struct nand_chip *chip = mtd->priv; 231e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter void __iomem *io_base = chip->IO_ADDR_R; 232e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter unsigned long off = ((unsigned long)buf & 3); 233e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter int sz; 234e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 235e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (off) { 23653936c56dcaf1db818fe953ae05592a8b5e345b5Alexander Clouter sz = min_t(int, 4 - off, len); 237e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter readsb(io_base, buf, sz); 238e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter buf += sz; 239e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter len -= sz; 240e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter } 241e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 242e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter sz = len >> 2; 243e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (sz) { 244e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter u32 *buf32 = (u32 *)buf; 245e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter readsl(io_base, buf32, sz); 246e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter buf += sz << 2; 247e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter len -= sz << 2; 248e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter } 249e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 250e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter if (len) 251e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter readsb(io_base, buf, len); 252e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter} 253e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter 25475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic struct mtd_partition ts78xx_ts_nand_parts[] = { 25575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter { 25675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .name = "mbr", 25775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .offset = 0, 25875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .size = SZ_128K, 25975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .mask_flags = MTD_WRITEABLE, 26075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, { 26175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .name = "kernel", 26275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .offset = MTDPART_OFS_APPEND, 26375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .size = SZ_4M, 26475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, { 26575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .name = "initrd", 26675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .offset = MTDPART_OFS_APPEND, 26775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .size = SZ_4M, 26875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, { 26975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .name = "rootfs", 27075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .offset = MTDPART_OFS_APPEND, 27175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .size = MTDPART_SIZ_FULL, 27275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter } 27375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter}; 27475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 27575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic struct platform_nand_data ts78xx_ts_nand_data = { 27675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .chip = { 277ef077179a2909d3d0d3accf29ad1ea9ebb19019bMarek Vasut .nr_chips = 1, 27875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .partitions = ts78xx_ts_nand_parts, 27975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), 28075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .chip_delay = 15, 281bb9ebd4e714385a2592a482845865ef2d58b2868Brian Norris .bbt_options = NAND_BBT_USE_FLASH, 28275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, 28375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .ctrl = { 28475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter /* 28575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * The HW ECC offloading functions, used to give about a 9% 28675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * performance increase for 'dd if=/dev/mtdblockX' and 5% for 28775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * nanddump. This all however was changed by git commit 28875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is 28975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter * no performance advantage to be had so we no longer bother 29075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter */ 29175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl, 29275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .dev_ready = ts78xx_ts_nand_dev_ready, 293e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter .write_buf = ts78xx_ts_nand_write_buf, 294e25bac968d41d994e5295f89547bdff6cb40588aAlexander Clouter .read_buf = ts78xx_ts_nand_read_buf, 29575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, 29675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter}; 29775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 298167473a5937f54aaac4c3c01a192a81214933a23Alexander Clouterstatic struct resource ts78xx_ts_nand_resources 299167473a5937f54aaac4c3c01a192a81214933a23Alexander Clouter = DEFINE_RES_MEM(TS_NAND_DATA, 4); 30075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 30175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic struct platform_device ts78xx_ts_nand_device = { 30275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .name = "gen_nand", 30375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .id = -1, 30475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .dev = { 30575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .platform_data = &ts78xx_ts_nand_data, 30675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter }, 30775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .resource = &ts78xx_ts_nand_resources, 30875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter .num_resources = 1, 30975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter}; 31075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 31175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic int ts78xx_ts_nand_load(void) 31275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter{ 31375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter int rc; 31475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 31575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (ts78xx_fpga.supports.ts_nand.init == 0) { 31675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter rc = platform_device_register(&ts78xx_ts_nand_device); 31775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (!rc) 31875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ts78xx_fpga.supports.ts_nand.init = 1; 31975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter } else 32075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter rc = platform_device_add(&ts78xx_ts_nand_device); 32175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 3224d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (rc) 3234d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_info("NAND could not be registered: %d\n", rc); 32475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter return rc; 32575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter}; 32675bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 32775bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouterstatic void ts78xx_ts_nand_unload(void) 32875bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter{ 32975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter platform_device_del(&ts78xx_ts_nand_device); 33075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter} 33175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter 33275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter/***************************************************************************** 333a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter * HW RNG 334a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ****************************************************************************/ 335a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter#define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044) 336a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 337167473a5937f54aaac4c3c01a192a81214933a23Alexander Clouterstatic struct resource ts78xx_ts_rng_resource 338167473a5937f54aaac4c3c01a192a81214933a23Alexander Clouter = DEFINE_RES_MEM(TS_RNG_DATA, 4); 339a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 340a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouterstatic struct timeriomem_rng_data ts78xx_ts_rng_data = { 341a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .period = 1000000, /* one second */ 342a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter}; 343a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 344a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouterstatic struct platform_device ts78xx_ts_rng_device = { 345a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .name = "timeriomem_rng", 346a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .id = -1, 347a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .dev = { 348a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .platform_data = &ts78xx_ts_rng_data, 349a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter }, 350a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .resource = &ts78xx_ts_rng_resource, 351a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter .num_resources = 1, 352a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter}; 353a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 354a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouterstatic int ts78xx_ts_rng_load(void) 355a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter{ 356a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter int rc; 357a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 358a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter if (ts78xx_fpga.supports.ts_rng.init == 0) { 359a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter rc = platform_device_register(&ts78xx_ts_rng_device); 360a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter if (!rc) 361a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ts78xx_fpga.supports.ts_rng.init = 1; 362a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter } else 363a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter rc = platform_device_add(&ts78xx_ts_rng_device); 364a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 3654d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (rc) 3664d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_info("RNG could not be registered: %d\n", rc); 367a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter return rc; 368a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter}; 369a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 370a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouterstatic void ts78xx_ts_rng_unload(void) 371a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter{ 372a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter platform_device_del(&ts78xx_ts_rng_device); 373a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter} 374a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter 375a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter/***************************************************************************** 37639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * FPGA 'hotplug' support code 3777171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 37839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic void ts78xx_fpga_devices_zero_init(void) 37939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 38039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.supports.ts_rtc.init = 0; 38175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ts78xx_fpga.supports.ts_nand.init = 0; 382a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ts78xx_fpga.supports.ts_rng.init = 0; 38339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 38439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 38539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic void ts78xx_fpga_supports(void) 38639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 38739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter /* TODO: put this 'table' into ts78xx-fpga.h */ 38839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter switch (ts78xx_fpga.id) { 3890c1355e36fdc304b102851312d80a1e69c01f5a2Alexander Clouter case TS7800_REV_1: 3900c1355e36fdc304b102851312d80a1e69c01f5a2Alexander Clouter case TS7800_REV_2: 3910c1355e36fdc304b102851312d80a1e69c01f5a2Alexander Clouter case TS7800_REV_3: 3920c1355e36fdc304b102851312d80a1e69c01f5a2Alexander Clouter case TS7800_REV_4: 3930c1355e36fdc304b102851312d80a1e69c01f5a2Alexander Clouter case TS7800_REV_5: 39417718e17a25cc989954a8430985b3133ca21422eAlexander Clouter case TS7800_REV_6: 39517718e17a25cc989954a8430985b3133ca21422eAlexander Clouter case TS7800_REV_7: 39617718e17a25cc989954a8430985b3133ca21422eAlexander Clouter case TS7800_REV_8: 39717718e17a25cc989954a8430985b3133ca21422eAlexander Clouter case TS7800_REV_9: 39839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.supports.ts_rtc.present = 1; 39975bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ts78xx_fpga.supports.ts_nand.present = 1; 400a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ts78xx_fpga.supports.ts_rng.present = 1; 40139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter break; 40239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter default: 403b3882330843650b751817712db57b9a7061e7879Alexander Clouter /* enable devices if magic matches */ 404b3882330843650b751817712db57b9a7061e7879Alexander Clouter switch ((ts78xx_fpga.id >> 8) & 0xffffff) { 405b3882330843650b751817712db57b9a7061e7879Alexander Clouter case TS7800_FPGA_MAGIC: 4069d06d34bcc62f4cc3679704ac42cff5b44a97c6eJoe Perches pr_warn("unrecognised FPGA revision 0x%.2x\n", 4079d06d34bcc62f4cc3679704ac42cff5b44a97c6eJoe Perches ts78xx_fpga.id & 0xff); 408b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_rtc.present = 1; 409b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_nand.present = 1; 410b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_rng.present = 1; 411b3882330843650b751817712db57b9a7061e7879Alexander Clouter break; 412b3882330843650b751817712db57b9a7061e7879Alexander Clouter default: 413b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_rtc.present = 0; 414b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_nand.present = 0; 415b3882330843650b751817712db57b9a7061e7879Alexander Clouter ts78xx_fpga.supports.ts_rng.present = 0; 416b3882330843650b751817712db57b9a7061e7879Alexander Clouter } 41739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 41839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 41939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 42039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic int ts78xx_fpga_load_devices(void) 42139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 42239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter int tmp, ret = 0; 42339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 42439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.supports.ts_rtc.present == 1) { 42539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter tmp = ts78xx_ts_rtc_load(); 4264d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (tmp) 427f5273fa3102fa4c25819f3034b8834c37d3e62a3Alexander Clouter ts78xx_fpga.supports.ts_rtc.present = 0; 42839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ret |= tmp; 42939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 43075bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (ts78xx_fpga.supports.ts_nand.present == 1) { 43175bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter tmp = ts78xx_ts_nand_load(); 4324d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (tmp) 43375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ts78xx_fpga.supports.ts_nand.present = 0; 43475bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ret |= tmp; 43575bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter } 436a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter if (ts78xx_fpga.supports.ts_rng.present == 1) { 437a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter tmp = ts78xx_ts_rng_load(); 4384d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter if (tmp) 439a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ts78xx_fpga.supports.ts_rng.present = 0; 440a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ret |= tmp; 441a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter } 44239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 44339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return ret; 44439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 44539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 44639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic int ts78xx_fpga_unload_devices(void) 44739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 44839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter int ret = 0; 44939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 45039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.supports.ts_rtc.present == 1) 45139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_ts_rtc_unload(); 45275bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter if (ts78xx_fpga.supports.ts_nand.present == 1) 45375bb6b9aab3255f440ef4e72a31978d1681105d6Alexander Clouter ts78xx_ts_nand_unload(); 454a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter if (ts78xx_fpga.supports.ts_rng.present == 1) 455a914d4309c4cf6e7c4d0dbce4822dcad38a7cf27Alexander Clouter ts78xx_ts_rng_unload(); 45639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 45739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return ret; 45839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 45939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 46039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic int ts78xx_fpga_load(void) 46139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 46239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 46339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 4644d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_info("FPGA magic=0x%.6x, rev=0x%.2x\n", 46539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter (ts78xx_fpga.id >> 8) & 0xffffff, 46639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.id & 0xff); 46739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 46839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga_supports(); 46939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 47039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga_load_devices()) { 47139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.state = -1; 47239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -EBUSY; 47339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 47439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 47539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return 0; 4767171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 4777171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 47839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic int ts78xx_fpga_unload(void) 47939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 48039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter unsigned int fpga_id; 48139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 48239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 48339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 48439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter /* 48539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * There does not seem to be a feasible way to block access to the GPIO 48639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * pins from userspace (/dev/mem). This if clause should hopefully warn 48739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * those foolish enough not to follow 'policy' :) 48839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * 48939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter * UrJTAG SVN since r1381 can be used to reprogram the FPGA 49039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter */ 49139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.id != fpga_id) { 4924d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_err("FPGA magic/rev mismatch\n" 49339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", 49439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, 49539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); 49639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.state = -1; 49739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -EBUSY; 49839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 49939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 50039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga_unload_devices()) { 50139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.state = -1; 50239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -EBUSY; 50339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 50439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 50539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return 0; 5067171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 5077171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 50839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic ssize_t ts78xx_fpga_show(struct kobject *kobj, 50939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter struct kobj_attribute *attr, char *buf) 51039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 51139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.state < 0) 51239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return sprintf(buf, "borked\n"); 51339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 51439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); 51539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 51639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 51739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic ssize_t ts78xx_fpga_store(struct kobject *kobj, 51839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter struct kobj_attribute *attr, const char *buf, size_t n) 51939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter{ 52039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter int value, ret; 52139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 52239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.state < 0) { 5234d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter pr_err("FPGA borked, you must powercycle ASAP\n"); 52439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -EBUSY; 52539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter } 52639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 52739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (strncmp(buf, "online", sizeof("online") - 1) == 0) 52839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter value = 1; 52939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) 53039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter value = 0; 5314d72cef17bb71a63526b6219bc06b7f31d86dde1Alexander Clouter else 53239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return -EINVAL; 53339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 53439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ts78xx_fpga.state == value) 53539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return n; 53639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 53739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ret = (ts78xx_fpga.state == 0) 53839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ? ts78xx_fpga_load() 53939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter : ts78xx_fpga_unload(); 54039008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 54139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (!(ret < 0)) 54239008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga.state = value; 54339008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 54439008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter return n; 54539008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter} 54639008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 54739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouterstatic struct kobj_attribute ts78xx_fpga_attr = 54839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); 54939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 5507171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter/***************************************************************************** 5517171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * General Setup 5527171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter ****************************************************************************/ 553554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunnstatic unsigned int ts78xx_mpp_modes[] __initdata = { 554554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP0_UNUSED, 555554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP1_GPIO, /* JTAG Clock */ 556554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP2_GPIO, /* JTAG Data In */ 557554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP3_GPIO, /* Lat ECP2 256 FPGA - PB2B */ 558554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP4_GPIO, /* JTAG Data Out */ 559554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP5_GPIO, /* JTAG TMS */ 560554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP6_GPIO, /* Lat ECP2 256 FPGA - PB31A_CLK4+ */ 561554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP7_GPIO, /* Lat ECP2 256 FPGA - PB22B */ 562554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP8_UNUSED, 563554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP9_UNUSED, 564554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP10_UNUSED, 565554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP11_UNUSED, 566554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP12_UNUSED, 567554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP13_UNUSED, 568554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP14_UNUSED, 569554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP15_UNUSED, 570554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP16_UART, 571554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP17_UART, 572554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP18_UART, 573554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn MPP19_UART, 574f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter /* 575f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[20] PCI Clock Out 1 576f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[21] PCI Clock Out 0 577f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[22] Unused 578f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[23] Unused 579f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[24] Unused 580f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter * MPP[25] Unused 581f54128609c4e7792fb52b03c3db0da78627ce607Alexander Clouter */ 582554cdaefd1cf7bb54b209c4e68c7cec87ce442a9Andrew Lunn 0, 5837171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter}; 5847171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 5857171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouterstatic void __init ts78xx_init(void) 5867171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter{ 58739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter int ret; 58839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter 5897171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter /* 5907171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * Setup basic Orion functions. Need to be called early. 5917171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter */ 5927171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_init(); 5937171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 5947171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_mpp_conf(ts78xx_mpp_modes); 5957171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 5967171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter /* 5977171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter * Configure peripherals. 5987171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter */ 5997171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_ehci0_init(); 6007171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_ehci1_init(); 6017171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_eth_init(&ts78xx_eth_data); 6027171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_sata_init(&ts78xx_sata_data); 6037171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_uart0_init(); 6047171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter orion5x_uart1_init(); 6051d5a1a6e92abb1ecb011a673e637146c4e232f1eSaeed Bishara orion5x_xor_init(); 6067171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 60739008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter /* FPGA init */ 60839008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ts78xx_fpga_devices_zero_init(); 60939008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter ret = ts78xx_fpga_load(); 6104f8cf6106dcf77b9b60af23cbb35fd537b1c9c1dAlexander Clouter ret = sysfs_create_file(firmware_kobj, &ts78xx_fpga_attr.attr); 61139008f959f4f3b60eecc5cec0ca077146c1f366bAlexander Clouter if (ret) 6127bcdca95c039d1cd1cfddd6aa012026b409ddb14Alexander Clouter pr_err("sysfs_create_file failed: %d\n", ret); 6137171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter} 6147171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter 6157171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander ClouterMACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") 6167171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */ 61765aa1b1ea499a75c9920c1ebadacec0a0b8a79a6Nicolas Pitre .atag_offset = 0x100, 6187171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .init_machine = ts78xx_init, 6197171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .map_io = ts78xx_map_io, 6204ee1f6b574765a6c97f945e6b0277e5ccac38cb5Lennert Buytenhek .init_early = orion5x_init_early, 6217171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander Clouter .init_irq = orion5x_init_irq, 6226bb27d7349db51b50c40534710fe164ca0d58902Stephen Warren .init_time = orion5x_timer_init, 623764cbcc2e3fa444c205b20b3d7908b06b60716abRussell King .restart = orion5x_restart, 6247171d8672bb0bcb744935bd2c6108378b5c6c6adAlexander ClouterMACHINE_END 625