3636 * The driver uses the Linux GPIO and interrupt framework to expose a virtual
3737 * GPIO for each outbound entry and a virtual interrupt controller for each
3838 * inbound entry.
39+ *
40+ * Driver supports two versions:
41+ * V1 - For processor that start after local host
42+ * V2 - For processor that start in early boot sequence
3943 */
4044
4145#define SMP2P_MAX_ENTRY 16
4852#define SMP2P_MAGIC 0x504d5324
4953#define SMP2P_ALL_FEATURES SMP2P_FEATURE_SSR_ACK
5054
55+ #define ONE 1
56+ #define TWO 2
57+ #define MAX_VERSION TWO
58+
5159/**
5260 * struct smp2p_smem_item - in memory communication structure
5361 * @magic: magic number
54- * @version: version - must be 1
62+ * @version: version
5563 * @features: features flag - currently unused
5664 * @local_pid: processor id of sending end
5765 * @remote_pid: processor id of receiving end
@@ -180,14 +188,23 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
180188static bool qcom_smp2p_check_ssr (struct qcom_smp2p * smp2p )
181189{
182190 struct smp2p_smem_item * in = smp2p -> in ;
191+ struct smp2p_entry * entry ;
183192 bool restart ;
184193
185194 if (!smp2p -> ssr_ack_enabled )
186195 return false;
187196
188197 restart = in -> flags & BIT (SMP2P_FLAGS_RESTART_DONE_BIT );
198+ restart = restart != smp2p -> ssr_ack ;
199+ if (restart && in -> version > ONE ) {
200+ list_for_each_entry (entry , & smp2p -> inbound , node ) {
201+ if (!entry -> value )
202+ continue ;
203+ entry -> last_value = 0 ;
204+ }
205+ }
189206
190- return restart != smp2p -> ssr_ack ;
207+ return restart ;
191208}
192209
193210static void qcom_smp2p_do_ssr_ack (struct qcom_smp2p * smp2p )
@@ -222,6 +239,56 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
222239 }
223240}
224241
242+ static int qcom_smp2p_in_version (struct qcom_smp2p * smp2p )
243+ {
244+ unsigned int smem_id = smp2p -> smem_items [SMP2P_INBOUND ];
245+ unsigned int pid = smp2p -> remote_pid ;
246+ struct smp2p_smem_item * in ;
247+ size_t size ;
248+
249+ in = qcom_smem_get (pid , smem_id , & size );
250+ if (IS_ERR (in ))
251+ return 0 ;
252+
253+ return in -> version ;
254+ }
255+
256+ static void qcom_smp2p_start_in (struct qcom_smp2p * smp2p )
257+ {
258+ unsigned int smem_id = smp2p -> smem_items [SMP2P_INBOUND ];
259+ unsigned int pid = smp2p -> remote_pid ;
260+ char buf [SMP2P_MAX_ENTRY_NAME ];
261+ struct smp2p_smem_item * in ;
262+ struct smp2p_entry * entry ;
263+ size_t size ;
264+ int i ;
265+
266+ in = qcom_smem_get (pid , smem_id , & size );
267+ if (IS_ERR (in ))
268+ return ;
269+
270+ smp2p -> in = in ;
271+
272+ /* Check if version is initialized and set to v2.
273+ * Early enumeration of inbound entries is required only
274+ * for early boot processors which have smp2p version 2.
275+ */
276+ if (in -> version != TWO )
277+ return ;
278+
279+ for (i = smp2p -> valid_entries ; i < in -> valid_entries ; i ++ ) {
280+ list_for_each_entry (entry , & smp2p -> inbound , node ) {
281+ memcpy (buf , in -> entries [i ].name , sizeof (buf ));
282+ if (!strcmp (buf , entry -> name )) {
283+ entry -> value = & in -> entries [i ].value ;
284+ entry -> last_value = readl (entry -> value );
285+ break ;
286+ }
287+ }
288+ }
289+ smp2p -> valid_entries = i ;
290+ }
291+
225292static void qcom_smp2p_notify_in (struct qcom_smp2p * smp2p )
226293{
227294 struct smp2p_smem_item * in ;
@@ -368,12 +435,31 @@ static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p)
368435 seq_printf (p , "%8s" , dev_name (entry -> smp2p -> dev ));
369436}
370437
438+ static int smp2p_irq_get_irqchip_state (struct irq_data * irqd , enum irqchip_irq_state which ,
439+ bool * state )
440+ {
441+ struct smp2p_entry * entry = irq_data_get_irq_chip_data (irqd );
442+ u32 val ;
443+
444+ if (which != IRQCHIP_STATE_LINE_LEVEL )
445+ return - EINVAL ;
446+
447+ if (!entry -> value )
448+ return - ENODEV ;
449+
450+ val = readl (entry -> value );
451+ * state = !!(val & BIT (irqd_to_hwirq (irqd )));
452+
453+ return 0 ;
454+ }
455+
371456static struct irq_chip smp2p_irq_chip = {
372457 .name = "smp2p" ,
373458 .irq_mask = smp2p_mask_irq ,
374459 .irq_unmask = smp2p_unmask_irq ,
375460 .irq_set_type = smp2p_set_irq_type ,
376461 .irq_print_chip = smp2p_irq_print_chip ,
462+ .irq_get_irqchip_state = smp2p_irq_get_irqchip_state ,
377463};
378464
379465static int smp2p_irq_map (struct irq_domain * d ,
@@ -464,6 +550,7 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
464550 struct smp2p_smem_item * out ;
465551 unsigned smem_id = smp2p -> smem_items [SMP2P_OUTBOUND ];
466552 unsigned pid = smp2p -> remote_pid ;
553+ u8 in_version ;
467554 int ret ;
468555
469556 ret = qcom_smem_alloc (pid , smem_id , sizeof (* out ));
@@ -485,12 +572,18 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
485572 out -> valid_entries = 0 ;
486573 out -> features = SMP2P_ALL_FEATURES ;
487574
575+ in_version = qcom_smp2p_in_version (smp2p );
576+ if (in_version > MAX_VERSION ) {
577+ dev_err (smp2p -> dev , "Unsupported smp2p version\n" );
578+ return - EINVAL ;
579+ }
580+
488581 /*
489582 * Make sure the rest of the header is written before we validate the
490583 * item by writing a valid version number.
491584 */
492585 wmb ();
493- out -> version = 1 ;
586+ out -> version = ( in_version ) ? in_version : 1 ;
494587
495588 qcom_smp2p_kick (smp2p );
496589
@@ -618,6 +711,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
618711 }
619712 }
620713
714+ /* Check inbound entries in the case of early boot processor */
715+ qcom_smp2p_start_in (smp2p );
716+
621717 /* Kick the outgoing edge after allocating entries */
622718 qcom_smp2p_kick (smp2p );
623719
0 commit comments