]>
Commit | Line | Data |
---|---|---|
4e43d779 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
726526c3 SD |
2 | /* |
3 | * Intel MIC Platform Software Stack (MPSS) | |
4 | * | |
5 | * Copyright(c) 2014 Intel Corporation. | |
6 | * | |
726526c3 SD |
7 | * Intel MIC Bus driver. |
8 | * | |
9 | * This implementation is very similar to the the virtio bus driver | |
10 | * implementation @ drivers/virtio/virtio.c | |
11 | */ | |
12 | #include <linux/slab.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/idr.h> | |
15 | #include <linux/mic_bus.h> | |
16 | ||
726526c3 SD |
17 | static ssize_t device_show(struct device *d, |
18 | struct device_attribute *attr, char *buf) | |
19 | { | |
20 | struct mbus_device *dev = dev_to_mbus(d); | |
21 | return sprintf(buf, "0x%04x\n", dev->id.device); | |
22 | } | |
23 | static DEVICE_ATTR_RO(device); | |
24 | ||
25 | static ssize_t vendor_show(struct device *d, | |
26 | struct device_attribute *attr, char *buf) | |
27 | { | |
28 | struct mbus_device *dev = dev_to_mbus(d); | |
29 | return sprintf(buf, "0x%04x\n", dev->id.vendor); | |
30 | } | |
31 | static DEVICE_ATTR_RO(vendor); | |
32 | ||
33 | static ssize_t modalias_show(struct device *d, | |
34 | struct device_attribute *attr, char *buf) | |
35 | { | |
36 | struct mbus_device *dev = dev_to_mbus(d); | |
37 | return sprintf(buf, "mbus:d%08Xv%08X\n", | |
38 | dev->id.device, dev->id.vendor); | |
39 | } | |
40 | static DEVICE_ATTR_RO(modalias); | |
41 | ||
42 | static struct attribute *mbus_dev_attrs[] = { | |
43 | &dev_attr_device.attr, | |
44 | &dev_attr_vendor.attr, | |
45 | &dev_attr_modalias.attr, | |
46 | NULL, | |
47 | }; | |
48 | ATTRIBUTE_GROUPS(mbus_dev); | |
49 | ||
50 | static inline int mbus_id_match(const struct mbus_device *dev, | |
51 | const struct mbus_device_id *id) | |
52 | { | |
53 | if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID) | |
54 | return 0; | |
55 | ||
56 | return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev->id.vendor; | |
57 | } | |
58 | ||
59 | /* | |
60 | * This looks through all the IDs a driver claims to support. If any of them | |
61 | * match, we return 1 and the kernel will call mbus_dev_probe(). | |
62 | */ | |
63 | static int mbus_dev_match(struct device *dv, struct device_driver *dr) | |
64 | { | |
65 | unsigned int i; | |
66 | struct mbus_device *dev = dev_to_mbus(dv); | |
67 | const struct mbus_device_id *ids; | |
68 | ||
69 | ids = drv_to_mbus(dr)->id_table; | |
70 | for (i = 0; ids[i].device; i++) | |
71 | if (mbus_id_match(dev, &ids[i])) | |
72 | return 1; | |
73 | return 0; | |
74 | } | |
75 | ||
76 | static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env) | |
77 | { | |
78 | struct mbus_device *dev = dev_to_mbus(dv); | |
79 | ||
80 | return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X", | |
81 | dev->id.device, dev->id.vendor); | |
82 | } | |
83 | ||
84 | static int mbus_dev_probe(struct device *d) | |
85 | { | |
86 | int err; | |
87 | struct mbus_device *dev = dev_to_mbus(d); | |
88 | struct mbus_driver *drv = drv_to_mbus(dev->dev.driver); | |
89 | ||
90 | err = drv->probe(dev); | |
91 | if (!err) | |
92 | if (drv->scan) | |
93 | drv->scan(dev); | |
94 | return err; | |
95 | } | |
96 | ||
97 | static int mbus_dev_remove(struct device *d) | |
98 | { | |
99 | struct mbus_device *dev = dev_to_mbus(d); | |
100 | struct mbus_driver *drv = drv_to_mbus(dev->dev.driver); | |
101 | ||
102 | drv->remove(dev); | |
103 | return 0; | |
104 | } | |
105 | ||
106 | static struct bus_type mic_bus = { | |
107 | .name = "mic_bus", | |
108 | .match = mbus_dev_match, | |
109 | .dev_groups = mbus_dev_groups, | |
110 | .uevent = mbus_uevent, | |
111 | .probe = mbus_dev_probe, | |
112 | .remove = mbus_dev_remove, | |
113 | }; | |
114 | ||
115 | int mbus_register_driver(struct mbus_driver *driver) | |
116 | { | |
117 | driver->driver.bus = &mic_bus; | |
118 | return driver_register(&driver->driver); | |
119 | } | |
120 | EXPORT_SYMBOL_GPL(mbus_register_driver); | |
121 | ||
122 | void mbus_unregister_driver(struct mbus_driver *driver) | |
123 | { | |
124 | driver_unregister(&driver->driver); | |
125 | } | |
126 | EXPORT_SYMBOL_GPL(mbus_unregister_driver); | |
127 | ||
128 | static void mbus_release_dev(struct device *d) | |
129 | { | |
130 | struct mbus_device *mbdev = dev_to_mbus(d); | |
131 | kfree(mbdev); | |
132 | } | |
133 | ||
134 | struct mbus_device * | |
5299709d | 135 | mbus_register_device(struct device *pdev, int id, const struct dma_map_ops *dma_ops, |
d411e793 AD |
136 | struct mbus_hw_ops *hw_ops, int index, |
137 | void __iomem *mmio_va) | |
726526c3 SD |
138 | { |
139 | int ret; | |
140 | struct mbus_device *mbdev; | |
141 | ||
142 | mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL); | |
143 | if (!mbdev) | |
144 | return ERR_PTR(-ENOMEM); | |
145 | ||
146 | mbdev->mmio_va = mmio_va; | |
147 | mbdev->dev.parent = pdev; | |
148 | mbdev->id.device = id; | |
149 | mbdev->id.vendor = MBUS_DEV_ANY_ID; | |
5657933d | 150 | mbdev->dev.dma_ops = dma_ops; |
726526c3 SD |
151 | mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask; |
152 | dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64)); | |
153 | mbdev->dev.release = mbus_release_dev; | |
154 | mbdev->hw_ops = hw_ops; | |
155 | mbdev->dev.bus = &mic_bus; | |
d411e793 | 156 | mbdev->index = index; |
726526c3 SD |
157 | dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index); |
158 | /* | |
159 | * device_register() causes the bus infrastructure to look for a | |
160 | * matching driver. | |
161 | */ | |
162 | ret = device_register(&mbdev->dev); | |
163 | if (ret) | |
d411e793 | 164 | goto free_mbdev; |
726526c3 | 165 | return mbdev; |
726526c3 | 166 | free_mbdev: |
82ff3ac7 | 167 | put_device(&mbdev->dev); |
726526c3 SD |
168 | return ERR_PTR(ret); |
169 | } | |
170 | EXPORT_SYMBOL_GPL(mbus_register_device); | |
171 | ||
172 | void mbus_unregister_device(struct mbus_device *mbdev) | |
173 | { | |
726526c3 | 174 | device_unregister(&mbdev->dev); |
726526c3 SD |
175 | } |
176 | EXPORT_SYMBOL_GPL(mbus_unregister_device); | |
177 | ||
178 | static int __init mbus_init(void) | |
179 | { | |
180 | return bus_register(&mic_bus); | |
181 | } | |
182 | ||
183 | static void __exit mbus_exit(void) | |
184 | { | |
185 | bus_unregister(&mic_bus); | |
726526c3 SD |
186 | } |
187 | ||
188 | core_initcall(mbus_init); | |
189 | module_exit(mbus_exit); | |
190 | ||
191 | MODULE_AUTHOR("Intel Corporation"); | |
192 | MODULE_DESCRIPTION("Intel(R) MIC Bus driver"); | |
193 | MODULE_LICENSE("GPL v2"); |