Esempio n. 1
0
static void
cris_finish (struct hw *me)
{
  struct cris_hw *crishw;
  const struct hw_property *vec_for_int;
  const struct hw_property *multiple_int;

  crishw = HW_ZALLOC (me, struct cris_hw);
  set_hw_data (me, crishw);
  set_hw_ports (me, cris_ports);
  set_hw_port_event (me, cris_port_event);

  vec_for_int = hw_find_property (me, "vec-for-int");
  if (vec_for_int != NULL)
    {
      unsigned32 vecsize;
      unsigned32 i;

      if (hw_property_type (vec_for_int) != array_property)
	hw_abort (me, "property \"vec-for-int\" has the wrong type");

      vecsize = hw_property_sizeof_array (vec_for_int) / sizeof (signed_cell);

      if ((vecsize % 2) != 0)
	hw_abort (me, "translation vector does not consist of even pairs");

      crishw->int_to_vec
	= hw_malloc (me, (vecsize/2 + 1) * sizeof (crishw->int_to_vec[0]));

      for (i = 0; i < vecsize/2; i++)
	{
	  signed_cell portval_sc;
	  signed_cell vec_sc;

	  if (!hw_find_integer_array_property (me, "vec-for-int", i*2,
					       &portval_sc)
	      || !hw_find_integer_array_property (me, "vec-for-int", i*2 + 1,
						  &vec_sc)
	      || portval_sc < 0
	      || vec_sc < 0)
	    hw_abort (me, "no valid vector translation pair %u", i);

	  crishw->int_to_vec[i].portval = (unsigned32) portval_sc;
	  crishw->int_to_vec[i].vec = (unsigned32) vec_sc;
	}

      crishw->int_to_vec[i].portval = 0;
      crishw->int_to_vec[i].vec = 0;
    }

  multiple_int = hw_find_property (me, "multiple-int");
  if (multiple_int != NULL)
    {
      if (hw_property_type (multiple_int) == integer_property)
	{
	  crishw->multiple_int_vector
	    = hw_find_integer_property (me, "multiple-int");
	  crishw->multi_int_action = cris_multint_vector;
	}
      else
	{
	  const char *action = hw_find_string_property (me, "multiple-int");

	  if (action == NULL)
	    hw_abort (me, "property \"multiple-int\" has the wrong type");

	  if (strcmp (action, "abort") == 0)
	    crishw->multi_int_action = cris_multint_abort;
	  else if (strcmp (action, "ignore_previous") == 0)
	    crishw->multi_int_action = cris_multint_ignore_previous;
	  else
	    hw_abort (me, "property \"multiple-int\" must be one of <vector number>\n"
		      "\"abort\" and \"ignore_previous\", not \"%s\"", action);
	}
    }
  else
    crishw->multi_int_action = cris_multint_abort;
}
Esempio n. 2
0
/* Device tree options:
     Required:
       .../reg <addr> <len>
       .../cmdset <primary; integer> [alt; integer]
     Optional:
       .../size <device size (must be pow of 2)>
       .../width <8|16|32>
       .../write_size <integer (must be pow of 2)>
       .../erase_regions <number blocks> <block size> \
                         [<number blocks> <block size> ...]
       .../voltage <vcc min> <vcc max> <vpp min> <vpp max>
       .../timeouts <typ unit write>  <typ buf write>  \
                    <typ block erase> <typ chip erase> \
                    <max unit write>  <max buf write>  \
                    <max block erase> <max chip erase>
       .../file <file> [ro|rw]
     Defaults:
       size: <len> from "reg"
       width: 8
       write_size: 0 (not supported)
       erase_region: 1 (can only erase whole chip)
       voltage: 0.0V (for all)
       timeouts: typ: 1µs, not supported, 1ms, not supported
                 max: 1µs, 1ms, 1ms, not supported

  TODO: Verify user args are valid (e.g. voltage is 8 bits).  */
static void
attach_cfi_regs (struct hw *me, struct cfi *cfi)
{
  address_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;
  bool fd_writable;
  int i, ret, fd;
  signed_cell ival;

  if (hw_find_property (me, "reg") == NULL)
    hw_abort (me, "Missing \"reg\" property");
  if (hw_find_property (me, "cmdset") == NULL)
    hw_abort (me, "Missing \"cmdset\" property");

  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    hw_abort (me, "\"reg\" property must contain three addr/size entries");

  hw_unit_address_to_attach_address (hw_parent (me),
				     &reg.address,
				     &attach_space, &attach_address, me);
  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);

  hw_attach_address (hw_parent (me),
		     0, attach_space, attach_address, attach_size, me);

  /* Extract the desired flash command set.  */
  ret = hw_find_integer_array_property (me, "cmdset", 0, &ival);
  if (ret != 1 && ret != 2)
    hw_abort (me, "\"cmdset\" property takes 1 or 2 entries");
  cfi_encode_16bit (cfi->query.p_id, ival);

  for (i = 0; i < ARRAY_SIZE (cfi_cmdsets); ++i)
    if (cfi_cmdsets[i]->id == ival)
      cfi->cmdset = cfi_cmdsets[i];
  if (cfi->cmdset == NULL)
    hw_abort (me, "cmdset %u not supported", ival);

  if (ret == 2)
    {
      hw_find_integer_array_property (me, "cmdset", 1, &ival);
      cfi_encode_16bit (cfi->query.a_id, ival);
    }

  /* Extract the desired device size.  */
  if (hw_find_property (me, "size"))
    cfi->dev_size = hw_find_integer_property (me, "size");
  else
    cfi->dev_size = attach_size;
  cfi->query.dev_size = log2 (cfi->dev_size);

  /* Extract the desired flash width.  */
  if (hw_find_property (me, "width"))
    {
      cfi->width = hw_find_integer_property (me, "width");
      if (cfi->width != 8 && cfi->width != 16 && cfi->width != 32)
	hw_abort (me, "\"width\" must be 8 or 16 or 32, not %u", cfi->width);
    }
  else
    /* Default to 8 bit.  */
    cfi->width = 8;
  /* Turn 8/16/32 into 1/2/4.  */
  cfi->width /= 8;

  /* Extract optional write buffer size.  */
  if (hw_find_property (me, "write_size"))
    {
      ival = hw_find_integer_property (me, "write_size");
      cfi_encode_16bit (cfi->query.max_buf_write_len, log2 (ival));
    }

  /* Extract optional erase regions.  */
  if (hw_find_property (me, "erase_regions"))
    {
      ret = hw_find_integer_array_property (me, "erase_regions", 0, &ival);
      if (ret % 2)
	hw_abort (me, "\"erase_regions\" must be specified in sets of 2");

      cfi->erase_region_info = HW_NALLOC (me, unsigned char, ret / 2);
      cfi->erase_regions = HW_NALLOC (me, struct cfi_erase_region, ret / 2);

      for (i = 0; i < ret; i += 2)
	{
	  unsigned blocks, size;

	  hw_find_integer_array_property (me, "erase_regions", i, &ival);
	  blocks = ival;

	  hw_find_integer_array_property (me, "erase_regions", i + 1, &ival);
	  size = ival;

	  cfi_add_erase_region (me, cfi, blocks, size);
	}
    }