xref: /linux/drivers/pinctrl/pinctrl-amdisp.c (revision 0227b49b50276657243e54f5609e65c4f0eaaf4d)
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