Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
Marek Behún | d63726e | 2022-06-01 17:17:06 +0200 | [diff] [blame] | 3 | * Copyright (C) 2018 Marek Behún <kabel@kernel.org> |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 4 | * Copyright (C) 2021 Pali Rohár <pali@kernel.org> |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 5 | */ |
| 6 | |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 7 | #include <asm/arch/soc.h> |
| 8 | #include <asm/io.h> |
| 9 | #include <linux/bitops.h> |
| 10 | #include <linux/delay.h> |
Tom Rini | dec7ea0 | 2024-05-20 13:35:03 -0600 | [diff] [blame] | 11 | #include <linux/errno.h> |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 12 | #include <mach/mbox.h> |
| 13 | |
| 14 | #define RWTM_BASE (MVEBU_REGISTER(0xb0000)) |
| 15 | #define RWTM_CMD_PARAM(i) (size_t)(RWTM_BASE + (i) * 4) |
| 16 | #define RWTM_CMD (RWTM_BASE + 0x40) |
| 17 | #define RWTM_CMD_RETSTATUS (RWTM_BASE + 0x80) |
| 18 | #define RWTM_CMD_STATUS(i) (size_t)(RWTM_BASE + 0x84 + (i) * 4) |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 19 | #define MAX_ARGS 16 |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 20 | |
| 21 | #define RWTM_HOST_INT_RESET (RWTM_BASE + 0xc8) |
| 22 | #define RWTM_HOST_INT_MASK (RWTM_BASE + 0xcc) |
| 23 | #define SP_CMD_COMPLETE BIT(0) |
| 24 | |
| 25 | #define MBOX_STS_SUCCESS (0x0 << 30) |
| 26 | #define MBOX_STS_FAIL (0x1 << 30) |
| 27 | #define MBOX_STS_BADCMD (0x2 << 30) |
| 28 | #define MBOX_STS_LATER (0x3 << 30) |
| 29 | #define MBOX_STS_ERROR(s) ((s) & (3 << 30)) |
| 30 | #define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff) |
| 31 | #define MBOX_STS_CMD(s) ((s) & 0x3ff) |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 32 | #define MBOX_STS_MARVELL_ERROR(s) ((s) == 0 ? 0 : \ |
| 33 | (s) == 2 ? ETIMEDOUT : \ |
| 34 | (s) == 3 ? EINVAL : \ |
| 35 | (s) == 4 ? ENOSYS : \ |
| 36 | EIO) |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 37 | |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 38 | int mbox_do_cmd(enum mbox_cmd cmd, u32 *in, int nin, u32 *out, int nout) |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 39 | { |
| 40 | const int tries = 50; |
| 41 | int i; |
| 42 | u32 status; |
| 43 | |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 44 | if (nin > MAX_ARGS || nout > MAX_ARGS) |
| 45 | return -EINVAL; |
| 46 | |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 47 | clrbits_le32(RWTM_HOST_INT_MASK, SP_CMD_COMPLETE); |
| 48 | |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 49 | for (i = 0; i < nin; i++) |
| 50 | writel(in[i], RWTM_CMD_PARAM(i)); |
| 51 | for (; i < MAX_ARGS; i++) |
| 52 | writel(0x0, RWTM_CMD_PARAM(i)); |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 53 | writel(cmd, RWTM_CMD); |
| 54 | |
| 55 | for (i = 0; i < tries; ++i) { |
| 56 | mdelay(10); |
| 57 | if (readl(RWTM_HOST_INT_RESET) & SP_CMD_COMPLETE) |
| 58 | break; |
| 59 | } |
| 60 | |
| 61 | if (i == tries) { |
| 62 | /* if timed out, don't read status */ |
| 63 | setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE); |
| 64 | return -ETIMEDOUT; |
| 65 | } |
| 66 | |
| 67 | for (i = 0; i < nout; ++i) |
| 68 | out[i] = readl(RWTM_CMD_STATUS(i)); |
| 69 | status = readl(RWTM_CMD_RETSTATUS); |
| 70 | |
| 71 | setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE); |
| 72 | |
| 73 | if (MBOX_STS_CMD(status) != cmd) |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 74 | return -MBOX_STS_MARVELL_ERROR(status); |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 75 | else if (MBOX_STS_ERROR(status) == MBOX_STS_FAIL) |
| 76 | return -(int)MBOX_STS_VALUE(status); |
Pali Rohár | 0e6dce7 | 2022-02-23 14:15:48 +0100 | [diff] [blame] | 77 | else if (MBOX_STS_ERROR(status) == MBOX_STS_BADCMD) |
| 78 | return -ENOSYS; |
Pali Rohár | deb1e92 | 2022-02-23 14:15:47 +0100 | [diff] [blame] | 79 | else if (MBOX_STS_ERROR(status) != MBOX_STS_SUCCESS) |
| 80 | return -EIO; |
| 81 | else |
| 82 | return MBOX_STS_VALUE(status); |
| 83 | } |