blob: 112479294d53b774913380576ddfa196be763151 [file] [log] [blame]
Vinod Koul2f52a512017-12-14 11:19:41 +05301// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2// Copyright(c) 2015-17 Intel Corporation.
3
4/*
5 * Cadence SoundWire Master module
6 * Used by Master driver
7 */
8
9#include <linux/delay.h>
10#include <linux/device.h>
11#include <linux/interrupt.h>
12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
14#include <linux/soundwire/sdw_registers.h>
15#include <linux/soundwire/sdw.h>
16#include "bus.h"
17#include "cadence_master.h"
18
19#define CDNS_MCP_CONFIG 0x0
20
21#define CDNS_MCP_CONFIG_MCMD_RETRY GENMASK(27, 24)
22#define CDNS_MCP_CONFIG_MPREQ_DELAY GENMASK(20, 16)
23#define CDNS_MCP_CONFIG_MMASTER BIT(7)
24#define CDNS_MCP_CONFIG_BUS_REL BIT(6)
25#define CDNS_MCP_CONFIG_SNIFFER BIT(5)
26#define CDNS_MCP_CONFIG_SSPMOD BIT(4)
27#define CDNS_MCP_CONFIG_CMD BIT(3)
28#define CDNS_MCP_CONFIG_OP GENMASK(2, 0)
29#define CDNS_MCP_CONFIG_OP_NORMAL 0
30
31#define CDNS_MCP_CONTROL 0x4
32
33#define CDNS_MCP_CONTROL_RST_DELAY GENMASK(10, 8)
34#define CDNS_MCP_CONTROL_CMD_RST BIT(7)
35#define CDNS_MCP_CONTROL_SOFT_RST BIT(6)
36#define CDNS_MCP_CONTROL_SW_RST BIT(5)
37#define CDNS_MCP_CONTROL_HW_RST BIT(4)
38#define CDNS_MCP_CONTROL_CLK_PAUSE BIT(3)
39#define CDNS_MCP_CONTROL_CLK_STOP_CLR BIT(2)
40#define CDNS_MCP_CONTROL_CMD_ACCEPT BIT(1)
41#define CDNS_MCP_CONTROL_BLOCK_WAKEUP BIT(0)
42
43
44#define CDNS_MCP_CMDCTRL 0x8
45#define CDNS_MCP_SSPSTAT 0xC
46#define CDNS_MCP_FRAME_SHAPE 0x10
47#define CDNS_MCP_FRAME_SHAPE_INIT 0x14
48
49#define CDNS_MCP_CONFIG_UPDATE 0x18
50#define CDNS_MCP_CONFIG_UPDATE_BIT BIT(0)
51
52#define CDNS_MCP_PHYCTRL 0x1C
53#define CDNS_MCP_SSP_CTRL0 0x20
54#define CDNS_MCP_SSP_CTRL1 0x28
55#define CDNS_MCP_CLK_CTRL0 0x30
56#define CDNS_MCP_CLK_CTRL1 0x38
57
58#define CDNS_MCP_STAT 0x40
59
60#define CDNS_MCP_STAT_ACTIVE_BANK BIT(20)
61#define CDNS_MCP_STAT_CLK_STOP BIT(16)
62
63#define CDNS_MCP_INTSTAT 0x44
64#define CDNS_MCP_INTMASK 0x48
65
66#define CDNS_MCP_INT_IRQ BIT(31)
67#define CDNS_MCP_INT_WAKEUP BIT(16)
68#define CDNS_MCP_INT_SLAVE_RSVD BIT(15)
69#define CDNS_MCP_INT_SLAVE_ALERT BIT(14)
70#define CDNS_MCP_INT_SLAVE_ATTACH BIT(13)
71#define CDNS_MCP_INT_SLAVE_NATTACH BIT(12)
72#define CDNS_MCP_INT_SLAVE_MASK GENMASK(15, 12)
73#define CDNS_MCP_INT_DPINT BIT(11)
74#define CDNS_MCP_INT_CTRL_CLASH BIT(10)
75#define CDNS_MCP_INT_DATA_CLASH BIT(9)
76#define CDNS_MCP_INT_CMD_ERR BIT(7)
77#define CDNS_MCP_INT_RX_WL BIT(2)
78#define CDNS_MCP_INT_TXE BIT(1)
79
80#define CDNS_MCP_INTSET 0x4C
81
82#define CDNS_SDW_SLAVE_STAT 0x50
83#define CDNS_MCP_SLAVE_STAT_MASK BIT(1, 0)
84
85#define CDNS_MCP_SLAVE_INTSTAT0 0x54
86#define CDNS_MCP_SLAVE_INTSTAT1 0x58
87#define CDNS_MCP_SLAVE_INTSTAT_NPRESENT BIT(0)
88#define CDNS_MCP_SLAVE_INTSTAT_ATTACHED BIT(1)
89#define CDNS_MCP_SLAVE_INTSTAT_ALERT BIT(2)
90#define CDNS_MCP_SLAVE_INTSTAT_RESERVED BIT(3)
91#define CDNS_MCP_SLAVE_STATUS_BITS GENMASK(3, 0)
92#define CDNS_MCP_SLAVE_STATUS_NUM 4
93
94#define CDNS_MCP_SLAVE_INTMASK0 0x5C
95#define CDNS_MCP_SLAVE_INTMASK1 0x60
96
97#define CDNS_MCP_SLAVE_INTMASK0_MASK GENMASK(30, 0)
98#define CDNS_MCP_SLAVE_INTMASK1_MASK GENMASK(16, 0)
99
100#define CDNS_MCP_PORT_INTSTAT 0x64
101#define CDNS_MCP_PDI_STAT 0x6C
102
103#define CDNS_MCP_FIFOLEVEL 0x78
104#define CDNS_MCP_FIFOSTAT 0x7C
105#define CDNS_MCP_RX_FIFO_AVAIL GENMASK(5, 0)
106
107#define CDNS_MCP_CMD_BASE 0x80
108#define CDNS_MCP_RESP_BASE 0x80
109#define CDNS_MCP_CMD_LEN 0x20
110#define CDNS_MCP_CMD_WORD_LEN 0x4
111
112#define CDNS_MCP_CMD_SSP_TAG BIT(31)
113#define CDNS_MCP_CMD_COMMAND GENMASK(30, 28)
114#define CDNS_MCP_CMD_DEV_ADDR GENMASK(27, 24)
115#define CDNS_MCP_CMD_REG_ADDR_H GENMASK(23, 16)
116#define CDNS_MCP_CMD_REG_ADDR_L GENMASK(15, 8)
117#define CDNS_MCP_CMD_REG_DATA GENMASK(7, 0)
118
119#define CDNS_MCP_CMD_READ 2
120#define CDNS_MCP_CMD_WRITE 3
121
122#define CDNS_MCP_RESP_RDATA GENMASK(15, 8)
123#define CDNS_MCP_RESP_ACK BIT(0)
124#define CDNS_MCP_RESP_NACK BIT(1)
125
126#define CDNS_DP_SIZE 128
127
128#define CDNS_DPN_B0_CONFIG(n) (0x100 + CDNS_DP_SIZE * (n))
129#define CDNS_DPN_B0_CH_EN(n) (0x104 + CDNS_DP_SIZE * (n))
130#define CDNS_DPN_B0_SAMPLE_CTRL(n) (0x108 + CDNS_DP_SIZE * (n))
131#define CDNS_DPN_B0_OFFSET_CTRL(n) (0x10C + CDNS_DP_SIZE * (n))
132#define CDNS_DPN_B0_HCTRL(n) (0x110 + CDNS_DP_SIZE * (n))
133#define CDNS_DPN_B0_ASYNC_CTRL(n) (0x114 + CDNS_DP_SIZE * (n))
134
135#define CDNS_DPN_B1_CONFIG(n) (0x118 + CDNS_DP_SIZE * (n))
136#define CDNS_DPN_B1_CH_EN(n) (0x11C + CDNS_DP_SIZE * (n))
137#define CDNS_DPN_B1_SAMPLE_CTRL(n) (0x120 + CDNS_DP_SIZE * (n))
138#define CDNS_DPN_B1_OFFSET_CTRL(n) (0x124 + CDNS_DP_SIZE * (n))
139#define CDNS_DPN_B1_HCTRL(n) (0x128 + CDNS_DP_SIZE * (n))
140#define CDNS_DPN_B1_ASYNC_CTRL(n) (0x12C + CDNS_DP_SIZE * (n))
141
142#define CDNS_DPN_CONFIG_BPM BIT(18)
143#define CDNS_DPN_CONFIG_BGC GENMASK(17, 16)
144#define CDNS_DPN_CONFIG_WL GENMASK(12, 8)
145#define CDNS_DPN_CONFIG_PORT_DAT GENMASK(3, 2)
146#define CDNS_DPN_CONFIG_PORT_FLOW GENMASK(1, 0)
147
148#define CDNS_DPN_SAMPLE_CTRL_SI GENMASK(15, 0)
149
150#define CDNS_DPN_OFFSET_CTRL_1 GENMASK(7, 0)
151#define CDNS_DPN_OFFSET_CTRL_2 GENMASK(15, 8)
152
153#define CDNS_DPN_HCTRL_HSTOP GENMASK(3, 0)
154#define CDNS_DPN_HCTRL_HSTART GENMASK(7, 4)
155#define CDNS_DPN_HCTRL_LCTRL GENMASK(10, 8)
156
157#define CDNS_PORTCTRL 0x130
158#define CDNS_PORTCTRL_DIRN BIT(7)
159#define CDNS_PORTCTRL_BANK_INVERT BIT(8)
160
161#define CDNS_PORT_OFFSET 0x80
162
163#define CDNS_PDI_CONFIG(n) (0x1100 + (n) * 16)
164
165#define CDNS_PDI_CONFIG_SOFT_RESET BIT(24)
166#define CDNS_PDI_CONFIG_CHANNEL GENMASK(15, 8)
167#define CDNS_PDI_CONFIG_PORT GENMASK(4, 0)
168
169/* Driver defaults */
170
171#define CDNS_DEFAULT_CLK_DIVIDER 0
172#define CDNS_DEFAULT_FRAME_SHAPE 0x30
173#define CDNS_DEFAULT_SSP_INTERVAL 0x18
174#define CDNS_TX_TIMEOUT 2000
175
176#define CDNS_PCM_PDI_OFFSET 0x2
177#define CDNS_PDM_PDI_OFFSET 0x6
178
179#define CDNS_SCP_RX_FIFOLEVEL 0x2
180
181/*
182 * register accessor helpers
183 */
184static inline u32 cdns_readl(struct sdw_cdns *cdns, int offset)
185{
186 return readl(cdns->registers + offset);
187}
188
189static inline void cdns_writel(struct sdw_cdns *cdns, int offset, u32 value)
190{
191 writel(value, cdns->registers + offset);
192}
193
194static inline void cdns_updatel(struct sdw_cdns *cdns,
195 int offset, u32 mask, u32 val)
196{
197 u32 tmp;
198
199 tmp = cdns_readl(cdns, offset);
200 tmp = (tmp & ~mask) | val;
201 cdns_writel(cdns, offset, tmp);
202}
203
204static int cdns_clear_bit(struct sdw_cdns *cdns, int offset, u32 value)
205{
206 int timeout = 10;
207 u32 reg_read;
208
209 writel(value, cdns->registers + offset);
210
211 /* Wait for bit to be self cleared */
212 do {
213 reg_read = readl(cdns->registers + offset);
214 if ((reg_read & value) == 0)
215 return 0;
216
217 timeout--;
218 udelay(50);
219 } while (timeout != 0);
220
221 return -EAGAIN;
222}
223
224/*
Sanyog Kale956baa12017-12-14 11:19:42 +0530225 * IO Calls
226 */
227static enum sdw_command_response cdns_fill_msg_resp(
228 struct sdw_cdns *cdns,
229 struct sdw_msg *msg, int count, int offset)
230{
231 int nack = 0, no_ack = 0;
232 int i;
233
234 /* check message response */
235 for (i = 0; i < count; i++) {
236 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
237 no_ack = 1;
238 dev_dbg(cdns->dev, "Msg Ack not received\n");
239 if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
240 nack = 1;
241 dev_err(cdns->dev, "Msg NACK received\n");
242 }
243 }
244 }
245
246 if (nack) {
247 dev_err(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num);
248 return SDW_CMD_FAIL;
249 } else if (no_ack) {
250 dev_dbg(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num);
251 return SDW_CMD_IGNORED;
252 }
253
254 /* fill response */
255 for (i = 0; i < count; i++)
256 msg->buf[i + offset] = cdns->response_buf[i] >>
257 SDW_REG_SHIFT(CDNS_MCP_RESP_RDATA);
258
259 return SDW_CMD_OK;
260}
261
262static enum sdw_command_response
263_cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
264 int offset, int count, bool defer)
265{
266 unsigned long time;
267 u32 base, i, data;
268 u16 addr;
269
270 /* Program the watermark level for RX FIFO */
271 if (cdns->msg_count != count) {
272 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, count);
273 cdns->msg_count = count;
274 }
275
276 base = CDNS_MCP_CMD_BASE;
277 addr = msg->addr;
278
279 for (i = 0; i < count; i++) {
280 data = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
281 data |= cmd << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
282 data |= addr++ << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
283
284 if (msg->flags == SDW_MSG_FLAG_WRITE)
285 data |= msg->buf[i + offset];
286
287 data |= msg->ssp_sync << SDW_REG_SHIFT(CDNS_MCP_CMD_SSP_TAG);
288 cdns_writel(cdns, base, data);
289 base += CDNS_MCP_CMD_WORD_LEN;
290 }
291
292 if (defer)
293 return SDW_CMD_OK;
294
295 /* wait for timeout or response */
296 time = wait_for_completion_timeout(&cdns->tx_complete,
297 msecs_to_jiffies(CDNS_TX_TIMEOUT));
298 if (!time) {
299 dev_err(cdns->dev, "IO transfer timed out\n");
300 msg->len = 0;
301 return SDW_CMD_TIMEOUT;
302 }
303
304 return cdns_fill_msg_resp(cdns, msg, count, offset);
305}
306
307static enum sdw_command_response cdns_program_scp_addr(
308 struct sdw_cdns *cdns, struct sdw_msg *msg)
309{
310 int nack = 0, no_ack = 0;
311 unsigned long time;
312 u32 data[2], base;
313 int i;
314
315 /* Program the watermark level for RX FIFO */
316 if (cdns->msg_count != CDNS_SCP_RX_FIFOLEVEL) {
317 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, CDNS_SCP_RX_FIFOLEVEL);
318 cdns->msg_count = CDNS_SCP_RX_FIFOLEVEL;
319 }
320
321 data[0] = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
322 data[0] |= 0x3 << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
323 data[1] = data[0];
324
325 data[0] |= SDW_SCP_ADDRPAGE1 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
326 data[1] |= SDW_SCP_ADDRPAGE2 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
327
328 data[0] |= msg->addr_page1;
329 data[1] |= msg->addr_page2;
330
331 base = CDNS_MCP_CMD_BASE;
332 cdns_writel(cdns, base, data[0]);
333 base += CDNS_MCP_CMD_WORD_LEN;
334 cdns_writel(cdns, base, data[1]);
335
336 time = wait_for_completion_timeout(&cdns->tx_complete,
337 msecs_to_jiffies(CDNS_TX_TIMEOUT));
338 if (!time) {
339 dev_err(cdns->dev, "SCP Msg trf timed out\n");
340 msg->len = 0;
341 return SDW_CMD_TIMEOUT;
342 }
343
344 /* check response the writes */
345 for (i = 0; i < 2; i++) {
346 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
347 no_ack = 1;
348 dev_err(cdns->dev, "Program SCP Ack not received");
349 if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
350 nack = 1;
351 dev_err(cdns->dev, "Program SCP NACK received");
352 }
353 }
354 }
355
356 /* For NACK, NO ack, don't return err if we are in Broadcast mode */
357 if (nack) {
358 dev_err(cdns->dev,
359 "SCP_addrpage NACKed for Slave %d", msg->dev_num);
360 return SDW_CMD_FAIL;
361 } else if (no_ack) {
362 dev_dbg(cdns->dev,
363 "SCP_addrpage ignored for Slave %d", msg->dev_num);
364 return SDW_CMD_IGNORED;
365 }
366
367 return SDW_CMD_OK;
368}
369
370static int cdns_prep_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int *cmd)
371{
372 int ret;
373
374 if (msg->page) {
375 ret = cdns_program_scp_addr(cdns, msg);
376 if (ret) {
377 msg->len = 0;
378 return ret;
379 }
380 }
381
382 switch (msg->flags) {
383 case SDW_MSG_FLAG_READ:
384 *cmd = CDNS_MCP_CMD_READ;
385 break;
386
387 case SDW_MSG_FLAG_WRITE:
388 *cmd = CDNS_MCP_CMD_WRITE;
389 break;
390
391 default:
392 dev_err(cdns->dev, "Invalid msg cmd: %d\n", msg->flags);
393 return -EINVAL;
394 }
395
396 return 0;
397}
398
Shreyas NCc91605f2018-04-26 18:38:43 +0530399enum sdw_command_response
Sanyog Kale956baa12017-12-14 11:19:42 +0530400cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg)
401{
402 struct sdw_cdns *cdns = bus_to_cdns(bus);
403 int cmd = 0, ret, i;
404
405 ret = cdns_prep_msg(cdns, msg, &cmd);
406 if (ret)
407 return SDW_CMD_FAIL_OTHER;
408
409 for (i = 0; i < msg->len / CDNS_MCP_CMD_LEN; i++) {
410 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
411 CDNS_MCP_CMD_LEN, false);
412 if (ret < 0)
413 goto exit;
414 }
415
416 if (!(msg->len % CDNS_MCP_CMD_LEN))
417 goto exit;
418
419 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
420 msg->len % CDNS_MCP_CMD_LEN, false);
421
422exit:
423 return ret;
424}
Shreyas NCc91605f2018-04-26 18:38:43 +0530425EXPORT_SYMBOL(cdns_xfer_msg);
Sanyog Kale956baa12017-12-14 11:19:42 +0530426
Shreyas NCc91605f2018-04-26 18:38:43 +0530427enum sdw_command_response
Sanyog Kale956baa12017-12-14 11:19:42 +0530428cdns_xfer_msg_defer(struct sdw_bus *bus,
429 struct sdw_msg *msg, struct sdw_defer *defer)
430{
431 struct sdw_cdns *cdns = bus_to_cdns(bus);
432 int cmd = 0, ret;
433
434 /* for defer only 1 message is supported */
435 if (msg->len > 1)
436 return -ENOTSUPP;
437
438 ret = cdns_prep_msg(cdns, msg, &cmd);
439 if (ret)
440 return SDW_CMD_FAIL_OTHER;
441
442 cdns->defer = defer;
443 cdns->defer->length = msg->len;
444
445 return _cdns_xfer_msg(cdns, msg, cmd, 0, msg->len, true);
446}
Shreyas NCc91605f2018-04-26 18:38:43 +0530447EXPORT_SYMBOL(cdns_xfer_msg_defer);
Sanyog Kale956baa12017-12-14 11:19:42 +0530448
Shreyas NCc91605f2018-04-26 18:38:43 +0530449enum sdw_command_response
Sanyog Kale956baa12017-12-14 11:19:42 +0530450cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num)
451{
452 struct sdw_cdns *cdns = bus_to_cdns(bus);
453 struct sdw_msg msg;
454
455 /* Create dummy message with valid device number */
456 memset(&msg, 0, sizeof(msg));
457 msg.dev_num = dev_num;
458
459 return cdns_program_scp_addr(cdns, &msg);
460}
Shreyas NCc91605f2018-04-26 18:38:43 +0530461EXPORT_SYMBOL(cdns_reset_page_addr);
Sanyog Kale956baa12017-12-14 11:19:42 +0530462
463/*
Vinod Koul2f52a512017-12-14 11:19:41 +0530464 * IRQ handling
465 */
466
Sanyog Kale956baa12017-12-14 11:19:42 +0530467static void cdns_read_response(struct sdw_cdns *cdns)
468{
469 u32 num_resp, cmd_base;
470 int i;
471
472 num_resp = cdns_readl(cdns, CDNS_MCP_FIFOSTAT);
473 num_resp &= CDNS_MCP_RX_FIFO_AVAIL;
474
475 cmd_base = CDNS_MCP_CMD_BASE;
476
477 for (i = 0; i < num_resp; i++) {
478 cdns->response_buf[i] = cdns_readl(cdns, cmd_base);
479 cmd_base += CDNS_MCP_CMD_WORD_LEN;
480 }
481}
482
Vinod Koul2f52a512017-12-14 11:19:41 +0530483static int cdns_update_slave_status(struct sdw_cdns *cdns,
484 u32 slave0, u32 slave1)
485{
486 enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
487 bool is_slave = false;
488 u64 slave, mask;
489 int i, set_status;
490
491 /* combine the two status */
492 slave = ((u64)slave1 << 32) | slave0;
493 memset(status, 0, sizeof(status));
494
495 for (i = 0; i <= SDW_MAX_DEVICES; i++) {
496 mask = (slave >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) &
497 CDNS_MCP_SLAVE_STATUS_BITS;
498 if (!mask)
499 continue;
500
501 is_slave = true;
502 set_status = 0;
503
504 if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) {
505 status[i] = SDW_SLAVE_RESERVED;
506 set_status++;
507 }
508
509 if (mask & CDNS_MCP_SLAVE_INTSTAT_ATTACHED) {
510 status[i] = SDW_SLAVE_ATTACHED;
511 set_status++;
512 }
513
514 if (mask & CDNS_MCP_SLAVE_INTSTAT_ALERT) {
515 status[i] = SDW_SLAVE_ALERT;
516 set_status++;
517 }
518
519 if (mask & CDNS_MCP_SLAVE_INTSTAT_NPRESENT) {
520 status[i] = SDW_SLAVE_UNATTACHED;
521 set_status++;
522 }
523
524 /* first check if Slave reported multiple status */
525 if (set_status > 1) {
526 dev_warn(cdns->dev,
527 "Slave reported multiple Status: %d\n",
528 status[i]);
529 /*
530 * TODO: we need to reread the status here by
531 * issuing a PING cmd
532 */
533 }
534 }
535
536 if (is_slave)
537 return sdw_handle_slave_status(&cdns->bus, status);
538
539 return 0;
540}
541
542/**
543 * sdw_cdns_irq() - Cadence interrupt handler
544 * @irq: irq number
545 * @dev_id: irq context
546 */
547irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
548{
549 struct sdw_cdns *cdns = dev_id;
550 u32 int_status;
551 int ret = IRQ_HANDLED;
552
553 /* Check if the link is up */
554 if (!cdns->link_up)
555 return IRQ_NONE;
556
557 int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT);
558
559 if (!(int_status & CDNS_MCP_INT_IRQ))
560 return IRQ_NONE;
561
Sanyog Kale956baa12017-12-14 11:19:42 +0530562 if (int_status & CDNS_MCP_INT_RX_WL) {
563 cdns_read_response(cdns);
564
565 if (cdns->defer) {
566 cdns_fill_msg_resp(cdns, cdns->defer->msg,
567 cdns->defer->length, 0);
568 complete(&cdns->defer->complete);
569 cdns->defer = NULL;
570 } else
571 complete(&cdns->tx_complete);
572 }
573
Vinod Koul2f52a512017-12-14 11:19:41 +0530574 if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
575
576 /* Slave is driving bit slot during control word */
577 dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
578 int_status |= CDNS_MCP_INT_CTRL_CLASH;
579 }
580
581 if (int_status & CDNS_MCP_INT_DATA_CLASH) {
582 /*
583 * Multiple slaves trying to drive bit slot, or issue with
584 * ownership of data bits or Slave gone bonkers
585 */
586 dev_err_ratelimited(cdns->dev, "Bus clash for data word\n");
587 int_status |= CDNS_MCP_INT_DATA_CLASH;
588 }
589
590 if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
591 /* Mask the Slave interrupt and wake thread */
592 cdns_updatel(cdns, CDNS_MCP_INTMASK,
593 CDNS_MCP_INT_SLAVE_MASK, 0);
594
595 int_status &= ~CDNS_MCP_INT_SLAVE_MASK;
596 ret = IRQ_WAKE_THREAD;
597 }
598
599 cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
600 return ret;
601}
602EXPORT_SYMBOL(sdw_cdns_irq);
603
604/**
605 * sdw_cdns_thread() - Cadence irq thread handler
606 * @irq: irq number
607 * @dev_id: irq context
608 */
609irqreturn_t sdw_cdns_thread(int irq, void *dev_id)
610{
611 struct sdw_cdns *cdns = dev_id;
612 u32 slave0, slave1;
613
614 dev_dbg(cdns->dev, "Slave status change\n");
615
616 slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
617 slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
618
619 cdns_update_slave_status(cdns, slave0, slave1);
620 cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0);
621 cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1);
622
623 /* clear and unmask Slave interrupt now */
624 cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK);
625 cdns_updatel(cdns, CDNS_MCP_INTMASK,
626 CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);
627
628 return IRQ_HANDLED;
629}
630EXPORT_SYMBOL(sdw_cdns_thread);
631
632/*
633 * init routines
634 */
Sanyog Kale956baa12017-12-14 11:19:42 +0530635static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
636{
637 u32 mask;
638
639 cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
640 CDNS_MCP_SLAVE_INTMASK0_MASK);
641 cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
642 CDNS_MCP_SLAVE_INTMASK1_MASK);
643
644 mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
645 CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH |
646 CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
647 CDNS_MCP_INT_RX_WL | CDNS_MCP_INT_IRQ | CDNS_MCP_INT_DPINT;
648
649 cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
650
651 return 0;
652}
653
654/**
655 * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
656 * @cdns: Cadence instance
657 */
658int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
659{
660 int ret;
661
662 _cdns_enable_interrupt(cdns);
663 ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
664 CDNS_MCP_CONFIG_UPDATE_BIT);
665 if (ret < 0)
666 dev_err(cdns->dev, "Config update timedout");
667
668 return ret;
669}
670EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
Vinod Koul2f52a512017-12-14 11:19:41 +0530671
Vinod Koul07abeff2018-04-26 18:38:48 +0530672static int cdns_allocate_pdi(struct sdw_cdns *cdns,
673 struct sdw_cdns_pdi **stream,
674 u32 num, u32 pdi_offset)
675{
676 struct sdw_cdns_pdi *pdi;
677 int i;
678
679 if (!num)
680 return 0;
681
682 pdi = devm_kcalloc(cdns->dev, num, sizeof(*pdi), GFP_KERNEL);
683 if (!pdi)
684 return -ENOMEM;
685
686 for (i = 0; i < num; i++) {
687 pdi[i].num = i + pdi_offset;
688 pdi[i].assigned = false;
689 }
690
691 *stream = pdi;
692 return 0;
693}
694
695/**
696 * sdw_cdns_pdi_init() - PDI initialization routine
697 *
698 * @cdns: Cadence instance
699 * @config: Stream configurations
700 */
701int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
702 struct sdw_cdns_stream_config config)
703{
704 struct sdw_cdns_streams *stream;
705 int offset, i, ret;
706
707 cdns->pcm.num_bd = config.pcm_bd;
708 cdns->pcm.num_in = config.pcm_in;
709 cdns->pcm.num_out = config.pcm_out;
710 cdns->pdm.num_bd = config.pdm_bd;
711 cdns->pdm.num_in = config.pdm_in;
712 cdns->pdm.num_out = config.pdm_out;
713
714 /* Allocate PDIs for PCMs */
715 stream = &cdns->pcm;
716
717 /* First two PDIs are reserved for bulk transfers */
718 stream->num_bd -= CDNS_PCM_PDI_OFFSET;
719 offset = CDNS_PCM_PDI_OFFSET;
720
721 ret = cdns_allocate_pdi(cdns, &stream->bd,
722 stream->num_bd, offset);
723 if (ret)
724 return ret;
725
726 offset += stream->num_bd;
727
728 ret = cdns_allocate_pdi(cdns, &stream->in,
729 stream->num_in, offset);
730 if (ret)
731 return ret;
732
733 offset += stream->num_in;
734
735 ret = cdns_allocate_pdi(cdns, &stream->out,
736 stream->num_out, offset);
737 if (ret)
738 return ret;
739
740 /* Update total number of PCM PDIs */
741 stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
742 cdns->num_ports = stream->num_pdi;
743
744 /* Allocate PDIs for PDMs */
745 stream = &cdns->pdm;
746 offset = CDNS_PDM_PDI_OFFSET;
747 ret = cdns_allocate_pdi(cdns, &stream->bd,
748 stream->num_bd, offset);
749 if (ret)
750 return ret;
751
752 offset += stream->num_bd;
753
754 ret = cdns_allocate_pdi(cdns, &stream->in,
755 stream->num_in, offset);
756 if (ret)
757 return ret;
758
759 offset += stream->num_in;
760
761 ret = cdns_allocate_pdi(cdns, &stream->out,
762 stream->num_out, offset);
763 if (ret)
764 return ret;
765
766 /* Update total number of PDM PDIs */
767 stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
768 cdns->num_ports += stream->num_pdi;
769
770 cdns->ports = devm_kcalloc(cdns->dev, cdns->num_ports,
771 sizeof(*cdns->ports), GFP_KERNEL);
772 if (!cdns->ports) {
773 ret = -ENOMEM;
774 return ret;
775 }
776
777 for (i = 0; i < cdns->num_ports; i++) {
778 cdns->ports[i].assigned = false;
779 cdns->ports[i].num = i + 1; /* Port 0 reserved for bulk */
780 }
781
782 return 0;
783}
784EXPORT_SYMBOL(sdw_cdns_pdi_init);
785
Vinod Koul2f52a512017-12-14 11:19:41 +0530786/**
787 * sdw_cdns_init() - Cadence initialization
788 * @cdns: Cadence instance
789 */
790int sdw_cdns_init(struct sdw_cdns *cdns)
791{
792 u32 val;
793 int ret;
794
795 /* Exit clock stop */
796 ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
797 CDNS_MCP_CONTROL_CLK_STOP_CLR);
798 if (ret < 0) {
799 dev_err(cdns->dev, "Couldn't exit from clock stop\n");
800 return ret;
801 }
802
803 /* Set clock divider */
804 val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);
805 val |= CDNS_DEFAULT_CLK_DIVIDER;
806 cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
807
808 /* Set the default frame shape */
809 cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, CDNS_DEFAULT_FRAME_SHAPE);
810
811 /* Set SSP interval to default value */
812 cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
813 cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, CDNS_DEFAULT_SSP_INTERVAL);
814
815 /* Set cmd accept mode */
816 cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT,
817 CDNS_MCP_CONTROL_CMD_ACCEPT);
818
819 /* Configure mcp config */
820 val = cdns_readl(cdns, CDNS_MCP_CONFIG);
821
822 /* Set Max cmd retry to 15 */
823 val |= CDNS_MCP_CONFIG_MCMD_RETRY;
824
825 /* Set frame delay between PREQ and ping frame to 15 frames */
826 val |= 0xF << SDW_REG_SHIFT(CDNS_MCP_CONFIG_MPREQ_DELAY);
827
828 /* Disable auto bus release */
829 val &= ~CDNS_MCP_CONFIG_BUS_REL;
830
831 /* Disable sniffer mode */
832 val &= ~CDNS_MCP_CONFIG_SNIFFER;
833
834 /* Set cmd mode for Tx and Rx cmds */
835 val &= ~CDNS_MCP_CONFIG_CMD;
836
837 /* Set operation to normal */
838 val &= ~CDNS_MCP_CONFIG_OP;
839 val |= CDNS_MCP_CONFIG_OP_NORMAL;
840
841 cdns_writel(cdns, CDNS_MCP_CONFIG, val);
842
843 return 0;
844}
845EXPORT_SYMBOL(sdw_cdns_init);
846
Vinod Koul07abeff2018-04-26 18:38:48 +0530847int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params)
848{
849 struct sdw_cdns *cdns = bus_to_cdns(bus);
850 int mcp_clkctrl_off, mcp_clkctrl;
851 int divider;
852
853 if (!params->curr_dr_freq) {
854 dev_err(cdns->dev, "NULL curr_dr_freq");
855 return -EINVAL;
856 }
857
858 divider = (params->max_dr_freq / params->curr_dr_freq) - 1;
859
860 if (params->next_bank)
861 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1;
862 else
863 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
864
865 mcp_clkctrl = cdns_readl(cdns, mcp_clkctrl_off);
866 mcp_clkctrl |= divider;
867 cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
868
869 return 0;
870}
871EXPORT_SYMBOL(cdns_bus_conf);
872
873static int cdns_port_params(struct sdw_bus *bus,
874 struct sdw_port_params *p_params, unsigned int bank)
875{
876 struct sdw_cdns *cdns = bus_to_cdns(bus);
877 int dpn_config = 0, dpn_config_off;
878
879 if (bank)
880 dpn_config_off = CDNS_DPN_B1_CONFIG(p_params->num);
881 else
882 dpn_config_off = CDNS_DPN_B0_CONFIG(p_params->num);
883
884 dpn_config = cdns_readl(cdns, dpn_config_off);
885
886 dpn_config |= ((p_params->bps - 1) <<
887 SDW_REG_SHIFT(CDNS_DPN_CONFIG_WL));
888 dpn_config |= (p_params->flow_mode <<
889 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_FLOW));
890 dpn_config |= (p_params->data_mode <<
891 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_DAT));
892
893 cdns_writel(cdns, dpn_config_off, dpn_config);
894
895 return 0;
896}
897
898static int cdns_transport_params(struct sdw_bus *bus,
899 struct sdw_transport_params *t_params,
900 enum sdw_reg_bank bank)
901{
902 struct sdw_cdns *cdns = bus_to_cdns(bus);
903 int dpn_offsetctrl = 0, dpn_offsetctrl_off;
904 int dpn_config = 0, dpn_config_off;
905 int dpn_hctrl = 0, dpn_hctrl_off;
906 int num = t_params->port_num;
907 int dpn_samplectrl_off;
908
909 /*
910 * Note: Only full data port is supported on the Master side for
911 * both PCM and PDM ports.
912 */
913
914 if (bank) {
915 dpn_config_off = CDNS_DPN_B1_CONFIG(num);
916 dpn_samplectrl_off = CDNS_DPN_B1_SAMPLE_CTRL(num);
917 dpn_hctrl_off = CDNS_DPN_B1_HCTRL(num);
918 dpn_offsetctrl_off = CDNS_DPN_B1_OFFSET_CTRL(num);
919 } else {
920 dpn_config_off = CDNS_DPN_B0_CONFIG(num);
921 dpn_samplectrl_off = CDNS_DPN_B0_SAMPLE_CTRL(num);
922 dpn_hctrl_off = CDNS_DPN_B0_HCTRL(num);
923 dpn_offsetctrl_off = CDNS_DPN_B0_OFFSET_CTRL(num);
924 }
925
926 dpn_config = cdns_readl(cdns, dpn_config_off);
927
928 dpn_config |= (t_params->blk_grp_ctrl <<
929 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BGC));
930 dpn_config |= (t_params->blk_pkg_mode <<
931 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BPM));
932 cdns_writel(cdns, dpn_config_off, dpn_config);
933
934 dpn_offsetctrl |= (t_params->offset1 <<
935 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_1));
936 dpn_offsetctrl |= (t_params->offset2 <<
937 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_2));
938 cdns_writel(cdns, dpn_offsetctrl_off, dpn_offsetctrl);
939
940 dpn_hctrl |= (t_params->hstart <<
941 SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTART));
942 dpn_hctrl |= (t_params->hstop << SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTOP));
943 dpn_hctrl |= (t_params->lane_ctrl <<
944 SDW_REG_SHIFT(CDNS_DPN_HCTRL_LCTRL));
945
946 cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl);
947 cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1));
948
949 return 0;
950}
951
952static int cdns_port_enable(struct sdw_bus *bus,
953 struct sdw_enable_ch *enable_ch, unsigned int bank)
954{
955 struct sdw_cdns *cdns = bus_to_cdns(bus);
956 int dpn_chnen_off, ch_mask;
957
958 if (bank)
959 dpn_chnen_off = CDNS_DPN_B1_CH_EN(enable_ch->port_num);
960 else
961 dpn_chnen_off = CDNS_DPN_B0_CH_EN(enable_ch->port_num);
962
963 ch_mask = enable_ch->ch_mask * enable_ch->enable;
964 cdns_writel(cdns, dpn_chnen_off, ch_mask);
965
966 return 0;
967}
968
969static const struct sdw_master_port_ops cdns_port_ops = {
970 .dpn_set_port_params = cdns_port_params,
971 .dpn_set_port_transport_params = cdns_transport_params,
972 .dpn_port_enable_ch = cdns_port_enable,
973};
974
Sanyog Kale956baa12017-12-14 11:19:42 +0530975/**
976 * sdw_cdns_probe() - Cadence probe routine
977 * @cdns: Cadence instance
978 */
979int sdw_cdns_probe(struct sdw_cdns *cdns)
980{
981 init_completion(&cdns->tx_complete);
Vinod Koul07abeff2018-04-26 18:38:48 +0530982 cdns->bus.port_ops = &cdns_port_ops;
Sanyog Kale956baa12017-12-14 11:19:42 +0530983
984 return 0;
985}
986EXPORT_SYMBOL(sdw_cdns_probe);
987
Vinod Koul2f52a512017-12-14 11:19:41 +0530988MODULE_LICENSE("Dual BSD/GPL");
989MODULE_DESCRIPTION("Cadence Soundwire Library");