blob: fa3d656562206c909096e8e87148976a6fe93210 [file] [log] [blame]
Tero Kristof81f4cd2020-02-14 11:18:15 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments' K3 Error Signalling Module driver
4 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05005 * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
Tero Kristof81f4cd2020-02-14 11:18:15 +02006 * Tero Kristo <t-kristo@ti.com>
7 *
8 */
9
Tero Kristof81f4cd2020-02-14 11:18:15 +020010#include <dm.h>
11#include <errno.h>
12#include <asm/io.h>
13#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060014#include <linux/bitops.h>
Tero Kristof81f4cd2020-02-14 11:18:15 +020015
16#define ESM_SFT_RST 0x0c
17#define ESM_SFT_RST_KEY 0x0f
Hari Nagalla85ae1e62022-03-09 14:42:28 -060018#define ESM_EN 0x08
19#define ESM_EN_KEY 0x0f
Tero Kristof81f4cd2020-02-14 11:18:15 +020020
21#define ESM_STS(i) (0x404 + (i) / 32 * 0x20)
Hari Nagalla85ae1e62022-03-09 14:42:28 -060022#define ESM_STS_MASK(i) (1 << ((i) % 32))
Tero Kristof81f4cd2020-02-14 11:18:15 +020023#define ESM_PIN_EN_SET_OFFSET(i) (0x414 + (i) / 32 * 0x20)
Hari Nagalla85ae1e62022-03-09 14:42:28 -060024#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))
Tero Kristof81f4cd2020-02-14 11:18:15 +020029
30static void esm_pin_enable(void __iomem *base, int pin)
31{
Hari Nagalla85ae1e62022-03-09 14:42:28 -060032 u32 value;
33
34 value = readl(base + ESM_PIN_EN_SET_OFFSET(pin));
35 value |= ESM_PIN_MASK(pin);
Tero Kristof81f4cd2020-02-14 11:18:15 +020036 /* Enable event */
Hari Nagalla85ae1e62022-03-09 14:42:28 -060037 writel(value, base + ESM_PIN_EN_SET_OFFSET(pin));
38}
39
40static 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
50static 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));
Tero Kristof81f4cd2020-02-14 11:18:15 +020058}
59
Hari Nagalla85ae1e62022-03-09 14:42:28 -060060static 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}
Tero Kristof81f4cd2020-02-14 11:18:15 +020069/**
70 * k3_esm_probe: configures ESM based on DT data
71 *
72 * Parses ESM info from device tree, and configures the module accordingly.
73 */
74static 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
Hari Nagalla85ae1e62022-03-09 14:42:28 -0600109 for (i = 0; i < num_pins; i++) {
110 esm_intr_prio_set(base, pins[i]);
111 esm_clear_raw_status(base, pins[i]);
Tero Kristof81f4cd2020-02-14 11:18:15 +0200112 esm_pin_enable(base, pins[i]);
Hari Nagalla85ae1e62022-03-09 14:42:28 -0600113 esm_intr_enable(base, pins[i]);
114 }
115
116 /* Enable ESM */
117 writel(ESM_EN_KEY, base + ESM_EN);
Tero Kristof81f4cd2020-02-14 11:18:15 +0200118
119free_pins:
120 kfree(pins);
121 return ret;
122}
123
124static const struct udevice_id k3_esm_ids[] = {
125 { .compatible = "ti,j721e-esm" },
126 {}
127};
128
129U_BOOT_DRIVER(k3_esm) = {
130 .name = "k3_esm",
131 .of_match = k3_esm_ids,
132 .id = UCLASS_MISC,
133 .probe = k3_esm_probe,
134};