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