Hi everybody,

The MPC5200 bus driver currently supports only two specific configurations:

* Non-Muxed 24b address, 8b data bus
* Muxed 25b address, 16b data bus

For my purposes I needed to use a Non-Muxed 26b address with a 16b data bus, i.e. what is referred to as "Large Flash Mode" in the MPC5200 User Manual. Therefore I have modified the bus driver and introduced 2 new arguments:

* ALEN: Address length in bits
* DLEN: Data length in bits

This should allow the bus driver to support all 8 non-muxed configurations specified in Table 9-2 as well as the 12 muxed configurations specified in Table 9-4. The behaviour defaults to Legacy Mode (which is what is used for the two configurations which are currently supported) but the pins corresponding to Large Flash Mode or MOST Graphics Mode will be used when the appropriate combination of ALEN and DLEN are enabled:

* ALEN=26,DLEN=8 or ALEN=26,DLEN=16 => sets address pins as per Large Flash Mode
* ALEN=24,DLEN=32 => sets address pins as per MOST Graphics Mode

Note that enabling the MUX option will no longer automatically change the configuration to 25b/16b as is done currently. However, it is trivial to restore the current behaviour by specifying the appropriate bus arguments, i.e. `initbus mpc5200 MUX ALEN=25 DLEN=16`.

I have only tested the non-Muxed Legacy and Large Flash Modes since that is all I have access to. I am relatively confident that these changes will not break the support for MUXed mode, but I am unable to verify this for myself. Would anyone on this list be able to run a quick test and/or consider committing this patch?

