Port-sparc64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

UltraSPARC III cpufreq driver



        Hello,

I have written a quick and dirty cpufreq driver for UltraSPARC-III class server. You will find attached a patch against -current.

scsibus3 at isp0: 256 targets, 8 luns per target
uhub0 at usb0: Sun Microsystems OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 4 ports with 4 removable, self powered
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
scsibus3: waiting 2 seconds for devices to settle...
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 23 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 750 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 375 MHz
schizo_set_cpufreq 750 MHz


schizo1: failed to register cpufreq

and driver stops...

As you can see, driver works on one CPU but not on second one. When I try to register cpufreq on second CPU because cf_backend->cf_init is true (in cpufreq_register function).

        Any idea to fix my code ?

        Regards,

        JKB
Index: arch/sparc64/dev/schizo.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizo.c,v
retrieving revision 1.31
diff -u -r1.31 schizo.c
--- arch/sparc64/dev/schizo.c   21 Jun 2013 20:09:58 -0000      1.31
+++ arch/sparc64/dev/schizo.c   8 Sep 2014 20:32:22 -0000
@@ -5,6 +5,7 @@
  * Copyright (c) 2002 Jason L. Wright (jason%thought.net@localhost)
  * Copyright (c) 2003 Henric Jungheim
  * Copyright (c) 2008, 2009, 2010, 2012 Matthew R. Green
+ * Copyright (c) 2014 Joël Bertrand (joel.bertrand%systella.fr@localhost)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,7 @@
 #include <sys/systm.h>
 #include <sys/time.h>
 #include <sys/reboot.h>
+#include <sys/cpufreq.h>
 
 #define _SPARC_BUS_DMA_PRIVATE
 #include <sys/bus.h>
@@ -86,6 +88,9 @@
 int schizo_safari_error(void *);
 int schizo_pci_error(void *);
 
+void schizo_get_cpufreq(void *, void *);
+void schizo_set_cpufreq(void *, void *);
+
 pci_chipset_tag_t schizo_alloc_chipset(struct schizo_pbm *, int,
     pci_chipset_tag_t);
 bus_space_tag_t schizo_alloc_mem_tag(struct schizo_pbm *);
@@ -136,6 +141,80 @@
 }
 
 void
