#include <linux/spi/spi.h>
 #include <linux/scatterlist.h>
 #include <linux/module.h>
+#include <linux/of_gpio.h>
 
 #include "spi-dw.h"
 
        dws->num_cs = 4;
        dws->max_freq = clk_get_rate(dwsmmio->clk);
 
+       if (pdev->dev.of_node) {
+               int i;
+
+               for (i = 0; i < dws->num_cs; i++) {
+                       int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+                                       "cs-gpios", i);
+
+                       if (cs_gpio == -EPROBE_DEFER) {
+                               ret = cs_gpio;
+                               goto out;
+                       }
+
+                       if (gpio_is_valid(cs_gpio)) {
+                               ret = devm_gpio_request(&pdev->dev, cs_gpio,
+                                               dev_name(&pdev->dev));
+                               if (ret)
+                                       goto out;
+                       }
+               }
+       }
+
        ret = dw_spi_add_host(&pdev->dev, dws);
        if (ret)
                goto out;
 
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
 
 #include "spi-dw.h"
 
 #define DONE_STATE     ((void *)2)
 #define ERROR_STATE    ((void *)-1)
 
-#define MRST_SPI_DEASSERT      0
-#define MRST_SPI_ASSERT                1
-
 /* Slave spi_dev related */
 struct chip_data {
        u16 cr0;
        last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
                                        transfer_list);
 
-       if (!last_transfer->cs_change && dws->cs_control)
-               dws->cs_control(MRST_SPI_DEASSERT);
+       if (!last_transfer->cs_change)
+               spi_chip_sel(dws, dws->cur_msg->spi, 0);
 
        spi_finalize_current_message(dws->master);
 }
                        dw_writew(dws, DW_SPI_CTRL0, cr0);
 
                spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
-               spi_chip_sel(dws, spi->chip_select);
+               spi_chip_sel(dws, spi, 1);
 
                /* Set the interrupt mask, for poll mode just disable all int */
                spi_mask_intr(dws, 0xff);
 {
        struct dw_spi_chip *chip_info = NULL;
        struct chip_data *chip;
+       int ret;
 
        /* Only alloc on first setup */
        chip = spi_get_ctldata(spi);
                        | (spi->mode  << SPI_MODE_OFFSET)
                        | (chip->tmode << SPI_TMOD_OFFSET);
 
+       if (gpio_is_valid(spi->cs_gpio)) {
+               ret = gpio_direction_output(spi->cs_gpio,
+                               !(spi->mode & SPI_CS_HIGH));
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
 
 
 #include <linux/io.h>
 #include <linux/scatterlist.h>
+#include <linux/gpio.h>
 
 /* Register offsets */
 #define DW_SPI_CTRL0                   0x00
        dw_writel(dws, DW_SPI_BAUDR, div);
 }
 
-static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi,
+               int active)
 {
-       if (cs > dws->num_cs)
-               return;
+       u16 cs = spi->chip_select;
+       int gpio_val = active ? (spi->mode & SPI_CS_HIGH) :
+               !(spi->mode & SPI_CS_HIGH);
 
        if (dws->cs_control)
-               dws->cs_control(1);
+               dws->cs_control(active);
+       if (gpio_is_valid(spi->cs_gpio))
+               gpio_set_value(spi->cs_gpio, gpio_val);
 
-       dw_writel(dws, DW_SPI_SER, 1 << cs);
+       if (active)
+               dw_writel(dws, DW_SPI_SER, 1 << cs);
 }
 
 /* Disable IRQ bits */