mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
soc: samsung: Add Exynos PMU driver
Add basic Power Management Unit (PMU) driver for Exynos SoCs. For now it's only capable of changing UART path in PMU, which is needed for E850-96 board. The driver's structure resembles the exynos-pmu driver from Linux kernel, and although it's very basic and slim at the moment, it can be easily extended in future if the need arises. UCLASS_NOP is used, as there are no benefits in using more elaborate classes like UCLASS_MISC in this case. The DM_FLAG_PROBE_AFTER_BIND flag is added in bind function, as the probe function must be always called for this driver. Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> Reviewed-by: Chanho Park <chanho61.park@samsung.com> Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
This commit is contained in:
parent
c9a3efdfc0
commit
8fd06aeb8a
3 changed files with 113 additions and 0 deletions
|
@ -5,6 +5,16 @@ menuconfig SOC_SAMSUNG
|
|||
|
||||
if SOC_SAMSUNG
|
||||
|
||||
config EXYNOS_PMU
|
||||
bool "Exynos PMU controller driver"
|
||||
depends on ARCH_EXYNOS
|
||||
select REGMAP
|
||||
select SYSCON
|
||||
help
|
||||
Enable support for system controller configuration driver. It allows
|
||||
one to configure system controller registers (e.g. some register in
|
||||
PMU syscon) by providing register's offset, mask and value.
|
||||
|
||||
config EXYNOS_USI
|
||||
bool "Exynos USI (Universal Serial Interface) driver"
|
||||
depends on ARCH_EXYNOS
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
|
||||
obj-$(CONFIG_EXYNOS_USI) += exynos-usi.o
|
||||
|
|
102
drivers/soc/samsung/exynos-pmu.c
Normal file
102
drivers/soc/samsung/exynos-pmu.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 Linaro Ltd.
|
||||
* Author: Sam Protsenko <semen.protsenko@linaro.org>
|
||||
*
|
||||
* Exynos PMU (Power Management Unit) driver.
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define EXYNOS850_UART_IO_SHARE_CTRL 0x0760
|
||||
#define SEL_RXD_AP_UART_SHIFT 16
|
||||
#define SEL_RXD_AP_UART_MASK GENMASK(17, 16)
|
||||
#define SEL_TXD_GPIO_1_SHIFT 20
|
||||
#define SEL_TXD_GPIO_1_MASK GENMASK(21, 20)
|
||||
#define RXD_GPIO_1 0x3
|
||||
#define TXD_AP_UART 0x0
|
||||
|
||||
struct exynos_pmu {
|
||||
struct udevice *dev;
|
||||
const struct exynos_pmu_data *pmu_data;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
struct exynos_pmu_data {
|
||||
int (*pmu_init)(struct exynos_pmu *priv);
|
||||
};
|
||||
|
||||
static int exynos850_pmu_init(struct exynos_pmu *priv)
|
||||
{
|
||||
ofnode node;
|
||||
bool uart_debug_1;
|
||||
unsigned int offset, mask, value;
|
||||
|
||||
node = dev_ofnode(priv->dev);
|
||||
uart_debug_1 = ofnode_read_bool(node, "samsung,uart-debug-1");
|
||||
if (!uart_debug_1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If uart1_pins are used for serial, AP UART lines have to be muxed
|
||||
* in PMU block to UART_DEBUG_1 path (GPIO_1). By default (reset value)
|
||||
* UART_DEBUG_0 path (uart0_pins) is connected to AP UART lines.
|
||||
*/
|
||||
offset = EXYNOS850_UART_IO_SHARE_CTRL;
|
||||
mask = SEL_RXD_AP_UART_MASK | SEL_TXD_GPIO_1_MASK;
|
||||
value = RXD_GPIO_1 << SEL_RXD_AP_UART_SHIFT |
|
||||
TXD_AP_UART << SEL_TXD_GPIO_1_SHIFT;
|
||||
return regmap_update_bits(priv->regmap, offset, mask, value);
|
||||
}
|
||||
|
||||
static const struct exynos_pmu_data exynos850_pmu_data = {
|
||||
.pmu_init = exynos850_pmu_init,
|
||||
};
|
||||
|
||||
static int exynos_pmu_bind(struct udevice *dev)
|
||||
{
|
||||
dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_pmu_probe(struct udevice *dev)
|
||||
{
|
||||
ofnode node;
|
||||
struct exynos_pmu *priv;
|
||||
|
||||
priv = dev_get_priv(dev);
|
||||
priv->dev = dev;
|
||||
|
||||
node = dev_ofnode(dev);
|
||||
priv->regmap = syscon_node_to_regmap(node);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
|
||||
priv->pmu_data = (struct exynos_pmu_data *)dev_get_driver_data(dev);
|
||||
if (priv->pmu_data && priv->pmu_data->pmu_init)
|
||||
return priv->pmu_data->pmu_init(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id exynos_pmu_ids[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos850-pmu",
|
||||
.data = (ulong)&exynos850_pmu_data
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(exynos_pmu) = {
|
||||
.name = "exynos-pmu",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = exynos_pmu_ids,
|
||||
.bind = exynos_pmu_bind,
|
||||
.probe = exynos_pmu_probe,
|
||||
.priv_auto = sizeof(struct exynos_pmu),
|
||||
};
|
Loading…
Add table
Reference in a new issue