@@ -28,4 +28,8 @@
#define smp_wmb() wmb()
#endif
+#ifndef cpu_relax
+#define cpu_relax() asm volatile ("":::"memory")
+#endif
+
#endif /* _ASM_BARRIER_H_ */
@@ -1,6 +1,7 @@
#ifndef _ASMPOWERPC_PROCESSOR_H_
#define _ASMPOWERPC_PROCESSOR_H_
+#include <libcflat.h>
#include <asm/ptrace.h>
#ifndef __ASSEMBLY__
@@ -8,4 +9,22 @@ void handle_exception(int trap, void (*func)(struct pt_regs *, void *), void *);
void do_handle_exception(struct pt_regs *regs);
#endif /* __ASSEMBLY__ */
+static inline uint64_t get_tb(void)
+{
+ uint64_t tb;
+
+ asm volatile ("mfspr %[tb],268" : [tb] "=r" (tb));
+
+ return tb;
+}
+
+extern void delay(uint64_t cycles);
+extern void udelay(uint64_t us);
+
+static inline void mdelay(uint64_t ms)
+{
+ while (ms--)
+ udelay(1000);
+}
+
#endif /* _ASMPOWERPC_PROCESSOR_H_ */
@@ -11,6 +11,8 @@
extern u32 cpus[NR_CPUS];
extern int nr_cpus;
+extern uint64_t tb_hz;
+
#define NR_MEM_REGIONS 8
#define MR_F_PRIMARY (1U << 0)
struct mem_region {
@@ -5,6 +5,8 @@
#include <libcflat.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
+#include <asm/setup.h>
+#include <asm/barrier.h>
static struct {
void (*func)(struct pt_regs *, void *data);
@@ -36,3 +38,16 @@ void do_handle_exception(struct pt_regs *regs)
printf("unhandled cpu exception 0x%lx\n", regs->trap);
abort();
}
+
+void delay(uint64_t cycles)
+{
+ uint64_t start = get_tb();
+
+ while ((get_tb() - start) < cycles)
+ cpu_relax();
+}
+
+void udelay(uint64_t us)
+{
+ delay((us * tb_hz) / 1000000);
+}
@@ -24,6 +24,7 @@ extern void setup_args_progname(const char *args);
u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
int nr_cpus;
+uint64_t tb_hz;
struct mem_region mem_regions[NR_MEM_REGIONS];
phys_addr_t __physical_start, __physical_end;
@@ -32,6 +33,7 @@ unsigned __icache_bytes, __dcache_bytes;
struct cpu_set_params {
unsigned icache_bytes;
unsigned dcache_bytes;
+ uint64_t tb_hz;
};
#define EXCEPTION_STACK_SIZE (32*1024) /* 32kB */
@@ -72,6 +74,12 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
data = (u32 *)prop->data;
params->dcache_bytes = fdt32_to_cpu(*data);
+ prop = fdt_get_property(dt_fdt(), fdtnode,
+ "timebase-frequency", NULL);
+ assert(prop != NULL);
+ data = (u32 *)prop->data;
+ params->tb_hz = fdt32_to_cpu(*data);
+
read_common_info = true;
}
}
@@ -86,6 +94,7 @@ static void cpu_init(void)
assert(ret == 0);
__icache_bytes = params.icache_bytes;
__dcache_bytes = params.dcache_bytes;
+ tb_hz = params.tb_hz;
/* Interrupt Endianness */