Blame view
drivers/mtd/spi/sf_probe.c
4.06 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
4d5e29a68
|
2 3 4 5 6 7 |
/* * SPI flash probing * * Copyright (C) 2008 Atmel Corporation * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. |
4d5e29a68
|
8 9 10 |
*/ #include <common.h> |
fbb099183
|
11 |
#include <dm.h> |
ae242cbfd
|
12 |
#include <errno.h> |
4d5e29a68
|
13 14 15 |
#include <malloc.h> #include <spi.h> #include <spi_flash.h> |
898e76c93
|
16 |
#include "sf_internal.h" |
4d5e29a68
|
17 |
|
ae242cbfd
|
18 19 20 |
/** * spi_flash_probe_slave() - Probe for a SPI flash device on a bus * |
ae242cbfd
|
21 22 23 |
* @flashp: Pointer to place to put flash info, which may be NULL if the * space should be allocated */ |
339fd6dca
|
24 |
static int spi_flash_probe_slave(struct spi_flash *flash) |
4d5e29a68
|
25 |
{ |
bfdb07eb4
|
26 |
struct spi_slave *spi = flash->spi; |
4d4ec9927
|
27 |
int ret; |
4d5e29a68
|
28 |
|
4d4ec9927
|
29 |
/* Setup spi_slave */ |
4d5e29a68
|
30 31 32 |
if (!spi) { printf("SF: Failed to set up slave "); |
ae242cbfd
|
33 |
return -ENODEV; |
4d5e29a68
|
34 |
} |
4d4ec9927
|
35 |
/* Claim spi bus */ |
4d5e29a68
|
36 37 38 39 |
ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d ", ret); |
ae242cbfd
|
40 |
return ret; |
4d5e29a68
|
41 |
} |
c4e886230
|
42 |
ret = spi_nor_scan(flash); |
0badb23d1
|
43 |
if (ret) |
4d4ec9927
|
44 |
goto err_read_id; |
4d5e29a68
|
45 |
|
832ce2027
|
46 |
#if CONFIG_IS_ENABLED(SPI_FLASH_MTD) |
9fe6d8716
|
47 48 |
ret = spi_flash_mtd_register(flash); #endif |
4d5e29a68
|
49 |
|
4d5e29a68
|
50 51 |
err_read_id: spi_release_bus(spi); |
ae242cbfd
|
52 53 |
return ret; } |
fbb099183
|
54 |
#ifndef CONFIG_DM_SPI_FLASH |
36890ff0d
|
55 56 |
struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) |
ae242cbfd
|
57 |
{ |
36890ff0d
|
58 |
struct spi_slave *bus; |
ae242cbfd
|
59 |
struct spi_flash *flash; |
36890ff0d
|
60 61 62 |
bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); if (!bus) return NULL; |
ae242cbfd
|
63 64 65 66 67 68 69 |
/* Allocate space if needed (not used by sf-uclass */ flash = calloc(1, sizeof(*flash)); if (!flash) { debug("SF: Failed to allocate spi_flash "); return NULL; } |
bfdb07eb4
|
70 71 |
flash->spi = bus; if (spi_flash_probe_slave(flash)) { |
ae242cbfd
|
72 73 74 75 76 77 |
spi_free_slave(bus); free(flash); return NULL; } return flash; |
4d5e29a68
|
78 |
} |
4d5e29a68
|
79 80 |
void spi_flash_free(struct spi_flash *flash) { |
832ce2027
|
81 |
#if CONFIG_IS_ENABLED(SPI_FLASH_MTD) |
9fe6d8716
|
82 83 |
spi_flash_mtd_unregister(); #endif |
4d5e29a68
|
84 85 86 |
spi_free_slave(flash->spi); free(flash); } |
fbb099183
|
87 88 89 90 91 92 |
#else /* defined CONFIG_DM_SPI_FLASH */ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, void *buf) { |
e564f054a
|
93 |
struct spi_flash *flash = dev_get_uclass_priv(dev); |
c4e886230
|
94 95 |
struct mtd_info *mtd = &flash->mtd; size_t retlen; |
fbb099183
|
96 |
|
c4e886230
|
97 |
return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); |
fbb099183
|
98 |
} |
339fd6dca
|
99 |
static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, |
a3e32c503
|
100 |
const void *buf) |
fbb099183
|
101 |
{ |
e564f054a
|
102 |
struct spi_flash *flash = dev_get_uclass_priv(dev); |
c4e886230
|
103 104 |
struct mtd_info *mtd = &flash->mtd; size_t retlen; |
fbb099183
|
105 |
|
c4e886230
|
106 |
return mtd->_write(mtd, offset, len, &retlen, buf); |
fbb099183
|
107 |
} |
339fd6dca
|
108 |
static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) |
fbb099183
|
109 |
{ |
e564f054a
|
110 |
struct spi_flash *flash = dev_get_uclass_priv(dev); |
c4e886230
|
111 112 113 114 115 116 117 118 119 120 121 122 |
struct mtd_info *mtd = &flash->mtd; struct erase_info instr; if (offset % mtd->erasesize || len % mtd->erasesize) { printf("SF: Erase offset/length not multiple of erase size "); return -EINVAL; } memset(&instr, 0, sizeof(instr)); instr.addr = offset; instr.len = len; |
fbb099183
|
123 |
|
c4e886230
|
124 |
return mtd->_erase(mtd, &instr); |
fbb099183
|
125 |
} |
a58986ca8
|
126 127 128 129 130 131 |
static int spi_flash_std_get_sw_write_prot(struct udevice *dev) { struct spi_flash *flash = dev_get_uclass_priv(dev); return spi_flash_cmd_get_sw_write_prot(flash); } |
339fd6dca
|
132 |
static int spi_flash_std_probe(struct udevice *dev) |
fbb099183
|
133 |
{ |
bcbe3d157
|
134 |
struct spi_slave *slave = dev_get_parent_priv(dev); |
d0cff03e1
|
135 |
struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); |
fbb099183
|
136 |
struct spi_flash *flash; |
e564f054a
|
137 |
flash = dev_get_uclass_priv(dev); |
fbb099183
|
138 |
flash->dev = dev; |
bfdb07eb4
|
139 |
flash->spi = slave; |
d0cff03e1
|
140 141 |
debug("%s: slave=%p, cs=%d ", __func__, slave, plat->cs); |
bfdb07eb4
|
142 |
return spi_flash_probe_slave(flash); |
fbb099183
|
143 |
} |
7371944a7
|
144 145 |
static int spi_flash_std_remove(struct udevice *dev) { |
832ce2027
|
146 |
#if CONFIG_IS_ENABLED(SPI_FLASH_MTD) |
7371944a7
|
147 148 149 150 |
spi_flash_mtd_unregister(); #endif return 0; } |
fbb099183
|
151 152 153 154 |
static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, |
a58986ca8
|
155 |
.get_sw_write_prot = spi_flash_std_get_sw_write_prot, |
fbb099183
|
156 157 158 |
}; static const struct udevice_id spi_flash_std_ids[] = { |
2ee6705be
|
159 |
{ .compatible = "jedec,spi-nor" }, |
fbb099183
|
160 161 162 163 164 165 166 167 |
{ } }; U_BOOT_DRIVER(spi_flash_std) = { .name = "spi_flash_std", .id = UCLASS_SPI_FLASH, .of_match = spi_flash_std_ids, .probe = spi_flash_std_probe, |
7371944a7
|
168 |
.remove = spi_flash_std_remove, |
fbb099183
|
169 170 171 172 173 |
.priv_auto_alloc_size = sizeof(struct spi_flash), .ops = &spi_flash_std_ops, }; #endif /* CONFIG_DM_SPI_FLASH */ |