1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * platform_msic.c: MSIC platform data initialization file
4  *
5  * (C) Copyright 2013 Intel Corporation
6  * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/interrupt.h>
11 #include <linux/scatterlist.h>
12 #include <linux/init.h>
13 #include <linux/sfi.h>
14 #include <linux/mfd/intel_msic.h>
15 #include <asm/intel_scu_ipc.h>
16 #include <asm/intel-mid.h>
17 #include "platform_msic.h"
18 
19 struct intel_msic_platform_data msic_pdata;
20 
21 static struct resource msic_resources[] = {
22 	{
23 		.start	= INTEL_MSIC_IRQ_PHYS_BASE,
24 		.end	= INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
25 		.flags	= IORESOURCE_MEM,
26 	},
27 };
28 
29 static struct platform_device msic_device = {
30 	.name		= "intel_msic",
31 	.id		= -1,
32 	.dev		= {
33 		.platform_data	= &msic_pdata,
34 	},
35 	.num_resources	= ARRAY_SIZE(msic_resources),
36 	.resource	= msic_resources,
37 };
38 
msic_scu_status_change(struct notifier_block * nb,unsigned long code,void * data)39 static int msic_scu_status_change(struct notifier_block *nb,
40 				  unsigned long code, void *data)
41 {
42 	if (code == SCU_DOWN) {
43 		platform_device_unregister(&msic_device);
44 		return 0;
45 	}
46 
47 	return platform_device_register(&msic_device);
48 }
49 
msic_init(void)50 static int __init msic_init(void)
51 {
52 	static struct notifier_block msic_scu_notifier = {
53 		.notifier_call	= msic_scu_status_change,
54 	};
55 
56 	/*
57 	 * We need to be sure that the SCU IPC is ready before MSIC device
58 	 * can be registered.
59 	 */
60 	if (intel_mid_has_msic())
61 		intel_scu_notifier_add(&msic_scu_notifier);
62 
63 	return 0;
64 }
65 arch_initcall(msic_init);
66 
67 /*
68  * msic_generic_platform_data - sets generic platform data for the block
69  * @info: pointer to the SFI device table entry for this block
70  * @block: MSIC block
71  *
72  * Function sets IRQ number from the SFI table entry for given device to
73  * the MSIC platform data.
74  */
msic_generic_platform_data(void * info,enum intel_msic_block block)75 void *msic_generic_platform_data(void *info, enum intel_msic_block block)
76 {
77 	struct sfi_device_table_entry *entry = info;
78 
79 	BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
80 	msic_pdata.irq[block] = entry->irq;
81 
82 	return NULL;
83 }
84