Imported Upstream version 7.9
[platform/upstream/gdb.git] / sim / bfin / dv-bfin_spi.c
1 /* Blackfin Serial Peripheral Interface (SPI) model
2
3    Copyright (C) 2010-2015 Free Software Foundation, Inc.
4    Contributed by Analog Devices, Inc.
5
6    This file is part of simulators.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22
23 #include "sim-main.h"
24 #include "devices.h"
25 #include "dv-bfin_spi.h"
26
27 /* XXX: This is merely a stub.  */
28
29 struct bfin_spi
30 {
31   /* This top portion matches common dv_bfin struct.  */
32   bu32 base;
33   struct hw *dma_master;
34   bool acked;
35
36   struct hw_event *handler;
37   char saved_byte;
38   int saved_count;
39
40   /* Order after here is important -- matches hardware MMR layout.  */
41   bu16 BFIN_MMR_16(ctl);
42   bu16 BFIN_MMR_16(flg);
43   bu16 BFIN_MMR_16(stat);
44   bu16 BFIN_MMR_16(tdbr);
45   bu16 BFIN_MMR_16(rdbr);
46   bu16 BFIN_MMR_16(baud);
47   bu16 BFIN_MMR_16(shadow);
48 };
49 #define mmr_base()      offsetof(struct bfin_spi, ctl)
50 #define mmr_offset(mmr) (offsetof(struct bfin_spi, mmr) - mmr_base())
51
52 static const char * const mmr_names[] =
53 {
54   "SPI_CTL", "SPI_FLG", "SPI_STAT", "SPI_TDBR",
55   "SPI_RDBR", "SPI_BAUD", "SPI_SHADOW",
56 };
57 #define mmr_name(off) mmr_names[(off) / 4]
58
59 static bool
60 bfin_spi_enabled (struct bfin_spi *spi)
61 {
62   return (spi->ctl & SPE);
63 }
64
65 static bu16
66 bfin_spi_timod (struct bfin_spi *spi)
67 {
68   return (spi->ctl & TIMOD);
69 }
70
71 static unsigned
72 bfin_spi_io_write_buffer (struct hw *me, const void *source, int space,
73                           address_word addr, unsigned nr_bytes)
74 {
75   struct bfin_spi *spi = hw_data (me);
76   bu32 mmr_off;
77   bu32 value;
78   bu16 *valuep;
79
80   value = dv_load_2 (source);
81   mmr_off = addr - spi->base;
82   valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);
83
84   HW_TRACE_WRITE ();
85
86   dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
87
88   switch (mmr_off)
89     {
90     case mmr_offset(stat):
91       dv_w1c_2 (valuep, value, ~(SPIF | TXS | RXS));
92       break;
93     case mmr_offset(tdbr):
94       *valuep = value;
95       if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == TDBR_CORE)
96         {
97           spi->stat |= RXS;
98           spi->stat &= ~TXS;
99         }
100       break;
101     case mmr_offset(rdbr):
102     case mmr_offset(ctl):
103     case mmr_offset(flg):
104     case mmr_offset(baud):
105     case mmr_offset(shadow):
106       *valuep = value;
107       break;
108     default:
109       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
110       break;
111     }
112
113   return nr_bytes;
114 }
115
116 static unsigned
117 bfin_spi_io_read_buffer (struct hw *me, void *dest, int space,
118                          address_word addr, unsigned nr_bytes)
119 {
120   struct bfin_spi *spi = hw_data (me);
121   bu32 mmr_off;
122   bu16 *valuep;
123
124   mmr_off = addr - spi->base;
125   valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);
126
127   HW_TRACE_READ ();
128
129   dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
130
131   switch (mmr_off)
132     {
133     case mmr_offset(rdbr):
134       dv_store_2 (dest, *valuep);
135       if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == RDBR_CORE)
136         spi->stat &= ~(RXS | TXS);
137       break;
138     case mmr_offset(ctl):
139     case mmr_offset(stat):
140     case mmr_offset(flg):
141     case mmr_offset(tdbr):
142     case mmr_offset(baud):
143     case mmr_offset(shadow):
144       dv_store_2 (dest, *valuep);
145       break;
146     default:
147       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
148       break;
149     }
150
151   return nr_bytes;
152 }
153
154 static unsigned
155 bfin_spi_dma_read_buffer (struct hw *me, void *dest, int space,
156                           unsigned_word addr, unsigned nr_bytes)
157 {
158   HW_TRACE_DMA_READ ();
159   return 0;
160 }
161
162 static unsigned
163 bfin_spi_dma_write_buffer (struct hw *me, const void *source,
164                            int space, unsigned_word addr,
165                            unsigned nr_bytes,
166                            int violate_read_only_section)
167 {
168   HW_TRACE_DMA_WRITE ();
169   return 0;
170 }
171
172 static const struct hw_port_descriptor bfin_spi_ports[] =
173 {
174   { "stat", 0, 0, output_port, },
175   { NULL, 0, 0, 0, },
176 };
177
178 static void
179 attach_bfin_spi_regs (struct hw *me, struct bfin_spi *spi)
180 {
181   address_word attach_address;
182   int attach_space;
183   unsigned attach_size;
184   reg_property_spec reg;
185
186   if (hw_find_property (me, "reg") == NULL)
187     hw_abort (me, "Missing \"reg\" property");
188
189   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
190     hw_abort (me, "\"reg\" property must contain three addr/size entries");
191
192   hw_unit_address_to_attach_address (hw_parent (me),
193                                      &reg.address,
194                                      &attach_space, &attach_address, me);
195   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
196
197   if (attach_size != BFIN_MMR_SPI_SIZE)
198     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SPI_SIZE);
199
200   hw_attach_address (hw_parent (me),
201                      0, attach_space, attach_address, attach_size, me);
202
203   spi->base = attach_address;
204 }
205
206 static void
207 bfin_spi_finish (struct hw *me)
208 {
209   struct bfin_spi *spi;
210
211   spi = HW_ZALLOC (me, struct bfin_spi);
212
213   set_hw_data (me, spi);
214   set_hw_io_read_buffer (me, bfin_spi_io_read_buffer);
215   set_hw_io_write_buffer (me, bfin_spi_io_write_buffer);
216   set_hw_dma_read_buffer (me, bfin_spi_dma_read_buffer);
217   set_hw_dma_write_buffer (me, bfin_spi_dma_write_buffer);
218   set_hw_ports (me, bfin_spi_ports);
219
220   attach_bfin_spi_regs (me, spi);
221
222   /* Initialize the SPI.  */
223   spi->ctl  = 0x0400;
224   spi->flg  = 0xFF00;
225   spi->stat = 0x0001;
226 }
227
228 const struct hw_descriptor dv_bfin_spi_descriptor[] =
229 {
230   {"bfin_spi", bfin_spi_finish,},
231   {NULL, NULL},
232 };