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:
parent
c8f4860360
commit
c3f7e882dc
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user