Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox updates from Jassi Brar:

- New Hi3660 mailbox driver

- Fix TEGRA Kconfig warning

- Broadcom: use dma_pool_zalloc instead of dma_pool_alloc+memset

* tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
mailbox: Add support for Hi3660 mailbox
dt-bindings: mailbox: Introduce Hi3660 controller binding
mailbox: tegra: relax TEGRA_HSP_MBOX Kconfig dependencies
maillbox: bcm-flexrm-mailbox: Use dma_pool_zalloc()

+375 -3
+51
Documentation/devicetree/bindings/mailbox/hisilicon,hi3660-mailbox.txt
··· 1 + Hisilicon Hi3660 Mailbox Controller 2 + 3 + Hisilicon Hi3660 mailbox controller supports up to 32 channels. Messages 4 + are passed between processors, including application & communication 5 + processors, MCU, HIFI, etc. Each channel is unidirectional and accessed 6 + by using MMIO registers; it supports maximum to 8 words message. 7 + 8 + Controller 9 + ---------- 10 + 11 + Required properties: 12 + - compatible: : Shall be "hisilicon,hi3660-mbox" 13 + - reg: : Offset and length of the device's register set 14 + - #mbox-cells: : Must be 3 15 + <&phandle channel dst_irq ack_irq> 16 + phandle : Label name of controller 17 + channel : Channel number 18 + dst_irq : Remote interrupt vector 19 + ack_irq : Local interrupt vector 20 + 21 + - interrupts: : Contains the two IRQ lines for mailbox. 22 + 23 + Example: 24 + 25 + mailbox: mailbox@e896b000 { 26 + compatible = "hisilicon,hi3660-mbox"; 27 + reg = <0x0 0xe896b000 0x0 0x1000>; 28 + interrupts = <0x0 0xc0 0x4>, 29 + <0x0 0xc1 0x4>; 30 + #mbox-cells = <3>; 31 + }; 32 + 33 + Client 34 + ------ 35 + 36 + Required properties: 37 + - compatible : See the client docs 38 + - mboxes : Standard property to specify a Mailbox (See ./mailbox.txt) 39 + Cells must match 'mbox-cells' (See Controller docs above) 40 + 41 + Optional properties 42 + - mbox-names : Name given to channels seen in the 'mboxes' property. 43 + 44 + Example: 45 + 46 + stub_clock: stub_clock@e896b500 { 47 + compatible = "hisilicon,hi3660-stub-clk"; 48 + reg = <0x0 0xe896b500 0x0 0x0100>; 49 + #clock-cells = <1>; 50 + mboxes = <&mailbox 13 3 0>; 51 + };
+9 -1
drivers/mailbox/Kconfig
··· 108 108 multiple processors within the SoC. Select this driver if your 109 109 platform has support for the hardware block. 110 110 111 + config HI3660_MBOX 112 + tristate "Hi3660 Mailbox" 113 + depends on ARCH_HISI && OF 114 + help 115 + An implementation of the hi3660 mailbox. It is used to send message 116 + between application processors and other processors/MCU/DSP. Select 117 + Y here if you want to use Hi3660 mailbox controller. 118 + 111 119 config HI6220_MBOX 112 120 tristate "Hi6220 Mailbox" 113 121 depends on ARCH_HISI ··· 142 134 143 135 config TEGRA_HSP_MBOX 144 136 bool "Tegra HSP (Hardware Synchronization Primitives) Driver" 145 - depends on ARCH_TEGRA_186_SOC 137 + depends on ARCH_TEGRA 146 138 help 147 139 The Tegra HSP driver is used for the interprocessor communication 148 140 between different remote processors and host processors on Tegra186
+2
drivers/mailbox/Makefile
··· 27 27 28 28 obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o 29 29 30 + obj-$(CONFIG_HI3660_MBOX) += hi3660-mailbox.o 31 + 30 32 obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o 31 33 32 34 obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
+1 -2
drivers/mailbox/bcm-flexrm-mailbox.c
··· 1268 1268 } 1269 1269 1270 1270 /* Allocate completion memory */ 1271 - ring->cmpl_base = dma_pool_alloc(ring->mbox->cmpl_pool, 1271 + ring->cmpl_base = dma_pool_zalloc(ring->mbox->cmpl_pool, 1272 1272 GFP_KERNEL, &ring->cmpl_dma_base); 1273 1273 if (!ring->cmpl_base) { 1274 1274 dev_err(ring->mbox->dev, ··· 1277 1277 ret = -ENOMEM; 1278 1278 goto fail_free_bd_memory; 1279 1279 } 1280 - memset(ring->cmpl_base, 0, RING_CMPL_SIZE); 1281 1280 1282 1281 /* Request IRQ */ 1283 1282 if (ring->irq == UINT_MAX) {
+312
drivers/mailbox/hi3660-mailbox.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2017-2018 Hisilicon Limited. 3 + // Copyright (c) 2017-2018 Linaro Limited. 4 + 5 + #include <linux/bitops.h> 6 + #include <linux/delay.h> 7 + #include <linux/device.h> 8 + #include <linux/err.h> 9 + #include <linux/interrupt.h> 10 + #include <linux/io.h> 11 + #include <linux/iopoll.h> 12 + #include <linux/mailbox_controller.h> 13 + #include <linux/module.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/slab.h> 16 + 17 + #include "mailbox.h" 18 + 19 + #define MBOX_CHAN_MAX 32 20 + 21 + #define MBOX_RX 0x0 22 + #define MBOX_TX 0x1 23 + 24 + #define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x40)) 25 + #define MBOX_SRC_REG 0x00 26 + #define MBOX_DST_REG 0x04 27 + #define MBOX_DCLR_REG 0x08 28 + #define MBOX_DSTAT_REG 0x0c 29 + #define MBOX_MODE_REG 0x10 30 + #define MBOX_IMASK_REG 0x14 31 + #define MBOX_ICLR_REG 0x18 32 + #define MBOX_SEND_REG 0x1c 33 + #define MBOX_DATA_REG 0x20 34 + 35 + #define MBOX_IPC_LOCK_REG 0xa00 36 + #define MBOX_IPC_UNLOCK 0x1acce551 37 + 38 + #define MBOX_AUTOMATIC_ACK 1 39 + 40 + #define MBOX_STATE_IDLE BIT(4) 41 + #define MBOX_STATE_ACK BIT(7) 42 + 43 + #define MBOX_MSG_LEN 8 44 + 45 + /** 46 + * Hi3660 mailbox channel information 47 + * 48 + * A channel can be used for TX or RX, it can trigger remote 49 + * processor interrupt to notify remote processor and can receive 50 + * interrupt if has incoming message. 51 + * 52 + * @dst_irq: Interrupt vector for remote processor 53 + * @ack_irq: Interrupt vector for local processor 54 + */ 55 + struct hi3660_chan_info { 56 + unsigned int dst_irq; 57 + unsigned int ack_irq; 58 + }; 59 + 60 + /** 61 + * Hi3660 mailbox controller data 62 + * 63 + * Mailbox controller includes 32 channels and can allocate 64 + * channel for message transferring. 65 + * 66 + * @dev: Device to which it is attached 67 + * @base: Base address of the register mapping region 68 + * @chan: Representation of channels in mailbox controller 69 + * @mchan: Representation of channel info 70 + * @controller: Representation of a communication channel controller 71 + */ 72 + struct hi3660_mbox { 73 + struct device *dev; 74 + void __iomem *base; 75 + struct mbox_chan chan[MBOX_CHAN_MAX]; 76 + struct hi3660_chan_info mchan[MBOX_CHAN_MAX]; 77 + struct mbox_controller controller; 78 + }; 79 + 80 + static struct hi3660_mbox *to_hi3660_mbox(struct mbox_controller *mbox) 81 + { 82 + return container_of(mbox, struct hi3660_mbox, controller); 83 + } 84 + 85 + static int hi3660_mbox_check_state(struct mbox_chan *chan) 86 + { 87 + unsigned long ch = (unsigned long)chan->con_priv; 88 + struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox); 89 + struct hi3660_chan_info *mchan = &mbox->mchan[ch]; 90 + void __iomem *base = MBOX_BASE(mbox, ch); 91 + unsigned long val; 92 + unsigned int ret; 93 + 94 + /* Mailbox is idle so directly bail out */ 95 + if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) 96 + return 0; 97 + 98 + /* Wait for acknowledge from remote */ 99 + ret = readx_poll_timeout_atomic(readl, base + MBOX_MODE_REG, 100 + val, (val & MBOX_STATE_ACK), 1000, 300000); 101 + if (ret) { 102 + dev_err(mbox->dev, "%s: timeout for receiving ack\n", __func__); 103 + return ret; 104 + } 105 + 106 + /* Ensure channel is released */ 107 + writel(0xffffffff, base + MBOX_IMASK_REG); 108 + writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG); 109 + return 0; 110 + } 111 + 112 + static int hi3660_mbox_unlock(struct mbox_chan *chan) 113 + { 114 + struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox); 115 + unsigned int val, retry = 3; 116 + 117 + do { 118 + writel(MBOX_IPC_UNLOCK, mbox->base + MBOX_IPC_LOCK_REG); 119 + 120 + val = readl(mbox->base + MBOX_IPC_LOCK_REG); 121 + if (!val) 122 + break; 123 + 124 + udelay(10); 125 + } while (retry--); 126 + 127 + if (val) 128 + dev_err(mbox->dev, "%s: failed to unlock mailbox\n", __func__); 129 + 130 + return (!val) ? 0 : -ETIMEDOUT; 131 + } 132 + 133 + static int hi3660_mbox_acquire_channel(struct mbox_chan *chan) 134 + { 135 + unsigned long ch = (unsigned long)chan->con_priv; 136 + struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox); 137 + struct hi3660_chan_info *mchan = &mbox->mchan[ch]; 138 + void __iomem *base = MBOX_BASE(mbox, ch); 139 + unsigned int val, retry; 140 + 141 + for (retry = 10; retry; retry--) { 142 + /* Check if channel is in idle state */ 143 + if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) { 144 + writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG); 145 + 146 + /* Check ack bit has been set successfully */ 147 + val = readl(base + MBOX_SRC_REG); 148 + if (val & BIT(mchan->ack_irq)) 149 + break; 150 + } 151 + } 152 + 153 + if (!retry) 154 + dev_err(mbox->dev, "%s: failed to acquire channel\n", __func__); 155 + 156 + return retry ? 0 : -ETIMEDOUT; 157 + } 158 + 159 + static int hi3660_mbox_startup(struct mbox_chan *chan) 160 + { 161 + int ret; 162 + 163 + ret = hi3660_mbox_check_state(chan); 164 + if (ret) 165 + return ret; 166 + 167 + ret = hi3660_mbox_unlock(chan); 168 + if (ret) 169 + return ret; 170 + 171 + ret = hi3660_mbox_acquire_channel(chan); 172 + if (ret) 173 + return ret; 174 + 175 + return 0; 176 + } 177 + 178 + static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg) 179 + { 180 + unsigned long ch = (unsigned long)chan->con_priv; 181 + struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox); 182 + struct hi3660_chan_info *mchan = &mbox->mchan[ch]; 183 + void __iomem *base = MBOX_BASE(mbox, ch); 184 + u32 *buf = msg; 185 + unsigned int i; 186 + 187 + /* Ensure channel is released */ 188 + writel_relaxed(0xffffffff, base + MBOX_IMASK_REG); 189 + writel_relaxed(BIT(mchan->ack_irq), base + MBOX_SRC_REG); 190 + 191 + /* Clear mask for destination interrupt */ 192 + writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG); 193 + 194 + /* Config destination for interrupt vector */ 195 + writel_relaxed(BIT(mchan->dst_irq), base + MBOX_DST_REG); 196 + 197 + /* Automatic acknowledge mode */ 198 + writel_relaxed(MBOX_AUTOMATIC_ACK, base + MBOX_MODE_REG); 199 + 200 + /* Fill message data */ 201 + for (i = 0; i < MBOX_MSG_LEN; i++) 202 + writel_relaxed(buf[i], base + MBOX_DATA_REG + i * 4); 203 + 204 + /* Trigger data transferring */ 205 + writel(BIT(mchan->ack_irq), base + MBOX_SEND_REG); 206 + return 0; 207 + } 208 + 209 + static struct mbox_chan_ops hi3660_mbox_ops = { 210 + .startup = hi3660_mbox_startup, 211 + .send_data = hi3660_mbox_send_data, 212 + }; 213 + 214 + static struct mbox_chan *hi3660_mbox_xlate(struct mbox_controller *controller, 215 + const struct of_phandle_args *spec) 216 + { 217 + struct hi3660_mbox *mbox = to_hi3660_mbox(controller); 218 + struct hi3660_chan_info *mchan; 219 + unsigned int ch = spec->args[0]; 220 + 221 + if (ch >= MBOX_CHAN_MAX) { 222 + dev_err(mbox->dev, "Invalid channel idx %d\n", ch); 223 + return ERR_PTR(-EINVAL); 224 + } 225 + 226 + mchan = &mbox->mchan[ch]; 227 + mchan->dst_irq = spec->args[1]; 228 + mchan->ack_irq = spec->args[2]; 229 + 230 + return &mbox->chan[ch]; 231 + } 232 + 233 + static const struct of_device_id hi3660_mbox_of_match[] = { 234 + { .compatible = "hisilicon,hi3660-mbox", }, 235 + {}, 236 + }; 237 + 238 + MODULE_DEVICE_TABLE(of, hi3660_mbox_of_match); 239 + 240 + static int hi3660_mbox_probe(struct platform_device *pdev) 241 + { 242 + struct device *dev = &pdev->dev; 243 + struct hi3660_mbox *mbox; 244 + struct mbox_chan *chan; 245 + struct resource *res; 246 + unsigned long ch; 247 + int err; 248 + 249 + mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); 250 + if (!mbox) 251 + return -ENOMEM; 252 + 253 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 254 + mbox->base = devm_ioremap_resource(dev, res); 255 + if (IS_ERR(mbox->base)) 256 + return PTR_ERR(mbox->base); 257 + 258 + mbox->dev = dev; 259 + mbox->controller.dev = dev; 260 + mbox->controller.chans = mbox->chan; 261 + mbox->controller.num_chans = MBOX_CHAN_MAX; 262 + mbox->controller.ops = &hi3660_mbox_ops; 263 + mbox->controller.of_xlate = hi3660_mbox_xlate; 264 + 265 + /* Initialize mailbox channel data */ 266 + chan = mbox->chan; 267 + for (ch = 0; ch < MBOX_CHAN_MAX; ch++) 268 + chan[ch].con_priv = (void *)ch; 269 + 270 + err = mbox_controller_register(&mbox->controller); 271 + if (err) { 272 + dev_err(dev, "Failed to register mailbox %d\n", err); 273 + return err; 274 + } 275 + 276 + platform_set_drvdata(pdev, mbox); 277 + dev_info(dev, "Mailbox enabled\n"); 278 + return 0; 279 + } 280 + 281 + static int hi3660_mbox_remove(struct platform_device *pdev) 282 + { 283 + struct hi3660_mbox *mbox = platform_get_drvdata(pdev); 284 + 285 + mbox_controller_unregister(&mbox->controller); 286 + return 0; 287 + } 288 + 289 + static struct platform_driver hi3660_mbox_driver = { 290 + .probe = hi3660_mbox_probe, 291 + .remove = hi3660_mbox_remove, 292 + .driver = { 293 + .name = "hi3660-mbox", 294 + .of_match_table = hi3660_mbox_of_match, 295 + }, 296 + }; 297 + 298 + static int __init hi3660_mbox_init(void) 299 + { 300 + return platform_driver_register(&hi3660_mbox_driver); 301 + } 302 + core_initcall(hi3660_mbox_init); 303 + 304 + static void __exit hi3660_mbox_exit(void) 305 + { 306 + platform_driver_unregister(&hi3660_mbox_driver); 307 + } 308 + module_exit(hi3660_mbox_exit); 309 + 310 + MODULE_LICENSE("GPL"); 311 + MODULE_DESCRIPTION("Hisilicon Hi3660 Mailbox Controller"); 312 + MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");