345 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Conexant Digicolor General Purpose Pin Mapping4 *5 * Author: Baruch Siach <baruch@tkos.co.il>6 *7 * Copyright (C) 2015 Paradox Innovation Ltd.8 *9 * TODO:10 * - GPIO interrupt support11 * - Pin pad configuration (pull up/down, strength)12 */13 14#include <linux/gpio/driver.h>15#include <linux/init.h>16#include <linux/io.h>17#include <linux/mod_devicetable.h>18#include <linux/platform_device.h>19#include <linux/spinlock.h>20 21#include <linux/pinctrl/machine.h>22#include <linux/pinctrl/pinconf.h>23#include <linux/pinctrl/pinconf-generic.h>24#include <linux/pinctrl/pinctrl.h>25#include <linux/pinctrl/pinmux.h>26 27#include "pinctrl-utils.h"28 29#define DRIVER_NAME "pinctrl-digicolor"30 31#define GP_CLIENTSEL(clct) ((clct)*8 + 0x20)32#define GP_DRIVE0(clct) (GP_CLIENTSEL(clct) + 2)33#define GP_OUTPUT0(clct) (GP_CLIENTSEL(clct) + 3)34#define GP_INPUT(clct) (GP_CLIENTSEL(clct) + 6)35 36#define PIN_COLLECTIONS ('R' - 'A' + 1)37#define PINS_PER_COLLECTION 838#define PINS_COUNT (PIN_COLLECTIONS * PINS_PER_COLLECTION)39 40struct dc_pinmap {41 void __iomem *regs;42 struct device *dev;43 struct pinctrl_dev *pctl;44 45 struct pinctrl_desc *desc;46 const char *pin_names[PINS_COUNT];47 48 struct gpio_chip chip;49 spinlock_t lock;50};51 52static int dc_get_groups_count(struct pinctrl_dev *pctldev)53{54 return PINS_COUNT;55}56 57static const char *dc_get_group_name(struct pinctrl_dev *pctldev,58 unsigned selector)59{60 struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);61 62 /* Exactly one group per pin */63 return pmap->desc->pins[selector].name;64}65 66static int dc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,67 const unsigned **pins,68 unsigned *num_pins)69{70 struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);71 72 *pins = &pmap->desc->pins[selector].number;73 *num_pins = 1;74 75 return 0;76}77 78static const struct pinctrl_ops dc_pinctrl_ops = {79 .get_groups_count = dc_get_groups_count,80 .get_group_name = dc_get_group_name,81 .get_group_pins = dc_get_group_pins,82 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,83 .dt_free_map = pinctrl_utils_free_map,84};85 86static const char *const dc_functions[] = {87 "gpio",88 "client_a",89 "client_b",90 "client_c",91};92 93static int dc_get_functions_count(struct pinctrl_dev *pctldev)94{95 return ARRAY_SIZE(dc_functions);96}97 98static const char *dc_get_fname(struct pinctrl_dev *pctldev, unsigned selector)99{100 return dc_functions[selector];101}102 103static int dc_get_groups(struct pinctrl_dev *pctldev, unsigned selector,104 const char * const **groups,105 unsigned * const num_groups)106{107 struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);108 109 *groups = pmap->pin_names;110 *num_groups = PINS_COUNT;111 112 return 0;113}114 115static void dc_client_sel(int pin_num, int *reg, int *bit)116{117 *bit = (pin_num % PINS_PER_COLLECTION) * 2;118 *reg = GP_CLIENTSEL(pin_num/PINS_PER_COLLECTION);119 120 if (*bit >= PINS_PER_COLLECTION) {121 *bit -= PINS_PER_COLLECTION;122 *reg += 1;123 }124}125 126static int dc_set_mux(struct pinctrl_dev *pctldev, unsigned selector,127 unsigned group)128{129 struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pctldev);130 int bit_off, reg_off;131 u8 reg;132 133 dc_client_sel(group, ®_off, &bit_off);134 135 reg = readb_relaxed(pmap->regs + reg_off);136 reg &= ~(3 << bit_off);137 reg |= (selector << bit_off);138 writeb_relaxed(reg, pmap->regs + reg_off);139 140 return 0;141}142 143static int dc_pmx_request_gpio(struct pinctrl_dev *pcdev,144 struct pinctrl_gpio_range *range,145 unsigned offset)146{147 struct dc_pinmap *pmap = pinctrl_dev_get_drvdata(pcdev);148 int bit_off, reg_off;149 u8 reg;150 151 dc_client_sel(offset, ®_off, &bit_off);152 153 reg = readb_relaxed(pmap->regs + reg_off);154 if ((reg & (3 << bit_off)) != 0)155 return -EBUSY;156 157 return 0;158}159 160static const struct pinmux_ops dc_pmxops = {161 .get_functions_count = dc_get_functions_count,162 .get_function_name = dc_get_fname,163 .get_function_groups = dc_get_groups,164 .set_mux = dc_set_mux,165 .gpio_request_enable = dc_pmx_request_gpio,166};167 168static int dc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)169{170 struct dc_pinmap *pmap = gpiochip_get_data(chip);171 int reg_off = GP_DRIVE0(gpio/PINS_PER_COLLECTION);172 int bit_off = gpio % PINS_PER_COLLECTION;173 u8 drive;174 unsigned long flags;175 176 spin_lock_irqsave(&pmap->lock, flags);177 drive = readb_relaxed(pmap->regs + reg_off);178 drive &= ~BIT(bit_off);179 writeb_relaxed(drive, pmap->regs + reg_off);180 spin_unlock_irqrestore(&pmap->lock, flags);181 182 return 0;183}184 185static void dc_gpio_set(struct gpio_chip *chip, unsigned gpio, int value);186 187static int dc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,188 int value)189{190 struct dc_pinmap *pmap = gpiochip_get_data(chip);191 int reg_off = GP_DRIVE0(gpio/PINS_PER_COLLECTION);192 int bit_off = gpio % PINS_PER_COLLECTION;193 u8 drive;194 unsigned long flags;195 196 dc_gpio_set(chip, gpio, value);197 198 spin_lock_irqsave(&pmap->lock, flags);199 drive = readb_relaxed(pmap->regs + reg_off);200 drive |= BIT(bit_off);201 writeb_relaxed(drive, pmap->regs + reg_off);202 spin_unlock_irqrestore(&pmap->lock, flags);203 204 return 0;205}206 207static int dc_gpio_get(struct gpio_chip *chip, unsigned gpio)208{209 struct dc_pinmap *pmap = gpiochip_get_data(chip);210 int reg_off = GP_INPUT(gpio/PINS_PER_COLLECTION);211 int bit_off = gpio % PINS_PER_COLLECTION;212 u8 input;213 214 input = readb_relaxed(pmap->regs + reg_off);215 216 return !!(input & BIT(bit_off));217}218 219static void dc_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)220{221 struct dc_pinmap *pmap = gpiochip_get_data(chip);222 int reg_off = GP_OUTPUT0(gpio/PINS_PER_COLLECTION);223 int bit_off = gpio % PINS_PER_COLLECTION;224 u8 output;225 unsigned long flags;226 227 spin_lock_irqsave(&pmap->lock, flags);228 output = readb_relaxed(pmap->regs + reg_off);229 if (value)230 output |= BIT(bit_off);231 else232 output &= ~BIT(bit_off);233 writeb_relaxed(output, pmap->regs + reg_off);234 spin_unlock_irqrestore(&pmap->lock, flags);235}236 237static int dc_gpiochip_add(struct dc_pinmap *pmap)238{239 struct gpio_chip *chip = &pmap->chip;240 int ret;241 242 chip->label = DRIVER_NAME;243 chip->parent = pmap->dev;244 chip->request = gpiochip_generic_request;245 chip->free = gpiochip_generic_free;246 chip->direction_input = dc_gpio_direction_input;247 chip->direction_output = dc_gpio_direction_output;248 chip->get = dc_gpio_get;249 chip->set = dc_gpio_set;250 chip->base = -1;251 chip->ngpio = PINS_COUNT;252 253 spin_lock_init(&pmap->lock);254 255 ret = gpiochip_add_data(chip, pmap);256 if (ret < 0)257 return ret;258 259 ret = gpiochip_add_pin_range(chip, dev_name(pmap->dev), 0, 0,260 PINS_COUNT);261 if (ret < 0) {262 gpiochip_remove(chip);263 return ret;264 }265 266 return 0;267}268 269static int dc_pinctrl_probe(struct platform_device *pdev)270{271 struct dc_pinmap *pmap;272 struct pinctrl_pin_desc *pins;273 struct pinctrl_desc *pctl_desc;274 char *pin_names;275 int name_len = strlen("GP_xx") + 1;276 int i, j;277 278 pmap = devm_kzalloc(&pdev->dev, sizeof(*pmap), GFP_KERNEL);279 if (!pmap)280 return -ENOMEM;281 282 pmap->regs = devm_platform_ioremap_resource(pdev, 0);283 if (IS_ERR(pmap->regs))284 return PTR_ERR(pmap->regs);285 286 pins = devm_kcalloc(&pdev->dev, PINS_COUNT, sizeof(*pins),287 GFP_KERNEL);288 if (!pins)289 return -ENOMEM;290 pin_names = devm_kcalloc(&pdev->dev, PINS_COUNT, name_len,291 GFP_KERNEL);292 if (!pin_names)293 return -ENOMEM;294 295 for (i = 0; i < PIN_COLLECTIONS; i++) {296 for (j = 0; j < PINS_PER_COLLECTION; j++) {297 int pin_id = i*PINS_PER_COLLECTION + j;298 char *name = &pin_names[pin_id * name_len];299 300 snprintf(name, name_len, "GP_%c%c", 'A'+i, '0'+j);301 302 pins[pin_id].number = pin_id;303 pins[pin_id].name = name;304 pmap->pin_names[pin_id] = name;305 }306 }307 308 pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);309 if (!pctl_desc)310 return -ENOMEM;311 312 pctl_desc->name = DRIVER_NAME,313 pctl_desc->owner = THIS_MODULE,314 pctl_desc->pctlops = &dc_pinctrl_ops,315 pctl_desc->pmxops = &dc_pmxops,316 pctl_desc->npins = PINS_COUNT;317 pctl_desc->pins = pins;318 pmap->desc = pctl_desc;319 320 pmap->dev = &pdev->dev;321 322 pmap->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, pmap);323 if (IS_ERR(pmap->pctl)) {324 dev_err(&pdev->dev, "pinctrl driver registration failed\n");325 return PTR_ERR(pmap->pctl);326 }327 328 return dc_gpiochip_add(pmap);329}330 331static const struct of_device_id dc_pinctrl_ids[] = {332 { .compatible = "cnxt,cx92755-pinctrl" },333 { /* sentinel */ }334};335 336static struct platform_driver dc_pinctrl_driver = {337 .driver = {338 .name = DRIVER_NAME,339 .of_match_table = dc_pinctrl_ids,340 .suppress_bind_attrs = true,341 },342 .probe = dc_pinctrl_probe,343};344builtin_platform_driver(dc_pinctrl_driver);345