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); }
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); }
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; }
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); } }
/*....................................................................... * 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; }
static inline void xilinx_timer0_stop(void) { write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT, timer_baseaddr + TCSR0); }
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; }
static inline void timer_ack(void) { write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0); }
/*....................................................................... * 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; }
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); }
/*....................................................................... * 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; }