1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright Altera Corporation (C) 2013-2014. All rights reserved 4 */ 5 6 #include <linux/device.h> 7 #include <linux/interrupt.h> 8 #include <linux/io.h> 9 #include <linux/kernel.h> 10 #include <linux/mailbox_controller.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/platform_device.h> 14 15 #define DRIVER_NAME "altera-mailbox" 16 17 #define MAILBOX_CMD_REG 0x00 18 #define MAILBOX_PTR_REG 0x04 19 #define MAILBOX_STS_REG 0x08 20 #define MAILBOX_INTMASK_REG 0x0C 21 22 #define INT_PENDING_MSK 0x1 23 #define INT_SPACE_MSK 0x2 24 25 #define STS_PENDING_MSK 0x1 26 #define STS_FULL_MSK 0x2 27 #define STS_FULL_OFT 0x1 28 29 #define MBOX_PENDING(status) (((status) & STS_PENDING_MSK)) 30 #define MBOX_FULL(status) (((status) & STS_FULL_MSK) >> STS_FULL_OFT) 31 32 enum altera_mbox_msg { 33 MBOX_CMD = 0, 34 MBOX_PTR, 35 }; 36 37 #define MBOX_POLLING_MS 5 /* polling interval 5ms */ 38 39 struct altera_mbox { 40 bool is_sender; /* 1-sender, 0-receiver */ 41 bool intr_mode; 42 int irq; 43 void __iomem *mbox_base; 44 struct device *dev; 45 struct mbox_controller controller; 46 47 /* If the controller supports only RX polling mode */ 48 struct timer_list rxpoll_timer; 49 struct mbox_chan *chan; 50 }; 51 52 static struct altera_mbox *mbox_chan_to_altera_mbox(struct mbox_chan *chan) 53 { 54 if (!chan || !chan->con_priv) 55 return NULL; 56 57 return (struct altera_mbox *)chan->con_priv; 58 } 59 60 static inline int altera_mbox_full(struct altera_mbox *mbox) 61 { 62 u32 status; 63 64 status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG); 65 return MBOX_FULL(status); 66 } 67 68 static inline int altera_mbox_pending(struct altera_mbox *mbox) 69 { 70 u32 status; 71 72 status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG); 73 return MBOX_PENDING(status); 74 } 75 76 static void altera_mbox_rx_intmask(struct altera_mbox *mbox, bool enable) 77 { 78 u32 mask; 79 80 mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG); 81 if (enable) 82 mask |= INT_PENDING_MSK; 83 else 84 mask &= ~INT_PENDING_MSK; 85 writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG); 86 } 87 88 static void altera_mbox_tx_intmask(struct altera_mbox *mbox, bool enable) 89 { 90 u32 mask; 91 92 mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG); 93 if (enable) 94 mask |= INT_SPACE_MSK; 95 else 96 mask &= ~INT_SPACE_MSK; 97 writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG); 98 } 99 100 static bool altera_mbox_is_sender(struct altera_mbox *mbox) 101 { 102 u32 reg; 103 /* Write a magic number to PTR register and read back this register. 104 * This register is read-write if it is a sender. 105 */ 106 #define MBOX_MAGIC 0xA5A5AA55 107 writel_relaxed(MBOX_MAGIC, mbox->mbox_base + MAILBOX_PTR_REG); 108 reg = readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG); 109 if (reg == MBOX_MAGIC) { 110 /* Clear to 0 */ 111 writel_relaxed(0, mbox->mbox_base + MAILBOX_PTR_REG); 112 return true; 113 } 114 return false; 115 } 116 117 static void altera_mbox_rx_data(struct mbox_chan *chan) 118 { 119 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 120 u32 data[2]; 121 122 if (altera_mbox_pending(mbox)) { 123 data[MBOX_PTR] = 124 readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG); 125 data[MBOX_CMD] = 126 readl_relaxed(mbox->mbox_base + MAILBOX_CMD_REG); 127 mbox_chan_received_data(chan, (void *)data); 128 } 129 } 130 131 static void altera_mbox_poll_rx(struct timer_list *t) 132 { 133 struct altera_mbox *mbox = from_timer(mbox, t, rxpoll_timer); 134 135 altera_mbox_rx_data(mbox->chan); 136 137 mod_timer(&mbox->rxpoll_timer, 138 jiffies + msecs_to_jiffies(MBOX_POLLING_MS)); 139 } 140 141 static irqreturn_t altera_mbox_tx_interrupt(int irq, void *p) 142 { 143 struct mbox_chan *chan = (struct mbox_chan *)p; 144 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 145 146 altera_mbox_tx_intmask(mbox, false); 147 mbox_chan_txdone(chan, 0); 148 149 return IRQ_HANDLED; 150 } 151 152 static irqreturn_t altera_mbox_rx_interrupt(int irq, void *p) 153 { 154 struct mbox_chan *chan = (struct mbox_chan *)p; 155 156 altera_mbox_rx_data(chan); 157 return IRQ_HANDLED; 158 } 159 160 static int altera_mbox_startup_sender(struct mbox_chan *chan) 161 { 162 int ret; 163 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 164 165 if (mbox->intr_mode) { 166 ret = request_irq(mbox->irq, altera_mbox_tx_interrupt, 0, 167 DRIVER_NAME, chan); 168 if (unlikely(ret)) { 169 dev_err(mbox->dev, 170 "failed to register mailbox interrupt:%d\n", 171 ret); 172 return ret; 173 } 174 } 175 176 return 0; 177 } 178 179 static int altera_mbox_startup_receiver(struct mbox_chan *chan) 180 { 181 int ret; 182 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 183 184 if (mbox->intr_mode) { 185 ret = request_irq(mbox->irq, altera_mbox_rx_interrupt, 0, 186 DRIVER_NAME, chan); 187 if (unlikely(ret)) { 188 mbox->intr_mode = false; 189 goto polling; /* use polling if failed */ 190 } 191 192 altera_mbox_rx_intmask(mbox, true); 193 return 0; 194 } 195 196 polling: 197 /* Setup polling timer */ 198 mbox->chan = chan; 199 timer_setup(&mbox->rxpoll_timer, altera_mbox_poll_rx, 0); 200 mod_timer(&mbox->rxpoll_timer, 201 jiffies + msecs_to_jiffies(MBOX_POLLING_MS)); 202 203 return 0; 204 } 205 206 static int altera_mbox_send_data(struct mbox_chan *chan, void *data) 207 { 208 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 209 u32 *udata = (u32 *)data; 210 211 if (!mbox || !data) 212 return -EINVAL; 213 if (!mbox->is_sender) { 214 dev_warn(mbox->dev, 215 "failed to send. This is receiver mailbox.\n"); 216 return -EINVAL; 217 } 218 219 if (altera_mbox_full(mbox)) 220 return -EBUSY; 221 222 /* Enable interrupt before send */ 223 if (mbox->intr_mode) 224 altera_mbox_tx_intmask(mbox, true); 225 226 /* Pointer register must write before command register */ 227 writel_relaxed(udata[MBOX_PTR], mbox->mbox_base + MAILBOX_PTR_REG); 228 writel_relaxed(udata[MBOX_CMD], mbox->mbox_base + MAILBOX_CMD_REG); 229 230 return 0; 231 } 232 233 static bool altera_mbox_last_tx_done(struct mbox_chan *chan) 234 { 235 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 236 237 /* Return false if mailbox is full */ 238 return altera_mbox_full(mbox) ? false : true; 239 } 240 241 static bool altera_mbox_peek_data(struct mbox_chan *chan) 242 { 243 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 244 245 return altera_mbox_pending(mbox) ? true : false; 246 } 247 248 static int altera_mbox_startup(struct mbox_chan *chan) 249 { 250 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 251 int ret = 0; 252 253 if (!mbox) 254 return -EINVAL; 255 256 if (mbox->is_sender) 257 ret = altera_mbox_startup_sender(chan); 258 else 259 ret = altera_mbox_startup_receiver(chan); 260 261 return ret; 262 } 263 264 static void altera_mbox_shutdown(struct mbox_chan *chan) 265 { 266 struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan); 267 268 if (mbox->intr_mode) { 269 /* Unmask all interrupt masks */ 270 writel_relaxed(~0, mbox->mbox_base + MAILBOX_INTMASK_REG); 271 free_irq(mbox->irq, chan); 272 } else if (!mbox->is_sender) { 273 del_timer_sync(&mbox->rxpoll_timer); 274 } 275 } 276 277 static const struct mbox_chan_ops altera_mbox_ops = { 278 .send_data = altera_mbox_send_data, 279 .startup = altera_mbox_startup, 280 .shutdown = altera_mbox_shutdown, 281 .last_tx_done = altera_mbox_last_tx_done, 282 .peek_data = altera_mbox_peek_data, 283 }; 284 285 static int altera_mbox_probe(struct platform_device *pdev) 286 { 287 struct altera_mbox *mbox; 288 struct mbox_chan *chans; 289 int ret; 290 291 mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), 292 GFP_KERNEL); 293 if (!mbox) 294 return -ENOMEM; 295 296 /* Allocated one channel */ 297 chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); 298 if (!chans) 299 return -ENOMEM; 300 301 mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0); 302 if (IS_ERR(mbox->mbox_base)) 303 return PTR_ERR(mbox->mbox_base); 304 305 /* Check is it a sender or receiver? */ 306 mbox->is_sender = altera_mbox_is_sender(mbox); 307 308 mbox->irq = platform_get_irq(pdev, 0); 309 if (mbox->irq >= 0) 310 mbox->intr_mode = true; 311 312 mbox->dev = &pdev->dev; 313 314 /* Hardware supports only one channel. */ 315 chans[0].con_priv = mbox; 316 mbox->controller.dev = mbox->dev; 317 mbox->controller.num_chans = 1; 318 mbox->controller.chans = chans; 319 mbox->controller.ops = &altera_mbox_ops; 320 321 if (mbox->is_sender) { 322 if (mbox->intr_mode) { 323 mbox->controller.txdone_irq = true; 324 } else { 325 mbox->controller.txdone_poll = true; 326 mbox->controller.txpoll_period = MBOX_POLLING_MS; 327 } 328 } 329 330 ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller); 331 if (ret) { 332 dev_err(&pdev->dev, "Register mailbox failed\n"); 333 goto err; 334 } 335 336 platform_set_drvdata(pdev, mbox); 337 err: 338 return ret; 339 } 340 341 static const struct of_device_id altera_mbox_match[] = { 342 { .compatible = "altr,mailbox-1.0" }, 343 { /* Sentinel */ } 344 }; 345 346 MODULE_DEVICE_TABLE(of, altera_mbox_match); 347 348 static struct platform_driver altera_mbox_driver = { 349 .probe = altera_mbox_probe, 350 .driver = { 351 .name = DRIVER_NAME, 352 .of_match_table = altera_mbox_match, 353 }, 354 }; 355 356 module_platform_driver(altera_mbox_driver); 357 358 MODULE_LICENSE("GPL v2"); 359 MODULE_DESCRIPTION("Altera mailbox specific functions"); 360 MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); 361 MODULE_ALIAS("platform:altera-mailbox"); 362