Author: landonf
Date: Sat Jun  4 19:31:06 2016
New Revision: 301408
URL: https://svnweb.freebsd.org/changeset/base/301408

Log:
  Fix several MIPS/BCM-blocking bugs in bhnd(4) chipc
  
  - Correct IRQ lines for UART (to fix IRQ lookup in future)
  - Check device unit in resource assignment during chipc_add_child
  - If chipc hint->size is RM_MAX_END, resource end should be same as window end
  - Clear reference from resource list entry to resource in case of resource 
release
  - Add CHIPC_GET_CAPS implementation
  - Correct chipc flash constants (to be unshifted)
  - Default implementation of get_attach_type should iterate over device tree
  - Add default implementation for BHND_CHIPC_GET_CAPS usable by chipc 
grandchildren
  
  Submitted by: Michael Zhilin <miz...@gmail.com>
  Approved by:  adrian (mentor)
  Differential Revision:        https://reviews.freebsd.org/D6584

Modified:
  head/sys/dev/bhnd/bhnd.h
  head/sys/dev/bhnd/bhnd_bus_if.m
  head/sys/dev/bhnd/bhnd_subr.c
  head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
  head/sys/dev/bhnd/cores/chipc/chipc.c
  head/sys/dev/bhnd/cores/chipc/chipcreg.h

Modified: head/sys/dev/bhnd/bhnd.h
==============================================================================
--- head/sys/dev/bhnd/bhnd.h    Sat Jun  4 19:00:11 2016        (r301407)
+++ head/sys/dev/bhnd/bhnd.h    Sat Jun  4 19:31:06 2016        (r301408)
@@ -356,6 +356,8 @@ int                          
bhnd_bus_generic_activate_resour
 int                             bhnd_bus_generic_deactivate_resource (device_t 
dev,
                                     device_t child, int type, int rid,
                                     struct bhnd_resource *r);
+bhnd_attach_type                bhnd_bus_generic_get_attach_type(device_t dev,
+                                    device_t child);
 
 
 

Modified: head/sys/dev/bhnd/bhnd_bus_if.m
==============================================================================
--- head/sys/dev/bhnd/bhnd_bus_if.m     Sat Jun  4 19:00:11 2016        
(r301407)
+++ head/sys/dev/bhnd/bhnd_bus_if.m     Sat Jun  4 19:31:06 2016        
(r301408)
@@ -55,12 +55,6 @@ CODE {
                panic("bhnd_bus_get_chipid unimplemented");
        }
 
-       static bhnd_attach_type
-       bhnd_bus_null_get_attach_type(device_t dev, device_t child)
-       {
-               panic("bhnd_bus_get_attach_type unimplemented");
-       }
-
        static int
        bhnd_bus_null_read_board_info(device_t dev, device_t child,
            struct bhnd_board_info *info)
@@ -203,7 +197,7 @@ METHOD const struct bhnd_chipid * get_ch
 METHOD bhnd_attach_type get_attach_type {
        device_t dev;
        device_t child;
-} DEFAULT bhnd_bus_null_get_attach_type;
+} DEFAULT bhnd_bus_generic_get_attach_type;
 
 /**
  * Attempt to read the BHND board identification from the parent bus.

Modified: head/sys/dev/bhnd/bhnd_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhnd_subr.c       Sat Jun  4 19:00:11 2016        
(r301407)
+++ head/sys/dev/bhnd/bhnd_subr.c       Sat Jun  4 19:31:06 2016        
(r301408)
@@ -1158,3 +1158,22 @@ bhnd_bus_generic_deactivate_resource(dev
 
        return (EINVAL);
 };
+
+/**
+ * Helper function for implementing BHND_BUS_GET_ATTACH_TYPE().
+ *
+ * This implementation of BHND_BUS_GET_ATTACH_TYPE() simply calls the
+ * BHND_BUS_GET_ATTACH_TYPE() method of the parent of @p dev.
+ */
+bhnd_attach_type
+bhnd_bus_generic_get_attach_type(device_t dev, device_t child)
+{
+       /* iterate from cores via bhnd to bridge or SoC */
+       if (device_get_parent(dev) != NULL)
+               return (BHND_BUS_GET_ATTACH_TYPE(device_get_parent(dev),
+                   child));
+
+       panic("bhnd_bus_get_attach_type unimplemented");
+       /* Unreachable */
+       return (BHND_ATTACH_ADAPTER);
+}

