blob: 1cface7f610bdc34baa09a8c892bf96f002125b3 [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
9#include <common.h>
10#include <dm.h>
11#include <errno.h>
12#include <asm/io.h>
Sumit Gargb7572e52022-07-27 13:52:04 +053013#include <dm/device_compat.h>
Caleb Connolly506eb532023-11-14 12:55:40 +000014#include <dm/device-internal.h>
Sumit Gargb7572e52022-07-27 13:52:04 +053015#include <dm/lists.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 Connolly506eb532023-11-14 12:55:40 +000018#include "pinctrl-qcom.h"
Ramon Friede43d8e72018-05-16 12:13:40 +030019
20struct msm_pinctrl_priv {
21 phys_addr_t base;
22 struct msm_pinctrl_data *data;
23};
24
25#define GPIO_CONFIG_OFFSET(x) ((x) * 0x1000)
26#define TLMM_GPIO_PULL_MASK GENMASK(1, 0)
27#define TLMM_FUNC_SEL_MASK GENMASK(5, 2)
28#define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6)
Ramon Fried772a99a2019-01-12 11:47:27 +020029#define TLMM_GPIO_DISABLE BIT(9)
Ramon Friede43d8e72018-05-16 12:13:40 +030030
31static const struct pinconf_param msm_conf_params[] = {
Sumit Gargfd1ad932023-02-01 19:28:52 +053032 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
Ramon Friede43d8e72018-05-16 12:13:40 +030033 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
Sumit Gargfd1ad932023-02-01 19:28:52 +053034 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
Ramon Friede43d8e72018-05-16 12:13:40 +030035};
36
37static int msm_get_functions_count(struct udevice *dev)
38{
39 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
40
41 return priv->data->functions_count;
42}
43
44static int msm_get_pins_count(struct udevice *dev)
45{
46 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
47
48 return priv->data->pin_count;
49}
50
51static const char *msm_get_function_name(struct udevice *dev,
52 unsigned int selector)
53{
54 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
55
56 return priv->data->get_function_name(dev, selector);
57}
58
59static int msm_pinctrl_probe(struct udevice *dev)
60{
61 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
62
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +090063 priv->base = dev_read_addr(dev);
Ramon Friede43d8e72018-05-16 12:13:40 +030064 priv->data = (struct msm_pinctrl_data *)dev->driver_data;
65
66 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
67}
68
69static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector)
70{
71 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
72
73 return priv->data->get_pin_name(dev, selector);
74}
75
76static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
77 unsigned int func_selector)
78{
79 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
80
81 clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
Ramon Fried772a99a2019-01-12 11:47:27 +020082 TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE,
Ramon Friede43d8e72018-05-16 12:13:40 +030083 priv->data->get_function_mux(func_selector) << 2);
84 return 0;
85}
86
87static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
88 unsigned int param, unsigned int argument)
89{
90 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
91
92 switch (param) {
93 case PIN_CONFIG_DRIVE_STRENGTH:
Sumit Gargfd1ad932023-02-01 19:28:52 +053094 argument = (argument / 2) - 1;
Ramon Friede43d8e72018-05-16 12:13:40 +030095 clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
96 TLMM_DRV_STRENGTH_MASK, argument << 6);
97 break;
98 case PIN_CONFIG_BIAS_DISABLE:
99 clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
100 TLMM_GPIO_PULL_MASK);
101 break;
Sumit Gargfd1ad932023-02-01 19:28:52 +0530102 case PIN_CONFIG_BIAS_PULL_UP:
103 clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
104 TLMM_GPIO_PULL_MASK, argument);
105 break;
Ramon Friede43d8e72018-05-16 12:13:40 +0300106 default:
107 return 0;
108 }
109
110 return 0;
111}
112
Caleb Connolly506eb532023-11-14 12:55:40 +0000113struct pinctrl_ops msm_pinctrl_ops = {
Ramon Friede43d8e72018-05-16 12:13:40 +0300114 .get_pins_count = msm_get_pins_count,
115 .get_pin_name = msm_get_pin_name,
116 .set_state = pinctrl_generic_set_state,
117 .pinmux_set = msm_pinmux_set,
118 .pinconf_num_params = ARRAY_SIZE(msm_conf_params),
119 .pinconf_params = msm_conf_params,
120 .pinconf_set = msm_pinconf_set,
121 .get_functions_count = msm_get_functions_count,
122 .get_function_name = msm_get_function_name,
123};
124
Caleb Connolly506eb532023-11-14 12:55:40 +0000125int msm_pinctrl_bind(struct udevice *dev)
Sumit Gargb7572e52022-07-27 13:52:04 +0530126{
127 ofnode node = dev_ofnode(dev);
Caleb Connolly506eb532023-11-14 12:55:40 +0000128 struct msm_pinctrl_data *data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
129 struct driver *drv;
130 struct udevice *pinctrl_dev;
Sumit Gargb7572e52022-07-27 13:52:04 +0530131 const char *name;
132 int ret;
133
Caleb Connolly506eb532023-11-14 12:55:40 +0000134 drv = lists_driver_lookup_name("pinctrl_qcom");
135 if (!drv)
136 return -ENOENT;
137
138 ret = device_bind_with_driver_data(dev_get_parent(dev), drv, ofnode_get_name(node), (ulong)data,
139 dev_ofnode(dev), &pinctrl_dev);
140 if (ret)
141 return ret;
142
Sumit Gargb7572e52022-07-27 13:52:04 +0530143 ofnode_get_property(node, "gpio-controller", &ret);
144 if (ret < 0)
145 return 0;
146
147 /* Get the name of gpio node */
148 name = ofnode_get_name(node);
149 if (!name)
150 return -EINVAL;
151
152 /* Bind gpio node */
153 ret = device_bind_driver_to_node(dev, "gpio_msm",
154 name, node, NULL);
Caleb Connolly506eb532023-11-14 12:55:40 +0000155 if (ret) {
156 device_unbind(pinctrl_dev);
Sumit Gargb7572e52022-07-27 13:52:04 +0530157 return ret;
Caleb Connolly506eb532023-11-14 12:55:40 +0000158 }
Sumit Gargb7572e52022-07-27 13:52:04 +0530159
160 return 0;
161}
162
Caleb Connolly506eb532023-11-14 12:55:40 +0000163U_BOOT_DRIVER(pinctrl_qcom) = {
164 .name = "pinctrl_qcom",
Ramon Friede43d8e72018-05-16 12:13:40 +0300165 .id = UCLASS_PINCTRL,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700166 .priv_auto = sizeof(struct msm_pinctrl_priv),
Ramon Friede43d8e72018-05-16 12:13:40 +0300167 .ops = &msm_pinctrl_ops,
168 .probe = msm_pinctrl_probe,
Ramon Friede43d8e72018-05-16 12:13:40 +0300169};