]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
81a87e18 MK |
2 | /* |
3 | * Qualcomm GPIO driver | |
4 | * | |
5 | * (C) Copyright 2015 Mateusz Kulikowski <[email protected]> | |
81a87e18 MK |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <dm.h> | |
10 | #include <errno.h> | |
11 | #include <asm/gpio.h> | |
12 | #include <asm/io.h> | |
13 | ||
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
16 | /* Register offsets */ | |
17 | #define GPIO_CONFIG_OFF(no) ((no) * 0x1000) | |
18 | #define GPIO_IN_OUT_OFF(no) ((no) * 0x1000 + 0x4) | |
19 | ||
20 | /* OE */ | |
21 | #define GPIO_OE_DISABLE (0x0 << 9) | |
22 | #define GPIO_OE_ENABLE (0x1 << 9) | |
23 | #define GPIO_OE_MASK (0x1 << 9) | |
24 | ||
25 | /* GPIO_IN_OUT register shifts. */ | |
26 | #define GPIO_IN 0 | |
27 | #define GPIO_OUT 1 | |
28 | ||
29 | struct msm_gpio_bank { | |
30 | phys_addr_t base; | |
31 | }; | |
32 | ||
33 | static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio) | |
34 | { | |
35 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
36 | phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio); | |
37 | ||
38 | /* Disable OE bit */ | |
39 | clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_DISABLE); | |
40 | ||
41 | return 0; | |
42 | } | |
43 | ||
44 | static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value) | |
45 | { | |
46 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
47 | ||
48 | value = !!value; | |
49 | /* set value */ | |
50 | writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio)); | |
51 | ||
52 | return 0; | |
53 | } | |
54 | ||
55 | static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio, | |
56 | int value) | |
57 | { | |
58 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
59 | phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio); | |
60 | ||
61 | value = !!value; | |
62 | /* set value */ | |
63 | writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio)); | |
64 | /* switch direction */ | |
65 | clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_ENABLE); | |
66 | ||
67 | return 0; | |
68 | } | |
69 | ||
70 | static int msm_gpio_get_value(struct udevice *dev, unsigned gpio) | |
71 | { | |
72 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
73 | ||
74 | return !!(readl(priv->base + GPIO_IN_OUT_OFF(gpio)) >> GPIO_IN); | |
75 | } | |
76 | ||
77 | static int msm_gpio_get_function(struct udevice *dev, unsigned offset) | |
78 | { | |
79 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
80 | ||
81 | if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE) | |
82 | return GPIOF_OUTPUT; | |
83 | ||
84 | return GPIOF_INPUT; | |
85 | } | |
86 | ||
87 | static const struct dm_gpio_ops gpio_msm_ops = { | |
88 | .direction_input = msm_gpio_direction_input, | |
89 | .direction_output = msm_gpio_direction_output, | |
90 | .get_value = msm_gpio_get_value, | |
91 | .set_value = msm_gpio_set_value, | |
92 | .get_function = msm_gpio_get_function, | |
93 | }; | |
94 | ||
95 | static int msm_gpio_probe(struct udevice *dev) | |
96 | { | |
97 | struct msm_gpio_bank *priv = dev_get_priv(dev); | |
98 | ||
2548493a | 99 | priv->base = dev_read_addr(dev); |
81a87e18 MK |
100 | |
101 | return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; | |
102 | } | |
103 | ||
104 | static int msm_gpio_ofdata_to_platdata(struct udevice *dev) | |
105 | { | |
106 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
107 | ||
e160f7d4 | 108 | uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), |
81a87e18 | 109 | "gpio-count", 0); |
e160f7d4 | 110 | uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), |
81a87e18 MK |
111 | "gpio-bank-name", NULL); |
112 | if (uc_priv->bank_name == NULL) | |
113 | uc_priv->bank_name = "soc"; | |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | static const struct udevice_id msm_gpio_ids[] = { | |
119 | { .compatible = "qcom,msm8916-pinctrl" }, | |
120 | { .compatible = "qcom,apq8016-pinctrl" }, | |
0c7eb6e5 | 121 | { .compatible = "qcom,ipq4019-pinctrl" }, |
81a87e18 MK |
122 | { } |
123 | }; | |
124 | ||
125 | U_BOOT_DRIVER(gpio_msm) = { | |
126 | .name = "gpio_msm", | |
127 | .id = UCLASS_GPIO, | |
128 | .of_match = msm_gpio_ids, | |
129 | .ofdata_to_platdata = msm_gpio_ofdata_to_platdata, | |
130 | .probe = msm_gpio_probe, | |
131 | .ops = &gpio_msm_ops, | |
41575d8e | 132 | .priv_auto = sizeof(struct msm_gpio_bank), |
81a87e18 | 133 | }; |