brintos

brintos / linux-shallow public Read only

0
0
Text · 8.9 KiB · a199dce Raw
365 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MPC52xx gpio driver4 *5 * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix6 */7 8#include <linux/of.h>9#include <linux/kernel.h>10#include <linux/slab.h>11#include <linux/gpio/legacy-of-mm-gpiochip.h>12#include <linux/io.h>13#include <linux/platform_device.h>14#include <linux/module.h>15 16#include <asm/mpc52xx.h>17#include <sysdev/fsl_soc.h>18 19static DEFINE_SPINLOCK(gpio_lock);20 21struct mpc52xx_gpiochip {22	struct of_mm_gpio_chip mmchip;23	unsigned int shadow_dvo;24	unsigned int shadow_gpioe;25	unsigned int shadow_ddr;26};27 28/*29 * GPIO LIB API implementation for wakeup GPIOs.30 *31 * There's a maximum of 8 wakeup GPIOs. Which of these are available32 * for use depends on your board setup.33 *34 * 0 -> GPIO_WKUP_735 * 1 -> GPIO_WKUP_636 * 2 -> PSC6_137 * 3 -> PSC6_038 * 4 -> ETH_1739 * 5 -> PSC3_940 * 6 -> PSC2_441 * 7 -> PSC1_442 *43 */44static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)45{46	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);47	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;48	unsigned int ret;49 50	ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;51 52	pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);53 54	return ret;55}56 57static inline void58__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)59{60	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);61	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);62	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;63 64	if (val)65		chip->shadow_dvo |= 1 << (7 - gpio);66	else67		chip->shadow_dvo &= ~(1 << (7 - gpio));68 69	out_8(&regs->wkup_dvo, chip->shadow_dvo);70}71 72static void73mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)74{75	unsigned long flags;76 77	spin_lock_irqsave(&gpio_lock, flags);78 79	__mpc52xx_wkup_gpio_set(gc, gpio, val);80 81	spin_unlock_irqrestore(&gpio_lock, flags);82 83	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);84}85 86static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)87{88	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);89	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);90	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;91	unsigned long flags;92 93	spin_lock_irqsave(&gpio_lock, flags);94 95	/* set the direction */96	chip->shadow_ddr &= ~(1 << (7 - gpio));97	out_8(&regs->wkup_ddr, chip->shadow_ddr);98 99	/* and enable the pin */100	chip->shadow_gpioe |= 1 << (7 - gpio);101	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);102 103	spin_unlock_irqrestore(&gpio_lock, flags);104 105	return 0;106}107 108static int109mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)110{111	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);112	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;113	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);114	unsigned long flags;115 116	spin_lock_irqsave(&gpio_lock, flags);117 118	__mpc52xx_wkup_gpio_set(gc, gpio, val);119 120	/* Then set direction */121	chip->shadow_ddr |= 1 << (7 - gpio);122	out_8(&regs->wkup_ddr, chip->shadow_ddr);123 124	/* Finally enable the pin */125	chip->shadow_gpioe |= 1 << (7 - gpio);126	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);127 128	spin_unlock_irqrestore(&gpio_lock, flags);129 130	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);131 132	return 0;133}134 135static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)136{137	struct mpc52xx_gpiochip *chip;138	struct mpc52xx_gpio_wkup __iomem *regs;139	struct gpio_chip *gc;140	int ret;141 142	chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);143	if (!chip)144		return -ENOMEM;145 146	platform_set_drvdata(ofdev, chip);147 148	gc = &chip->mmchip.gc;149 150	gc->ngpio            = 8;151	gc->direction_input  = mpc52xx_wkup_gpio_dir_in;152	gc->direction_output = mpc52xx_wkup_gpio_dir_out;153	gc->get              = mpc52xx_wkup_gpio_get;154	gc->set              = mpc52xx_wkup_gpio_set;155 156	ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);157	if (ret)158		return ret;159 160	regs = chip->mmchip.regs;161	chip->shadow_gpioe = in_8(&regs->wkup_gpioe);162	chip->shadow_ddr = in_8(&regs->wkup_ddr);163	chip->shadow_dvo = in_8(&regs->wkup_dvo);164 165	return 0;166}167 168static void mpc52xx_gpiochip_remove(struct platform_device *ofdev)169{170	struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev);171 172	of_mm_gpiochip_remove(&chip->mmchip);173}174 175static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {176	{ .compatible = "fsl,mpc5200-gpio-wkup", },177	{}178};179 180static struct platform_driver mpc52xx_wkup_gpiochip_driver = {181	.driver = {182		.name = "mpc5200-gpio-wkup",183		.of_match_table = mpc52xx_wkup_gpiochip_match,184	},185	.probe = mpc52xx_wkup_gpiochip_probe,186	.remove_new = mpc52xx_gpiochip_remove,187};188 189/*190 * GPIO LIB API implementation for simple GPIOs191 *192 * There's a maximum of 32 simple GPIOs. Which of these are available193 * for use depends on your board setup.194 * The numbering reflects the bit numbering in the port registers:195 *196 *  0..1  > reserved197 *  2..3  > IRDA198 *  4..7  > ETHR199 *  8..11 > reserved200 * 12..15 > USB201 * 16..17 > reserved202 * 18..23 > PSC3203 * 24..27 > PSC2204 * 28..31 > PSC1205 */206static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)207{208	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);209	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;210	unsigned int ret;211 212	ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;213 214	return ret;215}216 217static inline void218__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)219{220	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);221	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);222	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;223 224	if (val)225		chip->shadow_dvo |= 1 << (31 - gpio);226	else227		chip->shadow_dvo &= ~(1 << (31 - gpio));228	out_be32(&regs->simple_dvo, chip->shadow_dvo);229}230 231static void232mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)233{234	unsigned long flags;235 236	spin_lock_irqsave(&gpio_lock, flags);237 238	__mpc52xx_simple_gpio_set(gc, gpio, val);239 240	spin_unlock_irqrestore(&gpio_lock, flags);241 242	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);243}244 245static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)246{247	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);248	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);249	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;250	unsigned long flags;251 252	spin_lock_irqsave(&gpio_lock, flags);253 254	/* set the direction */255	chip->shadow_ddr &= ~(1 << (31 - gpio));256	out_be32(&regs->simple_ddr, chip->shadow_ddr);257 258	/* and enable the pin */259	chip->shadow_gpioe |= 1 << (31 - gpio);260	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);261 262	spin_unlock_irqrestore(&gpio_lock, flags);263 264	return 0;265}266 267static int268mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)269{270	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);271	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);272	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;273	unsigned long flags;274 275	spin_lock_irqsave(&gpio_lock, flags);276 277	/* First set initial value */278	__mpc52xx_simple_gpio_set(gc, gpio, val);279 280	/* Then set direction */281	chip->shadow_ddr |= 1 << (31 - gpio);282	out_be32(&regs->simple_ddr, chip->shadow_ddr);283 284	/* Finally enable the pin */285	chip->shadow_gpioe |= 1 << (31 - gpio);286	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);287 288	spin_unlock_irqrestore(&gpio_lock, flags);289 290	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);291 292	return 0;293}294 295static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)296{297	struct mpc52xx_gpiochip *chip;298	struct gpio_chip *gc;299	struct mpc52xx_gpio __iomem *regs;300	int ret;301 302	chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);303	if (!chip)304		return -ENOMEM;305 306	platform_set_drvdata(ofdev, chip);307 308	gc = &chip->mmchip.gc;309 310	gc->ngpio            = 32;311	gc->direction_input  = mpc52xx_simple_gpio_dir_in;312	gc->direction_output = mpc52xx_simple_gpio_dir_out;313	gc->get              = mpc52xx_simple_gpio_get;314	gc->set              = mpc52xx_simple_gpio_set;315 316	ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);317	if (ret)318		return ret;319 320	regs = chip->mmchip.regs;321	chip->shadow_gpioe = in_be32(&regs->simple_gpioe);322	chip->shadow_ddr = in_be32(&regs->simple_ddr);323	chip->shadow_dvo = in_be32(&regs->simple_dvo);324 325	return 0;326}327 328static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {329	{ .compatible = "fsl,mpc5200-gpio", },330	{}331};332 333static struct platform_driver mpc52xx_simple_gpiochip_driver = {334	.driver = {335		.name = "mpc5200-gpio",336		.of_match_table = mpc52xx_simple_gpiochip_match,337	},338	.probe = mpc52xx_simple_gpiochip_probe,339	.remove_new = mpc52xx_gpiochip_remove,340};341 342static struct platform_driver * const drivers[] = {343	&mpc52xx_wkup_gpiochip_driver,344	&mpc52xx_simple_gpiochip_driver,345};346 347static int __init mpc52xx_gpio_init(void)348{349	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));350}351 352/* Make sure we get initialised before anyone else tries to use us */353subsys_initcall(mpc52xx_gpio_init);354 355static void __exit mpc52xx_gpio_exit(void)356{357	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));358}359module_exit(mpc52xx_gpio_exit);360 361MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");362MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");363MODULE_LICENSE("GPL v2");364 365