1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Driver for the Intel SCU IPC mechanism |
4 | * |
5 | * (C) Copyright 2008-2010,2015 Intel Corporation |
6 | * Author: Sreedhara DS (sreedhara.ds@intel.com) |
7 | * |
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 |
12 | * 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 <asm/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 summary |
38 | * |
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 memory |
41 | * mapped registers. The following is the IPC mechanism |
42 | * |
43 | * 1. IA core cDMI interface claims this transaction and converts it to a |
44 | * Transaction Layer Packet (TLP) message which is sent across the cDMI. |
45 | * |
46 | * 2. South Complex cDMI block receives this message and writes it to |
47 | * the IPC-1 register block, causing an interrupt to the SCU |
48 | * |
49 | * 3. SCU firmware decodes this interrupt and IPC message and the appropriate |
50 | * 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 | |
57 | struct 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 0x04 |
67 | #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 0x80 |
76 | #define IPC_READ_BUFFER 0x90 |
77 | |
78 | /* Timeout in jiffies */ |
79 | #define IPC_TIMEOUT (10 * HZ) |
80 | |
81 | static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */ |
82 | static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */ |
83 | |
84 | static struct class intel_scu_ipc_class = { |
85 | .name = "intel_scu_ipc" , |
86 | }; |
87 | |
88 | /** |
89 | * intel_scu_ipc_dev_get() - Get SCU IPC instance |
90 | * |
91 | * The recommended new API takes SCU IPC instance as parameter and this |
92 | * function can be called by driver to get the instance. This also makes |
93 | * sure the driver providing the IPC functionality cannot be unloaded |
94 | * 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 | */ |
100 | struct 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(dev: &ipcdev->dev); |
107 | /* |
108 | * Prevent the IPC provider from being unloaded while it |
109 | * is being used. |
110 | */ |
111 | if (!try_module_get(module: ipcdev->owner)) |
112 | put_device(dev: &ipcdev->dev); |
113 | else |
114 | scu = ipcdev; |
115 | } |
116 | |
117 | mutex_unlock(lock: &ipclock); |
118 | return scu; |
119 | } |
120 | EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_get); |
121 | |
122 | /** |
123 | * intel_scu_ipc_dev_put() - Put SCU IPC instance |
124 | * @scu: SCU IPC instance |
125 | * |
126 | * This function releases the SCU IPC instance retrieved from |
127 | * intel_scu_ipc_dev_get() and allows the driver providing IPC to be |
128 | * unloaded. |
129 | */ |
130 | void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu) |
131 | { |
132 | if (scu) { |
133 | module_put(module: scu->owner); |
134 | put_device(dev: &scu->dev); |
135 | } |
136 | } |
137 | EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_put); |
138 | |
139 | struct intel_scu_ipc_devres { |
140 | struct intel_scu_ipc_dev *scu; |
141 | }; |
142 | |
143 | static 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 device |
153 | * @dev: Device requesting the SCU IPC device |
154 | * |
155 | * The recommended new API takes SCU IPC instance as parameter and this |
156 | * function can be called by driver to get the instance. This also makes |
157 | * sure the driver providing the IPC functionality cannot be unloaded |
158 | * while the caller has the instance. |
159 | * |
160 | * Returns %NULL if SCU IPC is not currently available. |
161 | */ |
162 | struct 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(res: dr); |
174 | return NULL; |
175 | } |
176 | |
177 | dr->scu = scu; |
178 | devres_add(dev, res: dr); |
179 | |
180 | return scu; |
181 | } |
182 | EXPORT_SYMBOL_GPL(devm_intel_scu_ipc_dev_get); |
183 | |
184 | /* |
185 | * Send ipc command |
186 | * Command Register (Write Only): |
187 | * A write to this register results in an interrupt to the SCU core processor |
188 | * Format: |
189 | * |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)| |
190 | */ |
191 | static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd) |
192 | { |
193 | reinit_completion(x: &scu->cmd_complete); |
194 | writel(val: cmd | IPC_IOC, addr: scu->ipc_base); |
195 | } |
196 | |
197 | /* |
198 | * Write ipc data |
199 | * IPC Write Buffer (Write Only): |
200 | * 16-byte buffer for sending data associated with IPC command to |
201 | * SCU. Size of the data is specified in the IPC_COMMAND_REG register |
202 | */ |
203 | static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset) |
204 | { |
205 | writel(val: data, addr: 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 IPC |
211 | * block and error status of the IPC command that was just processed by SCU |
212 | * Format: |
213 | * |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)| |
214 | */ |
215 | static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu) |
216 | { |
217 | return __raw_readl(addr: scu->ipc_base + IPC_STATUS); |
218 | } |
219 | |
220 | /* Read ipc byte data */ |
221 | static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset) |
222 | { |
223 | return readb(addr: scu->ipc_base + IPC_READ_BUFFER + offset); |
224 | } |
225 | |
226 | /* Read ipc u32 data */ |
227 | static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) |
228 | { |
229 | return readl(addr: scu->ipc_base + IPC_READ_BUFFER + offset); |
230 | } |
231 | |
232 | /* Wait till scu status is busy */ |
233 | static 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 */ |
247 | static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) |
248 | { |
249 | int status; |
250 | |
251 | wait_for_completion_timeout(x: &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 | |
263 | static 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 | |
268 | static 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(error: -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(error: -EBUSY); |
281 | } |
282 | |
283 | return scu; |
284 | } |
285 | |
286 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ |
287 | static 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(ptr: scu)) { |
301 | mutex_unlock(lock: &ipclock); |
302 | return PTR_ERR(ptr: 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, data: wbuf[nc], offset); |
313 | ipc_command(scu, cmd: (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, data: wbuf[nc], offset); |
319 | ipc_command(scu, cmd: (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, data: wbuf[0], offset: 0); /* Write wbuff */ |
324 | ipc_command(scu, cmd: 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, offset: nc); |
333 | } |
334 | mutex_unlock(lock: &ipclock); |
335 | return err; |
336 | } |
337 | |
338 | /** |
339 | * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU |
340 | * @scu: Optional SCU IPC instance |
341 | * @addr: Register on SCU |
342 | * @data: Return pointer for read byte |
343 | * |
344 | * Read a single register. Returns %0 on success or an error code. All |
345 | * locking between SCU accesses is handled for the caller. |
346 | * |
347 | * This function may sleep. |
348 | */ |
349 | int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) |
350 | { |
351 | return pwr_reg_rdwr(scu, addr: &addr, data, count: 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); |
352 | } |
353 | EXPORT_SYMBOL(intel_scu_ipc_dev_ioread8); |
354 | |
355 | /** |
356 | * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU |
357 | * @scu: Optional SCU IPC instance |
358 | * @addr: Register on SCU |
359 | * @data: Byte to write |
360 | * |
361 | * Write a single register. Returns %0 on success or an error code. All |
362 | * locking between SCU accesses is handled for the caller. |
363 | * |
364 | * This function may sleep. |
365 | */ |
366 | int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) |
367 | { |
368 | return pwr_reg_rdwr(scu, addr: &addr, data: &data, count: 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); |
369 | } |
370 | EXPORT_SYMBOL(intel_scu_ipc_dev_iowrite8); |
371 | |
372 | /** |
373 | * intel_scu_ipc_dev_readv() - Read a set of registers |
374 | * @scu: Optional SCU IPC instance |
375 | * @addr: Register list |
376 | * @data: Bytes to return |
377 | * @len: Length of array |
378 | * |
379 | * Read registers. Returns %0 on success or an error code. All locking |
380 | * 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 | */ |
386 | int 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, count: len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); |
390 | } |
391 | EXPORT_SYMBOL(intel_scu_ipc_dev_readv); |
392 | |
393 | /** |
394 | * intel_scu_ipc_dev_writev() - Write a set of registers |
395 | * @scu: Optional SCU IPC instance |
396 | * @addr: Register list |
397 | * @data: Bytes to write |
398 | * @len: Length of array |
399 | * |
400 | * Write registers. Returns %0 on success or an error code. All locking |
401 | * 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 | */ |
407 | int 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, count: len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); |
411 | } |
412 | EXPORT_SYMBOL(intel_scu_ipc_dev_writev); |
413 | |
414 | /** |
415 | * intel_scu_ipc_dev_update() - Update a register |
416 | * @scu: Optional SCU IPC instance |
417 | * @addr: Register address |
418 | * @data: Bits to update |
419 | * @mask: Mask of bits to update |
420 | * |
421 | * Read-modify-write power control unit register. The first data argument |
422 | * must be register value and second is mask value mask is a bitmap that |
423 | * 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 handled |
427 | * for the caller. |
428 | */ |
429 | int 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: &addr, data: tmp, count: 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); |
434 | } |
435 | EXPORT_SYMBOL(intel_scu_ipc_dev_update); |
436 | |
437 | /** |
438 | * intel_scu_ipc_dev_simple_command() - Send a simple command |
439 | * @scu: Optional SCU IPC instance |
440 | * @cmd: Command |
441 | * @sub: Sub type |
442 | * |
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 |
445 | * access by the time this function returns. |
446 | * |
447 | * This function may sleep. Locking for SCU accesses is handled for the |
448 | * caller. |
449 | */ |
450 | int 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(ptr: scu)) { |
459 | mutex_unlock(lock: &ipclock); |
460 | return PTR_ERR(ptr: scu); |
461 | } |
462 | |
463 | cmdval = sub << 12 | cmd; |
464 | ipc_command(scu, cmd: cmdval); |
465 | err = intel_scu_ipc_check_status(scu); |
466 | mutex_unlock(lock: &ipclock); |
467 | if (err) |
468 | dev_err(&scu->dev, "IPC command %#x failed with %d\n" , cmdval, err); |
469 | return err; |
470 | } |
471 | EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command); |
472 | |
473 | /** |
474 | * intel_scu_ipc_dev_command_with_size() - Command with data |
475 | * @scu: Optional SCU IPC instance |
476 | * @cmd: Command |
477 | * @sub: Sub type |
478 | * @in: Input data |
479 | * @inlen: Input length in bytes |
480 | * @size: Input size written to the IPC command register in whatever |
481 | * units (dword, byte) the particular firmware requires. Normally |
482 | * should be the same as @inlen. |
483 | * @out: Output data |
484 | * @outlen: Output length in bytes |
485 | * |
486 | * Issue a command to the SCU which involves data transfers. Do the |
487 | * data copies under the lock but leave it for the caller to interpret. |
488 | */ |
489 | int 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(ptr: scu)) { |
504 | mutex_unlock(lock: &ipclock); |
505 | return PTR_ERR(ptr: scu); |
506 | } |
507 | |
508 | memcpy(inbuf, in, inlen); |
509 | for (i = 0; i < inbuflen; i++) |
510 | ipc_data_writel(scu, data: inbuf[i], offset: 4 * i); |
511 | |
512 | cmdval = (size << 16) | (sub << 12) | cmd; |
513 | ipc_command(scu, cmd: 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, offset: 4 * i); |
521 | |
522 | memcpy(out, outbuf, outlen); |
523 | } |
524 | |
525 | mutex_unlock(lock: &ipclock); |
526 | if (err) |
527 | dev_err(&scu->dev, "IPC command %#x failed with %d\n" , cmdval, err); |
528 | return err; |
529 | } |
530 | EXPORT_SYMBOL(intel_scu_ipc_dev_command_with_size); |
531 | |
532 | /* |
533 | * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1 |
534 | * When ioc bit is set to 1, caller api must wait for interrupt handler called |
535 | * which in turn unlocks the caller api. Currently this is not used |
536 | * |
537 | * This is edge triggered so we need take no action to clear anything |
538 | */ |
539 | static 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(val: status | IPC_STATUS_IRQ, addr: scu->ipc_base + IPC_STATUS); |
545 | complete(&scu->cmd_complete); |
546 | |
547 | return IRQ_HANDLED; |
548 | } |
549 | |
550 | static 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(addr: scu->ipc_base); |
558 | release_mem_region(scu->mem.start, resource_size(&scu->mem)); |
559 | kfree(objp: scu); |
560 | } |
561 | |
562 | /** |
563 | * __intel_scu_ipc_register() - Register SCU IPC device |
564 | * @parent: Parent device |
565 | * @scu_data: Data used to configure SCU IPC |
566 | * @owner: Module registering the SCU IPC device |
567 | * |
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 |
570 | * failure. The caller may use the returned instance if it needs to do |
571 | * SCU IPC calls itself. |
572 | */ |
573 | struct 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(size: 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(offset: scu_data->mem.start, size: resource_size(res: &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(x: &scu->cmd_complete); |
616 | |
617 | if (scu->irq > 0) { |
618 | err = request_irq(irq: scu->irq, handler: ioc, flags: 0, name: "intel_scu_ipc" , dev: scu); |
619 | if (err) |
620 | goto err_unmap; |
621 | } |
622 | |
623 | /* |
624 | * After this point intel_scu_ipc_release() takes care of |
625 | * releasing the SCU IPC resources once refcount drops to zero. |
626 | */ |
627 | dev_set_name(dev: &scu->dev, name: "intel_scu_ipc" ); |
628 | err = device_register(dev: &scu->dev); |
629 | if (err) { |
630 | put_device(dev: &scu->dev); |
631 | goto err_unlock; |
632 | } |
633 | |
634 | /* Assign device at last */ |
635 | ipcdev = scu; |
636 | mutex_unlock(lock: &ipclock); |
637 | |
638 | return scu; |
639 | |
640 | err_unmap: |
641 | iounmap(addr: ipc_base); |
642 | err_release: |
643 | release_mem_region(scu_data->mem.start, resource_size(&scu_data->mem)); |
644 | err_free: |
645 | kfree(objp: scu); |
646 | err_unlock: |
647 | mutex_unlock(lock: &ipclock); |
648 | |
649 | return ERR_PTR(error: err); |
650 | } |
651 | EXPORT_SYMBOL_GPL(__intel_scu_ipc_register); |
652 | |
653 | /** |
654 | * intel_scu_ipc_unregister() - Unregister SCU IPC |
655 | * @scu: SCU IPC handle |
656 | * |
657 | * This unregisters the SCU IPC device and releases the acquired |
658 | * resources once the refcount goes to zero. |
659 | */ |
660 | void 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(dev: &scu->dev); |
666 | } |
667 | mutex_unlock(lock: &ipclock); |
668 | } |
669 | EXPORT_SYMBOL_GPL(intel_scu_ipc_unregister); |
670 | |
671 | static 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 device |
681 | * @parent: Parent device |
682 | * @scu_data: Data used to configure SCU IPC |
683 | * @owner: Module registering the SCU IPC device |
684 | * |
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 |
687 | * case of failure. The caller may use the returned instance if it needs |
688 | * to do SCU IPC calls itself. |
689 | */ |
690 | struct 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(ptr: scu)) { |
704 | devres_free(res: dr); |
705 | return scu; |
706 | } |
707 | |
708 | dr->scu = scu; |
709 | devres_add(dev: parent, res: dr); |
710 | |
711 | return scu; |
712 | } |
713 | EXPORT_SYMBOL_GPL(__devm_intel_scu_ipc_register); |
714 | |
715 | static int __init intel_scu_ipc_init(void) |
716 | { |
717 | return class_register(class: &intel_scu_ipc_class); |
718 | } |
719 | subsys_initcall(intel_scu_ipc_init); |
720 | |
721 | static void __exit intel_scu_ipc_exit(void) |
722 | { |
723 | class_unregister(class: &intel_scu_ipc_class); |
724 | } |
725 | module_exit(intel_scu_ipc_exit); |
726 | |