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