1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * AMD ISP Pinctrl Driver
4 *
5 * Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
6 *
7 */
8
9 #include <linux/gpio/driver.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12
13 #include "pinctrl-amdisp.h"
14
15 #define DRV_NAME "amdisp-pinctrl"
16 #define GPIO_CONTROL_PIN 4
17 #define GPIO_OFFSET_0 0x0
18 #define GPIO_OFFSET_1 0x4
19 #define GPIO_OFFSET_2 0x50
20
21 static const u32 gpio_offset[] = {
22 GPIO_OFFSET_0,
23 GPIO_OFFSET_1,
24 GPIO_OFFSET_2
25 };
26
27 struct amdisp_pinctrl_data {
28 const struct pinctrl_pin_desc *pins;
29 unsigned int npins;
30 const struct amdisp_function *functions;
31 unsigned int nfunctions;
32 const struct amdisp_pingroup *groups;
33 unsigned int ngroups;
34 };
35
36 static const struct amdisp_pinctrl_data amdisp_pinctrl_data = {
37 .pins = amdisp_pins,
38 .npins = ARRAY_SIZE(amdisp_pins),
39 .functions = amdisp_functions,
40 .nfunctions = ARRAY_SIZE(amdisp_functions),
41 .groups = amdisp_groups,
42 .ngroups = ARRAY_SIZE(amdisp_groups),
43 };
44
45 struct amdisp_pinctrl {
46 struct device *dev;
47 struct pinctrl_dev *pctrl;
48 struct pinctrl_desc desc;
49 struct pinctrl_gpio_range gpio_range;
50 struct gpio_chip gc;
51 const struct amdisp_pinctrl_data *data;
52 void __iomem *gpiobase;
53 raw_spinlock_t lock;
54 };
55
amdisp_get_groups_count(struct pinctrl_dev * pctldev)56 static int amdisp_get_groups_count(struct pinctrl_dev *pctldev)
57 {
58 struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
59
60 return pctrl->data->ngroups;
61 }
62
amdisp_get_group_name(struct pinctrl_dev * pctldev,unsigned int group)63 static const char *amdisp_get_group_name(struct pinctrl_dev *pctldev,
64 unsigned int group)
65 {
66 struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
67
68 return pctrl->data->groups[group].name;
69 }
70
amdisp_get_group_pins(struct pinctrl_dev * pctldev,unsigned int group,const unsigned int ** pins,unsigned int * num_pins)71 static int amdisp_get_group_pins(struct pinctrl_dev *pctldev,
72 unsigned int group,
73 const unsigned int **pins,
74 unsigned int *num_pins)
75 {
76 struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
77
78 *pins = pctrl->data->groups[group].pins;
79 *num_pins = pctrl->data->groups[group].npins;
80 return 0;
81 }
82
83 const struct pinctrl_ops amdisp_pinctrl_ops = {
84 .get_groups_count = amdisp_get_groups_count,
85 .get_group_name = amdisp_get_group_name,
86 .get_group_pins = amdisp_get_group_pins,
87 };
88
amdisp_gpio_get_direction(struct gpio_chip * gc,unsigned int gpio)89 static int amdisp_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
90 {
91 /* amdisp gpio only has output mode */
92 return GPIO_LINE_DIRECTION_OUT;
93 }
94
amdisp_gpio_direction_input(struct gpio_chip * gc,unsigned int gpio)95 static int amdisp_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
96 {
97 return -EOPNOTSUPP;
98 }
99
amdisp_gpio_direction_output(struct gpio_chip * gc,unsigned int gpio,int value)100 static int amdisp_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
101 int value)
102 {
103 /* Nothing to do, amdisp gpio only has output mode */
104 return 0;
105 }
106
amdisp_gpio_get(struct gpio_chip * gc,unsigned int gpio)107 static int amdisp_gpio_get(struct gpio_chip *gc, unsigned int gpio)
108 {
109 unsigned long flags;
110 u32 pin_reg;
111 struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
112
113 raw_spin_lock_irqsave(&pctrl->lock, flags);
114 pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
115 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
116
117 return !!(pin_reg & BIT(GPIO_CONTROL_PIN));
118 }
119
amdisp_gpio_set(struct gpio_chip * gc,unsigned int gpio,int value)120 static void amdisp_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
121 {
122 unsigned long flags;
123 u32 pin_reg;
124 struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
125
126 raw_spin_lock_irqsave(&pctrl->lock, flags);
127 pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
128 if (value)
129 pin_reg |= BIT(GPIO_CONTROL_PIN);
130 else
131 pin_reg &= ~BIT(GPIO_CONTROL_PIN);
132 writel(pin_reg, pctrl->gpiobase + gpio_offset[gpio]);
133 raw_spin_unlock_irqrestore(&pctrl->lock, flags);
134 }
135
amdisp_gpiochip_add(struct platform_device * pdev,struct amdisp_pinctrl * pctrl)136 static int amdisp_gpiochip_add(struct platform_device *pdev,
137 struct amdisp_pinctrl *pctrl)
138 {
139 struct gpio_chip *gc = &pctrl->gc;
140 struct pinctrl_gpio_range *grange = &pctrl->gpio_range;
141 int ret;
142
143 gc->label = dev_name(pctrl->dev);
144 gc->parent = &pdev->dev;
145 gc->names = amdisp_range_pins_name;
146 gc->request = gpiochip_generic_request;
147 gc->free = gpiochip_generic_free;
148 gc->get_direction = amdisp_gpio_get_direction;
149 gc->direction_input = amdisp_gpio_direction_input;
150 gc->direction_output = amdisp_gpio_direction_output;
151 gc->get = amdisp_gpio_get;
152 gc->set = amdisp_gpio_set;
153 gc->base = -1;
154 gc->ngpio = ARRAY_SIZE(amdisp_range_pins);
155
156 grange->id = 0;
157 grange->pin_base = 0;
158 grange->base = 0;
159 grange->pins = amdisp_range_pins;
160 grange->npins = ARRAY_SIZE(amdisp_range_pins);
161 grange->name = gc->label;
162 grange->gc = gc;
163
164 ret = devm_gpiochip_add_data(&pdev->dev, gc, pctrl);
165 if (ret)
166 return ret;
167
168 pinctrl_add_gpio_range(pctrl->pctrl, grange);
169
170 return 0;
171 }
172
amdisp_pinctrl_probe(struct platform_device * pdev)173 static int amdisp_pinctrl_probe(struct platform_device *pdev)
174 {
175 struct amdisp_pinctrl *pctrl;
176 struct resource *res;
177 int ret;
178
179 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
180 if (!pctrl)
181 return -ENOMEM;
182
183 pdev->dev.init_name = DRV_NAME;
184
185 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
186 if (!res)
187 return -EINVAL;
188
189 pctrl->gpiobase = devm_ioremap_resource(&pdev->dev, res);
190 if (IS_ERR(pctrl->gpiobase))
191 return PTR_ERR(pctrl->gpiobase);
192
193 platform_set_drvdata(pdev, pctrl);
194
195 pctrl->dev = &pdev->dev;
196 pctrl->data = &amdisp_pinctrl_data;
197 pctrl->desc.owner = THIS_MODULE;
198 pctrl->desc.pctlops = &amdisp_pinctrl_ops;
199 pctrl->desc.pmxops = NULL;
200 pctrl->desc.name = dev_name(&pdev->dev);
201 pctrl->desc.pins = pctrl->data->pins;
202 pctrl->desc.npins = pctrl->data->npins;
203 ret = devm_pinctrl_register_and_init(&pdev->dev, &pctrl->desc,
204 pctrl, &pctrl->pctrl);
205 if (ret)
206 return ret;
207
208 ret = pinctrl_enable(pctrl->pctrl);
209 if (ret)
210 return ret;
211
212 ret = amdisp_gpiochip_add(pdev, pctrl);
213 if (ret)
214 return ret;
215
216 return 0;
217 }
218
219 static struct platform_driver amdisp_pinctrl_driver = {
220 .driver = {
221 .name = DRV_NAME,
222 },
223 .probe = amdisp_pinctrl_probe,
224 };
225 module_platform_driver(amdisp_pinctrl_driver);
226
227 MODULE_AUTHOR("Benjamin Chan <benjamin.chan@amd.com>");
228 MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>");
229 MODULE_DESCRIPTION("AMDISP pinctrl driver");
230 MODULE_LICENSE("GPL v2");
231 MODULE_ALIAS("platform:" DRV_NAME);
232