leon.h 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
/*
 * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com) Gaisler Research
 * Copyright (C) 2004 Stefan Holst (mail@s-holst.de) Uni-Stuttgart
 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
 */

#ifndef LEON_H_INCLUDE
#define LEON_H_INCLUDE

#ifdef CONFIG_SPARC_LEON

/* mmu register access, ASI_LEON_MMUREGS */
#define LEON_CNR_CTRL		0x000
#define LEON_CNR_CTXP		0x100
#define LEON_CNR_CTX		0x200
#define LEON_CNR_F		0x300
#define LEON_CNR_FADDR		0x400

#define LEON_CNR_CTX_NCTX	256	/*number of MMU ctx */

#define LEON_CNR_CTRL_TLBDIS	0x80000000

#define LEON_MMUTLB_ENT_MAX	64

/*
 * diagnostic access from mmutlb.vhd:
 * 0: pte address
 * 4: pte
 * 8: additional flags
 */
#define LEON_DIAGF_LVL		0x3
#define LEON_DIAGF_WR		0x8
#define LEON_DIAGF_WR_SHIFT	3
#define LEON_DIAGF_HIT		0x10
#define LEON_DIAGF_HIT_SHIFT	4
#define LEON_DIAGF_CTX		0x1fe0
#define LEON_DIAGF_CTX_SHIFT	5
#define LEON_DIAGF_VALID	0x2000
#define LEON_DIAGF_VALID_SHIFT	13

/* irq masks */
#define LEON_HARD_INT(x)	(1 << (x))	/* irq 0-15 */
#define LEON_IRQMASK_R		0x0000fffe	/* bit 15- 1 of lregs.irqmask */
#define LEON_IRQPRIO_R		0xfffe0000	/* bit 31-17 of lregs.irqmask */

/* leon uart register definitions */
#define LEON_OFF_UDATA	0x0
#define LEON_OFF_USTAT	0x4
#define LEON_OFF_UCTRL	0x8
#define LEON_OFF_USCAL	0xc

#define LEON_UCTRL_RE	0x01
#define LEON_UCTRL_TE	0x02
#define LEON_UCTRL_RI	0x04
#define LEON_UCTRL_TI	0x08
#define LEON_UCTRL_PS	0x10
#define LEON_UCTRL_PE	0x20
#define LEON_UCTRL_FL	0x40
#define LEON_UCTRL_LB	0x80

#define LEON_USTAT_DR	0x01
#define LEON_USTAT_TS	0x02
#define LEON_USTAT_TH	0x04
#define LEON_USTAT_BR	0x08
#define LEON_USTAT_OV	0x10
#define LEON_USTAT_PE	0x20
#define LEON_USTAT_FE	0x40

#define LEON_MCFG2_SRAMDIS		0x00002000
#define LEON_MCFG2_SDRAMEN		0x00004000
#define LEON_MCFG2_SRAMBANKSZ		0x00001e00	/* [12-9] */
#define LEON_MCFG2_SRAMBANKSZ_SHIFT	9
#define LEON_MCFG2_SDRAMBANKSZ		0x03800000	/* [25-23] */
#define LEON_MCFG2_SDRAMBANKSZ_SHIFT	23

#define LEON_TCNT0_MASK	0x7fffff

#define LEON_USTAT_ERROR (LEON_USTAT_OV | LEON_USTAT_PE | LEON_USTAT_FE)
/* no break yet */

#define ASI_LEON3_SYSCTRL		0x02
#define ASI_LEON3_SYSCTRL_ICFG		0x08
#define ASI_LEON3_SYSCTRL_DCFG		0x0c
#define ASI_LEON3_SYSCTRL_CFG_SNOOPING (1 << 27)
#define ASI_LEON3_SYSCTRL_CFG_SSIZE(c) (1 << ((c >> 20) & 0xf))

#ifndef __ASSEMBLY__

/* do a virtual address read without cache */
static inline unsigned long leon_readnobuffer_reg(unsigned long paddr)
{
	unsigned long retval;
	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
			     "=r"(retval) : "r"(paddr), "i"(ASI_LEON_NOCACHE));
	return retval;
}

/* do a physical address bypass write, i.e. for 0x80000000 */
static inline void leon_store_reg(unsigned long paddr, unsigned long value)
{
	__asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r"(value), "r"(paddr),
			     "i"(ASI_LEON_BYPASS) : "memory");
}

/* do a physical address bypass load, i.e. for 0x80000000 */
static inline unsigned long leon_load_reg(unsigned long paddr)
{
	unsigned long retval;
	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
			     "=r"(retval) : "r"(paddr), "i"(ASI_LEON_BYPASS));
	return retval;
}

115
static inline void leon_srmmu_disabletlb(void)
116 117 118 119 120 121 122 123 124
{
	unsigned int retval;
	__asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
			     "i"(ASI_LEON_MMUREGS));
	retval |= LEON_CNR_CTRL_TLBDIS;
	__asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
			     "i"(ASI_LEON_MMUREGS) : "memory");
}

