1 // 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/debugfs.h> 12 #include <linux/interrupt.h> 13 #include <linux/io.h> 14 #include <linux/module.h> 15 #include <linux/mod_devicetable.h> 16 #include <linux/soundwire/sdw_registers.h> 17 #include <linux/soundwire/sdw.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 #include "bus.h" 21 #include "cadence_master.h" 22 23 static int interrupt_mask; 24 module_param_named(cnds_mcp_int_mask, interrupt_mask, int, 0444); 25 MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask"); 26 27 #define CDNS_MCP_CONFIG 0x0 28 29 #define CDNS_MCP_CONFIG_MCMD_RETRY GENMASK(27, 24) 30 #define CDNS_MCP_CONFIG_MPREQ_DELAY GENMASK(20, 16) 31 #define CDNS_MCP_CONFIG_MMASTER BIT(7) 32 #define CDNS_MCP_CONFIG_BUS_REL BIT(6) 33 #define CDNS_MCP_CONFIG_SNIFFER BIT(5) 34 #define CDNS_MCP_CONFIG_SSPMOD BIT(4) 35 #define CDNS_MCP_CONFIG_CMD BIT(3) 36 #define CDNS_MCP_CONFIG_OP GENMASK(2, 0) 37 #define CDNS_MCP_CONFIG_OP_NORMAL 0 38 39 #define CDNS_MCP_CONTROL 0x4 40 41 #define CDNS_MCP_CONTROL_RST_DELAY GENMASK(10, 8) 42 #define CDNS_MCP_CONTROL_CMD_RST BIT(7) 43 #define CDNS_MCP_CONTROL_SOFT_RST BIT(6) 44 #define CDNS_MCP_CONTROL_SW_RST BIT(5) 45 #define CDNS_MCP_CONTROL_HW_RST BIT(4) 46 #define CDNS_MCP_CONTROL_CLK_PAUSE BIT(3) 47 #define CDNS_MCP_CONTROL_CLK_STOP_CLR BIT(2) 48 #define CDNS_MCP_CONTROL_CMD_ACCEPT BIT(1) 49 #define CDNS_MCP_CONTROL_BLOCK_WAKEUP BIT(0) 50 51 #define CDNS_MCP_CMDCTRL 0x8 52 #define CDNS_MCP_SSPSTAT 0xC 53 #define CDNS_MCP_FRAME_SHAPE 0x10 54 #define CDNS_MCP_FRAME_SHAPE_INIT 0x14 55 #define CDNS_MCP_FRAME_SHAPE_COL_MASK GENMASK(2, 0) 56 #define CDNS_MCP_FRAME_SHAPE_ROW_OFFSET 3 57 58 #define CDNS_MCP_CONFIG_UPDATE 0x18 59 #define CDNS_MCP_CONFIG_UPDATE_BIT BIT(0) 60 61 #define CDNS_MCP_PHYCTRL 0x1C 62 #define CDNS_MCP_SSP_CTRL0 0x20 63 #define CDNS_MCP_SSP_CTRL1 0x28 64 #define CDNS_MCP_CLK_CTRL0 0x30 65 #define CDNS_MCP_CLK_CTRL1 0x38 66 #define CDNS_MCP_CLK_MCLKD_MASK GENMASK(7, 0) 67 68 #define CDNS_MCP_STAT 0x40 69 70 #define CDNS_MCP_STAT_ACTIVE_BANK BIT(20) 71 #define CDNS_MCP_STAT_CLK_STOP BIT(16) 72 73 #define CDNS_MCP_INTSTAT 0x44 74 #define CDNS_MCP_INTMASK 0x48 75 76 #define CDNS_MCP_INT_IRQ BIT(31) 77 #define CDNS_MCP_INT_WAKEUP BIT(16) 78 #define CDNS_MCP_INT_SLAVE_RSVD BIT(15) 79 #define CDNS_MCP_INT_SLAVE_ALERT BIT(14) 80 #define CDNS_MCP_INT_SLAVE_ATTACH BIT(13) 81 #define CDNS_MCP_INT_SLAVE_NATTACH BIT(12) 82 #define CDNS_MCP_INT_SLAVE_MASK GENMASK(15, 12) 83 #define CDNS_MCP_INT_DPINT BIT(11) 84 #define CDNS_MCP_INT_CTRL_CLASH BIT(10) 85 #define CDNS_MCP_INT_DATA_CLASH BIT(9) 86 #define CDNS_MCP_INT_PARITY BIT(8) 87 #define CDNS_MCP_INT_CMD_ERR BIT(7) 88 #define CDNS_MCP_INT_RX_NE BIT(3) 89 #define CDNS_MCP_INT_RX_WL BIT(2) 90 #define CDNS_MCP_INT_TXE BIT(1) 91 #define CDNS_MCP_INT_TXF BIT(0) 92 93 #define CDNS_MCP_INTSET 0x4C 94 95 #define CDNS_SDW_SLAVE_STAT 0x50 96 #define CDNS_MCP_SLAVE_STAT_MASK BIT(1, 0) 97 98 #define CDNS_MCP_SLAVE_INTSTAT0 0x54 99 #define CDNS_MCP_SLAVE_INTSTAT1 0x58 100 #define CDNS_MCP_SLAVE_INTSTAT_NPRESENT BIT(0) 101 #define CDNS_MCP_SLAVE_INTSTAT_ATTACHED BIT(1) 102 #define CDNS_MCP_SLAVE_INTSTAT_ALERT BIT(2) 103 #define CDNS_MCP_SLAVE_INTSTAT_RESERVED BIT(3) 104 #define CDNS_MCP_SLAVE_STATUS_BITS GENMASK(3, 0) 105 #define CDNS_MCP_SLAVE_STATUS_NUM 4 106 107 #define CDNS_MCP_SLAVE_INTMASK0 0x5C 108 #define CDNS_MCP_SLAVE_INTMASK1 0x60 109 110 #define CDNS_MCP_SLAVE_INTMASK0_MASK GENMASK(30, 0) 111 #define CDNS_MCP_SLAVE_INTMASK1_MASK GENMASK(16, 0) 112 113 #define CDNS_MCP_PORT_INTSTAT 0x64 114 #define CDNS_MCP_PDI_STAT 0x6C 115 116 #define CDNS_MCP_FIFOLEVEL 0x78 117 #define CDNS_MCP_FIFOSTAT 0x7C 118 #define CDNS_MCP_RX_FIFO_AVAIL GENMASK(5, 0) 119 120 #define CDNS_MCP_CMD_BASE 0x80 121 #define CDNS_MCP_RESP_BASE 0x80 122 #define CDNS_MCP_CMD_LEN 0x20 123 #define CDNS_MCP_CMD_WORD_LEN 0x4 124 125 #define CDNS_MCP_CMD_SSP_TAG BIT(31) 126 #define CDNS_MCP_CMD_COMMAND GENMASK(30, 28) 127 #define CDNS_MCP_CMD_DEV_ADDR GENMASK(27, 24) 128 #define CDNS_MCP_CMD_REG_ADDR_H GENMASK(23, 16) 129 #define CDNS_MCP_CMD_REG_ADDR_L GENMASK(15, 8) 130 #define CDNS_MCP_CMD_REG_DATA GENMASK(7, 0) 131 132 #define CDNS_MCP_CMD_READ 2 133 #define CDNS_MCP_CMD_WRITE 3 134 135 #define CDNS_MCP_RESP_RDATA GENMASK(15, 8) 136 #define CDNS_MCP_RESP_ACK BIT(0) 137 #define CDNS_MCP_RESP_NACK BIT(1) 138 139 #define CDNS_DP_SIZE 128 140 141 #define CDNS_DPN_B0_CONFIG(n) (0x100 + CDNS_DP_SIZE * (n)) 142 #define CDNS_DPN_B0_CH_EN(n) (0x104 + CDNS_DP_SIZE * (n)) 143 #define CDNS_DPN_B0_SAMPLE_CTRL(n) (0x108 + CDNS_DP_SIZE * (n)) 144 #define CDNS_DPN_B0_OFFSET_CTRL(n) (0x10C + CDNS_DP_SIZE * (n)) 145 #define CDNS_DPN_B0_HCTRL(n) (0x110 + CDNS_DP_SIZE * (n)) 146 #define CDNS_DPN_B0_ASYNC_CTRL(n) (0x114 + CDNS_DP_SIZE * (n)) 147 148 #define CDNS_DPN_B1_CONFIG(n) (0x118 + CDNS_DP_SIZE * (n)) 149 #define CDNS_DPN_B1_CH_EN(n) (0x11C + CDNS_DP_SIZE * (n)) 150 #define CDNS_DPN_B1_SAMPLE_CTRL(n) (0x120 + CDNS_DP_SIZE * (n)) 151 #define CDNS_DPN_B1_OFFSET_CTRL(n) (0x124 + CDNS_DP_SIZE * (n)) 152 #define CDNS_DPN_B1_HCTRL(n) (0x128 + CDNS_DP_SIZE * (n)) 153 #define CDNS_DPN_B1_ASYNC_CTRL(n) (0x12C + CDNS_DP_SIZE * (n)) 154 155 #define CDNS_DPN_CONFIG_BPM BIT(18) 156 #define CDNS_DPN_CONFIG_BGC GENMASK(17, 16) 157 #define CDNS_DPN_CONFIG_WL GENMASK(12, 8) 158 #define CDNS_DPN_CONFIG_PORT_DAT GENMASK(3, 2) 159 #define CDNS_DPN_CONFIG_PORT_FLOW GENMASK(1, 0) 160 161 #define CDNS_DPN_SAMPLE_CTRL_SI GENMASK(15, 0) 162 163 #define CDNS_DPN_OFFSET_CTRL_1 GENMASK(7, 0) 164 #define CDNS_DPN_OFFSET_CTRL_2 GENMASK(15, 8) 165 166 #define CDNS_DPN_HCTRL_HSTOP GENMASK(3, 0) 167 #define CDNS_DPN_HCTRL_HSTART GENMASK(7, 4) 168 #define CDNS_DPN_HCTRL_LCTRL GENMASK(10, 8) 169 170 #define CDNS_PORTCTRL 0x130 171 #define CDNS_PORTCTRL_DIRN BIT(7) 172 #define CDNS_PORTCTRL_BANK_INVERT BIT(8) 173 174 #define CDNS_PORT_OFFSET 0x80 175 176 #define CDNS_PDI_CONFIG(n) (0x1100 + (n) * 16) 177 178 #define CDNS_PDI_CONFIG_SOFT_RESET BIT(24) 179 #define CDNS_PDI_CONFIG_CHANNEL GENMASK(15, 8) 180 #define CDNS_PDI_CONFIG_PORT GENMASK(4, 0) 181 182 /* Driver defaults */ 183 #define CDNS_DEFAULT_SSP_INTERVAL 0x18 184 #define CDNS_TX_TIMEOUT 2000 185 186 #define CDNS_PCM_PDI_OFFSET 0x2 187 #define CDNS_PDM_PDI_OFFSET 0x6 188 189 #define CDNS_SCP_RX_FIFOLEVEL 0x2 190 191 /* 192 * register accessor helpers 193 */ 194 static inline u32 cdns_readl(struct sdw_cdns *cdns, int offset) 195 { 196 return readl(cdns->registers + offset); 197 } 198 199 static inline void cdns_writel(struct sdw_cdns *cdns, int offset, u32 value) 200 { 201 writel(value, cdns->registers + offset); 202 } 203 204 static inline void cdns_updatel(struct sdw_cdns *cdns, 205 int offset, u32 mask, u32 val) 206 { 207 u32 tmp; 208 209 tmp = cdns_readl(cdns, offset); 210 tmp = (tmp & ~mask) | val; 211 cdns_writel(cdns, offset, tmp); 212 } 213 214 static int cdns_clear_bit(struct sdw_cdns *cdns, int offset, u32 value) 215 { 216 int timeout = 10; 217 u32 reg_read; 218 219 writel(value, cdns->registers + offset); 220 221 /* Wait for bit to be self cleared */ 222 do { 223 reg_read = readl(cdns->registers + offset); 224 if ((reg_read & value) == 0) 225 return 0; 226 227 timeout--; 228 udelay(50); 229 } while (timeout != 0); 230 231 return -EAGAIN; 232 } 233 234 /* 235 * debugfs 236 */ 237 #ifdef CONFIG_DEBUG_FS 238 239 #define RD_BUF (2 * PAGE_SIZE) 240 241 static ssize_t cdns_sprintf(struct sdw_cdns *cdns, 242 char *buf, size_t pos, unsigned int reg) 243 { 244 return scnprintf(buf + pos, RD_BUF - pos, 245 "%4x\t%8x\n", reg, cdns_readl(cdns, reg)); 246 } 247 248 static int cdns_reg_show(struct seq_file *s, void *data) 249 { 250 struct sdw_cdns *cdns = s->private; 251 char *buf; 252 ssize_t ret; 253 int num_ports; 254 int i, j; 255 256 buf = kzalloc(RD_BUF, GFP_KERNEL); 257 if (!buf) 258 return -ENOMEM; 259 260 ret = scnprintf(buf, RD_BUF, "Register Value\n"); 261 ret += scnprintf(buf + ret, RD_BUF - ret, "\nMCP Registers\n"); 262 /* 8 MCP registers */ 263 for (i = CDNS_MCP_CONFIG; i <= CDNS_MCP_PHYCTRL; i += sizeof(u32)) 264 ret += cdns_sprintf(cdns, buf, ret, i); 265 266 ret += scnprintf(buf + ret, RD_BUF - ret, 267 "\nStatus & Intr Registers\n"); 268 /* 13 Status & Intr registers (offsets 0x70 and 0x74 not defined) */ 269 for (i = CDNS_MCP_STAT; i <= CDNS_MCP_FIFOSTAT; i += sizeof(u32)) 270 ret += cdns_sprintf(cdns, buf, ret, i); 271 272 ret += scnprintf(buf + ret, RD_BUF - ret, 273 "\nSSP & Clk ctrl Registers\n"); 274 ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL0); 275 ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL1); 276 ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL0); 277 ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL1); 278 279 ret += scnprintf(buf + ret, RD_BUF - ret, 280 "\nDPn B0 Registers\n"); 281 282 /* 283 * in sdw_cdns_pdi_init() we filter out the Bulk PDIs, 284 * so the indices need to be corrected again 285 */ 286 num_ports = cdns->num_ports + CDNS_PCM_PDI_OFFSET; 287 288 for (i = 0; i < num_ports; i++) { 289 ret += scnprintf(buf + ret, RD_BUF - ret, 290 "\nDP-%d\n", i); 291 for (j = CDNS_DPN_B0_CONFIG(i); 292 j < CDNS_DPN_B0_ASYNC_CTRL(i); j += sizeof(u32)) 293 ret += cdns_sprintf(cdns, buf, ret, j); 294 } 295 296 ret += scnprintf(buf + ret, RD_BUF - ret, 297 "\nDPn B1 Registers\n"); 298 for (i = 0; i < num_ports; i++) { 299 ret += scnprintf(buf + ret, RD_BUF - ret, 300 "\nDP-%d\n", i); 301 302 for (j = CDNS_DPN_B1_CONFIG(i); 303 j < CDNS_DPN_B1_ASYNC_CTRL(i); j += sizeof(u32)) 304 ret += cdns_sprintf(cdns, buf, ret, j); 305 } 306 307 ret += scnprintf(buf + ret, RD_BUF - ret, 308 "\nDPn Control Registers\n"); 309 for (i = 0; i < num_ports; i++) 310 ret += cdns_sprintf(cdns, buf, ret, 311 CDNS_PORTCTRL + i * CDNS_PORT_OFFSET); 312 313 ret += scnprintf(buf + ret, RD_BUF - ret, 314 "\nPDIn Config Registers\n"); 315 316 /* number of PDI and ports is interchangeable */ 317 for (i = 0; i < num_ports; i++) 318 ret += cdns_sprintf(cdns, buf, ret, CDNS_PDI_CONFIG(i)); 319 320 seq_printf(s, "%s", buf); 321 kfree(buf); 322 323 return 0; 324 } 325 DEFINE_SHOW_ATTRIBUTE(cdns_reg); 326 327 /** 328 * sdw_cdns_debugfs_init() - Cadence debugfs init 329 * @cdns: Cadence instance 330 * @root: debugfs root 331 */ 332 void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root) 333 { 334 debugfs_create_file("cdns-registers", 0400, root, cdns, &cdns_reg_fops); 335 } 336 EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init); 337 338 #endif /* CONFIG_DEBUG_FS */ 339 340 /* 341 * IO Calls 342 */ 343 static enum sdw_command_response 344 cdns_fill_msg_resp(struct sdw_cdns *cdns, 345 struct sdw_msg *msg, int count, int offset) 346 { 347 int nack = 0, no_ack = 0; 348 int i; 349 350 /* check message response */ 351 for (i = 0; i < count; i++) { 352 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { 353 no_ack = 1; 354 dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n"); 355 if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { 356 nack = 1; 357 dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); 358 } 359 } 360 } 361 362 if (nack) { 363 dev_err_ratelimited(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num); 364 return SDW_CMD_FAIL; 365 } else if (no_ack) { 366 dev_dbg_ratelimited(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num); 367 return SDW_CMD_IGNORED; 368 } 369 370 /* fill response */ 371 for (i = 0; i < count; i++) 372 msg->buf[i + offset] = cdns->response_buf[i] >> 373 SDW_REG_SHIFT(CDNS_MCP_RESP_RDATA); 374 375 return SDW_CMD_OK; 376 } 377 378 static enum sdw_command_response 379 _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd, 380 int offset, int count, bool defer) 381 { 382 unsigned long time; 383 u32 base, i, data; 384 u16 addr; 385 386 /* Program the watermark level for RX FIFO */ 387 if (cdns->msg_count != count) { 388 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, count); 389 cdns->msg_count = count; 390 } 391 392 base = CDNS_MCP_CMD_BASE; 393 addr = msg->addr; 394 395 for (i = 0; i < count; i++) { 396 data = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR); 397 data |= cmd << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND); 398 data |= addr++ << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L); 399 400 if (msg->flags == SDW_MSG_FLAG_WRITE) 401 data |= msg->buf[i + offset]; 402 403 data |= msg->ssp_sync << SDW_REG_SHIFT(CDNS_MCP_CMD_SSP_TAG); 404 cdns_writel(cdns, base, data); 405 base += CDNS_MCP_CMD_WORD_LEN; 406 } 407 408 if (defer) 409 return SDW_CMD_OK; 410 411 /* wait for timeout or response */ 412 time = wait_for_completion_timeout(&cdns->tx_complete, 413 msecs_to_jiffies(CDNS_TX_TIMEOUT)); 414 if (!time) { 415 dev_err(cdns->dev, "IO transfer timed out\n"); 416 msg->len = 0; 417 return SDW_CMD_TIMEOUT; 418 } 419 420 return cdns_fill_msg_resp(cdns, msg, count, offset); 421 } 422 423 static enum sdw_command_response 424 cdns_program_scp_addr(struct sdw_cdns *cdns, struct sdw_msg *msg) 425 { 426 int nack = 0, no_ack = 0; 427 unsigned long time; 428 u32 data[2], base; 429 int i; 430 431 /* Program the watermark level for RX FIFO */ 432 if (cdns->msg_count != CDNS_SCP_RX_FIFOLEVEL) { 433 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, CDNS_SCP_RX_FIFOLEVEL); 434 cdns->msg_count = CDNS_SCP_RX_FIFOLEVEL; 435 } 436 437 data[0] = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR); 438 data[0] |= 0x3 << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND); 439 data[1] = data[0]; 440 441 data[0] |= SDW_SCP_ADDRPAGE1 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L); 442 data[1] |= SDW_SCP_ADDRPAGE2 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L); 443 444 data[0] |= msg->addr_page1; 445 data[1] |= msg->addr_page2; 446 447 base = CDNS_MCP_CMD_BASE; 448 cdns_writel(cdns, base, data[0]); 449 base += CDNS_MCP_CMD_WORD_LEN; 450 cdns_writel(cdns, base, data[1]); 451 452 time = wait_for_completion_timeout(&cdns->tx_complete, 453 msecs_to_jiffies(CDNS_TX_TIMEOUT)); 454 if (!time) { 455 dev_err(cdns->dev, "SCP Msg trf timed out\n"); 456 msg->len = 0; 457 return SDW_CMD_TIMEOUT; 458 } 459 460 /* check response the writes */ 461 for (i = 0; i < 2; i++) { 462 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { 463 no_ack = 1; 464 dev_err(cdns->dev, "Program SCP Ack not received\n"); 465 if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { 466 nack = 1; 467 dev_err(cdns->dev, "Program SCP NACK received\n"); 468 } 469 } 470 } 471 472 /* For NACK, NO ack, don't return err if we are in Broadcast mode */ 473 if (nack) { 474 dev_err_ratelimited(cdns->dev, 475 "SCP_addrpage NACKed for Slave %d\n", msg->dev_num); 476 return SDW_CMD_FAIL; 477 } else if (no_ack) { 478 dev_dbg_ratelimited(cdns->dev, 479 "SCP_addrpage ignored for Slave %d\n", msg->dev_num); 480 return SDW_CMD_IGNORED; 481 } 482 483 return SDW_CMD_OK; 484 } 485 486 static int cdns_prep_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int *cmd) 487 { 488 int ret; 489 490 if (msg->page) { 491 ret = cdns_program_scp_addr(cdns, msg); 492 if (ret) { 493 msg->len = 0; 494 return ret; 495 } 496 } 497 498 switch (msg->flags) { 499 case SDW_MSG_FLAG_READ: 500 *cmd = CDNS_MCP_CMD_READ; 501 break; 502 503 case SDW_MSG_FLAG_WRITE: 504 *cmd = CDNS_MCP_CMD_WRITE; 505 break; 506 507 default: 508 dev_err(cdns->dev, "Invalid msg cmd: %d\n", msg->flags); 509 return -EINVAL; 510 } 511 512 return 0; 513 } 514 515 enum sdw_command_response 516 cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg) 517 { 518 struct sdw_cdns *cdns = bus_to_cdns(bus); 519 int cmd = 0, ret, i; 520 521 ret = cdns_prep_msg(cdns, msg, &cmd); 522 if (ret) 523 return SDW_CMD_FAIL_OTHER; 524 525 for (i = 0; i < msg->len / CDNS_MCP_CMD_LEN; i++) { 526 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN, 527 CDNS_MCP_CMD_LEN, false); 528 if (ret < 0) 529 goto exit; 530 } 531 532 if (!(msg->len % CDNS_MCP_CMD_LEN)) 533 goto exit; 534 535 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN, 536 msg->len % CDNS_MCP_CMD_LEN, false); 537 538 exit: 539 return ret; 540 } 541 EXPORT_SYMBOL(cdns_xfer_msg); 542 543 enum sdw_command_response 544 cdns_xfer_msg_defer(struct sdw_bus *bus, 545 struct sdw_msg *msg, struct sdw_defer *defer) 546 { 547 struct sdw_cdns *cdns = bus_to_cdns(bus); 548 int cmd = 0, ret; 549 550 /* for defer only 1 message is supported */ 551 if (msg->len > 1) 552 return -ENOTSUPP; 553 554 ret = cdns_prep_msg(cdns, msg, &cmd); 555 if (ret) 556 return SDW_CMD_FAIL_OTHER; 557 558 cdns->defer = defer; 559 cdns->defer->length = msg->len; 560 561 return _cdns_xfer_msg(cdns, msg, cmd, 0, msg->len, true); 562 } 563 EXPORT_SYMBOL(cdns_xfer_msg_defer); 564 565 enum sdw_command_response 566 cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num) 567 { 568 struct sdw_cdns *cdns = bus_to_cdns(bus); 569 struct sdw_msg msg; 570 571 /* Create dummy message with valid device number */ 572 memset(&msg, 0, sizeof(msg)); 573 msg.dev_num = dev_num; 574 575 return cdns_program_scp_addr(cdns, &msg); 576 } 577 EXPORT_SYMBOL(cdns_reset_page_addr); 578 579 /* 580 * IRQ handling 581 */ 582 583 static void cdns_read_response(struct sdw_cdns *cdns) 584 { 585 u32 num_resp, cmd_base; 586 int i; 587 588 num_resp = cdns_readl(cdns, CDNS_MCP_FIFOSTAT); 589 num_resp &= CDNS_MCP_RX_FIFO_AVAIL; 590 591 cmd_base = CDNS_MCP_CMD_BASE; 592 593 for (i = 0; i < num_resp; i++) { 594 cdns->response_buf[i] = cdns_readl(cdns, cmd_base); 595 cmd_base += CDNS_MCP_CMD_WORD_LEN; 596 } 597 } 598 599 static int cdns_update_slave_status(struct sdw_cdns *cdns, 600 u32 slave0, u32 slave1) 601 { 602 enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; 603 bool is_slave = false; 604 u64 slave; 605 u32 mask; 606 int i, set_status; 607 608 /* combine the two status */ 609 slave = ((u64)slave1 << 32) | slave0; 610 memset(status, 0, sizeof(status)); 611 612 for (i = 0; i <= SDW_MAX_DEVICES; i++) { 613 mask = (slave >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) & 614 CDNS_MCP_SLAVE_STATUS_BITS; 615 if (!mask) 616 continue; 617 618 is_slave = true; 619 set_status = 0; 620 621 if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) { 622 status[i] = SDW_SLAVE_RESERVED; 623 set_status++; 624 } 625 626 if (mask & CDNS_MCP_SLAVE_INTSTAT_ATTACHED) { 627 status[i] = SDW_SLAVE_ATTACHED; 628 set_status++; 629 } 630 631 if (mask & CDNS_MCP_SLAVE_INTSTAT_ALERT) { 632 status[i] = SDW_SLAVE_ALERT; 633 set_status++; 634 } 635 636 if (mask & CDNS_MCP_SLAVE_INTSTAT_NPRESENT) { 637 status[i] = SDW_SLAVE_UNATTACHED; 638 set_status++; 639 } 640 641 /* first check if Slave reported multiple status */ 642 if (set_status > 1) { 643 dev_warn_ratelimited(cdns->dev, 644 "Slave reported multiple Status: %d\n", 645 mask); 646 /* 647 * TODO: we need to reread the status here by 648 * issuing a PING cmd 649 */ 650 } 651 } 652 653 if (is_slave) 654 return sdw_handle_slave_status(&cdns->bus, status); 655 656 return 0; 657 } 658 659 /** 660 * sdw_cdns_irq() - Cadence interrupt handler 661 * @irq: irq number 662 * @dev_id: irq context 663 */ 664 irqreturn_t sdw_cdns_irq(int irq, void *dev_id) 665 { 666 struct sdw_cdns *cdns = dev_id; 667 u32 int_status; 668 int ret = IRQ_HANDLED; 669 670 /* Check if the link is up */ 671 if (!cdns->link_up) 672 return IRQ_NONE; 673 674 int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT); 675 676 if (!(int_status & CDNS_MCP_INT_IRQ)) 677 return IRQ_NONE; 678 679 if (int_status & CDNS_MCP_INT_RX_WL) { 680 cdns_read_response(cdns); 681 682 if (cdns->defer) { 683 cdns_fill_msg_resp(cdns, cdns->defer->msg, 684 cdns->defer->length, 0); 685 complete(&cdns->defer->complete); 686 cdns->defer = NULL; 687 } else { 688 complete(&cdns->tx_complete); 689 } 690 } 691 692 if (int_status & CDNS_MCP_INT_PARITY) { 693 /* Parity error detected by Master */ 694 dev_err_ratelimited(cdns->dev, "Parity error\n"); 695 } 696 697 if (int_status & CDNS_MCP_INT_CTRL_CLASH) { 698 /* Slave is driving bit slot during control word */ 699 dev_err_ratelimited(cdns->dev, "Bus clash for control word\n"); 700 } 701 702 if (int_status & CDNS_MCP_INT_DATA_CLASH) { 703 /* 704 * Multiple slaves trying to drive bit slot, or issue with 705 * ownership of data bits or Slave gone bonkers 706 */ 707 dev_err_ratelimited(cdns->dev, "Bus clash for data word\n"); 708 } 709 710 if (int_status & CDNS_MCP_INT_SLAVE_MASK) { 711 /* Mask the Slave interrupt and wake thread */ 712 cdns_updatel(cdns, CDNS_MCP_INTMASK, 713 CDNS_MCP_INT_SLAVE_MASK, 0); 714 715 int_status &= ~CDNS_MCP_INT_SLAVE_MASK; 716 ret = IRQ_WAKE_THREAD; 717 } 718 719 cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status); 720 return ret; 721 } 722 EXPORT_SYMBOL(sdw_cdns_irq); 723 724 /** 725 * sdw_cdns_thread() - Cadence irq thread handler 726 * @irq: irq number 727 * @dev_id: irq context 728 */ 729 irqreturn_t sdw_cdns_thread(int irq, void *dev_id) 730 { 731 struct sdw_cdns *cdns = dev_id; 732 u32 slave0, slave1; 733 734 dev_dbg_ratelimited(cdns->dev, "Slave status change\n"); 735 736 slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0); 737 slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1); 738 739 cdns_update_slave_status(cdns, slave0, slave1); 740 cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0); 741 cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1); 742 743 /* clear and unmask Slave interrupt now */ 744 cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK); 745 cdns_updatel(cdns, CDNS_MCP_INTMASK, 746 CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK); 747 748 return IRQ_HANDLED; 749 } 750 EXPORT_SYMBOL(sdw_cdns_thread); 751 752 /* 753 * init routines 754 */ 755 static int _cdns_enable_interrupt(struct sdw_cdns *cdns) 756 { 757 u32 mask; 758 759 cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, 760 CDNS_MCP_SLAVE_INTMASK0_MASK); 761 cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, 762 CDNS_MCP_SLAVE_INTMASK1_MASK); 763 764 /* enable detection of all slave state changes */ 765 mask = CDNS_MCP_INT_SLAVE_MASK; 766 767 /* enable detection of bus issues */ 768 mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH | 769 CDNS_MCP_INT_PARITY; 770 771 /* no detection of port interrupts for now */ 772 773 /* enable detection of RX fifo level */ 774 mask |= CDNS_MCP_INT_RX_WL; 775 776 /* 777 * CDNS_MCP_INT_IRQ needs to be set otherwise all previous 778 * settings are irrelevant 779 */ 780 mask |= CDNS_MCP_INT_IRQ; 781 782 if (interrupt_mask) /* parameter override */ 783 mask = interrupt_mask; 784 785 cdns_writel(cdns, CDNS_MCP_INTMASK, mask); 786 787 return 0; 788 } 789 790 /** 791 * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config 792 * @cdns: Cadence instance 793 */ 794 int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns) 795 { 796 int ret; 797 798 _cdns_enable_interrupt(cdns); 799 ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE, 800 CDNS_MCP_CONFIG_UPDATE_BIT); 801 if (ret < 0) 802 dev_err(cdns->dev, "Config update timedout\n"); 803 804 return ret; 805 } 806 EXPORT_SYMBOL(sdw_cdns_enable_interrupt); 807 808 static int cdns_allocate_pdi(struct sdw_cdns *cdns, 809 struct sdw_cdns_pdi **stream, 810 u32 num, u32 pdi_offset) 811 { 812 struct sdw_cdns_pdi *pdi; 813 int i; 814 815 if (!num) 816 return 0; 817 818 pdi = devm_kcalloc(cdns->dev, num, sizeof(*pdi), GFP_KERNEL); 819 if (!pdi) 820 return -ENOMEM; 821 822 for (i = 0; i < num; i++) { 823 pdi[i].num = i + pdi_offset; 824 pdi[i].assigned = false; 825 } 826 827 *stream = pdi; 828 return 0; 829 } 830 831 /** 832 * sdw_cdns_pdi_init() - PDI initialization routine 833 * 834 * @cdns: Cadence instance 835 * @config: Stream configurations 836 */ 837 int sdw_cdns_pdi_init(struct sdw_cdns *cdns, 838 struct sdw_cdns_stream_config config) 839 { 840 struct sdw_cdns_streams *stream; 841 int offset, i, ret; 842 843 cdns->pcm.num_bd = config.pcm_bd; 844 cdns->pcm.num_in = config.pcm_in; 845 cdns->pcm.num_out = config.pcm_out; 846 cdns->pdm.num_bd = config.pdm_bd; 847 cdns->pdm.num_in = config.pdm_in; 848 cdns->pdm.num_out = config.pdm_out; 849 850 /* Allocate PDIs for PCMs */ 851 stream = &cdns->pcm; 852 853 /* First two PDIs are reserved for bulk transfers */ 854 if (stream->num_bd < CDNS_PCM_PDI_OFFSET) 855 return -EINVAL; 856 stream->num_bd -= CDNS_PCM_PDI_OFFSET; 857 offset = CDNS_PCM_PDI_OFFSET; 858 859 ret = cdns_allocate_pdi(cdns, &stream->bd, 860 stream->num_bd, offset); 861 if (ret) 862 return ret; 863 864 offset += stream->num_bd; 865 866 ret = cdns_allocate_pdi(cdns, &stream->in, 867 stream->num_in, offset); 868 if (ret) 869 return ret; 870 871 offset += stream->num_in; 872 873 ret = cdns_allocate_pdi(cdns, &stream->out, 874 stream->num_out, offset); 875 if (ret) 876 return ret; 877 878 /* Update total number of PCM PDIs */ 879 stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out; 880 cdns->num_ports = stream->num_pdi; 881 882 /* Allocate PDIs for PDMs */ 883 stream = &cdns->pdm; 884 offset = CDNS_PDM_PDI_OFFSET; 885 ret = cdns_allocate_pdi(cdns, &stream->bd, 886 stream->num_bd, offset); 887 if (ret) 888 return ret; 889 890 offset += stream->num_bd; 891 892 ret = cdns_allocate_pdi(cdns, &stream->in, 893 stream->num_in, offset); 894 if (ret) 895 return ret; 896 897 offset += stream->num_in; 898 899 ret = cdns_allocate_pdi(cdns, &stream->out, 900 stream->num_out, offset); 901 if (ret) 902 return ret; 903 904 /* Update total number of PDM PDIs */ 905 stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out; 906 cdns->num_ports += stream->num_pdi; 907 908 cdns->ports = devm_kcalloc(cdns->dev, cdns->num_ports, 909 sizeof(*cdns->ports), GFP_KERNEL); 910 if (!cdns->ports) { 911 ret = -ENOMEM; 912 return ret; 913 } 914 915 for (i = 0; i < cdns->num_ports; i++) { 916 cdns->ports[i].assigned = false; 917 cdns->ports[i].num = i + 1; /* Port 0 reserved for bulk */ 918 } 919 920 return 0; 921 } 922 EXPORT_SYMBOL(sdw_cdns_pdi_init); 923 924 static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols) 925 { 926 u32 val; 927 int c; 928 int r; 929 930 r = sdw_find_row_index(n_rows); 931 c = sdw_find_col_index(n_cols) & CDNS_MCP_FRAME_SHAPE_COL_MASK; 932 933 val = (r << CDNS_MCP_FRAME_SHAPE_ROW_OFFSET) | c; 934 935 return val; 936 } 937 938 /** 939 * sdw_cdns_init() - Cadence initialization 940 * @cdns: Cadence instance 941 */ 942 int sdw_cdns_init(struct sdw_cdns *cdns) 943 { 944 struct sdw_bus *bus = &cdns->bus; 945 struct sdw_master_prop *prop = &bus->prop; 946 u32 val; 947 int divider; 948 int ret; 949 950 /* Exit clock stop */ 951 ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL, 952 CDNS_MCP_CONTROL_CLK_STOP_CLR); 953 if (ret < 0) { 954 dev_err(cdns->dev, "Couldn't exit from clock stop\n"); 955 return ret; 956 } 957 958 /* Set clock divider */ 959 divider = (prop->mclk_freq / prop->max_clk_freq) - 1; 960 961 cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0, 962 CDNS_MCP_CLK_MCLKD_MASK, divider); 963 cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1, 964 CDNS_MCP_CLK_MCLKD_MASK, divider); 965 966 /* 967 * Frame shape changes after initialization have to be done 968 * with the bank switch mechanism 969 */ 970 val = cdns_set_initial_frame_shape(prop->default_row, 971 prop->default_col); 972 cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val); 973 974 /* Set SSP interval to default value */ 975 cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL); 976 cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, CDNS_DEFAULT_SSP_INTERVAL); 977 978 /* Set cmd accept mode */ 979 cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT, 980 CDNS_MCP_CONTROL_CMD_ACCEPT); 981 982 /* Configure mcp config */ 983 val = cdns_readl(cdns, CDNS_MCP_CONFIG); 984 985 /* Set Max cmd retry to 15 */ 986 val |= CDNS_MCP_CONFIG_MCMD_RETRY; 987 988 /* Set frame delay between PREQ and ping frame to 15 frames */ 989 val |= 0xF << SDW_REG_SHIFT(CDNS_MCP_CONFIG_MPREQ_DELAY); 990 991 /* Disable auto bus release */ 992 val &= ~CDNS_MCP_CONFIG_BUS_REL; 993 994 /* Disable sniffer mode */ 995 val &= ~CDNS_MCP_CONFIG_SNIFFER; 996 997 /* Set cmd mode for Tx and Rx cmds */ 998 val &= ~CDNS_MCP_CONFIG_CMD; 999 1000 /* Set operation to normal */ 1001 val &= ~CDNS_MCP_CONFIG_OP; 1002 val |= CDNS_MCP_CONFIG_OP_NORMAL; 1003 1004 cdns_writel(cdns, CDNS_MCP_CONFIG, val); 1005 1006 return 0; 1007 } 1008 EXPORT_SYMBOL(sdw_cdns_init); 1009 1010 int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params) 1011 { 1012 struct sdw_master_prop *prop = &bus->prop; 1013 struct sdw_cdns *cdns = bus_to_cdns(bus); 1014 int mcp_clkctrl_off; 1015 int divider; 1016 1017 if (!params->curr_dr_freq) { 1018 dev_err(cdns->dev, "NULL curr_dr_freq\n"); 1019 return -EINVAL; 1020 } 1021 1022 divider = prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR / 1023 params->curr_dr_freq; 1024 divider--; /* divider is 1/(N+1) */ 1025 1026 if (params->next_bank) 1027 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1; 1028 else 1029 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0; 1030 1031 cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, divider); 1032 1033 return 0; 1034 } 1035 EXPORT_SYMBOL(cdns_bus_conf); 1036 1037 static int cdns_port_params(struct sdw_bus *bus, 1038 struct sdw_port_params *p_params, unsigned int bank) 1039 { 1040 struct sdw_cdns *cdns = bus_to_cdns(bus); 1041 int dpn_config = 0, dpn_config_off; 1042 1043 if (bank) 1044 dpn_config_off = CDNS_DPN_B1_CONFIG(p_params->num); 1045 else 1046 dpn_config_off = CDNS_DPN_B0_CONFIG(p_params->num); 1047 1048 dpn_config = cdns_readl(cdns, dpn_config_off); 1049 1050 dpn_config |= ((p_params->bps - 1) << 1051 SDW_REG_SHIFT(CDNS_DPN_CONFIG_WL)); 1052 dpn_config |= (p_params->flow_mode << 1053 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_FLOW)); 1054 dpn_config |= (p_params->data_mode << 1055 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_DAT)); 1056 1057 cdns_writel(cdns, dpn_config_off, dpn_config); 1058 1059 return 0; 1060 } 1061 1062 static int cdns_transport_params(struct sdw_bus *bus, 1063 struct sdw_transport_params *t_params, 1064 enum sdw_reg_bank bank) 1065 { 1066 struct sdw_cdns *cdns = bus_to_cdns(bus); 1067 int dpn_offsetctrl = 0, dpn_offsetctrl_off; 1068 int dpn_config = 0, dpn_config_off; 1069 int dpn_hctrl = 0, dpn_hctrl_off; 1070 int num = t_params->port_num; 1071 int dpn_samplectrl_off; 1072 1073 /* 1074 * Note: Only full data port is supported on the Master side for 1075 * both PCM and PDM ports. 1076 */ 1077 1078 if (bank) { 1079 dpn_config_off = CDNS_DPN_B1_CONFIG(num); 1080 dpn_samplectrl_off = CDNS_DPN_B1_SAMPLE_CTRL(num); 1081 dpn_hctrl_off = CDNS_DPN_B1_HCTRL(num); 1082 dpn_offsetctrl_off = CDNS_DPN_B1_OFFSET_CTRL(num); 1083 } else { 1084 dpn_config_off = CDNS_DPN_B0_CONFIG(num); 1085 dpn_samplectrl_off = CDNS_DPN_B0_SAMPLE_CTRL(num); 1086 dpn_hctrl_off = CDNS_DPN_B0_HCTRL(num); 1087 dpn_offsetctrl_off = CDNS_DPN_B0_OFFSET_CTRL(num); 1088 } 1089 1090 dpn_config = cdns_readl(cdns, dpn_config_off); 1091 1092 dpn_config |= (t_params->blk_grp_ctrl << 1093 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BGC)); 1094 dpn_config |= (t_params->blk_pkg_mode << 1095 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BPM)); 1096 cdns_writel(cdns, dpn_config_off, dpn_config); 1097 1098 dpn_offsetctrl |= (t_params->offset1 << 1099 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_1)); 1100 dpn_offsetctrl |= (t_params->offset2 << 1101 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_2)); 1102 cdns_writel(cdns, dpn_offsetctrl_off, dpn_offsetctrl); 1103 1104 dpn_hctrl |= (t_params->hstart << 1105 SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTART)); 1106 dpn_hctrl |= (t_params->hstop << SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTOP)); 1107 dpn_hctrl |= (t_params->lane_ctrl << 1108 SDW_REG_SHIFT(CDNS_DPN_HCTRL_LCTRL)); 1109 1110 cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl); 1111 cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1)); 1112 1113 return 0; 1114 } 1115 1116 static int cdns_port_enable(struct sdw_bus *bus, 1117 struct sdw_enable_ch *enable_ch, unsigned int bank) 1118 { 1119 struct sdw_cdns *cdns = bus_to_cdns(bus); 1120 int dpn_chnen_off, ch_mask; 1121 1122 if (bank) 1123 dpn_chnen_off = CDNS_DPN_B1_CH_EN(enable_ch->port_num); 1124 else 1125 dpn_chnen_off = CDNS_DPN_B0_CH_EN(enable_ch->port_num); 1126 1127 ch_mask = enable_ch->ch_mask * enable_ch->enable; 1128 cdns_writel(cdns, dpn_chnen_off, ch_mask); 1129 1130 return 0; 1131 } 1132 1133 static const struct sdw_master_port_ops cdns_port_ops = { 1134 .dpn_set_port_params = cdns_port_params, 1135 .dpn_set_port_transport_params = cdns_transport_params, 1136 .dpn_port_enable_ch = cdns_port_enable, 1137 }; 1138 1139 /** 1140 * sdw_cdns_probe() - Cadence probe routine 1141 * @cdns: Cadence instance 1142 */ 1143 int sdw_cdns_probe(struct sdw_cdns *cdns) 1144 { 1145 init_completion(&cdns->tx_complete); 1146 cdns->bus.port_ops = &cdns_port_ops; 1147 1148 return 0; 1149 } 1150 EXPORT_SYMBOL(sdw_cdns_probe); 1151 1152 int cdns_set_sdw_stream(struct snd_soc_dai *dai, 1153 void *stream, bool pcm, int direction) 1154 { 1155 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 1156 struct sdw_cdns_dma_data *dma; 1157 1158 dma = kzalloc(sizeof(*dma), GFP_KERNEL); 1159 if (!dma) 1160 return -ENOMEM; 1161 1162 if (pcm) 1163 dma->stream_type = SDW_STREAM_PCM; 1164 else 1165 dma->stream_type = SDW_STREAM_PDM; 1166 1167 dma->bus = &cdns->bus; 1168 dma->link_id = cdns->instance; 1169 1170 dma->stream = stream; 1171 1172 if (direction == SNDRV_PCM_STREAM_PLAYBACK) 1173 dai->playback_dma_data = dma; 1174 else 1175 dai->capture_dma_data = dma; 1176 1177 return 0; 1178 } 1179 EXPORT_SYMBOL(cdns_set_sdw_stream); 1180 1181 /** 1182 * cdns_find_pdi() - Find a free PDI 1183 * 1184 * @cdns: Cadence instance 1185 * @num: Number of PDIs 1186 * @pdi: PDI instances 1187 * 1188 * Find and return a free PDI for a given PDI array 1189 */ 1190 static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns, 1191 unsigned int num, 1192 struct sdw_cdns_pdi *pdi) 1193 { 1194 int i; 1195 1196 for (i = 0; i < num; i++) { 1197 if (pdi[i].assigned) 1198 continue; 1199 pdi[i].assigned = true; 1200 return &pdi[i]; 1201 } 1202 1203 return NULL; 1204 } 1205 1206 /** 1207 * sdw_cdns_config_stream: Configure a stream 1208 * 1209 * @cdns: Cadence instance 1210 * @port: Cadence data port 1211 * @ch: Channel count 1212 * @dir: Data direction 1213 * @pdi: PDI to be used 1214 */ 1215 void sdw_cdns_config_stream(struct sdw_cdns *cdns, 1216 struct sdw_cdns_port *port, 1217 u32 ch, u32 dir, struct sdw_cdns_pdi *pdi) 1218 { 1219 u32 offset, val = 0; 1220 1221 if (dir == SDW_DATA_DIR_RX) 1222 val = CDNS_PORTCTRL_DIRN; 1223 1224 offset = CDNS_PORTCTRL + port->num * CDNS_PORT_OFFSET; 1225 cdns_updatel(cdns, offset, CDNS_PORTCTRL_DIRN, val); 1226 1227 val = port->num; 1228 val |= ((1 << ch) - 1) << SDW_REG_SHIFT(CDNS_PDI_CONFIG_CHANNEL); 1229 cdns_writel(cdns, CDNS_PDI_CONFIG(pdi->num), val); 1230 } 1231 EXPORT_SYMBOL(sdw_cdns_config_stream); 1232 1233 /** 1234 * cdns_get_num_pdi() - Get number of PDIs required 1235 * 1236 * @cdns: Cadence instance 1237 * @pdi: PDI to be used 1238 * @num: Number of PDIs 1239 * @ch_count: Channel count 1240 */ 1241 static int cdns_get_num_pdi(struct sdw_cdns *cdns, 1242 struct sdw_cdns_pdi *pdi, 1243 unsigned int num, u32 ch_count) 1244 { 1245 int i, pdis = 0; 1246 1247 for (i = 0; i < num; i++) { 1248 if (pdi[i].assigned) 1249 continue; 1250 1251 if (pdi[i].ch_count < ch_count) 1252 ch_count -= pdi[i].ch_count; 1253 else 1254 ch_count = 0; 1255 1256 pdis++; 1257 1258 if (!ch_count) 1259 break; 1260 } 1261 1262 if (ch_count) 1263 return 0; 1264 1265 return pdis; 1266 } 1267 1268 /** 1269 * sdw_cdns_get_stream() - Get stream information 1270 * 1271 * @cdns: Cadence instance 1272 * @stream: Stream to be allocated 1273 * @ch: Channel count 1274 * @dir: Data direction 1275 */ 1276 int sdw_cdns_get_stream(struct sdw_cdns *cdns, 1277 struct sdw_cdns_streams *stream, 1278 u32 ch, u32 dir) 1279 { 1280 int pdis = 0; 1281 1282 if (dir == SDW_DATA_DIR_RX) 1283 pdis = cdns_get_num_pdi(cdns, stream->in, stream->num_in, ch); 1284 else 1285 pdis = cdns_get_num_pdi(cdns, stream->out, stream->num_out, ch); 1286 1287 /* check if we found PDI, else find in bi-directional */ 1288 if (!pdis) 1289 pdis = cdns_get_num_pdi(cdns, stream->bd, stream->num_bd, ch); 1290 1291 return pdis; 1292 } 1293 EXPORT_SYMBOL(sdw_cdns_get_stream); 1294 1295 /** 1296 * sdw_cdns_alloc_stream() - Allocate a stream 1297 * 1298 * @cdns: Cadence instance 1299 * @stream: Stream to be allocated 1300 * @port: Cadence data port 1301 * @ch: Channel count 1302 * @dir: Data direction 1303 */ 1304 int sdw_cdns_alloc_stream(struct sdw_cdns *cdns, 1305 struct sdw_cdns_streams *stream, 1306 struct sdw_cdns_port *port, u32 ch, u32 dir) 1307 { 1308 struct sdw_cdns_pdi *pdi = NULL; 1309 1310 if (dir == SDW_DATA_DIR_RX) 1311 pdi = cdns_find_pdi(cdns, stream->num_in, stream->in); 1312 else 1313 pdi = cdns_find_pdi(cdns, stream->num_out, stream->out); 1314 1315 /* check if we found a PDI, else find in bi-directional */ 1316 if (!pdi) 1317 pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd); 1318 1319 if (!pdi) 1320 return -EIO; 1321 1322 port->pdi = pdi; 1323 pdi->l_ch_num = 0; 1324 pdi->h_ch_num = ch - 1; 1325 pdi->dir = dir; 1326 pdi->ch_count = ch; 1327 1328 return 0; 1329 } 1330 EXPORT_SYMBOL(sdw_cdns_alloc_stream); 1331 1332 MODULE_LICENSE("Dual BSD/GPL"); 1333 MODULE_DESCRIPTION("Cadence Soundwire Library"); 1334