Author: landonf
Date: Tue Nov 28 00:42:44 2017
New Revision: 326301
URL: https://svnweb.freebsd.org/changeset/base/326301

Log:
  siba(4): Add support for devices have neither PMU nor PWRCTL support.
  
  Very early BHND Wi-Fi devices (e.g. BCM4318) do not support any form of
  dynamic clock control; on these devices, any PMU requests that cannot be
  met by the device's fixed clock state will return an appropriate error
  code.
  
  Approved by:  adrian (mentor, implicit)
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/dev/bhnd/siba/siba.c
  head/sys/dev/bhnd/siba/sibavar.h
  head/sys/modules/bhnd/siba/Makefile

Modified: head/sys/dev/bhnd/siba/siba.c
==============================================================================
--- head/sys/dev/bhnd/siba/siba.c       Tue Nov 28 00:41:17 2017        
(r326300)
+++ head/sys/dev/bhnd/siba/siba.c       Tue Nov 28 00:42:44 2017        
(r326301)
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/bus.h>
 
+#include <dev/bhnd/cores/chipc/chipc.h>
 #include <dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.h>
 
 #include "sibareg.h"
@@ -168,8 +169,9 @@ siba_read_ivar(device_t dev, device_t child, int index
                        return (0);
 
                case SIBA_PMU_PWRCTL:
-                       panic("bhnd_get_pmu_info() called with "
-                           "SIBA_PMU_PWRCTL");
+               case SIBA_PMU_FIXED:
+                       panic("bhnd_get_pmu_info() called with siba PMU state "
+                           "%d", dinfo->pmu_state);
                        return (ENXIO);
                }
 
@@ -211,8 +213,9 @@ siba_write_ivar(device_t dev, device_t child, int inde
                        return (0);
 
                case SIBA_PMU_PWRCTL:
-                       panic("bhnd_set_pmu_info() called with "
-                           "SIBA_PMU_PWRCTL");
+               case SIBA_PMU_FIXED:
+                       panic("bhnd_set_pmu_info() called with siba PMU state "
+                           "%d", dinfo->pmu_state);
                        return (ENXIO);
                }
 
@@ -237,7 +240,10 @@ siba_alloc_pmu(device_t dev, device_t child)
 {
        struct siba_softc       *sc;
        struct siba_devinfo     *dinfo;
+       device_t                 chipc;
        device_t                 pwrctl;
+       struct chipc_caps        ccaps;
+       siba_pmu_state           pmu_state;
        int                      error;
 
        if (device_get_parent(child) != dev)
@@ -245,11 +251,20 @@ siba_alloc_pmu(device_t dev, device_t child)
 
        sc = device_get_softc(dev);
        dinfo = device_get_ivars(child);
-       pwrctl = bhnd_retain_provider(child, BHND_SERVICE_PWRCTL);
+       pwrctl = NULL;
 
-       /* Unless this is a legacy PWRCTL chipset, defer to bhnd(4)'s PMU
-        * implementation */
-       if (pwrctl == NULL) {
+       /* Fetch ChipCommon capability flags */
+       chipc = bhnd_retain_provider(child, BHND_SERVICE_CHIPC);
+       if (chipc != NULL) {
+               ccaps = *BHND_CHIPC_GET_CAPS(chipc);
+               bhnd_release_provider(child, chipc, BHND_SERVICE_CHIPC);
+       } else {
+               memset(&ccaps, 0, sizeof(ccaps));
+       }
+
+       /* Defer to bhnd(4)'s PMU implementation if ChipCommon exists and
+        * advertises PMU support */
+       if (ccaps.pmu) {
                if ((error = bhnd_generic_alloc_pmu(dev, child)))
                        return (error);
 
@@ -259,8 +274,24 @@ siba_alloc_pmu(device_t dev, device_t child)
                return (0);
        }
 
-       /* This is a legacy PWRCTL chipset; we need to map all bhnd(4) bus PMU
-        * to PWRCTL operations ourselves.*/
+       /*
+        * This is either a legacy PWRCTL chipset, or the device does not
+        * support dynamic clock control.
+        * 
+        * We need to map all bhnd(4) bus PMU to PWRCTL or no-op operations.
+        */
+       if (ccaps.pwr_ctrl) {
+               pmu_state = SIBA_PMU_PWRCTL;
+               pwrctl = bhnd_retain_provider(child, BHND_SERVICE_PWRCTL);
+               if (pwrctl == NULL) {
+                       device_printf(dev, "PWRCTL not found\n");
+                       return (ENODEV);
+               }
+       } else {
+               pmu_state = SIBA_PMU_FIXED;
+               pwrctl = NULL;
+       }
+
        SIBA_LOCK(sc);
 
        /* Per-core PMU state already allocated? */
@@ -270,8 +301,8 @@ siba_alloc_pmu(device_t dev, device_t child)
        }
 
        /* Update the child's PMU allocation state, and transfer ownership of
-        * the PWRCTL provider reference */
-       dinfo->pmu_state = SIBA_PMU_PWRCTL;
+        * the PWRCTL provider reference (if any) */
+       dinfo->pmu_state = pmu_state;
        dinfo->pmu.pwrctl = pwrctl;
 
        SIBA_UNLOCK(sc);
@@ -324,6 +355,15 @@ siba_release_pmu(device_t dev, device_t child)
                /* Release the provider reference */
                bhnd_release_provider(child, pwrctl, BHND_SERVICE_PWRCTL);
                return (0);
+
+       case SIBA_PMU_FIXED:
+               /* Clean up the child's PMU state */
+               KASSERT(dinfo->pmu.pwrctl == NULL,
+                   ("PWRCTL reference with FIXED state"));
+
+               dinfo->pmu_state = SIBA_PMU_NONE;
+               dinfo->pmu.pwrctl = NULL;
+               SIBA_UNLOCK(sc);
        }
 
        panic("invalid PMU state: %d", dinfo->pmu_state);