Thanks,
Daniel Burr
diff --git a/urjtag/include/urjtag/bus_driver.h b/urjtag/include/urjtag/bus_driver.h
index 92bcfd4..f1dcd31 100644
--- a/urjtag/include/urjtag/bus_driver.h
+++ b/urjtag/include/urjtag/bus_driver.h
@@ -52,6 +52,8 @@ urj_bus_area_t;
 typedef enum URJ_BUS_PARAM_KEY
 {
     URJ_BUS_PARAM_KEY_MUX,      /* bool                         mpc5200 */
+    URJ_BUS_PARAM_KEY_ADDR_LEN, /* ulong = 8|16|24|25|26        mpc5200 */
+    URJ_BUS_PARAM_KEY_DATA_LEN, /* ulong = 8|16|32              mpc5200 */
     /* avr32: mode = OCD | HSBC | HSBU | x8 | x16 | x32         avr32 */
     URJ_BUS_PARAM_KEY_OCD,      /* bool                         avr32 */
     URJ_BUS_PARAM_KEY_HSBC,     /* bool                         avr32 */
diff --git a/urjtag/src/bus/buses.c b/urjtag/src/bus/buses.c
index 6d67f56..f1cffed 100644
--- a/urjtag/src/bus/buses.c
+++ b/urjtag/src/bus/buses.c
@@ -222,6 +222,8 @@ urj_bus_init_bus (urj_chain_t *chain, const urj_bus_driver_t *bus_driver,
 static const urj_param_descr_t bus_param[] =
 {
     { URJ_BUS_PARAM_KEY_MUX,        URJ_PARAM_TYPE_BOOL,    "MUX", },
+    { URJ_BUS_PARAM_KEY_ADDR_LEN,   URJ_PARAM_TYPE_LU,      "ALEN", },
+    { URJ_BUS_PARAM_KEY_DATA_LEN,   URJ_PARAM_TYPE_LU,      "DLEN", },
     { URJ_BUS_PARAM_KEY_OCD,        URJ_PARAM_TYPE_BOOL,    "OCD", },
     { URJ_BUS_PARAM_KEY_HSBC,       URJ_PARAM_TYPE_BOOL,    "HSBC", },
     { URJ_BUS_PARAM_KEY_HSBU,       URJ_PARAM_TYPE_BOOL,    "HSBU", },
diff --git a/urjtag/src/bus/mpc5200.c b/urjtag/src/bus/mpc5200.c
index 9672373..cee8138 100644
--- a/urjtag/src/bus/mpc5200.c
+++ b/urjtag/src/bus/mpc5200.c
@@ -20,11 +20,33 @@
  * 02111-1307, USA.
  *
  * Written by Asier Llano <a.ll...@usyscom.com>, 2004.
+ * Support for adjustable bus sizes added by Daniel Burr
+ * <db...@fami.com.au>, 2013.
  *
  * Documentation:
  * [1] Freescale, "Freescale MPC5200 Users Guide", Rev. 2, 08/2004
  *     Order Number: MPC5200UG
+ * [2] Freescale, "MPC5200 Users Guide", Rev. 3.1, 03/2006
+ *     Order Number: MPC5200UG
+ *
+ * If the 'MUX' option is enabled, the address and data are sent in
+ * different tenures using the LocalPlus Bus pins EXT_AD[31:0].
+ * See Table 9-4 in [2] for the list of supported combinations of
+ * 'ALEN' and 'DLEN'.
  *
+ * If 'MUX' is not enabled then the address and data are sent in
+ * a single tenure.  For legacy modes (i.e. where the combined length
+ * of the address and data bits is <= 32 bits) this is done using
+ * only the LocalPlus Bus pins EXT_AD[31:0].  If more address
+ * lines are needed then the pins corresponding to Large Flash mode
+ * or MOST Graphics mode are used, depending upon the values of the
+ * 'ALEN' and 'DLEN' options.  See Table 9-2 in [2] for the list
+ * of supported combinations of 'ALEN' and 'DLEN'.
+ *
+ * Note that the number of address bits specified via 'ALEN' refers
+ * to the number of pins connected to a single peripheral.  The CS
+ * pins are set based on the next 3 upper bits in the target address
+ * meaning that up to 6 different peripherals can be accessed.
  */
 
 #include <sysdep.h>
@@ -32,6 +54,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
+#include <assert.h>
 
 #include <urjtag/chain.h>
 #include <urjtag/part.h>
@@ -43,25 +66,40 @@
 
 #define LPC_NUM_CS      6
 #define LPC_NUM_AD      32
+#define NUM_LARGE_ADDR  10 /* +32 LPC pins = 42 */
+#define NUM_MOSTG_ADDR  14 /* +32 LPC pins + 10 Large Flash pins = 56 */
 #define LPC_ADDR_TO_CS(a) ((a) >> bp->lpc_num_ad)
 #define LPC_ADDR_SIZE   (((long unsigned long) 1 << bp->lpc_num_ad) * LPC_NUM_CS)
 
+typedef enum
+{
+    MODE_NOMUX_LEGACY,
+    MODE_NOMUX_MOST_G,
+    MODE_NOMUX_LARGE,
+    MODE_MUX_LEGACY,
+    MODE_MAX
+} modes_t;
+
 typedef struct
 {
     uint32_t last_adr;
-    urj_part_signal_t *ad[LPC_NUM_AD];
-    urj_part_signal_t *ncs[LPC_NUM_CS];
-    urj_part_signal_t *nwe;
-    urj_part_signal_t *noe;
-    urj_part_signal_t *ata_iso;
-    urj_part_signal_t *nale;
-    int muxed;
+    urj_part_signal_t *ad[LPC_NUM_AD]; /* LocalPlus Bus */
+    urj_part_signal_t *laddr[NUM_LARGE_ADDR]; /* Extra address pins for Large Flash mode */
+    urj_part_signal_t *maddr[NUM_MOSTG_ADDR]; /* Extra address pins for MOST Graphics mode */
+    urj_part_signal_t *ncs[LPC_NUM_CS]; /* Chip Select */
+    urj_part_signal_t *nwe; /* Write Enable */
+    urj_part_signal_t *noe; /* Output Enable */
+    urj_part_signal_t *ata_iso; /* ATA Isolation */
+    urj_part_signal_t *nale; /* Address Latch Enable */
+    modes_t mode;
     int lpc_num_ad;
     int lpc_num_d;
 } bus_params_t;
 
 #define LAST_ADR        ((bus_params_t *) bus->params)->last_adr
 #define AD              ((bus_params_t *) bus->params)->ad
+#define LADDR           ((bus_params_t *) bus->params)->laddr
+#define MADDR           ((bus_params_t *) bus->params)->maddr
 #define nCS             ((bus_params_t *) bus->params)->ncs
 #define nWE             ((bus_params_t *) bus->params)->nwe
 #define nOE             ((bus_params_t *) bus->params)->noe
@@ -82,6 +120,7 @@ mpc5200_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
     char buff[10];
     int i;
     int failed = 0;
+    const char* desc;
 
     bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t));
     if (bus == NULL)
@@ -89,6 +128,7 @@ mpc5200_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
     part = bus->part;
     bp = bus->params;
 
+    bp->mode = MODE_MAX;
     bp->lpc_num_ad = 24;
     bp->lpc_num_d = 8;
 
@@ -97,19 +137,104 @@ mpc5200_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
         switch (cmd_params[i]->key)
         {
         case URJ_BUS_PARAM_KEY_MUX:
-            bp->lpc_num_ad = 25;
-            bp->lpc_num_d = 16;
-            bp->muxed = 1;
+            // old defaults for muxed mode:
+            //bp->lpc_num_ad = 25;
+            //bp->lpc_num_d = 16;
+            bp->mode = MODE_MUX_LEGACY;
+            break;
+        case URJ_BUS_PARAM_KEY_ADDR_LEN:
+            switch (cmd_params[i]->value.lu)
+            {
+            case 8:
+            case 16:
+            case 24:
+            case 25:
+            case 26:
+                bp->lpc_num_ad = cmd_params[i]->value.lu;
+                break;
+            default:
+                urj_error_set (URJ_ERROR_INVALID,
+                               _("value %lu not valid for parameter %s"),
+                               cmd_params[i]->value.lu,
+                               urj_param_string(&urj_bus_param_list,
+                                                cmd_params[i]));
+                goto fail;
+            }
+            break;
+        case URJ_BUS_PARAM_KEY_DATA_LEN:
+            switch (cmd_params[i]->value.lu)
+            {
+            case 8:
+            case 16:
+            case 32:
+                bp->lpc_num_d = cmd_params[i]->value.lu;
+                break;
+            default:
+                urj_error_set (URJ_ERROR_INVALID,
+                               _("value %lu not valid for parameter %s"),
+                               cmd_params[i]->value.lu,
+                               urj_param_string(&urj_bus_param_list,
+                                                cmd_params[i]));
+                goto fail;
+            }
             break;
         default:
-            urj_bus_generic_free (bus);
             urj_error_set (URJ_ERROR_SYNTAX, "unrecognised bus parameter '%s'",
                            urj_param_string(&urj_bus_param_list, cmd_params[i]));
-            return NULL;
+            goto fail;
+        }
+    }
+
+    /* check for invalid combinations */
+
+    if (bp->mode == MODE_MUX_LEGACY)
+    {
+        /* See Table 9-4 in [2] */
+
+        if (bp->lpc_num_ad != 26)
+        {
+            desc = "MUXed Legacy";
+        }
+        else
+        {
+            urj_error_set (URJ_ERROR_INVALID, "Data length 26 not valid with mux mode enabled");
+            goto fail;
+        }
+    }
+    else
+    {
+        /* see Table 9-2 in [2] */
+
+        if ((bp->lpc_num_ad == 8 && bp->lpc_num_d == 8) ||
+            (bp->lpc_num_ad == 8 && bp->lpc_num_d == 16) ||
+            (bp->lpc_num_ad == 16 && bp->lpc_num_d == 8) ||
+            (bp->lpc_num_ad == 16 && bp->lpc_num_d == 16) ||
+            (bp->lpc_num_ad == 24 && bp->lpc_num_d == 8))
+        {
+            desc = "Non-MUXed Legacy";
+            bp->mode = MODE_NOMUX_LEGACY;
+        }
+        else if (bp->lpc_num_ad == 24 && bp->lpc_num_d == 32)
+        {
+            desc = "Non-MUXed MOST Graphics";
+            bp->mode = MODE_NOMUX_MOST_G;
+        }
+        else if ((bp->lpc_num_ad == 26 && bp->lpc_num_d == 8) ||
+                 (bp->lpc_num_ad == 26 && bp->lpc_num_d == 16))
+        {
+            desc = "Non-MUXed Large Flash";
+            bp->mode = MODE_NOMUX_LARGE;
+        }
+        else
+        {
+            urj_error_set (URJ_ERROR_INVALID, "Data length %i not valid with address length %i with mux mode disabled",
+                           bp->lpc_num_d, bp->lpc_num_ad);
+            goto fail;
         }
     }
