blob: 1714482bd34dfb575ec9e033fe43af5563a14abc [file] [log] [blame]
Alex Elder8c12cde2014-10-01 21:54:12 -05001/*
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -05002 * Greybus bundles
Alex Elder8c12cde2014-10-01 21:54:12 -05003 *
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +02004 * Copyright 2014-2015 Google Inc.
5 * Copyright 2014-2015 Linaro Ltd.
Alex Elder8c12cde2014-10-01 21:54:12 -05006 *
7 * Released under the GPLv2 only.
8 */
9
10#include "greybus.h"
11
Johan Hovold4396c002015-11-25 15:58:59 +010012static ssize_t bundle_class_show(struct device *dev,
13 struct device_attribute *attr, char *buf)
Viresh Kumar9f5f30e7122015-04-01 20:32:04 +053014{
15 struct gb_bundle *bundle = to_gb_bundle(dev);
16
Johan Hovold2b14dab2015-11-25 15:59:00 +010017 return sprintf(buf, "0x%02x\n", bundle->class);
Viresh Kumar9f5f30e7122015-04-01 20:32:04 +053018}
Johan Hovold4396c002015-11-25 15:58:59 +010019static DEVICE_ATTR_RO(bundle_class);
Viresh Kumar9f5f30e7122015-04-01 20:32:04 +053020
Johan Hovolda97015c2015-11-25 15:59:01 +010021static ssize_t bundle_id_show(struct device *dev,
22 struct device_attribute *attr, char *buf)
23{
24 struct gb_bundle *bundle = to_gb_bundle(dev);
25
26 return sprintf(buf, "%u\n", bundle->id);
27}
28static DEVICE_ATTR_RO(bundle_id);
29
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +020030static ssize_t state_show(struct device *dev, struct device_attribute *attr,
31 char *buf)
32{
33 struct gb_bundle *bundle = to_gb_bundle(dev);
34
35 if (bundle->state == NULL)
36 return sprintf(buf, "\n");
37
38 return sprintf(buf, "%s\n", bundle->state);
39}
40
41static ssize_t state_store(struct device *dev, struct device_attribute *attr,
42 const char *buf, size_t size)
43{
44 struct gb_bundle *bundle = to_gb_bundle(dev);
45
46 kfree(bundle->state);
Alex Elder22fd2a82015-04-17 14:41:47 -050047 bundle->state = kstrdup(buf, GFP_KERNEL);
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +020048 if (!bundle->state)
49 return -ENOMEM;
50
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +020051 /* Tell userspace that the file contents changed */
52 sysfs_notify(&bundle->dev.kobj, NULL, "state");
53
54 return size;
55}
56static DEVICE_ATTR_RW(state);
57
58
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050059static struct attribute *bundle_attrs[] = {
Johan Hovold4396c002015-11-25 15:58:59 +010060 &dev_attr_bundle_class.attr,
Johan Hovolda97015c2015-11-25 15:59:01 +010061 &dev_attr_bundle_id.attr,
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +020062 &dev_attr_state.attr,
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080063 NULL,
64};
65
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050066ATTRIBUTE_GROUPS(bundle);
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080067
Johan Hovold1db1b242015-12-07 15:05:40 +010068static struct gb_bundle *gb_bundle_find(struct gb_interface *intf,
69 u8 bundle_id)
70{
71 struct gb_bundle *bundle;
72
73 list_for_each_entry(bundle, &intf->bundles, links) {
74 if (bundle->id == bundle_id)
75 return bundle;
76 }
77
78 return NULL;
79}
80
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050081static void gb_bundle_release(struct device *dev)
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080082{
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050083 struct gb_bundle *bundle = to_gb_bundle(dev);
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080084
Greg Kroah-Hartman75052a52015-04-13 19:48:37 +020085 kfree(bundle->state);
Johan Hovold98fdf5a2016-01-21 17:34:09 +010086 kfree(bundle->cport_desc);
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050087 kfree(bundle);
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080088}
89
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050090struct device_type greybus_bundle_type = {
91 .name = "greybus_bundle",
92 .release = gb_bundle_release,
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +080093};
94
Alex Elder8c12cde2014-10-01 21:54:12 -050095/*
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -050096 * Create a gb_bundle structure to represent a discovered
97 * bundle. Returns a pointer to the new bundle or a null
Alex Elder8c12cde2014-10-01 21:54:12 -050098 * pointer if a failure occurs due to memory exhaustion.
99 */
Viresh Kumar7c183f72015-04-01 20:32:00 +0530100struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id,
Viresh Kumar88e6d372015-04-06 15:49:36 +0530101 u8 class)
Alex Elder8c12cde2014-10-01 21:54:12 -0500102{
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500103 struct gb_bundle *bundle;
Alex Elder8c12cde2014-10-01 21:54:12 -0500104
Alex Elder8267616b2015-06-09 17:42:57 -0500105 /*
106 * Reject any attempt to reuse a bundle id. We initialize
107 * these serially, so there's no need to worry about keeping
108 * the interface bundle list locked here.
109 */
110 if (gb_bundle_find(intf, bundle_id)) {
Johan Hovolda2347922015-12-07 15:05:41 +0100111 dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id);
Alex Elder8267616b2015-06-09 17:42:57 -0500112 return NULL;
113 }
114
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500115 bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
116 if (!bundle)
Alex Elder8c12cde2014-10-01 21:54:12 -0500117 return NULL;
118
Greg Kroah-Hartman4ab9b3c2014-12-19 14:56:31 -0800119 bundle->intf = intf;
Viresh Kumar7c183f72015-04-01 20:32:00 +0530120 bundle->id = bundle_id;
Viresh Kumar88e6d372015-04-06 15:49:36 +0530121 bundle->class = class;
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500122 INIT_LIST_HEAD(&bundle->connections);
Alex Elder8c12cde2014-10-01 21:54:12 -0500123
Greg Kroah-Hartman4ab9b3c2014-12-19 14:56:31 -0800124 bundle->dev.parent = &intf->dev;
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500125 bundle->dev.bus = &greybus_bus_type;
126 bundle->dev.type = &greybus_bundle_type;
127 bundle->dev.groups = bundle_groups;
128 device_initialize(&bundle->dev);
Johan Hovoldf0172c72015-11-25 15:59:05 +0100129 dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id);
Greg Kroah-Hartmanf0f61b92014-10-24 17:34:46 +0800130
Viresh Kumar928f2ab2015-06-04 18:16:45 +0530131 list_add(&bundle->links, &intf->bundles);
Alex Elder8c12cde2014-10-01 21:54:12 -0500132
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500133 return bundle;
Alex Elder8c12cde2014-10-01 21:54:12 -0500134}
135
Johan Hovolda7e36d02015-12-07 15:05:43 +0100136int gb_bundle_add(struct gb_bundle *bundle)
137{
138 int ret;
139
140 ret = device_add(&bundle->dev);
141 if (ret) {
142 dev_err(&bundle->dev, "failed to register bundle: %d\n", ret);
143 return ret;
144 }
145
146 return 0;
147}
148
Alex Elder8c12cde2014-10-01 21:54:12 -0500149/*
Greg Kroah-Hartman1db0a5f2014-12-12 17:10:17 -0500150 * Tear down a previously set up bundle.
Alex Elder8c12cde2014-10-01 21:54:12 -0500151 */
Alex Elderfe53b452015-06-12 10:21:11 -0500152void gb_bundle_destroy(struct gb_bundle *bundle)
Alex Elder8c12cde2014-10-01 21:54:12 -0500153{
Johan Hovolda7e36d02015-12-07 15:05:43 +0100154 if (device_is_registered(&bundle->dev))
155 device_del(&bundle->dev);
156
Alex Elderfe53b452015-06-12 10:21:11 -0500157 list_del(&bundle->links);
Johan Hovold48d70772015-02-13 11:28:09 +0800158
Johan Hovolda7e36d02015-12-07 15:05:43 +0100159 put_device(&bundle->dev);
Alex Elder8c12cde2014-10-01 21:54:12 -0500160}