#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/atomic.h>
#include <dev/ofw/fdt.h>
#include <dev/ofw/openfirm.h>
#include <machine/autoconf.h>
#include <machine/fdt.h>
#include <machine/intr.h>
#include <machine/octeonvar.h>
#include <machine/octeonreg.h>
#include <machine/octeon_model.h>
#include <octeon/dev/iobusvar.h>
#include <octeon/dev/octhcireg.h>
int iobusmatch(struct device *, void *, void *);
void iobusattach(struct device *, struct device *, void *);
int iobusprint(void *, const char *);
int iobussubmatch(struct device *, void *, void *);
int iobussearch(struct device *, void *, void *);
bus_addr_t iobus_pa_to_device(paddr_t);
paddr_t iobus_device_to_pa(bus_addr_t);
const struct cfattach iobus_ca = {
sizeof(struct device), iobusmatch, iobusattach
};
struct cfdriver iobus_cd = {
NULL, "iobus", DV_DULL
};
bus_space_t iobus_tag = {
.bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
.bus_private = NULL,
._space_read_1 = generic_space_read_1,
._space_write_1 = generic_space_write_1,
._space_read_2 = generic_space_read_2,
._space_write_2 = generic_space_write_2,
._space_read_4 = generic_space_read_4,
._space_write_4 = generic_space_write_4,
._space_read_8 = generic_space_read_8,
._space_write_8 = generic_space_write_8,
._space_read_raw_2 = generic_space_read_raw_2,
._space_write_raw_2 = generic_space_write_raw_2,
._space_read_raw_4 = generic_space_read_raw_4,
._space_write_raw_4 = generic_space_write_raw_4,
._space_read_raw_8 = generic_space_read_raw_8,
._space_write_raw_8 = generic_space_write_raw_8,
._space_map = iobus_space_map,
._space_unmap = iobus_space_unmap,
._space_subregion = generic_space_region,
._space_vaddr = generic_space_vaddr
};
struct machine_bus_dma_tag iobus_bus_dma_tag = {
NULL,
_dmamap_create,
_dmamap_destroy,
_dmamap_load,
_dmamap_load_mbuf,
_dmamap_load_uio,
_dmamap_load_raw,
_dmamap_load_buffer,
_dmamap_unload,
_dmamap_sync,
_dmamem_alloc,
_dmamem_free,
_dmamem_map,
_dmamem_unmap,
_dmamem_mmap,
iobus_pa_to_device,
iobus_device_to_pa,
0
};
static const struct octeon_iobus_addrs iobus_addrs[] = {
{ "octcf", OCTEON_CF_BASE },
{ "octrng", OCTEON_RNG_BASE },
{ "dwctwo", USBN_BASE },
{ "amdcf", OCTEON_AMDCF_BASE},
};
int iobus_found;
int
iobusmatch(struct device *parent, void *match, void *aux)
{
if (iobus_found)
return (0);
return (1);
}
int
iobusprint(void *aux, const char *iobus)
{
struct iobus_attach_args *aa = aux;
if (iobus != NULL)
printf("%s at %s", aa->aa_name, iobus);
if (aa->aa_addr != 0)
printf(" base 0x%lx", aa->aa_addr);
if (aa->aa_irq >= 0)
printf(" irq %d", aa->aa_irq);
return (UNCONF);
}
int
iobussubmatch(struct device *parent, void *vcf, void *args)
{
struct cfdata *cf = vcf;
struct iobus_attach_args *aa = args;
if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0)
return 0;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_addr)
return 0;
return (*cf->cf_attach->ca_match)(parent, cf, aa);
}
void
iobusattach(struct device *parent, struct device *self, void *aux)
{
struct iobus_attach_args aa;
struct fdt_attach_args fa;
struct octeon_config oc;
struct device *sc = self;
int soc;
iobus_found = 1;
printf("\n");
oc.mc_iobus_bust = &iobus_tag;
oc.mc_iobus_dmat = &iobus_bus_dma_tag;
void cn30xxfpa_bootstrap(struct octeon_config *);
cn30xxfpa_bootstrap(&oc);
void cn30xxpow_bootstrap(struct octeon_config *);
cn30xxpow_bootstrap(&oc);
if ((soc = OF_finddevice("/soc")) != -1) {
memset(&fa, 0, sizeof(fa));
fa.fa_name = "";
fa.fa_node = soc;
fa.fa_iot = &iobus_tag;
fa.fa_dmat = &iobus_bus_dma_tag;
config_found(self, &fa, NULL);
}
config_search(iobussearch, self, sc);
if (octeon_ver == OCTEON_2 || octeon_ver == OCTEON_3) {
memset(&aa, 0, sizeof(aa));
aa.aa_name = "octpcie";
aa.aa_bust = &iobus_tag;
aa.aa_dmat = &iobus_bus_dma_tag;
aa.aa_irq = -1;
config_found_sm(self, &aa, iobusprint, iobussubmatch);
}
}
int
iobussearch(struct device *parent, void *v, void *aux)
{
struct iobus_attach_args aa;
struct cfdata *cf = v;
int i;
aa.aa_name = cf->cf_driver->cd_name;
aa.aa_bust = &iobus_tag;
aa.aa_dmat = &iobus_bus_dma_tag;
aa.aa_addr = cf->cf_loc[0];
aa.aa_irq = cf->cf_loc[1];
aa.aa_unitno = cf->cf_unit;
if (aa.aa_addr == -1) {
for (i = 0; i < nitems(iobus_addrs); i++) {
if (strcmp(iobus_addrs[i].name, cf->cf_driver->cd_name) == 0)
aa.aa_addr = iobus_addrs[i].address;
}
if (aa.aa_addr == -1)
return 0;
}
if (cf->cf_attach->ca_match(parent, cf, &aa) == 0)
return 0;
config_attach(parent, cf, &aa, iobusprint);
return 1;
}
int
iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
int flags, bus_space_handle_t *bshp)
{
if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) {
*bshp = PHYS_TO_CKSEG0(offs);
return 0;
}
if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE))
offs +=
PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC);
*bshp = t->bus_base + offs;
return 0;
}
void
iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
}
bus_addr_t
iobus_pa_to_device(paddr_t pa)
{
return (bus_addr_t)pa;
}
paddr_t
iobus_device_to_pa(bus_addr_t addr)
{
return (paddr_t)addr;
}