[PATCH 1/2] i2c: xiic: Implement Power management
Enable power management. This patch enables the clocks before transfer and disables after the transfer. Signed-off-by: Shubhrajyoti Datta <shubh...@xilinx.com> --- drivers/i2c/busses/i2c-xiic.c | 86 +--- 1 files changed, 79 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 0b20449..b464a35 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #define DRIVER_NAME "xiic-i2c" @@ -66,6 +68,7 @@ enum xiic_endian { * @endianness: big/little-endian byte order */ struct xiic_i2c { + struct device *dev; void __iomem*base; wait_queue_head_t wait; struct i2c_adapter adap; @@ -77,6 +80,7 @@ struct xiic_i2c { struct i2c_msg *rx_msg; int rx_pos; enum xiic_endianendianness; + struct clk *clk; }; @@ -164,6 +168,7 @@ struct xiic_i2c { #define XIIC_RESET_MASK 0xAUL +#define XIIC_PM_TIMEOUT1000/* ms */ /* * The following constant is used for the device global interrupt enable * register, to enable all interrupts for the device, this is the only bit @@ -676,9 +681,13 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); + err = pm_runtime_get_sync(i2c->dev); + if (err < 0) + return err; + err = xiic_busy(i2c); if (err) - return err; + goto out; i2c->tx_msg = msgs; i2c->nmsgs = num; @@ -686,14 +695,20 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) xiic_start_xfer(i2c); if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) - return (i2c->state == STATE_DONE) ? num : -EIO; - else { + (i2c->state == STATE_DONE), HZ)) { + err = (i2c->state == STATE_DONE) ? num : -EIO; + goto out; + } else { i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; - return -ETIMEDOUT; + err = -ETIMEDOUT; + goto out; } +out: + pm_runtime_mark_last_busy(i2c->dev); + pm_runtime_put_autosuspend(i2c->dev); + return err; } static u32 xiic_func(struct i2c_adapter *adap) @@ -748,13 +763,26 @@ static int xiic_i2c_probe(struct platform_device *pdev) spin_lock_init(>lock); init_waitqueue_head(>wait); + i2c->clk = devm_clk_get(>dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(>dev, "input clock not found.\n"); + return PTR_ERR(i2c->clk); + } + ret = clk_prepare_enable(i2c->clk); + if (ret) + dev_err(>dev, "Unable to enable clock.\n"); + + pm_runtime_enable(i2c->dev); + pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); + pm_runtime_use_autosuspend(i2c->dev); + pm_runtime_set_active(i2c->dev); ret = devm_request_threaded_irq(>dev, irq, xiic_isr, xiic_process, IRQF_ONESHOT, pdev->name, i2c); if (ret < 0) { dev_err(>dev, "Cannot claim IRQ\n"); - return ret; + goto err_clk_dis; } /* @@ -776,7 +804,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(>dev, "Failed to add adapter\n"); xiic_deinit(i2c); - return ret; + goto err_clk_dis; } if (pdata) { @@ -786,16 +814,30 @@ static int xiic_i2c_probe(struct platform_device *pdev) } return 0; + +err_clk_dis: + clk_disable_unprepare(i2c->clk); + pm_runtime_set_suspended(>dev); + pm_runtime_disable(>dev); + return ret; } static int xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); + int ret; /* remove adapter & data */ i2c_del_adapter(>adap); + ret = clk_prepare_enable(i2c->clk); + if (ret) { + dev_err(>dev, "Unable to enable clock.\n"); + return ret; + } xiic_deinit(i2c); + clk_disable_unprepare(i2c->clk); + pm_runtime_disable(>dev); return 0; } @@ -808,12 +850,42 @@ static const struct of_device_id x
[PATCH 2/2] bindings: i2c: Add clock entries for i2c-xiic
Add clock description for i2c-xiic Signed-off-by: Shubhrajyoti Datta <shubh...@xilinx.com> --- Documentation/devicetree/bindings/i2c/i2c-xiic.txt |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-xiic.txt b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt index ceabbe9..caf42e9 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-xiic.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt @@ -6,14 +6,17 @@ Required properties: - interrupts : IIC controller unterrupt - #address-cells = <1> - #size-cells = <0> +- clocks: Input clock specifier. Refer to common clock bindings. Optional properties: - Child nodes conforming to i2c bus binding +- clock-names: Input clock name, should be 'pclk'. Example: axi_iic_0: i2c@4080 { compatible = "xlnx,xps-iic-2.00.a"; + clocks = < 15>; interrupts = < 1 2 >; reg = < 0x4080 0x1 >; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [[PATCH v2] 2/2] Altera Modular ADC driver support
> +static int alt_modular_adc_probe(struct platform_device *pdev) > +{ > + struct altera_adc *adc; > + struct device_node *np = pdev->dev.of_node; > + struct iio_dev *indio_dev; > + struct resource *mem; > + int ret; > + > + if (!np) > + return -ENODEV; > + > + indio_dev = iio_device_alloc(sizeof(struct altera_adc)); > + if (!indio_dev) { > + dev_err(>dev, "failed allocating iio device\n"); > + return -ENOMEM; > + } > + > + adc = iio_priv(indio_dev); > + > + mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, > + "sequencer_csr"); > + adc->seq_regs = devm_ioremap_resource(>dev, mem); > + if (IS_ERR(adc->seq_regs)) { > + ret = PTR_ERR(adc->seq_regs); > + goto err_iio; > + } > + > + mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, > + "sample_store_csr"); > + adc->sample_regs = devm_ioremap_resource(>dev, mem); > + if (IS_ERR(adc->sample_regs)) { > + ret = PTR_ERR(adc->sample_regs); > + goto err_iio; > + } > + > + ret = alt_modular_adc_parse_dt(indio_dev, >dev); > + if (ret < 0) { > + dev_err(>dev, "failed to parse device tree\n"); > + goto err_iio; > + } > + > + ret = alt_modular_adc_channel_init(indio_dev); > + if (ret < 0) { > + dev_err(>dev, "failed initialize ADC channels\n"); > + goto err_iio; > + } > + > + platform_set_drvdata(pdev, indio_dev); > + > + indio_dev->name = dev_name(>dev); > + indio_dev->dev.parent = >dev; > + indio_dev->dev.of_node = pdev->dev.of_node; > + indio_dev->info = _iio_info; > + indio_dev->modes = INDIO_DIRECT_MODE; > + indio_dev->num_channels = adc->slot_count; > + > + ret = iio_device_register(indio_dev); > + if (ret) > + goto err_iio; > + > + /* Disable Interrupt */ > + writel_relaxed(0, (adc->sample_regs + ADC_IER_REG)); Why disable interrupts? > + > + /* Start Continuous Sampling */ > + writel_relaxed((ADC_RUN_MSK), (adc->seq_regs + ADC_CMD_REG)); > + > + return 0; > + > + > +err_iio: > + iio_device_free(indio_dev); > + return ret; > +} > + > +static int alt_modular_adc_remove(struct platform_device *pdev) > +{ > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); > + struct altera_adc *adc = iio_priv(indio_dev); > + > + /* Stop ADC */ > + writel((ADC_STOP_MSK), (adc->seq_regs + ADC_CMD_REG)); > + > + /* Unregister ADC */ > + iio_device_unregister(indio_dev); > + > + return 0; > +} > + > +static struct platform_driver altr_modular_adc_driver = { > + .probe = alt_modular_adc_probe, > + .remove = alt_modular_adc_remove, > + .driver = { > + .name = "alt-modular-adc", > + .owner = THIS_MODULE, > + .of_match_table = alt_modular_adc_match, > + }, > +}; > + > + > +module_platform_driver(altr_modular_adc_driver); > + > +MODULE_DESCRIPTION("Altera Modular ADC Driver"); > +MODULE_AUTHOR("Chee Nouk Phoon"); > +MODULE_LICENSE("GPL v2"); > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH-v5 2/5] i2c: pxa: enable/disable i2c module across msg xfer
hi , On Tue, Jul 21, 2015 at 6:11 PM, Vaibhav Hiremath vaibhav.hirem...@linaro.org wrote: From: Yi Zhang yizh...@marvell.com Enable i2c module/unit before transmission and disable when it finishes. why? It's because the i2c bus may be disturbed if the slave device, typically a touch, powers on. Why should that be an issue? Is it an errata. In which mode it is an issue slave / master or both? As we do not want to break slave mode support, this patch introduces DT property to control disable of the I2C module after xfer in master mode of operation. i2c-disable-after-xfer : If set, driver will disable I2C module after msg xfer Signed-off-by: Yi Zhang yizh...@marvell.com Signed-off-by: Vaibhav Hiremath vaibhav.hirem...@linaro.org --- -- To unsubscribe from this list: send the line unsubscribe devicetree in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] ARM64: zynqmp: Add eeprom memories on i2c bus
On Wed, Jul 29, 2015 at 7:49 PM, Michal Simek michal.si...@xilinx.com wrote: Add i2c eeprom memories on i2c bus. Thanks for the patch. Feel free to add Reviewed-by: Shubhrajyoti Datta shubh...@xilinx.com Signed-off-by: Michal Simek michal.si...@xilinx.com --- Changes in v2: - Change eeprom max freq from 100k to 400k --- arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts index c5cc8dbd0968..3b1011169756 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts @@ -50,6 +50,24 @@ status = okay; }; +i2c0 { + status = okay; + clock-frequency = 40; + eeprom@54 { + compatible = at,24c64; + reg = 0x54; + }; +}; + +i2c1 { + status = okay; + clock-frequency = 40; + eeprom@55 { + compatible = at,24c64; + reg = 0x55; + }; +}; + sata { status = okay; ceva,broken-gen2; -- 2.3.5 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line unsubscribe devicetree in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 7/7] ARM64: zynqmp: Add eeprom memories on i2c bus
Hi, On Mon, Jul 27, 2015 at 3:18 PM, Michal Simek michal.si...@xilinx.com wrote: Add i2c eeprom memories on i2c bus. Signed-off-by: Michal Simek michal.si...@xilinx.com --- arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts index 206e18eca2fb..47debdcbefbf 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts @@ -36,6 +36,24 @@ status = okay; }; +i2c0 { + status = okay; + clock-frequency = 10; If I am not wrong eeprom could work at 400k Could we make that as the speed. + eeprom@54 { + compatible = at,24c64; + reg = 0x54; + }; +}; + +i2c1 { + status = okay; + clock-frequency = 10; + eeprom@55 { + compatible = at,24c64; + reg = 0x55; + }; +}; + gem0 { status = okay; phy-handle = phy0; -- 2.3.5 ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line unsubscribe devicetree in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/2] dma: Add Xilinx zynqmp dma engine driver support
On Mon, Jun 15, 2015 at 8:06 PM, Punnaiah Choudary Kalluri punnaiah.choudary.kall...@xilinx.com wrote: Added the basic driver for zynqmp dma engine used in Zynq UltraScale+ MPSoC. The initial release of this driver supports only memory to memory transfers. Signed-off-by: Punnaiah Choudary Kalluri punn...@xilinx.com --- snip +/** + * zynqmp_dma_chan_is_idle - Provides the channel idle status + * @chan: ZynqMP DMA DMA channel pointer + * + * Return: '1' if the channel is idle otherwise '0' + */ +static int zynqmp_dma_chan_is_idle(struct zynqmp_dma_chan *chan) maybe this could return bool. +{ + u32 regval; + + regval = readl(chan-regs + STATUS); + if (regval STATUS_BUSY) + return 0; + + return 1; +} + -- To unsubscribe from this list: send the line unsubscribe devicetree in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [LINUX RFC V2 2/2] spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller
hi, Some minor comments. On Fri, Jun 5, 2015 at 6:37 PM, Ranjit Waghmode ranjit.waghm...@xilinx.com wrote: This patch adds support for GQSPI controller driver used by Zynq Ultrascale+ MPSoC Signed-off-by: Ranjit Waghmode ranjit.waghm...@xilinx.com --- Here is the v2 series. snip + */ +static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) +{ + struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi-master); + u32 genfifoentry = 0x0, statusreg, timeout; + + genfifoentry |= GQSPI_GENFIFO_MODE_SPI; + genfifoentry |= xqspi-genfifobus; + + if (!is_high) { + genfifoentry |= xqspi-genfifocs; + genfifoentry |= GQSPI_GENFIFO_CS_SETUP; + } else { + genfifoentry |= GQSPI_GENFIFO_CS_HOLD; + } + + zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry); + + /* Dummy generic FIFO entry */ + zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0); + + /* Manually start the generic FIFO command */ + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, + zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) | + GQSPI_CFG_START_GEN_FIFO_MASK); + timeout = 1; + /* Wait until the generic FIFO command is empty */ + do { + statusreg = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST); + timeout--; Can this be not busy. + } while (!(statusreg + GQSPI_ISR_GENFIFOEMPTY_MASK) +(statusreg GQSPI_ISR_TXEMPTY_MASK) timeout); + if (!timeout) + dev_err(xqspi-dev, Chip select timed out\n); +} + +/** + * zynqmp_qspi_setup_transfer: Configure QSPI controller for specified + * transfer + * @qspi: Pointer to the spi_device structure + * @transfer: Pointer to the spi_transfer structure which provides + * information about next transfer setup parameters + * + * Sets the operational mode of QSPI controller for the next QSPI transfer and + * sets the requested clock frequency. + * + * Return: Always 0 + * + * Note: + * If the requested frequency is not an exact match with what can be + * obtained using the pre-scalar value, the driver sets the clock + * frequency which is lower than the requested frequency (maximum lower) + * for the transfer. + * + * If the requested frequency is higher or lower than that is supported + * by the QSPI controller the driver will set the highest or lowest + * frequency supported by controller. + */ +static int zynqmp_qspi_setup_transfer(struct spi_device *qspi, + struct spi_transfer *transfer) +{ + struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi-master); + ulong clk_rate; + u32 config_reg, req_hz, baud_rate_val = 0; + + if (transfer) + req_hz = transfer-speed_hz; + else + req_hz = qspi-max_speed_hz; + + /* Set the clock frequency */ + /* If req_hz == 0, default to lowest speed */ + clk_rate = clk_get_rate(xqspi-refclk); + + while ((baud_rate_val GQSPI_BAUD_DIV_MAX) + (clk_rate / + (GQSPI_BAUD_DIV_SHIFT baud_rate_val)) req_hz) + baud_rate_val++; + + config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); + + /* Set the QSPI clock phase and clock polarity */ + config_reg = (~GQSPI_CFG_CLK_PHA_MASK) (~GQSPI_CFG_CLK_POL_MASK); + + if (qspi-mode SPI_CPHA) + config_reg |= GQSPI_CFG_CLK_PHA_MASK; + if (qspi-mode SPI_CPOL) + config_reg |= GQSPI_CFG_CLK_POL_MASK; + + config_reg = ~GQSPI_CFG_BAUD_RATE_DIV_MASK; + config_reg |= (baud_rate_val GQSPI_CFG_BAUD_RATE_DIV_SHIFT); + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg); + return 0; +} + +/** + * zynqmp_qspi_setup: Configure the QSPI controller + * @qspi: Pointer to the spi_device structure + * + * Sets the operational mode of QSPI controller for the next QSPI transfer, + * baud rate and divisor value to setup the requested qspi clock. + * + * Return: 0 Always doesnt seem to be true + */ +static int zynqmp_qspi_setup(struct spi_device *qspi) +{ + if (qspi-master-busy) + return -EBUSY; + return 0; +} + +/** + * zynqmp_qspi_filltxfifo: Fills the TX FIFO as long as there is room in + * the FIFO or the bytes required to be + * transmitted. + * @xqspi: Pointer to the zynqmp_qspi structure + * @size: Number of bytes to be copied from TX buffer to TX FIFO + */ +static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size) +{ + u32 count = 0, intermediate; + + while ((xqspi-bytes_to_transfer 0) (count size)) { +
Re: [PATCH 1/3] mailbox: Adding driver for Xilinx LogiCORE IP mailbox.
Hi Moritz, Overall looks good some nitpicks below. On Fri, May 22, 2015 at 5:07 AM, Moritz Fischer moritz.fisc...@ettus.com wrote: The Xilinx LogiCORE IP mailbox is a FPGA core that allows for interprocessor communication via AXI4 memory mapped / AXI4 stream interfaces. It is single channel per core and allows for transmit and receive. Signed-off-by: Moritz Fischer moritz.fisc...@ettus.com --- drivers/mailbox/Kconfig | 8 + drivers/mailbox/Makefile | 2 + drivers/mailbox/mailbox-xilinx.c | 339 ++ 3 files changed, 349 insertions(+) diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 84b0a2d..e11e4b2 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -60,4 +60,12 @@ config ALTERA_MBOX An implementation of the Altera Mailbox soft core. It is used to send message between processors. Say Y here if you want to use the Altera mailbox support. + +config XILINX_MBOX + tristate Xilinx Mailbox + help + An implementation of the Xilinx Mailbox soft core. It is used + to send message between processors. Say Y here if you want to use the + Xilinx mailbox support. + endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index b18201e..d28a028 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o obj-$(CONFIG_PCC) += pcc.o obj-$(CONFIG_ALTERA_MBOX) += mailbox-altera.o + +obj-$(CONFIG_XILINX_MBOX) += mailbox-xilinx.o diff --git a/drivers/mailbox/mailbox-xilinx.c b/drivers/mailbox/mailbox-xilinx.c new file mode 100644 index 000..8d8aa17 --- /dev/null +++ b/drivers/mailbox/mailbox-xilinx.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2015, National Instruments Corp. All rights reserved. + * + * Driver for the Xilinx Logicore mailbox IP block + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include linux/device.h +#include linux/interrupt.h +#include linux/io.h +#include linux/kernel.h +#include linux/mailbox_controller.h +#include linux/module.h +#include linux/of.h +#include linux/platform_device.h + +#define DRIVER_NAME xilinx-mailbox + +/* register offsets */ +#define MAILBOX_REG_WRDATA 0x00 +#define MAILBOX_REG_RDDATA 0x08 +#define MAILBOX_REG_STATUS 0x10 +#define MAILBOX_REG_ERROR 0x14 +#define MAILBOX_REG_SIT 0x18 +#define MAILBOX_REG_RIT 0x1c +#define MAILBOX_REG_IS 0x20 +#define MAILBOX_REG_IE 0x24 +#define MAILBOX_REG_IP 0x28 + +/* status register */ +#define STS_RTA BIT(3) +#define STS_STA BIT(2) +#define STS_FULL BIT(1) +#define STS_EMPTY BIT(0) + +/* error register */ +#define ERR_FULL BIT(1) +#define ERR_EMPTY BIT(0) + +/* mailbox interrupt status register */ +#define INT_STATUS_ERR BIT(2) +#define INT_STATUS_RTI BIT(1) +#define INT_STATUS_STI BIT(0) + +/* mailbox interrupt enable register */ +#define INT_ENABLE_ERR BIT(2) +#define INT_ENABLE_RTI BIT(1) +#define INT_ENABLE_STI BIT(0) + +#define MBOX_POLLING_MS5 /* polling interval 5ms */ + +struct xilinx_mbox { + bool intr_mode; + int irq; + void __iomem *mbox_base; + struct device *dev; + struct mbox_controller controller; + + /* if the controller supports only RX polling mode */ + struct timer_list rxpoll_timer; +}; + +static struct xilinx_mbox *mbox_chan_to_xilinx_mbox(struct mbox_chan *chan) +{ + if (!chan || !chan-con_priv) + return NULL; + + return (struct xilinx_mbox *)chan-con_priv; +} + +static inline int xilinx_mbox_full(struct xilinx_mbox *mbox) Should this be a bool ? +{ + u32 status; + + status = readl_relaxed(mbox-mbox_base + MAILBOX_REG_STATUS); + return status STS_FULL; +} + +static inline int xilinx_mbox_pending(struct xilinx_mbox *mbox) +{ + u32 status; + + status = readl_relaxed(mbox-mbox_base + MAILBOX_REG_STATUS); + return !(status STS_EMPTY); +} + +static void xilinx_mbox_rx_intmask(struct xilinx_mbox *mbox, bool enable) +{ + u32 mask; + + mask = readl_relaxed(mbox-mbox_base + MAILBOX_REG_IE); + if (enable) + mask |= INT_ENABLE_RTI; + else + mask = ~INT_ENABLE_RTI; + writel_relaxed(mask, mbox-mbox_base + MAILBOX_REG_IE); +} + +static void xilinx_mbox_tx_intmask(struct xilinx_mbox *mbox, bool enable) +{ +