1313
1414#include <dt-bindings/mailbox/qcom-ipcc.h>
1515
16- #define IPCC_MBOX_MAX_CHAN 48
17-
1816/* IPCC Register offsets */
1917#define IPCC_REG_SEND_ID 0x0c
2018#define IPCC_REG_RECV_ID 0x10
@@ -52,9 +50,10 @@ struct qcom_ipcc {
5250 struct device * dev ;
5351 void __iomem * base ;
5452 struct irq_domain * irq_domain ;
55- struct mbox_chan chan [ IPCC_MBOX_MAX_CHAN ] ;
56- struct qcom_ipcc_chan_info mchan [ IPCC_MBOX_MAX_CHAN ] ;
53+ struct mbox_chan * chans ;
54+ struct qcom_ipcc_chan_info * mchan ;
5755 struct mbox_controller mbox ;
56+ int num_chans ;
5857 int irq ;
5958};
6059
@@ -166,41 +165,87 @@ static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
166165 struct qcom_ipcc * ipcc = to_qcom_ipcc (mbox );
167166 struct qcom_ipcc_chan_info * mchan ;
168167 struct mbox_chan * chan ;
169- unsigned int i ;
168+ struct device * dev ;
169+ int chan_id ;
170+
171+ dev = ipcc -> dev ;
170172
171173 if (ph -> args_count != 2 )
172174 return ERR_PTR (- EINVAL );
173175
174- for (i = 0 ; i < IPCC_MBOX_MAX_CHAN ; i ++ ) {
175- chan = & ipcc -> chan [i ];
176- if (!chan -> con_priv ) {
177- mchan = & ipcc -> mchan [i ];
178- mchan -> client_id = ph -> args [0 ];
179- mchan -> signal_id = ph -> args [1 ];
180- chan -> con_priv = mchan ;
181- break ;
182- }
176+ for (chan_id = 0 ; chan_id < mbox -> num_chans ; chan_id ++ ) {
177+ chan = & ipcc -> chans [chan_id ];
178+ mchan = chan -> con_priv ;
183179
184- chan = NULL ;
180+ if (!mchan )
181+ break ;
182+ else if (mchan -> client_id == ph -> args [0 ] &&
183+ mchan -> signal_id == ph -> args [1 ])
184+ return ERR_PTR (- EBUSY );
185185 }
186186
187- return chan ?: ERR_PTR (- EBUSY );
187+ if (chan_id >= mbox -> num_chans )
188+ return ERR_PTR (- EBUSY );
189+
190+ mchan = devm_kzalloc (dev , sizeof (* mchan ), GFP_KERNEL );
191+ if (!mchan )
192+ return ERR_PTR (- ENOMEM );
193+
194+ mchan -> client_id = ph -> args [0 ];
195+ mchan -> signal_id = ph -> args [1 ];
196+ chan -> con_priv = mchan ;
197+
198+ return chan ;
188199}
189200
190201static const struct mbox_chan_ops ipcc_mbox_chan_ops = {
191202 .send_data = qcom_ipcc_mbox_send_data ,
192203 .shutdown = qcom_ipcc_mbox_shutdown ,
193204};
194205
195- static int qcom_ipcc_setup_mbox (struct qcom_ipcc * ipcc )
206+ static int qcom_ipcc_setup_mbox (struct qcom_ipcc * ipcc ,
207+ struct device_node * controller_dn )
196208{
209+ struct of_phandle_args curr_ph ;
210+ struct device_node * client_dn ;
197211 struct mbox_controller * mbox ;
198212 struct device * dev = ipcc -> dev ;
213+ int i , j , ret ;
214+
215+ /*
216+ * Find out the number of clients interested in this mailbox
217+ * and create channels accordingly.
218+ */
219+ ipcc -> num_chans = 0 ;
220+ for_each_node_with_property (client_dn , "mboxes" ) {
221+ if (!of_device_is_available (client_dn ))
222+ continue ;
223+ i = of_count_phandle_with_args (client_dn ,
224+ "mboxes" , "#mbox-cells" );
225+ for (j = 0 ; j < i ; j ++ ) {
226+ ret = of_parse_phandle_with_args (client_dn , "mboxes" ,
227+ "#mbox-cells" , j , & curr_ph );
228+ of_node_put (curr_ph .np );
229+ if (!ret && curr_ph .np == controller_dn ) {
230+ ipcc -> num_chans ++ ;
231+ break ;
232+ }
233+ }
234+ }
235+
236+ /* If no clients are found, skip registering as a mbox controller */
237+ if (!ipcc -> num_chans )
238+ return 0 ;
239+
240+ ipcc -> chans = devm_kcalloc (dev , ipcc -> num_chans ,
241+ sizeof (struct mbox_chan ), GFP_KERNEL );
242+ if (!ipcc -> chans )
243+ return - ENOMEM ;
199244
200245 mbox = & ipcc -> mbox ;
201246 mbox -> dev = dev ;
202- mbox -> num_chans = IPCC_MBOX_MAX_CHAN ;
203- mbox -> chans = ipcc -> chan ;
247+ mbox -> num_chans = ipcc -> num_chans ;
248+ mbox -> chans = ipcc -> chans ;
204249 mbox -> ops = & ipcc_mbox_chan_ops ;
205250 mbox -> of_xlate = qcom_ipcc_mbox_xlate ;
206251 mbox -> txdone_irq = false;
@@ -212,6 +257,8 @@ static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc)
212257static int qcom_ipcc_probe (struct platform_device * pdev )
213258{
214259 struct qcom_ipcc * ipcc ;
260+ static int id ;
261+ char * name ;
215262 int ret ;
216263
217264 ipcc = devm_kzalloc (& pdev -> dev , sizeof (* ipcc ), GFP_KERNEL );
@@ -228,27 +275,33 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
228275 if (ipcc -> irq < 0 )
229276 return ipcc -> irq ;
230277
278+ name = devm_kasprintf (& pdev -> dev , GFP_KERNEL , "ipcc_%d" , id ++ );
279+ if (!name )
280+ return - ENOMEM ;
281+
231282 ipcc -> irq_domain = irq_domain_add_tree (pdev -> dev .of_node ,
232283 & qcom_ipcc_irq_ops , ipcc );
233284 if (!ipcc -> irq_domain )
234285 return - ENOMEM ;
235286
236- ret = qcom_ipcc_setup_mbox (ipcc );
287+ ret = qcom_ipcc_setup_mbox (ipcc , pdev -> dev . of_node );
237288 if (ret )
238289 goto err_mbox ;
239290
240291 ret = devm_request_irq (& pdev -> dev , ipcc -> irq , qcom_ipcc_irq_fn ,
241- IRQF_TRIGGER_HIGH , "ipcc" , ipcc );
292+ IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND , name , ipcc );
242293 if (ret < 0 ) {
243294 dev_err (& pdev -> dev , "Failed to register the irq: %d\n" , ret );
244- goto err_mbox ;
295+ goto err_req_irq ;
245296 }
246297
247- enable_irq_wake (ipcc -> irq );
248298 platform_set_drvdata (pdev , ipcc );
249299
250300 return 0 ;
251301
302+ err_req_irq :
303+ if (ipcc -> num_chans )
304+ mbox_controller_unregister (& ipcc -> mbox );
252305err_mbox :
253306 irq_domain_remove (ipcc -> irq_domain );
254307
0 commit comments