hc
2023-12-06 d38611ca164021d018c1b23eee65bbebc09c63e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Intel Merrifield watchdog platform device library file
 *
 * (C) Copyright 2014 Intel Corporation
 * Author: David Cohen <david.a.cohen@linux.intel.com>
 */
 
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/platform_data/intel-mid_wdt.h>
 
#include <asm/intel-mid.h>
#include <asm/intel_scu_ipc.h>
#include <asm/io_apic.h>
#include <asm/hw_irq.h>
 
#define TANGIER_EXT_TIMER0_MSI 12
 
static struct platform_device wdt_dev = {
   .name = "intel_mid_wdt",
   .id = -1,
};
 
static int tangier_probe(struct platform_device *pdev)
{
   struct irq_alloc_info info;
   struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
   int gsi = TANGIER_EXT_TIMER0_MSI;
   int irq;
 
   if (!pdata)
       return -EINVAL;
 
   /* IOAPIC builds identity mapping between GSI and IRQ on MID */
   ioapic_set_alloc_attr(&info, cpu_to_node(0), 1, 0);
   irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, &info);
   if (irq < 0) {
       dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n", gsi);
       return irq;
   }
 
   pdata->irq = irq;
   return 0;
}
 
static struct intel_mid_wdt_pdata tangier_pdata = {
   .probe = tangier_probe,
};
 
static int wdt_scu_status_change(struct notifier_block *nb,
                unsigned long code, void *data)
{
   if (code == SCU_DOWN) {
       platform_device_unregister(&wdt_dev);
       return 0;
   }
 
   return platform_device_register(&wdt_dev);
}
 
static struct notifier_block wdt_scu_notifier = {
   .notifier_call    = wdt_scu_status_change,
};
 
static int __init register_mid_wdt(void)
{
   if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
       return -ENODEV;
 
   wdt_dev.dev.platform_data = &tangier_pdata;
 
   /*
    * We need to be sure that the SCU IPC is ready before watchdog device
    * can be registered:
    */
   intel_scu_notifier_add(&wdt_scu_notifier);
 
   return 0;
}
arch_initcall(register_mid_wdt);