Lines Matching +full:p9 +full:- +full:occ +full:- +full:hwmon

1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/fsi-sbefifo.h>
16 #include <linux/fsi-occ.h>
42 struct occ { struct
58 #define to_occ(x) container_of((x), struct occ, mdev) argument
69 struct occ *occ; member
83 struct miscdevice *mdev = file->private_data; in occ_open()
84 struct occ *occ = to_occ(mdev); in occ_open() local
87 return -ENOMEM; in occ_open()
89 client->buffer = (u8 *)__get_free_page(GFP_KERNEL); in occ_open()
90 if (!client->buffer) { in occ_open()
92 return -ENOMEM; in occ_open()
95 client->occ = occ; in occ_open()
96 mutex_init(&client->lock); in occ_open()
97 file->private_data = client; in occ_open()
98 get_device(occ->dev); in occ_open()
100 /* We allocate a 1-page buffer, make sure it all fits */ in occ_open()
110 struct occ_client *client = file->private_data; in occ_read()
114 return -ENODEV; in occ_read()
117 return -EINVAL; in occ_read()
119 mutex_lock(&client->lock); in occ_read()
122 if (WARN_ON_ONCE(client->read_offset > client->data_size)) { in occ_read()
123 rc = -EIO; in occ_read()
128 rc = min(len, client->data_size - client->read_offset); in occ_read()
129 if (copy_to_user(buf, client->buffer + client->read_offset, rc)) in occ_read()
130 rc = -EFAULT; in occ_read()
132 client->read_offset += rc; in occ_read()
135 mutex_unlock(&client->lock); in occ_read()
143 struct occ_client *client = file->private_data; in occ_write()
149 return -ENODEV; in occ_write()
152 return -EINVAL; in occ_write()
154 mutex_lock(&client->lock); in occ_write()
157 cmd = client->buffer; in occ_write()
160 * Copy the user command (assume user data follows the occ command in occ_write()
163 * bytes 1-2: data length (msb first) in occ_write()
164 * bytes 3-n: data in occ_write()
167 rc = -EFAULT; in occ_write()
174 rc = -EINVAL; in occ_write()
180 rc = fsi_occ_submit(client->occ->dev, cmd, data_length + 6, cmd, in occ_write()
186 client->data_size = rlen; in occ_write()
187 client->read_offset = 0; in occ_write()
193 mutex_unlock(&client->lock); in occ_write()
200 struct occ_client *client = file->private_data; in occ_release()
202 put_device(client->occ->dev); in occ_release()
203 free_page((unsigned long)client->buffer); in occ_release()
217 static void occ_save_ffdc(struct occ *occ, __be32 *resp, size_t parsed_len, in occ_save_ffdc() argument
221 size_t dh = resp_len - parsed_len; in occ_save_ffdc()
222 size_t ffdc_len = (dh - 1) * 4; /* SBE words are four bytes */ in occ_save_ffdc()
225 if (ffdc_len > occ->client_buffer_size) in occ_save_ffdc()
226 ffdc_len = occ->client_buffer_size; in occ_save_ffdc()
228 memcpy(occ->client_buffer, ffdc, ffdc_len); in occ_save_ffdc()
229 occ->client_response_size = ffdc_len; in occ_save_ffdc()
233 static int occ_verify_checksum(struct occ *occ, struct occ_response *resp, in occ_verify_checksum() argument
237 u16 checksum_resp = get_unaligned_be16(&resp->data[data_length]); in occ_verify_checksum()
241 checksum = resp->seq_no; in occ_verify_checksum()
242 checksum += resp->cmd_type; in occ_verify_checksum()
243 checksum += resp->return_status; in occ_verify_checksum()
247 checksum += resp->data[i]; in occ_verify_checksum()
250 dev_err(occ->dev, "Bad checksum: %04x!=%04x\n", checksum, in occ_verify_checksum()
252 return -EBADE; in occ_verify_checksum()
258 static int occ_getsram(struct occ *occ, u32 offset, void *data, ssize_t len) in occ_getsram() argument
263 __be32 *resp = occ->buffer; in occ_getsram()
271 switch (occ->version) { in occ_getsram()
291 rc = sbefifo_submit(occ->sbefifo, cmd, cmd_len, resp, &resp_len); in occ_getsram()
295 rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_GET_OCC_SRAM, in occ_getsram()
298 dev_err(occ->dev, "SRAM read returned failure status: %08x\n", in occ_getsram()
300 occ_save_ffdc(occ, resp, parsed_len, resp_len); in occ_getsram()
301 return -ECOMM; in occ_getsram()
306 resp_data_len = be32_to_cpu(resp[parsed_len - 1]); in occ_getsram()
308 dev_err(occ->dev, "SRAM read expected %d bytes got %zd\n", in occ_getsram()
310 rc = -EBADMSG; in occ_getsram()
318 static int occ_putsram(struct occ *occ, const void *data, ssize_t len, in occ_putsram() argument
324 __be32 *buf = occ->buffer; in occ_putsram()
328 cmd_len = (occ->version == occ_p10) ? 6 : 5; in occ_putsram()
338 switch (occ->version) { in occ_putsram()
361 byte_buf[len - 2] = checksum >> 8; in occ_putsram()
362 byte_buf[len - 1] = checksum & 0xff; in occ_putsram()
364 rc = sbefifo_submit(occ->sbefifo, buf, cmd_len, buf, &resp_len); in occ_putsram()
368 rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_PUT_OCC_SRAM, in occ_putsram()
371 dev_err(occ->dev, "SRAM write returned failure status: %08x\n", in occ_putsram()
373 occ_save_ffdc(occ, buf, parsed_len, resp_len); in occ_putsram()
374 return -ECOMM; in occ_putsram()
380 dev_err(occ->dev, "SRAM write response length invalid: %zd\n", in occ_putsram()
382 rc = -EBADMSG; in occ_putsram()
386 dev_err(occ->dev, in occ_putsram()
389 rc = -EBADMSG; in occ_putsram()
396 static int occ_trigger_attn(struct occ *occ) in occ_trigger_attn() argument
398 __be32 *buf = occ->buffer; in occ_trigger_attn()
403 switch (occ->version) { in occ_trigger_attn()
419 buf[0] = cpu_to_be32(cmd_len); /* Chip-op length in words */ in occ_trigger_attn()
422 buf[5 + idx] = cpu_to_be32(0x20010000); /* Trigger OCC attention */ in occ_trigger_attn()
425 rc = sbefifo_submit(occ->sbefifo, buf, cmd_len, buf, &resp_len); in occ_trigger_attn()
429 rc = sbefifo_parse_status(occ->sbefifo, SBEFIFO_CMD_PUT_OCC_SRAM, in occ_trigger_attn()
432 dev_err(occ->dev, "SRAM attn returned failure status: %08x\n", in occ_trigger_attn()
434 occ_save_ffdc(occ, buf, parsed_len, resp_len); in occ_trigger_attn()
435 return -ECOMM; in occ_trigger_attn()
441 dev_err(occ->dev, "SRAM attn response length invalid: %zd\n", in occ_trigger_attn()
443 rc = -EBADMSG; in occ_trigger_attn()
447 dev_err(occ->dev, in occ_trigger_attn()
450 rc = -EBADMSG; in occ_trigger_attn()
460 return resp->return_status == OCC_RESP_CMD_IN_PRG || in fsi_occ_response_not_ready()
461 resp->return_status == OCC_RESP_CRIT_INIT || in fsi_occ_response_not_ready()
462 resp->seq_no != seq_no || resp->cmd_type != cmd_type; in fsi_occ_response_not_ready()
471 struct occ *occ = dev_get_drvdata(dev); in fsi_occ_submit() local
485 if (!occ) in fsi_occ_submit()
486 return -ENODEV; in fsi_occ_submit()
490 return -EINVAL; in fsi_occ_submit()
496 for (i = 1; i < req_len - 2; ++i) in fsi_occ_submit()
499 rc = mutex_lock_interruptible(&occ->occ_lock); in fsi_occ_submit()
503 occ->client_buffer = response; in fsi_occ_submit()
504 occ->client_buffer_size = user_resp_len; in fsi_occ_submit()
505 occ->client_response_size = 0; in fsi_occ_submit()
507 if (!occ->buffer) { in fsi_occ_submit()
508 rc = -ENOENT; in fsi_occ_submit()
515 * OCC response is uninitialized. Any sequence number the user is in fsi_occ_submit()
517 * interface to the OCC and therefore the only place we can guarantee in fsi_occ_submit()
520 seq_no = occ->sequence_number++; in fsi_occ_submit()
521 if (!occ->sequence_number) in fsi_occ_submit()
522 occ->sequence_number = 1; in fsi_occ_submit()
525 rc = occ_putsram(occ, request, req_len, seq_no, checksum); in fsi_occ_submit()
529 rc = occ_trigger_attn(occ); in fsi_occ_submit()
535 /* Read occ response header */ in fsi_occ_submit()
536 rc = occ_getsram(occ, 0, resp, 8); in fsi_occ_submit()
542 dev_err(occ->dev, in fsi_occ_submit()
544 resp->return_status, resp->seq_no, in fsi_occ_submit()
545 resp->cmd_type, seq_no, cmd_type); in fsi_occ_submit()
546 rc = -ETIMEDOUT; in fsi_occ_submit()
555 get_unaligned_be16(&resp->data_length); in fsi_occ_submit()
562 rc = -EMSGSIZE; in fsi_occ_submit()
571 rc = occ_getsram(occ, 0, resp, in fsi_occ_submit()
586 resp->return_status, resp_data_length); in fsi_occ_submit()
588 rc = occ_verify_checksum(occ, resp, resp_data_length); in fsi_occ_submit()
592 occ->client_response_size = resp_data_length + 7; in fsi_occ_submit()
595 *resp_len = occ->client_response_size; in fsi_occ_submit()
596 mutex_unlock(&occ->occ_lock); in fsi_occ_submit()
616 if (dev->of_node) in occ_unregister_of_child()
617 of_node_clear_flag(dev->of_node, OF_POPULATED); in occ_unregister_of_child()
627 struct occ *occ; in occ_probe() local
630 struct device *dev = &pdev->dev; in occ_probe()
633 .name = "occ-hwmon", in occ_probe()
636 occ = devm_kzalloc(dev, sizeof(*occ), GFP_KERNEL); in occ_probe()
637 if (!occ) in occ_probe()
638 return -ENOMEM; in occ_probe()
641 occ->buffer = kvmalloc(OCC_MAX_RESP_WORDS * 4, GFP_KERNEL); in occ_probe()
642 if (!occ->buffer) in occ_probe()
643 return -ENOMEM; in occ_probe()
645 occ->version = (uintptr_t)of_device_get_match_data(dev); in occ_probe()
646 occ->dev = dev; in occ_probe()
647 occ->sbefifo = dev->parent; in occ_probe()
649 * Quickly derive a pseudo-random number from jiffies so that in occ_probe()
650 * re-probing the driver doesn't accidentally overlap sequence numbers. in occ_probe()
652 occ->sequence_number = (u8)((jiffies % 0xff) + 1); in occ_probe()
653 mutex_init(&occ->occ_lock); in occ_probe()
655 if (dev->of_node) { in occ_probe()
656 rc = of_property_read_u32(dev->of_node, "reg", &reg); in occ_probe()
659 occ->idx = ida_alloc_range(&occ_ida, reg, reg, in occ_probe()
661 if (occ->idx < 0) in occ_probe()
662 occ->idx = ida_alloc_min(&occ_ida, 1, in occ_probe()
665 occ->idx = ida_alloc_min(&occ_ida, 1, GFP_KERNEL); in occ_probe()
668 occ->idx = ida_alloc_min(&occ_ida, 1, GFP_KERNEL); in occ_probe()
671 platform_set_drvdata(pdev, occ); in occ_probe()
673 snprintf(occ->name, sizeof(occ->name), "occ%d", occ->idx); in occ_probe()
674 occ->mdev.fops = &occ_fops; in occ_probe()
675 occ->mdev.minor = MISC_DYNAMIC_MINOR; in occ_probe()
676 occ->mdev.name = occ->name; in occ_probe()
677 occ->mdev.parent = dev; in occ_probe()
679 rc = misc_register(&occ->mdev); in occ_probe()
682 ida_free(&occ_ida, occ->idx); in occ_probe()
683 kvfree(occ->buffer); in occ_probe()
687 hwmon_node = of_get_child_by_name(dev->of_node, hwmon_dev_info.name); in occ_probe()
689 snprintf(child_name, sizeof(child_name), "%s.%d", hwmon_dev_info.name, occ->idx); in occ_probe()
695 occ->platform_hwmon = true; in occ_probe()
696 hwmon_dev_info.id = occ->idx; in occ_probe()
699 dev_warn(dev, "failed to create hwmon device\n"); in occ_probe()
707 struct occ *occ = platform_get_drvdata(pdev); in occ_remove() local
709 misc_deregister(&occ->mdev); in occ_remove()
711 mutex_lock(&occ->occ_lock); in occ_remove()
712 kvfree(occ->buffer); in occ_remove()
713 occ->buffer = NULL; in occ_remove()
714 mutex_unlock(&occ->occ_lock); in occ_remove()
716 if (occ->platform_hwmon) in occ_remove()
717 device_for_each_child(&pdev->dev, NULL, occ_unregister_platform_child); in occ_remove()
719 device_for_each_child(&pdev->dev, NULL, occ_unregister_of_child); in occ_remove()
721 ida_free(&occ_ida, occ->idx); in occ_remove()
726 .compatible = "ibm,p9-occ",
730 .compatible = "ibm,p10-occ",
739 .name = "occ",
762 MODULE_DESCRIPTION("BMC P9 OCC driver");