+
     urj_log (URJ_LOG_LEVEL_NORMAL,
-             "%sMUXed %db address, %db data bus\n", (bp->muxed ? "" : "Non-"),
+             "%s Mode, %db address, %db data bus\n", desc,
             bp->lpc_num_ad, bp->lpc_num_d);
 
     /* Get the signals */
@@ -119,6 +244,38 @@ mpc5200_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
         failed |= urj_bus_generic_attach_sig (part, &(AD[i]), buff);
     }
 
+    if (bp->mode == MODE_NOMUX_LARGE || bp->mode == MODE_NOMUX_MOST_G)
+    {
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[0]), "PCI_PAR");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[1]), "PCI_CBE_0_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[2]), "PCI_CBE_1_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[3]), "PCI_CBE_2_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[4]), "PCI_CBE_3_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[5]), "PCI_TRDY_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[6]), "PCI_IRDY_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[7]), "PCI_STOP_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[8]), "PCI_DEVSEL_B");
+        failed |= urj_bus_generic_attach_sig (part, &(LADDR[9]), "PCI_FRAME_B");
+    }
+
+    if (bp->mode == MODE_NOMUX_MOST_G)
+    {
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[0]), "PCI_SERR_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[1]), "PCI_PERR_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[2]), "PCI_IDSEL");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[3]), "PCI_REQ_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[4]), "PCI_GNT_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[5]), "PCI_RESET_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[6]), "ATA_DRQ");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[7]), "ATA_DACK_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[8]), "ATA_IOR_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[9]), "ATA_IOW_B");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[10]), "ATA_IOCHRDY");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[11]), "ATA_INTRQ");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[12]), "ATA_ISOLATION");
+        failed |= urj_bus_generic_attach_sig (part, &(MADDR[13]), "LP_ALE_B");
+    }
+
     for (i = 0; i < LPC_NUM_CS; i++)
     {
         sprintf (buff, "LP_CS%d_B", i);
@@ -129,17 +286,18 @@ mpc5200_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
 
     failed |= urj_bus_generic_attach_sig (part, &(nOE), "LP_OE");
 
-    failed |= urj_bus_generic_attach_sig (part, &(nALE), "LP_ALE_B");
+    if (bp->mode == MODE_MUX_LEGACY)
+        failed |= urj_bus_generic_attach_sig (part, &(nALE), "LP_ALE_B");
 
-    failed |= urj_bus_generic_attach_sig (part, &(ATA_ISO), "ATA_ISOLATION");
+    if (bp->mode != MODE_NOMUX_MOST_G)
+        failed |= urj_bus_generic_attach_sig (part, &(ATA_ISO), "ATA_ISOLATION");
 
-    if (failed)
-    {
-        urj_bus_generic_free (bus);
-        return NULL;
-    }
+    if (!failed) return bus;
+
+fail:
+    urj_bus_generic_free (bus);
+    return NULL;
 
-    return bus;
 }
 
 /**
@@ -190,8 +348,43 @@ setup_address (urj_bus_t *bus, uint32_t a)
     urj_part_t *p = bus->part;
     int i;
 
-    for (i = 0; i < bp->lpc_num_ad; i++)
-        urj_part_set_signal (p, AD[i], 1, (a >> i) & 1);
+    if (bp->mode == MODE_NOMUX_LEGACY || bp->mode == MODE_MUX_LEGACY)
+    {
+        /*
+         * Legacy mode: address bits sent only using LocalPlus bus
+         */
+        for (i = 0; i < bp->lpc_num_ad; i++)
+            urj_part_set_signal (p, AD[i], 1, (a >> i) & 1);
+    }
+    else if (bp->mode == MODE_NOMUX_MOST_G)
+    {
+        /*
+         * MOST Graphics mode: lower 10 bits go into LADDR and the
+         * rest go into MADDR
+         */
+        assert(bp->lpc_num_ad == 24);
+
+        for (i = 0; i < NUM_LARGE_ADDR; i++)
+            urj_part_set_signal (p, LADDR[i], 1, (a >> i) & 1);
+
+        for (i = 0; i < NUM_MOSTG_ADDR; i++)
+            urj_part_set_signal (p, MADDR[i], 1, (a >> (i+NUM_LARGE_ADDR)) & 1);
+
+    }
+    else if (bp->mode == MODE_NOMUX_LARGE)
+    {
+        /*
+         * Large Flash mode: lower 16 bits go into AD and the
+         * rest go into LADDR
+         */
+        assert(bp->lpc_num_ad == 26);
+
+        for (i = 0; i < 16; i++)
+            urj_part_set_signal (p, AD[i], 1, (a >> i) & 1);
+
+        for (i = 0; i < NUM_LARGE_ADDR; i++)
+            urj_part_set_signal (p, LADDR[i], 1, (a >> (i+16)) & 1);
+    }
 }
 
 static void
