Merge tag 'ti-v2020.07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
[oweals/u-boot.git] / drivers / misc / irq-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Google, LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #define LOG_CATEGORY UCLASS_IRQ
8
9 #include <common.h>
10 #include <dm.h>
11 #include <dt-structs.h>
12 #include <irq.h>
13 #include <log.h>
14 #include <dm/device-internal.h>
15
16 int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
17 {
18         const struct irq_ops *ops = irq_get_ops(dev);
19
20         if (!ops->route_pmc_gpio_gpe)
21                 return -ENOSYS;
22
23         return ops->route_pmc_gpio_gpe(dev, pmc_gpe_num);
24 }
25
26 int irq_set_polarity(struct udevice *dev, uint irq, bool active_low)
27 {
28         const struct irq_ops *ops = irq_get_ops(dev);
29
30         if (!ops->set_polarity)
31                 return -ENOSYS;
32
33         return ops->set_polarity(dev, irq, active_low);
34 }
35
36 int irq_snapshot_polarities(struct udevice *dev)
37 {
38         const struct irq_ops *ops = irq_get_ops(dev);
39
40         if (!ops->snapshot_polarities)
41                 return -ENOSYS;
42
43         return ops->snapshot_polarities(dev);
44 }
45
46 int irq_restore_polarities(struct udevice *dev)
47 {
48         const struct irq_ops *ops = irq_get_ops(dev);
49
50         if (!ops->restore_polarities)
51                 return -ENOSYS;
52
53         return ops->restore_polarities(dev);
54 }
55
56 int irq_read_and_clear(struct irq *irq)
57 {
58         const struct irq_ops *ops = irq_get_ops(irq->dev);
59
60         if (!ops->read_and_clear)
61                 return -ENOSYS;
62
63         return ops->read_and_clear(irq);
64 }
65
66 #if CONFIG_IS_ENABLED(OF_PLATDATA)
67 int irq_get_by_index_platdata(struct udevice *dev, int index,
68                               struct phandle_1_arg *cells, struct irq *irq)
69 {
70         int ret;
71
72         if (index != 0)
73                 return -ENOSYS;
74         ret = uclass_get_device(UCLASS_IRQ, 0, &irq->dev);
75         if (ret)
76                 return ret;
77         irq->id = cells[0].arg[0];
78
79         return 0;
80 }
81 #else
82 static int irq_of_xlate_default(struct irq *irq,
83                                 struct ofnode_phandle_args *args)
84 {
85         log_debug("(irq=%p)\n", irq);
86
87         if (args->args_count > 1) {
88                 log_debug("Invaild args_count: %d\n", args->args_count);
89                 return -EINVAL;
90         }
91
92         if (args->args_count)
93                 irq->id = args->args[0];
94         else
95                 irq->id = 0;
96
97         return 0;
98 }
99
100 static int irq_get_by_index_tail(int ret, ofnode node,
101                                  struct ofnode_phandle_args *args,
102                                  const char *list_name, int index,
103                                  struct irq *irq)
104 {
105         struct udevice *dev_irq;
106         const struct irq_ops *ops;
107
108         assert(irq);
109         irq->dev = NULL;
110         if (ret)
111                 goto err;
112
113         ret = uclass_get_device_by_ofnode(UCLASS_IRQ, args->node, &dev_irq);
114         if (ret) {
115                 log_debug("uclass_get_device_by_ofnode failed: err=%d\n", ret);
116                 return ret;
117         }
118
119         irq->dev = dev_irq;
120
121         ops = irq_get_ops(dev_irq);
122
123         if (ops->of_xlate)
124                 ret = ops->of_xlate(irq, args);
125         else
126                 ret = irq_of_xlate_default(irq, args);
127         if (ret) {
128                 log_debug("of_xlate() failed: %d\n", ret);
129                 return ret;
130         }
131
132         return irq_request(dev_irq, irq);
133 err:
134         log_debug("Node '%s', property '%s', failed to request IRQ index %d: %d\n",
135                   ofnode_get_name(node), list_name, index, ret);
136         return ret;
137 }
138
139 int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
140 {
141         struct ofnode_phandle_args args;
142         int ret;
143
144         ret = dev_read_phandle_with_args(dev, "interrupts-extended",
145                                          "#interrupt-cells", 0, index, &args);
146
147         return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
148                                      "interrupts-extended", index > 0, irq);
149 }
150 #endif /* OF_PLATDATA */
151
152 int irq_request(struct udevice *dev, struct irq *irq)
153 {
154         const struct irq_ops *ops;
155
156         log_debug("(dev=%p, irq=%p)\n", dev, irq);
157         if (!irq)
158                 return 0;
159         ops = irq_get_ops(dev);
160
161         irq->dev = dev;
162
163         if (!ops->request)
164                 return 0;
165
166         return ops->request(irq);
167 }
168
169 int irq_first_device_type(enum irq_dev_t type, struct udevice **devp)
170 {
171         int ret;
172
173         ret = uclass_first_device_drvdata(UCLASS_IRQ, type, devp);
174         if (ret)
175                 return log_msg_ret("find", ret);
176
177         return 0;
178 }
179
180 UCLASS_DRIVER(irq) = {
181         .id             = UCLASS_IRQ,
182         .name           = "irq",
183 };