1 /*
2 * SCOM FSI Client device driver
3 *
4 * Copyright (C) IBM Corporation 2016
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16 #include <linux/fsi.h>
17 #include <linux/module.h>
18 #include <linux/cdev.h>
19 #include <linux/delay.h>
20 #include <linux/fs.h>
21 #include <linux/uaccess.h>
22 #include <linux/slab.h>
23 #include <linux/cdev.h>
24 #include <linux/list.h>
25
26 #include <uapi/linux/fsi.h>
27
28 #define FSI_ENGID_SCOM 0x5
29
30 /* SCOM engine register set */
31 #define SCOM_DATA0_REG 0x00
32 #define SCOM_DATA1_REG 0x04
33 #define SCOM_CMD_REG 0x08
34 #define SCOM_FSI2PIB_RESET_REG 0x18
35 #define SCOM_STATUS_REG 0x1C /* Read */
36 #define SCOM_PIB_RESET_REG 0x1C /* Write */
37
38 /* Command register */
39 #define SCOM_WRITE_CMD 0x80000000
40 #define SCOM_READ_CMD 0x00000000
41
42 /* Status register bits */
43 #define SCOM_STATUS_ERR_SUMMARY 0x80000000
44 #define SCOM_STATUS_PROTECTION 0x01000000
45 #define SCOM_STATUS_PARITY 0x04000000
46 #define SCOM_STATUS_PIB_ABORT 0x00100000
47 #define SCOM_STATUS_PIB_RESP_MASK 0x00007000
48 #define SCOM_STATUS_PIB_RESP_SHIFT 12
49
50 #define SCOM_STATUS_FSI2PIB_ERROR (SCOM_STATUS_PROTECTION | \
51 SCOM_STATUS_PARITY | \
52 SCOM_STATUS_PIB_ABORT)
53 #define SCOM_STATUS_ANY_ERR (SCOM_STATUS_FSI2PIB_ERROR | \
54 SCOM_STATUS_PIB_RESP_MASK)
55 /* SCOM address encodings */
56 #define XSCOM_ADDR_IND_FLAG BIT_ULL(63)
57 #define XSCOM_ADDR_INF_FORM1 BIT_ULL(60)
58
59 /* SCOM indirect stuff */
60 #define XSCOM_ADDR_DIRECT_PART 0x7fffffffull
61 #define XSCOM_ADDR_INDIRECT_PART 0x000fffff00000000ull
62 #define XSCOM_DATA_IND_READ BIT_ULL(63)
63 #define XSCOM_DATA_IND_COMPLETE BIT_ULL(31)
64 #define XSCOM_DATA_IND_ERR_MASK 0x70000000ull
65 #define XSCOM_DATA_IND_ERR_SHIFT 28
66 #define XSCOM_DATA_IND_DATA 0x0000ffffull
67 #define XSCOM_DATA_IND_FORM1_DATA 0x000fffffffffffffull
68 #define XSCOM_ADDR_FORM1_LOW 0x000ffffffffull
69 #define XSCOM_ADDR_FORM1_HI 0xfff00000000ull
70 #define XSCOM_ADDR_FORM1_HI_SHIFT 20
71
72 /* Retries */
73 #define SCOM_MAX_RETRIES 100 /* Retries on busy */
74 #define SCOM_MAX_IND_RETRIES 10 /* Retries indirect not ready */
75
76 struct scom_device {
77 struct list_head link;
78 struct fsi_device *fsi_dev;
79 struct device dev;
80 struct cdev cdev;
81 struct mutex lock;
82 bool dead;
83 };
84
__put_scom(struct scom_device * scom_dev,uint64_t value,uint32_t addr,uint32_t * status)85 static int __put_scom(struct scom_device *scom_dev, uint64_t value,
86 uint32_t addr, uint32_t *status)
87 {
88 __be32 data, raw_status;
89 int rc;
90
91 data = cpu_to_be32((value >> 32) & 0xffffffff);
92 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
93 sizeof(uint32_t));
94 if (rc)
95 return rc;
96
97 data = cpu_to_be32(value & 0xffffffff);
98 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
99 sizeof(uint32_t));
100 if (rc)
101 return rc;
102
103 data = cpu_to_be32(SCOM_WRITE_CMD | addr);
104 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
105 sizeof(uint32_t));
106 if (rc)
107 return rc;
108 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
109 sizeof(uint32_t));
110 if (rc)
111 return rc;
112 *status = be32_to_cpu(raw_status);
113
114 return 0;
115 }
116
__get_scom(struct scom_device * scom_dev,uint64_t * value,uint32_t addr,uint32_t * status)117 static int __get_scom(struct scom_device *scom_dev, uint64_t *value,
118 uint32_t addr, uint32_t *status)
119 {
120 __be32 data, raw_status;
121 int rc;
122
123
124 *value = 0ULL;
125 data = cpu_to_be32(SCOM_READ_CMD | addr);
126 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
127 sizeof(uint32_t));
128 if (rc)
129 return rc;
130 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
131 sizeof(uint32_t));
132 if (rc)
133 return rc;
134
135 /*
136 * Read the data registers even on error, so we don't have
137 * to interpret the status register here.
138 */
139 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
140 sizeof(uint32_t));
141 if (rc)
142 return rc;
143 *value |= (uint64_t)be32_to_cpu(data) << 32;
144 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
145 sizeof(uint32_t));
146 if (rc)
147 return rc;
148 *value |= be32_to_cpu(data);
149 *status = be32_to_cpu(raw_status);
150
151 return rc;
152 }
153
put_indirect_scom_form0(struct scom_device * scom,uint64_t value,uint64_t addr,uint32_t * status)154 static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
155 uint64_t addr, uint32_t *status)
156 {
157 uint64_t ind_data, ind_addr;
158 int rc, retries, err = 0;
159
160 if (value & ~XSCOM_DATA_IND_DATA)
161 return -EINVAL;
162
163 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
164 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | value;
165 rc = __put_scom(scom, ind_data, ind_addr, status);
166 if (rc || (*status & SCOM_STATUS_ANY_ERR))
167 return rc;
168
169 for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
170 rc = __get_scom(scom, &ind_data, addr, status);
171 if (rc || (*status & SCOM_STATUS_ANY_ERR))
172 return rc;
173
174 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
175 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
176 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
177 return 0;
178
179 msleep(1);
180 }
181 return rc;
182 }
183
put_indirect_scom_form1(struct scom_device * scom,uint64_t value,uint64_t addr,uint32_t * status)184 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
185 uint64_t addr, uint32_t *status)
186 {
187 uint64_t ind_data, ind_addr;
188
189 if (value & ~XSCOM_DATA_IND_FORM1_DATA)
190 return -EINVAL;
191
192 ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
193 ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
194 return __put_scom(scom, ind_data, ind_addr, status);
195 }
196
get_indirect_scom_form0(struct scom_device * scom,uint64_t * value,uint64_t addr,uint32_t * status)197 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
198 uint64_t addr, uint32_t *status)
199 {
200 uint64_t ind_data, ind_addr;
201 int rc, retries, err = 0;
202
203 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
204 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
205 rc = __put_scom(scom, ind_data, ind_addr, status);
206 if (rc || (*status & SCOM_STATUS_ANY_ERR))
207 return rc;
208
209 for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
210 rc = __get_scom(scom, &ind_data, addr, status);
211 if (rc || (*status & SCOM_STATUS_ANY_ERR))
212 return rc;
213
214 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
215 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
216 *value = ind_data & XSCOM_DATA_IND_DATA;
217
218 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
219 return 0;
220
221 msleep(1);
222 }
223 return rc;
224 }
225
raw_put_scom(struct scom_device * scom,uint64_t value,uint64_t addr,uint32_t * status)226 static int raw_put_scom(struct scom_device *scom, uint64_t value,
227 uint64_t addr, uint32_t *status)
228 {
229 if (addr & XSCOM_ADDR_IND_FLAG) {
230 if (addr & XSCOM_ADDR_INF_FORM1)
231 return put_indirect_scom_form1(scom, value, addr, status);
232 else
233 return put_indirect_scom_form0(scom, value, addr, status);
234 } else
235 return __put_scom(scom, value, addr, status);
236 }
237
raw_get_scom(struct scom_device * scom,uint64_t * value,uint64_t addr,uint32_t * status)238 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
239 uint64_t addr, uint32_t *status)
240 {
241 if (addr & XSCOM_ADDR_IND_FLAG) {
242 if (addr & XSCOM_ADDR_INF_FORM1)
243 return -ENXIO;
244 return get_indirect_scom_form0(scom, value, addr, status);
245 } else
246 return __get_scom(scom, value, addr, status);
247 }
248
handle_fsi2pib_status(struct scom_device * scom,uint32_t status)249 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
250 {
251 uint32_t dummy = -1;
252
253 if (status & SCOM_STATUS_FSI2PIB_ERROR)
254 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
255 sizeof(uint32_t));
256
257 if (status & SCOM_STATUS_PROTECTION)
258 return -EPERM;
259 if (status & SCOM_STATUS_PARITY)
260 return -EIO;
261 /* Return -EBUSY on PIB abort to force a retry */
262 if (status & SCOM_STATUS_PIB_ABORT)
263 return -EBUSY;
264 return 0;
265 }
266
handle_pib_status(struct scom_device * scom,uint8_t status)267 static int handle_pib_status(struct scom_device *scom, uint8_t status)
268 {
269 uint32_t dummy = -1;
270
271 if (status == SCOM_PIB_SUCCESS)
272 return 0;
273 if (status == SCOM_PIB_BLOCKED)
274 return -EBUSY;
275
276 /* Reset the bridge */
277 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
278 sizeof(uint32_t));
279
280 switch(status) {
281 case SCOM_PIB_OFFLINE:
282 return -ENODEV;
283 case SCOM_PIB_BAD_ADDR:
284 return -ENXIO;
285 case SCOM_PIB_TIMEOUT:
286 return -ETIMEDOUT;
287 case SCOM_PIB_PARTIAL:
288 case SCOM_PIB_CLK_ERR:
289 case SCOM_PIB_PARITY_ERR:
290 default:
291 return -EIO;
292 }
293 }
294
put_scom(struct scom_device * scom,uint64_t value,uint64_t addr)295 static int put_scom(struct scom_device *scom, uint64_t value,
296 uint64_t addr)
297 {
298 uint32_t status, dummy = -1;
299 int rc, retries;
300
301 for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
302 rc = raw_put_scom(scom, value, addr, &status);
303 if (rc) {
304 /* Try resetting the bridge if FSI fails */
305 if (rc != -ENODEV && retries == 0) {
306 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
307 &dummy, sizeof(uint32_t));
308 rc = -EBUSY;
309 } else
310 return rc;
311 } else
312 rc = handle_fsi2pib_status(scom, status);
313 if (rc && rc != -EBUSY)
314 break;
315 if (rc == 0) {
316 rc = handle_pib_status(scom,
317 (status & SCOM_STATUS_PIB_RESP_MASK)
318 >> SCOM_STATUS_PIB_RESP_SHIFT);
319 if (rc && rc != -EBUSY)
320 break;
321 }
322 if (rc == 0)
323 break;
324 msleep(1);
325 }
326 return rc;
327 }
328
get_scom(struct scom_device * scom,uint64_t * value,uint64_t addr)329 static int get_scom(struct scom_device *scom, uint64_t *value,
330 uint64_t addr)
331 {
332 uint32_t status, dummy = -1;
333 int rc, retries;
334
335 for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
336 rc = raw_get_scom(scom, value, addr, &status);
337 if (rc) {
338 /* Try resetting the bridge if FSI fails */
339 if (rc != -ENODEV && retries == 0) {
340 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
341 &dummy, sizeof(uint32_t));
342 rc = -EBUSY;
343 } else
344 return rc;
345 } else
346 rc = handle_fsi2pib_status(scom, status);
347 if (rc && rc != -EBUSY)
348 break;
349 if (rc == 0) {
350 rc = handle_pib_status(scom,
351 (status & SCOM_STATUS_PIB_RESP_MASK)
352 >> SCOM_STATUS_PIB_RESP_SHIFT);
353 if (rc && rc != -EBUSY)
354 break;
355 }
356 if (rc == 0)
357 break;
358 msleep(1);
359 }
360 return rc;
361 }
362
scom_read(struct file * filep,char __user * buf,size_t len,loff_t * offset)363 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
364 loff_t *offset)
365 {
366 struct scom_device *scom = filep->private_data;
367 struct device *dev = &scom->fsi_dev->dev;
368 uint64_t val;
369 int rc;
370
371 if (len != sizeof(uint64_t))
372 return -EINVAL;
373
374 mutex_lock(&scom->lock);
375 if (scom->dead)
376 rc = -ENODEV;
377 else
378 rc = get_scom(scom, &val, *offset);
379 mutex_unlock(&scom->lock);
380 if (rc) {
381 dev_dbg(dev, "get_scom fail:%d\n", rc);
382 return rc;
383 }
384
385 rc = copy_to_user(buf, &val, len);
386 if (rc)
387 dev_dbg(dev, "copy to user failed:%d\n", rc);
388
389 return rc ? rc : len;
390 }
391
scom_write(struct file * filep,const char __user * buf,size_t len,loff_t * offset)392 static ssize_t scom_write(struct file *filep, const char __user *buf,
393 size_t len, loff_t *offset)
394 {
395 int rc;
396 struct scom_device *scom = filep->private_data;
397 struct device *dev = &scom->fsi_dev->dev;
398 uint64_t val;
399
400 if (len != sizeof(uint64_t))
401 return -EINVAL;
402
403 rc = copy_from_user(&val, buf, len);
404 if (rc) {
405 dev_dbg(dev, "copy from user failed:%d\n", rc);
406 return -EINVAL;
407 }
408
409 mutex_lock(&scom->lock);
410 if (scom->dead)
411 rc = -ENODEV;
412 else
413 rc = put_scom(scom, val, *offset);
414 mutex_unlock(&scom->lock);
415 if (rc) {
416 dev_dbg(dev, "put_scom failed with:%d\n", rc);
417 return rc;
418 }
419
420 return len;
421 }
422
scom_llseek(struct file * file,loff_t offset,int whence)423 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
424 {
425 switch (whence) {
426 case SEEK_CUR:
427 break;
428 case SEEK_SET:
429 file->f_pos = offset;
430 break;
431 default:
432 return -EINVAL;
433 }
434
435 return offset;
436 }
437
raw_convert_status(struct scom_access * acc,uint32_t status)438 static void raw_convert_status(struct scom_access *acc, uint32_t status)
439 {
440 acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
441 SCOM_STATUS_PIB_RESP_SHIFT;
442 acc->intf_errors = 0;
443
444 if (status & SCOM_STATUS_PROTECTION)
445 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
446 else if (status & SCOM_STATUS_PARITY)
447 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
448 else if (status & SCOM_STATUS_PIB_ABORT)
449 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
450 else if (status & SCOM_STATUS_ERR_SUMMARY)
451 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
452 }
453
scom_raw_read(struct scom_device * scom,void __user * argp)454 static int scom_raw_read(struct scom_device *scom, void __user *argp)
455 {
456 struct scom_access acc;
457 uint32_t status;
458 int rc;
459
460 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
461 return -EFAULT;
462
463 rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
464 if (rc)
465 return rc;
466 raw_convert_status(&acc, status);
467 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
468 return -EFAULT;
469 return 0;
470 }
471
scom_raw_write(struct scom_device * scom,void __user * argp)472 static int scom_raw_write(struct scom_device *scom, void __user *argp)
473 {
474 u64 prev_data, mask, data;
475 struct scom_access acc;
476 uint32_t status;
477 int rc;
478
479 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
480 return -EFAULT;
481
482 if (acc.mask) {
483 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
484 if (rc)
485 return rc;
486 if (status & SCOM_STATUS_ANY_ERR)
487 goto fail;
488 mask = acc.mask;
489 } else {
490 prev_data = mask = -1ull;
491 }
492 data = (prev_data & ~mask) | (acc.data & mask);
493 rc = raw_put_scom(scom, data, acc.addr, &status);
494 if (rc)
495 return rc;
496 fail:
497 raw_convert_status(&acc, status);
498 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
499 return -EFAULT;
500 return 0;
501 }
502
scom_reset(struct scom_device * scom,void __user * argp)503 static int scom_reset(struct scom_device *scom, void __user *argp)
504 {
505 uint32_t flags, dummy = -1;
506 int rc = 0;
507
508 if (get_user(flags, (__u32 __user *)argp))
509 return -EFAULT;
510 if (flags & SCOM_RESET_PIB)
511 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
512 sizeof(uint32_t));
513 if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
514 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
515 sizeof(uint32_t));
516 return rc;
517 }
518
scom_check(struct scom_device * scom,void __user * argp)519 static int scom_check(struct scom_device *scom, void __user *argp)
520 {
521 /* Still need to find out how to get "protected" */
522 return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
523 }
524
scom_ioctl(struct file * file,unsigned int cmd,unsigned long arg)525 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
526 {
527 struct scom_device *scom = file->private_data;
528 void __user *argp = (void __user *)arg;
529 int rc = -ENOTTY;
530
531 mutex_lock(&scom->lock);
532 if (scom->dead) {
533 mutex_unlock(&scom->lock);
534 return -ENODEV;
535 }
536 switch(cmd) {
537 case FSI_SCOM_CHECK:
538 rc = scom_check(scom, argp);
539 break;
540 case FSI_SCOM_READ:
541 rc = scom_raw_read(scom, argp);
542 break;
543 case FSI_SCOM_WRITE:
544 rc = scom_raw_write(scom, argp);
545 break;
546 case FSI_SCOM_RESET:
547 rc = scom_reset(scom, argp);
548 break;
549 }
550 mutex_unlock(&scom->lock);
551 return rc;
552 }
553
scom_open(struct inode * inode,struct file * file)554 static int scom_open(struct inode *inode, struct file *file)
555 {
556 struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
557
558 file->private_data = scom;
559
560 return 0;
561 }
562
563 static const struct file_operations scom_fops = {
564 .owner = THIS_MODULE,
565 .open = scom_open,
566 .llseek = scom_llseek,
567 .read = scom_read,
568 .write = scom_write,
569 .unlocked_ioctl = scom_ioctl,
570 };
571
scom_free(struct device * dev)572 static void scom_free(struct device *dev)
573 {
574 struct scom_device *scom = container_of(dev, struct scom_device, dev);
575
576 put_device(&scom->fsi_dev->dev);
577 kfree(scom);
578 }
579
scom_probe(struct device * dev)580 static int scom_probe(struct device *dev)
581 {
582 struct fsi_device *fsi_dev = to_fsi_dev(dev);
583 struct scom_device *scom;
584 int rc, didx;
585
586 scom = kzalloc(sizeof(*scom), GFP_KERNEL);
587 if (!scom)
588 return -ENOMEM;
589 dev_set_drvdata(dev, scom);
590 mutex_init(&scom->lock);
591
592 /* Grab a reference to the device (parent of our cdev), we'll drop it later */
593 if (!get_device(dev)) {
594 kfree(scom);
595 return -ENODEV;
596 }
597 scom->fsi_dev = fsi_dev;
598
599 /* Create chardev for userspace access */
600 scom->dev.type = &fsi_cdev_type;
601 scom->dev.parent = dev;
602 scom->dev.release = scom_free;
603 device_initialize(&scom->dev);
604
605 /* Allocate a minor in the FSI space */
606 rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
607 if (rc)
608 goto err;
609
610 dev_set_name(&scom->dev, "scom%d", didx);
611 cdev_init(&scom->cdev, &scom_fops);
612 rc = cdev_device_add(&scom->cdev, &scom->dev);
613 if (rc) {
614 dev_err(dev, "Error %d creating char device %s\n",
615 rc, dev_name(&scom->dev));
616 goto err_free_minor;
617 }
618
619 return 0;
620 err_free_minor:
621 fsi_free_minor(scom->dev.devt);
622 err:
623 put_device(&scom->dev);
624 return rc;
625 }
626
scom_remove(struct device * dev)627 static int scom_remove(struct device *dev)
628 {
629 struct scom_device *scom = dev_get_drvdata(dev);
630
631 mutex_lock(&scom->lock);
632 scom->dead = true;
633 mutex_unlock(&scom->lock);
634 cdev_device_del(&scom->cdev, &scom->dev);
635 fsi_free_minor(scom->dev.devt);
636 put_device(&scom->dev);
637
638 return 0;
639 }
640
641 static struct fsi_device_id scom_ids[] = {
642 {
643 .engine_type = FSI_ENGID_SCOM,
644 .version = FSI_VERSION_ANY,
645 },
646 { 0 }
647 };
648
649 static struct fsi_driver scom_drv = {
650 .id_table = scom_ids,
651 .drv = {
652 .name = "scom",
653 .bus = &fsi_bus_type,
654 .probe = scom_probe,
655 .remove = scom_remove,
656 }
657 };
658
scom_init(void)659 static int scom_init(void)
660 {
661 return fsi_driver_register(&scom_drv);
662 }
663
scom_exit(void)664 static void scom_exit(void)
665 {
666 fsi_driver_unregister(&scom_drv);
667 }
668
669 module_init(scom_init);
670 module_exit(scom_exit);
671 MODULE_LICENSE("GPL");
672