Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);