11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ###################################################################### 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 369f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner Octagon 5066 MTD Driver. 469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds is replacable by flash. Both units are mapped through a multiplexer 869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner into a 32k memory window at 0xe8000. The control register for the 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds multiplexing unit is located at IO 0x208 with a bit map of 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0-5 Page Selection in 32k increments 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6-7 Device selection: 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 00 SSD off 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 01 SSD 0 (Socket) 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10 SSD 1 (Flash chip) 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11 undefined 1669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds On each SSD, the first 128k is reserved for use by the bios 1869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner (actually it IS the bios..) This only matters if you are booting off the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flash, you must not put a file system starting there. 2069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The driver tries to do a detection algorithm to guess what sort of devices 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds are plugged into the sockets. 2369f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ##################################################################### */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINDOW_START 0xe8000 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINDOW_LENGTH 0x8000 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINDOW_SHIFT 27 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINDOW_MASK 0x7FFF 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PAGE_IO 0x208 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic volatile char page_n_dev = 0; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long iomapadr; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(oct5066_spin); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We use map_priv_1 to identify which device we are. 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __oct5066_page(struct map_info *map, __u8 byte) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(byte,PAGE_IO); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds page_n_dev = byte; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void oct5066_page(struct map_info *map, unsigned long ofs) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); 5769f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (page_n_dev != byte) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __oct5066_page(map, byte); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word oct5066_read8(struct map_info *map, unsigned long ofs) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word ret; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&oct5066_spin); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_page(map, ofs); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK)); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&oct5066_spin); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long thislen = len; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds thislen = WINDOW_LENGTH-(from & WINDOW_MASK); 7969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&oct5066_spin); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_page(map, from); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(to, iomapadr + from, thislen); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&oct5066_spin); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += thislen; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += thislen; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= thislen; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void oct5066_write8(struct map_info *map, map_word d, unsigned long adr) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&oct5066_spin); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_page(map, adr); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(d.x[0], iomapadr + (adr & WINDOW_MASK)); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&oct5066_spin); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long thislen = len; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds thislen = WINDOW_LENGTH-(to & WINDOW_MASK); 10469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&oct5066_spin); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_page(map, to); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(iomapadr + to, from, thislen); 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&oct5066_spin); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += thislen; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += thislen; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= thislen; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct map_info oct5066_map[2] = { 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Octagon 5066 Socket", 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .phys = NO_XIP, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .size = 512 * 1024, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bankwidth = 1, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = oct5066_read8, 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .copy_from = oct5066_copy_from, 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = oct5066_write8, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .copy_to = oct5066_copy_to, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .map_priv_1 = 1<<6 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "Octagon 5066 Internal Flash", 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .phys = NO_XIP, 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .size = 2 * 1024 * 1024, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bankwidth = 1, 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = oct5066_read8, 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .copy_from = oct5066_copy_from, 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = oct5066_write8, 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .copy_to = oct5066_copy_to, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .map_priv_1 = 2<<6 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// OctProbe - Sense if this is an octagon card 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// --------------------------------------------------------------------- 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Perform a simple validity test, we map the window select SSD0 and 14569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner change pages while monitoring the window. A change in the window, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controlled by the PAGE_IO port is a functioning 5066 board. This will 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fail if the thing in the socket is set to a uniform value. */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init OctProbe(void) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int Base = (1 << 6); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long I; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long Values[10]; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (I = 0; I != 20; I++) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(Base + (I%10),PAGE_IO); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (I < 10) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Record the value and check for uniqueness 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Values[I%10] = readl(iomapadr); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (I > 0 && Values[I%10] == Values[0]) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 16269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Make sure we get the same values on the second pass 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (Values[I%10] != readl(iomapadr)) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 16869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cleanup_oct5066(void) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<2; i++) { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (oct5066_mtd[i]) { 178ee0e87b174bb41f0310cf089262bf5dd8f95a212Jamie Iles mtd_device_unregister(oct5066_mtd[i]); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_destroy(oct5066_mtd[i]); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap((void *)iomapadr); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(PAGE_IO, 1); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 186d849257c428bf9f06f25fa3dea14cd1e7650948dDmitri Vorobievstatic int __init init_oct5066(void) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Do an autoprobe sequence 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!request_region(PAGE_IO,1,"Octagon SSD")) { 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "5066: Page Register in Use\n"); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!iomapadr) { 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "Failed to ioremap memory region\n"); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_rel; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (OctProbe() != 0) { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap((void *)iomapadr); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EAGAIN; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_unmap; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Print out our little header.. 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WINDOW_START+WINDOW_LENGTH); 21269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<2; i++) { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!oct5066_mtd[i]) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!oct5066_mtd[i]) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!oct5066_mtd[i]) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (oct5066_mtd[i]) { 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds oct5066_mtd[i]->owner = THIS_MODULE; 223ee0e87b174bb41f0310cf089262bf5dd8f95a212Jamie Iles mtd_device_register(oct5066_mtd[i], NULL, 0); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!oct5066_mtd[0] && !oct5066_mtd[1]) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup_oct5066(); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 23069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_unmap: 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap((void *)iomapadr); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_rel: 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(PAGE_IO, 1); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_oct5066); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cleanup_oct5066); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>"); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer"); 247