0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/delay.h>
0010 #include <linux/slab.h>
0011 #include <linux/ioport.h>
0012 #include <linux/device.h>
0013 #include <linux/io.h>
0014 #include <linux/io-64-nonatomic-hi-lo.h>
0015 #include <linux/fsl/mc.h>
0016
0017 #include "fsl-mc-private.h"
0018
0019
0020
0021
0022 #define MC_CMD_COMPLETION_TIMEOUT_MS 500
0023
0024
0025
0026
0027
0028 #define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
0029 #define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
0030
0031 static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
0032 {
0033 struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
0034
0035 return (enum mc_cmd_status)hdr->status;
0036 }
0037
0038 u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
0039 {
0040 struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
0041 u16 cmd_id = le16_to_cpu(hdr->cmd_id);
0042
0043 return cmd_id;
0044 }
0045
0046 static int mc_status_to_error(enum mc_cmd_status status)
0047 {
0048 static const int mc_status_to_error_map[] = {
0049 [MC_CMD_STATUS_OK] = 0,
0050 [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
0051 [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
0052 [MC_CMD_STATUS_DMA_ERR] = -EIO,
0053 [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
0054 [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
0055 [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
0056 [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
0057 [MC_CMD_STATUS_BUSY] = -EBUSY,
0058 [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
0059 [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
0060 };
0061
0062 if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
0063 return -EINVAL;
0064
0065 return mc_status_to_error_map[status];
0066 }
0067
0068 static const char *mc_status_to_string(enum mc_cmd_status status)
0069 {
0070 static const char *const status_strings[] = {
0071 [MC_CMD_STATUS_OK] = "Command completed successfully",
0072 [MC_CMD_STATUS_READY] = "Command ready to be processed",
0073 [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
0074 [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
0075 [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
0076 [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
0077 [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
0078 [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
0079 [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
0080 [MC_CMD_STATUS_BUSY] = "Device is busy",
0081 [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
0082 [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
0083 };
0084
0085 if ((unsigned int)status >= ARRAY_SIZE(status_strings))
0086 return "Unknown MC error";
0087
0088 return status_strings[status];
0089 }
0090
0091
0092
0093
0094
0095
0096
0097 static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
0098 struct fsl_mc_command *cmd)
0099 {
0100 int i;
0101
0102
0103 for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
0104
0105
0106
0107
0108
0109 writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
0110
0111
0112 writeq(le64_to_cpu(cmd->header), &portal->header);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
0125 *portal,
0126 struct fsl_mc_command *resp)
0127 {
0128 int i;
0129 enum mc_cmd_status status;
0130
0131
0132 resp->header = cpu_to_le64(readq_relaxed(&portal->header));
0133 status = mc_cmd_hdr_read_status(resp);
0134 if (status != MC_CMD_STATUS_OK)
0135 return status;
0136
0137
0138 for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
0139
0140
0141
0142
0143
0144 resp->params[i] =
0145 cpu_to_le64(readq_relaxed(&portal->params[i]));
0146
0147 return status;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
0160 struct fsl_mc_command *cmd,
0161 enum mc_cmd_status *mc_status)
0162 {
0163 enum mc_cmd_status status;
0164 unsigned long jiffies_until_timeout =
0165 jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
0166
0167
0168
0169
0170 for (;;) {
0171 status = mc_read_response(mc_io->portal_virt_addr, cmd);
0172 if (status != MC_CMD_STATUS_READY)
0173 break;
0174
0175
0176
0177
0178
0179 usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
0180 MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
0181
0182 if (time_after_eq(jiffies, jiffies_until_timeout)) {
0183 dev_dbg(mc_io->dev,
0184 "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
0185 &mc_io->portal_phys_addr,
0186 (unsigned int)mc_cmd_hdr_read_token(cmd),
0187 (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
0188
0189 return -ETIMEDOUT;
0190 }
0191 }
0192
0193 *mc_status = status;
0194 return 0;
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
0206 struct fsl_mc_command *cmd,
0207 enum mc_cmd_status *mc_status)
0208 {
0209 enum mc_cmd_status status;
0210 unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
0211
0212 BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
0213 MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
0214
0215 for (;;) {
0216 status = mc_read_response(mc_io->portal_virt_addr, cmd);
0217 if (status != MC_CMD_STATUS_READY)
0218 break;
0219
0220 udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
0221 timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
0222 if (timeout_usecs == 0) {
0223 dev_dbg(mc_io->dev,
0224 "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
0225 &mc_io->portal_phys_addr,
0226 (unsigned int)mc_cmd_hdr_read_token(cmd),
0227 (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
0228
0229 return -ETIMEDOUT;
0230 }
0231 }
0232
0233 *mc_status = status;
0234 return 0;
0235 }
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
0246 {
0247 int error;
0248 enum mc_cmd_status status;
0249 unsigned long irq_flags = 0;
0250
0251 if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
0252 return -EINVAL;
0253
0254 if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
0255 raw_spin_lock_irqsave(&mc_io->spinlock, irq_flags);
0256 else
0257 mutex_lock(&mc_io->mutex);
0258
0259
0260
0261
0262 mc_write_command(mc_io->portal_virt_addr, cmd);
0263
0264
0265
0266
0267 if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
0268 error = mc_polling_wait_preemptible(mc_io, cmd, &status);
0269 else
0270 error = mc_polling_wait_atomic(mc_io, cmd, &status);
0271
0272 if (error < 0)
0273 goto common_exit;
0274
0275 if (status != MC_CMD_STATUS_OK) {
0276 dev_dbg(mc_io->dev,
0277 "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
0278 &mc_io->portal_phys_addr,
0279 (unsigned int)mc_cmd_hdr_read_token(cmd),
0280 (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
0281 mc_status_to_string(status),
0282 (unsigned int)status);
0283
0284 error = mc_status_to_error(status);
0285 goto common_exit;
0286 }
0287
0288 error = 0;
0289 common_exit:
0290 if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
0291 raw_spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
0292 else
0293 mutex_unlock(&mc_io->mutex);
0294
0295 return error;
0296 }
0297 EXPORT_SYMBOL_GPL(mc_send_command);