Lines Matching +full:parent +full:- +full:interrupt +full:- +full:base
1 // SPDX-License-Identifier: GPL-2.0-only
13 #include <linux/interrupt.h>
57 * - direction: tx or rx
58 * - dst irq: peer core's irq number
59 * - ack irq: local irq number
60 * - slot number
65 struct hi6220_mbox *parent; member
80 void __iomem *base; member
95 status = readl(mbox->base + MBOX_MODE_REG(slot)); in mbox_set_state()
97 writel(status, mbox->base + MBOX_MODE_REG(slot)); in mbox_set_state()
105 mode = readl(mbox->base + MBOX_MODE_REG(slot)); in mbox_set_mode()
107 writel(mode, mbox->base + MBOX_MODE_REG(slot)); in mbox_set_mode()
112 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_last_tx_done()
113 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_last_tx_done()
117 BUG_ON(mbox->tx_irq_mode); in hi6220_mbox_last_tx_done()
119 state = readl(mbox->base + MBOX_MODE_REG(mchan->slot)); in hi6220_mbox_last_tx_done()
125 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_send_data()
126 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_send_data()
127 unsigned int slot = mchan->slot; in hi6220_mbox_send_data()
132 mchan->dir = MBOX_TX; in hi6220_mbox_send_data()
136 if (mbox->tx_irq_mode) in hi6220_mbox_send_data()
142 writel(buf[i], mbox->base + MBOX_DATA_REG(slot) + i * 4); in hi6220_mbox_send_data()
145 writel(BIT(mchan->dst_irq), DST_INT_RAW_REG(mbox->ipc)); in hi6220_mbox_send_data()
157 state = readl(ACK_INT_STAT_REG(mbox->ipc)); in hi6220_mbox_interrupt()
159 dev_warn(mbox->dev, "%s: spurious interrupt\n", in hi6220_mbox_interrupt()
166 state &= (state - 1); in hi6220_mbox_interrupt()
168 chan = mbox->irq_map_chan[intr_bit]; in hi6220_mbox_interrupt()
170 dev_warn(mbox->dev, "%s: unexpected irq vector %d\n", in hi6220_mbox_interrupt()
175 mchan = chan->con_priv; in hi6220_mbox_interrupt()
176 if (mchan->dir == MBOX_TX) in hi6220_mbox_interrupt()
180 msg[i] = readl(mbox->base + in hi6220_mbox_interrupt()
181 MBOX_DATA_REG(mchan->slot) + i * 4); in hi6220_mbox_interrupt()
187 writel(BIT(mchan->ack_irq), ACK_INT_CLR_REG(mbox->ipc)); in hi6220_mbox_interrupt()
188 mbox_set_state(mbox, mchan->slot, MBOX_STATE_IDLE); in hi6220_mbox_interrupt()
196 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_startup()
197 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_startup()
199 mchan->dir = 0; in hi6220_mbox_startup()
201 /* enable interrupt */ in hi6220_mbox_startup()
202 writel(BIT(mchan->ack_irq), ACK_INT_ENA_REG(mbox->ipc)); in hi6220_mbox_startup()
208 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_shutdown()
209 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_shutdown()
211 /* disable interrupt */ in hi6220_mbox_shutdown()
212 writel(BIT(mchan->ack_irq), ACK_INT_DIS_REG(mbox->ipc)); in hi6220_mbox_shutdown()
213 mbox->irq_map_chan[mchan->ack_irq] = NULL; in hi6220_mbox_shutdown()
226 struct hi6220_mbox *mbox = dev_get_drvdata(controller->dev); in hi6220_mbox_xlate()
229 unsigned int i = spec->args[0]; in hi6220_mbox_xlate()
230 unsigned int dst_irq = spec->args[1]; in hi6220_mbox_xlate()
231 unsigned int ack_irq = spec->args[2]; in hi6220_mbox_xlate()
234 if (i >= mbox->chan_num || dst_irq >= mbox->chan_num || in hi6220_mbox_xlate()
235 ack_irq >= mbox->chan_num) { in hi6220_mbox_xlate()
236 dev_err(mbox->dev, in hi6220_mbox_xlate()
239 return ERR_PTR(-EINVAL); in hi6220_mbox_xlate()
243 chan = &mbox->chan[i]; in hi6220_mbox_xlate()
244 if (mbox->irq_map_chan[ack_irq] == (void *)chan) { in hi6220_mbox_xlate()
245 dev_err(mbox->dev, "Channel in use\n"); in hi6220_mbox_xlate()
246 return ERR_PTR(-EBUSY); in hi6220_mbox_xlate()
249 mchan = chan->con_priv; in hi6220_mbox_xlate()
250 mchan->dst_irq = dst_irq; in hi6220_mbox_xlate()
251 mchan->ack_irq = ack_irq; in hi6220_mbox_xlate()
253 mbox->irq_map_chan[ack_irq] = (void *)chan; in hi6220_mbox_xlate()
258 { .compatible = "hisilicon,hi6220-mbox", },
265 struct device_node *node = pdev->dev.of_node; in hi6220_mbox_probe()
266 struct device *dev = &pdev->dev; in hi6220_mbox_probe()
272 return -ENOMEM; in hi6220_mbox_probe()
274 mbox->dev = dev; in hi6220_mbox_probe()
275 mbox->chan_num = MBOX_CHAN_MAX; in hi6220_mbox_probe()
276 mbox->mchan = devm_kcalloc(dev, in hi6220_mbox_probe()
277 mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL); in hi6220_mbox_probe()
278 if (!mbox->mchan) in hi6220_mbox_probe()
279 return -ENOMEM; in hi6220_mbox_probe()
281 mbox->chan = devm_kcalloc(dev, in hi6220_mbox_probe()
282 mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL); in hi6220_mbox_probe()
283 if (!mbox->chan) in hi6220_mbox_probe()
284 return -ENOMEM; in hi6220_mbox_probe()
286 mbox->irq = platform_get_irq(pdev, 0); in hi6220_mbox_probe()
287 if (mbox->irq < 0) in hi6220_mbox_probe()
288 return mbox->irq; in hi6220_mbox_probe()
290 mbox->ipc = devm_platform_ioremap_resource(pdev, 0); in hi6220_mbox_probe()
291 if (IS_ERR(mbox->ipc)) { in hi6220_mbox_probe()
293 return PTR_ERR(mbox->ipc); in hi6220_mbox_probe()
296 mbox->base = devm_platform_ioremap_resource(pdev, 1); in hi6220_mbox_probe()
297 if (IS_ERR(mbox->base)) { in hi6220_mbox_probe()
299 return PTR_ERR(mbox->base); in hi6220_mbox_probe()
302 err = devm_request_irq(dev, mbox->irq, hi6220_mbox_interrupt, 0, in hi6220_mbox_probe()
307 return -ENODEV; in hi6220_mbox_probe()
310 mbox->controller.dev = dev; in hi6220_mbox_probe()
311 mbox->controller.chans = &mbox->chan[0]; in hi6220_mbox_probe()
312 mbox->controller.num_chans = mbox->chan_num; in hi6220_mbox_probe()
313 mbox->controller.ops = &hi6220_mbox_ops; in hi6220_mbox_probe()
314 mbox->controller.of_xlate = hi6220_mbox_xlate; in hi6220_mbox_probe()
316 for (i = 0; i < mbox->chan_num; i++) { in hi6220_mbox_probe()
317 mbox->chan[i].con_priv = &mbox->mchan[i]; in hi6220_mbox_probe()
318 mbox->irq_map_chan[i] = NULL; in hi6220_mbox_probe()
320 mbox->mchan[i].parent = mbox; in hi6220_mbox_probe()
321 mbox->mchan[i].slot = i; in hi6220_mbox_probe()
324 /* mask and clear all interrupt vectors */ in hi6220_mbox_probe()
325 writel(0x0, ACK_INT_MSK_REG(mbox->ipc)); in hi6220_mbox_probe()
326 writel(~0x0, ACK_INT_CLR_REG(mbox->ipc)); in hi6220_mbox_probe()
328 /* use interrupt for tx's ack */ in hi6220_mbox_probe()
329 mbox->tx_irq_mode = !of_property_read_bool(node, "hi6220,mbox-tx-noirq"); in hi6220_mbox_probe()
331 if (mbox->tx_irq_mode) in hi6220_mbox_probe()
332 mbox->controller.txdone_irq = true; in hi6220_mbox_probe()
334 mbox->controller.txdone_poll = true; in hi6220_mbox_probe()
335 mbox->controller.txpoll_period = 5; in hi6220_mbox_probe()
338 err = devm_mbox_controller_register(dev, &mbox->controller); in hi6220_mbox_probe()
351 .name = "hi6220-mbox",