All pastes #1038960 Raw Edit

Diff

public text v1 · immutable
#1038960 ·published 2008-06-04 20:32 UTC
rendered paste body
From 57c08ae234f42060212c65235bb8d3f25ae17ade Mon Sep 17 00:00:00 2001From: Philipp Zabel <philipp.zabel@gmail.com>Date: Thu, 29 May 2008 12:24:32 +0200Subject: [PATCH] WIP: ASIC3: GPIO API support--- drivers/mfd/asic3.c       |  145 +++++++++++++++++++++++++++++++++++++++++---- include/linux/mfd/asic3.h |   14 +---- 2 files changed, 134 insertions(+), 25 deletions(-)diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.cindex ef8a492..599f872 100644--- a/drivers/mfd/asic3.c+++ b/drivers/mfd/asic3.c@@ -20,11 +20,34 @@ #include <linux/kernel.h> #include <linux/irq.h> #include <linux/io.h>+#include <linux/gpio.h> #include <linux/spinlock.h> #include <linux/platform_device.h>  #include <linux/mfd/asic3.h> +struct asic3;++struct asic3_gpio_chip {+	struct asic3 *asic;+	unsigned int base;+	struct gpio_chip chip;+};++struct asic3 {+	void __iomem *mapping;+	unsigned int bus_shift;+	unsigned int irq_nr;+	unsigned int irq_base;+	spinlock_t lock;+	u16 irq_bothedge[4];+	struct asic3_gpio_chip agpio[4];+	struct device *dev;+};++int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio);+void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val);+ static inline void asic3_write_register(struct asic3 *asic, 				 unsigned int reg, u32 value) {@@ -394,6 +417,46 @@ static void asic3_set_gpio(struct asic3 *asic, unsigned int base, 	     asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ 	} while (0) +/* GPIO API */+static int asic3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)+{+	struct asic3_gpio_chip *agpio;+	struct asic3 *asic;+	unsigned long flags;+	int val;++	agpio = container_of(chip, struct asic3_gpio_chip, chip);+	asic = agpio->asic;++	spin_lock_irqsave(&asic->lock, flags);+	val = asic3_read_register(asic, agpio->base + ASIC3_GPIO_Direction);+	val &= ~(1 << offset);+	asic3_write_register(asic, agpio->base + ASIC3_GPIO_Direction, val);+	spin_unlock_irqrestore(&asic->lock, flags);++	return 0;+}++static int asic3_gpio_direction_output(struct gpio_chip *chip,+					unsigned offset, int value)+{+	struct asic3_gpio_chip *agpio;+	struct asic3 *asic;+	unsigned long flags;+	int val;++	agpio = container_of(chip, struct asic3_gpio_chip, chip);+	asic = agpio->asic;++	spin_lock_irqsave(&asic->lock, flags);+	val =  asic3_read_register(asic, agpio->base + ASIC3_GPIO_Direction);+	val |= (1 << offset);+	asic3_write_register(asic, agpio->base + ASIC3_GPIO_Direction, val);+	spin_unlock_irqrestore(&asic->lock, flags);++	return 0;+}+ int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) { 	u32 mask = ASIC3_GPIO_bit(gpio);@@ -415,6 +478,19 @@ int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) } EXPORT_SYMBOL(asic3_gpio_get_value); +/* GPIO API */+static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset)+{+	struct asic3_gpio_chip *agpio;+	struct asic3 *asic;++	agpio = container_of(chip, struct asic3_gpio_chip, chip);+	asic = agpio->asic;++	return asic3_get_gpio(asic, agpio->base,+				ASIC3_GPIO_Status) & (1 << offset);+}+ void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) { 	u32 mask = ASIC3_GPIO_bit(gpio);@@ -443,10 +519,33 @@ void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) } EXPORT_SYMBOL(asic3_gpio_set_value); +/* GPIO API */+static void asic3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)+{+	struct asic3_gpio_chip *agpio;+	struct asic3 *asic;+	unsigned long flags;+	int val;++	agpio = container_of(chip, struct asic3_gpio_chip, chip);+	asic = agpio->asic;++	spin_lock_irqsave(&asic->lock, flags);+	val = asic3_read_register(asic, agpio->base + ASIC3_GPIO_Out);+	if (value)+		val |= (1 << offset);+	else+		val &= ~(1 << offset);+	asic3_write_register(asic, agpio->base + ASIC3_GPIO_Out, val);+	spin_unlock_irqrestore(&asic->lock, flags);+}+ static int asic3_gpio_probe(struct platform_device *pdev) { 	struct asic3_platform_data *pdata = pdev->dev.platform_data; 	struct asic3 *asic = platform_get_drvdata(pdev);+	struct gpio_chip *chip;+	int bank;  	asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); 	asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff);@@ -458,18 +557,34 @@ static int asic3_gpio_probe(struct platform_device *pdev) 	asic3_set_gpio_c(asic, SleepMask, 0xffff, 0xffff); 	asic3_set_gpio_d(asic, SleepMask, 0xffff, 0xffff); -	if (pdata) {-		asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init);-		asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir);-		asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata,-				     sleep_mask);-		asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out);-		asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata,-				     batt_fault_out);-		asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata,-				     sleep_conf);-		asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata,-				     alt_function);+	if (!pdata)+		return 0;++	asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init);+	asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir);+	asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata,+			     sleep_mask);+	asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out);+	asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata,+			     batt_fault_out);+	asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata,+			     sleep_conf);+	asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata,+			     alt_function);++	for (bank = 0; bank < 4; bank++) {+		asic->agpio[bank].asic = asic;+		asic->agpio[bank].base = ASIC3_GPIO_A_Base + +						bank * ASIC3_GPIO_Base_INCR;+		chip = &(asic->agpio[bank].chip);+		chip->label = "asic3";+		chip->get = asic3_gpio_get;+		chip->set = asic3_gpio_set;+		chip->direction_input = asic3_gpio_direction_input;+		chip->direction_output = asic3_gpio_direction_output;+		chip->base = pdata->gpio_base + 16 * bank;+		chip->ngpio = 16;+		gpiochip_add(chip); 	}  	return 0;@@ -477,6 +592,12 @@ static int asic3_gpio_probe(struct platform_device *pdev)  static void asic3_gpio_remove(struct platform_device *pdev) {+	struct asic3 *asic = platform_get_drvdata(pdev);+	int bank;++	for (bank = 0; bank < 4; bank++)+		gpiochip_remove(&(asic->agpio[bank].chip));+ 	return; } diff --git a/include/linux/mfd/asic3.h b/include/linux/mfd/asic3.hindex 4ab2162..f5d5df0 100644--- a/include/linux/mfd/asic3.h+++ b/include/linux/mfd/asic3.h@@ -16,16 +16,6 @@  #include <linux/types.h> -struct asic3 {-	void __iomem *mapping;-	unsigned int bus_shift;-	unsigned int irq_nr;-	unsigned int irq_base;-	spinlock_t lock;-	u16 irq_bothedge[4];-	struct device *dev;-};- struct asic3_platform_data { 	struct { 		u32 dir;@@ -40,14 +30,12 @@ struct asic3_platform_data { 	unsigned int bus_shift;  	unsigned int irq_base;+	unsigned int gpio_base;  	struct platform_device **children; 	unsigned int n_children; }; -int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio);-void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val);- #define ASIC3_NUM_GPIO_BANKS	4 #define ASIC3_GPIOS_PER_BANK	16 #define ASIC3_NUM_GPIOS		64-- 1.5.5.3