Lines Matching full:scu

3  * Driver for the Intel SCU IPC mechanism
8 * SCU running in ARC processor communicates with other entity running in IA
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
41 * To read or write information to the SCU, driver writes to IPC-1 memory
48 * the IPC-1 register block, causing an interrupt to the SCU
50 * 3. SCU firmware decodes this interrupt and IPC message and the appropriate
74 * 16 byte buffer for sending and receiving data to and from SCU.
83 static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
90 * intel_scu_ipc_dev_get() - Get SCU IPC instance
92 * The recommended new API takes SCU IPC instance as parameter and this
99 * Returns %NULL if SCU IPC is not currently available.
122 * intel_scu_ipc_dev_put() - Put SCU IPC instance
123 * @scu: SCU IPC instance
125 * This function releases the SCU IPC instance retrieved from
129 void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_dev_put() argument
131 if (scu) { in intel_scu_ipc_dev_put()
132 module_put(scu->owner); in intel_scu_ipc_dev_put()
133 put_device(&scu->dev); in intel_scu_ipc_dev_put()
139 struct intel_scu_ipc_dev *scu; member
145 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_dev_release() local
147 intel_scu_ipc_dev_put(scu); in devm_intel_scu_ipc_dev_release()
151 * devm_intel_scu_ipc_dev_get() - Allocate managed SCU IPC device
152 * @dev: Device requesting the SCU IPC device
154 * The recommended new API takes SCU IPC instance as parameter and this
159 * Returns %NULL if SCU IPC is not currently available.
164 struct intel_scu_ipc_dev *scu; in devm_intel_scu_ipc_dev_get() local
170 scu = intel_scu_ipc_dev_get(); in devm_intel_scu_ipc_dev_get()
171 if (!scu) { in devm_intel_scu_ipc_dev_get()
176 dr->scu = scu; in devm_intel_scu_ipc_dev_get()
179 return scu; in devm_intel_scu_ipc_dev_get()
186 * A write to this register results in an interrupt to the SCU core processor
190 static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd) in ipc_command() argument
192 reinit_completion(&scu->cmd_complete); in ipc_command()
193 writel(cmd | IPC_IOC, scu->ipc_base); in ipc_command()
200 * SCU. Size of the data is specified in the IPC_COMMAND_REG register
202 static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset) in ipc_data_writel() argument
204 writel(data, scu->ipc_base + IPC_WRITE_BUFFER + offset); in ipc_data_writel()
210 * block and error status of the IPC command that was just processed by SCU
214 static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu) in ipc_read_status() argument
216 return __raw_readl(scu->ipc_base + IPC_STATUS); in ipc_read_status()
220 static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) in ipc_data_readl() argument
222 return readl(scu->ipc_base + IPC_READ_BUFFER + offset); in ipc_data_readl()
225 /* Wait till scu status is busy */
226 static inline int busy_loop(struct intel_scu_ipc_dev *scu) in busy_loop() argument
231 err = readx_poll_timeout(ipc_read_status, scu, status, !(status & IPC_STATUS_BUSY), in busy_loop()
240 static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) in ipc_wait_for_interrupt() argument
244 wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT); in ipc_wait_for_interrupt()
246 status = ipc_read_status(scu); in ipc_wait_for_interrupt()
256 static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_check_status() argument
258 return scu->data.irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); in intel_scu_ipc_check_status()
261 static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_get() argument
265 if (!scu) in intel_scu_ipc_get()
266 scu = ipcdev; in intel_scu_ipc_get()
267 if (!scu) in intel_scu_ipc_get()
270 status = ipc_read_status(scu); in intel_scu_ipc_get()
272 dev_dbg(&scu->dev, "device is busy\n"); in intel_scu_ipc_get()
276 return scu; in intel_scu_ipc_get()
280 static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in pwr_reg_rdwr() argument
293 scu = intel_scu_ipc_get(scu); in pwr_reg_rdwr()
294 if (IS_ERR(scu)) in pwr_reg_rdwr()
295 return PTR_ERR(scu); in pwr_reg_rdwr()
304 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
305 ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
310 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
311 ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
315 ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */ in pwr_reg_rdwr()
316 ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
319 err = intel_scu_ipc_check_status(scu); in pwr_reg_rdwr()
325 wbuf[nc] = ipc_data_readl(scu, offset); in pwr_reg_rdwr()
332 * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU
333 * @scu: Optional SCU IPC instance
334 * @addr: Register on SCU
338 * locking between SCU accesses is handled for the caller.
342 int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) in intel_scu_ipc_dev_ioread8() argument
344 return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_ioread8()
349 * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU
350 * @scu: Optional SCU IPC instance
351 * @addr: Register on SCU
355 * locking between SCU accesses is handled for the caller.
359 int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) in intel_scu_ipc_dev_iowrite8() argument
361 return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_iowrite8()
367 * @scu: Optional SCU IPC instance
373 * between SCU accesses is handled for the caller.
379 int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_readv() argument
382 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_readv()
388 * @scu: Optional SCU IPC instance
394 * between SCU accesses is handled for the caller.
400 int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_writev() argument
403 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_writev()
409 * @scu: Optional SCU IPC instance
419 * This function may sleep. Locking between SCU accesses is handled
422 int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data, in intel_scu_ipc_dev_update() argument
426 return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); in intel_scu_ipc_dev_update()
432 * @scu: Optional SCU IPC instance
436 * Issue a simple command to the SCU. Do not use this interface if you must
437 * then access data as any data values may be overwritten by another SCU
440 * This function may sleep. Locking for SCU accesses is handled for the
443 int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, in intel_scu_ipc_dev_simple_command() argument
451 scu = intel_scu_ipc_get(scu); in intel_scu_ipc_dev_simple_command()
452 if (IS_ERR(scu)) in intel_scu_ipc_dev_simple_command()
453 return PTR_ERR(scu); in intel_scu_ipc_dev_simple_command()
456 ipc_command(scu, cmdval); in intel_scu_ipc_dev_simple_command()
457 err = intel_scu_ipc_check_status(scu); in intel_scu_ipc_dev_simple_command()
459 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_simple_command()
466 * @scu: Optional SCU IPC instance
477 * Issue a command to the SCU which involves data transfers. Do the
480 int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, in intel_scu_ipc_dev_command_with_size() argument
494 scu = intel_scu_ipc_get(scu); in intel_scu_ipc_dev_command_with_size()
495 if (IS_ERR(scu)) in intel_scu_ipc_dev_command_with_size()
496 return PTR_ERR(scu); in intel_scu_ipc_dev_command_with_size()
500 ipc_data_writel(scu, inbuf[i], 4 * i); in intel_scu_ipc_dev_command_with_size()
503 ipc_command(scu, cmdval); in intel_scu_ipc_dev_command_with_size()
504 err = intel_scu_ipc_check_status(scu); in intel_scu_ipc_dev_command_with_size()
506 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_command_with_size()
511 outbuf[i] = ipc_data_readl(scu, 4 * i); in intel_scu_ipc_dev_command_with_size()
528 struct intel_scu_ipc_dev *scu = dev_id; in ioc() local
529 int status = ipc_read_status(scu); in ioc()
531 writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS); in ioc()
532 complete(&scu->cmd_complete); in ioc()
539 struct intel_scu_ipc_dev *scu = container_of(dev, struct intel_scu_ipc_dev, dev); in intel_scu_ipc_release() local
540 struct intel_scu_ipc_data *data = &scu->data; in intel_scu_ipc_release()
543 free_irq(data->irq, scu); in intel_scu_ipc_release()
544 iounmap(scu->ipc_base); in intel_scu_ipc_release()
546 kfree(scu); 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.
567 struct intel_scu_ipc_dev *scu; in __intel_scu_ipc_register() local
576 scu = kzalloc(sizeof(*scu), GFP_KERNEL); in __intel_scu_ipc_register()
577 if (!scu) in __intel_scu_ipc_register()
580 scu->owner = owner; in __intel_scu_ipc_register()
581 scu->dev.parent = parent; in __intel_scu_ipc_register()
582 scu->dev.class = &intel_scu_ipc_class; in __intel_scu_ipc_register()
583 scu->dev.release = intel_scu_ipc_release; in __intel_scu_ipc_register()
585 memcpy(&scu->data, scu_data, sizeof(scu->data)); in __intel_scu_ipc_register()
586 data = &scu->data; in __intel_scu_ipc_register()
599 scu->ipc_base = ipc_base; in __intel_scu_ipc_register()
600 init_completion(&scu->cmd_complete); in __intel_scu_ipc_register()
603 err = request_irq(data->irq, ioc, 0, "intel_scu_ipc", scu); in __intel_scu_ipc_register()
610 * releasing the SCU IPC resources once refcount drops to zero. in __intel_scu_ipc_register()
612 dev_set_name(&scu->dev, "intel_scu_ipc"); in __intel_scu_ipc_register()
613 err = device_register(&scu->dev); in __intel_scu_ipc_register()
615 put_device(&scu->dev); in __intel_scu_ipc_register()
620 ipcdev = scu; in __intel_scu_ipc_register()
621 return scu; in __intel_scu_ipc_register()
628 kfree(scu); in __intel_scu_ipc_register()
634 * intel_scu_ipc_unregister() - Unregister SCU IPC
635 * @scu: SCU IPC handle
637 * This unregisters the SCU IPC device and releases the acquired
640 void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_unregister() argument
646 device_unregister(&scu->dev); in intel_scu_ipc_unregister()
654 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_unregister() local
656 intel_scu_ipc_unregister(scu); in devm_intel_scu_ipc_unregister()
660 * __devm_intel_scu_ipc_register() - Register managed SCU IPC device
662 * @scu_data: Data used to configure SCU IPC
663 * @owner: Module registering the SCU IPC device
665 * Call this function to register managed SCU IPC mechanism under
666 * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in
668 * to do SCU IPC calls itself.
676 struct intel_scu_ipc_dev *scu; in __devm_intel_scu_ipc_register() local
682 scu = __intel_scu_ipc_register(parent, scu_data, owner); in __devm_intel_scu_ipc_register()
683 if (IS_ERR(scu)) { in __devm_intel_scu_ipc_register()
685 return scu; in __devm_intel_scu_ipc_register()
688 dr->scu = scu; in __devm_intel_scu_ipc_register()
691 return scu; in __devm_intel_scu_ipc_register()