blob: 5f2141c71738dca5bfcf8664584523f26dd30400 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Intel MIC Platform Software Stack (MPSS)
4 *
5 * Copyright(c) 2015 Intel Corporation.
6 *
7 * Intel MIC COSM Bus Driver
8 */
9#include <linux/slab.h>
10#include <linux/module.h>
11#include <linux/idr.h>
12#include "cosm_bus.h"
13
14/* Unique numbering for cosm devices. */
15static DEFINE_IDA(cosm_index_ida);
16
17static int cosm_dev_probe(struct device *d)
18{
19 struct cosm_device *dev = dev_to_cosm(d);
20 struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
21
22 return drv->probe(dev);
23}
24
25static int cosm_dev_remove(struct device *d)
26{
27 struct cosm_device *dev = dev_to_cosm(d);
28 struct cosm_driver *drv = drv_to_cosm(dev->dev.driver);
29
30 drv->remove(dev);
31 return 0;
32}
33
34static struct bus_type cosm_bus = {
35 .name = "cosm_bus",
36 .probe = cosm_dev_probe,
37 .remove = cosm_dev_remove,
38};
39
40int cosm_register_driver(struct cosm_driver *driver)
41{
42 driver->driver.bus = &cosm_bus;
43 return driver_register(&driver->driver);
44}
45EXPORT_SYMBOL_GPL(cosm_register_driver);
46
47void cosm_unregister_driver(struct cosm_driver *driver)
48{
49 driver_unregister(&driver->driver);
50}
51EXPORT_SYMBOL_GPL(cosm_unregister_driver);
52
53static inline void cosm_release_dev(struct device *d)
54{
55 struct cosm_device *cdev = dev_to_cosm(d);
56
57 kfree(cdev);
58}
59
60struct cosm_device *
61cosm_register_device(struct device *pdev, struct cosm_hw_ops *hw_ops)
62{
63 struct cosm_device *cdev;
64 int ret;
65
66 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
67 if (!cdev)
68 return ERR_PTR(-ENOMEM);
69
70 cdev->dev.parent = pdev;
71 cdev->dev.release = cosm_release_dev;
72 cdev->hw_ops = hw_ops;
73 dev_set_drvdata(&cdev->dev, cdev);
74 cdev->dev.bus = &cosm_bus;
75
76 /* Assign a unique device index and hence name */
77 ret = ida_simple_get(&cosm_index_ida, 0, 0, GFP_KERNEL);
78 if (ret < 0)
79 goto free_cdev;
80
81 cdev->index = ret;
82 cdev->dev.id = ret;
83 dev_set_name(&cdev->dev, "cosm-dev%u", cdev->index);
84
85 ret = device_register(&cdev->dev);
86 if (ret)
87 goto ida_remove;
88 return cdev;
89ida_remove:
90 ida_simple_remove(&cosm_index_ida, cdev->index);
91free_cdev:
92 put_device(&cdev->dev);
93 return ERR_PTR(ret);
94}
95EXPORT_SYMBOL_GPL(cosm_register_device);
96
97void cosm_unregister_device(struct cosm_device *dev)
98{
99 int index = dev->index; /* save for after device release */
100
101 device_unregister(&dev->dev);
102 ida_simple_remove(&cosm_index_ida, index);
103}
104EXPORT_SYMBOL_GPL(cosm_unregister_device);
105
106struct cosm_device *cosm_find_cdev_by_id(int id)
107{
108 struct device *dev = subsys_find_device_by_id(&cosm_bus, id, NULL);
109
110 return dev ? container_of(dev, struct cosm_device, dev) : NULL;
111}
112EXPORT_SYMBOL_GPL(cosm_find_cdev_by_id);
113
114static int __init cosm_init(void)
115{
116 return bus_register(&cosm_bus);
117}
118
119static void __exit cosm_exit(void)
120{
121 bus_unregister(&cosm_bus);
122 ida_destroy(&cosm_index_ida);
123}
124
125core_initcall(cosm_init);
126module_exit(cosm_exit);
127
128MODULE_AUTHOR("Intel Corporation");
129MODULE_DESCRIPTION("Intel(R) MIC card OS state management bus driver");
130MODULE_LICENSE("GPL v2");