Author: mw
Date: Mon Apr  9 23:36:52 2018
New Revision: 332344
URL: https://svnweb.freebsd.org/changeset/base/332344

Log:
  Enable cesa driver to work with Linux DT binding
  
  Linux device tree binding, whose usage is obligatory,
  comprises faulty representation of Marvell cryptographic
  engine (CESA) - two engines are artificially gathered into
  single DT node, in order to avoid certain SW limitation.
  
  This patch improves the cesa driver to support above binding,
  depending on compatible string, which helps to ensure
  backward compatibility.
  
  Submitted by: Patryk Duda
  Obtained from: Semihalf
  Sponsored by: Stormshield
  Differential Revision: https://reviews.freebsd.org/D14760

Modified:
  head/sys/arm/mv/mv_common.c
  head/sys/arm/mv/mvwin.h
  head/sys/dev/cesa/cesa.c
  head/sys/dev/cesa/cesa.h

Modified: head/sys/arm/mv/mv_common.c
==============================================================================
--- head/sys/arm/mv/mv_common.c Mon Apr  9 22:59:10 2018        (r332343)
+++ head/sys/arm/mv/mv_common.c Mon Apr  9 23:36:52 2018        (r332344)
@@ -108,6 +108,7 @@ static int decode_win_xor_valid(void);
 static void decode_win_cpu_setup(void);
 static int decode_win_sdram_fixup(void);
 static void decode_win_cesa_setup(u_long);
+static void decode_win_a38x_cesa_setup(u_long);
 static void decode_win_usb_setup(u_long);
 static void decode_win_usb3_setup(u_long);
 static void decode_win_eth_setup(u_long);
@@ -120,6 +121,7 @@ static void decode_win_idma_setup(u_long);
 static void decode_win_xor_setup(u_long);
 
 static void decode_win_cesa_dump(u_long);
+static void decode_win_a38x_cesa_dump(u_long);
 static void decode_win_usb_dump(u_long);
 static void decode_win_usb3_dump(u_long);
 static void decode_win_eth_dump(u_long base);
@@ -226,6 +228,8 @@ static struct soc_node_spec soc_nodes[] = {
        { "mrvl,idma", &decode_win_idma_setup, &decode_win_idma_dump, 
&decode_win_idma_valid},
        { "mrvl,cesa", &decode_win_cesa_setup, &decode_win_cesa_dump, 
&decode_win_cesa_valid},
        { "mrvl,pcie", &decode_win_pcie_setup, &decode_win_pcie_dump, 
&decode_win_pcie_valid},
+       { "marvell,armada-38x-crypto", &decode_win_a38x_cesa_setup,
+           &decode_win_a38x_cesa_dump, &decode_win_cesa_valid},
        { NULL, NULL, NULL, NULL },
 };
 
@@ -1558,6 +1562,20 @@ decode_win_cesa_setup(u_long base)
                        }
                }
        }
+}
+
+static void
+decode_win_a38x_cesa_setup(u_long base)
+{
+       decode_win_cesa_setup(base);
+       decode_win_cesa_setup(base + MV_WIN_CESA_OFFSET);
+}
+
+static void
+decode_win_a38x_cesa_dump(u_long base)
+{
+       decode_win_cesa_dump(base);
+       decode_win_cesa_dump(base + MV_WIN_CESA_OFFSET);
 }
 
 /**************************************************************************

Modified: head/sys/arm/mv/mvwin.h
==============================================================================
--- head/sys/arm/mv/mvwin.h     Mon Apr  9 22:59:10 2018        (r332343)
+++ head/sys/arm/mv/mvwin.h     Mon Apr  9 23:36:52 2018        (r332344)
@@ -202,6 +202,8 @@
 #define        MV_WIN_NETA_OFFSET              0x2000
 #define        MV_WIN_NETA_BASE(n)             MV_WIN_ETH_BASE(n) + 
MV_WIN_NETA_OFFSET
 
+#define MV_WIN_CESA_OFFSET             0x2000
+
 #define MV_WIN_ETH_BASE(n)             (0x8 * (n) + 0x200)
 #define MV_WIN_ETH_SIZE(n)             (0x8 * (n) + 0x204)
 #define MV_WIN_ETH_REMAP(n)            (0x4 * (n) + 0x280)

Modified: head/sys/dev/cesa/cesa.c
==============================================================================
--- head/sys/dev/cesa/cesa.c    Mon Apr  9 22:59:10 2018        (r332343)
+++ head/sys/dev/cesa/cesa.c    Mon Apr  9 23:36:52 2018        (r332344)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/resource.h>
 #include <machine/fdt.h>
 
+#include <dev/fdt/simplebus.h>
 #include <dev/fdt/fdt_common.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$");
 
 static int     cesa_probe(device_t);
 static int     cesa_attach(device_t);
+static int     cesa_attach_late(device_t);
 static int     cesa_detach(device_t);
 static void    cesa_intr(void *);
 static int     cesa_newsession(device_t, u_int32_t *, struct cryptoini *);
@@ -1003,14 +1005,130 @@ cesa_setup_sram(struct cesa_softc *sc)
        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
+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)
 {
 
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       if (!ofw_bus_is_compatible(dev, "mrvl,cesa"))
+       if (!ofw_bus_search_compatible(dev, cesa_devices)->ocd_data)
                return (ENXIO);
 
        device_set_desc(dev, "Marvell Cryptographic Engine and Security "
@@ -1022,7 +1140,78 @@ cesa_probe(device_t dev)
 static int
 cesa_attach(device_t dev)
 {
+       static int engine_idx = 0;
+       struct simplebus_devinfo *ndi;
+       struct resource_list *rl;
        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;
        int error;
        int i;
@@ -1086,7 +1275,11 @@ cesa_attach(device_t dev)
        }
 
        /* Acquire SRAM base address */
-       error = cesa_setup_sram(sc);
+       if (!ofw_bus_is_compatible(dev, "marvell,armada-38x-crypto"))
+               error = cesa_setup_sram(sc);
+       else
+               error = cesa_setup_sram_armada(sc);
+
        if (error) {
                device_printf(dev, "could not setup SRAM\n");
                goto err1;

Modified: head/sys/dev/cesa/cesa.h
==============================================================================
--- head/sys/dev/cesa/cesa.h    Mon Apr  9 22:59:10 2018        (r332343)
+++ head/sys/dev/cesa/cesa.h    Mon Apr  9 23:36:52 2018        (r332344)
@@ -239,6 +239,7 @@ struct cesa_softc {
        bus_dma_tag_t                   sc_data_dtag;
        int                             sc_error;
        int                             sc_tperr;
+       uint8_t                         sc_cesa_engine_id;
 
        struct mtx                      sc_sc_lock;
        int                             sc_blocked;
@@ -367,4 +368,10 @@ struct cesa_chain_info {
 #define CESA_SA_SR                     0x0E0C
 #define CESA_SA_SR_ACTIVE              (1 << 0)
 
+#define CESA_TDMA_SIZE                 0x1000
+#define CESA_CESA_SIZE                 0x1000
+#define CESA0_TDMA_ADDR                        0x90000
+#define CESA0_CESA_ADDR                        0x9D000
+#define CESA1_TDMA_ADDR                        0x92000
+#define CESA1_CESA_ADDR                        0x9F000
 #endif
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to