Lines Matching +full:fsi +full:- +full:slave +full:- +full:engine
1 // SPDX-License-Identifier: GPL-2.0
18 #include <linux/fsi.h>
19 #include <linux/fsi-sbefifo.h>
35 #include <uapi/linux/fsi.h>
38 * The SBEFIFO is a pipe-like FSI device for communicating with
39 * the self boot engine on POWER processors.
50 #define SBEFIFO_UP 0x00 /* FSI -> Host */
51 #define SBEFIFO_DOWN 0x40 /* Host -> FSI */
53 /* Per-bank registers */
85 SBE_STATE_IPLING = 0x1, // IPL'ing - autonomous mode (transient)
86 SBE_STATE_ISTEP = 0x2, // ISTEP - Running IPL by steps (transient)
92 SBE_STATE_QUIESCE = 0x8, // Final state - needs SBE reset to get out
103 #define sbefifo_vacant(sts) (SBEFIFO_FIFO_DEPTH - sbefifo_populated(sts))
151 return sysfs_emit(buf, "%d\n", sbefifo->timed_out ? 1 : 0); in timeout_show()
172 ffdc_sz -= 3; in __sbefifo_dump_ffdc()
186 dev_warn(dev, "+---- SBE FFDC package %d for async err -----+\n", in __sbefifo_dump_ffdc()
189 dev_warn(dev, "+---- SBE FFDC package %d for cmd %02x:%02x -----+\n", in __sbefifo_dump_ffdc()
193 dev_warn(dev, "|-------------------------------------------|\n"); in __sbefifo_dump_ffdc()
200 ffdc_sz--; in __sbefifo_dump_ffdc()
201 if ((i & 3) == 3 || i == (w0 - 1)) { in __sbefifo_dump_ffdc()
209 dev_warn(dev, "+-------------------------------------------+\n"); in __sbefifo_dump_ffdc()
230 return -ENXIO; in sbefifo_parse_status()
232 dh = be32_to_cpu(response[resp_len - 1]); in sbefifo_parse_status()
236 return -ENXIO; in sbefifo_parse_status()
238 s0 = be32_to_cpu(response[resp_len - dh]); in sbefifo_parse_status()
239 s1 = be32_to_cpu(response[resp_len - dh + 1]); in sbefifo_parse_status()
243 return -ENXIO; in sbefifo_parse_status()
246 ffdc_sz = dh - 3; in sbefifo_parse_status()
250 sbefifo_dump_ffdc(dev, &response[resp_len - dh + 2], in sbefifo_parse_status()
254 *data_len = resp_len - dh; in sbefifo_parse_status()
269 rc = fsi_device_read(sbefifo->fsi_dev, reg, &raw_word, in sbefifo_regr()
283 return fsi_device_write(sbefifo->fsi_dev, reg, &raw_word, in sbefifo_regw()
293 rc = fsi_slave_read(sbefifo->fsi_dev->slave, CFAM_GP_MBOX_SBM_ADDR, in sbefifo_check_sbe_state()
301 return -ESHUTDOWN; in sbefifo_check_sbe_state()
306 return -ESHUTDOWN; in sbefifo_check_sbe_state()
308 return -EBUSY; in sbefifo_check_sbe_state()
317 return -ESHUTDOWN; in sbefifo_check_sbe_state()
322 sbefifo->async_ffdc = true; in sbefifo_check_sbe_state()
330 return fsi_device_read(sbefifo->fsi_dev, SBEFIFO_DOWN, word, in sbefifo_down_read()
336 return fsi_device_write(sbefifo->fsi_dev, SBEFIFO_UP, &word, in sbefifo_up_write()
342 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_request_reset()
350 sbefifo->broken = true; in sbefifo_request_reset()
371 sbefifo->broken = false; in sbefifo_request_reset()
379 return -ETIMEDOUT; in sbefifo_request_reset()
384 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_cleanup_hw()
396 if (sbefifo->broken) in sbefifo_cleanup_hw()
404 sbefifo->broken = true; in sbefifo_cleanup_hw()
413 sbefifo->broken = true; in sbefifo_cleanup_hw()
422 sbefifo->broken = true; in sbefifo_cleanup_hw()
426 sbefifo->broken = false; in sbefifo_cleanup_hw()
453 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_wait()
468 dev_err(dev, "FSI error %d reading status register\n", rc); in sbefifo_wait()
473 return -ENXIO; in sbefifo_wait()
480 sysfs_notify(&sbefifo->dev.kobj, NULL, dev_attr_timeout.attr.name); in sbefifo_wait()
481 sbefifo->timed_out = true; in sbefifo_wait()
484 return -ETIMEDOUT; in sbefifo_wait()
488 sbefifo->timed_out = false; in sbefifo_wait()
497 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_send_command()
513 timeout = msecs_to_jiffies(sbefifo->timeout_in_cmd_ms); in sbefifo_send_command()
522 while (len--) { in sbefifo_send_command()
525 dev_err(dev, "FSI error %d writing UP FIFO\n", rc); in sbefifo_send_command()
529 remaining -= chunk; in sbefifo_send_command()
530 vacant -= chunk; in sbefifo_send_command()
543 dev_err(dev, "FSI error %d writing EOT\n", rc); in sbefifo_send_command()
549 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_read_response()
559 timeout = msecs_to_jiffies(sbefifo->timeout_start_rsp_ms); in sbefifo_read_response()
576 while(len--) { in sbefifo_read_response()
594 sbefifo->broken = true; in sbefifo_read_response()
607 dev_err(dev, "FSI error %d ack'ing EOT\n", rc); in sbefifo_read_response()
608 sbefifo->broken = true; in sbefifo_read_response()
612 return overflow ? -EOVERFLOW : 0; in sbefifo_read_response()
618 return -EFAULT; in sbefifo_read_response()
630 return -EIO; in sbefifo_read_response()
648 struct device *dev = &sbefifo->fsi_dev->dev; in sbefifo_collect_async_ffdc()
656 sbefifo->async_ffdc = false; in sbefifo_collect_async_ffdc()
672 ffdc_sz = SBEFIFO_MAX_FFDC_SIZE - iov_iter_count(&ffdc_iter); in sbefifo_collect_async_ffdc()
691 struct device *dev = &sbefifo->fsi_dev->dev; in __sbefifo_submit()
694 if (sbefifo->dead) in __sbefifo_submit()
695 return -ENODEV; in __sbefifo_submit()
700 return -EINVAL; in __sbefifo_submit()
709 if (sbefifo->async_ffdc) in __sbefifo_submit()
713 if (rc != 0 && rc != -EOVERFLOW) in __sbefifo_submit()
728 * sbefifo_submit() - Submit and SBE fifo command and receive response
731 * @cmd_len: The command size (in 32-bit words)
736 * overflows, returns -EOVERFLOW
748 return -ENODEV; in sbefifo_submit()
751 return -ENODEV; in sbefifo_submit()
752 if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC)) in sbefifo_submit()
753 return -ENODEV; in sbefifo_submit()
755 return -EINVAL; in sbefifo_submit()
764 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_submit()
768 mutex_unlock(&sbefifo->lock); in sbefifo_submit()
771 rbytes -= iov_iter_count(&resp_iter); in sbefifo_submit()
784 if (is_vmalloc_addr(user->pending_cmd)) in sbefifo_release_command()
785 vfree(user->pending_cmd); in sbefifo_release_command()
786 user->pending_cmd = NULL; in sbefifo_release_command()
787 user->pending_len = 0; in sbefifo_release_command()
792 struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev); in sbefifo_user_open()
797 return -ENOMEM; in sbefifo_user_open()
799 file->private_data = user; in sbefifo_user_open()
800 user->sbefifo = sbefifo; in sbefifo_user_open()
801 user->cmd_page = (void *)__get_free_page(GFP_KERNEL); in sbefifo_user_open()
802 if (!user->cmd_page) { in sbefifo_user_open()
804 return -ENOMEM; in sbefifo_user_open()
806 mutex_init(&user->file_lock); in sbefifo_user_open()
807 user->cmd_timeout_ms = SBEFIFO_TIMEOUT_IN_CMD; in sbefifo_user_open()
808 user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_user_open()
816 struct sbefifo_user *user = file->private_data; in sbefifo_user_read()
824 return -EINVAL; in sbefifo_user_read()
825 sbefifo = user->sbefifo; in sbefifo_user_read()
827 return -EINVAL; in sbefifo_user_read()
829 mutex_lock(&user->file_lock); in sbefifo_user_read()
831 /* Cronus relies on -EAGAIN after a short read */ in sbefifo_user_read()
832 if (user->pending_len == 0) { in sbefifo_user_read()
833 rc = -EAGAIN; in sbefifo_user_read()
836 if (user->pending_len < 8) { in sbefifo_user_read()
837 rc = -EINVAL; in sbefifo_user_read()
840 cmd_len = user->pending_len >> 2; in sbefifo_user_read()
848 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_user_read()
851 sbefifo->timeout_in_cmd_ms = user->cmd_timeout_ms; in sbefifo_user_read()
852 sbefifo->timeout_start_rsp_ms = user->read_timeout_ms; in sbefifo_user_read()
853 rc = __sbefifo_submit(sbefifo, user->pending_cmd, cmd_len, &resp_iter); in sbefifo_user_read()
854 sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_user_read()
855 sbefifo->timeout_in_cmd_ms = SBEFIFO_TIMEOUT_IN_CMD; in sbefifo_user_read()
856 mutex_unlock(&sbefifo->lock); in sbefifo_user_read()
861 rc = len - iov_iter_count(&resp_iter); in sbefifo_user_read()
864 mutex_unlock(&user->file_lock); in sbefifo_user_read()
871 struct sbefifo_user *user = file->private_data; in sbefifo_user_write()
876 return -EINVAL; in sbefifo_user_write()
877 sbefifo = user->sbefifo; in sbefifo_user_write()
879 return -EINVAL; in sbefifo_user_write()
881 return -EINVAL; in sbefifo_user_write()
883 mutex_lock(&user->file_lock); in sbefifo_user_write()
885 /* Can we use the pre-allocate buffer ? If not, allocate */ in sbefifo_user_write()
887 user->pending_cmd = user->cmd_page; in sbefifo_user_write()
889 user->pending_cmd = vmalloc(len); in sbefifo_user_write()
890 if (!user->pending_cmd) { in sbefifo_user_write()
891 rc = -ENOMEM; in sbefifo_user_write()
896 if (copy_from_user(user->pending_cmd, buf, len)) { in sbefifo_user_write()
897 rc = -EFAULT; in sbefifo_user_write()
902 if (len == 4 && be32_to_cpu(*(__be32 *)user->pending_cmd) == in sbefifo_user_write()
906 user->pending_len = 0; in sbefifo_user_write()
909 rc = mutex_lock_interruptible(&sbefifo->lock); in sbefifo_user_write()
912 rc = sbefifo_request_reset(user->sbefifo); in sbefifo_user_write()
913 mutex_unlock(&sbefifo->lock); in sbefifo_user_write()
920 user->pending_len = len; in sbefifo_user_write()
922 if (!user->pending_len) in sbefifo_user_write()
925 mutex_unlock(&user->file_lock); in sbefifo_user_write()
933 struct sbefifo_user *user = file->private_data; in sbefifo_user_release()
936 return -EINVAL; in sbefifo_user_release()
939 free_page((unsigned long)user->cmd_page); in sbefifo_user_release()
947 struct device *dev = &user->sbefifo->dev; in sbefifo_cmd_timeout()
951 return -EFAULT; in sbefifo_cmd_timeout()
954 user->cmd_timeout_ms = SBEFIFO_TIMEOUT_IN_CMD; in sbefifo_cmd_timeout()
955 dev_dbg(dev, "Command timeout reset to %us\n", user->cmd_timeout_ms / 1000); in sbefifo_cmd_timeout()
959 user->cmd_timeout_ms = timeout * 1000; /* user timeout is in sec */ in sbefifo_cmd_timeout()
966 struct device *dev = &user->sbefifo->dev; in sbefifo_read_timeout()
970 return -EFAULT; in sbefifo_read_timeout()
973 user->read_timeout_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_read_timeout()
974 dev_dbg(dev, "Timeout reset to %us\n", user->read_timeout_ms / 1000); in sbefifo_read_timeout()
978 user->read_timeout_ms = timeout * 1000; /* user timeout is in sec */ in sbefifo_read_timeout()
985 struct sbefifo_user *user = file->private_data; in sbefifo_user_ioctl()
986 int rc = -ENOTTY; in sbefifo_user_ioctl()
989 return -EINVAL; in sbefifo_user_ioctl()
991 mutex_lock(&user->file_lock); in sbefifo_user_ioctl()
1000 mutex_unlock(&user->file_lock); in sbefifo_user_ioctl()
1017 put_device(&sbefifo->fsi_dev->dev); in sbefifo_free()
1038 return -ENOMEM; in sbefifo_probe()
1043 return -ENODEV; in sbefifo_probe()
1046 sbefifo->magic = SBEFIFO_MAGIC; in sbefifo_probe()
1047 sbefifo->fsi_dev = fsi_dev; in sbefifo_probe()
1049 mutex_init(&sbefifo->lock); in sbefifo_probe()
1050 sbefifo->timeout_in_cmd_ms = SBEFIFO_TIMEOUT_IN_CMD; in sbefifo_probe()
1051 sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP; in sbefifo_probe()
1054 sbefifo->dev.type = &fsi_cdev_type; in sbefifo_probe()
1055 sbefifo->dev.parent = dev; in sbefifo_probe()
1056 sbefifo->dev.release = sbefifo_free; in sbefifo_probe()
1057 device_initialize(&sbefifo->dev); in sbefifo_probe()
1059 /* Allocate a minor in the FSI space */ in sbefifo_probe()
1060 rc = fsi_get_new_minor(fsi_dev, fsi_dev_sbefifo, &sbefifo->dev.devt, &didx); in sbefifo_probe()
1064 dev_set_name(&sbefifo->dev, "sbefifo%d", didx); in sbefifo_probe()
1065 cdev_init(&sbefifo->cdev, &sbefifo_fops); in sbefifo_probe()
1066 rc = cdev_device_add(&sbefifo->cdev, &sbefifo->dev); in sbefifo_probe()
1069 rc, dev_name(&sbefifo->dev)); in sbefifo_probe()
1074 for_each_available_child_of_node(dev->of_node, np) { in sbefifo_probe()
1075 snprintf(child_name, sizeof(child_name), "%s-dev%d", in sbefifo_probe()
1076 dev_name(&sbefifo->dev), child_idx++); in sbefifo_probe()
1083 device_create_file(&sbefifo->dev, &dev_attr_timeout); in sbefifo_probe()
1087 fsi_free_minor(sbefifo->dev.devt); in sbefifo_probe()
1089 put_device(&sbefifo->dev); in sbefifo_probe()
1098 if (dev->of_node) in sbefifo_unregister_child()
1099 of_node_clear_flag(dev->of_node, OF_POPULATED); in sbefifo_unregister_child()
1110 device_remove_file(&sbefifo->dev, &dev_attr_timeout); in sbefifo_remove()
1112 mutex_lock(&sbefifo->lock); in sbefifo_remove()
1113 sbefifo->dead = true; in sbefifo_remove()
1114 mutex_unlock(&sbefifo->lock); in sbefifo_remove()
1116 cdev_device_del(&sbefifo->cdev, &sbefifo->dev); in sbefifo_remove()
1117 fsi_free_minor(sbefifo->dev.devt); in sbefifo_remove()
1119 put_device(&sbefifo->dev); in sbefifo_remove()
1159 MODULE_DESCRIPTION("Linux device interface to the POWER Self Boot Engine");