[ar531x] add initial port for the AR231x/531x series of SoCs.

These are older MIPS4kc parts from Atheros.  They typically ran at
sub-200MHz and have 11bg, 11a, or 11abg wifi MAC/PHYs integrated.

This port is the initial non-wifi pieces required to bring up the
chip.  I'll commit the redboot and other pieces later, and then
hopefully(!) wifi support will follow.

Submitted by:   Mori Hiroki <yamori813@yahoo.co.jp>
Differential Revision:  https://reviews.freebsd.org/D7237
This commit is contained in:
Adrian Chadd 2016-10-04 16:27:36 +00:00
parent 5420f76b59
commit 7c12b677f5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306675
22 changed files with 5926 additions and 0 deletions

View file

@ -0,0 +1,756 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include "opt_platform.h"
#include "opt_ar531x.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <machine/bus.h>
#ifdef INTRNG
#include <machine/intr.h>
#else
#include <machine/intr_machdep.h>
#endif
#ifdef INTRNG
#include "pic_if.h"
#define PIC_INTR_ISRC(sc, irq) (&(sc)->pic_irqs[(irq)].isrc)
#endif
#include <mips/atheros/ar531x/apbvar.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#ifdef AR531X_APB_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif /* AR531X_APB_DEBUG */
static int apb_activate_resource(device_t, device_t, int, int,
struct resource *);
static device_t apb_add_child(device_t, u_int, const char *, int);
static struct resource *
apb_alloc_resource(device_t, device_t, int, int *, rman_res_t,
rman_res_t, rman_res_t, u_int);
static int apb_attach(device_t);
static int apb_deactivate_resource(device_t, device_t, int, int,
struct resource *);
static struct resource_list *
apb_get_resource_list(device_t, device_t);
static void apb_hinted_child(device_t, const char *, int);
static int apb_filter(void *);
static int apb_probe(device_t);
static int apb_release_resource(device_t, device_t, int, int,
struct resource *);
#ifndef INTRNG
static int apb_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int apb_teardown_intr(device_t, device_t, struct resource *,
void *);
#endif
static void
apb_mask_irq(void *source)
{
unsigned int irq = (unsigned int)source;
uint32_t reg;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5315_SYSREG_BASE
+ AR5315_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5312_SYSREG_BASE
+ AR5312_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
}
}
static void
apb_unmask_irq(void *source)
{
uint32_t reg;
unsigned int irq = (unsigned int)source;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTMASK, reg | (1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK);
ATH_WRITE_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTMASK, reg | (1 << irq));
}
}
#ifdef INTRNG
static int
apb_pic_register_isrcs(struct apb_softc *sc)
{
int error;
uint32_t irq;
struct intr_irqsrc *isrc;
const char *name;
name = device_get_nameunit(sc->apb_dev);
for (irq = 0; irq < APB_NIRQS; irq++) {
sc->pic_irqs[irq].irq = irq;
isrc = PIC_INTR_ISRC(sc, irq);
error = intr_isrc_register(isrc, sc->apb_dev, 0, "%s", name);
if (error != 0) {
/* XXX call intr_isrc_deregister */
device_printf(sc->apb_dev, "%s failed", __func__);
return (error);
}
}
return (0);
}
static inline intptr_t
pic_xref(device_t dev)
{
return (0);
}
#endif
static int
apb_probe(device_t dev)
{
#ifdef INTRNG
device_set_desc(dev, "APB Bus bridge INTRNG");
#else
device_set_desc(dev, "APB Bus bridge");
#endif
return (0);
}
static int
apb_attach(device_t dev)
{
struct apb_softc *sc = device_get_softc(dev);
#ifdef INTRNG
intptr_t xref = pic_xref(dev);
int miscirq;
#else
int rid = 0;
#endif
sc->apb_dev = dev;
sc->apb_mem_rman.rm_type = RMAN_ARRAY;
sc->apb_mem_rman.rm_descr = "APB memory window";
if(ar531x_soc >= AR531X_SOC_AR5315) {
if (rman_init(&sc->apb_mem_rman) != 0 ||
rman_manage_region(&sc->apb_mem_rman,
AR5315_APB_BASE,
AR5315_APB_BASE + AR5315_APB_SIZE - 1) != 0)
panic("apb_attach: failed to set up memory rman");
} else {
if (rman_init(&sc->apb_mem_rman) != 0 ||
rman_manage_region(&sc->apb_mem_rman,
AR5312_APB_BASE,
AR5312_APB_BASE + AR5312_APB_SIZE - 1) != 0)
panic("apb_attach: failed to set up memory rman");
}
sc->apb_irq_rman.rm_type = RMAN_ARRAY;
sc->apb_irq_rman.rm_descr = "APB IRQ";
if (rman_init(&sc->apb_irq_rman) != 0 ||
rman_manage_region(&sc->apb_irq_rman,
APB_IRQ_BASE, APB_IRQ_END) != 0)
panic("apb_attach: failed to set up IRQ rman");
#ifndef INTRNG
if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC,
apb_filter, NULL, sc, &sc->sc_misc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
#else
/* Register the interrupts */
if (apb_pic_register_isrcs(sc) != 0) {
device_printf(dev, "could not register PIC ISRCs\n");
return (ENXIO);
}
/*
* Now, when everything is initialized, it's right time to
* register interrupt controller to interrupt framefork.
*/
if (intr_pic_register(dev, xref) == NULL) {
device_printf(dev, "could not register PIC\n");
return (ENXIO);
}
if(ar531x_soc >= AR531X_SOC_AR5315) {
miscirq = AR5315_CPU_IRQ_MISC;
} else {
miscirq = AR5312_IRQ_MISC;
}
cpu_establish_hardintr("aric", apb_filter, NULL, sc, miscirq,
INTR_TYPE_MISC, NULL);
#endif
/* mask all misc interrupt */
if(ar531x_soc >= AR531X_SOC_AR5315) {
ATH_WRITE_REG(AR5315_SYSREG_BASE
+ AR5315_SYSREG_MISC_INTMASK, 0);
} else {
ATH_WRITE_REG(AR5312_SYSREG_BASE
+ AR5312_SYSREG_MISC_INTMASK, 0);
}
bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
return (0);
}
static struct resource *
apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct apb_softc *sc = device_get_softc(bus);
struct apb_ivar *ivar = device_get_ivars(child);
struct resource *rv;
struct resource_list_entry *rle;
struct rman *rm;
int isdefault, needactivate, passthrough;
isdefault = (RMAN_IS_DEFAULT_RANGE(start, end));
needactivate = flags & RF_ACTIVE;
/*
* Pass memory requests to nexus device
*/
passthrough = (device_get_parent(child) != bus);
rle = NULL;
dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
__func__, bus, child, type, *rid, (void *)(intptr_t)start,
(void *)(intptr_t)end, count, flags);
if (passthrough)
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
rid, start, end, count, flags));
/*
* If this is an allocation of the "default" range for a given RID,
* and we know what the resources for this device are (ie. they aren't
* maintained by a child bus), then work out the start/end values.
*/
if (isdefault) {
rle = resource_list_find(&ivar->resources, type, *rid);
if (rle == NULL) {
return (NULL);
}
if (rle->res != NULL) {
panic("%s: resource entry is busy", __func__);
}
start = rle->start;
end = rle->end;
count = rle->count;
dprintf("%s: default resource (%p, %p, %jd)\n",
__func__, (void *)(intptr_t)start,
(void *)(intptr_t)end, count);
}
switch (type) {
case SYS_RES_IRQ:
rm = &sc->apb_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->apb_mem_rman;
break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0) {
printf("%s: could not reserve resource %d\n", __func__, type);
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
printf("%s: could not activate resource\n", __func__);
rman_release_resource(rv);
return (0);
}
}
return (rv);
}
static int
apb_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/* XXX: should we mask/unmask IRQ here? */
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
type, rid, r));
}
static int
apb_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = apb_get_resource_list(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
apb_setup_intr(device_t bus, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct apb_softc *sc = device_get_softc(bus);
int error;
int irq;
#ifndef INTRNG
struct intr_event *event;
#endif
#ifdef INTRNG
struct intr_irqsrc *isrc;
const char *name;
if ((rman_get_flags(ires) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
irq = rman_get_start(ires);
isrc = PIC_INTR_ISRC(sc, irq);
if(isrc->isrc_event == 0) {
error = intr_event_create(&isrc->isrc_event, (void *)irq,
0, irq, apb_mask_irq, apb_unmask_irq,
NULL, NULL, "apb intr%d:", irq);
if(error != 0)
return(error);
}
name = device_get_nameunit(child);
error = intr_event_add_handler(isrc->isrc_event, name, filt, handler,
arg, intr_priority(flags), flags, cookiep);
return(error);
#else
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
apb_mask_irq, apb_unmask_irq,
NULL, NULL,
"apb intr%d:", irq);
if (error == 0) {
sc->sc_eventstab[irq] = event;
sc->sc_intr_counter[irq] =
mips_intrcnt_create(event->ie_name);
}
else
return (error);
}
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
apb_unmask_irq((void*)irq);
return (0);
#endif
}
#ifndef INTRNG
static int
apb_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
#ifdef INTRNG
return (intr_teardown_irq(child, ires, cookie));
#else
struct apb_softc *sc = device_get_softc(dev);
int irq, result;
irq = rman_get_start(ires);
if (irq > APB_IRQ_END)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
apb_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result)
sc->sc_eventstab[irq] = NULL;
return (result);
#endif
}
static int
apb_filter(void *arg)
{
struct apb_softc *sc = arg;
struct intr_event *event;
uint32_t reg, irq;
if(ar531x_soc >= AR531X_SOC_AR5315)
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
else
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
for (irq = 0; irq < APB_NIRQS; irq++) {
if (reg & (1 << irq)) {
if(ar531x_soc >= AR531X_SOC_AR5315) {
ATH_WRITE_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
} else {
ATH_WRITE_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
}
event = sc->sc_eventstab[irq];
if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) {
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBDMAE);
}
/* Ignore non handle interrupts */
if (irq != 0 && irq != 6)
printf("Stray APB IRQ %d\n", irq);
continue;
}
intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
mips_intrcnt_inc(sc->sc_intr_counter[irq]);
}
}
return (FILTER_HANDLED);
}
#else
static int
apb_filter(void *arg)
{
struct apb_softc *sc = arg;
struct thread *td;
uint32_t i, intr;
td = curthread;
/* Workaround: do not inflate intr nesting level */
td->td_intr_nesting_level--;
if(ar531x_soc >= AR531X_SOC_AR5315)
intr = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
else
intr = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
while ((i = fls(intr)) != 0) {
i--;
intr &= ~(1u << i);
if(i == 1 && ar531x_soc < AR531X_SOC_AR5315) {
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_AHBDMAE);
}
if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i),
curthread->td_intr_frame) != 0) {
device_printf(sc->apb_dev,
"Stray interrupt %u detected\n", i);
apb_mask_irq((void*)i);
continue;
}
}
KASSERT(i == 0, ("all interrupts handled"));
td->td_intr_nesting_level++;
return (FILTER_HANDLED);
}
#endif
static void
apb_hinted_child(device_t bus, const char *dname, int dunit)
{
device_t child;
long maddr;
int msize;
int irq;
int result;
int mem_hints_count;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
/*
* Set hard-wired resources for hinted child using
* specific RIDs.
*/
mem_hints_count = 0;
if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
mem_hints_count++;
if (resource_int_value(dname, dunit, "msize", &msize) == 0)
mem_hints_count++;
/* check if all info for mem resource has been provided */
if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
printf("Either maddr or msize hint is missing for %s%d\n",
dname, dunit);
} else if (mem_hints_count) {
result = bus_set_resource(child, SYS_RES_MEMORY, 0,
maddr, msize);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
}
static device_t
apb_add_child(device_t bus, u_int order, const char *name, int unit)
{
device_t child;
struct apb_ivar *ivar;
ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
if (ivar == NULL) {
printf("Failed to allocate ivar\n");
return (0);
}
resource_list_init(&ivar->resources);
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL) {
printf("Can't add child %s%d ordered\n", name, unit);
return (0);
}
device_set_ivars(child, ivar);
return (child);
}
/*
* Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
* Provides pointer to resource_list for these routines
*/
static struct resource_list *
apb_get_resource_list(device_t dev, device_t child)
{
struct apb_ivar *ivar;
ivar = device_get_ivars(child);
return (&(ivar->resources));
}
#ifdef INTRNG
static void
apb_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
apb_unmask_irq((void*)irq);
}
static void
apb_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
apb_mask_irq((void*)irq);
}
static void
apb_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
apb_pic_disable_intr(dev, isrc);
}
static void
apb_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
apb_pic_enable_intr(dev, isrc);
}
static void
apb_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
uint32_t reg, irq;
irq = ((struct apb_pic_irqsrc *)isrc)->irq;
if(ar531x_soc >= AR531X_SOC_AR5315) {
reg = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_MISC_INTSTAT);
ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
} else {
reg = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_MISC_INTSTAT);
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT,
reg & ~(1 << irq));
}
}
static int
apb_pic_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
return (ENOTSUP);
}
#endif
static device_method_t apb_methods[] = {
DEVMETHOD(bus_activate_resource, apb_activate_resource),
DEVMETHOD(bus_add_child, apb_add_child),
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
DEVMETHOD(bus_deactivate_resource, apb_deactivate_resource),
DEVMETHOD(bus_get_resource_list, apb_get_resource_list),
DEVMETHOD(bus_hinted_child, apb_hinted_child),
DEVMETHOD(bus_release_resource, apb_release_resource),
DEVMETHOD(device_attach, apb_attach),
DEVMETHOD(device_probe, apb_probe),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
#ifdef INTRNG
DEVMETHOD(pic_disable_intr, apb_pic_disable_intr),
DEVMETHOD(pic_enable_intr, apb_pic_enable_intr),
DEVMETHOD(pic_map_intr, apb_pic_map_intr),
DEVMETHOD(pic_post_filter, apb_pic_post_filter),
DEVMETHOD(pic_post_ithread, apb_pic_post_ithread),
DEVMETHOD(pic_pre_ithread, apb_pic_pre_ithread),
// DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
#else
DEVMETHOD(bus_teardown_intr, apb_teardown_intr),
#endif
DEVMETHOD(bus_setup_intr, apb_setup_intr),
DEVMETHOD_END
};
static driver_t apb_driver = {
"apb",
apb_methods,
sizeof(struct apb_softc),
};
static devclass_t apb_devclass;
EARLY_DRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

