drivers: pinctrl: Add Qualcomm Milos TLMM driver

Add support for TLMM pin controller block (Top Level Mode Multiplexer)
on Milos SoC, with support for special pins.

Correct pin configuration is required for working debug UART and eMMC/SD
cards.

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
Link: https://patch.msgid.link/20260318-milos-bringup-v2-1-650b91dd75d8@fairphone.com
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
This commit is contained in:
Luca Weiss 2026-03-18 13:46:27 +01:00 committed by Casey Connolly
parent 16a16b55ce
commit 8e4fd3d1c3
3 changed files with 112 additions and 0 deletions

View File

@ -54,6 +54,14 @@ config PINCTRL_QCOM_IPQ9574
Say Y here to enable support for pinctrl on the IPQ9574 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_MILOS
bool "Qualcomm Milos Pinctrl"
default y if PINCTRL_QCOM_GENERIC
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon Milos SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_QCM2290
bool "Qualcomm QCM2290 Pinctrl"
default y if PINCTRL_QCOM_GENERIC

View File

@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_QCOM_IPQ4019) += pinctrl-ipq4019.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ5424) += pinctrl-ipq5424.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o
obj-$(CONFIG_PINCTRL_QCOM_MILOS) += pinctrl-milos.o
obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o
obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o
obj-$(CONFIG_PINCTRL_QCOM_QCS615) += pinctrl-qcs615.o

View File

@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Qualcomm Milos pinctrl
*
* (C) Copyright 2024 Linaro Ltd.
* (C) Copyright 2026 Luca Weiss <luca.weiss@fairphone.com>
*
*/
#include <dm.h>
#include "pinctrl-qcom.h"
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
static const struct pinctrl_function msm_pinctrl_functions[] = {
{"qup0_se5", 1},
{"sdc2_clk", 1},
{"sdc2_cmd", 1},
{"sdc2_data", 1},
{"gpio", 0},
};
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
.name = pg_name, \
.ctl_reg = ctl, \
.io_reg = 0, \
.pull_bit = pull, \
.drv_bit = drv, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = -1, \
}
#define UFS_RESET(pg_name, ctl, io) \
{ \
.name = pg_name, \
.ctl_reg = ctl, \
.io_reg = io, \
.pull_bit = 3, \
.drv_bit = 0, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = 0, \
}
static const struct msm_special_pin_data msm_special_pins_data[] = {
[0] = UFS_RESET("ufs_reset", 0xb4004, 0xb5000),
[1] = SDC_QDSD_PINGROUP("sdc2_clk", 0xab000, 0, 6),
[2] = SDC_QDSD_PINGROUP("sdc2_cmd", 0xab000, 12, 3),
[3] = SDC_QDSD_PINGROUP("sdc2_data", 0xab000, 9, 0),
};
static const char *milos_get_function_name(struct udevice *dev,
unsigned int selector)
{
return msm_pinctrl_functions[selector].name;
}
static const char *milos_get_pin_name(struct udevice *dev,
unsigned int selector)
{
if (selector >= 167 && selector <= 170)
snprintf(pin_name, MAX_PIN_NAME_LEN,
msm_special_pins_data[selector - 167].name);
else
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
return pin_name;
}
static int milos_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}
static struct msm_pinctrl_data milos_data = {
.pin_data = {
.pin_count = 171,
.special_pins_start = 167,
.special_pins_data = msm_special_pins_data,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = milos_get_function_name,
.get_function_mux = milos_get_function_mux,
.get_pin_name = milos_get_pin_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{ .compatible = "qcom,milos-tlmm", .data = (ulong)&milos_data },
{ /* Sentinel */ }
};
U_BOOT_DRIVER(pinctrl_milos) = {
.name = "pinctrl_milos",
.id = UCLASS_NOP,
.of_match = msm_pinctrl_ids,
.ops = &msm_pinctrl_ops,
.bind = msm_pinctrl_bind,
};