Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: intel_scu_ipc: Introduce new SCU IPC API

The current SCU IPC API has been operating on a single instance and
there has been no way to pin the providing module in place when the SCU
IPC is in use.

This implements a new API that takes the SCU IPC instance as first
parameter (NULL means the single instance is being used). The SCU IPC
instance can be retrieved by calling new function intel_scu_ipc_dev_get()
that take care of pinning the providing module in place as long as
intel_scu_ipc_dev_put() is not called.

The old API is updated to call the new API and is is left there in the
legacy API header to support the existing users that cannot be converted
easily.

Subsequent patches will convert most of the users over to the new API.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Mika Westerberg and committed by
Lee Jones
f57fa185 dd885649

+252 -61
+36 -2
arch/x86/include/asm/intel_scu_ipc.h
··· 18 18 }; 19 19 20 20 struct intel_scu_ipc_dev * 21 - intel_scu_ipc_register(struct device *parent, 22 - const struct intel_scu_ipc_data *scu_data); 21 + __intel_scu_ipc_register(struct device *parent, 22 + const struct intel_scu_ipc_data *scu_data, 23 + struct module *owner); 24 + 25 + #define intel_scu_ipc_register(parent, scu_data) \ 26 + __intel_scu_ipc_register(parent, scu_data, THIS_MODULE) 27 + 28 + struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void); 29 + void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu); 30 + struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev); 31 + 32 + int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, 33 + u8 *data); 34 + int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, 35 + u8 data); 36 + int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, 37 + u8 *data, size_t len); 38 + int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, 39 + u8 *data, size_t len); 40 + 41 + int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, 42 + u8 data, u8 mask); 43 + 44 + int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, 45 + int sub); 46 + int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, 47 + int sub, const void *in, size_t inlen, 48 + size_t size, void *out, size_t outlen); 49 + 50 + static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd, 51 + int sub, const void *in, size_t inlen, 52 + void *out, size_t outlen) 53 + { 54 + return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen, 55 + inlen, out, outlen); 56 + } 23 57 24 58 #include <asm/intel_scu_ipc_legacy.h> 25 59
+37 -8
arch/x86/include/asm/intel_scu_ipc_legacy.h
··· 19 19 #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ 20 20 #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ 21 21 22 + /* Don't call these in new code - they will be removed eventually */ 23 + 22 24 /* Read single register */ 23 - int intel_scu_ipc_ioread8(u16 addr, u8 *data); 25 + static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data) 26 + { 27 + return intel_scu_ipc_dev_ioread8(NULL, addr, data); 28 + } 24 29 25 30 /* Read a vector */ 26 - int intel_scu_ipc_readv(u16 *addr, u8 *data, int len); 31 + static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) 32 + { 33 + return intel_scu_ipc_dev_readv(NULL, addr, data, len); 34 + } 27 35 28 36 /* Write single register */ 29 - int intel_scu_ipc_iowrite8(u16 addr, u8 data); 37 + static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data) 38 + { 39 + return intel_scu_ipc_dev_iowrite8(NULL, addr, data); 40 + } 30 41 31 42 /* Write a vector */ 32 - int intel_scu_ipc_writev(u16 *addr, u8 *data, int len); 43 + static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) 44 + { 45 + return intel_scu_ipc_dev_writev(NULL, addr, data, len); 46 + } 33 47 34 48 /* Update single register based on the mask */ 35 - int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask); 49 + static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask) 50 + { 51 + return intel_scu_ipc_dev_update(NULL, addr, data, mask); 52 + } 36 53 37 54 /* Issue commands to the SCU with or without data */ 38 - int intel_scu_ipc_simple_command(int cmd, int sub); 39 - int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 40 - u32 *out, int outlen); 55 + static inline int intel_scu_ipc_simple_command(int cmd, int sub) 56 + { 57 + return intel_scu_ipc_dev_simple_command(NULL, cmd, sub); 58 + } 59 + 60 + static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 61 + u32 *out, int outlen) 62 + { 63 + /* New API takes both inlen and outlen as bytes so convert here */ 64 + size_t inbytes = inlen * sizeof(u32); 65 + size_t outbytes = outlen * sizeof(u32); 66 + 67 + return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes, 68 + inlen, out, outbytes); 69 + } 41 70 42 71 extern struct blocking_notifier_head intel_scu_notifier; 43 72
+179 -51
drivers/platform/x86/intel_scu_ipc.c
··· 56 56 struct intel_scu_ipc_dev { 57 57 struct device dev; 58 58 struct resource mem; 59 + struct module *owner; 59 60 int irq; 60 61 void __iomem *ipc_base; 61 62 struct completion cmd_complete; ··· 84 83 .name = "intel_scu_ipc", 85 84 .owner = THIS_MODULE, 86 85 }; 86 + 87 + /** 88 + * intel_scu_ipc_dev_get() - Get SCU IPC instance 89 + * 90 + * The recommended new API takes SCU IPC instance as parameter and this 91 + * function can be called by driver to get the instance. This also makes 92 + * sure the driver providing the IPC functionality cannot be unloaded 93 + * while the caller has the instance. 94 + * 95 + * Call intel_scu_ipc_dev_put() to release the instance. 96 + * 97 + * Returns %NULL if SCU IPC is not currently available. 98 + */ 99 + struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void) 100 + { 101 + struct intel_scu_ipc_dev *scu = NULL; 102 + 103 + mutex_lock(&ipclock); 104 + if (ipcdev) { 105 + get_device(&ipcdev->dev); 106 + /* 107 + * Prevent the IPC provider from being unloaded while it 108 + * is being used. 109 + */ 110 + if (!try_module_get(ipcdev->owner)) 111 + put_device(&ipcdev->dev); 112 + else 113 + scu = ipcdev; 114 + } 115 + 116 + mutex_unlock(&ipclock); 117 + return scu; 118 + } 119 + EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_get); 120 + 121 + /** 122 + * intel_scu_ipc_dev_put() - Put SCU IPC instance 123 + * @scu: SCU IPC instance 124 + * 125 + * This function releases the SCU IPC instance retrieved from 126 + * intel_scu_ipc_dev_get() and allows the driver providing IPC to be 127 + * unloaded. 128 + */ 129 + void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu) 130 + { 131 + if (scu) { 132 + module_put(scu->owner); 133 + put_device(&scu->dev); 134 + } 135 + } 136 + EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_put); 137 + 138 + struct intel_scu_ipc_devres { 139 + struct intel_scu_ipc_dev *scu; 140 + }; 141 + 142 + static void devm_intel_scu_ipc_dev_release(struct device *dev, void *res) 143 + { 144 + struct intel_scu_ipc_devres *dr = res; 145 + struct intel_scu_ipc_dev *scu = dr->scu; 146 + 147 + intel_scu_ipc_dev_put(scu); 148 + } 149 + 150 + /** 151 + * devm_intel_scu_ipc_dev_get() - Allocate managed SCU IPC device 152 + * @dev: Device requesting the SCU IPC device 153 + * 154 + * The recommended new API takes SCU IPC instance as parameter and this 155 + * function can be called by driver to get the instance. This also makes 156 + * sure the driver providing the IPC functionality cannot be unloaded 157 + * while the caller has the instance. 158 + * 159 + * Returns %NULL if SCU IPC is not currently available. 160 + */ 161 + struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev) 162 + { 163 + struct intel_scu_ipc_devres *dr; 164 + struct intel_scu_ipc_dev *scu; 165 + 166 + dr = devres_alloc(devm_intel_scu_ipc_dev_release, sizeof(*dr), GFP_KERNEL); 167 + if (!dr) 168 + return NULL; 169 + 170 + scu = intel_scu_ipc_dev_get(); 171 + if (!scu) { 172 + devres_free(dr); 173 + return NULL; 174 + } 175 + 176 + dr->scu = scu; 177 + devres_add(dev, dr); 178 + 179 + return scu; 180 + } 181 + EXPORT_SYMBOL_GPL(devm_intel_scu_ipc_dev_get); 87 182 88 183 /* 89 184 * Send ipc command ··· 268 171 } 269 172 270 173 /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ 271 - static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) 174 + static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 175 + u32 count, u32 op, u32 id) 272 176 { 273 - struct intel_scu_ipc_dev *scu; 274 177 int nc; 275 178 u32 offset = 0; 276 179 int err; ··· 280 183 memset(cbuf, 0, sizeof(cbuf)); 281 184 282 185 mutex_lock(&ipclock); 283 - if (!ipcdev) { 186 + if (!scu) 187 + scu = ipcdev; 188 + if (!scu) { 284 189 mutex_unlock(&ipclock); 285 190 return -ENODEV; 286 191 } 287 - scu = ipcdev; 288 192 289 193 for (nc = 0; nc < count; nc++, offset += 2) { 290 194 cbuf[offset] = addr[nc]; ··· 321 223 } 322 224 323 225 /** 324 - * intel_scu_ipc_ioread8 - read a word via the SCU 226 + * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU 227 + * @scu: Optional SCU IPC instance 325 228 * @addr: Register on SCU 326 229 * @data: Return pointer for read byte 327 230 * ··· 331 232 * 332 233 * This function may sleep. 333 234 */ 334 - int intel_scu_ipc_ioread8(u16 addr, u8 *data) 235 + int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) 335 236 { 336 - return pwr_reg_rdwr(&addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 237 + return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 337 238 } 338 - EXPORT_SYMBOL(intel_scu_ipc_ioread8); 239 + EXPORT_SYMBOL(intel_scu_ipc_dev_ioread8); 339 240 340 241 /** 341 - * intel_scu_ipc_iowrite8 - write a byte via the SCU 242 + * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU 243 + * @scu: Optional SCU IPC instance 342 244 * @addr: Register on SCU 343 245 * @data: Byte to write 344 246 * ··· 348 248 * 349 249 * This function may sleep. 350 250 */ 351 - int intel_scu_ipc_iowrite8(u16 addr, u8 data) 251 + int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) 352 252 { 353 - return pwr_reg_rdwr(&addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 253 + return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 354 254 } 355 - EXPORT_SYMBOL(intel_scu_ipc_iowrite8); 255 + EXPORT_SYMBOL(intel_scu_ipc_dev_iowrite8); 356 256 357 257 /** 358 - * intel_scu_ipc_readvv - read a set of registers 258 + * intel_scu_ipc_dev_readv() - Read a set of registers 259 + * @scu: Optional SCU IPC instance 359 260 * @addr: Register list 360 261 * @data: Bytes to return 361 262 * @len: Length of array ··· 368 267 * 369 268 * This function may sleep. 370 269 */ 371 - int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) 270 + int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 271 + size_t len) 372 272 { 373 - return pwr_reg_rdwr(addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 273 + return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 374 274 } 375 - EXPORT_SYMBOL(intel_scu_ipc_readv); 275 + EXPORT_SYMBOL(intel_scu_ipc_dev_readv); 376 276 377 277 /** 378 - * intel_scu_ipc_writev - write a set of registers 278 + * intel_scu_ipc_dev_writev() - Write a set of registers 279 + * @scu: Optional SCU IPC instance 379 280 * @addr: Register list 380 281 * @data: Bytes to write 381 282 * @len: Length of array ··· 389 286 * 390 287 * This function may sleep. 391 288 */ 392 - int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) 289 + int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 290 + size_t len) 393 291 { 394 - return pwr_reg_rdwr(addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 292 + return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 395 293 } 396 - EXPORT_SYMBOL(intel_scu_ipc_writev); 294 + EXPORT_SYMBOL(intel_scu_ipc_dev_writev); 397 295 398 296 /** 399 - * intel_scu_ipc_update_register - r/m/w a register 297 + * intel_scu_ipc_dev_update() - Update a register 298 + * @scu: Optional SCU IPC instance 400 299 * @addr: Register address 401 - * @bits: Bits to update 300 + * @data: Bits to update 402 301 * @mask: Mask of bits to update 403 302 * 404 303 * Read-modify-write power control unit register. The first data argument ··· 411 306 * This function may sleep. Locking between SCU accesses is handled 412 307 * for the caller. 413 308 */ 414 - int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask) 309 + int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data, 310 + u8 mask) 415 311 { 416 - u8 data[2] = { bits, mask }; 417 - return pwr_reg_rdwr(&addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); 312 + u8 tmp[2] = { data, mask }; 313 + return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); 418 314 } 419 - EXPORT_SYMBOL(intel_scu_ipc_update_register); 315 + EXPORT_SYMBOL(intel_scu_ipc_dev_update); 420 316 421 317 /** 422 - * intel_scu_ipc_simple_command - send a simple command 318 + * intel_scu_ipc_dev_simple_command() - Send a simple command 319 + * @scu: Optional SCU IPC instance 423 320 * @cmd: Command 424 321 * @sub: Sub type 425 322 * ··· 432 325 * This function may sleep. Locking for SCU accesses is handled for the 433 326 * caller. 434 327 */ 435 - int intel_scu_ipc_simple_command(int cmd, int sub) 328 + int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, 329 + int sub) 436 330 { 437 - struct intel_scu_ipc_dev *scu; 438 331 u32 cmdval; 439 332 int err; 440 333 441 334 mutex_lock(&ipclock); 442 - if (!ipcdev) { 335 + if (!scu) 336 + scu = ipcdev; 337 + if (!scu) { 443 338 mutex_unlock(&ipclock); 444 339 return -ENODEV; 445 340 } ··· 454 345 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 455 346 return err; 456 347 } 457 - EXPORT_SYMBOL(intel_scu_ipc_simple_command); 348 + EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command); 458 349 459 350 /** 460 - * intel_scu_ipc_command - command with data 351 + * intel_scu_ipc_command_with_size() - Command with data 352 + * @scu: Optional SCU IPC instance 461 353 * @cmd: Command 462 354 * @sub: Sub type 463 355 * @in: Input data 464 - * @inlen: Input length in dwords 356 + * @inlen: Input length in bytes 357 + * @size: Input size written to the IPC command register in whatever 358 + * units (dword, byte) the particular firmware requires. Normally 359 + * should be the same as @inlen. 465 360 * @out: Output data 466 - * @outlen: Output length in dwords 361 + * @outlen: Output length in bytes 467 362 * 468 363 * Issue a command to the SCU which involves data transfers. Do the 469 364 * data copies under the lock but leave it for the caller to interpret. 470 365 */ 471 - int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 472 - u32 *out, int outlen) 366 + int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, 367 + int sub, const void *in, size_t inlen, 368 + size_t size, void *out, size_t outlen) 473 369 { 474 - struct intel_scu_ipc_dev *scu; 475 - u32 cmdval; 370 + size_t outbuflen = DIV_ROUND_UP(outlen, sizeof(u32)); 371 + size_t inbuflen = DIV_ROUND_UP(inlen, sizeof(u32)); 372 + u32 cmdval, inbuf[4] = {}; 476 373 int i, err; 477 374 375 + if (inbuflen > 4 || outbuflen > 4) 376 + return -EINVAL; 377 + 478 378 mutex_lock(&ipclock); 479 - if (!ipcdev) { 379 + if (!scu) 380 + scu = ipcdev; 381 + if (!scu) { 480 382 mutex_unlock(&ipclock); 481 383 return -ENODEV; 482 384 } 483 - scu = ipcdev; 484 385 485 - for (i = 0; i < inlen; i++) 486 - ipc_data_writel(scu, *in++, 4 * i); 386 + memcpy(inbuf, in, inlen); 387 + for (i = 0; i < inbuflen; i++) 388 + ipc_data_writel(scu, inbuf[i], 4 * i); 487 389 488 - cmdval = (inlen << 16) | (sub << 12) | cmd; 390 + cmdval = (size << 16) | (sub << 12) | cmd; 489 391 ipc_command(scu, cmdval); 490 392 err = intel_scu_ipc_check_status(scu); 491 393 492 394 if (!err) { 493 - for (i = 0; i < outlen; i++) 494 - *out++ = ipc_data_readl(scu, 4 * i); 395 + u32 outbuf[4] = {}; 396 + 397 + for (i = 0; i < outbuflen; i++) 398 + outbuf[i] = ipc_data_readl(scu, 4 * i); 399 + 400 + memcpy(out, outbuf, outlen); 495 401 } 496 402 497 403 mutex_unlock(&ipclock); ··· 514 390 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 515 391 return err; 516 392 } 517 - EXPORT_SYMBOL(intel_scu_ipc_command); 393 + EXPORT_SYMBOL(intel_scu_ipc_dev_command_with_size); 518 394 519 395 /* 520 396 * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1 ··· 547 423 } 548 424 549 425 /** 550 - * intel_scu_ipc_register() - Register SCU IPC device 426 + * __intel_scu_ipc_register() - Register SCU IPC device 551 427 * @parent: Parent device 552 428 * @scu_data: Data used to configure SCU IPC 429 + * @owner: Module registering the SCU IPC device 553 430 * 554 431 * Call this function to register SCU IPC mechanism under @parent. 555 432 * Returns pointer to the new SCU IPC device or ERR_PTR() in case of 556 - * failure. 433 + * failure. The caller may use the returned instance if it needs to do 434 + * SCU IPC calls itself. 557 435 */ 558 436 struct intel_scu_ipc_dev * 559 - intel_scu_ipc_register(struct device *parent, 560 - const struct intel_scu_ipc_data *scu_data) 437 + __intel_scu_ipc_register(struct device *parent, 438 + const struct intel_scu_ipc_data *scu_data, 439 + struct module *owner) 561 440 { 562 441 int err; 563 442 struct intel_scu_ipc_dev *scu; ··· 579 452 goto err_unlock; 580 453 } 581 454 455 + scu->owner = owner; 582 456 scu->dev.parent = parent; 583 457 scu->dev.class = &intel_scu_ipc_class; 584 458 scu->dev.release = intel_scu_ipc_release; ··· 635 507 636 508 return ERR_PTR(err); 637 509 } 638 - EXPORT_SYMBOL_GPL(intel_scu_ipc_register); 510 + EXPORT_SYMBOL_GPL(__intel_scu_ipc_register); 639 511 640 512 static int __init intel_scu_ipc_init(void) 641 513 {