Port-sparc64 archive

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

Re: UltraSPARC III/IIe cpufreq drivers, please test



        Hello,

I'm adding a UltraSPARC-IIe cpufreq driver to psycho that runs on my Blade 100.

        Warning :
- I assume that an UltraSPARC-IIe system is ONLY and ALWAYS uniprocessor. I never see any US-IIe SMP system, but I'm not sure that all US-IIe systems are UP. - I only has US-IIe, not US-IIi+ that could use /4 and /8 frequency dividers. Thus, I only use /1, /2 and /6, and I assume that regular US-IIe system run faster than 6*66 MHz (as cpu clock has to be greater than PCI clock).

You will find a patch against 7.99.1 kernel. A prebuilt kernel is available at http://www.systella.fr/~bertrand/netbsd.gz

        Please test,

        JKB
Index: dev/psycho.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/psycho.c,v
retrieving revision 1.118
diff -u -r1.118 psycho.c
--- dev/psycho.c        7 Dec 2013 11:17:24 -0000       1.118
+++ dev/psycho.c        13 Sep 2014 10:41:21 -0000
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (c) 1999, 2000 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
@@ -85,6 +86,8 @@
 #include <sys/systm.h>
 #include <sys/time.h>
 #include <sys/reboot.h>
+#include <sys/cpu.h>
+#include <sys/cpufreq.h>
 
 #include <uvm/uvm.h>
 
@@ -124,6 +127,9 @@
 static int     psycho_pci_find_ino(const struct pci_attach_args *,
                                    pci_intr_handle_t *);
 
+void psycho_get_cpufreq(void *, void *);
+void psycho_set_cpufreq(void *, void *);
+
 /* Interrupt handlers */
 static int psycho_ue(void *);
 static int psycho_ce(void *);
@@ -276,6 +282,98 @@
 }
 #endif
 
+void
+psycho_set_cpufreq(void *aux, void *freq)
+{
+       uint32_t        f;
+
+       uint64_t        cmd;
+       uint64_t        esctrl;
+
+       struct psycho_softc *sc;
+
+       f = (*((uint32_t *) freq));
+       sc = curcpu()->sc;
+
+       if (sc == NULL)
+               return;
+
+       if (f == sc->sc_cf.cf_state[0].cfs_freq)
+               cmd = ESTAR_FULL;
+       else if (f == sc->sc_cf.cf_state[1].cfs_freq)
+               cmd = ESTAR_DIV_2;
+       else if (f == sc->sc_cf.cf_state[2].cfs_freq)
+               cmd = ESTAR_DIV_6;
+       else
+       {
+               aprint_error("cpufreq failed: switching to max frequency\n");
+               cmd = ESTAR_FULL;
+       }
+
+       esctrl = bus_space_read_8(sc->sc_bustag, sc->sc_bh,
+                       offsetof(struct psychoreg, estar_mode));
+
+       esctrl &= (~0x111UL);
+       esctrl |= cmd;
+
+       bus_space_write_8(sc->sc_bustag, sc->sc_bh,
+               offsetof(struct psychoreg, estar_mode), esctrl);
+       aprint_normal("psycho_set_cpufreq %u MHz (cpu %lu)\n", f,
+                       (unsigned long) cpu_number());
+}
+
+void
+psycho_get_cpufreq(void *aux, void *freq)
+{
+       uint32_t        f;
+       uint64_t        esctrl;
+
+       struct psycho_softc *sc;
+
+       sc = curcpu()->sc;
+
+       if (sc == NULL)
+               return;
+
+       esctrl = bus_space_read_8(sc->sc_bustag, sc->sc_bh,
+                       offsetof(struct psychoreg, estar_mode));
+
+       switch(esctrl & (~0x111UL))
+       {
+               default:
+               case ESTAR_FULL:
+                       f = sc->sc_cf.cf_state[0].cfs_freq;
+                       break;
+
+               case ESTAR_DIV_2:
+                       f = sc->sc_cf.cf_state[1].cfs_freq;
+                       break;
+
+               case ESTAR_DIV_6:
+                       f = sc->sc_cf.cf_state[2].cfs_freq;
+                       break;
+       }
+
+       (*((uint32_t *) freq)) = f;
+       aprint_normal("psycho_get_cpufreq %u MHz (cpu %lu)\n", f,
+                       (unsigned long) cpu_number());
+}
+
+static void
+psycho_setup_cpufreq(device_t dev)
+{
+       int     ret;
+       struct psycho_softc *sc = device_private(dev);
+
+       cpu_lookup(device_unit(dev))->sc = sc;
+       aprint_normal("register UltraSPARC-IIe cpufreq driver\n");
+       ret = cpufreq_register(&(sc->sc_cf));
+
+       if (ret != 0)
+               aprint_error_dev(sc->sc_dev, "failed to register cpufreq\n");
+}
+
+
 /*
  * SUNW,psycho initialisation ..
  *     - find the per-psycho registers
@@ -690,6 +788,27 @@
        pba.pba_pc = pp->pp_pc;
 
        config_found_ia(self, "pcibus", &pba, psycho_print);
+
+       if (strstr(cpu_getmodel(), "SUNW,UltraSPARC-IIe") != NULL)
+       {
+               (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 
/ 6;
+               sc->sc_cf.cf_state_count = 3;
+
+               sc->sc_cf.cf_mp = false;
+               sc->sc_cf.cf_cookie = NULL;
+               sc->sc_cf.cf_get_freq = psycho_get_cpufreq;
+               sc->sc_cf.cf_set_freq = psycho_set_cpufreq;
+
+               (void) strlcpy(sc->sc_cf.cf_name, "us2e cpufreq",
+                               sizeof(sc->sc_cf.cf_name));
+
+               config_interrupts(sc->sc_dev, psycho_setup_cpufreq);
+       }
 }
 
 static int
Index: dev/psychovar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/psychovar.h,v
retrieving revision 1.21
diff -u -r1.21 psychovar.h
--- dev/psychovar.h     7 Dec 2013 11:17:24 -0000       1.21
+++ dev/psychovar.h     13 Sep 2014 10:41:21 -0000
@@ -125,6 +125,7 @@
        struct sysmon_pswitch           *sc_smcontext;  /* power switch 
definition */
        int                             sc_powerpressed;/* already signaled */
        uint64_t                        sc_last_stick;
