brintos

brintos / linux-shallow public Read only

0
0
Text · 14.2 KiB · c097e31 Raw
547 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * GPIO driver for LPC32xx SoC4 *5 * Author: Kevin Wells <kevin.wells@nxp.com>6 *7 * Copyright (C) 2010 NXP Semiconductors8 */9 10#include <linux/kernel.h>11#include <linux/init.h>12#include <linux/io.h>13#include <linux/errno.h>14#include <linux/gpio/driver.h>15#include <linux/of.h>16#include <linux/platform_device.h>17#include <linux/module.h>18 19#define LPC32XX_GPIO_P3_INP_STATE		(0x000)20#define LPC32XX_GPIO_P3_OUTP_SET		(0x004)21#define LPC32XX_GPIO_P3_OUTP_CLR		(0x008)22#define LPC32XX_GPIO_P3_OUTP_STATE		(0x00C)23#define LPC32XX_GPIO_P2_DIR_SET			(0x010)24#define LPC32XX_GPIO_P2_DIR_CLR			(0x014)25#define LPC32XX_GPIO_P2_DIR_STATE		(0x018)26#define LPC32XX_GPIO_P2_INP_STATE		(0x01C)27#define LPC32XX_GPIO_P2_OUTP_SET		(0x020)28#define LPC32XX_GPIO_P2_OUTP_CLR		(0x024)29#define LPC32XX_GPIO_P2_MUX_SET			(0x028)30#define LPC32XX_GPIO_P2_MUX_CLR			(0x02C)31#define LPC32XX_GPIO_P2_MUX_STATE		(0x030)32#define LPC32XX_GPIO_P0_INP_STATE		(0x040)33#define LPC32XX_GPIO_P0_OUTP_SET		(0x044)34#define LPC32XX_GPIO_P0_OUTP_CLR		(0x048)35#define LPC32XX_GPIO_P0_OUTP_STATE		(0x04C)36#define LPC32XX_GPIO_P0_DIR_SET			(0x050)37#define LPC32XX_GPIO_P0_DIR_CLR			(0x054)38#define LPC32XX_GPIO_P0_DIR_STATE		(0x058)39#define LPC32XX_GPIO_P1_INP_STATE		(0x060)40#define LPC32XX_GPIO_P1_OUTP_SET		(0x064)41#define LPC32XX_GPIO_P1_OUTP_CLR		(0x068)42#define LPC32XX_GPIO_P1_OUTP_STATE		(0x06C)43#define LPC32XX_GPIO_P1_DIR_SET			(0x070)44#define LPC32XX_GPIO_P1_DIR_CLR			(0x074)45#define LPC32XX_GPIO_P1_DIR_STATE		(0x078)46 47#define GPIO012_PIN_TO_BIT(x)			(1 << (x))48#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))49#define GPO3_PIN_TO_BIT(x)			(1 << (x))50#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)51#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))52#define GPIO3_PIN_IN_SEL(x, y)			(((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)53#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)54#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)55#define GPO3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)56 57#define LPC32XX_GPIO_P0_MAX	858#define LPC32XX_GPIO_P1_MAX	2459#define LPC32XX_GPIO_P2_MAX	1360#define LPC32XX_GPIO_P3_MAX	661#define LPC32XX_GPI_P3_MAX	2962#define LPC32XX_GPO_P3_MAX	2463 64#define LPC32XX_GPIO_P0_GRP	065#define LPC32XX_GPIO_P1_GRP	(LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)66#define LPC32XX_GPIO_P2_GRP	(LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)67#define LPC32XX_GPIO_P3_GRP	(LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)68#define LPC32XX_GPI_P3_GRP	(LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)69#define LPC32XX_GPO_P3_GRP	(LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)70 71struct gpio_regs {72	unsigned long inp_state;73	unsigned long outp_state;74	unsigned long outp_set;75	unsigned long outp_clr;76	unsigned long dir_set;77	unsigned long dir_clr;78};79 80/*81 * GPIO names82 */83static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {84	"p0.0", "p0.1", "p0.2", "p0.3",85	"p0.4", "p0.5", "p0.6", "p0.7"86};87 88static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {89	"p1.0", "p1.1", "p1.2", "p1.3",90	"p1.4", "p1.5", "p1.6", "p1.7",91	"p1.8", "p1.9", "p1.10", "p1.11",92	"p1.12", "p1.13", "p1.14", "p1.15",93	"p1.16", "p1.17", "p1.18", "p1.19",94	"p1.20", "p1.21", "p1.22", "p1.23",95};96 97static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {98	"p2.0", "p2.1", "p2.2", "p2.3",99	"p2.4", "p2.5", "p2.6", "p2.7",100	"p2.8", "p2.9", "p2.10", "p2.11",101	"p2.12"102};103 104static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {105	"gpio00", "gpio01", "gpio02", "gpio03",106	"gpio04", "gpio05"107};108 109static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {110	"gpi00", "gpi01", "gpi02", "gpi03",111	"gpi04", "gpi05", "gpi06", "gpi07",112	"gpi08", "gpi09",  NULL,    NULL,113	 NULL,    NULL,    NULL,   "gpi15",114	"gpi16", "gpi17", "gpi18", "gpi19",115	"gpi20", "gpi21", "gpi22", "gpi23",116	"gpi24", "gpi25", "gpi26", "gpi27",117	"gpi28"118};119 120static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {121	"gpo00", "gpo01", "gpo02", "gpo03",122	"gpo04", "gpo05", "gpo06", "gpo07",123	"gpo08", "gpo09", "gpo10", "gpo11",124	"gpo12", "gpo13", "gpo14", "gpo15",125	"gpo16", "gpo17", "gpo18", "gpo19",126	"gpo20", "gpo21", "gpo22", "gpo23"127};128 129static struct gpio_regs gpio_grp_regs_p0 = {130	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,131	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,132	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,133	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,134	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,135};136 137static struct gpio_regs gpio_grp_regs_p1 = {138	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,139	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,140	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,141	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,142	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,143};144 145static struct gpio_regs gpio_grp_regs_p2 = {146	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,147	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,148	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,149	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,150	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,151};152 153static struct gpio_regs gpio_grp_regs_p3 = {154	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,155	.outp_state	= LPC32XX_GPIO_P3_OUTP_STATE,156	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,157	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,158	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,159	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,160};161 162struct lpc32xx_gpio_chip {163	struct gpio_chip	chip;164	struct gpio_regs	*gpio_grp;165	void __iomem		*reg_base;166};167 168static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)169{170	return __raw_readl(group->reg_base + offset);171}172 173static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)174{175	__raw_writel(val, group->reg_base + offset);176}177 178static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,179	unsigned pin, int input)180{181	if (input)182		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),183			group->gpio_grp->dir_clr);184	else185		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),186			group->gpio_grp->dir_set);187}188 189static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,190	unsigned pin, int input)191{192	u32 u = GPIO3_PIN_TO_BIT(pin);193 194	if (input)195		gpreg_write(group, u, group->gpio_grp->dir_clr);196	else197		gpreg_write(group, u, group->gpio_grp->dir_set);198}199 200static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,201	unsigned pin, int high)202{203	if (high)204		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),205			group->gpio_grp->outp_set);206	else207		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),208			group->gpio_grp->outp_clr);209}210 211static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,212	unsigned pin, int high)213{214	u32 u = GPIO3_PIN_TO_BIT(pin);215 216	if (high)217		gpreg_write(group, u, group->gpio_grp->outp_set);218	else219		gpreg_write(group, u, group->gpio_grp->outp_clr);220}221 222static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,223	unsigned pin, int high)224{225	if (high)226		gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);227	else228		gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);229}230 231static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,232	unsigned pin)233{234	return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),235		pin);236}237 238static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,239	unsigned pin)240{241	int state = gpreg_read(group, group->gpio_grp->inp_state);242 243	/*244	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped245	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.246	 */247	return GPIO3_PIN_IN_SEL(state, pin);248}249 250static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,251	unsigned pin)252{253	return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);254}255 256static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,257	unsigned pin)258{259	return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);260}261 262/*263 * GPIO primitives.264 */265static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,266	unsigned pin)267{268	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);269 270	__set_gpio_dir_p012(group, pin, 1);271 272	return 0;273}274 275static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,276	unsigned pin)277{278	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);279 280	__set_gpio_dir_p3(group, pin, 1);281 282	return 0;283}284 285static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,286	unsigned pin)287{288	return 0;289}290 291static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)292{293	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);294 295	return !!__get_gpio_state_p012(group, pin);296}297 298static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)299{300	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);301 302	return !!__get_gpio_state_p3(group, pin);303}304 305static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)306{307	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);308 309	return !!__get_gpi_state_p3(group, pin);310}311 312static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,313	int value)314{315	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);316 317	__set_gpio_level_p012(group, pin, value);318	__set_gpio_dir_p012(group, pin, 0);319 320	return 0;321}322 323static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,324	int value)325{326	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);327 328	__set_gpio_level_p3(group, pin, value);329	__set_gpio_dir_p3(group, pin, 0);330 331	return 0;332}333 334static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,335	int value)336{337	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);338 339	__set_gpo_level_p3(group, pin, value);340	return 0;341}342 343static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,344	int value)345{346	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);347 348	__set_gpio_level_p012(group, pin, value);349}350 351static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,352	int value)353{354	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);355 356	__set_gpio_level_p3(group, pin, value);357}358 359static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,360	int value)361{362	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);363 364	__set_gpo_level_p3(group, pin, value);365}366 367static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)368{369	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);370 371	return !!__get_gpo_state_p3(group, pin);372}373 374static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)375{376	if (pin < chip->ngpio)377		return 0;378 379	return -EINVAL;380}381 382static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)383{384	return -ENXIO;385}386 387static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)388{389	return -ENXIO;390}391 392static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)393{394	return -ENXIO;395}396 397static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {398	{399		.chip = {400			.label			= "gpio_p0",401			.direction_input	= lpc32xx_gpio_dir_input_p012,402			.get			= lpc32xx_gpio_get_value_p012,403			.direction_output	= lpc32xx_gpio_dir_output_p012,404			.set			= lpc32xx_gpio_set_value_p012,405			.request		= lpc32xx_gpio_request,406			.to_irq			= lpc32xx_gpio_to_irq_p01,407			.base			= LPC32XX_GPIO_P0_GRP,408			.ngpio			= LPC32XX_GPIO_P0_MAX,409			.names			= gpio_p0_names,410			.can_sleep		= false,411		},412		.gpio_grp = &gpio_grp_regs_p0,413	},414	{415		.chip = {416			.label			= "gpio_p1",417			.direction_input	= lpc32xx_gpio_dir_input_p012,418			.get			= lpc32xx_gpio_get_value_p012,419			.direction_output	= lpc32xx_gpio_dir_output_p012,420			.set			= lpc32xx_gpio_set_value_p012,421			.request		= lpc32xx_gpio_request,422			.to_irq			= lpc32xx_gpio_to_irq_p01,423			.base			= LPC32XX_GPIO_P1_GRP,424			.ngpio			= LPC32XX_GPIO_P1_MAX,425			.names			= gpio_p1_names,426			.can_sleep		= false,427		},428		.gpio_grp = &gpio_grp_regs_p1,429	},430	{431		.chip = {432			.label			= "gpio_p2",433			.direction_input	= lpc32xx_gpio_dir_input_p012,434			.get			= lpc32xx_gpio_get_value_p012,435			.direction_output	= lpc32xx_gpio_dir_output_p012,436			.set			= lpc32xx_gpio_set_value_p012,437			.request		= lpc32xx_gpio_request,438			.base			= LPC32XX_GPIO_P2_GRP,439			.ngpio			= LPC32XX_GPIO_P2_MAX,440			.names			= gpio_p2_names,441			.can_sleep		= false,442		},443		.gpio_grp = &gpio_grp_regs_p2,444	},445	{446		.chip = {447			.label			= "gpio_p3",448			.direction_input	= lpc32xx_gpio_dir_input_p3,449			.get			= lpc32xx_gpio_get_value_p3,450			.direction_output	= lpc32xx_gpio_dir_output_p3,451			.set			= lpc32xx_gpio_set_value_p3,452			.request		= lpc32xx_gpio_request,453			.to_irq			= lpc32xx_gpio_to_irq_gpio_p3,454			.base			= LPC32XX_GPIO_P3_GRP,455			.ngpio			= LPC32XX_GPIO_P3_MAX,456			.names			= gpio_p3_names,457			.can_sleep		= false,458		},459		.gpio_grp = &gpio_grp_regs_p3,460	},461	{462		.chip = {463			.label			= "gpi_p3",464			.direction_input	= lpc32xx_gpio_dir_in_always,465			.get			= lpc32xx_gpi_get_value,466			.request		= lpc32xx_gpio_request,467			.to_irq			= lpc32xx_gpio_to_irq_gpi_p3,468			.base			= LPC32XX_GPI_P3_GRP,469			.ngpio			= LPC32XX_GPI_P3_MAX,470			.names			= gpi_p3_names,471			.can_sleep		= false,472		},473		.gpio_grp = &gpio_grp_regs_p3,474	},475	{476		.chip = {477			.label			= "gpo_p3",478			.direction_output	= lpc32xx_gpio_dir_out_always,479			.set			= lpc32xx_gpo_set_value,480			.get			= lpc32xx_gpo_get_value,481			.request		= lpc32xx_gpio_request,482			.base			= LPC32XX_GPO_P3_GRP,483			.ngpio			= LPC32XX_GPO_P3_MAX,484			.names			= gpo_p3_names,485			.can_sleep		= false,486		},487		.gpio_grp = &gpio_grp_regs_p3,488	},489};490 491static int lpc32xx_of_xlate(struct gpio_chip *gc,492			    const struct of_phandle_args *gpiospec, u32 *flags)493{494	/* Is this the correct bank? */495	u32 bank = gpiospec->args[0];496	if ((bank >= ARRAY_SIZE(lpc32xx_gpiochip) ||497	    (gc != &lpc32xx_gpiochip[bank].chip)))498		return -EINVAL;499 500	if (flags)501		*flags = gpiospec->args[2];502	return gpiospec->args[1];503}504 505static int lpc32xx_gpio_probe(struct platform_device *pdev)506{507	int i;508	void __iomem *reg_base;509 510	reg_base = devm_platform_ioremap_resource(pdev, 0);511	if (IS_ERR(reg_base))512		return PTR_ERR(reg_base);513 514	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {515		lpc32xx_gpiochip[i].chip.parent = &pdev->dev;516		if (pdev->dev.of_node) {517			lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;518			lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;519			lpc32xx_gpiochip[i].reg_base = reg_base;520		}521		devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,522				  &lpc32xx_gpiochip[i]);523	}524 525	return 0;526}527 528static const struct of_device_id lpc32xx_gpio_of_match[] = {529	{ .compatible = "nxp,lpc3220-gpio", },530	{ },531};532MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);533 534static struct platform_driver lpc32xx_gpio_driver = {535	.driver		= {536		.name	= "lpc32xx-gpio",537		.of_match_table = lpc32xx_gpio_of_match,538	},539	.probe		= lpc32xx_gpio_probe,540};541 542module_platform_driver(lpc32xx_gpio_driver);543 544MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");545MODULE_LICENSE("GPL");546MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");547