View file

@ -0,0 +1,63 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*
* $FreeBSD$
*/
#ifndef _APBVAR_H_
#define _APBVAR_H_
#define APB_IRQ_BASE 0
#define APB_IRQ_END 31
#define APB_NIRQS 32
struct apb_pic_irqsrc {
struct intr_irqsrc isrc;
u_int irq;
};
struct apb_softc {
device_t apb_dev;
struct rman apb_irq_rman;
struct rman apb_mem_rman;
/* IRQ events structs for child devices */
struct intr_event *sc_eventstab[APB_NIRQS];
#ifndef INTRNG
mips_intrcnt_t sc_intr_counter[APB_NIRQS];
#endif
/* Resources and cookies for MIPS CPU INTs */
struct resource *sc_misc_irq;
void *sc_misc_ih;
#ifdef INTRNG
struct apb_pic_irqsrc pic_irqs[APB_NIRQS];
#endif
};
struct apb_ivar {
struct resource_list resources;
};
#endif /* _APBVAR_H_ */

View file

@ -0,0 +1,209 @@
/*-
* Copyright (c) 2016 Hiroki Mori
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
static void
ar5312_chip_detect_mem_size(void)
{
uint32_t memsize;
uint32_t memcfg, bank0, bank1;
/*
* Determine the memory size as established by system
* firmware.
*
* NB: we allow compile time override
*/
memcfg = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG1);
bank0 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK0);
bank1 = __SHIFTOUT(memcfg, AR5312_MEM_CFG1_BANK1);
memsize = (bank0 ? (1 << (bank0 + 1)) : 0) +
(bank1 ? (1 << (bank1 + 1)) : 0);
memsize <<= 20;
realmem = memsize;
}
static void
ar5312_chip_detect_sys_frequency(void)
{
uint32_t predivisor;
uint32_t multiplier;
const uint32_t clockctl = ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_CLOCKCTL);
if(ar531x_soc == AR531X_SOC_AR5313) {
predivisor = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_PREDIVIDE);
multiplier = __SHIFTOUT(clockctl, AR2313_CLOCKCTL_MULTIPLIER);
} else {
predivisor = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_PREDIVIDE);
multiplier = __SHIFTOUT(clockctl, AR5312_CLOCKCTL_MULTIPLIER);
}
const uint32_t divisor = (0x5421 >> (predivisor * 4)) & 15;
const uint32_t cpufreq = (40000000 / divisor) * multiplier;
u_ar531x_cpu_freq = cpufreq;
u_ar531x_ahb_freq = cpufreq / 4;
u_ar531x_ddr_freq = 0;
}
/*
* This does not lock the CPU whilst doing the work!
*/
static void
ar5312_chip_device_reset(void)
{
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_RESETCTL,
AR5312_RESET_SYSTEM);
}
static void
ar5312_chip_device_start(void)
{
uint32_t cfg0, cfg1;
uint32_t bank0, bank1;
uint32_t size0, size1;
cfg0 = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG0);
cfg1 = ATH_READ_REG(AR5312_SDRAMCTL_BASE + AR5312_SDRAMCTL_MEM_CFG1);
bank0 = __SHIFTOUT(cfg1, AR5312_MEM_CFG1_BANK0);
bank1 = __SHIFTOUT(cfg1, AR5312_MEM_CFG1_BANK1);
size0 = bank0 ? (1 << (bank0 + 1)) : 0;
size1 = bank1 ? (1 << (bank1 + 1)) : 0;
size0 <<= 20;
size1 <<= 20;
printf("SDRMCTL %x %x %x %x\n", cfg0, cfg1, size0, size1);
ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBPERR);
ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBDMAE);
// ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_WDOG_CTL, 0);
ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_ENABLE, 0);
ATH_WRITE_REG(AR5312_SYSREG_BASE+AR5312_SYSREG_ENABLE,
ATH_READ_REG(AR5312_SYSREG_BASE+AR5312_SYSREG_ENABLE) |
AR5312_ENABLE_ENET0 | AR5312_ENABLE_ENET1);
}
static int
ar5312_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_RESETCTL);
return ((reg & mask) == mask);
}
static void
ar5312_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
}
/* Speed is either 10, 100 or 1000 */
static void
ar5312_chip_set_pll_ge(int unit, int speed)
{
}
static void
ar5312_chip_ddr_flush_ge(int unit)
{
}
static void
ar5312_chip_soc_init(void)
{
u_ar531x_uart_addr = MIPS_PHYS_TO_KSEG1(AR5312_UART0_BASE);
u_ar531x_gpio_di = AR5312_GPIO_DI;
u_ar531x_gpio_do = AR5312_GPIO_DO;
u_ar531x_gpio_cr = AR5312_GPIO_CR;
u_ar531x_gpio_pins = AR5312_GPIO_PINS;
u_ar531x_wdog_ctl = AR5312_SYSREG_WDOG_CTL;
u_ar531x_wdog_timer = AR5312_SYSREG_WDOG_TIMER;
}
static uint32_t
ar5312_chip_get_eth_pll(unsigned int mac, int speed)
{
return 0;
}
struct ar5315_cpu_def ar5312_chip_def = {
&ar5312_chip_detect_mem_size,
&ar5312_chip_detect_sys_frequency,
&ar5312_chip_device_reset,
&ar5312_chip_device_start,
&ar5312_chip_device_stopped,
&ar5312_chip_set_pll_ge,
&ar5312_chip_set_mii_speed,
&ar5312_chip_ddr_flush_ge,
&ar5312_chip_get_eth_pll,
&ar5312_chip_soc_init,
};

View file

@ -0,0 +1,34 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/* $FreeBSD$ */
#ifndef __AR5312_CHIP_H__
#define __AR5312_CHIP_H__
extern struct ar5315_cpu_def ar5312_chip_def;
#endif

View file

@ -0,0 +1,239 @@
/* $Id: ar5312reg.h,v 1.4 2011/07/07 05:06:44 matt Exp $ */
/*
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* This code was written by Garrett D'Amore for the Champaign-Urbana
* Community Wireless Network Project.
*
* 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 acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE 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.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_AR5312REG_H_
#define _MIPS_ATHEROS_AR5312REG_H_
#define AR5312_MEM0_BASE 0x00000000 /* sdram */
#define AR5312_MEM1_BASE 0x08000000 /* sdram/flash */
#define AR5312_MEM3_BASE 0x10000000 /* flash */
#define AR5312_WLAN0_BASE 0x18000000
#define AR5312_ENET0_BASE 0x18100000
#define AR5312_ENET1_BASE 0x18200000
#define AR5312_SDRAMCTL_BASE 0x18300000
#define AR5312_FLASHCTL_BASE 0x18400000
#define AR5312_WLAN1_BASE 0x18500000
#define AR5312_UART0_BASE 0x1C000000 /* high speed */
#define AR5312_UART1_BASE 0x1C001000
#define AR5312_GPIO_BASE 0x1C002000
#define AR5312_SYSREG_BASE 0x1C003000
#define AR5312_UARTDMA_BASE 0x1C004000
#define AR5312_FLASH_BASE 0x1E000000
#define AR5312_FLASH_END 0x20000000 /* possibly aliased */
/*
* FLASHCTL registers -- offset relative to AR531X_FLASHCTL_BASE
*/
#define AR5312_FLASHCTL_0 0x00
#define AR5312_FLASHCTL_1 0x04
#define AR5312_FLASHCTL_2 0x08
#define AR5312_FLASHCTL_IDCY __BITS(0,3) /* idle cycle turn */
#define AR5312_FLASHCTL_WST1 __BITS(5,9) /* wait state 1 */
#define AR5312_FLASHCTL_RBLE __BIT(10) /* rd byte enable */
#define AR5312_FLASHCTL_WST2 __BITS(11,15) /* wait state 1 */
#define AR5312_FLASHCTL_AC __BITS(16,18) /* addr chk */
#define AR5312_FLASHCTL_AC_128K 0
#define AR5312_FLASHCTL_AC_256K 1
#define AR5312_FLASHCTL_AC_512K 2
#define AR5312_FLASHCTL_AC_1M 3
#define AR5312_FLASHCTL_AC_2M 4
#define AR5312_FLASHCTL_AC_4M 5
#define AR5312_FLASHCTL_AC_8M 6
#define AR5312_FLASHCTL_AC_16M 7
#define AR5312_FLASHCTL_E __BIT(19) /* enable */
#define AR5312_FLASHCTL_BUSERR __BIT(24) /* buserr */
#define AR5312_FLASHCTL_WPERR __BIT(25) /* wperr */
#define AR5312_FLASHCTL_WP __BIT(26) /* wp */
#define AR5312_FLASHCTL_BM __BIT(27) /* bm */
#define AR5312_FLASHCTL_MW __BITS(28,29) /* mem width */
#define AR5312_FLASHCTL_AT __BITS(31,30) /* access type */
/*
* GPIO registers -- offset relative to AR531X_GPIO_BASE
*/
#define AR5312_GPIO_DO 0
#define AR5312_GPIO_DI 4
#define AR5312_GPIO_CR 8
#define AR5312_GPIO_PINS 8
/*
* SYSREG registers -- offset relative to AR531X_SYSREG_BASE
*/
#define AR5312_SYSREG_TIMER 0x0000
#define AR5312_SYSREG_TIMER_RELOAD 0x0004
#define AR5312_SYSREG_WDOG_CTL 0x0008
#define AR5312_SYSREG_WDOG_TIMER 0x000c
#define AR5312_SYSREG_MISC_INTSTAT 0x0010
#define AR5312_SYSREG_MISC_INTMASK 0x0014
#define AR5312_SYSREG_INTSTAT 0x0018
#define AR5312_SYSREG_RESETCTL 0x0020
#define AR5312_SYSREG_CLOCKCTL 0x0064
#define AR5312_SYSREG_SCRATCH 0x006c
#define AR5312_SYSREG_AHBPERR 0x0070
#define AR5312_SYSREG_PROC 0x0074
#define AR5312_SYSREG_AHBDMAE 0x0078
#define AR5312_SYSREG_ENABLE 0x0080
#define AR5312_SYSREG_REVISION 0x0090
/* WDOG_CTL watchdog control bits */
#define AR5312_WDOG_CTL_IGNORE 0x0000
#define AR5312_WDOG_CTL_NMI 0x0001
#define AR5312_WDOG_CTL_RESET 0x0002
/* Resets */
#define AR5312_RESET_SYSTEM __BIT(0)
#define AR5312_RESET_CPU __BIT(1)
#define AR5312_RESET_WLAN0 __BIT(2) /* mac & bb */
#define AR5312_RESET_PHY0 __BIT(3) /* enet phy */
#define AR5312_RESET_PHY1 __BIT(4) /* enet phy */
#define AR5312_RESET_ENET0 __BIT(5) /* mac */
#define AR5312_RESET_ENET1 __BIT(6) /* mac */
#define AR5312_RESET_UART0 __BIT(8) /* mac */
#define AR5312_RESET_WLAN1 __BIT(9) /* mac & bb */
#define AR5312_RESET_APB __BIT(10) /* bridge */
#define AR5312_RESET_WARM_CPU __BIT(16)
#define AR5312_RESET_WARM_WLAN0_MAC __BIT(17)
#define AR5312_RESET_WARM_WLAN0_BB __BIT(18)
#define AR5312_RESET_NMI __BIT(20)
#define AR5312_RESET_WARM_WLAN1_MAC __BIT(21)
#define AR5312_RESET_WARM_WLAN1_BB __BIT(22)
#define AR5312_RESET_LOCAL_BUS __BIT(23)
#define AR5312_RESET_WDOG __BIT(24)
/* AR5312/2312 clockctl bits */
#define AR5312_CLOCKCTL_PREDIVIDE __BITS(4,5)
#define AR5312_CLOCKCTL_MULTIPLIER __BITS(8,12)
#define AR5312_CLOCKCTL_DOUBLER __BIT(16)
/* AR2313 clockctl */
#define AR2313_CLOCKCTL_PREDIVIDE __BITS(12,13)
#define AR2313_CLOCKCTL_MULTIPLIER __BITS(16,20)
/* Enables */
#define AR5312_ENABLE_WLAN0 __BIT(0)
#define AR5312_ENABLE_ENET0 __BIT(1)
#define AR5312_ENABLE_ENET1 __BIT(2)
#define AR5312_ENABLE_WLAN1 __BITS(7,8) /* both DMA and PIO */
/* Revision ids */
#define AR5312_REVISION_WMAC_MAJOR(x) (((x) >> 12) & 0xf)
#define AR5312_REVISION_WMAC_MINOR(x) (((x) >> 8) & 0xf)
#define AR5312_REVISION_WMAC(x) (((x) >> 8) & 0xff)
#define AR5312_REVISION_MAJOR(x) (((x) >> 4) & 0xf)
#define AR5312_REVISION_MINOR(x) (((x) >> 0) & 0xf)
#define AR5312_REVISION_MAJ_AR5311 0x1
#define AR5312_REVISION_MAJ_AR5312 0x4
#define AR5312_REVISION_MAJ_AR2313 0x5
#define AR5312_REVISION_MAJ_AR5315 0xB
/*
* SDRAMCTL registers -- offset relative to SDRAMCTL
*/
#define AR5312_SDRAMCTL_MEM_CFG0 0x0000
#define AR5312_SDRAMCTL_MEM_CFG1 0x0004
/* memory config 1 bits */
#define AR5312_MEM_CFG1_BANK0 __BITS(8,10)
#define AR5312_MEM_CFG1_BANK1 __BITS(12,15)
/* helper macro for accessing system registers without bus space */
#define REGVAL(x) *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
#define GETSYSREG(x) REGVAL((x) + AR5312_SYSREG_BASE)
#define PUTSYSREG(x,v) (REGVAL((x) + AR5312_SYSREG_BASE)) = (v)
#define GETSDRAMREG(x) REGVAL((x) + AR5312_SDRAMCTL_BASE)
#define PUTSDRAMREG(x,v) (REGVAL((x) + AR5312_SDRAMCTL_BASE)) = (v)
/*
* Interrupts.
*/
#define AR5312_IRQ_WLAN0 0
#define AR5312_IRQ_ENET0 1
#define AR5312_IRQ_ENET1 2
#define AR5312_IRQ_WLAN1 3
#define AR5312_IRQ_MISC 4
#define AR5312_MISC_IRQ_TIMER 1
#define AR5312_MISC_IRQ_AHBPERR 2
#define AR5312_MISC_IRQ_AHBDMAE 3
#define AR5312_MISC_IRQ_GPIO 4
#define AR5312_MISC_IRQ_UART0 5
#define AR5312_MISC_IRQ_UART0_DMA 6
#define AR5312_MISC_IRQ_WDOG 7
/*
* Board data. This is located in flash somewhere, ar531x_board_info
* locates it.
*/
#include <dev/ath/ath_hal/ah_soc.h> /* XXX really doesn't belong in hal */
/* XXX write-around for now */
#define AR5312_BOARD_MAGIC AR531X_BD_MAGIC
/* config bits */
#define AR5312_BOARD_CONFIG_ENET0 BD_ENET0
#define AR5312_BOARD_CONFIG_ENET1 BD_ENET1
#define AR5312_BOARD_CONFIG_UART1 BD_UART1
#define AR5312_BOARD_CONFIG_UART0 BD_UART0
#define AR5312_BOARD_CONFIG_RSTFACTORY BD_RSTFACTORY
#define AR5312_BOARD_CONFIG_SYSLED BD_SYSLED
#define AR5312_BOARD_CONFIG_EXTUARTCLK BD_EXTUARTCLK
#define AR5312_BOARD_CONFIG_CPUFREQ BD_CPUFREQ
#define AR5312_BOARD_CONFIG_SYSFREQ BD_SYSFREQ
#define AR5312_BOARD_CONFIG_WLAN0 BD_WLAN0
#define AR5312_BOARD_CONFIG_MEMCAP BD_MEMCAP
#define AR5312_BOARD_CONFIG_DISWDOG BD_DISWATCHDOG
#define AR5312_BOARD_CONFIG_WLAN1 BD_WLAN1
#define AR5312_BOARD_CONFIG_AR2312 BD_ISCASPER
#define AR5312_BOARD_CONFIG_WLAN0_2G BD_WLAN0_2G_EN
#define AR5312_BOARD_CONFIG_WLAN0_5G BD_WLAN0_5G_EN
#define AR5312_BOARD_CONFIG_WLAN1_2G BD_WLAN1_2G_EN
#define AR5312_BOARD_CONFIG_WLAN1_5G BD_WLAN1_5G_EN
#define AR5312_APB_BASE AR5312_UART0_BASE
#define AR5312_APB_SIZE 0x02000000
#endif /* _MIPS_ATHEROS_AR531XREG_H_ */

