Reimplement all functions to access the system control unit in C.

The only reason we need to have the sb_load64() and sb_store64()
functions in assembly is to cheat the compiler and generate the
'ld' and 'sd' instructions which it otherwise will not do when
compiling for a 32-bit architecture. There are some 64-bit
registers in the SCD unit that must be accessed using 64-bit
load and store instructions.
This commit is contained in:
Neel Natu 2010-02-05 03:20:47 +00:00
parent c8f4860360
commit c3f7e882dc
4 changed files with 145 additions and 126 deletions

View File

@ -22,6 +22,8 @@
* 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.
*
* $FreeBSD$
*/
#include <machine/asm.h>
@ -41,115 +43,40 @@
.set noreorder
/*
* return (MIPS_PHYS_TO_KSEG1(0x10020008))
* Parameters: none
* Parameters: uint32_t ptr
* Return value: *(uint64_t *)ptr
*/
LEAF(sb_read_syscfg)
lui v0, 0xb002
ori v0, v0, 0x8
ld v1, 0(v0) /* syscfg = MIPS_PHYS_TO_KSEG1(0x10020008) */
LEAF(sb_load64)
ld v1, 0(a0) /* result = *(uint64_t *)ptr */
move v0, v1
#if defined(TARGET_BIG_ENDIAN)
dsll32 v1, v1, 0
dsrl32 v1, v1, 0 /* v1 = lower_uint32(result) */
jr ra
dsrl32 v0, v0, 0 /* v0 = upper_uint32(result) */
#else
dsll32 v0, v0, 0
dsrl32 v0, v0, 0 /* v0 = lower_uint32(mask) */
dsrl32 v0, v0, 0 /* v0 = lower_uint32(result) */
jr ra
dsrl32 v1, v1, 0 /* v1 = upper_uint32(mask) */
END(sb_read_syscfg)
dsrl32 v1, v1, 0 /* v1 = upper_uint32(result) */
#endif
END(sb_load64)
/*
* MIPS_PHYS_TO_KSEG1(0x10020008) = (uint64_t)val
* Parameters:
* - lower_uint32(val): a0
* - upper_uint32(val): a1
* Parameters: uint32_t ptr, uint64_t val
* Return value: void
*/
LEAF(sb_write_syscfg)
lui v0, 0xb002
ori v0, v0, 0x8
dsll32 a1, a1, 0 /* clear lower 32 bits of a1 */
dsll32 a0, a0, 0
dsrl32 a0, a0, 0 /* clear upper 32 bits of a0 */
or a1, a1, a0
sd a1, 0(v0) /* MIPS_PHYS_TO_KSEG1(0x10020008) = val */
LEAF(sb_store64)
#if defined(TARGET_BIG_ENDIAN)
dsll32 a2, a2, 0 /* a2 = upper_uint32(val) */
dsll32 a3, a3, 0 /* a3 = lower_uint32(val) */
dsrl32 a3, a3, 0
#else
dsll32 a3, a3, 0 /* a3 = upper_uint32(val) */
dsll32 a2, a2, 0 /* a2 = lower_uint32(val) */
dsrl32 a2, a2, 0
#endif
or t0, a2, a3
jr ra
nop
nop
END(sb_write_syscfg)
/*
* MIPS_PHYS_TO_KSEG1(0x10020028) |= (1 << intsrc)
*
* Parameters:
* - intsrc (a0)
*/
LEAF(sb_disable_intsrc)
lui v0, 0xb002
ori v0, v0, 0x28
ld v1, 0(v0) /* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
li a1, 1
dsllv a1, a1, a0
or a1, a1, v1 /* mask |= (1 << intsrc) */
jr ra
sd a1, 0(v0) /* MIPS_PHYS_TO_KSEG1(0x10020028) = mask */
END(sb_disable_intsrc)
/*
* MIPS_PHYS_TO_KSEG1(0x10020028) &= ~(1 << intsrc)
*
* Parameters:
* - intsrc (a0)
*/
LEAF(sb_enable_intsrc)
lui v0, 0xb002
ori v0, v0, 0x28
ld v1, 0(v0) /* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
li a2, 1
dsllv a2, a2, a0
nor a2, zero, a2
and a2, a2, v1 /* mask &= ~(1 << intsrc) */
sd a2, 0(v0) /* MIPS_PHYS_TO_KSEG1(0x10020028) = mask */
jr ra
nop
END(sb_enable_intsrc)
/*
* return ((uint64_t)MIPS_PHYS_TO_KSEG1(0x10020028))
* Parameters: none
*/
LEAF(sb_read_intsrc_mask)
lui v0, 0xb002
ori v0, v0, 0x28
ld v1, 0(v0) /* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
move v0, v1
dsll32 v0, v0, 0
dsrl32 v0, v0, 0 /* v0 = lower_uint32(mask) */
jr ra
dsrl32 v1, v1, 0 /* v1 = upper_uint32(mask) */
END(sb_read_intsrc_mask)
/*
* return ((uint64_t *)MIPS_PHYS_TO_KSEG1(0x10020200) + intsrc)
* Parameters:
* - intsrc (a0)
*/
LEAF(sb_read_intmap)
sll a0, a0, 3 /* compute the offset of the intmap register */
lui v0, 0xb002
addu a0, a0, v0
ld v0, 512(a0) /* v0 = MIPS_PHYS_TO_KSEG1(0x10020200) + off */
jr ra
nop
END(sb_read_intmap)
/*
* (uint64_t *)MIPS_PHYS_TO_KSEG1(0x10020200) + intsrc = irq
* Parameters:
* - intsrc (a0)
* - irq (a1)
*/
LEAF(sb_write_intmap)
sll a0, a0, 0x3 /* compute the offset of the intmap register */
lui v0, 0xb002
addu a0, a0, v0
sd a1, 512(a0) /* MIPS_PHYS_TO_KSEG1(0x10020200) + off = irq */
jr ra
nop
END(sb_write_intmap)
sd t0, 0(a0)
END(sb_store64)

