.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Hardware monitoring driver for PMBus devices |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2010, 2011 Ericsson AB. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program; if not, write to the Free Software |
---|
18 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
19 | 6 | */ |
---|
20 | 7 | |
---|
21 | 8 | #include <linux/kernel.h> |
---|
.. | .. |
---|
27 | 14 | #include <linux/i2c.h> |
---|
28 | 15 | #include <linux/pmbus.h> |
---|
29 | 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[]; |
---|
30 | 24 | |
---|
31 | 25 | /* |
---|
32 | 26 | * Find sensor groups and status registers on each page. |
---|
.. | .. |
---|
110 | 104 | int page; |
---|
111 | 105 | |
---|
112 | 106 | for (page = 1; page < PMBUS_PAGES; page++) { |
---|
113 | | - if (pmbus_set_page(client, page) < 0) |
---|
| 107 | + if (pmbus_set_page(client, page, 0xff) < 0) |
---|
114 | 108 | break; |
---|
115 | 109 | } |
---|
116 | | - pmbus_set_page(client, 0); |
---|
| 110 | + pmbus_set_page(client, 0, 0xff); |
---|
117 | 111 | info->pages = page; |
---|
118 | 112 | } else { |
---|
119 | 113 | info->pages = 1; |
---|
.. | .. |
---|
123 | 117 | } |
---|
124 | 118 | |
---|
125 | 119 | if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { |
---|
126 | | - int vout_mode; |
---|
| 120 | + int vout_mode, i; |
---|
127 | 121 | |
---|
128 | 122 | vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); |
---|
129 | 123 | if (vout_mode >= 0 && vout_mode != 0xff) { |
---|
.. | .. |
---|
132 | 126 | break; |
---|
133 | 127 | case 1: |
---|
134 | 128 | info->format[PSC_VOLTAGE_OUT] = vid; |
---|
135 | | - info->vrm_version = vr11; |
---|
| 129 | + for (i = 0; i < info->pages; i++) |
---|
| 130 | + info->vrm_version[i] = vr11; |
---|
136 | 131 | break; |
---|
137 | 132 | case 2: |
---|
138 | 133 | info->format[PSC_VOLTAGE_OUT] = direct; |
---|
.. | .. |
---|
166 | 161 | return ret; |
---|
167 | 162 | } |
---|
168 | 163 | |
---|
169 | | -static int pmbus_probe(struct i2c_client *client, |
---|
170 | | - const struct i2c_device_id *id) |
---|
| 164 | +static int pmbus_probe(struct i2c_client *client) |
---|
171 | 165 | { |
---|
172 | 166 | struct pmbus_driver_info *info; |
---|
173 | 167 | struct pmbus_platform_data *pdata = NULL; |
---|
174 | 168 | struct device *dev = &client->dev; |
---|
| 169 | + struct pmbus_device_info *device_info; |
---|
175 | 170 | |
---|
176 | 171 | info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); |
---|
177 | 172 | if (!info) |
---|
178 | 173 | return -ENOMEM; |
---|
179 | 174 | |
---|
180 | | - if (!strcmp(id->name, "dps460") || !strcmp(id->name, "dps800") || |
---|
181 | | - !strcmp(id->name, "sgd009")) { |
---|
| 175 | + device_info = (struct pmbus_device_info *)i2c_match_id(pmbus_id, client)->driver_data; |
---|
| 176 | + if (device_info->flags & PMBUS_SKIP_STATUS_CHECK) { |
---|
182 | 177 | pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data), |
---|
183 | 178 | GFP_KERNEL); |
---|
184 | 179 | if (!pdata) |
---|
.. | .. |
---|
187 | 182 | pdata->flags = PMBUS_SKIP_STATUS_CHECK; |
---|
188 | 183 | } |
---|
189 | 184 | |
---|
190 | | - info->pages = id->driver_data; |
---|
| 185 | + info->pages = device_info->pages; |
---|
191 | 186 | info->identify = pmbus_identify; |
---|
192 | 187 | dev->platform_data = pdata; |
---|
193 | 188 | |
---|
194 | | - return pmbus_do_probe(client, id, info); |
---|
| 189 | + return pmbus_do_probe(client, info); |
---|
195 | 190 | } |
---|
| 191 | + |
---|
| 192 | +static const struct pmbus_device_info pmbus_info_one = { |
---|
| 193 | + .pages = 1, |
---|
| 194 | + .flags = 0 |
---|
| 195 | +}; |
---|
| 196 | +static const struct pmbus_device_info pmbus_info_zero = { |
---|
| 197 | + .pages = 0, |
---|
| 198 | + .flags = 0 |
---|
| 199 | +}; |
---|
| 200 | +static const struct pmbus_device_info pmbus_info_one_skip = { |
---|
| 201 | + .pages = 1, |
---|
| 202 | + .flags = PMBUS_SKIP_STATUS_CHECK |
---|
| 203 | +}; |
---|
196 | 204 | |
---|
197 | 205 | /* |
---|
198 | 206 | * Use driver_data to set the number of pages supported by the chip. |
---|
199 | 207 | */ |
---|
200 | 208 | static const struct i2c_device_id pmbus_id[] = { |
---|
201 | | - {"adp4000", 1}, |
---|
202 | | - {"bmr453", 1}, |
---|
203 | | - {"bmr454", 1}, |
---|
204 | | - {"dps460", 1}, |
---|
205 | | - {"dps800", 1}, |
---|
206 | | - {"mdt040", 1}, |
---|
207 | | - {"ncp4200", 1}, |
---|
208 | | - {"ncp4208", 1}, |
---|
209 | | - {"pdt003", 1}, |
---|
210 | | - {"pdt006", 1}, |
---|
211 | | - {"pdt012", 1}, |
---|
212 | | - {"pmbus", 0}, |
---|
213 | | - {"sgd009", 1}, |
---|
214 | | - {"tps40400", 1}, |
---|
215 | | - {"tps544b20", 1}, |
---|
216 | | - {"tps544b25", 1}, |
---|
217 | | - {"tps544c20", 1}, |
---|
218 | | - {"tps544c25", 1}, |
---|
219 | | - {"udt020", 1}, |
---|
| 209 | + {"adp4000", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 210 | + {"bmr453", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 211 | + {"bmr454", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 212 | + {"dps460", (kernel_ulong_t)&pmbus_info_one_skip}, |
---|
| 213 | + {"dps650ab", (kernel_ulong_t)&pmbus_info_one_skip}, |
---|
| 214 | + {"dps800", (kernel_ulong_t)&pmbus_info_one_skip}, |
---|
| 215 | + {"max20796", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 216 | + {"mdt040", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 217 | + {"ncp4200", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 218 | + {"ncp4208", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 219 | + {"pdt003", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 220 | + {"pdt006", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 221 | + {"pdt012", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 222 | + {"pmbus", (kernel_ulong_t)&pmbus_info_zero}, |
---|
| 223 | + {"sgd009", (kernel_ulong_t)&pmbus_info_one_skip}, |
---|
| 224 | + {"tps40400", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 225 | + {"tps544b20", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 226 | + {"tps544b25", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 227 | + {"tps544c20", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 228 | + {"tps544c25", (kernel_ulong_t)&pmbus_info_one}, |
---|
| 229 | + {"udt020", (kernel_ulong_t)&pmbus_info_one}, |
---|
220 | 230 | {} |
---|
221 | 231 | }; |
---|
222 | 232 | |
---|
.. | .. |
---|
227 | 237 | .driver = { |
---|
228 | 238 | .name = "pmbus", |
---|
229 | 239 | }, |
---|
230 | | - .probe = pmbus_probe, |
---|
| 240 | + .probe_new = pmbus_probe, |
---|
231 | 241 | .remove = pmbus_do_remove, |
---|
232 | 242 | .id_table = pmbus_id, |
---|
233 | 243 | }; |
---|