xref: /openbmc/linux/drivers/hwmon/xgene-hwmon.c (revision 4f6cce39)
1 /*
2  * APM X-Gene SoC Hardware Monitoring Driver
3  *
4  * Copyright (c) 2016, Applied Micro Circuits Corporation
5  * Author: Loc Ho <lho@apm.com>
6  *         Hoan Tran <hotran@apm.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  *
21  * This driver provides the following features:
22  *  - Retrieve CPU total power (uW)
23  *  - Retrieve IO total power (uW)
24  *  - Retrieve SoC temperature (milli-degree C) and alarm
25  */
26 #include <linux/acpi.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/hwmon.h>
29 #include <linux/hwmon-sysfs.h>
30 #include <linux/io.h>
31 #include <linux/interrupt.h>
32 #include <linux/kfifo.h>
33 #include <linux/mailbox_controller.h>
34 #include <linux/mailbox_client.h>
35 #include <linux/module.h>
36 #include <linux/of.h>
37 #include <linux/platform_device.h>
38 
39 #include <acpi/pcc.h>
40 
41 /* SLIMpro message defines */
42 #define MSG_TYPE_DBG			0
43 #define MSG_TYPE_ERR			7
44 #define MSG_TYPE_PWRMGMT		9
45 
46 #define MSG_TYPE(v)			(((v) & 0xF0000000) >> 28)
47 #define MSG_TYPE_SET(v)			(((v) << 28) & 0xF0000000)
48 #define MSG_SUBTYPE(v)			(((v) & 0x0F000000) >> 24)
49 #define MSG_SUBTYPE_SET(v)		(((v) << 24) & 0x0F000000)
50 
51 #define DBG_SUBTYPE_SENSOR_READ		4
52 #define SENSOR_RD_MSG			0x04FFE902
53 #define SENSOR_RD_EN_ADDR(a)		((a) & 0x000FFFFF)
54 #define PMD_PWR_REG			0x20
55 #define PMD_PWR_MW_REG			0x26
56 #define SOC_PWR_REG			0x21
57 #define SOC_PWR_MW_REG			0x27
58 #define SOC_TEMP_REG			0x10
59 
60 #define TEMP_NEGATIVE_BIT		8
61 #define SENSOR_INVALID_DATA		BIT(15)
62 
63 #define PWRMGMT_SUBTYPE_TPC		1
64 #define TPC_ALARM			2
65 #define TPC_GET_ALARM			3
66 #define TPC_CMD(v)			(((v) & 0x00FF0000) >> 16)
67 #define TPC_CMD_SET(v)			(((v) << 16) & 0x00FF0000)
68 #define TPC_EN_MSG(hndl, cmd, type) \
69 	(MSG_TYPE_SET(MSG_TYPE_PWRMGMT) | \
70 	MSG_SUBTYPE_SET(hndl) | TPC_CMD_SET(cmd) | type)
71 
72 /* PCC defines */
73 #define PCC_SIGNATURE_MASK		0x50424300
74 #define PCCC_GENERATE_DB_INT		BIT(15)
75 #define PCCS_CMD_COMPLETE		BIT(0)
76 #define PCCS_SCI_DOORBEL		BIT(1)
77 #define PCCS_PLATFORM_NOTIFICATION	BIT(3)
78 /*
79  * Arbitrary retries in case the remote processor is slow to respond
80  * to PCC commands
81  */
82 #define PCC_NUM_RETRIES			500
83 
84 #define ASYNC_MSG_FIFO_SIZE		16
85 #define MBOX_OP_TIMEOUTMS		1000
86 
87 #define WATT_TO_mWATT(x)		((x) * 1000)
88 #define mWATT_TO_uWATT(x)		((x) * 1000)
89 #define CELSIUS_TO_mCELSIUS(x)		((x) * 1000)
90 
91 #define to_xgene_hwmon_dev(cl)		\
92 	container_of(cl, struct xgene_hwmon_dev, mbox_client)
93 
94 struct slimpro_resp_msg {
95 	u32 msg;
96 	u32 param1;
97 	u32 param2;
98 } __packed;
99 
100 struct xgene_hwmon_dev {
101 	struct device		*dev;
102 	struct mbox_chan	*mbox_chan;
103 	struct mbox_client	mbox_client;
104 	int			mbox_idx;
105 
106 	spinlock_t		kfifo_lock;
107 	struct mutex		rd_mutex;
108 	struct completion	rd_complete;
109 	int			resp_pending;
110 	struct slimpro_resp_msg sync_msg;
111 
112 	struct work_struct	workq;
113 	struct kfifo_rec_ptr_1	async_msg_fifo;
114 
115 	struct device		*hwmon_dev;
116 	bool			temp_critical_alarm;
117 
118 	phys_addr_t		comm_base_addr;
119 	void			*pcc_comm_addr;
120 	u64			usecs_lat;
121 };
122 
123 /*
124  * This function tests and clears a bitmask then returns its old value
125  */
126 static u16 xgene_word_tst_and_clr(u16 *addr, u16 mask)
127 {
128 	u16 ret, val;
129 
130 	val = le16_to_cpu(READ_ONCE(*addr));
131 	ret = val & mask;
132 	val &= ~mask;
133 	WRITE_ONCE(*addr, cpu_to_le16(val));
134 
135 	return ret;
136 }
137 
138 static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
139 {
140 	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
141 	u32 *ptr = (void *)(generic_comm_base + 1);
142 	int rc, i;
143 	u16 val;
144 
145 	mutex_lock(&ctx->rd_mutex);
146 	init_completion(&ctx->rd_complete);
147 	ctx->resp_pending = true;
148 
149 	/* Write signature for subspace */
150 	WRITE_ONCE(generic_comm_base->signature,
151 		   cpu_to_le32(PCC_SIGNATURE_MASK | ctx->mbox_idx));
152 
153 	/* Write to the shared command region */
154 	WRITE_ONCE(generic_comm_base->command,
155 		   cpu_to_le16(MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT));
156 
157 	/* Flip CMD COMPLETE bit */
158 	val = le16_to_cpu(READ_ONCE(generic_comm_base->status));
159 	val &= ~PCCS_CMD_COMPLETE;
160 	WRITE_ONCE(generic_comm_base->status, cpu_to_le16(val));
161 
162 	/* Copy the message to the PCC comm space */
163 	for (i = 0; i < sizeof(struct slimpro_resp_msg) / 4; i++)
164 		WRITE_ONCE(ptr[i], cpu_to_le32(msg[i]));
165 
166 	/* Ring the doorbell */
167 	rc = mbox_send_message(ctx->mbox_chan, msg);
168 	if (rc < 0) {
169 		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
170 		goto err;
171 	}
172 	if (!wait_for_completion_timeout(&ctx->rd_complete,
173 					 usecs_to_jiffies(ctx->usecs_lat))) {
174 		dev_err(ctx->dev, "Mailbox operation timed out\n");
175 		rc = -ETIMEDOUT;
176 		goto err;
177 	}
178 
179 	/* Check for error message */
180 	if (MSG_TYPE(ctx->sync_msg.msg) == MSG_TYPE_ERR) {
181 		rc = -EINVAL;
182 		goto err;
183 	}
184 
185 	msg[0] = ctx->sync_msg.msg;
186 	msg[1] = ctx->sync_msg.param1;
187 	msg[2] = ctx->sync_msg.param2;
188 
189 err:
190 	mbox_chan_txdone(ctx->mbox_chan, 0);
191 	ctx->resp_pending = false;
192 	mutex_unlock(&ctx->rd_mutex);
193 	return rc;
194 }
195 
196 static int xgene_hwmon_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
197 {
198 	int rc;
199 
200 	mutex_lock(&ctx->rd_mutex);
201 	init_completion(&ctx->rd_complete);
202 	ctx->resp_pending = true;
203 
204 	rc = mbox_send_message(ctx->mbox_chan, msg);
205 	if (rc < 0) {
206 		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
207 		goto err;
208 	}
209 
210 	if (!wait_for_completion_timeout(&ctx->rd_complete,
211 					 msecs_to_jiffies(MBOX_OP_TIMEOUTMS))) {
212 		dev_err(ctx->dev, "Mailbox operation timed out\n");
213 		rc = -ETIMEDOUT;
214 		goto err;
215 	}
216 
217 	/* Check for error message */
218 	if (MSG_TYPE(ctx->sync_msg.msg) == MSG_TYPE_ERR) {
219 		rc = -EINVAL;
220 		goto err;
221 	}
222 
223 	msg[0] = ctx->sync_msg.msg;
224 	msg[1] = ctx->sync_msg.param1;
225 	msg[2] = ctx->sync_msg.param2;
226 
227 err:
228 	ctx->resp_pending = false;
229 	mutex_unlock(&ctx->rd_mutex);
230 	return rc;
231 }
232 
233 static int xgene_hwmon_reg_map_rd(struct xgene_hwmon_dev *ctx, u32 addr,
234 				  u32 *data)
235 {
236 	u32 msg[3];
237 	int rc;
238 
239 	msg[0] = SENSOR_RD_MSG;
240 	msg[1] = SENSOR_RD_EN_ADDR(addr);
241 	msg[2] = 0;
242 
243 	if (acpi_disabled)
244 		rc = xgene_hwmon_rd(ctx, msg);
245 	else
246 		rc = xgene_hwmon_pcc_rd(ctx, msg);
247 
248 	if (rc < 0)
249 		return rc;
250 
251 	/*
252 	 * Check if sensor data is valid.
253 	 */
254 	if (msg[1] & SENSOR_INVALID_DATA)
255 		return -ENODATA;
256 
257 	*data = msg[1];
258 
259 	return rc;
260 }
261 
262 static int xgene_hwmon_get_notification_msg(struct xgene_hwmon_dev *ctx,
263 					    u32 *amsg)
264 {
265 	u32 msg[3];
266 	int rc;
267 
268 	msg[0] = TPC_EN_MSG(PWRMGMT_SUBTYPE_TPC, TPC_GET_ALARM, 0);
269 	msg[1] = 0;
270 	msg[2] = 0;
271 
272 	rc = xgene_hwmon_pcc_rd(ctx, msg);
273 	if (rc < 0)
274 		return rc;
275 
276 	amsg[0] = msg[0];
277 	amsg[1] = msg[1];
278 	amsg[2] = msg[2];
279 
280 	return rc;
281 }
282 
283 static int xgene_hwmon_get_cpu_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
284 {
285 	u32 watt, mwatt;
286 	int rc;
287 
288 	rc = xgene_hwmon_reg_map_rd(ctx, PMD_PWR_REG, &watt);
289 	if (rc < 0)
290 		return rc;
291 
292 	rc = xgene_hwmon_reg_map_rd(ctx, PMD_PWR_MW_REG, &mwatt);
293 	if (rc < 0)
294 		return rc;
295 
296 	*val = WATT_TO_mWATT(watt) + mwatt;
297 	return 0;
298 }
299 
300 static int xgene_hwmon_get_io_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
301 {
302 	u32 watt, mwatt;
303 	int rc;
304 
305 	rc = xgene_hwmon_reg_map_rd(ctx, SOC_PWR_REG, &watt);
306 	if (rc < 0)
307 		return rc;
308 
309 	rc = xgene_hwmon_reg_map_rd(ctx, SOC_PWR_MW_REG, &mwatt);
310 	if (rc < 0)
311 		return rc;
312 
313 	*val = WATT_TO_mWATT(watt) + mwatt;
314 	return 0;
315 }
316 
317 static int xgene_hwmon_get_temp(struct xgene_hwmon_dev *ctx, u32 *val)
318 {
319 	return xgene_hwmon_reg_map_rd(ctx, SOC_TEMP_REG, val);
320 }
321 
322 /*
323  * Sensor temperature/power functions
324  */
325 static ssize_t temp1_input_show(struct device *dev,
326 				struct device_attribute *attr,
327 				char *buf)
328 {
329 	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
330 	int rc, temp;
331 	u32 val;
332 
333 	rc = xgene_hwmon_get_temp(ctx, &val);
334 	if (rc < 0)
335 		return rc;
336 
337 	temp = sign_extend32(val, TEMP_NEGATIVE_BIT);
338 
339 	return snprintf(buf, PAGE_SIZE, "%d\n", CELSIUS_TO_mCELSIUS(temp));
340 }
341 
342 static ssize_t temp1_label_show(struct device *dev,
343 				struct device_attribute *attr,
344 				char *buf)
345 {
346 	return snprintf(buf, PAGE_SIZE, "SoC Temperature\n");
347 }
348 
349 static ssize_t temp1_critical_alarm_show(struct device *dev,
350 					 struct device_attribute *devattr,
351 					 char *buf)
352 {
353 	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
354 
355 	return snprintf(buf, PAGE_SIZE, "%d\n", ctx->temp_critical_alarm);
356 }
357 
358 static ssize_t power1_label_show(struct device *dev,
359 				 struct device_attribute *attr,
360 				 char *buf)
361 {
362 	return snprintf(buf, PAGE_SIZE, "CPU power\n");
363 }
364 
365 static ssize_t power2_label_show(struct device *dev,
366 				 struct device_attribute *attr,
367 				 char *buf)
368 {
369 	return snprintf(buf, PAGE_SIZE, "IO power\n");
370 }
371 
372 static ssize_t power1_input_show(struct device *dev,
373 				 struct device_attribute *attr,
374 				 char *buf)
375 {
376 	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
377 	u32 val;
378 	int rc;
379 
380 	rc = xgene_hwmon_get_cpu_pwr(ctx, &val);
381 	if (rc < 0)
382 		return rc;
383 
384 	return snprintf(buf, PAGE_SIZE, "%u\n", mWATT_TO_uWATT(val));
385 }
386 
387 static ssize_t power2_input_show(struct device *dev,
388 				 struct device_attribute *attr,
389 				 char *buf)
390 {
391 	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
392 	u32 val;
393 	int rc;
394 
395 	rc = xgene_hwmon_get_io_pwr(ctx, &val);
396 	if (rc < 0)
397 		return rc;
398 
399 	return snprintf(buf, PAGE_SIZE, "%u\n", mWATT_TO_uWATT(val));
400 }
401 
402 static DEVICE_ATTR_RO(temp1_label);
403 static DEVICE_ATTR_RO(temp1_input);
404 static DEVICE_ATTR_RO(temp1_critical_alarm);
405 static DEVICE_ATTR_RO(power1_label);
406 static DEVICE_ATTR_RO(power1_input);
407 static DEVICE_ATTR_RO(power2_label);
408 static DEVICE_ATTR_RO(power2_input);
409 
410 static struct attribute *xgene_hwmon_attrs[] = {
411 	&dev_attr_temp1_label.attr,
412 	&dev_attr_temp1_input.attr,
413 	&dev_attr_temp1_critical_alarm.attr,
414 	&dev_attr_power1_label.attr,
415 	&dev_attr_power1_input.attr,
416 	&dev_attr_power2_label.attr,
417 	&dev_attr_power2_input.attr,
418 	NULL,
419 };
420 
421 ATTRIBUTE_GROUPS(xgene_hwmon);
422 
423 static int xgene_hwmon_tpc_alarm(struct xgene_hwmon_dev *ctx,
424 				 struct slimpro_resp_msg *amsg)
425 {
426 	ctx->temp_critical_alarm = !!amsg->param2;
427 	sysfs_notify(&ctx->dev->kobj, NULL, "temp1_critical_alarm");
428 
429 	return 0;
430 }
431 
432 static void xgene_hwmon_process_pwrmsg(struct xgene_hwmon_dev *ctx,
433 				       struct slimpro_resp_msg *amsg)
434 {
435 	if ((MSG_SUBTYPE(amsg->msg) == PWRMGMT_SUBTYPE_TPC) &&
436 	    (TPC_CMD(amsg->msg) == TPC_ALARM))
437 		xgene_hwmon_tpc_alarm(ctx, amsg);
438 }
439 
440 /*
441  * This function is called to process async work queue
442  */
443 static void xgene_hwmon_evt_work(struct work_struct *work)
444 {
445 	struct slimpro_resp_msg amsg;
446 	struct xgene_hwmon_dev *ctx;
447 	int ret;
448 
449 	ctx = container_of(work, struct xgene_hwmon_dev, workq);
450 	while (kfifo_out_spinlocked(&ctx->async_msg_fifo, &amsg,
451 				    sizeof(struct slimpro_resp_msg),
452 				    &ctx->kfifo_lock)) {
453 		/*
454 		 * If PCC, send a consumer command to Platform to get info
455 		 * If Slimpro Mailbox, get message from specific FIFO
456 		 */
457 		if (!acpi_disabled) {
458 			ret = xgene_hwmon_get_notification_msg(ctx,
459 							       (u32 *)&amsg);
460 			if (ret < 0)
461 				continue;
462 		}
463 
464 		if (MSG_TYPE(amsg.msg) == MSG_TYPE_PWRMGMT)
465 			xgene_hwmon_process_pwrmsg(ctx, &amsg);
466 	}
467 }
468 
469 static int xgene_hwmon_rx_ready(struct xgene_hwmon_dev *ctx, void *msg)
470 {
471 	if (IS_ERR_OR_NULL(ctx->hwmon_dev) && !ctx->resp_pending) {
472 		/* Enqueue to the FIFO */
473 		kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
474 				    sizeof(struct slimpro_resp_msg),
475 				    &ctx->kfifo_lock);
476 		return -ENODEV;
477 	}
478 
479 	return 0;
480 }
481 
482 /*
483  * This function is called when the SLIMpro Mailbox received a message
484  */
485 static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
486 {
487 	struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
488 
489 	/*
490 	 * While the driver registers with the mailbox framework, an interrupt
491 	 * can be pending before the probe function completes its
492 	 * initialization. If such condition occurs, just queue up the message
493 	 * as the driver is not ready for servicing the callback.
494 	 */
495 	if (xgene_hwmon_rx_ready(ctx, msg) < 0)
496 		return;
497 
498 	/*
499 	 * Response message format:
500 	 * msg[0] is the return code of the operation
501 	 * msg[1] is the first parameter word
502 	 * msg[2] is the second parameter word
503 	 *
504 	 * As message only supports dword size, just assign it.
505 	 */
506 
507 	/* Check for sync query */
508 	if (ctx->resp_pending &&
509 	    ((MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_ERR) ||
510 	     (MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_DBG &&
511 	      MSG_SUBTYPE(((u32 *)msg)[0]) == DBG_SUBTYPE_SENSOR_READ) ||
512 	     (MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_PWRMGMT &&
513 	      MSG_SUBTYPE(((u32 *)msg)[0]) == PWRMGMT_SUBTYPE_TPC &&
514 	      TPC_CMD(((u32 *)msg)[0]) == TPC_ALARM))) {
515 		ctx->sync_msg.msg = ((u32 *)msg)[0];
516 		ctx->sync_msg.param1 = ((u32 *)msg)[1];
517 		ctx->sync_msg.param2 = ((u32 *)msg)[2];
518 
519 		/* Operation waiting for response */
520 		complete(&ctx->rd_complete);
521 
522 		return;
523 	}
524 
525 	/* Enqueue to the FIFO */
526 	kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
527 			    sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock);
528 	/* Schedule the bottom handler */
529 	schedule_work(&ctx->workq);
530 }
531 
532 /*
533  * This function is called when the PCC Mailbox received a message
534  */
535 static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg)
536 {
537 	struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
538 	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
539 	struct slimpro_resp_msg amsg;
540 
541 	/*
542 	 * While the driver registers with the mailbox framework, an interrupt
543 	 * can be pending before the probe function completes its
544 	 * initialization. If such condition occurs, just queue up the message
545 	 * as the driver is not ready for servicing the callback.
546 	 */
547 	if (xgene_hwmon_rx_ready(ctx, &amsg) < 0)
548 		return;
549 
550 	msg = generic_comm_base + 1;
551 	/* Check if platform sends interrupt */
552 	if (!xgene_word_tst_and_clr(&generic_comm_base->status,
553 				    PCCS_SCI_DOORBEL))
554 		return;
555 
556 	/*
557 	 * Response message format:
558 	 * msg[0] is the return code of the operation
559 	 * msg[1] is the first parameter word
560 	 * msg[2] is the second parameter word
561 	 *
562 	 * As message only supports dword size, just assign it.
563 	 */
564 
565 	/* Check for sync query */
566 	if (ctx->resp_pending &&
567 	    ((MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_ERR) ||
568 	     (MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_DBG &&
569 	      MSG_SUBTYPE(((u32 *)msg)[0]) == DBG_SUBTYPE_SENSOR_READ) ||
570 	     (MSG_TYPE(((u32 *)msg)[0]) == MSG_TYPE_PWRMGMT &&
571 	      MSG_SUBTYPE(((u32 *)msg)[0]) == PWRMGMT_SUBTYPE_TPC &&
572 	      TPC_CMD(((u32 *)msg)[0]) == TPC_ALARM))) {
573 		/* Check if platform completes command */
574 		if (xgene_word_tst_and_clr(&generic_comm_base->status,
575 					   PCCS_CMD_COMPLETE)) {
576 			ctx->sync_msg.msg = ((u32 *)msg)[0];
577 			ctx->sync_msg.param1 = ((u32 *)msg)[1];
578 			ctx->sync_msg.param2 = ((u32 *)msg)[2];
579 
580 			/* Operation waiting for response */
581 			complete(&ctx->rd_complete);
582 
583 			return;
584 		}
585 	}
586 
587 	/*
588 	 * Platform notifies interrupt to OSPM.
589 	 * OPSM schedules a consumer command to get this information
590 	 * in a workqueue. Platform must wait until OSPM has issued
591 	 * a consumer command that serves this notification.
592 	 */
593 
594 	/* Enqueue to the FIFO */
595 	kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg,
596 			    sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock);
597 	/* Schedule the bottom handler */
598 	schedule_work(&ctx->workq);
599 }
600 
601 static void xgene_hwmon_tx_done(struct mbox_client *cl, void *msg, int ret)
602 {
603 	if (ret) {
604 		dev_dbg(cl->dev, "TX did not complete: CMD sent:%x, ret:%d\n",
605 			*(u16 *)msg, ret);
606 	} else {
607 		dev_dbg(cl->dev, "TX completed. CMD sent:%x, ret:%d\n",
608 			*(u16 *)msg, ret);
609 	}
610 }
611 
612 static int xgene_hwmon_probe(struct platform_device *pdev)
613 {
614 	struct xgene_hwmon_dev *ctx;
615 	struct mbox_client *cl;
616 	int rc;
617 
618 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
619 	if (!ctx)
620 		return -ENOMEM;
621 
622 	ctx->dev = &pdev->dev;
623 	platform_set_drvdata(pdev, ctx);
624 	cl = &ctx->mbox_client;
625 
626 	spin_lock_init(&ctx->kfifo_lock);
627 	mutex_init(&ctx->rd_mutex);
628 
629 	rc = kfifo_alloc(&ctx->async_msg_fifo,
630 			 sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
631 			 GFP_KERNEL);
632 	if (rc)
633 		goto out_mbox_free;
634 
635 	INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
636 
637 	/* Request mailbox channel */
638 	cl->dev = &pdev->dev;
639 	cl->tx_done = xgene_hwmon_tx_done;
640 	cl->tx_block = false;
641 	cl->tx_tout = MBOX_OP_TIMEOUTMS;
642 	cl->knows_txdone = false;
643 	if (acpi_disabled) {
644 		cl->rx_callback = xgene_hwmon_rx_cb;
645 		ctx->mbox_chan = mbox_request_channel(cl, 0);
646 		if (IS_ERR(ctx->mbox_chan)) {
647 			dev_err(&pdev->dev,
648 				"SLIMpro mailbox channel request failed\n");
649 			return -ENODEV;
650 		}
651 	} else {
652 		struct acpi_pcct_hw_reduced *cppc_ss;
653 
654 		if (device_property_read_u32(&pdev->dev, "pcc-channel",
655 					     &ctx->mbox_idx)) {
656 			dev_err(&pdev->dev, "no pcc-channel property\n");
657 			return -ENODEV;
658 		}
659 
660 		cl->rx_callback = xgene_hwmon_pcc_rx_cb;
661 		ctx->mbox_chan = pcc_mbox_request_channel(cl, ctx->mbox_idx);
662 		if (IS_ERR(ctx->mbox_chan)) {
663 			dev_err(&pdev->dev,
664 				"PPC channel request failed\n");
665 			return -ENODEV;
666 		}
667 
668 		/*
669 		 * The PCC mailbox controller driver should
670 		 * have parsed the PCCT (global table of all
671 		 * PCC channels) and stored pointers to the
672 		 * subspace communication region in con_priv.
673 		 */
674 		cppc_ss = ctx->mbox_chan->con_priv;
675 		if (!cppc_ss) {
676 			dev_err(&pdev->dev, "PPC subspace not found\n");
677 			rc = -ENODEV;
678 			goto out_mbox_free;
679 		}
680 
681 		if (!ctx->mbox_chan->mbox->txdone_irq) {
682 			dev_err(&pdev->dev, "PCC IRQ not supported\n");
683 			rc = -ENODEV;
684 			goto out_mbox_free;
685 		}
686 
687 		/*
688 		 * This is the shared communication region
689 		 * for the OS and Platform to communicate over.
690 		 */
691 		ctx->comm_base_addr = cppc_ss->base_address;
692 		if (ctx->comm_base_addr) {
693 			ctx->pcc_comm_addr = memremap(ctx->comm_base_addr,
694 							cppc_ss->length,
695 							MEMREMAP_WB);
696 		} else {
697 			dev_err(&pdev->dev, "Failed to get PCC comm region\n");
698 			rc = -ENODEV;
699 			goto out_mbox_free;
700 		}
701 
702 		if (!ctx->pcc_comm_addr) {
703 			dev_err(&pdev->dev,
704 				"Failed to ioremap PCC comm region\n");
705 			rc = -ENOMEM;
706 			goto out_mbox_free;
707 		}
708 
709 		/*
710 		 * cppc_ss->latency is just a Nominal value. In reality
711 		 * the remote processor could be much slower to reply.
712 		 * So add an arbitrary amount of wait on top of Nominal.
713 		 */
714 		ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
715 	}
716 
717 	ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
718 							   "apm_xgene",
719 							   ctx,
720 							   xgene_hwmon_groups);
721 	if (IS_ERR(ctx->hwmon_dev)) {
722 		dev_err(&pdev->dev, "Failed to register HW monitor device\n");
723 		rc = PTR_ERR(ctx->hwmon_dev);
724 		goto out;
725 	}
726 
727 	/*
728 	 * Schedule the bottom handler if there is a pending message.
729 	 */
730 	schedule_work(&ctx->workq);
731 
732 	dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
733 
734 	return 0;
735 
736 out:
737 	if (acpi_disabled)
738 		mbox_free_channel(ctx->mbox_chan);
739 	else
740 		pcc_mbox_free_channel(ctx->mbox_chan);
741 out_mbox_free:
742 	kfifo_free(&ctx->async_msg_fifo);
743 
744 	return rc;
745 }
746 
747 static int xgene_hwmon_remove(struct platform_device *pdev)
748 {
749 	struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
750 
751 	hwmon_device_unregister(ctx->hwmon_dev);
752 	kfifo_free(&ctx->async_msg_fifo);
753 	if (acpi_disabled)
754 		mbox_free_channel(ctx->mbox_chan);
755 	else
756 		pcc_mbox_free_channel(ctx->mbox_chan);
757 
758 	return 0;
759 }
760 
761 #ifdef CONFIG_ACPI
762 static const struct acpi_device_id xgene_hwmon_acpi_match[] = {
763 	{"APMC0D29", 0},
764 	{},
765 };
766 MODULE_DEVICE_TABLE(acpi, xgene_hwmon_acpi_match);
767 #endif
768 
769 static const struct of_device_id xgene_hwmon_of_match[] = {
770 	{.compatible = "apm,xgene-slimpro-hwmon"},
771 	{}
772 };
773 MODULE_DEVICE_TABLE(of, xgene_hwmon_of_match);
774 
775 static struct platform_driver xgene_hwmon_driver __refdata = {
776 	.probe = xgene_hwmon_probe,
777 	.remove = xgene_hwmon_remove,
778 	.driver = {
779 		.name = "xgene-slimpro-hwmon",
780 		.of_match_table = xgene_hwmon_of_match,
781 		.acpi_match_table = ACPI_PTR(xgene_hwmon_acpi_match),
782 	},
783 };
784 module_platform_driver(xgene_hwmon_driver);
785 
786 MODULE_DESCRIPTION("APM X-Gene SoC hardware monitor");
787 MODULE_LICENSE("GPL");
788