blob: dc3d8c4d90347d264a67c0e30d9fc2cb3a0d9799 [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>
Caleb Connollyfabb8972023-11-14 12:55:42 +000016#include <asm/gpio.h>
Ramon Friede43d8e72018-05-16 12:13:40 +030017#include <dm/pinctrl.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.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
Ramon Friede43d8e72018-05-16 12:13:40 +030031#define TLMM_GPIO_PULL_MASK GENMASK(1, 0)
32#define TLMM_FUNC_SEL_MASK GENMASK(5, 2)
33#define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6)
Ramon Fried772a99a2019-01-12 11:47:27 +020034#define TLMM_GPIO_DISABLE BIT(9)
Ramon Friede43d8e72018-05-16 12:13:40 +030035
36static const struct pinconf_param msm_conf_params[] = {
Sumit Gargfd1ad932023-02-01 19:28:52 +053037 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
Ramon Friede43d8e72018-05-16 12:13:40 +030038 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
Sumit Gargfd1ad932023-02-01 19:28:52 +053039 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
Ramon Friede43d8e72018-05-16 12:13:40 +030040};
41
42static int msm_get_functions_count(struct udevice *dev)
43{
44 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
45
46 return priv->data->functions_count;
47}
48
49static int msm_get_pins_count(struct udevice *dev)
50{
51 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
52
Caleb Connollyfabb8972023-11-14 12:55:42 +000053 return priv->data->pin_data.pin_count;
Ramon Friede43d8e72018-05-16 12:13:40 +030054}
55
56static const char *msm_get_function_name(struct udevice *dev,
57 unsigned int selector)
58{
59 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
60
61 return priv->data->get_function_name(dev, selector);
62}
63
64static int msm_pinctrl_probe(struct udevice *dev)
65{
66 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
67
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +090068 priv->base = dev_read_addr(dev);
Caleb Connollyfabb8972023-11-14 12:55:42 +000069 priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
Ramon Friede43d8e72018-05-16 12:13:40 +030070
71 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
72}
73
74static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector)
75{
76 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
77
78 return priv->data->get_pin_name(dev, selector);
79}
80
81static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
82 unsigned int func_selector)
83{
84 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
85
Caleb Connollyfabb8972023-11-14 12:55:42 +000086 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Ramon Fried772a99a2019-01-12 11:47:27 +020087 TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE,
Ramon Friede43d8e72018-05-16 12:13:40 +030088 priv->data->get_function_mux(func_selector) << 2);
89 return 0;
90}
91
92static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
93 unsigned int param, unsigned int argument)
94{
95 struct msm_pinctrl_priv *priv = dev_get_priv(dev);
96
97 switch (param) {
98 case PIN_CONFIG_DRIVE_STRENGTH:
Sumit Gargfd1ad932023-02-01 19:28:52 +053099 argument = (argument / 2) - 1;
Caleb Connollyfabb8972023-11-14 12:55:42 +0000100 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Ramon Friede43d8e72018-05-16 12:13:40 +0300101 TLMM_DRV_STRENGTH_MASK, argument << 6);
102 break;
103 case PIN_CONFIG_BIAS_DISABLE:
Caleb Connollyfabb8972023-11-14 12:55:42 +0000104 clrbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Ramon Friede43d8e72018-05-16 12:13:40 +0300105 TLMM_GPIO_PULL_MASK);
106 break;
Sumit Gargfd1ad932023-02-01 19:28:52 +0530107 case PIN_CONFIG_BIAS_PULL_UP:
Caleb Connollyfabb8972023-11-14 12:55:42 +0000108 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
Sumit Gargfd1ad932023-02-01 19:28:52 +0530109 TLMM_GPIO_PULL_MASK, argument);
110 break;
Ramon Friede43d8e72018-05-16 12:13:40 +0300111 default:
112 return 0;
113 }
114
115 return 0;
116}
117
Caleb Connolly506eb532023-11-14 12:55:40 +0000118struct pinctrl_ops msm_pinctrl_ops = {
Ramon Friede43d8e72018-05-16 12:13:40 +0300119 .get_pins_count = msm_get_pins_count,
120 .get_pin_name = msm_get_pin_name,
121 .set_state = pinctrl_generic_set_state,
122 .pinmux_set = msm_pinmux_set,
123 .pinconf_num_params = ARRAY_SIZE(msm_conf_params),
124 .pinconf_params = msm_conf_params,
125 .pinconf_set = msm_pinconf_set,
126 .get_functions_count = msm_get_functions_count,
127 .get_function_name = msm_get_function_name,
128};
129
Caleb Connolly506eb532023-11-14 12:55:40 +0000130int msm_pinctrl_bind(struct udevice *dev)
Sumit Gargb7572e52022-07-27 13:52:04 +0530131{
132 ofnode node = dev_ofnode(dev);
Caleb Connolly506eb532023-11-14 12:55:40 +0000133 struct msm_pinctrl_data *data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
134 struct driver *drv;
135 struct udevice *pinctrl_dev;
Sumit Gargb7572e52022-07-27 13:52:04 +0530136 const char *name;
137 int ret;
138
Caleb Connolly506eb532023-11-14 12:55:40 +0000139 drv = lists_driver_lookup_name("pinctrl_qcom");
140 if (!drv)
141 return -ENOENT;
142
143 ret = device_bind_with_driver_data(dev_get_parent(dev), drv, ofnode_get_name(node), (ulong)data,
144 dev_ofnode(dev), &pinctrl_dev);
145 if (ret)
146 return ret;
147
Sumit Gargb7572e52022-07-27 13:52:04 +0530148 ofnode_get_property(node, "gpio-controller", &ret);
149 if (ret < 0)
150 return 0;
151
152 /* Get the name of gpio node */
153 name = ofnode_get_name(node);
154 if (!name)
155 return -EINVAL;
156
Caleb Connollyfabb8972023-11-14 12:55:42 +0000157 drv = lists_driver_lookup_name("gpio_msm");
158 if (!drv) {
159 printf("Can't find gpio_msm driver\n");
160 return -ENODEV;
161 }
162
163 /* Bind gpio device as a child of the pinctrl device */
164 ret = device_bind_with_driver_data(pinctrl_dev, drv,
165 name, (ulong)&data->pin_data, node, NULL);
Caleb Connolly506eb532023-11-14 12:55:40 +0000166 if (ret) {
167 device_unbind(pinctrl_dev);
Sumit Gargb7572e52022-07-27 13:52:04 +0530168 return ret;
Caleb Connolly506eb532023-11-14 12:55:40 +0000169 }
Sumit Gargb7572e52022-07-27 13:52:04 +0530170
171 return 0;
172}
173
Caleb Connolly506eb532023-11-14 12:55:40 +0000174U_BOOT_DRIVER(pinctrl_qcom) = {
175 .name = "pinctrl_qcom",
Ramon Friede43d8e72018-05-16 12:13:40 +0300176 .id = UCLASS_PINCTRL,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700177 .priv_auto = sizeof(struct msm_pinctrl_priv),
Ramon Friede43d8e72018-05-16 12:13:40 +0300178 .ops = &msm_pinctrl_ops,
179 .probe = msm_pinctrl_probe,
Ramon Friede43d8e72018-05-16 12:13:40 +0300180};