View File

@ -23,6 +23,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@ -30,10 +34,12 @@
#include <sys/bus.h>
#include <machine/resource.h>
#include <machine/intr_machdep.h>
#include "sb_scd.h"
__FBSDID("$FreeBSD$");
extern void sb_store64(uint32_t addr, uint64_t val);
extern uint64_t sb_load64(uint32_t addr);
/*
* System Control and Debug (SCD) unit on the Sibyte ZBbus.
@ -44,8 +50,38 @@ __FBSDID("$FreeBSD$");
*/
#define GET_VAL_64(x, b, n) (((x) >> (b)) & ((1ULL << (n)) - 1))
#define SYSREV_ADDR MIPS_PHYS_TO_KSEG1(0x10020000)
#define SYSREV_NUM_PROCESSORS(x) GET_VAL_64((x), 24, 4)
#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008)
#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5)
#define INTSRC_MASK_ADDR(cpu) \
(MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13))
#define INTSRC_MAP_ADDR(cpu, intsrc) \
(MIPS_PHYS_TO_KSEG1(0x10020200) | ((cpu) << 13)) + (intsrc * 8)
#define MAILBOX_SET_ADDR(cpu) \
(MIPS_PHYS_TO_KSEG1(0x100200C8) | ((cpu) << 13))
#define MAILBOX_CLEAR_ADDR(cpu) \
(MIPS_PHYS_TO_KSEG1(0x100200D0) | ((cpu) << 13))
static uint64_t
sb_read_syscfg(void)
{
return (sb_load64(SYSCFG_ADDR));
}
static void
sb_write_syscfg(uint64_t val)
{
sb_store64(SYSCFG_ADDR, val);
}
uint64_t
sb_cpu_speed(void)
{
@ -76,6 +112,71 @@ sb_system_reset(void)
sb_write_syscfg(syscfg);
}
void
sb_disable_intsrc(int cpu, int src)
{
uint32_t regaddr;
uint64_t val;
regaddr = INTSRC_MASK_ADDR(cpu);
val = sb_load64(regaddr);
val |= 1ULL << src;
sb_store64(regaddr, val);
}
void
sb_enable_intsrc(int cpu, int src)
{
uint32_t regaddr;
uint64_t val;
regaddr = INTSRC_MASK_ADDR(cpu);
val = sb_load64(regaddr);
val &= ~(1ULL << src);
sb_store64(regaddr, val);
}
void
sb_write_intsrc_mask(int cpu, uint64_t val)
{
uint32_t regaddr;
regaddr = INTSRC_MASK_ADDR(cpu);
sb_store64(regaddr, val);
}
uint64_t
sb_read_intsrc_mask(int cpu)
{
uint32_t regaddr;
uint64_t val;
regaddr = INTSRC_MASK_ADDR(cpu);
val = sb_load64(regaddr);
return (val);
}
void
sb_write_intmap(int cpu, int intsrc, int intrnum)
{
uint32_t regaddr;
regaddr = INTSRC_MAP_ADDR(cpu, intsrc);
sb_store64(regaddr, intrnum);
}
int
sb_read_intmap(int cpu, int intsrc)
{
uint32_t regaddr;
regaddr = INTSRC_MAP_ADDR(cpu, intsrc);
return (sb_load64(regaddr) & 0x7);
}
int
sb_route_intsrc(int intsrc)
{
@ -86,16 +187,10 @@ sb_route_intsrc(int intsrc)
/*
* Interrupt 5 is used by sources internal to the CPU (e.g. timer).
* Use a deterministic mapping for the remaining sources to map to
* interrupt numbers 0 through 4.
* Use a deterministic mapping for the remaining sources.
*/
intrnum = intsrc % 5;
/*
* Program the interrupt mapper while we are here.
*/
sb_write_intmap(intsrc, intrnum);
return (intrnum);
}
@ -116,16 +211,14 @@ scd_attach(device_t dev)
int rid;
struct resource *res;
if (bootverbose) {
if (bootverbose)
device_printf(dev, "attached.\n");
}
rid = 0;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR,
SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0);
if (res == NULL) {
if (res == NULL)
panic("Cannot allocate resource for system control and debug.");
}
return (0);
}

