From e54ff9a92f08218f0c1fcb20635d34c87829d05b Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:06:24 +0530 Subject: [PATCH] misc: add sl28cpld base driver Add a multi-function device driver which will probe its children and provides methods to access the device. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- MAINTAINERS | 5 ++ drivers/misc/Kconfig | 8 +++ drivers/misc/Makefile | 1 + drivers/misc/sl28cpld.c | 105 ++++++++++++++++++++++++++++++++++++++++ include/sl28cpld.h | 14 ++++++ 5 files changed, 133 insertions(+) create mode 100644 drivers/misc/sl28cpld.c create mode 100644 include/sl28cpld.h diff --git a/MAINTAINERS b/MAINTAINERS index fb171e0c68..8b3870ff96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1161,6 +1161,11 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git F: arch/sh/ +SL28CLPD +M: Michael Walle +S: Maintained +F: drivers/misc/sl28cpld.c + SPI M: Jagan Teki S: Maintained diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0ade3e32b0..7029bb7b5c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -512,4 +512,12 @@ config ESM_PMIC config FSL_IFC bool +config SL28CPLD + bool "Enable Kontron sl28cpld multi-function driver" + depends on DM_I2C + help + Support for the Kontron sl28cpld management controller. This is + the base driver which provides common access methods for the + sub-drivers. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bca7b24e99..f22eff601a 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -82,3 +82,4 @@ obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_ESM_PMIC) += esm_pmic.o +obj-$(CONFIG_SL28CPLD) += sl28cpld.o diff --git a/drivers/misc/sl28cpld.c b/drivers/misc/sl28cpld.c new file mode 100644 index 0000000000..01ef1c6178 --- /dev/null +++ b/drivers/misc/sl28cpld.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include + +struct sl28cpld_child_plat { + uint offset; +}; + +/* + * The access methods works either with the first argument being a child + * device or with the MFD device itself. + */ +static int sl28cpld_read_child(struct udevice *dev, uint offset) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_read(mfd, offset + plat->offset); +} + +int sl28cpld_read(struct udevice *dev, uint offset) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_read(dev, offset); + else + return sl28cpld_read_child(dev, offset); +} + +static int sl28cpld_write_child(struct udevice *dev, uint offset, + uint8_t value) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_write(mfd, offset + plat->offset, value); +} + +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_write(dev, offset, value); + else + return sl28cpld_write_child(dev, offset, value); +} + +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, + uint8_t set) +{ + int val; + + val = sl28cpld_read(dev, offset); + if (val < 0) + return val; + + val &= ~clear; + val |= set; + + return sl28cpld_write(dev, offset, val); +} + +static int sl28cpld_probe(struct udevice *dev) +{ + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | + DM_I2C_CHIP_WR_ADDRESS); + + return 0; +} + +static int sl28cpld_child_post_bind(struct udevice *dev) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + int offset; + + if (!dev_has_ofnode(dev)) + return 0; + + offset = dev_read_u32_default(dev, "reg", -1); + if (offset == -1) + return -EINVAL; + + plat->offset = offset; + + return 0; +} + +static const struct udevice_id sl28cpld_ids[] = { + { .compatible = "kontron,sl28cpld" }, + {} +}; + +U_BOOT_DRIVER(sl28cpld) = { + .name = "sl28cpld", + .id = UCLASS_NOP, + .of_match = sl28cpld_ids, + .probe = sl28cpld_probe, + .bind = dm_scan_fdt_dev, + .flags = DM_FLAG_PRE_RELOC, + .per_child_plat_auto = sizeof(struct sl28cpld_child_plat), + .child_post_bind = sl28cpld_child_post_bind, +}; diff --git a/include/sl28cpld.h b/include/sl28cpld.h new file mode 100644 index 0000000000..d116607cfb --- /dev/null +++ b/include/sl28cpld.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Michael Walle + */ + +#ifndef __SL28CPLD_H +#define __SL28CPLD_H + +int sl28cpld_read(struct udevice *dev, uint offset); +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value); +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, + uint8_t set); + +#endif -- 2.39.5