]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/hsi/hsi.c
HSI: Add channel resource support to HSI clients
[karo-tx-linux.git] / drivers / hsi / hsi.c
1 /*
2  * HSI core.
3  *
4  * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Carlos Chinea <carlos.chinea@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22 #include <linux/hsi/hsi.h>
23 #include <linux/compiler.h>
24 #include <linux/list.h>
25 #include <linux/kobject.h>
26 #include <linux/slab.h>
27 #include <linux/string.h>
28 #include <linux/notifier.h>
29 #include "hsi_core.h"
30
31 static ssize_t modalias_show(struct device *dev,
32                         struct device_attribute *a __maybe_unused, char *buf)
33 {
34         return sprintf(buf, "hsi:%s\n", dev_name(dev));
35 }
36 static DEVICE_ATTR_RO(modalias);
37
38 static struct attribute *hsi_bus_dev_attrs[] = {
39         &dev_attr_modalias.attr,
40         NULL,
41 };
42 ATTRIBUTE_GROUPS(hsi_bus_dev);
43
44 static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
45 {
46         add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
47
48         return 0;
49 }
50
51 static int hsi_bus_match(struct device *dev, struct device_driver *driver)
52 {
53         return strcmp(dev_name(dev), driver->name) == 0;
54 }
55
56 static struct bus_type hsi_bus_type = {
57         .name           = "hsi",
58         .dev_groups     = hsi_bus_dev_groups,
59         .match          = hsi_bus_match,
60         .uevent         = hsi_bus_uevent,
61 };
62
63 static void hsi_client_release(struct device *dev)
64 {
65         struct hsi_client *cl = to_hsi_client(dev);
66
67         kfree(cl->tx_cfg.channels);
68         kfree(cl->rx_cfg.channels);
69         kfree(cl);
70 }
71
72 static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
73 {
74         struct hsi_client *cl;
75         size_t size;
76
77         cl = kzalloc(sizeof(*cl), GFP_KERNEL);
78         if (!cl)
79                 return;
80
81         cl->tx_cfg = info->tx_cfg;
82         if (cl->tx_cfg.channels) {
83                 size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
84                 cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
85                 memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
86         }
87
88         cl->rx_cfg = info->rx_cfg;
89         if (cl->rx_cfg.channels) {
90                 size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
91                 cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
92                 memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
93         }
94
95         cl->device.bus = &hsi_bus_type;
96         cl->device.parent = &port->device;
97         cl->device.release = hsi_client_release;
98         dev_set_name(&cl->device, "%s", info->name);
99         cl->device.platform_data = info->platform_data;
100         if (info->archdata)
101                 cl->device.archdata = *info->archdata;
102         if (device_register(&cl->device) < 0) {
103                 pr_err("hsi: failed to register client: %s\n", info->name);
104                 put_device(&cl->device);
105         }
106 }
107
108 static void hsi_scan_board_info(struct hsi_controller *hsi)
109 {
110         struct hsi_cl_info *cl_info;
111         struct hsi_port *p;
112
113         list_for_each_entry(cl_info, &hsi_board_list, list)
114                 if (cl_info->info.hsi_id == hsi->id) {
115                         p = hsi_find_port_num(hsi, cl_info->info.port);
116                         if (!p)
117                                 continue;
118                         hsi_new_client(p, &cl_info->info);
119                 }
120 }
121
122 static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
123 {
124         device_unregister(dev);
125
126         return 0;
127 }
128
129 static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
130 {
131         device_for_each_child(dev, NULL, hsi_remove_client);
132         device_unregister(dev);
133
134         return 0;
135 }
136
137 static void hsi_controller_release(struct device *dev)
138 {
139         struct hsi_controller *hsi = to_hsi_controller(dev);
140
141         kfree(hsi->port);
142         kfree(hsi);
143 }
144
145 static void hsi_port_release(struct device *dev)
146 {
147         kfree(to_hsi_port(dev));
148 }
149
150 /**
151  * hsi_unregister_port - Unregister an HSI port
152  * @port: The HSI port to unregister
153  */
154 void hsi_port_unregister_clients(struct hsi_port *port)
155 {
156         device_for_each_child(&port->device, NULL, hsi_remove_client);
157 }
158 EXPORT_SYMBOL_GPL(hsi_port_unregister_clients);
159
160 /**
161  * hsi_unregister_controller - Unregister an HSI controller
162  * @hsi: The HSI controller to register
163  */
164 void hsi_unregister_controller(struct hsi_controller *hsi)
165 {
166         device_for_each_child(&hsi->device, NULL, hsi_remove_port);
167         device_unregister(&hsi->device);
168 }
169 EXPORT_SYMBOL_GPL(hsi_unregister_controller);
170
171 /**
172  * hsi_register_controller - Register an HSI controller and its ports
173  * @hsi: The HSI controller to register
174  *
175  * Returns -errno on failure, 0 on success.
176  */
177 int hsi_register_controller(struct hsi_controller *hsi)
178 {
179         unsigned int i;
180         int err;
181
182         err = device_add(&hsi->device);
183         if (err < 0)
184                 return err;
185         for (i = 0; i < hsi->num_ports; i++) {
186                 hsi->port[i]->device.parent = &hsi->device;
187                 err = device_add(&hsi->port[i]->device);
188                 if (err < 0)
189                         goto out;
190         }
191         /* Populate HSI bus with HSI clients */
192         hsi_scan_board_info(hsi);
193
194         return 0;
195 out:
196         while (i-- > 0)
197                 device_del(&hsi->port[i]->device);
198         device_del(&hsi->device);
199
200         return err;
201 }
202 EXPORT_SYMBOL_GPL(hsi_register_controller);
203
204 /**
205  * hsi_register_client_driver - Register an HSI client to the HSI bus
206  * @drv: HSI client driver to register
207  *
208  * Returns -errno on failure, 0 on success.
209  */
210 int hsi_register_client_driver(struct hsi_client_driver *drv)
211 {
212         drv->driver.bus = &hsi_bus_type;
213
214         return driver_register(&drv->driver);
215 }
216 EXPORT_SYMBOL_GPL(hsi_register_client_driver);
217
218 static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
219 {
220         return 0;
221 }
222
223 static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
224 {
225         return 0;
226 }
227
228 /**
229  * hsi_put_controller - Free an HSI controller
230  *
231  * @hsi: Pointer to the HSI controller to freed
232  *
233  * HSI controller drivers should only use this function if they need
234  * to free their allocated hsi_controller structures before a successful
235  * call to hsi_register_controller. Other use is not allowed.
236  */
237 void hsi_put_controller(struct hsi_controller *hsi)
238 {
239         unsigned int i;
240
241         if (!hsi)
242                 return;
243
244         for (i = 0; i < hsi->num_ports; i++)
245                 if (hsi->port && hsi->port[i])
246                         put_device(&hsi->port[i]->device);
247         put_device(&hsi->device);
248 }
249 EXPORT_SYMBOL_GPL(hsi_put_controller);
250
251 /**
252  * hsi_alloc_controller - Allocate an HSI controller and its ports
253  * @n_ports: Number of ports on the HSI controller
254  * @flags: Kernel allocation flags
255  *
256  * Return NULL on failure or a pointer to an hsi_controller on success.
257  */
258 struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
259 {
260         struct hsi_controller   *hsi;
261         struct hsi_port         **port;
262         unsigned int            i;
263
264         if (!n_ports)
265                 return NULL;
266
267         hsi = kzalloc(sizeof(*hsi), flags);
268         if (!hsi)
269                 return NULL;
270         port = kzalloc(sizeof(*port)*n_ports, flags);
271         if (!port) {
272                 kfree(hsi);
273                 return NULL;
274         }
275         hsi->num_ports = n_ports;
276         hsi->port = port;
277         hsi->device.release = hsi_controller_release;
278         device_initialize(&hsi->device);
279
280         for (i = 0; i < n_ports; i++) {
281                 port[i] = kzalloc(sizeof(**port), flags);
282                 if (port[i] == NULL)
283                         goto out;
284                 port[i]->num = i;
285                 port[i]->async = hsi_dummy_msg;
286                 port[i]->setup = hsi_dummy_cl;
287                 port[i]->flush = hsi_dummy_cl;
288                 port[i]->start_tx = hsi_dummy_cl;
289                 port[i]->stop_tx = hsi_dummy_cl;
290                 port[i]->release = hsi_dummy_cl;
291                 mutex_init(&port[i]->lock);
292                 ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
293                 dev_set_name(&port[i]->device, "port%d", i);
294                 hsi->port[i]->device.release = hsi_port_release;
295                 device_initialize(&hsi->port[i]->device);
296         }
297
298         return hsi;
299 out:
300         hsi_put_controller(hsi);
301
302         return NULL;
303 }
304 EXPORT_SYMBOL_GPL(hsi_alloc_controller);
305
306 /**
307  * hsi_free_msg - Free an HSI message
308  * @msg: Pointer to the HSI message
309  *
310  * Client is responsible to free the buffers pointed by the scatterlists.
311  */
312 void hsi_free_msg(struct hsi_msg *msg)
313 {
314         if (!msg)
315                 return;
316         sg_free_table(&msg->sgt);
317         kfree(msg);
318 }
319 EXPORT_SYMBOL_GPL(hsi_free_msg);
320
321 /**
322  * hsi_alloc_msg - Allocate an HSI message
323  * @nents: Number of memory entries
324  * @flags: Kernel allocation flags
325  *
326  * nents can be 0. This mainly makes sense for read transfer.
327  * In that case, HSI drivers will call the complete callback when
328  * there is data to be read without consuming it.
329  *
330  * Return NULL on failure or a pointer to an hsi_msg on success.
331  */
332 struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
333 {
334         struct hsi_msg *msg;
335         int err;
336
337         msg = kzalloc(sizeof(*msg), flags);
338         if (!msg)
339                 return NULL;
340
341         if (!nents)
342                 return msg;
343
344         err = sg_alloc_table(&msg->sgt, nents, flags);
345         if (unlikely(err)) {
346                 kfree(msg);
347                 msg = NULL;
348         }
349
350         return msg;
351 }
352 EXPORT_SYMBOL_GPL(hsi_alloc_msg);
353
354 /**
355  * hsi_async - Submit an HSI transfer to the controller
356  * @cl: HSI client sending the transfer
357  * @msg: The HSI transfer passed to controller
358  *
359  * The HSI message must have the channel, ttype, complete and destructor
360  * fields set beforehand. If nents > 0 then the client has to initialize
361  * also the scatterlists to point to the buffers to write to or read from.
362  *
363  * HSI controllers relay on pre-allocated buffers from their clients and they
364  * do not allocate buffers on their own.
365  *
366  * Once the HSI message transfer finishes, the HSI controller calls the
367  * complete callback with the status and actual_len fields of the HSI message
368  * updated. The complete callback can be called before returning from
369  * hsi_async.
370  *
371  * Returns -errno on failure or 0 on success
372  */
373 int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
374 {
375         struct hsi_port *port = hsi_get_port(cl);
376
377         if (!hsi_port_claimed(cl))
378                 return -EACCES;
379
380         WARN_ON_ONCE(!msg->destructor || !msg->complete);
381         msg->cl = cl;
382
383         return port->async(msg);
384 }
385 EXPORT_SYMBOL_GPL(hsi_async);
386
387 /**
388  * hsi_claim_port - Claim the HSI client's port
389  * @cl: HSI client that wants to claim its port
390  * @share: Flag to indicate if the client wants to share the port or not.
391  *
392  * Returns -errno on failure, 0 on success.
393  */
394 int hsi_claim_port(struct hsi_client *cl, unsigned int share)
395 {
396         struct hsi_port *port = hsi_get_port(cl);
397         int err = 0;
398
399         mutex_lock(&port->lock);
400         if ((port->claimed) && (!port->shared || !share)) {
401                 err = -EBUSY;
402                 goto out;
403         }
404         if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
405                 err = -ENODEV;
406                 goto out;
407         }
408         port->claimed++;
409         port->shared = !!share;
410         cl->pclaimed = 1;
411 out:
412         mutex_unlock(&port->lock);
413
414         return err;
415 }
416 EXPORT_SYMBOL_GPL(hsi_claim_port);
417
418 /**
419  * hsi_release_port - Release the HSI client's port
420  * @cl: HSI client which previously claimed its port
421  */
422 void hsi_release_port(struct hsi_client *cl)
423 {
424         struct hsi_port *port = hsi_get_port(cl);
425
426         mutex_lock(&port->lock);
427         /* Allow HW driver to do some cleanup */
428         port->release(cl);
429         if (cl->pclaimed)
430                 port->claimed--;
431         BUG_ON(port->claimed < 0);
432         cl->pclaimed = 0;
433         if (!port->claimed)
434                 port->shared = 0;
435         module_put(to_hsi_controller(port->device.parent)->owner);
436         mutex_unlock(&port->lock);
437 }
438 EXPORT_SYMBOL_GPL(hsi_release_port);
439
440 static int hsi_event_notifier_call(struct notifier_block *nb,
441                                 unsigned long event, void *data __maybe_unused)
442 {
443         struct hsi_client *cl = container_of(nb, struct hsi_client, nb);
444
445         (*cl->ehandler)(cl, event);
446
447         return 0;
448 }
449
450 /**
451  * hsi_register_port_event - Register a client to receive port events
452  * @cl: HSI client that wants to receive port events
453  * @handler: Event handler callback
454  *
455  * Clients should register a callback to be able to receive
456  * events from the ports. Registration should happen after
457  * claiming the port.
458  * The handler can be called in interrupt context.
459  *
460  * Returns -errno on error, or 0 on success.
461  */
462 int hsi_register_port_event(struct hsi_client *cl,
463                         void (*handler)(struct hsi_client *, unsigned long))
464 {
465         struct hsi_port *port = hsi_get_port(cl);
466
467         if (!handler || cl->ehandler)
468                 return -EINVAL;
469         if (!hsi_port_claimed(cl))
470                 return -EACCES;
471         cl->ehandler = handler;
472         cl->nb.notifier_call = hsi_event_notifier_call;
473
474         return atomic_notifier_chain_register(&port->n_head, &cl->nb);
475 }
476 EXPORT_SYMBOL_GPL(hsi_register_port_event);
477
478 /**
479  * hsi_unregister_port_event - Stop receiving port events for a client
480  * @cl: HSI client that wants to stop receiving port events
481  *
482  * Clients should call this function before releasing their associated
483  * port.
484  *
485  * Returns -errno on error, or 0 on success.
486  */
487 int hsi_unregister_port_event(struct hsi_client *cl)
488 {
489         struct hsi_port *port = hsi_get_port(cl);
490         int err;
491
492         WARN_ON(!hsi_port_claimed(cl));
493
494         err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
495         if (!err)
496                 cl->ehandler = NULL;
497
498         return err;
499 }
500 EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
501
502 /**
503  * hsi_event -Notifies clients about port events
504  * @port: Port where the event occurred
505  * @event: The event type
506  *
507  * Clients should not be concerned about wake line behavior. However, due
508  * to a race condition in HSI HW protocol, clients need to be notified
509  * about wake line changes, so they can implement a workaround for it.
510  *
511  * Events:
512  * HSI_EVENT_START_RX - Incoming wake line high
513  * HSI_EVENT_STOP_RX - Incoming wake line down
514  *
515  * Returns -errno on error, or 0 on success.
516  */
517 int hsi_event(struct hsi_port *port, unsigned long event)
518 {
519         return atomic_notifier_call_chain(&port->n_head, event, NULL);
520 }
521 EXPORT_SYMBOL_GPL(hsi_event);
522
523 /**
524  * hsi_get_channel_id_by_name - acquire channel id by channel name
525  * @cl: HSI client, which uses the channel
526  * @name: name the channel is known under
527  *
528  * Clients can call this function to get the hsi channel ids similar to
529  * requesting IRQs or GPIOs by name. This function assumes the same
530  * channel configuration is used for RX and TX.
531  *
532  * Returns -errno on error or channel id on success.
533  */
534 int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)
535 {
536         int i;
537
538         if (!cl->rx_cfg.channels)
539                 return -ENOENT;
540
541         for (i = 0; i < cl->rx_cfg.num_channels; i++)
542                 if (!strcmp(cl->rx_cfg.channels[i].name, name))
543                         return cl->rx_cfg.channels[i].id;
544
545         return -ENXIO;
546 }
547 EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name);
548
549 static int __init hsi_init(void)
550 {
551         return bus_register(&hsi_bus_type);
552 }
553 postcore_initcall(hsi_init);
554
555 static void __exit hsi_exit(void)
556 {
557         bus_unregister(&hsi_bus_type);
558 }
559 module_exit(hsi_exit);
560
561 MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
562 MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
563 MODULE_LICENSE("GPL v2");