View file

@ -0,0 +1,256 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* All rights reserved.
* Copyright (c) 2016, Hiroki Mori
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_chip.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
/* XXX these shouldn't be in here - this file is a per-chip file */
/* XXX these should be in the top-level ar5315 type, not ar5315 -chip */
uint32_t u_ar531x_cpu_freq;
uint32_t u_ar531x_ahb_freq;
uint32_t u_ar531x_ddr_freq;
uint32_t u_ar531x_uart_addr;
uint32_t u_ar531x_gpio_di;
uint32_t u_ar531x_gpio_do;
uint32_t u_ar531x_gpio_cr;
uint32_t u_ar531x_gpio_pins;
uint32_t u_ar531x_wdog_ctl;
uint32_t u_ar531x_wdog_timer;
static void
ar5315_chip_detect_mem_size(void)
{
uint32_t memsize = 0;
uint32_t memcfg, cw, rw, dw;
/*
* Determine the memory size. We query the board info.
*/
memcfg = ATH_READ_REG(AR5315_SDRAMCTL_BASE + AR5315_SDRAMCTL_MEM_CFG);
cw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_COL_WIDTH);
cw += 1;
rw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_ROW_WIDTH);
rw += 1;
/* XXX: according to redboot, this could be wrong if DDR SDRAM */
dw = __SHIFTOUT(memcfg, AR5315_MEM_CFG_DATA_WIDTH);
dw += 1;
dw *= 8; /* bits */
/* not too sure about this math, but it _seems_ to add up */
memsize = (1 << cw) * (1 << rw) * dw;
#if 0
printf("SDRAM_MEM_CFG =%x, cw=%d rw=%d dw=%d xmemsize=%d\n", memcfg,
cw, rw, dw, memsize);
#endif
realmem = memsize;
}
static void
ar5315_chip_detect_sys_frequency(void)
{
uint32_t freq_ref, freq_pll;
static const uint8_t pll_divide_table[] = {
2, 3, 4, 6, 3,
/*
* these entries are bogus, but it avoids a possible
* bad table dereference
*/
1, 1, 1
};
static const uint8_t pre_divide_table[] = {
1, 2, 4, 5
};
const uint32_t pllc = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_PLLC_CTL);
const uint32_t refdiv = pre_divide_table[AR5315_PLLC_REF_DIV(pllc)];
const uint32_t fbdiv = AR5315_PLLC_FB_DIV(pllc);
const uint32_t div2 = (AR5315_PLLC_DIV_2(pllc) + 1) * 2; /* results in 2 or 4 */
freq_ref = 40000000;
/* 40MHz reference clk, reference and feedback dividers */
freq_pll = (freq_ref / refdiv) * div2 * fbdiv;
const uint32_t pllout[4] = {
/* CLKM select */
[0] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
[1] = freq_pll / pll_divide_table[AR5315_PLLC_CLKM(pllc)],
/* CLKC select */
[2] = freq_pll / pll_divide_table[AR5315_PLLC_CLKC(pllc)],
/* ref_clk select */
[3] = freq_ref, /* use original reference clock */
};
const uint32_t amba_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_AMBACLK);
uint32_t ambadiv = AR5315_CLOCKCTL_DIV(amba_clkctl);
ambadiv = ambadiv ? (ambadiv * 2) : 1;
u_ar531x_ahb_freq = pllout[AR5315_CLOCKCTL_SELECT(amba_clkctl)] / ambadiv;
const uint32_t cpu_clkctl = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_CPUCLK);
uint32_t cpudiv = AR5315_CLOCKCTL_DIV(cpu_clkctl);
cpudiv = cpudiv ? (cpudiv * 2) : 1;
u_ar531x_cpu_freq = pllout[AR5315_CLOCKCTL_SELECT(cpu_clkctl)] / cpudiv;
u_ar531x_ddr_freq = 0;
}
/*
* This does not lock the CPU whilst doing the work!
*/
static void
ar5315_chip_device_reset(void)
{
ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_COLDRESET,
AR5315_COLD_AHB | AR5315_COLD_APB | AR5315_COLD_CPU);
}
static void
ar5315_chip_device_start(void)
{
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ERR0,
AR5315_AHB_ERROR_DET);
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ERR1);
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_WDOG_CTL,
AR5315_WDOG_CTL_IGNORE);
// set Ethernet AHB master arbitration control
// Maybe RedBoot was enabled. But to make sure.
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL,
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL) |
AR5315_ARB_ENET);
// set Ethernet controller byteswap control
/*
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN,
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN) |
AR5315_ENDIAN_ENET);
*/
/* Disable interrupts for all gpio pins. */
ATH_WRITE_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_GPIO_INT, 0);
printf("AHB Master Arbitration Control %08x\n",
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_AHB_ARB_CTL));
printf("Byteswap Control %08x\n",
ATH_READ_REG(AR5315_SYSREG_BASE+AR5315_SYSREG_ENDIAN));
}
static int
ar5315_chip_device_stopped(uint32_t mask)
{
uint32_t reg;
reg = ATH_READ_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_COLDRESET);
return ((reg & mask) == mask);
}
static void
ar5315_chip_set_mii_speed(uint32_t unit, uint32_t speed)
{
}
/* Speed is either 10, 100 or 1000 */
static void
ar5315_chip_set_pll_ge(int unit, int speed)
{
}
static void
ar5315_chip_ddr_flush_ge(int unit)
{
}
static void
ar5315_chip_soc_init(void)
{
u_ar531x_uart_addr = MIPS_PHYS_TO_KSEG1(AR5315_UART_BASE);
u_ar531x_gpio_di = AR5315_SYSREG_GPIO_DI;
u_ar531x_gpio_do = AR5315_SYSREG_GPIO_DO;
u_ar531x_gpio_cr = AR5315_SYSREG_GPIO_CR;
u_ar531x_gpio_pins = AR5315_GPIO_PINS;
u_ar531x_wdog_ctl = AR5315_SYSREG_WDOG_CTL;
u_ar531x_wdog_timer = AR5315_SYSREG_WDOG_TIMER;
}
static uint32_t
ar5315_chip_get_eth_pll(unsigned int mac, int speed)
{
return 0;
}
struct ar5315_cpu_def ar5315_chip_def = {
&ar5315_chip_detect_mem_size,
&ar5315_chip_detect_sys_frequency,
&ar5315_chip_device_reset,
&ar5315_chip_device_start,
&ar5315_chip_device_stopped,
&ar5315_chip_set_pll_ge,
&ar5315_chip_set_mii_speed,
&ar5315_chip_ddr_flush_ge,
&ar5315_chip_get_eth_pll,
&ar5315_chip_soc_init,
};

View file

@ -0,0 +1,34 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/* $FreeBSD$ */
#ifndef __AR5315_CHIP_H__
#define __AR5315_CHIP_H__
extern struct ar5315_cpu_def ar5315_chip_def;
#endif

View file

@ -0,0 +1,139 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/* $FreeBSD$ */
#ifndef __AR5315_CPUDEF_H__
#define __AR5315_CPUDEF_H__
struct ar5315_cpu_def {
void (* detect_mem_size) (void);
void (* detect_sys_frequency) (void);
void (* ar5315_chip_device_reset) (void);
void (* ar5315_chip_device_start) (void);
int (* ar5315_chip_device_stopped) (uint32_t);
void (* ar5315_chip_set_pll_ge) (int, int);
void (* ar5315_chip_set_mii_speed) (uint32_t, uint32_t);
void (* ar5315_chip_ddr_flush_ge) (int);
uint32_t (* ar5315_chip_get_eth_pll) (unsigned int, int);
void (* ar5315_chip_soc_init) (void);
/*
* Allow to change MII bus mode:
* AR5315_ARGE_MII_MODE_MII
* AR5315_ARGE_MII_MODE_RMII
* AR5315_ARGE_MII_MODE_GMII
* AR5315_ARGE_MII_MODE_RGMII
* mii_mode(unit, mode);
*/
#define AR5315_ARGE_MII_MODE_MII 0x0100
#define AR5315_ARGE_MII_MODE_RMII 0x0101
#define AR5315_ARGE_MII_MODE_GMII 0x1000
#define AR5315_ARGE_MII_MODE_RGMII 0x1001
void (* ar5315_chip_set_mii_mode) (int, int, int);
};
extern struct ar5315_cpu_def * ar5315_cpu_ops;
static inline void ar531x_detect_mem_size(void)
{
ar5315_cpu_ops->detect_mem_size();
}
static inline void ar531x_detect_sys_frequency(void)
{
ar5315_cpu_ops->detect_sys_frequency();
}
static inline void ar531x_device_reset(void)
{
ar5315_cpu_ops->ar5315_chip_device_reset();
}
static inline void ar531x_device_start(void)
{
ar5315_cpu_ops->ar5315_chip_device_start();
}
static inline int ar531x_device_stopped(uint32_t mask)
{
return ar5315_cpu_ops->ar5315_chip_device_stopped(mask);
}
static inline void ar531x_device_set_pll_ge(int unit, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_pll_ge(unit, speed);
}
static inline void ar531x_device_set_mii_speed(int unit, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_mii_speed(unit, speed);
}
static inline void ar531x_device_flush_ddr_ge(int unit)
{
ar5315_cpu_ops->ar5315_chip_ddr_flush_ge(unit);
}
static inline void ar531x_device_soc_init(void)
{
ar5315_cpu_ops->ar5315_chip_soc_init();
}
static inline void ar531x_device_set_mii_mode(int unit, int mode, int speed)
{
ar5315_cpu_ops->ar5315_chip_set_mii_mode(unit, mode, speed);
}
/* XXX shouldn't be here! */
extern uint32_t u_ar531x_cpu_freq;
extern uint32_t u_ar531x_ahb_freq;
extern uint32_t u_ar531x_ddr_freq;
extern uint32_t u_ar531x_uart_addr;
extern uint32_t u_ar531x_gpio_di;
extern uint32_t u_ar531x_gpio_do;
extern uint32_t u_ar531x_gpio_cr;
extern uint32_t u_ar531x_gpio_pins;
extern uint32_t u_ar531x_wdog_ctl;
extern uint32_t u_ar531x_wdog_timer;
static inline uint32_t ar531x_cpu_freq(void) { return u_ar531x_cpu_freq; }
static inline uint32_t ar531x_ahb_freq(void) { return u_ar531x_ahb_freq; }
static inline uint32_t ar531x_ddr_freq(void) { return u_ar531x_ddr_freq; }
static inline uint32_t ar531x_uart_addr(void) { return u_ar531x_uart_addr; }
static inline uint32_t ar531x_gpio_di(void) { return u_ar531x_gpio_di; }
static inline uint32_t ar531x_gpio_cr(void) { return u_ar531x_gpio_cr; }
static inline uint32_t ar531x_gpio_do(void) { return u_ar531x_gpio_do; }
static inline uint32_t ar531x_gpio_pins(void) { return u_ar531x_gpio_pins; }
static inline uint32_t ar531x_wdog_ctl(void) { return u_ar531x_wdog_ctl; }
static inline uint32_t ar531x_wdog_timer(void) { return u_ar531x_wdog_timer; }
#endif

