blob: 80cd28bb231fc70f46614d7487ea4d737b429a92 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +02002/*
3 * Qualcomm GPIO driver
4 *
5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +02006 */
7
8#include <common.h>
9#include <dm.h>
10#include <errno.h>
Simon Glass401d1c42020-10-30 21:38:53 -060011#include <asm/global_data.h>
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020012#include <asm/gpio.h>
13#include <asm/io.h>
Caleb Connollya5764ae2023-11-14 12:55:42 +000014#include <mach/gpio.h>
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020015
16DECLARE_GLOBAL_DATA_PTR;
17
Mateusz Kulikowski81a87e12016-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 Connollya5764ae2023-11-14 12:55:42 +000029 const struct msm_pin_data *pin_data;
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020030};
31
Caleb Connollya5764ae2023-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 Kulikowski81a87e12016-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 Kulikowski81a87e12016-03-31 23:12:15 +020041
42 /* Disable OE bit */
Caleb Connollya5764ae2023-11-14 12:55:42 +000043 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
44 GPIO_OE_MASK, GPIO_OE_DISABLE);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020045
46 return 0;
47}
48
Caleb Connollye3195392023-11-14 12:55:43 +000049static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020050{
51 struct msm_gpio_bank *priv = dev_get_priv(dev);
52
53 value = !!value;
54 /* set value */
Caleb Connollya5764ae2023-11-14 12:55:42 +000055 writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020056
57 return 0;
58}
59
Caleb Connollye3195392023-11-14 12:55:43 +000060static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020061 int value)
62{
63 struct msm_gpio_bank *priv = dev_get_priv(dev);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020064
65 value = !!value;
66 /* set value */
Caleb Connollya5764ae2023-11-14 12:55:42 +000067 writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio));
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020068 /* switch direction */
Caleb Connollya5764ae2023-11-14 12:55:42 +000069 clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
70 GPIO_OE_MASK, GPIO_OE_ENABLE);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020071
72 return 0;
73}
74
Caleb Connollye3195392023-11-14 12:55:43 +000075static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020076{
77 struct msm_gpio_bank *priv = dev_get_priv(dev);
78
Caleb Connollya5764ae2023-11-14 12:55:42 +000079 return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020080}
81
Caleb Connollye3195392023-11-14 12:55:43 +000082static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio)
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020083{
84 struct msm_gpio_bank *priv = dev_get_priv(dev);
85
Caleb Connollya5764ae2023-11-14 12:55:42 +000086 if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +020087 return GPIOF_OUTPUT;
88
89 return GPIOF_INPUT;
90}
91
92static const struct dm_gpio_ops gpio_msm_ops = {
93 .direction_input = msm_gpio_direction_input,
94 .direction_output = msm_gpio_direction_output,
95 .get_value = msm_gpio_get_value,
96 .set_value = msm_gpio_set_value,
97 .get_function = msm_gpio_get_function,
98};
99
100static int msm_gpio_probe(struct udevice *dev)
101{
102 struct msm_gpio_bank *priv = dev_get_priv(dev);
103
Masahiro Yamada25484932020-07-17 14:36:48 +0900104 priv->base = dev_read_addr(dev);
Caleb Connollya5764ae2023-11-14 12:55:42 +0000105 priv->pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200106
107 return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
108}
109
Simon Glassd1998a92020-12-03 16:55:21 -0700110static int msm_gpio_of_to_plat(struct udevice *dev)
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200111{
112 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Caleb Connollya5764ae2023-11-14 12:55:42 +0000113 const struct msm_pin_data *pin_data = (struct msm_pin_data *)dev_get_driver_data(dev);
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200114
Caleb Connollya5764ae2023-11-14 12:55:42 +0000115 /* Get the pin count from the pinctrl driver */
116 uc_priv->gpio_count = pin_data->pin_count;
Simon Glasse160f7d2017-01-17 16:52:55 -0700117 uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200118 "gpio-bank-name", NULL);
119 if (uc_priv->bank_name == NULL)
120 uc_priv->bank_name = "soc";
121
122 return 0;
123}
124
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200125U_BOOT_DRIVER(gpio_msm) = {
126 .name = "gpio_msm",
127 .id = UCLASS_GPIO,
Simon Glassd1998a92020-12-03 16:55:21 -0700128 .of_to_plat = msm_gpio_of_to_plat,
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200129 .probe = msm_gpio_probe,
130 .ops = &gpio_msm_ops,
Sumit Garg0ddabb62022-07-27 13:52:04 +0530131 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glass41575d82020-12-03 16:55:17 -0700132 .priv_auto = sizeof(struct msm_gpio_bank),
Mateusz Kulikowski81a87e12016-03-31 23:12:15 +0200133};