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
39 * To read or write information to the SCU, driver writes to IPC-1 memory
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
72 * 16 byte buffer for sending and receiving data to and from SCU.
81 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
240 status = ipc_read_status(scu); in busy_loop()
251 static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) in ipc_wait_for_interrupt() argument
255 if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) in ipc_wait_for_interrupt()
258 status = ipc_read_status(scu); in ipc_wait_for_interrupt()
265 static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_check_status() argument
267 return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); in intel_scu_ipc_check_status()
271 static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in pwr_reg_rdwr() argument
283 if (!scu) in pwr_reg_rdwr()
284 scu = ipcdev; in pwr_reg_rdwr()
285 if (!scu) { in pwr_reg_rdwr()
297 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
298 ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
303 ipc_data_writel(scu, wbuf[nc], offset); in pwr_reg_rdwr()
304 ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
308 ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */ in pwr_reg_rdwr()
309 ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op); in pwr_reg_rdwr()
312 err = intel_scu_ipc_check_status(scu); in pwr_reg_rdwr()
315 memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16); in pwr_reg_rdwr()
317 data[nc] = ipc_data_readb(scu, nc); in pwr_reg_rdwr()
324 * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU
325 * @scu: Optional SCU IPC instance
326 * @addr: Register on SCU
330 * locking between SCU accesses is handled for the caller.
334 int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) in intel_scu_ipc_dev_ioread8() argument
336 return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_ioread8()
341 * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU
342 * @scu: Optional SCU IPC instance
343 * @addr: Register on SCU
347 * locking between SCU accesses is handled for the caller.
351 int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) in intel_scu_ipc_dev_iowrite8() argument
353 return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_iowrite8()
359 * @scu: Optional SCU IPC instance
365 * between SCU accesses is handled for the caller.
371 int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_readv() argument
374 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); in intel_scu_ipc_dev_readv()
380 * @scu: Optional SCU IPC instance
386 * between SCU accesses is handled for the caller.
392 int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, in intel_scu_ipc_dev_writev() argument
395 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); in intel_scu_ipc_dev_writev()
401 * @scu: Optional SCU IPC instance
411 * This function may sleep. Locking between SCU accesses is handled
414 int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data, in intel_scu_ipc_dev_update() argument
418 return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); in intel_scu_ipc_dev_update()
424 * @scu: Optional SCU IPC instance
428 * Issue a simple command to the SCU. Do not use this interface if you must
429 * then access data as any data values may be overwritten by another SCU
432 * This function may sleep. Locking for SCU accesses is handled for the
435 int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, in intel_scu_ipc_dev_simple_command() argument
442 if (!scu) in intel_scu_ipc_dev_simple_command()
443 scu = ipcdev; in intel_scu_ipc_dev_simple_command()
444 if (!scu) { in intel_scu_ipc_dev_simple_command()
448 scu = ipcdev; in intel_scu_ipc_dev_simple_command()
450 ipc_command(scu, cmdval); in intel_scu_ipc_dev_simple_command()
451 err = intel_scu_ipc_check_status(scu); 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()
461 * @scu: Optional SCU IPC instance
472 * Issue a command to the SCU which involves data transfers. Do the
475 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
488 if (!scu) in intel_scu_ipc_dev_command_with_size()
489 scu = ipcdev; in intel_scu_ipc_dev_command_with_size()
490 if (!scu) { in intel_scu_ipc_dev_command_with_size()
497 ipc_data_writel(scu, inbuf[i], 4 * i); in intel_scu_ipc_dev_command_with_size()
500 ipc_command(scu, cmdval); in intel_scu_ipc_dev_command_with_size()
501 err = intel_scu_ipc_check_status(scu); in intel_scu_ipc_dev_command_with_size()
507 outbuf[i] = ipc_data_readl(scu, 4 * i); 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()
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; in intel_scu_ipc_release() local
541 scu = container_of(dev, struct intel_scu_ipc_dev, dev); in intel_scu_ipc_release()
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()
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.
566 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()
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()
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()
622 ipcdev = scu; in __intel_scu_ipc_register()
625 return scu; in __intel_scu_ipc_register()
632 kfree(scu); 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
647 void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu) in intel_scu_ipc_unregister() argument
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() local
663 intel_scu_ipc_unregister(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.
683 struct intel_scu_ipc_dev *scu; in __devm_intel_scu_ipc_register() local
689 scu = __intel_scu_ipc_register(parent, scu_data, owner); in __devm_intel_scu_ipc_register()
690 if (IS_ERR(scu)) { in __devm_intel_scu_ipc_register()
692 return scu; in __devm_intel_scu_ipc_register()
695 dr->scu = scu; in __devm_intel_scu_ipc_register()
698 return scu; in __devm_intel_scu_ipc_register()