Beispiel #1
0
static inline void xilinx_timer0_start_periodic(unsigned long load_val)
{
	if (!load_val)
		load_val = 1;
	/* loading value to timer reg */
	write_fn(load_val, timer_baseaddr + TLR0);

	/* load the initial value */
	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);

	/* see timer data sheet for detail
	 * !ENALL - don't enable 'em all
	 * !PWMA - disable pwm
	 * TINT - clear interrupt status
	 * ENT- enable timer itself
	 * ENIT - enable interrupt
	 * !LOAD - clear the bit to let go
	 * ARHT - auto reload
	 * !CAPT - no external trigger
	 * !GENT - no external signal
	 * UDT - set the timer as down counter
	 * !MDT0 - generate mode
	 */
	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
		 timer_baseaddr + TCSR0);
}
Beispiel #2
0
static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
{
	if (!load_val)
		load_val = 1;
	/* loading value to timer reg */
	write_fn(load_val, timer_baseaddr + TLR0);

	/* load the initial value */
	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);

	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
		 timer_baseaddr + TCSR0);
}
Beispiel #3
0
static int __init xilinx_clocksource_init(void)
{
	if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq))
		panic("failed to register clocksource");

	/* stop timer1 */
	write_fn(read_fn(timer_baseaddr + TCSR1) & ~TCSR_ENT,
		 timer_baseaddr + TCSR1);
	/* start timer1 - up counting without interrupt */
	write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, timer_baseaddr + TCSR1);

	/* register timecounter - for ftrace support */
	init_xilinx_timecounter();
	return 0;
}
Beispiel #4
0
void LK_VECTOR_Write(int fd, struct Vector* vec,void (*write_fn)(int fd, void* entry))
{
  Word i;
  Word size=LK_VECTOR_Size(vec);
  Word objSize;
  void* base;
  LK_FILE_PUT2(fd,size);
  if(size==0) return;
  base = LK_VECTOR_GetPtr(vec,0);
  objSize= vec->objSize;
  for(i=0;i<size;i++)
  {
    write_fn(fd,((u_int8_t *)base)+i*objSize);
  }
}
Beispiel #5
0
/*.......................................................................
 * Write a given number of spaces to the specified stdio output string.
 *
 * Input:
 *  write_fn  GlWriteFn *  The callback function to use to write the
 *                         output.
 *  data           void *  A pointer to arbitrary data to be passed to
 *                         write_fn() whenever it is called.
 *  c               int    The padding character.
 *  n               int    The number of spaces to be written.
 * Output:
 *  return          int    0 - OK.
 *                         1 - Error.
 */
