1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Freescale Layerscape MC I/O wrapper
4  *
5  * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
6  * Author: German Rivera <German.Rivera@freescale.com>
7  */
8 
9 #include <fsl-mc/fsl_mc_sys.h>
10 #include <fsl-mc/fsl_mc_cmd.h>
11 #include <errno.h>
12 #include <asm/io.h>
13 #include <linux/delay.h>
14 
mc_cmd_hdr_read_cmdid(struct mc_command * cmd)15 static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
16 {
17 	struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
18 	u16 cmd_id = le16_to_cpu(hdr->cmd_id);
19 
20 	return cmd_id;
21 }
22 
23 /**
24  * mc_send_command - Send MC command and wait for response
25  *
26  * @mc_io: Pointer to MC I/O object to be used
27  * @cmd: MC command buffer. On input, it contains the command to send to the MC.
28  * On output, it contains the response from the MC if any.
29  *
30  * Depending on the sharing option specified when creating the MC portal
31  * wrapper, this function will use a spinlock or mutex to ensure exclusive
32  * access to the MC portal from the point when the command is sent until a
33  * response is received from the MC.
34  */
mc_send_command(struct fsl_mc_io * mc_io,struct mc_command * cmd)35 int mc_send_command(struct fsl_mc_io *mc_io,
36 		    struct mc_command *cmd)
37 {
38 	enum mc_cmd_status status;
39 	int timeout = 12000;
40 
41 	mc_write_command(mc_io->mmio_regs, cmd);
42 
43 	for ( ; ; ) {
44 		status = mc_read_response(mc_io->mmio_regs, cmd);
45 		if (status != MC_CMD_STATUS_READY)
46 			break;
47 
48 		if (--timeout == 0) {
49 			printf("Error: Timeout waiting for MC response\n");
50 			return -ETIMEDOUT;
51 		}
52 
53 		udelay(500);
54 	}
55 
56 	if (status != MC_CMD_STATUS_OK) {
57 		printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
58 		       mc_io->mmio_regs,
59 			(unsigned int)mc_cmd_hdr_read_token(cmd),
60 		       (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
61 		       (unsigned int)status);
62 
63 		return -EIO;
64 	}
65 
66 	return 0;
67 }
68