Ejemplo n.º 1
0
void
do_hw_attach_regs (struct hw *hw)
{
  static const char *(reg_property_names[]) = {
    "attach-addresses",
    "assigned-addresses",
    "reg",
    "alternate-reg" ,
    NULL
  };
  const char **reg_property_name;
  int nr_valid_reg_properties = 0;
  for (reg_property_name = reg_property_names;
       *reg_property_name != NULL;
       reg_property_name++)
    {
      if (hw_find_property (hw, *reg_property_name) != NULL)
	{
	  reg_property_spec reg;
	  int reg_entry;
	  for (reg_entry = 0;
	       hw_find_reg_array_property (hw, *reg_property_name, reg_entry,
					   &reg);
	       reg_entry++)
	    {
	      unsigned_word attach_address;
	      int attach_space;
	      unsigned attach_size;
	      if (!hw_unit_address_to_attach_address (hw_parent (hw),
						      &reg.address,
						      &attach_space,
						      &attach_address,
						      hw))
		continue;
	      if (!hw_unit_size_to_attach_size (hw_parent (hw),
						&reg.size,
						&attach_size, hw))
		continue;
	      hw_attach_address (hw_parent (hw),
				 0,
				 attach_space, attach_address, attach_size,
				 hw);
	      nr_valid_reg_properties++;
	    }
	  /* if first option matches don't try for any others */
	  if (reg_property_name == reg_property_names)
	    break;
	}
    }
}
static void
attach_m68hc11eepr_regs (struct hw *me,
                         struct m68hc11eepr *controller)
{
  unsigned_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;

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

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

  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);

  /* Attach the two IO registers that control the EEPROM.
     The EEPROM is only attached at reset time because it may
     be enabled/disabled by the EEON bit in the CONFIG register.  */
  hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
                     io_map, M6811_PPROG, 1, me);
  hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
                     io_map, M6811_CONFIG, 1, me);

  if (hw_find_property (me, "file") == NULL)
    controller->file_name = "m6811.eeprom";
  else
    controller->file_name = hw_find_string_property (me, "file");
  
  controller->attach_space = attach_space;
  controller->base_address = attach_address;
  controller->eeprom = (char*) hw_malloc (me, attach_size + 1);
  controller->eeprom_min_cycles = 10000;
  controller->size = attach_size + 1;
  controller->mapped = 0;
  
  m6811eepr_memory_rw (controller, O_RDONLY);
}
static void
attach_tx3904sio_regs (struct hw *me,
		      struct tx3904sio *controller)
{
  unsigned_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;

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

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

  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);

  if(hw_find_property(me, "backend") != NULL)
    {
      const char* value = hw_find_string_property(me, "backend");
      if(! strcmp(value, "tcp"))
	controller->backend = sio_tcp;
      else if(! strcmp(value, "stdio"))
	controller->backend = sio_stdio;
      else
	hw_abort(me, "illegal value for backend parameter `%s': use tcp or stdio", value);
    }

  controller->base_address = attach_address;
}
Ejemplo n.º 4
0
static void
attach_tx3904tmr_regs (struct hw *me,
		      struct tx3904tmr *controller)
{
  unsigned_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;

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

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

  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);

  if(hw_find_property(me, "clock") != NULL)
    controller->clock_ticks = (unsigned_4) hw_find_integer_property(me, "clock");

  if(hw_find_property(me, "ext") != NULL)
    controller->ext_ticks = (unsigned_4) hw_find_integer_property(me, "ext");

  controller->base_address = attach_address;
}
static void
attach_nvram_regs (struct hw *me, struct nvram *controller)
{
  unsigned_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;
  int result, oerrno;

  /* Get ram bank description (base and size).  */
  if (hw_find_property (me, "reg") == NULL)
    hw_abort (me, "Missing \"reg\" property");

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

  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);

  controller->mode         = NVRAM_SAVE_ALL;
  controller->base_address = attach_address;
  controller->size         = attach_size;
  controller->fd           = -1;
  
  /* Get the file where the ram content must be loaded/saved.  */
  if(hw_find_property (me, "file") == NULL)
    hw_abort (me, "Missing \"file\" property");
  
  controller->file_name = hw_find_string_property (me, "file");

  /* Get the mode which defines how to save the memory.  */
  if(hw_find_property (me, "mode") != NULL)
    {
      const char *value = hw_find_string_property (me, "mode");

      if (strcmp (value, "map") == 0)
        controller->mode = NVRAM_MAP_FILE;
      else if (strcmp (value, "save-modified") == 0)
        controller->mode = NVRAM_SAVE_MODIFIED;
      else if (strcmp (value, "save-all") == 0)
        controller->mode = NVRAM_SAVE_ALL;
      else
	hw_abort (me, "illegal value for mode parameter `%s': "
                  "use map, save-modified or save-all", value);
    }

  /* Initialize the ram by loading/mapping the file in memory.
     If the file does not exist, create and give it some content.  */
  switch (controller->mode)
    {
    case NVRAM_MAP_FILE:
      hw_abort (me, "'map' mode is not yet implemented, use 'save-modified'");
      break;

    case NVRAM_SAVE_MODIFIED:
    case NVRAM_SAVE_ALL:
      controller->data = (char*) hw_malloc (me, attach_size);
      if (controller->data == 0)
        hw_abort (me, "Not enough memory, try to use the mode 'map'");

      memset (controller->data, 0, attach_size);
      controller->fd = open (controller->file_name, O_RDWR);
      if (controller->fd < 0)
        {
          controller->fd = open (controller->file_name,
                                 O_RDWR | O_CREAT, 0644);
          if (controller->fd < 0)
            hw_abort (me, "Cannot open or create file '%s'",
                      controller->file_name);
          result = write (controller->fd, controller->data, attach_size);
          if (result != attach_size)
            {
              oerrno = errno;
              hw_free (me, controller->data);
              close (controller->fd);
              errno = oerrno;
              hw_abort (me, "Failed to save the ram content");
            }
        }
      else
        {
          result = read (controller->fd, controller->data, attach_size);
          if (result != attach_size)
            {
              oerrno = errno;
              hw_free (me, controller->data);
              close (controller->fd);
              errno = oerrno;
              hw_abort (me, "Failed to load the ram content");
            }
        }
      if (controller->mode == NVRAM_SAVE_ALL)
        {
          close (controller->fd);
          controller->fd = -1;
        }
      break;

    default:
      break;
    }
}
Ejemplo n.º 6
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);
	}
    }