726 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for the Intel SCU IPC mechanism4 *5 * (C) Copyright 2008-2010,2015 Intel Corporation6 * Author: Sreedhara DS (sreedhara.ds@intel.com)7 *8 * SCU running in ARC processor communicates with other entity running in IA9 * 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 and11 * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with12 * IPC-1 Driver provides an API for power control unit registers (e.g. MSIC)13 * along with other APIs.14 */15 16#include <linux/delay.h>17#include <linux/device.h>18#include <linux/errno.h>19#include <linux/init.h>20#include <linux/interrupt.h>21#include <linux/io.h>22#include <linux/iopoll.h>23#include <linux/module.h>24#include <linux/slab.h>25 26#include <linux/platform_data/x86/intel_scu_ipc.h>27 28/* IPC defines the following message types */29#define IPCMSG_PCNTRL 0xff /* Power controller unit read/write */30 31/* Command id associated with message IPCMSG_PCNTRL */32#define IPC_CMD_PCNTRL_W 0 /* Register write */33#define IPC_CMD_PCNTRL_R 1 /* Register read */34#define IPC_CMD_PCNTRL_M 2 /* Register read-modify-write */35 36/*37 * IPC register summary38 *39 * IPC register blocks are memory mapped at fixed address of PCI BAR 0.40 * To read or write information to the SCU, driver writes to IPC-1 memory41 * mapped registers. The following is the IPC mechanism42 *43 * 1. IA core cDMI interface claims this transaction and converts it to a44 * Transaction Layer Packet (TLP) message which is sent across the cDMI.45 *46 * 2. South Complex cDMI block receives this message and writes it to47 * the IPC-1 register block, causing an interrupt to the SCU48 *49 * 3. SCU firmware decodes this interrupt and IPC message and the appropriate50 * message handler is called within firmware.51 */52 53#define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */54#define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */55#define IPC_IOC 0x100 /* IPC command register IOC bit */56 57struct intel_scu_ipc_dev {58 struct device dev;59 struct resource mem;60 struct module *owner;61 int irq;62 void __iomem *ipc_base;63 struct completion cmd_complete;64};65 66#define IPC_STATUS 0x0467#define IPC_STATUS_IRQ BIT(2)68#define IPC_STATUS_ERR BIT(1)69#define IPC_STATUS_BUSY BIT(0)70 71/*72 * IPC Write/Read Buffers:73 * 16 byte buffer for sending and receiving data to and from SCU.74 */75#define IPC_WRITE_BUFFER 0x8076#define IPC_READ_BUFFER 0x9077 78/* Timeout in jiffies */79#define IPC_TIMEOUT (10 * HZ)80 81static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */82static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */83 84static struct class intel_scu_ipc_class = {85 .name = "intel_scu_ipc",86};87 88/**89 * intel_scu_ipc_dev_get() - Get SCU IPC instance90 *91 * The recommended new API takes SCU IPC instance as parameter and this92 * function can be called by driver to get the instance. This also makes93 * sure the driver providing the IPC functionality cannot be unloaded94 * while the caller has the instance.95 *96 * Call intel_scu_ipc_dev_put() to release the instance.97 *98 * Returns %NULL if SCU IPC is not currently available.99 */100struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void)101{102 struct intel_scu_ipc_dev *scu = NULL;103 104 mutex_lock(&ipclock);105 if (ipcdev) {106 get_device(&ipcdev->dev);107 /*108 * Prevent the IPC provider from being unloaded while it109 * is being used.110 */111 if (!try_module_get(ipcdev->owner))112 put_device(&ipcdev->dev);113 else114 scu = ipcdev;115 }116 117 mutex_unlock(&ipclock);118 return scu;119}120EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_get);121 122/**123 * intel_scu_ipc_dev_put() - Put SCU IPC instance124 * @scu: SCU IPC instance125 *126 * This function releases the SCU IPC instance retrieved from127 * intel_scu_ipc_dev_get() and allows the driver providing IPC to be128 * unloaded.129 */130void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu)131{132 if (scu) {133 module_put(scu->owner);134 put_device(&scu->dev);135 }136}137EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_put);138 139struct intel_scu_ipc_devres {140 struct intel_scu_ipc_dev *scu;141};142 143static void devm_intel_scu_ipc_dev_release(struct device *dev, void *res)144{145 struct intel_scu_ipc_devres *dr = res;146 struct intel_scu_ipc_dev *scu = dr->scu;147 148 intel_scu_ipc_dev_put(scu);149}150 151/**152 * devm_intel_scu_ipc_dev_get() - Allocate managed SCU IPC device153 * @dev: Device requesting the SCU IPC device154 *155 * The recommended new API takes SCU IPC instance as parameter and this156 * function can be called by driver to get the instance. This also makes157 * sure the driver providing the IPC functionality cannot be unloaded158 * while the caller has the instance.159 *160 * Returns %NULL if SCU IPC is not currently available.161 */162struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev)163{164 struct intel_scu_ipc_devres *dr;165 struct intel_scu_ipc_dev *scu;166 167 dr = devres_alloc(devm_intel_scu_ipc_dev_release, sizeof(*dr), GFP_KERNEL);168 if (!dr)169 return NULL;170 171 scu = intel_scu_ipc_dev_get();172 if (!scu) {173 devres_free(dr);174 return NULL;175 }176 177 dr->scu = scu;178 devres_add(dev, dr);179 180 return scu;181}182EXPORT_SYMBOL_GPL(devm_intel_scu_ipc_dev_get);183 184/*185 * Send ipc command186 * Command Register (Write Only):187 * A write to this register results in an interrupt to the SCU core processor188 * Format:189 * |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)|190 */191static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)192{193 reinit_completion(&scu->cmd_complete);194 writel(cmd | IPC_IOC, scu->ipc_base);195}196 197/*198 * Write ipc data199 * IPC Write Buffer (Write Only):200 * 16-byte buffer for sending data associated with IPC command to201 * SCU. Size of the data is specified in the IPC_COMMAND_REG register202 */203static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset)204{205 writel(data, scu->ipc_base + IPC_WRITE_BUFFER + offset);206}207 208/*209 * Status Register (Read Only):210 * Driver will read this register to get the ready/busy status of the IPC211 * block and error status of the IPC command that was just processed by SCU212 * Format:213 * |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)|214 */215static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu)216{217 return __raw_readl(scu->ipc_base + IPC_STATUS);218}219 220/* Read ipc byte data */221static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset)222{223 return readb(scu->ipc_base + IPC_READ_BUFFER + offset);224}225 226/* Read ipc u32 data */227static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)228{229 return readl(scu->ipc_base + IPC_READ_BUFFER + offset);230}231 232/* Wait till scu status is busy */233static inline int busy_loop(struct intel_scu_ipc_dev *scu)234{235 u8 status;236 int err;237 238 err = readx_poll_timeout(ipc_read_status, scu, status, !(status & IPC_STATUS_BUSY),239 100, jiffies_to_usecs(IPC_TIMEOUT));240 if (err)241 return err;242 243 return (status & IPC_STATUS_ERR) ? -EIO : 0;244}245 246/* Wait till ipc ioc interrupt is received or timeout in 10 HZ */247static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)248{249 int status;250 251 wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT);252 253 status = ipc_read_status(scu);254 if (status & IPC_STATUS_BUSY)255 return -ETIMEDOUT;256 257 if (status & IPC_STATUS_ERR)258 return -EIO;259 260 return 0;261}262 263static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu)264{265 return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu);266}267 268static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu)269{270 u8 status;271 272 if (!scu)273 scu = ipcdev;274 if (!scu)275 return ERR_PTR(-ENODEV);276 277 status = ipc_read_status(scu);278 if (status & IPC_STATUS_BUSY) {279 dev_dbg(&scu->dev, "device is busy\n");280 return ERR_PTR(-EBUSY);281 }282 283 return scu;284}285 286/* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */287static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data,288 u32 count, u32 op, u32 id)289{290 int nc;291 u32 offset = 0;292 int err;293 u8 cbuf[IPC_WWBUF_SIZE];294 u32 *wbuf = (u32 *)&cbuf;295 296 memset(cbuf, 0, sizeof(cbuf));297 298 mutex_lock(&ipclock);299 scu = intel_scu_ipc_get(scu);300 if (IS_ERR(scu)) {301 mutex_unlock(&ipclock);302 return PTR_ERR(scu);303 }304 305 for (nc = 0; nc < count; nc++, offset += 2) {306 cbuf[offset] = addr[nc];307 cbuf[offset + 1] = addr[nc] >> 8;308 }309 310 if (id == IPC_CMD_PCNTRL_R) {311 for (nc = 0, offset = 0; nc < count; nc++, offset += 4)312 ipc_data_writel(scu, wbuf[nc], offset);313 ipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op);314 } else if (id == IPC_CMD_PCNTRL_W) {315 for (nc = 0; nc < count; nc++, offset += 1)316 cbuf[offset] = data[nc];317 for (nc = 0, offset = 0; nc < count; nc++, offset += 4)318 ipc_data_writel(scu, wbuf[nc], offset);319 ipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op);320 } else if (id == IPC_CMD_PCNTRL_M) {321 cbuf[offset] = data[0];322 cbuf[offset + 1] = data[1];323 ipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */324 ipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op);325 }326 327 err = intel_scu_ipc_check_status(scu);328 if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */329 /* Workaround: values are read as 0 without memcpy_fromio */330 memcpy_fromio(cbuf, scu->ipc_base + 0x90, 16);331 for (nc = 0; nc < count; nc++)332 data[nc] = ipc_data_readb(scu, nc);333 }334 mutex_unlock(&ipclock);335 return err;336}337 338/**339 * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU340 * @scu: Optional SCU IPC instance341 * @addr: Register on SCU342 * @data: Return pointer for read byte343 *344 * Read a single register. Returns %0 on success or an error code. All345 * locking between SCU accesses is handled for the caller.346 *347 * This function may sleep.348 */349int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data)350{351 return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R);352}353EXPORT_SYMBOL(intel_scu_ipc_dev_ioread8);354 355/**356 * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU357 * @scu: Optional SCU IPC instance358 * @addr: Register on SCU359 * @data: Byte to write360 *361 * Write a single register. Returns %0 on success or an error code. All362 * locking between SCU accesses is handled for the caller.363 *364 * This function may sleep.365 */366int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data)367{368 return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W);369}370EXPORT_SYMBOL(intel_scu_ipc_dev_iowrite8);371 372/**373 * intel_scu_ipc_dev_readv() - Read a set of registers374 * @scu: Optional SCU IPC instance375 * @addr: Register list376 * @data: Bytes to return377 * @len: Length of array378 *379 * Read registers. Returns %0 on success or an error code. All locking380 * between SCU accesses is handled for the caller.381 *382 * The largest array length permitted by the hardware is 5 items.383 *384 * This function may sleep.385 */386int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data,387 size_t len)388{389 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R);390}391EXPORT_SYMBOL(intel_scu_ipc_dev_readv);392 393/**394 * intel_scu_ipc_dev_writev() - Write a set of registers395 * @scu: Optional SCU IPC instance396 * @addr: Register list397 * @data: Bytes to write398 * @len: Length of array399 *400 * Write registers. Returns %0 on success or an error code. All locking401 * between SCU accesses is handled for the caller.402 *403 * The largest array length permitted by the hardware is 5 items.404 *405 * This function may sleep.406 */407int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data,408 size_t len)409{410 return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W);411}412EXPORT_SYMBOL(intel_scu_ipc_dev_writev);413 414/**415 * intel_scu_ipc_dev_update() - Update a register416 * @scu: Optional SCU IPC instance417 * @addr: Register address418 * @data: Bits to update419 * @mask: Mask of bits to update420 *421 * Read-modify-write power control unit register. The first data argument422 * must be register value and second is mask value mask is a bitmap that423 * indicates which bits to update. %0 = masked. Don't modify this bit, %1 =424 * modify this bit. returns %0 on success or an error code.425 *426 * This function may sleep. Locking between SCU accesses is handled427 * for the caller.428 */429int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data,430 u8 mask)431{432 u8 tmp[2] = { data, mask };433 return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M);434}435EXPORT_SYMBOL(intel_scu_ipc_dev_update);436 437/**438 * intel_scu_ipc_dev_simple_command() - Send a simple command439 * @scu: Optional SCU IPC instance440 * @cmd: Command441 * @sub: Sub type442 *443 * Issue a simple command to the SCU. Do not use this interface if you must444 * then access data as any data values may be overwritten by another SCU445 * access by the time this function returns.446 *447 * This function may sleep. Locking for SCU accesses is handled for the448 * caller.449 */450int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,451 int sub)452{453 u32 cmdval;454 int err;455 456 mutex_lock(&ipclock);457 scu = intel_scu_ipc_get(scu);458 if (IS_ERR(scu)) {459 mutex_unlock(&ipclock);460 return PTR_ERR(scu);461 }462 463 cmdval = sub << 12 | cmd;464 ipc_command(scu, cmdval);465 err = intel_scu_ipc_check_status(scu);466 mutex_unlock(&ipclock);467 if (err)468 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err);469 return err;470}471EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command);472 473/**474 * intel_scu_ipc_dev_command_with_size() - Command with data475 * @scu: Optional SCU IPC instance476 * @cmd: Command477 * @sub: Sub type478 * @in: Input data479 * @inlen: Input length in bytes480 * @size: Input size written to the IPC command register in whatever481 * units (dword, byte) the particular firmware requires. Normally482 * should be the same as @inlen.483 * @out: Output data484 * @outlen: Output length in bytes485 *486 * Issue a command to the SCU which involves data transfers. Do the487 * data copies under the lock but leave it for the caller to interpret.488 */489int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd,490 int sub, const void *in, size_t inlen,491 size_t size, void *out, size_t outlen)492{493 size_t outbuflen = DIV_ROUND_UP(outlen, sizeof(u32));494 size_t inbuflen = DIV_ROUND_UP(inlen, sizeof(u32));495 u32 cmdval, inbuf[4] = {};496 int i, err;497 498 if (inbuflen > 4 || outbuflen > 4)499 return -EINVAL;500 501 mutex_lock(&ipclock);502 scu = intel_scu_ipc_get(scu);503 if (IS_ERR(scu)) {504 mutex_unlock(&ipclock);505 return PTR_ERR(scu);506 }507 508 memcpy(inbuf, in, inlen);509 for (i = 0; i < inbuflen; i++)510 ipc_data_writel(scu, inbuf[i], 4 * i);511 512 cmdval = (size << 16) | (sub << 12) | cmd;513 ipc_command(scu, cmdval);514 err = intel_scu_ipc_check_status(scu);515 516 if (!err) {517 u32 outbuf[4] = {};518 519 for (i = 0; i < outbuflen; i++)520 outbuf[i] = ipc_data_readl(scu, 4 * i);521 522 memcpy(out, outbuf, outlen);523 }524 525 mutex_unlock(&ipclock);526 if (err)527 dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err);528 return err;529}530EXPORT_SYMBOL(intel_scu_ipc_dev_command_with_size);531 532/*533 * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1534 * When ioc bit is set to 1, caller api must wait for interrupt handler called535 * which in turn unlocks the caller api. Currently this is not used536 *537 * This is edge triggered so we need take no action to clear anything538 */539static irqreturn_t ioc(int irq, void *dev_id)540{541 struct intel_scu_ipc_dev *scu = dev_id;542 int status = ipc_read_status(scu);543 544 writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS);545 complete(&scu->cmd_complete);546 547 return IRQ_HANDLED;548}549 550static void intel_scu_ipc_release(struct device *dev)551{552 struct intel_scu_ipc_dev *scu;553 554 scu = container_of(dev, struct intel_scu_ipc_dev, dev);555 if (scu->irq > 0)556 free_irq(scu->irq, scu);557 iounmap(scu->ipc_base);558 release_mem_region(scu->mem.start, resource_size(&scu->mem));559 kfree(scu);560}561 562/**563 * __intel_scu_ipc_register() - Register SCU IPC device564 * @parent: Parent device565 * @scu_data: Data used to configure SCU IPC566 * @owner: Module registering the SCU IPC device567 *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 of570 * failure. The caller may use the returned instance if it needs to do571 * SCU IPC calls itself.572 */573struct intel_scu_ipc_dev *574__intel_scu_ipc_register(struct device *parent,575 const struct intel_scu_ipc_data *scu_data,576 struct module *owner)577{578 int err;579 struct intel_scu_ipc_dev *scu;580 void __iomem *ipc_base;581 582 mutex_lock(&ipclock);583 /* We support only one IPC */584 if (ipcdev) {585 err = -EBUSY;586 goto err_unlock;587 }588 589 scu = kzalloc(sizeof(*scu), GFP_KERNEL);590 if (!scu) {591 err = -ENOMEM;592 goto err_unlock;593 }594 595 scu->owner = owner;596 scu->dev.parent = parent;597 scu->dev.class = &intel_scu_ipc_class;598 scu->dev.release = intel_scu_ipc_release;599 600 if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem),601 "intel_scu_ipc")) {602 err = -EBUSY;603 goto err_free;604 }605 606 ipc_base = ioremap(scu_data->mem.start, resource_size(&scu_data->mem));607 if (!ipc_base) {608 err = -ENOMEM;609 goto err_release;610 }611 612 scu->ipc_base = ipc_base;613 scu->mem = scu_data->mem;614 scu->irq = scu_data->irq;615 init_completion(&scu->cmd_complete);616 617 if (scu->irq > 0) {618 err = request_irq(scu->irq, ioc, 0, "intel_scu_ipc", scu);619 if (err)620 goto err_unmap;621 }622 623 /*624 * After this point intel_scu_ipc_release() takes care of625 * releasing the SCU IPC resources once refcount drops to zero.626 */627 dev_set_name(&scu->dev, "intel_scu_ipc");628 err = device_register(&scu->dev);629 if (err) {630 put_device(&scu->dev);631 goto err_unlock;632 }633 634 /* Assign device at last */635 ipcdev = scu;636 mutex_unlock(&ipclock);637 638 return scu;639 640err_unmap:641 iounmap(ipc_base);642err_release:643 release_mem_region(scu_data->mem.start, resource_size(&scu_data->mem));644err_free:645 kfree(scu);646err_unlock:647 mutex_unlock(&ipclock);648 649 return ERR_PTR(err);650}651EXPORT_SYMBOL_GPL(__intel_scu_ipc_register);652 653/**654 * intel_scu_ipc_unregister() - Unregister SCU IPC655 * @scu: SCU IPC handle656 *657 * This unregisters the SCU IPC device and releases the acquired658 * resources once the refcount goes to zero.659 */660void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu)661{662 mutex_lock(&ipclock);663 if (!WARN_ON(!ipcdev)) {664 ipcdev = NULL;665 device_unregister(&scu->dev);666 }667 mutex_unlock(&ipclock);668}669EXPORT_SYMBOL_GPL(intel_scu_ipc_unregister);670 671static void devm_intel_scu_ipc_unregister(struct device *dev, void *res)672{673 struct intel_scu_ipc_devres *dr = res;674 struct intel_scu_ipc_dev *scu = dr->scu;675 676 intel_scu_ipc_unregister(scu);677}678 679/**680 * __devm_intel_scu_ipc_register() - Register managed SCU IPC device681 * @parent: Parent device682 * @scu_data: Data used to configure SCU IPC683 * @owner: Module registering the SCU IPC device684 *685 * Call this function to register managed SCU IPC mechanism under686 * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in687 * case of failure. The caller may use the returned instance if it needs688 * to do SCU IPC calls itself.689 */690struct intel_scu_ipc_dev *691__devm_intel_scu_ipc_register(struct device *parent,692 const struct intel_scu_ipc_data *scu_data,693 struct module *owner)694{695 struct intel_scu_ipc_devres *dr;696 struct intel_scu_ipc_dev *scu;697 698 dr = devres_alloc(devm_intel_scu_ipc_unregister, sizeof(*dr), GFP_KERNEL);699 if (!dr)700 return NULL;701 702 scu = __intel_scu_ipc_register(parent, scu_data, owner);703 if (IS_ERR(scu)) {704 devres_free(dr);705 return scu;706 }707 708 dr->scu = scu;709 devres_add(parent, dr);710 711 return scu;712}713EXPORT_SYMBOL_GPL(__devm_intel_scu_ipc_register);714 715static int __init intel_scu_ipc_init(void)716{717 return class_register(&intel_scu_ipc_class);718}719subsys_initcall(intel_scu_ipc_init);720 721static void __exit intel_scu_ipc_exit(void)722{723 class_unregister(&intel_scu_ipc_class);724}725module_exit(intel_scu_ipc_exit);726