From 88800b2f2ffd3e436266e4dff9586d48b5b54500 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:56:04 +0000 Subject: [ARM] orion5x: add rtc-m48t86 to orion5x_defconfig The TS-7800 can have a M48T86 RTC onboard Signed-off-by: Alexander Clouter --- arch/arm/configs/orion5x_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig index b2456ca544c..45dcd086fee 100644 --- a/arch/arm/configs/orion5x_defconfig +++ b/arch/arm/configs/orion5x_defconfig @@ -1177,7 +1177,7 @@ CONFIG_RTC_DRV_S35390A=y # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_M48T86=y # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_V3020 is not set -- cgit v1.2.3-70-g09d2 From c3dfdb0823213c81f60987c8a3770b89ea95cad6 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:57:13 +0000 Subject: [ARM] orion5x: remove TS-78xx NOR support as it does not exist The TS-7800's M25P40 is not available to the kernel, it's used to load the initial bitstream onto the FPGA and so these hooks point to nothing and need to be removed. Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/ts78xx-setup.c | 46 ------------------------------------ 1 file changed, 46 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 1368e9fd1a0..0cb34b9a6d8 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -40,12 +39,6 @@ #define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) #define TS78XX_FPGA_REGS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) -/* - * 512kB NOR flash Device - */ -#define TS78XX_NOR_BOOT_BASE 0xff800000 -#define TS78XX_NOR_BOOT_SIZE SZ_512K - /***************************************************************************** * I/O Address Mapping ****************************************************************************/ @@ -64,41 +57,6 @@ void __init ts78xx_map_io(void) iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc)); } -/***************************************************************************** - * 512kB NOR Boot Flash - the chip is a M25P40 - ****************************************************************************/ -static struct mtd_partition ts78xx_nor_boot_flash_resources[] = { - { - .name = "ts-bootrom", - .offset = 0, - /* only the first 256kB is used */ - .size = SZ_256K, - .mask_flags = MTD_WRITEABLE, - }, -}; - -static struct physmap_flash_data ts78xx_nor_boot_flash_data = { - .width = 1, - .parts = ts78xx_nor_boot_flash_resources, - .nr_parts = ARRAY_SIZE(ts78xx_nor_boot_flash_resources), -}; - -static struct resource ts78xx_nor_boot_flash_resource = { - .flags = IORESOURCE_MEM, - .start = TS78XX_NOR_BOOT_BASE, - .end = TS78XX_NOR_BOOT_BASE + TS78XX_NOR_BOOT_SIZE - 1, -}; - -static struct platform_device ts78xx_nor_boot_flash = { - .name = "physmap-flash", - .id = -1, - .dev = { - .platform_data = &ts78xx_nor_boot_flash_data, - }, - .num_resources = 1, - .resource = &ts78xx_nor_boot_flash_resource, -}; - /***************************************************************************** * Ethernet ****************************************************************************/ @@ -257,10 +215,6 @@ static void __init ts78xx_init(void) orion5x_uart1_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE, - TS78XX_NOR_BOOT_SIZE); - platform_device_register(&ts78xx_nor_boot_flash); - if (!ts78xx_rtc_init()) printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); } -- cgit v1.2.3-70-g09d2 From f54128609c4e7792fb52b03c3db0da78627ce607 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 21:59:15 +0000 Subject: [ARM] orion5x: TS-78xx comment shifting moved the MPP comments to the mpp area of the platform code Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/ts78xx-setup.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 0cb34b9a6d8..b194956518a 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -181,6 +181,14 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { { 17, MPP_UART }, { 18, MPP_UART }, { 19, MPP_UART }, + /* + * MPP[20] PCI Clock Out 1 + * MPP[21] PCI Clock Out 0 + * MPP[22] Unused + * MPP[23] Unused + * MPP[24] Unused + * MPP[25] Unused + */ { -1 }, }; @@ -195,15 +203,6 @@ static void __init ts78xx_init(void) orion5x_mpp_conf(ts78xx_mpp_modes); - /* - * MPP[20] PCI Clock Out 1 - * MPP[21] PCI Clock Out 0 - * MPP[22] Unused - * MPP[23] Unused - * MPP[24] Unused - * MPP[25] Unused - */ - /* * Configure peripherals. */ -- cgit v1.2.3-70-g09d2 From 39008f959f4f3b60eecc5cec0ca077146c1f366b Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 6 Feb 2009 22:16:55 +0000 Subject: [ARM] orion5x: TS-78xx support for 'hotplug' of FPGA devices the FPGA on the TS-7800 provides access to a number of devices and so we have to be careful when reprogramming it. As we are effectively turning a bus off/on we have to inform the kernel that it should stop using anything provided by the FPGA (currently only the RTC however the NAND, LCD, etc is to come) before it's reprogrammed. Once reprogramed, we can tell the kernel to (re)enable things by checking the FPGA ID against a lookup table for what a particular FPGA bitstream can provide. Signed-off-by: Alexander Clouter --- arch/arm/mach-orion5x/Kconfig | 1 + arch/arm/mach-orion5x/ts78xx-fpga.h | 27 ++++ arch/arm/mach-orion5x/ts78xx-setup.c | 251 +++++++++++++++++++++++++++-------- 3 files changed, 224 insertions(+), 55 deletions(-) create mode 100644 arch/arm/mach-orion5x/ts78xx-fpga.h (limited to 'arch/arm') diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index f59a8d0e082..2c7035d8dcb 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -71,6 +71,7 @@ config MACH_WRT350N_V2 config MACH_TS78XX bool "Technologic Systems TS-78xx" + select PM help Say 'Y' here if you want your kernel to support the Technologic Systems TS-78xx platform. diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h new file mode 100644 index 00000000000..0b8e30faff1 --- /dev/null +++ b/arch/arm/mach-orion5x/ts78xx-fpga.h @@ -0,0 +1,27 @@ +#define FPGAID(_magic, _rev) ((_magic << 8) + _rev) + +/* + * get yer id's from http://ts78xx.digriz.org.uk/ + * do *not* make up your own or 'borrow' any! + */ +enum fpga_ids { + /* Technologic Systems */ + TS7800_REV_B = FPGAID(0x00b480, 0x03), +}; + +struct fpga_device { + unsigned present:1; + unsigned init:1; +}; + +struct fpga_devices { + /* Technologic Systems */ + struct fpga_device ts_rtc; +}; + +struct ts78xx_fpga_data { + unsigned int id; + int state; + + struct fpga_devices supports; +}; diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index b194956518a..baa25d0fd5c 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include "common.h" #include "mpp.h" +#include "ts78xx-fpga.h" /***************************************************************************** * TS-78xx Info @@ -32,12 +34,11 @@ #define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 #define TS78XX_FPGA_REGS_SIZE SZ_1M -#define TS78XX_FPGA_REGS_SYSCON_ID (TS78XX_FPGA_REGS_VIRT_BASE | 0x000) -#define TS78XX_FPGA_REGS_SYSCON_LCDI (TS78XX_FPGA_REGS_VIRT_BASE | 0x004) -#define TS78XX_FPGA_REGS_SYSCON_LCDO (TS78XX_FPGA_REGS_VIRT_BASE | 0x008) - -#define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) -#define TS78XX_FPGA_REGS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) +static struct ts78xx_fpga_data ts78xx_fpga = { + .id = 0, + .state = 1, +/* .supports = ... - populated by ts78xx_fpga_supports() */ +}; /***************************************************************************** * I/O Address Mapping @@ -64,32 +65,42 @@ static struct mv643xx_eth_platform_data ts78xx_eth_data = { .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data ts78xx_sata_data = { + .n_ports = 2, +}; + /***************************************************************************** * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c ****************************************************************************/ #ifdef CONFIG_RTC_DRV_M48T86 -static unsigned char ts78xx_rtc_readbyte(unsigned long addr) +#define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) +#define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) + +static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) { - writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); - return readb(TS78XX_FPGA_REGS_RTC_DATA); + writeb(addr, TS_RTC_CTRL); + return readb(TS_RTC_DATA); } -static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr) +static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) { - writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); - writeb(value, TS78XX_FPGA_REGS_RTC_DATA); + writeb(addr, TS_RTC_CTRL); + writeb(value, TS_RTC_DATA); } -static struct m48t86_ops ts78xx_rtc_ops = { - .readbyte = ts78xx_rtc_readbyte, - .writebyte = ts78xx_rtc_writebyte, +static struct m48t86_ops ts78xx_ts_rtc_ops = { + .readbyte = ts78xx_ts_rtc_readbyte, + .writebyte = ts78xx_ts_rtc_writebyte, }; -static struct platform_device ts78xx_rtc_device = { +static struct platform_device ts78xx_ts_rtc_device = { .name = "rtc-m48t86", .id = -1, .dev = { - .platform_data = &ts78xx_rtc_ops, + .platform_data = &ts78xx_ts_rtc_ops, }, .num_resources = 0, }; @@ -104,59 +115,185 @@ static struct platform_device ts78xx_rtc_device = { * TODO: track down a guinea pig without an RTC to see if we can work out a * better RTC detection routine */ -static int __init ts78xx_rtc_init(void) +static int ts78xx_ts_rtc_load(void) { unsigned char tmp_rtc0, tmp_rtc1; - tmp_rtc0 = ts78xx_rtc_readbyte(126); - tmp_rtc1 = ts78xx_rtc_readbyte(127); - - ts78xx_rtc_writebyte(0x00, 126); - ts78xx_rtc_writebyte(0x55, 127); - if (ts78xx_rtc_readbyte(127) == 0x55) { - ts78xx_rtc_writebyte(0xaa, 127); - if (ts78xx_rtc_readbyte(127) == 0xaa - && ts78xx_rtc_readbyte(126) == 0x00) { - ts78xx_rtc_writebyte(tmp_rtc0, 126); - ts78xx_rtc_writebyte(tmp_rtc1, 127); - platform_device_register(&ts78xx_rtc_device); - return 1; + tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); + tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); + + ts78xx_ts_rtc_writebyte(0x00, 126); + ts78xx_ts_rtc_writebyte(0x55, 127); + if (ts78xx_ts_rtc_readbyte(127) == 0x55) { + ts78xx_ts_rtc_writebyte(0xaa, 127); + if (ts78xx_ts_rtc_readbyte(127) == 0xaa + && ts78xx_ts_rtc_readbyte(126) == 0x00) { + ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); + ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); + if (ts78xx_fpga.supports.ts_rtc.init == 0) { + ts78xx_fpga.supports.ts_rtc.init = 1; + platform_device_register(&ts78xx_ts_rtc_device); + } else + platform_device_add(&ts78xx_ts_rtc_device); + return 0; } } - return 0; + ts78xx_fpga.supports.ts_rtc.present = 0; + return -ENODEV; }; + +static void ts78xx_ts_rtc_unload(void) +{ + platform_device_del(&ts78xx_ts_rtc_device); +} #else -static int __init ts78xx_rtc_init(void) +static int ts78xx_ts_rtc_load(void) { return 0; } + +static void ts78xx_ts_rtc_unload(void) +{ +} #endif /***************************************************************************** - * SATA + * FPGA 'hotplug' support code ****************************************************************************/ -static struct mv_sata_platform_data ts78xx_sata_data = { - .n_ports = 2, +static void ts78xx_fpga_devices_zero_init(void) +{ + ts78xx_fpga.supports.ts_rtc.init = 0; +} + +static void ts78xx_fpga_supports(void) +{ + /* TODO: put this 'table' into ts78xx-fpga.h */ + switch (ts78xx_fpga.id) { + case TS7800_REV_B: + ts78xx_fpga.supports.ts_rtc.present = 1; + break; + default: + ts78xx_fpga.supports.ts_rtc.present = 0; + } +} + +static int ts78xx_fpga_load_devices(void) +{ + int tmp, ret = 0; + + if (ts78xx_fpga.supports.ts_rtc.present == 1) { + tmp = ts78xx_ts_rtc_load(); + if (tmp) + printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); + ret |= tmp; + } + + return ret; +} + +static int ts78xx_fpga_unload_devices(void) +{ + int ret = 0; + + if (ts78xx_fpga.supports.ts_rtc.present == 1) + ts78xx_ts_rtc_unload(); + + return ret; +} + +static int ts78xx_fpga_load(void) +{ + ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); + + printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n", + (ts78xx_fpga.id >> 8) & 0xffffff, + ts78xx_fpga.id & 0xff); + + ts78xx_fpga_supports(); + + if (ts78xx_fpga_load_devices()) { + ts78xx_fpga.state = -1; + return -EBUSY; + } + + return 0; }; -/***************************************************************************** - * print some information regarding the board - ****************************************************************************/ -static void __init ts78xx_print_board_id(void) -{ - unsigned int board_info; - - board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID); - printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ", - board_info & 0xff, - (board_info >> 8) & 0xffffff); - board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI); - printk("JP1=%d, JP2=%d\n", - (board_info >> 30) & 0x1, - (board_info >> 31) & 0x1); +static int ts78xx_fpga_unload(void) +{ + unsigned int fpga_id; + + fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); + + /* + * There does not seem to be a feasible way to block access to the GPIO + * pins from userspace (/dev/mem). This if clause should hopefully warn + * those foolish enough not to follow 'policy' :) + * + * UrJTAG SVN since r1381 can be used to reprogram the FPGA + */ + if (ts78xx_fpga.id != fpga_id) { + printk(KERN_ERR "TS-78xx FPGA: magic/rev mismatch\n" + "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", + (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, + (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); + ts78xx_fpga.state = -1; + return -EBUSY; + } + + if (ts78xx_fpga_unload_devices()) { + ts78xx_fpga.state = -1; + return -EBUSY; + } + + return 0; }; +static ssize_t ts78xx_fpga_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + if (ts78xx_fpga.state < 0) + return sprintf(buf, "borked\n"); + + return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); +} + +static ssize_t ts78xx_fpga_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + int value, ret; + + if (ts78xx_fpga.state < 0) { + printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n"); + return -EBUSY; + } + + if (strncmp(buf, "online", sizeof("online") - 1) == 0) + value = 1; + else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) + value = 0; + else { + printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n"); + return -EINVAL; + } + + if (ts78xx_fpga.state == value) + return n; + + ret = (ts78xx_fpga.state == 0) + ? ts78xx_fpga_load() + : ts78xx_fpga_unload(); + + if (!(ret < 0)) + ts78xx_fpga.state = value; + + return n; +} + +static struct kobj_attribute ts78xx_fpga_attr = + __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); + /***************************************************************************** * General Setup ****************************************************************************/ @@ -194,13 +331,13 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { static void __init ts78xx_init(void) { + int ret; + /* * Setup basic Orion functions. Need to be called early. */ orion5x_init(); - ts78xx_print_board_id(); - orion5x_mpp_conf(ts78xx_mpp_modes); /* @@ -214,8 +351,12 @@ static void __init ts78xx_init(void) orion5x_uart1_init(); orion5x_xor_init(); - if (!ts78xx_rtc_init()) - printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); + /* FPGA init */ + ts78xx_fpga_devices_zero_init(); + ret = ts78xx_fpga_load(); + ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr); + if (ret) + printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); } MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") -- cgit v1.2.3-70-g09d2