[PATCH 3/3] ep93xx pcmcia support for the contec micro9 board

Lennert Buytenhek buytenh at wantstofly.org
Mon Apr 30 09:27:23 EDT 2007


Signed-off-by: Lennert Buytenhek <buytenh at wantstofly.org>

Index: linux-2.6.20/arch/arm/mach-ep93xx/micro9.c
===================================================================
--- linux-2.6.20.orig/arch/arm/mach-ep93xx/micro9.c
+++ linux-2.6.20/arch/arm/mach-ep93xx/micro9.c
@@ -16,12 +16,14 @@
 #include <linux/mm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 
 #include <linux/mtd/physmap.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
 
+#include <asm/arch/gpio.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
@@ -92,11 +94,63 @@ static void __init micro9h_init(void)
        platform_device_register(&micro9h_flash);
 }
 
+void micro9_tps2206_write(int val)
+{
+	int i;
+
+	eeclk_eedat_claim();
+
+	/*
+	 * First pull EECLK low, so that transitions on EEDAT
+	 * don't cause start or stop conditions.
+	 */
+	gpio_line_config(EP93XX_GPIO_LINE_EECLK, GPIO_OUT);
+	gpio_line_set(EP93XX_GPIO_LINE_EECLK, 0);
+	udelay(1);
+
+	for (i = 8; i >= 0; i--) {
+		if (val & (1 << i))
+			gpio_line_config(EP93XX_GPIO_LINE_EEDAT, GPIO_IN);
+		else {
+			gpio_line_config(EP93XX_GPIO_LINE_EEDAT, GPIO_OUT);
+			gpio_line_set(EP93XX_GPIO_LINE_EEDAT, 0);
+		}
+		udelay(1);
+
+		gpio_line_config(EP93XX_GPIO_LINE_EECLK, GPIO_IN);
+		udelay(1);
+		gpio_line_config(EP93XX_GPIO_LINE_EECLK, GPIO_OUT);
+		gpio_line_set(EP93XX_GPIO_LINE_EECLK, 0);
+	}
+	udelay(1);
+	gpio_line_set(EP93XX_GPIO_LINE_SLA0, 1);
+	udelay(1);
+	gpio_line_set(EP93XX_GPIO_LINE_SLA0, 0);
+
+	gpio_line_config(EP93XX_GPIO_LINE_EEDAT, GPIO_IN);
+	udelay(1);
+	gpio_line_config(EP93XX_GPIO_LINE_EECLK, GPIO_IN);
+
+	eeclk_eedat_release();
+}
+
+static void micro9_tps2206_init(void)
+{
+	gpio_line_config(EP93XX_GPIO_LINE_EECLK, GPIO_IN);
+	gpio_line_config(EP93XX_GPIO_LINE_EEDAT, GPIO_IN);
+
+	gpio_line_set(EP93XX_GPIO_LINE_SLA0, 0);
+	gpio_line_config(EP93XX_GPIO_LINE_SLA0, GPIO_OUT);
+
+	micro9_tps2206_write(0);
+}
+
 static void __init micro9h_init_machine(void)
 {
        ep93xx_init_devices();
        micro9_init();
        micro9h_init();
+	micro9_tps2206_init();
 }
 
 MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H")
