colibri_imx6: fix video stdout in default environment
[oweals/u-boot.git] / drivers / gpio / intel_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Google LLC
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <fdtdec.h>
10 #include <log.h>
11 #include <p2sb.h>
12 #include <pch.h>
13 #include <pci.h>
14 #include <syscon.h>
15 #include <asm/cpu.h>
16 #include <asm/gpio.h>
17 #include <asm/intel_pinctrl.h>
18 #include <asm/intel_pinctrl_defs.h>
19 #include <asm/io.h>
20 #include <asm/pci.h>
21 #include <asm/arch/gpio.h>
22 #include <dt-bindings/gpio/x86-gpio.h>
23
24 static int intel_gpio_direction_input(struct udevice *dev, uint offset)
25 {
26         struct udevice *pinctrl = dev_get_parent(dev);
27         uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset);
28
29         pcr_clrsetbits32(pinctrl, config_offset,
30                          PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE |
31                                   PAD_CFG0_RX_DISABLE,
32                          PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE);
33
34         return 0;
35 }
36
37 static int intel_gpio_direction_output(struct udevice *dev, uint offset,
38                                        int value)
39 {
40         struct udevice *pinctrl = dev_get_parent(dev);
41         uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset);
42
43         pcr_clrsetbits32(pinctrl, config_offset,
44                          PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
45                                   PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
46                          PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
47                                   (value ? PAD_CFG0_TX_STATE : 0));
48
49         return 0;
50 }
51
52 static int intel_gpio_get_value(struct udevice *dev, uint offset)
53 {
54         struct udevice *pinctrl = dev_get_parent(dev);
55         uint mode, rx_tx;
56         u32 reg;
57
58         reg = intel_pinctrl_get_config_reg(pinctrl, offset);
59         mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT;
60         if (!mode) {
61                 rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE);
62                 if (rx_tx == PAD_CFG0_TX_DISABLE)
63                         return reg & PAD_CFG0_RX_STATE ? 1 : 0;
64                 else if (rx_tx == PAD_CFG0_RX_DISABLE)
65                         return reg & PAD_CFG0_TX_STATE ? 1 : 0;
66         }
67
68         return 0;
69 }
70
71 static int intel_gpio_set_value(struct udevice *dev, unsigned offset, int value)
72 {
73         struct udevice *pinctrl = dev_get_parent(dev);
74         uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset);
75
76         pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_TX_STATE,
77                          value ? PAD_CFG0_TX_STATE : 0);
78
79         return 0;
80 }
81
82 static int intel_gpio_get_function(struct udevice *dev, uint offset)
83 {
84         struct udevice *pinctrl = dev_get_parent(dev);
85         uint mode, rx_tx;
86         u32 reg;
87
88         reg = intel_pinctrl_get_config_reg(pinctrl, offset);
89         mode = (reg & PAD_CFG0_MODE_MASK) >> PAD_CFG0_MODE_SHIFT;
90         if (!mode) {
91                 rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE);
92                 if (rx_tx == PAD_CFG0_TX_DISABLE)
93                         return GPIOF_INPUT;
94                 else if (rx_tx == PAD_CFG0_RX_DISABLE)
95                         return GPIOF_OUTPUT;
96         }
97
98         return GPIOF_FUNC;
99 }
100
101 static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc,
102                             struct ofnode_phandle_args *args)
103 {
104         struct udevice *pinctrl, *dev;
105         int gpio, ret;
106
107         /*
108          * GPIO numbers are global in the device tree so it doesn't matter
109          * which one is used
110          */
111         gpio = args->args[0];
112         ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset);
113         if (ret)
114                 return log_msg_ret("bad", ret);
115         device_find_first_child(pinctrl, &dev);
116         if (!dev)
117                 return log_msg_ret("no child", -ENOENT);
118         desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
119         desc->dev = dev;
120
121         return 0;
122 }
123
124 static int intel_gpio_probe(struct udevice *dev)
125 {
126         return 0;
127 }
128
129 static int intel_gpio_ofdata_to_platdata(struct udevice *dev)
130 {
131         struct gpio_dev_priv *upriv = dev_get_uclass_priv(dev);
132         struct intel_pinctrl_priv *pinctrl_priv = dev_get_priv(dev->parent);
133         const struct pad_community *comm = pinctrl_priv->comm;
134
135         upriv->gpio_count = comm->last_pad - comm->first_pad + 1;
136         upriv->bank_name = dev->name;
137
138         return 0;
139 }
140
141 static const struct dm_gpio_ops gpio_intel_ops = {
142         .direction_input        = intel_gpio_direction_input,
143         .direction_output       = intel_gpio_direction_output,
144         .get_value              = intel_gpio_get_value,
145         .set_value              = intel_gpio_set_value,
146         .get_function           = intel_gpio_get_function,
147         .xlate                  = intel_gpio_xlate,
148 };
149
150 static const struct udevice_id intel_intel_gpio_ids[] = {
151         { .compatible = "intel,gpio" },
152         { }
153 };
154
155 U_BOOT_DRIVER(gpio_intel) = {
156         .name   = "gpio_intel",
157         .id     = UCLASS_GPIO,
158         .of_match = intel_intel_gpio_ids,
159         .ops    = &gpio_intel_ops,
160         .ofdata_to_platdata     = intel_gpio_ofdata_to_platdata,
161         .probe  = intel_gpio_probe,
162 };