Prepare v2024.10
[platform/kernel/u-boot.git] / drivers / gpio / bcm2835_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2012 Vikram Narayananan
4  * <vikram186@gmail.com>
5  */
6
7 #include <dm.h>
8 #include <dm/pinctrl.h>
9 #include <errno.h>
10 #include <asm/gpio.h>
11 #include <asm/io.h>
12 #include <fdtdec.h>
13
14 struct bcm2835_gpios {
15         struct bcm2835_gpio_regs *reg;
16         struct udevice *pinctrl;
17 };
18
19 static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
20 {
21         struct bcm2835_gpios *gpios = dev_get_priv(dev);
22         unsigned val;
23
24         val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
25         val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
26         val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
27         writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
28
29         return 0;
30 }
31
32 static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio,
33                                          int value)
34 {
35         struct bcm2835_gpios *gpios = dev_get_priv(dev);
36         unsigned val;
37
38         gpio_set_value(gpio, value);
39
40         val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
41         val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
42         val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
43         writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
44
45         return 0;
46 }
47
48 static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio)
49 {
50         unsigned val;
51
52         val = readl(&gpios->reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
53
54         return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
55 }
56
57 static int bcm2835_gpio_get_value(struct udevice *dev, unsigned gpio)
58 {
59         const struct bcm2835_gpios *gpios = dev_get_priv(dev);
60
61         return bcm2835_get_value(gpios, gpio);
62 }
63
64 static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio,
65                                   int value)
66 {
67         struct bcm2835_gpios *gpios = dev_get_priv(dev);
68         u32 *output_reg = value ? gpios->reg->gpset : gpios->reg->gpclr;
69
70         writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
71                                 &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
72
73         return 0;
74 }
75
76 static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
77 {
78         struct bcm2835_gpios *priv = dev_get_priv(dev);
79         int funcid;
80
81         funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset);
82
83         switch (funcid) {
84         case BCM2835_GPIO_OUTPUT:
85                 return GPIOF_OUTPUT;
86         case BCM2835_GPIO_INPUT:
87                 return GPIOF_INPUT;
88         default:
89                 return GPIOF_FUNC;
90         }
91 }
92
93 static const struct dm_gpio_ops gpio_bcm2835_ops = {
94         .direction_input        = bcm2835_gpio_direction_input,
95         .direction_output       = bcm2835_gpio_direction_output,
96         .get_value              = bcm2835_gpio_get_value,
97         .set_value              = bcm2835_gpio_set_value,
98         .get_function           = bcm2835_gpio_get_function,
99 };
100
101 static int bcm2835_gpio_probe(struct udevice *dev)
102 {
103         struct bcm2835_gpios *gpios = dev_get_priv(dev);
104         struct bcm2835_gpio_plat *plat = dev_get_plat(dev);
105         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
106
107         uc_priv->bank_name = "GPIO";
108         uc_priv->gpio_count = BCM2835_GPIO_COUNT;
109         gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
110
111         /* We know we're spawned by the pinctrl driver */
112         gpios->pinctrl = dev->parent;
113
114         return 0;
115 }
116
117 #if CONFIG_IS_ENABLED(OF_CONTROL)
118 static int bcm2835_gpio_of_to_plat(struct udevice *dev)
119 {
120         struct bcm2835_gpio_plat *plat = dev_get_plat(dev);
121         fdt_addr_t addr;
122
123         addr = dev_read_addr(dev);
124         if (addr == FDT_ADDR_T_NONE)
125                 return -EINVAL;
126
127         plat->base = addr;
128         return 0;
129 }
130 #endif
131
132 U_BOOT_DRIVER(gpio_bcm2835) = {
133         .name   = "gpio_bcm2835",
134         .id     = UCLASS_GPIO,
135         .of_to_plat = of_match_ptr(bcm2835_gpio_of_to_plat),
136         .plat_auto      = sizeof(struct bcm2835_gpio_plat),
137         .ops    = &gpio_bcm2835_ops,
138         .probe  = bcm2835_gpio_probe,
139         .flags  = DM_FLAG_PRE_RELOC,
140         .priv_auto      = sizeof(struct bcm2835_gpios),
141 };