@@ -154,4 +208,3 @@ MACHINE_START(MICRO9L, "Contec Hypercont
        .init_machine   = micro9l_init_machine,
 MACHINE_END
 #endif
-
Index: linux-2.6.20/drivers/pcmcia/Makefile
===================================================================
--- linux-2.6.20.orig/drivers/pcmcia/Makefile
+++ linux-2.6.20/drivers/pcmcia/Makefile
@@ -56,6 +56,7 @@ au1x00_ss-$(CONFIG_MIPS_DB1550)			+= au1
 au1x00_ss-$(CONFIG_MIPS_XXS1500)		+= au1000_xxs1500.o
 
 ep93xx_cs-$(CONFIG_MACH_ADSSPHERE)		+= ep93xx_adssphere.o
+ep93xx_cs-$(CONFIG_MACH_MICRO9)			+= ep93xx_micro9.o
 
 sa1111_cs-y					+= sa1111_generic.o
 sa1111_cs-$(CONFIG_ASSABET_NEPONSET)		+= sa1100_neponset.o
Index: linux-2.6.20/drivers/pcmcia/ep93xx_micro9.c
===================================================================
--- /dev/null
+++ linux-2.6.20/drivers/pcmcia/ep93xx_micro9.c
@@ -0,0 +1,182 @@
+/*
+ * linux/drivers/pcmcia/ep93xx_micro9.c
+ * Copyright (C) 2007 Lennert Buytenhek <buytenh at wantstofly.org>
+ *
+ * Adapted from ep93xx_adssphere.c, which is:
+ *   Copyright (C) 2005 Robert Whaley <rwhaley at applieddata.net>
+ *
+ * Adapted from pxa27x_mainstone.c, which is:
+ *   Copyright (C) 2004 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <pcmcia/ss.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+#include "soc_common.h"
+
+#define EP93XX_GPIO_PFDR	EP93XX_GPIO_REG(0x30)
+
+#define PCMCIACNT		(EP93XX_PCMCIA_CONTROLLER_BASE + 0x40)
+
+#define TPS2206_NOT_SHUTDOWN	0x0100
+#define TPS2206_BVCC_0V		0x0000
+#define TPS2206_BVCC_5V		0x0040
+#define TPS2206_BVCC_3V3	0x0080
+#define TPS2206_BVPP_0V		0x0000
+#define TPS2206_BVPP_12V	0x0010
+#define TPS2206_BVPP_VCC	0x0020
+#define TPS2206_BVPP_HIGHZ	0x0030
+#define TPS2206_AVCC_0V		0x0000
+#define TPS2206_AVCC_3V3	0x0004
+#define TPS2206_AVCC_5V		0x0008
+#define TPS2206_AVPP_0V		0x0000
+#define TPS2206_AVPP_12V	0x0001
+#define TPS2206_AVPP_VCC	0x0002
+#define TPS2206_AVPP_HIGHZ	0x0003
+
+
+static struct pcmcia_irqs irqs[] = {
+	{ 0, IRQ_EP93XX_GPIO(EP93XX_GPIO_LINE_MCCD1),  "PCMCIA CD1" },
+	{ 0, IRQ_EP93XX_GPIO(EP93XX_GPIO_LINE_MCCD2),  "PCMCIA CD2" },
+	{ 0, IRQ_EP93XX_GPIO(EP93XX_GPIO_LINE_MCBVD1), "PCMCIA STSCHG/BVD1" },
+	{ 0, IRQ_EP93XX_GPIO(EP93XX_GPIO_LINE_MCBVD2), "PCMCIA SPKR/BVD2" },
+};
+
+static int micro9_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	if (skt->nr == 0) {
+		skt->irq = IRQ_EP93XX_GPIO(EP93XX_GPIO_LINE_READY);
+		return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	}
+
+	return -ENXIO;
+}
+
+static void micro9_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void micro9_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+					  struct pcmcia_state *state)
+{
+	unsigned long status;
+
+	status = readl(EP93XX_GPIO_PFDR);
+	state->detect = (status & 0x06) ? 0 : 1;
+	state->ready  = (status & 0x40) ? 1 : 0;
+	state->wrprot = (status & 0x01) ? 0 : 1;
+	state->bvd1   = (status & 0x08) ? 1 : 0;
+	state->bvd2   = (status & 0x10) ? 1 : 0;
+	state->vs_3v  = (status & 0x20) ? 0 : 1;
+	state->vs_Xv  = (status & 0x80) ? 0 : 1;
+}
+
+static int micro9_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+					     const socket_state_t *state)
+{
+	int val;
+
+	if (skt->nr != 0) {
+		printk(KERN_ERR "%s: socket %u invalid\n", __func__, skt->nr);
+		return -1;
+	}
+
+	val = TPS2206_NOT_SHUTDOWN;
+	if (state->Vcc == 0) {
+		val |= TPS2206_AVCC_0V;
+	} else if (state->Vcc == 33) {
+		val |= TPS2206_AVCC_3V3;
+	} else if (state->Vcc == 50) {
+		val |= TPS2206_AVCC_5V;
+	} else {
+		printk(KERN_ERR "%s: bad Vcc %u\n", __FUNCTION__, state->Vcc);
+		val &= ~TPS2206_NOT_SHUTDOWN;
+	}
+	if (state->Vpp == 0) {
+		val |= TPS2206_AVPP_0V;
+	} else if (state->Vpp == state->Vcc) {
+		val |= TPS2206_AVPP_VCC;
+	} else if (state->Vpp == 120) {
+		val |= TPS2206_AVPP_12V;
+	} else {
+		printk(KERN_ERR "%s: bad Vpp %u\n", __FUNCTION__, state->Vpp);
+		val &= ~TPS2206_NOT_SHUTDOWN;
+	}
+
+	micro9_tps2206_write(val);
+
+	if (state->flags & SS_RESET)
+		/* see EP93xx User's Guide */
+		writel(0x15, PCMCIACNT);
+	else
+		/* CF mode -  BIT1 for PCMCIA mode */
+		writel(0x11, PCMCIACNT);
+
+	return 0;
+}
+
+static void micro9_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void micro9_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static struct pcmcia_low_level micro9_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+	.hw_init		= micro9_pcmcia_hw_init,
+	.hw_shutdown		= micro9_pcmcia_hw_shutdown,
+	.socket_state		= micro9_pcmcia_socket_state,
+	.configure_socket	= micro9_pcmcia_configure_socket,
+	.socket_init		= micro9_pcmcia_socket_init,
+	.socket_suspend		= micro9_pcmcia_socket_suspend,
+	.nr			= 1,
+};
+
+static struct platform_device micro9_pcmcia = {
+	.name		= "ep93xx-pcmcia",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &micro9_pcmcia_ops,
+	},
+};
+
+static int __init micro9_pcmcia_init(void)
+{
+	int ret;
+
+	ret = 0;
+	if (machine_is_micro9())
+		ret = platform_device_register(&micro9_pcmcia);
+
+	return ret;
+}
+
+static void __exit micro9_pcmcia_exit(void)
+{
+	if (machine_is_micro9())
+		platform_device_unregister(&micro9_pcmcia);
+}
+
+module_init(micro9_pcmcia_init);
+module_exit(micro9_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
Index: linux-2.6.20/include/asm-arm/arch-ep93xx/hardware.h
===================================================================
--- linux-2.6.20.orig/include/asm-arm/arch-ep93xx/hardware.h
+++ linux-2.6.20/include/asm-arm/arch-ep93xx/hardware.h
@@ -10,4 +10,5 @@
 
 #include "adssphere.h"
 #include "gesbc9312.h"
+#include "micro9.h"
 #include "ts72xx.h"
Index: linux-2.6.20/include/asm-arm/arch-ep93xx/micro9.h
===================================================================
--- /dev/null
+++ linux-2.6.20/include/asm-arm/arch-ep93xx/micro9.h
@@ -0,0 +1,7 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/micro9.h
+ */
+
+#ifndef __ASSEMBLY__
+void micro9_tps2206_write(int);
+#endif



More information about the linux-pcmcia mailing list