0001
0002
0003
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
0118
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
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 };