blob: 233ad4a908f5469e1ef210ddba6d7ec573fd4e15 [file] [log] [blame]
Sam Protsenko2800e692024-01-10 21:09:01 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2023 Linaro Ltd.
4 * Author: Sam Protsenko <semen.protsenko@linaro.org>
5 *
6 * Exynos PMU (Power Management Unit) driver.
7 */
8
9#include <dm.h>
10#include <errno.h>
11#include <regmap.h>
12#include <syscon.h>
13#include <linux/bitops.h>
14#include <linux/err.h>
15
16#define EXYNOS850_UART_IO_SHARE_CTRL 0x0760
17#define SEL_RXD_AP_UART_SHIFT 16
18#define SEL_RXD_AP_UART_MASK GENMASK(17, 16)
19#define SEL_TXD_GPIO_1_SHIFT 20
20#define SEL_TXD_GPIO_1_MASK GENMASK(21, 20)
21#define RXD_GPIO_1 0x3
22#define TXD_AP_UART 0x0
23
24struct exynos_pmu {
25 struct udevice *dev;
26 const struct exynos_pmu_data *pmu_data;
27 struct regmap *regmap;
28};
29
30struct exynos_pmu_data {
31 int (*pmu_init)(struct exynos_pmu *priv);
32};
33
34static int exynos850_pmu_init(struct exynos_pmu *priv)
35{
36 ofnode node;
37 bool uart_debug_1;
38 unsigned int offset, mask, value;
39
40 node = dev_ofnode(priv->dev);
41 uart_debug_1 = ofnode_read_bool(node, "samsung,uart-debug-1");
42 if (!uart_debug_1)
43 return 0;
44
45 /*
46 * If uart1_pins are used for serial, AP UART lines have to be muxed
47 * in PMU block to UART_DEBUG_1 path (GPIO_1). By default (reset value)
48 * UART_DEBUG_0 path (uart0_pins) is connected to AP UART lines.
49 */
50 offset = EXYNOS850_UART_IO_SHARE_CTRL;
51 mask = SEL_RXD_AP_UART_MASK | SEL_TXD_GPIO_1_MASK;
52 value = RXD_GPIO_1 << SEL_RXD_AP_UART_SHIFT |
53 TXD_AP_UART << SEL_TXD_GPIO_1_SHIFT;
54 return regmap_update_bits(priv->regmap, offset, mask, value);
55}
56
57static const struct exynos_pmu_data exynos850_pmu_data = {
58 .pmu_init = exynos850_pmu_init,
59};
60
61static int exynos_pmu_bind(struct udevice *dev)
62{
63 dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
64 return 0;
65}
66
67static int exynos_pmu_probe(struct udevice *dev)
68{
69 ofnode node;
70 struct exynos_pmu *priv;
71
72 priv = dev_get_priv(dev);
73 priv->dev = dev;
74
75 node = dev_ofnode(dev);
76 priv->regmap = syscon_node_to_regmap(node);
77 if (IS_ERR(priv->regmap))
78 return PTR_ERR(priv->regmap);
79
80 priv->pmu_data = (struct exynos_pmu_data *)dev_get_driver_data(dev);
81 if (priv->pmu_data && priv->pmu_data->pmu_init)
82 return priv->pmu_data->pmu_init(priv);
83
84 return 0;
85}
86
87static const struct udevice_id exynos_pmu_ids[] = {
88 {
89 .compatible = "samsung,exynos850-pmu",
90 .data = (ulong)&exynos850_pmu_data
91 },
92 { /* sentinel */ }
93};
94
95U_BOOT_DRIVER(exynos_pmu) = {
96 .name = "exynos-pmu",
97 .id = UCLASS_NOP,
98 .of_match = exynos_pmu_ids,
99 .bind = exynos_pmu_bind,
100 .probe = exynos_pmu_probe,
101 .priv_auto = sizeof(struct exynos_pmu),
102};