blob: 3c3336e76358cc61032d430814e31e33f5ef52c7 [file] [log] [blame]
Ramon Friede43d8e72018-05-16 12:13:40 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * TLMM driver for Qualcomm APQ8016, APQ8096
4 *
5 * (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
6 *
7 */
8
Ramon Friede43d8e72018-05-16 12:13:40 +03009#include <dm.h>
10#include <errno.h>
11#include <asm/io.h>
Sumit Gargb7572e52022-07-27 13:52:04 +053012#include <dm/device_compat.h>
Caleb Connolly506eb532023-11-14 12:55:40 +000013#include <dm/device-internal.h>
Sumit Gargb7572e52022-07-27 13:52:04 +053014#include <dm/lists.h>
Caleb Connollyfabb8972023-11-14 12:55:42 +000015#include <asm/gpio.h>
Ramon Friede43d8e72018-05-16 12:13:40 +030016#include <dm/pinctrl.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Caleb Connolly190005c2024-02-26 17:26:17 +000018#include <linux/bug.h>
Caleb Connollyfabb8972023-11-14 12:55:42 +000019#include <mach/gpio.h>
20
Caleb Connolly506eb532023-11-14 12:55:40 +000021#include "pinctrl-qcom.h"
Ramon Friede43d8e72018-05-16 12:13:40 +030022
23struct msm_pinctrl_priv {
24 phys_addr_t base;
25 struct msm_pinctrl_data *data;
26};
27
Caleb Connollyfabb8972023-11-14 12:55:42 +000028#define GPIO_CONFIG_REG(priv, x) \
29 (qcom_pin_offset((priv)->data->pin_data.pin_offsets, x))
30
Sumit Gargadc3bcb2024-04-12 15:24:35 +053031#define GPIO_IN_OUT_REG(priv, x) \
32 (GPIO_CONFIG_REG(priv, x) + 0x4)
33
34#define TLMM_GPIO_PULL_MASK GENMASK(1, 0)
35#define TLMM_FUNC_SEL_MASK GENMASK(5, 2)
36#define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6)
37#define TLMM_GPIO_OUTPUT_MASK BIT(1)
38#define TLMM_GPIO_OE_MASK BIT(9)
39
40/* GPIO register shifts. */
41#define GPIO_OUT_SHIFT 1
Ramon Friede43d8e72018-05-16 12:13:40 +030042
43static const struct pinconf_param msm_conf_params[] = {
Sumit Gargfd1ad932023-02-01 19:28:52 +053044 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
Ramon Friede43d8e72018-05-16 12:13:40 +030045 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
Sumit Gargfd1ad932023-02-01 19:28:52 +053046 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
Sumit Gargadc3bcb2024-04-12 15:24:35 +053047 { "output-high", PIN_CONFIG_OUTPUT, 1, },
48 { "output-low", PIN_CONFIG_OUTPUT, 0, },
Ramon Friede43d8e72018-05-16 12:13:40 +030049};
50
51static int msm_get_functions_count(struct udevice *dev)
52{
53 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
54
55 return priv->data->functions_count;
56}
57
58static int msm_get_pins_count(struct udevice *dev)
59{
60 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
61
Caleb Connollyfabb8972023-11-14 12:55:42 +000062 return priv->data->pin_data.pin_count;
Ramon Friede43d8e72018-05-16 12:13:40 +030063}
64
65static const char *msm_get_function_name(struct udevice *dev,
66 unsigned int selector)
67{
68 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
69
70 return priv->data->get_function_name(dev, selector);
71}
72
73static int msm_pinctrl_probe(struct udevice *dev)
74{
75 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
76
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +090077 priv->base = dev_read_addr(dev);
Caleb Connollyfabb8972023-11-14 12:55:42 +000078 priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
Ramon Friede43d8e72018-05-16 12:13:40 +030079
80 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
81}
82
83static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector)
84{
85 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
86
87 return priv->data->get_pin_name(dev, selector);
88}
89
90static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
91 unsigned int func_selector)
92{
93 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
Volodymyr Babchukc4cc9792024-03-11 21:33:46 +000094 u32 func = priv->data->get_function_mux(pin_selector, func_selector);
Ramon Friede43d8e72018-05-16 12:13:40 +030095
Caleb Connolly190005c2024-02-26 17:26:17 +000096 /* Always NOP for special pins, assume they're in the correct state */
97 if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
98 return 0;
99
Caleb Connollyfabb8972023-11-14 12:55:42 +0000100 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Sumit Gargadc3bcb2024-04-12 15:24:35 +0530101 TLMM_FUNC_SEL_MASK | TLMM_GPIO_OE_MASK, func << 2);
Ramon Friede43d8e72018-05-16 12:13:40 +0300102 return 0;
103}
104
105static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
106 unsigned int param, unsigned int argument)
107{
108 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
109
Caleb Connolly190005c2024-02-26 17:26:17 +0000110 /* Always NOP for special pins */
111 if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
112 return 0;
113
Ramon Friede43d8e72018-05-16 12:13:40 +0300114 switch (param) {
115 case PIN_CONFIG_DRIVE_STRENGTH:
Sumit Gargfd1ad932023-02-01 19:28:52 +0530116 argument = (argument / 2) - 1;
Caleb Connollyfabb8972023-11-14 12:55:42 +0000117 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Ramon Friede43d8e72018-05-16 12:13:40 +0300118 TLMM_DRV_STRENGTH_MASK, argument << 6);
119 break;
120 case PIN_CONFIG_BIAS_DISABLE:
Caleb Connollyfabb8972023-11-14 12:55:42 +0000121 clrbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Ramon Friede43d8e72018-05-16 12:13:40 +0300122 TLMM_GPIO_PULL_MASK);
123 break;
Sumit Gargfd1ad932023-02-01 19:28:52 +0530124 case PIN_CONFIG_BIAS_PULL_UP:
Caleb Connollyfabb8972023-11-14 12:55:42 +0000125 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Sumit Gargfd1ad932023-02-01 19:28:52 +0530126 TLMM_GPIO_PULL_MASK, argument);
127 break;
Sumit Gargadc3bcb2024-04-12 15:24:35 +0530128 case PIN_CONFIG_OUTPUT:
129 writel(argument << GPIO_OUT_SHIFT,
130 priv->base + GPIO_IN_OUT_REG(priv, pin_selector));
131 setbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
132 TLMM_GPIO_OE_MASK);
133 break;
Ramon Friede43d8e72018-05-16 12:13:40 +0300134 default:
135 return 0;
136 }
137
138 return 0;
139}
140
Caleb Connolly506eb532023-11-14 12:55:40 +0000141struct pinctrl_ops msm_pinctrl_ops = {
Ramon Friede43d8e72018-05-16 12:13:40 +0300142 .get_pins_count = msm_get_pins_count,
143 .get_pin_name = msm_get_pin_name,
144 .set_state = pinctrl_generic_set_state,
145 .pinmux_set = msm_pinmux_set,
146 .pinconf_num_params = ARRAY_SIZE(msm_conf_params),
147 .pinconf_params = msm_conf_params,
148 .pinconf_set = msm_pinconf_set,
149 .get_functions_count = msm_get_functions_count,
150 .get_function_name = msm_get_function_name,
151};
152
Caleb Connolly506eb532023-11-14 12:55:40 +0000153int msm_pinctrl_bind(struct udevice *dev)
Sumit Gargb7572e52022-07-27 13:52:04 +0530154{
155 ofnode node = dev_ofnode(dev);
Caleb Connolly506eb532023-11-14 12:55:40 +0000156 struct msm_pinctrl_data *data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
157 struct driver *drv;
158 struct udevice *pinctrl_dev;
Sumit Gargb7572e52022-07-27 13:52:04 +0530159 const char *name;
160 int ret;
161
Caleb Connolly190005c2024-02-26 17:26:17 +0000162 if (!data->pin_data.special_pins_start)
163 dev_warn(dev, "Special pins start index not defined!\n");
164
Caleb Connolly506eb532023-11-14 12:55:40 +0000165 drv = lists_driver_lookup_name("pinctrl_qcom");
166 if (!drv)
167 return -ENOENT;
168
169 ret = device_bind_with_driver_data(dev_get_parent(dev), drv, ofnode_get_name(node), (ulong)data,
170 dev_ofnode(dev), &pinctrl_dev);
171 if (ret)
172 return ret;
173
Sumit Gargb7572e52022-07-27 13:52:04 +0530174 ofnode_get_property(node, "gpio-controller", &ret);
175 if (ret < 0)
176 return 0;
177
178 /* Get the name of gpio node */
179 name = ofnode_get_name(node);
180 if (!name)
181 return -EINVAL;
182
Caleb Connollyfabb8972023-11-14 12:55:42 +0000183 drv = lists_driver_lookup_name("gpio_msm");
184 if (!drv) {
185 printf("Can't find gpio_msm driver\n");
186 return -ENODEV;
187 }
188
189 /* Bind gpio device as a child of the pinctrl device */
190 ret = device_bind_with_driver_data(pinctrl_dev, drv,
191 name, (ulong)&data->pin_data, node, NULL);
Caleb Connolly506eb532023-11-14 12:55:40 +0000192 if (ret) {
193 device_unbind(pinctrl_dev);
Sumit Gargb7572e52022-07-27 13:52:04 +0530194 return ret;
Caleb Connolly506eb532023-11-14 12:55:40 +0000195 }
Sumit Gargb7572e52022-07-27 13:52:04 +0530196
197 return 0;
198}
199
Caleb Connolly506eb532023-11-14 12:55:40 +0000200U_BOOT_DRIVER(pinctrl_qcom) = {
201 .name = "pinctrl_qcom",
Ramon Friede43d8e72018-05-16 12:13:40 +0300202 .id = UCLASS_PINCTRL,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700203 .priv_auto = sizeof(struct msm_pinctrl_priv),
Ramon Friede43d8e72018-05-16 12:13:40 +0300204 .ops = &msm_pinctrl_ops,
205 .probe = msm_pinctrl_probe,
Ramon Friede43d8e72018-05-16 12:13:40 +0300206};