View File

@ -22,6 +22,8 @@
* 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.
*
* $FreeBSD$
*/
#ifndef _SB_SCD_H_
@ -33,14 +35,11 @@ uint64_t sb_cpu_speed(void);
void sb_system_reset(void);
int sb_route_intsrc(int src);
void sb_enable_intsrc(int src);
void sb_disable_intsrc(int src);
uint64_t sb_read_intsrc_mask(void);
int sb_read_intmap(int intsrc);
void sb_write_intmap(int intsrc, int intrnum);
uint64_t sb_read_syscfg(void);
void sb_write_syscfg(uint64_t val);
void sb_enable_intsrc(int cpu, int src);
void sb_disable_intsrc(int cpu, int src);
uint64_t sb_read_intsrc_mask(int cpu);
void sb_write_intsrc_mask(int cpu, uint64_t mask);
void sb_write_intmap(int cpu, int intsrc, int intrnum);
int sb_read_intmap(int cpu, int intsrc);
#endif /* _SB_SCD_H_ */

View File

@ -118,7 +118,7 @@ sb_intmap_activate(int intrnum, device_t dev, int rid)
map = sb_intmap_lookup(intrnum, dev, rid);
if (map) {
sb_enable_intsrc(map->intsrc);
sb_enable_intsrc(0, map->intsrc);
} else {
/*
* In zbbus_setup_intr() we blindly call sb_intmap_activate()