[go: nahoru, domu]

1e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/*
2ca632f556697d45d67ed5cada7cedf3ddfe0db4bGrant Likely * Designware SPI core controller driver (refer pxa2xx_spi.c)
3e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang *
4e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * Copyright (c) 2009, Intel Corporation.
5e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang *
6e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * This program is free software; you can redistribute it and/or modify it
7e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * under the terms and conditions of the GNU General Public License,
8e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * version 2, as published by the Free Software Foundation.
9e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang *
10e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * This program is distributed in the hope it will be useful, but WITHOUT
11e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * more details.
14e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang */
15e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
16e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/dma-mapping.h>
17e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/interrupt.h>
18d7614de422c0b55db0c1013a6c72330187536004Paul Gortmaker#include <linux/module.h>
19e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/highmem.h>
20e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/delay.h>
215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
22e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/spi/spi.h>
23d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach#include <linux/gpio.h>
24e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
25ca632f556697d45d67ed5cada7cedf3ddfe0db4bGrant Likely#include "spi-dw.h"
26568a60eda2e90a11bb3d7f8ef3f6800e9b60d4e5Grant Likely
27e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#ifdef CONFIG_DEBUG_FS
28e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#include <linux/debugfs.h>
29e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#endif
30e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
31e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#define START_STATE	((void *)0)
32e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#define RUNNING_STATE	((void *)1)
33e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#define DONE_STATE	((void *)2)
34e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#define ERROR_STATE	((void *)-1)
35e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
36e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/* Slave spi_dev related */
37e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstruct chip_data {
38e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u16 cr0;
39e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 cs;			/* chip select pin */
40e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 n_bytes;		/* current is a 1/2/4 byte op */
41e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 tmode;		/* TR/TO/RO/EEPROM */
42e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 type;		/* SPI/SSP/MicroWire */
43e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
44e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 poll_mode;		/* 1 means use poll mode */
45e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
46e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 dma_width;
47e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 rx_threshold;
48e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 tx_threshold;
49e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 enable_dma;
50e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 bits_per_word;
51e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u16 clk_div;		/* baud rate divider */
52e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 speed_hz;		/* baud rate */
53e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	void (*cs_control)(u32 command);
54e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang};
55e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
56e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#ifdef CONFIG_DEBUG_FS
57e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#define SPI_REGS_BUFSIZE	1024
5853288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf,
5953288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko		size_t count, loff_t *ppos)
60e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
6153288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	struct dw_spi *dws = file->private_data;
62e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	char *buf;
63e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 len = 0;
64e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	ssize_t ret;
65e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
66e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
67e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!buf)
68e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return 0;
69e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
70e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
7153288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko			"%s registers:\n", dev_name(&dws->master->dev));
72e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
73e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			"=================================\n");
74e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
757eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"CTRL0: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL0));
76e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
777eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"CTRL1: \t\t0x%08x\n", dw_readl(dws, DW_SPI_CTRL1));
78e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
797eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"SSIENR: \t0x%08x\n", dw_readl(dws, DW_SPI_SSIENR));
80e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
817eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"SER: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SER));
82e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
837eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"BAUDR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_BAUDR));
84e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
857eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"TXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_TXFLTR));
86e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
877eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"RXFTLR: \t0x%08x\n", dw_readl(dws, DW_SPI_RXFLTR));
88e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
897eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"TXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_TXFLR));
90e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
917eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"RXFLR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_RXFLR));
92e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
937eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"SR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_SR));
94e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
957eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"IMR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_IMR));
96e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
977eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"ISR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_ISR));
98e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
997eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"DMACR: \t\t0x%08x\n", dw_readl(dws, DW_SPI_DMACR));
100e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
1017eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"DMATDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMATDLR));
102e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
1037eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			"DMARDLR: \t0x%08x\n", dw_readl(dws, DW_SPI_DMARDLR));
104e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
105e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			"=================================\n");
106e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
10753288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
108e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	kfree(buf);
109e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return ret;
110e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
111e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
11253288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic const struct file_operations dw_spi_regs_ops = {
113e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	.owner		= THIS_MODULE,
114234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd	.open		= simple_open,
11553288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	.read		= dw_spi_show_regs,
1166038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek		= default_llseek,
117e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang};
118e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
11953288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic int dw_spi_debugfs_init(struct dw_spi *dws)
120e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
12153288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	dws->debugfs = debugfs_create_dir("dw_spi", NULL);
122e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!dws->debugfs)
123e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return -ENOMEM;
124e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
125e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	debugfs_create_file("registers", S_IFREG | S_IRUGO,
12653288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko		dws->debugfs, (void *)dws, &dw_spi_regs_ops);
127e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return 0;
128e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
129e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
13053288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic void dw_spi_debugfs_remove(struct dw_spi *dws)
131e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
132fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han	debugfs_remove_recursive(dws->debugfs);
133e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
134e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
135e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#else
13653288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic inline int dw_spi_debugfs_init(struct dw_spi *dws)
137e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
13820a588fcc862df79d8fcafbc41950e3ae93dea09George Shore	return 0;
139e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
140e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
14153288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenkostatic inline void dw_spi_debugfs_remove(struct dw_spi *dws)
142e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
143e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
144e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang#endif /* CONFIG_DEBUG_FS */
145e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
1462ff271bf6505038d8c937e73438ea3c80c387439Alek Du/* Return the max entries we can fill into tx fifo */
1472ff271bf6505038d8c937e73438ea3c80c387439Alek Dustatic inline u32 tx_max(struct dw_spi *dws)
1482ff271bf6505038d8c937e73438ea3c80c387439Alek Du{
1492ff271bf6505038d8c937e73438ea3c80c387439Alek Du	u32 tx_left, tx_room, rxtx_gap;
1502ff271bf6505038d8c937e73438ea3c80c387439Alek Du
1512ff271bf6505038d8c937e73438ea3c80c387439Alek Du	tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
1527eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten	tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR);
1532ff271bf6505038d8c937e73438ea3c80c387439Alek Du
1542ff271bf6505038d8c937e73438ea3c80c387439Alek Du	/*
1552ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * Another concern is about the tx/rx mismatch, we
1562ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * though to use (dws->fifo_len - rxflr - txflr) as
1572ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * one maximum value for tx, but it doesn't cover the
1582ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * data which is out of tx/rx fifo and inside the
1592ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * shift registers. So a control from sw point of
1602ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 * view is taken.
1612ff271bf6505038d8c937e73438ea3c80c387439Alek Du	 */
1622ff271bf6505038d8c937e73438ea3c80c387439Alek Du	rxtx_gap =  ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx))
1632ff271bf6505038d8c937e73438ea3c80c387439Alek Du			/ dws->n_bytes;
1642ff271bf6505038d8c937e73438ea3c80c387439Alek Du
1652ff271bf6505038d8c937e73438ea3c80c387439Alek Du	return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap));
1662ff271bf6505038d8c937e73438ea3c80c387439Alek Du}
1672ff271bf6505038d8c937e73438ea3c80c387439Alek Du
1682ff271bf6505038d8c937e73438ea3c80c387439Alek Du/* Return the max entries we should read out of rx fifo */
1692ff271bf6505038d8c937e73438ea3c80c387439Alek Dustatic inline u32 rx_max(struct dw_spi *dws)
1702ff271bf6505038d8c937e73438ea3c80c387439Alek Du{
1712ff271bf6505038d8c937e73438ea3c80c387439Alek Du	u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
1722ff271bf6505038d8c937e73438ea3c80c387439Alek Du
173fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han	return min_t(u32, rx_left, dw_readw(dws, DW_SPI_RXFLR));
1742ff271bf6505038d8c937e73438ea3c80c387439Alek Du}
1752ff271bf6505038d8c937e73438ea3c80c387439Alek Du
1763b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Dustatic void dw_writer(struct dw_spi *dws)
177e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
1782ff271bf6505038d8c937e73438ea3c80c387439Alek Du	u32 max = tx_max(dws);
179de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang	u16 txw = 0;
180e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
1812ff271bf6505038d8c937e73438ea3c80c387439Alek Du	while (max--) {
1822ff271bf6505038d8c937e73438ea3c80c387439Alek Du		/* Set the tx word if the transfer's original "tx" is not null */
1832ff271bf6505038d8c937e73438ea3c80c387439Alek Du		if (dws->tx_end - dws->len) {
1842ff271bf6505038d8c937e73438ea3c80c387439Alek Du			if (dws->n_bytes == 1)
1852ff271bf6505038d8c937e73438ea3c80c387439Alek Du				txw = *(u8 *)(dws->tx);
1862ff271bf6505038d8c937e73438ea3c80c387439Alek Du			else
1872ff271bf6505038d8c937e73438ea3c80c387439Alek Du				txw = *(u16 *)(dws->tx);
1882ff271bf6505038d8c937e73438ea3c80c387439Alek Du		}
1897eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		dw_writew(dws, DW_SPI_DR, txw);
1902ff271bf6505038d8c937e73438ea3c80c387439Alek Du		dws->tx += dws->n_bytes;
191e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
192e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
193e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
1943b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Dustatic void dw_reader(struct dw_spi *dws)
195e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
1962ff271bf6505038d8c937e73438ea3c80c387439Alek Du	u32 max = rx_max(dws);
197de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang	u16 rxw;
198e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
1992ff271bf6505038d8c937e73438ea3c80c387439Alek Du	while (max--) {
2007eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		rxw = dw_readw(dws, DW_SPI_DR);
201de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang		/* Care rx only if the transfer's original "rx" is not null */
202de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang		if (dws->rx_end - dws->len) {
203de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang			if (dws->n_bytes == 1)
204de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang				*(u8 *)(dws->rx) = rxw;
205de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang			else
206de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang				*(u16 *)(dws->rx) = rxw;
207de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang		}
208de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang		dws->rx += dws->n_bytes;
209e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
210e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
211e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
212e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void *next_transfer(struct dw_spi *dws)
213e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
214e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_message *msg = dws->cur_msg;
215e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_transfer *trans = dws->cur_transfer;
216e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
217e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Move to next transfer */
218e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (trans->transfer_list.next != &msg->transfers) {
219e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dws->cur_transfer =
220e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			list_entry(trans->transfer_list.next,
221e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang					struct spi_transfer,
222e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang					transfer_list);
223e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return RUNNING_STATE;
224fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han	}
225fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han
226fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han	return DONE_STATE;
227e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
228e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
229e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/*
230e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * Note: first step is the protocol driver prepares
231e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * a dma-capable memory, and this func just need translate
232e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang * the virt addr to physical
233e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang */
234e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic int map_dma_buffers(struct dw_spi *dws)
235e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
2367063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	if (!dws->cur_msg->is_dma_mapped
2377063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		|| !dws->dma_inited
2387063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		|| !dws->cur_chip->enable_dma
2397063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		|| !dws->dma_ops)
240e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return 0;
241e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
242e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (dws->cur_transfer->tx_dma)
243e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dws->tx_dma = dws->cur_transfer->tx_dma;
244e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
245e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (dws->cur_transfer->rx_dma)
246e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dws->rx_dma = dws->cur_transfer->rx_dma;
247e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
248e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return 1;
249e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
250e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
251e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/* Caller already set message->status; dma and pio irqs are blocked */
252e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void giveback(struct dw_spi *dws)
253e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
254e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_transfer *last_transfer;
255e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_message *msg;
256e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
257e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	msg = dws->cur_msg;
258e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_msg = NULL;
259e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_transfer = NULL;
260e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->prev_chip = dws->cur_chip;
261e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_chip = NULL;
262e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->dma_mapped = 0;
263e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
26423e2c2aa45a213ea25636ac5add66c2507e7361bAxel Lin	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
265e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang					transfer_list);
266e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
267d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach	if (!last_transfer->cs_change)
26808a707b87874eaaa0f336ab604ecd6e5e9f286ddAndy Shevchenko		spi_chip_sel(dws, msg->spi, 0);
269e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
270ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	spi_finalize_current_message(dws->master);
271e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
272e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
273e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void int_error_stop(struct dw_spi *dws, const char *msg)
274e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
2758a33a373e5ffb6040c58ff41ea48ba21d5f8b5e9Alek Du	/* Stop the hw */
276e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 0);
277e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
278e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dev_err(&dws->master->dev, "%s\n", msg);
279e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_msg->state = ERROR_STATE;
280e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	tasklet_schedule(&dws->pump_transfers);
281e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
282e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
2837063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tangvoid dw_spi_xfer_done(struct dw_spi *dws)
284e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
28525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* Update total byte transferred return count actual bytes read */
286e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_msg->actual_length += dws->len;
287e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
288e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Move to next transfer */
289e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_msg->state = next_transfer(dws);
290e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
291e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Handle end of message */
292e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (dws->cur_msg->state == DONE_STATE) {
293e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dws->cur_msg->status = 0;
294e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		giveback(dws);
295e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	} else
296e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		tasklet_schedule(&dws->pump_transfers);
297e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
2987063c0d942a1af2993531fbe52b4c74c1db818c4Feng TangEXPORT_SYMBOL_GPL(dw_spi_xfer_done);
299e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
300e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic irqreturn_t interrupt_transfer(struct dw_spi *dws)
301e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
3027eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten	u16 irq_status = dw_readw(dws, DW_SPI_ISR);
303e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
304e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Error handling */
305e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
3067eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		dw_readw(dws, DW_SPI_TXOICR);
3077eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		dw_readw(dws, DW_SPI_RXOICR);
3087eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		dw_readw(dws, DW_SPI_RXUICR);
3093b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
310e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return IRQ_HANDLED;
311e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
312e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
3133b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du	dw_reader(dws);
3143b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du	if (dws->rx_end == dws->rx) {
3153b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		spi_mask_intr(dws, SPI_INT_TXEI);
3163b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		dw_spi_xfer_done(dws);
3173b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		return IRQ_HANDLED;
3183b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du	}
319552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	if (irq_status & SPI_INT_TXEI) {
320552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		spi_mask_intr(dws, SPI_INT_TXEI);
3213b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		dw_writer(dws);
3223b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		/* Enable TX irq always, it will be disabled when RX finished */
3233b8a4dd3ebfcc647260ad5c39ef4f73eb3a6b155Alek Du		spi_umask_intr(dws, SPI_INT_TXEI);
324e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
325e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
326e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return IRQ_HANDLED;
327e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
328e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
329e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic irqreturn_t dw_spi_irq(int irq, void *dev_id)
330e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
331e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct dw_spi *dws = dev_id;
3327eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten	u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
333cbcc062abb16d39839b3d8d4e3d20360fc21eb58Yong Wang
334cbcc062abb16d39839b3d8d4e3d20360fc21eb58Yong Wang	if (!irq_status)
335cbcc062abb16d39839b3d8d4e3d20360fc21eb58Yong Wang		return IRQ_NONE;
336e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
337e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!dws->cur_msg) {
338e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		spi_mask_intr(dws, SPI_INT_TXEI);
339e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return IRQ_HANDLED;
340e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
341e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
342e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return dws->transfer_handler(dws);
343e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
344e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
345e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/* Must be called inside pump_transfers() */
346e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void poll_transfer(struct dw_spi *dws)
347e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
3482ff271bf6505038d8c937e73438ea3c80c387439Alek Du	do {
3492ff271bf6505038d8c937e73438ea3c80c387439Alek Du		dw_writer(dws);
350de6efe0a966cf86b3c4039a610b2d4157db707f2Feng Tang		dw_reader(dws);
3512ff271bf6505038d8c937e73438ea3c80c387439Alek Du		cpu_relax();
3522ff271bf6505038d8c937e73438ea3c80c387439Alek Du	} while (dws->rx_end > dws->rx);
353e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
3547063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	dw_spi_xfer_done(dws);
355e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
356e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
357e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void pump_transfers(unsigned long data)
358e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
359e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct dw_spi *dws = (struct dw_spi *)data;
360e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_message *message = NULL;
361e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_transfer *transfer = NULL;
362e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_transfer *previous = NULL;
363e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_device *spi = NULL;
364e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct chip_data *chip = NULL;
365e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 bits = 0;
366e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 imask = 0;
367e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u8 cs_change = 0;
368552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	u16 txint_level = 0;
369e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u16 clk_div = 0;
370e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 speed = 0;
371e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	u32 cr0 = 0;
372e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
373e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Get current state information */
374e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	message = dws->cur_msg;
375e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	transfer = dws->cur_transfer;
376e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip = dws->cur_chip;
377e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi = message->spi;
378e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
379e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (message->state == ERROR_STATE) {
380e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		message->status = -EIO;
381e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		goto early_exit;
382e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
383e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
384e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Handle end of message */
385e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (message->state == DONE_STATE) {
386e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		message->status = 0;
387e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		goto early_exit;
388e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
389e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
390c3c6e231d860774037e7001ff3d536e5644fe2daAndy Shevchenko	/* Delay if requested at end of transfer */
391e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (message->state == RUNNING_STATE) {
392e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		previous = list_entry(transfer->transfer_list.prev,
393e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang					struct spi_transfer,
394e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang					transfer_list);
395e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		if (previous->delay_usecs)
396e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			udelay(previous->delay_usecs);
397e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
398e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
399e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->n_bytes = chip->n_bytes;
400e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->dma_width = chip->dma_width;
401e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cs_control = chip->cs_control;
402e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
403e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->rx_dma = transfer->rx_dma;
404e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->tx_dma = transfer->tx_dma;
405e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->tx = (void *)transfer->tx_buf;
406e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->tx_end = dws->tx + transfer->len;
407e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->rx = transfer->rx_buf;
408e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->rx_end = dws->rx + transfer->len;
409e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->len = dws->cur_transfer->len;
410e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (chip != dws->prev_chip)
411e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		cs_change = 1;
412e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
413e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	cr0 = chip->cr0;
414e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
415e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Handle per transfer options for bpw and speed */
416e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (transfer->speed_hz) {
417e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		speed = chip->speed_hz;
418e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
4190a8727e69778683495058852f783eeda141a754eThor Thayer		if ((transfer->speed_hz != speed) || (!chip->clk_div)) {
420e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			speed = transfer->speed_hz;
421e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
422e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			/* clk_div doesn't support odd number */
423e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			clk_div = dws->max_freq / speed;
424552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang			clk_div = (clk_div + 1) & 0xfffe;
425e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
426e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			chip->speed_hz = speed;
427e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			chip->clk_div = clk_div;
428e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		}
429e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
430e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (transfer->bits_per_word) {
431e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		bits = transfer->bits_per_word;
43224778be20f87d5aadb19624fc768b3159fa43efcStephen Warren		dws->n_bytes = dws->dma_width = bits >> 3;
433e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		cr0 = (bits - 1)
434e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (chip->type << SPI_FRF_OFFSET)
435e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (spi->mode << SPI_MODE_OFFSET)
436e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (chip->tmode << SPI_TMOD_OFFSET);
437e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
438e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	message->state = RUNNING_STATE;
439e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
440052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	/*
441052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	 * Adjust transfer mode if necessary. Requires platform dependent
442052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	 * chipselect mechanism.
443052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	 */
444052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	if (dws->cs_control) {
445052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore		if (dws->rx && dws->tx)
446e3e55ff5854655d8723ad8b307f02515aecc3df5Feng Tang			chip->tmode = SPI_TMOD_TR;
447052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore		else if (dws->rx)
448e3e55ff5854655d8723ad8b307f02515aecc3df5Feng Tang			chip->tmode = SPI_TMOD_RO;
449052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore		else
450e3e55ff5854655d8723ad8b307f02515aecc3df5Feng Tang			chip->tmode = SPI_TMOD_TO;
451052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore
452e3e55ff5854655d8723ad8b307f02515aecc3df5Feng Tang		cr0 &= ~SPI_TMOD_MASK;
453052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore		cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
454052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore	}
455052dc7c45d8f685fb3720a08331ba3e91e87937eGeorge Shore
456e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Check if current transfer is a DMA transaction */
457e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->dma_mapped = map_dma_buffers(dws);
458e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
459552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	/*
460552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	 * Interrupt mode
461552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	 * we only need set the TXEI IRQ, as TX/RX always happen syncronizely
462552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	 */
463e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!dws->dma_mapped && !chip->poll_mode) {
464552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		int templen = dws->len / dws->n_bytes;
465fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han
466552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		txint_level = dws->fifo_len / 2;
467552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		txint_level = (templen > txint_level) ? txint_level : templen;
468552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang
469fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han		imask |= SPI_INT_TXEI | SPI_INT_TXOI |
470fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han			 SPI_INT_RXUI | SPI_INT_RXOI;
471e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dws->transfer_handler = interrupt_transfer;
472e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
473e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
474e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/*
475e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 * Reprogram registers only if
476e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 *	1. chip select changes
477e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 *	2. clk_div is changed
478e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 *	3. control value changes
479e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 */
4807eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten	if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) {
481e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		spi_enable_chip(dws, 0);
482e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
4837eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		if (dw_readw(dws, DW_SPI_CTRL0) != cr0)
4847eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			dw_writew(dws, DW_SPI_CTRL0, cr0);
485e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
486552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
487d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach		spi_chip_sel(dws, spi, 1);
488552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang
4892f263d9d4f0432e4f7a708c95fab82f83ec14947Justin P. Mattock		/* Set the interrupt mask, for poll mode just disable all int */
490e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		spi_mask_intr(dws, 0xff);
491552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		if (imask)
492e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			spi_umask_intr(dws, imask);
493552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		if (txint_level)
4947eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			dw_writew(dws, DW_SPI_TXFLTR, txint_level);
495e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
496e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		spi_enable_chip(dws, 1);
497e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		if (cs_change)
498e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			dws->prev_chip = chip;
499e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
500e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
501e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (dws->dma_mapped)
5027063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		dws->dma_ops->dma_transfer(dws, cs_change);
503e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
504e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (chip->poll_mode)
505e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		poll_transfer(dws);
506e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
507e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return;
508e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
509e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangearly_exit:
510e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	giveback(dws);
511e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
512e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
513ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siachstatic int dw_spi_transfer_one_message(struct spi_master *master,
514ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach		struct spi_message *msg)
515e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
516ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	struct dw_spi *dws = spi_master_get_devdata(master);
517e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
518ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	dws->cur_msg = msg;
519c3c6e231d860774037e7001ff3d536e5644fe2daAndy Shevchenko	/* Initial message state */
520e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_msg->state = START_STATE;
521e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
522e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang						struct spi_transfer,
523e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang						transfer_list);
524e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
525e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
526ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	/* Launch transfers */
527e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	tasklet_schedule(&dws->pump_transfers);
528e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
529e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return 0;
530e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
531e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
532e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/* This may be called twice for each spi dev */
533e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic int dw_spi_setup(struct spi_device *spi)
534e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
535e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct dw_spi_chip *chip_info = NULL;
536e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct chip_data *chip;
537d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach	int ret;
538e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
539e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Only alloc on first setup */
540e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip = spi_get_ctldata(spi);
541e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!chip) {
542a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
543e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		if (!chip)
544e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			return -ENOMEM;
54543f627ac9de42607b2cdcc7a41f2bcc82187e06aBaruch Siach		spi_set_ctldata(spi, chip);
546e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
547e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
548e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/*
549e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 * Protocol drivers may change the chip settings, so...
550e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 * if chip_info exists, use it
551e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	 */
552e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip_info = spi->controller_data;
553e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
554e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* chip_info doesn't always exist */
555e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (chip_info) {
556e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		if (chip_info->cs_control)
557e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			chip->cs_control = chip_info->cs_control;
558e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
559e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->poll_mode = chip_info->poll_mode;
560e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->type = chip_info->type;
561e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
562e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->rx_threshold = 0;
563e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->tx_threshold = 0;
564e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
565e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->enable_dma = chip_info->enable_dma;
566e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
567e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
56824778be20f87d5aadb19624fc768b3159fa43efcStephen Warren	if (spi->bits_per_word == 8) {
569e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->n_bytes = 1;
570e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->dma_width = 1;
57124778be20f87d5aadb19624fc768b3159fa43efcStephen Warren	} else if (spi->bits_per_word == 16) {
572e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->n_bytes = 2;
573e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		chip->dma_width = 2;
574e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
575e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip->bits_per_word = spi->bits_per_word;
576e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
577552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	if (!spi->max_speed_hz) {
578552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		dev_err(&spi->dev, "No max speed HZ parameter\n");
579552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang		return -EINVAL;
580552e450929a7298cc8834fd2824a60b2e914f70eFeng Tang	}
581e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
582e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip->tmode = 0; /* Tx & Rx */
583e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Default SPI mode is SCPOL = 0, SCPH = 0 */
584e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	chip->cr0 = (chip->bits_per_word - 1)
585e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (chip->type << SPI_FRF_OFFSET)
586e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (spi->mode  << SPI_MODE_OFFSET)
587e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang			| (chip->tmode << SPI_TMOD_OFFSET);
588e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
589c3ce15bf2ae5cde3392944ad043b80f123510cdeAndy Shevchenko	if (spi->mode & SPI_LOOP)
590c3ce15bf2ae5cde3392944ad043b80f123510cdeAndy Shevchenko		chip->cr0 |= 1 << SPI_SRL_OFFSET;
591c3ce15bf2ae5cde3392944ad043b80f123510cdeAndy Shevchenko
592d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach	if (gpio_is_valid(spi->cs_gpio)) {
593d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach		ret = gpio_direction_output(spi->cs_gpio,
594d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach				!(spi->mode & SPI_CS_HIGH));
595d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach		if (ret)
596d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach			return ret;
597d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach	}
598d9c73bb8a3a5e4b76d2ad55da00d9ea776475c81Baruch Siach
599e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return 0;
600e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
601e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
602a97c883a16da7e0691a3be5465926c92a8da4da6Axel Linstatic void dw_spi_cleanup(struct spi_device *spi)
603a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin{
604a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin	struct chip_data *chip = spi_get_ctldata(spi);
605a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin
606a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin	kfree(chip);
607a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin	spi_set_ctldata(spi, NULL);
608a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin}
609a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin
610e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang/* Restart the controller, disable all interrupts, clean rx fifo */
611e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangstatic void spi_hw_init(struct dw_spi *dws)
612e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
613e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 0);
614e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_mask_intr(dws, 0xff);
615e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 1);
616c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang
617c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	/*
618c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	 * Try to detect the FIFO depth if not set by interface driver,
619c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	 * the depth could be from 2 to 256 from HW spec
620c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	 */
621c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	if (!dws->fifo_len) {
622c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang		u32 fifo;
623fadcace703bbb985a996d01141499bd8d1f7d5bcJingoo Han
624c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang		for (fifo = 2; fifo <= 257; fifo++) {
6257eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			dw_writew(dws, DW_SPI_TXFLTR, fifo);
6267eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten			if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
627c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang				break;
628c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang		}
629c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang
630c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang		dws->fifo_len = (fifo == 257) ? 0 : fifo;
6317eb187b3cd3f6f285d91a196dbefac9b6adbb07cH Hartley Sweeten		dw_writew(dws, DW_SPI_TXFLTR, 0);
632c587b6fa05106606053fc5e8e344f07cd34ace23Feng Tang	}
633e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
634e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
63504f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siachint dw_spi_add_host(struct device *dev, struct dw_spi *dws)
636e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
637e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	struct spi_master *master;
638e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	int ret;
639e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
640e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	BUG_ON(dws == NULL);
641e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
64204f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siach	master = spi_alloc_master(dev, 0);
64304f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siach	if (!master)
64404f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siach		return -ENOMEM;
645e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
646e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->master = master;
647e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->type = SSI_MOTO_SPI;
648e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->prev_chip = NULL;
649e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->dma_inited = 0;
650e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
651c3c6e231d860774037e7001ff3d536e5644fe2daAndy Shevchenko	snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
652e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
65304f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siach	ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
65440bfff85ffb5c85ffabcb6d71e64f70799595f89Liu, ShuoX			dws->name, dws);
655e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (ret < 0) {
656e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dev_err(&master->dev, "can not get IRQ\n");
657e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		goto err_free_master;
658e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
659e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
660c3ce15bf2ae5cde3392944ad043b80f123510cdeAndy Shevchenko	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
66124778be20f87d5aadb19624fc768b3159fa43efcStephen Warren	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
662e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	master->bus_num = dws->bus_num;
663e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	master->num_chipselect = dws->num_cs;
664e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	master->setup = dw_spi_setup;
665a97c883a16da7e0691a3be5465926c92a8da4da6Axel Lin	master->cleanup = dw_spi_cleanup;
666ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	master->transfer_one_message = dw_spi_transfer_one_message;
667765ee709eb40abf0c43c6d864ac6f01677b7fd5aAxel Lin	master->max_speed_hz = dws->max_freq;
6689c6de47d53a3ce8df1642ae67823688eb98a190aThor Thayer	master->dev.of_node = dev->of_node;
669e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
670e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Basic HW init */
671e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_hw_init(dws);
672e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
6737063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	if (dws->dma_ops && dws->dma_ops->dma_init) {
6747063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		ret = dws->dma_ops->dma_init(dws);
6757063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		if (ret) {
6767063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang			dev_warn(&master->dev, "DMA init failed\n");
6777063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang			dws->dma_inited = 0;
6787063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		}
6797063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	}
6807063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang
681ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	tasklet_init(&dws->pump_transfers, pump_transfers, (unsigned long)dws);
682e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
683e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_master_set_devdata(master, dws);
68404f421e7b0b10de3fae543dac4d324b449a1db6bBaruch Siach	ret = devm_spi_register_master(dev, master);
685e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (ret) {
686e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dev_err(&master->dev, "problem registering spi master\n");
687ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach		goto err_dma_exit;
688e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	}
689e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
69053288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	dw_spi_debugfs_init(dws);
691e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return 0;
692e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
693ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siacherr_dma_exit:
6947063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	if (dws->dma_ops && dws->dma_ops->dma_exit)
6957063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		dws->dma_ops->dma_exit(dws);
696e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 0);
697e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangerr_free_master:
698e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_master_put(master);
699e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return ret;
700e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
70179290a2aa2fd1c179a285218472092475630dc0eFeng TangEXPORT_SYMBOL_GPL(dw_spi_add_host);
702e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
703fd4a319bc933ae93e68935b21924a9ca4ba2d060Grant Likelyvoid dw_spi_remove_host(struct dw_spi *dws)
704e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
705e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (!dws)
706e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return;
70753288fe9bdc7e8a0265bbe9074f71f1a6c478008Andy Shevchenko	dw_spi_debugfs_remove(dws);
708e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
7097063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang	if (dws->dma_ops && dws->dma_ops->dma_exit)
7107063c0d942a1af2993531fbe52b4c74c1db818c4Feng Tang		dws->dma_ops->dma_exit(dws);
711e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 0);
712e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	/* Disable clk */
713e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_set_clk(dws, 0);
714e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
71579290a2aa2fd1c179a285218472092475630dc0eFeng TangEXPORT_SYMBOL_GPL(dw_spi_remove_host);
716e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
717e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangint dw_spi_suspend_host(struct dw_spi *dws)
718e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
719e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	int ret = 0;
720e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
721ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	ret = spi_master_suspend(dws->master);
722e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (ret)
723e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		return ret;
724e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_enable_chip(dws, 0);
725e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_set_clk(dws, 0);
726e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return ret;
727e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
72879290a2aa2fd1c179a285218472092475630dc0eFeng TangEXPORT_SYMBOL_GPL(dw_spi_suspend_host);
729e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
730e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tangint dw_spi_resume_host(struct dw_spi *dws)
731e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang{
732e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	int ret;
733e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
734e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	spi_hw_init(dws);
735ec37e8e1f0e376776dde5e9539af414d2ec31f71Baruch Siach	ret = spi_master_resume(dws->master);
736e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	if (ret)
737e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
738e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang	return ret;
739e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang}
74079290a2aa2fd1c179a285218472092475630dc0eFeng TangEXPORT_SYMBOL_GPL(dw_spi_resume_host);
741e24c745272072fd2abe55209f1949b7b7ee602a7Feng Tang
742e24c745272072fd2abe55209f1949b7b7ee602a7Feng TangMODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
743e24c745272072fd2abe55209f1949b7b7ee602a7Feng TangMODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
744e24c745272072fd2abe55209f1949b7b7ee602a7Feng TangMODULE_LICENSE("GPL v2");
745