+schizo_set_cpufreq(void *aux, void *freq)
+{
+       uint32_t        f;
+
+       uint64_t        cmd;
+       uint64_t        esctrl;
+
+       struct schizo_softc *sc;
+
+       f = (*((uint32_t *) freq));
+       sc = aux;
+
+       if (f == sc->sc_cf.cf_state[0].cfs_freq)
+               cmd = SCZ_ESCTRL_CLK_MAX;
+       else if (f == sc->sc_cf.cf_state[1].cfs_freq)
+               cmd = SCZ_ESCTRL_CLK_DIV_2;
+       else if (f == sc->sc_cf.cf_state[2].cfs_freq)
+               cmd = SCZ_ESCTRL_CLK_DIV_32;
+       else
+       {
+               printf("cpufreq failed: switching to max frequency\n");
+               cmd = SCZ_ESCTRL_CLK_MAX;
+       }
+
+       esctrl = schizo_read(sc, SCZ_ESCTRL);
+       esctrl &= (~SCZ_ESCTRL_CLK_MASK);
+       esctrl |= cmd;
+       schizo_write(sc, SCZ_ESCTRL, esctrl);
+
+       printf("schizo_set_cpufreq %u MHz\n", f);
+}
+
+void
+schizo_get_cpufreq(void *aux, void *freq)
+{
+       uint32_t        f;
+       uint64_t        esctrl;
+
+       struct schizo_softc *sc;
+
+       sc = aux;
+       esctrl = schizo_read(sc, SCZ_ESCTRL);
+
+       switch(esctrl & (~SCZ_ESCTRL_CLK_MASK))
+       {
+               default:
+               case SCZ_ESCTRL_CLK_MAX:
+                       f = sc->sc_cf.cf_state[0].cfs_freq;
+                       break;
+
+               case SCZ_ESCTRL_CLK_DIV_2:
+                       f = sc->sc_cf.cf_state[1].cfs_freq;
+                       break;
+
+               case SCZ_ESCTRL_CLK_DIV_32:
+                       f = sc->sc_cf.cf_state[2].cfs_freq;
+                       break;
+       }
+
+       (*((uint32_t *) freq)) = f;
+}
+
+static void
+schizo_setup_cpufreq(device_t dev)
+{
+       struct schizo_softc *sc = device_private(dev);
+       int ret;
+
+       ret = cpufreq_register(&(sc->sc_cf));
+       if (ret != 0)
+               aprint_error_dev(sc->sc_dev, "failed to register cpufreq\n");
+}
+
+void
 schizo_attach(device_t parent, device_t self, void *aux)
 {
        struct schizo_softc *sc = device_private(self);
@@ -318,6 +397,26 @@
        schizo_set_intr(sc, pbm, PIL_HIGH, schizo_safari_error, sc,
            SCZ_SERR_INO, "safari");
 
+       /*
+        * Register with cpufreq(9)
+        */
+
+       (void) memset(&(sc->sc_cf), 0, sizeof(struct cpufreq));
+
+       sc->sc_cf.cf_state[0].cfs_freq = (uint32_t) 
(curcpu()->ci_cpu_clockrate[1]);
+       sc->sc_cf.cf_state[1].cfs_freq = sc->sc_cf.cf_state[0].cfs_freq / 2;
+       sc->sc_cf.cf_state[2].cfs_freq = sc->sc_cf.cf_state[0].cfs_freq / 32;
+       sc->sc_cf.cf_state_count = 3;
+
+       sc->sc_cf.cf_mp = false;
+       sc->sc_cf.cf_cookie = sc;
+       sc->sc_cf.cf_get_freq = schizo_get_cpufreq;
+       sc->sc_cf.cf_set_freq = schizo_set_cpufreq;
+
+       (void) strlcpy(sc->sc_cf.cf_name, "safari", sizeof(sc->sc_cf.cf_name));
+
+       config_interrupts(sc->sc_dev, schizo_setup_cpufreq);
+
        if (sc->sc_tomatillo) {
                /*
                 * Enable the IOCACHE.
Index: arch/sparc64/dev/schizoreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizoreg.h,v
retrieving revision 1.9
diff -u -r1.9 schizoreg.h
--- arch/sparc64/dev/schizoreg.h        25 Mar 2012 03:13:08 -0000      1.9
+++ arch/sparc64/dev/schizoreg.h        8 Sep 2014 20:32:22 -0000
@@ -4,6 +4,7 @@
 /*
  * Copyright (c) 2002 Jason L. Wright (jason%thought.net@localhost)
  * Copyright (c) 2010 Matthew R. Green
+ * Copyright (c) 2014 Joël Bertrand (joel.bertrand%systella.fr@localhost)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -15,7 +16,7 @@
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ e THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
@@ -76,8 +77,9 @@
        volatile u_int64_t      ue_afar;
        volatile u_int64_t      ce_afsr;
        volatile u_int64_t      ce_afar;
+       volatile u_int64_t      esctrl;
 
-       volatile u_int64_t      _unused4[253942];
+       volatile u_int64_t      _unused4[253941];
        struct schizo_pbm_regs pbm_a;
        struct schizo_pbm_regs pbm_b;
 };
@@ -101,6 +103,7 @@
 #define        SCZ_UE_AFAR                     0x10038
 #define        SCZ_CE_AFSR                     0x10040
 #define        SCZ_CE_AFAR                     0x10048
+#define SCZ_ESCTRL                     0x10050
 
 /* These are relative to the PBM */
 #define        SCZ_PCI_IOMMU_CTRL              0x00200
@@ -298,3 +301,8 @@
        u_int32_t       size_hi;
        u_int32_t       size_lo;
 };
+
+#define SCZ_ESCTRL_CLK_MAX             0x0000000000000000UL
+#define SCZ_ESCTRL_CLK_DIV_2   0x0000000040000000UL
+#define SCZ_ESCTRL_CLK_DIV_32  0x0000000080000000UL
+#define SCZ_ESCTRL_CLK_MASK            0x00000000C0000000UL
Index: arch/sparc64/dev/schizovar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizovar.h,v
retrieving revision 1.6
diff -u -r1.6 schizovar.h
--- arch/sparc64/dev/schizovar.h        25 Mar 2012 03:13:08 -0000      1.6
+++ arch/sparc64/dev/schizovar.h        8 Sep 2014 20:32:22 -0000
@@ -64,6 +64,7 @@
        int sc_busa;
        int sc_tomatillo;
        uint32_t sc_ver;
+       struct cpufreq sc_cf;
 };
 
 #define        schizo_read(sc,r) \
Index: kern/subr_cpufreq.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_cpufreq.c,v
retrieving revision 1.9
diff -u -r1.9 subr_cpufreq.c
--- kern/subr_cpufreq.c 12 Feb 2014 20:20:15 -0000      1.9
+++ kern/subr_cpufreq.c 8 Sep 2014 20:32:27 -0000
@@ -66,8 +66,10 @@
        uint32_t c, i, j, k, m;
        int rv;
 
+printf("<1>\n");
        if (cold != 0)
                return EBUSY;
+printf("<2>\n");
 
        KASSERT(cf != NULL);
        KASSERT(cf_backend != NULL);
@@ -78,7 +80,9 @@
 
        mutex_enter(&cpufreq_lock);
 
+printf("<3>\n");
        if (cf_backend->cf_init != false) {
+printf("<4>\n");
                mutex_exit(&cpufreq_lock);
                return EALREADY;
        }
@@ -95,9 +99,11 @@
         * Sanity check the values and verify descending order.
         */
        for (c = i = 0; i < cf->cf_state_count; i++) {
+printf("<5>\n");
 
                CTASSERT(CPUFREQ_STATE_ENABLED != 0);
                CTASSERT(CPUFREQ_STATE_DISABLED != 0);
+printf("<6>\n");
 
                if (cf->cf_state[i].cfs_freq == 0)
                        continue;
@@ -128,15 +134,18 @@
 
        cf_backend->cf_state_count = c;
 
+printf("<7>\n");
        if (cf_backend->cf_state_count == 0) {
                mutex_exit(&cpufreq_lock);
                cpufreq_deregister();
+printf("<8>\n");
                return EINVAL;
        }
 
        rv = cpufreq_latency();
 
        if (rv != 0) {
+printf("<9>\n");
                mutex_exit(&cpufreq_lock);
                cpufreq_deregister();
                return rv;


Home | Main Index | Thread Index | Old Index