[BACK]Return to cpu.h CVS log [TXT][DIR] Up to [local] / sys / arch / powerpc / include

File: [local] / sys / arch / powerpc / include / cpu.h (download)

Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:07:47 2008 UTC (16 years, 3 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD
Changes since 1.1: +0 -0 lines

Import of OpenBSD 4.2 release kernel tree with initial code to support 
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO

Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)

/*	$OpenBSD: cpu.h,v 1.31 2007/03/23 21:06:05 miod Exp $	*/
/*	$NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $	*/

/*
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef	_POWERPC_CPU_H_
#define	_POWERPC_CPU_H_

#include <machine/frame.h>

#include <sys/device.h>
#include <sys/lock.h>
#include <sys/sched.h>

struct cpu_info {
	struct device *ci_dev;		/* our device */
	struct schedstate_percpu ci_schedstate; /* scheduler state */

	struct proc *ci_curproc;

	struct pcb *ci_curpcb;
	struct pmap *ci_curpm;
	struct proc *ci_fpuproc;
	struct proc *ci_vecproc;
	struct pcb *ci_idle_pcb;	/* PA of our idle pcb */
	int ci_cpuid;

	volatile int ci_astpending;
	volatile int ci_want_resched;
	volatile int ci_cpl;
	volatile int ci_iactive;
	volatile int ci_ipending;
	int ci_intrdepth;
	char *ci_intstk;
#define CPUSAVE_LEN	8
	register_t ci_tempsave[CPUSAVE_LEN];
	register_t ci_ddbsave[CPUSAVE_LEN];
#define DISISAVE_LEN	4
	register_t ci_disisave[DISISAVE_LEN];
};

static __inline struct cpu_info *
curcpu(void)
{
	struct cpu_info *ci;

	__asm volatile ("mfsprg %0,0" : "=r"(ci));
	return ci;
}

#define	curpcb			(curcpu()->ci_curpcb)
#define	curpm			(curcpu()->ci_curpm)

#define CPU_INFO_UNIT(ci)	((ci)->ci_dev->dv_unit)

#ifdef MULTIPROCESSOR

#define PPC_MAXPROCS		4

static __inline int
cpu_number(void)
{
	int pir;

	__asm ("mfspr %0,1023" : "=r"(pir));
	return pir;
}

void	cpu_boot_secondary_processors(void);

#define CPU_IS_PRIMARY(ci)	((ci)->ci_cpuid == 0)
#define CPU_INFO_ITERATOR		int
#define CPU_INFO_FOREACH(cii, ci)					\
	for (cii = 0, ci = &cpu_info[0]; cii < PPC_MAXPROCS; cii++, ci++)

#else

#define PPC_MAXPROCS		1

#define cpu_number()		0

#define CPU_IS_PRIMARY(ci)	1
#define CPU_INFO_ITERATOR		int
#define CPU_INFO_FOREACH(cii, ci)					\
	for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL)

#endif

extern struct cpu_info cpu_info[PPC_MAXPROCS];

#define	CLKF_USERMODE(frame)	(((frame)->srr1 & PSL_PR) != 0)
#define	CLKF_PC(frame)		((frame)->srr0)
#define	CLKF_INTR(frame)	((frame)->depth != 0)

/*
 * This is used during profiling to integrate system time.
 */
#define	PROC_PC(p)		(trapframe(p)->srr0)

#define	cpu_wait(p)		do { /* nothing */ } while (0)

void	delay(unsigned);
#define	DELAY(n)		delay(n)

#define	need_resched(ci)	(ci->ci_want_resched = 1, ci->ci_astpending = 1)
#define	need_proftick(p)	do { curcpu()->ci_astpending = 1; } while (0)
#define	signotify(p)		(curcpu()->ci_astpending = 1)

extern char *bootpath;

#ifndef	CACHELINESIZE
#define	CACHELINESIZE	32			/* For now		XXX */
#endif

static __inline void
syncicache(void *from, int len)
{
	int l;
	char *p = from;

	len = len + (((u_int32_t) from) & (CACHELINESIZE - 1));
	l = len;

	do {
		__asm __volatile ("dcbst 0,%0" :: "r"(p));
		p += CACHELINESIZE;
	} while ((l -= CACHELINESIZE) > 0);
	__asm __volatile ("sync");
	p = from;
	l = len;
	do {
		__asm __volatile ("icbi 0,%0" :: "r"(p));
		p += CACHELINESIZE;
	} while ((l -= CACHELINESIZE) > 0);
	__asm __volatile ("isync");
}

static __inline void
invdcache(void *from, int len)
{
	int l;
	char *p = from;

	len = len + (((u_int32_t) from) & (CACHELINESIZE - 1));
	l = len;

	do {
		__asm __volatile ("dcbi 0,%0" :: "r"(p));
		p += CACHELINESIZE;
	} while ((l -= CACHELINESIZE) > 0);
	__asm __volatile ("sync");
}