@@ -363,6 +403,22 @@ siba_get_clock_latency(device_t dev, device_t child, b
                 SIBA_UNLOCK(sc);
 
                 return (error);
+
+       case SIBA_PMU_FIXED:
+               SIBA_UNLOCK(sc);
+
+               /* HT clock is always available, and incurs no transition
+                * delay. */
+               switch (clock) {
+               case BHND_CLOCK_HT:
+                       *latency = 0;
+                       return (0);
+
+               default:
+                       return (ENODEV);
+               }
+
+               return (ENODEV);
        }
 
        panic("invalid PMU state: %d", dinfo->pmu_state);
@@ -401,6 +457,11 @@ siba_get_clock_freq(device_t dev, device_t child, bhnd
                SIBA_UNLOCK(sc);
 
                return (error);
+
+       case SIBA_PMU_FIXED:
+               SIBA_UNLOCK(sc);
+
+               return (ENODEV);
        }
 
        panic("invalid PMU state: %d", dinfo->pmu_state);
@@ -432,6 +493,7 @@ siba_request_ext_rsrc(device_t dev, device_t child, u_
                return (bhnd_generic_request_ext_rsrc(dev, child, rsrc));
 
        case SIBA_PMU_PWRCTL:
+       case SIBA_PMU_FIXED:
                /* HW does not support per-core external resources */
                SIBA_UNLOCK(sc);
                return (ENODEV);
@@ -466,6 +528,7 @@ siba_release_ext_rsrc(device_t dev, device_t child, u_
                return (bhnd_generic_release_ext_rsrc(dev, child, rsrc));
 
        case SIBA_PMU_PWRCTL:
+       case SIBA_PMU_FIXED:
                /* HW does not support per-core external resources */
                SIBA_UNLOCK(sc);
                return (ENODEV);
@@ -506,6 +569,22 @@ siba_request_clock(device_t dev, device_t child, bhnd_
                SIBA_UNLOCK(sc);
 
                return (error);
+
+       case SIBA_PMU_FIXED:
+               SIBA_UNLOCK(sc);
+
+               /* HT clock is always available, and fulfills any of the
+                * following clock requests */
+               switch (clock) {
+               case BHND_CLOCK_DYN:
+               case BHND_CLOCK_ILP:
+               case BHND_CLOCK_ALP:
+               case BHND_CLOCK_HT:
+                       return (0);
+
+               default:
+                       return (ENODEV);
+               }
        }
 
        panic("invalid PMU state: %d", dinfo->pmu_state);
@@ -537,6 +616,7 @@ siba_enable_clocks(device_t dev, device_t child, uint3
                return (bhnd_generic_enable_clocks(dev, child, clocks));
 
        case SIBA_PMU_PWRCTL:
+       case SIBA_PMU_FIXED:
                SIBA_UNLOCK(sc);
 
                /* All (supported) clocks are already enabled by default */

Modified: head/sys/dev/bhnd/siba/sibavar.h
==============================================================================
--- head/sys/dev/bhnd/siba/sibavar.h    Tue Nov 28 00:41:17 2017        
(r326300)
+++ head/sys/dev/bhnd/siba/sibavar.h    Tue Nov 28 00:42:44 2017        
(r326301)
@@ -194,6 +194,7 @@ typedef enum {
        SIBA_PMU_NONE,          /**< If the core has not yet allocated PMU 
state */
        SIBA_PMU_BHND,          /**< If standard bhnd(4) PMU support should be 
used */
        SIBA_PMU_PWRCTL,        /**< If legacy PWRCTL PMU support should be 
used */
+       SIBA_PMU_FIXED,         /**< If legacy fixed (no-op) PMU support should 
be used */
 } siba_pmu_state;
 
 /**

Modified: head/sys/modules/bhnd/siba/Makefile
==============================================================================
--- head/sys/modules/bhnd/siba/Makefile Tue Nov 28 00:41:17 2017        
(r326300)
+++ head/sys/modules/bhnd/siba/Makefile Tue Nov 28 00:42:44 2017        
(r326301)
@@ -7,7 +7,8 @@ SRCS=   siba.c siba_subr.c \
        siba_erom.c
 
 SRCS+= device_if.h bus_if.h
-SRCS+= bhnd_bus_if.h bhnd_erom_if.h \
-       bhnd_pmu_if.h bhnd_pwrctl_if.h
+SRCS+= bhnd_bus_if.h bhnd_chipc_if.h \
+       bhnd_erom_if.h bhnd_pmu_if.h \
+       bhnd_pwrctl_if.h
 
 .include <bsd.kmod.mk>
_______________________________________________
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