Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/cesa/cesa.c
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
#include <machine/fdt.h> | #include <machine/fdt.h> | ||||
#include <dev/fdt/simplebus.h> | |||||
#include <dev/fdt/fdt_common.h> | #include <dev/fdt/fdt_common.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 <sys/md5.h> | #include <sys/md5.h> | ||||
#include <crypto/sha1.h> | #include <crypto/sha1.h> | ||||
#include <crypto/sha2/sha256.h> | #include <crypto/sha2/sha256.h> | ||||
#include <crypto/rijndael/rijndael.h> | #include <crypto/rijndael/rijndael.h> | ||||
#include <opencrypto/cryptodev.h> | #include <opencrypto/cryptodev.h> | ||||
#include "cryptodev_if.h" | #include "cryptodev_if.h" | ||||
#include <arm/mv/mvreg.h> | #include <arm/mv/mvreg.h> | ||||
#include <arm/mv/mvvar.h> | #include <arm/mv/mvvar.h> | ||||
#include "cesa.h" | #include "cesa.h" | ||||
static int cesa_probe(device_t); | static int cesa_probe(device_t); | ||||
static int cesa_attach(device_t); | static int cesa_attach(device_t); | ||||
static int cesa_attach_late(device_t); | |||||
static int cesa_detach(device_t); | static int cesa_detach(device_t); | ||||
static void cesa_intr(void *); | static void cesa_intr(void *); | ||||
static int cesa_newsession(device_t, u_int32_t *, struct cryptoini *); | static int cesa_newsession(device_t, u_int32_t *, struct cryptoini *); | ||||
static int cesa_freesession(device_t, u_int64_t); | static int cesa_freesession(device_t, u_int64_t); | ||||
static int cesa_process(device_t, struct cryptop *, int); | static int cesa_process(device_t, struct cryptop *, int); | ||||
static struct resource_spec cesa_res_spec[] = { | static struct resource_spec cesa_res_spec[] = { | ||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, | { SYS_RES_MEMORY, 0, RF_ACTIVE }, | ||||
▲ Show 20 Lines • Show All 911 Lines • ▼ Show 20 Lines | cesa_setup_sram(struct cesa_softc *sc) | ||||
sram_va = pmap_mapdev(sc->sc_sram_base_pa, sc->sc_sram_size); | sram_va = pmap_mapdev(sc->sc_sram_base_pa, sc->sc_sram_size); | ||||
if (sram_va == NULL) | if (sram_va == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
sc->sc_sram_base_va = (vm_offset_t)sram_va; | sc->sc_sram_base_va = (vm_offset_t)sram_va; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* Function: device_from_node | |||||
* This function returns appropriate device_t to phandle_t | |||||
* Parameters: | |||||
* root - device where you want to start search | |||||
* if you provide NULL here, function will take | |||||
* "root0" device as root. | |||||
* node - we are checking every device_t to be | |||||
* appropriate with this. | |||||
*/ | |||||
static device_t | |||||
device_from_node(device_t root, phandle_t node) | |||||
{ | |||||
device_t *children, retval; | |||||
int nkid, i; | |||||
/* Nothing matches no node */ | |||||
if (node == -1) | |||||
return (NULL); | |||||
if (root == NULL) | |||||
/* Get root of device tree */ | |||||
if ((root = device_lookup_by_name("root0")) == NULL) | |||||
return (NULL); | |||||
if (device_get_children(root, &children, &nkid) != 0) | |||||
return (NULL); | |||||
retval = NULL; | |||||
for (i = 0; i < nkid; i++) { | |||||
/* Check if device and node matches */ | |||||
if (OFW_BUS_GET_NODE(root, children[i]) == node) { | |||||
retval = children[i]; | |||||
break; | |||||
} | |||||
/* or go deeper */ | |||||
if ((retval = device_from_node(children[i], node)) != NULL) | |||||
break; | |||||
} | |||||
free(children, M_TEMP); | |||||
return (retval); | |||||
} | |||||
static int | static int | ||||
cesa_setup_sram_armada(struct cesa_softc *sc) | |||||
{ | |||||
phandle_t sram_node; | |||||
ihandle_t sram_ihandle; | |||||
pcell_t sram_handle[2]; | |||||
void *sram_va; | |||||
int rv, j; | |||||
struct resource_list rl; | |||||
struct resource_list_entry *rle; | |||||
struct simplebus_softc *ssc; | |||||
device_t sdev; | |||||
/* Get refs to SRAMS from CESA node */ | |||||
rv = OF_getencprop(ofw_bus_get_node(sc->sc_dev), "marvell,crypto-srams", | |||||
(void *)sram_handle, sizeof(sram_handle)); | |||||
if (rv <= 0) | |||||
return (rv); | |||||
if (sc->sc_cesa_engine_id >= 2) | |||||
return (ENXIO); | |||||
/* Get SRAM node on the basis of sc_cesa_engine_id */ | |||||
sram_ihandle = (ihandle_t)sram_handle[sc->sc_cesa_engine_id]; | |||||
sram_node = OF_instance_to_package(sram_ihandle); | |||||
/* Get device_t of simplebus (sram_node parent) */ | |||||
sdev = device_from_node(NULL, OF_parent(sram_node)); | |||||
if (!sdev) | |||||
return (ENXIO); | |||||
ssc = device_get_softc(sdev); | |||||
resource_list_init(&rl); | |||||
/* Parse reg property to resource list */ | |||||
ofw_bus_reg_to_rl(sdev, sram_node, ssc->acells, | |||||
ssc->scells, &rl); | |||||
/* We expect only one resource */ | |||||
rle = resource_list_find(&rl, SYS_RES_MEMORY, 0); | |||||
if (rle == NULL) | |||||
return (ENXIO); | |||||
/* Remap through ranges property */ | |||||
for (j = 0; j < ssc->nranges; j++) { | |||||
if (rle->start >= ssc->ranges[j].bus && | |||||
rle->end < ssc->ranges[j].bus + ssc->ranges[j].size) { | |||||
rle->start -= ssc->ranges[j].bus; | |||||
rle->start += ssc->ranges[j].host; | |||||
rle->end -= ssc->ranges[j].bus; | |||||
rle->end += ssc->ranges[j].host; | |||||
} | |||||
} | |||||
sc->sc_sram_base_pa = rle->start; | |||||
sc->sc_sram_size = rle->count; | |||||
/* SRAM memory was not mapped in platform_sram_devmap(), map it now */ | |||||
sram_va = pmap_mapdev(sc->sc_sram_base_pa, sc->sc_sram_size); | |||||
if (sram_va == NULL) | |||||
return (ENOMEM); | |||||
sc->sc_sram_base_va = (vm_offset_t)sram_va; | |||||
return (0); | |||||
} | |||||
struct ofw_compat_data cesa_devices[] = { | |||||
{ "mrvl,cesa", (uintptr_t)true }, | |||||
{ "marvell,armada-38x-crypto", (uintptr_t)true }, | |||||
{ NULL, 0 } | |||||
}; | |||||
static int | |||||
cesa_probe(device_t dev) | cesa_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (!ofw_bus_is_compatible(dev, "mrvl,cesa")) | if (!ofw_bus_search_compatible(dev, cesa_devices)->ocd_data) | ||||
return (ENXIO); | return (ENXIO); | ||||
device_set_desc(dev, "Marvell Cryptographic Engine and Security " | device_set_desc(dev, "Marvell Cryptographic Engine and Security " | ||||
"Accelerator"); | "Accelerator"); | ||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
static int | static int | ||||
cesa_attach(device_t dev) | cesa_attach(device_t dev) | ||||
{ | { | ||||
static int engine_idx = 0; | |||||
struct simplebus_devinfo *ndi; | |||||
struct resource_list *rl; | |||||
struct cesa_softc *sc; | struct cesa_softc *sc; | ||||
if (!ofw_bus_is_compatible(dev, "marvell,armada-38x-crypto")) | |||||
return (cesa_attach_late(dev)); | |||||
/* | |||||
* Get simplebus_devinfo which contains | |||||
* resource list filled with adresses and | |||||
* interrupts read form FDT. | |||||
* Let's correct it by splitting resources | |||||
* for each engine. | |||||
*/ | |||||
if ((ndi = device_get_ivars(dev)) == NULL) | |||||
return (ENXIO); | |||||
rl = &ndi->rl; | |||||
switch (engine_idx) { | |||||
case 0: | |||||
/* Update regs values */ | |||||
resource_list_add(rl, SYS_RES_MEMORY, 0, CESA0_TDMA_ADDR, | |||||
CESA0_TDMA_ADDR + CESA_TDMA_SIZE - 1, CESA_TDMA_SIZE); | |||||
resource_list_add(rl, SYS_RES_MEMORY, 1, CESA0_CESA_ADDR, | |||||
CESA0_CESA_ADDR + CESA_CESA_SIZE - 1, CESA_CESA_SIZE); | |||||
/* Remove unused interrupt */ | |||||
resource_list_delete(rl, SYS_RES_IRQ, 1); | |||||
break; | |||||
case 1: | |||||
/* Update regs values */ | |||||
resource_list_add(rl, SYS_RES_MEMORY, 0, CESA1_TDMA_ADDR, | |||||
CESA1_TDMA_ADDR + CESA_TDMA_SIZE - 1, CESA_TDMA_SIZE); | |||||
resource_list_add(rl, SYS_RES_MEMORY, 1, CESA1_CESA_ADDR, | |||||
CESA1_CESA_ADDR + CESA_CESA_SIZE - 1, CESA_CESA_SIZE); | |||||
/* Remove unused interrupt */ | |||||
resource_list_delete(rl, SYS_RES_IRQ, 0); | |||||
resource_list_find(rl, SYS_RES_IRQ, 1)->rid = 0; | |||||
break; | |||||
default: | |||||
device_printf(dev, "Bad cesa engine_idx\n"); | |||||
return (ENXIO); | |||||
} | |||||
sc = device_get_softc(dev); | |||||
sc->sc_cesa_engine_id = engine_idx; | |||||
/* | |||||
* Call simplebus_add_device only once. | |||||
* It will create second cesa driver instance | |||||
* with the same FDT node as first instance. | |||||
* When second driver reach this function, | |||||
* it will be configured to use second cesa engine | |||||
*/ | |||||
if (engine_idx == 0) | |||||
simplebus_add_device(device_get_parent(dev), ofw_bus_get_node(dev), | |||||
0, "cesa", 1, NULL); | |||||
engine_idx++; | |||||
return (cesa_attach_late(dev)); | |||||
} | |||||
static int | |||||
cesa_attach_late(device_t dev) | |||||
{ | |||||
struct cesa_softc *sc; | |||||
uint32_t d, r, val; | uint32_t d, r, val; | ||||
int error; | int error; | ||||
int i; | int i; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->sc_blocked = 0; | sc->sc_blocked = 0; | ||||
sc->sc_error = 0; | sc->sc_error = 0; | ||||
sc->sc_dev = dev; | sc->sc_dev = dev; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | cesa_attach_late(device_t dev) | ||||
/* Allocate I/O and IRQ resources */ | /* Allocate I/O and IRQ resources */ | ||||
error = bus_alloc_resources(dev, cesa_res_spec, sc->sc_res); | error = bus_alloc_resources(dev, cesa_res_spec, sc->sc_res); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "could not allocate resources\n"); | device_printf(dev, "could not allocate resources\n"); | ||||
goto err0; | goto err0; | ||||
} | } | ||||
/* Acquire SRAM base address */ | /* Acquire SRAM base address */ | ||||
if (!ofw_bus_is_compatible(dev, "marvell,armada-38x-crypto")) | |||||
error = cesa_setup_sram(sc); | error = cesa_setup_sram(sc); | ||||
else | |||||
error = cesa_setup_sram_armada(sc); | |||||
if (error) { | if (error) { | ||||
device_printf(dev, "could not setup SRAM\n"); | device_printf(dev, "could not setup SRAM\n"); | ||||
goto err1; | goto err1; | ||||
} | } | ||||
/* Setup interrupt handler */ | /* Setup interrupt handler */ | ||||
error = bus_setup_intr(dev, sc->sc_res[RES_CESA_IRQ], INTR_TYPE_NET | | error = bus_setup_intr(dev, sc->sc_res[RES_CESA_IRQ], INTR_TYPE_NET | | ||||
INTR_MPSAFE, NULL, cesa_intr, sc, &(sc->sc_icookie)); | INTR_MPSAFE, NULL, cesa_intr, sc, &(sc->sc_icookie)); | ||||
▲ Show 20 Lines • Show All 604 Lines • Show Last 20 Lines |