+       struct cpufreq sc_cf;
 };
 
 /* get a PCI offset address from bus_space_handle_t */
Index: dev/schizo.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizo.c,v
retrieving revision 1.31
diff -u -r1.31 schizo.c
--- dev/schizo.c        21 Jun 2013 20:09:58 -0000      1.31
+++ dev/schizo.c        13 Sep 2014 10:41:21 -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,8 @@
 #include <sys/systm.h>
 #include <sys/time.h>
 #include <sys/reboot.h>
+#include <sys/cpu.h>
+#include <sys/cpufreq.h>
 
 #define _SPARC_BUS_DMA_PRIVATE
 #include <sys/bus.h>
@@ -86,6 +89,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 +142,100 @@
 }
 
 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 = curcpu()->sc;
+
+       if (sc == NULL)
+               return;
+
+       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
+       {
+               aprint_error("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);
+
+       aprint_normal("schizo_set_cpufreq %u MHz (cpu %lu)\n", f,
+                       (unsigned long) cpu_number());
+}
+
+void
+schizo_get_cpufreq(void *aux, void *freq)
+{
+       uint32_t        f;
+       uint64_t        esctrl;
+
+       struct schizo_softc *sc;
+
+       sc = curcpu()->sc;
+
+       if (sc == NULL)
+               return;
+
+       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;
+       aprint_normal("schizo_get_cpufreq %u MHz (cpu %lu)\n", f,
+                       (unsigned long) cpu_number());
+}
+
+static void
+schizo_setup_cpufreq(device_t dev)
+{
+       // schizo_setup_cpufreq() is calling once by each schizo_attach().
+
+       struct schizo_softc *sc = device_private(dev);
+       int     ret;
+
+aprint_normal("device_unit(dev)=%d\n", device_unit(dev));      
+       cpu_lookup(device_unit(dev))->sc = sc;
+
+       if (device_unit(dev) == 0)
+       {
+               aprint_normal("register safari cpufreq driver\n");
+               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 +418,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 = true;
+       sc->sc_cf.cf_cookie = NULL;
+       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: dev/schizoreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizoreg.h,v
retrieving revision 1.9
diff -u -r1.9 schizoreg.h
--- dev/schizoreg.h     25 Mar 2012 03:13:08 -0000      1.9
+++ dev/schizoreg.h     13 Sep 2014 10:41:21 -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: dev/schizovar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/schizovar.h,v
retrieving revision 1.6
diff -u -r1.6 schizovar.h
--- dev/schizovar.h     25 Mar 2012 03:13:08 -0000      1.6
+++ dev/schizovar.h     13 Sep 2014 10:41:21 -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: include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/include/cpu.h,v
retrieving revision 1.112
diff -u -r1.112 cpu.h
--- include/cpu.h       4 Sep 2014 18:48:29 -0000       1.112
+++ include/cpu.h       13 Sep 2014 10:41:22 -0000
@@ -199,6 +199,9 @@
        bool                    ci_pci_fault;
 
        volatile void           *ci_ddb_regs;   /* DDB regs */
+
+       /* cpufreq */
+       void                            *sc;
 };
 
 #endif /* _KERNEL || _KMEMUSER */
Index: sparc64/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/clock.c,v
retrieving revision 1.117
diff -u -r1.117 clock.c
--- sparc64/clock.c     25 Jul 2014 17:54:50 -0000      1.117
+++ sparc64/clock.c     13 Sep 2014 10:41:22 -0000
@@ -93,6 +93,7 @@
 #include "psycho.h"
 /* just because US-IIe STICK registers live in psycho space */
 #if NPSYCHO > 0
+#include <sys/cpufreq.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <sparc64/dev/iommureg.h>
Index: sparc64/cpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/cpu.c,v
retrieving revision 1.117
diff -u -r1.117 cpu.c
--- sparc64/cpu.c       1 Sep 2014 19:01:55 -0000       1.117
+++ sparc64/cpu.c       13 Sep 2014 10:41:22 -0000
@@ -362,6 +362,8 @@
        }
        aprint_normal_dev(dev, "");
 
+       ci->sc = NULL;
+
        /* XXX sun4v mising cache info printout */
        bigcache = 0;
 


Home | Main Index | Thread Index | Old Index