View file

@ -0,0 +1,534 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/*
* GPIO driver for AR5315
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_gpiovar.h>
#include <dev/gpio/gpiobusvar.h>
#include "gpio_if.h"
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
/*
* Helpers
*/
static void ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc,
uint32_t mask);
static void ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc,
uint32_t mask);
static void ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc,
struct gpio_pin *pin, uint32_t flags);
/*
* Driver stuff
*/
static int ar5315_gpio_probe(device_t dev);
static int ar5315_gpio_attach(device_t dev);
static int ar5315_gpio_detach(device_t dev);
static int ar5315_gpio_filter(void *arg);
static void ar5315_gpio_intr(void *arg);
/*
* GPIO interface
*/
static device_t ar5315_gpio_get_bus(device_t);
static int ar5315_gpio_pin_max(device_t dev, int *maxpin);
static int ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
static int ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
*flags);
static int ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
static int ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
static int ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
static int ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
static int ar5315_gpio_pin_toggle(device_t dev, uint32_t pin);
/*
* Enable/disable the GPIO function control space.
*
* This is primarily for the AR5315, which has SPI CS1/CS2, UART, SLIC, I2S
* as GPIO pin options.
*/
static void
ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc, uint32_t mask)
{
// GPIO_SET_BITS(sc, AR5315_GPIO_FUNCTION, mask);
}
static void
ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc, uint32_t mask)
{
// GPIO_CLEAR_BITS(sc, AR5315_GPIO_FUNCTION, mask);
}
static void
ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc, struct gpio_pin *pin,
unsigned int flags)
{
uint32_t mask;
mask = 1 << pin->gp_pin;
/*
* Manage input/output
*/
if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
if (flags & GPIO_PIN_OUTPUT) {
pin->gp_flags |= GPIO_PIN_OUTPUT;
GPIO_SET_BITS(sc, ar531x_gpio_cr(), mask);
}
else {
pin->gp_flags |= GPIO_PIN_INPUT;
GPIO_CLEAR_BITS(sc, ar531x_gpio_cr(), mask);
}
}
}
static device_t
ar5315_gpio_get_bus(device_t dev)
{
struct ar5315_gpio_softc *sc;
sc = device_get_softc(dev);
return (sc->busdev);
}
static int
ar5315_gpio_pin_max(device_t dev, int *maxpin)
{
*maxpin = ar531x_gpio_pins() - 1;
return (0);
}
static int
ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*caps = sc->gpio_pins[i].gp_caps;
GPIO_UNLOCK(sc);
return (0);
}
static int
ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
int dir;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
dir = GPIO_READ(sc, ar531x_gpio_cr()) & (1 << pin);
*flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
/*
GPIO_LOCK(sc);
*flags = sc->gpio_pins[i].gp_flags;
GPIO_UNLOCK(sc);
*/
return (0);
}
static int
ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
GPIO_UNLOCK(sc);
return (0);
}
static int
ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
int i;
struct ar5315_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
ar5315_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
return (0);
}
static int
ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
uint32_t state;
state = GPIO_READ(sc, ar531x_gpio_do());
if(value == 1) {
state |= (1 << pin);
} else {
state &= ~(1 << pin);
}
GPIO_WRITE(sc, ar531x_gpio_do(), state);
return (0);
}
static int
ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
*val = (GPIO_READ(sc, ar531x_gpio_di()) & (1 << pin)) ? 1 : 0;
return (0);
}
static int
ar5315_gpio_pin_toggle(device_t dev, uint32_t pin)
{
int res, i;
struct ar5315_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
res = (GPIO_READ(sc, ar531x_gpio_do()) & (1 << pin)) ? 1 : 0;
if (res)
GPIO_CLEAR_BITS(sc, ar531x_gpio_do(), pin);
else
GPIO_SET_BITS(sc, ar531x_gpio_do(), pin);
return (0);
}
static int
ar5315_gpio_filter(void *arg)
{
/* TODO: something useful */
return (FILTER_STRAY);
}
static void
ar5315_gpio_intr(void *arg)
{
struct ar5315_gpio_softc *sc = arg;
GPIO_LOCK(sc);
/* TODO: something useful */
GPIO_UNLOCK(sc);
}
static int
ar5315_gpio_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR531x GPIO driver");
return (0);
}
static int
ar5315_gpio_attach(device_t dev)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
int i, j, maxpin;
int mask, pinon;
uint32_t oe;
KASSERT((device_get_unit(dev) == 0),
("ar5315_gpio: Only one gpio module supported"));
mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
/* Map control/status registers. */
sc->gpio_mem_rid = 0;
sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->gpio_mem_rid, RF_ACTIVE);
if (sc->gpio_mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC,
ar5315_gpio_filter, ar5315_gpio_intr, sc, &sc->gpio_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
ar5315_gpio_detach(dev);
return (ENXIO);
}
sc->dev = dev;
/* Enable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_set", &mask) == 0) {
device_printf(dev, "function_set: 0x%x\n", mask);
ar5315_gpio_function_enable(sc, mask);
}
/* Disable function bits that are required */
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"function_clear", &mask) == 0) {
device_printf(dev, "function_clear: 0x%x\n", mask);
ar5315_gpio_function_disable(sc, mask);
}
/* Initialise all pins specified in the mask, up to the pin count */
(void) ar5315_gpio_pin_max(dev, &maxpin);
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinmask", &mask) != 0)
mask = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinon", &pinon) != 0)
pinon = 0;
device_printf(dev, "gpio pinmask=0x%x\n", mask);
for (j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
sc->gpio_npins++;
}
/* Iniatilize the GPIO pins, keep the loader settings. */
oe = GPIO_READ(sc, ar531x_gpio_cr());
sc->gpio_pins = malloc(sizeof(struct gpio_pin) * sc->gpio_npins,
M_DEVBUF, M_WAITOK | M_ZERO);
for (i = 0, j = 0; j <= maxpin; j++) {
if ((mask & (1 << j)) == 0)
continue;
snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
"pin %d", j);
sc->gpio_pins[i].gp_pin = j;
sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
if (oe & (1 << j))
sc->gpio_pins[i].gp_flags = GPIO_PIN_OUTPUT;
else
sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT;
i++;
}
#if 0
/* Turn on the hinted pins. */
for (i = 0; i < sc->gpio_npins; i++) {
j = sc->gpio_pins[i].gp_pin;
if ((pinon & (1 << j)) != 0) {
ar5315_gpio_pin_setflags(dev, j, GPIO_PIN_OUTPUT);
ar5315_gpio_pin_set(dev, j, 1);
}
}
/*
* Search through the function hints, in case there's some
* overrides such as LNA control.
*
* hint.gpio.X.func.<pin>.gpiofunc=<func value>
* hint.gpio.X.func.<pin>.gpiomode=1 (for output, default low)
*/
for (i = 0; i <= maxpin; i++) {
char buf[32];
int gpiofunc, gpiomode;
snprintf(buf, 32, "func.%d.gpiofunc", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiofunc) != 0)
continue;
/* Get the mode too */
snprintf(buf, 32, "func.%d.gpiomode", i);
if (resource_int_value(device_get_name(dev),
device_get_unit(dev),
buf,
&gpiomode) != 0)
continue;
/* We only handle mode=1 for now */
if (gpiomode != 1)
continue;
device_printf(dev, "%s: GPIO %d: func=%d, mode=%d\n",
__func__,
i,
gpiofunc,
gpiomode);
/* Set output (bit == 0) */
oe = GPIO_READ(sc, ar531x_gpio_cr());
oe &= ~ (1 << i);
GPIO_WRITE(sc, ar531x_gpio_cr(), oe);
/* Set pin value = 0, so it stays low by default */
oe = GPIO_READ(sc, ar531x_gpio_do());
oe &= ~ (1 << i);
GPIO_WRITE(sc, ar531x_gpio_do(), oe);
/* Finally: Set the output config */
// ar5315_gpio_ouput_configure(i, gpiofunc);
}
#endif
sc->busdev = gpiobus_attach_bus(dev);
if (sc->busdev == NULL) {
ar5315_gpio_detach(dev);
return (ENXIO);
}
return (0);
}
static int
ar5315_gpio_detach(device_t dev)
{
struct ar5315_gpio_softc *sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
gpiobus_detach_bus(dev);
if (sc->gpio_ih)
bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih);
if (sc->gpio_irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid,
sc->gpio_irq_res);
if (sc->gpio_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
sc->gpio_mem_res);
if (sc->gpio_pins)
free(sc->gpio_pins, M_DEVBUF);
mtx_destroy(&sc->gpio_mtx);
return(0);
}
static device_method_t ar5315_gpio_methods[] = {
DEVMETHOD(device_probe, ar5315_gpio_probe),
DEVMETHOD(device_attach, ar5315_gpio_attach),
DEVMETHOD(device_detach, ar5315_gpio_detach),
/* GPIO protocol */
DEVMETHOD(gpio_get_bus, ar5315_gpio_get_bus),
DEVMETHOD(gpio_pin_max, ar5315_gpio_pin_max),
DEVMETHOD(gpio_pin_getname, ar5315_gpio_pin_getname),
DEVMETHOD(gpio_pin_getflags, ar5315_gpio_pin_getflags),
DEVMETHOD(gpio_pin_getcaps, ar5315_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_setflags, ar5315_gpio_pin_setflags),
DEVMETHOD(gpio_pin_get, ar5315_gpio_pin_get),
DEVMETHOD(gpio_pin_set, ar5315_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ar5315_gpio_pin_toggle),
{0, 0},
};
static driver_t ar5315_gpio_driver = {
"gpio",
ar5315_gpio_methods,
sizeof(struct ar5315_gpio_softc),
};
static devclass_t ar5315_gpio_devclass;
DRIVER_MODULE(ar5315_gpio, apb, ar5315_gpio_driver, ar5315_gpio_devclass, 0, 0);

View file

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*
* $FreeBSD$
*
*/
#ifndef __AR5315_GPIOVAR_H__
#define __AR5315_GPIOVAR_H__
#include <sys/timepps.h>
#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->gpio_mtx)
#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->gpio_mtx)
#define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->gpio_mtx, MA_OWNED)
/*
* register space access macros
*/
#define GPIO_WRITE(sc, reg, val) do { \
bus_write_4(sc->gpio_mem_res, (reg), (val)); \
} while (0)
#define GPIO_READ(sc, reg) bus_read_4(sc->gpio_mem_res, (reg))
#define GPIO_SET_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) | (bits))
#define GPIO_CLEAR_BITS(sc, reg, bits) \
GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) & ~(bits))
#define AR5315_GPIO_PINS 23
#define AR5312_GPIO_PINS 8
struct ar5315_gpio_softc {
device_t dev;
device_t busdev;
struct mtx gpio_mtx;
struct resource *gpio_mem_res;
int gpio_mem_rid;
struct resource *gpio_irq_res;
int gpio_irq_rid;
void *gpio_ih;
int gpio_npins;
struct gpio_pin *gpio_pins;
int gpio_ppspin;
struct pps_state gpio_pps;
uint32_t gpio_ppsenable;
};
#endif /* __AR5315_GPIOVAR_H__ */

View file

