diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h --- a/arch/ppc/platforms/4xx/yucca.h +++ b/arch/ppc/platforms/4xx/yucca.h @@ -32,12 +32,88 @@ /* External timer clock frequency */ #define YUCCA_TMR_CLK 25000000 +/* System Memory map (physical address, not effective address) + * Flash and other devices via EBC. + * + * This should be the same mapping as done by PIBS in the + * (not mandatory but ease code reading between two codes) + * xxx/boardlib/ebc.c + * + * depending of the switch setting off the board, the location of devices + * in the address map are not the same: + */ +/* Common definitions */ + +#define BOARD_SMALL_FLASH_SIZE 0x100000 /* 1M */ +#define BOARD_FRAM_SIZE 0x8000 +#define BOARD_SRAM_SIZE 0x100000 +#define BOARD_OPER_FLASH_SIZE 0x400000 /* 4M */ + + +/* Configuration 1: + * the small flash and sram are placed on top (CS0) + * the Large flash is placed below (CS2) + * The FPGA and FRAM at the end (CS1) + * xxxx----xxxx---- + */ +#define BOARD_CONF1_SMALL_FLASH 0x00000004FFF00000ull +#define BOARD_CONF1_FRAM 0x00000004FF000000ull +#define BOARD_CONF1_OPER_FLASH 0x00000004E7C00000ull +#define BOARD_CONF1_SRAM 0x00000004E7000000ull + +/* Configuration 2: + * the small flash and sram are placed on top (CS0) + * but now sram before smal flash + * the Large flash is placed below (no change) (CS2) + * The FPGA and FRAM stay in same place. (CS1) + * xxxx----xxxx---- + */ +#define BOARD_CONF2_OPER_FLASH 0x00000004FFC00000ull +#define BOARD_CONF2_SRAM 0x00000004FF000000ull +#define BOARD_CONF2_SMALL_FLASH 0x00000004E7F00000ull +#define BOARD_CONF2_FRAM 0x00000004E7000000ull + +/* Configuration 3: + * the Large flash is placed on top, (CS0) + * the small flash and sram are placed below. (CS2) + * The FPGA and FRAM stay in same place. (CS1) + * xxxx----xxxx---- + */ +#define BOARD_CONF3_SRAM 0x00000004FFF00000ull +#define BOARD_CONF3_OPER_FLASH 0x00000004FF000000ull +#define BOARD_CONF3_SMALL_FLASH 0x00000004E7F00000ull +#define BOARD_CONF3_FRAM 0x00000004E7000000ull + /* * FPGA registers */ #define YUCCA_FPGA_REG_BASE 0x00000004e2000000ULL #define YUCCA_FPGA_REG_SIZE 0x24 +#define FPGA_REG10 0x10 /* Ethernet/Reset/Boot + configs */ +#define FPGA_REG10_ETH_MODE10 0x8000 +#define FPGA_REG10_ETH_MODE100 0x4000 +#define FPGA_REG10_ETH_MODE1000 0x2000 +#define FPGA_REG10_ETH_FORCE_DUPLEX 0x1000 +#define FPGA_REG10_LOG_RESET_ETHERNET 0x0800 +#define FPGA_REG10_ETH_AUTO_NEGO 0x0400 +#define FPGA_REG10_LOG_INT_ETH 0x0200 +#define FPGA_REG10_LOG_RESET_HISR 0x0080 +#define FPGA_REG10_LOG_RESET_DISPLAY 0x0040 +#define FPGA_REG10_LOG_RESET_SDRAM 0x0020 +#define FPGA_REG10_LOG_OPBOOT 0x0010 +#define FPGA_REG10_LOG_SRAM_BOOT 0x0008 +#define FPGA_REG10_LOG_BTBOOT 0x0004 + +/*Boot configurations */ +#define BOARD_CONFIG_MASK (0x001C) +#define BOARD_CONFIG_1 (0x0018) +#define BOARD_CONFIG_2 (0x000C) +#define BOARD_CONFIG_3 (0x0014) +#define BOARD_BOOT_OPER_FLASH(x) (((x) & BOARD_CONFIG_MASK) == \ + BOARD_CONFIG_2) + #define FPGA_REG1A 0x1a #define FPGA_REG1A_PE0_GLED 0x8000 diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -339,6 +339,14 @@ config MTD_OCOTEA Ocotea board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. +config MTD_YUCCA + tristate "Flash devices mapped on IBM 440SPe Yucca" + depends on MTD_CFI && YUCCA + help + This enables access routines for the flash chips on the IBM 440SPe + Yucca board. If you have one of these boards and would like to + use the flash chips on it, say 'Y'. + config MTD_REDWOOD tristate "CFI Flash devices mapped on IBM Redwood" depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 ) diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o obj-$(CONFIG_MTD_EBONY) += ebony.o obj-$(CONFIG_MTD_OCOTEA) += ocotea.o +obj-$(CONFIG_MTD_YUCCA) += yucca_flash.o obj-$(CONFIG_MTD_BEECH) += beech-mtd.o obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o obj-$(CONFIG_MTD_WALNUT) += walnut.o diff --git a/drivers/mtd/maps/yucca_flash.c b/drivers/mtd/maps/yucca_flash.c new file mode 100644 --- /dev/null +++ b/drivers/mtd/maps/yucca_flash.c @@ -0,0 +1,297 @@ +/* + * Mapping for Yucca user flash + * + * This was derived from the luan.c + * + * Ruslan Sushko + * Matt Porter + * + * Copyright (C) 2002-2005 MontaVista Software Inc. + * (C) Copyright IBM Corp. 2004 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *oper_flash_mtd = NULL; +static struct mtd_info *small_flash_mtd = NULL; +static struct mtd_info *fram_mtd = NULL; +static struct mtd_info *sram_mtd = NULL; + +static struct map_info yucca_sram_map = { + .name = "Yucca SRAM", + .size = BOARD_SRAM_SIZE, + .bankwidth = 2, +}; + +static struct map_info yucca_fram_map = { + .name = "Yucca FRAM", + .size = BOARD_FRAM_SIZE, + .bankwidth = 1, +}; + +static struct map_info yucca_small_map = { + .name = "Yucca small flash", + .size = BOARD_SMALL_FLASH_SIZE, + .bankwidth = 1, +}; + +static struct map_info yucca_oper_map = { + .name = "Yucca Operational flash", + .size = BOARD_OPER_FLASH_SIZE, + .bankwidth = 2, +}; + +static struct mtd_partition yucca_sram_partitions[] = { + { + .name = "SRAM", + .offset = 0x0, + .size = 0x100000, + } +}; + +static struct mtd_partition yucca_fram_partitions[] = { + { + .name = "FRAM", + .offset = 0x0, + .size = 0x8000, + } +}; + +static struct mtd_partition yucca_small_partitions[] = { + { + .name = "U-boot", + .offset = 0x0, + .size = 0x100000, + } +}; + +static struct mtd_partition yucca_oper_partitions[] = { + { + .name = "Linux Kernel", + .offset = 0, + .size = 0x100000, + }, + { + .name = "Free Area", + .offset = 0x100000, + .size = 0x300000, + } +}; + +#define NB_OF(x) (sizeof(x)/sizeof(x[0])) +static void cleanup_yucca(void); + + +int __init init_yucca(void) +{ + u16 fpga10_reg; + volatile u16 *fpga_adr; + unsigned long long small_flash_base, oper_flash_base; + unsigned long long sram_base, fram_base; + int memconfig = 0; + int err = 0; + + fpga_adr = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE); + if (!fpga_adr) + return -ENOMEM; + + + fpga10_reg = *((u16*)((u32)fpga_adr + FPGA_REG10)); + iounmap(fpga_adr); + switch (fpga10_reg & BOARD_CONFIG_MASK) { + default: + printk("Memory config switches are invalid: " + "fpga10_reg= %x. Using default configuration\n", + fpga10_reg); + case BOARD_CONFIG_1: + memconfig = 1; + small_flash_base = BOARD_CONF1_SMALL_FLASH; + oper_flash_base = BOARD_CONF1_OPER_FLASH; + sram_base = BOARD_CONF1_SRAM; + fram_base = BOARD_CONF1_FRAM; + break; + case BOARD_CONFIG_2: + memconfig = 2; + small_flash_base = BOARD_CONF2_SMALL_FLASH; + oper_flash_base = BOARD_CONF2_OPER_FLASH; + sram_base = BOARD_CONF2_SRAM; + fram_base = BOARD_CONF3_FRAM; + break; + case BOARD_CONFIG_3: + memconfig = 3; + small_flash_base = BOARD_CONF3_SMALL_FLASH; + oper_flash_base = BOARD_CONF3_OPER_FLASH; + sram_base = BOARD_CONF3_SRAM; + fram_base = BOARD_CONF3_FRAM; + break; + } + + printk("Using EBC memory configuration #%d\n", memconfig); + + yucca_small_map.phys = small_flash_base; + yucca_small_map.virt = ioremap64(small_flash_base, + yucca_small_map.size); + + if (!yucca_small_map.virt) { + printk("Failed to ioremap small flash\n"); + err = -EIO; + goto ret_err; + } + + simple_map_init(&yucca_small_map); + + small_flash_mtd = do_map_probe("map_rom", &yucca_small_map); + if (small_flash_mtd) { + small_flash_mtd->owner = THIS_MODULE; + add_mtd_partitions(small_flash_mtd, yucca_small_partitions, + NB_OF(yucca_small_partitions)); + } else { + printk("map probe failed for small flash\n"); + err = -ENXIO; + goto ret_err; + } + + yucca_oper_map.phys = oper_flash_base; + yucca_oper_map.virt = ioremap64(oper_flash_base, + yucca_oper_map.size); + + if (!yucca_oper_map.virt) { + printk("Failed to ioremap oper flash\n"); + err = -EIO; + goto ret_err; + } + + simple_map_init(&yucca_oper_map); + + oper_flash_mtd = do_map_probe("cfi_probe", &yucca_oper_map); + if (oper_flash_mtd) { + oper_flash_mtd->owner = THIS_MODULE; + add_mtd_partitions(oper_flash_mtd, yucca_oper_partitions, + NB_OF(yucca_oper_partitions)); + } else { + printk("map probe failed for oper flash\n"); + err = -ENXIO; + goto ret_err; + } + + yucca_sram_map.phys = sram_base; + yucca_sram_map.virt = ioremap64(sram_base, + yucca_sram_map.size); + + if (!yucca_sram_map.virt) { + printk("Failed to ioremap SRAM\n"); + err = -EIO; + goto ret_err; + } + + simple_map_init(&yucca_sram_map); + + sram_mtd = do_map_probe("map_ram", &yucca_sram_map); + if (sram_mtd) { + sram_mtd->owner = THIS_MODULE; + add_mtd_partitions(sram_mtd, yucca_sram_partitions, + NB_OF(yucca_sram_partitions)); + } else { + printk("map probe failed for SRAM\n"); + err = -ENXIO; + goto ret_err; + } + + yucca_fram_map.phys = fram_base; + yucca_fram_map.virt = ioremap64(fram_base, + yucca_fram_map.size); + + if (!yucca_fram_map.virt) { + printk("Failed to ioremap FRAM\n"); + err = -EIO; + goto ret_err; + } + + simple_map_init(&yucca_fram_map); + + fram_mtd = do_map_probe("map_ram", &yucca_fram_map); + if (fram_mtd) { + fram_mtd->owner = THIS_MODULE; + add_mtd_partitions(fram_mtd, yucca_fram_partitions, + NB_OF(yucca_fram_partitions)); + } else { + printk("map probe failed for FRAM\n"); + err = -ENXIO; + goto ret_err; + } + return 0; +ret_err: + cleanup_yucca(); + return err; +} + +static void cleanup_yucca(void) +{ + if (yucca_small_map.virt) { + iounmap((void *)yucca_small_map.virt); + yucca_small_map.virt = 0; + } + + if (yucca_oper_map.virt) { + iounmap((void *)yucca_oper_map.virt); + yucca_oper_map.virt = 0; + } + + if (yucca_fram_map.virt) { + iounmap((void *)yucca_fram_map.virt); + yucca_fram_map.virt = 0; + } + + if (yucca_sram_map.virt) { + iounmap((void *)yucca_sram_map.virt); + yucca_sram_map.virt = 0; + } + + if (oper_flash_mtd) { + del_mtd_partitions(oper_flash_mtd); + map_destroy(oper_flash_mtd); + } + + if (small_flash_mtd) { + del_mtd_partitions(small_flash_mtd); + map_destroy(small_flash_mtd); + } + + if (fram_mtd) { + del_mtd_partitions(fram_mtd); + map_destroy(fram_mtd); + } + + if (sram_mtd) { + del_mtd_partitions(sram_mtd); + map_destroy(sram_mtd); + } + +} + +static void __exit rem_yucca(void) +{ + cleanup_yucca(); +} + +module_init(init_yucca); +module_exit(rem_yucca); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ruslan V. Sushko "); +MODULE_DESCRIPTION("MTD map and partitions for AMCC 440SPe Yucca board"); +