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/interrupt.h>
0007 #include <linux/irq.h>
0008 #include <linux/io.h>
0009 #include <linux/of.h>
0010 #include <linux/platform_device.h>
0011 
0012 #include <soc/tegra/bpmp.h>
0013 
0014 #include "bpmp-private.h"
0015 
0016 #define TRIGGER_OFFSET      0x000
0017 #define RESULT_OFFSET(id)   (0xc00 + id * 4)
0018 #define TRIGGER_ID_SHIFT    16
0019 #define TRIGGER_CMD_GET     4
0020 
0021 #define STA_OFFSET      0
0022 #define SET_OFFSET      4
0023 #define CLR_OFFSET      8
0024 
0025 #define CH_MASK(ch) (0x3 << ((ch) * 2))
0026 #define SL_SIGL(ch) (0x0 << ((ch) * 2))
0027 #define SL_QUED(ch) (0x1 << ((ch) * 2))
0028 #define MA_FREE(ch) (0x2 << ((ch) * 2))
0029 #define MA_ACKD(ch) (0x3 << ((ch) * 2))
0030 
0031 struct tegra210_bpmp {
0032     void __iomem *atomics;
0033     void __iomem *arb_sema;
0034     struct irq_data *tx_irq_data;
0035 };
0036 
0037 static u32 bpmp_channel_status(struct tegra_bpmp *bpmp, unsigned int index)
0038 {
0039     struct tegra210_bpmp *priv = bpmp->priv;
0040 
0041     return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(index);
0042 }
0043 
0044 static bool tegra210_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
0045 {
0046     unsigned int index = channel->index;
0047 
0048     return bpmp_channel_status(channel->bpmp, index) == MA_ACKD(index);
0049 }
0050 
0051 static bool tegra210_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
0052 {
0053     unsigned int index = channel->index;
0054 
0055     return bpmp_channel_status(channel->bpmp, index) == SL_SIGL(index);
0056 }
0057 
0058 static bool
0059 tegra210_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
0060 {
0061     unsigned int index = channel->index;
0062 
0063     return bpmp_channel_status(channel->bpmp, index) == MA_FREE(index);
0064 }
0065 
0066 static bool
0067 tegra210_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
0068 {
0069     unsigned int index = channel->index;
0070 
0071     return bpmp_channel_status(channel->bpmp, index) == SL_QUED(index);
0072 }
0073 
0074 static int tegra210_bpmp_post_request(struct tegra_bpmp_channel *channel)
0075 {
0076     struct tegra210_bpmp *priv = channel->bpmp->priv;
0077 
0078     __raw_writel(CH_MASK(channel->index), priv->arb_sema + CLR_OFFSET);
0079 
0080     return 0;
0081 }
0082 
0083 static int tegra210_bpmp_post_response(struct tegra_bpmp_channel *channel)
0084 {
0085     struct tegra210_bpmp *priv = channel->bpmp->priv;
0086 
0087     __raw_writel(MA_ACKD(channel->index), priv->arb_sema + SET_OFFSET);
0088 
0089     return 0;
0090 }
0091 
0092 static int tegra210_bpmp_ack_response(struct tegra_bpmp_channel *channel)
0093 {
0094     struct tegra210_bpmp *priv = channel->bpmp->priv;
0095 
0096     __raw_writel(MA_ACKD(channel->index) ^ MA_FREE(channel->index),
0097              priv->arb_sema + CLR_OFFSET);
0098 
0099     return 0;
0100 }
0101 
0102 static int tegra210_bpmp_ack_request(struct tegra_bpmp_channel *channel)
0103 {
0104     struct tegra210_bpmp *priv = channel->bpmp->priv;
0105 
0106     __raw_writel(SL_QUED(channel->index), priv->arb_sema + SET_OFFSET);
0107 
0108     return 0;
0109 }
0110 
0111 static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
0112 {
0113     struct tegra210_bpmp *priv = bpmp->priv;
0114     struct irq_data *irq_data = priv->tx_irq_data;
0115 
0116     /*
0117      * Tegra Legacy Interrupt Controller (LIC) is used to notify BPMP of
0118      * available messages
0119      */
0120     if (irq_data->chip->irq_retrigger)
0121         return irq_data->chip->irq_retrigger(irq_data);
0122 
0123     return -EINVAL;
0124 }
0125 
0126 static irqreturn_t rx_irq(int irq, void *data)
0127 {
0128     struct tegra_bpmp *bpmp = data;
0129 
0130     tegra_bpmp_handle_rx(bpmp);
0131 
0132     return IRQ_HANDLED;
0133 }
0134 
0135 static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
0136                       struct tegra_bpmp *bpmp,
0137                       unsigned int index)
0138 {
0139     struct tegra210_bpmp *priv = bpmp->priv;
0140     u32 address;
0141     void *p;
0142 
0143     /* Retrieve channel base address from BPMP */
0144     writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
0145            priv->atomics + TRIGGER_OFFSET);
0146     address = readl(priv->atomics + RESULT_OFFSET(index));
0147 
0148     p = devm_ioremap(bpmp->dev, address, 0x80);
0149     if (!p)
0150         return -ENOMEM;
0151 
0152     channel->ib = p;
0153     channel->ob = p;
0154     channel->index = index;
0155     init_completion(&channel->completion);
0156     channel->bpmp = bpmp;
0157 
0158     return 0;
0159 }
0160 
0161 static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
0162 {
0163     struct platform_device *pdev = to_platform_device(bpmp->dev);
0164     struct tegra210_bpmp *priv;
0165     unsigned int i;
0166     int err;
0167 
0168     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0169     if (!priv)
0170         return -ENOMEM;
0171 
0172     bpmp->priv = priv;
0173 
0174     priv->atomics = devm_platform_ioremap_resource(pdev, 0);
0175     if (IS_ERR(priv->atomics))
0176         return PTR_ERR(priv->atomics);
0177 
0178     priv->arb_sema = devm_platform_ioremap_resource(pdev, 1);
0179     if (IS_ERR(priv->arb_sema))
0180         return PTR_ERR(priv->arb_sema);
0181 
0182     err = tegra210_bpmp_channel_init(bpmp->tx_channel, bpmp,
0183                      bpmp->soc->channels.cpu_tx.offset);
0184     if (err < 0)
0185         return err;
0186 
0187     err = tegra210_bpmp_channel_init(bpmp->rx_channel, bpmp,
0188                      bpmp->soc->channels.cpu_rx.offset);
0189     if (err < 0)
0190         return err;
0191 
0192     for (i = 0; i < bpmp->threaded.count; i++) {
0193         unsigned int index = bpmp->soc->channels.thread.offset + i;
0194 
0195         err = tegra210_bpmp_channel_init(&bpmp->threaded_channels[i],
0196                          bpmp, index);
0197         if (err < 0)
0198             return err;
0199     }
0200 
0201     err = platform_get_irq_byname(pdev, "tx");
0202     if (err < 0) {
0203         dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
0204         return err;
0205     }
0206 
0207     priv->tx_irq_data = irq_get_irq_data(err);
0208     if (!priv->tx_irq_data) {
0209         dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
0210         return -ENOENT;
0211     }
0212 
0213     err = platform_get_irq_byname(pdev, "rx");
0214     if (err < 0) {
0215         dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
0216         return err;
0217     }
0218 
0219     err = devm_request_irq(&pdev->dev, err, rx_irq,
0220                    IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
0221     if (err < 0) {
0222         dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
0223         return err;
0224     }
0225 
0226     return 0;
0227 }
0228 
0229 const struct tegra_bpmp_ops tegra210_bpmp_ops = {
0230     .init = tegra210_bpmp_init,
0231     .is_response_ready = tegra210_bpmp_is_response_ready,
0232     .is_request_ready = tegra210_bpmp_is_request_ready,
0233     .ack_response = tegra210_bpmp_ack_response,
0234     .ack_request = tegra210_bpmp_ack_request,
0235     .is_response_channel_free = tegra210_bpmp_is_response_channel_free,
0236     .is_request_channel_free = tegra210_bpmp_is_request_channel_free,
0237     .post_response = tegra210_bpmp_post_response,
0238     .post_request = tegra210_bpmp_post_request,
0239     .ring_doorbell = tegra210_bpmp_ring_doorbell,
0240 };