Skip to contentSkip to conversation

OSK + tps65010 uses gpiolib

PATCH In review David Brownell 1 participant 1 message Oct 30, 2007

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 2/2 OSK + tps65010 uses gpiolib

This builds on an update to make OMAP use new struct gpio_chip" library code for its GPIOs. Given that, this patch:

* Exposes tps65010 GPIOs and LEDs through the GPIO framework

* Converts the OSK board to use that framework (not quite everywhere; at least the serial line wakeup still need updating)

* Removes "old style" OSK led support, except for the Mistral board whose red-or-green LED isn't really supported by the new framework.

* Converts the tps65010 to "new style" GPIO leds, and adds a CF activity light.

Note that you may need a patch to the leds-gpio driver depending on how your kernel is configured (PREEMPT may be trouble).

NEEDS UPDATING: the tps_init() logic should probably become a callback from the tps65010 driver.

BUGFIX IMPLIED: in the "gpiolib" patch, line 251 of lib/gpiolib.c is rejecting gpio_direction_output() unless a get() is possible. Typo; that should check for set() instead. The TPS65010 code is currently output-only...

---
 arch/arm/mach-omap1/board-osk.c       |   66 ++++++++++++++++++------
 arch/arm/mach-omap1/leds-osk.c        |   92 ----------------------------------
 arch/arm/mach-omap1/leds.c            |   15 ++---
 drivers/i2c/chips/tps65010.c          |   61 ++++++++++++++++++++++
 drivers/input/touchscreen/ads7846.c   |   33 ------------
 include/asm-arm/arch-omap/board-osk.h |   11 ++++
 include/asm-arm/arch-omap/tps65010.h  |   17 ++++++
 7 files changed, 147 insertions(+), 148 deletions(-)
arch/arm/mach-omap1/board-osk.c +50 -16
@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/leds.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -183,11 +184,17 @@ static struct platform_device *osk5912_d
 	&osk5912_mcbsp1_device,
 };
 
