| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Texas Instruments' K3 Error Signalling Module driver
- *
- * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- * Tero Kristo <t-kristo@ti.com>
- *
- */
- #include <common.h>
- #include <dm.h>
- #include <errno.h>
- #include <asm/io.h>
- #include <dm/device_compat.h>
- #include <linux/bitops.h>
- #define ESM_SFT_RST 0x0c
- #define ESM_SFT_RST_KEY 0x0f
- #define ESM_EN 0x08
- #define ESM_EN_KEY 0x0f
- #define ESM_STS(i) (0x404 + (i) / 32 * 0x20)
- #define ESM_STS_MASK(i) (1 << ((i) % 32))
- #define ESM_PIN_EN_SET_OFFSET(i) (0x414 + (i) / 32 * 0x20)
- #define ESM_PIN_MASK(i) (1 << ((i) % 32))
- #define ESM_INTR_EN_SET_OFFSET(i) (0x408 + (i) / 32 * 0x20)
- #define ESM_INTR_MASK(i) (1 << ((i) % 32))
- #define ESM_INTR_PRIO_SET_OFFSET(i) (0x410 + (i) / 32 * 0x20)
- #define ESM_INTR_PRIO_MASK(i) (1 << ((i) % 32))
- static void esm_pin_enable(void __iomem *base, int pin)
- {
- u32 value;
- value = readl(base + ESM_PIN_EN_SET_OFFSET(pin));
- value |= ESM_PIN_MASK(pin);
- /* Enable event */
- writel(value, base + ESM_PIN_EN_SET_OFFSET(pin));
- }
- static void esm_intr_enable(void __iomem *base, int pin)
- {
- u32 value;
- value = readl(base + ESM_INTR_EN_SET_OFFSET(pin));
- value |= ESM_INTR_MASK(pin);
- /* Enable Interrupt event */
- writel(value, base + ESM_INTR_EN_SET_OFFSET(pin));
- }
- static void esm_intr_prio_set(void __iomem *base, int pin)
- {
- u32 value;
- value = readl(base + ESM_INTR_PRIO_SET_OFFSET(pin));
- value |= ESM_INTR_PRIO_MASK(pin);
- /* Set to priority */
- writel(value, base + ESM_INTR_PRIO_SET_OFFSET(pin));
- }
- static void esm_clear_raw_status(void __iomem *base, int pin)
- {
- u32 value;
- value = readl(base + ESM_STS(pin));
- value |= ESM_STS_MASK(pin);
- /* Clear Event status */
- writel(value, base + ESM_STS(pin));
- }
- /**
- * k3_esm_probe: configures ESM based on DT data
- *
- * Parses ESM info from device tree, and configures the module accordingly.
- */
- static int k3_esm_probe(struct udevice *dev)
- {
- int ret;
- void __iomem *base;
- int num_pins;
- u32 *pins;
- int i;
- base = dev_remap_addr_index(dev, 0);
- if (!base)
- return -ENODEV;
- num_pins = dev_read_size(dev, "ti,esm-pins");
- if (num_pins < 0) {
- dev_err(dev, "ti,esm-pins property missing or invalid: %d\n",
- num_pins);
- return num_pins;
- }
- num_pins /= sizeof(u32);
- pins = kmalloc(num_pins * sizeof(u32), __GFP_ZERO);
- if (!pins)
- return -ENOMEM;
- ret = dev_read_u32_array(dev, "ti,esm-pins", pins, num_pins);
- if (ret < 0) {
- dev_err(dev, "failed to read ti,esm-pins property: %d\n",
- ret);
- goto free_pins;
- }
- /* Clear any pending events */
- writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST);
- for (i = 0; i < num_pins; i++) {
- esm_intr_prio_set(base, pins[i]);
- esm_clear_raw_status(base, pins[i]);
- esm_pin_enable(base, pins[i]);
- esm_intr_enable(base, pins[i]);
- }
- /* Enable ESM */
- writel(ESM_EN_KEY, base + ESM_EN);
- free_pins:
- kfree(pins);
- return ret;
- }
- static const struct udevice_id k3_esm_ids[] = {
- { .compatible = "ti,j721e-esm" },
- {}
- };
- U_BOOT_DRIVER(k3_esm) = {
- .name = "k3_esm",
- .of_match = k3_esm_ids,
- .id = UCLASS_MISC,
- .probe = k3_esm_probe,
- };
|