summaryrefslogtreecommitdiff
path: root/drivers/net/fsl-mc/mc_sys.c
blob: b5ae2ea3eb56db1920a0e123c0190153ffa0f32d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// SPDX-License-Identifier: GPL-2.0+
/*
 * Freescale Layerscape MC I/O wrapper
 *
 * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
 * Author: German Rivera <German.Rivera@freescale.com>
 */

#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <linux/delay.h>

#define MC_CMD_HDR_READ_CMDID(_hdr) \
	((uint16_t)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S))

/**
 * mc_send_command - Send MC command and wait for response
 *
 * @mc_io: Pointer to MC I/O object to be used
 * @cmd: MC command buffer. On input, it contains the command to send to the MC.
 * On output, it contains the response from the MC if any.
 *
 * Depending on the sharing option specified when creating the MC portal
 * wrapper, this function will use a spinlock or mutex to ensure exclusive
 * access to the MC portal from the point when the command is sent until a
 * response is received from the MC.
 */
int mc_send_command(struct fsl_mc_io *mc_io,
		    struct mc_command *cmd)
{
	enum mc_cmd_status status;
	int timeout = 12000;

	mc_write_command(mc_io->mmio_regs, cmd);

	for ( ; ; ) {
		status = mc_read_response(mc_io->mmio_regs, cmd);
		if (status != MC_CMD_STATUS_READY)
			break;

		if (--timeout == 0) {
			printf("Error: Timeout waiting for MC response\n");
			return -ETIMEDOUT;
		}

		udelay(500);
	}

	if (status != MC_CMD_STATUS_OK) {
		printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
		       mc_io->mmio_regs,
			(unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
		       (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
		       (unsigned int)status);

		return -EIO;
	}

	return 0;
}