Prepare v2024.10
[platform/kernel/u-boot.git] / drivers / misc / k3_esm.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments' K3 Error Signalling Module driver
4  *
5  * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
6  *      Tero Kristo <t-kristo@ti.com>
7  *
8  */
9
10 #include <dm.h>
11 #include <errno.h>
12 #include <asm/io.h>
13 #include <dm/device_compat.h>
14 #include <linux/bitops.h>
15
16 #define ESM_SFT_RST                     0x0c
17 #define ESM_SFT_RST_KEY                 0x0f
18 #define ESM_EN                          0x08
19 #define ESM_EN_KEY                      0x0f
20
21 #define ESM_STS(i)                      (0x404 + (i) / 32 * 0x20)
22 #define ESM_STS_MASK(i)                 (1 << ((i) % 32))
23 #define ESM_PIN_EN_SET_OFFSET(i)        (0x414 + (i) / 32 * 0x20)
24 #define ESM_PIN_MASK(i)                 (1 << ((i) % 32))
25 #define ESM_INTR_EN_SET_OFFSET(i)       (0x408 + (i) / 32 * 0x20)
26 #define ESM_INTR_MASK(i)                (1 << ((i) % 32))
27 #define ESM_INTR_PRIO_SET_OFFSET(i)     (0x410 + (i) / 32 * 0x20)
28 #define ESM_INTR_PRIO_MASK(i)           (1 << ((i) % 32))
29
30 static void esm_pin_enable(void __iomem *base, int pin)
31 {
32         u32 value;
33
34         value = readl(base + ESM_PIN_EN_SET_OFFSET(pin));
35         value |= ESM_PIN_MASK(pin);
36         /* Enable event */
37         writel(value, base + ESM_PIN_EN_SET_OFFSET(pin));
38 }
39
40 static void esm_intr_enable(void __iomem *base, int pin)
41 {
42         u32 value;
43
44         value = readl(base + ESM_INTR_EN_SET_OFFSET(pin));
45         value |= ESM_INTR_MASK(pin);
46         /* Enable Interrupt event */
47         writel(value, base + ESM_INTR_EN_SET_OFFSET(pin));
48 }
49
50 static void esm_intr_prio_set(void __iomem *base, int pin)
51 {
52         u32 value;
53
54         value = readl(base + ESM_INTR_PRIO_SET_OFFSET(pin));
55         value |= ESM_INTR_PRIO_MASK(pin);
56         /* Set to priority */
57         writel(value, base + ESM_INTR_PRIO_SET_OFFSET(pin));
58 }
59
60 static void esm_clear_raw_status(void __iomem *base, int pin)
61 {
62         u32 value;
63
64         value = readl(base + ESM_STS(pin));
65         value |= ESM_STS_MASK(pin);
66         /* Clear Event status */
67         writel(value, base + ESM_STS(pin));
68 }
69 /**
70  * k3_esm_probe: configures ESM based on DT data
71  *
72  * Parses ESM info from device tree, and configures the module accordingly.
73  */
74 static int k3_esm_probe(struct udevice *dev)
75 {
76         int ret;
77         void __iomem *base;
78         int num_pins;
79         u32 *pins;
80         int i;
81
82         base = dev_remap_addr_index(dev, 0);
83         if (!base)
84                 return -ENODEV;
85
86         num_pins = dev_read_size(dev, "ti,esm-pins");
87         if (num_pins < 0) {
88                 dev_err(dev, "ti,esm-pins property missing or invalid: %d\n",
89                         num_pins);
90                 return num_pins;
91         }
92
93         num_pins /= sizeof(u32);
94
95         pins = kmalloc(num_pins * sizeof(u32), __GFP_ZERO);
96         if (!pins)
97                 return -ENOMEM;
98
99         ret = dev_read_u32_array(dev, "ti,esm-pins", pins, num_pins);
100         if (ret < 0) {
101                 dev_err(dev, "failed to read ti,esm-pins property: %d\n",
102                         ret);
103                 goto free_pins;
104         }
105
106         /* Clear any pending events */
107         writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST);
108
109         for (i = 0; i < num_pins; i++) {
110                 esm_intr_prio_set(base, pins[i]);
111                 esm_clear_raw_status(base, pins[i]);
112                 esm_pin_enable(base, pins[i]);
113                 esm_intr_enable(base, pins[i]);
114         }
115
116         /* Enable ESM */
117         writel(ESM_EN_KEY, base + ESM_EN);
118
119 free_pins:
120         kfree(pins);
121         return ret;
122 }
123
124 static const struct udevice_id k3_esm_ids[] = {
125         { .compatible = "ti,j721e-esm" },
126         {}
127 };
128
129 U_BOOT_DRIVER(k3_esm) = {
130         .name = "k3_esm",
131         .of_match = k3_esm_ids,
132         .id = UCLASS_MISC,
133         .probe = k3_esm_probe,
134 };