1 /*! \page License
2 * Copyright (C) 2009, H&D Wireless AB All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * 3. The name of H&D Wireless AB may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
20 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <string.h>
29
30 #include "compiler.h"
31 #include "preprocessor.h"
32 #include "board.h"
33 #include "power_clocks_lib.h"
34 #include "gpio.h"
35 #include "spi.h"
36 #include "conf_at45dbx.h"
37 #include "at45dbx.h"
38 #include <board_init.h>
39 #include <nvram.h>
40
41
42 static struct nvram {
43 uint8_t read;
44 void *data;
45 uint32_t len;
46 uint16_t off;
47 } PRIV;
48
nvram_init(void)49 int nvram_init(void)
50 {
51 spi_options_t spiOptions = {
52 .reg = AT45DBX_SPI_FIRST_NPCS,
53 .baudrate = AT45DBX_SPI_MASTER_SPEED,
54 .bits = AT45DBX_SPI_BITS,
55 .spck_delay = 0,
56 .trans_delay = 0,
57 .stay_act = 1,
58 .spi_mode = 0,
59 .modfdis = 1
60 };
61
62 at45dbx_init(spiOptions, FPBA_HZ);
63 return 0;
64 }
65
66
67 /**
68 * Invoked by at45dbx driver
69 *
70 */
at45dbx_read_multiple_sector_callback(const void * psector)71 void at45dbx_read_multiple_sector_callback(const void *psector)
72 {
73 struct nvram *priv = &PRIV;
74 const uint8_t *buf = psector;
75
76 if (!priv->read)
77 return;
78
79 memcpy(priv->data, buf + priv->off, priv->len);
80 }
81
82
83 /**
84 * Invoked by at45dbx driver
85 *
86 */
at45dbx_write_multiple_sector_callback(void * psector)87 void at45dbx_write_multiple_sector_callback(void *psector)
88 {
89 struct nvram *priv = &PRIV;
90 uint8_t *buf = psector;
91 memcpy(buf + priv->off, priv->data, priv->len);
92 }
93
94
95 /**
96 * Write/read any number bytes into any offset of nor flash by taking care
97 * of cases where the length is not aligned to the sector size or where
98 * the addr is not aligned to the sector offsets.
99 *
100 */
nvram_rw(uint32_t addr,void * data,uint16_t len,int write)101 static int nvram_rw(uint32_t addr, void *data, uint16_t len, int write)
102 {
103 struct nvram *priv = &PRIV;
104 priv->read = write ? 0 : 1;
105
106 while (len) {
107 uint32_t sector = addr / AT45DBX_SECTOR_SIZE;
108 priv->data = data;
109 priv->off = addr % AT45DBX_SECTOR_SIZE;
110 priv->len = AT45DBX_SECTOR_SIZE;
111
112 if (len < AT45DBX_SECTOR_SIZE)
113 priv->len = len;
114
115 if (priv->len > AT45DBX_SECTOR_SIZE - priv->off)
116 priv->len = AT45DBX_SECTOR_SIZE - priv->off;
117
118 at45dbx_read_open(sector);
119 at45dbx_read_multiple_sector(1);
120 at45dbx_read_close();
121
122 if (write) {
123 at45dbx_write_open(sector);
124 at45dbx_write_multiple_sector(1);
125 at45dbx_write_close();
126 }
127
128 data += priv->len;
129 len -= priv->len;
130 addr += priv->len;
131 }
132
133 return 0;
134 }
135
136 /**
137 * Write any number bytes into any offset of nor flash.
138 *
139 */
nvram_write(uint32_t addr,const void * data,uint32_t len)140 int nvram_write(uint32_t addr, const void *data, uint32_t len)
141 {
142 return nvram_rw(addr, (void *) data, len, 1);
143 }
144
145
146 /**
147 * Read any number bytes into any offset of nor flash.
148 *
149 */
nvram_read(uint32_t addr,void * data,uint32_t len)150 int nvram_read(uint32_t addr, void *data, uint32_t len)
151 {
152 return nvram_rw(addr, data, len, 0);
153 }
154