125
static inline void leon_srmmu_enabletlb(void)
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
{
	unsigned int retval;
	__asm__ __volatile__("lda [%%g0] %2, %0\n\t" : "=r"(retval) : "r"(0),
			     "i"(ASI_LEON_MMUREGS));
	retval = retval & ~LEON_CNR_CTRL_TLBDIS;
	__asm__ __volatile__("sta %0, [%%g0] %2\n\t" : : "r"(retval), "r"(0),
			     "i"(ASI_LEON_MMUREGS) : "memory");
}

/* macro access for leon_load_reg() and leon_store_reg() */
#define LEON3_BYPASS_LOAD_PA(x)	    (leon_load_reg((unsigned long)(x)))
#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
#define LEON3_BYPASS_ANDIN_PA(x, v) LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) & v)
#define LEON3_BYPASS_ORIN_PA(x, v)  LEON3_BYPASS_STORE_PA(x, LEON3_BYPASS_LOAD_PA(x) | v)
#define LEON_BYPASS_LOAD_PA(x)      leon_load_reg((unsigned long)(x))
#define LEON_BYPASS_STORE_PA(x, v)  leon_store_reg((unsigned long)(x), (unsigned long)(v))
#define LEON_REGLOAD_PA(x)          leon_load_reg((unsigned long)(x)+LEON_PREGS)
#define LEON_REGSTORE_PA(x, v)      leon_store_reg((unsigned long)(x)+LEON_PREGS, (unsigned long)(v))
#define LEON_REGSTORE_OR_PA(x, v)   LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) | (unsigned long)(v))
#define LEON_REGSTORE_AND_PA(x, v)  LEON_REGSTORE_PA(x, LEON_REGLOAD_PA(x) & (unsigned long)(v))

/* macro access for leon_readnobuffer_reg() */
#define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x))

extern void leon_init(void);
extern void leon_switch_mm(void);
extern void leon_init_IRQ(void);

extern unsigned long last_valid_pfn;

156
static inline unsigned long sparc_leon3_get_dcachecfg(void)
157 158 159 160 161 162 163 164 165 166
{
	unsigned int retval;
	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
			     "=r"(retval) :
			     "r"(ASI_LEON3_SYSCTRL_DCFG),
			     "i"(ASI_LEON3_SYSCTRL));
	return retval;
}

/* enable snooping */
167
static inline void sparc_leon3_enable_snooping(void)
168 169 170 171 172 173 174
{
	__asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
			  "set 0x800000, %%l2\n\t"
			  "or  %%l2, %%l1, %%l2\n\t"
			  "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
};

175 176 177 178 179 180 181 182
static inline int sparc_leon3_snooping_enabled(void)
{
	u32 cctrl;
	__asm__ __volatile__("lda [%%g0] 2, %0\n\t" : "=r"(cctrl));
        return (cctrl >> 23) & 1;
};

static inline void sparc_leon3_disable_cache(void)
183 184 185 186 187 188 189
{
	__asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
			  "set 0x00000f, %%l2\n\t"
			  "andn  %%l2, %%l1, %%l2\n\t"
			  "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
};

190 191 192 193 194 195 196 197 198 199 200 201
static inline unsigned long sparc_leon3_asr17(void)
{
	u32 asr17;
	__asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
	return asr17;
};

static inline int sparc_leon3_cpuid(void)
{
	return sparc_leon3_asr17() >> 28;
}

202 203 204
#endif /*!__ASSEMBLY__*/

#ifdef CONFIG_SMP
205
# define LEON3_IRQ_IPI_DEFAULT		13
206
# define LEON3_IRQ_TICKER		(leon3_ticker_irq)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
# define LEON3_IRQ_CROSS_CALL		15
#endif

#if defined(PAGE_SIZE_LEON_8K)
#define LEON_PAGE_SIZE_LEON 1
#elif defined(PAGE_SIZE_LEON_16K)
#define LEON_PAGE_SIZE_LEON 2)
#else
#define LEON_PAGE_SIZE_LEON 0
#endif

#if LEON_PAGE_SIZE_LEON == 0
/* [ 8, 6, 6 ] + 12 */
#define LEON_PGD_SH    24
#define LEON_PGD_M     0xff
#define LEON_PMD_SH    18
#define LEON_PMD_SH_V  (LEON_PGD_SH-2)
#define LEON_PMD_M     0x3f
#define LEON_PTE_SH    12
#define LEON_PTE_M     0x3f
#elif LEON_PAGE_SIZE_LEON == 1
/* [ 7, 6, 6 ] + 13 */
#define LEON_PGD_SH    25
#define LEON_PGD_M     0x7f
#define LEON_PMD_SH    19
#define LEON_PMD_SH_V  (LEON_PGD_SH-1)
#define LEON_PMD_M     0x3f
#define LEON_PTE_SH    13
#define LEON_PTE_M     0x3f
#elif LEON_PAGE_SIZE_LEON == 2
/* [ 6, 6, 6 ] + 14 */
#define LEON_PGD_SH    26
#define LEON_PGD_M     0x3f
#define LEON_PMD_SH    20
#define LEON_PMD_SH_V  (LEON_PGD_SH-0)
#define LEON_PMD_M     0x3f
#define LEON_PTE_SH    14
#define LEON_PTE_M     0x3f
#elif LEON_PAGE_SIZE_LEON == 3
/* [ 4, 7, 6 ] + 15 */
#define LEON_PGD_SH    28
#define LEON_PGD_M     0x0f
#define LEON_PMD_SH    21
#define LEON_PMD_SH_V  (LEON_PGD_SH-0)
#define LEON_PMD_M     0x7f
#define LEON_PTE_SH    15
#define LEON_PTE_M     0x3f
#else
#error cannot determine LEON_PAGE_SIZE_LEON
#endif

