[stage 1] mailbox: qemu-mailbox: Add txdone intr
authorNikita Shubin <nikita.shubin@maquefel.me>
Mon, 10 Jun 2024 09:19:03 +0000 (12:19 +0300)
committerNikita Shubin <nikita.shubin@maquefel.me>
Mon, 17 Jun 2024 10:32:04 +0000 (13:32 +0300)
- add txdone separate interrupt
- add startup()/shutdown() to unmask/mask interrupts

Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
drivers/mailbox/qemu-mailbox.c

index 999310989d8973a8b6f86a417b65a855c86516b5..1313b569a6255a3881cbdad048c7f74b17f5f95e 100644 (file)
@@ -21,6 +21,8 @@
 
 #define QEMU_MBOX_CFG                  0x0
 #define QEMU_MBOX_ISTATUS              0x4
+#define QEMU_MBOX_IEN                  0x8
+#define QEMU_MBOX_TXDONE               0x10
 
 #define QEMU_MBOX_CHAN_STRIDE          0x20
 #define QEMU_MBOX_CHAN_ADDR(chan)      (QEMU_MBOX_CHAN_STRIDE + (chan * QEMU_MBOX_CHAN_STRIDE))
@@ -58,6 +60,24 @@ static irqreturn_t qemu_mbox_isr(int virq, void *data)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t qemu_mbox_txdone_isr(int virq, void *data)
+{
+       struct qemu_mbox *mbox = data;
+       struct mbox_chan *chan;
+       unsigned int stat = 0;
+       int offset;
+
+       regmap_read(mbox->map, QEMU_MBOX_TXDONE, &stat);
+
+       for_each_set_bit(offset, (unsigned long *)&stat, QEMU_MBOX_MAX_CHAN_CNT) {
+               chan = &mbox->mbox.chans[offset];
+               if (chan->cl)
+                       mbox_chan_txdone(chan, 0);
+       }
+
+       return IRQ_HANDLED;
+}
+
 struct mbox_chan *qemu_mbox_request_channel(struct mbox_client *cl)
 {
        struct qemu_mbox *mbox = __mbox;
@@ -86,6 +106,22 @@ static int qemu_mbox_send_data(struct mbox_chan *link, void *data)
        return regmap_write(mbox->map, QEMU_MBOX_CHAN_ADDR(chan), *msg);
 }
 
+static int qemu_mbox_startup(struct mbox_chan *link)
+{
+       unsigned long chan = (unsigned long)link->con_priv;
+       struct qemu_mbox *mbox = get_qemu_mbox(link->mbox);
+
+       return regmap_set_bits(mbox->map, QEMU_MBOX_IEN, BIT(chan));
+}
+
+static void qemu_mbox_shutdown(struct mbox_chan *link)
+{
+       unsigned long chan = (unsigned long)link->con_priv;
+       struct qemu_mbox *mbox = get_qemu_mbox(link->mbox);
+
+       regmap_clear_bits(mbox->map, QEMU_MBOX_IEN, BIT(chan));
+}
+
 static const struct regmap_config qemu_mbox_regmap_config = {
        .reg_bits = 32,
        .reg_stride = 4,
@@ -95,6 +131,8 @@ static const struct regmap_config qemu_mbox_regmap_config = {
 
 static const struct mbox_chan_ops qemu_mbox_chan_ops = {
        .send_data      = qemu_mbox_send_data,
+       .startup        = qemu_mbox_startup,
+       .shutdown       = qemu_mbox_shutdown,
 };
 
 static int qemu_mbox_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -127,7 +165,7 @@ static int qemu_mbox_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return dev_err_probe(dev, PTR_ERR(qemu_mbox->map),
                                     "Unable to initialize register map\n");
 
-       err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
+       err = pci_alloc_irq_vectors(pdev, 2, 2, PCI_IRQ_MSIX);
        if (err < 0)
                return dev_err_probe(dev, err,
                                     "Unable to allocate irqs\n");
@@ -139,6 +177,13 @@ static int qemu_mbox_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return dev_err_probe(dev, err,
                                     "Can't claim irq\n");
 
+       err =  devm_request_irq(&pdev->dev, pci_irq_vector(pdev, 1),
+                               qemu_mbox_txdone_isr, 0,
+                               "qemu_mbox_txdone_isr", qemu_mbox);
+       if (err)
+               return dev_err_probe(dev, err,
+                                    "Can't claim txdone irq\n");
+
        pci_set_master(pdev);
 
        mbox = &qemu_mbox->mbox;