blob: 41faeb3d858201f521ee7416a359e260a048cec6 [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 *
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>
Simon Glass4dcacfc2020-05-10 11:40:13 -060015#include <linux/bitops.h>
Tero Kristof81f4cd2020-02-14 11:18:15 +020016
17#define ESM_SFT_RST 0x0c
18#define ESM_SFT_RST_KEY 0x0f
Hari Nagalla85ae1e62022-03-09 14:42:28 -060019#define ESM_EN 0x08
20#define ESM_EN_KEY 0x0f
Tero Kristof81f4cd2020-02-14 11:18:15 +020021
22#define ESM_STS(i) (0x404 + (i) / 32 * 0x20)
Hari Nagalla85ae1e62022-03-09 14:42:28 -060023#define ESM_STS_MASK(i) (1 << ((i) % 32))
Tero Kristof81f4cd2020-02-14 11:18:15 +020024#define ESM_PIN_EN_SET_OFFSET(i) (0x414 + (i) / 32 * 0x20)
Hari Nagalla85ae1e62022-03-09 14:42:28 -060025#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))
Tero Kristof81f4cd2020-02-14 11:18:15 +020030
31static void esm_pin_enable(void __iomem *base, int pin)
32{
Hari Nagalla85ae1e62022-03-09 14:42:28 -060033 u32 value;
34
35 value = readl(base + ESM_PIN_EN_SET_OFFSET(pin));
36 value |= ESM_PIN_MASK(pin);
Tero Kristof81f4cd2020-02-14 11:18:15 +020037 /* Enable event */
Hari Nagalla85ae1e62022-03-09 14:42:28 -060038 writel(value, base + ESM_PIN_EN_SET_OFFSET(pin));
39}
40
41static 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
51static 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));
Tero Kristof81f4cd2020-02-14 11:18:15 +020059}
60
Hari Nagalla85ae1e62022-03-09 14:42:28 -060061static 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}
Tero Kristof81f4cd2020-02-14 11:18:15 +020070/**
71 * k3_esm_probe: configures ESM based on DT data
72 *
73 * Parses ESM info from device tree, and configures the module accordingly.
74 */
75static 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
Hari Nagalla85ae1e62022-03-09 14:42:28 -0600110 for (i = 0; i < num_pins; i++) {
111 esm_intr_prio_set(base, pins[i]);
112 esm_clear_raw_status(base, pins[i]);
Tero Kristof81f4cd2020-02-14 11:18:15 +0200113 esm_pin_enable(base, pins[i]);
Hari Nagalla85ae1e62022-03-09 14:42:28 -0600114 esm_intr_enable(base, pins[i]);
115 }
116
117 /* Enable ESM */
118 writel(ESM_EN_KEY, base + ESM_EN);
Tero Kristof81f4cd2020-02-14 11:18:15 +0200119
120free_pins:
121 kfree(pins);
122 return ret;
123}
124
125static const struct udevice_id k3_esm_ids[] = {
126 { .compatible = "ti,j721e-esm" },
127 {}
128};
129
130U_BOOT_DRIVER(k3_esm) = {
131 .name = "k3_esm",
132 .of_match = k3_esm_ids,
133 .id = UCLASS_MISC,
134 .probe = k3_esm_probe,
135};