299 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2017-2018 HiSilicon Limited.3// Copyright (c) 2017-2018 Linaro Limited.4 5#include <linux/bitops.h>6#include <linux/delay.h>7#include <linux/device.h>8#include <linux/err.h>9#include <linux/interrupt.h>10#include <linux/io.h>11#include <linux/iopoll.h>12#include <linux/mailbox_controller.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/slab.h>17 18#include "mailbox.h"19 20#define MBOX_CHAN_MAX 3221 22#define MBOX_RX 0x023#define MBOX_TX 0x124 25#define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x40))26#define MBOX_SRC_REG 0x0027#define MBOX_DST_REG 0x0428#define MBOX_DCLR_REG 0x0829#define MBOX_DSTAT_REG 0x0c30#define MBOX_MODE_REG 0x1031#define MBOX_IMASK_REG 0x1432#define MBOX_ICLR_REG 0x1833#define MBOX_SEND_REG 0x1c34#define MBOX_DATA_REG 0x2035 36#define MBOX_IPC_LOCK_REG 0xa0037#define MBOX_IPC_UNLOCK 0x1acce55138 39#define MBOX_AUTOMATIC_ACK 140 41#define MBOX_STATE_IDLE BIT(4)42#define MBOX_STATE_READY BIT(5)43#define MBOX_STATE_ACK BIT(7)44 45#define MBOX_MSG_LEN 846 47/**48 * struct hi3660_chan_info - Hi3660 mailbox channel information49 * @dst_irq: Interrupt vector for remote processor50 * @ack_irq: Interrupt vector for local processor51 *52 * A channel can be used for TX or RX, it can trigger remote53 * processor interrupt to notify remote processor and can receive54 * interrupt if it has an incoming message.55 */56struct hi3660_chan_info {57 unsigned int dst_irq;58 unsigned int ack_irq;59};60 61/**62 * struct hi3660_mbox - Hi3660 mailbox controller data63 * @dev: Device to which it is attached64 * @base: Base address of the register mapping region65 * @chan: Representation of channels in mailbox controller66 * @mchan: Representation of channel info67 * @controller: Representation of a communication channel controller68 *69 * Mailbox controller includes 32 channels and can allocate70 * channel for message transferring.71 */72struct hi3660_mbox {73 struct device *dev;74 void __iomem *base;75 struct mbox_chan chan[MBOX_CHAN_MAX];76 struct hi3660_chan_info mchan[MBOX_CHAN_MAX];77 struct mbox_controller controller;78};79 80static struct hi3660_mbox *to_hi3660_mbox(struct mbox_controller *mbox)81{82 return container_of(mbox, struct hi3660_mbox, controller);83}84 85static int hi3660_mbox_check_state(struct mbox_chan *chan)86{87 unsigned long ch = (unsigned long)chan->con_priv;88 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);89 struct hi3660_chan_info *mchan = &mbox->mchan[ch];90 void __iomem *base = MBOX_BASE(mbox, ch);91 unsigned long val;92 unsigned int ret;93 94 /* Mailbox is ready to use */95 if (readl(base + MBOX_MODE_REG) & MBOX_STATE_READY)96 return 0;97 98 /* Wait for acknowledge from remote */99 ret = readx_poll_timeout_atomic(readl, base + MBOX_MODE_REG,100 val, (val & MBOX_STATE_ACK), 1000, 300000);101 if (ret) {102 dev_err(mbox->dev, "%s: timeout for receiving ack\n", __func__);103 return ret;104 }105 106 /* clear ack state, mailbox will get back to ready state */107 writel(BIT(mchan->ack_irq), base + MBOX_ICLR_REG);108 109 return 0;110}111 112static int hi3660_mbox_unlock(struct mbox_chan *chan)113{114 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);115 unsigned int val, retry = 3;116 117 do {118 writel(MBOX_IPC_UNLOCK, mbox->base + MBOX_IPC_LOCK_REG);119 120 val = readl(mbox->base + MBOX_IPC_LOCK_REG);121 if (!val)122 break;123 124 udelay(10);125 } while (retry--);126 127 if (val)128 dev_err(mbox->dev, "%s: failed to unlock mailbox\n", __func__);129 130 return (!val) ? 0 : -ETIMEDOUT;131}132 133static int hi3660_mbox_acquire_channel(struct mbox_chan *chan)134{135 unsigned long ch = (unsigned long)chan->con_priv;136 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);137 struct hi3660_chan_info *mchan = &mbox->mchan[ch];138 void __iomem *base = MBOX_BASE(mbox, ch);139 unsigned int val, retry;140 141 for (retry = 10; retry; retry--) {142 /* Check if channel is in idle state */143 if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) {144 writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG);145 146 /* Check ack bit has been set successfully */147 val = readl(base + MBOX_SRC_REG);148 if (val & BIT(mchan->ack_irq))149 break;150 }151 }152 153 if (!retry)154 dev_err(mbox->dev, "%s: failed to acquire channel\n", __func__);155 156 return retry ? 0 : -ETIMEDOUT;157}158 159static int hi3660_mbox_startup(struct mbox_chan *chan)160{161 int ret;162 163 ret = hi3660_mbox_unlock(chan);164 if (ret)165 return ret;166 167 ret = hi3660_mbox_acquire_channel(chan);168 if (ret)169 return ret;170 171 return 0;172}173 174static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)175{176 unsigned long ch = (unsigned long)chan->con_priv;177 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);178 struct hi3660_chan_info *mchan = &mbox->mchan[ch];179 void __iomem *base = MBOX_BASE(mbox, ch);180 u32 *buf = msg;181 unsigned int i;182 int ret;183 184 ret = hi3660_mbox_check_state(chan);185 if (ret)186 return ret;187 188 /* Clear mask for destination interrupt */189 writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG);190 191 /* Config destination for interrupt vector */192 writel_relaxed(BIT(mchan->dst_irq), base + MBOX_DST_REG);193 194 /* Automatic acknowledge mode */195 writel_relaxed(MBOX_AUTOMATIC_ACK, base + MBOX_MODE_REG);196 197 /* Fill message data */198 for (i = 0; i < MBOX_MSG_LEN; i++)199 writel_relaxed(buf[i], base + MBOX_DATA_REG + i * 4);200 201 /* Trigger data transferring */202 writel(BIT(mchan->ack_irq), base + MBOX_SEND_REG);203 return 0;204}205 206static const struct mbox_chan_ops hi3660_mbox_ops = {207 .startup = hi3660_mbox_startup,208 .send_data = hi3660_mbox_send_data,209};210 211static struct mbox_chan *hi3660_mbox_xlate(struct mbox_controller *controller,212 const struct of_phandle_args *spec)213{214 struct hi3660_mbox *mbox = to_hi3660_mbox(controller);215 struct hi3660_chan_info *mchan;216 unsigned int ch = spec->args[0];217 218 if (ch >= MBOX_CHAN_MAX) {219 dev_err(mbox->dev, "Invalid channel idx %d\n", ch);220 return ERR_PTR(-EINVAL);221 }222 223 mchan = &mbox->mchan[ch];224 mchan->dst_irq = spec->args[1];225 mchan->ack_irq = spec->args[2];226 227 return &mbox->chan[ch];228}229 230static const struct of_device_id hi3660_mbox_of_match[] = {231 { .compatible = "hisilicon,hi3660-mbox", },232 {},233};234 235MODULE_DEVICE_TABLE(of, hi3660_mbox_of_match);236 237static int hi3660_mbox_probe(struct platform_device *pdev)238{239 struct device *dev = &pdev->dev;240 struct hi3660_mbox *mbox;241 struct mbox_chan *chan;242 unsigned long ch;243 int err;244 245 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);246 if (!mbox)247 return -ENOMEM;248 249 mbox->base = devm_platform_ioremap_resource(pdev, 0);250 if (IS_ERR(mbox->base))251 return PTR_ERR(mbox->base);252 253 mbox->dev = dev;254 mbox->controller.dev = dev;255 mbox->controller.chans = mbox->chan;256 mbox->controller.num_chans = MBOX_CHAN_MAX;257 mbox->controller.ops = &hi3660_mbox_ops;258 mbox->controller.of_xlate = hi3660_mbox_xlate;259 260 /* Initialize mailbox channel data */261 chan = mbox->chan;262 for (ch = 0; ch < MBOX_CHAN_MAX; ch++)263 chan[ch].con_priv = (void *)ch;264 265 err = devm_mbox_controller_register(dev, &mbox->controller);266 if (err) {267 dev_err(dev, "Failed to register mailbox %d\n", err);268 return err;269 }270 271 platform_set_drvdata(pdev, mbox);272 dev_info(dev, "Mailbox enabled\n");273 return 0;274}275 276static struct platform_driver hi3660_mbox_driver = {277 .probe = hi3660_mbox_probe,278 .driver = {279 .name = "hi3660-mbox",280 .of_match_table = hi3660_mbox_of_match,281 },282};283 284static int __init hi3660_mbox_init(void)285{286 return platform_driver_register(&hi3660_mbox_driver);287}288core_initcall(hi3660_mbox_init);289 290static void __exit hi3660_mbox_exit(void)291{292 platform_driver_unregister(&hi3660_mbox_driver);293}294module_exit(hi3660_mbox_exit);295 296MODULE_LICENSE("GPL");297MODULE_DESCRIPTION("Hisilicon Hi3660 Mailbox Controller");298MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");299