]>
Commit | Line | Data |
---|---|---|
4d5e29a6 JT |
1 | /* |
2 | * SPI flash probing | |
3 | * | |
4 | * Copyright (C) 2008 Atmel Corporation | |
5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik | |
6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | |
7 | * | |
0c88a84a | 8 | * SPDX-License-Identifier: GPL-2.0+ |
4d5e29a6 JT |
9 | */ |
10 | ||
11 | #include <common.h> | |
fbb09918 | 12 | #include <dm.h> |
ae242cbf | 13 | #include <errno.h> |
4d5e29a6 JT |
14 | #include <malloc.h> |
15 | #include <spi.h> | |
16 | #include <spi_flash.h> | |
17 | ||
898e76c9 | 18 | #include "sf_internal.h" |
4d5e29a6 | 19 | |
ae242cbf SG |
20 | /** |
21 | * spi_flash_probe_slave() - Probe for a SPI flash device on a bus | |
22 | * | |
ae242cbf SG |
23 | * @flashp: Pointer to place to put flash info, which may be NULL if the |
24 | * space should be allocated | |
25 | */ | |
339fd6dc | 26 | static int spi_flash_probe_slave(struct spi_flash *flash) |
4d5e29a6 | 27 | { |
bfdb07eb | 28 | struct spi_slave *spi = flash->spi; |
4d4ec992 | 29 | int ret; |
4d5e29a6 | 30 | |
4d4ec992 | 31 | /* Setup spi_slave */ |
4d5e29a6 JT |
32 | if (!spi) { |
33 | printf("SF: Failed to set up slave\n"); | |
ae242cbf | 34 | return -ENODEV; |
4d5e29a6 JT |
35 | } |
36 | ||
4d4ec992 | 37 | /* Claim spi bus */ |
4d5e29a6 JT |
38 | ret = spi_claim_bus(spi); |
39 | if (ret) { | |
40 | debug("SF: Failed to claim SPI bus: %d\n", ret); | |
ae242cbf | 41 | return ret; |
4d5e29a6 JT |
42 | } |
43 | ||
bfdb07eb | 44 | ret = spi_flash_scan(flash); |
0badb23d | 45 | if (ret) |
4d4ec992 | 46 | goto err_read_id; |
4d5e29a6 | 47 | |
9fe6d871 DS |
48 | #ifdef CONFIG_SPI_FLASH_MTD |
49 | ret = spi_flash_mtd_register(flash); | |
50 | #endif | |
4d5e29a6 | 51 | |
4d5e29a6 JT |
52 | err_read_id: |
53 | spi_release_bus(spi); | |
ae242cbf SG |
54 | return ret; |
55 | } | |
56 | ||
fbb09918 | 57 | #ifndef CONFIG_DM_SPI_FLASH |
339fd6dc | 58 | static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) |
ae242cbf SG |
59 | { |
60 | struct spi_flash *flash; | |
61 | ||
62 | /* Allocate space if needed (not used by sf-uclass */ | |
63 | flash = calloc(1, sizeof(*flash)); | |
64 | if (!flash) { | |
65 | debug("SF: Failed to allocate spi_flash\n"); | |
66 | return NULL; | |
67 | } | |
68 | ||
bfdb07eb JT |
69 | flash->spi = bus; |
70 | if (spi_flash_probe_slave(flash)) { | |
ae242cbf SG |
71 | spi_free_slave(bus); |
72 | free(flash); | |
73 | return NULL; | |
74 | } | |
75 | ||
76 | return flash; | |
4d5e29a6 JT |
77 | } |
78 | ||
ae242cbf | 79 | struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, |
0efc0249 SG |
80 | unsigned int max_hz, unsigned int spi_mode) |
81 | { | |
ae242cbf | 82 | struct spi_slave *bus; |
0efc0249 | 83 | |
ae242cbf | 84 | bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); |
4fbad92e PF |
85 | if (!bus) |
86 | return NULL; | |
ae242cbf | 87 | return spi_flash_probe_tail(bus); |
0efc0249 SG |
88 | } |
89 | ||
90 | #ifdef CONFIG_OF_SPI_FLASH | |
91 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, | |
92 | int spi_node) | |
93 | { | |
ae242cbf | 94 | struct spi_slave *bus; |
0efc0249 | 95 | |
ae242cbf | 96 | bus = spi_setup_slave_fdt(blob, slave_node, spi_node); |
4fbad92e PF |
97 | if (!bus) |
98 | return NULL; | |
ae242cbf | 99 | return spi_flash_probe_tail(bus); |
0efc0249 SG |
100 | } |
101 | #endif | |
102 | ||
4d5e29a6 JT |
103 | void spi_flash_free(struct spi_flash *flash) |
104 | { | |
9fe6d871 DS |
105 | #ifdef CONFIG_SPI_FLASH_MTD |
106 | spi_flash_mtd_unregister(); | |
107 | #endif | |
4d5e29a6 JT |
108 | spi_free_slave(flash->spi); |
109 | free(flash); | |
110 | } | |
fbb09918 SG |
111 | |
112 | #else /* defined CONFIG_DM_SPI_FLASH */ | |
113 | ||
114 | static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, | |
115 | void *buf) | |
116 | { | |
e564f054 | 117 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 SG |
118 | |
119 | return spi_flash_cmd_read_ops(flash, offset, len, buf); | |
120 | } | |
121 | ||
339fd6dc | 122 | static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, |
fbb09918 SG |
123 | const void *buf) |
124 | { | |
e564f054 | 125 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 | 126 | |
074eed51 | 127 | #if defined(CONFIG_SPI_FLASH_SST) |
1fabefdd | 128 | if (flash->flags & SNOR_F_SST_WR) { |
cdf33938 | 129 | if (flash->spi->mode & SPI_TX_BYTE) |
074eed51 BM |
130 | return sst_write_bp(flash, offset, len, buf); |
131 | else | |
132 | return sst_write_wp(flash, offset, len, buf); | |
133 | } | |
134 | #endif | |
135 | ||
fbb09918 SG |
136 | return spi_flash_cmd_write_ops(flash, offset, len, buf); |
137 | } | |
138 | ||
339fd6dc | 139 | static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) |
fbb09918 | 140 | { |
e564f054 | 141 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 SG |
142 | |
143 | return spi_flash_cmd_erase_ops(flash, offset, len); | |
144 | } | |
145 | ||
339fd6dc | 146 | static int spi_flash_std_probe(struct udevice *dev) |
fbb09918 | 147 | { |
bcbe3d15 | 148 | struct spi_slave *slave = dev_get_parent_priv(dev); |
d0cff03e | 149 | struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); |
fbb09918 SG |
150 | struct spi_flash *flash; |
151 | ||
e564f054 | 152 | flash = dev_get_uclass_priv(dev); |
fbb09918 | 153 | flash->dev = dev; |
bfdb07eb | 154 | flash->spi = slave; |
d0cff03e | 155 | debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); |
bfdb07eb | 156 | return spi_flash_probe_slave(flash); |
fbb09918 SG |
157 | } |
158 | ||
159 | static const struct dm_spi_flash_ops spi_flash_std_ops = { | |
160 | .read = spi_flash_std_read, | |
161 | .write = spi_flash_std_write, | |
162 | .erase = spi_flash_std_erase, | |
163 | }; | |
164 | ||
165 | static const struct udevice_id spi_flash_std_ids[] = { | |
166 | { .compatible = "spi-flash" }, | |
167 | { } | |
168 | }; | |
169 | ||
170 | U_BOOT_DRIVER(spi_flash_std) = { | |
171 | .name = "spi_flash_std", | |
172 | .id = UCLASS_SPI_FLASH, | |
173 | .of_match = spi_flash_std_ids, | |
174 | .probe = spi_flash_std_probe, | |
175 | .priv_auto_alloc_size = sizeof(struct spi_flash), | |
176 | .ops = &spi_flash_std_ops, | |
177 | }; | |
178 | ||
179 | #endif /* CONFIG_DM_SPI_FLASH */ |