Lines Matching +full:gpio +full:- +full:ctrl

1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
11 #include <linux/gpio/consumer.h>
38 /* -- Safe counters. -------------------------------------------------------- */
41 * ssh_seq_reset() - Reset/initialize sequence ID counter.
46 WRITE_ONCE(c->value, 0); in ssh_seq_reset()
50 * ssh_seq_next() - Get next sequence ID.
57 u8 old = READ_ONCE(c->value); in ssh_seq_next()
61 while (unlikely((ret = cmpxchg(&c->value, old, new)) != old)) { in ssh_seq_next()
70 * ssh_rqid_reset() - Reset/initialize request ID counter.
75 WRITE_ONCE(c->value, 0); in ssh_rqid_reset()
79 * ssh_rqid_next() - Get next request ID.
87 u16 old = READ_ONCE(c->value); in ssh_rqid_next()
91 while (unlikely((ret = cmpxchg(&c->value, old, new)) != old)) { in ssh_rqid_next()
100 /* -- Event notifier/callbacks. --------------------------------------------- */
111 * ssam_event_matches_notifier() - Test if an event matches a notifier.
121 bool match = n->event.id.target_category == event->target_category; in ssam_event_matches_notifier()
123 if (n->event.mask & SSAM_EVENT_MASK_TARGET) in ssam_event_matches_notifier()
124 match &= n->event.reg.target_id == event->target_id; in ssam_event_matches_notifier()
126 if (n->event.mask & SSAM_EVENT_MASK_INSTANCE) in ssam_event_matches_notifier()
127 match &= n->event.id.instance == event->instance_id; in ssam_event_matches_notifier()
133 * ssam_nfblk_call_chain() - Call event notifier callbacks of the given chain.
140 * ssam_notifier_from_errno() on any non-zero error value.
153 idx = srcu_read_lock(&nh->srcu); in ssam_nfblk_call_chain()
155 list_for_each_entry_rcu(nf, &nh->head, base.node, in ssam_nfblk_call_chain()
156 srcu_read_lock_held(&nh->srcu)) { in ssam_nfblk_call_chain()
158 ret = (ret & SSAM_NOTIF_STATE_MASK) | nf->base.fn(nf, event); in ssam_nfblk_call_chain()
164 srcu_read_unlock(&nh->srcu, idx); in ssam_nfblk_call_chain()
169 * ssam_nfblk_insert() - Insert a new notifier block into the given notifier
177 * Return: Returns zero on success, %-EEXIST if the notifier block has already
186 list_for_each(h, &nh->head) { in ssam_nfblk_insert()
191 return -EEXIST; in ssam_nfblk_insert()
194 if (nb->priority > p->priority) in ssam_nfblk_insert()
198 list_add_tail_rcu(&nb->node, h); in ssam_nfblk_insert()
203 * ssam_nfblk_find() - Check if a notifier block is registered on the given
220 list_for_each_entry(p, &nh->head, node) { in ssam_nfblk_find()
229 * ssam_nfblk_remove() - Remove a notifier block from its notifier list.
235 * synchronize_srcu() with ``nh->srcu`` after leaving the critical section, to
240 list_del_rcu(&nb->node); in ssam_nfblk_remove()
244 * ssam_nf_head_init() - Initialize the given notifier head.
251 status = init_srcu_struct(&nh->srcu); in ssam_nf_head_init()
255 INIT_LIST_HEAD(&nh->head); in ssam_nf_head_init()
260 * ssam_nf_head_destroy() - Deinitialize the given notifier head.
265 cleanup_srcu_struct(&nh->srcu); in ssam_nf_head_destroy()
269 /* -- Event/notification registry. ------------------------------------------ */
272 * struct ssam_nf_refcount_key - Key used for event activation reference
283 * struct ssam_nf_refcount_entry - RB-tree entry for reference counting event
285 * @node: The node of this entry in the rb-tree.
287 * @refcount: The reference-count of the event.
298 * ssam_nf_refcount_inc() - Increment reference-/activation-count of the given
304 * Increments the reference-/activation-count associated with the specified
308 * Note: ``nf->lock`` must be held when calling this function.
311 * with %-ENOSPC if there have already been %INT_MAX events of the specified
312 * ID and type registered, or %-ENOMEM if the entry could not be allocated.
320 struct rb_node **link = &nf->refcount.rb_node; in ssam_nf_refcount_inc()
324 lockdep_assert_held(&nf->lock); in ssam_nf_refcount_inc()
333 cmp = memcmp(&key, &entry->key, sizeof(key)); in ssam_nf_refcount_inc()
335 link = &(*link)->rb_left; in ssam_nf_refcount_inc()
337 link = &(*link)->rb_right; in ssam_nf_refcount_inc()
338 } else if (entry->refcount < INT_MAX) { in ssam_nf_refcount_inc()
339 entry->refcount++; in ssam_nf_refcount_inc()
343 return ERR_PTR(-ENOSPC); in ssam_nf_refcount_inc()
349 return ERR_PTR(-ENOMEM); in ssam_nf_refcount_inc()
351 entry->key = key; in ssam_nf_refcount_inc()
352 entry->refcount = 1; in ssam_nf_refcount_inc()
354 rb_link_node(&entry->node, parent, link); in ssam_nf_refcount_inc()
355 rb_insert_color(&entry->node, &nf->refcount); in ssam_nf_refcount_inc()
361 * ssam_nf_refcount_dec() - Decrement reference-/activation-count of the given
367 * Decrements the reference-/activation-count of the specified event,
371 * Note: ``nf->lock`` must be held when calling this function.
382 struct rb_node *node = nf->refcount.rb_node; in ssam_nf_refcount_dec()
385 lockdep_assert_held(&nf->lock); in ssam_nf_refcount_dec()
393 cmp = memcmp(&key, &entry->key, sizeof(key)); in ssam_nf_refcount_dec()
395 node = node->rb_left; in ssam_nf_refcount_dec()
397 node = node->rb_right; in ssam_nf_refcount_dec()
399 entry->refcount--; in ssam_nf_refcount_dec()
400 if (entry->refcount == 0) in ssam_nf_refcount_dec()
401 rb_erase(&entry->node, &nf->refcount); in ssam_nf_refcount_dec()
411 * ssam_nf_refcount_dec_free() - Decrement reference-/activation-count of the
417 * Decrements the reference-/activation-count of the specified event, freeing
420 * Note: ``nf->lock`` must be held when calling this function.
428 lockdep_assert_held(&nf->lock); in ssam_nf_refcount_dec_free()
431 if (entry && entry->refcount == 0) in ssam_nf_refcount_dec_free()
436 * ssam_nf_refcount_empty() - Test if the notification system has any
442 return RB_EMPTY_ROOT(&nf->refcount); in ssam_nf_refcount_empty()
446 * ssam_nf_call() - Call notification callbacks for the provided event.
454 * bit set. Note that this bit is set automatically when converting non-zero
475 nf_head = &nf->head[ssh_rqid_to_event(rqid)]; in ssam_nf_call()
482 status, event->target_category, event->target_id, in ssam_nf_call()
483 event->command_id, event->instance_id); in ssam_nf_call()
487 rqid, event->target_category, event->target_id, in ssam_nf_call()
488 event->command_id, event->instance_id); in ssam_nf_call()
493 * ssam_nf_init() - Initialize the notifier system.
501 status = ssam_nf_head_init(&nf->head[i]); in ssam_nf_init()
507 while (i--) in ssam_nf_init()
508 ssam_nf_head_destroy(&nf->head[i]); in ssam_nf_init()
513 mutex_init(&nf->lock); in ssam_nf_init()
518 * ssam_nf_destroy() - Deinitialize the notifier system.
526 ssam_nf_head_destroy(&nf->head[i]); in ssam_nf_destroy()
528 mutex_destroy(&nf->lock); in ssam_nf_destroy()
532 /* -- Event/async request completion system. -------------------------------- */
537 * SSAM_CPLT_WQ_BATCH - Maximum number of event item completions executed per
544 * SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN - Maximum payload length for a cached
556 * ssam_event_item_cache_init() - Initialize the event item cache.
567 return -ENOMEM; in ssam_event_item_cache_init()
574 * ssam_event_item_cache_destroy() - Deinitialize the event item cache.
593 * ssam_event_item_free() - Free the provided event item.
599 item->ops.free(item); in ssam_event_item_free()
603 * ssam_event_item_alloc() - Allocate an event item with the given payload size.
624 item->ops.free = __ssam_event_item_free_cached; in ssam_event_item_alloc()
630 item->ops.free = __ssam_event_item_free_generic; in ssam_event_item_alloc()
633 item->event.length = len; in ssam_event_item_alloc()
640 * ssam_event_queue_push() - Push an event item to the event queue.
647 spin_lock(&q->lock); in ssam_event_queue_push()
648 list_add_tail(&item->node, &q->head); in ssam_event_queue_push()
649 spin_unlock(&q->lock); in ssam_event_queue_push()
653 * ssam_event_queue_pop() - Pop the next event item from the event queue.
663 spin_lock(&q->lock); in ssam_event_queue_pop()
664 item = list_first_entry_or_null(&q->head, struct ssam_event_item, node); in ssam_event_queue_pop()
666 list_del(&item->node); in ssam_event_queue_pop()
667 spin_unlock(&q->lock); in ssam_event_queue_pop()
673 * ssam_event_queue_is_empty() - Check if the event queue is empty.
680 spin_lock(&q->lock); in ssam_event_queue_is_empty()
681 empty = list_empty(&q->head); in ssam_event_queue_is_empty()
682 spin_unlock(&q->lock); in ssam_event_queue_is_empty()
688 * ssam_cplt_get_event_queue() - Get the event queue for the given parameters.
706 dev_err(cplt->dev, "event: unsupported request ID: %#06x\n", rqid); in ssam_cplt_get_event_queue()
711 dev_warn(cplt->dev, "event: unsupported target ID: %u\n", tid); in ssam_cplt_get_event_queue()
715 return &cplt->event.target[tidx].queue[event]; in ssam_cplt_get_event_queue()
719 * ssam_cplt_submit() - Submit a work item to the completion system workqueue.
725 return queue_work(cplt->wq, work); in ssam_cplt_submit()
729 * ssam_cplt_submit_event() - Submit an event to the completion system.
737 * Return: Returns zero on success, %-EINVAL if there is no event queue that
745 evq = ssam_cplt_get_event_queue(cplt, item->event.target_id, item->rqid); in ssam_cplt_submit_event()
747 return -EINVAL; in ssam_cplt_submit_event()
750 ssam_cplt_submit(cplt, &evq->work); in ssam_cplt_submit_event()
755 * ssam_cplt_flush() - Flush the completion system.
763 * to-be-completed events, the event queue work function may re-schedule its
773 flush_workqueue(cplt->wq); in ssam_cplt_flush()
785 nf = &queue->cplt->event.notif; in ssam_event_queue_work_fn()
786 dev = queue->cplt->dev; in ssam_event_queue_work_fn()
794 ssam_nf_call(nf, dev, item->rqid, &item->event); in ssam_event_queue_work_fn()
796 } while (--iterations); in ssam_event_queue_work_fn()
799 ssam_cplt_submit(queue->cplt, &queue->work); in ssam_event_queue_work_fn()
803 * ssam_event_queue_init() - Initialize an event queue.
810 evq->cplt = cplt; in ssam_event_queue_init()
811 spin_lock_init(&evq->lock); in ssam_event_queue_init()
812 INIT_LIST_HEAD(&evq->head); in ssam_event_queue_init()
813 INIT_WORK(&evq->work, ssam_event_queue_work_fn); in ssam_event_queue_init()
817 * ssam_cplt_init() - Initialize completion system.
826 cplt->dev = dev; in ssam_cplt_init()
828 cplt->wq = alloc_workqueue(SSAM_CPLT_WQ_NAME, WQ_UNBOUND | WQ_MEM_RECLAIM, 0); in ssam_cplt_init()
829 if (!cplt->wq) in ssam_cplt_init()
830 return -ENOMEM; in ssam_cplt_init()
832 for (c = 0; c < ARRAY_SIZE(cplt->event.target); c++) { in ssam_cplt_init()
833 target = &cplt->event.target[c]; in ssam_cplt_init()
835 for (i = 0; i < ARRAY_SIZE(target->queue); i++) in ssam_cplt_init()
836 ssam_event_queue_init(cplt, &target->queue[i]); in ssam_cplt_init()
839 status = ssam_nf_init(&cplt->event.notif); in ssam_cplt_init()
841 destroy_workqueue(cplt->wq); in ssam_cplt_init()
847 * ssam_cplt_destroy() - Deinitialize the completion system.
851 * yet-to-be-completed, event items and requests have been handled.
861 destroy_workqueue(cplt->wq); in ssam_cplt_destroy()
862 ssam_nf_destroy(&cplt->event.notif); in ssam_cplt_destroy()
866 /* -- Main SSAM device structures. ------------------------------------------ */
869 * ssam_controller_device() - Get the &struct device associated with this
874 * providing its lower-level transport.
878 return ssh_rtl_get_device(&c->rtl); in ssam_controller_device()
884 struct ssam_controller *ctrl = to_ssam_controller(kref, kref); in __ssam_controller_release() local
887 * The lock-call here is to satisfy lockdep. At this point we really in __ssam_controller_release()
891 ssam_controller_lock(ctrl); in __ssam_controller_release()
892 ssam_controller_destroy(ctrl); in __ssam_controller_release()
893 ssam_controller_unlock(ctrl); in __ssam_controller_release()
895 kfree(ctrl); in __ssam_controller_release()
899 * ssam_controller_get() - Increment reference count of controller.
907 kref_get(&c->kref); in ssam_controller_get()
913 * ssam_controller_put() - Decrement reference count of controller.
919 kref_put(&c->kref, __ssam_controller_release); in ssam_controller_put()
924 * ssam_controller_statelock() - Lock the controller against state transitions.
933 * ``statelock`` functions represent the read-lock part of a r/w-semaphore.
935 * holding the write-part of this r/w-semaphore (see ssam_controller_lock()
942 down_read(&c->lock); in ssam_controller_statelock()
947 * ssam_controller_stateunlock() - Unlock controller state transitions.
954 up_read(&c->lock); in ssam_controller_stateunlock()
959 * ssam_controller_lock() - Acquire the main controller lock.
970 down_write(&c->lock); in ssam_controller_lock()
974 * ssam_controller_unlock() - Release the main controller lock.
981 up_write(&c->lock); in ssam_controller_unlock()
988 struct ssam_controller *ctrl = to_ssam_controller(rtl, rtl); in ssam_handle_event() local
991 item = ssam_event_item_alloc(data->len, GFP_KERNEL); in ssam_handle_event()
995 item->rqid = get_unaligned_le16(&cmd->rqid); in ssam_handle_event()
996 item->event.target_category = cmd->tc; in ssam_handle_event()
997 item->event.target_id = cmd->sid; in ssam_handle_event()
998 item->event.command_id = cmd->cid; in ssam_handle_event()
999 item->event.instance_id = cmd->iid; in ssam_handle_event()
1000 memcpy(&item->event.data[0], data->ptr, data->len); in ssam_handle_event()
1002 if (WARN_ON(ssam_cplt_submit_event(&ctrl->cplt, item))) in ssam_handle_event()
1010 static bool ssam_notifier_is_empty(struct ssam_controller *ctrl);
1011 static void ssam_notifier_unregister_all(struct ssam_controller *ctrl);
1015 /* d5e383e1-d892-4a76-89fc-f6aaae7ed5b5 */
1051 return -EIO; in ssam_dsm_get_functions()
1053 for (i = 0; i < obj->buffer.length && i < 8; i++) in ssam_dsm_get_functions()
1054 mask |= (((u64)obj->buffer.pointer[i]) << (i * 8)); in ssam_dsm_get_functions()
1075 return -EIO; in ssam_dsm_load_u32()
1077 val = obj->integer.value; in ssam_dsm_load_u32()
1081 return -ERANGE; in ssam_dsm_load_u32()
1088 * ssam_controller_caps_load_from_acpi() - Load controller capabilities from
1107 /* Pre-load supported DSM functions. */ in ssam_controller_caps_load_from_acpi()
1114 &caps->ssh_power_profile); in ssam_controller_caps_load_from_acpi()
1120 &caps->screen_on_sleep_idle_timeout); in ssam_controller_caps_load_from_acpi()
1126 &caps->screen_off_sleep_idle_timeout); in ssam_controller_caps_load_from_acpi()
1135 caps->d3_closes_handle = !!d3_closes_handle; in ssam_controller_caps_load_from_acpi()
1138 &caps->ssh_buffer_size); in ssam_controller_caps_load_from_acpi()
1146 * ssam_controller_caps_load_from_of() - Load controller capabilities from OF/DT.
1158 caps->d3_closes_handle = true; in ssam_controller_caps_load_from_of()
1159 caps->screen_on_sleep_idle_timeout = 5000; in ssam_controller_caps_load_from_of()
1160 caps->screen_off_sleep_idle_timeout = 30; in ssam_controller_caps_load_from_of()
1161 caps->ssh_buffer_size = 48; in ssam_controller_caps_load_from_of()
1168 * ssam_controller_caps_load() - Load controller capabilities
1179 caps->ssh_power_profile = U32_MAX; in ssam_controller_caps_load()
1180 caps->screen_on_sleep_idle_timeout = U32_MAX; in ssam_controller_caps_load()
1181 caps->screen_off_sleep_idle_timeout = U32_MAX; in ssam_controller_caps_load()
1182 caps->d3_closes_handle = false; in ssam_controller_caps_load()
1183 caps->ssh_buffer_size = U32_MAX; in ssam_controller_caps_load()
1192 * ssam_controller_init() - Initialize SSAM controller.
1193 * @ctrl: The controller to initialize.
1204 int ssam_controller_init(struct ssam_controller *ctrl, in ssam_controller_init() argument
1209 init_rwsem(&ctrl->lock); in ssam_controller_init()
1210 kref_init(&ctrl->kref); in ssam_controller_init()
1212 status = ssam_controller_caps_load(&serdev->dev, &ctrl->caps); in ssam_controller_init()
1216 dev_dbg(&serdev->dev, in ssam_controller_init()
1223 ctrl->caps.ssh_power_profile, in ssam_controller_init()
1224 ctrl->caps.ssh_buffer_size, in ssam_controller_init()
1225 ctrl->caps.screen_on_sleep_idle_timeout, in ssam_controller_init()
1226 ctrl->caps.screen_off_sleep_idle_timeout, in ssam_controller_init()
1227 ctrl->caps.d3_closes_handle); in ssam_controller_init()
1229 ssh_seq_reset(&ctrl->counter.seq); in ssam_controller_init()
1230 ssh_rqid_reset(&ctrl->counter.rqid); in ssam_controller_init()
1233 status = ssam_cplt_init(&ctrl->cplt, &serdev->dev); in ssam_controller_init()
1238 status = ssh_rtl_init(&ctrl->rtl, serdev, &ssam_rtl_ops); in ssam_controller_init()
1240 ssam_cplt_destroy(&ctrl->cplt); in ssam_controller_init()
1246 * exclusive context, due to smoke-testing in in ssam_controller_init()
1249 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_INITIALIZED); in ssam_controller_init()
1254 * ssam_controller_start() - Start the receiver and transmitter threads of the
1256 * @ctrl: The controller.
1265 int ssam_controller_start(struct ssam_controller *ctrl) in ssam_controller_start() argument
1269 lockdep_assert_held_write(&ctrl->lock); in ssam_controller_start()
1271 if (ctrl->state != SSAM_CONTROLLER_INITIALIZED) in ssam_controller_start()
1272 return -EINVAL; in ssam_controller_start()
1274 status = ssh_rtl_start(&ctrl->rtl); in ssam_controller_start()
1280 * exclusive context, due to smoke-testing in in ssam_controller_start()
1283 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STARTED); in ssam_controller_start()
1288 * SSAM_CTRL_SHUTDOWN_FLUSH_TIMEOUT - Timeout for flushing requests during
1298 * ssam_controller_shutdown() - Shut down the controller.
1299 * @ctrl: The controller.
1303 * will fail with %-ESHUTDOWN. While it is discouraged to do so, this function
1319 void ssam_controller_shutdown(struct ssam_controller *ctrl) in ssam_controller_shutdown() argument
1321 enum ssam_controller_state s = ctrl->state; in ssam_controller_shutdown()
1324 lockdep_assert_held_write(&ctrl->lock); in ssam_controller_shutdown()
1336 status = ssh_rtl_flush(&ctrl->rtl, SSAM_CTRL_SHUTDOWN_FLUSH_TIMEOUT); in ssam_controller_shutdown()
1338 ssam_err(ctrl, "failed to flush request transport layer: %d\n", in ssam_controller_shutdown()
1343 ssam_cplt_flush(&ctrl->cplt); in ssam_controller_shutdown()
1350 WARN_ON(!ssam_notifier_is_empty(ctrl)); in ssam_controller_shutdown()
1356 ssam_notifier_unregister_all(ctrl); in ssam_controller_shutdown()
1362 ssh_rtl_shutdown(&ctrl->rtl); in ssam_controller_shutdown()
1366 * exclusive context, due to smoke-testing in in ssam_controller_shutdown()
1369 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STOPPED); in ssam_controller_shutdown()
1370 ctrl->rtl.ptl.serdev = NULL; in ssam_controller_shutdown()
1374 * ssam_controller_destroy() - Destroy the controller and free its resources.
1375 * @ctrl: The controller.
1388 void ssam_controller_destroy(struct ssam_controller *ctrl) in ssam_controller_destroy() argument
1390 lockdep_assert_held_write(&ctrl->lock); in ssam_controller_destroy()
1392 if (ctrl->state == SSAM_CONTROLLER_UNINITIALIZED) in ssam_controller_destroy()
1395 WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED && in ssam_controller_destroy()
1396 ctrl->state != SSAM_CONTROLLER_INITIALIZED); in ssam_controller_destroy()
1407 ssam_cplt_destroy(&ctrl->cplt); in ssam_controller_destroy()
1408 ssh_rtl_destroy(&ctrl->rtl); in ssam_controller_destroy()
1412 * exclusive context, due to smoke-testing in in ssam_controller_destroy()
1415 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_UNINITIALIZED); in ssam_controller_destroy()
1419 * ssam_controller_suspend() - Suspend the controller.
1420 * @ctrl: The controller to suspend.
1422 * Marks the controller as suspended. Note that display-off and D0-exit
1428 * Return: Returns %-EINVAL if the controller is currently not in the
1431 int ssam_controller_suspend(struct ssam_controller *ctrl) in ssam_controller_suspend() argument
1433 ssam_controller_lock(ctrl); in ssam_controller_suspend()
1435 if (ctrl->state != SSAM_CONTROLLER_STARTED) { in ssam_controller_suspend()
1436 ssam_controller_unlock(ctrl); in ssam_controller_suspend()
1437 return -EINVAL; in ssam_controller_suspend()
1440 ssam_dbg(ctrl, "pm: suspending controller\n"); in ssam_controller_suspend()
1444 * smoke-testing in ssam_request_sync_submit(). in ssam_controller_suspend()
1446 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_SUSPENDED); in ssam_controller_suspend()
1448 ssam_controller_unlock(ctrl); in ssam_controller_suspend()
1453 * ssam_controller_resume() - Resume the controller from suspend.
1454 * @ctrl: The controller to resume.
1457 * ssam_controller_suspend(). This function does not issue display-on and
1458 * D0-entry notifications. If required, those have to be sent manually after
1461 * Return: Returns %-EINVAL if the controller is currently not suspended.
1463 int ssam_controller_resume(struct ssam_controller *ctrl) in ssam_controller_resume() argument
1465 ssam_controller_lock(ctrl); in ssam_controller_resume()
1467 if (ctrl->state != SSAM_CONTROLLER_SUSPENDED) { in ssam_controller_resume()
1468 ssam_controller_unlock(ctrl); in ssam_controller_resume()
1469 return -EINVAL; in ssam_controller_resume()
1472 ssam_dbg(ctrl, "pm: resuming controller\n"); in ssam_controller_resume()
1476 * smoke-testing in ssam_request_sync_submit(). in ssam_controller_resume()
1478 WRITE_ONCE(ctrl->state, SSAM_CONTROLLER_STARTED); in ssam_controller_resume()
1480 ssam_controller_unlock(ctrl); in ssam_controller_resume()
1485 /* -- Top-level request interface ------------------------------------------- */
1488 * ssam_request_write_data() - Construct and write SAM request message to
1491 * @ctrl: The controller via which the request will be sent.
1503 * %-EINVAL if the payload length provided in the request specification is too
1508 struct ssam_controller *ctrl, in ssam_request_write_data() argument
1515 if (spec->length > SSH_COMMAND_MAX_PAYLOAD_SIZE) in ssam_request_write_data()
1516 return -EINVAL; in ssam_request_write_data()
1518 if (SSH_COMMAND_MESSAGE_LENGTH(spec->length) > buf->len) in ssam_request_write_data()
1519 return -EINVAL; in ssam_request_write_data()
1521 msgb_init(&msgb, buf->ptr, buf->len); in ssam_request_write_data()
1522 seq = ssh_seq_next(&ctrl->counter.seq); in ssam_request_write_data()
1523 rqid = ssh_rqid_next(&ctrl->counter.rqid); in ssam_request_write_data()
1538 r->status = status; in ssam_request_sync_complete()
1540 if (r->resp) in ssam_request_sync_complete()
1541 r->resp->length = 0; in ssam_request_sync_complete()
1551 if (!r->resp || !r->resp->pointer) { in ssam_request_sync_complete()
1552 if (data->len) in ssam_request_sync_complete()
1557 if (data->len > r->resp->capacity) { in ssam_request_sync_complete()
1560 r->resp->capacity, data->len); in ssam_request_sync_complete()
1561 r->status = -ENOSPC; in ssam_request_sync_complete()
1565 r->resp->length = data->len; in ssam_request_sync_complete()
1566 memcpy(r->resp->pointer, data->ptr, data->len); in ssam_request_sync_complete()
1571 complete_all(&container_of(rqst, struct ssam_request_sync, base)->comp); in ssam_request_sync_release()
1580 * ssam_request_sync_alloc() - Allocate a synchronous request.
1596 * Return: Returns zero on success, %-ENOMEM if the request could not be
1607 return -ENOMEM; in ssam_request_sync_alloc()
1609 buffer->ptr = (u8 *)(*rqst + 1); in ssam_request_sync_alloc()
1610 buffer->len = msglen; in ssam_request_sync_alloc()
1617 * ssam_request_sync_free() - Free a synchronous request.
1638 * ssam_request_sync_init() - Initialize a synchronous request struct.
1647 * Return: Returns zero on success or %-EINVAL if the given flags are invalid.
1654 status = ssh_request_init(&rqst->base, flags, &ssam_request_sync_ops); in ssam_request_sync_init()
1658 init_completion(&rqst->comp); in ssam_request_sync_init()
1659 rqst->resp = NULL; in ssam_request_sync_init()
1660 rqst->status = 0; in ssam_request_sync_init()
1667 * ssam_request_sync_submit() - Submit a synchronous request.
1668 * @ctrl: The controller with which to submit the request.
1684 int ssam_request_sync_submit(struct ssam_controller *ctrl, in ssam_request_sync_submit() argument
1703 if (WARN_ON(READ_ONCE(ctrl->state) != SSAM_CONTROLLER_STARTED)) { in ssam_request_sync_submit()
1704 ssh_request_put(&rqst->base); in ssam_request_sync_submit()
1705 return -ENODEV; in ssam_request_sync_submit()
1708 status = ssh_rtl_submit(&ctrl->rtl, &rqst->base); in ssam_request_sync_submit()
1709 ssh_request_put(&rqst->base); in ssam_request_sync_submit()
1716 * ssam_request_do_sync() - Execute a synchronous request.
1717 * @ctrl: The controller via which the request will be submitted.
1728 int ssam_request_do_sync(struct ssam_controller *ctrl, in ssam_request_do_sync() argument
1737 status = ssam_request_sync_alloc(spec->length, GFP_KERNEL, &rqst, &buf); in ssam_request_do_sync()
1741 status = ssam_request_sync_init(rqst, spec->flags); in ssam_request_do_sync()
1749 len = ssam_request_write_data(&buf, ctrl, spec); in ssam_request_do_sync()
1757 status = ssam_request_sync_submit(ctrl, rqst); in ssam_request_do_sync()
1767 * ssam_request_do_sync_with_buffer() - Execute a synchronous request with the
1768 * provided buffer as back-end for the message buffer.
1769 * @ctrl: The controller via which the request will be submitted.
1787 int ssam_request_do_sync_with_buffer(struct ssam_controller *ctrl, in ssam_request_do_sync_with_buffer() argument
1796 status = ssam_request_sync_init(&rqst, spec->flags); in ssam_request_do_sync_with_buffer()
1802 len = ssam_request_write_data(buf, ctrl, spec); in ssam_request_do_sync_with_buffer()
1806 ssam_request_sync_set_data(&rqst, buf->ptr, len); in ssam_request_do_sync_with_buffer()
1808 status = ssam_request_sync_submit(ctrl, &rqst); in ssam_request_do_sync_with_buffer()
1817 /* -- Internal SAM requests. ------------------------------------------------ */
1855 * struct ssh_notification_params - Command payload to enable/disable SSH
1873 static int __ssam_ssh_event_request(struct ssam_controller *ctrl, in __ssam_ssh_event_request() argument
1887 return -EINVAL; in __ssam_ssh_event_request()
1906 status = ssam_retry(ssam_request_do_sync_onstack, ctrl, &rqst, &result, in __ssam_ssh_event_request()
1913 * ssam_ssh_event_enable() - Enable SSH event.
1914 * @ctrl: The controller for which to enable the event.
1926 * negative on direct failure) or %-EPROTO if the request response indicates a
1929 static int ssam_ssh_event_enable(struct ssam_controller *ctrl, in ssam_ssh_event_enable() argument
1935 status = __ssam_ssh_event_request(ctrl, reg, reg.cid_enable, id, flags); in ssam_ssh_event_enable()
1937 if (status < 0 && status != -EINVAL) { in ssam_ssh_event_enable()
1938 ssam_err(ctrl, in ssam_ssh_event_enable()
1944 ssam_err(ctrl, in ssam_ssh_event_enable()
1947 return -EPROTO; in ssam_ssh_event_enable()
1954 * ssam_ssh_event_disable() - Disable SSH event.
1955 * @ctrl: The controller for which to disable the event.
1967 * negative on direct failure) or %-EPROTO if the request response indicates a
1970 static int ssam_ssh_event_disable(struct ssam_controller *ctrl, in ssam_ssh_event_disable() argument
1976 status = __ssam_ssh_event_request(ctrl, reg, reg.cid_disable, id, flags); in ssam_ssh_event_disable()
1978 if (status < 0 && status != -EINVAL) { in ssam_ssh_event_disable()
1979 ssam_err(ctrl, in ssam_ssh_event_disable()
1985 ssam_err(ctrl, in ssam_ssh_event_disable()
1988 return -EPROTO; in ssam_ssh_event_disable()
1995 /* -- Wrappers for internal SAM requests. ----------------------------------- */
1998 * ssam_get_firmware_version() - Get the SAM/EC firmware version.
1999 * @ctrl: The controller.
2005 int ssam_get_firmware_version(struct ssam_controller *ctrl, u32 *version) in ssam_get_firmware_version() argument
2010 status = ssam_retry(ssam_ssh_get_firmware_version, ctrl, &__version); in ssam_get_firmware_version()
2019 * ssam_ctrl_notif_display_off() - Notify EC that the display has been turned
2021 * @ctrl: The controller.
2024 * a lower-power state. This will prevent events from being sent directly.
2025 * Rather, the EC signals an event by pulling the wakeup GPIO high for as long
2027 * one by one, via the GPIO callback request. All pending events accumulated
2028 * during this state can also be released by issuing the display-on
2030 * the GPIO.
2035 * This function will only send the display-off notification command if
2042 * status of the executed SAM request if that request failed, or %-EPROTO if
2045 int ssam_ctrl_notif_display_off(struct ssam_controller *ctrl) in ssam_ctrl_notif_display_off() argument
2050 ssam_dbg(ctrl, "pm: notifying display off\n"); in ssam_ctrl_notif_display_off()
2052 status = ssam_retry(ssam_ssh_notif_display_off, ctrl, &response); in ssam_ctrl_notif_display_off()
2057 ssam_err(ctrl, "unexpected response from display-off notification: %#04x\n", in ssam_ctrl_notif_display_off()
2059 return -EPROTO; in ssam_ctrl_notif_display_off()
2066 * ssam_ctrl_notif_display_on() - Notify EC that the display has been turned on.
2067 * @ctrl: The controller.
2070 * exited its lower-power state. This notification is the counterpart to the
2071 * display-off notification sent via ssam_ctrl_notif_display_off() and will
2074 * This function will only send the display-on notification command if display
2081 * status of the executed SAM request if that request failed, or %-EPROTO if
2084 int ssam_ctrl_notif_display_on(struct ssam_controller *ctrl) in ssam_ctrl_notif_display_on() argument
2089 ssam_dbg(ctrl, "pm: notifying display on\n"); in ssam_ctrl_notif_display_on()
2091 status = ssam_retry(ssam_ssh_notif_display_on, ctrl, &response); in ssam_ctrl_notif_display_on()
2096 ssam_err(ctrl, "unexpected response from display-on notification: %#04x\n", in ssam_ctrl_notif_display_on()
2098 return -EPROTO; in ssam_ctrl_notif_display_on()
2105 * ssam_ctrl_notif_d0_exit() - Notify EC that the driver/device exits the D0
2107 * @ctrl: The controller
2110 * favor of a lower-power state. Exact effects of this function related to the
2113 * This function will only send the D0-exit notification command if D0-state
2120 * status of the executed SAM request if that request failed, or %-EPROTO if
2123 int ssam_ctrl_notif_d0_exit(struct ssam_controller *ctrl) in ssam_ctrl_notif_d0_exit() argument
2128 if (!ctrl->caps.d3_closes_handle) in ssam_ctrl_notif_d0_exit()
2131 ssam_dbg(ctrl, "pm: notifying D0 exit\n"); in ssam_ctrl_notif_d0_exit()
2133 status = ssam_retry(ssam_ssh_notif_d0_exit, ctrl, &response); in ssam_ctrl_notif_d0_exit()
2138 ssam_err(ctrl, "unexpected response from D0-exit notification: %#04x\n", in ssam_ctrl_notif_d0_exit()
2140 return -EPROTO; in ssam_ctrl_notif_d0_exit()
2147 * ssam_ctrl_notif_d0_entry() - Notify EC that the driver/device enters the D0
2149 * @ctrl: The controller
2151 * Notifies the EC that the driver has exited a lower-power state and entered
2155 * This function will only send the D0-entry notification command if D0-state
2162 * status of the executed SAM request if that request failed, or %-EPROTO if
2165 int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl) in ssam_ctrl_notif_d0_entry() argument
2170 if (!ctrl->caps.d3_closes_handle) in ssam_ctrl_notif_d0_entry()
2173 ssam_dbg(ctrl, "pm: notifying D0 entry\n"); in ssam_ctrl_notif_d0_entry()
2175 status = ssam_retry(ssam_ssh_notif_d0_entry, ctrl, &response); in ssam_ctrl_notif_d0_entry()
2180 ssam_err(ctrl, "unexpected response from D0-entry notification: %#04x\n", in ssam_ctrl_notif_d0_entry()
2182 return -EPROTO; in ssam_ctrl_notif_d0_entry()
2189 /* -- Top-level event registry interface. ----------------------------------- */
2192 * ssam_nf_refcount_enable() - Enable event for reference count entry if it has
2194 * @ctrl: The controller to enable the event on.
2207 * Note: ``nf->lock`` must be held when calling this function.
2210 * returns the status of the event-enable EC command.
2212 static int ssam_nf_refcount_enable(struct ssam_controller *ctrl, in ssam_nf_refcount_enable() argument
2215 const struct ssam_event_registry reg = entry->key.reg; in ssam_nf_refcount_enable()
2216 const struct ssam_event_id id = entry->key.id; in ssam_nf_refcount_enable()
2217 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_nf_refcount_enable()
2220 lockdep_assert_held(&nf->lock); in ssam_nf_refcount_enable()
2222 ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", in ssam_nf_refcount_enable()
2223 reg.target_category, id.target_category, id.instance, entry->refcount); in ssam_nf_refcount_enable()
2225 if (entry->refcount == 1) { in ssam_nf_refcount_enable()
2226 status = ssam_ssh_event_enable(ctrl, reg, id, flags); in ssam_nf_refcount_enable()
2230 entry->flags = flags; in ssam_nf_refcount_enable()
2232 } else if (entry->flags != flags) { in ssam_nf_refcount_enable()
2233 ssam_warn(ctrl, in ssam_nf_refcount_enable()
2235 flags, entry->flags, reg.target_category, id.target_category, in ssam_nf_refcount_enable()
2243 * ssam_nf_refcount_disable_free() - Disable event for reference count entry if
2245 * @ctrl: The controller to disable the event on.
2257 * hot-removable devices, where event disable requests may time out after the
2271 * Note: ``nf->lock`` must be held when calling this function.
2274 * returns the status of the event-enable EC command.
2276 static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl, in ssam_nf_refcount_disable_free() argument
2279 const struct ssam_event_registry reg = entry->key.reg; in ssam_nf_refcount_disable_free()
2280 const struct ssam_event_id id = entry->key.id; in ssam_nf_refcount_disable_free()
2281 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_nf_refcount_disable_free()
2284 lockdep_assert_held(&nf->lock); in ssam_nf_refcount_disable_free()
2286 ssam_dbg(ctrl, "%s event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", in ssam_nf_refcount_disable_free()
2288 id.instance, entry->refcount); in ssam_nf_refcount_disable_free()
2290 if (entry->flags != flags) { in ssam_nf_refcount_disable_free()
2291 ssam_warn(ctrl, in ssam_nf_refcount_disable_free()
2293 flags, entry->flags, reg.target_category, id.target_category, in ssam_nf_refcount_disable_free()
2297 if (ec && entry->refcount == 0) { in ssam_nf_refcount_disable_free()
2298 status = ssam_ssh_event_disable(ctrl, reg, id, flags); in ssam_nf_refcount_disable_free()
2306 * ssam_notifier_register() - Register an event notifier.
2307 * @ctrl: The controller to register the notifier on.
2320 * Return: Returns zero on success, %-ENOSPC if there have already been
2322 * registered, %-ENOMEM if the corresponding event entry could not be
2324 * for the specific associated event, returns the status of the event-enable
2325 * EC-command.
2327 int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notifier *n) in ssam_notifier_register() argument
2329 u16 rqid = ssh_tc_to_rqid(n->event.id.target_category); in ssam_notifier_register()
2336 return -EINVAL; in ssam_notifier_register()
2338 nf = &ctrl->cplt.event.notif; in ssam_notifier_register()
2339 nf_head = &nf->head[ssh_rqid_to_event(rqid)]; in ssam_notifier_register()
2341 mutex_lock(&nf->lock); in ssam_notifier_register()
2343 if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) { in ssam_notifier_register()
2344 entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id); in ssam_notifier_register()
2346 mutex_unlock(&nf->lock); in ssam_notifier_register()
2351 status = ssam_nfblk_insert(nf_head, &n->base); in ssam_notifier_register()
2354 ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id); in ssam_notifier_register()
2356 mutex_unlock(&nf->lock); in ssam_notifier_register()
2361 status = ssam_nf_refcount_enable(ctrl, entry, n->event.flags); in ssam_notifier_register()
2363 ssam_nfblk_remove(&n->base); in ssam_notifier_register()
2364 ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id); in ssam_notifier_register()
2365 mutex_unlock(&nf->lock); in ssam_notifier_register()
2366 synchronize_srcu(&nf_head->srcu); in ssam_notifier_register()
2371 mutex_unlock(&nf->lock); in ssam_notifier_register()
2377 * __ssam_notifier_unregister() - Unregister an event notifier.
2378 * @ctrl: The controller the notifier has been registered on.
2386 * Useful for hot-removable devices, where communication may fail once the
2390 * Return: Returns zero on success, %-ENOENT if the given notifier block has
2393 * event-disable EC-command.
2395 int __ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n, in __ssam_notifier_unregister() argument
2398 u16 rqid = ssh_tc_to_rqid(n->event.id.target_category); in __ssam_notifier_unregister()
2405 return -EINVAL; in __ssam_notifier_unregister()
2407 nf = &ctrl->cplt.event.notif; in __ssam_notifier_unregister()
2408 nf_head = &nf->head[ssh_rqid_to_event(rqid)]; in __ssam_notifier_unregister()
2410 mutex_lock(&nf->lock); in __ssam_notifier_unregister()
2412 if (!ssam_nfblk_find(nf_head, &n->base)) { in __ssam_notifier_unregister()
2413 mutex_unlock(&nf->lock); in __ssam_notifier_unregister()
2414 return -ENOENT; in __ssam_notifier_unregister()
2421 if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) { in __ssam_notifier_unregister()
2422 entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); in __ssam_notifier_unregister()
2430 status = -ENOENT; in __ssam_notifier_unregister()
2434 status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags, disable); in __ssam_notifier_unregister()
2438 ssam_nfblk_remove(&n->base); in __ssam_notifier_unregister()
2439 mutex_unlock(&nf->lock); in __ssam_notifier_unregister()
2440 synchronize_srcu(&nf_head->srcu); in __ssam_notifier_unregister()
2447 * ssam_controller_event_enable() - Enable the specified event.
2448 * @ctrl: The controller to enable the event for.
2456 * Note: In general, ssam_notifier_register() with a non-observer notifier
2461 * Return: Returns zero on success, %-ENOSPC if the reference count for the
2462 * specified event has reached its maximum, %-ENOMEM if the corresponding event
2465 * this call), returns the status of the event-enable EC-command.
2467 int ssam_controller_event_enable(struct ssam_controller *ctrl, in ssam_controller_event_enable() argument
2472 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_controller_event_enable()
2477 return -EINVAL; in ssam_controller_event_enable()
2479 mutex_lock(&nf->lock); in ssam_controller_event_enable()
2483 mutex_unlock(&nf->lock); in ssam_controller_event_enable()
2487 status = ssam_nf_refcount_enable(ctrl, entry, flags); in ssam_controller_event_enable()
2490 mutex_unlock(&nf->lock); in ssam_controller_event_enable()
2494 mutex_unlock(&nf->lock); in ssam_controller_event_enable()
2500 * ssam_controller_event_disable() - Disable the specified event.
2501 * @ctrl: The controller to disable the event for.
2510 * non-observer notifier should be preferred for enabling/disabling events, as
2514 * Return: Returns zero on success, %-ENOENT if the given event has not been
2516 * during this call, returns the status of the event-disable EC-command.
2518 int ssam_controller_event_disable(struct ssam_controller *ctrl, in ssam_controller_event_disable() argument
2523 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_controller_event_disable()
2528 return -EINVAL; in ssam_controller_event_disable()
2530 mutex_lock(&nf->lock); in ssam_controller_event_disable()
2534 mutex_unlock(&nf->lock); in ssam_controller_event_disable()
2535 return -ENOENT; in ssam_controller_event_disable()
2538 status = ssam_nf_refcount_disable_free(ctrl, entry, flags, true); in ssam_controller_event_disable()
2540 mutex_unlock(&nf->lock); in ssam_controller_event_disable()
2546 * ssam_notifier_disable_registered() - Disable events for all registered
2548 * @ctrl: The controller for which to disable the notifiers/events.
2555 * See ssam_notifier_restore_registered() to restore/re-enable all events
2566 int ssam_notifier_disable_registered(struct ssam_controller *ctrl) in ssam_notifier_disable_registered() argument
2568 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_notifier_disable_registered()
2572 mutex_lock(&nf->lock); in ssam_notifier_disable_registered()
2573 for (n = rb_first(&nf->refcount); n; n = rb_next(n)) { in ssam_notifier_disable_registered()
2577 status = ssam_ssh_event_disable(ctrl, e->key.reg, in ssam_notifier_disable_registered()
2578 e->key.id, e->flags); in ssam_notifier_disable_registered()
2582 mutex_unlock(&nf->lock); in ssam_notifier_disable_registered()
2591 ssam_ssh_event_enable(ctrl, e->key.reg, e->key.id, e->flags); in ssam_notifier_disable_registered()
2593 mutex_unlock(&nf->lock); in ssam_notifier_disable_registered()
2599 * ssam_notifier_restore_registered() - Restore/re-enable events for all
2601 * @ctrl: The controller for which to restore the notifiers/events.
2603 * Restores/re-enables all events for which notifiers have been registered on
2607 * This function is intended to restore/re-enable all registered events after
2611 void ssam_notifier_restore_registered(struct ssam_controller *ctrl) in ssam_notifier_restore_registered() argument
2613 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_notifier_restore_registered()
2616 mutex_lock(&nf->lock); in ssam_notifier_restore_registered()
2617 for (n = rb_first(&nf->refcount); n; n = rb_next(n)) { in ssam_notifier_restore_registered()
2623 ssam_ssh_event_enable(ctrl, e->key.reg, e->key.id, e->flags); in ssam_notifier_restore_registered()
2625 mutex_unlock(&nf->lock); in ssam_notifier_restore_registered()
2629 * ssam_notifier_is_empty() - Check if there are any registered notifiers.
2630 * @ctrl: The controller to check on.
2635 static bool ssam_notifier_is_empty(struct ssam_controller *ctrl) in ssam_notifier_is_empty() argument
2637 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_notifier_is_empty()
2640 mutex_lock(&nf->lock); in ssam_notifier_is_empty()
2642 mutex_unlock(&nf->lock); in ssam_notifier_is_empty()
2648 * ssam_notifier_unregister_all() - Unregister all currently registered
2650 * @ctrl: The controller to unregister the notifiers on.
2656 static void ssam_notifier_unregister_all(struct ssam_controller *ctrl) in ssam_notifier_unregister_all() argument
2658 struct ssam_nf *nf = &ctrl->cplt.event.notif; in ssam_notifier_unregister_all()
2661 mutex_lock(&nf->lock); in ssam_notifier_unregister_all()
2662 rbtree_postorder_for_each_entry_safe(e, n, &nf->refcount, node) { in ssam_notifier_unregister_all()
2664 ssam_ssh_event_disable(ctrl, e->key.reg, e->key.id, e->flags); in ssam_notifier_unregister_all()
2667 nf->refcount = RB_ROOT; in ssam_notifier_unregister_all()
2668 mutex_unlock(&nf->lock); in ssam_notifier_unregister_all()
2672 /* -- Wakeup IRQ. ----------------------------------------------------------- */
2676 struct ssam_controller *ctrl = dev_id; in ssam_irq_handle() local
2678 ssam_dbg(ctrl, "pm: wake irq triggered\n"); in ssam_irq_handle()
2682 * When the EC is in display-off or any other non-D0 state, it in ssam_irq_handle()
2686 * release these events one-by-one. in ssam_irq_handle()
2693 * TODO: Send GPIO callback command repeatedly to EC until callback in ssam_irq_handle()
2696 * all events have been released (return = 0x00), the GPIO is in ssam_irq_handle()
2697 * re-armed. Detect wakeup events during this process, go back to in ssam_irq_handle()
2705 * ssam_irq_setup() - Set up SAM EC wakeup-GPIO interrupt.
2706 * @ctrl: The controller for which the IRQ should be set up.
2708 * Set up an IRQ for the wakeup-GPIO pin of the SAM EC. This IRQ can be used
2711 * Note that this IRQ can only be triggered while the EC is in the display-off
2713 * Instead the wakeup-GPIO gets pulled to "high" as long as there are pending
2714 * events and these events need to be released one-by-one via the GPIO
2715 * callback request, either until there are no events left and the GPIO is
2716 * reset, or all at once by transitioning the EC out of the display-off state,
2717 * which will also clear the GPIO.
2723 * IRQ should be disabled by default to avoid spurious wake-ups, caused, for
2729 * for functions to transition the EC into and out of the display-off state as
2736 int ssam_irq_setup(struct ssam_controller *ctrl) in ssam_irq_setup() argument
2738 struct device *dev = ssam_controller_device(ctrl); in ssam_irq_setup()
2744 * The actual GPIO interrupt is declared in ACPI as TRIGGER_HIGH. in ssam_irq_setup()
2745 * However, the GPIO line only gets reset by sending the GPIO callback in ssam_irq_setup()
2746 * command to SAM (or alternatively the display-on notification). As in ssam_irq_setup()
2756 gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS); in ssam_irq_setup()
2768 "ssam_wakeup", ctrl); in ssam_irq_setup()
2772 ctrl->irq.num = irq; in ssam_irq_setup()
2777 * ssam_irq_free() - Free SAM EC wakeup-GPIO interrupt.
2778 * @ctrl: The controller for which the IRQ should be freed.
2780 * Free the wakeup-GPIO IRQ previously set-up via ssam_irq_setup().
2782 void ssam_irq_free(struct ssam_controller *ctrl) in ssam_irq_free() argument
2784 free_irq(ctrl->irq.num, ctrl); in ssam_irq_free()
2785 ctrl->irq.num = -1; in ssam_irq_free()
2789 * ssam_irq_arm_for_wakeup() - Arm the EC IRQ for wakeup, if enabled.
2790 * @ctrl: The controller for which the IRQ should be armed.
2802 int ssam_irq_arm_for_wakeup(struct ssam_controller *ctrl) in ssam_irq_arm_for_wakeup() argument
2804 struct device *dev = ssam_controller_device(ctrl); in ssam_irq_arm_for_wakeup()
2807 enable_irq(ctrl->irq.num); in ssam_irq_arm_for_wakeup()
2809 status = enable_irq_wake(ctrl->irq.num); in ssam_irq_arm_for_wakeup()
2811 ssam_err(ctrl, "failed to enable wake IRQ: %d\n", status); in ssam_irq_arm_for_wakeup()
2812 disable_irq(ctrl->irq.num); in ssam_irq_arm_for_wakeup()
2816 ctrl->irq.wakeup_enabled = true; in ssam_irq_arm_for_wakeup()
2818 ctrl->irq.wakeup_enabled = false; in ssam_irq_arm_for_wakeup()
2825 * ssam_irq_disarm_wakeup() - Disarm the wakeup IRQ.
2826 * @ctrl: The controller for which the IRQ should be disarmed.
2835 void ssam_irq_disarm_wakeup(struct ssam_controller *ctrl) in ssam_irq_disarm_wakeup() argument
2839 if (ctrl->irq.wakeup_enabled) { in ssam_irq_disarm_wakeup()
2840 status = disable_irq_wake(ctrl->irq.num); in ssam_irq_disarm_wakeup()
2842 ssam_err(ctrl, "failed to disable wake IRQ: %d\n", status); in ssam_irq_disarm_wakeup()
2844 ctrl->irq.wakeup_enabled = false; in ssam_irq_disarm_wakeup()
2846 disable_irq(ctrl->irq.num); in ssam_irq_disarm_wakeup()