^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2013-2016 Freescale Semiconductor Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * I/O services to send MC commands to the MC hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io-64-nonatomic-hi-lo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fsl/mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "fsl-mc-private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Timeout in milliseconds to wait for the completion of an MC command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MC_CMD_COMPLETION_TIMEOUT_MS 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * usleep_range() min and max values used to throttle down polling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * iterations while waiting for MC command completion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return (enum mc_cmd_status)hdr->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u16 cmd_id = le16_to_cpu(hdr->cmd_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return cmd_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int mc_status_to_error(enum mc_cmd_status status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static const int mc_status_to_error_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) [MC_CMD_STATUS_OK] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) [MC_CMD_STATUS_DMA_ERR] = -EIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [MC_CMD_STATUS_BUSY] = -EBUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return mc_status_to_error_map[status];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const char *mc_status_to_string(enum mc_cmd_status status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const char *const status_strings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) [MC_CMD_STATUS_OK] = "Command completed successfully",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) [MC_CMD_STATUS_READY] = "Command ready to be processed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) [MC_CMD_STATUS_BUSY] = "Device is busy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if ((unsigned int)status >= ARRAY_SIZE(status_strings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return "Unknown MC error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return status_strings[status];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * mc_write_command - writes a command to a Management Complex (MC) portal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @portal: pointer to an MC portal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @cmd: pointer to a filled command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct fsl_mc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* copy command parameters into the portal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Data is already in the expected LE byte-order. Do an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * extra LE -> CPU conversion so that the CPU -> LE done in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * the device io write api puts it back in the right order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* submit the command by writing the header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) writeq(le64_to_cpu(cmd->header), &portal->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * mc_read_response - reads the response for the last MC command from a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Management Complex (MC) portal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @portal: pointer to an MC portal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @resp: pointer to command response buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *portal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct fsl_mc_command *resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) enum mc_cmd_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Copy command response header from MC portal: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) resp->header = cpu_to_le64(readq_relaxed(&portal->header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) status = mc_cmd_hdr_read_status(resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (status != MC_CMD_STATUS_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* Copy command response data from MC portal: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Data is expected to be in LE byte-order. Do an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * extra CPU -> LE to revert the LE -> CPU done in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * the device io read api.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) resp->params[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) cpu_to_le64(readq_relaxed(&portal->params[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * Waits for the completion of an MC command doing preemptible polling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * uslepp_range() is called between polling iterations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * @mc_io: MC I/O object to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * @cmd: command buffer to receive MC response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * @mc_status: MC command completion status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct fsl_mc_command *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) enum mc_cmd_status *mc_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) enum mc_cmd_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned long jiffies_until_timeout =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * Wait for response from the MC hardware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) status = mc_read_response(mc_io->portal_virt_addr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (status != MC_CMD_STATUS_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * TODO: When MC command completion interrupts are supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * call wait function here instead of usleep_range()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (time_after_eq(jiffies, jiffies_until_timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_dbg(mc_io->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) &mc_io->portal_phys_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) (unsigned int)mc_cmd_hdr_read_token(cmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *mc_status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Waits for the completion of an MC command doing atomic polling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * udelay() is called between polling iterations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @mc_io: MC I/O object to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @cmd: command buffer to receive MC response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @mc_status: MC command completion status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct fsl_mc_command *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) enum mc_cmd_status *mc_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) enum mc_cmd_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) status = mc_read_response(mc_io->portal_virt_addr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (status != MC_CMD_STATUS_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (timeout_usecs == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dev_dbg(mc_io->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) &mc_io->portal_phys_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) (unsigned int)mc_cmd_hdr_read_token(cmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *mc_status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Sends a command to the MC device using the given MC I/O object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * @mc_io: MC I/O object to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @cmd: command to be sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Returns '0' on Success; Error code otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) enum mc_cmd_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned long irq_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) raw_spin_lock_irqsave(&mc_io->spinlock, irq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mutex_lock(&mc_io->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * Send command to the MC hardware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mc_write_command(mc_io->portal_virt_addr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Wait for response from the MC hardware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) error = mc_polling_wait_preemptible(mc_io, cmd, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) error = mc_polling_wait_atomic(mc_io, cmd, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto common_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (status != MC_CMD_STATUS_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dev_dbg(mc_io->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) &mc_io->portal_phys_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) (unsigned int)mc_cmd_hdr_read_token(cmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mc_status_to_string(status),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) (unsigned int)status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) error = mc_status_to_error(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto common_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) common_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) raw_spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) mutex_unlock(&mc_io->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) EXPORT_SYMBOL_GPL(mc_send_command);