aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 12:41:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 12:41:12 -0500
commit384d11fa0e2ca15a3e7e52db34a4e43bedf0dc70 (patch)
treeb68ecd9458fb77d6b80e1389fc3705ca360a7def /drivers/firmware
parent6ad63dec9c2c80710896edd1996e56c54a230870 (diff)
parent8ceb820b69fe6ff58234ff604146a9e88e6c1974 (diff)
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann: "As usual, the drivers/tee and drivers/reset subsystems get merged here, with the expected set of smaller updates and some new hardware support. The tee subsystem now supports device drivers to be attached to a tee, the first example here is a random number driver with its implementation in the secure world. Three new power domain drivers get added for specific chip families: - Broadcom BCM283x chips (used in Raspberry Pi) - Qualcomm Snapdragon phone chips - Xilinx ZynqMP FPGA SoCs One new driver is added to talk to the BPMP firmware on NVIDIA Tegra210 Existing drivers are extended for new SoC variants from NXP, NVIDIA, Amlogic and Qualcomm" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (113 commits) tee: optee: update optee_msg.h and optee_smc.h to dual license tee: add cancellation support to client interface dpaa2-eth: configure the cache stashing amount on a queue soc: fsl: dpio: configure cache stashing destination soc: fsl: dpio: enable frame data cache stashing per software portal soc: fsl: guts: make fsl_guts_get_svr() static hwrng: make symbol 'optee_rng_id_table' static tee: optee: Fix unsigned comparison with less than zero hwrng: Fix unsigned comparison with less than zero tee: fix possible error pointer ctx dereferencing hwrng: optee: Initialize some structs using memset instead of braces tee: optee: Initialize some structs using memset instead of braces soc: fsl: dpio: fix memory leak of a struct qbman on error exit path clk: tegra: dfll: Make symbol 'tegra210_cpu_cvb_tables' static soc: qcom: llcc-slice: Fix typos qcom: soc: llcc-slice: Consolidate some code qcom: soc: llcc-slice: Clear the global drv_data pointer on error drivers: soc: xilinx: Add ZynqMP power domain driver firmware: xilinx: Add APIs to control node status/power dt-bindings: power: Add ZynqMP power domain bindings ...
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/imx/misc.c38
-rw-r--r--drivers/firmware/imx/scu-pd.c1
-rw-r--r--drivers/firmware/raspberrypi.c11
-rw-r--r--drivers/firmware/tegra/Makefile3
-rw-r--r--drivers/firmware/tegra/bpmp-private.h34
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c305
-rw-r--r--drivers/firmware/tegra/bpmp-tegra210.c243
-rw-r--r--drivers/firmware/tegra/bpmp.c376
-rw-r--r--drivers/firmware/ti_sci.c21
-rw-r--r--drivers/firmware/xilinx/Kconfig1
-rw-r--r--drivers/firmware/xilinx/zynqmp.c166
11 files changed, 954 insertions, 245 deletions
diff --git a/drivers/firmware/imx/misc.c b/drivers/firmware/imx/misc.c
index 97f5424dbac9..4b56a587dacd 100644
--- a/drivers/firmware/imx/misc.c
+++ b/drivers/firmware/imx/misc.c
@@ -18,6 +18,14 @@ struct imx_sc_msg_req_misc_set_ctrl {
18 u16 resource; 18 u16 resource;
19} __packed; 19} __packed;
20 20
21struct imx_sc_msg_req_cpu_start {
22 struct imx_sc_rpc_msg hdr;
23 u32 address_hi;
24 u32 address_lo;
25 u16 resource;
26 u8 enable;
27} __packed;
28
21struct imx_sc_msg_req_misc_get_ctrl { 29struct imx_sc_msg_req_misc_get_ctrl {
22 struct imx_sc_rpc_msg hdr; 30 struct imx_sc_rpc_msg hdr;
23 u32 ctrl; 31 u32 ctrl;
@@ -97,3 +105,33 @@ int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
97 return 0; 105 return 0;
98} 106}
99EXPORT_SYMBOL(imx_sc_misc_get_control); 107EXPORT_SYMBOL(imx_sc_misc_get_control);
108
109/*
110 * This function starts/stops a CPU identified by @resource
111 *
112 * @param[in] ipc IPC handle
113 * @param[in] resource resource the control is associated with
114 * @param[in] enable true for start, false for stop
115 * @param[in] phys_addr initial instruction address to be executed
116 *
117 * @return Returns 0 for success and < 0 for errors.
118 */
119int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
120 bool enable, u64 phys_addr)
121{
122 struct imx_sc_msg_req_cpu_start msg;
123 struct imx_sc_rpc_msg *hdr = &msg.hdr;
124
125 hdr->ver = IMX_SC_RPC_VERSION;
126 hdr->svc = IMX_SC_RPC_SVC_PM;
127 hdr->func = IMX_SC_PM_FUNC_CPU_START;
128 hdr->size = 4;
129
130 msg.address_hi = phys_addr >> 32;
131 msg.address_lo = phys_addr;
132 msg.resource = resource;
133 msg.enable = enable;
134
135 return imx_scu_call_rpc(ipc, &msg, true);
136}
137EXPORT_SYMBOL(imx_sc_pm_cpu_start);
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 407245f2efd0..39a94c7177fc 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -322,6 +322,7 @@ static int imx_sc_pd_probe(struct platform_device *pdev)
322 322
323static const struct of_device_id imx_sc_pd_match[] = { 323static const struct of_device_id imx_sc_pd_match[] = {
324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd}, 324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
325 { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
325 { /* sentinel */ } 326 { /* sentinel */ }
326}; 327};
327 328
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a13558154ac3..61be15d9df7d 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -238,6 +238,16 @@ static int rpi_firmware_probe(struct platform_device *pdev)
238 return 0; 238 return 0;
239} 239}
240 240
241static void rpi_firmware_shutdown(struct platform_device *pdev)
242{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev);
244
245 if (!fw)
246 return;
247
248 rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
249}
250
241static int rpi_firmware_remove(struct platform_device *pdev) 251static int rpi_firmware_remove(struct platform_device *pdev)
242{ 252{
243 struct rpi_firmware *fw = platform_get_drvdata(pdev); 253 struct rpi_firmware *fw = platform_get_drvdata(pdev);
@@ -278,6 +288,7 @@ static struct platform_driver rpi_firmware_driver = {
278 .of_match_table = rpi_firmware_of_match, 288 .of_match_table = rpi_firmware_of_match,
279 }, 289 },
280 .probe = rpi_firmware_probe, 290 .probe = rpi_firmware_probe,
291 .shutdown = rpi_firmware_shutdown,
281 .remove = rpi_firmware_remove, 292 .remove = rpi_firmware_remove,
282}; 293};
283module_platform_driver(rpi_firmware_driver); 294module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
index 1b826dcca719..676b01caff05 100644
--- a/drivers/firmware/tegra/Makefile
+++ b/drivers/firmware/tegra/Makefile
@@ -1,4 +1,7 @@
1tegra-bpmp-y = bpmp.o 1tegra-bpmp-y = bpmp.o
2tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC) += bpmp-tegra210.o
3tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
4tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC) += bpmp-tegra186.o
2tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o 5tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
3obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o 6obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
4obj-$(CONFIG_TEGRA_IVC) += ivc.o 7obj-$(CONFIG_TEGRA_IVC) += ivc.o
diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h
new file mode 100644
index 000000000000..54d560c48398
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-private.h
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#ifndef __FIRMWARE_TEGRA_BPMP_PRIVATE_H
7#define __FIRMWARE_TEGRA_BPMP_PRIVATE_H
8
9#include <soc/tegra/bpmp.h>
10
11struct tegra_bpmp_ops {
12 int (*init)(struct tegra_bpmp *bpmp);
13 void (*deinit)(struct tegra_bpmp *bpmp);
14 bool (*is_response_ready)(struct tegra_bpmp_channel *channel);
15 bool (*is_request_ready)(struct tegra_bpmp_channel *channel);
16 int (*ack_response)(struct tegra_bpmp_channel *channel);
17 int (*ack_request)(struct tegra_bpmp_channel *channel);
18 bool (*is_response_channel_free)(struct tegra_bpmp_channel *channel);
19 bool (*is_request_channel_free)(struct tegra_bpmp_channel *channel);
20 int (*post_response)(struct tegra_bpmp_channel *channel);
21 int (*post_request)(struct tegra_bpmp_channel *channel);
22 int (*ring_doorbell)(struct tegra_bpmp *bpmp);
23 int (*resume)(struct tegra_bpmp *bpmp);
24};
25
26#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
27 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
28extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
29#endif
30#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
31extern const struct tegra_bpmp_ops tegra210_bpmp_ops;
32#endif
33
34#endif
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
new file mode 100644
index 000000000000..ea308751635f
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -0,0 +1,305 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#include <linux/genalloc.h>
7#include <linux/mailbox_client.h>
8#include <linux/platform_device.h>
9
10#include <soc/tegra/bpmp.h>
11#include <soc/tegra/bpmp-abi.h>
12#include <soc/tegra/ivc.h>
13
14#include "bpmp-private.h"
15
16struct tegra186_bpmp {
17 struct tegra_bpmp *parent;
18
19 struct {
20 struct gen_pool *pool;
21 dma_addr_t phys;
22 void *virt;
23 } tx, rx;
24
25 struct {
26 struct mbox_client client;
27 struct mbox_chan *channel;
28 } mbox;
29};
30
31static inline struct tegra_bpmp *
32mbox_client_to_bpmp(struct mbox_client *client)
33{
34 struct tegra186_bpmp *priv;
35
36 priv = container_of(client, struct tegra186_bpmp, mbox.client);
37
38 return priv->parent;
39}
40
41static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
42{
43 void *frame;
44
45 frame = tegra_ivc_read_get_next_frame(channel->ivc);
46 if (IS_ERR(frame)) {
47 channel->ib = NULL;
48 return false;
49 }
50
51 channel->ib = frame;
52
53 return true;
54}
55
56static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
57{
58 void *frame;
59
60 frame = tegra_ivc_write_get_next_frame(channel->ivc);
61 if (IS_ERR(frame)) {
62 channel->ob = NULL;
63 return false;
64 }
65
66 channel->ob = frame;
67
68 return true;
69}
70
71static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
72{
73 return tegra_ivc_read_advance(channel->ivc);
74}
75
76static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
77{
78 return tegra_ivc_write_advance(channel->ivc);
79}
80
81static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
82{
83 struct tegra186_bpmp *priv = bpmp->priv;
84 int err;
85
86 err = mbox_send_message(priv->mbox.channel, NULL);
87 if (err < 0)
88 return err;
89
90 mbox_client_txdone(priv->mbox.channel, 0);
91
92 return 0;
93}
94
95static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
96{
97 struct tegra_bpmp *bpmp = data;
98 struct tegra186_bpmp *priv = bpmp->priv;
99
100 if (WARN_ON(priv->mbox.channel == NULL))
101 return;
102
103 tegra186_bpmp_ring_doorbell(bpmp);
104}
105
106static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
107 struct tegra_bpmp *bpmp,
108 unsigned int index)
109{
110 struct tegra186_bpmp *priv = bpmp->priv;
111 size_t message_size, queue_size;
112 unsigned int offset;
113 int err;
114
115 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
116 GFP_KERNEL);
117 if (!channel->ivc)
118 return -ENOMEM;
119
120 message_size = tegra_ivc_align(MSG_MIN_SZ);
121 queue_size = tegra_ivc_total_queue_size(message_size);
122 offset = queue_size * index;
123
124 err = tegra_ivc_init(channel->ivc, NULL,
125 priv->rx.virt + offset, priv->rx.phys + offset,
126 priv->tx.virt + offset, priv->tx.phys + offset,
127 1, message_size, tegra186_bpmp_ivc_notify,
128 bpmp);
129 if (err < 0) {
130 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
131 index, err);
132 return err;
133 }
134
135 init_completion(&channel->completion);
136 channel->bpmp = bpmp;
137
138 return 0;
139}
140
141static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
142{
143 /* reset the channel state */
144 tegra_ivc_reset(channel->ivc);
145
146 /* sync the channel state with BPMP */
147 while (tegra_ivc_notified(channel->ivc))
148 ;
149}
150
151static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
152{
153 tegra_ivc_cleanup(channel->ivc);
154}
155
156static void mbox_handle_rx(struct mbox_client *client, void *data)
157{
158 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
159
160 tegra_bpmp_handle_rx(bpmp);
161}
162
163static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
164{
165 struct tegra186_bpmp *priv;
166 unsigned int i;
167 int err;
168
169 priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
170 if (!priv)
171 return -ENOMEM;
172
173 bpmp->priv = priv;
174 priv->parent = bpmp;
175
176 priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
177 if (!priv->tx.pool) {
178 dev_err(bpmp->dev, "TX shmem pool not found\n");
179 return -ENOMEM;
180 }
181
182 priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
183 if (!priv->tx.virt) {
184 dev_err(bpmp->dev, "failed to allocate from TX pool\n");
185 return -ENOMEM;
186 }
187
188 priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
189 if (!priv->rx.pool) {
190 dev_err(bpmp->dev, "RX shmem pool not found\n");
191 err = -ENOMEM;
192 goto free_tx;
193 }
194
195 priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
196 if (!priv->rx.virt) {
197 dev_err(bpmp->dev, "failed to allocate from RX pool\n");
198 err = -ENOMEM;
199 goto free_tx;
200 }
201
202 err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
203 bpmp->soc->channels.cpu_tx.offset);
204 if (err < 0)
205 goto free_rx;
206
207 err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
208 bpmp->soc->channels.cpu_rx.offset);
209 if (err < 0)
210 goto cleanup_tx_channel;
211
212 for (i = 0; i < bpmp->threaded.count; i++) {
213 unsigned int index = bpmp->soc->channels.thread.offset + i;
214
215 err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
216 bpmp, index);
217 if (err < 0)
218 goto cleanup_channels;
219 }
220
221 /* mbox registration */
222 priv->mbox.client.dev = bpmp->dev;
223 priv->mbox.client.rx_callback = mbox_handle_rx;
224 priv->mbox.client.tx_block = false;
225 priv->mbox.client.knows_txdone = false;
226
227 priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
228 if (IS_ERR(priv->mbox.channel)) {
229 err = PTR_ERR(priv->mbox.channel);
230 dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
231 goto cleanup_channels;
232 }
233
234 tegra186_bpmp_channel_reset(bpmp->tx_channel);
235 tegra186_bpmp_channel_reset(bpmp->rx_channel);
236
237 for (i = 0; i < bpmp->threaded.count; i++)
238 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
239
240 return 0;
241
242cleanup_channels:
243 for (i = 0; i < bpmp->threaded.count; i++) {
244 if (!bpmp->threaded_channels[i].bpmp)
245 continue;
246
247 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
248 }
249
250 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
251cleanup_tx_channel:
252 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
253free_rx:
254 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
255free_tx:
256 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
257
258 return err;
259}
260
261static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
262{
263 struct tegra186_bpmp *priv = bpmp->priv;
264 unsigned int i;
265
266 mbox_free_channel(priv->mbox.channel);
267
268 for (i = 0; i < bpmp->threaded.count; i++)
269 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
270
271 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
272 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
273
274 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
275 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
276}
277
278static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
279{
280 unsigned int i;
281
282 /* reset message channels */
283 tegra186_bpmp_channel_reset(bpmp->tx_channel);
284 tegra186_bpmp_channel_reset(bpmp->rx_channel);
285
286 for (i = 0; i < bpmp->threaded.count; i++)
287 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
288
289 return 0;
290}
291
292const struct tegra_bpmp_ops tegra186_bpmp_ops = {
293 .init = tegra186_bpmp_init,
294 .deinit = tegra186_bpmp_deinit,
295 .is_response_ready = tegra186_bpmp_is_message_ready,
296 .is_request_ready = tegra186_bpmp_is_message_ready,
297 .ack_response = tegra186_bpmp_ack_message,
298 .ack_request = tegra186_bpmp_ack_message,
299 .is_response_channel_free = tegra186_bpmp_is_channel_free,
300 .is_request_channel_free = tegra186_bpmp_is_channel_free,
301 .post_response = tegra186_bpmp_post_message,
302 .post_request = tegra186_bpmp_post_message,
303 .ring_doorbell = tegra186_bpmp_ring_doorbell,
304 .resume = tegra186_bpmp_resume,
305};
diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c
new file mode 100644
index 000000000000..ae15940a078e
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra210.c
@@ -0,0 +1,243 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#include <linux/interrupt.h>
7#include <linux/irq.h>
8#include <linux/io.h>
9#include <linux/of.h>
10#include <linux/platform_device.h>
11
12#include <soc/tegra/bpmp.h>
13
14#include "bpmp-private.h"
15
16#define TRIGGER_OFFSET 0x000
17#define RESULT_OFFSET(id) (0xc00 + id * 4)
18#define TRIGGER_ID_SHIFT 16
19#define TRIGGER_CMD_GET 4
20
21#define STA_OFFSET 0
22#define SET_OFFSET 4
23#define CLR_OFFSET 8
24
25#define CH_MASK(ch) (0x3 << ((ch) * 2))
26#define SL_SIGL(ch) (0x0 << ((ch) * 2))
27#define SL_QUED(ch) (0x1 << ((ch) * 2))
28#define MA_FREE(ch) (0x2 << ((ch) * 2))
29#define MA_ACKD(ch) (0x3 << ((ch) * 2))
30
31struct tegra210_bpmp {
32 void __iomem *atomics;
33 void __iomem *arb_sema;
34 struct irq_data *tx_irq_data;
35};
36
37static u32 bpmp_channel_status(struct tegra_bpmp *bpmp, unsigned int index)
38{
39 struct tegra210_bpmp *priv = bpmp->priv;
40
41 return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(index);
42}
43
44static bool tegra210_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
45{
46 unsigned int index = channel->index;
47
48 return bpmp_channel_status(channel->bpmp, index) == MA_ACKD(index);
49}
50
51static bool tegra210_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
52{
53 unsigned int index = channel->index;
54
55 return bpmp_channel_status(channel->bpmp, index) == SL_SIGL(index);
56}
57
58static bool
59tegra210_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
60{
61 unsigned int index = channel->index;
62
63 return bpmp_channel_status(channel->bpmp, index) == MA_FREE(index);
64}
65
66static bool
67tegra210_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
68{
69 unsigned int index = channel->index;
70
71 return bpmp_channel_status(channel->bpmp, index) == SL_QUED(index);
72}
73
74static int tegra210_bpmp_post_request(struct tegra_bpmp_channel *channel)
75{
76 struct tegra210_bpmp *priv = channel->bpmp->priv;
77
78 __raw_writel(CH_MASK(channel->index), priv->arb_sema + CLR_OFFSET);
79
80 return 0;
81}
82
83static int tegra210_bpmp_post_response(struct tegra_bpmp_channel *channel)
84{
85 struct tegra210_bpmp *priv = channel->bpmp->priv;
86
87 __raw_writel(MA_ACKD(channel->index), priv->arb_sema + SET_OFFSET);
88
89 return 0;
90}
91
92static int tegra210_bpmp_ack_response(struct tegra_bpmp_channel *channel)
93{
94 struct tegra210_bpmp *priv = channel->bpmp->priv;
95
96 __raw_writel(MA_ACKD(channel->index) ^ MA_FREE(channel->index),
97 priv->arb_sema + CLR_OFFSET);
98
99 return 0;
100}
101
102static int tegra210_bpmp_ack_request(struct tegra_bpmp_channel *channel)
103{
104 struct tegra210_bpmp *priv = channel->bpmp->priv;
105
106 __raw_writel(SL_QUED(channel->index), priv->arb_sema + SET_OFFSET);
107
108 return 0;
109}
110
111static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
112{
113 struct tegra210_bpmp *priv = bpmp->priv;
114 struct irq_data *irq_data = priv->tx_irq_data;
115
116 /*
117 * Tegra Legacy Interrupt Controller (LIC) is used to notify BPMP of
118 * available messages
119 */
120 if (irq_data->chip->irq_retrigger)
121 return irq_data->chip->irq_retrigger(irq_data);
122
123 return -EINVAL;
124}
125
126static irqreturn_t rx_irq(int irq, void *data)
127{
128 struct tegra_bpmp *bpmp = data;
129
130 tegra_bpmp_handle_rx(bpmp);
131
132 return IRQ_HANDLED;
133}
134
135static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
136 struct tegra_bpmp *bpmp,
137 unsigned int index)
138{
139 struct tegra210_bpmp *priv = bpmp->priv;
140 u32 address;
141 void *p;
142
143 /* Retrieve channel base address from BPMP */
144 writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
145 priv->atomics + TRIGGER_OFFSET);
146 address = readl(priv->atomics + RESULT_OFFSET(index));
147
148 p = devm_ioremap(bpmp->dev, address, 0x80);
149 if (!p)
150 return -ENOMEM;
151
152 channel->ib = p;
153 channel->ob = p;
154 channel->index = index;
155 init_completion(&channel->completion);
156 channel->bpmp = bpmp;
157
158 return 0;
159}
160
161static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
162{
163 struct platform_device *pdev = to_platform_device(bpmp->dev);
164 struct tegra210_bpmp *priv;
165 struct resource *res;
166 unsigned int i;
167 int err;
168
169 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
170 if (!priv)
171 return -ENOMEM;
172
173 bpmp->priv = priv;
174
175 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
176 priv->atomics = devm_ioremap_resource(&pdev->dev, res);
177 if (IS_ERR(priv->atomics))
178 return PTR_ERR(priv->atomics);
179
180 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
181 priv->arb_sema = devm_ioremap_resource(&pdev->dev, res);
182 if (IS_ERR(priv->arb_sema))
183 return PTR_ERR(priv->arb_sema);
184
185 err = tegra210_bpmp_channel_init(bpmp->tx_channel, bpmp,
186 bpmp->soc->channels.cpu_tx.offset);
187 if (err < 0)
188 return err;
189
190 err = tegra210_bpmp_channel_init(bpmp->rx_channel, bpmp,
191 bpmp->soc->channels.cpu_rx.offset);
192 if (err < 0)
193 return err;
194
195 for (i = 0; i < bpmp->threaded.count; i++) {
196 unsigned int index = bpmp->soc->channels.thread.offset + i;
197
198 err = tegra210_bpmp_channel_init(&bpmp->threaded_channels[i],
199 bpmp, index);
200 if (err < 0)
201 return err;
202 }
203
204 err = platform_get_irq_byname(pdev, "tx");
205 if (err < 0) {
206 dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
207 return err;
208 }
209
210 priv->tx_irq_data = irq_get_irq_data(err);
211 if (!priv->tx_irq_data) {
212 dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
213 return err;
214 }
215
216 err = platform_get_irq_byname(pdev, "rx");
217 if (err < 0) {
218 dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
219 return err;
220 }
221
222 err = devm_request_irq(&pdev->dev, err, rx_irq,
223 IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
224 if (err < 0) {
225 dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
226 return err;
227 }
228
229 return 0;
230}
231
232const struct tegra_bpmp_ops tegra210_bpmp_ops = {
233 .init = tegra210_bpmp_init,
234 .is_response_ready = tegra210_bpmp_is_response_ready,
235 .is_request_ready = tegra210_bpmp_is_request_ready,
236 .ack_response = tegra210_bpmp_ack_response,
237 .ack_request = tegra210_bpmp_ack_request,
238 .is_response_channel_free = tegra210_bpmp_is_response_channel_free,
239 .is_request_channel_free = tegra210_bpmp_is_request_channel_free,
240 .post_response = tegra210_bpmp_post_response,
241 .post_request = tegra210_bpmp_post_request,
242 .ring_doorbell = tegra210_bpmp_ring_doorbell,
243};
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 689478b92bce..dd775e8ba5a0 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -26,6 +26,8 @@
26#include <soc/tegra/bpmp-abi.h> 26#include <soc/tegra/bpmp-abi.h>
27#include <soc/tegra/ivc.h> 27#include <soc/tegra/ivc.h>
28 28
29#include "bpmp-private.h"
30
29#define MSG_ACK BIT(0) 31#define MSG_ACK BIT(0)
30#define MSG_RING BIT(1) 32#define MSG_RING BIT(1)
31#define TAG_SZ 32 33#define TAG_SZ 32
@@ -36,6 +38,14 @@ mbox_client_to_bpmp(struct mbox_client *client)
36 return container_of(client, struct tegra_bpmp, mbox.client); 38 return container_of(client, struct tegra_bpmp, mbox.client);
37} 39}
38 40
41static inline const struct tegra_bpmp_ops *
42channel_to_ops(struct tegra_bpmp_channel *channel)
43{
44 struct tegra_bpmp *bpmp = channel->bpmp;
45
46 return bpmp->soc->ops;
47}
48
39struct tegra_bpmp *tegra_bpmp_get(struct device *dev) 49struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
40{ 50{
41 struct platform_device *pdev; 51 struct platform_device *pdev;
@@ -96,22 +106,21 @@ static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
96 (msg->rx.size == 0 || msg->rx.data); 106 (msg->rx.size == 0 || msg->rx.data);
97} 107}
98 108
99static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel) 109static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
100{ 110{
101 void *frame; 111 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
102 112
103 frame = tegra_ivc_read_get_next_frame(channel->ivc); 113 return ops->is_response_ready(channel);
104 if (IS_ERR(frame)) { 114}
105 channel->ib = NULL;
106 return false;
107 }
108 115
109 channel->ib = frame; 116static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
117{
118 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
110 119
111 return true; 120 return ops->is_request_ready(channel);
112} 121}
113 122
114static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel) 123static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
115{ 124{
116 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; 125 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
117 ktime_t end; 126 ktime_t end;
@@ -119,29 +128,45 @@ static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
119 end = ktime_add_us(ktime_get(), timeout); 128 end = ktime_add_us(ktime_get(), timeout);
120 129
121 do { 130 do {
122 if (tegra_bpmp_master_acked(channel)) 131 if (tegra_bpmp_is_response_ready(channel))
123 return 0; 132 return 0;
124 } while (ktime_before(ktime_get(), end)); 133 } while (ktime_before(ktime_get(), end));
125 134
126 return -ETIMEDOUT; 135 return -ETIMEDOUT;
127} 136}
128 137
129static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel) 138static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel)
130{ 139{
131 void *frame; 140 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
132 141
133 frame = tegra_ivc_write_get_next_frame(channel->ivc); 142 return ops->ack_response(channel);
134 if (IS_ERR(frame)) { 143}
135 channel->ob = NULL;
136 return false;
137 }
138 144
139 channel->ob = frame; 145static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel)
146{
147 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
140 148
141 return true; 149 return ops->ack_request(channel);
142} 150}
143 151
144static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel) 152static bool
153tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
154{
155 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
156
157 return ops->is_request_channel_free(channel);
158}
159
160static bool
161tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
162{
163 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
164
165 return ops->is_response_channel_free(channel);
166}
167
168static int
169tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel)
145{ 170{
146 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout; 171 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
147 ktime_t start, now; 172 ktime_t start, now;
@@ -149,7 +174,7 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
149 start = ns_to_ktime(local_clock()); 174 start = ns_to_ktime(local_clock());
150 175
151 do { 176 do {
152 if (tegra_bpmp_master_free(channel)) 177 if (tegra_bpmp_is_request_channel_free(channel))
153 return 0; 178 return 0;
154 179
155 now = ns_to_ktime(local_clock()); 180 now = ns_to_ktime(local_clock());
@@ -158,6 +183,25 @@ static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
158 return -ETIMEDOUT; 183 return -ETIMEDOUT;
159} 184}
160 185
186static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel)
187{
188 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
189
190 return ops->post_request(channel);
191}
192
193static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel)
194{
195 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
196
197 return ops->post_response(channel);
198}
199
200static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
201{
202 return bpmp->soc->ops->ring_doorbell(bpmp);
203}
204
161static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, 205static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
162 void *data, size_t size, int *ret) 206 void *data, size_t size, int *ret)
163{ 207{
@@ -166,7 +210,7 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
166 if (data && size > 0) 210 if (data && size > 0)
167 memcpy(data, channel->ib->data, size); 211 memcpy(data, channel->ib->data, size);
168 212
169 err = tegra_ivc_read_advance(channel->ivc); 213 err = tegra_bpmp_ack_response(channel);
170 if (err < 0) 214 if (err < 0)
171 return err; 215 return err;
172 216
@@ -210,7 +254,7 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
210 if (data && size > 0) 254 if (data && size > 0)
211 memcpy(channel->ob->data, data, size); 255 memcpy(channel->ob->data, data, size);
212 256
213 return tegra_ivc_write_advance(channel->ivc); 257 return tegra_bpmp_post_request(channel);
214} 258}
215 259
216static struct tegra_bpmp_channel * 260static struct tegra_bpmp_channel *
@@ -238,7 +282,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
238 282
239 channel = &bpmp->threaded_channels[index]; 283 channel = &bpmp->threaded_channels[index];
240 284
241 if (!tegra_bpmp_master_free(channel)) { 285 if (!tegra_bpmp_is_request_channel_free(channel)) {
242 err = -EBUSY; 286 err = -EBUSY;
243 goto unlock; 287 goto unlock;
244 } 288 }
@@ -270,7 +314,7 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
270{ 314{
271 int err; 315 int err;
272 316
273 err = tegra_bpmp_wait_master_free(channel); 317 err = tegra_bpmp_wait_request_channel_free(channel);
274 if (err < 0) 318 if (err < 0)
275 return err; 319 return err;
276 320
@@ -302,13 +346,11 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
302 346
303 spin_unlock(&bpmp->atomic_tx_lock); 347 spin_unlock(&bpmp->atomic_tx_lock);
304 348
305 err = mbox_send_message(bpmp->mbox.channel, NULL); 349 err = tegra_bpmp_ring_doorbell(bpmp);
306 if (err < 0) 350 if (err < 0)
307 return err; 351 return err;
308 352
309 mbox_client_txdone(bpmp->mbox.channel, 0); 353 err = tegra_bpmp_wait_response(channel);
310
311 err = tegra_bpmp_wait_ack(channel);
312 if (err < 0) 354 if (err < 0)
313 return err; 355 return err;
314 356
@@ -335,12 +377,10 @@ int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
335 if (IS_ERR(channel)) 377 if (IS_ERR(channel))
336 return PTR_ERR(channel); 378 return PTR_ERR(channel);
337 379
338 err = mbox_send_message(bpmp->mbox.channel, NULL); 380 err = tegra_bpmp_ring_doorbell(bpmp);
339 if (err < 0) 381 if (err < 0)
340 return err; 382 return err;
341 383
342 mbox_client_txdone(bpmp->mbox.channel, 0);
343
344 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout); 384 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
345 385
346 err = wait_for_completion_timeout(&channel->completion, timeout); 386 err = wait_for_completion_timeout(&channel->completion, timeout);
@@ -369,38 +409,34 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
369{ 409{
370 unsigned long flags = channel->ib->flags; 410 unsigned long flags = channel->ib->flags;
371 struct tegra_bpmp *bpmp = channel->bpmp; 411 struct tegra_bpmp *bpmp = channel->bpmp;
372 struct tegra_bpmp_mb_data *frame;
373 int err; 412 int err;
374 413
375 if (WARN_ON(size > MSG_DATA_MIN_SZ)) 414 if (WARN_ON(size > MSG_DATA_MIN_SZ))
376 return; 415 return;
377 416
378 err = tegra_ivc_read_advance(channel->ivc); 417 err = tegra_bpmp_ack_request(channel);
379 if (WARN_ON(err < 0)) 418 if (WARN_ON(err < 0))
380 return; 419 return;
381 420
382 if ((flags & MSG_ACK) == 0) 421 if ((flags & MSG_ACK) == 0)
383 return; 422 return;
384 423
385 frame = tegra_ivc_write_get_next_frame(channel->ivc); 424 if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
386 if (WARN_ON(IS_ERR(frame)))
387 return; 425 return;
388 426
389 frame->code = code; 427 channel->ob->code = code;
390 428
391 if (data && size > 0) 429 if (data && size > 0)
392 memcpy(frame->data, data, size); 430 memcpy(channel->ob->data, data, size);
393 431
394 err = tegra_ivc_write_advance(channel->ivc); 432 err = tegra_bpmp_post_response(channel);
395 if (WARN_ON(err < 0)) 433 if (WARN_ON(err < 0))
396 return; 434 return;
397 435
398 if (flags & MSG_RING) { 436 if (flags & MSG_RING) {
399 err = mbox_send_message(bpmp->mbox.channel, NULL); 437 err = tegra_bpmp_ring_doorbell(bpmp);
400 if (WARN_ON(err < 0)) 438 if (WARN_ON(err < 0))
401 return; 439 return;
402
403 mbox_client_txdone(bpmp->mbox.channel, 0);
404 } 440 }
405} 441}
406EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return); 442EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return);
@@ -627,9 +663,8 @@ static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
627 complete(&channel->completion); 663 complete(&channel->completion);
628} 664}
629 665
630static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) 666void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
631{ 667{
632 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
633 struct tegra_bpmp_channel *channel; 668 struct tegra_bpmp_channel *channel;
634 unsigned int i, count; 669 unsigned int i, count;
635 unsigned long *busy; 670 unsigned long *busy;
@@ -638,7 +673,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
638 count = bpmp->soc->channels.thread.count; 673 count = bpmp->soc->channels.thread.count;
639 busy = bpmp->threaded.busy; 674 busy = bpmp->threaded.busy;
640 675
641 if (tegra_bpmp_master_acked(channel)) 676 if (tegra_bpmp_is_request_ready(channel))
642 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel); 677 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
643 678
644 spin_lock(&bpmp->lock); 679 spin_lock(&bpmp->lock);
@@ -648,7 +683,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
648 683
649 channel = &bpmp->threaded_channels[i]; 684 channel = &bpmp->threaded_channels[i];
650 685
651 if (tegra_bpmp_master_acked(channel)) { 686 if (tegra_bpmp_is_response_ready(channel)) {
652 tegra_bpmp_channel_signal(channel); 687 tegra_bpmp_channel_signal(channel);
653 clear_bit(i, busy); 688 clear_bit(i, busy);
654 } 689 }
@@ -657,74 +692,9 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
657 spin_unlock(&bpmp->lock); 692 spin_unlock(&bpmp->lock);
658} 693}
659 694
660static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
661{
662 struct tegra_bpmp *bpmp = data;
663 int err;
664
665 if (WARN_ON(bpmp->mbox.channel == NULL))
666 return;
667
668 err = mbox_send_message(bpmp->mbox.channel, NULL);
669 if (err < 0)
670 return;
671
672 mbox_client_txdone(bpmp->mbox.channel, 0);
673}
674
675static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
676 struct tegra_bpmp *bpmp,
677 unsigned int index)
678{
679 size_t message_size, queue_size;
680 unsigned int offset;
681 int err;
682
683 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
684 GFP_KERNEL);
685 if (!channel->ivc)
686 return -ENOMEM;
687
688 message_size = tegra_ivc_align(MSG_MIN_SZ);
689 queue_size = tegra_ivc_total_queue_size(message_size);
690 offset = queue_size * index;
691
692 err = tegra_ivc_init(channel->ivc, NULL,
693 bpmp->rx.virt + offset, bpmp->rx.phys + offset,
694 bpmp->tx.virt + offset, bpmp->tx.phys + offset,
695 1, message_size, tegra_bpmp_ivc_notify,
696 bpmp);
697 if (err < 0) {
698 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
699 index, err);
700 return err;
701 }
702
703 init_completion(&channel->completion);
704 channel->bpmp = bpmp;
705
706 return 0;
707}
708
709static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
710{
711 /* reset the channel state */
712 tegra_ivc_reset(channel->ivc);
713
714 /* sync the channel state with BPMP */
715 while (tegra_ivc_notified(channel->ivc))
716 ;
717}
718
719static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
720{
721 tegra_ivc_cleanup(channel->ivc);
722}
723
724static int tegra_bpmp_probe(struct platform_device *pdev) 695static int tegra_bpmp_probe(struct platform_device *pdev)
725{ 696{
726 struct tegra_bpmp *bpmp; 697 struct tegra_bpmp *bpmp;
727 unsigned int i;
728 char tag[TAG_SZ]; 698 char tag[TAG_SZ];
729 size_t size; 699 size_t size;
730 int err; 700 int err;
@@ -736,32 +706,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
736 bpmp->soc = of_device_get_match_data(&pdev->dev); 706 bpmp->soc = of_device_get_match_data(&pdev->dev);
737 bpmp->dev = &pdev->dev; 707 bpmp->dev = &pdev->dev;
738 708
739 bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
740 if (!bpmp->tx.pool) {
741 dev_err(&pdev->dev, "TX shmem pool not found\n");
742 return -ENOMEM;
743 }
744
745 bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
746 if (!bpmp->tx.virt) {
747 dev_err(&pdev->dev, "failed to allocate from TX pool\n");
748 return -ENOMEM;
749 }
750
751 bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
752 if (!bpmp->rx.pool) {
753 dev_err(&pdev->dev, "RX shmem pool not found\n");
754 err = -ENOMEM;
755 goto free_tx;
756 }
757
758 bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
759 if (!bpmp->rx.virt) {
760 dev_err(&pdev->dev, "failed to allocate from RX pool\n");
761 err = -ENOMEM;
762 goto free_tx;
763 }
764
765 INIT_LIST_HEAD(&bpmp->mrqs); 709 INIT_LIST_HEAD(&bpmp->mrqs);
766 spin_lock_init(&bpmp->lock); 710 spin_lock_init(&bpmp->lock);
767 711
@@ -771,81 +715,38 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
771 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long); 715 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
772 716
773 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 717 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
774 if (!bpmp->threaded.allocated) { 718 if (!bpmp->threaded.allocated)
775 err = -ENOMEM; 719 return -ENOMEM;
776 goto free_rx;
777 }
778 720
779 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 721 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
780 if (!bpmp->threaded.busy) { 722 if (!bpmp->threaded.busy)
781 err = -ENOMEM; 723 return -ENOMEM;
782 goto free_rx;
783 }
784 724
785 spin_lock_init(&bpmp->atomic_tx_lock); 725 spin_lock_init(&bpmp->atomic_tx_lock);
786 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel), 726 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
787 GFP_KERNEL); 727 GFP_KERNEL);
788 if (!bpmp->tx_channel) { 728 if (!bpmp->tx_channel)
789 err = -ENOMEM; 729 return -ENOMEM;
790 goto free_rx;
791 }
792 730
793 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel), 731 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
794 GFP_KERNEL); 732 GFP_KERNEL);
795 if (!bpmp->rx_channel) { 733 if (!bpmp->rx_channel)
796 err = -ENOMEM; 734 return -ENOMEM;
797 goto free_rx;
798 }
799 735
800 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count, 736 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
801 sizeof(*bpmp->threaded_channels), 737 sizeof(*bpmp->threaded_channels),
802 GFP_KERNEL); 738 GFP_KERNEL);
803 if (!bpmp->threaded_channels) { 739 if (!bpmp->threaded_channels)
804 err = -ENOMEM; 740 return -ENOMEM;
805 goto free_rx;
806 }
807
808 err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
809 bpmp->soc->channels.cpu_tx.offset);
810 if (err < 0)
811 goto free_rx;
812 741
813 err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp, 742 err = bpmp->soc->ops->init(bpmp);
814 bpmp->soc->channels.cpu_rx.offset);
815 if (err < 0) 743 if (err < 0)
816 goto cleanup_tx_channel; 744 return err;
817
818 for (i = 0; i < bpmp->threaded.count; i++) {
819 err = tegra_bpmp_channel_init(
820 &bpmp->threaded_channels[i], bpmp,
821 bpmp->soc->channels.thread.offset + i);
822 if (err < 0)
823 goto cleanup_threaded_channels;
824 }
825
826 /* mbox registration */
827 bpmp->mbox.client.dev = &pdev->dev;
828 bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
829 bpmp->mbox.client.tx_block = false;
830 bpmp->mbox.client.knows_txdone = false;
831
832 bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
833 if (IS_ERR(bpmp->mbox.channel)) {
834 err = PTR_ERR(bpmp->mbox.channel);
835 dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
836 goto cleanup_threaded_channels;
837 }
838
839 /* reset message channels */
840 tegra_bpmp_channel_reset(bpmp->tx_channel);
841 tegra_bpmp_channel_reset(bpmp->rx_channel);
842 for (i = 0; i < bpmp->threaded.count; i++)
843 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
844 745
845 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING, 746 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
846 tegra_bpmp_mrq_handle_ping, bpmp); 747 tegra_bpmp_mrq_handle_ping, bpmp);
847 if (err < 0) 748 if (err < 0)
848 goto free_mbox; 749 goto deinit;
849 750
850 err = tegra_bpmp_ping(bpmp); 751 err = tegra_bpmp_ping(bpmp);
851 if (err < 0) { 752 if (err < 0) {
@@ -867,17 +768,23 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
867 if (err < 0) 768 if (err < 0)
868 goto free_mrq; 769 goto free_mrq;
869 770
870 err = tegra_bpmp_init_clocks(bpmp); 771 if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
871 if (err < 0) 772 err = tegra_bpmp_init_clocks(bpmp);
872 goto free_mrq; 773 if (err < 0)
774 goto free_mrq;
775 }
873 776
874 err = tegra_bpmp_init_resets(bpmp); 777 if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
875 if (err < 0) 778 err = tegra_bpmp_init_resets(bpmp);
876 goto free_mrq; 779 if (err < 0)
780 goto free_mrq;
781 }
877 782
878 err = tegra_bpmp_init_powergates(bpmp); 783 if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
879 if (err < 0) 784 err = tegra_bpmp_init_powergates(bpmp);
880 goto free_mrq; 785 if (err < 0)
786 goto free_mrq;
787 }
881 788
882 err = tegra_bpmp_init_debugfs(bpmp); 789 err = tegra_bpmp_init_debugfs(bpmp);
883 if (err < 0) 790 if (err < 0)
@@ -887,41 +794,27 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
887 794
888free_mrq: 795free_mrq:
889 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp); 796 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
890free_mbox: 797deinit:
891 mbox_free_channel(bpmp->mbox.channel); 798 if (bpmp->soc->ops->deinit)
892cleanup_threaded_channels: 799 bpmp->soc->ops->deinit(bpmp);
893 for (i = 0; i < bpmp->threaded.count; i++) {
894 if (bpmp->threaded_channels[i].bpmp)
895 tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
896 }
897 800
898 tegra_bpmp_channel_cleanup(bpmp->rx_channel);
899cleanup_tx_channel:
900 tegra_bpmp_channel_cleanup(bpmp->tx_channel);
901free_rx:
902 gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
903free_tx:
904 gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
905 return err; 801 return err;
906} 802}
907 803
908static int __maybe_unused tegra_bpmp_resume(struct device *dev) 804static int __maybe_unused tegra_bpmp_resume(struct device *dev)
909{ 805{
910 struct tegra_bpmp *bpmp = dev_get_drvdata(dev); 806 struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
911 unsigned int i;
912
913 /* reset message channels */
914 tegra_bpmp_channel_reset(bpmp->tx_channel);
915 tegra_bpmp_channel_reset(bpmp->rx_channel);
916
917 for (i = 0; i < bpmp->threaded.count; i++)
918 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
919 807
920 return 0; 808 if (bpmp->soc->ops->resume)
809 return bpmp->soc->ops->resume(bpmp);
810 else
811 return 0;
921} 812}
922 813
923static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume); 814static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume);
924 815
816#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
817 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
925static const struct tegra_bpmp_soc tegra186_soc = { 818static const struct tegra_bpmp_soc tegra186_soc = {
926 .channels = { 819 .channels = {
927 .cpu_tx = { 820 .cpu_tx = {
@@ -938,11 +831,42 @@ static const struct tegra_bpmp_soc tegra186_soc = {
938 .timeout = 0, 831 .timeout = 0,
939 }, 832 },
940 }, 833 },
834 .ops = &tegra186_bpmp_ops,
941 .num_resets = 193, 835 .num_resets = 193,
942}; 836};
837#endif
838
839#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
840static const struct tegra_bpmp_soc tegra210_soc = {
841 .channels = {
842 .cpu_tx = {
843 .offset = 0,
844 .count = 1,
845 .timeout = 60 * USEC_PER_SEC,
846 },
847 .thread = {
848 .offset = 4,
849 .count = 1,
850 .timeout = 600 * USEC_PER_SEC,
851 },
852 .cpu_rx = {
853 .offset = 8,
854 .count = 1,
855 .timeout = 0,
856 },
857 },
858 .ops = &tegra210_bpmp_ops,
859};
860#endif
943 861
944static const struct of_device_id tegra_bpmp_match[] = { 862static const struct of_device_id tegra_bpmp_match[] = {
863#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
864 IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
945 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc }, 865 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
866#endif
867#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
868 { .compatible = "nvidia,tegra210-bpmp", .data = &tegra210_soc },
869#endif
946 { } 870 { }
947}; 871};
948 872
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 69ed1464175c..3fbbb61012c4 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -146,25 +146,8 @@ static int ti_sci_debug_show(struct seq_file *s, void *unused)
146 return 0; 146 return 0;
147} 147}
148 148
149/** 149/* Provide the log file operations interface*/
150 * ti_sci_debug_open() - debug file open 150DEFINE_SHOW_ATTRIBUTE(ti_sci_debug);
151 * @inode: inode pointer
152 * @file: file pointer
153 *
154 * Return: result of single_open
155 */
156static int ti_sci_debug_open(struct inode *inode, struct file *file)
157{
158 return single_open(file, ti_sci_debug_show, inode->i_private);
159}
160
161/* log file operations */
162static const struct file_operations ti_sci_debug_fops = {
163 .open = ti_sci_debug_open,
164 .read = seq_read,
165 .llseek = seq_lseek,
166 .release = single_release,
167};
168 151
169/** 152/**
170 * ti_sci_debugfs_create() - Create log debug file 153 * ti_sci_debugfs_create() - Create log debug file
diff --git a/drivers/firmware/xilinx/Kconfig b/drivers/firmware/xilinx/Kconfig
index 8f44b9cd295a..bd33bbf70daf 100644
--- a/drivers/firmware/xilinx/Kconfig
+++ b/drivers/firmware/xilinx/Kconfig
@@ -6,6 +6,7 @@ menu "Zynq MPSoC Firmware Drivers"
6 6
7config ZYNQMP_FIRMWARE 7config ZYNQMP_FIRMWARE
8 bool "Enable Xilinx Zynq MPSoC firmware interface" 8 bool "Enable Xilinx Zynq MPSoC firmware interface"
9 select MFD_CORE
9 help 10 help
10 Firmware interface driver is used by different 11 Firmware interface driver is used by different
11 drivers to communicate with the firmware for 12 drivers to communicate with the firmware for
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 9a1c72a9280f..98f936125643 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -14,6 +14,7 @@
14#include <linux/compiler.h> 14#include <linux/compiler.h>
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/mfd/core.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/of.h> 19#include <linux/of.h>
19#include <linux/of_platform.h> 20#include <linux/of_platform.h>
@@ -23,6 +24,12 @@
23#include <linux/firmware/xlnx-zynqmp.h> 24#include <linux/firmware/xlnx-zynqmp.h>
24#include "zynqmp-debug.h" 25#include "zynqmp-debug.h"
25 26
27static const struct mfd_cell firmware_devs[] = {
28 {
29 .name = "zynqmp_power_controller",
30 },
31};
32
26/** 33/**
27 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes 34 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
28 * @ret_status: PMUFW return code 35 * @ret_status: PMUFW return code
@@ -187,6 +194,29 @@ static int zynqmp_pm_get_api_version(u32 *version)
187} 194}
188 195
189/** 196/**
197 * zynqmp_pm_get_chipid - Get silicon ID registers
198 * @idcode: IDCODE register
199 * @version: version register
200 *
201 * Return: Returns the status of the operation and the idcode and version
202 * registers in @idcode and @version.
203 */
204static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
205{
206 u32 ret_payload[PAYLOAD_ARG_CNT];
207 int ret;
208
209 if (!idcode || !version)
210 return -EINVAL;
211
212 ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
213 *idcode = ret_payload[1];
214 *version = ret_payload[2];
215
216 return ret;
217}
218
219/**
190 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version 220 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
191 * @version: Returned version value 221 * @version: Returned version value
192 * 222 *
@@ -469,8 +499,129 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
469 arg1, arg2, out); 499 arg1, arg2, out);
470} 500}
471 501
502/**
503 * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
504 * @reset: Reset to be configured
505 * @assert_flag: Flag stating should reset be asserted (1) or
506 * released (0)
507 *
508 * Return: Returns status, either success or error+reason
509 */
510static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
511 const enum zynqmp_pm_reset_action assert_flag)
512{
513 return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
514 0, 0, NULL);
515}
516
517/**
518 * zynqmp_pm_reset_get_status - Get status of the reset
519 * @reset: Reset whose status should be returned
520 * @status: Returned status
521 *
522 * Return: Returns status, either success or error+reason
523 */
524static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
525 u32 *status)
526{
527 u32 ret_payload[PAYLOAD_ARG_CNT];
528 int ret;
529
530 if (!status)
531 return -EINVAL;
532
533 ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
534 0, 0, ret_payload);
535 *status = ret_payload[1];
536
537 return ret;
538}
539
540/**
541 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
542 * master has initialized its own power management
543 *
544 * This API function is to be used for notify the power management controller
545 * about the completed power management initialization.
546 *
547 * Return: Returns status, either success or error+reason
548 */
549static int zynqmp_pm_init_finalize(void)
550{
551 return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
552}
553
554/**
555 * zynqmp_pm_set_suspend_mode() - Set system suspend mode
556 * @mode: Mode to set for system suspend
557 *
558 * This API function is used to set mode of system suspend.
559 *
560 * Return: Returns status, either success or error+reason
561 */
562static int zynqmp_pm_set_suspend_mode(u32 mode)
563{
564 return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
565}
566
567/**
568 * zynqmp_pm_request_node() - Request a node with specific capabilities
569 * @node: Node ID of the slave
570 * @capabilities: Requested capabilities of the slave
571 * @qos: Quality of service (not supported)
572 * @ack: Flag to specify whether acknowledge is requested
573 *
574 * This function is used by master to request particular node from firmware.
575 * Every master must request node before using it.
576 *
577 * Return: Returns status, either success or error+reason
578 */
579static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
580 const u32 qos,
581 const enum zynqmp_pm_request_ack ack)
582{
583 return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
584 qos, ack, NULL);
585}
586
587/**
588 * zynqmp_pm_release_node() - Release a node
589 * @node: Node ID of the slave
590 *
591 * This function is used by master to inform firmware that master
592 * has released node. Once released, master must not use that node
593 * without re-request.
594 *
595 * Return: Returns status, either success or error+reason
596 */
597static int zynqmp_pm_release_node(const u32 node)
598{
599 return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
600}
601
602/**
603 * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
604 * @node: Node ID of the slave
605 * @capabilities: Requested capabilities of the slave
606 * @qos: Quality of service (not supported)
607 * @ack: Flag to specify whether acknowledge is requested
608 *
609 * This API function is to be used for slaves a PU already has requested
610 * to change its capabilities.
611 *
612 * Return: Returns status, either success or error+reason
613 */
614static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
615 const u32 qos,
616 const enum zynqmp_pm_request_ack ack)
617{
618 return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
619 qos, ack, NULL);
620}
621
472static const struct zynqmp_eemi_ops eemi_ops = { 622static const struct zynqmp_eemi_ops eemi_ops = {
473 .get_api_version = zynqmp_pm_get_api_version, 623 .get_api_version = zynqmp_pm_get_api_version,
624 .get_chipid = zynqmp_pm_get_chipid,
474 .query_data = zynqmp_pm_query_data, 625 .query_data = zynqmp_pm_query_data,
475 .clock_enable = zynqmp_pm_clock_enable, 626 .clock_enable = zynqmp_pm_clock_enable,
476 .clock_disable = zynqmp_pm_clock_disable, 627 .clock_disable = zynqmp_pm_clock_disable,
@@ -482,6 +633,13 @@ static const struct zynqmp_eemi_ops eemi_ops = {
482 .clock_setparent = zynqmp_pm_clock_setparent, 633 .clock_setparent = zynqmp_pm_clock_setparent,
483 .clock_getparent = zynqmp_pm_clock_getparent, 634 .clock_getparent = zynqmp_pm_clock_getparent,
484 .ioctl = zynqmp_pm_ioctl, 635 .ioctl = zynqmp_pm_ioctl,
636 .reset_assert = zynqmp_pm_reset_assert,
637 .reset_get_status = zynqmp_pm_reset_get_status,
638 .init_finalize = zynqmp_pm_init_finalize,
639 .set_suspend_mode = zynqmp_pm_set_suspend_mode,
640 .request_node = zynqmp_pm_request_node,
641 .release_node = zynqmp_pm_release_node,
642 .set_requirement = zynqmp_pm_set_requirement,
485}; 643};
486 644
487/** 645/**
@@ -538,11 +696,19 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
538 696
539 zynqmp_pm_api_debugfs_init(); 697 zynqmp_pm_api_debugfs_init();
540 698
699 ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
700 ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
701 if (ret) {
702 dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
703 return ret;
704 }
705
541 return of_platform_populate(dev->of_node, NULL, NULL, dev); 706 return of_platform_populate(dev->of_node, NULL, NULL, dev);
542} 707}
543 708
544static int zynqmp_firmware_remove(struct platform_device *pdev) 709static int zynqmp_firmware_remove(struct platform_device *pdev)
545{ 710{
711 mfd_remove_devices(&pdev->dev);
546 zynqmp_pm_api_debugfs_exit(); 712 zynqmp_pm_api_debugfs_exit();
547 713
548 return 0; 714 return 0;