From 2d21e7d9eecaa95a517f79e8fba37a18bd9eda50 Mon Sep 17 00:00:00 2001
From: Mychaela Falconia <falcon@freecalypso.org>
Date: Mon, 28 Sep 2020 19:07:40 +0000
Subject: [PATCH 1/3] gtm900b target: fix GPIO configuration

This change fixes one bug and one uncertainty:

Bug: Huawei defined Calypso GPIO 3 to be DTR input on this modem,
following TI's precedent from C-Sample and D-Sample platforms.
(Huawei's documentation calls the corresponding FPC interface pin
UART_DTR without even mentioning that it is actually wired to
Calypso GPIO 3 in the hardware.)

The previous code (erroneously copied from gta0x target which is
different in this regard) configured this GPIO to be an output,
creating a driver conflict.

Uncertainty: GPIOs 4, 6, 10, 11 and 12 power up as inputs, and
Huawei's official fw leaves them as such.  But in the absence of
someone reverse-engineering a sacrificial GTM900 module by slicing
its PCB and imaging its copper layers and vias, we don't know if
these Calypso pins are simply unconnected like they are on Openmoko
devices (in which case they are floating inputs and should be
switched to driving dummy outputs), or if they are tied off in the
hardware in one way or another, in which case leaving them as inputs
is correct.

On the reasoning that floating inputs are a lesser evil than driver
conflicts or shorted outputs, leave these GPIOs as inputs until
we gain better knowledge of this aspect of the hardware.
---
 src/target/firmware/board/gtm900b/init.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/target/firmware/board/gtm900b/init.c b/src/target/firmware/board/gtm900b/init.c
index 38ede10..f04d314 100644
--- a/src/target/firmware/board/gtm900b/init.c
+++ b/src/target/firmware/board/gtm900b/init.c
@@ -67,14 +67,12 @@ static void board_io_init(void)
 	writew(reg, ASIC_CONF_REG);
 
 	/*
-	 * Most Calypso peripheral interface signals are unconnected
-	 * on this modem.  We configure them to be GPIOs in IO_CONF_REG,
-	 * then configure them to be outputs in IO_CNTL_REG, then set
-	 * the outputs to 0 in ARMIO_LATCH_OUT.
+	 * Configure Calypso GPIO and multifunction pins the same way
+	 * how Huawei's official firmware configures them.
 	 */
 	writew(0x03F5, IO_CONF_REG);
-	writew(0xC000, IO_CNTL_REG);
-	writew(0x0000, ARMIO_LATCH_OUT);
+	writew(0xDC58, IO_CNTL_REG);
+	writew(0x0007, ARMIO_LATCH_OUT);
 
 	/* Set LPG output permanently on (power LED) */
 	writew(1, LPG_PM_REG);
-- 
2.9.0


From e19b6fc51784e772357dd402d22ac5dafaee391f Mon Sep 17 00:00:00 2001
From: Mychaela Falconia <falcon@freecalypso.org>
Date: Mon, 28 Sep 2020 19:31:30 +0000
Subject: [PATCH 2/3] gtm900b target: fix MEMIF configuration

* Switch Calypso output CS4/ADD22 to ADD22 function as needed
  in order to access the upper half of the flash on GTM900 hw
  variant MG01GSMT.

* Set WS=4 for safety - please refer to this technical article for
  the underlying theory:

https://www.freecalypso.org/hg/freecalypso-docs/file/tip/MEMIF-wait-states
---
 src/target/firmware/board/gtm900b/init.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/target/firmware/board/gtm900b/init.c b/src/target/firmware/board/gtm900b/init.c
index f04d314..8de9956 100644
--- a/src/target/firmware/board/gtm900b/init.c
+++ b/src/target/firmware/board/gtm900b/init.c
@@ -50,6 +50,7 @@
 
 #define ARMIO_LATCH_OUT 0xfffe4802
 #define IO_CNTL_REG	0xfffe4804
+#define ARM_CONF_REG	0xfffef006
 #define ASIC_CONF_REG	0xfffef008
 #define IO_CONF_REG	0xfffef00a
 #define LPG_LCR_REG	0xfffe7800
@@ -77,13 +78,28 @@ static void board_io_init(void)
 	/* Set LPG output permanently on (power LED) */
 	writew(1, LPG_PM_REG);
 	writew((1 << 7), LPG_LCR_REG);
