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/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/slab.h> 17 18 #include "mailbox.h" 19 20 #define MBOX_CHAN_MAX 32 21 22 #define MBOX_RX 0x0 23 #define MBOX_TX 0x1 24 25 #define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x40)) 26 #define MBOX_SRC_REG 0x00 27 #define MBOX_DST_REG 0x04 28 #define MBOX_DCLR_REG 0x08 29 #define MBOX_DSTAT_REG 0x0c 30 #define MBOX_MODE_REG 0x10 31 #define MBOX_IMASK_REG 0x14 32 #define MBOX_ICLR_REG 0x18 33 #define MBOX_SEND_REG 0x1c 34 #define MBOX_DATA_REG 0x20 35 36 #define MBOX_IPC_LOCK_REG 0xa00 37 #define MBOX_IPC_UNLOCK 0x1acce551 38 39 #define MBOX_AUTOMATIC_ACK 1 40 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 8 46 47 /** 48 * struct hi3660_chan_info - Hi3660 mailbox channel information 49 * @dst_irq: Interrupt vector for remote processor 50 * @ack_irq: Interrupt vector for local processor 51 * 52 * A channel can be used for TX or RX, it can trigger remote 53 * processor interrupt to notify remote processor and can receive 54 * interrupt if it has an incoming message. 55 */ 56 struct hi3660_chan_info { 57 unsigned int dst_irq; 58 unsigned int ack_irq; 59 }; 60 61 /** 62 * struct hi3660_mbox - Hi3660 mailbox controller data 63 * @dev: Device to which it is attached 64 * @base: Base address of the register mapping region 65 * @chan: Representation of channels in mailbox controller 66 * @mchan: Representation of channel info 67 * @controller: Representation of a communication channel controller 68 * 69 * Mailbox controller includes 32 channels and can allocate 70 * channel for message transferring. 71 */ 72 struct 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 80 static struct hi3660_mbox *to_hi3660_mbox(struct mbox_controller *mbox) 81 { 82 return container_of(mbox, struct hi3660_mbox, controller); 83 } 84 85 static 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 112 static 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 133 static 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 159 static 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 174 static 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 206 static const struct mbox_chan_ops hi3660_mbox_ops = { 207 .startup = hi3660_mbox_startup, 208 .send_data = hi3660_mbox_send_data, 209 }; 210 211 static 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 230 static const struct of_device_id hi3660_mbox_of_match[] = { 231 { .compatible = "hisilicon,hi3660-mbox", }, 232 {}, 233 }; 234 235 MODULE_DEVICE_TABLE(of, hi3660_mbox_of_match); 236 237 static 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 276 static 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 284 static int __init hi3660_mbox_init(void) 285 { 286 return platform_driver_register(&hi3660_mbox_driver); 287 } 288 core_initcall(hi3660_mbox_init); 289 290 static void __exit hi3660_mbox_exit(void) 291 { 292 platform_driver_unregister(&hi3660_mbox_driver); 293 } 294 module_exit(hi3660_mbox_exit); 295 296 MODULE_LICENSE("GPL"); 297 MODULE_DESCRIPTION("Hisilicon Hi3660 Mailbox Controller"); 298 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); 299