| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * MOXA ART SoCs GPIO driver. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2013 Jonas Jensen | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Jonas Jensen <jonas.jensen@gmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is licensed under the terms of the GNU General Public | 
					
						
							|  |  |  |  * License version 2.  This program is licensed "as is" without any | 
					
						
							|  |  |  |  * warranty of any kind, whether express or implied. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/err.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/irq.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							|  |  |  | #include <linux/gpio.h>
 | 
					
						
							|  |  |  | #include <linux/platform_device.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/of_address.h>
 | 
					
						
							|  |  |  | #include <linux/of_gpio.h>
 | 
					
						
							|  |  |  | #include <linux/pinctrl/consumer.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/timer.h>
 | 
					
						
							|  |  |  | #include <linux/bitops.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GPIO_DATA_OUT		0x00
 | 
					
						
							|  |  |  | #define GPIO_DATA_IN		0x04
 | 
					
						
							|  |  |  | #define GPIO_PIN_DIRECTION	0x08
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct moxart_gpio_chip { | 
					
						
							|  |  |  | 	struct gpio_chip gpio; | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 	void __iomem *base; | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return container_of(chip, struct moxart_gpio_chip, gpio); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return pinctrl_request_gpio(offset); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	pinctrl_free_gpio(offset); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 	void __iomem *ioaddr = gc->base + GPIO_DATA_OUT; | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | 	u32 reg = readl(ioaddr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value) | 
					
						
							|  |  |  | 		reg = reg | BIT(offset); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		reg = reg & ~BIT(offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writel(reg, ioaddr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 	u32 ret = readl(gc->base + GPIO_PIN_DIRECTION); | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (ret & BIT(offset)) | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 		return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset)); | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 		return !!(readl(gc->base + GPIO_DATA_IN) & BIT(offset)); | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-25 10:43:33 +08:00
										 |  |  | static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); | 
					
						
							|  |  |  | 	void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writel(readl(ioaddr) & ~BIT(offset), ioaddr); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int moxart_gpio_direction_output(struct gpio_chip *chip, | 
					
						
							|  |  |  | 					unsigned offset, int value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); | 
					
						
							|  |  |  | 	void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-25 10:44:19 +08:00
										 |  |  | 	moxart_gpio_set(chip, offset, value); | 
					
						
							| 
									
										
										
										
											2014-03-25 10:43:33 +08:00
										 |  |  | 	writel(readl(ioaddr) | BIT(offset), ioaddr); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | static struct gpio_chip moxart_template_chip = { | 
					
						
							|  |  |  | 	.label			= "moxart-gpio", | 
					
						
							|  |  |  | 	.request		= moxart_gpio_request, | 
					
						
							|  |  |  | 	.free			= moxart_gpio_free, | 
					
						
							|  |  |  | 	.direction_input	= moxart_gpio_direction_input, | 
					
						
							|  |  |  | 	.direction_output	= moxart_gpio_direction_output, | 
					
						
							|  |  |  | 	.set			= moxart_gpio_set, | 
					
						
							|  |  |  | 	.get			= moxart_gpio_get, | 
					
						
							|  |  |  | 	.ngpio			= 32, | 
					
						
							| 
									
										
										
										
											2013-12-16 10:11:34 +08:00
										 |  |  | 	.owner			= THIS_MODULE, | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int moxart_gpio_probe(struct platform_device *pdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct device *dev = &pdev->dev; | 
					
						
							|  |  |  | 	struct resource *res; | 
					
						
							|  |  |  | 	struct moxart_gpio_chip *mgc; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL); | 
					
						
							| 
									
										
										
										
											2014-04-29 17:37:09 +09:00
										 |  |  | 	if (!mgc) | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	mgc->gpio = moxart_template_chip; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 	mgc->base = devm_ioremap_resource(dev, res); | 
					
						
							| 
									
										
										
										
											2013-12-16 10:12:38 +08:00
										 |  |  | 	if (IS_ERR(mgc->base)) | 
					
						
							| 
									
										
										
										
											2013-12-02 11:27:59 +01:00
										 |  |  | 		return PTR_ERR(mgc->base); | 
					
						
							| 
									
										
										
										
											2013-11-29 12:11:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mgc->gpio.dev = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = gpiochip_add(&mgc->gpio); | 
					
						
							|  |  |  | 	if (ret) { | 
					
						
							|  |  |  | 		dev_err(dev, "%s: gpiochip_add failed\n", | 
					
						
							|  |  |  | 			dev->of_node->full_name); | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct of_device_id moxart_gpio_match[] = { | 
					
						
							|  |  |  | 	{ .compatible = "moxa,moxart-gpio" }, | 
					
						
							|  |  |  | 	{ } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct platform_driver moxart_gpio_driver = { | 
					
						
							|  |  |  | 	.driver	= { | 
					
						
							|  |  |  | 		.name		= "moxart-gpio", | 
					
						
							|  |  |  | 		.owner		= THIS_MODULE, | 
					
						
							|  |  |  | 		.of_match_table	= moxart_gpio_match, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	.probe	= moxart_gpio_probe, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | module_platform_driver(moxart_gpio_driver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_DESCRIPTION("MOXART GPIO chip driver"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>"); |