Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018, NVIDIA CORPORATION.
0004  */
0005 
0006 #include <linux/genalloc.h>
0007 #include <linux/mailbox_client.h>
0008 #include <linux/platform_device.h>
0009 
0010 #include <soc/tegra/bpmp.h>
0011 #include <soc/tegra/bpmp-abi.h>
0012 #include <soc/tegra/ivc.h>
0013 
0014 #include "bpmp-private.h"
0015 
0016 struct tegra186_bpmp {
0017     struct tegra_bpmp *parent;
0018 
0019     struct {
0020         struct gen_pool *pool;
0021         dma_addr_t phys;
0022         void *virt;
0023     } tx, rx;
0024 
0025     struct {
0026         struct mbox_client client;
0027         struct mbox_chan *channel;
0028     } mbox;
0029 };
0030 
0031 static inline struct tegra_bpmp *
0032 mbox_client_to_bpmp(struct mbox_client *client)
0033 {
0034     struct tegra186_bpmp *priv;
0035 
0036     priv = container_of(client, struct tegra186_bpmp, mbox.client);
0037 
0038     return priv->parent;
0039 }
0040 
0041 static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
0042 {
0043     void *frame;
0044 
0045     frame = tegra_ivc_read_get_next_frame(channel->ivc);
0046     if (IS_ERR(frame)) {
0047         channel->ib = NULL;
0048         return false;
0049     }
0050 
0051     channel->ib = frame;
0052 
0053     return true;
0054 }
0055 
0056 static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
0057 {
0058     void *frame;
0059 
0060     frame = tegra_ivc_write_get_next_frame(channel->ivc);
0061     if (IS_ERR(frame)) {
0062         channel->ob = NULL;
0063         return false;
0064     }
0065 
0066     channel->ob = frame;
0067 
0068     return true;
0069 }
0070 
0071 static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
0072 {
0073     return tegra_ivc_read_advance(channel->ivc);
0074 }
0075 
0076 static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
0077 {
0078     return tegra_ivc_write_advance(channel->ivc);
0079 }
0080 
0081 static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
0082 {
0083     struct tegra186_bpmp *priv = bpmp->priv;
0084     int err;
0085 
0086     err = mbox_send_message(priv->mbox.channel, NULL);
0087     if (err < 0)
0088         return err;
0089 
0090     mbox_client_txdone(priv->mbox.channel, 0);
0091 
0092     return 0;
0093 }
0094 
0095 static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
0096 {
0097     struct tegra_bpmp *bpmp = data;
0098     struct tegra186_bpmp *priv = bpmp->priv;
0099 
0100     if (WARN_ON(priv->mbox.channel == NULL))
0101         return;
0102 
0103     tegra186_bpmp_ring_doorbell(bpmp);
0104 }
0105 
0106 static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
0107                       struct tegra_bpmp *bpmp,
0108                       unsigned int index)
0109 {
0110     struct tegra186_bpmp *priv = bpmp->priv;
0111     size_t message_size, queue_size;
0112     unsigned int offset;
0113     int err;
0114 
0115     channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
0116                     GFP_KERNEL);
0117     if (!channel->ivc)
0118         return -ENOMEM;
0119 
0120     message_size = tegra_ivc_align(MSG_MIN_SZ);
0121     queue_size = tegra_ivc_total_queue_size(message_size);
0122     offset = queue_size * index;
0123 
0124     err = tegra_ivc_init(channel->ivc, NULL,
0125                  priv->rx.virt + offset, priv->rx.phys + offset,
0126                  priv->tx.virt + offset, priv->tx.phys + offset,
0127                  1, message_size, tegra186_bpmp_ivc_notify,
0128                  bpmp);
0129     if (err < 0) {
0130         dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
0131             index, err);
0132         return err;
0133     }
0134 
0135     init_completion(&channel->completion);
0136     channel->bpmp = bpmp;
0137 
0138     return 0;
0139 }
0140 
0141 static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
0142 {
0143     /* reset the channel state */
0144     tegra_ivc_reset(channel->ivc);
0145 
0146     /* sync the channel state with BPMP */
0147     while (tegra_ivc_notified(channel->ivc))
0148         ;
0149 }
0150 
0151 static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
0152 {
0153     tegra_ivc_cleanup(channel->ivc);
0154 }
0155 
0156 static void mbox_handle_rx(struct mbox_client *client, void *data)
0157 {
0158     struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
0159 
0160     tegra_bpmp_handle_rx(bpmp);
0161 }
0162 
0163 static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
0164 {
0165     struct tegra186_bpmp *priv;
0166     unsigned int i;
0167     int err;
0168 
0169     priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
0170     if (!priv)
0171         return -ENOMEM;
0172 
0173     bpmp->priv = priv;
0174     priv->parent = bpmp;
0175 
0176     priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
0177     if (!priv->tx.pool) {
0178         dev_err(bpmp->dev, "TX shmem pool not found\n");
0179         return -EPROBE_DEFER;
0180     }
0181 
0182     priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
0183     if (!priv->tx.virt) {
0184         dev_err(bpmp->dev, "failed to allocate from TX pool\n");
0185         return -ENOMEM;
0186     }
0187 
0188     priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
0189     if (!priv->rx.pool) {
0190         dev_err(bpmp->dev, "RX shmem pool not found\n");
0191         err = -EPROBE_DEFER;
0192         goto free_tx;
0193     }
0194 
0195     priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
0196     if (!priv->rx.virt) {
0197         dev_err(bpmp->dev, "failed to allocate from RX pool\n");
0198         err = -ENOMEM;
0199         goto free_tx;
0200     }
0201 
0202     err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
0203                      bpmp->soc->channels.cpu_tx.offset);
0204     if (err < 0)
0205         goto free_rx;
0206 
0207     err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
0208                      bpmp->soc->channels.cpu_rx.offset);
0209     if (err < 0)
0210         goto cleanup_tx_channel;
0211 
0212     for (i = 0; i < bpmp->threaded.count; i++) {
0213         unsigned int index = bpmp->soc->channels.thread.offset + i;
0214 
0215         err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
0216                          bpmp, index);
0217         if (err < 0)
0218             goto cleanup_channels;
0219     }
0220 
0221     /* mbox registration */
0222     priv->mbox.client.dev = bpmp->dev;
0223     priv->mbox.client.rx_callback = mbox_handle_rx;
0224     priv->mbox.client.tx_block = false;
0225     priv->mbox.client.knows_txdone = false;
0226 
0227     priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
0228     if (IS_ERR(priv->mbox.channel)) {
0229         err = PTR_ERR(priv->mbox.channel);
0230         dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
0231         goto cleanup_channels;
0232     }
0233 
0234     tegra186_bpmp_channel_reset(bpmp->tx_channel);
0235     tegra186_bpmp_channel_reset(bpmp->rx_channel);
0236 
0237     for (i = 0; i < bpmp->threaded.count; i++)
0238         tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
0239 
0240     return 0;
0241 
0242 cleanup_channels:
0243     for (i = 0; i < bpmp->threaded.count; i++) {
0244         if (!bpmp->threaded_channels[i].bpmp)
0245             continue;
0246 
0247         tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
0248     }
0249 
0250     tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
0251 cleanup_tx_channel:
0252     tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
0253 free_rx:
0254     gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
0255 free_tx:
0256     gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
0257 
0258     return err;
0259 }
0260 
0261 static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
0262 {
0263     struct tegra186_bpmp *priv = bpmp->priv;
0264     unsigned int i;
0265 
0266     mbox_free_channel(priv->mbox.channel);
0267 
0268     for (i = 0; i < bpmp->threaded.count; i++)
0269         tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
0270 
0271     tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
0272     tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
0273 
0274     gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
0275     gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
0276 }
0277 
0278 static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
0279 {
0280     unsigned int i;
0281 
0282     /* reset message channels */
0283     tegra186_bpmp_channel_reset(bpmp->tx_channel);
0284     tegra186_bpmp_channel_reset(bpmp->rx_channel);
0285 
0286     for (i = 0; i < bpmp->threaded.count; i++)
0287         tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
0288 
0289     return 0;
0290 }
0291 
0292 const struct tegra_bpmp_ops tegra186_bpmp_ops = {
0293     .init = tegra186_bpmp_init,
0294     .deinit = tegra186_bpmp_deinit,
0295     .is_response_ready = tegra186_bpmp_is_message_ready,
0296     .is_request_ready = tegra186_bpmp_is_message_ready,
0297     .ack_response = tegra186_bpmp_ack_message,
0298     .ack_request = tegra186_bpmp_ack_message,
0299     .is_response_channel_free = tegra186_bpmp_is_channel_free,
0300     .is_request_channel_free = tegra186_bpmp_is_channel_free,
0301     .post_response = tegra186_bpmp_post_message,
0302     .post_request = tegra186_bpmp_post_message,
0303     .ring_doorbell = tegra186_bpmp_ring_doorbell,
0304     .resume = tegra186_bpmp_resume,
0305 };