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