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