Lines Matching +full:ipc +full:- +full:3

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for the Intel SCU IPC mechanism
5 * (C) Copyright 2008-2010,2015 Intel Corporation
9 * core through IPC mechanism which in turn messaging between IA core ad SCU.
10 * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
11 * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with
12 * IPC-1 Driver provides an API for power control unit registers (e.g. MSIC)
27 /* IPC defines the following message types */
33 #define IPC_CMD_PCNTRL_M 2 /* Register read-modify-write */
36 * IPC register summary
38 * IPC register blocks are memory mapped at fixed address of PCI BAR 0.
39 * To read or write information to the SCU, driver writes to IPC-1 memory
40 * mapped registers. The following is the IPC mechanism
46 * the IPC-1 register block, causing an interrupt to the SCU
48 * 3. SCU firmware decodes this interrupt and IPC message and the appropriate
52 #define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */
53 #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */
54 #define IPC_IOC 0x100 /* IPC command register IOC bit */
71 * IPC Write/Read Buffers:
89 * intel_scu_ipc_dev_get() - Get SCU IPC instance
91 * The recommended new API takes SCU IPC instance as parameter and this
93 * sure the driver providing the IPC functionality cannot be unloaded
98 * Returns %NULL if SCU IPC is not currently available.
106 get_device(&ipcdev->dev); in intel_scu_ipc_dev_get()
108 * Prevent the IPC provider from being unloaded while it in intel_scu_ipc_dev_get()
111 if (!try_module_get(ipcdev->owner)) in intel_scu_ipc_dev_get()
112 put_device(&ipcdev->dev); in intel_scu_ipc_dev_get()
123 * intel_scu_ipc_dev_put() - Put SCU IPC instance
124 * @scu: SCU IPC instance
126 * This function releases the SCU IPC instance retrieved from
127 * intel_scu_ipc_dev_get() and allows the driver providing IPC to be
133 module_put(scu->owner); in intel_scu_ipc_dev_put()
134 put_device(&scu->dev); in intel_scu_ipc_dev_put()
146 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_dev_release()
152 * devm_intel_scu_ipc_dev_get() - Allocate managed SCU IPC device
153 * @dev: Device requesting the SCU IPC device
155 * The recommended new API takes SCU IPC instance as parameter and this
157 * sure the driver providing the IPC functionality cannot be unloaded
160 * Returns %NULL if SCU IPC is not currently available.
177 dr->scu = scu; in devm_intel_scu_ipc_dev_get()
185 * Send ipc command
189 * |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)|
193 reinit_completion(&scu->cmd_complete); in ipc_command()
194 writel(cmd | IPC_IOC, scu->ipc_base); in ipc_command()
198 * Write ipc data
199 * IPC Write Buffer (Write Only):
200 * 16-byte buffer for sending data associated with IPC command to
205 writel(data, scu->ipc_base + IPC_WRITE_BUFFER + offset); in ipc_data_writel()
210 * Driver will read this register to get the ready/busy status of the IPC
211 * block and error status of the IPC command that was just processed by SCU
217 return __raw_readl(scu->ipc_base + IPC_STATUS); in ipc_read_status()
220 /* Read ipc byte data */
223 return readb(scu->ipc_base + IPC_READ_BUFFER + offset); in ipc_data_readb()
226 /* Read ipc u32 data */
229 return readl(scu->ipc_base + IPC_READ_BUFFER + offset); in ipc_data_readl()
242 return (status & IPC_STATUS_ERR) ? -EIO : 0; in busy_loop()
247 return -ETIMEDOUT; in busy_loop()
250 /* Wait till ipc ioc interrupt is received or timeout in 10 HZ */
255 if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) in ipc_wait_for_interrupt()
256 return -ETIMEDOUT; in ipc_wait_for_interrupt()
260 return -EIO; in ipc_wait_for_interrupt()
267 return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); in intel_scu_ipc_check_status()
287 return -ENODEV; in pwr_reg_rdwr()
304 ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
315 memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16); in pwr_reg_rdwr()
324 * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU
325 * @scu: Optional SCU IPC instance
341 * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU
342 * @scu: Optional SCU IPC instance
358 * intel_scu_ipc_dev_readv() - Read a set of registers
359 * @scu: Optional SCU IPC instance
379 * intel_scu_ipc_dev_writev() - Write a set of registers
380 * @scu: Optional SCU IPC instance
400 * intel_scu_ipc_dev_update() - Update a register
401 * @scu: Optional SCU IPC instance
406 * Read-modify-write power control unit register. The first data argument
423 * intel_scu_ipc_dev_simple_command() - Send a simple command
424 * @scu: Optional SCU IPC instance
446 return -ENODEV; in intel_scu_ipc_dev_simple_command()
454 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_simple_command()
460 * intel_scu_ipc_dev_command_with_size() - Command with data
461 * @scu: Optional SCU IPC instance
466 * @size: Input size written to the IPC command register in whatever
485 return -EINVAL; in intel_scu_ipc_dev_command_with_size()
492 return -ENODEV; in intel_scu_ipc_dev_command_with_size()
514 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_command_with_size()
531 writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS); in ioc()
532 complete(&scu->cmd_complete); in ioc()
542 if (scu->irq > 0) in intel_scu_ipc_release()
543 free_irq(scu->irq, scu); in intel_scu_ipc_release()
544 iounmap(scu->ipc_base); in intel_scu_ipc_release()
545 release_mem_region(scu->mem.start, resource_size(&scu->mem)); in intel_scu_ipc_release()
550 * __intel_scu_ipc_register() - Register SCU IPC device
552 * @scu_data: Data used to configure SCU IPC
553 * @owner: Module registering the SCU IPC device
555 * Call this function to register SCU IPC mechanism under @parent.
556 * Returns pointer to the new SCU IPC device or ERR_PTR() in case of
558 * SCU IPC calls itself.
570 /* We support only one IPC */ in __intel_scu_ipc_register()
572 err = -EBUSY; in __intel_scu_ipc_register()
578 err = -ENOMEM; in __intel_scu_ipc_register()
582 scu->owner = owner; in __intel_scu_ipc_register()
583 scu->dev.parent = parent; in __intel_scu_ipc_register()
584 scu->dev.class = &intel_scu_ipc_class; in __intel_scu_ipc_register()
585 scu->dev.release = intel_scu_ipc_release; in __intel_scu_ipc_register()
586 dev_set_name(&scu->dev, "intel_scu_ipc"); in __intel_scu_ipc_register()
588 if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem), in __intel_scu_ipc_register()
590 err = -EBUSY; in __intel_scu_ipc_register()
594 ipc_base = ioremap(scu_data->mem.start, resource_size(&scu_data->mem)); in __intel_scu_ipc_register()
596 err = -ENOMEM; in __intel_scu_ipc_register()
600 scu->ipc_base = ipc_base; in __intel_scu_ipc_register()
601 scu->mem = scu_data->mem; in __intel_scu_ipc_register()
602 scu->irq = scu_data->irq; in __intel_scu_ipc_register()
603 init_completion(&scu->cmd_complete); in __intel_scu_ipc_register()
605 if (scu->irq > 0) { in __intel_scu_ipc_register()
606 err = request_irq(scu->irq, ioc, 0, "intel_scu_ipc", scu); in __intel_scu_ipc_register()
613 * releasing the SCU IPC resources once refcount drops to zero. in __intel_scu_ipc_register()
615 err = device_register(&scu->dev); in __intel_scu_ipc_register()
617 put_device(&scu->dev); in __intel_scu_ipc_register()
630 release_mem_region(scu_data->mem.start, resource_size(&scu_data->mem)); in __intel_scu_ipc_register()
641 * intel_scu_ipc_unregister() - Unregister SCU IPC
642 * @scu: SCU IPC handle
644 * This unregisters the SCU IPC device and releases the acquired
652 device_unregister(&scu->dev); in intel_scu_ipc_unregister()
661 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_unregister()
667 * __devm_intel_scu_ipc_register() - Register managed SCU IPC device
669 * @scu_data: Data used to configure SCU IPC
670 * @owner: Module registering the SCU IPC device
672 * Call this function to register managed SCU IPC mechanism under
673 * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in
675 * to do SCU IPC calls itself.
695 dr->scu = scu; in __devm_intel_scu_ipc_register()