summaryrefslogtreecommitdiff
path: root/include/fan.h
blob: 31af7a58ffff2c25d7285324e7d7a0e76b83b0b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* Copyright 2013 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Fan control module for Chrome EC */

#ifndef __CROS_EC_FAN_H
#define __CROS_EC_FAN_H

#ifdef CONFIG_ZEPHYR
#ifdef CONFIG_PLATFORM_EC_FAN

#include <zephyr/devicetree.h>
#define NODE_ID_AND_COMMA(node_id) node_id,
enum fan_channel {
#if DT_NODE_EXISTS(DT_INST(0, cros_ec_fans))
	DT_FOREACH_CHILD(DT_INST(0, cros_ec_fans), NODE_ID_AND_COMMA)
#endif /* cros_ec_fans */
		FAN_CH_COUNT
};

BUILD_ASSERT(FAN_CH_COUNT == CONFIG_PLATFORM_EC_NUM_FANS);

#endif /* CONFIG_PLATFORM_EC_FAN */
#endif /* CONFIG_ZEPHYR */

struct fan_conf {
	unsigned int flags;
	/* Hardware channel number (the meaning is chip-specific) */
	int ch;
	/* Active-high power_good input GPIO, or -1 if none */
	int pgood_gpio;
	/* Active-high power_enable output GPIO, or -1 if none */
	int enable_gpio;
};

struct fan_rpm {
	/* rpm_min is to keep turning. rpm_start is to begin turning */
	int rpm_min;
	int rpm_start;
	int rpm_max;
};

/* Characteristic of each physical fan */
struct fan_t {
	const struct fan_conf *conf;
	const struct fan_rpm *rpm;
};

/* Values for .flags field */
/*   Enable automatic RPM control using tach input */
#define FAN_USE_RPM_MODE BIT(0)
/*   Require a higher duty cycle to start up than to keep running */
#define FAN_USE_FAST_START BIT(1)

/* The list of fans is instantiated in board.c. */
#ifdef CONFIG_FAN_DYNAMIC
extern struct fan_t fans[];
#else
extern const struct fan_t fans[];
#endif

/* For convenience */
#define FAN_CH(fan) fans[fan].conf->ch

/**
 * Set the amount of active cooling needed. The thermal control task will call
 * this frequently, and the fan control logic will attempt to provide it.
 *
 * @param fan   Fan number (index into fans[])
 * @param pct   Percentage of cooling effort needed (0 - 100)
 */
void fan_set_percent_needed(int fan, int pct);

/**
 * This function translates the percentage of cooling needed into a target RPM.
 * The default implementation should be sufficient for most needs, but
 * individual boards may provide a custom version if needed (see config.h).
 *
 * @param fan   Fan number (index into fans[])
 * @param pct   Percentage of cooling effort needed (always in [0,100])
 * Return       Target RPM for fan
 */
int fan_percent_to_rpm(int fan, int pct);

/**
 * These functions require chip-specific implementations.
 */

/* Enable/Disable the fan controller */
void fan_set_enabled(int ch, int enabled);
int fan_get_enabled(int ch);

/* Fixed pwm duty cycle (0-100%) */
void fan_set_duty(int ch, int percent);
int fan_get_duty(int ch);

/* Enable/Disable automatic RPM control using tach feedback */
void fan_set_rpm_mode(int ch, int rpm_mode);
int fan_get_rpm_mode(int ch);

/* Set the target for the automatic RPM control */
void fan_set_rpm_target(int ch, int rpm);
int fan_get_rpm_actual(int ch);
int fan_get_rpm_target(int ch);

/* Is the fan stalled when it shouldn't be? */
int fan_is_stalled(int ch);

/**
 * STOPPED means not spinning.
 *
 * When setting fan rpm, some implementations in chip layer (npcx and it83xx)
 * is to adjust fan pwm duty steps by steps. In this period, fan_status will
 * be marked as CHANGING. After change is done, fan_status will become LOCKED.
 *
 * In the period of changing pwm duty, if it's trying to increase/decrease duty
 * even when duty is already in upper/lower bound. Then this action won't work,
 * and fan_status will be marked as FRUSTRATED.
 *
 * For other implementations in chip layer (mchp), there is no
 * changing period. So they don't have CHANGING status.
 * Just return status as LOCKED in normal spinning case, return STOPPED when
 * not spinning, return FRUSTRATED when the related flags (which is read from
 * chip's register) is set.
 */
enum fan_status {
	FAN_STATUS_STOPPED = 0,
	FAN_STATUS_CHANGING = 1,
	FAN_STATUS_LOCKED = 2,
	FAN_STATUS_FRUSTRATED = 3
};
enum fan_status fan_get_status(int ch);

/* Initialize the HW according to the desired flags */
void fan_channel_setup(int ch, unsigned int flags);

int fan_get_count(void);

void fan_set_count(int count);

int is_thermal_control_enabled(int idx);

#endif /* __CROS_EC_FAN_H */