+static struct tps65010_board tps_board = {
+	.base		= OSK_TPS_GPIO_BASE,
+	.outmask	= 0x0f,
+};
+
 static struct i2c_board_info __initdata osk_i2c_board_info[] = {
 	{
 		I2C_BOARD_INFO("tps65010", 0x48),
 		.type		= "tps65010",
 		.irq		= OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
+		.platform_data	= &tps_board,
 	},
 	/* TODO when driver support is ready:
 	 *  - aic23 audio chip at 0x1a
@@ -198,7 +205,7 @@ static struct i2c_board_info __initdata 
 
 static void __init osk_init_smc91x(void)
 {
-	if ((omap_request_gpio(0)) < 0) {
+	if ((gpio_request(0, "smc_irq")) < 0) {
 		printk("Error requesting gpio 0 for smc91x irq\n");
 		return;
 	}
@@ -210,7 +217,7 @@ static void __init osk_init_smc91x(void)
 static void __init osk_init_cf(void)
 {
 	omap_cfg_reg(M7_1610_GPIO62);
-	if ((omap_request_gpio(62)) < 0) {
+	if ((gpio_request(62, "cf_irq")) < 0) {
 		printk("Error requesting gpio 62 for CF irq\n");
 		return;
 	}
@@ -334,7 +341,7 @@ static struct platform_device *mistral_d
 
 static int mistral_get_pendown_state(void)
 {
-	return !omap_get_gpio_datain(4);
+	return !gpio_get_value(4);
 }
 
 static const struct ads7846_platform_data mistral_ts_info = {
@@ -396,25 +403,30 @@ static void __init osk_mistral_init(void
 	omap_cfg_reg(W14_1610_CCP_DATAP);
 
 	/* CAM_PWDN */
-	if (omap_request_gpio(11) == 0) {
+	if (gpio_request(11, "cam_pwdn") == 0) {
 		omap_cfg_reg(N20_1610_GPIO11);
-		omap_set_gpio_direction(11, 0 /* out */);
-		omap_set_gpio_dataout(11, 0 /* off */);
+		gpio_direction_output(11, 0);
 	} else
 		pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
 
 
 	// omap_cfg_reg(P19_1610_GPIO6);	// BUSY
+	gpio_request(6, "ts_busy");
+	gpio_direction_input(6);
+
 	omap_cfg_reg(P20_1610_GPIO4);	// PENIRQ
+	gpio_request(4, "ts_int");
+	gpio_direction_input(4);
 	set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
+
 	spi_register_board_info(mistral_boardinfo,
 			ARRAY_SIZE(mistral_boardinfo));
 
 	/* the sideways button (SW1) is for use as a "wakeup" button */
 	omap_cfg_reg(N15_1610_MPUIO2);
-	if (omap_request_gpio(OMAP_MPUIO(2)) == 0) {
+	if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) {
 		int ret = 0;
-		omap_set_gpio_direction(OMAP_MPUIO(2), 1);
+		gpio_direction_input(OMAP_MPUIO(2));
 		set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
 #ifdef	CONFIG_PM
 		/* share the IRQ in case someone wants to use the
@@ -425,7 +437,7 @@ static void __init osk_mistral_init(void
 				IRQF_SHARED, "mistral_wakeup",
 				&osk_mistral_wake_interrupt);
 		if (ret != 0) {
-			omap_free_gpio(OMAP_MPUIO(2));
+			gpio_free(OMAP_MPUIO(2));
 			printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
 				ret);
 		} else
@@ -438,10 +450,8 @@ static void __init osk_mistral_init(void
 	 * board, like the touchscreen, EEPROM, and wakeup (!) switch.
 	 */
 	omap_cfg_reg(PWL);
-	if (omap_request_gpio(2) == 0) {
-		omap_set_gpio_direction(2, 0 /* out */);
-		omap_set_gpio_dataout(2, 1 /* on */);
-	}
+	if (gpio_request(2, "lcd_pwr") == 0)
+		gpio_direction_output(2, 1);
 
 	platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
 }
@@ -486,6 +496,26 @@ static void __init osk_map_io(void)
 }
 
 #ifdef CONFIG_TPS65010
+
+static struct gpio_led tps_leds[] = {
+	{ .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9",
+			.default_trigger = "ide-disk", /* CF */ },
+	{ .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
+	{ .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
+			.default_trigger = "heartbeat", },
+};
+
+static struct gpio_led_platform_data tps_led_data = {
+	.num_leds	= ARRAY_SIZE(tps_leds),
+	.leds		= tps_leds,
+};
+
+static struct platform_device tps_led_dev = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &tps_led_data,
+};
+
 static int __init osk_tps_init(void)
 {
 	if (!machine_is_omap_osk())
@@ -500,16 +530,20 @@ static int __init osk_tps_init(void)
 	/* Set GPIO 1 HIGH to disable VBUS power supply;
 	 * OHCI driver powers it up/down as needed.
 	 */
-	tps65010_set_gpio_out_value(GPIO1, HIGH);
+	if (gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "vbus_dis") == 0)
+		gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1);
 
 	/* Set GPIO 2 low to turn on LED D3 */
 	tps65010_set_gpio_out_value(GPIO2, HIGH);
 
 	/* Set GPIO 3 low to take ethernet out of reset */
-	tps65010_set_gpio_out_value(GPIO3, LOW);
+	if (gpio_request(OSK_TPS_GPIO_LAN_RESET, "lan_reset") == 0)
+		gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0);
 
 	/* gpio4 for VDD_DSP */
 	/* FIXME send power to DSP iff it's configured */
+	if (gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_pwr_en") == 0)
+		gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1);
 
 	/* Enable LOW_PWR */
 	tps65010_set_low_pwr(ON);
@@ -518,7 +552,7 @@ static int __init osk_tps_init(void)
 	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
 			| TPS_LDO1_ENABLE);
 
-	return 0;
+	return platform_device_register(&tps_led_dev);
 }
 fs_initcall(osk_tps_init);
 #endif
arch/arm/mach-omap1/leds-osk.c +1 -91

156 lines not on this page · raw message

arch/arm/mach-omap1/leds.c +8 -7
@@ -5,11 +5,12 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/list.h>
 
 #include <asm/leds.h>
+#include <asm/gpio.h>
 #include <asm/mach-types.h>
 
-#include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 
 #include "leds.h"
@@ -25,17 +26,17 @@ omap_leds_init(void)
 			|| machine_is_omap_perseus2())
 		leds_event = h2p2_dbg_leds_event;
 
+#ifdef	CONFIG_OMAP_OSK_MISTRAL
 	else if (machine_is_omap_osk())
 		leds_event = osk_leds_event;
