blob: 2d8eccff7d888e68e0050da2183d07b4ca52b4e9 [file] [log] [blame]
Lionel Debieve402a46b2019-11-04 12:28:15 +01001/*
2 * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <errno.h>
8
9#include <drivers/nand.h>
10#include <lib/utils.h>
11#include <plat/common/platform.h>
12
13#define SZ_512 0x200U
Lionel Debievecb0dbc42019-09-25 09:11:31 +020014#define SZ_64M 0x4000000U
Lionel Debieve402a46b2019-11-04 12:28:15 +010015
Lionel Debieve186b0462019-09-24 18:30:12 +020016#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
17static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
Lionel Debieve402a46b2019-11-04 12:28:15 +010018{
19 int result;
20 uint32_t nand_param;
21
22 /* Check if NAND parameters are stored in OTP */
23 result = bsec_shadow_read_otp(&nand_param, NAND_OTP);
24 if (result != BSEC_OK) {
25 ERROR("BSEC: NAND_OTP Error %i\n", result);
26 return -EACCES;
27 }
28
29 if (nand_param == 0U) {
30 return 0;
31 }
32
33 if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
34 goto ecc;
35 }
36
37 /* NAND parameter shall be read from OTP */
38 if ((nand_param & NAND_WIDTH_MASK) != 0U) {
39 nand_dev->buswidth = NAND_BUS_WIDTH_16;
40 } else {
41 nand_dev->buswidth = NAND_BUS_WIDTH_8;
42 }
43
44 switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
45 case NAND_PAGE_SIZE_2K:
46 nand_dev->page_size = 0x800U;
47 break;
48
49 case NAND_PAGE_SIZE_4K:
50 nand_dev->page_size = 0x1000U;
51 break;
52
53 case NAND_PAGE_SIZE_8K:
54 nand_dev->page_size = 0x2000U;
55 break;
56
57 default:
58 ERROR("Cannot read NAND page size\n");
59 return -EINVAL;
60 }
61
62 switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
63 case NAND_BLOCK_SIZE_64_PAGES:
64 nand_dev->block_size = 64U * nand_dev->page_size;
65 break;
66
67 case NAND_BLOCK_SIZE_128_PAGES:
68 nand_dev->block_size = 128U * nand_dev->page_size;
69 break;
70
71 case NAND_BLOCK_SIZE_256_PAGES:
72 nand_dev->block_size = 256U * nand_dev->page_size;
73 break;
74
75 default:
76 ERROR("Cannot read NAND block size\n");
77 return -EINVAL;
78 }
79
80 nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
81 NAND_BLOCK_NB_SHIFT) *
82 NAND_BLOCK_NB_UNIT * nand_dev->block_size;
83
84ecc:
Lionel Debieve186b0462019-09-24 18:30:12 +020085 if (is_slc) {
86 switch ((nand_param & NAND_ECC_BIT_NB_MASK) >>
87 NAND_ECC_BIT_NB_SHIFT) {
88 case NAND_ECC_BIT_NB_1_BITS:
89 nand_dev->ecc.max_bit_corr = 1U;
90 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +010091
Lionel Debieve186b0462019-09-24 18:30:12 +020092 case NAND_ECC_BIT_NB_4_BITS:
93 nand_dev->ecc.max_bit_corr = 4U;
94 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +010095
Lionel Debieve186b0462019-09-24 18:30:12 +020096 case NAND_ECC_BIT_NB_8_BITS:
97 nand_dev->ecc.max_bit_corr = 8U;
98 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +010099
Lionel Debieve186b0462019-09-24 18:30:12 +0200100 case NAND_ECC_ON_DIE:
101 nand_dev->ecc.mode = NAND_ECC_ONDIE;
102 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100103
Lionel Debieve186b0462019-09-24 18:30:12 +0200104 default:
105 if (nand_dev->ecc.max_bit_corr == 0U) {
106 ERROR("No valid eccbit number\n");
107 return -EINVAL;
108 }
109 }
110 } else {
111 /* Selected multiple plane NAND */
112 if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) {
113 nand_dev->nb_planes = 2U;
114 } else {
115 nand_dev->nb_planes = 1U;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100116 }
117 }
118
119 VERBOSE("OTP: Block %i Page %i Size %lli\n", nand_dev->block_size,
120 nand_dev->page_size, nand_dev->size);
121
122 return 0;
123}
Lionel Debieve186b0462019-09-24 18:30:12 +0200124#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
Lionel Debieve402a46b2019-11-04 12:28:15 +0100125
126#if STM32MP_RAW_NAND
127int plat_get_raw_nand_data(struct rawnand_device *device)
128{
129 device->nand_dev->ecc.mode = NAND_ECC_HW;
130 device->nand_dev->ecc.size = SZ_512;
131
Lionel Debieve186b0462019-09-24 18:30:12 +0200132 return get_data_from_otp(device->nand_dev, true);
133}
134#endif
135
136#if STM32MP_SPI_NAND
137int plat_get_spi_nand_data(struct spinand_device *device)
138{
139 zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op));
140 device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X;
141 device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
142 device->spi_read_cache_op.addr.nbytes = 2U;
143 device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
144 device->spi_read_cache_op.dummy.nbytes = 1U;
145 device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
146 device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
147 device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN;
148
149 return get_data_from_otp(device->nand_dev, false);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100150}
151#endif
152
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200153#if STM32MP_SPI_NOR
154int plat_get_nor_data(struct nor_device *device)
155{
156 device->size = SZ_64M;
157
158 zeromem(&device->read_op, sizeof(struct spi_mem_op));
159 device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4;
160 device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
161 device->read_op.addr.nbytes = 3U;
162 device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
163 device->read_op.dummy.nbytes = 1U;
164 device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
165 device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
166 device->read_op.data.dir = SPI_MEM_DATA_IN;
167
168 return 0;
169}
170#endif