#define FUNC_SPR(n, name) \
static __inline u_int32_t ppc_mf ## name (void)			\
{								\
	u_int32_t ret;						\
	__asm __volatile ("mfspr %0," # n : "=r" (ret));	\
	return ret;						\
}								\
static __inline void ppc_mt ## name (u_int32_t val)		\
{								\
	__asm __volatile ("mtspr "# n ",%0" :: "r" (val));	\
}								\

FUNC_SPR(0, mq)
FUNC_SPR(1, xer)
FUNC_SPR(4, rtcu)
FUNC_SPR(5, rtcl)
FUNC_SPR(8, lr)
FUNC_SPR(9, ctr)
FUNC_SPR(18, dsisr)
FUNC_SPR(19, dar)
FUNC_SPR(22, dec)
FUNC_SPR(25, sdr1)
FUNC_SPR(26, srr0)
FUNC_SPR(27, srr1)
FUNC_SPR(256, vrsave)
FUNC_SPR(272, sprg0)
FUNC_SPR(273, sprg1)
FUNC_SPR(274, sprg2)
FUNC_SPR(275, sprg3)
FUNC_SPR(280, asr)
FUNC_SPR(282, ear)
FUNC_SPR(287, pvr)
FUNC_SPR(528, ibat0u)
FUNC_SPR(529, ibat0l)
FUNC_SPR(530, ibat1u)
FUNC_SPR(531, ibat1l)
FUNC_SPR(532, ibat2u)
FUNC_SPR(533, ibat2l)
FUNC_SPR(534, ibat3u)
FUNC_SPR(535, ibat3l)
FUNC_SPR(536, dbat0u)
FUNC_SPR(537, dbat0l)
FUNC_SPR(538, dbat1u)
FUNC_SPR(539, dbat1l)
FUNC_SPR(540, dbat2u)
FUNC_SPR(541, dbat2l)
FUNC_SPR(542, dbat3u)
FUNC_SPR(543, dbat3l)
FUNC_SPR(1008, hid0)
FUNC_SPR(1009, hid1)
FUNC_SPR(1010, iabr)
FUNC_SPR(1017, l2cr)
FUNC_SPR(1018, l3cr)
FUNC_SPR(1013, dabr)
FUNC_SPR(1023, pir)

static __inline u_int32_t
ppc_mftbl (void)
{
	int ret;
	__asm __volatile ("mftb %0" : "=r" (ret));
	return ret;
}

static __inline u_int64_t
ppc_mftb(void)
{
	u_long scratch;
	u_int64_t tb;

	__asm __volatile ("1: mftbu %0; mftb %0+1; mftbu %1;"
	    " cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch));
	return tb;
}

static __inline u_int32_t
ppc_mfmsr (void)
{
	int ret;
        __asm __volatile ("mfmsr %0" : "=r" (ret));
	return ret;
}

static __inline void
ppc_mtmsr (u_int32_t val)
{
        __asm __volatile ("mtmsr %0" :: "r" (val));
}

static __inline void
ppc_mtsrin(u_int32_t val, u_int32_t sn_shifted)
{
	__asm __volatile ("mtsrin %0,%1" :: "r"(val), "r"(sn_shifted));
}

u_int64_t ppc64_mfscomc(void);
void ppc_mtscomc(u_int32_t);
void ppc64_mtscomc(u_int64_t);
u_int64_t ppc64_mfscomd(void);
void ppc_mtscomd(u_int32_t);

#include <machine/psl.h>

/*
 * General functions to enable and disable interrupts
 * without having inlined assembly code in many functions.
 */
static __inline void
ppc_intr_enable(int enable)
{
	u_int32_t msr;
	if (enable != 0) {
		msr = ppc_mfmsr();
		msr |= PSL_EE;
		ppc_mtmsr(msr);
	}
}

static __inline int
ppc_intr_disable(void)
{
	u_int32_t emsr, dmsr;
	emsr = ppc_mfmsr();
	dmsr = emsr & ~PSL_EE;
	ppc_mtmsr(dmsr);
	return (emsr & PSL_EE);
}

int ppc_cpuspeed(int *);
void ppc_check_procid(void);
extern int ppc_proc_is_64b;

/*
 * PowerPC CPU types
 */
#define	PPC_CPU_MPC601		1
#define	PPC_CPU_MPC603		3
#define	PPC_CPU_MPC604		4
#define	PPC_CPU_MPC603e		6
#define	PPC_CPU_MPC603ev	7
#define	PPC_CPU_MPC750		8
#define	PPC_CPU_MPC604ev	9
#define	PPC_CPU_MPC7400		12
#define	PPC_CPU_IBM970FX	0x003c
#define	PPC_CPU_IBM970MP	0x0044
#define	PPC_CPU_IBM750FX	0x7000
#define	PPC_CPU_MPC7410		0x800c
#define	PPC_CPU_MPC7447A	0x8003
#define	PPC_CPU_MPC7448		0x8004
#define	PPC_CPU_MPC7450		0x8000
#define	PPC_CPU_MPC7455		0x8001
#define	PPC_CPU_MPC7457		0x8002

/*
 * This needs to be included late since it relies on definitions higher
 * up in this file.
 */
#if defined(MULTIPROCESSOR) && defined(_KERNEL)
#include <sys/mplock.h>
#endif

#endif	/* _POWERPC_CPU_H_ */