@ -0,0 +1,351 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009 Oleksandr Tymoshenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ar531x.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
extern char edata[], end[];
uint32_t ar711_base_mac[ETHER_ADDR_LEN];
/* 4KB static data aread to keep a copy of the bootload env until
the dynamic kenv is setup */
char boot1_env[4096];
/*
* We get a string in from Redboot with the all the arguments together,
* "foo=bar bar=baz". Split them up and save in kenv.
*/
static void
parse_argv(char *str)
{
char *n, *v;
while ((v = strsep(&str, " ")) != NULL) {
if (*v == '\0')
continue;
if (*v == '-') {
while (*v != '\0') {
v++;
switch (*v) {
case 'a': boothowto |= RB_ASKNAME; break;
case 'd': boothowto |= RB_KDB; break;
case 'g': boothowto |= RB_GDB; break;
case 's': boothowto |= RB_SINGLE; break;
case 'v': boothowto |= RB_VERBOSE; break;
}
}
} else {
n = strsep(&v, "=");
if (v == NULL)
kern_setenv(n, "1");
else
kern_setenv(n, v);
}
}
}
void
platform_cpu_init()
{
/* Nothing special */
}
void
platform_reset(void)
{
ar531x_device_reset();
/* Wait for reset */
while(1)
;
}
/*
* Obtain the MAC address via the Redboot environment.
*/
static void
ar5315_redboot_get_macaddr(void)
{
char *var;
int count = 0;
/*
* "ethaddr" is passed via envp on RedBoot platforms
* "kmac" is passed via argv on RouterBOOT platforms
*/
if ((var = kern_getenv("ethaddr")) != NULL ||
(var = kern_getenv("kmac")) != NULL) {
count = sscanf(var, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
&ar711_base_mac[0], &ar711_base_mac[1],
&ar711_base_mac[2], &ar711_base_mac[3],
&ar711_base_mac[4], &ar711_base_mac[5]);
if (count < 6)
memset(ar711_base_mac, 0,
sizeof(ar711_base_mac));
freeenv(var);
}
}
#if defined(SOC_VENDOR) || defined(SOC_MODEL) || defined(SOC_REV)
static SYSCTL_NODE(_hw, OID_AUTO, soc, CTLFLAG_RD, 0,
"System on Chip information");
#endif
#if defined(SOC_VENDOR)
static char hw_soc_vendor[] = SOC_VENDOR;
SYSCTL_STRING(_hw_soc, OID_AUTO, vendor, CTLFLAG_RD, hw_soc_vendor, 0,
"SoC vendor");
#endif
#if defined(SOC_MODEL)
static char hw_soc_model[] = SOC_MODEL;
SYSCTL_STRING(_hw_soc, OID_AUTO, model, CTLFLAG_RD, hw_soc_model, 0,
"SoC model");
#endif
#if defined(SOC_REV)
static char hw_soc_revision[] = SOC_REV;
SYSCTL_STRING(_hw_soc, OID_AUTO, revision, CTLFLAG_RD, hw_soc_revision, 0,
"SoC revision");
#endif
#if defined(DEVICE_VENDOR) || defined(DEVICE_MODEL) || defined(DEVICE_REV)
static SYSCTL_NODE(_hw, OID_AUTO, device, CTLFLAG_RD, 0, "Board information");
#endif
#if defined(DEVICE_VENDOR)
static char hw_device_vendor[] = DEVICE_VENDOR;
SYSCTL_STRING(_hw_device, OID_AUTO, vendor, CTLFLAG_RD, hw_device_vendor, 0,
"Board vendor");
#endif
#if defined(DEVICE_MODEL)
static char hw_device_model[] = DEVICE_MODEL;
SYSCTL_STRING(_hw_device, OID_AUTO, model, CTLFLAG_RD, hw_device_model, 0,
"Board model");
#endif
#if defined(DEVICE_REV)
static char hw_device_revision[] = DEVICE_REV;
SYSCTL_STRING(_hw_device, OID_AUTO, revision, CTLFLAG_RD, hw_device_revision, 0,
"Board revision");
#endif
void
platform_start(__register_t a0 __unused, __register_t a1 __unused,
__register_t a2 __unused, __register_t a3 __unused)
{
uint64_t platform_counter_freq;
int argc = 0, i;
char **argv = NULL;
#ifndef AR531X_ENV_UBOOT
char **envp = NULL;
#endif
vm_offset_t kernend;
/*
* clear the BSS and SBSS segments, this should be first call in
* the function
*/
kernend = (vm_offset_t)&end;
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
mips_postboot_fixup();
/* Initialize pcpu stuff */
mips_pcpu0_init();
/*
* Until some more sensible abstractions for uboot/redboot
* environment handling, we have to make this a compile-time
* hack. The existing code handles the uboot environment
* very incorrectly so we should just ignore initialising
* the relevant pointers.
*/
#ifndef AR531X_ENV_UBOOT
argc = a0;
argv = (char**)a1;
envp = (char**)a2;
#endif
/*
* Protect ourselves from garbage in registers
*/
if (MIPS_IS_VALID_PTR(envp)) {
for (i = 0; envp[i]; i += 2) {
if (strcmp(envp[i], "memsize") == 0)
realmem = btoc(strtoul(envp[i+1], NULL, 16));
}
}
ar5315_detect_sys_type();
// RedBoot SDRAM Detect is missing
// ar531x_detect_mem_size();
/*
* Just wild guess. RedBoot let us down and didn't reported
* memory size
*/
if (realmem == 0)
realmem = btoc(16*1024*1024);
/*
* Allow build-time override in case Redboot lies
* or in other situations (eg where there's u-boot)
* where there isn't (yet) a convienent method of
* being told how much RAM is available.
*
* This happens on at least the Ubiquiti LS-SR71A
* board, where redboot says there's 16mb of RAM
* but in fact there's 32mb.
*/
#if defined(AR531X_REALMEM)
realmem = btoc(AR531X_REALMEM);
#endif
/* phys_avail regions are in bytes */
phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
phys_avail[1] = ctob(realmem);
dump_avail[0] = phys_avail[0];
dump_avail[1] = phys_avail[1] - phys_avail[0];
physmem = realmem;
/*
* ns8250 uart code uses DELAY so ticker should be inititalized
* before cninit. And tick_init_params refers to hz, so * init_param1
* should be called first.
*/
init_param1();
boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
// boothowto |= RB_VERBOSE;
// boothowto |= (RB_SINGLE);
/* Detect the system type - this is needed for subsequent chipset-specific calls */
ar531x_device_soc_init();
ar531x_detect_sys_frequency();
platform_counter_freq = ar531x_cpu_freq();
mips_timer_init_params(platform_counter_freq, 1);
cninit();
init_static_kenv(boot1_env, sizeof(boot1_env));
printf("CPU platform: %s\n", ar5315_get_system_type());
printf("CPU Frequency=%d MHz\n", ar531x_cpu_freq() / 1000000);
printf("CPU DDR Frequency=%d MHz\n", ar531x_ddr_freq() / 1000000);
printf("CPU AHB Frequency=%d MHz\n", ar531x_ahb_freq() / 1000000);
printf("platform frequency: %lld\n", platform_counter_freq);
printf("arguments: \n");
printf(" a0 = %08x\n", a0);
printf(" a1 = %08x\n", a1);
printf(" a2 = %08x\n", a2);
printf(" a3 = %08x\n", a3);
/*
* XXX this code is very redboot specific.
*/
printf("Cmd line:");
if (MIPS_IS_VALID_PTR(argv)) {
for (i = 0; i < argc; i++) {
printf(" %s", argv[i]);
parse_argv(argv[i]);
}
}
else
printf ("argv is invalid");
printf("\n");
printf("Environment:\n");
#if 0
if (MIPS_IS_VALID_PTR(envp)) {
if (envp[0] && strchr(envp[0], '=') ) {
char *env_val; //
for (i = 0; envp[i]; i++) {
env_val = strchr(envp[i], '=');
/* Not sure if we correct to change data, but env in RAM */
*(env_val++) = '\0';
printf("= %s = %s\n", envp[i], env_val);
kern_setenv(envp[i], env_val);
}
} else {
for (i = 0; envp[i]; i+=2) {
printf(" %s = %s\n", envp[i], envp[i+1]);
kern_setenv(envp[i], envp[i+1]);
}
}
}
else
printf ("envp is invalid\n");
#else
printf ("envp skiped\n");
#endif
/* Redboot if_are MAC address is in the environment */
ar5315_redboot_get_macaddr();
init_param2(physmem);
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
mutex_init();
ar531x_device_start();
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}

View file

@ -0,0 +1,161 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_ar531x.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <net/ethernet.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5312reg.h>
#include <mips/atheros/ar531x/ar5315_setup.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar531x/ar5315_chip.h>
#include <mips/atheros/ar531x/ar5312_chip.h>
#include <mips/atheros/ar724x_chip.h>
#include <mips/atheros/ar91xx_chip.h>
#include <dev/ath/ath_hal/ah_soc.h>
#define AR5315_SYS_TYPE_LEN 128
static char ar5315_sys_type[AR5315_SYS_TYPE_LEN];
enum ar531x_soc_type ar531x_soc;
struct ar5315_cpu_def * ar5315_cpu_ops = NULL;
void
ar5315_detect_sys_type(void)
{
char *chip = "????";
uint32_t ver = 0;
uint32_t rev = 0;
#if 0
const uint8_t *ptr, *end;
static const struct ar531x_boarddata *board = NULL;
ptr = (const uint8_t *) MIPS_PHYS_TO_KSEG1(AR5315_CONFIG_END
- 0x1000);
end = (const uint8_t *)AR5315_CONFIG_BASE;
for (; ptr > end; ptr -= 0x1000) {
if (*(const uint32_t *)ptr == AR531X_BD_MAGIC) {
board = (const struct ar531x_boarddata *) ptr;
rev = board->major;
break;
}
}
#endif
int soctype;
#ifdef AR531X_1ST_GENERATION
soctype = AR_FIRST_GEN;
#else
soctype = AR_SECOND_GEN;
#endif
if(soctype == AR_SECOND_GEN) {
ar5315_cpu_ops = &ar5315_chip_def;
ver = ATH_READ_REG(AR5315_SYSREG_BASE +
AR5315_SYSREG_SREV);
switch (ver) {
case 0x86:
ar531x_soc = AR531X_SOC_AR5315;
chip = "2315";
break;
case 0x87:
ar531x_soc = AR531X_SOC_AR5316;
chip = "2316";
break;
case 0x90:
ar531x_soc = AR531X_SOC_AR5317;
chip = "2317";
break;
case 0x91:
ar531x_soc = AR531X_SOC_AR5318;
chip = "2318";
break;
}
} else {
ar5315_cpu_ops = &ar5312_chip_def;
ver = ATH_READ_REG(AR5312_SYSREG_BASE +
AR5312_SYSREG_REVISION);
rev = AR5312_REVISION_MINOR(ver);
switch (AR5312_REVISION_MAJOR(ver)) {
case AR5312_REVISION_MAJ_AR5311:
ar531x_soc = AR531X_SOC_AR5311;
chip = "5311";
break;
case AR5312_REVISION_MAJ_AR5312:
ar531x_soc = AR531X_SOC_AR5312;
chip = "5312";
break;
case AR5312_REVISION_MAJ_AR2313:
ar531x_soc = AR531X_SOC_AR5313;
chip = "2313";
break;
}
}
sprintf(ar5315_sys_type, "Atheros AR%s rev %u", chip, rev);
}
const char *
ar5315_get_system_type(void)
{
return ar5315_sys_type;
}

View file

@ -0,0 +1,51 @@
/*-
* Copyright (c) 2010 Adrian Chadd
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/* $FreeBSD$ */
#ifndef __AR5315_SETUP_H__
#define __AR5315_SETUP_H__
enum ar531x_soc_type {
AR531X_SOC_UNKNOWN,
AR531X_SOC_AR5311,
AR531X_SOC_AR5312,
AR531X_SOC_AR5313,
AR531X_SOC_AR5314,
AR531X_SOC_AR5315,
AR531X_SOC_AR5316,
AR531X_SOC_AR5317,
AR531X_SOC_AR5318,
};
extern enum ar531x_soc_type ar531x_soc;
extern void ar5315_detect_sys_type(void);
extern const char *ar5315_get_system_type(void);
#define AR_FIRST_GEN 1
#define AR_SECOND_GEN 2
#endif

View file

