File Index
Files and directories
Sign in
FILE

pinctrl-amdisp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pinctrl/pinctrl-amdisp.c C
  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
 21static const u32 gpio_offset[] = {
 22	GPIO_OFFSET_0,
 23	GPIO_OFFSET_1,
 24	GPIO_OFFSET_2
 25};
 26
 27struct 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
 36static 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
 45struct 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
 56static 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
 63static 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
 71static 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
 83const 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
 89static 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
 95static int amdisp_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
 96{
 97	return -EOPNOTSUPP;
 98}
 99
100static 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
107static 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
120static 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
138static 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
175static 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
221static struct platform_driver amdisp_pinctrl_driver = {
222	.driver = {
223		.name = DRV_NAME,
224	},
225	.probe = amdisp_pinctrl_probe,
226};
227module_platform_driver(amdisp_pinctrl_driver);
228
229MODULE_AUTHOR("Benjamin Chan <benjamin.chan@amd.com>");
230MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>");
231MODULE_DESCRIPTION("AMDISP pinctrl driver");
232MODULE_LICENSE("GPL v2");
233MODULE_ALIAS("platform:" DRV_NAME);
~/ Read-only file preview.