1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd. 4 * Copyright (C) 2015 Linaro Ltd. 5 * Based on ARM MHU driver by Jassi Brar <jaswinder.singh@linaro.org> 6 * Copyright (C) 2020 ARM Ltd. 7 */ 8 9 #include <linux/amba/bus.h> 10 #include <linux/device.h> 11 #include <linux/err.h> 12 #include <linux/interrupt.h> 13 #include <linux/io.h> 14 #include <linux/kernel.h> 15 #include <linux/mailbox_controller.h> 16 #include <linux/module.h> 17 #include <linux/of.h> 18 19 #define INTR_STAT_OFS 0x0 20 #define INTR_SET_OFS 0x8 21 #define INTR_CLR_OFS 0x10 22 23 #define MHU_LP_OFFSET 0x0 24 #define MHU_HP_OFFSET 0x20 25 #define MHU_SEC_OFFSET 0x200 26 #define TX_REG_OFFSET 0x100 27 28 #define MHU_CHANS 3 /* Secure, Non-Secure High and Low Priority */ 29 #define MHU_CHAN_MAX 20 /* Max channels to save on unused RAM */ 30 #define MHU_NUM_DOORBELLS 32 31 32 struct mhu_db_link { 33 unsigned int irq; 34 void __iomem *tx_reg; 35 void __iomem *rx_reg; 36 }; 37 38 struct arm_mhu { 39 void __iomem *base; 40 struct mhu_db_link mlink[MHU_CHANS]; 41 struct mbox_controller mbox; 42 struct device *dev; 43 }; 44 45 /** 46 * struct mhu_db_channel - ARM MHU Mailbox allocated channel information 47 * 48 * @mhu: Pointer to parent mailbox device 49 * @pchan: Physical channel within which this doorbell resides in 50 * @doorbell: doorbell number pertaining to this channel 51 */ 52 struct mhu_db_channel { 53 struct arm_mhu *mhu; 54 unsigned int pchan; 55 unsigned int doorbell; 56 }; 57 58 static inline struct mbox_chan * 59 mhu_db_mbox_to_channel(struct mbox_controller *mbox, unsigned int pchan, 60 unsigned int doorbell) 61 { 62 int i; 63 struct mhu_db_channel *chan_info; 64 65 for (i = 0; i < mbox->num_chans; i++) { 66 chan_info = mbox->chans[i].con_priv; 67 if (chan_info && chan_info->pchan == pchan && 68 chan_info->doorbell == doorbell) 69 return &mbox->chans[i]; 70 } 71 72 return NULL; 73 } 74 75 static void mhu_db_mbox_clear_irq(struct mbox_chan *chan) 76 { 77 struct mhu_db_channel *chan_info = chan->con_priv; 78 void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].rx_reg; 79 80 writel_relaxed(BIT(chan_info->doorbell), base + INTR_CLR_OFS); 81 } 82 83 static unsigned int mhu_db_mbox_irq_to_pchan_num(struct arm_mhu *mhu, int irq) 84 { 85 unsigned int pchan; 86 87 for (pchan = 0; pchan < MHU_CHANS; pchan++) 88 if (mhu->mlink[pchan].irq == irq) 89 break; 90 return pchan; 91 } 92 93 static struct mbox_chan * 94 mhu_db_mbox_irq_to_channel(struct arm_mhu *mhu, unsigned int pchan) 95 { 96 unsigned long bits; 97 unsigned int doorbell; 98 struct mbox_chan *chan = NULL; 99 struct mbox_controller *mbox = &mhu->mbox; 100 void __iomem *base = mhu->mlink[pchan].rx_reg; 101 102 bits = readl_relaxed(base + INTR_STAT_OFS); 103 if (!bits) 104 /* No IRQs fired in specified physical channel */ 105 return NULL; 106 107 /* An IRQ has fired, find the associated channel */ 108 for (doorbell = 0; bits; doorbell++) { 109 if (!test_and_clear_bit(doorbell, &bits)) 110 continue; 111 112 chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell); 113 if (chan) 114 break; 115 dev_err(mbox->dev, 116 "Channel not registered: pchan: %d doorbell: %d\n", 117 pchan, doorbell); 118 } 119 120 return chan; 121 } 122 123 static irqreturn_t mhu_db_mbox_rx_handler(int irq, void *data) 124 { 125 struct mbox_chan *chan; 126 struct arm_mhu *mhu = data; 127 unsigned int pchan = mhu_db_mbox_irq_to_pchan_num(mhu, irq); 128 129 while (NULL != (chan = mhu_db_mbox_irq_to_channel(mhu, pchan))) { 130 mbox_chan_received_data(chan, NULL); 131 mhu_db_mbox_clear_irq(chan); 132 } 133 134 return IRQ_HANDLED; 135 } 136 137 static bool mhu_db_last_tx_done(struct mbox_chan *chan) 138 { 139 struct mhu_db_channel *chan_info = chan->con_priv; 140 void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; 141 142 if (readl_relaxed(base + INTR_STAT_OFS) & BIT(chan_info->doorbell)) 143 return false; 144 145 return true; 146 } 147 148 static int mhu_db_send_data(struct mbox_chan *chan, void *data) 149 { 150 struct mhu_db_channel *chan_info = chan->con_priv; 151 void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; 152 153 /* Send event to co-processor */ 154 writel_relaxed(BIT(chan_info->doorbell), base + INTR_SET_OFS); 155 156 return 0; 157 } 158 159 static int mhu_db_startup(struct mbox_chan *chan) 160 { 161 mhu_db_mbox_clear_irq(chan); 162 return 0; 163 } 164 165 static void mhu_db_shutdown(struct mbox_chan *chan) 166 { 167 struct mhu_db_channel *chan_info = chan->con_priv; 168 struct mbox_controller *mbox = &chan_info->mhu->mbox; 169 int i; 170 171 for (i = 0; i < mbox->num_chans; i++) 172 if (chan == &mbox->chans[i]) 173 break; 174 175 if (mbox->num_chans == i) { 176 dev_warn(mbox->dev, "Request to free non-existent channel\n"); 177 return; 178 } 179 180 /* Reset channel */ 181 mhu_db_mbox_clear_irq(chan); 182 devm_kfree(mbox->dev, chan->con_priv); 183 chan->con_priv = NULL; 184 } 185 186 static struct mbox_chan *mhu_db_mbox_xlate(struct mbox_controller *mbox, 187 const struct of_phandle_args *spec) 188 { 189 struct arm_mhu *mhu = dev_get_drvdata(mbox->dev); 190 struct mhu_db_channel *chan_info; 191 struct mbox_chan *chan; 192 unsigned int pchan = spec->args[0]; 193 unsigned int doorbell = spec->args[1]; 194 int i; 195 196 /* Bounds checking */ 197 if (pchan >= MHU_CHANS || doorbell >= MHU_NUM_DOORBELLS) { 198 dev_err(mbox->dev, 199 "Invalid channel requested pchan: %d doorbell: %d\n", 200 pchan, doorbell); 201 return ERR_PTR(-EINVAL); 202 } 203 204 /* Is requested channel free? */ 205 chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell); 206 if (chan) { 207 dev_err(mbox->dev, "Channel in use: pchan: %d doorbell: %d\n", 208 pchan, doorbell); 209 return ERR_PTR(-EBUSY); 210 } 211 212 /* Find the first free slot */ 213 for (i = 0; i < mbox->num_chans; i++) 214 if (!mbox->chans[i].con_priv) 215 break; 216 217 if (mbox->num_chans == i) { 218 dev_err(mbox->dev, "No free channels left\n"); 219 return ERR_PTR(-EBUSY); 220 } 221 222 chan = &mbox->chans[i]; 223 224 chan_info = devm_kzalloc(mbox->dev, sizeof(*chan_info), GFP_KERNEL); 225 if (!chan_info) 226 return ERR_PTR(-ENOMEM); 227 228 chan_info->mhu = mhu; 229 chan_info->pchan = pchan; 230 chan_info->doorbell = doorbell; 231 232 chan->con_priv = chan_info; 233 234 dev_dbg(mbox->dev, "mbox: created channel phys: %d doorbell: %d\n", 235 pchan, doorbell); 236 237 return chan; 238 } 239 240 static const struct mbox_chan_ops mhu_db_ops = { 241 .send_data = mhu_db_send_data, 242 .startup = mhu_db_startup, 243 .shutdown = mhu_db_shutdown, 244 .last_tx_done = mhu_db_last_tx_done, 245 }; 246 247 static int mhu_db_probe(struct amba_device *adev, const struct amba_id *id) 248 { 249 u32 cell_count; 250 int i, err, max_chans; 251 struct arm_mhu *mhu; 252 struct mbox_chan *chans; 253 struct device *dev = &adev->dev; 254 struct device_node *np = dev->of_node; 255 int mhu_reg[MHU_CHANS] = { 256 MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET, 257 }; 258 259 if (!of_device_is_compatible(np, "arm,mhu-doorbell")) 260 return -ENODEV; 261 262 err = of_property_read_u32(np, "#mbox-cells", &cell_count); 263 if (err) { 264 dev_err(dev, "failed to read #mbox-cells in '%pOF'\n", np); 265 return err; 266 } 267 268 if (cell_count == 2) { 269 max_chans = MHU_CHAN_MAX; 270 } else { 271 dev_err(dev, "incorrect value of #mbox-cells in '%pOF'\n", np); 272 return -EINVAL; 273 } 274 275 mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); 276 if (!mhu) 277 return -ENOMEM; 278 279 mhu->base = devm_ioremap_resource(dev, &adev->res); 280 if (IS_ERR(mhu->base)) 281 return PTR_ERR(mhu->base); 282 283 chans = devm_kcalloc(dev, max_chans, sizeof(*chans), GFP_KERNEL); 284 if (!chans) 285 return -ENOMEM; 286 287 mhu->dev = dev; 288 mhu->mbox.dev = dev; 289 mhu->mbox.chans = chans; 290 mhu->mbox.num_chans = max_chans; 291 mhu->mbox.txdone_irq = false; 292 mhu->mbox.txdone_poll = true; 293 mhu->mbox.txpoll_period = 1; 294 295 mhu->mbox.of_xlate = mhu_db_mbox_xlate; 296 amba_set_drvdata(adev, mhu); 297 298 mhu->mbox.ops = &mhu_db_ops; 299 300 err = devm_mbox_controller_register(dev, &mhu->mbox); 301 if (err) { 302 dev_err(dev, "Failed to register mailboxes %d\n", err); 303 return err; 304 } 305 306 for (i = 0; i < MHU_CHANS; i++) { 307 int irq = mhu->mlink[i].irq = adev->irq[i]; 308 309 if (irq <= 0) { 310 dev_dbg(dev, "No IRQ found for Channel %d\n", i); 311 continue; 312 } 313 314 mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i]; 315 mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET; 316 317 err = devm_request_threaded_irq(dev, irq, NULL, 318 mhu_db_mbox_rx_handler, 319 IRQF_ONESHOT, "mhu_db_link", mhu); 320 if (err) { 321 dev_err(dev, "Can't claim IRQ %d\n", irq); 322 mbox_controller_unregister(&mhu->mbox); 323 return err; 324 } 325 } 326 327 dev_info(dev, "ARM MHU Doorbell mailbox registered\n"); 328 return 0; 329 } 330 331 static struct amba_id mhu_ids[] = { 332 { 333 .id = 0x1bb098, 334 .mask = 0xffffff, 335 }, 336 { 0, 0 }, 337 }; 338 MODULE_DEVICE_TABLE(amba, mhu_ids); 339 340 static struct amba_driver arm_mhu_db_driver = { 341 .drv = { 342 .name = "mhu-doorbell", 343 }, 344 .id_table = mhu_ids, 345 .probe = mhu_db_probe, 346 }; 347 module_amba_driver(arm_mhu_db_driver); 348 349 MODULE_LICENSE("GPL v2"); 350 MODULE_DESCRIPTION("ARM MHU Doorbell Driver"); 351 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); 352