Merge tag 'thermal-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / mellanox / mlxsw / core_thermal.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved
3  * Copyright (c) 2016 Ivan Vecera <cera@cera.cz>
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/device.h>
9 #include <linux/sysfs.h>
10 #include <linux/thermal.h>
11 #include <linux/err.h>
12 #include <linux/sfp.h>
13
14 #include "core.h"
15 #include "core_env.h"
16
17 #define MLXSW_THERMAL_POLL_INT  1000    /* ms */
18 #define MLXSW_THERMAL_SLOW_POLL_INT     20000   /* ms */
19 #define MLXSW_THERMAL_ASIC_TEMP_NORM    75000   /* 75C */
20 #define MLXSW_THERMAL_ASIC_TEMP_HIGH    85000   /* 85C */
21 #define MLXSW_THERMAL_ASIC_TEMP_HOT     105000  /* 105C */
22 #define MLXSW_THERMAL_HYSTERESIS_TEMP   5000    /* 5C */
23 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
24 #define MLXSW_THERMAL_MAX_STATE 10
25 #define MLXSW_THERMAL_MIN_STATE 2
26 #define MLXSW_THERMAL_MAX_DUTY  255
27
28 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
29 static char * const mlxsw_thermal_external_allowed_cdev[] = {
30         "mlxreg_fan",
31 };
32
33 enum mlxsw_thermal_trips {
34         MLXSW_THERMAL_TEMP_TRIP_NORM,
35         MLXSW_THERMAL_TEMP_TRIP_HIGH,
36         MLXSW_THERMAL_TEMP_TRIP_HOT,
37 };
38
39 struct mlxsw_thermal_trip {
40         int     type;
41         int     temp;
42         int     hyst;
43         int     min_state;
44         int     max_state;
45 };
46
47 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
48         {       /* In range - 0-40% PWM */
49                 .type           = THERMAL_TRIP_ACTIVE,
50                 .temp           = MLXSW_THERMAL_ASIC_TEMP_NORM,
51                 .hyst           = MLXSW_THERMAL_HYSTERESIS_TEMP,
52                 .min_state      = 0,
53                 .max_state      = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
54         },
55         {
56                 /* In range - 40-100% PWM */
57                 .type           = THERMAL_TRIP_ACTIVE,
58                 .temp           = MLXSW_THERMAL_ASIC_TEMP_HIGH,
59                 .hyst           = MLXSW_THERMAL_HYSTERESIS_TEMP,
60                 .min_state      = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
61                 .max_state      = MLXSW_THERMAL_MAX_STATE,
62         },
63         {       /* Warning */
64                 .type           = THERMAL_TRIP_HOT,
65                 .temp           = MLXSW_THERMAL_ASIC_TEMP_HOT,
66                 .min_state      = MLXSW_THERMAL_MAX_STATE,
67                 .max_state      = MLXSW_THERMAL_MAX_STATE,
68         },
69 };
70
71 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
72
73 /* Make sure all trips are writable */
74 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
75
76 struct mlxsw_thermal;
77
78 struct mlxsw_thermal_module {
79         struct mlxsw_thermal *parent;
80         struct thermal_zone_device *tzdev;
81         struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
82         int module; /* Module or gearbox number */
83         u8 slot_index;
84 };
85
86 struct mlxsw_thermal_area {
87         struct mlxsw_thermal_module *tz_module_arr;
88         u8 tz_module_num;
89         struct mlxsw_thermal_module *tz_gearbox_arr;
90         u8 tz_gearbox_num;
91         u8 slot_index;
92         bool active;
93 };
94
95 struct mlxsw_thermal {
96         struct mlxsw_core *core;
97         const struct mlxsw_bus_info *bus_info;
98         struct thermal_zone_device *tzdev;
99         int polling_delay;
100         struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
101         u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
102         struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
103         struct mlxsw_thermal_area line_cards[];
104 };
105
106 static inline u8 mlxsw_state_to_duty(int state)
107 {
108         return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
109                                  MLXSW_THERMAL_MAX_STATE);
110 }
111
112 static inline int mlxsw_duty_to_state(u8 duty)
113 {
114         return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
115                                  MLXSW_THERMAL_MAX_DUTY);
116 }
117
118 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
119                                         struct thermal_cooling_device *cdev)
120 {
121         int i;
122
123         for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
124                 if (thermal->cdevs[i] == cdev)
125                         return i;
126
127         /* Allow mlxsw thermal zone binding to an external cooling device */
128         for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
129                 if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
130                         return 0;
131         }
132
133         return -ENODEV;
134 }
135
136 static void
137 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
138 {
139         tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
140         tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
141         tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
142 }
143
144 static int
145 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
146                                   struct mlxsw_thermal_module *tz,
147                                   int crit_temp, int emerg_temp)
148 {
149         int err;
150
151         /* Do not try to query temperature thresholds directly from the module's
152          * EEPROM if we got valid thresholds from MTMP.
153          */
154         if (!emerg_temp || !crit_temp) {
155                 err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
156                                                            tz->module,
157                                                            SFP_TEMP_HIGH_WARN,
158                                                            &crit_temp);
159                 if (err)
160                         return err;
161
162                 err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
163                                                            tz->module,
164                                                            SFP_TEMP_HIGH_ALARM,
165                                                            &emerg_temp);
166                 if (err)
167                         return err;
168         }
169
170         if (crit_temp > emerg_temp) {
171                 dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
172                          tz->tzdev->type, crit_temp, emerg_temp);
173                 return 0;
174         }
175
176         /* According to the system thermal requirements, the thermal zones are
177          * defined with three trip points. The critical and emergency
178          * temperature thresholds, provided by QSFP module are set as "active"
179          * and "hot" trip points, "normal" trip point is derived from "active"
180          * by subtracting double hysteresis value.
181          */
182         if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
183                 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
184                                         MLXSW_THERMAL_MODULE_TEMP_SHIFT;
185         else
186                 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
187         tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
188         tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
189
190         return 0;
191 }
192
193 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
194                               struct thermal_cooling_device *cdev)
195 {
196         struct mlxsw_thermal *thermal = tzdev->devdata;
197         struct device *dev = thermal->bus_info->dev;
198         int i, err;
199
200         /* If the cooling device is one of ours bind it */
201         if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
202                 return 0;
203
204         for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
205                 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
206
207                 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
208                                                        trip->max_state,
209                                                        trip->min_state,
210                                                        THERMAL_WEIGHT_DEFAULT);
211                 if (err < 0) {
212                         dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
213                         return err;
214                 }
215         }
216         return 0;
217 }
218
219 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
220                                 struct thermal_cooling_device *cdev)
221 {
222         struct mlxsw_thermal *thermal = tzdev->devdata;
223         struct device *dev = thermal->bus_info->dev;
224         int i;
225         int err;
226
227         /* If the cooling device is our one unbind it */
228         if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
229                 return 0;
230
231         for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
232                 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
233                 if (err < 0) {
234                         dev_err(dev, "Failed to unbind cooling device\n");
235                         return err;
236                 }
237         }
238         return 0;
239 }
240
241 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
242                                   int *p_temp)
243 {
244         struct mlxsw_thermal *thermal = tzdev->devdata;
245         struct device *dev = thermal->bus_info->dev;
246         char mtmp_pl[MLXSW_REG_MTMP_LEN];
247         int temp;
248         int err;
249
250         mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
251
252         err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
253         if (err) {
254                 dev_err(dev, "Failed to query temp sensor\n");
255                 return err;
256         }
257         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
258
259         *p_temp = temp;
260         return 0;
261 }
262
263 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
264                                        int trip,
265                                        enum thermal_trip_type *p_type)
266 {
267         struct mlxsw_thermal *thermal = tzdev->devdata;
268
269         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
270                 return -EINVAL;
271
272         *p_type = thermal->trips[trip].type;
273         return 0;
274 }
275
276 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
277                                        int trip, int *p_temp)
278 {
279         struct mlxsw_thermal *thermal = tzdev->devdata;
280
281         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
282                 return -EINVAL;
283
284         *p_temp = thermal->trips[trip].temp;
285         return 0;
286 }
287
288 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
289                                        int trip, int temp)
290 {
291         struct mlxsw_thermal *thermal = tzdev->devdata;
292
293         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
294                 return -EINVAL;
295
296         thermal->trips[trip].temp = temp;
297         return 0;
298 }
299
300 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
301                                        int trip, int *p_hyst)
302 {
303         struct mlxsw_thermal *thermal = tzdev->devdata;
304
305         *p_hyst = thermal->trips[trip].hyst;
306         return 0;
307 }
308
309 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
310                                        int trip, int hyst)
311 {
312         struct mlxsw_thermal *thermal = tzdev->devdata;
313
314         thermal->trips[trip].hyst = hyst;
315         return 0;
316 }
317
318 static struct thermal_zone_params mlxsw_thermal_params = {
319         .no_hwmon = true,
320 };
321
322 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
323         .bind = mlxsw_thermal_bind,
324         .unbind = mlxsw_thermal_unbind,
325         .get_temp = mlxsw_thermal_get_temp,
326         .get_trip_type  = mlxsw_thermal_get_trip_type,
327         .get_trip_temp  = mlxsw_thermal_get_trip_temp,
328         .set_trip_temp  = mlxsw_thermal_set_trip_temp,
329         .get_trip_hyst  = mlxsw_thermal_get_trip_hyst,
330         .set_trip_hyst  = mlxsw_thermal_set_trip_hyst,
331 };
332
333 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
334                                      struct thermal_cooling_device *cdev)
335 {
336         struct mlxsw_thermal_module *tz = tzdev->devdata;
337         struct mlxsw_thermal *thermal = tz->parent;
338         int i, j, err;
339
340         /* If the cooling device is one of ours bind it */
341         if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
342                 return 0;
343
344         for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
345                 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
346
347                 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
348                                                        trip->max_state,
349                                                        trip->min_state,
350                                                        THERMAL_WEIGHT_DEFAULT);
351                 if (err < 0)
352                         goto err_thermal_zone_bind_cooling_device;
353         }
354         return 0;
355
356 err_thermal_zone_bind_cooling_device:
357         for (j = i - 1; j >= 0; j--)
358                 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
359         return err;
360 }
361
362 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
363                                        struct thermal_cooling_device *cdev)
364 {
365         struct mlxsw_thermal_module *tz = tzdev->devdata;
366         struct mlxsw_thermal *thermal = tz->parent;
367         int i;
368         int err;
369
370         /* If the cooling device is one of ours unbind it */
371         if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
372                 return 0;
373
374         for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
375                 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
376                 WARN_ON(err);
377         }
378         return err;
379 }
380
381 static void
382 mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
383                                              u8 slot_index, u16 sensor_index,
384                                              int *p_temp, int *p_crit_temp,
385                                              int *p_emerg_temp)
386 {
387         char mtmp_pl[MLXSW_REG_MTMP_LEN];
388         int err;
389
390         /* Read module temperature and thresholds. */
391         mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, sensor_index,
392                             false, false);
393         err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
394         if (err) {
395                 /* Set temperature and thresholds to zero to avoid passing
396                  * uninitialized data back to the caller.
397                  */
398                 *p_temp = 0;
399                 *p_crit_temp = 0;
400                 *p_emerg_temp = 0;
401
402                 return;
403         }
404         mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, p_crit_temp, p_emerg_temp,
405                               NULL);
406 }
407
408 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
409                                          int *p_temp)
410 {
411         struct mlxsw_thermal_module *tz = tzdev->devdata;
412         struct mlxsw_thermal *thermal = tz->parent;
413         int temp, crit_temp, emerg_temp;
414         struct device *dev;
415         u16 sensor_index;
416
417         dev = thermal->bus_info->dev;
418         sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
419
420         /* Read module temperature and thresholds. */
421         mlxsw_thermal_module_temp_and_thresholds_get(thermal->core,
422                                                      tz->slot_index,
423                                                      sensor_index, &temp,
424                                                      &crit_temp, &emerg_temp);
425         *p_temp = temp;
426
427         if (!temp)
428                 return 0;
429
430         /* Update trip points. */
431         mlxsw_thermal_module_trips_update(dev, thermal->core, tz,
432                                           crit_temp, emerg_temp);
433
434         return 0;
435 }
436
437 static int
438 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
439                                    enum thermal_trip_type *p_type)
440 {
441         struct mlxsw_thermal_module *tz = tzdev->devdata;
442
443         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
444                 return -EINVAL;
445
446         *p_type = tz->trips[trip].type;
447         return 0;
448 }
449
450 static int
451 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
452                                    int trip, int *p_temp)
453 {
454         struct mlxsw_thermal_module *tz = tzdev->devdata;
455
456         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
457                 return -EINVAL;
458
459         *p_temp = tz->trips[trip].temp;
460         return 0;
461 }
462
463 static int
464 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
465                                    int trip, int temp)
466 {
467         struct mlxsw_thermal_module *tz = tzdev->devdata;
468
469         if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
470                 return -EINVAL;
471
472         tz->trips[trip].temp = temp;
473         return 0;
474 }
475
476 static int
477 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
478                                    int *p_hyst)
479 {
480         struct mlxsw_thermal_module *tz = tzdev->devdata;
481
482         *p_hyst = tz->trips[trip].hyst;
483         return 0;
484 }
485
486 static int
487 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
488                                    int hyst)
489 {
490         struct mlxsw_thermal_module *tz = tzdev->devdata;
491
492         tz->trips[trip].hyst = hyst;
493         return 0;
494 }
495
496 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
497         .bind           = mlxsw_thermal_module_bind,
498         .unbind         = mlxsw_thermal_module_unbind,
499         .get_temp       = mlxsw_thermal_module_temp_get,
500         .get_trip_type  = mlxsw_thermal_module_trip_type_get,
501         .get_trip_temp  = mlxsw_thermal_module_trip_temp_get,
502         .set_trip_temp  = mlxsw_thermal_module_trip_temp_set,
503         .get_trip_hyst  = mlxsw_thermal_module_trip_hyst_get,
504         .set_trip_hyst  = mlxsw_thermal_module_trip_hyst_set,
505 };
506
507 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
508                                           int *p_temp)
509 {
510         struct mlxsw_thermal_module *tz = tzdev->devdata;
511         struct mlxsw_thermal *thermal = tz->parent;
512         char mtmp_pl[MLXSW_REG_MTMP_LEN];
513         u16 index;
514         int temp;
515         int err;
516
517         index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
518         mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
519
520         err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
521         if (err)
522                 return err;
523
524         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
525
526         *p_temp = temp;
527         return 0;
528 }
529
530 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
531         .bind           = mlxsw_thermal_module_bind,
532         .unbind         = mlxsw_thermal_module_unbind,
533         .get_temp       = mlxsw_thermal_gearbox_temp_get,
534         .get_trip_type  = mlxsw_thermal_module_trip_type_get,
535         .get_trip_temp  = mlxsw_thermal_module_trip_temp_get,
536         .set_trip_temp  = mlxsw_thermal_module_trip_temp_set,
537         .get_trip_hyst  = mlxsw_thermal_module_trip_hyst_get,
538         .set_trip_hyst  = mlxsw_thermal_module_trip_hyst_set,
539 };
540
541 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
542                                        unsigned long *p_state)
543 {
544         *p_state = MLXSW_THERMAL_MAX_STATE;
545         return 0;
546 }
547
548 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
549                                        unsigned long *p_state)
550
551 {
552         struct mlxsw_thermal *thermal = cdev->devdata;
553         struct device *dev = thermal->bus_info->dev;
554         char mfsc_pl[MLXSW_REG_MFSC_LEN];
555         int err, idx;
556         u8 duty;
557
558         idx = mlxsw_get_cooling_device_idx(thermal, cdev);
559         if (idx < 0)
560                 return idx;
561
562         mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
563         err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
564         if (err) {
565                 dev_err(dev, "Failed to query PWM duty\n");
566                 return err;
567         }
568
569         duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
570         *p_state = mlxsw_duty_to_state(duty);
571         return 0;
572 }
573
574 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
575                                        unsigned long state)
576
577 {
578         struct mlxsw_thermal *thermal = cdev->devdata;
579         struct device *dev = thermal->bus_info->dev;
580         char mfsc_pl[MLXSW_REG_MFSC_LEN];
581         int idx;
582         int err;
583
584         if (state > MLXSW_THERMAL_MAX_STATE)
585                 return -EINVAL;
586
587         idx = mlxsw_get_cooling_device_idx(thermal, cdev);
588         if (idx < 0)
589                 return idx;
590
591         /* Normalize the state to the valid speed range. */
592         state = thermal->cooling_levels[state];
593         mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
594         err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
595         if (err) {
596                 dev_err(dev, "Failed to write PWM duty\n");
597                 return err;
598         }
599         return 0;
600 }
601
602 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
603         .get_max_state  = mlxsw_thermal_get_max_state,
604         .get_cur_state  = mlxsw_thermal_get_cur_state,
605         .set_cur_state  = mlxsw_thermal_set_cur_state,
606 };
607
608 static int
609 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
610 {
611         char tz_name[THERMAL_NAME_LENGTH];
612         int err;
613
614         if (module_tz->slot_index)
615                 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
616                          module_tz->slot_index, module_tz->module + 1);
617         else
618                 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
619                          module_tz->module + 1);
620         module_tz->tzdev = thermal_zone_device_register(tz_name,
621                                                         MLXSW_THERMAL_NUM_TRIPS,
622                                                         MLXSW_THERMAL_TRIP_MASK,
623                                                         module_tz,
624                                                         &mlxsw_thermal_module_ops,
625                                                         &mlxsw_thermal_params,
626                                                         0,
627                                                         module_tz->parent->polling_delay);
628         if (IS_ERR(module_tz->tzdev)) {
629                 err = PTR_ERR(module_tz->tzdev);
630                 return err;
631         }
632
633         err = thermal_zone_device_enable(module_tz->tzdev);
634         if (err)
635                 thermal_zone_device_unregister(module_tz->tzdev);
636
637         return err;
638 }
639
640 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
641 {
642         thermal_zone_device_unregister(tzdev);
643 }
644
645 static int
646 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
647                           struct mlxsw_thermal *thermal,
648                           struct mlxsw_thermal_area *area, u8 module)
649 {
650         struct mlxsw_thermal_module *module_tz;
651         int dummy_temp, crit_temp, emerg_temp;
652         u16 sensor_index;
653
654         sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module;
655         module_tz = &area->tz_module_arr[module];
656         /* Skip if parent is already set (case of port split). */
657         if (module_tz->parent)
658                 return 0;
659         module_tz->module = module;
660         module_tz->slot_index = area->slot_index;
661         module_tz->parent = thermal;
662         memcpy(module_tz->trips, default_thermal_trips,
663                sizeof(thermal->trips));
664         /* Initialize all trip point. */
665         mlxsw_thermal_module_trips_reset(module_tz);
666         /* Read module temperature and thresholds. */
667         mlxsw_thermal_module_temp_and_thresholds_get(core, area->slot_index,
668                                                      sensor_index, &dummy_temp,
669                                                      &crit_temp, &emerg_temp);
670         /* Update trip point according to the module data. */
671         return mlxsw_thermal_module_trips_update(dev, core, module_tz,
672                                                  crit_temp, emerg_temp);
673 }
674
675 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
676 {
677         if (module_tz && module_tz->tzdev) {
678                 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
679                 module_tz->tzdev = NULL;
680                 module_tz->parent = NULL;
681         }
682 }
683
684 static int
685 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
686                            struct mlxsw_thermal *thermal,
687                            struct mlxsw_thermal_area *area)
688 {
689         struct mlxsw_thermal_module *module_tz;
690         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
691         int i, err;
692
693         mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
694         err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
695         if (err)
696                 return err;
697
698         mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
699                                &area->tz_module_num, NULL);
700
701         /* For modular system module counter could be zero. */
702         if (!area->tz_module_num)
703                 return 0;
704
705         area->tz_module_arr = kcalloc(area->tz_module_num,
706                                       sizeof(*area->tz_module_arr),
707                                       GFP_KERNEL);
708         if (!area->tz_module_arr)
709                 return -ENOMEM;
710
711         for (i = 0; i < area->tz_module_num; i++) {
712                 err = mlxsw_thermal_module_init(dev, core, thermal, area, i);
713                 if (err)
714                         goto err_thermal_module_init;
715         }
716
717         for (i = 0; i < area->tz_module_num; i++) {
718                 module_tz = &area->tz_module_arr[i];
719                 if (!module_tz->parent)
720                         continue;
721                 err = mlxsw_thermal_module_tz_init(module_tz);
722                 if (err)
723                         goto err_thermal_module_tz_init;
724         }
725
726         return 0;
727
728 err_thermal_module_tz_init:
729 err_thermal_module_init:
730         for (i = area->tz_module_num - 1; i >= 0; i--)
731                 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
732         kfree(area->tz_module_arr);
733         return err;
734 }
735
736 static void
737 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
738                            struct mlxsw_thermal_area *area)
739 {
740         int i;
741
742         for (i = area->tz_module_num - 1; i >= 0; i--)
743                 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
744         kfree(area->tz_module_arr);
745 }
746
747 static int
748 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
749 {
750         char tz_name[THERMAL_NAME_LENGTH];
751         int ret;
752
753         if (gearbox_tz->slot_index)
754                 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
755                          gearbox_tz->slot_index, gearbox_tz->module + 1);
756         else
757                 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
758                          gearbox_tz->module + 1);
759         gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
760                                                 MLXSW_THERMAL_NUM_TRIPS,
761                                                 MLXSW_THERMAL_TRIP_MASK,
762                                                 gearbox_tz,
763                                                 &mlxsw_thermal_gearbox_ops,
764                                                 &mlxsw_thermal_params, 0,
765                                                 gearbox_tz->parent->polling_delay);
766         if (IS_ERR(gearbox_tz->tzdev))
767                 return PTR_ERR(gearbox_tz->tzdev);
768
769         ret = thermal_zone_device_enable(gearbox_tz->tzdev);
770         if (ret)
771                 thermal_zone_device_unregister(gearbox_tz->tzdev);
772
773         return ret;
774 }
775
776 static void
777 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
778 {
779         thermal_zone_device_unregister(gearbox_tz->tzdev);
780 }
781
782 static int
783 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
784                              struct mlxsw_thermal *thermal,
785                              struct mlxsw_thermal_area *area)
786 {
787         enum mlxsw_reg_mgpir_device_type device_type;
788         struct mlxsw_thermal_module *gearbox_tz;
789         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
790         u8 gbox_num;
791         int i;
792         int err;
793
794         mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
795         err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
796         if (err)
797                 return err;
798
799         mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
800                                NULL, NULL);
801         if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
802             !gbox_num)
803                 return 0;
804
805         area->tz_gearbox_num = gbox_num;
806         area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
807                                        sizeof(*area->tz_gearbox_arr),
808                                        GFP_KERNEL);
809         if (!area->tz_gearbox_arr)
810                 return -ENOMEM;
811
812         for (i = 0; i < area->tz_gearbox_num; i++) {
813                 gearbox_tz = &area->tz_gearbox_arr[i];
814                 memcpy(gearbox_tz->trips, default_thermal_trips,
815                        sizeof(thermal->trips));
816                 gearbox_tz->module = i;
817                 gearbox_tz->parent = thermal;
818                 gearbox_tz->slot_index = area->slot_index;
819                 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
820                 if (err)
821                         goto err_thermal_gearbox_tz_init;
822         }
823
824         return 0;
825
826 err_thermal_gearbox_tz_init:
827         for (i--; i >= 0; i--)
828                 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
829         kfree(area->tz_gearbox_arr);
830         return err;
831 }
832
833 static void
834 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
835                              struct mlxsw_thermal_area *area)
836 {
837         int i;
838
839         for (i = area->tz_gearbox_num - 1; i >= 0; i--)
840                 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
841         kfree(area->tz_gearbox_arr);
842 }
843
844 static void
845 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
846                          void *priv)
847 {
848         struct mlxsw_thermal *thermal = priv;
849         struct mlxsw_thermal_area *linecard;
850         int err;
851
852         linecard = &thermal->line_cards[slot_index];
853
854         if (linecard->active)
855                 return;
856
857         linecard->slot_index = slot_index;
858         err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
859                                          thermal, linecard);
860         if (err) {
861                 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
862                         slot_index);
863                 return;
864         }
865
866         err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
867                                            thermal->core, thermal, linecard);
868         if (err) {
869                 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
870                         slot_index);
871                 goto err_thermal_linecard_gearboxes_init;
872         }
873
874         linecard->active = true;
875
876         return;
877
878 err_thermal_linecard_gearboxes_init:
879         mlxsw_thermal_modules_fini(thermal, linecard);
880 }
881
882 static void
883 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
884                            void *priv)
885 {
886         struct mlxsw_thermal *thermal = priv;
887         struct mlxsw_thermal_area *linecard;
888
889         linecard = &thermal->line_cards[slot_index];
890         if (!linecard->active)
891                 return;
892         linecard->active = false;
893         mlxsw_thermal_gearboxes_fini(thermal, linecard);
894         mlxsw_thermal_modules_fini(thermal, linecard);
895 }
896
897 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
898         .got_active = mlxsw_thermal_got_active,
899         .got_inactive = mlxsw_thermal_got_inactive,
900 };
901
902 int mlxsw_thermal_init(struct mlxsw_core *core,
903                        const struct mlxsw_bus_info *bus_info,
904                        struct mlxsw_thermal **p_thermal)
905 {
906         char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
907         enum mlxsw_reg_mfcr_pwm_frequency freq;
908         struct device *dev = bus_info->dev;
909         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
910         struct mlxsw_thermal *thermal;
911         u8 pwm_active, num_of_slots;
912         u16 tacho_active;
913         int err, i;
914
915         mlxsw_reg_mgpir_pack(mgpir_pl, 0);
916         err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
917         if (err)
918                 return err;
919
920         mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
921                                &num_of_slots);
922
923         thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
924                           GFP_KERNEL);
925         if (!thermal)
926                 return -ENOMEM;
927
928         thermal->core = core;
929         thermal->bus_info = bus_info;
930         memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
931         thermal->line_cards[0].slot_index = 0;
932
933         err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
934         if (err) {
935                 dev_err(dev, "Failed to probe PWMs\n");
936                 goto err_reg_query;
937         }
938         mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
939
940         for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
941                 if (tacho_active & BIT(i)) {
942                         char mfsl_pl[MLXSW_REG_MFSL_LEN];
943
944                         mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
945
946                         /* We need to query the register to preserve maximum */
947                         err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
948                                               mfsl_pl);
949                         if (err)
950                                 goto err_reg_query;
951
952                         /* set the minimal RPMs to 0 */
953                         mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
954                         err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
955                                               mfsl_pl);
956                         if (err)
957                                 goto err_reg_write;
958                 }
959         }
960         for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
961                 if (pwm_active & BIT(i)) {
962                         struct thermal_cooling_device *cdev;
963
964                         cdev = thermal_cooling_device_register("mlxsw_fan",
965                                                                thermal,
966                                                                &mlxsw_cooling_ops);
967                         if (IS_ERR(cdev)) {
968                                 err = PTR_ERR(cdev);
969                                 dev_err(dev, "Failed to register cooling device\n");
970                                 goto err_thermal_cooling_device_register;
971                         }
972                         thermal->cdevs[i] = cdev;
973                 }
974         }
975
976         /* Initialize cooling levels per PWM state. */
977         for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
978                 thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
979
980         thermal->polling_delay = bus_info->low_frequency ?
981                                  MLXSW_THERMAL_SLOW_POLL_INT :
982                                  MLXSW_THERMAL_POLL_INT;
983
984         thermal->tzdev = thermal_zone_device_register("mlxsw",
985                                                       MLXSW_THERMAL_NUM_TRIPS,
986                                                       MLXSW_THERMAL_TRIP_MASK,
987                                                       thermal,
988                                                       &mlxsw_thermal_ops,
989                                                       &mlxsw_thermal_params, 0,
990                                                       thermal->polling_delay);
991         if (IS_ERR(thermal->tzdev)) {
992                 err = PTR_ERR(thermal->tzdev);
993                 dev_err(dev, "Failed to register thermal zone\n");
994                 goto err_thermal_zone_device_register;
995         }
996
997         err = mlxsw_thermal_modules_init(dev, core, thermal,
998                                          &thermal->line_cards[0]);
999         if (err)
1000                 goto err_thermal_modules_init;
1001
1002         err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
1003                                            &thermal->line_cards[0]);
1004         if (err)
1005                 goto err_thermal_gearboxes_init;
1006
1007         err = mlxsw_linecards_event_ops_register(core,
1008                                                  &mlxsw_thermal_event_ops,
1009                                                  thermal);
1010         if (err)
1011                 goto err_linecards_event_ops_register;
1012
1013         err = thermal_zone_device_enable(thermal->tzdev);
1014         if (err)
1015                 goto err_thermal_zone_device_enable;
1016
1017         thermal->line_cards[0].active = true;
1018         *p_thermal = thermal;
1019         return 0;
1020
1021 err_thermal_zone_device_enable:
1022         mlxsw_linecards_event_ops_unregister(thermal->core,
1023                                              &mlxsw_thermal_event_ops,
1024                                              thermal);
1025 err_linecards_event_ops_register:
1026         mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1027 err_thermal_gearboxes_init:
1028         mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1029 err_thermal_modules_init:
1030         if (thermal->tzdev) {
1031                 thermal_zone_device_unregister(thermal->tzdev);
1032                 thermal->tzdev = NULL;
1033         }
1034 err_thermal_zone_device_register:
1035 err_thermal_cooling_device_register:
1036         for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1037                 if (thermal->cdevs[i])
1038                         thermal_cooling_device_unregister(thermal->cdevs[i]);
1039 err_reg_write:
1040 err_reg_query:
1041         kfree(thermal);
1042         return err;
1043 }
1044
1045 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1046 {
1047         int i;
1048
1049         thermal->line_cards[0].active = false;
1050         mlxsw_linecards_event_ops_unregister(thermal->core,
1051                                              &mlxsw_thermal_event_ops,
1052                                              thermal);
1053         mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1054         mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1055         if (thermal->tzdev) {
1056                 thermal_zone_device_unregister(thermal->tzdev);
1057                 thermal->tzdev = NULL;
1058         }
1059
1060         for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1061                 if (thermal->cdevs[i]) {
1062                         thermal_cooling_device_unregister(thermal->cdevs[i]);
1063                         thermal->cdevs[i] = NULL;
1064                 }
1065         }
1066
1067         kfree(thermal);
1068 }