brintos

brintos / linux-shallow public Read only

0
0
Text · 8.3 KiB · a042317 Raw
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, &reg_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, &reg_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