1 /* 2 * Driver for the NXP SAA7164 PCIe bridge 3 * 4 * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include "saa7164.h" 23 24 /* The message bus to/from the firmware is a ring buffer in PCI address 25 * space. Establish the defaults. 26 */ 27 int saa7164_bus_setup(struct saa7164_dev *dev) 28 { 29 struct tmComResBusInfo *b = &dev->bus; 30 31 mutex_init(&b->lock); 32 33 b->Type = TYPE_BUS_PCIe; 34 b->m_wMaxReqSize = SAA_DEVICE_MAXREQUESTSIZE; 35 36 b->m_pdwSetRing = (u8 __iomem *)(dev->bmmio + 37 ((u32)dev->busdesc.CommandRing)); 38 39 b->m_dwSizeSetRing = SAA_DEVICE_BUFFERBLOCKSIZE; 40 41 b->m_pdwGetRing = (u8 __iomem *)(dev->bmmio + 42 ((u32)dev->busdesc.ResponseRing)); 43 44 b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE; 45 46 b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + 47 (2 * sizeof(u64)); 48 b->m_dwSetReadPos = b->m_dwSetWritePos + (1 * sizeof(u32)); 49 50 b->m_dwGetWritePos = b->m_dwSetWritePos + (2 * sizeof(u32)); 51 b->m_dwGetReadPos = b->m_dwSetWritePos + (3 * sizeof(u32)); 52 53 return 0; 54 } 55 56 void saa7164_bus_dump(struct saa7164_dev *dev) 57 { 58 struct tmComResBusInfo *b = &dev->bus; 59 60 dprintk(DBGLVL_BUS, "Dumping the bus structure:\n"); 61 dprintk(DBGLVL_BUS, " .type = %d\n", b->Type); 62 dprintk(DBGLVL_BUS, " .dev->bmmio = 0x%p\n", dev->bmmio); 63 dprintk(DBGLVL_BUS, " .m_wMaxReqSize = 0x%x\n", b->m_wMaxReqSize); 64 dprintk(DBGLVL_BUS, " .m_pdwSetRing = 0x%p\n", b->m_pdwSetRing); 65 dprintk(DBGLVL_BUS, " .m_dwSizeSetRing = 0x%x\n", b->m_dwSizeSetRing); 66 dprintk(DBGLVL_BUS, " .m_pdwGetRing = 0x%p\n", b->m_pdwGetRing); 67 dprintk(DBGLVL_BUS, " .m_dwSizeGetRing = 0x%x\n", b->m_dwSizeGetRing); 68 69 dprintk(DBGLVL_BUS, " .m_dwSetReadPos = 0x%x (0x%08x)\n", 70 b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos)); 71 72 dprintk(DBGLVL_BUS, " .m_dwSetWritePos = 0x%x (0x%08x)\n", 73 b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos)); 74 75 dprintk(DBGLVL_BUS, " .m_dwGetReadPos = 0x%x (0x%08x)\n", 76 b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos)); 77 78 dprintk(DBGLVL_BUS, " .m_dwGetWritePos = 0x%x (0x%08x)\n", 79 b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos)); 80 81 } 82 83 /* Intensionally throw a BUG() if the state of the message bus looks corrupt */ 84 static void saa7164_bus_verify(struct saa7164_dev *dev) 85 { 86 struct tmComResBusInfo *b = &dev->bus; 87 int bug = 0; 88 89 if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing) 90 bug++; 91 92 if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing) 93 bug++; 94 95 if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing) 96 bug++; 97 98 if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing) 99 bug++; 100 101 if (bug) { 102 saa_debug = 0xffff; /* Ensure we get the bus dump */ 103 saa7164_bus_dump(dev); 104 saa_debug = 1024; /* Ensure we get the bus dump */ 105 BUG(); 106 } 107 } 108 109 static void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo *m, 110 void *buf) 111 { 112 dprintk(DBGLVL_BUS, "Dumping msg structure:\n"); 113 dprintk(DBGLVL_BUS, " .id = %d\n", m->id); 114 dprintk(DBGLVL_BUS, " .flags = 0x%x\n", m->flags); 115 dprintk(DBGLVL_BUS, " .size = 0x%x\n", m->size); 116 dprintk(DBGLVL_BUS, " .command = 0x%x\n", m->command); 117 dprintk(DBGLVL_BUS, " .controlselector = 0x%x\n", m->controlselector); 118 dprintk(DBGLVL_BUS, " .seqno = %d\n", m->seqno); 119 if (buf) 120 dprintk(DBGLVL_BUS, " .buffer (ignored)\n"); 121 } 122 123 /* 124 * Places a command or a response on the bus. The implementation does not 125 * know if it is a command or a response it just places the data on the 126 * bus depending on the bus information given in the struct tmComResBusInfo 127 * structure. If the command or response does not fit into the bus ring 128 * buffer it will be refused. 129 * 130 * Return Value: 131 * SAA_OK The function executed successfully. 132 * < 0 One or more members are not initialized. 133 */ 134 int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, 135 void *buf) 136 { 137 struct tmComResBusInfo *bus = &dev->bus; 138 u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp; 139 u32 new_swp, space_rem; 140 int ret = SAA_ERR_BAD_PARAMETER; 141 u16 size; 142 143 if (!msg) { 144 printk(KERN_ERR "%s() !msg\n", __func__); 145 return SAA_ERR_BAD_PARAMETER; 146 } 147 148 dprintk(DBGLVL_BUS, "%s()\n", __func__); 149 150 saa7164_bus_verify(dev); 151 152 if (msg->size > dev->bus.m_wMaxReqSize) { 153 printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n", 154 __func__); 155 return SAA_ERR_BAD_PARAMETER; 156 } 157 158 if ((msg->size > 0) && (buf == NULL)) { 159 printk(KERN_ERR "%s() Missing message buffer\n", __func__); 160 return SAA_ERR_BAD_PARAMETER; 161 } 162 163 /* Lock the bus from any other access */ 164 mutex_lock(&bus->lock); 165 166 bytes_to_write = sizeof(*msg) + msg->size; 167 free_write_space = 0; 168 timeout = SAA_BUS_TIMEOUT; 169 curr_srp = saa7164_readl(bus->m_dwSetReadPos); 170 curr_swp = saa7164_readl(bus->m_dwSetWritePos); 171 172 /* Deal with ring wrapping issues */ 173 if (curr_srp > curr_swp) 174 /* Deal with the wrapped ring */ 175 free_write_space = curr_srp - curr_swp; 176 else 177 /* The ring has not wrapped yet */ 178 free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp; 179 180 dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__, 181 bytes_to_write); 182 183 dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__, 184 free_write_space); 185 186 dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp); 187 dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp); 188 189 /* Process the msg and write the content onto the bus */ 190 while (bytes_to_write >= free_write_space) { 191 192 if (timeout-- == 0) { 193 printk(KERN_ERR "%s() bus timeout\n", __func__); 194 ret = SAA_ERR_NO_RESOURCES; 195 goto out; 196 } 197 198 /* TODO: Review this delay, efficient? */ 199 /* Wait, allowing the hardware fetch time */ 200 mdelay(1); 201 202 /* Check the space usage again */ 203 curr_srp = saa7164_readl(bus->m_dwSetReadPos); 204 205 /* Deal with ring wrapping issues */ 206 if (curr_srp > curr_swp) 207 /* Deal with the wrapped ring */ 208 free_write_space = curr_srp - curr_swp; 209 else 210 /* Read didn't wrap around the buffer */ 211 free_write_space = (curr_srp + bus->m_dwSizeSetRing) - 212 curr_swp; 213 214 } 215 216 /* Calculate the new write position */ 217 new_swp = curr_swp + bytes_to_write; 218 219 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp); 220 dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__, 221 bus->m_dwSizeSetRing); 222 223 /* 224 * Make a copy of msg->size before it is converted to le16 since it is 225 * used in the code below. 226 */ 227 size = msg->size; 228 /* Convert to le16/le32 */ 229 msg->size = (__force u16)cpu_to_le16(msg->size); 230 msg->command = (__force u32)cpu_to_le32(msg->command); 231 msg->controlselector = (__force u16)cpu_to_le16(msg->controlselector); 232 233 /* Mental Note: line 462 tmmhComResBusPCIe.cpp */ 234 235 /* Check if we're going to wrap again */ 236 if (new_swp > bus->m_dwSizeSetRing) { 237 238 /* Ring wraps */ 239 new_swp -= bus->m_dwSizeSetRing; 240 241 space_rem = bus->m_dwSizeSetRing - curr_swp; 242 243 dprintk(DBGLVL_BUS, "%s() space_rem = %x\n", __func__, 244 space_rem); 245 246 dprintk(DBGLVL_BUS, "%s() sizeof(*msg) = %d\n", __func__, 247 (u32)sizeof(*msg)); 248 249 if (space_rem < sizeof(*msg)) { 250 dprintk(DBGLVL_BUS, "%s() tr4\n", __func__); 251 252 /* Split the msg into pieces as the ring wraps */ 253 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem); 254 memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem, 255 sizeof(*msg) - space_rem); 256 257 memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem, 258 buf, size); 259 260 } else if (space_rem == sizeof(*msg)) { 261 dprintk(DBGLVL_BUS, "%s() tr5\n", __func__); 262 263 /* Additional data at the beginning of the ring */ 264 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 265 memcpy_toio(bus->m_pdwSetRing, buf, size); 266 267 } else { 268 /* Additional data wraps around the ring */ 269 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 270 if (size > 0) { 271 memcpy_toio(bus->m_pdwSetRing + curr_swp + 272 sizeof(*msg), buf, space_rem - 273 sizeof(*msg)); 274 memcpy_toio(bus->m_pdwSetRing, (u8 *)buf + 275 space_rem - sizeof(*msg), 276 bytes_to_write - space_rem); 277 } 278 279 } 280 281 } /* (new_swp > bus->m_dwSizeSetRing) */ 282 else { 283 dprintk(DBGLVL_BUS, "%s() tr6\n", __func__); 284 285 /* The ring buffer doesn't wrap, two simple copies */ 286 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg)); 287 memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf, 288 size); 289 } 290 291 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp); 292 293 /* Update the bus write position */ 294 saa7164_writel(bus->m_dwSetWritePos, new_swp); 295 296 /* Convert back to cpu after writing the msg to the ringbuffer. */ 297 msg->size = le16_to_cpu((__force __le16)msg->size); 298 msg->command = le32_to_cpu((__force __le32)msg->command); 299 msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector); 300 ret = SAA_OK; 301 302 out: 303 saa7164_bus_dump(dev); 304 mutex_unlock(&bus->lock); 305 saa7164_bus_verify(dev); 306 return ret; 307 } 308 309 /* 310 * Receive a command or a response from the bus. The implementation does not 311 * know if it is a command or a response it simply dequeues the data, 312 * depending on the bus information given in the struct tmComResBusInfo 313 * structure. 314 * 315 * Return Value: 316 * 0 The function executed successfully. 317 * < 0 One or more members are not initialized. 318 */ 319 int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, 320 void *buf, int peekonly) 321 { 322 struct tmComResBusInfo *bus = &dev->bus; 323 u32 bytes_to_read, write_distance, curr_grp, curr_gwp, 324 new_grp, buf_size, space_rem; 325 struct tmComResInfo msg_tmp; 326 int ret = SAA_ERR_BAD_PARAMETER; 327 328 saa7164_bus_verify(dev); 329 330 if (msg == NULL) 331 return ret; 332 333 if (msg->size > dev->bus.m_wMaxReqSize) { 334 printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n", 335 __func__); 336 return ret; 337 } 338 339 if ((peekonly == 0) && (msg->size > 0) && (buf == NULL)) { 340 printk(KERN_ERR 341 "%s() Missing msg buf, size should be %d bytes\n", 342 __func__, msg->size); 343 return ret; 344 } 345 346 mutex_lock(&bus->lock); 347 348 /* Peek the bus to see if a msg exists, if it's not what we're expecting 349 * then return cleanly else read the message from the bus. 350 */ 351 curr_gwp = saa7164_readl(bus->m_dwGetWritePos); 352 curr_grp = saa7164_readl(bus->m_dwGetReadPos); 353 354 if (curr_gwp == curr_grp) { 355 ret = SAA_ERR_EMPTY; 356 goto out; 357 } 358 359 bytes_to_read = sizeof(*msg); 360 361 /* Calculate write distance to current read position */ 362 write_distance = 0; 363 if (curr_gwp >= curr_grp) 364 /* Write doesn't wrap around the ring */ 365 write_distance = curr_gwp - curr_grp; 366 else 367 /* Write wraps around the ring */ 368 write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp; 369 370 if (bytes_to_read > write_distance) { 371 printk(KERN_ERR "%s() No message/response found\n", __func__); 372 ret = SAA_ERR_INVALID_COMMAND; 373 goto out; 374 } 375 376 /* Calculate the new read position */ 377 new_grp = curr_grp + bytes_to_read; 378 if (new_grp > bus->m_dwSizeGetRing) { 379 380 /* Ring wraps */ 381 new_grp -= bus->m_dwSizeGetRing; 382 space_rem = bus->m_dwSizeGetRing - curr_grp; 383 384 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem); 385 memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing, 386 bytes_to_read - space_rem); 387 388 } else { 389 /* No wrapping */ 390 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read); 391 } 392 /* Convert from little endian to CPU */ 393 msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size); 394 msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command); 395 msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector); 396 397 /* No need to update the read positions, because this was a peek */ 398 /* If the caller specifically want to peek, return */ 399 if (peekonly) { 400 memcpy(msg, &msg_tmp, sizeof(*msg)); 401 goto peekout; 402 } 403 404 /* Check if the command/response matches what is expected */ 405 if ((msg_tmp.id != msg->id) || (msg_tmp.command != msg->command) || 406 (msg_tmp.controlselector != msg->controlselector) || 407 (msg_tmp.seqno != msg->seqno) || (msg_tmp.size != msg->size)) { 408 409 printk(KERN_ERR "%s() Unexpected msg miss-match\n", __func__); 410 saa7164_bus_dumpmsg(dev, msg, buf); 411 saa7164_bus_dumpmsg(dev, &msg_tmp, NULL); 412 ret = SAA_ERR_INVALID_COMMAND; 413 goto out; 414 } 415 416 /* Get the actual command and response from the bus */ 417 buf_size = msg->size; 418 419 bytes_to_read = sizeof(*msg) + msg->size; 420 /* Calculate write distance to current read position */ 421 write_distance = 0; 422 if (curr_gwp >= curr_grp) 423 /* Write doesn't wrap around the ring */ 424 write_distance = curr_gwp - curr_grp; 425 else 426 /* Write wraps around the ring */ 427 write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp; 428 429 if (bytes_to_read > write_distance) { 430 printk(KERN_ERR "%s() Invalid bus state, missing msg " 431 "or mangled ring, faulty H/W / bad code?\n", __func__); 432 ret = SAA_ERR_INVALID_COMMAND; 433 goto out; 434 } 435 436 /* Calculate the new read position */ 437 new_grp = curr_grp + bytes_to_read; 438 if (new_grp > bus->m_dwSizeGetRing) { 439 440 /* Ring wraps */ 441 new_grp -= bus->m_dwSizeGetRing; 442 space_rem = bus->m_dwSizeGetRing - curr_grp; 443 444 if (space_rem < sizeof(*msg)) { 445 /* msg wraps around the ring */ 446 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem); 447 memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing, 448 sizeof(*msg) - space_rem); 449 if (buf) 450 memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) - 451 space_rem, buf_size); 452 453 } else if (space_rem == sizeof(*msg)) { 454 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 455 if (buf) 456 memcpy_fromio(buf, bus->m_pdwGetRing, buf_size); 457 } else { 458 /* Additional data wraps around the ring */ 459 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 460 if (buf) { 461 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + 462 sizeof(*msg), space_rem - sizeof(*msg)); 463 memcpy_fromio(buf + space_rem - sizeof(*msg), 464 bus->m_pdwGetRing, bytes_to_read - 465 space_rem); 466 } 467 468 } 469 470 } else { 471 /* No wrapping */ 472 memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); 473 if (buf) 474 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), 475 buf_size); 476 } 477 /* Convert from little endian to CPU */ 478 msg->size = le16_to_cpu((__force __le16)msg->size); 479 msg->command = le32_to_cpu((__force __le32)msg->command); 480 msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector); 481 482 /* Update the read positions, adjusting the ring */ 483 saa7164_writel(bus->m_dwGetReadPos, new_grp); 484 485 peekout: 486 ret = SAA_OK; 487 out: 488 mutex_unlock(&bus->lock); 489 saa7164_bus_verify(dev); 490 return ret; 491 } 492 493