#define PAGE_MIN_SHIFT   (12)
#define PAGE_MIN_SIZE    (1UL << PAGE_MIN_SHIFT)

#define LEON3_XCCR_SETS_MASK  0x07000000UL
#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL

#define LEON2_CCR_DSETS_MASK 0x03000000UL
#define LEON2_CFG_SSIZE_MASK 0x00007000UL

#ifndef __ASSEMBLY__
extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
extern void leon_flush_icache_all(void);
extern void leon_flush_dcache_all(void);
extern void leon_flush_cache_all(void);
extern void leon_flush_tlb_all(void);
extern int leon_flush_during_switch;
extern int leon_flush_needed(void);

struct vm_area_struct;
extern void leon_flush_icache_all(void);
extern void leon_flush_dcache_all(void);
extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
extern void leon_flush_cache_all(void);
extern void leon_flush_tlb_all(void);
extern int leon_flush_during_switch;
extern int leon_flush_needed(void);
extern void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);

/* struct that hold LEON3 cache configuration registers */
struct leon3_cacheregs {
	unsigned long ccr;	/* 0x00 - Cache Control Register  */
	unsigned long iccr;     /* 0x08 - Instruction Cache Configuration Register */
	unsigned long dccr;	/* 0x0c - Data Cache Configuration Register */
};

/* struct that hold LEON2 cache configuration register
 * & configuration register
 */
struct leon2_cacheregs {
	unsigned long ccr, cfg;
};

#ifdef __KERNEL__

#include <linux/interrupt.h>

struct device_node;
305 306 307
extern unsigned int leon_build_device_irq(unsigned int real_irq,
					   irq_flow_handler_t flow_handler,
					   const char *name, int do_ack);
308 309 310
extern void leon_update_virq_handling(unsigned int virq,
			      irq_flow_handler_t flow_handler,
			      const char *name, int do_ack);
311
extern void leon_init_timers(void);
312 313 314 315 316 317 318 319 320 321 322
extern void leon_trans_init(struct device_node *dp);
extern void leon_node_init(struct device_node *dp, struct device_node ***nextp);
extern void leon_init_IRQ(void);
extern void leon_init(void);
extern unsigned long srmmu_swprobe(unsigned long vaddr, unsigned long *paddr);
extern void init_leon(void);
extern void poke_leonsparc(void);
extern void leon3_getCacheRegs(struct leon3_cacheregs *regs);
extern int leon_flush_needed(void);
extern void leon_switch_mm(void);
extern int srmmu_swprobe_trace;
323
extern int leon3_ticker_irq;
324

K
Konrad Eisele 已提交
325 326 327 328 329 330 331 332 333 334 335 336
#ifdef CONFIG_SMP
extern int leon_smp_nrcpus(void);
extern void leon_clear_profile_irq(int cpu);
extern void leon_smp_done(void);
extern void leon_boot_cpus(void);
extern int leon_boot_one_cpu(int i);
void leon_init_smp(void);
extern void cpu_idle(void);
extern void init_IRQ(void);
extern void cpu_panic(void);
extern int __leon_processor_id(void);
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
337
extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
K
Konrad Eisele 已提交
338

339
extern unsigned int real_irq_entry[];
340
extern unsigned int smpleon_ipi[];
K
Konrad Eisele 已提交
341 342 343
extern unsigned int patchme_maybe_smp_msg[];
extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
extern unsigned int linux_trap_ipi15_sun4m[];
344
extern int leon_ipi_irq;
K
Konrad Eisele 已提交
345 346 347

#endif /* CONFIG_SMP */

348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
#endif /* __KERNEL__ */

#endif /* __ASSEMBLY__ */

/* macros used in leon_mm.c */
#define PFN(x)           ((x) >> PAGE_SHIFT)
#define _pfn_valid(pfn)	 ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
#define _SRMMU_PTE_PMASK_LEON 0xffffffff

#else /* defined(CONFIG_SPARC_LEON) */

/* nop definitions for !LEON case */
#define leon_init() do {} while (0)
#define leon_switch_mm() do {} while (0)
#define leon_init_IRQ() do {} while (0)
#define init_leon() do {} while (0)
K
Konrad Eisele 已提交
364 365 366 367
#define leon_smp_done() do {} while (0)
#define leon_boot_cpus() do {} while (0)
#define leon_boot_one_cpu(i) 1
#define leon_init_smp() do {} while (0)
368 369 370 371

#endif /* !defined(CONFIG_SPARC_LEON) */

#endif