Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.17-rc4 233 lines 5.9 kB view raw
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);