@ -0,0 +1,287 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/pmap.h>
#include <dev/spibus/spi.h>
#include <dev/spibus/spibusvar.h>
#include "spibus_if.h"
#include <mips/atheros/ar531x/arspireg.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#undef AR531X_SPI_DEBUG
#ifdef AR531X_SPI_DEBUG
#define dprintf printf
#else
#define dprintf(x, arg...)
#endif
/*
* register space access macros
*/
#define SPI_WRITE(sc, reg, val) do { \
bus_write_4(sc->sc_mem_res, (reg), (val)); \
} while (0)
#define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg))
#define SPI_SET_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits))
#define SPI_CLEAR_BITS(sc, reg, bits) \
SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits))
struct ar5315_spi_softc {
device_t sc_dev;
struct resource *sc_mem_res;
uint32_t sc_reg_ctrl;
uint32_t sc_debug;
};
static void
ar5315_spi_attach_sysctl(device_t dev)
{
struct ar5315_spi_softc *sc;
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree;
sc = device_get_softc(dev);
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->sc_debug, 0,
"ar5315_spi debugging flags");
}
static int
ar5315_spi_probe(device_t dev)
{
device_set_desc(dev, "AR5315 SPI");
return (0);
}
static int
ar5315_spi_attach(device_t dev)
{
struct ar5315_spi_softc *sc = device_get_softc(dev);
int rid;
sc->sc_dev = dev;
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_mem_res) {
device_printf(dev, "Could not map memory\n");
return (ENXIO);
}
device_add_child(dev, "spibus", 0);
ar5315_spi_attach_sysctl(dev);
return (bus_generic_attach(dev));
}
static void
ar5315_spi_chip_activate(struct ar5315_spi_softc *sc, int cs)
{
}
static void
ar5315_spi_chip_deactivate(struct ar5315_spi_softc *sc, int cs)
{
}
static int
ar5315_spi_get_block(off_t offset, caddr_t data, off_t count)
{
int i;
for(i = 0; i < count / 4; ++i) {
*((uint32_t *)data + i) = ATH_READ_REG(AR5315_MEM1_BASE + offset + i * 4);
}
// printf("ar5315_spi_get_blockr: %x %x %x\n",
// (int)offset, (int)count, *(uint32_t *)data);
return (0);
}
static int
ar5315_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
struct ar5315_spi_softc *sc;
uint8_t *buf_in, *buf_out;
struct spibus_ivar *devi = SPIBUS_IVAR(child);
int lin, lout;
uint32_t ctl, cnt, op, rdat;
int i, j;
sc = device_get_softc(dev);
if (sc->sc_debug & 0x8000)
printf("ar5315_spi_transfer: CMD ");
/* Open SPI controller interface */
ar5315_spi_chip_activate(sc, devi->cs);
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
/*
* Transfer command
*/
buf_out = (uint8_t *)cmd->tx_cmd;
op = buf_out[0];
if(op == 0x0b) {
int offset = buf_out[1] << 16 | buf_out[2] << 8 | buf_out[3];
ar5315_spi_get_block(offset, cmd->rx_data, cmd->rx_data_sz);
return (0);
}
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
if (sc->sc_debug & 0x8000) {
printf("%08x ", op);
printf("tx_cmd_sz=%d rx_cmd_sz=%d ", cmd->tx_cmd_sz,
cmd->rx_cmd_sz);
if(cmd->tx_cmd_sz != 1) {
printf("%08x ", *((uint32_t *)cmd->tx_cmd));
printf("%08x ", *((uint32_t *)cmd->tx_cmd + 1));
}
}
SPI_WRITE(sc, ARSPI_REG_OPCODE, op);
/* clear all of the tx and rx bits */
ctl &= ~(ARSPI_CTL_TXCNT_MASK | ARSPI_CTL_RXCNT_MASK);
/* now set txcnt */
cnt = 1;
ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT);
cnt = 24;
/* now set txcnt */
if(cmd->rx_cmd_sz < 24)
cnt = cmd->rx_cmd_sz;
ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT);
ctl |= ARSPI_CTL_START;
SPI_WRITE(sc, ARSPI_REG_CTL, ctl);
if(op == 0x0b)
SPI_WRITE(sc, ARSPI_REG_DATA, 0);
if (sc->sc_debug & 0x8000)
printf("\nDATA ");
/*
* Receive/transmit data (depends on command)
*/
// buf_out = (uint8_t *)cmd->tx_data;
buf_in = (uint8_t *)cmd->rx_cmd;
// lout = cmd->tx_data_sz;
lin = cmd->rx_cmd_sz;
if (sc->sc_debug & 0x8000)
printf("t%d r%d ", lout, lin);
for(i = 0; i <= (cnt - 1) / 4; ++i) {
do {
ctl = SPI_READ(sc, ARSPI_REG_CTL);
} while (ctl & ARSPI_CTL_BUSY);
rdat = SPI_READ(sc, ARSPI_REG_DATA);
if (sc->sc_debug & 0x8000)
printf("I%08x ", rdat);
for(j = 0; j < 4; ++j) {
buf_in[i * 4 + j + 1] = 0xff & (rdat >> (8 * j));
if(i * 4 + j + 2 == cnt)
break;
}
}
ar5315_spi_chip_deactivate(sc, devi->cs);
/*
* Close SPI controller interface, restore flash memory mapped access.
*/
if (sc->sc_debug & 0x8000)
printf("\n");
return (0);
}
static int
ar5315_spi_detach(device_t dev)
{
struct ar5315_spi_softc *sc = device_get_softc(dev);
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
return (0);
}
static device_method_t ar5315_spi_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ar5315_spi_probe),
DEVMETHOD(device_attach, ar5315_spi_attach),
DEVMETHOD(device_detach, ar5315_spi_detach),
DEVMETHOD(spibus_transfer, ar5315_spi_transfer),
// DEVMETHOD(spibus_get_block, ar5315_spi_get_block),
DEVMETHOD_END
};
static driver_t ar5315_spi_driver = {
"spi",
ar5315_spi_methods,
sizeof(struct ar5315_spi_softc),
};
static devclass_t ar5315_spi_devclass;
DRIVER_MODULE(ar5315_spi, nexus, ar5315_spi_driver, ar5315_spi_devclass, 0, 0);

View file

@ -0,0 +1,150 @@
/*-
* Copyright (c) 2016, Hiroki Mori
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* 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 unmodified, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*/
/*
* Watchdog driver for AR5315
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/watchdog.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
struct ar5315_wdog_softc {
device_t dev;
int armed;
int reboot_from_watchdog;
int debug;
};
static void
ar5315_wdog_watchdog_fn(void *private, u_int cmd, int *error)
{
struct ar5315_wdog_softc *sc = private;
uint64_t timer_val;
cmd &= WD_INTERVAL;
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: cmd: %x\n", cmd);
if (cmd > 0) {
timer_val = (uint64_t)(1ULL << cmd) * ar531x_ahb_freq() /
1000000000;
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: programming timer: %jx\n", (uintmax_t) timer_val);
/*
* Load timer with large enough value to prevent spurious
* reset
*/
ATH_WRITE_REG(ar531x_wdog_timer(),
ar531x_ahb_freq() * 10);
ATH_WRITE_REG(ar531x_wdog_ctl(),
AR5315_WDOG_CTL_RESET);
ATH_WRITE_REG(ar531x_wdog_timer(),
(timer_val & 0xffffffff));
sc->armed = 1;
*error = 0;
} else {
if (sc->debug)
device_printf(sc->dev, "ar5315_wdog_watchdog_fn: disarming\n");
if (sc->armed) {
ATH_WRITE_REG(ar531x_wdog_ctl(),
AR5315_WDOG_CTL_IGNORE);
sc->armed = 0;
}
}
}
static int
ar5315_wdog_probe(device_t dev)
{
device_set_desc(dev, "Atheros AR531x watchdog timer");
return (0);
}
static void
ar5315_wdog_sysctl(device_t dev)
{
struct ar5315_wdog_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
struct sysctl_oid *tree = device_get_sysctl_tree(sc->dev);
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"debug", CTLFLAG_RW, &sc->debug, 0,
"enable watchdog debugging");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"armed", CTLFLAG_RD, &sc->armed, 0,
"whether the watchdog is armed");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"reboot_from_watchdog", CTLFLAG_RD, &sc->reboot_from_watchdog, 0,
"whether the system rebooted from the watchdog");
}
static int
ar5315_wdog_attach(device_t dev)
{
struct ar5315_wdog_softc *sc = device_get_softc(dev);
/* Initialise */
sc->reboot_from_watchdog = 0;
sc->armed = 0;
sc->debug = 0;
ATH_WRITE_REG(ar531x_wdog_ctl(), AR5315_WDOG_CTL_IGNORE);
sc->dev = dev;
EVENTHANDLER_REGISTER(watchdog_list, ar5315_wdog_watchdog_fn, sc, 0);
ar5315_wdog_sysctl(dev);
return (0);
}
static device_method_t ar5315_wdog_methods[] = {
DEVMETHOD(device_probe, ar5315_wdog_probe),
DEVMETHOD(device_attach, ar5315_wdog_attach),
DEVMETHOD_END
};
static driver_t ar5315_wdog_driver = {
"ar5315_wdog",
ar5315_wdog_methods,
sizeof(struct ar5315_wdog_softc),
};
static devclass_t ar5315_wdog_devclass;
DRIVER_MODULE(ar5315_wdog, apb, ar5315_wdog_driver, ar5315_wdog_devclass, 0, 0);

View file