static int _io_pad_line(GlWriteFn *write_fn, void *data, int c, int n)
{
  enum {FILL_SIZE=20};
  char fill[FILL_SIZE+1];
/*
 * Fill the buffer with the specified padding character.
 */
  memset(fill, c, FILL_SIZE);
  fill[FILL_SIZE] = '\0';
/*
 * Write the spaces using the above literal string of spaces as
 * many times as needed to output the requested number of spaces.
 */
  while(n > 0) {
    int nnew = n <= FILL_SIZE ? n : FILL_SIZE;
    if(write_fn(data, fill, nnew) != nnew)
      return 1;
    n -= nnew;
  };
  return 0;
}
Beispiel #6
0
static inline void xilinx_timer0_stop(void)
{
	write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT,
		 timer_baseaddr + TCSR0);
}
Beispiel #7
0
static int __init xilinx_timer_init(struct device_node *timer)
{
	struct clk *clk;
	static int initialized;
	u32 irq;
	u32 timer_num = 1;
	int ret;

	if (initialized)
		return -EINVAL;

	initialized = 1;

	timer_baseaddr = of_iomap(timer, 0);
	if (!timer_baseaddr) {
		pr_err("ERROR: invalid timer base address\n");
		return -ENXIO;
	}

	write_fn = timer_write32;
	read_fn = timer_read32;

	write_fn(TCSR_MDT, timer_baseaddr + TCSR0);
	if (!(read_fn(timer_baseaddr + TCSR0) & TCSR_MDT)) {
		write_fn = timer_write32_be;
		read_fn = timer_read32_be;
	}

	irq = irq_of_parse_and_map(timer, 0);
	if (irq <= 0) {
		pr_err("Failed to parse and map irq");
		return -EINVAL;
	}

	of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
	if (timer_num) {
		pr_err("Please enable two timers in HW\n");
		return -EINVAL;
	}

	pr_info("%pOF: irq=%d\n", timer, irq);

	clk = of_clk_get(timer, 0);
	if (IS_ERR(clk)) {
		pr_err("ERROR: timer CCF input clock not found\n");
		/* If there is clock-frequency property than use it */
		of_property_read_u32(timer, "clock-frequency",
				    &timer_clock_freq);
	} else {
		timer_clock_freq = clk_get_rate(clk);
	}

	if (!timer_clock_freq) {
		pr_err("ERROR: Using CPU clock frequency\n");
		timer_clock_freq = cpuinfo.cpu_clock_freq;
	}

	freq_div_hz = timer_clock_freq / HZ;

	ret = setup_irq(irq, &timer_irqaction);
	if (ret) {
		pr_err("Failed to setup IRQ");
		return ret;
	}

	ret = xilinx_clocksource_init();
	if (ret)
		return ret;

	ret = xilinx_clockevent_init();
	if (ret)
		return ret;

	sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);

	return 0;
}
Beispiel #8
0
static inline void timer_ack(void)
{
	write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0);
}
Beispiel #9
0
/*.......................................................................
 * Display a left-justified string over multiple terminal lines,
 * taking account of the specified width of the terminal. Optional
 * indentation and an option prefix string can be specified to be
 * displayed at the start of each new terminal line used, and if
 * needed, a single paragraph can be broken across multiple calls.
 * Note that literal newlines in the input string can be used to force
 * a newline at any point, and that in order to allow individual
 * paragraphs to be written using multiple calls to this function,
 * unless an explicit newline character is specified at the end of the
 * string, a newline will not be started at the end of the last word
 * in the string. Note that when a new line is started between two
 * words that are separated by spaces, those spaces are not output,
 * whereas when a new line is started because a newline character was
 * found in the string, only the spaces before the newline character
 * are discarded.
 *
 * Input:
 *  write_fn  GlWriteFn *  The callback function to use to write the
 *                         output.
 *  data           void *  A pointer to arbitrary data to be passed to
 *                         write_fn() whenever it is called.
 *  fp             FILE *  The stdio stream to write to.
 *  indentation     int    The number of fill characters to use to
 *                        indent the start of each new terminal line.
 *  prefix   const char *  An optional prefix string to write after the
 *                         indentation margin at the start of each new
 *                         terminal line. You can specify NULL if no
 *                         prefix is required.
 *  suffix   const char *  An optional suffix string to draw at the end
 *                         of the terminal line. The line will be padded
 *                         where necessary to ensure that the suffix ends
 *                         in the last column of the terminal line. If
 *                         no suffix is desired, specify NULL.
 *  fill_char       int    The padding character to use when indenting
 *                         and filling up to the suffix.
 *  term_width      int    The width of the terminal being written to.
 *  start           int    The number of characters already written to
 *                         the start of the current terminal line. This
 *                         is primarily used to allow individual
 *                         paragraphs to be written over multiple calls
 *                         to this function, but can also be used to
 *                         allow you to start the first line of a
 *                         paragraph with a different prefix or
 *                         indentation than those specified above.
 *  string   const char *  The string to be written.
 * Output:
 *  return          int    On error -1 is returned. Otherwise the
 *                         return value is the terminal column index at
 *                         which the cursor was left after writing the
 *                         final word in the string. Successful return
 *                         values can thus be passed verbatim to the
 *                         'start' arguments of subsequent calls to
 *                         _io_display_text() to allow the printing of a
 *                         paragraph to be broken across multiple calls
 *                         to _io_display_text().
 */
