0001
0002
0003
0004
0005
0006
0007
0008
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
0067
0068
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
0083
0084
0085 region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
0086 if (region_cfg.s.en) {
0087
0088
0089
0090
0091
0092
0093
0094
0095
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
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");