@ -0,0 +1,244 @@
/* $Id: ar5315reg.h,v 1.3 2011/07/07 05:06:44 matt Exp $ */
/*
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* This code was written by Garrett D'Amore for the Champaign-Urbana
* Community Wireless Network Project.
*
* 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 acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE 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.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_AR5315REG_H_
#define _MIPS_ATHEROS_AR5315REG_H_
#define AR5315_MEM0_BASE 0x00000000 /* sdram */
#define AR5315_MEM1_BASE 0x08000000 /* spi flash */
#define AR5315_WLAN_BASE 0x10000000
#define AR5315_PCI_BASE 0x10100000
#define AR5315_SDRAMCTL_BASE 0x10300000
#define AR5315_LOCAL_BASE 0x10400000 /* local bus */
#define AR5315_ENET_BASE 0x10500000
#define AR5315_SYSREG_BASE 0x11000000
#define AR5315_UART_BASE 0x11100000
#define AR5315_SPI_BASE 0x11300000 /* spi flash */
#define AR5315_BOOTROM_BASE 0x1FC00000 /* boot rom */
#define AR5315_CONFIG_BASE 0x087D0000 /* flash start */
#define AR5315_CONFIG_END 0x087FF000 /* flash end */
#define AR5315_RADIO_END 0x1FFFF000 /* radio end */
#if 0
#define AR5315_PCIEXT_BASE 0x80000000 /* pci external */
#define AR5315_RAM2_BASE 0xc0000000
#define AR5315_RAM3_BASE 0xe0000000
#endif
/*
* SYSREG registers -- offset relative to AR531X_SYSREG_BASE
*/
#define AR5315_SYSREG_COLDRESET 0x0000
#define AR5315_SYSREG_RESETCTL 0x0004
#define AR5315_SYSREG_AHB_ARB_CTL 0x0008
#define AR5315_SYSREG_ENDIAN 0x000c
#define AR5315_SYSREG_NMI_CTL 0x0010
#define AR5315_SYSREG_SREV 0x0014
#define AR5315_SYSREG_IF_CTL 0x0018
#define AR5315_SYSREG_MISC_INTSTAT 0x0020
#define AR5315_SYSREG_MISC_INTMASK 0x0024
#define AR5315_SYSREG_GISR 0x0028
#define AR5315_SYSREG_TIMER 0x0030
#define AR5315_SYSREG_RELOAD 0x0034
#define AR5315_SYSREG_WDOG_TIMER 0x0038
#define AR5315_SYSREG_WDOG_CTL 0x003c
#define AR5315_SYSREG_PERFCNT0 0x0048
#define AR5315_SYSREG_PERFCNT1 0x004c
#define AR5315_SYSREG_AHB_ERR0 0x0050
#define AR5315_SYSREG_AHB_ERR1 0x0054
#define AR5315_SYSREG_AHB_ERR2 0x0058
#define AR5315_SYSREG_AHB_ERR3 0x005c
#define AR5315_SYSREG_AHB_ERR4 0x0060
#define AR5315_SYSREG_PLLC_CTL 0x0064
#define AR5315_SYSREG_PLLV_CTL 0x0068
#define AR5315_SYSREG_CPUCLK 0x006c
#define AR5315_SYSREG_AMBACLK 0x0070
#define AR5315_SYSREG_SYNCCLK 0x0074
#define AR5315_SYSREG_DSL_SLEEP_CTL 0x0080
#define AR5315_SYSREG_DSL_SLEEP_DUR 0x0084
#define AR5315_SYSREG_GPIO_DI 0x0088
#define AR5315_SYSREG_GPIO_DO 0x0090
#define AR5315_SYSREG_GPIO_CR 0x0098
#define AR5315_SYSREG_GPIO_INT 0x00a0
#define AR5315_GPIO_PINS 23
/* Cold resets (AR5315_SYSREG_COLDRESET) */
#define AR5315_COLD_AHB 0x00000001
#define AR5315_COLD_APB 0x00000002
#define AR5315_COLD_CPU 0x00000004
#define AR5315_COLD_CPU_WARM 0x00000008
/* Resets (AR5315_SYSREG_RESETCTL) */
#define AR5315_RESET_WARM_WLAN0_MAC 0x00000001
#define AR5315_RESET_WARM_WLAN0_BB 0x00000002
#define AR5315_RESET_MPEGTS 0x00000004 /* MPEG-TS */
#define AR5315_RESET_PCIDMA 0x00000008 /* PCI dma */
#define AR5315_RESET_MEMCTL 0x00000010
#define AR5315_RESET_LOCAL 0x00000020 /* local bus */
#define AR5315_RESET_I2C 0x00000040 /* i2c */
#define AR5315_RESET_SPI 0x00000080 /* SPI */
#define AR5315_RESET_UART 0x00000100
#define AR5315_RESET_IR 0x00000200 /* infrared */
#define AR5315_RESET_PHY0 0x00000400 /* enet phy */
#define AR5315_RESET_ENET0 0x00000800
/* Watchdog control (AR5315_SYSREG_WDOG_CTL) */
#define AR5315_WDOG_CTL_IGNORE 0x0000
#define AR5315_WDOG_CTL_NMI 0x0001
#define AR5315_WDOG_CTL_RESET 0x0002
/* AR5315 AHB arbitration control (AR5315_SYSREG_AHB_ARB_CTL) */
#define AR5315_ARB_CPU 0x00001
#define AR5315_ARB_WLAN 0x00002
#define AR5315_ARB_MPEGTS 0x00004
#define AR5315_ARB_LOCAL 0x00008
#define AR5315_ARB_PCI 0x00010
#define AR5315_ARB_ENET 0x00020
#define AR5315_ARB_RETRY 0x00100
/* AR5315 endianness control (AR5315_SYSREG_ENDIAN) */
#define AR5315_ENDIAN_AHB 0x00001
#define AR5315_ENDIAN_WLAN 0x00002
#define AR5315_ENDIAN_MPEGTS 0x00004
#define AR5315_ENDIAN_PCI 0x00008
#define AR5315_ENDIAN_MEMCTL 0x00010
#define AR5315_ENDIAN_LOCAL 0x00020
#define AR5315_ENDIAN_ENET 0x00040
#define AR5315_ENDIAN_MERGE 0x00200
#define AR5315_ENDIAN_CPU 0x00400
#define AR5315_ENDIAN_PCIAHB 0x00800
#define AR5315_ENDIAN_PCIAHB_BRIDGE 0x01000
#define AR5315_ENDIAN_SPI 0x08000
#define AR5315_ENDIAN_CPU_DRAM 0x10000
#define AR5315_ENDIAN_CPU_PCI 0x20000
#define AR5315_ENDIAN_CPU_MMR 0x40000
/* AR5315 AHB error bits */
#define AR5315_AHB_ERROR_DET 1 /* error detected */
#define AR5315_AHB_ERROR_OVR 2 /* AHB overflow */
#define AR5315_AHB_ERROR_WDT 4 /* wdt (not hresp) */
/* AR5315 clocks */
#define AR5315_PLLC_REF_DIV(reg) ((reg) & 0x3)
#define AR5315_PLLC_FB_DIV(reg) (((reg) & 0x7c) >> 2)
#define AR5315_PLLC_DIV_2(reg) (((reg) & 0x80) >> 7)
#define AR5315_PLLC_CLKC(reg) (((reg) & 0x1c000) >> 14)
#define AR5315_PLLC_CLKM(reg) (((reg) & 0x700000) >> 20)
#define AR5315_CLOCKCTL_SELECT(reg) ((reg) & 0x3)
#define AR5315_CLOCKCTL_DIV(reg) (((reg) & 0xc) >> 2)
/*
* SDRAMCTL registers -- offset relative to SDRAMCTL
*/
#define AR5315_SDRAMCTL_MEM_CFG 0x0000
#define AR5315_MEM_CFG_DATA_WIDTH __BITS(13,14)
#define AR5315_MEM_CFG_COL_WIDTH __BITS(9,12)
#define AR5315_MEM_CFG_ROW_WIDTH __BITS(5,8)
/* memory config 1 bits */
#define AR531X_MEM_CFG1_BANK0 __BITS(8,10)
#define AR531X_MEM_CFG1_BANK1 __BITS(12,14)
/*
* PCI configuration stuff. I don't pretend to fully understand these
* registers, they seem to be magic numbers in the Linux code.
*/
#define AR5315_PCI_MAC_RC 0x4000
#define AR5315_PCI_MAC_SCR 0x4004
#define AR5315_PCI_MAC_INTPEND 0x4008
#define AR5315_PCI_MAC_SFR 0x400c
#define AR5315_PCI_MAC_PCICFG 0x4010
#define AR5315_PCI_MAC_SREV 0x4020
#define PCI_MAC_RC_MAC 0x1
#define PCI_MAC_RC_BB 0x2
#define PCI_MAC_SCR_SLM_MASK 0x00030000
#define PCI_MAC_SCR_SLM_FWAKE 0x00000000
#define PCI_MAC_SCR_SLM_FSLEEP 0x00010000
#define PCI_MAC_SCR_SLM_NORMAL 0x00020000
#define PCI_MAC_PCICFG_SPWR_DN 0x00010000
/* IRQS */
#define AR5315_CPU_IRQ_MISC 0
#define AR5315_CPU_IRQ_WLAN 1
#define AR5315_CPU_IRQ_ENET 2
#define AR5315_MISC_IRQ_UART 0
#define AR5315_MISC_IRQ_I2C 1
#define AR5315_MISC_IRQ_SPI 2
#define AR5315_MISC_IRQ_AHBE 3
#define AR5315_MISC_IRQ_AHPE 4
#define AR5315_MISC_IRQ_TIMER 5
#define AR5315_MISC_IRQ_GPIO 6
#define AR5315_MISC_IRQ_WDOG 7
#define AR5315_MISC_IRQ_IR 8
#define AR5315_APB_BASE AR5315_SYSREG_BASE
#define AR5315_APB_SIZE 0x06000000
#define ATH_READ_REG(reg) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg)))
#define ATH_WRITE_REG(reg, val) \
*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val)
/* Helpers from NetBSD cdefs.h */
/* __BIT(n): nth bit, where __BIT(0) == 0x1. */
#define __BIT(__n) \
(((__n) >= NBBY * sizeof(uintmax_t)) ? 0 : ((uintmax_t)1 << (__n)))
/* __BITS(m, n): bits m through n, m < n. */
#define __BITS(__m, __n) \
((__BIT(MAX((__m), (__n)) + 1) - 1) ^ (__BIT(MIN((__m), (__n))) - 1))
/* find least significant bit that is set */
#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
#define __SHIFTOUT_MASK(__mask) __SHIFTOUT((__mask), (__mask))
#endif /* _MIPS_ATHEROS_AR531XREG_H_ */

View file

@ -0,0 +1,62 @@
/* $NetBSD: arspireg.h,v 1.1 2006/10/14 15:33:23 gdamore Exp $ */
/*-
* Copyright (c) 2006 Urbana-Champaign Independent Media Center.
* Copyright (c) 2006 Garrett D'Amore.
* All rights reserved.
*
* Portions of this code were written by Garrett D'Amore for the
* Champaign-Urbana Community Wireless Network Project.
*
* 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 acknowledgements:
* This product includes software developed by the Urbana-Champaign
* Independent Media Center.
* This product includes software developed by Garrett D'Amore.
* 4. Urbana-Champaign Independent Media Center's name and Garrett
* D'Amore's name may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER AND GARRETT D'AMORE ``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 THE URBANA-CHAMPAIGN INDEPENDENT
* MEDIA CENTER OR GARRETT D'AMORE 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.
*
* $FreeBSD$
*/
#ifndef _MIPS_ATHEROS_DEV_ARSPIREG_H
#define _MIPS_ATHEROS_DEV_ARSPIREG_H
#define ARSPI_REG_CTL 0x00
#define ARSPI_REG_OPCODE 0x04
#define ARSPI_REG_DATA 0x08
#define ARSPI_CTL_START 0x00000100
#define ARSPI_CTL_BUSY 0x00010000
#define ARSPI_CTL_TXCNT_MASK 0x0000000f
#define ARSPI_CTL_TXCNT_SHIFT 0
#define ARSPI_CTL_RXCNT_MASK 0x000000f0
#define ARSPI_CTL_RXCNT_SHIFT 4
#define ARSPI_CTL_SIZE_MASK 0x00060000
#define ARSPI_CTL_CLKSEL_MASK 0x03000000
#endif /* _MIPS_ATHEROS_DEV_ARSPIREG_H */

View file

