4 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
6 * SPDX-License-Identifier: GPL-2.0+
15 DECLARE_GLOBAL_DATA_PTR
;
17 /* Register offsets */
18 #define GPIO_CONFIG_OFF(no) ((no) * 0x1000)
19 #define GPIO_IN_OUT_OFF(no) ((no) * 0x1000 + 0x4)
22 #define GPIO_OE_DISABLE (0x0 << 9)
23 #define GPIO_OE_ENABLE (0x1 << 9)
24 #define GPIO_OE_MASK (0x1 << 9)
26 /* GPIO_IN_OUT register shifts. */
30 struct msm_gpio_bank
{
34 static int msm_gpio_direction_input(struct udevice
*dev
, unsigned int gpio
)
36 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
37 phys_addr_t reg
= priv
->base
+ GPIO_CONFIG_OFF(gpio
);
40 clrsetbits_le32(reg
, GPIO_OE_MASK
, GPIO_OE_DISABLE
);
45 static int msm_gpio_set_value(struct udevice
*dev
, unsigned gpio
, int value
)
47 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
51 writel(value
<< GPIO_OUT
, priv
->base
+ GPIO_IN_OUT_OFF(gpio
));
56 static int msm_gpio_direction_output(struct udevice
*dev
, unsigned gpio
,
59 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
60 phys_addr_t reg
= priv
->base
+ GPIO_CONFIG_OFF(gpio
);
64 writel(value
<< GPIO_OUT
, priv
->base
+ GPIO_IN_OUT_OFF(gpio
));
65 /* switch direction */
66 clrsetbits_le32(reg
, GPIO_OE_MASK
, GPIO_OE_ENABLE
);
71 static int msm_gpio_get_value(struct udevice
*dev
, unsigned gpio
)
73 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
75 return !!(readl(priv
->base
+ GPIO_IN_OUT_OFF(gpio
)) >> GPIO_IN
);
78 static int msm_gpio_get_function(struct udevice
*dev
, unsigned offset
)
80 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
82 if (readl(priv
->base
+ GPIO_CONFIG_OFF(offset
)) & GPIO_OE_ENABLE
)
88 static const struct dm_gpio_ops gpio_msm_ops
= {
89 .direction_input
= msm_gpio_direction_input
,
90 .direction_output
= msm_gpio_direction_output
,
91 .get_value
= msm_gpio_get_value
,
92 .set_value
= msm_gpio_set_value
,
93 .get_function
= msm_gpio_get_function
,
96 static int msm_gpio_probe(struct udevice
*dev
)
98 struct msm_gpio_bank
*priv
= dev_get_priv(dev
);
100 priv
->base
= dev_get_addr(dev
);
102 return priv
->base
== FDT_ADDR_T_NONE
? -EINVAL
: 0;
105 static int msm_gpio_ofdata_to_platdata(struct udevice
*dev
)
107 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
109 uc_priv
->gpio_count
= fdtdec_get_int(gd
->fdt_blob
, dev_of_offset(dev
),
111 uc_priv
->bank_name
= fdt_getprop(gd
->fdt_blob
, dev_of_offset(dev
),
112 "gpio-bank-name", NULL
);
113 if (uc_priv
->bank_name
== NULL
)
114 uc_priv
->bank_name
= "soc";
119 static const struct udevice_id msm_gpio_ids
[] = {
120 { .compatible
= "qcom,msm8916-pinctrl" },
121 { .compatible
= "qcom,apq8016-pinctrl" },
125 U_BOOT_DRIVER(gpio_msm
) = {
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
,
132 .priv_auto_alloc_size
= sizeof(struct msm_gpio_bank
),