Re: UltraSPARC III/IIe cpufreq drivers, please test
BERTRAND Joël <[email protected]>
| Newsgroups | gmane.os.netbsd.ports.sparc64 |
|---|---|
| Message-ID | <[email protected]> |
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
cpufreq_patch2
(text/plain, 11.8 KB)
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 <[email protected]> * 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 ([email protected]) * Copyright (c) 2003 Henric Jungheim * Copyright (c) 2008, 2009, 2010, 2012 Matthew R. Green + * Copyright (c) 2014 Joël Bertrand ([email protected]) * 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 ([email protected]) * Copyright (c) 2010 Matthew R. Green + * Copyright (c) 2014 Joël Bertrand ([email protected]) * 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;