]> Git Repo - u-boot.git/blame - drivers/mtd/spi/sf_probe.c
mtd: spi-nor: allow registering multiple MTDs when DM is enabled
[u-boot.git] / drivers / mtd / spi / sf_probe.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
4d5e29a6
JT
2/*
3 * SPI flash probing
4 *
5 * Copyright (C) 2008 Atmel Corporation
6 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
7 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
4d5e29a6
JT
8 */
9
10#include <common.h>
fbb09918 11#include <dm.h>
ae242cbf 12#include <errno.h>
f7ae49fc 13#include <log.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 26static 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
c4e88623 44 ret = spi_nor_scan(flash);
0badb23d 45 if (ret)
4d4ec992 46 goto err_read_id;
4d5e29a6 47
3ee152b9
JT
48 if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
49 ret = spi_flash_mtd_register(flash);
4d5e29a6 50
4d5e29a6
JT
51err_read_id:
52 spi_release_bus(spi);
ae242cbf
SG
53 return ret;
54}
55
56c40460 56#if !CONFIG_IS_ENABLED(DM_SPI_FLASH)
36890ff0
MS
57struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
58 unsigned int max_hz, unsigned int spi_mode)
ae242cbf 59{
36890ff0 60 struct spi_slave *bus;
ae242cbf
SG
61 struct spi_flash *flash;
62
36890ff0
MS
63 bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
64 if (!bus)
65 return NULL;
66
ae242cbf
SG
67 /* Allocate space if needed (not used by sf-uclass */
68 flash = calloc(1, sizeof(*flash));
69 if (!flash) {
70 debug("SF: Failed to allocate spi_flash\n");
71 return NULL;
72 }
73
bfdb07eb
JT
74 flash->spi = bus;
75 if (spi_flash_probe_slave(flash)) {
ae242cbf
SG
76 spi_free_slave(bus);
77 free(flash);
78 return NULL;
79 }
80
81 return flash;
4d5e29a6
JT
82}
83
4d5e29a6
JT
84void spi_flash_free(struct spi_flash *flash)
85{
3ee152b9 86 if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
b7f06056 87 spi_flash_mtd_unregister(flash);
3ee152b9 88
4d5e29a6
JT
89 spi_free_slave(flash->spi);
90 free(flash);
91}
fbb09918
SG
92
93#else /* defined CONFIG_DM_SPI_FLASH */
94
95static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
96 void *buf)
97{
e564f054 98 struct spi_flash *flash = dev_get_uclass_priv(dev);
c4e88623
V
99 struct mtd_info *mtd = &flash->mtd;
100 size_t retlen;
fbb09918 101
c4e88623 102 return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
fbb09918
SG
103}
104
339fd6dc 105static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
a3e32c50 106 const void *buf)
fbb09918 107{
e564f054 108 struct spi_flash *flash = dev_get_uclass_priv(dev);
c4e88623
V
109 struct mtd_info *mtd = &flash->mtd;
110 size_t retlen;
fbb09918 111
c4e88623 112 return mtd->_write(mtd, offset, len, &retlen, buf);
fbb09918
SG
113}
114
339fd6dc 115static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
fbb09918 116{
e564f054 117 struct spi_flash *flash = dev_get_uclass_priv(dev);
c4e88623
V
118 struct mtd_info *mtd = &flash->mtd;
119 struct erase_info instr;
120
121 if (offset % mtd->erasesize || len % mtd->erasesize) {
e567ec84 122 debug("SF: Erase offset/length not multiple of erase size\n");
c4e88623
V
123 return -EINVAL;
124 }
125
126 memset(&instr, 0, sizeof(instr));
127 instr.addr = offset;
128 instr.len = len;
fbb09918 129
c4e88623 130 return mtd->_erase(mtd, &instr);
fbb09918
SG
131}
132
b3b60f59
SG
133static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
134{
135 struct spi_flash *flash = dev_get_uclass_priv(dev);
136
137 return spi_flash_cmd_get_sw_write_prot(flash);
138}
139
4806fcea 140int spi_flash_std_probe(struct udevice *dev)
fbb09918 141{
bcbe3d15 142 struct spi_slave *slave = dev_get_parent_priv(dev);
fbb09918
SG
143 struct spi_flash *flash;
144
e564f054 145 flash = dev_get_uclass_priv(dev);
fbb09918 146 flash->dev = dev;
bfdb07eb 147 flash->spi = slave;
bfdb07eb 148 return spi_flash_probe_slave(flash);
fbb09918
SG
149}
150
7371944a
BB
151static int spi_flash_std_remove(struct udevice *dev)
152{
b7f06056
MB
153 struct spi_flash *flash = dev_get_uclass_priv(dev);
154
3ee152b9 155 if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
b7f06056 156 spi_flash_mtd_unregister(flash);
3ee152b9 157
7371944a
BB
158 return 0;
159}
160
fbb09918
SG
161static const struct dm_spi_flash_ops spi_flash_std_ops = {
162 .read = spi_flash_std_read,
163 .write = spi_flash_std_write,
164 .erase = spi_flash_std_erase,
b3b60f59 165 .get_sw_write_prot = spi_flash_std_get_sw_write_prot,
fbb09918
SG
166};
167
168static const struct udevice_id spi_flash_std_ids[] = {
2ee6705b 169 { .compatible = "jedec,spi-nor" },
fbb09918
SG
170 { }
171};
172
e3e2470f
WL
173U_BOOT_DRIVER(jedec_spi_nor) = {
174 .name = "jedec_spi_nor",
fbb09918
SG
175 .id = UCLASS_SPI_FLASH,
176 .of_match = spi_flash_std_ids,
177 .probe = spi_flash_std_probe,
7371944a 178 .remove = spi_flash_std_remove,
a1a8a633 179 .priv_auto = sizeof(struct spi_nor),
fbb09918
SG
180 .ops = &spi_flash_std_ops,
181};
182
bdf8fd76 183DM_DRIVER_ALIAS(jedec_spi_nor, spansion_m25p16)
addf358b 184
fbb09918 185#endif /* CONFIG_DM_SPI_FLASH */
This page took 0.297533 seconds and 4 git commands to generate.