^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2018, NVIDIA CORPORATION.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/mailbox_client.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <soc/tegra/bpmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <soc/tegra/bpmp-abi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <soc/tegra/ivc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "bpmp-private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct tegra186_bpmp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct tegra_bpmp *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct gen_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) dma_addr_t phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void *virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) } tx, rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct mbox_client client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct mbox_chan *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) } mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static inline struct tegra_bpmp *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) mbox_client_to_bpmp(struct mbox_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct tegra186_bpmp *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) priv = container_of(client, struct tegra186_bpmp, mbox.client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return priv->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void *frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) frame = tegra_ivc_read_get_next_frame(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (IS_ERR(frame)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) channel->ib = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) channel->ib = frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void *frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) frame = tegra_ivc_write_get_next_frame(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (IS_ERR(frame)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) channel->ob = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) channel->ob = frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return tegra_ivc_read_advance(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return tegra_ivc_write_advance(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct tegra186_bpmp *priv = bpmp->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) err = mbox_send_message(priv->mbox.channel, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mbox_client_txdone(priv->mbox.channel, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct tegra_bpmp *bpmp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct tegra186_bpmp *priv = bpmp->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (WARN_ON(priv->mbox.channel == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) tegra186_bpmp_ring_doorbell(bpmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct tegra_bpmp *bpmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct tegra186_bpmp *priv = bpmp->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) size_t message_size, queue_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!channel->ivc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) message_size = tegra_ivc_align(MSG_MIN_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) queue_size = tegra_ivc_total_queue_size(message_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) offset = queue_size * index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) err = tegra_ivc_init(channel->ivc, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) priv->rx.virt + offset, priv->rx.phys + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) priv->tx.virt + offset, priv->tx.phys + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 1, message_size, tegra186_bpmp_ivc_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) bpmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) index, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) init_completion(&channel->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) channel->bpmp = bpmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* reset the channel state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) tegra_ivc_reset(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* sync the channel state with BPMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) while (tegra_ivc_notified(channel->ivc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) tegra_ivc_cleanup(channel->ivc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void mbox_handle_rx(struct mbox_client *client, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) tegra_bpmp_handle_rx(bpmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct tegra186_bpmp *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) bpmp->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) priv->parent = bpmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!priv->tx.pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) dev_err(bpmp->dev, "TX shmem pool not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!priv->tx.virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev_err(bpmp->dev, "failed to allocate from TX pool\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!priv->rx.pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dev_err(bpmp->dev, "RX shmem pool not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) err = -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto free_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!priv->rx.virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dev_err(bpmp->dev, "failed to allocate from RX pool\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto free_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) bpmp->soc->channels.cpu_tx.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto free_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) bpmp->soc->channels.cpu_rx.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto cleanup_tx_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (i = 0; i < bpmp->threaded.count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned int index = bpmp->soc->channels.thread.offset + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) bpmp, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto cleanup_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* mbox registration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) priv->mbox.client.dev = bpmp->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) priv->mbox.client.rx_callback = mbox_handle_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) priv->mbox.client.tx_block = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) priv->mbox.client.knows_txdone = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (IS_ERR(priv->mbox.channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) err = PTR_ERR(priv->mbox.channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) goto cleanup_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) tegra186_bpmp_channel_reset(bpmp->tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) tegra186_bpmp_channel_reset(bpmp->rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) for (i = 0; i < bpmp->threaded.count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) cleanup_channels:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) for (i = 0; i < bpmp->threaded.count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!bpmp->threaded_channels[i].bpmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) cleanup_tx_channel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) free_rx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) free_tx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct tegra186_bpmp *priv = bpmp->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mbox_free_channel(priv->mbox.channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) for (i = 0; i < bpmp->threaded.count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* reset message channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) tegra186_bpmp_channel_reset(bpmp->tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) tegra186_bpmp_channel_reset(bpmp->rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) for (i = 0; i < bpmp->threaded.count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) const struct tegra_bpmp_ops tegra186_bpmp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .init = tegra186_bpmp_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .deinit = tegra186_bpmp_deinit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .is_response_ready = tegra186_bpmp_is_message_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .is_request_ready = tegra186_bpmp_is_message_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .ack_response = tegra186_bpmp_ack_message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .ack_request = tegra186_bpmp_ack_message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .is_response_channel_free = tegra186_bpmp_is_channel_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .is_request_channel_free = tegra186_bpmp_is_channel_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .post_response = tegra186_bpmp_post_message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .post_request = tegra186_bpmp_post_message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .ring_doorbell = tegra186_bpmp_ring_doorbell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .resume = tegra186_bpmp_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) };