Lines Matching +full:mbox +full:- +full:tx
1 // SPDX-License-Identifier: GPL-2.0-only
56 * - direction: tx or rx
57 * - dst irq: peer core's irq number
58 * - ack irq: local irq number
59 * - slot number
72 /* flag of enabling tx's irq mode */
89 static void mbox_set_state(struct hi6220_mbox *mbox, in mbox_set_state() argument
94 status = readl(mbox->base + MBOX_MODE_REG(slot)); in mbox_set_state()
96 writel(status, mbox->base + MBOX_MODE_REG(slot)); in mbox_set_state()
99 static void mbox_set_mode(struct hi6220_mbox *mbox, in mbox_set_mode() argument
104 mode = readl(mbox->base + MBOX_MODE_REG(slot)); in mbox_set_mode()
106 writel(mode, mbox->base + MBOX_MODE_REG(slot)); in mbox_set_mode()
111 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_last_tx_done()
112 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_last_tx_done() local
116 BUG_ON(mbox->tx_irq_mode); in hi6220_mbox_last_tx_done()
118 state = readl(mbox->base + MBOX_MODE_REG(mchan->slot)); in hi6220_mbox_last_tx_done()
124 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_send_data()
125 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_send_data() local
126 unsigned int slot = mchan->slot; in hi6220_mbox_send_data()
130 /* indicate as a TX channel */ in hi6220_mbox_send_data()
131 mchan->dir = MBOX_TX; in hi6220_mbox_send_data()
133 mbox_set_state(mbox, slot, MBOX_STATE_TX); in hi6220_mbox_send_data()
135 if (mbox->tx_irq_mode) in hi6220_mbox_send_data()
136 mbox_set_mode(mbox, slot, MBOX_ACK_IRQ); in hi6220_mbox_send_data()
138 mbox_set_mode(mbox, slot, MBOX_ACK_AUTOMATIC); in hi6220_mbox_send_data()
141 writel(buf[i], mbox->base + MBOX_DATA_REG(slot) + i * 4); in hi6220_mbox_send_data()
144 writel(BIT(mchan->dst_irq), DST_INT_RAW_REG(mbox->ipc)); in hi6220_mbox_send_data()
150 struct hi6220_mbox *mbox = p; in hi6220_mbox_interrupt() local
156 state = readl(ACK_INT_STAT_REG(mbox->ipc)); in hi6220_mbox_interrupt()
158 dev_warn(mbox->dev, "%s: spurious interrupt\n", in hi6220_mbox_interrupt()
165 state &= (state - 1); in hi6220_mbox_interrupt()
167 chan = mbox->irq_map_chan[intr_bit]; in hi6220_mbox_interrupt()
169 dev_warn(mbox->dev, "%s: unexpected irq vector %d\n", in hi6220_mbox_interrupt()
174 mchan = chan->con_priv; in hi6220_mbox_interrupt()
175 if (mchan->dir == MBOX_TX) in hi6220_mbox_interrupt()
179 msg[i] = readl(mbox->base + in hi6220_mbox_interrupt()
180 MBOX_DATA_REG(mchan->slot) + i * 4); in hi6220_mbox_interrupt()
186 writel(BIT(mchan->ack_irq), ACK_INT_CLR_REG(mbox->ipc)); in hi6220_mbox_interrupt()
187 mbox_set_state(mbox, mchan->slot, MBOX_STATE_IDLE); in hi6220_mbox_interrupt()
195 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_startup()
196 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_startup() local
198 mchan->dir = 0; in hi6220_mbox_startup()
201 writel(BIT(mchan->ack_irq), ACK_INT_ENA_REG(mbox->ipc)); in hi6220_mbox_startup()
207 struct hi6220_mbox_chan *mchan = chan->con_priv; in hi6220_mbox_shutdown()
208 struct hi6220_mbox *mbox = mchan->parent; in hi6220_mbox_shutdown() local
211 writel(BIT(mchan->ack_irq), ACK_INT_DIS_REG(mbox->ipc)); in hi6220_mbox_shutdown()
212 mbox->irq_map_chan[mchan->ack_irq] = NULL; in hi6220_mbox_shutdown()
225 struct hi6220_mbox *mbox = dev_get_drvdata(controller->dev); in hi6220_mbox_xlate() local
228 unsigned int i = spec->args[0]; in hi6220_mbox_xlate()
229 unsigned int dst_irq = spec->args[1]; in hi6220_mbox_xlate()
230 unsigned int ack_irq = spec->args[2]; in hi6220_mbox_xlate()
233 if (i >= mbox->chan_num || dst_irq >= mbox->chan_num || in hi6220_mbox_xlate()
234 ack_irq >= mbox->chan_num) { in hi6220_mbox_xlate()
235 dev_err(mbox->dev, in hi6220_mbox_xlate()
238 return ERR_PTR(-EINVAL); in hi6220_mbox_xlate()
242 chan = &mbox->chan[i]; in hi6220_mbox_xlate()
243 if (mbox->irq_map_chan[ack_irq] == (void *)chan) { in hi6220_mbox_xlate()
244 dev_err(mbox->dev, "Channel in use\n"); in hi6220_mbox_xlate()
245 return ERR_PTR(-EBUSY); in hi6220_mbox_xlate()
248 mchan = chan->con_priv; in hi6220_mbox_xlate()
249 mchan->dst_irq = dst_irq; in hi6220_mbox_xlate()
250 mchan->ack_irq = ack_irq; in hi6220_mbox_xlate()
252 mbox->irq_map_chan[ack_irq] = (void *)chan; in hi6220_mbox_xlate()
257 { .compatible = "hisilicon,hi6220-mbox", },
264 struct device_node *node = pdev->dev.of_node; in hi6220_mbox_probe()
265 struct device *dev = &pdev->dev; in hi6220_mbox_probe()
266 struct hi6220_mbox *mbox; in hi6220_mbox_probe() local
269 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); in hi6220_mbox_probe()
270 if (!mbox) in hi6220_mbox_probe()
271 return -ENOMEM; in hi6220_mbox_probe()
273 mbox->dev = dev; in hi6220_mbox_probe()
274 mbox->chan_num = MBOX_CHAN_MAX; in hi6220_mbox_probe()
275 mbox->mchan = devm_kcalloc(dev, in hi6220_mbox_probe()
276 mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL); in hi6220_mbox_probe()
277 if (!mbox->mchan) in hi6220_mbox_probe()
278 return -ENOMEM; in hi6220_mbox_probe()
280 mbox->chan = devm_kcalloc(dev, in hi6220_mbox_probe()
281 mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL); in hi6220_mbox_probe()
282 if (!mbox->chan) in hi6220_mbox_probe()
283 return -ENOMEM; in hi6220_mbox_probe()
285 mbox->irq = platform_get_irq(pdev, 0); in hi6220_mbox_probe()
286 if (mbox->irq < 0) in hi6220_mbox_probe()
287 return mbox->irq; in hi6220_mbox_probe()
289 mbox->ipc = devm_platform_ioremap_resource(pdev, 0); in hi6220_mbox_probe()
290 if (IS_ERR(mbox->ipc)) { in hi6220_mbox_probe()
292 return PTR_ERR(mbox->ipc); in hi6220_mbox_probe()
295 mbox->base = devm_platform_ioremap_resource(pdev, 1); in hi6220_mbox_probe()
296 if (IS_ERR(mbox->base)) { in hi6220_mbox_probe()
298 return PTR_ERR(mbox->base); in hi6220_mbox_probe()
301 err = devm_request_irq(dev, mbox->irq, hi6220_mbox_interrupt, 0, in hi6220_mbox_probe()
302 dev_name(dev), mbox); in hi6220_mbox_probe()
306 return -ENODEV; in hi6220_mbox_probe()
309 mbox->controller.dev = dev; in hi6220_mbox_probe()
310 mbox->controller.chans = &mbox->chan[0]; in hi6220_mbox_probe()
311 mbox->controller.num_chans = mbox->chan_num; in hi6220_mbox_probe()
312 mbox->controller.ops = &hi6220_mbox_ops; in hi6220_mbox_probe()
313 mbox->controller.of_xlate = hi6220_mbox_xlate; in hi6220_mbox_probe()
315 for (i = 0; i < mbox->chan_num; i++) { in hi6220_mbox_probe()
316 mbox->chan[i].con_priv = &mbox->mchan[i]; in hi6220_mbox_probe()
317 mbox->irq_map_chan[i] = NULL; in hi6220_mbox_probe()
319 mbox->mchan[i].parent = mbox; in hi6220_mbox_probe()
320 mbox->mchan[i].slot = i; in hi6220_mbox_probe()
324 writel(0x0, ACK_INT_MSK_REG(mbox->ipc)); in hi6220_mbox_probe()
325 writel(~0x0, ACK_INT_CLR_REG(mbox->ipc)); in hi6220_mbox_probe()
327 /* use interrupt for tx's ack */ in hi6220_mbox_probe()
328 if (of_find_property(node, "hi6220,mbox-tx-noirq", NULL)) in hi6220_mbox_probe()
329 mbox->tx_irq_mode = false; in hi6220_mbox_probe()
331 mbox->tx_irq_mode = true; in hi6220_mbox_probe()
333 if (mbox->tx_irq_mode) in hi6220_mbox_probe()
334 mbox->controller.txdone_irq = true; in hi6220_mbox_probe()
336 mbox->controller.txdone_poll = true; in hi6220_mbox_probe()
337 mbox->controller.txpoll_period = 5; in hi6220_mbox_probe()
340 err = devm_mbox_controller_register(dev, &mbox->controller); in hi6220_mbox_probe()
346 platform_set_drvdata(pdev, mbox); in hi6220_mbox_probe()
353 .name = "hi6220-mbox",