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