1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org> |
4 | * |
5 | * Based on drivers/spmi/spmi.c: |
6 | * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. |
7 | */ |
8 | |
9 | #include <linux/acpi.h> |
10 | #include <linux/errno.h> |
11 | #include <linux/idr.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> |
14 | #include <linux/of.h> |
15 | #include <linux/of_device.h> |
16 | #include <linux/pm_domain.h> |
17 | #include <linux/pm_runtime.h> |
18 | #include <linux/property.h> |
19 | #include <linux/sched.h> |
20 | #include <linux/serdev.h> |
21 | #include <linux/slab.h> |
22 | |
23 | #include <linux/platform_data/x86/apple.h> |
24 | |
25 | static bool is_registered; |
26 | static DEFINE_IDA(ctrl_ida); |
27 | |
28 | static ssize_t modalias_show(struct device *dev, |
29 | struct device_attribute *attr, char *buf) |
30 | { |
31 | int len; |
32 | |
33 | len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); |
34 | if (len != -ENODEV) |
35 | return len; |
36 | |
37 | return of_device_modalias(dev, str: buf, PAGE_SIZE); |
38 | } |
39 | static DEVICE_ATTR_RO(modalias); |
40 | |
41 | static struct attribute *serdev_device_attrs[] = { |
42 | &dev_attr_modalias.attr, |
43 | NULL, |
44 | }; |
45 | ATTRIBUTE_GROUPS(serdev_device); |
46 | |
47 | static int serdev_device_uevent(const struct device *dev, struct kobj_uevent_env *env) |
48 | { |
49 | int rc; |
50 | |
51 | /* TODO: platform modalias */ |
52 | |
53 | rc = acpi_device_uevent_modalias(dev, env); |
54 | if (rc != -ENODEV) |
55 | return rc; |
56 | |
57 | return of_device_uevent_modalias(dev, env); |
58 | } |
59 | |
60 | static void serdev_device_release(struct device *dev) |
61 | { |
62 | struct serdev_device *serdev = to_serdev_device(d: dev); |
63 | kfree(objp: serdev); |
64 | } |
65 | |
66 | static const struct device_type serdev_device_type = { |
67 | .groups = serdev_device_groups, |
68 | .uevent = serdev_device_uevent, |
69 | .release = serdev_device_release, |
70 | }; |
71 | |
72 | static bool is_serdev_device(const struct device *dev) |
73 | { |
74 | return dev->type == &serdev_device_type; |
75 | } |
76 | |
77 | static void serdev_ctrl_release(struct device *dev) |
78 | { |
79 | struct serdev_controller *ctrl = to_serdev_controller(d: dev); |
80 | ida_simple_remove(&ctrl_ida, ctrl->nr); |
81 | kfree(objp: ctrl); |
82 | } |
83 | |
84 | static const struct device_type serdev_ctrl_type = { |
85 | .release = serdev_ctrl_release, |
86 | }; |
87 | |
88 | static int serdev_device_match(struct device *dev, struct device_driver *drv) |
89 | { |
90 | if (!is_serdev_device(dev)) |
91 | return 0; |
92 | |
93 | /* TODO: platform matching */ |
94 | if (acpi_driver_match_device(dev, drv)) |
95 | return 1; |
96 | |
97 | return of_driver_match_device(dev, drv); |
98 | } |
99 | |
100 | /** |
101 | * serdev_device_add() - add a device previously constructed via serdev_device_alloc() |
102 | * @serdev: serdev_device to be added |
103 | */ |
104 | int serdev_device_add(struct serdev_device *serdev) |
105 | { |
106 | struct serdev_controller *ctrl = serdev->ctrl; |
107 | struct device *parent = serdev->dev.parent; |
108 | int err; |
109 | |
110 | dev_set_name(dev: &serdev->dev, name: "%s-%d" , dev_name(dev: parent), serdev->nr); |
111 | |
112 | /* Only a single slave device is currently supported. */ |
113 | if (ctrl->serdev) { |
114 | dev_err(&serdev->dev, "controller busy\n" ); |
115 | return -EBUSY; |
116 | } |
117 | ctrl->serdev = serdev; |
118 | |
119 | err = device_add(dev: &serdev->dev); |
120 | if (err < 0) { |
121 | dev_err(&serdev->dev, "Can't add %s, status %pe\n" , |
122 | dev_name(&serdev->dev), ERR_PTR(err)); |
123 | goto err_clear_serdev; |
124 | } |
125 | |
126 | dev_dbg(&serdev->dev, "device %s registered\n" , dev_name(&serdev->dev)); |
127 | |
128 | return 0; |
129 | |
130 | err_clear_serdev: |
131 | ctrl->serdev = NULL; |
132 | return err; |
133 | } |
134 | EXPORT_SYMBOL_GPL(serdev_device_add); |
135 | |
136 | /** |
137 | * serdev_device_remove(): remove an serdev device |
138 | * @serdev: serdev_device to be removed |
139 | */ |
140 | void serdev_device_remove(struct serdev_device *serdev) |
141 | { |
142 | struct serdev_controller *ctrl = serdev->ctrl; |
143 | |
144 | device_unregister(dev: &serdev->dev); |
145 | ctrl->serdev = NULL; |
146 | } |
147 | EXPORT_SYMBOL_GPL(serdev_device_remove); |
148 | |
149 | int serdev_device_open(struct serdev_device *serdev) |
150 | { |
151 | struct serdev_controller *ctrl = serdev->ctrl; |
152 | int ret; |
153 | |
154 | if (!ctrl || !ctrl->ops->open) |
155 | return -EINVAL; |
156 | |
157 | ret = ctrl->ops->open(ctrl); |
158 | if (ret) |
159 | return ret; |
160 | |
161 | ret = pm_runtime_get_sync(dev: &ctrl->dev); |
162 | if (ret < 0) { |
163 | pm_runtime_put_noidle(dev: &ctrl->dev); |
164 | goto err_close; |
165 | } |
166 | |
167 | return 0; |
168 | |
169 | err_close: |
170 | if (ctrl->ops->close) |
171 | ctrl->ops->close(ctrl); |
172 | |
173 | return ret; |
174 | } |
175 | EXPORT_SYMBOL_GPL(serdev_device_open); |
176 | |
177 | void serdev_device_close(struct serdev_device *serdev) |
178 | { |
179 | struct serdev_controller *ctrl = serdev->ctrl; |
180 | |
181 | if (!ctrl || !ctrl->ops->close) |
182 | return; |
183 | |
184 | pm_runtime_put(dev: &ctrl->dev); |
185 | |
186 | ctrl->ops->close(ctrl); |
187 | } |
188 | EXPORT_SYMBOL_GPL(serdev_device_close); |
189 | |
190 | static void devm_serdev_device_close(void *serdev) |
191 | { |
192 | serdev_device_close(serdev); |
193 | } |
194 | |
195 | int devm_serdev_device_open(struct device *dev, struct serdev_device *serdev) |
196 | { |
197 | int ret; |
198 | |
199 | ret = serdev_device_open(serdev); |
200 | if (ret) |
201 | return ret; |
202 | |
203 | return devm_add_action_or_reset(dev, devm_serdev_device_close, serdev); |
204 | } |
205 | EXPORT_SYMBOL_GPL(devm_serdev_device_open); |
206 | |
207 | void serdev_device_write_wakeup(struct serdev_device *serdev) |
208 | { |
209 | complete(&serdev->write_comp); |
210 | } |
211 | EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); |
212 | |
213 | /** |
214 | * serdev_device_write_buf() - write data asynchronously |
215 | * @serdev: serdev device |
216 | * @buf: data to be written |
217 | * @count: number of bytes to write |
218 | * |
219 | * Write data to the device asynchronously. |
220 | * |
221 | * Note that any accepted data has only been buffered by the controller; use |
222 | * serdev_device_wait_until_sent() to make sure the controller write buffer |
223 | * has actually been emptied. |
224 | * |
225 | * Return: The number of bytes written (less than count if not enough room in |
226 | * the write buffer), or a negative errno on errors. |
227 | */ |
228 | int serdev_device_write_buf(struct serdev_device *serdev, |
229 | const unsigned char *buf, size_t count) |
230 | { |
231 | struct serdev_controller *ctrl = serdev->ctrl; |
232 | |
233 | if (!ctrl || !ctrl->ops->write_buf) |
234 | return -EINVAL; |
235 | |
236 | return ctrl->ops->write_buf(ctrl, buf, count); |
237 | } |
238 | EXPORT_SYMBOL_GPL(serdev_device_write_buf); |
239 | |
240 | /** |
241 | * serdev_device_write() - write data synchronously |
242 | * @serdev: serdev device |
243 | * @buf: data to be written |
244 | * @count: number of bytes to write |
245 | * @timeout: timeout in jiffies, or 0 to wait indefinitely |
246 | * |
247 | * Write data to the device synchronously by repeatedly calling |
248 | * serdev_device_write() until the controller has accepted all data (unless |
249 | * interrupted by a timeout or a signal). |
250 | * |
251 | * Note that any accepted data has only been buffered by the controller; use |
252 | * serdev_device_wait_until_sent() to make sure the controller write buffer |
253 | * has actually been emptied. |
254 | * |
255 | * Note that this function depends on serdev_device_write_wakeup() being |
256 | * called in the serdev driver write_wakeup() callback. |
257 | * |
258 | * Return: The number of bytes written (less than count if interrupted), |
259 | * -ETIMEDOUT or -ERESTARTSYS if interrupted before any bytes were written, or |
260 | * a negative errno on errors. |
261 | */ |
262 | int serdev_device_write(struct serdev_device *serdev, |
263 | const unsigned char *buf, size_t count, |
264 | long timeout) |
265 | { |
266 | struct serdev_controller *ctrl = serdev->ctrl; |
267 | int written = 0; |
268 | int ret; |
269 | |
270 | if (!ctrl || !ctrl->ops->write_buf || !serdev->ops->write_wakeup) |
271 | return -EINVAL; |
272 | |
273 | if (timeout == 0) |
274 | timeout = MAX_SCHEDULE_TIMEOUT; |
275 | |
276 | mutex_lock(&serdev->write_lock); |
277 | do { |
278 | reinit_completion(x: &serdev->write_comp); |
279 | |
280 | ret = ctrl->ops->write_buf(ctrl, buf, count); |
281 | if (ret < 0) |
282 | break; |
283 | |
284 | written += ret; |
285 | buf += ret; |
286 | count -= ret; |
287 | |
288 | if (count == 0) |
289 | break; |
290 | |
291 | timeout = wait_for_completion_interruptible_timeout(x: &serdev->write_comp, |
292 | timeout); |
293 | } while (timeout > 0); |
294 | mutex_unlock(lock: &serdev->write_lock); |
295 | |
296 | if (ret < 0) |
297 | return ret; |
298 | |
299 | if (timeout <= 0 && written == 0) { |
300 | if (timeout == -ERESTARTSYS) |
301 | return -ERESTARTSYS; |
302 | else |
303 | return -ETIMEDOUT; |
304 | } |
305 | |
306 | return written; |
307 | } |
308 | EXPORT_SYMBOL_GPL(serdev_device_write); |
309 | |
310 | void serdev_device_write_flush(struct serdev_device *serdev) |
311 | { |
312 | struct serdev_controller *ctrl = serdev->ctrl; |
313 | |
314 | if (!ctrl || !ctrl->ops->write_flush) |
315 | return; |
316 | |
317 | ctrl->ops->write_flush(ctrl); |
318 | } |
319 | EXPORT_SYMBOL_GPL(serdev_device_write_flush); |
320 | |
321 | int serdev_device_write_room(struct serdev_device *serdev) |
322 | { |
323 | struct serdev_controller *ctrl = serdev->ctrl; |
324 | |
325 | if (!ctrl || !ctrl->ops->write_room) |
326 | return 0; |
327 | |
328 | return serdev->ctrl->ops->write_room(ctrl); |
329 | } |
330 | EXPORT_SYMBOL_GPL(serdev_device_write_room); |
331 | |
332 | unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned int speed) |
333 | { |
334 | struct serdev_controller *ctrl = serdev->ctrl; |
335 | |
336 | if (!ctrl || !ctrl->ops->set_baudrate) |
337 | return 0; |
338 | |
339 | return ctrl->ops->set_baudrate(ctrl, speed); |
340 | |
341 | } |
342 | EXPORT_SYMBOL_GPL(serdev_device_set_baudrate); |
343 | |
344 | void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable) |
345 | { |
346 | struct serdev_controller *ctrl = serdev->ctrl; |
347 | |
348 | if (!ctrl || !ctrl->ops->set_flow_control) |
349 | return; |
350 | |
351 | ctrl->ops->set_flow_control(ctrl, enable); |
352 | } |
353 | EXPORT_SYMBOL_GPL(serdev_device_set_flow_control); |
354 | |
355 | int serdev_device_set_parity(struct serdev_device *serdev, |
356 | enum serdev_parity parity) |
357 | { |
358 | struct serdev_controller *ctrl = serdev->ctrl; |
359 | |
360 | if (!ctrl || !ctrl->ops->set_parity) |
361 | return -EOPNOTSUPP; |
362 | |
363 | return ctrl->ops->set_parity(ctrl, parity); |
364 | } |
365 | EXPORT_SYMBOL_GPL(serdev_device_set_parity); |
366 | |
367 | void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout) |
368 | { |
369 | struct serdev_controller *ctrl = serdev->ctrl; |
370 | |
371 | if (!ctrl || !ctrl->ops->wait_until_sent) |
372 | return; |
373 | |
374 | ctrl->ops->wait_until_sent(ctrl, timeout); |
375 | } |
376 | EXPORT_SYMBOL_GPL(serdev_device_wait_until_sent); |
377 | |
378 | int serdev_device_get_tiocm(struct serdev_device *serdev) |
379 | { |
380 | struct serdev_controller *ctrl = serdev->ctrl; |
381 | |
382 | if (!ctrl || !ctrl->ops->get_tiocm) |
383 | return -EOPNOTSUPP; |
384 | |
385 | return ctrl->ops->get_tiocm(ctrl); |
386 | } |
387 | EXPORT_SYMBOL_GPL(serdev_device_get_tiocm); |
388 | |
389 | int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear) |
390 | { |
391 | struct serdev_controller *ctrl = serdev->ctrl; |
392 | |
393 | if (!ctrl || !ctrl->ops->set_tiocm) |
394 | return -EOPNOTSUPP; |
395 | |
396 | return ctrl->ops->set_tiocm(ctrl, set, clear); |
397 | } |
398 | EXPORT_SYMBOL_GPL(serdev_device_set_tiocm); |
399 | |
400 | int serdev_device_break_ctl(struct serdev_device *serdev, int break_state) |
401 | { |
402 | struct serdev_controller *ctrl = serdev->ctrl; |
403 | |
404 | if (!ctrl || !ctrl->ops->break_ctl) |
405 | return -EOPNOTSUPP; |
406 | |
407 | return ctrl->ops->break_ctl(ctrl, break_state); |
408 | } |
409 | EXPORT_SYMBOL_GPL(serdev_device_break_ctl); |
410 | |
411 | static int serdev_drv_probe(struct device *dev) |
412 | { |
413 | const struct serdev_device_driver *sdrv = to_serdev_device_driver(d: dev->driver); |
414 | int ret; |
415 | |
416 | ret = dev_pm_domain_attach(dev, power_on: true); |
417 | if (ret) |
418 | return ret; |
419 | |
420 | ret = sdrv->probe(to_serdev_device(d: dev)); |
421 | if (ret) |
422 | dev_pm_domain_detach(dev, power_off: true); |
423 | |
424 | return ret; |
425 | } |
426 | |
427 | static void serdev_drv_remove(struct device *dev) |
428 | { |
429 | const struct serdev_device_driver *sdrv = to_serdev_device_driver(d: dev->driver); |
430 | if (sdrv->remove) |
431 | sdrv->remove(to_serdev_device(d: dev)); |
432 | |
433 | dev_pm_domain_detach(dev, power_off: true); |
434 | } |
435 | |
436 | static struct bus_type serdev_bus_type = { |
437 | .name = "serial" , |
438 | .match = serdev_device_match, |
439 | .probe = serdev_drv_probe, |
440 | .remove = serdev_drv_remove, |
441 | }; |
442 | |
443 | /** |
444 | * serdev_device_alloc() - Allocate a new serdev device |
445 | * @ctrl: associated controller |
446 | * |
447 | * Caller is responsible for either calling serdev_device_add() to add the |
448 | * newly allocated controller, or calling serdev_device_put() to discard it. |
449 | */ |
450 | struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl) |
451 | { |
452 | struct serdev_device *serdev; |
453 | |
454 | serdev = kzalloc(size: sizeof(*serdev), GFP_KERNEL); |
455 | if (!serdev) |
456 | return NULL; |
457 | |
458 | serdev->ctrl = ctrl; |
459 | device_initialize(dev: &serdev->dev); |
460 | serdev->dev.parent = &ctrl->dev; |
461 | serdev->dev.bus = &serdev_bus_type; |
462 | serdev->dev.type = &serdev_device_type; |
463 | init_completion(x: &serdev->write_comp); |
464 | mutex_init(&serdev->write_lock); |
465 | return serdev; |
466 | } |
467 | EXPORT_SYMBOL_GPL(serdev_device_alloc); |
468 | |
469 | /** |
470 | * serdev_controller_alloc() - Allocate a new serdev controller |
471 | * @parent: parent device |
472 | * @size: size of private data |
473 | * |
474 | * Caller is responsible for either calling serdev_controller_add() to add the |
475 | * newly allocated controller, or calling serdev_controller_put() to discard it. |
476 | * The allocated private data region may be accessed via |
477 | * serdev_controller_get_drvdata() |
478 | */ |
479 | struct serdev_controller *serdev_controller_alloc(struct device *parent, |
480 | size_t size) |
481 | { |
482 | struct serdev_controller *ctrl; |
483 | int id; |
484 | |
485 | if (WARN_ON(!parent)) |
486 | return NULL; |
487 | |
488 | ctrl = kzalloc(size: sizeof(*ctrl) + size, GFP_KERNEL); |
489 | if (!ctrl) |
490 | return NULL; |
491 | |
492 | id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); |
493 | if (id < 0) { |
494 | dev_err(parent, |
495 | "unable to allocate serdev controller identifier.\n" ); |
496 | goto err_free; |
497 | } |
498 | |
499 | ctrl->nr = id; |
500 | |
501 | device_initialize(dev: &ctrl->dev); |
502 | ctrl->dev.type = &serdev_ctrl_type; |
503 | ctrl->dev.bus = &serdev_bus_type; |
504 | ctrl->dev.parent = parent; |
505 | device_set_node(dev: &ctrl->dev, dev_fwnode(parent)); |
506 | serdev_controller_set_drvdata(ctrl, data: &ctrl[1]); |
507 | |
508 | dev_set_name(dev: &ctrl->dev, name: "serial%d" , id); |
509 | |
510 | pm_runtime_no_callbacks(dev: &ctrl->dev); |
511 | pm_suspend_ignore_children(dev: &ctrl->dev, enable: true); |
512 | |
513 | dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n" , ctrl, id); |
514 | return ctrl; |
515 | |
516 | err_free: |
517 | kfree(objp: ctrl); |
518 | |
519 | return NULL; |
520 | } |
521 | EXPORT_SYMBOL_GPL(serdev_controller_alloc); |
522 | |
523 | static int of_serdev_register_devices(struct serdev_controller *ctrl) |
524 | { |
525 | struct device_node *node; |
526 | struct serdev_device *serdev = NULL; |
527 | int err; |
528 | bool found = false; |
529 | |
530 | for_each_available_child_of_node(ctrl->dev.of_node, node) { |
531 | if (!of_get_property(node, name: "compatible" , NULL)) |
532 | continue; |
533 | |
534 | dev_dbg(&ctrl->dev, "adding child %pOF\n" , node); |
535 | |
536 | serdev = serdev_device_alloc(ctrl); |
537 | if (!serdev) |
538 | continue; |
539 | |
540 | device_set_node(dev: &serdev->dev, of_fwnode_handle(node)); |
541 | |
542 | err = serdev_device_add(serdev); |
543 | if (err) { |
544 | dev_err(&serdev->dev, |
545 | "failure adding device. status %pe\n" , |
546 | ERR_PTR(err)); |
547 | serdev_device_put(serdev); |
548 | } else |
549 | found = true; |
550 | } |
551 | if (!found) |
552 | return -ENODEV; |
553 | |
554 | return 0; |
555 | } |
556 | |
557 | #ifdef CONFIG_ACPI |
558 | |
559 | #define SERDEV_ACPI_MAX_SCAN_DEPTH 32 |
560 | |
561 | struct acpi_serdev_lookup { |
562 | acpi_handle device_handle; |
563 | acpi_handle controller_handle; |
564 | int n; |
565 | int index; |
566 | }; |
567 | |
568 | /** |
569 | * serdev_acpi_get_uart_resource - Gets UARTSerialBus resource if type matches |
570 | * @ares: ACPI resource |
571 | * @uart: Pointer to UARTSerialBus resource will be returned here |
572 | * |
573 | * Checks if the given ACPI resource is of type UARTSerialBus. |
574 | * In this case, returns a pointer to it to the caller. |
575 | * |
576 | * Return: True if resource type is of UARTSerialBus, otherwise false. |
577 | */ |
578 | bool serdev_acpi_get_uart_resource(struct acpi_resource *ares, |
579 | struct acpi_resource_uart_serialbus **uart) |
580 | { |
581 | struct acpi_resource_uart_serialbus *sb; |
582 | |
583 | if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) |
584 | return false; |
585 | |
586 | sb = &ares->data.uart_serial_bus; |
587 | if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_UART) |
588 | return false; |
589 | |
590 | *uart = sb; |
591 | return true; |
592 | } |
593 | EXPORT_SYMBOL_GPL(serdev_acpi_get_uart_resource); |
594 | |
595 | static int acpi_serdev_parse_resource(struct acpi_resource *ares, void *data) |
596 | { |
597 | struct acpi_serdev_lookup *lookup = data; |
598 | struct acpi_resource_uart_serialbus *sb; |
599 | acpi_status status; |
600 | |
601 | if (!serdev_acpi_get_uart_resource(ares, &sb)) |
602 | return 1; |
603 | |
604 | if (lookup->index != -1 && lookup->n++ != lookup->index) |
605 | return 1; |
606 | |
607 | status = acpi_get_handle(parent: lookup->device_handle, |
608 | pathname: sb->resource_source.string_ptr, |
609 | ret_handle: &lookup->controller_handle); |
610 | if (ACPI_FAILURE(status)) |
611 | return 1; |
612 | |
613 | /* |
614 | * NOTE: Ideally, we would also want to retrieve other properties here, |
615 | * once setting them before opening the device is supported by serdev. |
616 | */ |
617 | |
618 | return 1; |
619 | } |
620 | |
621 | static int acpi_serdev_do_lookup(struct acpi_device *adev, |
622 | struct acpi_serdev_lookup *lookup) |
623 | { |
624 | struct list_head resource_list; |
625 | int ret; |
626 | |
627 | lookup->device_handle = acpi_device_handle(adev); |
628 | lookup->controller_handle = NULL; |
629 | lookup->n = 0; |
630 | |
631 | INIT_LIST_HEAD(list: &resource_list); |
632 | ret = acpi_dev_get_resources(adev, list: &resource_list, |
633 | preproc: acpi_serdev_parse_resource, preproc_data: lookup); |
634 | acpi_dev_free_resource_list(list: &resource_list); |
635 | |
636 | if (ret < 0) |
637 | return -EINVAL; |
638 | |
639 | return 0; |
640 | } |
641 | |
642 | static int acpi_serdev_check_resources(struct serdev_controller *ctrl, |
643 | struct acpi_device *adev) |
644 | { |
645 | struct acpi_serdev_lookup lookup; |
646 | int ret; |
647 | |
648 | if (acpi_bus_get_status(device: adev) || !adev->status.present) |
649 | return -EINVAL; |
650 | |
651 | /* Look for UARTSerialBusV2 resource */ |
652 | lookup.index = -1; // we only care for the last device |
653 | |
654 | ret = acpi_serdev_do_lookup(adev, lookup: &lookup); |
655 | if (ret) |
656 | return ret; |
657 | |
658 | /* |
659 | * Apple machines provide an empty resource template, so on those |
660 | * machines just look for immediate children with a "baud" property |
661 | * (from the _DSM method) instead. |
662 | */ |
663 | if (!lookup.controller_handle && x86_apple_machine && |
664 | !acpi_dev_get_property(adev, name: "baud" , ACPI_TYPE_BUFFER, NULL)) |
665 | acpi_get_parent(object: adev->handle, out_handle: &lookup.controller_handle); |
666 | |
667 | /* Make sure controller and ResourceSource handle match */ |
668 | if (!device_match_acpi_handle(dev: ctrl->dev.parent, handle: lookup.controller_handle)) |
669 | return -ENODEV; |
670 | |
671 | return 0; |
672 | } |
673 | |
674 | static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl, |
675 | struct acpi_device *adev) |
676 | { |
677 | struct serdev_device *serdev; |
678 | int err; |
679 | |
680 | serdev = serdev_device_alloc(ctrl); |
681 | if (!serdev) { |
682 | dev_err(&ctrl->dev, "failed to allocate serdev device for %s\n" , |
683 | dev_name(&adev->dev)); |
684 | return AE_NO_MEMORY; |
685 | } |
686 | |
687 | ACPI_COMPANION_SET(&serdev->dev, adev); |
688 | acpi_device_set_enumerated(adev); |
689 | |
690 | err = serdev_device_add(serdev); |
691 | if (err) { |
692 | dev_err(&serdev->dev, |
693 | "failure adding ACPI serdev device. status %pe\n" , |
694 | ERR_PTR(err)); |
695 | serdev_device_put(serdev); |
696 | } |
697 | |
698 | return AE_OK; |
699 | } |
700 | |
701 | static const struct acpi_device_id serdev_acpi_devices_blacklist[] = { |
702 | { "INT3511" , 0 }, |
703 | { "INT3512" , 0 }, |
704 | { }, |
705 | }; |
706 | |
707 | static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level, |
708 | void *data, void **return_value) |
709 | { |
710 | struct acpi_device *adev = acpi_fetch_acpi_dev(handle); |
711 | struct serdev_controller *ctrl = data; |
712 | |
713 | if (!adev || acpi_device_enumerated(adev)) |
714 | return AE_OK; |
715 | |
716 | /* Skip if black listed */ |
717 | if (!acpi_match_device_ids(device: adev, ids: serdev_acpi_devices_blacklist)) |
718 | return AE_OK; |
719 | |
720 | if (acpi_serdev_check_resources(ctrl, adev)) |
721 | return AE_OK; |
722 | |
723 | return acpi_serdev_register_device(ctrl, adev); |
724 | } |
725 | |
726 | |
727 | static int acpi_serdev_register_devices(struct serdev_controller *ctrl) |
728 | { |
729 | acpi_status status; |
730 | bool skip; |
731 | int ret; |
732 | |
733 | if (!has_acpi_companion(dev: ctrl->dev.parent)) |
734 | return -ENODEV; |
735 | |
736 | /* |
737 | * Skip registration on boards where the ACPI tables are known to |
738 | * contain buggy devices. Note serdev_controller_add() must still |
739 | * succeed in this case, so that the proper serdev devices can be |
740 | * added "manually" later. |
741 | */ |
742 | ret = acpi_quirk_skip_serdev_enumeration(controller_parent: ctrl->dev.parent, skip: &skip); |
743 | if (ret) |
744 | return ret; |
745 | if (skip) |
746 | return 0; |
747 | |
748 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
749 | SERDEV_ACPI_MAX_SCAN_DEPTH, |
750 | descending_callback: acpi_serdev_add_device, NULL, context: ctrl, NULL); |
751 | if (ACPI_FAILURE(status)) |
752 | dev_warn(&ctrl->dev, "failed to enumerate serdev slaves\n" ); |
753 | |
754 | if (!ctrl->serdev) |
755 | return -ENODEV; |
756 | |
757 | return 0; |
758 | } |
759 | #else |
760 | static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl) |
761 | { |
762 | return -ENODEV; |
763 | } |
764 | #endif /* CONFIG_ACPI */ |
765 | |
766 | /** |
767 | * serdev_controller_add() - Add an serdev controller |
768 | * @ctrl: controller to be registered. |
769 | * |
770 | * Register a controller previously allocated via serdev_controller_alloc() with |
771 | * the serdev core. |
772 | */ |
773 | int serdev_controller_add(struct serdev_controller *ctrl) |
774 | { |
775 | int ret_of, ret_acpi, ret; |
776 | |
777 | /* Can't register until after driver model init */ |
778 | if (WARN_ON(!is_registered)) |
779 | return -EAGAIN; |
780 | |
781 | ret = device_add(dev: &ctrl->dev); |
782 | if (ret) |
783 | return ret; |
784 | |
785 | pm_runtime_enable(dev: &ctrl->dev); |
786 | |
787 | ret_of = of_serdev_register_devices(ctrl); |
788 | ret_acpi = acpi_serdev_register_devices(ctrl); |
789 | if (ret_of && ret_acpi) { |
790 | dev_dbg(&ctrl->dev, "no devices registered: of:%pe acpi:%pe\n" , |
791 | ERR_PTR(ret_of), ERR_PTR(ret_acpi)); |
792 | ret = -ENODEV; |
793 | goto err_rpm_disable; |
794 | } |
795 | |
796 | dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n" , |
797 | ctrl->nr, &ctrl->dev); |
798 | return 0; |
799 | |
800 | err_rpm_disable: |
801 | pm_runtime_disable(dev: &ctrl->dev); |
802 | device_del(dev: &ctrl->dev); |
803 | return ret; |
804 | }; |
805 | EXPORT_SYMBOL_GPL(serdev_controller_add); |
806 | |
807 | /* Remove a device associated with a controller */ |
808 | static int serdev_remove_device(struct device *dev, void *data) |
809 | { |
810 | struct serdev_device *serdev = to_serdev_device(d: dev); |
811 | if (dev->type == &serdev_device_type) |
812 | serdev_device_remove(serdev); |
813 | return 0; |
814 | } |
815 | |
816 | /** |
817 | * serdev_controller_remove(): remove an serdev controller |
818 | * @ctrl: controller to remove |
819 | * |
820 | * Remove a serdev controller. Caller is responsible for calling |
821 | * serdev_controller_put() to discard the allocated controller. |
822 | */ |
823 | void serdev_controller_remove(struct serdev_controller *ctrl) |
824 | { |
825 | if (!ctrl) |
826 | return; |
827 | |
828 | device_for_each_child(dev: &ctrl->dev, NULL, fn: serdev_remove_device); |
829 | pm_runtime_disable(dev: &ctrl->dev); |
830 | device_del(dev: &ctrl->dev); |
831 | } |
832 | EXPORT_SYMBOL_GPL(serdev_controller_remove); |
833 | |
834 | /** |
835 | * __serdev_device_driver_register() - Register client driver with serdev core |
836 | * @sdrv: client driver to be associated with client-device. |
837 | * @owner: client driver owner to set. |
838 | * |
839 | * This API will register the client driver with the serdev framework. |
840 | * It is typically called from the driver's module-init function. |
841 | */ |
842 | int __serdev_device_driver_register(struct serdev_device_driver *sdrv, struct module *owner) |
843 | { |
844 | sdrv->driver.bus = &serdev_bus_type; |
845 | sdrv->driver.owner = owner; |
846 | |
847 | /* force drivers to async probe so I/O is possible in probe */ |
848 | sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS; |
849 | |
850 | return driver_register(drv: &sdrv->driver); |
851 | } |
852 | EXPORT_SYMBOL_GPL(__serdev_device_driver_register); |
853 | |
854 | static void __exit serdev_exit(void) |
855 | { |
856 | bus_unregister(bus: &serdev_bus_type); |
857 | ida_destroy(ida: &ctrl_ida); |
858 | } |
859 | module_exit(serdev_exit); |
860 | |
861 | static int __init serdev_init(void) |
862 | { |
863 | int ret; |
864 | |
865 | ret = bus_register(bus: &serdev_bus_type); |
866 | if (ret) |
867 | return ret; |
868 | |
869 | is_registered = true; |
870 | return 0; |
871 | } |
872 | /* Must be before serial drivers register */ |
873 | postcore_initcall(serdev_init); |
874 | |
875 | MODULE_AUTHOR("Rob Herring <robh@kernel.org>" ); |
876 | MODULE_LICENSE("GPL v2" ); |
877 | MODULE_DESCRIPTION("Serial attached device bus" ); |
878 | |