1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Hardware monitoring driver for PMBus devices |
4 | * |
5 | * Copyright (c) 2010, 2011 Ericsson AB. |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/init.h> |
11 | #include <linux/err.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/mutex.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/pmbus.h> |
16 | #include "pmbus.h" |
17 | |
18 | struct pmbus_device_info { |
19 | int pages; |
20 | u32 flags; |
21 | }; |
22 | |
23 | static const struct i2c_device_id pmbus_id[]; |
24 | |
25 | /* |
26 | * Find sensor groups and status registers on each page. |
27 | */ |
28 | static void pmbus_find_sensor_groups(struct i2c_client *client, |
29 | struct pmbus_driver_info *info) |
30 | { |
31 | int page; |
32 | |
33 | /* Sensors detected on page 0 only */ |
34 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_VIN)) |
35 | info->func[0] |= PMBUS_HAVE_VIN; |
36 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_VCAP)) |
37 | info->func[0] |= PMBUS_HAVE_VCAP; |
38 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_IIN)) |
39 | info->func[0] |= PMBUS_HAVE_IIN; |
40 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_PIN)) |
41 | info->func[0] |= PMBUS_HAVE_PIN; |
42 | if (info->func[0] |
43 | && pmbus_check_byte_register(client, page: 0, reg: PMBUS_STATUS_INPUT)) |
44 | info->func[0] |= PMBUS_HAVE_STATUS_INPUT; |
45 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_FAN_CONFIG_12) && |
46 | pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_FAN_SPEED_1)) { |
47 | info->func[0] |= PMBUS_HAVE_FAN12; |
48 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_STATUS_FAN_12)) |
49 | info->func[0] |= PMBUS_HAVE_STATUS_FAN12; |
50 | } |
51 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_FAN_CONFIG_34) && |
52 | pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_FAN_SPEED_3)) { |
53 | info->func[0] |= PMBUS_HAVE_FAN34; |
54 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_STATUS_FAN_34)) |
55 | info->func[0] |= PMBUS_HAVE_STATUS_FAN34; |
56 | } |
57 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_TEMPERATURE_1)) |
58 | info->func[0] |= PMBUS_HAVE_TEMP; |
59 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_TEMPERATURE_2)) |
60 | info->func[0] |= PMBUS_HAVE_TEMP2; |
61 | if (pmbus_check_word_register(client, page: 0, reg: PMBUS_READ_TEMPERATURE_3)) |
62 | info->func[0] |= PMBUS_HAVE_TEMP3; |
63 | if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
64 | | PMBUS_HAVE_TEMP3) |
65 | && pmbus_check_byte_register(client, page: 0, |
66 | reg: PMBUS_STATUS_TEMPERATURE)) |
67 | info->func[0] |= PMBUS_HAVE_STATUS_TEMP; |
68 | |
69 | /* Sensors detected on all pages */ |
70 | for (page = 0; page < info->pages; page++) { |
71 | if (pmbus_check_word_register(client, page, reg: PMBUS_READ_VOUT)) { |
72 | info->func[page] |= PMBUS_HAVE_VOUT; |
73 | if (pmbus_check_byte_register(client, page, |
74 | reg: PMBUS_STATUS_VOUT)) |
75 | info->func[page] |= PMBUS_HAVE_STATUS_VOUT; |
76 | } |
77 | if (pmbus_check_word_register(client, page, reg: PMBUS_READ_IOUT)) { |
78 | info->func[page] |= PMBUS_HAVE_IOUT; |
79 | if (pmbus_check_byte_register(client, page: 0, |
80 | reg: PMBUS_STATUS_IOUT)) |
81 | info->func[page] |= PMBUS_HAVE_STATUS_IOUT; |
82 | } |
83 | if (pmbus_check_word_register(client, page, reg: PMBUS_READ_POUT)) |
84 | info->func[page] |= PMBUS_HAVE_POUT; |
85 | } |
86 | } |
87 | |
88 | /* |
89 | * Identify chip parameters. |
90 | */ |
91 | static int pmbus_identify(struct i2c_client *client, |
92 | struct pmbus_driver_info *info) |
93 | { |
94 | int ret = 0; |
95 | |
96 | if (!info->pages) { |
97 | /* |
98 | * Check if the PAGE command is supported. If it is, |
99 | * keep setting the page number until it fails or until the |
100 | * maximum number of pages has been reached. Assume that |
101 | * this is the number of pages supported by the chip. |
102 | */ |
103 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_PAGE)) { |
104 | int page; |
105 | |
106 | for (page = 1; page < PMBUS_PAGES; page++) { |
107 | if (pmbus_set_page(client, page, phase: 0xff) < 0) |
108 | break; |
109 | } |
110 | pmbus_set_page(client, page: 0, phase: 0xff); |
111 | info->pages = page; |
112 | } else { |
113 | info->pages = 1; |
114 | } |
115 | |
116 | pmbus_clear_faults(client); |
117 | } |
118 | |
119 | if (pmbus_check_byte_register(client, page: 0, reg: PMBUS_VOUT_MODE)) { |
120 | int vout_mode, i; |
121 | |
122 | vout_mode = pmbus_read_byte_data(client, page: 0, reg: PMBUS_VOUT_MODE); |
123 | if (vout_mode >= 0 && vout_mode != 0xff) { |
124 | switch (vout_mode >> 5) { |
125 | case 0: |
126 | break; |
127 | case 1: |
128 | info->format[PSC_VOLTAGE_OUT] = vid; |
129 | for (i = 0; i < info->pages; i++) |
130 | info->vrm_version[i] = vr11; |
131 | break; |
132 | case 2: |
133 | info->format[PSC_VOLTAGE_OUT] = direct; |
134 | break; |
135 | default: |
136 | ret = -ENODEV; |
137 | goto abort; |
138 | } |
139 | } |
140 | } |
141 | |
142 | /* |
143 | * We should check if the COEFFICIENTS register is supported. |
144 | * If it is, and the chip is configured for direct mode, we can read |
145 | * the coefficients from the chip, one set per group of sensor |
146 | * registers. |
147 | * |
148 | * To do this, we will need access to a chip which actually supports the |
149 | * COEFFICIENTS command, since the command is too complex to implement |
150 | * without testing it. Until then, abort if a chip configured for direct |
151 | * mode was detected. |
152 | */ |
153 | if (info->format[PSC_VOLTAGE_OUT] == direct) { |
154 | ret = -ENODEV; |
155 | goto abort; |
156 | } |
157 | |
158 | /* Try to find sensor groups */ |
159 | pmbus_find_sensor_groups(client, info); |
160 | abort: |
161 | return ret; |
162 | } |
163 | |
164 | static int pmbus_probe(struct i2c_client *client) |
165 | { |
166 | struct pmbus_driver_info *info; |
167 | struct pmbus_platform_data *pdata = NULL; |
168 | struct device *dev = &client->dev; |
169 | struct pmbus_device_info *device_info; |
170 | |
171 | info = devm_kzalloc(dev, size: sizeof(struct pmbus_driver_info), GFP_KERNEL); |
172 | if (!info) |
173 | return -ENOMEM; |
174 | |
175 | device_info = (struct pmbus_device_info *)i2c_match_id(id: pmbus_id, client)->driver_data; |
176 | if (device_info->flags) { |
177 | pdata = devm_kzalloc(dev, size: sizeof(struct pmbus_platform_data), |
178 | GFP_KERNEL); |
179 | if (!pdata) |
180 | return -ENOMEM; |
181 | |
182 | pdata->flags = device_info->flags; |
183 | } |
184 | |
185 | info->pages = device_info->pages; |
186 | info->identify = pmbus_identify; |
187 | dev->platform_data = pdata; |
188 | |
189 | return pmbus_do_probe(client, info); |
190 | } |
191 | |
192 | static const struct pmbus_device_info pmbus_info_one = { |
193 | .pages = 1, |
194 | .flags = 0 |
195 | }; |
196 | |
197 | static const struct pmbus_device_info pmbus_info_zero = { |
198 | .pages = 0, |
199 | .flags = 0 |
200 | }; |
201 | |
202 | static const struct pmbus_device_info pmbus_info_one_skip = { |
203 | .pages = 1, |
204 | .flags = PMBUS_SKIP_STATUS_CHECK |
205 | }; |
206 | |
207 | static const struct pmbus_device_info pmbus_info_one_status = { |
208 | .pages = 1, |
209 | .flags = PMBUS_READ_STATUS_AFTER_FAILED_CHECK |
210 | }; |
211 | |
212 | /* |
213 | * Use driver_data to set the number of pages supported by the chip. |
214 | */ |
215 | static const struct i2c_device_id pmbus_id[] = { |
216 | {"adp4000" , (kernel_ulong_t)&pmbus_info_one}, |
217 | {"bmr310" , (kernel_ulong_t)&pmbus_info_one_status}, |
218 | {"bmr453" , (kernel_ulong_t)&pmbus_info_one}, |
219 | {"bmr454" , (kernel_ulong_t)&pmbus_info_one}, |
220 | {"bmr456" , (kernel_ulong_t)&pmbus_info_one}, |
221 | {"bmr457" , (kernel_ulong_t)&pmbus_info_one}, |
222 | {"bmr458" , (kernel_ulong_t)&pmbus_info_one_status}, |
223 | {"bmr480" , (kernel_ulong_t)&pmbus_info_one_status}, |
224 | {"bmr490" , (kernel_ulong_t)&pmbus_info_one_status}, |
225 | {"bmr491" , (kernel_ulong_t)&pmbus_info_one_status}, |
226 | {"bmr492" , (kernel_ulong_t)&pmbus_info_one}, |
227 | {"dps460" , (kernel_ulong_t)&pmbus_info_one_skip}, |
228 | {"dps650ab" , (kernel_ulong_t)&pmbus_info_one_skip}, |
229 | {"dps800" , (kernel_ulong_t)&pmbus_info_one_skip}, |
230 | {"max20796" , (kernel_ulong_t)&pmbus_info_one}, |
231 | {"mdt040" , (kernel_ulong_t)&pmbus_info_one}, |
232 | {"ncp4200" , (kernel_ulong_t)&pmbus_info_one}, |
233 | {"ncp4208" , (kernel_ulong_t)&pmbus_info_one}, |
234 | {"pdt003" , (kernel_ulong_t)&pmbus_info_one}, |
235 | {"pdt006" , (kernel_ulong_t)&pmbus_info_one}, |
236 | {"pdt012" , (kernel_ulong_t)&pmbus_info_one}, |
237 | {"pmbus" , (kernel_ulong_t)&pmbus_info_zero}, |
238 | {"sgd009" , (kernel_ulong_t)&pmbus_info_one_skip}, |
239 | {"tps40400" , (kernel_ulong_t)&pmbus_info_one}, |
240 | {"tps544b20" , (kernel_ulong_t)&pmbus_info_one}, |
241 | {"tps544b25" , (kernel_ulong_t)&pmbus_info_one}, |
242 | {"tps544c20" , (kernel_ulong_t)&pmbus_info_one}, |
243 | {"tps544c25" , (kernel_ulong_t)&pmbus_info_one}, |
244 | {"udt020" , (kernel_ulong_t)&pmbus_info_one}, |
245 | {} |
246 | }; |
247 | |
248 | MODULE_DEVICE_TABLE(i2c, pmbus_id); |
249 | |
250 | /* This is the driver that will be inserted */ |
251 | static struct i2c_driver pmbus_driver = { |
252 | .driver = { |
253 | .name = "pmbus" , |
254 | }, |
255 | .probe = pmbus_probe, |
256 | .id_table = pmbus_id, |
257 | }; |
258 | |
259 | module_i2c_driver(pmbus_driver); |
260 | |
261 | MODULE_AUTHOR("Guenter Roeck" ); |
262 | MODULE_DESCRIPTION("Generic PMBus driver" ); |
263 | MODULE_LICENSE("GPL" ); |
264 | MODULE_IMPORT_NS(PMBUS); |
265 | |