1142168ebSJonas Gorski /*
2142168ebSJonas Gorski * Broadcom BCM63XX High Speed SPI Controller driver
3142168ebSJonas Gorski *
4142168ebSJonas Gorski * Copyright 2000-2010 Broadcom Corporation
5879a879cSJonas Gorski * Copyright 2012-2013 Jonas Gorski <jonas.gorski@gmail.com>
6142168ebSJonas Gorski *
7142168ebSJonas Gorski * Licensed under the GNU/GPL. See COPYING for details.
8142168ebSJonas Gorski */
9142168ebSJonas Gorski
10142168ebSJonas Gorski #include <linux/kernel.h>
11142168ebSJonas Gorski #include <linux/init.h>
12142168ebSJonas Gorski #include <linux/io.h>
13142168ebSJonas Gorski #include <linux/clk.h>
14142168ebSJonas Gorski #include <linux/module.h>
15142168ebSJonas Gorski #include <linux/platform_device.h>
16142168ebSJonas Gorski #include <linux/delay.h>
17142168ebSJonas Gorski #include <linux/dma-mapping.h>
18142168ebSJonas Gorski #include <linux/err.h>
19142168ebSJonas Gorski #include <linux/interrupt.h>
20142168ebSJonas Gorski #include <linux/spi/spi.h>
21142168ebSJonas Gorski #include <linux/mutex.h>
227ab24635SJonas Gorski #include <linux/of.h>
23c6182a18SWilliam Zhang #include <linux/spi/spi-mem.h>
24c6182a18SWilliam Zhang #include <linux/mtd/spi-nor.h>
250eeadddbSÁlvaro Fernández Rojas #include <linux/reset.h>
26fb8695e3SÁlvaro Fernández Rojas #include <linux/pm_runtime.h>
27142168ebSJonas Gorski
28142168ebSJonas Gorski #define HSSPI_GLOBAL_CTRL_REG 0x0
29142168ebSJonas Gorski #define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
30142168ebSJonas Gorski #define GLOBAL_CTRL_CS_POLARITY_MASK 0x000000ff
31142168ebSJonas Gorski #define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT 8
32142168ebSJonas Gorski #define GLOBAL_CTRL_PLL_CLK_CTRL_MASK 0x0000ff00
33142168ebSJonas Gorski #define GLOBAL_CTRL_CLK_GATE_SSOFF BIT(16)
34142168ebSJonas Gorski #define GLOBAL_CTRL_CLK_POLARITY BIT(17)
35142168ebSJonas Gorski #define GLOBAL_CTRL_MOSI_IDLE BIT(18)
36142168ebSJonas Gorski
37142168ebSJonas Gorski #define HSSPI_GLOBAL_EXT_TRIGGER_REG 0x4
38142168ebSJonas Gorski
39142168ebSJonas Gorski #define HSSPI_INT_STATUS_REG 0x8
40142168ebSJonas Gorski #define HSSPI_INT_STATUS_MASKED_REG 0xc
41142168ebSJonas Gorski #define HSSPI_INT_MASK_REG 0x10
42142168ebSJonas Gorski
43142168ebSJonas Gorski #define HSSPI_PINGx_CMD_DONE(i) BIT((i * 8) + 0)
44142168ebSJonas Gorski #define HSSPI_PINGx_RX_OVER(i) BIT((i * 8) + 1)
45142168ebSJonas Gorski #define HSSPI_PINGx_TX_UNDER(i) BIT((i * 8) + 2)
46142168ebSJonas Gorski #define HSSPI_PINGx_POLL_TIMEOUT(i) BIT((i * 8) + 3)
47142168ebSJonas Gorski #define HSSPI_PINGx_CTRL_INVAL(i) BIT((i * 8) + 4)
48142168ebSJonas Gorski
49142168ebSJonas Gorski #define HSSPI_INT_CLEAR_ALL 0xff001f1f
50142168ebSJonas Gorski
51142168ebSJonas Gorski #define HSSPI_PINGPONG_COMMAND_REG(x) (0x80 + (x) * 0x40)
52142168ebSJonas Gorski #define PINGPONG_CMD_COMMAND_MASK 0xf
53142168ebSJonas Gorski #define PINGPONG_COMMAND_NOOP 0
54142168ebSJonas Gorski #define PINGPONG_COMMAND_START_NOW 1
55142168ebSJonas Gorski #define PINGPONG_COMMAND_START_TRIGGER 2
56142168ebSJonas Gorski #define PINGPONG_COMMAND_HALT 3
57142168ebSJonas Gorski #define PINGPONG_COMMAND_FLUSH 4
58142168ebSJonas Gorski #define PINGPONG_CMD_PROFILE_SHIFT 8
59142168ebSJonas Gorski #define PINGPONG_CMD_SS_SHIFT 12
60142168ebSJonas Gorski
61142168ebSJonas Gorski #define HSSPI_PINGPONG_STATUS_REG(x) (0x84 + (x) * 0x40)
6250a6620dSWilliam Zhang #define HSSPI_PINGPONG_STATUS_SRC_BUSY BIT(1)
63142168ebSJonas Gorski
64142168ebSJonas Gorski #define HSSPI_PROFILE_CLK_CTRL_REG(x) (0x100 + (x) * 0x20)
65142168ebSJonas Gorski #define CLK_CTRL_FREQ_CTRL_MASK 0x0000ffff
66142168ebSJonas Gorski #define CLK_CTRL_SPI_CLK_2X_SEL BIT(14)
67142168ebSJonas Gorski #define CLK_CTRL_ACCUM_RST_ON_LOOP BIT(15)
68142168ebSJonas Gorski
69142168ebSJonas Gorski #define HSSPI_PROFILE_SIGNAL_CTRL_REG(x) (0x104 + (x) * 0x20)
70142168ebSJonas Gorski #define SIGNAL_CTRL_LATCH_RISING BIT(12)
71142168ebSJonas Gorski #define SIGNAL_CTRL_LAUNCH_RISING BIT(13)
72142168ebSJonas Gorski #define SIGNAL_CTRL_ASYNC_INPUT_PATH BIT(16)
73142168ebSJonas Gorski
74142168ebSJonas Gorski #define HSSPI_PROFILE_MODE_CTRL_REG(x) (0x108 + (x) * 0x20)
75142168ebSJonas Gorski #define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT 8
76142168ebSJonas Gorski #define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT 12
77142168ebSJonas Gorski #define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT 16
78142168ebSJonas Gorski #define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT 18
79142168ebSJonas Gorski #define MODE_CTRL_MODE_3WIRE BIT(20)
80142168ebSJonas Gorski #define MODE_CTRL_PREPENDBYTE_CNT_SHIFT 24
81142168ebSJonas Gorski
82142168ebSJonas Gorski #define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
83142168ebSJonas Gorski
84142168ebSJonas Gorski
85f4d86223SJonas Gorski #define HSSPI_OP_MULTIBIT BIT(11)
86142168ebSJonas Gorski #define HSSPI_OP_CODE_SHIFT 13
87142168ebSJonas Gorski #define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
88142168ebSJonas Gorski #define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
89142168ebSJonas Gorski #define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
90142168ebSJonas Gorski #define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
91142168ebSJonas Gorski #define HSSPI_OP_SETIRQ (4 << HSSPI_OP_CODE_SHIFT)
92142168ebSJonas Gorski
93142168ebSJonas Gorski #define HSSPI_BUFFER_LEN 512
94142168ebSJonas Gorski #define HSSPI_OPCODE_LEN 2
95142168ebSJonas Gorski
96142168ebSJonas Gorski #define HSSPI_MAX_PREPEND_LEN 15
97142168ebSJonas Gorski
98b7a82103SWilliam Zhang /*
99b7a82103SWilliam Zhang * Some chip require 30MHz but other require 25MHz. Use smaller value to cover
100b7a82103SWilliam Zhang * both cases.
101b7a82103SWilliam Zhang */
102b7a82103SWilliam Zhang #define HSSPI_MAX_SYNC_CLOCK 25000000
103142168ebSJonas Gorski
1047ab24635SJonas Gorski #define HSSPI_SPI_MAX_CS 8
105142168ebSJonas Gorski #define HSSPI_BUS_NUM 1 /* 0 is legacy SPI */
10650a6620dSWilliam Zhang #define HSSPI_POLL_STATUS_TIMEOUT_MS 100
10750a6620dSWilliam Zhang
10850a6620dSWilliam Zhang #define HSSPI_WAIT_MODE_POLLING 0
10950a6620dSWilliam Zhang #define HSSPI_WAIT_MODE_INTR 1
11050a6620dSWilliam Zhang #define HSSPI_WAIT_MODE_MAX HSSPI_WAIT_MODE_INTR
111142168ebSJonas Gorski
112b7a82103SWilliam Zhang /*
113b7a82103SWilliam Zhang * Default transfer mode is auto. If the msg is prependable, use the prepend
114b7a82103SWilliam Zhang * mode. If not, falls back to use the dummy cs workaround mode but limit the
115b7a82103SWilliam Zhang * clock to 25MHz to make sure it works in all board design.
116b7a82103SWilliam Zhang */
117b7a82103SWilliam Zhang #define HSSPI_XFER_MODE_AUTO 0
118b7a82103SWilliam Zhang #define HSSPI_XFER_MODE_PREPEND 1
119b7a82103SWilliam Zhang #define HSSPI_XFER_MODE_DUMMYCS 2
120b7a82103SWilliam Zhang #define HSSPI_XFER_MODE_MAX HSSPI_XFER_MODE_DUMMYCS
121b7a82103SWilliam Zhang
122b7a82103SWilliam Zhang #define bcm63xx_prepend_printk_on_checkfail(bs, fmt, ...) \
123b7a82103SWilliam Zhang do { \
124b7a82103SWilliam Zhang if (bs->xfer_mode == HSSPI_XFER_MODE_AUTO) \
125b7a82103SWilliam Zhang dev_dbg(&bs->pdev->dev, fmt, ##__VA_ARGS__); \
126b7a82103SWilliam Zhang else if (bs->xfer_mode == HSSPI_XFER_MODE_PREPEND) \
127b7a82103SWilliam Zhang dev_err(&bs->pdev->dev, fmt, ##__VA_ARGS__); \
128b7a82103SWilliam Zhang } while (0)
129b7a82103SWilliam Zhang
130142168ebSJonas Gorski struct bcm63xx_hsspi {
131142168ebSJonas Gorski struct completion done;
132142168ebSJonas Gorski struct mutex bus_mutex;
13350a6620dSWilliam Zhang struct mutex msg_mutex;
134142168ebSJonas Gorski struct platform_device *pdev;
135142168ebSJonas Gorski struct clk *clk;
1360fd85869SJonas Gorski struct clk *pll_clk;
137142168ebSJonas Gorski void __iomem *regs;
138142168ebSJonas Gorski u8 __iomem *fifo;
139142168ebSJonas Gorski
140142168ebSJonas Gorski u32 speed_hz;
141142168ebSJonas Gorski u8 cs_polarity;
14250a6620dSWilliam Zhang u32 wait_mode;
143b7a82103SWilliam Zhang u32 xfer_mode;
144b7a82103SWilliam Zhang u32 prepend_cnt;
145b7a82103SWilliam Zhang u8 *prepend_buf;
14650a6620dSWilliam Zhang };
14750a6620dSWilliam Zhang
wait_mode_show(struct device * dev,struct device_attribute * attr,char * buf)14850a6620dSWilliam Zhang static ssize_t wait_mode_show(struct device *dev, struct device_attribute *attr,
14950a6620dSWilliam Zhang char *buf)
15050a6620dSWilliam Zhang {
15150a6620dSWilliam Zhang struct spi_controller *ctrl = dev_get_drvdata(dev);
152*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
15350a6620dSWilliam Zhang
15450a6620dSWilliam Zhang return sprintf(buf, "%d\n", bs->wait_mode);
15550a6620dSWilliam Zhang }
15650a6620dSWilliam Zhang
wait_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)15750a6620dSWilliam Zhang static ssize_t wait_mode_store(struct device *dev, struct device_attribute *attr,
15850a6620dSWilliam Zhang const char *buf, size_t count)
15950a6620dSWilliam Zhang {
16050a6620dSWilliam Zhang struct spi_controller *ctrl = dev_get_drvdata(dev);
161*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
16250a6620dSWilliam Zhang u32 val;
16350a6620dSWilliam Zhang
16450a6620dSWilliam Zhang if (kstrtou32(buf, 10, &val))
16550a6620dSWilliam Zhang return -EINVAL;
16650a6620dSWilliam Zhang
16750a6620dSWilliam Zhang if (val > HSSPI_WAIT_MODE_MAX) {
16850a6620dSWilliam Zhang dev_warn(dev, "invalid wait mode %u\n", val);
16950a6620dSWilliam Zhang return -EINVAL;
17050a6620dSWilliam Zhang }
17150a6620dSWilliam Zhang
17250a6620dSWilliam Zhang mutex_lock(&bs->msg_mutex);
17350a6620dSWilliam Zhang bs->wait_mode = val;
17450a6620dSWilliam Zhang /* clear interrupt status to avoid spurious int on next transfer */
17550a6620dSWilliam Zhang if (val == HSSPI_WAIT_MODE_INTR)
17650a6620dSWilliam Zhang __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
17750a6620dSWilliam Zhang mutex_unlock(&bs->msg_mutex);
17850a6620dSWilliam Zhang
17950a6620dSWilliam Zhang return count;
18050a6620dSWilliam Zhang }
18150a6620dSWilliam Zhang
18250a6620dSWilliam Zhang static DEVICE_ATTR_RW(wait_mode);
18350a6620dSWilliam Zhang
xfer_mode_show(struct device * dev,struct device_attribute * attr,char * buf)184b7a82103SWilliam Zhang static ssize_t xfer_mode_show(struct device *dev, struct device_attribute *attr,
185b7a82103SWilliam Zhang char *buf)
186b7a82103SWilliam Zhang {
187b7a82103SWilliam Zhang struct spi_controller *ctrl = dev_get_drvdata(dev);
188*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
189b7a82103SWilliam Zhang
190b7a82103SWilliam Zhang return sprintf(buf, "%d\n", bs->xfer_mode);
191b7a82103SWilliam Zhang }
192b7a82103SWilliam Zhang
xfer_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)193b7a82103SWilliam Zhang static ssize_t xfer_mode_store(struct device *dev, struct device_attribute *attr,
194b7a82103SWilliam Zhang const char *buf, size_t count)
195b7a82103SWilliam Zhang {
196b7a82103SWilliam Zhang struct spi_controller *ctrl = dev_get_drvdata(dev);
197*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl);
198b7a82103SWilliam Zhang u32 val;
199b7a82103SWilliam Zhang
200b7a82103SWilliam Zhang if (kstrtou32(buf, 10, &val))
201b7a82103SWilliam Zhang return -EINVAL;
202b7a82103SWilliam Zhang
203b7a82103SWilliam Zhang if (val > HSSPI_XFER_MODE_MAX) {
204b7a82103SWilliam Zhang dev_warn(dev, "invalid xfer mode %u\n", val);
205b7a82103SWilliam Zhang return -EINVAL;
206b7a82103SWilliam Zhang }
207b7a82103SWilliam Zhang
208b7a82103SWilliam Zhang mutex_lock(&bs->msg_mutex);
209b7a82103SWilliam Zhang bs->xfer_mode = val;
210b7a82103SWilliam Zhang mutex_unlock(&bs->msg_mutex);
211b7a82103SWilliam Zhang
212b7a82103SWilliam Zhang return count;
213b7a82103SWilliam Zhang }
214b7a82103SWilliam Zhang
215b7a82103SWilliam Zhang static DEVICE_ATTR_RW(xfer_mode);
216b7a82103SWilliam Zhang
21750a6620dSWilliam Zhang static struct attribute *bcm63xx_hsspi_attrs[] = {
21850a6620dSWilliam Zhang &dev_attr_wait_mode.attr,
219b7a82103SWilliam Zhang &dev_attr_xfer_mode.attr,
22050a6620dSWilliam Zhang NULL,
22150a6620dSWilliam Zhang };
22250a6620dSWilliam Zhang
22350a6620dSWilliam Zhang static const struct attribute_group bcm63xx_hsspi_group = {
22450a6620dSWilliam Zhang .attrs = bcm63xx_hsspi_attrs,
225142168ebSJonas Gorski };
226142168ebSJonas Gorski
227b7a82103SWilliam Zhang static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
228b7a82103SWilliam Zhang struct spi_device *spi, int hz);
229b7a82103SWilliam Zhang
bcm63xx_hsspi_max_message_size(struct spi_device * spi)230b7a82103SWilliam Zhang static size_t bcm63xx_hsspi_max_message_size(struct spi_device *spi)
231b7a82103SWilliam Zhang {
232b7a82103SWilliam Zhang return HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN;
233b7a82103SWilliam Zhang }
234b7a82103SWilliam Zhang
bcm63xx_hsspi_wait_cmd(struct bcm63xx_hsspi * bs)235b7a82103SWilliam Zhang static int bcm63xx_hsspi_wait_cmd(struct bcm63xx_hsspi *bs)
236b7a82103SWilliam Zhang {
237b7a82103SWilliam Zhang unsigned long limit;
238b7a82103SWilliam Zhang u32 reg = 0;
239b7a82103SWilliam Zhang int rc = 0;
240b7a82103SWilliam Zhang
241b7a82103SWilliam Zhang if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) {
242b7a82103SWilliam Zhang if (wait_for_completion_timeout(&bs->done, HZ) == 0)
243b7a82103SWilliam Zhang rc = 1;
244b7a82103SWilliam Zhang } else {
245b7a82103SWilliam Zhang /* polling mode checks for status busy bit */
246b7a82103SWilliam Zhang limit = jiffies + msecs_to_jiffies(HSSPI_POLL_STATUS_TIMEOUT_MS);
247b7a82103SWilliam Zhang
248b7a82103SWilliam Zhang while (!time_after(jiffies, limit)) {
249b7a82103SWilliam Zhang reg = __raw_readl(bs->regs + HSSPI_PINGPONG_STATUS_REG(0));
250b7a82103SWilliam Zhang if (reg & HSSPI_PINGPONG_STATUS_SRC_BUSY)
251b7a82103SWilliam Zhang cpu_relax();
252b7a82103SWilliam Zhang else
253b7a82103SWilliam Zhang break;
254b7a82103SWilliam Zhang }
255b7a82103SWilliam Zhang if (reg & HSSPI_PINGPONG_STATUS_SRC_BUSY)
256b7a82103SWilliam Zhang rc = 1;
257b7a82103SWilliam Zhang }
258b7a82103SWilliam Zhang
259b7a82103SWilliam Zhang if (rc)
260b7a82103SWilliam Zhang dev_err(&bs->pdev->dev, "transfer timed out!\n");
261b7a82103SWilliam Zhang
262b7a82103SWilliam Zhang return rc;
263b7a82103SWilliam Zhang }
264b7a82103SWilliam Zhang
bcm63xx_prepare_prepend_transfer(struct spi_controller * host,struct spi_message * msg,struct spi_transfer * t_prepend)265*2c40be6bSYang Yingliang static bool bcm63xx_prepare_prepend_transfer(struct spi_controller *host,
266b7a82103SWilliam Zhang struct spi_message *msg,
267b7a82103SWilliam Zhang struct spi_transfer *t_prepend)
268b7a82103SWilliam Zhang {
269b7a82103SWilliam Zhang
270*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
271b7a82103SWilliam Zhang bool tx_only = false;
272b7a82103SWilliam Zhang struct spi_transfer *t;
273b7a82103SWilliam Zhang
274b7a82103SWilliam Zhang /*
275b7a82103SWilliam Zhang * Multiple transfers within a message may be combined into one transfer
276b7a82103SWilliam Zhang * to the controller using its prepend feature. A SPI message is prependable
277b7a82103SWilliam Zhang * only if the following are all true:
278b7a82103SWilliam Zhang * 1. One or more half duplex write transfer in single bit mode
279b7a82103SWilliam Zhang * 2. Optional full duplex read/write at the end
280b7a82103SWilliam Zhang * 3. No delay and cs_change between transfers
281b7a82103SWilliam Zhang */
282b7a82103SWilliam Zhang bs->prepend_cnt = 0;
283b7a82103SWilliam Zhang list_for_each_entry(t, &msg->transfers, transfer_list) {
284b7a82103SWilliam Zhang if ((spi_delay_to_ns(&t->delay, t) > 0) || t->cs_change) {
285b7a82103SWilliam Zhang bcm63xx_prepend_printk_on_checkfail(bs,
286b7a82103SWilliam Zhang "Delay or cs change not supported in prepend mode!\n");
287b7a82103SWilliam Zhang return false;
288b7a82103SWilliam Zhang }
289b7a82103SWilliam Zhang
290b7a82103SWilliam Zhang tx_only = false;
291b7a82103SWilliam Zhang if (t->tx_buf && !t->rx_buf) {
292b7a82103SWilliam Zhang tx_only = true;
293b7a82103SWilliam Zhang if (bs->prepend_cnt + t->len >
294b7a82103SWilliam Zhang (HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN)) {
295b7a82103SWilliam Zhang bcm63xx_prepend_printk_on_checkfail(bs,
296b7a82103SWilliam Zhang "exceed max buf len, abort prepending transfers!\n");
297b7a82103SWilliam Zhang return false;
298b7a82103SWilliam Zhang }
299b7a82103SWilliam Zhang
300b7a82103SWilliam Zhang if (t->tx_nbits > SPI_NBITS_SINGLE &&
301b7a82103SWilliam Zhang !list_is_last(&t->transfer_list, &msg->transfers)) {
302b7a82103SWilliam Zhang bcm63xx_prepend_printk_on_checkfail(bs,
303b7a82103SWilliam Zhang "multi-bit prepend buf not supported!\n");
304b7a82103SWilliam Zhang return false;
305b7a82103SWilliam Zhang }
306b7a82103SWilliam Zhang
307b7a82103SWilliam Zhang if (t->tx_nbits == SPI_NBITS_SINGLE) {
308b7a82103SWilliam Zhang memcpy(bs->prepend_buf + bs->prepend_cnt, t->tx_buf, t->len);
309b7a82103SWilliam Zhang bs->prepend_cnt += t->len;
310b7a82103SWilliam Zhang }
311b7a82103SWilliam Zhang } else {
312b7a82103SWilliam Zhang if (!list_is_last(&t->transfer_list, &msg->transfers)) {
313b7a82103SWilliam Zhang bcm63xx_prepend_printk_on_checkfail(bs,
314b7a82103SWilliam Zhang "rx/tx_rx transfer not supported when it is not last one!\n");
315b7a82103SWilliam Zhang return false;
316b7a82103SWilliam Zhang }
317b7a82103SWilliam Zhang }
318b7a82103SWilliam Zhang
319b7a82103SWilliam Zhang if (list_is_last(&t->transfer_list, &msg->transfers)) {
320b7a82103SWilliam Zhang memcpy(t_prepend, t, sizeof(struct spi_transfer));
321b7a82103SWilliam Zhang
322b7a82103SWilliam Zhang if (tx_only && t->tx_nbits == SPI_NBITS_SINGLE) {
323b7a82103SWilliam Zhang /*
324b7a82103SWilliam Zhang * if the last one is also a single bit tx only transfer, merge
325b7a82103SWilliam Zhang * all of them into one single tx transfer
326b7a82103SWilliam Zhang */
327b7a82103SWilliam Zhang t_prepend->len = bs->prepend_cnt;
328b7a82103SWilliam Zhang t_prepend->tx_buf = bs->prepend_buf;
329b7a82103SWilliam Zhang bs->prepend_cnt = 0;
330b7a82103SWilliam Zhang } else {
331b7a82103SWilliam Zhang /*
332b7a82103SWilliam Zhang * if the last one is not a tx only transfer or dual tx xfer, all
333b7a82103SWilliam Zhang * the previous transfers are sent through prepend bytes and
334b7a82103SWilliam Zhang * make sure it does not exceed the max prepend len
335b7a82103SWilliam Zhang */
336b7a82103SWilliam Zhang if (bs->prepend_cnt > HSSPI_MAX_PREPEND_LEN) {
337b7a82103SWilliam Zhang bcm63xx_prepend_printk_on_checkfail(bs,
338b7a82103SWilliam Zhang "exceed max prepend len, abort prepending transfers!\n");
339b7a82103SWilliam Zhang return false;
340b7a82103SWilliam Zhang }
341b7a82103SWilliam Zhang }
342b7a82103SWilliam Zhang }
343b7a82103SWilliam Zhang }
344b7a82103SWilliam Zhang
345b7a82103SWilliam Zhang return true;
346b7a82103SWilliam Zhang }
347b7a82103SWilliam Zhang
bcm63xx_hsspi_do_prepend_txrx(struct spi_device * spi,struct spi_transfer * t)348b7a82103SWilliam Zhang static int bcm63xx_hsspi_do_prepend_txrx(struct spi_device *spi,
349b7a82103SWilliam Zhang struct spi_transfer *t)
350b7a82103SWilliam Zhang {
351*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
3529e264f3fSAmit Kumar Mahapatra via Alsa-devel unsigned int chip_select = spi_get_chipselect(spi, 0);
3532cca486cSWilliam Zhang u16 opcode = 0, val;
354b7a82103SWilliam Zhang const u8 *tx = t->tx_buf;
355b7a82103SWilliam Zhang u8 *rx = t->rx_buf;
356b7a82103SWilliam Zhang u32 reg = 0;
357b7a82103SWilliam Zhang
358b7a82103SWilliam Zhang /*
359b7a82103SWilliam Zhang * shouldn't happen as we set the max_message_size in the probe.
360b7a82103SWilliam Zhang * but check it again in case some driver does not honor the max size
361b7a82103SWilliam Zhang */
362b7a82103SWilliam Zhang if (t->len + bs->prepend_cnt > (HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN)) {
363b7a82103SWilliam Zhang dev_warn(&bs->pdev->dev,
364b7a82103SWilliam Zhang "Prepend message large than fifo size len %d prepend %d\n",
365b7a82103SWilliam Zhang t->len, bs->prepend_cnt);
366b7a82103SWilliam Zhang return -EINVAL;
367b7a82103SWilliam Zhang }
368b7a82103SWilliam Zhang
369b7a82103SWilliam Zhang bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
370b7a82103SWilliam Zhang
371b7a82103SWilliam Zhang if (tx && rx)
372b7a82103SWilliam Zhang opcode = HSSPI_OP_READ_WRITE;
373b7a82103SWilliam Zhang else if (tx)
374b7a82103SWilliam Zhang opcode = HSSPI_OP_WRITE;
375b7a82103SWilliam Zhang else if (rx)
376b7a82103SWilliam Zhang opcode = HSSPI_OP_READ;
377b7a82103SWilliam Zhang
378b7a82103SWilliam Zhang if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) ||
379b7a82103SWilliam Zhang (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) {
380b7a82103SWilliam Zhang opcode |= HSSPI_OP_MULTIBIT;
381b7a82103SWilliam Zhang
382b7a82103SWilliam Zhang if (t->rx_nbits == SPI_NBITS_DUAL) {
383b7a82103SWilliam Zhang reg |= 1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT;
384b7a82103SWilliam Zhang reg |= bs->prepend_cnt << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT;
385b7a82103SWilliam Zhang }
386b7a82103SWilliam Zhang if (t->tx_nbits == SPI_NBITS_DUAL) {
387b7a82103SWilliam Zhang reg |= 1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT;
388b7a82103SWilliam Zhang reg |= bs->prepend_cnt << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT;
389b7a82103SWilliam Zhang }
390b7a82103SWilliam Zhang }
391b7a82103SWilliam Zhang
392b7a82103SWilliam Zhang reg |= bs->prepend_cnt << MODE_CTRL_PREPENDBYTE_CNT_SHIFT;
393b7a82103SWilliam Zhang __raw_writel(reg | 0xff,
394b7a82103SWilliam Zhang bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
395b7a82103SWilliam Zhang
396b7a82103SWilliam Zhang reinit_completion(&bs->done);
397b7a82103SWilliam Zhang if (bs->prepend_cnt)
398b7a82103SWilliam Zhang memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, bs->prepend_buf,
399b7a82103SWilliam Zhang bs->prepend_cnt);
400b7a82103SWilliam Zhang if (tx)
401b7a82103SWilliam Zhang memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN + bs->prepend_cnt, tx,
402b7a82103SWilliam Zhang t->len);
403b7a82103SWilliam Zhang
4042cca486cSWilliam Zhang *(__be16 *)(&val) = cpu_to_be16(opcode | t->len);
4052cca486cSWilliam Zhang __raw_writew(val, bs->fifo);
406b7a82103SWilliam Zhang /* enable interrupt */
407b7a82103SWilliam Zhang if (bs->wait_mode == HSSPI_WAIT_MODE_INTR)
408b7a82103SWilliam Zhang __raw_writel(HSSPI_PINGx_CMD_DONE(0), bs->regs + HSSPI_INT_MASK_REG);
409b7a82103SWilliam Zhang
410b7a82103SWilliam Zhang /* start the transfer */
411b7a82103SWilliam Zhang reg = chip_select << PINGPONG_CMD_SS_SHIFT |
412b7a82103SWilliam Zhang chip_select << PINGPONG_CMD_PROFILE_SHIFT |
413b7a82103SWilliam Zhang PINGPONG_COMMAND_START_NOW;
414b7a82103SWilliam Zhang __raw_writel(reg, bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
415b7a82103SWilliam Zhang
416b7a82103SWilliam Zhang if (bcm63xx_hsspi_wait_cmd(bs))
417b7a82103SWilliam Zhang return -ETIMEDOUT;
418b7a82103SWilliam Zhang
419b7a82103SWilliam Zhang if (rx)
420b7a82103SWilliam Zhang memcpy_fromio(rx, bs->fifo, t->len);
421b7a82103SWilliam Zhang
422b7a82103SWilliam Zhang return 0;
423b7a82103SWilliam Zhang }
424b7a82103SWilliam Zhang
bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi * bs,unsigned int cs,bool active)425c3c25ea7SAravind Thokala static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned int cs,
426142168ebSJonas Gorski bool active)
427142168ebSJonas Gorski {
428142168ebSJonas Gorski u32 reg;
429142168ebSJonas Gorski
430142168ebSJonas Gorski mutex_lock(&bs->bus_mutex);
431142168ebSJonas Gorski reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
432142168ebSJonas Gorski
433142168ebSJonas Gorski reg &= ~BIT(cs);
434142168ebSJonas Gorski if (active == !(bs->cs_polarity & BIT(cs)))
435142168ebSJonas Gorski reg |= BIT(cs);
436142168ebSJonas Gorski
437142168ebSJonas Gorski __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
438142168ebSJonas Gorski mutex_unlock(&bs->bus_mutex);
439142168ebSJonas Gorski }
440142168ebSJonas Gorski
bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi * bs,struct spi_device * spi,int hz)441142168ebSJonas Gorski static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
442142168ebSJonas Gorski struct spi_device *spi, int hz)
443142168ebSJonas Gorski {
4449e264f3fSAmit Kumar Mahapatra via Alsa-devel unsigned int profile = spi_get_chipselect(spi, 0);
445142168ebSJonas Gorski u32 reg;
446142168ebSJonas Gorski
447142168ebSJonas Gorski reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
448142168ebSJonas Gorski __raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
449142168ebSJonas Gorski bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
450142168ebSJonas Gorski
451142168ebSJonas Gorski reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
452142168ebSJonas Gorski if (hz > HSSPI_MAX_SYNC_CLOCK)
453142168ebSJonas Gorski reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
454142168ebSJonas Gorski else
455142168ebSJonas Gorski reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
456142168ebSJonas Gorski __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
457142168ebSJonas Gorski
458142168ebSJonas Gorski mutex_lock(&bs->bus_mutex);
459142168ebSJonas Gorski /* setup clock polarity */
460142168ebSJonas Gorski reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
461142168ebSJonas Gorski reg &= ~GLOBAL_CTRL_CLK_POLARITY;
462142168ebSJonas Gorski if (spi->mode & SPI_CPOL)
463142168ebSJonas Gorski reg |= GLOBAL_CTRL_CLK_POLARITY;
464142168ebSJonas Gorski __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
465142168ebSJonas Gorski mutex_unlock(&bs->bus_mutex);
466142168ebSJonas Gorski }
467142168ebSJonas Gorski
bcm63xx_hsspi_do_txrx(struct spi_device * spi,struct spi_transfer * t)468142168ebSJonas Gorski static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
469142168ebSJonas Gorski {
470*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
4719e264f3fSAmit Kumar Mahapatra via Alsa-devel unsigned int chip_select = spi_get_chipselect(spi, 0);
4722cca486cSWilliam Zhang u16 opcode = 0, val;
473142168ebSJonas Gorski int pending = t->len;
474142168ebSJonas Gorski int step_size = HSSPI_BUFFER_LEN;
475142168ebSJonas Gorski const u8 *tx = t->tx_buf;
476142168ebSJonas Gorski u8 *rx = t->rx_buf;
477b7a82103SWilliam Zhang u32 reg = 0;
478142168ebSJonas Gorski
479142168ebSJonas Gorski bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
480c00d5e93SWilliam Zhang if (!t->cs_off)
4819e264f3fSAmit Kumar Mahapatra via Alsa-devel bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), true);
482142168ebSJonas Gorski
483142168ebSJonas Gorski if (tx && rx)
484142168ebSJonas Gorski opcode = HSSPI_OP_READ_WRITE;
485142168ebSJonas Gorski else if (tx)
486142168ebSJonas Gorski opcode = HSSPI_OP_WRITE;
487142168ebSJonas Gorski else if (rx)
488142168ebSJonas Gorski opcode = HSSPI_OP_READ;
489142168ebSJonas Gorski
490142168ebSJonas Gorski if (opcode != HSSPI_OP_READ)
491142168ebSJonas Gorski step_size -= HSSPI_OPCODE_LEN;
492142168ebSJonas Gorski
493f4d86223SJonas Gorski if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) ||
494811ff802SWilliam Zhang (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) {
495f4d86223SJonas Gorski opcode |= HSSPI_OP_MULTIBIT;
496f4d86223SJonas Gorski
497811ff802SWilliam Zhang if (t->rx_nbits == SPI_NBITS_DUAL)
498b7a82103SWilliam Zhang reg |= 1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT;
499811ff802SWilliam Zhang if (t->tx_nbits == SPI_NBITS_DUAL)
500b7a82103SWilliam Zhang reg |= 1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT;
501811ff802SWilliam Zhang }
502811ff802SWilliam Zhang
503b7a82103SWilliam Zhang __raw_writel(reg | 0xff,
504142168ebSJonas Gorski bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
505142168ebSJonas Gorski
506142168ebSJonas Gorski while (pending > 0) {
507142168ebSJonas Gorski int curr_step = min_t(int, step_size, pending);
508142168ebSJonas Gorski
509aa0fe826SAxel Lin reinit_completion(&bs->done);
510142168ebSJonas Gorski if (tx) {
511142168ebSJonas Gorski memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
512142168ebSJonas Gorski tx += curr_step;
513142168ebSJonas Gorski }
514142168ebSJonas Gorski
5152cca486cSWilliam Zhang *(__be16 *)(&val) = cpu_to_be16(opcode | curr_step);
5162cca486cSWilliam Zhang __raw_writew(val, bs->fifo);
517142168ebSJonas Gorski
518142168ebSJonas Gorski /* enable interrupt */
51950a6620dSWilliam Zhang if (bs->wait_mode == HSSPI_WAIT_MODE_INTR)
520142168ebSJonas Gorski __raw_writel(HSSPI_PINGx_CMD_DONE(0),
521142168ebSJonas Gorski bs->regs + HSSPI_INT_MASK_REG);
522142168ebSJonas Gorski
523b7a82103SWilliam Zhang reg = !chip_select << PINGPONG_CMD_SS_SHIFT |
524142168ebSJonas Gorski chip_select << PINGPONG_CMD_PROFILE_SHIFT |
525b7a82103SWilliam Zhang PINGPONG_COMMAND_START_NOW;
526b7a82103SWilliam Zhang __raw_writel(reg, bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
527142168ebSJonas Gorski
528b7a82103SWilliam Zhang if (bcm63xx_hsspi_wait_cmd(bs))
529b7a82103SWilliam Zhang return -ETIMEDOUT;
530142168ebSJonas Gorski
531142168ebSJonas Gorski if (rx) {
532142168ebSJonas Gorski memcpy_fromio(rx, bs->fifo, curr_step);
533142168ebSJonas Gorski rx += curr_step;
534142168ebSJonas Gorski }
535142168ebSJonas Gorski
536142168ebSJonas Gorski pending -= curr_step;
537142168ebSJonas Gorski }
538142168ebSJonas Gorski
539142168ebSJonas Gorski return 0;
540142168ebSJonas Gorski }
541142168ebSJonas Gorski
bcm63xx_hsspi_setup(struct spi_device * spi)542142168ebSJonas Gorski static int bcm63xx_hsspi_setup(struct spi_device *spi)
543142168ebSJonas Gorski {
544*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
545142168ebSJonas Gorski u32 reg;
546142168ebSJonas Gorski
547142168ebSJonas Gorski reg = __raw_readl(bs->regs +
5489e264f3fSAmit Kumar Mahapatra via Alsa-devel HSSPI_PROFILE_SIGNAL_CTRL_REG(spi_get_chipselect(spi, 0)));
549142168ebSJonas Gorski reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
550142168ebSJonas Gorski if (spi->mode & SPI_CPHA)
551142168ebSJonas Gorski reg |= SIGNAL_CTRL_LAUNCH_RISING;
552142168ebSJonas Gorski else
553142168ebSJonas Gorski reg |= SIGNAL_CTRL_LATCH_RISING;
554142168ebSJonas Gorski __raw_writel(reg, bs->regs +
5559e264f3fSAmit Kumar Mahapatra via Alsa-devel HSSPI_PROFILE_SIGNAL_CTRL_REG(spi_get_chipselect(spi, 0)));
556142168ebSJonas Gorski
557142168ebSJonas Gorski mutex_lock(&bs->bus_mutex);
558142168ebSJonas Gorski reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
559142168ebSJonas Gorski
560142168ebSJonas Gorski /* only change actual polarities if there is no transfer */
561142168ebSJonas Gorski if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) {
562142168ebSJonas Gorski if (spi->mode & SPI_CS_HIGH)
5639e264f3fSAmit Kumar Mahapatra via Alsa-devel reg |= BIT(spi_get_chipselect(spi, 0));
564142168ebSJonas Gorski else
5659e264f3fSAmit Kumar Mahapatra via Alsa-devel reg &= ~BIT(spi_get_chipselect(spi, 0));
566142168ebSJonas Gorski __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
567142168ebSJonas Gorski }
568142168ebSJonas Gorski
569142168ebSJonas Gorski if (spi->mode & SPI_CS_HIGH)
5709e264f3fSAmit Kumar Mahapatra via Alsa-devel bs->cs_polarity |= BIT(spi_get_chipselect(spi, 0));
571142168ebSJonas Gorski else
5729e264f3fSAmit Kumar Mahapatra via Alsa-devel bs->cs_polarity &= ~BIT(spi_get_chipselect(spi, 0));
573142168ebSJonas Gorski
574142168ebSJonas Gorski mutex_unlock(&bs->bus_mutex);
575142168ebSJonas Gorski
576142168ebSJonas Gorski return 0;
577142168ebSJonas Gorski }
578142168ebSJonas Gorski
bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device * spi,struct spi_message * msg)579b7a82103SWilliam Zhang static int bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device *spi,
580142168ebSJonas Gorski struct spi_message *msg)
581142168ebSJonas Gorski {
582*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller);
583142168ebSJonas Gorski int status = -EINVAL;
584142168ebSJonas Gorski int dummy_cs;
585c00d5e93SWilliam Zhang bool keep_cs = false;
586b7a82103SWilliam Zhang struct spi_transfer *t;
587142168ebSJonas Gorski
588b7a82103SWilliam Zhang /*
589b7a82103SWilliam Zhang * This controller does not support keeping CS active during idle.
590142168ebSJonas Gorski * To work around this, we use the following ugly hack:
591142168ebSJonas Gorski *
592142168ebSJonas Gorski * a. Invert the target chip select's polarity so it will be active.
593142168ebSJonas Gorski * b. Select a "dummy" chip select to use as the hardware target.
594142168ebSJonas Gorski * c. Invert the dummy chip select's polarity so it will be inactive
595142168ebSJonas Gorski * during the actual transfers.
596142168ebSJonas Gorski * d. Tell the hardware to send to the dummy chip select. Thanks to
597142168ebSJonas Gorski * the multiplexed nature of SPI the actual target will receive
598142168ebSJonas Gorski * the transfer and we see its response.
599142168ebSJonas Gorski *
600142168ebSJonas Gorski * e. At the end restore the polarities again to their default values.
601142168ebSJonas Gorski */
602142168ebSJonas Gorski
6039e264f3fSAmit Kumar Mahapatra via Alsa-devel dummy_cs = !spi_get_chipselect(spi, 0);
604142168ebSJonas Gorski bcm63xx_hsspi_set_cs(bs, dummy_cs, true);
605142168ebSJonas Gorski
606142168ebSJonas Gorski list_for_each_entry(t, &msg->transfers, transfer_list) {
607b7a82103SWilliam Zhang /*
608b7a82103SWilliam Zhang * We are here because one of reasons below:
609b7a82103SWilliam Zhang * a. Message is not prependable and in default auto xfer mode. This mean
610b7a82103SWilliam Zhang * we fallback to dummy cs mode at maximum 25MHz safe clock rate.
611b7a82103SWilliam Zhang * b. User set to use the dummy cs mode.
612b7a82103SWilliam Zhang */
613b7a82103SWilliam Zhang if (bs->xfer_mode == HSSPI_XFER_MODE_AUTO) {
614b7a82103SWilliam Zhang if (t->speed_hz > HSSPI_MAX_SYNC_CLOCK) {
615b7a82103SWilliam Zhang t->speed_hz = HSSPI_MAX_SYNC_CLOCK;
616b7a82103SWilliam Zhang dev_warn_once(&bs->pdev->dev,
617b7a82103SWilliam Zhang "Force to dummy cs mode. Reduce the speed to %dHz",
618b7a82103SWilliam Zhang t->speed_hz);
619b7a82103SWilliam Zhang }
620b7a82103SWilliam Zhang }
621b7a82103SWilliam Zhang
622142168ebSJonas Gorski status = bcm63xx_hsspi_do_txrx(spi, t);
623142168ebSJonas Gorski if (status)
624142168ebSJonas Gorski break;
625142168ebSJonas Gorski
626142168ebSJonas Gorski msg->actual_length += t->len;
627142168ebSJonas Gorski
628e74dc5c7SAlexandru Ardelean spi_transfer_delay_exec(t);
629142168ebSJonas Gorski
630c00d5e93SWilliam Zhang /* use existing cs change logic from spi_transfer_one_message */
631c00d5e93SWilliam Zhang if (t->cs_change) {
632c00d5e93SWilliam Zhang if (list_is_last(&t->transfer_list, &msg->transfers)) {
633c00d5e93SWilliam Zhang keep_cs = true;
634c00d5e93SWilliam Zhang } else {
635c00d5e93SWilliam Zhang if (!t->cs_off)
6369e264f3fSAmit Kumar Mahapatra via Alsa-devel bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), false);
637c00d5e93SWilliam Zhang
638c00d5e93SWilliam Zhang spi_transfer_cs_change_delay_exec(msg, t);
639c00d5e93SWilliam Zhang
640c00d5e93SWilliam Zhang if (!list_next_entry(t, transfer_list)->cs_off)
6419e264f3fSAmit Kumar Mahapatra via Alsa-devel bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), true);
642c00d5e93SWilliam Zhang }
643c00d5e93SWilliam Zhang } else if (!list_is_last(&t->transfer_list, &msg->transfers) &&
644c00d5e93SWilliam Zhang t->cs_off != list_next_entry(t, transfer_list)->cs_off) {
6459e264f3fSAmit Kumar Mahapatra via Alsa-devel bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), t->cs_off);
646c00d5e93SWilliam Zhang }
647142168ebSJonas Gorski }
648142168ebSJonas Gorski
649c00d5e93SWilliam Zhang bcm63xx_hsspi_set_cs(bs, dummy_cs, false);
650c00d5e93SWilliam Zhang if (status || !keep_cs)
6519e264f3fSAmit Kumar Mahapatra via Alsa-devel bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), false);
652142168ebSJonas Gorski
653b7a82103SWilliam Zhang return status;
654b7a82103SWilliam Zhang }
655b7a82103SWilliam Zhang
bcm63xx_hsspi_transfer_one(struct spi_controller * host,struct spi_message * msg)656*2c40be6bSYang Yingliang static int bcm63xx_hsspi_transfer_one(struct spi_controller *host,
657b7a82103SWilliam Zhang struct spi_message *msg)
658b7a82103SWilliam Zhang {
659*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
660b7a82103SWilliam Zhang struct spi_device *spi = msg->spi;
661b7a82103SWilliam Zhang int status = -EINVAL;
662b7a82103SWilliam Zhang bool prependable = false;
663b7a82103SWilliam Zhang struct spi_transfer t_prepend;
664b7a82103SWilliam Zhang
665b7a82103SWilliam Zhang mutex_lock(&bs->msg_mutex);
666b7a82103SWilliam Zhang
667b7a82103SWilliam Zhang if (bs->xfer_mode != HSSPI_XFER_MODE_DUMMYCS)
668*2c40be6bSYang Yingliang prependable = bcm63xx_prepare_prepend_transfer(host, msg, &t_prepend);
669b7a82103SWilliam Zhang
670b7a82103SWilliam Zhang if (prependable) {
671b7a82103SWilliam Zhang status = bcm63xx_hsspi_do_prepend_txrx(spi, &t_prepend);
672b7a82103SWilliam Zhang msg->actual_length = (t_prepend.len + bs->prepend_cnt);
673b7a82103SWilliam Zhang } else {
674b7a82103SWilliam Zhang if (bs->xfer_mode == HSSPI_XFER_MODE_PREPEND) {
675b7a82103SWilliam Zhang dev_err(&bs->pdev->dev,
676b7a82103SWilliam Zhang "User sets prepend mode but msg not prependable! Abort transfer\n");
677b7a82103SWilliam Zhang status = -EINVAL;
678b7a82103SWilliam Zhang } else
679b7a82103SWilliam Zhang status = bcm63xx_hsspi_do_dummy_cs_txrx(spi, msg);
680b7a82103SWilliam Zhang }
681b7a82103SWilliam Zhang
68250a6620dSWilliam Zhang mutex_unlock(&bs->msg_mutex);
683142168ebSJonas Gorski msg->status = status;
684*2c40be6bSYang Yingliang spi_finalize_current_message(host);
685142168ebSJonas Gorski
686142168ebSJonas Gorski return 0;
687142168ebSJonas Gorski }
688142168ebSJonas Gorski
bcm63xx_hsspi_mem_supports_op(struct spi_mem * mem,const struct spi_mem_op * op)689c6182a18SWilliam Zhang static bool bcm63xx_hsspi_mem_supports_op(struct spi_mem *mem,
690c6182a18SWilliam Zhang const struct spi_mem_op *op)
691c6182a18SWilliam Zhang {
692c6182a18SWilliam Zhang if (!spi_mem_default_supports_op(mem, op))
693c6182a18SWilliam Zhang return false;
694c6182a18SWilliam Zhang
695c6182a18SWilliam Zhang /* Controller doesn't support spi mem dual io mode */
696c6182a18SWilliam Zhang if ((op->cmd.opcode == SPINOR_OP_READ_1_2_2) ||
697c6182a18SWilliam Zhang (op->cmd.opcode == SPINOR_OP_READ_1_2_2_4B) ||
698c6182a18SWilliam Zhang (op->cmd.opcode == SPINOR_OP_READ_1_2_2_DTR) ||
699c6182a18SWilliam Zhang (op->cmd.opcode == SPINOR_OP_READ_1_2_2_DTR_4B))
700c6182a18SWilliam Zhang return false;
701c6182a18SWilliam Zhang
702c6182a18SWilliam Zhang return true;
703c6182a18SWilliam Zhang }
704c6182a18SWilliam Zhang
705c6182a18SWilliam Zhang static const struct spi_controller_mem_ops bcm63xx_hsspi_mem_ops = {
706c6182a18SWilliam Zhang .supports_op = bcm63xx_hsspi_mem_supports_op,
707c6182a18SWilliam Zhang };
708c6182a18SWilliam Zhang
bcm63xx_hsspi_interrupt(int irq,void * dev_id)709142168ebSJonas Gorski static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
710142168ebSJonas Gorski {
711142168ebSJonas Gorski struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id;
712142168ebSJonas Gorski
713142168ebSJonas Gorski if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0)
714142168ebSJonas Gorski return IRQ_NONE;
715142168ebSJonas Gorski
716142168ebSJonas Gorski __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
717142168ebSJonas Gorski __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
718142168ebSJonas Gorski
719142168ebSJonas Gorski complete(&bs->done);
720142168ebSJonas Gorski
721142168ebSJonas Gorski return IRQ_HANDLED;
722142168ebSJonas Gorski }
723142168ebSJonas Gorski
bcm63xx_hsspi_probe(struct platform_device * pdev)724142168ebSJonas Gorski static int bcm63xx_hsspi_probe(struct platform_device *pdev)
725142168ebSJonas Gorski {
726*2c40be6bSYang Yingliang struct spi_controller *host;
727142168ebSJonas Gorski struct bcm63xx_hsspi *bs;
728142168ebSJonas Gorski void __iomem *regs;
729142168ebSJonas Gorski struct device *dev = &pdev->dev;
7300fd85869SJonas Gorski struct clk *clk, *pll_clk = NULL;
731142168ebSJonas Gorski int irq, ret;
7327ab24635SJonas Gorski u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
7330eeadddbSÁlvaro Fernández Rojas struct reset_control *reset;
734142168ebSJonas Gorski
735142168ebSJonas Gorski irq = platform_get_irq(pdev, 0);
7366b8ac10eSStephen Boyd if (irq < 0)
737378da4a6SGustavo A. R. Silva return irq;
738142168ebSJonas Gorski
739e364c8c2SYueHaibing regs = devm_platform_ioremap_resource(pdev, 0);
740142168ebSJonas Gorski if (IS_ERR(regs))
741142168ebSJonas Gorski return PTR_ERR(regs);
742142168ebSJonas Gorski
743b1bdd4f8SJingoo Han clk = devm_clk_get(dev, "hsspi");
744142168ebSJonas Gorski
745142168ebSJonas Gorski if (IS_ERR(clk))
746142168ebSJonas Gorski return PTR_ERR(clk);
747142168ebSJonas Gorski
7480eeadddbSÁlvaro Fernández Rojas reset = devm_reset_control_get_optional_exclusive(dev, NULL);
7490eeadddbSÁlvaro Fernández Rojas if (IS_ERR(reset))
7500eeadddbSÁlvaro Fernández Rojas return PTR_ERR(reset);
7510eeadddbSÁlvaro Fernández Rojas
7520d7412edSStefan Potyra ret = clk_prepare_enable(clk);
7530d7412edSStefan Potyra if (ret)
7540d7412edSStefan Potyra return ret;
7550d7412edSStefan Potyra
7560eeadddbSÁlvaro Fernández Rojas ret = reset_control_reset(reset);
7570eeadddbSÁlvaro Fernández Rojas if (ret) {
7580eeadddbSÁlvaro Fernández Rojas dev_err(dev, "unable to reset device: %d\n", ret);
7590eeadddbSÁlvaro Fernández Rojas goto out_disable_clk;
7600eeadddbSÁlvaro Fernández Rojas }
7610eeadddbSÁlvaro Fernández Rojas
762142168ebSJonas Gorski rate = clk_get_rate(clk);
763ff18e1efSJonas Gorski if (!rate) {
7640fd85869SJonas Gorski pll_clk = devm_clk_get(dev, "pll");
765ff18e1efSJonas Gorski
7660d7412edSStefan Potyra if (IS_ERR(pll_clk)) {
7670d7412edSStefan Potyra ret = PTR_ERR(pll_clk);
7680d7412edSStefan Potyra goto out_disable_clk;
769ff18e1efSJonas Gorski }
770142168ebSJonas Gorski
7710d7412edSStefan Potyra ret = clk_prepare_enable(pll_clk);
772dea5de1bSJonas Gorski if (ret)
7730d7412edSStefan Potyra goto out_disable_clk;
7740d7412edSStefan Potyra
7750d7412edSStefan Potyra rate = clk_get_rate(pll_clk);
7760d7412edSStefan Potyra if (!rate) {
7770d7412edSStefan Potyra ret = -EINVAL;
7780fd85869SJonas Gorski goto out_disable_pll_clk;
7790d7412edSStefan Potyra }
7800d7412edSStefan Potyra }
781142168ebSJonas Gorski
782*2c40be6bSYang Yingliang host = spi_alloc_host(&pdev->dev, sizeof(*bs));
783*2c40be6bSYang Yingliang if (!host) {
784142168ebSJonas Gorski ret = -ENOMEM;
7850fd85869SJonas Gorski goto out_disable_pll_clk;
786142168ebSJonas Gorski }
787142168ebSJonas Gorski
788*2c40be6bSYang Yingliang bs = spi_controller_get_devdata(host);
789142168ebSJonas Gorski bs->pdev = pdev;
790142168ebSJonas Gorski bs->clk = clk;
7910fd85869SJonas Gorski bs->pll_clk = pll_clk;
792142168ebSJonas Gorski bs->regs = regs;
793142168ebSJonas Gorski bs->speed_hz = rate;
794142168ebSJonas Gorski bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
79550a6620dSWilliam Zhang bs->wait_mode = HSSPI_WAIT_MODE_POLLING;
796b7a82103SWilliam Zhang bs->prepend_buf = devm_kzalloc(dev, HSSPI_BUFFER_LEN, GFP_KERNEL);
797b7a82103SWilliam Zhang if (!bs->prepend_buf) {
798b7a82103SWilliam Zhang ret = -ENOMEM;
799*2c40be6bSYang Yingliang goto out_put_host;
800b7a82103SWilliam Zhang }
801142168ebSJonas Gorski
802142168ebSJonas Gorski mutex_init(&bs->bus_mutex);
80350a6620dSWilliam Zhang mutex_init(&bs->msg_mutex);
804aa0fe826SAxel Lin init_completion(&bs->done);
805142168ebSJonas Gorski
806*2c40be6bSYang Yingliang host->mem_ops = &bcm63xx_hsspi_mem_ops;
807*2c40be6bSYang Yingliang host->dev.of_node = dev->of_node;
8087ab24635SJonas Gorski if (!dev->of_node)
809*2c40be6bSYang Yingliang host->bus_num = HSSPI_BUS_NUM;
8107ab24635SJonas Gorski
8117ab24635SJonas Gorski of_property_read_u32(dev->of_node, "num-cs", &num_cs);
8127ab24635SJonas Gorski if (num_cs > 8) {
8137ab24635SJonas Gorski dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
8147ab24635SJonas Gorski num_cs);
8157ab24635SJonas Gorski num_cs = HSSPI_SPI_MAX_CS;
8167ab24635SJonas Gorski }
817*2c40be6bSYang Yingliang host->num_chipselect = num_cs;
818*2c40be6bSYang Yingliang host->setup = bcm63xx_hsspi_setup;
819*2c40be6bSYang Yingliang host->transfer_one_message = bcm63xx_hsspi_transfer_one;
820*2c40be6bSYang Yingliang host->max_transfer_size = bcm63xx_hsspi_max_message_size;
821*2c40be6bSYang Yingliang host->max_message_size = bcm63xx_hsspi_max_message_size;
822b7a82103SWilliam Zhang
823*2c40be6bSYang Yingliang host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
824f4d86223SJonas Gorski SPI_RX_DUAL | SPI_TX_DUAL;
825*2c40be6bSYang Yingliang host->bits_per_word_mask = SPI_BPW_MASK(8);
826*2c40be6bSYang Yingliang host->auto_runtime_pm = true;
827142168ebSJonas Gorski
828*2c40be6bSYang Yingliang platform_set_drvdata(pdev, host);
829142168ebSJonas Gorski
830142168ebSJonas Gorski /* Initialize the hardware */
831142168ebSJonas Gorski __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
832142168ebSJonas Gorski
833142168ebSJonas Gorski /* clean up any pending interrupts */
834142168ebSJonas Gorski __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
835142168ebSJonas Gorski
836142168ebSJonas Gorski /* read out default CS polarities */
837142168ebSJonas Gorski reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
838142168ebSJonas Gorski bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
839142168ebSJonas Gorski __raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
840142168ebSJonas Gorski bs->regs + HSSPI_GLOBAL_CTRL_REG);
841142168ebSJonas Gorski
84250a6620dSWilliam Zhang if (irq > 0) {
843142168ebSJonas Gorski ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
844142168ebSJonas Gorski pdev->name, bs);
845142168ebSJonas Gorski
846142168ebSJonas Gorski if (ret)
847*2c40be6bSYang Yingliang goto out_put_host;
84850a6620dSWilliam Zhang }
849142168ebSJonas Gorski
850fb8695e3SÁlvaro Fernández Rojas pm_runtime_enable(&pdev->dev);
851fb8695e3SÁlvaro Fernández Rojas
85297b7cea0SDan Carpenter ret = sysfs_create_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
85397b7cea0SDan Carpenter if (ret) {
85450a6620dSWilliam Zhang dev_err(&pdev->dev, "couldn't register sysfs group\n");
85550a6620dSWilliam Zhang goto out_pm_disable;
85650a6620dSWilliam Zhang }
85750a6620dSWilliam Zhang
858142168ebSJonas Gorski /* register and we are done */
859*2c40be6bSYang Yingliang ret = devm_spi_register_controller(dev, host);
860142168ebSJonas Gorski if (ret)
86150a6620dSWilliam Zhang goto out_sysgroup_disable;
86250a6620dSWilliam Zhang
86350a6620dSWilliam Zhang dev_info(dev, "Broadcom 63XX High Speed SPI Controller driver");
864142168ebSJonas Gorski
865142168ebSJonas Gorski return 0;
866142168ebSJonas Gorski
86750a6620dSWilliam Zhang out_sysgroup_disable:
86850a6620dSWilliam Zhang sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
869fb8695e3SÁlvaro Fernández Rojas out_pm_disable:
870fb8695e3SÁlvaro Fernández Rojas pm_runtime_disable(&pdev->dev);
871*2c40be6bSYang Yingliang out_put_host:
872*2c40be6bSYang Yingliang spi_controller_put(host);
8730fd85869SJonas Gorski out_disable_pll_clk:
8740fd85869SJonas Gorski clk_disable_unprepare(pll_clk);
875142168ebSJonas Gorski out_disable_clk:
876142168ebSJonas Gorski clk_disable_unprepare(clk);
877142168ebSJonas Gorski return ret;
878142168ebSJonas Gorski }
879142168ebSJonas Gorski
880142168ebSJonas Gorski
bcm63xx_hsspi_remove(struct platform_device * pdev)88104cd5f3fSUwe Kleine-König static void bcm63xx_hsspi_remove(struct platform_device *pdev)
882142168ebSJonas Gorski {
883*2c40be6bSYang Yingliang struct spi_controller *host = platform_get_drvdata(pdev);
884*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
885142168ebSJonas Gorski
886142168ebSJonas Gorski /* reset the hardware and block queue progress */
887142168ebSJonas Gorski __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
8880fd85869SJonas Gorski clk_disable_unprepare(bs->pll_clk);
889142168ebSJonas Gorski clk_disable_unprepare(bs->clk);
89050a6620dSWilliam Zhang sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group);
891142168ebSJonas Gorski }
892142168ebSJonas Gorski
893937ebf9cSJonas Gorski #ifdef CONFIG_PM_SLEEP
bcm63xx_hsspi_suspend(struct device * dev)894142168ebSJonas Gorski static int bcm63xx_hsspi_suspend(struct device *dev)
895142168ebSJonas Gorski {
896*2c40be6bSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
897*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
898142168ebSJonas Gorski
899*2c40be6bSYang Yingliang spi_controller_suspend(host);
9000fd85869SJonas Gorski clk_disable_unprepare(bs->pll_clk);
901937ebf9cSJonas Gorski clk_disable_unprepare(bs->clk);
902142168ebSJonas Gorski
903142168ebSJonas Gorski return 0;
904142168ebSJonas Gorski }
905142168ebSJonas Gorski
bcm63xx_hsspi_resume(struct device * dev)906142168ebSJonas Gorski static int bcm63xx_hsspi_resume(struct device *dev)
907142168ebSJonas Gorski {
908*2c40be6bSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
909*2c40be6bSYang Yingliang struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host);
910937ebf9cSJonas Gorski int ret;
911142168ebSJonas Gorski
912937ebf9cSJonas Gorski ret = clk_prepare_enable(bs->clk);
913937ebf9cSJonas Gorski if (ret)
914937ebf9cSJonas Gorski return ret;
915937ebf9cSJonas Gorski
9160fd85869SJonas Gorski if (bs->pll_clk) {
9170fd85869SJonas Gorski ret = clk_prepare_enable(bs->pll_clk);
9189bb9ef2bSQinglang Miao if (ret) {
9199bb9ef2bSQinglang Miao clk_disable_unprepare(bs->clk);
9200fd85869SJonas Gorski return ret;
9210fd85869SJonas Gorski }
9229bb9ef2bSQinglang Miao }
9230fd85869SJonas Gorski
924*2c40be6bSYang Yingliang spi_controller_resume(host);
925142168ebSJonas Gorski
926142168ebSJonas Gorski return 0;
927142168ebSJonas Gorski }
928142168ebSJonas Gorski #endif
929142168ebSJonas Gorski
9301480916eSJingoo Han static SIMPLE_DEV_PM_OPS(bcm63xx_hsspi_pm_ops, bcm63xx_hsspi_suspend,
9311480916eSJingoo Han bcm63xx_hsspi_resume);
932142168ebSJonas Gorski
9337ab24635SJonas Gorski static const struct of_device_id bcm63xx_hsspi_of_match[] = {
9347ab24635SJonas Gorski { .compatible = "brcm,bcm6328-hsspi", },
93599d7428aSWilliam Zhang { .compatible = "brcm,bcmbca-hsspi-v1.0", },
9367ab24635SJonas Gorski { },
9377ab24635SJonas Gorski };
9380b85a842SAndres Galacho MODULE_DEVICE_TABLE(of, bcm63xx_hsspi_of_match);
9397ab24635SJonas Gorski
940142168ebSJonas Gorski static struct platform_driver bcm63xx_hsspi_driver = {
941142168ebSJonas Gorski .driver = {
942142168ebSJonas Gorski .name = "bcm63xx-hsspi",
943937ebf9cSJonas Gorski .pm = &bcm63xx_hsspi_pm_ops,
9447ab24635SJonas Gorski .of_match_table = bcm63xx_hsspi_of_match,
945142168ebSJonas Gorski },
946142168ebSJonas Gorski .probe = bcm63xx_hsspi_probe,
94704cd5f3fSUwe Kleine-König .remove_new = bcm63xx_hsspi_remove,
948142168ebSJonas Gorski };
949142168ebSJonas Gorski
950142168ebSJonas Gorski module_platform_driver(bcm63xx_hsspi_driver);
951142168ebSJonas Gorski
952142168ebSJonas Gorski MODULE_ALIAS("platform:bcm63xx_hsspi");
953142168ebSJonas Gorski MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver");
954142168ebSJonas Gorski MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
955142168ebSJonas Gorski MODULE_LICENSE("GPL");
956