Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *   Octeon Bootbus flash setup
0003  *
0004  * This file is subject to the terms and conditions of the GNU General Public
0005  * License.  See the file "COPYING" in the main directory of this archive
0006  * for more details.
0007  *
0008  * Copyright (C) 2007, 2008 Cavium Networks
0009  */
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/semaphore.h>
0013 #include <linux/mtd/mtd.h>
0014 #include <linux/mtd/map.h>
0015 #include <linux/of_platform.h>
0016 #include <linux/mtd/partitions.h>
0017 
0018 #include <asm/octeon/octeon.h>
0019 
0020 static struct map_info flash_map;
0021 static struct mtd_info *mymtd;
0022 static const char *part_probe_types[] = {
0023     "cmdlinepart",
0024 #ifdef CONFIG_MTD_REDBOOT_PARTS
0025     "RedBoot",
0026 #endif
0027     NULL
0028 };
0029 
0030 static map_word octeon_flash_map_read(struct map_info *map, unsigned long ofs)
0031 {
0032     map_word r;
0033 
0034     down(&octeon_bootbus_sem);
0035     r = inline_map_read(map, ofs);
0036     up(&octeon_bootbus_sem);
0037 
0038     return r;
0039 }
0040 
0041 static void octeon_flash_map_write(struct map_info *map, const map_word datum,
0042                    unsigned long ofs)
0043 {
0044     down(&octeon_bootbus_sem);
0045     inline_map_write(map, datum, ofs);
0046     up(&octeon_bootbus_sem);
0047 }
0048 
0049 static void octeon_flash_map_copy_from(struct map_info *map, void *to,
0050                        unsigned long from, ssize_t len)
0051 {
0052     down(&octeon_bootbus_sem);
0053     inline_map_copy_from(map, to, from, len);
0054     up(&octeon_bootbus_sem);
0055 }
0056 
0057 static void octeon_flash_map_copy_to(struct map_info *map, unsigned long to,
0058                      const void *from, ssize_t len)
0059 {
0060     down(&octeon_bootbus_sem);
0061     inline_map_copy_to(map, to, from, len);
0062     up(&octeon_bootbus_sem);
0063 }
0064 
0065 /*
0066  * Module/ driver initialization.
0067  *
0068  * Returns Zero on success
0069  */
0070 static int octeon_flash_probe(struct platform_device *pdev)
0071 {
0072     union cvmx_mio_boot_reg_cfgx region_cfg;
0073     u32 cs;
0074     int r;
0075     struct device_node *np = pdev->dev.of_node;
0076 
0077     r = of_property_read_u32(np, "reg", &cs);
0078     if (r)
0079         return r;
0080 
0081     /*
0082      * Read the bootbus region 0 setup to determine the base
0083      * address of the flash.
0084      */
0085     region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
0086     if (region_cfg.s.en) {
0087         /*
0088          * The bootloader always takes the flash and sets its
0089          * address so the entire flash fits below
0090          * 0x1fc00000. This way the flash aliases to
0091          * 0x1fc00000 for booting. Software can access the
0092          * full flash at the true address, while core boot can
0093          * access 4MB.
0094          */
0095         /* Use this name so old part lines work */
0096         flash_map.name = "phys_mapped_flash";
0097         flash_map.phys = region_cfg.s.base << 16;
0098         flash_map.size = 0x1fc00000 - flash_map.phys;
0099         /* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
0100         flash_map.bankwidth = region_cfg.s.width + 1;
0101         flash_map.virt = ioremap(flash_map.phys, flash_map.size);
0102         pr_notice("Bootbus flash: Setting flash for %luMB flash at "
0103               "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
0104         WARN_ON(!map_bankwidth_supported(flash_map.bankwidth));
0105         flash_map.read = octeon_flash_map_read;
0106         flash_map.write = octeon_flash_map_write;
0107         flash_map.copy_from = octeon_flash_map_copy_from;
0108         flash_map.copy_to = octeon_flash_map_copy_to;
0109         mymtd = do_map_probe("cfi_probe", &flash_map);
0110         if (mymtd) {
0111             mymtd->owner = THIS_MODULE;
0112             mtd_device_parse_register(mymtd, part_probe_types,
0113                           NULL, NULL, 0);
0114         } else {
0115             pr_err("Failed to register MTD device for flash\n");
0116         }
0117     }
0118     return 0;
0119 }
0120 
0121 static const struct of_device_id of_flash_match[] = {
0122     {
0123         .compatible = "cfi-flash",
0124     },
0125     { },
0126 };
0127 MODULE_DEVICE_TABLE(of, of_flash_match);
0128 
0129 static struct platform_driver of_flash_driver = {
0130     .driver = {
0131         .name = "octeon-of-flash",
0132         .of_match_table = of_flash_match,
0133     },
0134     .probe      = octeon_flash_probe,
0135 };
0136 
0137 static int octeon_flash_init(void)
0138 {
0139     return platform_driver_register(&of_flash_driver);
0140 }
0141 late_initcall(octeon_flash_init);
0142 
0143 MODULE_LICENSE("GPL");