[PATCH 1/2] i2c: xiic: Implement Power management

2016-01-04 Thread Shubhrajyoti Datta
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

2016-01-04 Thread Shubhrajyoti Datta
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

2015-09-04 Thread Shubhrajyoti Datta
> +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

2015-08-05 Thread Shubhrajyoti Datta
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

2015-07-29 Thread Shubhrajyoti Datta
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

2015-07-27 Thread Shubhrajyoti Datta
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

2015-06-15 Thread Shubhrajyoti Datta
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

2015-06-06 Thread Shubhrajyoti Datta
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.

2015-05-22 Thread Shubhrajyoti Datta
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)
 +{
 +