0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/err.h>
0011 #include <linux/slab.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/mutex.h>
0015 #include <linux/uaccess.h>
0016 #include <linux/hte.h>
0017 #include <linux/delay.h>
0018 #include <linux/debugfs.h>
0019
0020 #define HTE_TS_NAME_LEN 10
0021
0022
0023 static DEFINE_SPINLOCK(hte_lock);
0024 static LIST_HEAD(hte_devices);
0025
0026 enum {
0027 HTE_TS_REGISTERED,
0028 HTE_TS_REQ,
0029 HTE_TS_DISABLE,
0030 HTE_TS_QUEUE_WK,
0031 };
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 struct hte_ts_info {
0055 u32 xlated_id;
0056 unsigned long flags;
0057 unsigned long hte_cb_flags;
0058 u64 seq;
0059 char *line_name;
0060 bool free_attr_name;
0061 hte_ts_cb_t cb;
0062 hte_ts_sec_cb_t tcb;
0063 atomic_t dropped_ts;
0064 spinlock_t slock;
0065 struct work_struct cb_work;
0066 struct mutex req_mlock;
0067 struct dentry *ts_dbg_root;
0068 struct hte_device *gdev;
0069 void *cl_data;
0070 };
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 struct hte_device {
0084 u32 nlines;
0085 atomic_t ts_req;
0086 struct device *sdev;
0087 struct dentry *dbg_root;
0088 struct list_head list;
0089 struct hte_chip *chip;
0090 struct module *owner;
0091 struct hte_ts_info ei[];
0092 };
0093
0094 #ifdef CONFIG_DEBUG_FS
0095
0096 static struct dentry *hte_root;
0097
0098 static int __init hte_subsys_dbgfs_init(void)
0099 {
0100
0101 hte_root = debugfs_create_dir("hte", NULL);
0102
0103 return 0;
0104 }
0105 subsys_initcall(hte_subsys_dbgfs_init);
0106
0107 static void hte_chip_dbgfs_init(struct hte_device *gdev)
0108 {
0109 const struct hte_chip *chip = gdev->chip;
0110 const char *name = chip->name ? chip->name : dev_name(chip->dev);
0111
0112 gdev->dbg_root = debugfs_create_dir(name, hte_root);
0113
0114 debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root,
0115 &gdev->ts_req);
0116 debugfs_create_u32("total_ts", 0444, gdev->dbg_root,
0117 &gdev->nlines);
0118 }
0119
0120 static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei)
0121 {
0122 if (!ei->gdev->dbg_root || !name)
0123 return;
0124
0125 ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root);
0126
0127 debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root,
0128 &ei->dropped_ts);
0129 }
0130
0131 #else
0132
0133 static void hte_chip_dbgfs_init(struct hte_device *gdev)
0134 {
0135 }
0136
0137 static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei)
0138 {
0139 }
0140
0141 #endif
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 int hte_ts_put(struct hte_ts_desc *desc)
0153 {
0154 int ret = 0;
0155 unsigned long flag;
0156 struct hte_device *gdev;
0157 struct hte_ts_info *ei;
0158
0159 if (!desc)
0160 return -EINVAL;
0161
0162 ei = desc->hte_data;
0163
0164 if (!ei || !ei->gdev)
0165 return -EINVAL;
0166
0167 gdev = ei->gdev;
0168
0169 mutex_lock(&ei->req_mlock);
0170
0171 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) &&
0172 !test_bit(HTE_TS_REGISTERED, &ei->flags))) {
0173 dev_info(gdev->sdev, "id:%d is not requested\n",
0174 desc->attr.line_id);
0175 ret = -EINVAL;
0176 goto unlock;
0177 }
0178
0179 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) &&
0180 test_bit(HTE_TS_REGISTERED, &ei->flags))) {
0181 dev_info(gdev->sdev, "id:%d is registered but not requested\n",
0182 desc->attr.line_id);
0183 ret = -EINVAL;
0184 goto unlock;
0185 }
0186
0187 if (test_bit(HTE_TS_REQ, &ei->flags) &&
0188 !test_bit(HTE_TS_REGISTERED, &ei->flags)) {
0189 clear_bit(HTE_TS_REQ, &ei->flags);
0190 desc->hte_data = NULL;
0191 ret = 0;
0192 goto mod_put;
0193 }
0194
0195 ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id);
0196 if (ret) {
0197 dev_err(gdev->sdev, "id: %d free failed\n",
0198 desc->attr.line_id);
0199 goto unlock;
0200 }
0201
0202 kfree(ei->line_name);
0203 if (ei->free_attr_name)
0204 kfree_const(desc->attr.name);
0205
0206 debugfs_remove_recursive(ei->ts_dbg_root);
0207
0208 spin_lock_irqsave(&ei->slock, flag);
0209
0210 if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) {
0211 spin_unlock_irqrestore(&ei->slock, flag);
0212 flush_work(&ei->cb_work);
0213 spin_lock_irqsave(&ei->slock, flag);
0214 }
0215
0216 atomic_dec(&gdev->ts_req);
0217 atomic_set(&ei->dropped_ts, 0);
0218
0219 ei->seq = 1;
0220 ei->flags = 0;
0221 desc->hte_data = NULL;
0222
0223 spin_unlock_irqrestore(&ei->slock, flag);
0224
0225 ei->cb = NULL;
0226 ei->tcb = NULL;
0227 ei->cl_data = NULL;
0228
0229 mod_put:
0230 module_put(gdev->owner);
0231 unlock:
0232 mutex_unlock(&ei->req_mlock);
0233 dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id);
0234
0235 return ret;
0236 }
0237 EXPORT_SYMBOL_GPL(hte_ts_put);
0238
0239 static int hte_ts_dis_en_common(struct hte_ts_desc *desc, bool en)
0240 {
0241 u32 ts_id;
0242 struct hte_device *gdev;
0243 struct hte_ts_info *ei;
0244 int ret;
0245 unsigned long flag;
0246
0247 if (!desc)
0248 return -EINVAL;
0249
0250 ei = desc->hte_data;
0251
0252 if (!ei || !ei->gdev)
0253 return -EINVAL;
0254
0255 gdev = ei->gdev;
0256 ts_id = desc->attr.line_id;
0257
0258 mutex_lock(&ei->req_mlock);
0259
0260 if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) {
0261 dev_dbg(gdev->sdev, "id:%d is not registered", ts_id);
0262 ret = -EUSERS;
0263 goto out;
0264 }
0265
0266 spin_lock_irqsave(&ei->slock, flag);
0267
0268 if (en) {
0269 if (!test_bit(HTE_TS_DISABLE, &ei->flags)) {
0270 ret = 0;
0271 goto out_unlock;
0272 }
0273
0274 spin_unlock_irqrestore(&ei->slock, flag);
0275 ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id);
0276 if (ret) {
0277 dev_warn(gdev->sdev, "id: %d enable failed\n",
0278 ts_id);
0279 goto out;
0280 }
0281
0282 spin_lock_irqsave(&ei->slock, flag);
0283 clear_bit(HTE_TS_DISABLE, &ei->flags);
0284 } else {
0285 if (test_bit(HTE_TS_DISABLE, &ei->flags)) {
0286 ret = 0;
0287 goto out_unlock;
0288 }
0289
0290 spin_unlock_irqrestore(&ei->slock, flag);
0291 ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id);
0292 if (ret) {
0293 dev_warn(gdev->sdev, "id: %d disable failed\n",
0294 ts_id);
0295 goto out;
0296 }
0297
0298 spin_lock_irqsave(&ei->slock, flag);
0299 set_bit(HTE_TS_DISABLE, &ei->flags);
0300 }
0301
0302 out_unlock:
0303 spin_unlock_irqrestore(&ei->slock, flag);
0304 out:
0305 mutex_unlock(&ei->req_mlock);
0306 return ret;
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319 int hte_disable_ts(struct hte_ts_desc *desc)
0320 {
0321 return hte_ts_dis_en_common(desc, false);
0322 }
0323 EXPORT_SYMBOL_GPL(hte_disable_ts);
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 int hte_enable_ts(struct hte_ts_desc *desc)
0334 {
0335 return hte_ts_dis_en_common(desc, true);
0336 }
0337 EXPORT_SYMBOL_GPL(hte_enable_ts);
0338
0339 static void hte_do_cb_work(struct work_struct *w)
0340 {
0341 unsigned long flag;
0342 struct hte_ts_info *ei = container_of(w, struct hte_ts_info, cb_work);
0343
0344 if (unlikely(!ei->tcb))
0345 return;
0346
0347 ei->tcb(ei->cl_data);
0348
0349 spin_lock_irqsave(&ei->slock, flag);
0350 clear_bit(HTE_TS_QUEUE_WK, &ei->flags);
0351 spin_unlock_irqrestore(&ei->slock, flag);
0352 }
0353
0354 static int __hte_req_ts(struct hte_ts_desc *desc, hte_ts_cb_t cb,
0355 hte_ts_sec_cb_t tcb, void *data)
0356 {
0357 int ret;
0358 struct hte_device *gdev;
0359 struct hte_ts_info *ei = desc->hte_data;
0360
0361 gdev = ei->gdev;
0362
0363
0364
0365
0366 mutex_lock(&ei->req_mlock);
0367
0368 if (test_bit(HTE_TS_REGISTERED, &ei->flags) ||
0369 !test_bit(HTE_TS_REQ, &ei->flags)) {
0370 dev_dbg(gdev->chip->dev, "id:%u req failed\n",
0371 desc->attr.line_id);
0372 ret = -EUSERS;
0373 goto unlock;
0374 }
0375
0376 ei->cb = cb;
0377 ei->tcb = tcb;
0378 if (tcb)
0379 INIT_WORK(&ei->cb_work, hte_do_cb_work);
0380
0381 ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id);
0382 if (ret < 0) {
0383 dev_err(gdev->chip->dev, "ts request failed\n");
0384 goto unlock;
0385 }
0386
0387 ei->cl_data = data;
0388 ei->seq = 1;
0389
0390 atomic_inc(&gdev->ts_req);
0391
0392 ei->line_name = NULL;
0393 if (!desc->attr.name) {
0394 ei->line_name = kzalloc(HTE_TS_NAME_LEN, GFP_KERNEL);
0395 if (ei->line_name)
0396 scnprintf(ei->line_name, HTE_TS_NAME_LEN, "ts_%u",
0397 desc->attr.line_id);
0398 }
0399
0400 hte_ts_dbgfs_init(desc->attr.name == NULL ?
0401 ei->line_name : desc->attr.name, ei);
0402 set_bit(HTE_TS_REGISTERED, &ei->flags);
0403
0404 dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u",
0405 desc->attr.line_id, ei->xlated_id);
0406
0407 ret = 0;
0408
0409 unlock:
0410 mutex_unlock(&ei->req_mlock);
0411
0412 return ret;
0413 }
0414
0415 static int hte_bind_ts_info_locked(struct hte_ts_info *ei,
0416 struct hte_ts_desc *desc, u32 x_id)
0417 {
0418 int ret = 0;
0419
0420 mutex_lock(&ei->req_mlock);
0421
0422 if (test_bit(HTE_TS_REQ, &ei->flags)) {
0423 dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n",
0424 desc->attr.line_id);
0425 ret = -EUSERS;
0426 goto out;
0427 }
0428
0429 set_bit(HTE_TS_REQ, &ei->flags);
0430 desc->hte_data = ei;
0431 ei->xlated_id = x_id;
0432
0433 out:
0434 mutex_unlock(&ei->req_mlock);
0435
0436 return ret;
0437 }
0438
0439 static struct hte_device *of_node_to_htedevice(struct device_node *np)
0440 {
0441 struct hte_device *gdev;
0442
0443 spin_lock(&hte_lock);
0444
0445 list_for_each_entry(gdev, &hte_devices, list)
0446 if (gdev->chip && gdev->chip->dev &&
0447 gdev->chip->dev->of_node == np) {
0448 spin_unlock(&hte_lock);
0449 return gdev;
0450 }
0451
0452 spin_unlock(&hte_lock);
0453
0454 return ERR_PTR(-ENODEV);
0455 }
0456
0457 static struct hte_device *hte_find_dev_from_linedata(struct hte_ts_desc *desc)
0458 {
0459 struct hte_device *gdev;
0460
0461 spin_lock(&hte_lock);
0462
0463 list_for_each_entry(gdev, &hte_devices, list)
0464 if (gdev->chip && gdev->chip->match_from_linedata) {
0465 if (!gdev->chip->match_from_linedata(gdev->chip, desc))
0466 continue;
0467 spin_unlock(&hte_lock);
0468 return gdev;
0469 }
0470
0471 spin_unlock(&hte_lock);
0472
0473 return ERR_PTR(-ENODEV);
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487 int of_hte_req_count(struct device *dev)
0488 {
0489 int count;
0490
0491 if (!dev || !dev->of_node)
0492 return -EINVAL;
0493
0494 count = of_count_phandle_with_args(dev->of_node, "timestamps",
0495 "#timestamp-cells");
0496
0497 return count ? count : -ENOENT;
0498 }
0499 EXPORT_SYMBOL_GPL(of_hte_req_count);
0500
0501 static inline struct hte_device *hte_get_dev(struct hte_ts_desc *desc)
0502 {
0503 return hte_find_dev_from_linedata(desc);
0504 }
0505
0506 static struct hte_device *hte_of_get_dev(struct device *dev,
0507 struct hte_ts_desc *desc,
0508 int index,
0509 struct of_phandle_args *args,
0510 bool *free_name)
0511 {
0512 int ret;
0513 struct device_node *np;
0514 char *temp;
0515
0516 if (!dev->of_node)
0517 return ERR_PTR(-EINVAL);
0518
0519 np = dev->of_node;
0520
0521 if (!of_find_property(np, "timestamp-names", NULL)) {
0522
0523 desc->attr.name = NULL;
0524 } else {
0525 ret = of_property_read_string_index(np, "timestamp-names",
0526 index, &desc->attr.name);
0527 if (ret) {
0528 pr_err("can't parse \"timestamp-names\" property\n");
0529 return ERR_PTR(ret);
0530 }
0531 *free_name = false;
0532 if (desc->attr.name) {
0533 temp = skip_spaces(desc->attr.name);
0534 if (!*temp)
0535 desc->attr.name = NULL;
0536 }
0537 }
0538
0539 ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells",
0540 index, args);
0541 if (ret) {
0542 pr_err("%s(): can't parse \"timestamps\" property\n",
0543 __func__);
0544 return ERR_PTR(ret);
0545 }
0546
0547 of_node_put(args->np);
0548
0549 return of_node_to_htedevice(args->np);
0550 }
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index)
0568 {
0569 struct hte_device *gdev;
0570 struct hte_ts_info *ei;
0571 const struct fwnode_handle *fwnode;
0572 struct of_phandle_args args;
0573 u32 xlated_id;
0574 int ret;
0575 bool free_name = false;
0576
0577 if (!desc)
0578 return -EINVAL;
0579
0580 fwnode = dev ? dev_fwnode(dev) : NULL;
0581
0582 if (is_of_node(fwnode))
0583 gdev = hte_of_get_dev(dev, desc, index, &args, &free_name);
0584 else
0585 gdev = hte_get_dev(desc);
0586
0587 if (IS_ERR(gdev)) {
0588 pr_err("%s() no hte dev found\n", __func__);
0589 return PTR_ERR(gdev);
0590 }
0591
0592 if (!try_module_get(gdev->owner))
0593 return -ENODEV;
0594
0595 if (!gdev->chip) {
0596 pr_err("%s(): requested id does not have provider\n",
0597 __func__);
0598 ret = -ENODEV;
0599 goto put;
0600 }
0601
0602 if (is_of_node(fwnode)) {
0603 if (!gdev->chip->xlate_of)
0604 ret = -EINVAL;
0605 else
0606 ret = gdev->chip->xlate_of(gdev->chip, &args,
0607 desc, &xlated_id);
0608 } else {
0609 if (!gdev->chip->xlate_plat)
0610 ret = -EINVAL;
0611 else
0612 ret = gdev->chip->xlate_plat(gdev->chip, desc,
0613 &xlated_id);
0614 }
0615
0616 if (ret < 0)
0617 goto put;
0618
0619 ei = &gdev->ei[xlated_id];
0620
0621 ret = hte_bind_ts_info_locked(ei, desc, xlated_id);
0622 if (ret)
0623 goto put;
0624
0625 ei->free_attr_name = free_name;
0626
0627 return 0;
0628
0629 put:
0630 module_put(gdev->owner);
0631 return ret;
0632 }
0633 EXPORT_SYMBOL_GPL(hte_ts_get);
0634
0635 static void __devm_hte_release_ts(void *res)
0636 {
0637 hte_ts_put(res);
0638 }
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656 int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb,
0657 hte_ts_sec_cb_t tcb, void *data)
0658 {
0659 int ret;
0660 struct hte_ts_info *ei;
0661
0662 if (!desc || !desc->hte_data || !cb)
0663 return -EINVAL;
0664
0665 ei = desc->hte_data;
0666 if (!ei || !ei->gdev)
0667 return -EINVAL;
0668
0669 ret = __hte_req_ts(desc, cb, tcb, data);
0670 if (ret < 0) {
0671 dev_err(ei->gdev->chip->dev,
0672 "failed to request id: %d\n", desc->attr.line_id);
0673 return ret;
0674 }
0675
0676 return 0;
0677 }
0678 EXPORT_SYMBOL_GPL(hte_request_ts_ns);
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc,
0699 hte_ts_cb_t cb, hte_ts_sec_cb_t tcb,
0700 void *data)
0701 {
0702 int err;
0703
0704 if (!dev)
0705 return -EINVAL;
0706
0707 err = hte_request_ts_ns(desc, cb, tcb, data);
0708 if (err)
0709 return err;
0710
0711 err = devm_add_action_or_reset(dev, __devm_hte_release_ts, desc);
0712 if (err)
0713 return err;
0714
0715 return 0;
0716 }
0717 EXPORT_SYMBOL_GPL(devm_hte_request_ts_ns);
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735 int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id,
0736 unsigned long edge_flags, const char *name, void *data)
0737 {
0738 if (!desc)
0739 return -EINVAL;
0740
0741 memset(&desc->attr, 0, sizeof(desc->attr));
0742
0743 desc->attr.edge_flags = edge_flags;
0744 desc->attr.line_id = line_id;
0745 desc->attr.line_data = data;
0746 if (name) {
0747 name = kstrdup_const(name, GFP_KERNEL);
0748 if (!name)
0749 return -ENOMEM;
0750 }
0751
0752 desc->attr.name = name;
0753
0754 return 0;
0755 }
0756 EXPORT_SYMBOL_GPL(hte_init_line_attr);
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768 int hte_get_clk_src_info(const struct hte_ts_desc *desc,
0769 struct hte_clk_info *ci)
0770 {
0771 struct hte_chip *chip;
0772 struct hte_ts_info *ei;
0773
0774 if (!desc || !desc->hte_data || !ci) {
0775 pr_debug("%s:%d\n", __func__, __LINE__);
0776 return -EINVAL;
0777 }
0778
0779 ei = desc->hte_data;
0780 if (!ei->gdev || !ei->gdev->chip)
0781 return -EINVAL;
0782
0783 chip = ei->gdev->chip;
0784 if (!chip->ops->get_clk_src_info)
0785 return -EOPNOTSUPP;
0786
0787 return chip->ops->get_clk_src_info(chip, ci);
0788 }
0789 EXPORT_SYMBOL_GPL(hte_get_clk_src_info);
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803 int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id,
0804 struct hte_ts_data *data)
0805 {
0806 enum hte_return ret;
0807 int st = 0;
0808 struct hte_ts_info *ei;
0809 unsigned long flag;
0810
0811 if (!chip || !data || !chip->gdev)
0812 return -EINVAL;
0813
0814 if (xlated_id >= chip->nlines)
0815 return -EINVAL;
0816
0817 ei = &chip->gdev->ei[xlated_id];
0818
0819 spin_lock_irqsave(&ei->slock, flag);
0820
0821
0822 data->seq = ei->seq++;
0823
0824 if (!test_bit(HTE_TS_REGISTERED, &ei->flags) ||
0825 test_bit(HTE_TS_DISABLE, &ei->flags)) {
0826 dev_dbg(chip->dev, "Unknown timestamp push\n");
0827 atomic_inc(&ei->dropped_ts);
0828 st = -EINVAL;
0829 goto unlock;
0830 }
0831
0832 ret = ei->cb(data, ei->cl_data);
0833 if (ret == HTE_RUN_SECOND_CB && ei->tcb) {
0834 queue_work(system_unbound_wq, &ei->cb_work);
0835 set_bit(HTE_TS_QUEUE_WK, &ei->flags);
0836 }
0837
0838 unlock:
0839 spin_unlock_irqrestore(&ei->slock, flag);
0840
0841 return st;
0842 }
0843 EXPORT_SYMBOL_GPL(hte_push_ts_ns);
0844
0845 static int hte_register_chip(struct hte_chip *chip)
0846 {
0847 struct hte_device *gdev;
0848 u32 i;
0849
0850 if (!chip || !chip->dev || !chip->dev->of_node)
0851 return -EINVAL;
0852
0853 if (!chip->ops || !chip->ops->request || !chip->ops->release) {
0854 dev_err(chip->dev, "Driver needs to provide ops\n");
0855 return -EINVAL;
0856 }
0857
0858 gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL);
0859 if (!gdev)
0860 return -ENOMEM;
0861
0862 gdev->chip = chip;
0863 chip->gdev = gdev;
0864 gdev->nlines = chip->nlines;
0865 gdev->sdev = chip->dev;
0866
0867 for (i = 0; i < chip->nlines; i++) {
0868 gdev->ei[i].gdev = gdev;
0869 mutex_init(&gdev->ei[i].req_mlock);
0870 spin_lock_init(&gdev->ei[i].slock);
0871 }
0872
0873 if (chip->dev->driver)
0874 gdev->owner = chip->dev->driver->owner;
0875 else
0876 gdev->owner = THIS_MODULE;
0877
0878 of_node_get(chip->dev->of_node);
0879
0880 INIT_LIST_HEAD(&gdev->list);
0881
0882 spin_lock(&hte_lock);
0883 list_add_tail(&gdev->list, &hte_devices);
0884 spin_unlock(&hte_lock);
0885
0886 hte_chip_dbgfs_init(gdev);
0887
0888 dev_dbg(chip->dev, "Added hte chip\n");
0889
0890 return 0;
0891 }
0892
0893 static int hte_unregister_chip(struct hte_chip *chip)
0894 {
0895 struct hte_device *gdev;
0896
0897 if (!chip)
0898 return -EINVAL;
0899
0900 gdev = chip->gdev;
0901
0902 spin_lock(&hte_lock);
0903 list_del(&gdev->list);
0904 spin_unlock(&hte_lock);
0905
0906 gdev->chip = NULL;
0907
0908 of_node_put(chip->dev->of_node);
0909 debugfs_remove_recursive(gdev->dbg_root);
0910 kfree(gdev);
0911
0912 dev_dbg(chip->dev, "Removed hte chip\n");
0913
0914 return 0;
0915 }
0916
0917 static void _hte_devm_unregister_chip(void *chip)
0918 {
0919 hte_unregister_chip(chip);
0920 }
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932 int devm_hte_register_chip(struct hte_chip *chip)
0933 {
0934 int err;
0935
0936 err = hte_register_chip(chip);
0937 if (err)
0938 return err;
0939
0940 err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip,
0941 chip);
0942 if (err)
0943 return err;
0944
0945 return 0;
0946 }
0947 EXPORT_SYMBOL_GPL(devm_hte_register_chip);