#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.2 2022/09/29 06:39:58 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/bus.h>
#include <sys/mutex.h>
#include <uvm/uvm.h>
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <hppa/hppa/machdep.h>
#include <hppa/dev/cpudevs.h>
#include <hppa/dev/viper.h>
struct l2_mioc {
uint32_t pad[0x20];
uint32_t mioc_control;
uint32_t mioc_status;
uint32_t pad1[6];
uint32_t sltcv;
#define SLTCV_AVWL 0x00002000
#define SLTCV_UP4COUT 0x00001000
#define SLTCV_EDCEN 0x08000000
#define SLTCV_EDTAG 0x10000000
#define SLTCV_CHKTP 0x20000000
#define SLTCV_LOWPWR 0x40000000
#define SLTCV_ENABLE 0x80000000
#define SLTCV_BITS "\020\15avwl\16up4cout\24edcen\25edtag\26chktp\27lowpwr\30l2ena"
uint32_t tagmask;
uint32_t diagtag;
uint32_t sltestat;
uint32_t slteadd;
uint32_t pad2[3];
uint32_t mtcv;
uint32_t ref;
uint32_t pad3[4];
uint32_t mderradd;
uint32_t pad4;
uint32_t dmaerr;
uint32_t dioerr;
uint32_t gsc_timeout;
uint32_t hidmamem;
uint32_t pad5[2];
uint32_t memcomp[16];
uint32_t memmask[16];
uint32_t memtest;
uint32_t pad6[0xf];
uint32_t outchk;
uint32_t pad7[0x168];
uint32_t gsc15x_config;
};
struct mem_softc {
device_t sc_dev;
volatile struct vi_trs *sc_vp;
volatile struct l2_mioc *sc_l2;
};
int memmatch(device_t, cfdata_t, void *);
void memattach(device_t, device_t, void *);
CFATTACH_DECL_NEW(mem, sizeof(struct mem_softc), memmatch, memattach,
NULL, NULL);
int
memmatch(device_t parent, cfdata_t cf, void *aux)
{
struct confargs *ca = aux;
if (ca->ca_type.iodc_type != HPPA_TYPE_MEMORY ||
ca->ca_type.iodc_sv_model != HPPA_MEMORY_PDEP)
return 0;
return 1;
}
void
memattach(device_t parent, device_t self, void *aux)
{
struct pdc_iodc_minit pdc_minit;
struct confargs *ca = aux;
struct mem_softc *sc = device_private(self);
int err, pagezero_cookie;
char bits[128];
sc->sc_dev = self;
aprint_normal(":");
pagezero_cookie = hppa_pagezero_map();
if (ca->ca_hpa == (hppa_hpa_t)VIPER_HPA) {
sc->sc_vp = (struct vi_trs *)
&((struct iomod *)ca->ca_hpa)->priv_trs;
if (sc->sc_vp->vi_status.hw_rev == 0) {
uint32_t vic;
int s, settimeout;
switch (cpu_modelno) {
case HPPA_BOARD_HP715_33:
case HPPA_BOARD_HP715S_33:
case HPPA_BOARD_HP715T_33:
case HPPA_BOARD_HP715_50:
case HPPA_BOARD_HP715S_50:
case HPPA_BOARD_HP715T_50:
case HPPA_BOARD_HP715_75:
case HPPA_BOARD_HP725_50:
case HPPA_BOARD_HP725_75:
settimeout = 1;
break;
default:
settimeout = 0;
break;
}
if (device_cfdata(self)->cf_flags & 1)
settimeout = !settimeout;
snprintb(bits, sizeof(bits), VIPER_BITS, VI_CTRL);
aprint_normal(" viper rev %x, ctrl %s",
sc->sc_vp->vi_status.hw_rev, bits);
s = splhigh();
vic = VI_CTRL;
((struct vi_ctrl *)&vic)->core_den = 0;
((struct vi_ctrl *)&vic)->sgc0_den = 0;
((struct vi_ctrl *)&vic)->sgc1_den = 0;
((struct vi_ctrl *)&vic)->eisa_den = 1;
((struct vi_ctrl *)&vic)->core_prf = 1;
if (settimeout &&
((struct vi_ctrl *)&vic)->vsc_tout == 0)
((struct vi_ctrl *)&vic)->vsc_tout = 850;
sc->sc_vp->vi_control = vic;
__asm __volatile("stwas %1, 0(%0)"
:: "r" (&VI_CTRL), "r" (vic) : "memory");
splx(s);
#ifdef DEBUG
snprintb(bits, sizeof(bits), VIPER_BITS, VI_CTRL);
printf (" >> %s", bits);
#endif
} else
sc->sc_vp = NULL;
} else
sc->sc_vp = NULL;
err = pdcproc_iodc_ninit(&pdc_minit, ca->ca_hpa, PAGE0->imm_spa_size);
if (err < 0)
pdc_minit.max_spa = PAGE0->imm_max_mem;
hppa_pagezero_unmap(pagezero_cookie);
aprint_normal(" size %d", pdc_minit.max_spa / (1024*1024));
if (pdc_minit.max_spa % (1024*1024))
aprint_normal(".%d", pdc_minit.max_spa % (1024*1024));
aprint_normal("MB");
if (hppa_cpu_info->hci_cputype == hpcxl2) {
sc->sc_l2 = (struct l2_mioc *)ca->ca_hpa;
#ifdef DEBUG
snprintb(bits, sizeof(bits), SLTCV_BITS, sc->sc_l2->sltcv);
printf(", sltcv %s", bits);
#endif
if (sc->sc_l2->sltcv & SLTCV_ENABLE) {
uint32_t tagmask = sc->sc_l2->tagmask >> 20;
aprint_normal(", %dMB L2 cache", tagmask + 1);
}
}
aprint_normal("\n");
}
void
viper_setintrwnd(uint32_t mask)
{
device_t dv;
struct mem_softc *sc;
dv = device_find_by_driver_unit("mem", 0);
sc = device_private(dv);
if (sc->sc_vp)
sc->sc_vp->vi_intrwd;
}
void
viper_eisa_en(void)
{
device_t dv;
struct mem_softc *sc;
dv = device_find_by_driver_unit("mem", 0);
sc = device_private(dv);
if (sc->sc_vp) {
int pagezero_cookie;
uint32_t vic;
int s;
pagezero_cookie = hppa_pagezero_map();
s = splhigh();
vic = VI_CTRL;
((struct vi_ctrl *)&vic)->eisa_den = 0;
sc->sc_vp->vi_control = vic;
__asm __volatile("stwas %1, 0(%0)"
:: "r" (&VI_CTRL), "r" (vic) : "memory");
splx(s);
hppa_pagezero_unmap(pagezero_cookie);
}
}