2 * Greybus interface code
4 * Copyright 2014 Google Inc.
5 * Copyright 2014 Linaro Ltd.
7 * Released under the GPLv2 only.
12 /* interface sysfs attributes */
13 #define gb_interface_attr(field, type) \
14 static ssize_t field##_show(struct device *dev, \
15 struct device_attribute *attr, \
18 struct gb_interface *intf = to_gb_interface(dev); \
19 return sprintf(buf, "%"#type"\n", intf->field); \
21 static DEVICE_ATTR_RO(field)
23 gb_interface_attr(vendor, x);
24 gb_interface_attr(product, x);
25 gb_interface_attr(unique_id, llX);
26 gb_interface_attr(vendor_string, s);
27 gb_interface_attr(product_string, s);
29 static struct attribute *interface_attrs[] = {
30 &dev_attr_vendor.attr,
31 &dev_attr_product.attr,
32 &dev_attr_unique_id.attr,
33 &dev_attr_vendor_string.attr,
34 &dev_attr_product_string.attr,
37 ATTRIBUTE_GROUPS(interface);
40 /* XXX This could be per-host device */
41 static DEFINE_SPINLOCK(gb_interfaces_lock);
43 static int gb_interface_match_one_id(struct gb_interface *intf,
44 const struct greybus_interface_id *id)
46 if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) &&
47 (id->vendor != intf->vendor))
50 if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) &&
51 (id->product != intf->product))
54 if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) &&
55 (id->unique_id != intf->unique_id))
61 const struct greybus_interface_id *
62 gb_interface_match_id(struct gb_interface *intf,
63 const struct greybus_interface_id *id)
68 for (; id->vendor || id->product || id->unique_id ||
69 id->driver_info; id++) {
70 if (gb_interface_match_one_id(intf, id))
77 // FIXME, odds are you don't want to call this function, rework the caller to
78 // not need it please.
79 struct gb_interface *gb_interface_find(struct greybus_host_device *hd,
82 struct gb_interface *intf;
84 list_for_each_entry(intf, &hd->interfaces, links)
85 if (intf->interface_id == interface_id)
91 static void greybus_interface_release(struct device *dev)
93 struct gb_interface *intf = to_gb_interface(dev);
98 struct device_type greybus_interface_type = {
99 .name = "greybus_interface",
100 .release = greybus_interface_release,
104 * A Greybus module represents a user-replicable component on an Ara
105 * phone. An interface is the physical connection on that module. A
106 * module may have more than one interface.
108 * Create a gb_interface structure to represent a discovered interface.
109 * The position of interface within the Endo is encoded in "interface_id"
112 * Returns a pointer to the new interfce or a null pointer if a
113 * failure occurs due to memory exhaustion.
115 static struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
118 struct gb_module *module;
119 struct gb_interface *intf;
122 intf = gb_interface_find(hd, interface_id);
124 dev_err(hd->parent, "Duplicate interface with interface-id: %d will not be created\n",
129 module = gb_module_find_or_create(hd, get_module_id(interface_id));
133 intf = kzalloc(sizeof(*intf), GFP_KERNEL);
137 intf->hd = hd; /* XXX refcount? */
138 intf->module = module;
139 intf->interface_id = interface_id;
140 INIT_LIST_HEAD(&intf->bundles);
141 INIT_LIST_HEAD(&intf->manifest_descs);
143 intf->dev.parent = &module->dev;
144 intf->dev.bus = &greybus_bus_type;
145 intf->dev.type = &greybus_interface_type;
146 intf->dev.groups = interface_groups;
147 intf->dev.dma_mask = hd->parent->dma_mask;
148 device_initialize(&intf->dev);
149 dev_set_name(&intf->dev, "%s:%d", dev_name(&module->dev), interface_id);
151 retval = device_add(&intf->dev);
153 pr_err("failed to add interface device for id 0x%02hhx\n",
158 spin_lock_irq(&gb_interfaces_lock);
159 list_add_tail(&intf->links, &hd->interfaces);
160 spin_unlock_irq(&gb_interfaces_lock);
165 put_device(&intf->dev);
168 put_device(&module->dev);
173 * Tear down a previously set up module.
175 static void gb_interface_destroy(struct gb_interface *intf)
177 struct gb_module *module;
182 spin_lock_irq(&gb_interfaces_lock);
183 list_del(&intf->links);
184 spin_unlock_irq(&gb_interfaces_lock);
186 gb_bundle_destroy(intf);
188 kfree(intf->product_string);
189 kfree(intf->vendor_string);
190 /* kref_put(module->hd); */
192 module = intf->module;
193 device_unregister(&intf->dev);
194 gb_module_remove(module);
200 * Pass in a buffer that _should_ contain a Greybus module manifest
201 * and register a greybus device structure with the kernel core.
203 void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data,
206 struct gb_interface *intf;
208 intf = gb_interface_create(hd, interface_id);
210 dev_err(hd->parent, "failed to create interface\n");
215 * Parse the manifest and build up our data structures
216 * representing what's in it.
218 if (!gb_manifest_parse(intf, data, size)) {
219 dev_err(hd->parent, "manifest error\n");
225 * We've successfully parsed the manifest. Now we need to
226 * allocate CPort Id's for connecting to the CPorts found on
227 * other modules. For each of these, establish a connection
228 * between the local and remote CPorts (including
229 * configuring the switch to allow them to communicate).
235 gb_interface_destroy(intf);
238 void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id)
240 struct gb_interface *intf = gb_interface_find(hd, interface_id);
243 gb_interface_destroy(intf);
245 dev_err(hd->parent, "interface id %d not found\n",
249 void gb_remove_interfaces(struct greybus_host_device *hd)
251 struct gb_interface *intf, *temp;
253 list_for_each_entry_safe(intf, temp, &hd->interfaces, links)
254 gb_interface_destroy(intf);