int _io_display_text(GlWriteFn *write_fn, void *data, int indentation,
		     const char *prefix, const char *suffix, int fill_char,
		     int term_width, int start, const char *string)
{
  int ndone;        /* The number of characters written from string[] */
  int nnew;         /* The number of characters to be displayed next */
  int was_space;    /* True if the previous character was a space or tab */
  int last = start; /* The column number of the last character written */
  int prefix_len;   /* The length of the optional line prefix string */
  int suffix_len;   /* The length of the optional line prefix string */
  int margin_width; /* The total number of columns used by the indentation */
                    /*  margin and the prefix string. */
  int i;
/*
 * Check the arguments?
 */
  if(!string || !write_fn) {
    errno = EINVAL;
    return -1;
  };
/*
 * Enforce sensible values on the arguments.
 */
  if(term_width < 0)
    term_width = 0;
  if(indentation > term_width)
    indentation = term_width;
  else if(indentation < 0)
    indentation = 0;
  if(start > term_width)
    start = term_width;
  else if(start < 0)
    start = 0;
/*
 * Get the length of the prefix string.
 */
  prefix_len = prefix ? strlen(prefix) : 0;
/*
 * Get the length of the suffix string.
 */
  suffix_len = suffix ? strlen(suffix) : 0;
/*
 * How many characters are devoted to indenting and prefixing each line?
 */
  margin_width = indentation + prefix_len;
/*
 * Write as many terminal lines as are needed to display the whole string.
 */
  for(ndone=0; string[ndone]; start=0) {
    last = start;
/*
 * Write spaces from the current position in the terminal line to the
 * width of the requested indentation margin.
 */
    if(indentation > 0 && last < indentation) {
      if(_io_pad_line(write_fn, data, fill_char, indentation - last))
	return -1;
      last = indentation;
    };
/*
 * If a prefix string has been specified, display it unless we have
 * passed where it should end in the terminal output line.
 */
    if(prefix_len > 0 && last < margin_width) {
      int pstart = last - indentation;
      int plen = prefix_len - pstart;
      if(write_fn(data, prefix+pstart, plen) != plen)
	return -1;
      last = margin_width;
    };
/*
 * Locate the end of the last complete word in the string before
 * (term_width - start) characters have been seen. To handle the case
 * where a single word is wider than the available space after the
 * indentation and prefix margins, always make sure that at least one
 * word is printed after the margin, regardless of whether it won't
 * fit on the line. The two exceptions to this rule are if an embedded
 * newline is found in the string or the end of the string is reached
 * before any word has been seen.
 */
    nnew = 0;
    was_space = 0;
    for(i=ndone; string[i] && (last+i-ndone < term_width - suffix_len ||
			   (nnew==0 && last==margin_width)); i++) {
      if(string[i] == '\n') {
	if(!was_space)
	  nnew = i-ndone;
	break;
      } else if(isspace((int) string[i])) {
	if(!was_space) {
	  nnew = i-ndone+1;
	  was_space = 1;
	};
      } else {
	was_space = 0;
      };
    };
/*
 * Does the end of the string delimit the last word that will fit on the
 * output line?
 */
    if(nnew==0 && string[i] == '\0')
      nnew = i-ndone;
/*
 * Write the new line.
 */
    if(write_fn(data, string+ndone, nnew) != nnew)
      return -1;
    ndone += nnew;
    last += nnew;
/*
 * Start a newline unless we have reached the end of the input string.
 * In the latter case, in order to give the caller the chance to
 * concatenate multiple calls to _io_display_text(), omit the newline,
 * leaving it up to the caller to write this.
 */
    if(string[ndone] != '\0') {
/*
 * If a suffix has been provided, pad out the end of the line with spaces
 * such that the suffix will end in the right-most terminal column.
 */
      if(suffix_len > 0) {
	int npad = term_width - suffix_len - last;
	if(npad > 0 && _io_pad_line(write_fn, data, fill_char, npad))
	  return -1;
	last += npad;
	if(write_fn(data, suffix, suffix_len) != suffix_len)
	  return -1;
	last += suffix_len;
      };
/*
 * Start a new line.
 */
      if(write_fn(data, "\n",  1) != 1)
	return -1;
/*
 * Skip any spaces and tabs that follow the last word that was written.
 */
      while(string[ndone] && isspace((int)string[ndone]) &&
	    string[ndone] != '\n')
	ndone++;
/*
 * If the terminating character was a literal newline character,
 * skip it in the input string, since we just wrote it.
 */
      if(string[ndone] == '\n')
	ndone++;
      last = 0;
    };
  };
/*
 * Return the column number of the last character printed.
 */
  return last;
}
Beispiel #10
0
static void __init xilinx_timer_init(struct device_node *timer)
{
	struct clk *clk;
	static int initialized;
	u32 irq;
	u32 timer_num = 1;

	if (initialized)
		return;

	initialized = 1;

	timer_baseaddr = of_iomap(timer, 0);
	if (!timer_baseaddr) {
		pr_err("ERROR: invalid timer base address\n");
		BUG();
	}

	write_fn = timer_write32;
	read_fn = timer_read32;

	write_fn(TCSR_MDT, timer_baseaddr + TCSR0);
	if (!(read_fn(timer_baseaddr + TCSR0) & TCSR_MDT)) {
		write_fn = timer_write32_be;
		read_fn = timer_read32_be;
	}

	irq = irq_of_parse_and_map(timer, 0);

	of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
	if (timer_num) {
		pr_emerg("Please enable two timers in HW\n");
		BUG();
	}

	pr_info("%s: irq=%d\n", timer->full_name, irq);

	clk = of_clk_get(timer, 0);
	if (IS_ERR(clk)) {
		pr_err("ERROR: timer CCF input clock not found\n");
		/* If there is clock-frequency property than use it */
		of_property_read_u32(timer, "clock-frequency",
				    &timer_clock_freq);
	} else {
		timer_clock_freq = clk_get_rate(clk);
	}

	if (!timer_clock_freq) {
		pr_err("ERROR: Using CPU clock frequency\n");
		timer_clock_freq = cpuinfo.cpu_clock_freq;
	}

	freq_div_hz = timer_clock_freq / HZ;

	setup_irq(irq, &timer_irqaction);
#ifdef CONFIG_HEART_BEAT
	microblaze_setup_heartbeat();
#endif
	xilinx_clocksource_init();
	xilinx_clockevent_init();

	sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);
}
Beispiel #11
0
/*.......................................................................
 * Write as many characters as possible from the start of a character
 * queue via a given output callback function, removing those written
 * from the queue.
 *
 * Input:
 *  cq        GlCharQueue *  The queue to write characters from.
 *  write_fn  GL_WRITE_FN *  The function to call to output characters,
 *                           or 0 to simply discard the contents of the
 *                           queue.
 *  data             void *  Anonymous data to pass to write_fn().
 * Output:
 *  return   GlFlushState    The status of the flush operation:
 *                             GLQ_FLUSH_DONE  -  The flush operation
 *                                                completed successfully.
 *                             GLQ_FLUSH_AGAIN -  The flush operation
 *                                                couldn't be completed
 *                                                on this call. Call this
 *                                                function again when the
 *                                                output channel can accept
 *                                                further output.
 *                             GLQ_FLUSH_ERROR    Unrecoverable error.
 */
