Commit | Line | Data |
---|---|---|
5b3b1688 DD |
1 | /* |
2 | * Octeon Bootbus flash setup | |
3 | * | |
4 | * This file is subject to the terms and conditions of the GNU General Public | |
5 | * License. See the file "COPYING" in the main directory of this archive | |
6 | * for more details. | |
7 | * | |
8 | * Copyright (C) 2007, 2008 Cavium Networks | |
9 | */ | |
10 | #include <linux/kernel.h> | |
7f481716 | 11 | #include <linux/module.h> |
8c1e6b14 | 12 | #include <linux/semaphore.h> |
5b3b1688 DD |
13 | #include <linux/mtd/mtd.h> |
14 | #include <linux/mtd/map.h> | |
7f481716 | 15 | #include <linux/of_platform.h> |
5b3b1688 DD |
16 | #include <linux/mtd/partitions.h> |
17 | ||
18 | #include <asm/octeon/octeon.h> | |
19 | ||
20 | static struct map_info flash_map; | |
21 | static struct mtd_info *mymtd; | |
5b3b1688 DD |
22 | static const char *part_probe_types[] = { |
23 | "cmdlinepart", | |
24 | #ifdef CONFIG_MTD_REDBOOT_PARTS | |
25 | "RedBoot", | |
26 | #endif | |
27 | NULL | |
28 | }; | |
5b3b1688 | 29 | |
8c1e6b14 DD |
30 | static map_word octeon_flash_map_read(struct map_info *map, unsigned long ofs) |
31 | { | |
32 | map_word r; | |
33 | ||
34 | down(&octeon_bootbus_sem); | |
35 | r = inline_map_read(map, ofs); | |
36 | up(&octeon_bootbus_sem); | |
37 | ||
38 | return r; | |
39 | } | |
40 | ||
41 | static void octeon_flash_map_write(struct map_info *map, const map_word datum, | |
42 | unsigned long ofs) | |
43 | { | |
44 | down(&octeon_bootbus_sem); | |
45 | inline_map_write(map, datum, ofs); | |
46 | up(&octeon_bootbus_sem); | |
47 | } | |
48 | ||
49 | static void octeon_flash_map_copy_from(struct map_info *map, void *to, | |
50 | unsigned long from, ssize_t len) | |
51 | { | |
52 | down(&octeon_bootbus_sem); | |
53 | inline_map_copy_from(map, to, from, len); | |
54 | up(&octeon_bootbus_sem); | |
55 | } | |
56 | ||
57 | static void octeon_flash_map_copy_to(struct map_info *map, unsigned long to, | |
58 | const void *from, ssize_t len) | |
59 | { | |
60 | down(&octeon_bootbus_sem); | |
61 | inline_map_copy_to(map, to, from, len); | |
62 | up(&octeon_bootbus_sem); | |
63 | } | |
64 | ||
5b3b1688 DD |
65 | /** |
66 | * Module/ driver initialization. | |
67 | * | |
68 | * Returns Zero on success | |
69 | */ | |
7f481716 | 70 | static int octeon_flash_probe(struct platform_device *pdev) |
5b3b1688 | 71 | { |
7f481716 DD |
72 | union cvmx_mio_boot_reg_cfgx region_cfg; |
73 | u32 cs; | |
74 | int r; | |
75 | struct device_node *np = pdev->dev.of_node; | |
76 | ||
77 | r = of_property_read_u32(np, "reg", &cs); | |
78 | if (r) | |
79 | return r; | |
80 | ||
5b3b1688 DD |
81 | /* |
82 | * Read the bootbus region 0 setup to determine the base | |
83 | * address of the flash. | |
84 | */ | |
7f481716 | 85 | region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); |
5b3b1688 DD |
86 | if (region_cfg.s.en) { |
87 | /* | |
88 | * The bootloader always takes the flash and sets its | |
89 | * address so the entire flash fits below | |
90 | * 0x1fc00000. This way the flash aliases to | |
91 | * 0x1fc00000 for booting. Software can access the | |
92 | * full flash at the true address, while core boot can | |
93 | * access 4MB. | |
94 | */ | |
95 | /* Use this name so old part lines work */ | |
96 | flash_map.name = "phys_mapped_flash"; | |
97 | flash_map.phys = region_cfg.s.base << 16; | |
98 | flash_map.size = 0x1fc00000 - flash_map.phys; | |
0f731711 CH |
99 | /* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */ |
100 | flash_map.bankwidth = region_cfg.s.width + 1; | |
5b3b1688 DD |
101 | flash_map.virt = ioremap(flash_map.phys, flash_map.size); |
102 | pr_notice("Bootbus flash: Setting flash for %luMB flash at " | |
12e22e8e | 103 | "0x%08llx\n", flash_map.size >> 20, flash_map.phys); |
8c1e6b14 DD |
104 | WARN_ON(!map_bankwidth_supported(flash_map.bankwidth)); |
105 | flash_map.read = octeon_flash_map_read; | |
106 | flash_map.write = octeon_flash_map_write; | |
107 | flash_map.copy_from = octeon_flash_map_copy_from; | |
108 | flash_map.copy_to = octeon_flash_map_copy_to; | |
5b3b1688 DD |
109 | mymtd = do_map_probe("cfi_probe", &flash_map); |
110 | if (mymtd) { | |
111 | mymtd->owner = THIS_MODULE; | |
b2f90941 | 112 | mtd_device_parse_register(mymtd, part_probe_types, |
42d7fbe2 | 113 | NULL, NULL, 0); |
5b3b1688 DD |
114 | } else { |
115 | pr_err("Failed to register MTD device for flash\n"); | |
116 | } | |
117 | } | |
118 | return 0; | |
119 | } | |
120 | ||
7f481716 DD |
121 | static const struct of_device_id of_flash_match[] = { |
122 | { | |
123 | .compatible = "cfi-flash", | |
124 | }, | |
125 | { }, | |
126 | }; | |
127 | MODULE_DEVICE_TABLE(of, of_flash_match); | |
128 | ||
129 | static struct platform_driver of_flash_driver = { | |
130 | .driver = { | |
131 | .name = "octeon-of-flash", | |
7f481716 DD |
132 | .of_match_table = of_flash_match, |
133 | }, | |
134 | .probe = octeon_flash_probe, | |
135 | }; | |
136 | ||
137 | static int octeon_flash_init(void) | |
138 | { | |
139 | return platform_driver_register(&of_flash_driver); | |
140 | } | |
141 | late_initcall(octeon_flash_init); | |
142 | ||
143 | MODULE_LICENSE("GPL"); |