1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Intel Merrifield watchdog platform device library file |
4 | * |
5 | * (C) Copyright 2014 Intel Corporation |
6 | * Author: David Cohen <david.a.cohen@linux.intel.com> |
7 | */ |
8 | |
9 | #include <linux/init.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/platform_device.h> |
12 | #include <linux/platform_data/intel-mid_wdt.h> |
13 | |
14 | #include <asm/cpu_device_id.h> |
15 | #include <asm/intel-family.h> |
16 | #include <asm/io_apic.h> |
17 | #include <asm/hw_irq.h> |
18 | |
19 | #define TANGIER_EXT_TIMER0_MSI 12 |
20 | |
21 | static struct platform_device wdt_dev = { |
22 | .name = "intel_mid_wdt" , |
23 | .id = -1, |
24 | }; |
25 | |
26 | static int tangier_probe(struct platform_device *pdev) |
27 | { |
28 | struct irq_alloc_info info; |
29 | struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data; |
30 | int gsi = TANGIER_EXT_TIMER0_MSI; |
31 | int irq; |
32 | |
33 | if (!pdata) |
34 | return -EINVAL; |
35 | |
36 | /* IOAPIC builds identity mapping between GSI and IRQ on MID */ |
37 | ioapic_set_alloc_attr(info: &info, cpu_to_node(cpu: 0), trigger: 1, polarity: 0); |
38 | irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC, info: &info); |
39 | if (irq < 0) { |
40 | dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n" , gsi); |
41 | return irq; |
42 | } |
43 | |
44 | pdata->irq = irq; |
45 | return 0; |
46 | } |
47 | |
48 | static struct intel_mid_wdt_pdata tangier_pdata = { |
49 | .probe = tangier_probe, |
50 | }; |
51 | |
52 | static const struct x86_cpu_id intel_mid_cpu_ids[] = { |
53 | X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &tangier_pdata), |
54 | {} |
55 | }; |
56 | |
57 | static int __init register_mid_wdt(void) |
58 | { |
59 | const struct x86_cpu_id *id; |
60 | |
61 | id = x86_match_cpu(match: intel_mid_cpu_ids); |
62 | if (!id) |
63 | return -ENODEV; |
64 | |
65 | wdt_dev.dev.platform_data = (struct intel_mid_wdt_pdata *)id->driver_data; |
66 | return platform_device_register(&wdt_dev); |
67 | } |
68 | arch_initcall(register_mid_wdt); |
69 | |
70 | static void __exit unregister_mid_wdt(void) |
71 | { |
72 | platform_device_unregister(&wdt_dev); |
73 | } |
74 | __exitcall(unregister_mid_wdt); |
75 | |