1 /* -*- c++ -*- */
2 /*
3 * Copyright 2009 Free Software Foundation, Inc.
4 * Copyright 2009-2011 Ettus Research LLC
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "spi_flash_private.h"
21 #include <stdlib.h> // abort
22 #include <nonstdio.h>
23
24 uint32_t
spi_flash_rdid(void)25 spi_flash_rdid(void)
26 {
27 return spif_transact(SPI_TXRX, SPI_SS_FLASH, RDID_CMD << 24, 32, FLAGS) & 0xffffff;
28 }
29
spi_flash_log2_memory_size(void)30 size_t spi_flash_log2_memory_size(void)
31 {
32 static size_t _spi_flash_log2_memory_size = 0;
33 if (_spi_flash_log2_memory_size == 0){
34 uint32_t id = spi_flash_rdid();
35 uint8_t type = (id >> 8) & 0xff;
36 uint8_t size = (id >> 0) & 0xff;
37 if (type != 0x20) abort();
38 _spi_flash_log2_memory_size = size;
39 }
40 if (_spi_flash_log2_memory_size < 22 ||
41 _spi_flash_log2_memory_size > 24 ) abort();
42 return _spi_flash_log2_memory_size;
43 }
44
spi_flash_log2_sector_size(void)45 size_t spi_flash_log2_sector_size(void)
46 {
47 static unsigned char log2_sector_size[3] = {
48 16, /* M25P32 */
49 16, /* M25P64 */
50 18, /* M25P128 */
51 };
52 return log2_sector_size[spi_flash_log2_memory_size() - 22];
53 }
54
spi_flash_sector_size(void)55 size_t spi_flash_sector_size(void)
56 {
57 return ((size_t) 1) << spi_flash_log2_sector_size();
58 }
59
spi_flash_memory_size(void)60 size_t spi_flash_memory_size(void)
61 {
62 return ((size_t) 1) << spi_flash_log2_memory_size();
63 }
64
65 void
spi_flash_read(uint32_t flash_addr,size_t nbytes,void * buf)66 spi_flash_read(uint32_t flash_addr, size_t nbytes, void *buf)
67 {
68 /*
69 * We explicitly control the slave select here (/S), so that we can
70 * do the entire read operation as a single transaction from
71 * device's point of view. (The most our SPI peripheral can transfer
72 * in a single shot is 16 bytes.)
73 */
74 spif_wait();
75
76 spif_regs->ss = 0;
77 spif_regs->ctrl = FLAGS; // ASS is now clear and no chip select is enabled.
78
79 /*
80 * Do the 5 byte instruction tranfer:
81 * FAST_READ_CMD, ADDR2, ADDR1, ADDR0, DUMMY
82 */
83 spif_regs->txrx1 = FAST_READ_CMD;
84 spif_regs->txrx0 = ((flash_addr & 0x00ffffff) << 8);
85 spif_regs->ss = SPI_SS_FLASH; // assert chip select
86 spif_regs->ctrl = FLAGS | LEN(5 * 8);
87 spif_regs->ctrl = FLAGS | LEN(5 * 8) | SPI_CTRL_GO_BSY;
88 spif_wait();
89
90 /*
91 * Read up to 16 bytes at a time until done
92 */
93 unsigned char *dst = (unsigned char *) buf;
94 size_t m;
95 for (size_t n = 0; n < nbytes; n += m){
96
97 spif_regs->ctrl = FLAGS | LEN(16 * 8); // xfer 16 bytes
98 spif_regs->ctrl = FLAGS | LEN(16 * 8) | SPI_CTRL_GO_BSY;
99 spif_wait();
100
101 uint32_t w[4];
102 w[0] = spif_regs->txrx3; // txrx3 has first bits in it
103 w[1] = spif_regs->txrx2;
104 w[2] = spif_regs->txrx1;
105 w[3] = spif_regs->txrx0;
106 unsigned char *src = (unsigned char *) &w[0];
107 m = min(nbytes - n, 16);
108 for (size_t i = 0; i < m; i++)
109 *(dst++) = src[i];
110 }
111 spif_regs->ss = 0; // deassert chip select
112 }
113