1*9fdf0c62Smpi /* $OpenBSD: pwmfan.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */
2572fa3f5Spatrick /*
3572fa3f5Spatrick * Copyright (c) 2019 Krystian Lewandowski
4572fa3f5Spatrick * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
5572fa3f5Spatrick * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
6572fa3f5Spatrick *
7572fa3f5Spatrick * Permission to use, copy, modify, and distribute this software for any
8572fa3f5Spatrick * purpose with or without fee is hereby granted, provided that the above
9572fa3f5Spatrick * copyright notice and this permission notice appear in all copies.
10572fa3f5Spatrick *
11572fa3f5Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12572fa3f5Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13572fa3f5Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14572fa3f5Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15572fa3f5Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16572fa3f5Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17572fa3f5Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18572fa3f5Spatrick */
19572fa3f5Spatrick
20572fa3f5Spatrick #include <sys/param.h>
21572fa3f5Spatrick #include <sys/systm.h>
22572fa3f5Spatrick #include <sys/device.h>
23572fa3f5Spatrick #include <sys/malloc.h>
24572fa3f5Spatrick
25572fa3f5Spatrick #include <machine/fdt.h>
26572fa3f5Spatrick #include <machine/bus.h>
27572fa3f5Spatrick
28572fa3f5Spatrick #include <dev/ofw/openfirm.h>
29572fa3f5Spatrick #include <dev/ofw/ofw_gpio.h>
30572fa3f5Spatrick #include <dev/ofw/ofw_misc.h>
31572fa3f5Spatrick #include <dev/ofw/ofw_thermal.h>
32572fa3f5Spatrick
33572fa3f5Spatrick struct pwmfan_softc {
34572fa3f5Spatrick struct device sc_dev;
35572fa3f5Spatrick uint32_t *sc_pwm;
36572fa3f5Spatrick int sc_pwm_len;
37572fa3f5Spatrick uint32_t *sc_levels;
38572fa3f5Spatrick int sc_nlevels;
39572fa3f5Spatrick int sc_curlevel;
40572fa3f5Spatrick
41572fa3f5Spatrick struct cooling_device sc_cd;
42572fa3f5Spatrick };
43572fa3f5Spatrick
44572fa3f5Spatrick int pwmfan_match(struct device *, void *, void *);
45572fa3f5Spatrick void pwmfan_attach(struct device *, struct device *, void *);
46572fa3f5Spatrick
47*9fdf0c62Smpi const struct cfattach pwmfan_ca = {
48572fa3f5Spatrick sizeof(struct pwmfan_softc), pwmfan_match, pwmfan_attach
49572fa3f5Spatrick };
50572fa3f5Spatrick
51572fa3f5Spatrick struct cfdriver pwmfan_cd = {
52572fa3f5Spatrick NULL, "pwmfan", DV_DULL
53572fa3f5Spatrick };
54572fa3f5Spatrick
55572fa3f5Spatrick uint32_t pwmfan_get_cooling_level(void *, uint32_t *);
56572fa3f5Spatrick void pwmfan_set_cooling_level(void *, uint32_t *, uint32_t);
57572fa3f5Spatrick
58572fa3f5Spatrick int
pwmfan_match(struct device * parent,void * match,void * aux)59572fa3f5Spatrick pwmfan_match(struct device *parent, void *match, void *aux)
60572fa3f5Spatrick {
61572fa3f5Spatrick struct fdt_attach_args *faa = aux;
62572fa3f5Spatrick
63572fa3f5Spatrick return OF_is_compatible(faa->fa_node, "pwm-fan");
64572fa3f5Spatrick }
65572fa3f5Spatrick
66572fa3f5Spatrick void
pwmfan_attach(struct device * parent,struct device * self,void * aux)67572fa3f5Spatrick pwmfan_attach(struct device *parent, struct device *self, void *aux)
68572fa3f5Spatrick {
69572fa3f5Spatrick struct pwmfan_softc *sc = (struct pwmfan_softc *)self;
70572fa3f5Spatrick struct fdt_attach_args *faa = aux;
71572fa3f5Spatrick int len;
72572fa3f5Spatrick
73572fa3f5Spatrick len = OF_getproplen(faa->fa_node, "pwms");
74572fa3f5Spatrick if (len < 0) {
75572fa3f5Spatrick printf(": no pwm\n");
76572fa3f5Spatrick return;
77572fa3f5Spatrick }
78572fa3f5Spatrick
79572fa3f5Spatrick sc->sc_pwm = malloc(len, M_DEVBUF, M_WAITOK);
80572fa3f5Spatrick OF_getpropintarray(faa->fa_node, "pwms", sc->sc_pwm, len);
81572fa3f5Spatrick sc->sc_pwm_len = len;
82572fa3f5Spatrick
83572fa3f5Spatrick len = OF_getproplen(faa->fa_node, "cooling-levels");
84572fa3f5Spatrick if (len < 0) {
85572fa3f5Spatrick free(sc->sc_pwm, M_DEVBUF, sc->sc_pwm_len);
86572fa3f5Spatrick printf(": no cooling levels\n");
87572fa3f5Spatrick return;
88572fa3f5Spatrick }
89572fa3f5Spatrick
90572fa3f5Spatrick sc->sc_levels = malloc(len, M_DEVBUF, M_WAITOK);
91572fa3f5Spatrick OF_getpropintarray(faa->fa_node, "cooling-levels",
92572fa3f5Spatrick sc->sc_levels, len);
93572fa3f5Spatrick sc->sc_nlevels = len / sizeof(uint32_t);
94572fa3f5Spatrick
95572fa3f5Spatrick printf("\n");
96572fa3f5Spatrick
97572fa3f5Spatrick sc->sc_cd.cd_node = faa->fa_node;
98572fa3f5Spatrick sc->sc_cd.cd_cookie = sc;
99572fa3f5Spatrick sc->sc_cd.cd_get_level = pwmfan_get_cooling_level;
100572fa3f5Spatrick sc->sc_cd.cd_set_level = pwmfan_set_cooling_level;
101572fa3f5Spatrick cooling_device_register(&sc->sc_cd);
102572fa3f5Spatrick }
103572fa3f5Spatrick
104572fa3f5Spatrick uint32_t
pwmfan_get_cooling_level(void * cookie,uint32_t * cells)105572fa3f5Spatrick pwmfan_get_cooling_level(void *cookie, uint32_t *cells)
106572fa3f5Spatrick {
107572fa3f5Spatrick struct pwmfan_softc *sc = cookie;
108572fa3f5Spatrick
109572fa3f5Spatrick return sc->sc_curlevel;
110572fa3f5Spatrick }
111572fa3f5Spatrick
112572fa3f5Spatrick void
pwmfan_set_cooling_level(void * cookie,uint32_t * cells,uint32_t level)113572fa3f5Spatrick pwmfan_set_cooling_level(void *cookie, uint32_t *cells, uint32_t level)
114572fa3f5Spatrick {
115572fa3f5Spatrick struct pwmfan_softc *sc = cookie;
116572fa3f5Spatrick struct pwm_state ps;
117572fa3f5Spatrick
118572fa3f5Spatrick if (level == sc->sc_curlevel || level > sc->sc_nlevels ||
119572fa3f5Spatrick sc->sc_levels[level] > 255)
120572fa3f5Spatrick return;
121572fa3f5Spatrick
122572fa3f5Spatrick if (pwm_init_state(sc->sc_pwm, &ps))
123572fa3f5Spatrick return;
124572fa3f5Spatrick
125572fa3f5Spatrick sc->sc_curlevel = level;
126572fa3f5Spatrick level = sc->sc_levels[level];
127572fa3f5Spatrick
128572fa3f5Spatrick ps.ps_enabled = level ? 1 : 0;
129572fa3f5Spatrick ps.ps_pulse_width = (ps.ps_period * level) / 255;
130572fa3f5Spatrick pwm_set_state(sc->sc_pwm, &ps);
131572fa3f5Spatrick }
132