Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/allwinner/if_emac.c
Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/mii/mii.h> | #include <dev/mii/mii.h> | ||||
#include <dev/mii/miivar.h> | #include <dev/mii/miivar.h> | ||||
#include <arm/allwinner/if_emacreg.h> | #include <arm/allwinner/if_emacreg.h> | ||||
#include <dev/extres/clk/clk.h> | |||||
#include "miibus_if.h" | #include "miibus_if.h" | ||||
#include "gpio_if.h" | #include "gpio_if.h" | ||||
#include "a10_clk.h" | |||||
#include "a10_sramc.h" | #include "a10_sramc.h" | ||||
struct emac_softc { | struct emac_softc { | ||||
struct ifnet *emac_ifp; | struct ifnet *emac_ifp; | ||||
device_t emac_dev; | device_t emac_dev; | ||||
device_t emac_miibus; | device_t emac_miibus; | ||||
bus_space_handle_t emac_handle; | bus_space_handle_t emac_handle; | ||||
bus_space_tag_t emac_tag; | bus_space_tag_t emac_tag; | ||||
struct resource *emac_res; | struct resource *emac_res; | ||||
struct resource *emac_irq; | struct resource *emac_irq; | ||||
void *emac_intrhand; | void *emac_intrhand; | ||||
clk_t emac_clk; | |||||
int emac_if_flags; | int emac_if_flags; | ||||
struct mtx emac_mtx; | struct mtx emac_mtx; | ||||
struct callout emac_tick_ch; | struct callout emac_tick_ch; | ||||
int emac_watchdog_timer; | int emac_watchdog_timer; | ||||
int emac_rx_process_limit; | int emac_rx_process_limit; | ||||
int emac_link; | int emac_link; | ||||
uint32_t emac_fifo_mask; | uint32_t emac_fifo_mask; | ||||
}; | }; | ||||
static int emac_probe(device_t); | static int emac_probe(device_t); | ||||
static int emac_attach(device_t); | static int emac_attach(device_t); | ||||
static int emac_detach(device_t); | static int emac_detach(device_t); | ||||
static int emac_shutdown(device_t); | static int emac_shutdown(device_t); | ||||
static int emac_suspend(device_t); | static int emac_suspend(device_t); | ||||
static int emac_resume(device_t); | static int emac_resume(device_t); | ||||
static void emac_sys_setup(void); | static int emac_sys_setup(struct emac_softc *); | ||||
static void emac_reset(struct emac_softc *); | static void emac_reset(struct emac_softc *); | ||||
static void emac_init_locked(struct emac_softc *); | static void emac_init_locked(struct emac_softc *); | ||||
static void emac_start_locked(struct ifnet *); | static void emac_start_locked(struct ifnet *); | ||||
static void emac_init(void *); | static void emac_init(void *); | ||||
static void emac_stop_locked(struct emac_softc *); | static void emac_stop_locked(struct emac_softc *); | ||||
static void emac_intr(void *); | static void emac_intr(void *); | ||||
static int emac_ioctl(struct ifnet *, u_long, caddr_t); | static int emac_ioctl(struct ifnet *, u_long, caddr_t); | ||||
Show All 11 Lines | |||||
static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); | static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); | ||||
static int sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS); | static int sysctl_hw_emac_proc_limit(SYSCTL_HANDLER_ARGS); | ||||
#define EMAC_READ_REG(sc, reg) \ | #define EMAC_READ_REG(sc, reg) \ | ||||
bus_space_read_4(sc->emac_tag, sc->emac_handle, reg) | bus_space_read_4(sc->emac_tag, sc->emac_handle, reg) | ||||
#define EMAC_WRITE_REG(sc, reg, val) \ | #define EMAC_WRITE_REG(sc, reg, val) \ | ||||
bus_space_write_4(sc->emac_tag, sc->emac_handle, reg, val) | bus_space_write_4(sc->emac_tag, sc->emac_handle, reg, val) | ||||
static void | static int | ||||
emac_sys_setup(void) | emac_sys_setup(struct emac_softc *sc) | ||||
{ | { | ||||
int error; | |||||
/* Activate EMAC clock. */ | /* Activate EMAC clock. */ | ||||
a10_clk_emac_activate(); | error = clk_get_by_ofw_index(sc->emac_dev, 0, &sc->emac_clk); | ||||
if (error != 0) { | |||||
device_printf(sc->emac_dev, "cannot get clock\n"); | |||||
return (error); | |||||
} | |||||
error = clk_enable(sc->emac_clk); | |||||
if (error != 0) { | |||||
device_printf(sc->emac_dev, "cannot enable clock\n"); | |||||
return (error); | |||||
} | |||||
/* Map sram. */ | /* Map sram. */ | ||||
a10_map_to_emac(); | a10_map_to_emac(); | ||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
emac_get_hwaddr(struct emac_softc *sc, uint8_t *hwaddr) | emac_get_hwaddr(struct emac_softc *sc, uint8_t *hwaddr) | ||||
{ | { | ||||
uint32_t val0, val1, rnd; | uint32_t val0, val1, rnd; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 622 Lines • ▼ Show 20 Lines | if (sc->emac_intrhand != NULL) | ||||
bus_teardown_intr(sc->emac_dev, sc->emac_irq, | bus_teardown_intr(sc->emac_dev, sc->emac_irq, | ||||
sc->emac_intrhand); | sc->emac_intrhand); | ||||
if (sc->emac_miibus != NULL) { | if (sc->emac_miibus != NULL) { | ||||
device_delete_child(sc->emac_dev, sc->emac_miibus); | device_delete_child(sc->emac_dev, sc->emac_miibus); | ||||
bus_generic_detach(sc->emac_dev); | bus_generic_detach(sc->emac_dev); | ||||
} | } | ||||
if (sc->emac_clk != NULL) | |||||
clk_disable(sc->emac_clk); | |||||
if (sc->emac_res != NULL) | if (sc->emac_res != NULL) | ||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->emac_res); | bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->emac_res); | ||||
if (sc->emac_irq != NULL) | if (sc->emac_irq != NULL) | ||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->emac_irq); | bus_release_resource(dev, SYS_RES_IRQ, 0, sc->emac_irq); | ||||
if (sc->emac_ifp != NULL) | if (sc->emac_ifp != NULL) | ||||
if_free(sc->emac_ifp); | if_free(sc->emac_ifp); | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
if (sc->emac_rx_process_limit < EMAC_PROC_MIN || | if (sc->emac_rx_process_limit < EMAC_PROC_MIN || | ||||
sc->emac_rx_process_limit > EMAC_PROC_MAX) { | sc->emac_rx_process_limit > EMAC_PROC_MAX) { | ||||
device_printf(dev, "process_limit value out of range; " | device_printf(dev, "process_limit value out of range; " | ||||
"using default: %d\n", EMAC_PROC_DEFAULT); | "using default: %d\n", EMAC_PROC_DEFAULT); | ||||
sc->emac_rx_process_limit = EMAC_PROC_DEFAULT; | sc->emac_rx_process_limit = EMAC_PROC_DEFAULT; | ||||
} | } | ||||
} | } | ||||
/* Setup EMAC */ | /* Setup EMAC */ | ||||
emac_sys_setup(); | error = emac_sys_setup(sc); | ||||
if (error != 0) | |||||
goto fail; | |||||
emac_reset(sc); | emac_reset(sc); | ||||
ifp = sc->emac_ifp = if_alloc(IFT_ETHER); | ifp = sc->emac_ifp = if_alloc(IFT_ETHER); | ||||
if (ifp == NULL) { | if (ifp == NULL) { | ||||
device_printf(dev, "unable to allocate ifp\n"); | device_printf(dev, "unable to allocate ifp\n"); | ||||
error = ENOSPC; | error = ENOSPC; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 250 Lines • Show Last 20 Lines |