blob: ba53c7a1359a044a9d6b1ae14f7eeee946a46d6d [file] [log] [blame]
Lionel Debieve402a46b2019-11-04 12:28:15 +01001/*
Yann Gautier4359c9a2022-01-27 13:55:18 +01002 * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
Lionel Debieve402a46b2019-11-04 12:28:15 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Lionel Debieve129f6512021-04-13 17:11:00 +02007#include <assert.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +01008#include <errno.h>
9
Yann Gautier4359c9a2022-01-27 13:55:18 +010010#include <common/debug.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +010011#include <drivers/nand.h>
Madhukar Pappireddyfc9b4112019-12-23 14:49:52 -060012#include <drivers/raw_nand.h>
13#include <drivers/spi_nand.h>
14#include <drivers/spi_nor.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +010015#include <lib/utils.h>
16#include <plat/common/platform.h>
17
Lionel Debieve186b0462019-09-24 18:30:12 +020018#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
Lionel Debieve129f6512021-04-13 17:11:00 +020019#if STM32MP13
20void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size)
21{
22 assert(buffer_addr != NULL);
23 assert(buf_size != NULL);
24
25 *buffer_addr = (void *)STM32MP_MTD_BUFFER;
26 *buf_size = PLATFORM_MTD_MAX_PAGE_SIZE;
27}
28#endif
29
Lionel Debieve186b0462019-09-24 18:30:12 +020030static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
Lionel Debieve402a46b2019-11-04 12:28:15 +010031{
Lionel Debieve402a46b2019-11-04 12:28:15 +010032 uint32_t nand_param;
33
34 /* Check if NAND parameters are stored in OTP */
Lionel Debievebc2d88d2019-11-04 14:31:38 +010035 if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) {
36 ERROR("BSEC: NAND_OTP Error\n");
Lionel Debieve402a46b2019-11-04 12:28:15 +010037 return -EACCES;
38 }
39
40 if (nand_param == 0U) {
41 return 0;
42 }
43
44 if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
45 goto ecc;
46 }
47
48 /* NAND parameter shall be read from OTP */
49 if ((nand_param & NAND_WIDTH_MASK) != 0U) {
50 nand_dev->buswidth = NAND_BUS_WIDTH_16;
51 } else {
52 nand_dev->buswidth = NAND_BUS_WIDTH_8;
53 }
54
55 switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
56 case NAND_PAGE_SIZE_2K:
57 nand_dev->page_size = 0x800U;
58 break;
59
60 case NAND_PAGE_SIZE_4K:
61 nand_dev->page_size = 0x1000U;
62 break;
63
64 case NAND_PAGE_SIZE_8K:
65 nand_dev->page_size = 0x2000U;
66 break;
67
68 default:
69 ERROR("Cannot read NAND page size\n");
70 return -EINVAL;
71 }
72
73 switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
74 case NAND_BLOCK_SIZE_64_PAGES:
75 nand_dev->block_size = 64U * nand_dev->page_size;
76 break;
77
78 case NAND_BLOCK_SIZE_128_PAGES:
79 nand_dev->block_size = 128U * nand_dev->page_size;
80 break;
81
82 case NAND_BLOCK_SIZE_256_PAGES:
83 nand_dev->block_size = 256U * nand_dev->page_size;
84 break;
85
86 default:
87 ERROR("Cannot read NAND block size\n");
88 return -EINVAL;
89 }
90
91 nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
92 NAND_BLOCK_NB_SHIFT) *
93 NAND_BLOCK_NB_UNIT * nand_dev->block_size;
94
95ecc:
Lionel Debieve186b0462019-09-24 18:30:12 +020096 if (is_slc) {
97 switch ((nand_param & NAND_ECC_BIT_NB_MASK) >>
98 NAND_ECC_BIT_NB_SHIFT) {
99 case NAND_ECC_BIT_NB_1_BITS:
100 nand_dev->ecc.max_bit_corr = 1U;
101 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100102
Lionel Debieve186b0462019-09-24 18:30:12 +0200103 case NAND_ECC_BIT_NB_4_BITS:
104 nand_dev->ecc.max_bit_corr = 4U;
105 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100106
Lionel Debieve186b0462019-09-24 18:30:12 +0200107 case NAND_ECC_BIT_NB_8_BITS:
108 nand_dev->ecc.max_bit_corr = 8U;
109 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100110
Lionel Debieve186b0462019-09-24 18:30:12 +0200111 case NAND_ECC_ON_DIE:
112 nand_dev->ecc.mode = NAND_ECC_ONDIE;
113 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100114
Lionel Debieve186b0462019-09-24 18:30:12 +0200115 default:
116 if (nand_dev->ecc.max_bit_corr == 0U) {
117 ERROR("No valid eccbit number\n");
118 return -EINVAL;
119 }
120 }
121 } else {
122 /* Selected multiple plane NAND */
123 if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) {
124 nand_dev->nb_planes = 2U;
125 } else {
126 nand_dev->nb_planes = 1U;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100127 }
128 }
129
Yann Gautier37bea082022-02-14 11:10:59 +0100130 VERBOSE("OTP: Block %u Page %u Size %llu\n", nand_dev->block_size,
131 nand_dev->page_size, nand_dev->size);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100132
133 return 0;
134}
Lionel Debieve186b0462019-09-24 18:30:12 +0200135#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
Lionel Debieve402a46b2019-11-04 12:28:15 +0100136
137#if STM32MP_RAW_NAND
138int plat_get_raw_nand_data(struct rawnand_device *device)
139{
140 device->nand_dev->ecc.mode = NAND_ECC_HW;
141 device->nand_dev->ecc.size = SZ_512;
142
Lionel Debieve186b0462019-09-24 18:30:12 +0200143 return get_data_from_otp(device->nand_dev, true);
144}
145#endif
146
147#if STM32MP_SPI_NAND
148int plat_get_spi_nand_data(struct spinand_device *device)
149{
150 zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op));
151 device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X;
152 device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
153 device->spi_read_cache_op.addr.nbytes = 2U;
154 device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
155 device->spi_read_cache_op.dummy.nbytes = 1U;
156 device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
157 device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
158 device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN;
159
160 return get_data_from_otp(device->nand_dev, false);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100161}
162#endif
163
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200164#if STM32MP_SPI_NOR
165int plat_get_nor_data(struct nor_device *device)
166{
167 device->size = SZ_64M;
168
169 zeromem(&device->read_op, sizeof(struct spi_mem_op));
170 device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4;
171 device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
172 device->read_op.addr.nbytes = 3U;
173 device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
174 device->read_op.dummy.nbytes = 1U;
175 device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
176 device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
177 device->read_op.data.dir = SPI_MEM_DATA_IN;
178
179 return 0;
180}
181#endif