summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0052-Implemented-Bone-Cape-configuration-from-EEPROM.-Onl.patch
blob: 15b428e39aa4b2b1c04aa8683a09eb67cd841db6 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
From 2ab55bf6a97122999e0cd6cbe18869fb89b59c0a Mon Sep 17 00:00:00 2001
From: Bas Laarhoven <sjml@xs4all.nl>
Date: Sun, 13 May 2012 18:14:22 +0200
Subject: [PATCH 52/79] Implemented Bone Cape configuration from EEPROM. Only
 used for BEBOPR cape for now.

Signed-off-by: Bas Laarhoven <sjml@xs4all.nl>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
 arch/arm/mach-omap2/board-am335xevm.c |  304 +++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux33xx.c         |   14 ++
 2 files changed, 318 insertions(+)

diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
index c6ec997..7fb8295 100644
--- a/arch/arm/mach-omap2/board-am335xevm.c
+++ b/arch/arm/mach-omap2/board-am335xevm.c
@@ -2231,6 +2231,304 @@ static void tt3201_init(int evm_id, int profile)
 
 	am33xx_d_can_init(1);
 }
+
+static const char* cape_pins[] = {
+/*
+  From SRM RevA5.0.1:
+*/
+  /* offset  88 - P9-22 */ "uart2_rxd",
+  /* offset  90 - P9-21 */ "uart2_txd",
+  /* offset  92 - P9-18 */ "spi0_d1",
+  /* offset  94 - P9-17 */ "spi0_cs0",
+  /* offset  96 - P9-42 */ "ecap0_in_pwm0_out",
+  /* offset  98 - P8-35 */ "lcd_data12",
+  /* offset 100 - P8-33 */ "lcd_data13",
+  /* offset 102 - P8-31 */ "lcd_data14",
+  /* offset 104 - P8-32 */ "lcd_data15",
+  /* offset 106 - P9-19 */ "uart1_rtsn",
+  /* offset 108 - P9-20 */ "uart1_ctsn",
+  /* offset 110 - P9-26 */ "uart1_rxd",
+  /* offset 112 - P9-24 */ "uart1_txd",
+  /* offset 114 - P9-41 */ "xdma_event_intr1",
+  /* offset 116 - P8-19 */ "gpmc_ad8",
+  /* offset 118 - P8-13 */ "gpmc_ad9",
+  /* offset 120 - P8-14 */ "gpmc_ad10",
+  /* offset 122 - P8-17 */ "gpmc_ad12",
+  /* offset 124 - P9-11 */ "gpmc_wait0",
+  /* offset 126 - P9-13 */ "gpmc_wpn",
+  /* offset 128 - P8-25 */ "gpmc_ad0",
+  /* offset 130 - P8-24 */ "gpmc_ad1",
+  /* offset 132 - P8- 5 */ "gpmc_ad2",
+  /* offset 134 - P8- 6 */ "gpmc_ad3",
+  /* offset 136 - P8-23 */ "gpmc_ad4",
+  /* offset 138 - P8-22 */ "gpmc_ad5",
+  /* offset 140 - P8- 3 */ "gpmc_ad6",
+  /* offset 142 - P8- 4 */ "gpmc_ad7",
+  /* offset 144 - P8-12 */ "gpmc_ad12",
+  /* offset 146 - P8-11 */ "gpmc_ad13",
+  /* offset 148 - P8-16 */ "gpmc_ad14",
+  /* offset 150 - P8-15 */ "gpmc_ad15",
+  /* offset 152 - P9-15 */ "gpmc_a0",
+  /* offset 154 - P9-23 */ "gpmc_a1",
+  /* offset 156 - P9-14 */ "gpmc_a2",
+  /* offset 158 - P9-16 */ "gpmc_a3",
+  /* offset 160 - P9-12 */ "gpmc_be1n",
+  /* offset 162 - P8-26 */ "gpmc_csn0",
+  /* offset 164 - P8-21 */ "gpmc_csn1",
+  /* offset 166 - P8-20 */ "gpmc_csn2",
+  /* offset 168 - P8-18 */ "gpmc_clk",
+  /* offset 170 - P8-7  */ "gpmc_advn_ale",
+  /* offset 172 - P8-9  */ "gpmc_ben0_cle",
+  /* offset 174 - P8-10 */ "gpmc_wen",
+  /* offset 176 - P8-8  */ "gpmc_csn3",
+  /* offset 178 - P8-45 */ "lcd_data0",
+  /* offset 180 - P8-46 */ "lcd_data1",
+  /* offset 182 - P8-43 */ "lcd_data2",
+  /* offset 184 - P8-44 */ "lcd_data3",
+  /* offset 186 - P8-41 */ "lcd_data4",
+  /* offset 188 - P8-42 */ "lcd_data5",
+  /* offset 190 - P8-39 */ "lcd_data6",
+  /* offset 192 - P8-40 */ "lcd_data7",
+  /* offset 194 - P8-37 */ "lcd_data8",
+  /* offset 196 - P8-38 */ "lcd_data9",
+  /* offset 198 - P8-36 */ "lcd_data10",
+  /* offset 200 - P8-34 */ "lcd_data11",
+  /* offset 202 - P8-27 */ "lcd_vsync",
+  /* offset 204 - P8-29 */ "lcd_hsync",
+  /* offset 206 - P8-28 */ "lcd_pclk",
+  /* offset 208 - P8-30 */ "lcd_ac_bias_en",
+  /* offset 210 - P9-29 */ "mcasp0_fsx",
+  /* offset 212 - P9-30 */ "mcasp0_axr0",
+  /* offset 214 - P9-28 */ "mcasp0_ahclkr",
+  /* offset 216 - P9-27 */ "mcasp0_fsr",
+  /* offset 218 - P9-31 */ "mcasp0_aclkx",
+  /* offset 220 - P9-25 */ "mcasp0_ahclkx",
+  /* offset 222 - P9-39 */ "ain0",
+  /* offset 224 - P9-40 */ "ain1",
+  /* offset 226 - P9-37 */ "ain2",
+  /* offset 228 - P9-38 */ "ain3",
+  /* offset 230 - P9-33 */ "ain4",
+  /* offset 232 - P9-36 */ "ain5",
+  /* offset 234 - P9-35 */ "ain6",
+};
+
+#define BIG_ENDIAN_16( i) ( ((i & 255) << 8) | ((i >> 8) & 255) )
+#define NR_ITEMS( x) (sizeof( (x)) / sizeof( *(x)))
+
+extern int am33xx_mux_get_entry( int index, struct omap_mux** mux);
+
+typedef union {
+/*
+  From SRM RevA5.0.1:
+  Bit 15     Pin is used or not: 0=Unused by Cape 1=Used by Cape
+  Bit 14-13  Pin Direction: 10=Output 01=Input 11=BDIR
+  Bit 12-7   Reserved
+  Bit 6      Slew Rate: 0=Fast 1=Slow
+  Bit 5      Rx Enable: 0=Disabled 1=Enabled
+  Bit 4      Pull Up/Dn Select: 0=Pulldown 1=PullUp
+  Bit 3      Pull Up/DN enabled: 0=Enabled 1=Disabled
+  Bit 2-0    Mux Mode Selection: Mode 0-7
+*/
+	struct {
+		uint16_t    mux             : 3;
+	  	uint16_t    pull_enable     : 1;
+		uint16_t    pull_up         : 1;
+	  	uint16_t    rx_enable       : 1;
+		uint16_t    slew_rate       : 1;
+	  	uint16_t    reserved        : 6;
+	  	uint16_t    direction       : 2;
+	  	uint16_t    used            : 1;
+	};
+  	uint16_t      value;
+} pin_def;
+
+#define DEBUG_EEPROM_CONFIG 0
+
+static int bone_io_get_mux_setting( pin_def setting)
+{
+	int pin_setting;
+
+	switch (setting.direction) {
+	case 1:
+	/* input */
+	  	if (setting.pull_enable) {
+			if (setting.pull_up) {
+			  	pin_setting = AM33XX_PIN_INPUT_PULLUP;
+			} else {
+			  	pin_setting = AM33XX_PIN_INPUT_PULLDOWN;
+			}
+		} else {
+		  	pin_setting = AM33XX_PIN_INPUT;
+		}
+		if (!setting.rx_enable) {
+#if DEBUG_EEPROM_CONFIG
+			pr_warning( "  pin is set as input but the receiver is not enabled!\n");
+#endif
+		}
+		break;
+	case 2:
+	/* output */
+	  	pin_setting = AM33XX_PIN_OUTPUT;
+		break;
+	case 3:
+	/* bi-dir */
+	default:
+	/* reserved */
+#if DEBUG_EEPROM_CONFIG
+	  	pr_warning( "  pin ignored because it uses an unsupported mode: 0x%04x\n",
+			    setting.direction);
+#endif
+		return -1;
+	}
+#if DEBUG_EEPROM_CONFIG
+	pr_info("  pin is configured as %s\n",
+		(pin_setting & AM33XX_PIN_INPUT) ? "input" : "output");
+#endif
+	switch (setting.mux) {
+	case 0: pin_setting |= OMAP_MUX_MODE0; break;
+	case 1: pin_setting |= OMAP_MUX_MODE1; break;
+	case 2: pin_setting |= OMAP_MUX_MODE2; break;
+	case 3: pin_setting |= OMAP_MUX_MODE3; break;
+	case 4: pin_setting |= OMAP_MUX_MODE4; break;
+	case 5: pin_setting |= OMAP_MUX_MODE5; break;
+	case 6: pin_setting |= OMAP_MUX_MODE6; break;
+	case 7: pin_setting |= OMAP_MUX_MODE7; break;
+	}
+	return pin_setting;
+}
+
+static struct omap_mux* bone_io_pin_lookup( const char* pin_name)
+{
+	int index = 0;
+	struct omap_mux* mux;
+
+	for (;;) {
+		if (am33xx_mux_get_entry( index, &mux) < 0) {
+		  	/* no more entries */
+#if DEBUG_EEPROM_CONFIG
+		  	pr_warning( "   configuration error, pin '%s' not found in mux database\n",
+				    pin_name);
+#endif
+			return NULL;
+		}
+		if (mux != NULL &&
+		    mux->muxnames[ 0] != NULL &&
+		    strcmp( mux->muxnames[ 0], pin_name) == 0)
+		{
+			/* entry found */
+#if DEBUG_EEPROM_CONFIG
+			pr_info( "   found pin '%s' at index %d in mux database'\n",
+				 pin_name, index);
+#endif
+			return mux;
+		}
+		++index;
+	}
+}
+
+static int bone_io_config_pin( const char* pin_name, pin_def eeprom_setting)
+{
+	struct omap_mux* mux;
+	char* signal_name;
+	int pin_setting = bone_io_get_mux_setting( eeprom_setting);
+	int l1, l2;
+	char full_name[ 50];
+
+	if (pin_setting < 0) {
+		return -1;
+	}
+
+	mux = bone_io_pin_lookup( pin_name);
+
+	if (mux == NULL) {
+		return -1;
+	}
+
+	signal_name = mux->muxnames[ eeprom_setting.mux];
+
+	if (signal_name == NULL) {
+#if DEBUG_EEPROM_CONFIG
+	  	pr_warning( "    Configuration error, no signal found for pin '%s' in mode %d\n",
+			    pin_name, eeprom_setting.mux);
+#endif
+		return -1;
+	}
+
+#if DEBUG_EEPROM_CONFIG
+	pr_info( "    setting pin '%s' to signal '%s'\n",
+		 pin_name, signal_name);
+#endif
+  	l1 = strlen( pin_name);
+	l2 = strlen( signal_name);
+
+	if (l1 + 1 + l2 + 1 > sizeof( full_name)) {
+#if DEBUG_EEPROM_CONFIG
+	  	pr_warning( "    Internal error, combined signal name too long\n");
+#endif
+		return -1;
+	} else {
+	  	memcpy( full_name, pin_name, l1);
+		full_name[ l1] = '.';
+		memcpy( full_name + l1 + 1, signal_name, l2);
+		full_name[ l1 + 1 + l2] = '\0';
+		if (omap_mux_init_signal( full_name, pin_setting) < 0) {
+			return -1;
+		}
+#if DEBUG_EEPROM_CONFIG
+		pr_info( "     mux '%s' was set to mode 0x%04x\n",
+			 full_name, pin_setting);
+#endif
+	}
+	// return 0 for input, 1 for output
+	return (pin_setting & AM33XX_PIN_INPUT) ? 0 : 1;
+}
+
+#define RULER( x) \
+	do { \
+		char* p = status; \
+		int i = 0; \
+		int cnt = x; \
+		status[ cnt] = '\0'; \
+		while (cnt--) { \
+			if (++i == 10) { \
+				*p++ = '+'; \
+				i = 0; \
+			} else { \
+				*p++ = '-'; \
+			} \
+		} \
+		pr_info( "+%s+\n", status); \
+	} while (0)
+
+static void bone_io_config_from_cape_eeprom( void)
+{
+	int i;
+	int cnt = BIG_ENDIAN_16( cape_config.numpins);
+	u16* pmuxdata;
+	char status[ NR_ITEMS( cape_config.muxdata) + 1];
+
+	pr_info( "BeagleBone cape: configuring %2d out of %2d signals:\n",
+		 cnt, NR_ITEMS( cape_config.muxdata));
+	RULER( NR_ITEMS( cape_config.muxdata));
+	for (i = 0, pmuxdata = cape_config.muxdata ; i < NR_ITEMS( cape_config.muxdata) ; ++i, ++pmuxdata) {
+		const char* pin_name = cape_pins[ i];
+		pin_def pin_setting = { .value = BIG_ENDIAN_16( *pmuxdata) };
+
+		if (pin_setting.used) {
+			switch (bone_io_config_pin( pin_name, pin_setting)) {
+			case 0:  status[ i] = 'i'; break;
+			case 1:  status[ i] = 'o'; break;
+			default: status[ i] = '#'; break;
+			}
+		} else {
+			status[ i] = ' ';
+		}
+	}
+	status[ NR_ITEMS( cape_config.muxdata)] = '\0';
+	pr_info( "|%s|\n", status);
+	RULER( NR_ITEMS( cape_config.muxdata));
+}
+
 static void beaglebone_cape_setup(struct memory_accessor *mem_acc, void *context)
 {
 	int ret;
@@ -2280,6 +2578,12 @@ static void beaglebone_cape_setup(struct memory_accessor *mem_acc, void *context
 	snprintf(tmp, sizeof(cape_config.partnumber) + 1, "%s", cape_config.partnumber);
 	pr_info("BeagleBone cape partnumber: %s\n", tmp);   
 
+	if (!strncmp( "BEBOPR", cape_config.name, 6)) {
+		pr_info( "BeagleBone cape: initializing BEBOPR cape\n");
+		bone_io_config_from_cape_eeprom();
+		return;	// if configured from eeprom, skip all other initialization
+	}
+
 	if (!strncmp("BB-BONE-DVID-01", cape_config.partnumber, 15)) {
 		pr_info("BeagleBone cape: initializing DVI cape\n");
 		
diff --git a/arch/arm/mach-omap2/mux33xx.c b/arch/arm/mach-omap2/mux33xx.c
index 72ac899..43c8989 100644
--- a/arch/arm/mach-omap2/mux33xx.c
+++ b/arch/arm/mach-omap2/mux33xx.c
@@ -616,6 +616,20 @@ int __init am33xx_mux_init(struct omap_board_mux *board_subset)
 			AM33XX_CONTROL_PADCONF_MUX_SIZE, am33xx_muxmodes,
 			NULL, board_subset, NULL);
 }
+
+#define NR_ITEMS( x) (sizeof( (x)) / sizeof( *(x)))
+
+int am33xx_mux_get_entry( int index, struct omap_mux** mux)
+{
+  if (index >= 0 && index < NR_ITEMS( am33xx_muxmodes)) {
+    *mux = &am33xx_muxmodes[ index];
+    return 0;
+  } else {
+    *mux = NULL;
+    return -1;
+  }
+}
+
 #else
 int __init am33xx_mux_init(struct omap_board_mux *board_subset)
 {
-- 
1.7.10