@@ -269,13 +462,14 @@ mpc5200_bus_read_start (urj_bus_t *bus, uint32_t adr)
         urj_part_set_signal (p, nCS[i], 1, !(cs == i));
     }
 
-    urj_part_set_signal_high (p, ATA_ISO);
+    if (bp->mode != MODE_NOMUX_MOST_G)
+        urj_part_set_signal_high (p, ATA_ISO);
     urj_part_set_signal_high (p, nWE);
     urj_part_set_signal_low (p, nOE);
 
     setup_address (bus, adr);
 
-    if (!bp->muxed)
+    if (bp->mode != MODE_MUX_LEGACY)
         set_data_in (bus, adr);
     else
     {
@@ -299,7 +493,7 @@ mpc5200_bus_read_next (urj_bus_t *bus, uint32_t adr)
     urj_part_t *p = bus->part;
     uint32_t d;
 
-    if (!bp->muxed)
+    if (bp->mode != MODE_MUX_LEGACY)
     {
         setup_address (bus, adr);
         urj_tap_chain_shift_data_registers (bus->chain, 1);
@@ -337,7 +531,7 @@ mpc5200_bus_read_end (urj_bus_t *bus)
     urj_part_t *p = bus->part;
     int i;
 
-    if (bp->muxed)
+    if (bp->mode == MODE_MUX_LEGACY)
     {
         set_data_in (bus, LAST_ADR);
         urj_tap_chain_shift_data_registers (bus->chain, 0);
@@ -367,7 +561,7 @@ mpc5200_bus_write (urj_bus_t *bus, uint32_t adr, uint32_t data)
     uint8_t cs = LPC_ADDR_TO_CS (adr);
     int i;
 
-    if (bp->muxed)
+    if (bp->mode == MODE_MUX_LEGACY)
     {
         setup_address (bus, adr);
         urj_part_set_signal_low (p, nALE);
@@ -380,11 +574,12 @@ mpc5200_bus_write (urj_bus_t *bus, uint32_t adr, uint32_t data)
     {
         urj_part_set_signal (p, nCS[i], 1, !(cs == i));
     }
-    urj_part_set_signal_high (p, ATA_ISO);
+    if (bp->mode != MODE_NOMUX_MOST_G)
+        urj_part_set_signal_high (p, ATA_ISO);
     urj_part_set_signal_high (p, nWE);
     urj_part_set_signal_high (p, nOE);
 
-    if (!bp->muxed)
+    if (bp->mode != MODE_MUX_LEGACY)
         setup_address (bus, adr);
     setup_data (bus, adr, data);
 
@@ -398,7 +593,8 @@ mpc5200_bus_write (urj_bus_t *bus, uint32_t adr, uint32_t data)
 
 const urj_bus_driver_t urj_bus_mpc5200_bus = {
     "mpc5200",
-    N_("Freescale MPC5200 compatible bus driver via BSR, parameter: [mux]"),
+    N_("Freescale MPC5200 compatible bus driver via BSR, parameters:\n"
+       "           [mux] [alen=8|16|24|25|26] [dlen=8|16|32]"),
     mpc5200_bus_new,
     urj_bus_generic_free,
     mpc5200_bus_printinfo,
------------------------------------------------------------------------------
Shape the Mobile Experience: Free Subscription
Software experts and developers: Be at the forefront of tech innovation.
Intel(R) Software Adrenaline delivers strategic insight and game-changing 
conversations that shape the rapidly evolving mobile landscape. Sign up now. 
http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk
_______________________________________________
UrJTAG-development mailing list
UrJTAG-development@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to