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 int 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 return 0;
136 }
137
amdisp_gpiochip_add(struct platform_device * pdev,struct amdisp_pinctrl * pctrl)138 static int amdisp_gpiochip_add(struct platform_device *pdev,
139 struct amdisp_pinctrl *pctrl)
140 {
141 struct gpio_chip *gc = &pctrl->gc;
142 struct pinctrl_gpio_range *grange = &pctrl->gpio_range;
143 int ret;
144
145 gc->label = dev_name(pctrl->dev);
146 gc->parent = &pdev->dev;
147 gc->names = amdisp_range_pins_name;
148 gc->request = gpiochip_generic_request;
149 gc->free = gpiochip_generic_free;
150 gc->get_direction = amdisp_gpio_get_direction;
151 gc->direction_input = amdisp_gpio_direction_input;
152 gc->direction_output = amdisp_gpio_direction_output;
153 gc->get = amdisp_gpio_get;
154 gc->set = amdisp_gpio_set;
155 gc->base = -1;
156 gc->ngpio = ARRAY_SIZE(amdisp_range_pins);
157
158 grange->id = 0;
159 grange->pin_base = 0;
160 grange->base = 0;
161 grange->pins = amdisp_range_pins;
162 grange->npins = ARRAY_SIZE(amdisp_range_pins);
163 grange->name = gc->label;
164 grange->gc = gc;
165
166 ret = devm_gpiochip_add_data(&pdev->dev, gc, pctrl);
167 if (ret)
168 return ret;
169
170 pinctrl_add_gpio_range(pctrl->pctrl, grange);
171
172 return 0;
173 }
174
amdisp_pinctrl_probe(struct platform_device * pdev)175 static int amdisp_pinctrl_probe(struct platform_device *pdev)
176 {
177 struct amdisp_pinctrl *pctrl;
178 struct resource *res;
179 int ret;
180
181 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
182 if (!pctrl)
183 return -ENOMEM;
184
185 pdev->dev.init_name = DRV_NAME;
186
187 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
188 if (!res)
189 return -EINVAL;
190
191 pctrl->gpiobase = devm_ioremap_resource(&pdev->dev, res);
192 if (IS_ERR(pctrl->gpiobase))
193 return PTR_ERR(pctrl->gpiobase);
194
195 platform_set_drvdata(pdev, pctrl);
196
197 pctrl->dev = &pdev->dev;
198 pctrl->data = &amdisp_pinctrl_data;
199 pctrl->desc.owner = THIS_MODULE;
200 pctrl->desc.pctlops = &amdisp_pinctrl_ops;
201 pctrl->desc.pmxops = NULL;
202 pctrl->desc.name = dev_name(&pdev->dev);
203 pctrl->desc.pins = pctrl->data->pins;
204 pctrl->desc.npins = pctrl->data->npins;
205 ret = devm_pinctrl_register_and_init(&pdev->dev, &pctrl->desc,
206 pctrl, &pctrl->pctrl);
207 if (ret)
208 return ret;
209
210 ret = pinctrl_enable(pctrl->pctrl);
211 if (ret)
212 return ret;
213
214 ret = amdisp_gpiochip_add(pdev, pctrl);
215 if (ret)
216 return ret;
217
218 return 0;
219 }
220
221 static struct platform_driver amdisp_pinctrl_driver = {
222 .driver = {
223 .name = DRV_NAME,
224 },
225 .probe = amdisp_pinctrl_probe,
226 };
227 module_platform_driver(amdisp_pinctrl_driver);
228
229 MODULE_AUTHOR("Benjamin Chan <benjamin.chan@amd.com>");
230 MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>");
231 MODULE_DESCRIPTION("AMDISP pinctrl driver");
232 MODULE_LICENSE("GPL v2");
233 MODULE_ALIAS("platform:" DRV_NAME);
234