1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _LINUX_UNITS_H
3  #define _LINUX_UNITS_H
4  
5  #include <linux/bits.h>
6  #include <linux/math.h>
7  
8  /* Metric prefixes in accordance with Système international (d'unités) */
9  #define PETA	1000000000000000ULL
10  #define TERA	1000000000000ULL
11  #define GIGA	1000000000UL
12  #define MEGA	1000000UL
13  #define KILO	1000UL
14  #define HECTO	100UL
15  #define DECA	10UL
16  #define DECI	10UL
17  #define CENTI	100UL
18  #define MILLI	1000UL
19  #define MICRO	1000000UL
20  #define NANO	1000000000UL
21  #define PICO	1000000000000ULL
22  #define FEMTO	1000000000000000ULL
23  
24  #define NANOHZ_PER_HZ		1000000000UL
25  #define MICROHZ_PER_HZ		1000000UL
26  #define MILLIHZ_PER_HZ		1000UL
27  
28  #define HZ_PER_KHZ		1000UL
29  #define HZ_PER_MHZ		1000000UL
30  
31  #define KHZ_PER_MHZ		1000UL
32  #define KHZ_PER_GHZ		1000000UL
33  
34  #define MILLIWATT_PER_WATT	1000UL
35  #define MICROWATT_PER_MILLIWATT	1000UL
36  #define MICROWATT_PER_WATT	1000000UL
37  
38  #define BYTES_PER_KBIT		(KILO / BITS_PER_BYTE)
39  #define BYTES_PER_MBIT		(MEGA / BITS_PER_BYTE)
40  #define BYTES_PER_GBIT		(GIGA / BITS_PER_BYTE)
41  
42  #define ABSOLUTE_ZERO_MILLICELSIUS -273150
43  
milli_kelvin_to_millicelsius(long t)44  static inline long milli_kelvin_to_millicelsius(long t)
45  {
46  	return t + ABSOLUTE_ZERO_MILLICELSIUS;
47  }
48  
millicelsius_to_milli_kelvin(long t)49  static inline long millicelsius_to_milli_kelvin(long t)
50  {
51  	return t - ABSOLUTE_ZERO_MILLICELSIUS;
52  }
53  
54  #define MILLIDEGREE_PER_DEGREE 1000
55  #define MILLIDEGREE_PER_DECIDEGREE 100
56  
kelvin_to_millicelsius(long t)57  static inline long kelvin_to_millicelsius(long t)
58  {
59  	return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE);
60  }
61  
millicelsius_to_kelvin(long t)62  static inline long millicelsius_to_kelvin(long t)
63  {
64  	t = millicelsius_to_milli_kelvin(t);
65  
66  	return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
67  }
68  
deci_kelvin_to_celsius(long t)69  static inline long deci_kelvin_to_celsius(long t)
70  {
71  	t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
72  
73  	return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
74  }
75  
celsius_to_deci_kelvin(long t)76  static inline long celsius_to_deci_kelvin(long t)
77  {
78  	t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE);
79  
80  	return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
81  }
82  
83  /**
84   * deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius
85   * @t: temperature value in decidegrees Kelvin
86   * @offset: difference between Kelvin and Celsius in millidegrees
87   *
88   * Return: temperature value in millidegrees Celsius
89   */
deci_kelvin_to_millicelsius_with_offset(long t,long offset)90  static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset)
91  {
92  	return t * MILLIDEGREE_PER_DECIDEGREE - offset;
93  }
94  
deci_kelvin_to_millicelsius(long t)95  static inline long deci_kelvin_to_millicelsius(long t)
96  {
97  	return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
98  }
99  
millicelsius_to_deci_kelvin(long t)100  static inline long millicelsius_to_deci_kelvin(long t)
101  {
102  	t = millicelsius_to_milli_kelvin(t);
103  
104  	return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
105  }
106  
kelvin_to_celsius(long t)107  static inline long kelvin_to_celsius(long t)
108  {
109  	return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
110  				     MILLIDEGREE_PER_DEGREE);
111  }
112  
celsius_to_kelvin(long t)113  static inline long celsius_to_kelvin(long t)
114  {
115  	return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
116  				     MILLIDEGREE_PER_DEGREE);
117  }
118  
119  #endif /* _LINUX_UNITS_H */
120