Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/ti/ti_pruss.c
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
#include <machine/frame.h> | #include <machine/frame.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#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 <arm/ti/ti_prcm.h> | #include <dev/extres/clk/clk.h> | ||||
#include <arm/ti/ti_sysc.h> | |||||
#include <arm/ti/ti_pruss.h> | #include <arm/ti/ti_pruss.h> | ||||
#include <arm/ti/ti_prm.h> | |||||
#ifdef DEBUG | #ifdef DEBUG | ||||
#define DPRINTF(fmt, ...) do { \ | #define DPRINTF(fmt, ...) do { \ | ||||
printf("%s: ", __func__); \ | printf("%s: ", __func__); \ | ||||
printf(fmt, __VA_ARGS__); \ | printf(fmt, __VA_ARGS__); \ | ||||
} while (0) | } while (0) | ||||
#else | #else | ||||
#define DPRINTF(fmt, ...) | #define DPRINTF(fmt, ...) | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | static driver_t ti_pruss_driver = { | ||||
"ti_pruss", | "ti_pruss", | ||||
ti_pruss_methods, | ti_pruss_methods, | ||||
sizeof(struct ti_pruss_softc) | sizeof(struct ti_pruss_softc) | ||||
}; | }; | ||||
static devclass_t ti_pruss_devclass; | static devclass_t ti_pruss_devclass; | ||||
DRIVER_MODULE(ti_pruss, simplebus, ti_pruss_driver, ti_pruss_devclass, 0, 0); | DRIVER_MODULE(ti_pruss, simplebus, ti_pruss_driver, ti_pruss_devclass, 0, 0); | ||||
MODULE_DEPEND(ti_pruss, ti_prcm, 1, 1, 1); | MODULE_DEPEND(ti_pruss, ti_sysc, 1, 1, 1); | ||||
MODULE_DEPEND(ti_pruss, ti_prm, 1, 1, 1); | |||||
static struct resource_spec ti_pruss_irq_spec[] = { | static struct resource_spec ti_pruss_irq_spec[] = { | ||||
{ SYS_RES_IRQ, 0, RF_ACTIVE }, | { SYS_RES_IRQ, 0, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 1, RF_ACTIVE }, | { SYS_RES_IRQ, 1, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 2, RF_ACTIVE }, | { SYS_RES_IRQ, 2, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 3, RF_ACTIVE }, | { SYS_RES_IRQ, 3, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 4, RF_ACTIVE }, | { SYS_RES_IRQ, 4, RF_ACTIVE }, | ||||
{ SYS_RES_IRQ, 5, RF_ACTIVE }, | { SYS_RES_IRQ, 5, RF_ACTIVE }, | ||||
▲ Show 20 Lines • Show All 337 Lines • ▼ Show 20 Lines | ti_pruss_probe(device_t dev) | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | static int | ||||
ti_pruss_attach(device_t dev) | ti_pruss_attach(device_t dev) | ||||
{ | { | ||||
struct ti_pruss_softc *sc; | struct ti_pruss_softc *sc; | ||||
int rid, i; | int rid, i, err, ncells; | ||||
uint32_t reg; | |||||
phandle_t node; | |||||
clk_t l3_gclk, pruss_ocp_gclk; | |||||
phandle_t ti_prm_ref, *cells; | |||||
device_t ti_prm_dev; | |||||
if (ti_prcm_clk_enable(PRUSS_CLK) != 0) { | rid = 0; | ||||
device_printf(dev, "could not enable PRUSS clock\n"); | sc = device_get_softc(dev); | ||||
node = ofw_bus_get_node(device_get_parent(dev)); | |||||
if (node <= 0) { | |||||
device_printf(dev, "Cant get ofw node\n"); | |||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
sc = device_get_softc(dev); | |||||
rid = 0; | /* | ||||
* Follow activate pattern from sys/arm/ti/am335x/am335x_prcm.c | |||||
* by Damjan Marion | |||||
*/ | |||||
/* Set MODULEMODE to ENABLE(2) */ | |||||
/* Wait for MODULEMODE to become ENABLE(2) */ | |||||
if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) { | |||||
device_printf(dev, "Could not enable PRUSS clock\n"); | |||||
return (ENXIO); | |||||
} | |||||
/* Set CLKTRCTRL to SW_WKUP(2) */ | |||||
/* Wait for the 200 MHz OCP clock to become active */ | |||||
/* Wait for the 200 MHz IEP clock to become active */ | |||||
/* Wait for the 192 MHz UART clock to become active */ | |||||
/* | |||||
* At the moment there is no reference to CM_PER_PRU_ICSS_CLKSTCTRL@140 | |||||
* in the devicetree. The register reset state are SW_WKUP(2) as default | |||||
* so at the moment ignore setting this register. | |||||
*/ | |||||
/* Select L3F as OCP clock */ | |||||
/* Get the clock and set the parent */ | |||||
err = clk_get_by_name(dev, "l3_gclk", &l3_gclk); | |||||
if (err) { | |||||
device_printf(dev, "Cant get l3_gclk err %d\n", err); | |||||
return (ENXIO); | |||||
} | |||||
err = clk_get_by_name(dev, "pruss_ocp_gclk@530", &pruss_ocp_gclk); | |||||
if (err) { | |||||
device_printf(dev, "Cant get pruss_ocp_gclk@530 err %d\n", err); | |||||
return (ENXIO); | |||||
} | |||||
err = clk_set_parent_by_clk(pruss_ocp_gclk, l3_gclk); | |||||
if (err) { | |||||
device_printf(dev, | |||||
"Cant set pruss_ocp_gclk parent to l3_gclk err %d\n", err); | |||||
return (ENXIO); | |||||
} | |||||
/* Clear the RESET bit */ | |||||
/* Find the ti_prm */ | |||||
/* #reset-cells should not been used in this way but... */ | |||||
err = ofw_bus_parse_xref_list_alloc(node, "resets", "#reset-cells", 0, | |||||
&ti_prm_ref, &ncells, &cells); | |||||
OF_prop_free(cells); | |||||
if (err) { | |||||
device_printf(dev, | |||||
"Cant fetch \"resets\" reference %x\n", err); | |||||
return (ENXIO); | |||||
} | |||||
ti_prm_dev = OF_device_from_xref(ti_prm_ref); | |||||
if (ti_prm_dev == NULL) { | |||||
device_printf(dev, "Cant get device from \"resets\"\n"); | |||||
return (ENXIO); | |||||
} | |||||
err = ti_prm_reset(ti_prm_dev); | |||||
if (err) { | |||||
device_printf(dev, "ti_prm_reset failed %d\n", err); | |||||
return (ENXIO); | |||||
} | |||||
/* End of clock activation */ | |||||
mtx_init(&sc->sc_mtx, "TI PRUSS", NULL, MTX_DEF); | mtx_init(&sc->sc_mtx, "TI PRUSS", NULL, MTX_DEF); | ||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | ||||
RF_ACTIVE); | RF_ACTIVE); | ||||
if (sc->sc_mem_res == NULL) { | if (sc->sc_mem_res == NULL) { | ||||
device_printf(dev, "could not allocate memory resource\n"); | device_printf(dev, "could not allocate memory resource\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | if (i < TI_PRUSS_HOST_IRQS) { | ||||
ti_pruss_detach(dev); | ti_pruss_detach(dev); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
mtx_init(&sc->sc_irq_devs[i].sc_mtx, "TI PRUSS IRQ", NULL, MTX_DEF); | mtx_init(&sc->sc_irq_devs[i].sc_mtx, "TI PRUSS IRQ", NULL, MTX_DEF); | ||||
knlist_init_mtx(&sc->sc_irq_devs[i].sc_selinfo.si_note, &sc->sc_irq_devs[i].sc_mtx); | knlist_init_mtx(&sc->sc_irq_devs[i].sc_selinfo.si_note, &sc->sc_irq_devs[i].sc_mtx); | ||||
} | } | ||||
} | } | ||||
reg = ti_pruss_reg_read(sc, | |||||
ti_sysc_get_sysc_address_offset_host(device_get_parent(dev))); | |||||
if (ti_pruss_reg_read(sc, PRUSS_AM33XX_INTC) == PRUSS_AM33XX_REV) | if (ti_pruss_reg_read(sc, PRUSS_AM33XX_INTC) == PRUSS_AM33XX_REV) | ||||
device_printf(dev, "AM33xx PRU-ICSS\n"); | device_printf(dev, "AM33xx PRU-ICSS\n"); | ||||
sc->sc_pdev = make_dev(&ti_pruss_cdevsw, 0, UID_ROOT, GID_WHEEL, | sc->sc_pdev = make_dev(&ti_pruss_cdevsw, 0, UID_ROOT, GID_WHEEL, | ||||
0600, "pruss%d", device_get_unit(dev)); | 0600, "pruss%d", device_get_unit(dev)); | ||||
sc->sc_pdev->si_drv1 = dev; | sc->sc_pdev->si_drv1 = dev; | ||||
▲ Show 20 Lines • Show All 161 Lines • Show Last 20 Lines |