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 
20 #define ESM_STS(i)			(0x404 + (i) / 32 * 0x20)
21 #define ESM_PIN_EN_SET_OFFSET(i)	(0x414 + (i) / 32 * 0x20)
22 #define ESM_PIN_MASK(i)			BIT((i) & 0x1f)
23 
esm_pin_enable(void __iomem * base,int pin)24 static void esm_pin_enable(void __iomem *base, int pin)
25 {
26 	/* Enable event */
27 	writel(ESM_PIN_MASK(pin), base + ESM_PIN_EN_SET_OFFSET(pin));
28 }
29 
30 /**
31  * k3_esm_probe: configures ESM based on DT data
32  *
33  * Parses ESM info from device tree, and configures the module accordingly.
34  */
k3_esm_probe(struct udevice * dev)35 static int k3_esm_probe(struct udevice *dev)
36 {
37 	int ret;
38 	void __iomem *base;
39 	int num_pins;
40 	u32 *pins;
41 	int i;
42 
43 	base = dev_remap_addr_index(dev, 0);
44 	if (!base)
45 		return -ENODEV;
46 
47 	num_pins = dev_read_size(dev, "ti,esm-pins");
48 	if (num_pins < 0) {
49 		dev_err(dev, "ti,esm-pins property missing or invalid: %d\n",
50 			num_pins);
51 		return num_pins;
52 	}
53 
54 	num_pins /= sizeof(u32);
55 
56 	pins = kmalloc(num_pins * sizeof(u32), __GFP_ZERO);
57 	if (!pins)
58 		return -ENOMEM;
59 
60 	ret = dev_read_u32_array(dev, "ti,esm-pins", pins, num_pins);
61 	if (ret < 0) {
62 		dev_err(dev, "failed to read ti,esm-pins property: %d\n",
63 			ret);
64 		goto free_pins;
65 	}
66 
67 	/* Clear any pending events */
68 	writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST);
69 
70 	for (i = 0; i < num_pins; i++)
71 		esm_pin_enable(base, pins[i]);
72 
73 free_pins:
74 	kfree(pins);
75 	return ret;
76 }
77 
78 static const struct udevice_id k3_esm_ids[] = {
79 	{ .compatible = "ti,j721e-esm" },
80 	{}
81 };
82 
83 U_BOOT_DRIVER(k3_esm) = {
84 	.name = "k3_esm",
85 	.of_match = k3_esm_ids,
86 	.id = UCLASS_MISC,
87 	.probe = k3_esm_probe,
88 };
89