@ -0,0 +1,30 @@
# $FreeBSD$
mips/atheros/ar531x/apb.c standard
mips/atheros/ar531x/if_are.c optional are
mips/atheros/ar531x/ar5315_spi.c optional ar5315_spi
mips/atheros/ar531x/ar5315_wdog.c optional ar5315_wdog
mips/atheros/ar531x/ar5315_gpio.c optional gpio
mips/atheros/ar531x/ar5315_machdep.c standard
mips/atheros/ar531x/ar5315_chip.c standard
mips/atheros/ar531x/ar5315_setup.c standard
mips/atheros/ar531x/uart_bus_ar5315.c optional uart_ar5315
mips/atheros/ar531x/uart_cpu_ar5315.c optional uart_ar5315
mips/atheros/ar531x/ar5312_chip.c standard
mips/atheros/ar71xx_bus_space_reversed.c standard
#mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
dev/etherswitch/e6000sw/e6060sw.c optional etherswitch
dev/etherswitch/realtek/rtl830x.c optional etherswitch
# Hack to reuse ARM intrng code
kern/subr_intr.c standard
kern/msi_if.m standard
kern/pic_if.m standard
# Intrng compatible MIPS32 interrupt controller
mips/mips/mips_pic.c standard

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,401 @@
/*-
* Copyright (C) 2007
* Oleksandr Tymoshenko <gonzo@freebsd.org>. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR HIS RELATIVES 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 MIND, 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.
*
* $FreeBSD$
*
*/
#ifndef __IF_AREREG_H__
#define __IF_AREREG_H__
struct are_desc {
uint32_t are_stat;
uint32_t are_devcs;
uint32_t are_addr;
uint32_t are_link;
};
#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1))
#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16)
#define ARE_RX_RING_CNT 128
#define ARE_TX_RING_CNT 128
#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT
#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT
#define ARE_RING_ALIGN sizeof(struct are_desc)
#define ARE_RX_ALIGN sizeof(uint32_t)
#define ARE_MAXFRAGS 8
#define ARE_TX_INTR_THRESH 8
#define ARE_TX_RING_ADDR(sc, i) \
((sc)->are_rdata.are_tx_ring_paddr + sizeof(struct are_desc) * (i))
#define ARE_RX_RING_ADDR(sc, i) \
((sc)->are_rdata.are_rx_ring_paddr + sizeof(struct are_desc) * (i))
#define ARE_INC(x,y) (x) = (((x) + 1) % y)
struct are_txdesc {
struct mbuf *tx_m;
bus_dmamap_t tx_dmamap;
};
struct are_rxdesc {
struct mbuf *rx_m;
bus_dmamap_t rx_dmamap;
struct are_desc *desc;
/* Use this values on error instead of allocating new mbuf */
uint32_t saved_ctl, saved_ca;
};
struct are_chain_data {
bus_dma_tag_t are_parent_tag;
bus_dma_tag_t are_tx_tag;
struct are_txdesc are_txdesc[ARE_TX_RING_CNT];
bus_dma_tag_t are_rx_tag;
struct are_rxdesc are_rxdesc[ARE_RX_RING_CNT];
bus_dma_tag_t are_tx_ring_tag;
bus_dma_tag_t are_rx_ring_tag;
bus_dmamap_t are_tx_ring_map;
bus_dmamap_t are_rx_ring_map;
bus_dmamap_t are_rx_sparemap;
int are_tx_pkts;
int are_tx_prod;
int are_tx_cons;
int are_tx_cnt;
int are_rx_cons;
};
struct are_ring_data {
struct are_desc *are_rx_ring;
struct are_desc *are_tx_ring;
bus_addr_t are_rx_ring_paddr;
bus_addr_t are_tx_ring_paddr;
};
struct are_softc {
struct ifnet *are_ifp; /* interface info */
bus_space_handle_t are_bhandle; /* bus space handle */
bus_space_tag_t are_btag; /* bus space tag */
device_t are_dev;
uint8_t are_eaddr[ETHER_ADDR_LEN];
struct resource *are_res;
int are_rid;
struct resource *are_irq;
void *are_intrhand;
u_int32_t sc_inten; /* copy of CSR_INTEN */
u_int32_t sc_rxint_mask; /* mask of Rx interrupts we want */
u_int32_t sc_txint_mask; /* mask of Tx interrupts we want */
#ifdef ARE_MII
device_t are_miibus;
#else
struct ifmedia are_ifmedia;
#endif
#ifdef ARE_MDIO
device_t are_miiproxy;
#endif
bus_dma_tag_t are_parent_tag;
bus_dma_tag_t are_tag;
struct mtx are_mtx;
struct callout are_stat_callout;
struct task are_link_task;
struct are_chain_data are_cdata;
struct are_ring_data are_rdata;
int are_link_status;
int are_detach;
};
#define ARE_LOCK(_sc) mtx_lock(&(_sc)->are_mtx)
#define ARE_UNLOCK(_sc) mtx_unlock(&(_sc)->are_mtx)
#define ARE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->are_mtx, MA_OWNED)
/*
* register space access macros
*/
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val)
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->are_btag, sc->are_bhandle, reg)
/* $NetBSD: aereg.h,v 1.2 2008/04/28 20:23:28 martin Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 THE FOUNDATION OR CONTRIBUTORS
* 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.
*/
/*
* Descriptor Status bits common to transmit and receive.
*/
#define ADSTAT_OWN 0x80000000 /* Tulip owns descriptor */
#define ADSTAT_ES 0x00008000 /* Error Summary */
/*
* Descriptor Status bits for Receive Descriptor.
*/
#define ADSTAT_Rx_FF 0x40000000 /* Filtering Fail */
#define ADSTAT_Rx_FL 0x3fff0000 /* Frame Length including CRC */
#define ADSTAT_Rx_DE 0x00004000 /* Descriptor Error */
#define ADSTAT_Rx_LE 0x00001000 /* Length Error */
#define ADSTAT_Rx_RF 0x00000800 /* Runt Frame */
#define ADSTAT_Rx_MF 0x00000400 /* Multicast Frame */
#define ADSTAT_Rx_FS 0x00000200 /* First Descriptor */
#define ADSTAT_Rx_LS 0x00000100 /* Last Descriptor */
#define ADSTAT_Rx_TL 0x00000080 /* Frame Too Long */
#define ADSTAT_Rx_CS 0x00000040 /* Collision Seen */
#define ADSTAT_Rx_RT 0x00000020 /* Frame Type */
#define ADSTAT_Rx_RW 0x00000010 /* Receive Watchdog */
#define ADSTAT_Rx_RE 0x00000008 /* Report on MII Error */
#define ADSTAT_Rx_DB 0x00000004 /* Dribbling Bit */
#define ADSTAT_Rx_CE 0x00000002 /* CRC Error */
#define ADSTAT_Rx_ZER 0x00000001 /* Zero (always 0) */
#define ADSTAT_Rx_LENGTH(x) (((x) & ADSTAT_Rx_FL) >> 16)
/*
* Descriptor Status bits for Transmit Descriptor.
*/
#define ADSTAT_Tx_ES 0x00008000 /* Error Summary */
#define ADSTAT_Tx_TO 0x00004000 /* Transmit Jabber Timeout */
#define ADSTAT_Tx_LO 0x00000800 /* Loss of Carrier */
#define ADSTAT_Tx_NC 0x00000400 /* No Carrier */
#define ADSTAT_Tx_LC 0x00000200 /* Late Collision */
#define ADSTAT_Tx_EC 0x00000100 /* Excessive Collisions */
#define ADSTAT_Tx_HF 0x00000080 /* Heartbeat Fail */
#define ADSTAT_Tx_CC 0x00000078 /* Collision Count */
#define ADSTAT_Tx_ED 0x00000004 /* Excessive Deferral */
#define ADSTAT_Tx_UF 0x00000002 /* Underflow Error */
#define ADSTAT_Tx_DE 0x00000001 /* Deferred */
#define ADSTAT_Tx_COLLISIONS(x) (((x) & ADSTAT_Tx_CC) >> 3)
/*
* Descriptor Control bits common to transmit and receive.
*/
#define ADCTL_SIZE1 0x000007ff /* Size of buffer 1 */
#define ADCTL_SIZE1_SHIFT 0
#define ADCTL_SIZE2 0x003ff800 /* Size of buffer 2 */
#define ADCTL_SIZE2_SHIFT 11
#define ADCTL_ER 0x02000000 /* End of Ring */
#define ADCTL_CH 0x01000000 /* Second Address Chained */
/*
* Descriptor Control bits for Transmit Descriptor.
*/
#define ADCTL_Tx_IC 0x80000000 /* Interrupt on Completion */
#define ADCTL_Tx_LS 0x40000000 /* Last Segment */
#define ADCTL_Tx_FS 0x20000000 /* First Segment */
#define ADCTL_Tx_AC 0x04000000 /* Add CRC Disable */
#define ADCTL_Tx_DPD 0x00800000 /* Disabled Padding */
/*
* Control registers.
*/
/* tese are registers only found on this part */
#define CSR_MACCTL 0x0000 /* mac control */
#define CSR_MACHI 0x0004
#define CSR_MACLO 0x0008
#define CSR_HTHI 0x000C /* multicast table high */
#define CSR_HTLO 0x0010 /* multicast table low */
#define CSR_MIIADDR 0x0014 /* mii address */
#define CSR_MIIDATA 0x0018 /* mii data */
#define CSR_FLOWC 0x001C /* flow control */
#define CSR_VL1 0x0020 /* vlan 1 tag */
/* these are more or less normal Tulip registers */
#define CSR_BUSMODE 0x1000 /* bus mode */
#define CSR_TXPOLL 0x1004 /* tx poll demand */
#define CSR_RXPOLL 0x1008 /* rx poll demand */
#define CSR_RXLIST 0x100C /* rx base descriptor address */
#define CSR_TXLIST 0x1010 /* tx base descriptor address */
#define CSR_STATUS 0x1014 /* (interrupt) status */
#define CSR_OPMODE 0x1018 /* operation mode */
#define CSR_INTEN 0x101C /* interrupt enable */
#define CSR_MISSED 0x1020 /* missed frame counter */
#define CSR_HTBA 0x1050 /* host tx buffer address (ro) */
#define CSR_HRBA 0x1054 /* host rx buffer address (ro) */
/* CSR_MACCTL - Mac Control */
#define MACCTL_RE 0x00000004 /* rx enable */
#define MACCTL_TE 0x00000008 /* tx enable */
#define MACCTL_DC 0x00000020 /* deferral check */
#define MACCTL_PSTR 0x00000100 /* automatic pad strip */
#define MACCTL_DTRY 0x00000400 /* disable retry */
#define MACCTL_DBF 0x00000800 /* disable broadcast frames */
#define MACCTL_LCC 0x00001000 /* late collision control */
#define MACCTL_HASH 0x00002000 /* hash filtering enable */
#define MACCTL_HO 0x00008000 /* disable perfect filtering */
#define MACCTL_PB 0x00010000 /* pass bad frames */
#define MACCTL_IF 0x00020000 /* inverse filtering */
#define MACCTL_PR 0x00040000 /* promiscuous mode */
#define MACCTL_PM 0x00080000 /* pass all multicast */
#define MACCTL_FDX 0x00100000 /* full duplex mode */
#define MACCTL_LOOP 0x00600000 /* loopback mask */
#define MACCTL_LOOP_INT 0x00200000 /* internal loopback */
#define MACCTL_LOOP_EXT 0x00400000 /* external loopback */
#define MACCTL_LOOP_NONE 0x00000000
#define MACCTL_DRO 0x00800000 /* disable receive own */
#define MACCTL_PS 0x08000000 /* port select, 0 = mii */
#define MACCTL_HBD 0x10000000 /* heartbeat disable */
#define MACCTL_BLE 0x40000000 /* mac big endian */
#define MACCTL_RA 0x80000000 /* receive all packets */
/* CSR_MIIADDR - MII Addess */
#define MIIADDR_BUSY 0x00000001 /* mii busy */
#define MIIADDR_WRITE 0x00000002 /* mii write */
#define MIIADDR_REG_MASK 0x000007C0 /* mii register */
#define MIIADDR_REG_SHIFT 6
#define MIIADDR_PHY_MASK 0x0000F800 /* mii phy */
#define MIIADDR_PHY_SHIFT 11
#define MIIADDR_GETREG(x) (((x) & MIIADDR_REG) >> 6)
#define MIIADDR_PUTREG(x) (((x) << 6) & MIIADR_REG)
#define MIIADDR_GETPHY(x) (((x) & MIIADDR_PHY) >> 11)
#define MIIADDR_PUTPHY(x) (((x) << 6) & MIIADR_PHY)
/* CSR_FLOWC - Flow Control */
#define FLOWC_FCB 0x00000001 /* flow control busy */
#define FLOWC_FCE 0x00000002 /* flow control enable */
#define FLOWC_PCF 0x00000004 /* pass control frames */
#define FLOWC_PT 0xffff0000 /* pause time */
/* CSR_BUSMODE - Bus Mode */
#define BUSMODE_SWR 0x00000001 /* software reset */
#define BUSMODE_BAR 0x00000002 /* bus arbitration */
#define BUSMODE_DSL 0x0000007c /* descriptor skip length */
#define BUSMODE_BLE 0x00000080 /* data buf endian */
/* programmable burst length */
#define BUSMODE_PBL_DEFAULT 0x00000000 /* default value */
#define BUSMODE_PBL_1LW 0x00000100 /* 1 longword */
#define BUSMODE_PBL_2LW 0x00000200 /* 2 longwords */
#define BUSMODE_PBL_4LW 0x00000400 /* 4 longwords */
#define BUSMODE_PBL_8LW 0x00000800 /* 8 longwords */
#define BUSMODE_PBL_16LW 0x00001000 /* 16 longwords */
#define BUSMODE_PBL_32LW 0x00002000 /* 32 longwords */
#define BUSMODE_DBO 0x00100000 /* descriptor endian */
#define BUSMODE_ALIGN_16B 0x01000000 /* force oddhw rx buf align */
/* CSR_TXPOLL - Transmit Poll Demand */
#define TXPOLL_TPD 0x00000001 /* transmit poll demand */
/* CSR_RXPOLL - Receive Poll Demand */
#define RXPOLL_RPD 0x00000001 /* receive poll demand */
/* CSR_STATUS - Status */
#define STATUS_TI 0x00000001 /* transmit interrupt */
#define STATUS_TPS 0x00000002 /* transmit process stopped */
#define STATUS_TU 0x00000004 /* transmit buffer unavail */
#define STATUS_TJT 0x00000008 /* transmit jabber timeout */
#define STATUS_UNF 0x00000020 /* transmit underflow */
#define STATUS_RI 0x00000040 /* receive interrupt */
#define STATUS_RU 0x00000080 /* receive buffer unavail */
#define STATUS_RPS 0x00000100 /* receive process stopped */
#define STATUS_ETI 0x00000400 /* early transmit interrupt */
#define STATUS_SE 0x00002000 /* system error */
#define STATUS_ER 0x00004000 /* early receive (21041) */
#define STATUS_AIS 0x00008000 /* abnormal intr summary */
#define STATUS_NIS 0x00010000 /* normal interrupt summary */
#define STATUS_RS 0x000e0000 /* receive process state */
#define STATUS_RS_STOPPED 0x00000000 /* Stopped */
#define STATUS_RS_FETCH 0x00020000 /* Running - fetch receive
descriptor */
#define STATUS_RS_CHECK 0x00040000 /* Running - check for end
of receive */
#define STATUS_RS_WAIT 0x00060000 /* Running - wait for packet */
#define STATUS_RS_SUSPENDED 0x00080000 /* Suspended */
#define STATUS_RS_CLOSE 0x000a0000 /* Running - close receive
descriptor */
#define STATUS_RS_FLUSH 0x000c0000 /* Running - flush current
frame from FIFO */
#define STATUS_RS_QUEUE 0x000e0000 /* Running - queue current
frame from FIFO into
buffer */
#define STATUS_TS 0x00700000 /* transmit process state */
#define STATUS_TS_STOPPED 0x00000000 /* Stopped */
#define STATUS_TS_FETCH 0x00100000 /* Running - fetch transmit
descriptor */
#define STATUS_TS_WAIT 0x00200000 /* Running - wait for end
of transmission */
#define STATUS_TS_READING 0x00300000 /* Running - read buffer from
memory and queue into
FIFO */
#define STATUS_TS_SUSPENDED 0x00600000 /* Suspended */
#define STATUS_TS_CLOSE 0x00700000 /* Running - close transmit
descriptor */
#define STATUS_TX_ABORT 0x00800000 /* Transmit bus abort */
#define STATUS_RX_ABORT 0x01000000 /* Transmit bus abort */
/* CSR_OPMODE - Operation Mode */
#define OPMODE_SR 0x00000002 /* start receive */
#define OPMODE_OSF 0x00000004 /* operate on second frame */
#define OPMODE_ST 0x00002000 /* start transmitter */
#define OPMODE_TR 0x0000c000 /* threshold control */
#define OPMODE_TR_32 0x00000000 /* 32 words */
#define OPMODE_TR_64 0x00004000 /* 64 words */
#define OPMODE_TR_128 0x00008000 /* 128 words */
#define OPMODE_TR_256 0x0000c000 /* 256 words */
#define OPMODE_SF 0x00200000 /* store and forward mode */
/* CSR_INTEN - Interrupt Enable */
/* See bits for CSR_STATUS -- Status */
/* CSR_MISSED - Missed Frames */
#define MISSED_MFC 0xffff0000 /* missed packet count */
#define MISSED_FOC 0x0000ffff /* fifo overflow counter */
#define MISSED_GETMFC(x) ((x) & MISSED_MFC)
#define MISSED_GETFOC(x) (((x) & MISSED_FOC) >> 16)
#endif /* __IF_AREREG_H__ */

View file

@ -0,0 +1,89 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include "uart_if.h"
static int uart_ar5315_probe(device_t dev);
extern struct uart_class uart_ar5315_uart_class;
static device_method_t uart_ar5315_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_ar5315_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
DEVMETHOD_END
};
static driver_t uart_ar5315_driver = {
uart_driver_name,
uart_ar5315_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_ar5315_probe(device_t dev)
{
struct uart_softc *sc;
uint64_t freq;
freq = ar531x_ahb_freq();
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_ns8250_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.regshft = 2;
sc->sc_sysdev->bas.bst = mips_bus_space_generic;
sc->sc_sysdev->bas.bsh = ar531x_uart_addr() + 3;
sc->sc_bas.regshft = 2;
sc->sc_bas.bst = mips_bus_space_generic;
sc->sc_bas.bsh = ar531x_uart_addr() + 3;
return (uart_bus_probe(dev, 2, freq, 0, 0));
}
DRIVER_MODULE(uart, apb, uart_ar5315_driver, uart_devclass, 0, 0);

View file

@ -0,0 +1,76 @@
/*-
* Copyright (c) 2009 Oleksandr Tymoshenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
*
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <mips/atheros/ar531x/ar5315reg.h>
#include <mips/atheros/ar531x/ar5315_cpudef.h>
#include <mips/atheros/ar71xx_bus_space_reversed.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
uint64_t freq;
freq = ar531x_ahb_freq();
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = ar71xx_bus_space_reversed;
di->bas.regshft = 2;
di->bas.rclk = freq;
di->baudrate = 9600; // RedBoot default is 9600
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = ar71xx_bus_space_reversed;
di->bas.bsh = ar531x_uart_addr();
return (0);
}