UltraSPARC III cpufreq driver
BERTRAND Joël <[email protected]>
| Newsgroups | gmane.os.netbsd.ports.sparc64 |
|---|---|
| Message-ID | <[email protected]> |
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
cpufreq_patch
(text/plain, 7.1 KB)
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 ([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,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 ([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: 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;