Modified: head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
==============================================================================
--- head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m       Sat Jun  4 19:00:11 
2016        (r301407)
+++ head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m       Sat Jun  4 19:31:06 
2016        (r301408)
@@ -39,6 +39,29 @@ INTERFACE bhnd_chipc;
 HEADER {
        /* forward declarations */
        struct chipc_caps;
+       struct chipc_caps       *bhnd_chipc_generic_get_caps(device_t dev);
+}
+
+CODE {
+
+       /**
+        * Helper function for implementing BHND_CHIPC_GET_CAPS().
+        *
+        * This implementation of BHND_CHIPC_GET_CAPS() simply calls the
+        * BHND_CHIPC_GET_CAPS() method of the parent of @p dev.
+        */
+       struct chipc_caps*
+       bhnd_chipc_generic_get_caps(device_t dev)
+       {
+       
+               if (device_get_parent(dev) != NULL)
+                       return (BHND_CHIPC_GET_CAPS(device_get_parent(dev)));
+       
+               panic("bhnd_chipc_generic_get_caps unimplemented");
+               /* Unreachable */
+               return (NULL);
+       }
+
 }
 
 /**
@@ -77,7 +100,7 @@ METHOD void write_chipctrl {
  */
 METHOD struct chipc_caps * get_caps {
        device_t dev;
-}
+} DEFAULT bhnd_chipc_generic_get_caps;
 
 /**
  * Enable hardware access to the SPROM.

Modified: head/sys/dev/bhnd/cores/chipc/chipc.c
==============================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc.c       Sat Jun  4 19:00:11 2016        
(r301407)
+++ head/sys/dev/bhnd/cores/chipc/chipc.c       Sat Jun  4 19:31:06 2016        
(r301408)
@@ -110,12 +110,13 @@ static const struct chipc_hint {
        u_int            region;
 } chipc_hints[] = {
        // FIXME: cfg/spi port1.1 mapping on siba(4) SoCs
+       // FIXME: IRQ shouldn't be hardcoded
        /* device       unit    type            rid     base                    
size                    port,region */
        { "bhnd_nvram", 0, SYS_RES_MEMORY,      0,      CHIPC_SPROM_OTP,        
CHIPC_SPROM_OTP_SIZE,   0,0 },
        { "uart",       0, SYS_RES_MEMORY,      0,      CHIPC_UART0_BASE,       
CHIPC_UART_SIZE,        0,0 },
-       { "uart",       0, SYS_RES_IRQ,         0,      0,                      
RM_MAX_END },
+       { "uart",       0, SYS_RES_IRQ,         0,      2,                      
1 },
        { "uart",       1, SYS_RES_MEMORY,      0,      CHIPC_UART1_BASE,       
CHIPC_UART_SIZE,        0,0 },
-       { "uart",       1, SYS_RES_IRQ,         0,      0,                      
RM_MAX_END },
+       { "uart",       1, SYS_RES_IRQ,         0,      2,                      
1 },
        { "spi",        0, SYS_RES_MEMORY,      0,      0,                      
RM_MAX_END,             1,1 },
        { "spi",        0, SYS_RES_MEMORY,      1,      CHIPC_SFLASH_BASE,      
CHIPC_SFLASH_SIZE,      0,0 },
        { "cfi",        0, SYS_RES_MEMORY,      0,      0,                      
RM_MAX_END,             1,1},
@@ -480,12 +481,30 @@ chipc_add_child(device_t dev, u_int orde
        struct chipc_devinfo    *dinfo;
        const struct chipc_hint *hint;
        device_t                 child;
+       devclass_t               child_dc;
        int                      error;
+       int                      busrel_unit;
 
        child = device_add_child_ordered(dev, order, name, unit);
        if (child == NULL)
                return (NULL);
 
+       /* system-wide device unit */
+       unit = device_get_unit(child);
+       child_dc = device_get_devclass(child);
+
+       busrel_unit = 0;
+       for (int i = 0; i < unit; i++) {
+               device_t        tmp;
+
+               tmp = devclass_get_device(child_dc, i);
+               if (tmp != NULL && (device_get_parent(tmp) == dev))
+                       busrel_unit++;
+       }
+
+       /* bus-wide device unit (override unit for further hint matching) */
+       unit = busrel_unit;
+
        dinfo = malloc(sizeof(struct chipc_devinfo), M_BHND, M_NOWAIT);
        if (dinfo == NULL) {
                device_delete_child(dev, child);
@@ -504,9 +523,14 @@ chipc_add_child(device_t dev, u_int orde
                bhnd_addr_t     region_addr;
                bhnd_size_t     region_size;
 
+               /* Check device name */
                if (strcmp(hint->name, name) != 0)
                        continue;
 
+               /* Check device unit */
+               if (hint->unit >= 0 && unit != hint->unit)
+                       continue;
+
                switch (hint->type) {
                case SYS_RES_IRQ:
                        /* Add child resource */
@@ -535,8 +559,9 @@ chipc_add_child(device_t dev, u_int orde
 
                        /* Verify requested range is mappable */
                        if (hint->base > region_size ||
-                           hint->size > region_size ||
-                           region_size - hint->base < hint->size )
+                           (hint->size != RM_MAX_END &&
+                               (hint->size > region_size ||
+                                region_size - hint->base < hint->size )))
                        {
                                device_printf(dev,
                                    "%s%u.%u region cannot map requested range "
@@ -546,9 +571,17 @@ chipc_add_child(device_t dev, u_int orde
                                    hint->size);
                        }
 
-                       /* Add child resource */
-                       error = bus_set_resource(child, hint->type,
-                           hint->rid, region_addr + hint->base, hint->size);
+                       /*
+                        * Add child resource. If hint doesn't define the end
+                        * of resource window (RX_MAX_END), use end of region.
+                        */
+
+                       error = bus_set_resource(child,
+                                   hint->type,
+                                   hint->rid, region_addr + hint->base,
+                                   (hint->size == RM_MAX_END) ?
+                                           region_size - hint->base :
+                                           hint->size);
                        if (error) {
                                device_printf(dev,
                                    "bus_set_resource() failed for %s: %d\n",
@@ -754,8 +787,10 @@ chipc_alloc_resource(device_t dev, devic
                
                if (rle->res != NULL) {
                        device_printf(dev,
-                           "resource entry %#x type %d for child %s is busy\n",
-                           *rid, type, device_get_nameunit(child));
+                           "resource entry %#x type %d for child %s is busy "
+                           "[%d]\n",
+                           *rid, type, device_get_nameunit(child),
+                           rman_get_flags(rle->res));
                        
                        return (NULL);
                }
@@ -821,10 +856,11 @@ static int
 chipc_release_resource(device_t dev, device_t child, int type, int rid,
     struct resource *r)
 {
-       struct chipc_softc      *sc;
-       struct chipc_region     *cr;
-       struct rman             *rm;
-       int                      error;
+       struct chipc_softc              *sc;
+       struct chipc_region             *cr;
+       struct rman                     *rm;
+       struct resource_list_entry      *rle;
+       int                              error;
 
        sc = device_get_softc(dev);
 
@@ -853,6 +889,11 @@ chipc_release_resource(device_t dev, dev
        /* Drop allocation reference */
        chipc_release_region(sc, cr, RF_ALLOCATED);
 
+       /* Clear reference from the resource list entry if exists */
+       rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, rid);
+       if (rle != NULL)
+               rle->res = NULL;
+
        return (0);
 }
 
@@ -1238,6 +1279,15 @@ chipc_write_chipctrl(device_t dev, uint3
        CHIPC_UNLOCK(sc);
 }
 
+static struct chipc_caps *
+chipc_get_caps(device_t dev)
+{
+       struct chipc_softc      *sc;
+
+       sc = device_get_softc(dev);
+       return (&sc->caps);
+}
+
 static device_method_t chipc_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,                 chipc_probe),
@@ -1279,6 +1329,7 @@ static device_method_t chipc_methods[] =
        DEVMETHOD(bhnd_chipc_write_chipctrl,    chipc_write_chipctrl),
        DEVMETHOD(bhnd_chipc_enable_sprom,      chipc_enable_sprom_pins),
        DEVMETHOD(bhnd_chipc_disable_sprom,     chipc_disable_sprom_pins),
+       DEVMETHOD(bhnd_chipc_get_caps,          chipc_get_caps),
 
        DEVMETHOD_END
 };

Modified: head/sys/dev/bhnd/cores/chipc/chipcreg.h
==============================================================================
--- head/sys/dev/bhnd/cores/chipc/chipcreg.h    Sat Jun  4 19:00:11 2016        
(r301407)
+++ head/sys/dev/bhnd/cores/chipc/chipcreg.h    Sat Jun  4 19:31:06 2016        
(r301408)
@@ -240,11 +240,11 @@
 #define          CHIPC_CAP_EXTBUS_PROG         0x2             /* ExtBus: 
ProgIf only */
 #define        CHIPC_CAP_FLASH_MASK            0x00000700      /* Type of 
flash */
 #define        CHIPC_CAP_FLASH_SHIFT           8
-#define          CHIPC_CAP_FLASH_NONE          0x000           /* No flash */
-#define          CHIPC_CAP_SFLASH_ST           0x100           /* ST serial 
flash */
-#define          CHIPC_CAP_SFLASH_AT           0x200           /* Atmel serial 
flash */
-#define          CHIPC_CAP_NFLASH              0x300           /* NAND flash */
-#define          CHIPC_CAP_PFLASH              0x700           /* Parallel 
flash */
+#define          CHIPC_CAP_FLASH_NONE          0x0             /* No flash */
+#define          CHIPC_CAP_SFLASH_ST           0x1             /* ST serial 
flash */
+#define          CHIPC_CAP_SFLASH_AT           0x2             /* Atmel serial 
flash */
+#define          CHIPC_CAP_NFLASH              0x3             /* NAND flash */
+#define          CHIPC_CAP_PFLASH              0x7             /* Parallel 
flash */
 #define        CHIPC_CAP_PLL_MASK              0x00038000      /* Type of PLL 
*/
 #define        CHIPC_CAP_PLL_SHIFT             15
 #define        CHIPC_CAP_PWR_CTL               0x00040000      /* Power 
control */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to