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