diff options
Diffstat (limited to 'arch/mips/cavium-octeon/flash_setup.c')
-rw-r--r-- | arch/mips/cavium-octeon/flash_setup.c | 83 |
1 files changed, 77 insertions, 6 deletions
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c index 237e5b1a72d8..a5e8f4a784af 100644 --- a/arch/mips/cavium-octeon/flash_setup.c +++ b/arch/mips/cavium-octeon/flash_setup.c | |||
@@ -8,9 +8,11 @@ | |||
8 | * Copyright (C) 2007, 2008 Cavium Networks | 8 | * Copyright (C) 2007, 2008 Cavium Networks |
9 | */ | 9 | */ |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/export.h> | 11 | #include <linux/module.h> |
12 | #include <linux/semaphore.h> | ||
12 | #include <linux/mtd/mtd.h> | 13 | #include <linux/mtd/mtd.h> |
13 | #include <linux/mtd/map.h> | 14 | #include <linux/mtd/map.h> |
15 | #include <linux/of_platform.h> | ||
14 | #include <linux/mtd/partitions.h> | 16 | #include <linux/mtd/partitions.h> |
15 | 17 | ||
16 | #include <asm/octeon/octeon.h> | 18 | #include <asm/octeon/octeon.h> |
@@ -25,19 +27,62 @@ static const char *part_probe_types[] = { | |||
25 | NULL | 27 | NULL |
26 | }; | 28 | }; |
27 | 29 | ||
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 | |||
28 | /** | 65 | /** |
29 | * Module/ driver initialization. | 66 | * Module/ driver initialization. |
30 | * | 67 | * |
31 | * Returns Zero on success | 68 | * Returns Zero on success |
32 | */ | 69 | */ |
33 | static int __init flash_init(void) | 70 | static int octeon_flash_probe(struct platform_device *pdev) |
34 | { | 71 | { |
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 | |||
35 | /* | 81 | /* |
36 | * Read the bootbus region 0 setup to determine the base | 82 | * Read the bootbus region 0 setup to determine the base |
37 | * address of the flash. | 83 | * address of the flash. |
38 | */ | 84 | */ |
39 | union cvmx_mio_boot_reg_cfgx region_cfg; | 85 | region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); |
40 | region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(0)); | ||
41 | if (region_cfg.s.en) { | 86 | if (region_cfg.s.en) { |
42 | /* | 87 | /* |
43 | * The bootloader always takes the flash and sets its | 88 | * The bootloader always takes the flash and sets its |
@@ -56,7 +101,11 @@ static int __init flash_init(void) | |||
56 | flash_map.virt = ioremap(flash_map.phys, flash_map.size); | 101 | flash_map.virt = ioremap(flash_map.phys, flash_map.size); |
57 | pr_notice("Bootbus flash: Setting flash for %luMB flash at " | 102 | pr_notice("Bootbus flash: Setting flash for %luMB flash at " |
58 | "0x%08llx\n", flash_map.size >> 20, flash_map.phys); | 103 | "0x%08llx\n", flash_map.size >> 20, flash_map.phys); |
59 | simple_map_init(&flash_map); | 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; | ||
60 | mymtd = do_map_probe("cfi_probe", &flash_map); | 109 | mymtd = do_map_probe("cfi_probe", &flash_map); |
61 | if (mymtd) { | 110 | if (mymtd) { |
62 | mymtd->owner = THIS_MODULE; | 111 | mymtd->owner = THIS_MODULE; |
@@ -69,4 +118,26 @@ static int __init flash_init(void) | |||
69 | return 0; | 118 | return 0; |
70 | } | 119 | } |
71 | 120 | ||
72 | late_initcall(flash_init); | 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", | ||
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"); | ||