1 /* 2 * arch/arm/mach-ep93xx/ts72xx.c 3 * Technologic Systems TS72xx SBC support. 4 * 5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or (at 10 * your option) any later version. 11 */ 12 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 15 #include <linux/kernel.h> 16 #include <linux/init.h> 17 #include <linux/platform_device.h> 18 #include <linux/io.h> 19 #include <linux/mtd/nand.h> 20 #include <linux/mtd/partitions.h> 21 22 #include <mach/hardware.h> 23 24 #include <asm/mach-types.h> 25 #include <asm/mach/map.h> 26 #include <asm/mach/arch.h> 27 28 #include "soc.h" 29 #include "ts72xx.h" 30 31 static struct map_desc ts72xx_io_desc[] __initdata = { 32 { 33 .virtual = (unsigned long)TS72XX_MODEL_VIRT_BASE, 34 .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE), 35 .length = TS72XX_MODEL_SIZE, 36 .type = MT_DEVICE, 37 }, { 38 .virtual = (unsigned long)TS72XX_OPTIONS_VIRT_BASE, 39 .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE), 40 .length = TS72XX_OPTIONS_SIZE, 41 .type = MT_DEVICE, 42 }, { 43 .virtual = (unsigned long)TS72XX_OPTIONS2_VIRT_BASE, 44 .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), 45 .length = TS72XX_OPTIONS2_SIZE, 46 .type = MT_DEVICE, 47 } 48 }; 49 50 static void __init ts72xx_map_io(void) 51 { 52 ep93xx_map_io(); 53 iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); 54 } 55 56 57 /************************************************************************* 58 * NAND flash 59 *************************************************************************/ 60 #define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */ 61 #define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */ 62 63 static void ts72xx_nand_hwcontrol(struct mtd_info *mtd, 64 int cmd, unsigned int ctrl) 65 { 66 struct nand_chip *chip = mtd_to_nand(mtd); 67 68 if (ctrl & NAND_CTRL_CHANGE) { 69 void __iomem *addr = chip->IO_ADDR_R; 70 unsigned char bits; 71 72 addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE); 73 74 bits = __raw_readb(addr) & ~0x07; 75 bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */ 76 bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */ 77 bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */ 78 79 __raw_writeb(bits, addr); 80 } 81 82 if (cmd != NAND_CMD_NONE) 83 __raw_writeb(cmd, chip->IO_ADDR_W); 84 } 85 86 static int ts72xx_nand_device_ready(struct mtd_info *mtd) 87 { 88 struct nand_chip *chip = mtd_to_nand(mtd); 89 void __iomem *addr = chip->IO_ADDR_R; 90 91 addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); 92 93 return !!(__raw_readb(addr) & 0x20); 94 } 95 96 #define TS72XX_BOOTROM_PART_SIZE (SZ_16K) 97 #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) 98 99 static struct mtd_partition ts72xx_nand_parts[] = { 100 { 101 .name = "TS-BOOTROM", 102 .offset = 0, 103 .size = TS72XX_BOOTROM_PART_SIZE, 104 .mask_flags = MTD_WRITEABLE, /* force read-only */ 105 }, { 106 .name = "Linux", 107 .offset = MTDPART_OFS_RETAIN, 108 .size = TS72XX_REDBOOT_PART_SIZE, 109 /* leave so much for last partition */ 110 }, { 111 .name = "RedBoot", 112 .offset = MTDPART_OFS_APPEND, 113 .size = MTDPART_SIZ_FULL, 114 .mask_flags = MTD_WRITEABLE, /* force read-only */ 115 }, 116 }; 117 118 static struct platform_nand_data ts72xx_nand_data = { 119 .chip = { 120 .nr_chips = 1, 121 .chip_offset = 0, 122 .chip_delay = 15, 123 .partitions = ts72xx_nand_parts, 124 .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts), 125 }, 126 .ctrl = { 127 .cmd_ctrl = ts72xx_nand_hwcontrol, 128 .dev_ready = ts72xx_nand_device_ready, 129 }, 130 }; 131 132 static struct resource ts72xx_nand_resource[] = { 133 { 134 .start = 0, /* filled in later */ 135 .end = 0, /* filled in later */ 136 .flags = IORESOURCE_MEM, 137 }, 138 }; 139 140 static struct platform_device ts72xx_nand_flash = { 141 .name = "gen_nand", 142 .id = -1, 143 .dev.platform_data = &ts72xx_nand_data, 144 .resource = ts72xx_nand_resource, 145 .num_resources = ARRAY_SIZE(ts72xx_nand_resource), 146 }; 147 148 149 static void __init ts72xx_register_flash(void) 150 { 151 /* 152 * TS7200 has NOR flash all other TS72xx board have NAND flash. 153 */ 154 if (board_is_ts7200()) { 155 ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M); 156 } else { 157 resource_size_t start; 158 159 if (is_ts9420_installed()) 160 start = EP93XX_CS7_PHYS_BASE; 161 else 162 start = EP93XX_CS6_PHYS_BASE; 163 164 ts72xx_nand_resource[0].start = start; 165 ts72xx_nand_resource[0].end = start + SZ_16M - 1; 166 167 platform_device_register(&ts72xx_nand_flash); 168 } 169 } 170 171 /************************************************************************* 172 * RTC M48T86 173 *************************************************************************/ 174 #define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000) 175 #define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000) 176 177 static struct resource ts72xx_rtc_resources[] = { 178 DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01), 179 DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01), 180 }; 181 182 static struct platform_device ts72xx_rtc_device = { 183 .name = "rtc-m48t86", 184 .id = -1, 185 .resource = ts72xx_rtc_resources, 186 .num_resources = ARRAY_SIZE(ts72xx_rtc_resources), 187 }; 188 189 static struct resource ts72xx_wdt_resources[] = { 190 { 191 .start = TS72XX_WDT_CONTROL_PHYS_BASE, 192 .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1, 193 .flags = IORESOURCE_MEM, 194 }, 195 { 196 .start = TS72XX_WDT_FEED_PHYS_BASE, 197 .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1, 198 .flags = IORESOURCE_MEM, 199 }, 200 }; 201 202 static struct platform_device ts72xx_wdt_device = { 203 .name = "ts72xx-wdt", 204 .id = -1, 205 .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), 206 .resource = ts72xx_wdt_resources, 207 }; 208 209 static struct ep93xx_eth_data __initdata ts72xx_eth_data = { 210 .phy_id = 1, 211 }; 212 213 static void __init ts72xx_init_machine(void) 214 { 215 ep93xx_init_devices(); 216 ts72xx_register_flash(); 217 platform_device_register(&ts72xx_rtc_device); 218 platform_device_register(&ts72xx_wdt_device); 219 220 ep93xx_register_eth(&ts72xx_eth_data, 1); 221 } 222 223 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") 224 /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ 225 .atag_offset = 0x100, 226 .map_io = ts72xx_map_io, 227 .init_irq = ep93xx_init_irq, 228 .init_time = ep93xx_timer_init, 229 .init_machine = ts72xx_init_machine, 230 .init_late = ep93xx_init_late, 231 .restart = ep93xx_restart, 232 MACHINE_END 233