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