Message ID | SYBP282MB2238F93AB57A398E322644C3C4CE2@SYBP282MB2238.AUSP282.PROD.OUTLOOK.COM (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | riscv: sophgo: add mailbox support for cv18x SoCs | expand |
Hi Yuntao, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.10-rc4 next-20240619] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Yuntao-Dai/dt-bindings-mailbox-add-Sophgo-cv18x-SoCs-mailbox/20240618-232307 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/SYBP282MB2238F93AB57A398E322644C3C4CE2%40SYBP282MB2238.AUSP282.PROD.OUTLOOK.COM patch subject: [PATCH 3/3] mailbox: sophgo: add mailbox driver for cv18x SoCs config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20240620/202406200221.v3RvI4Qb-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240620/202406200221.v3RvI4Qb-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202406200221.v3RvI4Qb-lkp@intel.com/ All warnings (new ones prefixed by >>): drivers/mailbox/cv1800b-mailbox.c: In function 'cv1800b_mbox_send_data': >> drivers/mailbox/cv1800b-mailbox.c:83:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 83 | int idx = (int)chan->con_priv; | ^ drivers/mailbox/cv1800b-mailbox.c: In function 'cv1800b_mbox_probe': >> drivers/mailbox/cv1800b-mailbox.c:160:48: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 160 | mb->mbox.chans[idx].con_priv = (void *)idx; | ^ vim +83 drivers/mailbox/cv1800b-mailbox.c 79 80 static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) 81 { 82 struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); > 83 int idx = (int)chan->con_priv; 84 u8 en, valid; 85 u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; 86 87 memcpy_toio(addr, data, 8); 88 89 valid = 1 << idx; 90 writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); 91 en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 92 writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 93 writeb(valid, mbox->mbox_base + MBOX_SET_REG); 94 95 return 0; 96 } 97 98 static bool cv1800b_last_tx_done(struct mbox_chan *chan) 99 { 100 return true; 101 } 102 103 static const struct mbox_chan_ops cv1800b_mbox_chan_ops = { 104 .send_data = cv1800b_mbox_send_data, 105 .last_tx_done = cv1800b_last_tx_done, 106 }; 107 108 static const struct of_device_id cv1800b_mbox_of_match[] = { 109 { .compatible = "sophgo,cv1800b-mailbox", }, 110 {}, 111 }; 112 MODULE_DEVICE_TABLE(of, cv1800b_mbox_of_match); 113 114 static int cv1800b_mbox_probe(struct platform_device *pdev) 115 { 116 struct device *dev = &pdev->dev; 117 struct cv1800b_mbox *mb; 118 int irq, idx, err, cpu; 119 120 if (!dev->of_node) 121 return -ENODEV; 122 123 mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL); 124 if (!mb) 125 return -ENOMEM; 126 127 mb->mbox_base = devm_of_iomap(dev, dev->of_node, 0, NULL); 128 if (IS_ERR(mb->mbox_base)) 129 return dev_err_probe(dev, PTR_ERR(mb->mbox_base), 130 "Failed to map resource\n"); 131 132 err = of_property_read_s32(dev->of_node, "sendto", &cpu); 133 if (err) 134 return dev_err_probe(dev, err, 135 "Failed to find <sendto> in of_node\n"); 136 137 mb->sendto = cpu; 138 139 err = of_property_read_s32(dev->of_node, "recvid", &cpu); 140 if (err) { 141 return dev_err_probe(dev, err, 142 "Failed to find <recvid> in of_node\n"); 143 } 144 mb->recvid = cpu; 145 146 mb->mbox.dev = dev; 147 mb->mbox.num_chans = MAILBOX_MAX_CHAN; 148 mb->mbox.chans = mb->chans; 149 mb->mbox.ops = &cv1800b_mbox_chan_ops; 150 mb->mbox.txdone_poll = true; 151 152 irq = platform_get_irq_byname(pdev, "mailbox"); 153 err = devm_request_threaded_irq(dev, irq, cv1800b_mbox_irq, 154 cv1800b_mbox_isr, IRQF_ONESHOT, 155 dev_name(&pdev->dev), mb); 156 if (err < 0) 157 return dev_err_probe(dev, err, "Failed to register irq\n"); 158 159 for (idx = 0; idx < MAILBOX_MAX_CHAN; idx++) > 160 mb->mbox.chans[idx].con_priv = (void *)idx; 161 162 err = devm_mbox_controller_register(dev, &mb->mbox); 163 if (err) 164 return dev_err_probe(dev, err, "Failed to register mailbox\n"); 165 166 platform_set_drvdata(pdev, mb); 167 return 0; 168 } 169
Hi Yuntao, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.10-rc4 next-20240619] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Yuntao-Dai/dt-bindings-mailbox-add-Sophgo-cv18x-SoCs-mailbox/20240618-232307 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/SYBP282MB2238F93AB57A398E322644C3C4CE2%40SYBP282MB2238.AUSP282.PROD.OUTLOOK.COM patch subject: [PATCH 3/3] mailbox: sophgo: add mailbox driver for cv18x SoCs config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20240620/202406200820.Wms9UPDw-lkp@intel.com/config) compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240620/202406200820.Wms9UPDw-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202406200820.Wms9UPDw-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/mailbox/cv1800b-mailbox.c:83:12: warning: cast to smaller integer type 'int' from 'void *' [-Wvoid-pointer-to-int-cast] 83 | int idx = (int)chan->con_priv; | ^~~~~~~~~~~~~~~~~~~ >> drivers/mailbox/cv1800b-mailbox.c:160:34: warning: cast to 'void *' from smaller integer type 'int' [-Wint-to-void-pointer-cast] 160 | mb->mbox.chans[idx].con_priv = (void *)idx; | ^~~~~~~~~~~ 2 warnings generated. vim +83 drivers/mailbox/cv1800b-mailbox.c 79 80 static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) 81 { 82 struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); > 83 int idx = (int)chan->con_priv; 84 u8 en, valid; 85 u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; 86 87 memcpy_toio(addr, data, 8); 88 89 valid = 1 << idx; 90 writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); 91 en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 92 writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 93 writeb(valid, mbox->mbox_base + MBOX_SET_REG); 94 95 return 0; 96 } 97 98 static bool cv1800b_last_tx_done(struct mbox_chan *chan) 99 { 100 return true; 101 } 102 103 static const struct mbox_chan_ops cv1800b_mbox_chan_ops = { 104 .send_data = cv1800b_mbox_send_data, 105 .last_tx_done = cv1800b_last_tx_done, 106 }; 107 108 static const struct of_device_id cv1800b_mbox_of_match[] = { 109 { .compatible = "sophgo,cv1800b-mailbox", }, 110 {}, 111 }; 112 MODULE_DEVICE_TABLE(of, cv1800b_mbox_of_match); 113 114 static int cv1800b_mbox_probe(struct platform_device *pdev) 115 { 116 struct device *dev = &pdev->dev; 117 struct cv1800b_mbox *mb; 118 int irq, idx, err, cpu; 119 120 if (!dev->of_node) 121 return -ENODEV; 122 123 mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL); 124 if (!mb) 125 return -ENOMEM; 126 127 mb->mbox_base = devm_of_iomap(dev, dev->of_node, 0, NULL); 128 if (IS_ERR(mb->mbox_base)) 129 return dev_err_probe(dev, PTR_ERR(mb->mbox_base), 130 "Failed to map resource\n"); 131 132 err = of_property_read_s32(dev->of_node, "sendto", &cpu); 133 if (err) 134 return dev_err_probe(dev, err, 135 "Failed to find <sendto> in of_node\n"); 136 137 mb->sendto = cpu; 138 139 err = of_property_read_s32(dev->of_node, "recvid", &cpu); 140 if (err) { 141 return dev_err_probe(dev, err, 142 "Failed to find <recvid> in of_node\n"); 143 } 144 mb->recvid = cpu; 145 146 mb->mbox.dev = dev; 147 mb->mbox.num_chans = MAILBOX_MAX_CHAN; 148 mb->mbox.chans = mb->chans; 149 mb->mbox.ops = &cv1800b_mbox_chan_ops; 150 mb->mbox.txdone_poll = true; 151 152 irq = platform_get_irq_byname(pdev, "mailbox"); 153 err = devm_request_threaded_irq(dev, irq, cv1800b_mbox_irq, 154 cv1800b_mbox_isr, IRQF_ONESHOT, 155 dev_name(&pdev->dev), mb); 156 if (err < 0) 157 return dev_err_probe(dev, err, "Failed to register irq\n"); 158 159 for (idx = 0; idx < MAILBOX_MAX_CHAN; idx++) > 160 mb->mbox.chans[idx].con_priv = (void *)idx; 161 162 err = devm_mbox_controller_register(dev, &mb->mbox); 163 if (err) 164 return dev_err_probe(dev, err, "Failed to register mailbox\n"); 165 166 platform_set_drvdata(pdev, mb); 167 return 0; 168 } 169
Hi Yuntao, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.10-rc4 next-20240620] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Yuntao-Dai/dt-bindings-mailbox-add-Sophgo-cv18x-SoCs-mailbox/20240618-232307 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/SYBP282MB2238F93AB57A398E322644C3C4CE2%40SYBP282MB2238.AUSP282.PROD.OUTLOOK.COM patch subject: [PATCH 3/3] mailbox: sophgo: add mailbox driver for cv18x SoCs config: powerpc-randconfig-r121-20240621 (https://download.01.org/0day-ci/archive/20240621/202406210836.gWHxzdUE-lkp@intel.com/config) compiler: powerpc-linux-gcc (GCC) 13.2.0 reproduce: (https://download.01.org/0day-ci/archive/20240621/202406210836.gWHxzdUE-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202406210836.gWHxzdUE-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/mailbox/cv1800b-mailbox.c:66:25: sparse: sparse: cast removes address space '__iomem' of expression drivers/mailbox/cv1800b-mailbox.c:85:22: sparse: sparse: cast removes address space '__iomem' of expression >> drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void volatile [noderef] __iomem *d @@ got unsigned long long [usertype] *addr @@ drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: expected void volatile [noderef] __iomem *d drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: got unsigned long long [usertype] *addr vim +/__iomem +66 drivers/mailbox/cv1800b-mailbox.c 51 52 static irqreturn_t cv1800b_mbox_irq(int irq, void *dev_id) 53 { 54 struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; 55 u8 set, valid; 56 u64 *addr; 57 size_t i; 58 59 set = readb(mbox->mbox_base + MBOX_SET_INT_REG(mbox->recvid)); 60 61 if (!set) 62 return IRQ_NONE; 63 64 for (i = 0; i < MAILBOX_MAX_CHAN; i++) { 65 valid = set & (1 << i); > 66 addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + i; 67 if (valid) { 68 mbox->content[i] = addr; 69 writeb(valid, mbox->mbox_base + 70 MBOX_SET_CLR_REG(mbox->recvid)); 71 writeb(~valid, 72 mbox->mbox_base + MBOX_EN_REG(mbox->recvid)); 73 return IRQ_WAKE_THREAD; 74 } 75 } 76 77 return IRQ_NONE; 78 } 79 80 static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) 81 { 82 struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); 83 int idx = (int)chan->con_priv; 84 u8 en, valid; 85 u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; 86 > 87 memcpy_toio(addr, data, 8); 88 89 valid = 1 << idx; 90 writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); 91 en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 92 writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 93 writeb(valid, mbox->mbox_base + MBOX_SET_REG); 94 95 return 0; 96 } 97
Hi Yuntao, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.10-rc4 next-20240620] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Yuntao-Dai/dt-bindings-mailbox-add-Sophgo-cv18x-SoCs-mailbox/20240618-232307 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/SYBP282MB2238F93AB57A398E322644C3C4CE2%40SYBP282MB2238.AUSP282.PROD.OUTLOOK.COM patch subject: [PATCH 3/3] mailbox: sophgo: add mailbox driver for cv18x SoCs config: powerpc-randconfig-r121-20240621 (https://download.01.org/0day-ci/archive/20240621/202406212145.yo80iIS0-lkp@intel.com/config) compiler: powerpc-linux-gcc (GCC) 13.2.0 reproduce: (https://download.01.org/0day-ci/archive/20240621/202406212145.yo80iIS0-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202406212145.yo80iIS0-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/mailbox/cv1800b-mailbox.c:66:25: sparse: sparse: cast removes address space '__iomem' of expression drivers/mailbox/cv1800b-mailbox.c:85:22: sparse: sparse: cast removes address space '__iomem' of expression >> drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void volatile [noderef] __iomem *d @@ got unsigned long long [usertype] *addr @@ drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: expected void volatile [noderef] __iomem *d drivers/mailbox/cv1800b-mailbox.c:87:21: sparse: got unsigned long long [usertype] *addr vim +/__iomem +66 drivers/mailbox/cv1800b-mailbox.c 51 52 static irqreturn_t cv1800b_mbox_irq(int irq, void *dev_id) 53 { 54 struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; 55 u8 set, valid; 56 u64 *addr; 57 size_t i; 58 59 set = readb(mbox->mbox_base + MBOX_SET_INT_REG(mbox->recvid)); 60 61 if (!set) 62 return IRQ_NONE; 63 64 for (i = 0; i < MAILBOX_MAX_CHAN; i++) { 65 valid = set & (1 << i); > 66 addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + i; 67 if (valid) { 68 mbox->content[i] = addr; 69 writeb(valid, mbox->mbox_base + 70 MBOX_SET_CLR_REG(mbox->recvid)); 71 writeb(~valid, 72 mbox->mbox_base + MBOX_EN_REG(mbox->recvid)); 73 return IRQ_WAKE_THREAD; 74 } 75 } 76 77 return IRQ_NONE; 78 } 79 80 static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) 81 { 82 struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); 83 int idx = (int)chan->con_priv; 84 u8 en, valid; 85 u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; 86 > 87 memcpy_toio(addr, data, 8); 88 89 valid = 1 << idx; 90 writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); 91 en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 92 writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); 93 writeb(valid, mbox->mbox_base + MBOX_SET_REG); 94 95 return 0; 96 } 97
Hi Yuntao, On 2024/6/18 23:12, Yuntao Dai wrote: > Add mailbox controller driver for cv18x SoCs, tested on mailbox-test > client. > > Signed-off-by: Yuntao Dai <d1581209858@live.com> > --- > drivers/mailbox/Kconfig | 11 ++ > drivers/mailbox/Makefile | 2 + > drivers/mailbox/cv1800b-mailbox.c | 181 ++++++++++++++++++++++++++++++ > 3 files changed, 194 insertions(+) > create mode 100644 drivers/mailbox/cv1800b-mailbox.c > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > index 3b8842c4a..4e5593861 100644 > --- a/drivers/mailbox/Kconfig > +++ b/drivers/mailbox/Kconfig > @@ -286,4 +286,15 @@ config QCOM_IPCC > acts as an interrupt controller for receiving interrupts from clients. > Say Y here if you want to build this driver. > > +config CV1800B_MBOX > + tristate "cv1800b mailbox" > + depends on OF > + depends on ARCH_SOPHGO || COMPILE_TEST > + help > + Mailbox driver implementation for Sophgo cv180x SoCs. This driver > + can be used to send message between different processors in SoC. Any > + processer can write data in a channel, and set co-responding register > + to raise interrupt to notice another processor, and it is allowed to > + send data to itself. > + > endif > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > index 5cf2f54de..71f0f746e 100644 > --- a/drivers/mailbox/Makefile > +++ b/drivers/mailbox/Makefile > @@ -62,3 +62,5 @@ obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o > obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o > better > obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o > + > +obj-$(CONFIG_CV1800B_MBOX) += cv1800b-mailbox.o > \ No newline at end of file > diff --git a/drivers/mailbox/cv1800b-mailbox.c b/drivers/mailbox/cv1800b-mailbox.c > new file mode 100644 > index 000000000..8ef2a5492 > --- /dev/null > +++ b/drivers/mailbox/cv1800b-mailbox.c > @@ -0,0 +1,181 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > + > +#include <linux/device.h> > +#include <linux/err.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <linux/kfifo.h> > +#include <linux/mailbox_controller.h> > +#include <linux/mailbox_client.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/slab.h> > + > +#define MAILBOX_MAX_CHAN 0x0008 > +#define MAILBOX_DONE_OFFSET 0x0002 > +#define MAILBOX_CONTEXT_SIZE 0x0040 > +#define MAILBOX_CONTEXT_OFFSET 0x0400 > + > +#define MBOX_EN_REG(cpu) (cpu << 2) > +#define MBOX_DONE_REG(cpu) ((cpu << 2) + MAILBOX_DONE_OFFSET) > + > +#define MBOX_SET_CLR_REG(cpu) (0x10 + (cpu << 4)) > +#define MBOX_SET_INT_REG(cpu) (0x18 + (cpu << 4)) > + > +#define MBOX_SET_REG 0x60 > + > +struct cv1800b_mbox { > + struct mbox_controller mbox; > + struct mbox_chan chans[MAILBOX_MAX_CHAN]; > + u64 *content[MAILBOX_MAX_CHAN]; > + void __iomem *mbox_base; > + int sendto; > + int recvid; > +}; > + > +static irqreturn_t cv1800b_mbox_isr(int irq, void *dev_id) > +{ > + struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; > + size_t i; > + > + for (i = 0; i < MAILBOX_MAX_CHAN; i++) { > + if (mbox->content[i]) { > + mbox_chan_received_data(&mbox->chans[i], > + mbox->content[i]); I tested this driver but met "NULL pointer dereference" Oops here when I sent message from the c906l core without binding clients. I think maybe it's better to add a check here, like: struct mbox_chan *chan = &mbox->chans[i]; if (chan->cl) { mbox_chan_received_data(chan, mbox->content[i]); } Best, Junhui Liu > + mbox->content[i] = NULL; > + return IRQ_HANDLED; > + } > + } > + return IRQ_NONE; > +} > + > +static irqreturn_t cv1800b_mbox_irq(int irq, void *dev_id) > +{ > + struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; > + u8 set, valid; > + u64 *addr; > + size_t i; > + > + set = readb(mbox->mbox_base + MBOX_SET_INT_REG(mbox->recvid)); > + > + if (!set) > + return IRQ_NONE; > + > + for (i = 0; i < MAILBOX_MAX_CHAN; i++) { > + valid = set & (1 << i); > + addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + i; > + if (valid) { > + mbox->content[i] = addr; > + writeb(valid, mbox->mbox_base + > + MBOX_SET_CLR_REG(mbox->recvid)); > + writeb(~valid, > + mbox->mbox_base + MBOX_EN_REG(mbox->recvid)); > + return IRQ_WAKE_THREAD; > + } > + } > + > + return IRQ_NONE; > +} > + > +static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) > +{ > + struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); > + int idx = (int)chan->con_priv; > + u8 en, valid; > + u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; > + > + memcpy_toio(addr, data, 8); > + > + valid = 1 << idx; > + writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); > + en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); > + writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); > + writeb(valid, mbox->mbox_base + MBOX_SET_REG); > + > + return 0; > +} > + > +static bool cv1800b_last_tx_done(struct mbox_chan *chan) > +{ > + return true; > +} > + > +static const struct mbox_chan_ops cv1800b_mbox_chan_ops = { > + .send_data = cv1800b_mbox_send_data, > + .last_tx_done = cv1800b_last_tx_done, > +}; > + > +static const struct of_device_id cv1800b_mbox_of_match[] = { > + { .compatible = "sophgo,cv1800b-mailbox", }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, cv1800b_mbox_of_match); > + > +static int cv1800b_mbox_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct cv1800b_mbox *mb; > + int irq, idx, err, cpu; > + > + if (!dev->of_node) > + return -ENODEV; > + > + mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL); > + if (!mb) > + return -ENOMEM; > + > + mb->mbox_base = devm_of_iomap(dev, dev->of_node, 0, NULL); > + if (IS_ERR(mb->mbox_base)) > + return dev_err_probe(dev, PTR_ERR(mb->mbox_base), > + "Failed to map resource\n"); > + > + err = of_property_read_s32(dev->of_node, "sendto", &cpu); > + if (err) > + return dev_err_probe(dev, err, > + "Failed to find <sendto> in of_node\n"); > + > + mb->sendto = cpu; > + > + err = of_property_read_s32(dev->of_node, "recvid", &cpu); > + if (err) { > + return dev_err_probe(dev, err, > + "Failed to find <recvid> in of_node\n"); > + } > + mb->recvid = cpu; > + > + mb->mbox.dev = dev; > + mb->mbox.num_chans = MAILBOX_MAX_CHAN; > + mb->mbox.chans = mb->chans; > + mb->mbox.ops = &cv1800b_mbox_chan_ops; > + mb->mbox.txdone_poll = true; > + > + irq = platform_get_irq_byname(pdev, "mailbox"); > + err = devm_request_threaded_irq(dev, irq, cv1800b_mbox_irq, > + cv1800b_mbox_isr, IRQF_ONESHOT, > + dev_name(&pdev->dev), mb); > + if (err < 0) > + return dev_err_probe(dev, err, "Failed to register irq\n"); > + > + for (idx = 0; idx < MAILBOX_MAX_CHAN; idx++) > + mb->mbox.chans[idx].con_priv = (void *)idx; > + > + err = devm_mbox_controller_register(dev, &mb->mbox); > + if (err) > + return dev_err_probe(dev, err, "Failed to register mailbox\n"); > + > + platform_set_drvdata(pdev, mb); > + return 0; > +} > + > +static struct platform_driver cv1800b_mbox_driver = { > + .driver = { > + .name = "cv1800b-mbox", > + .of_match_table = cv1800b_mbox_of_match, > + }, > + .probe = cv1800b_mbox_probe, > +}; > + > +module_platform_driver(cv1800b_mbox_driver); > + > +MODULE_DESCRIPTION("cv1800b mailbox driver"); > +MODULE_LICENSE("GPL");
Hi Junhui, On Tue, Jul 2, 2024 at 11:08 PM, Junhui Liu <liujh2818@gmail.com> wrote: > Hi Yuntao, > > On 2024/6/18 23:12, Yuntao Dai wrote: >> Add mailbox controller driver for cv18x SoCs, tested on mailbox-test >> client. >> >> Signed-off-by: Yuntao Dai <d1581209858@live.com> >> --- >> drivers/mailbox/Kconfig | 11 ++ >> drivers/mailbox/Makefile | 2 + >> drivers/mailbox/cv1800b-mailbox.c | 181 >> ++++++++++++++++++++++++++++++ >> 3 files changed, 194 insertions(+) >> create mode 100644 drivers/mailbox/cv1800b-mailbox.c >> >> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig >> index 3b8842c4a..4e5593861 100644 >> --- a/drivers/mailbox/Kconfig >> +++ b/drivers/mailbox/Kconfig >> @@ -286,4 +286,15 @@ config QCOM_IPCC >> acts as an interrupt controller for receiving interrupts from >> clients. >> Say Y here if you want to build this driver. >> +config CV1800B_MBOX >> + tristate "cv1800b mailbox" >> + depends on OF >> + depends on ARCH_SOPHGO || COMPILE_TEST >> + help >> + Mailbox driver implementation for Sophgo cv180x SoCs. This driver >> + can be used to send message between different processors in SoC. >> Any >> + processer can write data in a channel, and set co-responding >> register >> + to raise interrupt to notice another processor, and it is >> allowed to >> + send data to itself. >> + >> endif >> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile >> index 5cf2f54de..71f0f746e 100644 >> --- a/drivers/mailbox/Makefile >> +++ b/drivers/mailbox/Makefile >> @@ -62,3 +62,5 @@ obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o >> obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o >> better >> obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o >> + >> +obj-$(CONFIG_CV1800B_MBOX) += cv1800b-mailbox.o >> \ No newline at end of file >> diff --git a/drivers/mailbox/cv1800b-mailbox.c >> b/drivers/mailbox/cv1800b-mailbox.c >> new file mode 100644 >> index 000000000..8ef2a5492 >> --- /dev/null >> +++ b/drivers/mailbox/cv1800b-mailbox.c >> @@ -0,0 +1,181 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later >> + >> +#include <linux/device.h> >> +#include <linux/err.h> >> +#include <linux/interrupt.h> >> +#include <linux/io.h> >> +#include <linux/kfifo.h> >> +#include <linux/mailbox_controller.h> >> +#include <linux/mailbox_client.h> >> +#include <linux/module.h> >> +#include <linux/platform_device.h> >> +#include <linux/slab.h> >> + >> +#define MAILBOX_MAX_CHAN 0x0008 >> +#define MAILBOX_DONE_OFFSET 0x0002 >> +#define MAILBOX_CONTEXT_SIZE 0x0040 >> +#define MAILBOX_CONTEXT_OFFSET 0x0400 >> + >> +#define MBOX_EN_REG(cpu) (cpu << 2) >> +#define MBOX_DONE_REG(cpu) ((cpu << 2) + MAILBOX_DONE_OFFSET) >> + >> +#define MBOX_SET_CLR_REG(cpu) (0x10 + (cpu << 4)) >> +#define MBOX_SET_INT_REG(cpu) (0x18 + (cpu << 4)) >> + >> +#define MBOX_SET_REG 0x60 >> + >> +struct cv1800b_mbox { >> + struct mbox_controller mbox; >> + struct mbox_chan chans[MAILBOX_MAX_CHAN]; >> + u64 *content[MAILBOX_MAX_CHAN]; >> + void __iomem *mbox_base; >> + int sendto; >> + int recvid; >> +}; >> + >> +static irqreturn_t cv1800b_mbox_isr(int irq, void *dev_id) >> +{ >> + struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; >> + size_t i; >> + >> + for (i = 0; i < MAILBOX_MAX_CHAN; i++) { >> + if (mbox->content[i]) { >> + mbox_chan_received_data(&mbox->chans[i], >> + mbox->content[i]); > I tested this driver but met "NULL pointer dereference" Oops here > when I sent message from the c906l core without binding clients. > > I think maybe it's better to add a check here, like: > > struct mbox_chan *chan = &mbox->chans[i]; > if (chan->cl) { > mbox_chan_received_data(chan, mbox->content[i]); > } > > Best, > Junhui Liu Thanks for your addvice, I will take it. On the other side, I am not sure weather mailbox driver can work without register mailbox client correctly? Best regards, Yuntao
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 3b8842c4a..4e5593861 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -286,4 +286,15 @@ config QCOM_IPCC acts as an interrupt controller for receiving interrupts from clients. Say Y here if you want to build this driver. +config CV1800B_MBOX + tristate "cv1800b mailbox" + depends on OF + depends on ARCH_SOPHGO || COMPILE_TEST + help + Mailbox driver implementation for Sophgo cv180x SoCs. This driver + can be used to send message between different processors in SoC. Any + processer can write data in a channel, and set co-responding register + to raise interrupt to notice another processor, and it is allowed to + send data to itself. + endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 5cf2f54de..71f0f746e 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -62,3 +62,5 @@ obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o + +obj-$(CONFIG_CV1800B_MBOX) += cv1800b-mailbox.o \ No newline at end of file diff --git a/drivers/mailbox/cv1800b-mailbox.c b/drivers/mailbox/cv1800b-mailbox.c new file mode 100644 index 000000000..8ef2a5492 --- /dev/null +++ b/drivers/mailbox/cv1800b-mailbox.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kfifo.h> +#include <linux/mailbox_controller.h> +#include <linux/mailbox_client.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define MAILBOX_MAX_CHAN 0x0008 +#define MAILBOX_DONE_OFFSET 0x0002 +#define MAILBOX_CONTEXT_SIZE 0x0040 +#define MAILBOX_CONTEXT_OFFSET 0x0400 + +#define MBOX_EN_REG(cpu) (cpu << 2) +#define MBOX_DONE_REG(cpu) ((cpu << 2) + MAILBOX_DONE_OFFSET) + +#define MBOX_SET_CLR_REG(cpu) (0x10 + (cpu << 4)) +#define MBOX_SET_INT_REG(cpu) (0x18 + (cpu << 4)) + +#define MBOX_SET_REG 0x60 + +struct cv1800b_mbox { + struct mbox_controller mbox; + struct mbox_chan chans[MAILBOX_MAX_CHAN]; + u64 *content[MAILBOX_MAX_CHAN]; + void __iomem *mbox_base; + int sendto; + int recvid; +}; + +static irqreturn_t cv1800b_mbox_isr(int irq, void *dev_id) +{ + struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; + size_t i; + + for (i = 0; i < MAILBOX_MAX_CHAN; i++) { + if (mbox->content[i]) { + mbox_chan_received_data(&mbox->chans[i], + mbox->content[i]); + mbox->content[i] = NULL; + return IRQ_HANDLED; + } + } + return IRQ_NONE; +} + +static irqreturn_t cv1800b_mbox_irq(int irq, void *dev_id) +{ + struct cv1800b_mbox *mbox = (struct cv1800b_mbox *)dev_id; + u8 set, valid; + u64 *addr; + size_t i; + + set = readb(mbox->mbox_base + MBOX_SET_INT_REG(mbox->recvid)); + + if (!set) + return IRQ_NONE; + + for (i = 0; i < MAILBOX_MAX_CHAN; i++) { + valid = set & (1 << i); + addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + i; + if (valid) { + mbox->content[i] = addr; + writeb(valid, mbox->mbox_base + + MBOX_SET_CLR_REG(mbox->recvid)); + writeb(~valid, + mbox->mbox_base + MBOX_EN_REG(mbox->recvid)); + return IRQ_WAKE_THREAD; + } + } + + return IRQ_NONE; +} + +static int cv1800b_mbox_send_data(struct mbox_chan *chan, void *data) +{ + struct cv1800b_mbox *mbox = dev_get_drvdata(chan->mbox->dev); + int idx = (int)chan->con_priv; + u8 en, valid; + u64 *addr = (u64 *)(mbox->mbox_base + MAILBOX_CONTEXT_OFFSET) + idx; + + memcpy_toio(addr, data, 8); + + valid = 1 << idx; + writeb(valid, mbox->mbox_base + MBOX_SET_CLR_REG(mbox->sendto)); + en = readb(mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); + writeb(en | valid, mbox->mbox_base + MBOX_EN_REG(mbox->sendto)); + writeb(valid, mbox->mbox_base + MBOX_SET_REG); + + return 0; +} + +static bool cv1800b_last_tx_done(struct mbox_chan *chan) +{ + return true; +} + +static const struct mbox_chan_ops cv1800b_mbox_chan_ops = { + .send_data = cv1800b_mbox_send_data, + .last_tx_done = cv1800b_last_tx_done, +}; + +static const struct of_device_id cv1800b_mbox_of_match[] = { + { .compatible = "sophgo,cv1800b-mailbox", }, + {}, +}; +MODULE_DEVICE_TABLE(of, cv1800b_mbox_of_match); + +static int cv1800b_mbox_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cv1800b_mbox *mb; + int irq, idx, err, cpu; + + if (!dev->of_node) + return -ENODEV; + + mb = devm_kzalloc(dev, sizeof(*mb), GFP_KERNEL); + if (!mb) + return -ENOMEM; + + mb->mbox_base = devm_of_iomap(dev, dev->of_node, 0, NULL); + if (IS_ERR(mb->mbox_base)) + return dev_err_probe(dev, PTR_ERR(mb->mbox_base), + "Failed to map resource\n"); + + err = of_property_read_s32(dev->of_node, "sendto", &cpu); + if (err) + return dev_err_probe(dev, err, + "Failed to find <sendto> in of_node\n"); + + mb->sendto = cpu; + + err = of_property_read_s32(dev->of_node, "recvid", &cpu); + if (err) { + return dev_err_probe(dev, err, + "Failed to find <recvid> in of_node\n"); + } + mb->recvid = cpu; + + mb->mbox.dev = dev; + mb->mbox.num_chans = MAILBOX_MAX_CHAN; + mb->mbox.chans = mb->chans; + mb->mbox.ops = &cv1800b_mbox_chan_ops; + mb->mbox.txdone_poll = true; + + irq = platform_get_irq_byname(pdev, "mailbox"); + err = devm_request_threaded_irq(dev, irq, cv1800b_mbox_irq, + cv1800b_mbox_isr, IRQF_ONESHOT, + dev_name(&pdev->dev), mb); + if (err < 0) + return dev_err_probe(dev, err, "Failed to register irq\n"); + + for (idx = 0; idx < MAILBOX_MAX_CHAN; idx++) + mb->mbox.chans[idx].con_priv = (void *)idx; + + err = devm_mbox_controller_register(dev, &mb->mbox); + if (err) + return dev_err_probe(dev, err, "Failed to register mailbox\n"); + + platform_set_drvdata(pdev, mb); + return 0; +} + +static struct platform_driver cv1800b_mbox_driver = { + .driver = { + .name = "cv1800b-mbox", + .of_match_table = cv1800b_mbox_of_match, + }, + .probe = cv1800b_mbox_probe, +}; + +module_platform_driver(cv1800b_mbox_driver); + +MODULE_DESCRIPTION("cv1800b mailbox driver"); +MODULE_LICENSE("GPL");
Add mailbox controller driver for cv18x SoCs, tested on mailbox-test client. Signed-off-by: Yuntao Dai <d1581209858@live.com> --- drivers/mailbox/Kconfig | 11 ++ drivers/mailbox/Makefile | 2 + drivers/mailbox/cv1800b-mailbox.c | 181 ++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/mailbox/cv1800b-mailbox.c