+
+	/* configure ADD(22), needed for second half of flash on MG01GSMT */
+	reg = readw(ARM_CONF_REG);
+	reg |= (1 << 3);
+	writew(reg, ARM_CONF_REG);
 }
 
 void board_init(int with_irq)
 {
-	/* Configure the memory interface */
-	calypso_mem_cfg(CALYPSO_nCS0, 3, CALYPSO_MEM_16bit, 1);
-	calypso_mem_cfg(CALYPSO_nCS1, 3, CALYPSO_MEM_16bit, 1);
+	/*
+	 * Configure the memory interface.
+	 * Huawei's official fw sets WS=4 for RAM, but not for flash -
+	 * but let's be consistent and use WS=4 for both.  Please refer
+	 * to this technical article for the underlying theory:
+https://www.freecalypso.org/hg/freecalypso-docs/file/tip/MEMIF-wait-states
+	 */
+	calypso_mem_cfg(CALYPSO_nCS0, 4, CALYPSO_MEM_16bit, 1);
+	calypso_mem_cfg(CALYPSO_nCS1, 4, CALYPSO_MEM_16bit, 1);
+	/*
+	 * The remaining 3 chip selects are unused on this hw,
+	 * thus their settings are dummies.
+	 */
 	calypso_mem_cfg(CALYPSO_nCS2, 5, CALYPSO_MEM_16bit, 1);
 	calypso_mem_cfg(CALYPSO_nCS3, 5, CALYPSO_MEM_16bit, 1);
 	calypso_mem_cfg(CALYPSO_CS4, 0, CALYPSO_MEM_8bit, 1);
-- 
2.9.0


From bee94f08d26aaad9becff53d3665997e8da7f8c1 Mon Sep 17 00:00:00 2001
From: Mychaela Falconia <falcon@freecalypso.org>
Date: Mon, 28 Sep 2020 19:42:41 +0000
Subject: [PATCH 3/3] gtm900b target: fix flash-based hardware variant
 autodetection

The original code used simplified logic whereby it assumed that
Spansion flash means MG01GSMT and Samsung flash means MGCxGSMT.
However, there exist MGC2GSMT hw variants with Spansion S71PL032J
flash in them, thus it is necessary to check the complete device ID
rather than just the flash manufacturer ID to distinguish between
MG01GSMT with 8 MiB flash (S71PL064J) and MGCxGSMT with 4 MiB flash
(S71PL032J, K5A3281CTM or K5L3316CAM).

Distinguishing between 4 MiB and 8 MiB flash chip types is also
necessary in order to configure TIFFS reader for the correct FFS
location matching that used by the original firmware, which is
in turn necessary in order to read factory RF calibration values.
---
 src/target/firmware/board/gtm900b/init.c         | 67 ++++++++++++++++++++++++
 src/target/firmware/board/gtm900b/rffe_gtm900b.c | 38 ++------------
 2 files changed, 72 insertions(+), 33 deletions(-)

diff --git a/src/target/firmware/board/gtm900b/init.c b/src/target/firmware/board/gtm900b/init.c
index 8de9956..934e96e 100644
--- a/src/target/firmware/board/gtm900b/init.c
+++ b/src/target/firmware/board/gtm900b/init.c
@@ -56,6 +56,8 @@
 #define LPG_LCR_REG	0xfffe7800
 #define LPG_PM_REG	0xfffe7801
 
+int gtm900_hw_is_mg01gsmt;
+
 static void board_io_init(void)
 {
 	uint16_t reg;
@@ -85,6 +87,68 @@ static void board_io_init(void)
 	writew(reg, ARM_CONF_REG);
 }
 
+/*
+ * There exist two firmware-incompatible versions of GTM900-B hardware:
+ * MG01GSMT and MGCxGSMT.  They have different flash chip types (8 MiB
+ * vs. 4 MiB) with correspondingly different TIFFS configurations
+ * (and we need TIFFS in order to read factory RF calibration values),
+ * and they have different (incompatible) RFFE control signals.
+ *
+ * We are going to check the flash chip type and use it to decide which
+ * hw variant we are running on.
+ */
+static void board_flash_init(void)
+{
+	uint16_t manufacturer_id, device_id[3];
+
+	/* Use an address above the Calypso boot ROM
+	 * so we don't need to unmap it to access the flash. */
+	flash_get_id((void *)0x40000, &manufacturer_id, device_id);
+
+	switch (manufacturer_id) {
+	case CFI_MANUF_SPANSION:
+		/* is it S71PL064J? */
+		if (device_id[0] == 0x227E && device_id[1] == 0x2202 &&
+		    device_id[2] == 0x2201) {
+			gtm900_hw_is_mg01gsmt = 1;
+			break;
+		}
+		/* is it S71PL032J? */
+		if (device_id[0] == 0x227E && device_id[1] == 0x220A &&
+		    device_id[2] == 0x2201) {
+			gtm900_hw_is_mg01gsmt = 0;
+			break;
+		}
+		goto bad;
+	case CFI_MANUF_SAMSUNG:
+		/* is it K5A3281CTM? */
+		if (device_id[0] == 0x22A0) {
+			gtm900_hw_is_mg01gsmt = 0;
+			break;
+		}
+		/* is it K5L3316CAM? */
+		if (device_id[0] == 0x257E && device_id[1] == 0x2503 &&
+		    device_id[2] == 0x2501) {
+			gtm900_hw_is_mg01gsmt = 0;
+			break;
+		}
+		/* FALL THRU */
+	default:
+	bad:
+		printf("Unknown module detected, "
+		       "flash ID 0x%04x 0x%04x 0x%04x 0x%04x\n"
+		       "Please contact mailing list!\n\n", manufacturer_id,
+		       device_id[0], device_id[1], device_id[2]);
+		return;
+	}
+
+	/* Initialize TIFFS reader */
+	if (gtm900_hw_is_mg01gsmt)
+		tiffs_init(0x700000, 0x10000, 15);
+	else
+		tiffs_init(0x380000, 0x10000, 7);
+}
+
 void board_init(int with_irq)
 {
 	/*
@@ -151,4 +215,7 @@ https://www.freecalypso.org/hg/freecalypso-docs/file/tip/MEMIF-wait-states
 
 	/* Initialize ABB driver (uses SPI) */
 	twl3025_init();
+
+	/* Initialize board flash */
+	board_flash_init();
 }
diff --git a/src/target/firmware/board/gtm900b/rffe_gtm900b.c b/src/target/firmware/board/gtm900b/rffe_gtm900b.c
index 633c637..3efb5e2 100644
--- a/src/target/firmware/board/gtm900b/rffe_gtm900b.c
+++ b/src/target/firmware/board/gtm900b/rffe_gtm900b.c
@@ -1,5 +1,5 @@
 /* RF frontend driver for Huawei GTM900-B modems, supporting both
- * MG01GSMT and MG01GSMT hardware variants */
+ * MG01GSMT and MGCxGSMT hardware variants */
 
 /* (C) 2019 by Steve Markgraf <steve@steve-m.de>
  *
@@ -63,12 +63,7 @@
  * Tx2: high band PA output
  */
 
-typedef enum rffe_var {
-	RFFE_MGC2GSMT,
-	RFFE_MG01GSMT
-} rffe_var_t;
-
-static rffe_var_t rffe_variant = RFFE_MGC2GSMT;
+extern int gtm900_hw_is_mg01gsmt;	/* set in init.c */
 
 static inline void rffe_mode_mgc2gsmt(enum gsm_band band, int tx)
 {
@@ -139,10 +134,10 @@ static inline void rffe_mode_mg01gsmt(enum gsm_band band, int tx)
 /* switch RF Frontend Mode */
 void rffe_mode(enum gsm_band band, int tx)
 {
-	if (rffe_variant == RFFE_MGC2GSMT)
-		rffe_mode_mgc2gsmt(band, tx);
-	else
+	if (gtm900_hw_is_mg01gsmt)
 		rffe_mode_mg01gsmt(band, tx);
+	else
+		rffe_mode_mgc2gsmt(band, tx);
 }
 
 uint32_t rffe_get_rx_ports(void)
@@ -166,7 +161,6 @@ int rffe_iq_swapped(uint16_t band_arfcn, int tx)
 void rffe_init(void)
 {
 	uint16_t reg;
-	uint16_t manufacturer_id = 0;
 
 	reg = readw(ARM_CONF_REG);
 	reg &= ~ (1 << 7);	/* TSPACT4 I/O function, not nRDYMEM */
@@ -176,28 +170,6 @@ void rffe_init(void)
 	tsp_setup(IOTA_STROBE, 1, 0, 0);
 
 	trf6151_init(RITA_STROBE, RITA_RESET);
-
-	/* Detect the used RFFE variant based on the used flash chip.
-	 * The MGC2GSMT uses a Samsung flash, whereas the MG01GSMT uses
-	 * a Spansion flash. We use an address above the Calpso bootrom
-	 * so we do not need to unmap it to access the flash. */
-	flash_get_id((void *)0x40000, &manufacturer_id, NULL);
-
-	switch (manufacturer_id) {
-	case CFI_MANUF_SPANSION:
-		printf("Detected MG01GSMT module\n\n");
-		rffe_variant = RFFE_MG01GSMT;
-		break;
-	case CFI_MANUF_SAMSUNG:
-		printf("Detected MGC2GSMT module\n\n");
-		rffe_variant = RFFE_MGC2GSMT;
-		break;
-	default:
-		printf("Unknown module detected, flash ID 0x%4.4x\n"
-		       "Please contact mailing list!\n\n", manufacturer_id);
-		rffe_variant = RFFE_MGC2GSMT;
-		break;
-	}
 }
 
 uint8_t rffe_get_gain(void)
-- 
2.9.0

