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
40 * To read or write information to the SCU, driver writes to IPC-1 memory
47 * the IPC-1 register block, causing an interrupt to the SCU
49 * 3. SCU firmware decodes this interrupt and IPC message and the appropriate
73 * 16 byte buffer for sending and receiving data to and from SCU.
82 static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
89 * intel_scu_ipc_dev_get() - Get SCU IPC instance
91 * The recommended new API takes SCU IPC instance as parameter and this
98 * Returns %NULL if SCU IPC is not currently available.
102 struct intel_scu_ipc_dev *scu = NULL; in intel_scu_ipc_dev_get() local
114 scu = ipcdev; in intel_scu_ipc_dev_get()
118 return scu; 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
130 void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_dev_put() argument
132 if (scu) { in intel_scu_ipc_dev_put()
133 module_put(scu->owner); in intel_scu_ipc_dev_put()
134 put_device(&scu->dev); in intel_scu_ipc_dev_put()
140 struct intel_scu_ipc_dev *scu; member
146 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_dev_release() local
148 intel_scu_ipc_dev_put(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
160 * Returns %NULL if SCU IPC is not currently available.
165 struct intel_scu_ipc_dev *scu; in devm_intel_scu_ipc_dev_get() local
171 scu = intel_scu_ipc_dev_get(); in devm_intel_scu_ipc_dev_get()
172 if (!scu) { in devm_intel_scu_ipc_dev_get()
177 dr->scu = scu; in devm_intel_scu_ipc_dev_get()
180 return scu; in devm_intel_scu_ipc_dev_get()
187 * A write to this register results in an interrupt to the SCU core processor
191 static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd) in ipc_command() argument
193 reinit_completion(&scu->cmd_complete); in ipc_command()
194 writel(cmd | IPC_IOC, scu->ipc_base); in ipc_command()
201 * SCU. Size of the data is specified in the IPC_COMMAND_REG register
203 static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset) in ipc_data_writel() argument
205 writel(data, scu->ipc_base + IPC_WRITE_BUFFER + offset); in ipc_data_writel()
211 * block and error status of the IPC command that was just processed by SCU
215 static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu) in ipc_read_status() argument
217 return __raw_readl(scu->ipc_base + IPC_STATUS); in ipc_read_status()
221 static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset) in ipc_data_readb() argument
223 return readb(scu->ipc_base + IPC_READ_BUFFER + offset); in ipc_data_readb()
227 static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) in ipc_data_readl() argument
229 return readl(scu->ipc_base + IPC_READ_BUFFER + offset); in ipc_data_readl()
232 /* Wait till scu status is busy */
233 static inline int busy_loop(struct intel_scu_ipc_dev *scu) in busy_loop() argument
238 err = readx_poll_timeout(ipc_read_status, scu, status, !(status & IPC_STATUS_BUSY), in busy_loop()
247 static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) in ipc_wait_for_interrupt() argument
251 wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT); in ipc_wait_for_interrupt()
253 status = ipc_read_status(scu); in ipc_wait_for_interrupt()
263 static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_check_status() argument
265 return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); in intel_scu_ipc_check_status()
268 static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_get() argument
272 if (!scu) in intel_scu_ipc_get()
273 scu = ipcdev; in intel_scu_ipc_get()
274 if (!scu) in intel_scu_ipc_get()
277 status = ipc_read_status(scu); in intel_scu_ipc_get()
279 dev_dbg(&scu->dev, "device is busy\n"); in intel_scu_ipc_get()
283 return scu; in intel_scu_ipc_get()
287 static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in pwr_reg_rdwr() argument
299 scu = intel_scu_ipc_get(scu); in pwr_reg_rdwr()
300 if (IS_ERR(scu)) { in pwr_reg_rdwr()
302 return PTR_ERR(scu); in pwr_reg_rdwr()
312 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
313 ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
318 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
319 ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
323 ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */ in pwr_reg_rdwr()
324 ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
327 err = intel_scu_ipc_check_status(scu); in pwr_reg_rdwr()
330 memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16); in pwr_reg_rdwr()
332 data[nc] = ipc_data_readb(scu, nc); in pwr_reg_rdwr()
339 * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU
340 * @scu: Optional SCU IPC instance
341 * @addr: Register on SCU
345 * locking between SCU accesses is handled for the caller.
349 int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) in intel_scu_ipc_dev_ioread8() argument
351 return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_ioread8()
356 * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU
357 * @scu: Optional SCU IPC instance
358 * @addr: Register on SCU
362 * locking between SCU accesses is handled for the caller.
366 int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) in intel_scu_ipc_dev_iowrite8() argument
368 return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_iowrite8()
374 * @scu: Optional SCU IPC instance
380 * between SCU accesses is handled for the caller.
386 int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_readv() argument
389 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_readv()
395 * @scu: Optional SCU IPC instance
401 * between SCU accesses is handled for the caller.
407 int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_writev() argument
410 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_writev()
416 * @scu: Optional SCU IPC instance
426 * This function may sleep. Locking between SCU accesses is handled
429 int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data, in intel_scu_ipc_dev_update() argument
433 return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); in intel_scu_ipc_dev_update()
439 * @scu: Optional SCU IPC instance
443 * Issue a simple command to the SCU. Do not use this interface if you must
444 * then access data as any data values may be overwritten by another SCU
447 * This function may sleep. Locking for SCU accesses is handled for the
450 int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, in intel_scu_ipc_dev_simple_command() argument
457 scu = intel_scu_ipc_get(scu); in intel_scu_ipc_dev_simple_command()
458 if (IS_ERR(scu)) { in intel_scu_ipc_dev_simple_command()
460 return PTR_ERR(scu); in intel_scu_ipc_dev_simple_command()
464 ipc_command(scu, cmdval); in intel_scu_ipc_dev_simple_command()
465 err = intel_scu_ipc_check_status(scu); in intel_scu_ipc_dev_simple_command()
468 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_simple_command()
475 * @scu: Optional SCU IPC instance
486 * Issue a command to the SCU which involves data transfers. Do the
489 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
502 scu = intel_scu_ipc_get(scu); in intel_scu_ipc_dev_command_with_size()
503 if (IS_ERR(scu)) { in intel_scu_ipc_dev_command_with_size()
505 return PTR_ERR(scu); in intel_scu_ipc_dev_command_with_size()
510 ipc_data_writel(scu, inbuf[i], 4 * i); in intel_scu_ipc_dev_command_with_size()
513 ipc_command(scu, cmdval); in intel_scu_ipc_dev_command_with_size()
514 err = intel_scu_ipc_check_status(scu); in intel_scu_ipc_dev_command_with_size()
520 outbuf[i] = ipc_data_readl(scu, 4 * i); in intel_scu_ipc_dev_command_with_size()
527 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); in intel_scu_ipc_dev_command_with_size()
541 struct intel_scu_ipc_dev *scu = dev_id; in ioc() local
542 int status = ipc_read_status(scu); in ioc()
544 writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS); in ioc()
545 complete(&scu->cmd_complete); in ioc()
552 struct intel_scu_ipc_dev *scu; in intel_scu_ipc_release() local
554 scu = container_of(dev, struct intel_scu_ipc_dev, dev); in intel_scu_ipc_release()
555 if (scu->irq > 0) in intel_scu_ipc_release()
556 free_irq(scu->irq, scu); in intel_scu_ipc_release()
557 iounmap(scu->ipc_base); in intel_scu_ipc_release()
558 release_mem_region(scu->mem.start, resource_size(&scu->mem)); in intel_scu_ipc_release()
559 kfree(scu); in intel_scu_ipc_release()
563 * __intel_scu_ipc_register() - Register SCU IPC device
565 * @scu_data: Data used to configure SCU IPC
566 * @owner: Module registering the SCU IPC device
568 * Call this function to register SCU IPC mechanism under @parent.
569 * Returns pointer to the new SCU IPC device or ERR_PTR() in case of
571 * SCU IPC calls itself.
579 struct intel_scu_ipc_dev *scu; in __intel_scu_ipc_register() local
589 scu = kzalloc(sizeof(*scu), GFP_KERNEL); in __intel_scu_ipc_register()
590 if (!scu) { in __intel_scu_ipc_register()
595 scu->owner = owner; in __intel_scu_ipc_register()
596 scu->dev.parent = parent; in __intel_scu_ipc_register()
597 scu->dev.class = &intel_scu_ipc_class; in __intel_scu_ipc_register()
598 scu->dev.release = intel_scu_ipc_release; in __intel_scu_ipc_register()
612 scu->ipc_base = ipc_base; in __intel_scu_ipc_register()
613 scu->mem = scu_data->mem; in __intel_scu_ipc_register()
614 scu->irq = scu_data->irq; in __intel_scu_ipc_register()
615 init_completion(&scu->cmd_complete); in __intel_scu_ipc_register()
617 if (scu->irq > 0) { in __intel_scu_ipc_register()
618 err = request_irq(scu->irq, ioc, 0, "intel_scu_ipc", scu); in __intel_scu_ipc_register()
625 * releasing the SCU IPC resources once refcount drops to zero. in __intel_scu_ipc_register()
627 dev_set_name(&scu->dev, "intel_scu_ipc"); in __intel_scu_ipc_register()
628 err = device_register(&scu->dev); in __intel_scu_ipc_register()
630 put_device(&scu->dev); in __intel_scu_ipc_register()
635 ipcdev = scu; in __intel_scu_ipc_register()
638 return scu; in __intel_scu_ipc_register()
645 kfree(scu); in __intel_scu_ipc_register()
654 * intel_scu_ipc_unregister() - Unregister SCU IPC
655 * @scu: SCU IPC handle
657 * This unregisters the SCU IPC device and releases the acquired
660 void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_unregister() argument
665 device_unregister(&scu->dev); in intel_scu_ipc_unregister()
674 struct intel_scu_ipc_dev *scu = dr->scu; in devm_intel_scu_ipc_unregister() local
676 intel_scu_ipc_unregister(scu); in devm_intel_scu_ipc_unregister()
680 * __devm_intel_scu_ipc_register() - Register managed SCU IPC device
682 * @scu_data: Data used to configure SCU IPC
683 * @owner: Module registering the SCU IPC device
685 * Call this function to register managed SCU IPC mechanism under
686 * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in
688 * to do SCU IPC calls itself.
696 struct intel_scu_ipc_dev *scu; in __devm_intel_scu_ipc_register() local
702 scu = __intel_scu_ipc_register(parent, scu_data, owner); in __devm_intel_scu_ipc_register()
703 if (IS_ERR(scu)) { in __devm_intel_scu_ipc_register()
705 return scu; in __devm_intel_scu_ipc_register()
708 dr->scu = scu; in __devm_intel_scu_ipc_register()
711 return scu; in __devm_intel_scu_ipc_register()