summaryrefslogtreecommitdiff
path: root/packages/linux/linux-2.6.24/ts72xx/ep93xx-i2c.diff
blob: b68fb14e2ed465c6ad1ba4324ab8dcd4bd5ec685 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

Instantiate the ep93xx gpio i2c bus driver in the generic ep93xx
code.

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

Index: linux-2.6.22/arch/arm/mach-ep93xx/core.c
===================================================================
--- linux-2.6.22.orig/arch/arm/mach-ep93xx/core.c	2007-08-30 00:42:49.000000000 +0200
+++ linux-2.6.22/arch/arm/mach-ep93xx/core.c	2007-08-30 00:43:00.000000000 +0200
@@ -509,6 +509,52 @@
 };
 
 
+static DEFINE_MUTEX(eeclk_eedat_mutex);
+static int i2c_transaction_in_progress;
+
+static void ep93xx_i2c_start_condition(void *cookie)
+{
+	if (!i2c_transaction_in_progress) {
+		mutex_lock(&eeclk_eedat_mutex);
+		i2c_transaction_in_progress = 1;
+	}
+}
+
+static void ep93xx_i2c_stop_condition(void *cookie)
+{
+	if (i2c_transaction_in_progress) {
+		mutex_unlock(&eeclk_eedat_mutex);
+		i2c_transaction_in_progress = 0;
+	} else {
+		printk(KERN_WARNING "ep93xx: i2c stop without start??\n");
+	}
+}
+
+static struct ep93xx_i2c_data ep93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.start			= ep93xx_i2c_start_condition,
+	.stop			= ep93xx_i2c_stop_condition,
+};
+
+static struct platform_device ep93xx_i2c_device = {
+	.name			= "ep93xx-i2c",
+	.id			= 0,
+	.dev.platform_data	= &ep93xx_i2c_gpio_data,
+	.num_resources		= 0,
+};
+
+void eeclk_eedat_claim(void)
+{
+	mutex_lock(&eeclk_eedat_mutex);
+}
+
+void eeclk_eedat_release(void)
+{
+	mutex_unlock(&eeclk_eedat_mutex);
+}
+
+
 void __init ep93xx_init_devices(void)
 {
 	unsigned int v;
@@ -521,10 +567,20 @@
 	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
 	__raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
 
+	/*
+	 * When EECLK/EEDAT are in open drain mode (EEDRIVE=0b11),
+	 * writing a 1 to their Data Register bits causes subsequent
+	 * reads from the Data Direction Register to return 'input',
+	 * which confuses gpio_line_config().  So, we use CMOS drive
+	 * mode instead.
+	 */
+	__raw_writel(0, EP93XX_GPIO_EEDRIVE);
+
 	amba_device_register(&uart1_device, &iomem_resource);
 	amba_device_register(&uart2_device, &iomem_resource);
 	amba_device_register(&uart3_device, &iomem_resource);
 
 	platform_device_register(&ep93xx_rtc_device);
 	platform_device_register(&ep93xx_ohci_device);
+	platform_device_register(&ep93xx_i2c_device);
 }
Index: linux-2.6.22/include/asm-arm/arch-ep93xx/ep93xx-regs.h
===================================================================
--- linux-2.6.22.orig/include/asm-arm/arch-ep93xx/ep93xx-regs.h	2007-08-30 00:42:49.000000000 +0200
+++ linux-2.6.22/include/asm-arm/arch-ep93xx/ep93xx-regs.h	2007-08-30 00:43:00.000000000 +0200
@@ -91,6 +91,7 @@
 #define EP93XX_GPIO_B_INT_ENABLE	EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
 #define EP93XX_GPIO_B_INT_DEBOUNCE	EP93XX_GPIO_REG(0xc4)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE			(EP93XX_APB_VIRT_BASE + 0x00080000)
 
Index: linux-2.6.22/include/asm-arm/arch-ep93xx/platform.h
===================================================================
--- linux-2.6.22.orig/include/asm-arm/arch-ep93xx/platform.h	2007-08-30 00:42:52.000000000 +0200
+++ linux-2.6.22/include/asm-arm/arch-ep93xx/platform.h	2007-08-30 00:43:00.000000000 +0200
@@ -10,6 +10,9 @@
 void ep93xx_init_devices(void);
 extern struct sys_timer ep93xx_timer;
 
+void eeclk_eedat_claim(void);
+void eeclk_eedat_release(void);
+
 struct ep93xx_eth_data
 {
 	unsigned char	dev_addr[6];