+#endif
 
 	else
 		return -1;
 
 	if (machine_is_omap_h2()
 			|| machine_is_omap_h3()
-#ifdef	CONFIG_OMAP_OSK_MISTRAL
 			|| machine_is_omap_osk()
-#endif
 			) {
 
 		/* LED1/LED2 pins can be used as GPIO (as done here), or by
@@ -47,14 +48,14 @@ omap_leds_init(void)
 		 * that's a different kind of LED (just one color at a time).
 		 */
 		omap_cfg_reg(P18_1610_GPIO3);
-		if (omap_request_gpio(3) == 0)
-			omap_set_gpio_direction(3, 0);
+		if (gpio_request(3, "timer_led") == 0)
+			gpio_direction_output(3, 0);
 		else
 			printk(KERN_WARNING "LED: can't get GPIO3/red?\n");
 
 		omap_cfg_reg(MPUIO4);
-		if (omap_request_gpio(OMAP_MPUIO(4)) == 0)
-			omap_set_gpio_direction(OMAP_MPUIO(4), 0);
+		if (gpio_request(OMAP_MPUIO(4), "idle_led") == 0)
+			gpio_direction_output(OMAP_MPUIO(4), 0);
 		else
 			printk(KERN_WARNING "LED: can't get MPUIO4/green?\n");
 	}
drivers/i2c/chips/tps65010.c +60 -1

91 lines not on this page · raw message

drivers/input/touchscreen/ads7846.c +0 -33
@@ -1175,31 +1175,6 @@ static struct spi_driver ads7846_driver 
 
 static int __init ads7846_init(void)
 {
-	/* grr, board-specific init should stay out of drivers!! */
-
-#ifdef	CONFIG_ARCH_OMAP
-	if (machine_is_omap_osk()) {
-		/* GPIO4 = PENIRQ; GPIO6 = BUSY */
-		omap_request_gpio(4);
-		omap_set_gpio_direction(4, 1);
-		omap_request_gpio(6);
-		omap_set_gpio_direction(6, 1);
-	}
-	// also TI 1510 Innovator, bitbanging through FPGA
-	// also Nokia 770
-	// also Palm Tungsten T2
-#endif
-
-	// PXA:
-	// also Dell Axim X50
-	// also HP iPaq H191x/H192x/H415x/H435x
-	// also Intel Lubbock (additional to UCB1400; as temperature sensor)
-	// also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
-
-	// Atmel at91sam9261-EK uses ads7843
-
-	// also various AMD Au1x00 devel boards
-
 	return spi_register_driver(&ads7846_driver);
 }
 module_init(ads7846_init);
@@ -1207,14 +1182,6 @@ module_init(ads7846_init);
 static void __exit ads7846_exit(void)
 {
 	spi_unregister_driver(&ads7846_driver);
-
-#ifdef	CONFIG_ARCH_OMAP
-	if (machine_is_omap_osk()) {
-		omap_free_gpio(4);
-		omap_free_gpio(6);
-	}
-#endif
-
 }
 module_exit(ads7846_exit);
 
include/asm-arm/arch-omap/board-osk.h +11 -0
@@ -32,5 +32,16 @@
 /* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
 #define OMAP_OSK_ETHR_START		0x04800300
 
+/* TPS65010 has four GPIOs.  nPG and LED2 can be treated like GPIOs with
+ * alternate pin configurations for hardware-controlled blinking.
+ */
+#define OSK_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+#	define OSK_TPS_GPIO_USB_PWR_EN	(OSK_TPS_GPIO_BASE + 0)
+#	define OSK_TPS_GPIO_LED_D3	(OSK_TPS_GPIO_BASE + 1)
+#	define OSK_TPS_GPIO_LAN_RESET	(OSK_TPS_GPIO_BASE + 2)
+#	define OSK_TPS_GPIO_DSP_PWR_EN	(OSK_TPS_GPIO_BASE + 3)
+#	define OSK_TPS_GPIO_LED_D9	(OSK_TPS_GPIO_BASE + 4)
+#	define OSK_TPS_GPIO_LED_D2	(OSK_TPS_GPIO_BASE + 5)
+
 #endif /*  __ASM_ARCH_OMAP_OSK_H */
 
include/asm-arm/arch-omap/tps65010.h +17 -0
@@ -152,5 +152,22 @@ extern int tps65010_config_vregs1(unsign
  */
 extern int tps65013_set_low_pwr(unsigned mode);
 
+
+/**
+ * struct tps65010_board - packages GPIO and LED lines
+ * @base: the GPIO number to assign to GPIO-1
+ * @outmask: bit (N-1) is set to allow GPIO-N to be used
+ *	as an (open drain) output
+ *
+ * Board data may be used to package the GPIO (and LED) lines
+ * for use in by the generic GPIO and LED frameworks.  The first
+ * four GPIOs starting at gpio_base are GPIO1..GPIO4; the next
+ * two are LED1..LED2.
+ */
+struct tps65010_board {
+	int			base;
+	unsigned		outmask;
+};
+
 #endif /*  __ASM_ARCH_TPS65010_H */