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_ACK BIT(7) 42 43 #define MBOX_MSG_LEN 8 44 45 /** 46 * Hi3660 mailbox channel information 47 * 48 * A channel can be used for TX or RX, it can trigger remote 49 * processor interrupt to notify remote processor and can receive 50 * interrupt if has incoming message. 51 * 52 * @dst_irq: Interrupt vector for remote processor 53 * @ack_irq: Interrupt vector for local processor 54 */ 55 struct hi3660_chan_info { 56 unsigned int dst_irq; 57 unsigned int ack_irq; 58 }; 59 60 /** 61 * Hi3660 mailbox controller data 62 * 63 * Mailbox controller includes 32 channels and can allocate 64 * channel for message transferring. 65 * 66 * @dev: Device to which it is attached 67 * @base: Base address of the register mapping region 68 * @chan: Representation of channels in mailbox controller 69 * @mchan: Representation of channel info 70 * @controller: Representation of a communication channel controller 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 idle so directly bail out */ 95 if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) 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 /* Ensure channel is released */ 107 writel(0xffffffff, base + MBOX_IMASK_REG); 108 writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG); 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_check_state(chan); 164 if (ret) 165 return ret; 166 167 ret = hi3660_mbox_unlock(chan); 168 if (ret) 169 return ret; 170 171 ret = hi3660_mbox_acquire_channel(chan); 172 if (ret) 173 return ret; 174 175 return 0; 176 } 177 178 static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg) 179 { 180 unsigned long ch = (unsigned long)chan->con_priv; 181 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox); 182 struct hi3660_chan_info *mchan = &mbox->mchan[ch]; 183 void __iomem *base = MBOX_BASE(mbox, ch); 184 u32 *buf = msg; 185 unsigned int i; 186 187 /* Ensure channel is released */ 188 writel_relaxed(0xffffffff, base + MBOX_IMASK_REG); 189 writel_relaxed(BIT(mchan->ack_irq), base + MBOX_SRC_REG); 190 191 /* Clear mask for destination interrupt */ 192 writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG); 193 194 /* Config destination for interrupt vector */ 195 writel_relaxed(BIT(mchan->dst_irq), base + MBOX_DST_REG); 196 197 /* Automatic acknowledge mode */ 198 writel_relaxed(MBOX_AUTOMATIC_ACK, base + MBOX_MODE_REG); 199 200 /* Fill message data */ 201 for (i = 0; i < MBOX_MSG_LEN; i++) 202 writel_relaxed(buf[i], base + MBOX_DATA_REG + i * 4); 203 204 /* Trigger data transferring */ 205 writel(BIT(mchan->ack_irq), base + MBOX_SEND_REG); 206 return 0; 207 } 208 209 static struct mbox_chan_ops hi3660_mbox_ops = { 210 .startup = hi3660_mbox_startup, 211 .send_data = hi3660_mbox_send_data, 212 }; 213 214 static struct mbox_chan *hi3660_mbox_xlate(struct mbox_controller *controller, 215 const struct of_phandle_args *spec) 216 { 217 struct hi3660_mbox *mbox = to_hi3660_mbox(controller); 218 struct hi3660_chan_info *mchan; 219 unsigned int ch = spec->args[0]; 220 221 if (ch >= MBOX_CHAN_MAX) { 222 dev_err(mbox->dev, "Invalid channel idx %d\n", ch); 223 return ERR_PTR(-EINVAL); 224 } 225 226 mchan = &mbox->mchan[ch]; 227 mchan->dst_irq = spec->args[1]; 228 mchan->ack_irq = spec->args[2]; 229 230 return &mbox->chan[ch]; 231 } 232 233 static const struct of_device_id hi3660_mbox_of_match[] = { 234 { .compatible = "hisilicon,hi3660-mbox", }, 235 {}, 236 }; 237 238 MODULE_DEVICE_TABLE(of, hi3660_mbox_of_match); 239 240 static int hi3660_mbox_probe(struct platform_device *pdev) 241 { 242 struct device *dev = &pdev->dev; 243 struct hi3660_mbox *mbox; 244 struct mbox_chan *chan; 245 struct resource *res; 246 unsigned long ch; 247 int err; 248 249 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); 250 if (!mbox) 251 return -ENOMEM; 252 253 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 254 mbox->base = devm_ioremap_resource(dev, res); 255 if (IS_ERR(mbox->base)) 256 return PTR_ERR(mbox->base); 257 258 mbox->dev = dev; 259 mbox->controller.dev = dev; 260 mbox->controller.chans = mbox->chan; 261 mbox->controller.num_chans = MBOX_CHAN_MAX; 262 mbox->controller.ops = &hi3660_mbox_ops; 263 mbox->controller.of_xlate = hi3660_mbox_xlate; 264 265 /* Initialize mailbox channel data */ 266 chan = mbox->chan; 267 for (ch = 0; ch < MBOX_CHAN_MAX; ch++) 268 chan[ch].con_priv = (void *)ch; 269 270 err = mbox_controller_register(&mbox->controller); 271 if (err) { 272 dev_err(dev, "Failed to register mailbox %d\n", err); 273 return err; 274 } 275 276 platform_set_drvdata(pdev, mbox); 277 dev_info(dev, "Mailbox enabled\n"); 278 return 0; 279 } 280 281 static int hi3660_mbox_remove(struct platform_device *pdev) 282 { 283 struct hi3660_mbox *mbox = platform_get_drvdata(pdev); 284 285 mbox_controller_unregister(&mbox->controller); 286 return 0; 287 } 288 289 static struct platform_driver hi3660_mbox_driver = { 290 .probe = hi3660_mbox_probe, 291 .remove = hi3660_mbox_remove, 292 .driver = { 293 .name = "hi3660-mbox", 294 .of_match_table = hi3660_mbox_of_match, 295 }, 296 }; 297 298 static int __init hi3660_mbox_init(void) 299 { 300 return platform_driver_register(&hi3660_mbox_driver); 301 } 302 core_initcall(hi3660_mbox_init); 303 304 static void __exit hi3660_mbox_exit(void) 305 { 306 platform_driver_unregister(&hi3660_mbox_driver); 307 } 308 module_exit(hi3660_mbox_exit); 309 310 MODULE_LICENSE("GPL"); 311 MODULE_DESCRIPTION("Hisilicon Hi3660 Mailbox Controller"); 312 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); 313