dv-cfi.c revision 1.1.1.6
1/* Common Flash Memory Interface (CFI) model.
2   http://www.spansion.com/Support/AppNotes/CFI_Spec_AN_03.pdf
3   http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf
4
5   Copyright (C) 2010-2017 Free Software Foundation, Inc.
6   Contributed by Analog Devices, Inc.
7
8   This file is part of simulators.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 3 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23/* TODO: support vendor query tables.  */
24
25#include "config.h"
26
27#include <math.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <stdbool.h>
31#include <unistd.h>
32#ifdef HAVE_SYS_MMAN_H
33#include <sys/mman.h>
34#endif
35
36#include "sim-main.h"
37#include "hw-base.h"
38#include "hw-main.h"
39#include "dv-cfi.h"
40
41/* Flashes are simple state machines, so here we cover all the
42   different states a device might be in at any particular time.  */
43enum cfi_state
44{
45  CFI_STATE_READ,
46  CFI_STATE_READ_ID,
47  CFI_STATE_CFI_QUERY,
48  CFI_STATE_PROTECT,
49  CFI_STATE_STATUS,
50  CFI_STATE_ERASE,
51  CFI_STATE_WRITE,
52  CFI_STATE_WRITE_BUFFER,
53  CFI_STATE_WRITE_BUFFER_CONFIRM,
54};
55
56/* This is the structure that all CFI conforming devices must provided
57   when asked for it.  This allows a single driver to dynamically support
58   different flash geometries without having to hardcode specs.
59
60   If you want to start mucking about here, you should just grab the
61   CFI spec and review that (see top of this file for URIs).  */
62struct cfi_query
63{
64  /* This is always 'Q' 'R' 'Y'.  */
65  unsigned char qry[3];
66  /* Primary vendor ID.  */
67  unsigned char p_id[2];
68  /* Primary query table address.  */
69  unsigned char p_adr[2];
70  /* Alternate vendor ID.  */
71  unsigned char a_id[2];
72  /* Alternate query table address.  */
73  unsigned char a_adr[2];
74  union
75  {
76    /* Voltage levels.  */
77    unsigned char voltages[4];
78    struct
79    {
80      /* Normal min voltage level.  */
81      unsigned char vcc_min;
82      /* Normal max voltage level.  */
83      unsigned char vcc_max;
84      /* Programming min volage level.  */
85      unsigned char vpp_min;
86      /* Programming max volage level.  */
87      unsigned char vpp_max;
88    };
89  };
90  union
91  {
92    /* Operational timeouts.  */
93    unsigned char timeouts[8];
94    struct
95    {
96      /* Typical timeout for writing a single "unit".  */
97      unsigned char timeout_typ_unit_write;
98      /* Typical timeout for writing a single "buffer".  */
99      unsigned char timeout_typ_buf_write;
100      /* Typical timeout for erasing a block.  */
101      unsigned char timeout_typ_block_erase;
102      /* Typical timeout for erasing the chip.  */
103      unsigned char timeout_typ_chip_erase;
104      /* Max timeout for writing a single "unit".  */
105      unsigned char timeout_max_unit_write;
106      /* Max timeout for writing a single "buffer".  */
107      unsigned char timeout_max_buf_write;
108      /* Max timeout for erasing a block.  */
109      unsigned char timeout_max_block_erase;
110      /* Max timeout for erasing the chip.  */
111      unsigned char timeout_max_chip_erase;
112    };
113  };
114  /* Flash size is 2^dev_size bytes.  */
115  unsigned char dev_size;
116  /* Flash device interface description.  */
117  unsigned char iface_desc[2];
118  /* Max length of a single buffer write is 2^max_buf_write_len bytes.  */
119  unsigned char max_buf_write_len[2];
120  /* Number of erase regions.  */
121  unsigned char num_erase_regions;
122  /* The erase regions would now be an array after this point, but since
123     it is dynamic, we'll provide that from "struct cfi" when requested.  */
124  /*unsigned char erase_region_info;*/
125};
126
127/* Flashes may have regions with different erase sizes.  There is one
128   structure per erase region.  */
129struct cfi_erase_region
130{
131  unsigned blocks;
132  unsigned size;
133  unsigned start;
134  unsigned end;
135};
136
137struct cfi;
138
139/* Flashes are accessed via commands -- you write a certain number to
140   a special address to change the flash state and access info other
141   than the data.  Diff companies have implemented their own command
142   set.  This structure abstracts the different command sets so that
143   we can support multiple ones with just a single sim driver.  */
144struct cfi_cmdset
145{
146  unsigned id;
147  void (*setup) (struct hw *me, struct cfi *cfi);
148  bool (*write) (struct hw *me, struct cfi *cfi, const void *source,
149		 unsigned offset, unsigned value, unsigned nr_bytes);
150  bool (*read) (struct hw *me, struct cfi *cfi, void *dest,
151		unsigned offset, unsigned shifted_offset, unsigned nr_bytes);
152};
153
154/* The per-flash state.  Much of this comes from the device tree which
155   people declare themselves.  See top of attach_cfi_regs() for more
156   info.  */
157struct cfi
158{
159  unsigned width, dev_size, status;
160  enum cfi_state state;
161  unsigned char *data, *mmap;
162
163  struct cfi_query query;
164  const struct cfi_cmdset *cmdset;
165
166  unsigned char *erase_region_info;
167  struct cfi_erase_region *erase_regions;
168};
169
170/* Helpful strings which are used with HW_TRACE.  */
171static const char * const state_names[] =
172{
173  "READ", "READ_ID", "CFI_QUERY", "PROTECT", "STATUS", "ERASE", "WRITE",
174  "WRITE_BUFFER", "WRITE_BUFFER_CONFIRM",
175};
176
177/* Erase the block specified by the offset into the given CFI flash.  */
178static void
179cfi_erase_block (struct hw *me, struct cfi *cfi, unsigned offset)
180{
181  unsigned i;
182  struct cfi_erase_region *region;
183
184  /* If no erase regions, then we can only do whole chip erase.  */
185  /* XXX: Is this within spec ?  Or must there always be at least one ?  */
186  if (!cfi->query.num_erase_regions)
187    memset (cfi->data, 0xff, cfi->dev_size);
188
189  for (i = 0; i < cfi->query.num_erase_regions; ++i)
190    {
191      region = &cfi->erase_regions[i];
192
193      if (offset >= region->end)
194	continue;
195
196      /* XXX: Does spec require the erase addr to be erase block aligned ?
197	      Maybe this is check is overly cautious ...  */
198      offset &= ~(region->size - 1);
199      memset (cfi->data + offset, 0xff, region->size);
200      break;
201    }
202}
203
204/* Depending on the bus width, addresses might be bit shifted.  This
205   helps us normalize everything without cluttering up the rest of
206   the code.  */
207static unsigned
208cfi_unshift_addr (struct cfi *cfi, unsigned addr)
209{
210  switch (cfi->width)
211    {
212    case 4: addr >>= 1; /* fallthrough.  */
213    case 2: addr >>= 1;
214    }
215  return addr;
216}
217
218/* CFI requires all values to be little endian in its structure, so
219   this helper writes a 16bit value into a little endian byte buffer.  */
220static void
221cfi_encode_16bit (unsigned char *data, unsigned num)
222{
223  data[0] = num;
224  data[1] = num >> 8;
225}
226
227/* The functions required to implement the Intel command set.  */
228
229static bool
230cmdset_intel_write (struct hw *me, struct cfi *cfi, const void *source,
231		    unsigned offset, unsigned value, unsigned nr_bytes)
232{
233  switch (cfi->state)
234    {
235    case CFI_STATE_READ:
236    case CFI_STATE_READ_ID:
237      switch (value)
238	{
239	case INTEL_CMD_ERASE_BLOCK:
240	  cfi->state = CFI_STATE_ERASE;
241	  break;
242	case INTEL_CMD_WRITE:
243	case INTEL_CMD_WRITE_ALT:
244	  cfi->state = CFI_STATE_WRITE;
245	  break;
246	case INTEL_CMD_STATUS_CLEAR:
247	  cfi->status = INTEL_SR_DWS;
248	  break;
249	case INTEL_CMD_LOCK_SETUP:
250	  cfi->state = CFI_STATE_PROTECT;
251	  break;
252	default:
253	  return false;
254	}
255      break;
256
257    case CFI_STATE_ERASE:
258      if (value == INTEL_CMD_ERASE_CONFIRM)
259	{
260	  cfi_erase_block (me, cfi, offset);
261	  cfi->status &= ~(INTEL_SR_PS | INTEL_SR_ES);
262	}
263      else
264	cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
265      cfi->state = CFI_STATE_STATUS;
266      break;
267
268    case CFI_STATE_PROTECT:
269      switch (value)
270	{
271	case INTEL_CMD_LOCK_BLOCK:
272	case INTEL_CMD_UNLOCK_BLOCK:
273	case INTEL_CMD_LOCK_DOWN_BLOCK:
274	  /* XXX: Handle the command.  */
275	  break;
276	default:
277	  /* Kick out.  */
278	  cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
279	  break;
280	}
281      cfi->state = CFI_STATE_STATUS;
282      break;
283
284    default:
285      return false;
286    }
287
288  return true;
289}
290
291static bool
292cmdset_intel_read (struct hw *me, struct cfi *cfi, void *dest,
293		   unsigned offset, unsigned shifted_offset, unsigned nr_bytes)
294{
295  unsigned char *sdest = dest;
296
297  switch (cfi->state)
298    {
299    case CFI_STATE_STATUS:
300    case CFI_STATE_ERASE:
301      *sdest = cfi->status;
302      break;
303
304    case CFI_STATE_READ_ID:
305      switch (shifted_offset & 0x1ff)
306	{
307	case 0x00:	/* Manufacturer Code.  */
308	  cfi_encode_16bit (dest, INTEL_ID_MANU);
309	  break;
310	case 0x01:	/* Device ID Code.  */
311	  /* XXX: Push to device tree ?  */
312	  cfi_encode_16bit (dest, 0xad);
313	  break;
314	case 0x02:	/* Block lock state.  */
315	  /* XXX: This is per-block ...  */
316	  *sdest = 0x00;
317	  break;
318	case 0x05:	/* Read Configuration Register.  */
319	  cfi_encode_16bit (dest, (1 << 15));
320	  break;
321	default:
322	  return false;
323	}
324      break;
325
326    default:
327      return false;
328    }
329
330  return true;
331}
332
333static void
334cmdset_intel_setup (struct hw *me, struct cfi *cfi)
335{
336  cfi->status = INTEL_SR_DWS;
337}
338
339static const struct cfi_cmdset cfi_cmdset_intel =
340{
341  CFI_CMDSET_INTEL, cmdset_intel_setup, cmdset_intel_write, cmdset_intel_read,
342};
343
344/* All of the supported command sets get listed here.  We then walk this
345   array to see if the user requested command set is implemented.  */
346static const struct cfi_cmdset * const cfi_cmdsets[] =
347{
348  &cfi_cmdset_intel,
349};
350
351/* All writes to the flash address space come here.  Using the state
352   machine, we figure out what to do with this specific write.  All
353   common code sits here and if there is a request we can't process,
354   we hand it off to the command set-specific write function.  */
355static unsigned
356cfi_io_write_buffer (struct hw *me, const void *source, int space,
357		     address_word addr, unsigned nr_bytes)
358{
359  struct cfi *cfi = hw_data (me);
360  const unsigned char *ssource = source;
361  enum cfi_state old_state;
362  unsigned offset, shifted_offset, value;
363
364  offset = addr & (cfi->dev_size - 1);
365  shifted_offset = cfi_unshift_addr (cfi, offset);
366
367  if (cfi->width != nr_bytes)
368    {
369      HW_TRACE ((me, "write 0x%08lx length %u does not match flash width %u",
370		 (unsigned long) addr, nr_bytes, cfi->width));
371      return nr_bytes;
372    }
373
374  if (cfi->state == CFI_STATE_WRITE)
375    {
376      /* NOR flash can only go from 1 to 0.  */
377      unsigned i;
378
379      HW_TRACE ((me, "program %#x length %u", offset, nr_bytes));
380
381      for (i = 0; i < nr_bytes; ++i)
382	cfi->data[offset + i] &= ssource[i];
383
384      cfi->state = CFI_STATE_STATUS;
385
386      return nr_bytes;
387    }
388
389  value = ssource[0];
390
391  old_state = cfi->state;
392
393  if (value == CFI_CMD_READ || value == CFI_CMD_RESET)
394    {
395      cfi->state = CFI_STATE_READ;
396      goto done;
397    }
398
399  switch (cfi->state)
400    {
401    case CFI_STATE_READ:
402    case CFI_STATE_READ_ID:
403      if (value == CFI_CMD_CFI_QUERY)
404	{
405	  if (shifted_offset == CFI_ADDR_CFI_QUERY_START)
406	    cfi->state = CFI_STATE_CFI_QUERY;
407	  goto done;
408	}
409
410      if (value == CFI_CMD_READ_ID)
411	{
412	  cfi->state = CFI_STATE_READ_ID;
413	  goto done;
414	}
415
416      /* Fall through.  */
417
418    default:
419      if (!cfi->cmdset->write (me, cfi, source, offset, value, nr_bytes))
420	HW_TRACE ((me, "unhandled command %#x at %#x", value, offset));
421      break;
422    }
423
424 done:
425  HW_TRACE ((me, "write 0x%08lx command {%#x,%#x,%#x,%#x}; state %s -> %s",
426	     (unsigned long) addr, ssource[0],
427	     nr_bytes > 1 ? ssource[1] : 0,
428	     nr_bytes > 2 ? ssource[2] : 0,
429	     nr_bytes > 3 ? ssource[3] : 0,
430	     state_names[old_state], state_names[cfi->state]));
431
432  return nr_bytes;
433}
434
435/* All reads to the flash address space come here.  Using the state
436   machine, we figure out what to return -- actual data stored in the
437   flash, the CFI query structure, some status info, or something else ?
438   Any requests that we can't handle are passed to the command set-
439   specific read function.  */
440static unsigned
441cfi_io_read_buffer (struct hw *me, void *dest, int space,
442		    address_word addr, unsigned nr_bytes)
443{
444  struct cfi *cfi = hw_data (me);
445  unsigned char *sdest = dest;
446  unsigned offset, shifted_offset;
447
448  offset = addr & (cfi->dev_size - 1);
449  shifted_offset = cfi_unshift_addr (cfi, offset);
450
451  /* XXX: Is this OK to enforce ?  */
452#if 0
453  if (cfi->state != CFI_STATE_READ && cfi->width != nr_bytes)
454    {
455      HW_TRACE ((me, "read 0x%08lx length %u does not match flash width %u",
456		 (unsigned long) addr, nr_bytes, cfi->width));
457      return nr_bytes;
458    }
459#endif
460
461  HW_TRACE ((me, "%s read 0x%08lx length %u",
462	     state_names[cfi->state], (unsigned long) addr, nr_bytes));
463
464  switch (cfi->state)
465    {
466    case CFI_STATE_READ:
467      memcpy (dest, cfi->data + offset, nr_bytes);
468      break;
469
470    case CFI_STATE_CFI_QUERY:
471      if (shifted_offset >= CFI_ADDR_CFI_QUERY_RESULT &&
472	  shifted_offset < CFI_ADDR_CFI_QUERY_RESULT + sizeof (cfi->query) +
473		     (cfi->query.num_erase_regions * 4))
474	{
475	  unsigned char *qry;
476
477	  shifted_offset -= CFI_ADDR_CFI_QUERY_RESULT;
478	  if (shifted_offset >= sizeof (cfi->query))
479	    {
480	      qry = cfi->erase_region_info;
481	      shifted_offset -= sizeof (cfi->query);
482	    }
483	  else
484	    qry = (void *) &cfi->query;
485
486	  sdest[0] = qry[shifted_offset];
487	  memset (sdest + 1, 0, nr_bytes - 1);
488
489	  break;
490	}
491
492    default:
493      if (!cfi->cmdset->read (me, cfi, dest, offset, shifted_offset, nr_bytes))
494	HW_TRACE ((me, "unhandled state %s", state_names[cfi->state]));
495      break;
496    }
497
498  return nr_bytes;
499}
500
501/* Clean up any state when this device is removed (e.g. when shutting
502   down, or when reloading via gdb).  */
503static void
504cfi_delete_callback (struct hw *me)
505{
506#ifdef HAVE_MMAP
507  struct cfi *cfi = hw_data (me);
508
509  if (cfi->mmap)
510    munmap (cfi->mmap, cfi->dev_size);
511#endif
512}
513
514/* Helper function to easily add CFI erase regions to the existing set.  */
515static void
516cfi_add_erase_region (struct hw *me, struct cfi *cfi,
517		      unsigned blocks, unsigned size)
518{
519  unsigned num_regions = cfi->query.num_erase_regions;
520  struct cfi_erase_region *region;
521  unsigned char *qry_region;
522
523  /* Store for our own usage.  */
524  region = &cfi->erase_regions[num_regions];
525  region->blocks = blocks;
526  region->size = size;
527  if (num_regions == 0)
528    region->start = 0;
529  else
530    region->start = region[-1].end;
531  region->end = region->start + (blocks * size);
532
533  /* Regions are 4 bytes long.  */
534  qry_region = cfi->erase_region_info + 4 * num_regions;
535
536  /* [0][1] = number erase blocks - 1 */
537  if (blocks > 0xffff + 1)
538    hw_abort (me, "erase blocks %u too big to fit into region info", blocks);
539  cfi_encode_16bit (&qry_region[0], blocks - 1);
540
541  /* [2][3] = block size / 256 bytes */
542  if (size > 0xffff * 256)
543    hw_abort (me, "erase size %u too big to fit into region info", size);
544  cfi_encode_16bit (&qry_region[2], size / 256);
545
546  /* Yet another region.  */
547  cfi->query.num_erase_regions = num_regions + 1;
548}
549
550/* Device tree options:
551     Required:
552       .../reg <addr> <len>
553       .../cmdset <primary; integer> [alt; integer]
554     Optional:
555       .../size <device size (must be pow of 2)>
556       .../width <8|16|32>
557       .../write_size <integer (must be pow of 2)>
558       .../erase_regions <number blocks> <block size> \
559                         [<number blocks> <block size> ...]
560       .../voltage <vcc min> <vcc max> <vpp min> <vpp max>
561       .../timeouts <typ unit write>  <typ buf write>  \
562                    <typ block erase> <typ chip erase> \
563                    <max unit write>  <max buf write>  \
564                    <max block erase> <max chip erase>
565       .../file <file> [ro|rw]
566     Defaults:
567       size: <len> from "reg"
568       width: 8
569       write_size: 0 (not supported)
570       erase_region: 1 (can only erase whole chip)
571       voltage: 0.0V (for all)
572       timeouts: typ: 1��s, not supported, 1ms, not supported
573                 max: 1��s, 1ms, 1ms, not supported
574
575  TODO: Verify user args are valid (e.g. voltage is 8 bits).  */
576static void
577attach_cfi_regs (struct hw *me, struct cfi *cfi)
578{
579  address_word attach_address;
580  int attach_space;
581  unsigned attach_size;
582  reg_property_spec reg;
583  bool fd_writable;
584  int i, ret, fd;
585  signed_cell ival;
586
587  if (hw_find_property (me, "reg") == NULL)
588    hw_abort (me, "Missing \"reg\" property");
589  if (hw_find_property (me, "cmdset") == NULL)
590    hw_abort (me, "Missing \"cmdset\" property");
591
592  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
593    hw_abort (me, "\"reg\" property must contain three addr/size entries");
594
595  hw_unit_address_to_attach_address (hw_parent (me),
596				     &reg.address,
597				     &attach_space, &attach_address, me);
598  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
599
600  hw_attach_address (hw_parent (me),
601		     0, attach_space, attach_address, attach_size, me);
602
603  /* Extract the desired flash command set.  */
604  ret = hw_find_integer_array_property (me, "cmdset", 0, &ival);
605  if (ret != 1 && ret != 2)
606    hw_abort (me, "\"cmdset\" property takes 1 or 2 entries");
607  cfi_encode_16bit (cfi->query.p_id, ival);
608
609  for (i = 0; i < ARRAY_SIZE (cfi_cmdsets); ++i)
610    if (cfi_cmdsets[i]->id == ival)
611      cfi->cmdset = cfi_cmdsets[i];
612  if (cfi->cmdset == NULL)
613    hw_abort (me, "cmdset %u not supported", ival);
614
615  if (ret == 2)
616    {
617      hw_find_integer_array_property (me, "cmdset", 1, &ival);
618      cfi_encode_16bit (cfi->query.a_id, ival);
619    }
620
621  /* Extract the desired device size.  */
622  if (hw_find_property (me, "size"))
623    cfi->dev_size = hw_find_integer_property (me, "size");
624  else
625    cfi->dev_size = attach_size;
626  cfi->query.dev_size = log2 (cfi->dev_size);
627
628  /* Extract the desired flash width.  */
629  if (hw_find_property (me, "width"))
630    {
631      cfi->width = hw_find_integer_property (me, "width");
632      if (cfi->width != 8 && cfi->width != 16 && cfi->width != 32)
633	hw_abort (me, "\"width\" must be 8 or 16 or 32, not %u", cfi->width);
634    }
635  else
636    /* Default to 8 bit.  */
637    cfi->width = 8;
638  /* Turn 8/16/32 into 1/2/4.  */
639  cfi->width /= 8;
640
641  /* Extract optional write buffer size.  */
642  if (hw_find_property (me, "write_size"))
643    {
644      ival = hw_find_integer_property (me, "write_size");
645      cfi_encode_16bit (cfi->query.max_buf_write_len, log2 (ival));
646    }
647
648  /* Extract optional erase regions.  */
649  if (hw_find_property (me, "erase_regions"))
650    {
651      ret = hw_find_integer_array_property (me, "erase_regions", 0, &ival);
652      if (ret % 2)
653	hw_abort (me, "\"erase_regions\" must be specified in sets of 2");
654
655      cfi->erase_region_info = HW_NALLOC (me, unsigned char, ret / 2);
656      cfi->erase_regions = HW_NALLOC (me, struct cfi_erase_region, ret / 2);
657
658      for (i = 0; i < ret; i += 2)
659	{
660	  unsigned blocks, size;
661
662	  hw_find_integer_array_property (me, "erase_regions", i, &ival);
663	  blocks = ival;
664
665	  hw_find_integer_array_property (me, "erase_regions", i + 1, &ival);
666	  size = ival;
667
668	  cfi_add_erase_region (me, cfi, blocks, size);
669	}
670    }
671
672  /* Extract optional voltages.  */
673  if (hw_find_property (me, "voltage"))
674    {
675      unsigned num = ARRAY_SIZE (cfi->query.voltages);
676
677      ret = hw_find_integer_array_property (me, "voltage", 0, &ival);
678      if (ret > num)
679	hw_abort (me, "\"voltage\" may have only %u arguments", num);
680
681      for (i = 0; i < ret; ++i)
682	{
683	  hw_find_integer_array_property (me, "voltage", i, &ival);
684	  cfi->query.voltages[i] = ival;
685	}
686    }
687
688  /* Extract optional timeouts.  */
689  if (hw_find_property (me, "timeout"))
690    {
691      unsigned num = ARRAY_SIZE (cfi->query.timeouts);
692
693      ret = hw_find_integer_array_property (me, "timeout", 0, &ival);
694      if (ret > num)
695	hw_abort (me, "\"timeout\" may have only %u arguments", num);
696
697      for (i = 0; i < ret; ++i)
698	{
699	  hw_find_integer_array_property (me, "timeout", i, &ival);
700	  cfi->query.timeouts[i] = ival;
701	}
702    }
703
704  /* Extract optional file.  */
705  fd = -1;
706  fd_writable = false;
707  if (hw_find_property (me, "file"))
708    {
709      const char *file;
710
711      ret = hw_find_string_array_property (me, "file", 0, &file);
712      if (ret > 2)
713	hw_abort (me, "\"file\" may take only one argument");
714      if (ret == 2)
715	{
716	  const char *writable;
717
718	  hw_find_string_array_property (me, "file", 1, &writable);
719	  fd_writable = !strcmp (writable, "rw");
720	}
721
722      fd = open (file, fd_writable ? O_RDWR : O_RDONLY);
723      if (fd < 0)
724	hw_abort (me, "unable to read file `%s': %s", file, strerror (errno));
725    }
726
727  /* Figure out where our initial flash data is coming from.  */
728  if (fd != -1 && fd_writable)
729    {
730#if defined (HAVE_MMAP) && defined (HAVE_POSIX_FALLOCATE)
731      posix_fallocate (fd, 0, cfi->dev_size);
732
733      cfi->mmap = mmap (NULL, cfi->dev_size,
734			PROT_READ | (fd_writable ? PROT_WRITE : 0),
735			MAP_SHARED, fd, 0);
736
737      if (cfi->mmap == MAP_FAILED)
738	cfi->mmap = NULL;
739      else
740	cfi->data = cfi->mmap;
741#else
742      sim_io_eprintf (hw_system (me),
743		      "cfi: sorry, file write support requires mmap()\n");
744#endif
745    }
746  if (!cfi->data)
747    {
748      size_t read_len;
749
750      cfi->data = HW_NALLOC (me, unsigned char, cfi->dev_size);
751
752      if (fd != -1)
753	{
754	  /* Use stdio to avoid EINTR issues with read().  */
755	  FILE *fp = fdopen (fd, "r");
756
757	  if (fp)
758	    read_len = fread (cfi->data, 1, cfi->dev_size, fp);
759	  else
760	    read_len = 0;
761
762	  /* Don't need to fclose() with fdopen("r").  */
763	}
764      else
765	read_len = 0;
766
767      memset (cfi->data, 0xff, cfi->dev_size - read_len);
768    }
769
770  close (fd);
771}
772
773/* Once we've been declared in the device tree, this is the main
774   entry point. So allocate state, attach memory addresses, and
775   all that fun stuff.  */
776static void
777cfi_finish (struct hw *me)
778{
779  struct cfi *cfi;
780
781  cfi = HW_ZALLOC (me, struct cfi);
782
783  set_hw_data (me, cfi);
784  set_hw_io_read_buffer (me, cfi_io_read_buffer);
785  set_hw_io_write_buffer (me, cfi_io_write_buffer);
786  set_hw_delete (me, cfi_delete_callback);
787
788  attach_cfi_regs (me, cfi);
789
790  /* Initialize the CFI.  */
791  cfi->state = CFI_STATE_READ;
792  memcpy (cfi->query.qry, "QRY", 3);
793  cfi->cmdset->setup (me, cfi);
794}
795
796/* Every device is required to declare this.  */
797const struct hw_descriptor dv_cfi_descriptor[] =
798{
799  {"cfi", cfi_finish,},
800  {NULL, NULL},
801};
802