blob: 5e57b0cbde75b934ad84c78d81246d581a99d601 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +02002/*
3 * Qualcomm GPIO driver
4 *
5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +02006 */
7
8#include <common.h>
9#include <dm.h>
10#include <errno.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020012#include <asm/gpio.h>
13#include <asm/io.h>
Caleb Connollyfabb8972023-11-14 12:55:42 +000014#include <mach/gpio.h>
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020015
16DECLARE_GLOBAL_DATA_PTR;
17
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020018/* OE */
19#define GPIO_OE_DISABLE (0x0 << 9)
20#define GPIO_OE_ENABLE (0x1 << 9)
21#define GPIO_OE_MASK (0x1 << 9)
22
23/* GPIO_IN_OUT register shifts. */
24#define GPIO_IN 0
25#define GPIO_OUT 1
26
27struct msm_gpio_bank {
28 phys_addr_t base;
Caleb Connollyfabb8972023-11-14 12:55:42 +000029 const struct msm_pin_data *pin_data;
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020030};
31
Caleb Connollyfabb8972023-11-14 12:55:42 +000032#define GPIO_CONFIG_REG(dev, x) \
33 (qcom_pin_offset(((struct msm_gpio_bank *)dev_get_priv(dev))->pin_data->pin_offsets, x))
34
35#define GPIO_IN_OUT_REG(dev, x) \
36 (GPIO_CONFIG_REG(dev, x) + 0x4)
37
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020038static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
39{
40 struct msm_gpio_bank *priv = dev_get_priv(dev);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020041
Caleb Connolly190005c2024-02-26 17:26:17 +000042 /* Always NOP for special pins, assume they're in the correct state */
43 if (qcom_is_special_pin(priv->pin_data, gpio))
44 return 0;
45
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020046 /* Disable OE bit */
Caleb Connollyfabb8972023-11-14 12:55:42 +000047 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
48 GPIO_OE_MASK, GPIO_OE_DISABLE);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020049
50 return 0;
51}
52
Caleb Connolly8fff7eb2023-11-14 12:55:43 +000053static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020054{
55 struct msm_gpio_bank *priv = dev_get_priv(dev);
56
Caleb Connolly190005c2024-02-26 17:26:17 +000057 /* Always NOP for special pins, assume they're in the correct state */
58 if (qcom_is_special_pin(priv->pin_data, gpio))
59 return 0;
60
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020061 value = !!value;
62 /* set value */
Caleb Connollyfabb8972023-11-14 12:55:42 +000063 writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020064
65 return 0;
66}
67
Caleb Connolly8fff7eb2023-11-14 12:55:43 +000068static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020069 int value)
70{
71 struct msm_gpio_bank *priv = dev_get_priv(dev);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020072
Caleb Connolly190005c2024-02-26 17:26:17 +000073 /* Always NOP for special pins, assume they're in the correct state */
74 if (qcom_is_special_pin(priv->pin_data, gpio))
75 return 0;
76
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020077 value = !!value;
78 /* set value */
Caleb Connollyfabb8972023-11-14 12:55:42 +000079 writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020080 /* switch direction */
Caleb Connollyfabb8972023-11-14 12:55:42 +000081 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
82 GPIO_OE_MASK, GPIO_OE_ENABLE);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020083
84 return 0;
85}
86
Caleb Connolly8fff7eb2023-11-14 12:55:43 +000087static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020088{
89 struct msm_gpio_bank *priv = dev_get_priv(dev);
90
Caleb Connolly190005c2024-02-26 17:26:17 +000091 /* Always NOP for special pins, assume they're in the correct state */
92 if (qcom_is_special_pin(priv->pin_data, gpio))
93 return 0;
94
Caleb Connollyfabb8972023-11-14 12:55:42 +000095 return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020096}
97
Caleb Connolly8fff7eb2023-11-14 12:55:43 +000098static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio)
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +020099{
100 struct msm_gpio_bank *priv = dev_get_priv(dev);
101
Caleb Connolly190005c2024-02-26 17:26:17 +0000102 /* Always NOP for special pins, assume they're in the correct state */
103 if (qcom_is_special_pin(priv->pin_data, gpio))
104 return 0;
105
Caleb Connollyfabb8972023-11-14 12:55:42 +0000106 if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200107 return GPIOF_OUTPUT;
108
109 return GPIOF_INPUT;
110}
111
112static const struct dm_gpio_ops gpio_msm_ops = {
113 .direction_input = msm_gpio_direction_input,
114 .direction_output = msm_gpio_direction_output,
115 .get_value = msm_gpio_get_value,
116 .set_value = msm_gpio_set_value,
117 .get_function = msm_gpio_get_function,
118};
119
120static int msm_gpio_probe(struct udevice *dev)
121{
122 struct msm_gpio_bank *priv = dev_get_priv(dev);
123
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900124 priv->base = dev_read_addr(dev);
Caleb Connollyfabb8972023-11-14 12:55:42 +0000125 priv->pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200126
127 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
128}
129
Simon Glassaad29ae2020-12-03 16:55:21 -0700130static int msm_gpio_of_to_plat(struct udevice *dev)
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200131{
132 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Caleb Connollyfabb8972023-11-14 12:55:42 +0000133 const struct msm_pin_data *pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200134
Caleb Connollyfabb8972023-11-14 12:55:42 +0000135 /* Get the pin count from the pinctrl driver */
136 uc_priv->gpio_count = pin_data->pin_count;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700137 uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200138 "gpio-bank-name", NULL);
139 if (uc_priv->bank_name == NULL)
140 uc_priv->bank_name = "soc";
141
142 return 0;
143}
144
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200145U_BOOT_DRIVER(gpio_msm) = {
146 .name = "gpio_msm",
147 .id = UCLASS_GPIO,
Simon Glassaad29ae2020-12-03 16:55:21 -0700148 .of_to_plat = msm_gpio_of_to_plat,
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200149 .probe = msm_gpio_probe,
150 .ops = &gpio_msm_ops,
Sumit Gargb7572e52022-07-27 13:52:04 +0530151 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700152 .priv_auto = sizeof(struct msm_gpio_bank),
Mateusz Kulikowskia1b3ae92016-03-31 23:12:15 +0200153};