]>
Commit | Line | Data |
---|---|---|
7e589bc1 SG |
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> | |
f7ae49fc | 10 | #include <log.h> |
7e589bc1 SG |
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 | ||
b840c395 | 43 | pcr_clrsetbits32(pinctrl, config_offset, |
7e589bc1 | 44 | PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | |
28c62680 | 45 | PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE, |
7e589bc1 SG |
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) | |
ea86e725 | 63 | return reg & PAD_CFG0_RX_STATE ? 1 : 0; |
7e589bc1 | 64 | else if (rx_tx == PAD_CFG0_RX_DISABLE) |
ea86e725 | 65 | return reg & PAD_CFG0_TX_STATE ? 1 : 0; |
7e589bc1 SG |
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 | ||
b840c395 | 76 | pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_TX_STATE, |
7e589bc1 SG |
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 | }; |