GlqFlushState _glq_flush_queue(GlCharQueue *cq, GlWriteFn *write_fn,
			       void *data)
{
/*
 * Check the arguments.
 */
  if(!cq) {
    errno = EINVAL;
    return GLQ_FLUSH_ERROR;
  };
/*
 * If possible keep writing until all of the chained buffers have been
 * emptied and removed from the list.
 */
  while(cq->buffers.head) {
/*
 * Are we looking at the only node in the list?
 */
    int is_tail = cq->buffers.head == cq->buffers.tail;
/*
 * How many characters more than an exact multiple of the buffer-segment
 * size have been added to the buffer so far?
 */
    int nmodulo = cq->ntotal % GL_CQ_SIZE;
/*
 * How many characters of the buffer segment at the head of the list
 * have been used? Note that this includes any characters that have
 * already been flushed. Also note that if nmodulo==0, this means that
 * the tail buffer segment is full. The reason for this is that we
 * don't allocate new tail buffer segments until there is at least one
 * character to be added to them.
 */
    int nhead = (!is_tail || nmodulo == 0) ? GL_CQ_SIZE : nmodulo;
/*
 * How many characters remain to be flushed from the buffer
 * at the head of the list?
 */
    int nbuff = nhead - (cq->nflush % GL_CQ_SIZE);
/*
 * Attempt to write this number.
 */
    int nnew = write_fn(data, cq->buffers.head->bytes +
			cq->nflush % GL_CQ_SIZE, nbuff);
/*
 * Was anything written?
 */
    if(nnew > 0) {
/*
 * Increment the count of the number of characters that have
 * been flushed from the head of the queue.
 */
      cq->nflush += nnew;
/*
 * If we succeded in writing all of the contents of the current
 * buffer segment, remove it from the queue.
 */
      if(nnew == nbuff) {
/*
 * If we just emptied the last node left in the list, then the queue is
 * now empty and should be reset.
 */
	if(is_tail) {
	  _glq_empty_queue(cq);
	} else {
/*
 * Get the node to be removed from the head of the list.
 */
	  CqCharBuff *node = cq->buffers.head;
/*
 * Make the node that follows it the new head of the queue.
 */
	  cq->buffers.head = node->next;
/*
 * Return it to the freelist.
 */
	  node = (CqCharBuff *) _del_FreeListNode(cq->bufmem, node);
	};
      };
/*
 * If the write blocked, request that this function be called again
 * when space to write next becomes available.
 */
    } else if(nnew==0) {
      return GLQ_FLUSH_AGAIN;
/*
 * I/O error.
 */
    } else {
      _err_record_msg(cq->err, "Error writing to terminal", END_ERR_MSG);
      return GLQ_FLUSH_ERROR;
    };
  };
/*
 * To get here the queue must now be empty.
 */
  return GLQ_FLUSH_DONE;
}