[U-Boot] [PATCH 06/11] powerpc/ppc4xx: Support gdsys multichannel iocon hardware

Dirk Eibach
2013-04-22T11:16:07Z

Signed-off-by: Dirk Eibach <eibach@gdsys.de>
---
board/gdsys/405ep/iocon.c | 253 ++++++++++++++++++++++++++++++++++++++-------
include/configs/iocon.h | 37 ++++---
include/gdsys_fpga.h | 15 ++-
3 files changed, 248 insertions(+), 57 deletions(-)

diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c
index 0fc7db2..ece45d6 100644
--- a/board/gdsys/405ep/iocon.c
+++ b/board/gdsys/405ep/iocon.c
@@ -23,6 +23,7 @@

#include <common.h>
#include <command.h>
+#include <errno.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/ppc4xx-gpio.h>
@@ -31,6 +32,13 @@
#include <gdsys_fpga.h>

#include "../common/osd.h"
+#include "../common/mclink.h"
+
+#include <i2c.h>
+#include <pca953x.h>
+#include <pca9698.h>
+
+DECLARE_GLOBAL_DATA_PTR;

#define LATCH0_BASE (CONFIG_SYS_LATCH_BASE)
#define LATCH1_BASE (CONFIG_SYS_LATCH_BASE + 0x100)
@@ -47,11 +55,20 @@ enum {
HWVER_100 = 0,
HWVER_104 = 1,
HWVER_110 = 2,
+ HWVER_120 = 3,
+ HWVER_200 = 4,
+ HWVER_210 = 5,
+};
+
+enum {
+ FPGA_HWVER_200 = 0,
+ FPGA_HWVER_210 = 1,
};

enum {
COMPRESSION_NONE = 0,
- COMPRESSION_TYPE1_DELTA,
+ COMPRESSION_TYPE1_DELTA = 1,
+ COMPRESSION_TYPE1_TYPE2_DELTA = 3,
};

enum {
@@ -67,8 +84,56 @@ enum {

enum {
RAM_DDR2_32 = 0,
+ RAM_DDR3_32 = 1,
+};
+
+enum {
+ MCFPGA_DONE = 1 << 0,
+ MCFPGA_INIT_N = 1 << 1,
+ MCFPGA_PROGRAM_N = 1 << 2,
+ MCFPGA_UPDATE_ENABLE_N = 1 << 3,
+ MCFPGA_RESET_N = 1 << 4,
};

+unsigned int mclink_fpgacount;
+
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data)
+{
+ int res;
+ struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0);
+
+ switch (fpga) {
+ case 0:
+ out_le16((u16 *)fpga_0 + reg / sizeof(u16), data);
+ break;
+ default:
+ res = mclink_send(fpga - 1, reg, data);
+ if (res < 0)
+ printf("mclink_send reg %02x data %04x returned %d\n",
+ reg, data, res);
+ break;
+ }
+}
+
+u16 fpga_get_reg(unsigned int fpga, u16 reg)
+{
+ int res;
+ u16 data;
+ struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0);
+
+ switch (fpga) {
+ case 0:
+ return in_le16((u16 *)fpga_0 + reg / sizeof(u16));
+ default:
+ if (fpga > mclink_fpgacount)
+ return -EINVAL;
+ res = mclink_receive(fpga - 1, reg, &data);
+ if (res < 0)
+ printf("mclink_receive returned %d\n", res);
+ return data;
+ }
+}
+
/*
* Check Board Identity:
*/
@@ -90,12 +155,11 @@ int checkboard(void)
return 0;
}

-static void print_fpga_info(void)
+static void print_fpga_info(unsigned int fpga)
{
- struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0);
- u16 versions = in_le16(&fpga->versions);
- u16 fpga_version = in_le16(&fpga->fpga_version);
- u16 fpga_features = in_le16(&fpga->fpga_features);
+ u16 versions = fpga_get_reg(fpga, REG(versions));
+ u16 fpga_version = fpga_get_reg(fpga, REG(fpga_version));
+ u16 fpga_features = fpga_get_reg(fpga, REG(fpga_features));
unsigned unit_type;
unsigned hardware_version;
unsigned feature_compression;
@@ -105,9 +169,9 @@ static void print_fpga_info(void)
unsigned feature_ramconfig;
unsigned feature_carriers;
unsigned feature_video_channels;
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;

unit_type = (versions & 0xf000) >> 12;
- hardware_version = versions & 0x000f;
feature_compression = (fpga_features & 0xe000) >> 13;
feature_osd = fpga_features & (1<<11);
feature_audio = (fpga_features & 0x0600) >> 9;
@@ -116,6 +180,9 @@ static void print_fpga_info(void)
feature_carriers = (fpga_features & 0x000c) >> 2;
feature_video_channels = fpga_features & 0x0003;

+ if (legacy)
+ printf("legacy ");
+
switch (unit_type) {
case UNITTYPE_MAIN_USER:
printf("Mainchannel");
@@ -130,27 +197,68 @@ static void print_fpga_info(void)
break;
}

- switch (hardware_version) {
- case HWVER_100:
- printf(" HW-Ver 1.00\n");
- break;
-
- case HWVER_104:
- printf(" HW-Ver 1.04\n");
- break;
-
- case HWVER_110:
- printf(" HW-Ver 1.10\n");
- break;
+ if (unit_type == UNITTYPE_MAIN_USER) {
+ if (legacy)
+ hardware_version =
+ (in_le16((void *)LATCH2_BASE)>>8) & 0x0f;
+ else
+ hardware_version =
+ (!!pca9698_get_value(0x20, 24) << 0)
+ | (!!pca9698_get_value(0x20, 25) << 1)
+ | (!!pca9698_get_value(0x20, 26) << 2)
+ | (!!pca9698_get_value(0x20, 27) << 3);
+ switch (hardware_version) {
+ case HWVER_100:
+ printf(" HW-Ver 1.00,");
+ break;
+
+ case HWVER_104:
+ printf(" HW-Ver 1.04,");
+ break;
+
+ case HWVER_110:
+ printf(" HW-Ver 1.10,");
+ break;
+
+ case HWVER_120:
+ printf(" HW-Ver 1.20-1.21,");
+ break;
+
+ case HWVER_200:
+ printf(" HW-Ver 2.00,");
+ break;
+
+ case HWVER_210:
+ printf(" HW-Ver 2.10,");
+ break;
+
+ default:
+ printf(" HW-Ver %d(not supported),",
+ hardware_version);
+ break;
+ }
+ }

- default:
- printf(" HW-Ver %d(not supported)\n",
- hardware_version);
- break;
+ if (unit_type == UNITTYPE_VIDEO_USER) {
+ hardware_version = versions & 0x000f;
+ switch (hardware_version) {
+ case FPGA_HWVER_200:
+ printf(" HW-Ver 2.00,");
+ break;
+
+ case FPGA_HWVER_210:
+ printf(" HW-Ver 2.10,");
+ break;
+
+ default:
+ printf(" HW-Ver %d(not supported),",
+ hardware_version);
+ break;
+ }
}

- printf(" FPGA V %d.%02d, features:",
- fpga_version / 100, fpga_version % 100);
+ printf(" FPGA V %d.%02d\n features:",
+ fpga_version / 100, fpga_version % 100);

switch (feature_compression) {
@@ -162,6 +270,10 @@ static void print_fpga_info(void)
printf(" type1-deltacompression");
break;

+ case COMPRESSION_TYPE1_TYPE2_DELTA:
+ printf(" type1-deltacompression, type2-inlinecompression");
+ break;
+
default:
printf(" compression %d(not supported)", feature_compression);
break;
@@ -208,6 +320,10 @@ static void print_fpga_info(void)
printf(", RAM 32 bit DDR2");
break;

+ case RAM_DDR3_32:
+ printf(", RAM 32 bit DDR3");
+ break;
+
default:
printf(", RAM %d(not supported)", feature_ramconfig);
break;
@@ -220,41 +336,94 @@ static void print_fpga_info(void)

int last_stage_init(void)
{
- print_fpga_info();
+ int slaves;
+ unsigned int k;
+ unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 };
+
+ print_fpga_info(0);
+ osd_probe(0);
+
+ /* wait for FPGA done */
+ for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
+ unsigned int ctr = 0;
+
+ if (i2c_probe(mclink_controllers[k]))
+ continue;
+
+ while (!(pca953x_get_val(mclink_controllers[k])
+ & MCFPGA_DONE)) {
+ udelay(100000);
+ if (ctr++ > 5) {
+ printf("no done for mclink_controller %d\n", k);
+ break;
+ }
+ }
+ }
+
+ /* wait for slave-PLLs to be up and running */
+ udelay(500000);
+
+ mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
+ slaves = mclink_probe();
+ mclink_fpgacount = 0;
+
+ if (slaves <= 0)
+ return 0;
+
+ mclink_fpgacount = slaves;
+
+ for (k = 1; k <= slaves; ++k) {
+ print_fpga_info(k);
+ osd_probe(k);
+ }

- return osd_probe(0);
+ return 0;
}

/*
* provide access to fpga gpios (for I2C bitbang)
*/
-void fpga_gpio_set(int pin)
+void fpga_gpio_set(unsigned int bus, int pin)
{
- out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x18), pin);
+ fpga_set_reg(bus, REG(gpio.set), pin);
}

-void fpga_gpio_clear(int pin)
+void fpga_gpio_clear(unsigned int bus, int pin)
{
- out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x16), pin);
+ fpga_set_reg(bus, REG(gpio.clear), pin);
}

-int fpga_gpio_get(int pin)
+int fpga_gpio_get(unsigned int bus, int pin)
{
- return in_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x14)) & pin;
+ return fpga_get_reg(bus, REG(gpio.read)) & pin;
}

void gd405ep_init(void)
{
+ unsigned int k;
+
+ if (i2c_probe(0x20)) { /* i2c_probe returns 0 on success */
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k)
+ gd->fpga_state[k] |= FPGA_STATE_PLATFORM;
+ } else {
+ pca9698_direction_output(0x20, 4, 1);
+ }
}

void gd405ep_set_fpga_reset(unsigned state)
{
- if (state) {
- out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
- out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
+
+ if (legacy) {
+ if (state) {
+ out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
+ out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
+ } else {
+ out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
+ out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
+ }
} else {
- out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
- out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
+ pca9698_set_value(0x20, 4, state ? 0 : 1);
}
}

@@ -269,5 +438,11 @@ void gd405ep_setup_hw(void)

int gd405ep_get_fpga_done(unsigned fpga)
{
- return in_le16((void *)LATCH2_BASE) & CONFIG_SYS_FPGA_DONE(fpga);
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
+
+ if (legacy)
+ return in_le16((void *)LATCH2_BASE)
+ & CONFIG_SYS_FPGA_DONE(fpga);
+ else
+ return pca9698_get_value(0x20, 20);
}
diff --git a/include/configs/iocon.h b/include/configs/iocon.h
index 7f8825b..e99efa6 100644
--- a/include/configs/iocon.h
+++ b/include/configs/iocon.h
@@ -112,28 +112,31 @@
*/
#define CONFIG_SYS_I2C_SPEED 400000

-/* enable I2C and select the hardware/software driver */
-#undef CONFIG_HARD_I2C /* I2C with hardware support */
-#define CONFIG_SOFT_I2C 1 /* I2C bit-banged */
-
+#define CONFIG_PCA953X /* NXP PCA9554 */
+#define CONFIG_PCA9698 /* NXP PCA9698 */
/*
* Software (bit-bang) I2C driver configuration
*/

#ifndef __ASSEMBLY__
-void fpga_gpio_set(int pin);
-void fpga_gpio_clear(int pin);
-int fpga_gpio_get(int pin);
+void fpga_gpio_set(unsigned int bus, int pin);
+void fpga_gpio_clear(unsigned int bus, int pin);
+int fpga_gpio_get(unsigned int bus, int pin);
#endif

-#define I2C_ACTIVE { }
-#define I2C_TRISTATE { }
-#define I2C_READ fpga_gpio_get(0x0040) ? 1 : 0
-#define I2C_SDA(bit) if (bit) fpga_gpio_set(0x0040); \
- else fpga_gpio_clear(0x0040)
-#define I2C_SCL(bit) if (bit) fpga_gpio_set(0x0020); \
- else fpga_gpio_clear(0x0020)
-#define I2C_DELAY udelay(25) /* 1/4 I2C clock duration */
+#define BB_I2C_SOFT_DECLARATIONS(bus)
+#define BB_I2C_ACTIVE(bus) { }
+#define BB_I2C_TRISTATE(bus) { }
+#define BB_I2C_READ(bus) fpga_gpio_get(bus, 0x0040) ? 1 : 0
+#define BB_I2C_SDA(bus, bit) if (bit) \
+ fpga_gpio_set(bus, 0x0040); \
+ else \
+ fpga_gpio_clear(bus, 0x0040)
+#define BB_I2C_SCL(bus, bit) if (bit) \
+ fpga_gpio_set(bus, 0x0020); \
+ else \
+ fpga_gpio_clear(bus, 0x0020)
+#define BB_I2C_DELAY(bus) udelay(25) /* 1/4 I2C clock duration */

/*
* OSD hardware
@@ -252,6 +255,8 @@ int fpga_gpio_get(int pin);

#define CONFIG_SYS_FPGA_COUNT 1

+#define CONFIG_SYS_MCLINK_MAX 3
+
/* Memory Bank 3 (Latches) initialization */
#define CONFIG_SYS_LATCH_BASE 0x7f200000
#define CONFIG_SYS_EBC_PB3AP 0x02025080
@@ -267,6 +272,6 @@ int fpga_gpio_get(int pin);
*/
#define CONFIG_SYS_MPC92469AC
#define CONFIG_SYS_CH7301
-#define CONFIG_SYS_OSD_SCREENS CONFIG_SYS_FPGA_COUNT
+#define CONFIG_SYS_OSD_SCREENS 1

#endif /* __CONFIG_H */
diff --git a/include/gdsys_fpga.h b/include/gdsys_fpga.h
index c12a31d..b246f2f 100644
--- a/include/gdsys_fpga.h
+++ b/include/gdsys_fpga.h
@@ -117,10 +117,21 @@ struct ihs_fpga {
u16 mpc3w_control; /* 0x001a */
u16 reserved_1[19]; /* 0x001c */
u16 videocontrol; /* 0x0042 */
- u16 reserved_2[93]; /* 0x0044 */
+ u16 reserved_2[14]; /* 0x0044 */
+ u16 mc_int; /* 0x0060 */
+ u16 mc_int_en; /* 0x0062 */
+ u16 mc_status; /* 0x0064 */
+ u16 mc_control; /* 0x0066 */
+ u16 mc_tx_data; /* 0x0068 */
+ u16 mc_tx_address; /* 0x006a */
+ u16 mc_tx_cmd; /* 0x006c */
+ u16 mc_res; /* 0x006e */
+ u16 mc_rx_cmd_status; /* 0x0070 */
+ u16 mc_rx_data; /* 0x0072 */
+ u16 reserved_3[69]; /* 0x0074 */
u16 reflection_high; /* 0x00fe */
struct ihs_osd osd; /* 0x0100 */
- u16 reserved_3[889]; /* 0x010e */
+ u16 reserved_4[889]; /* 0x010e */
u16 videomem; /* 0x0800 */
};
#endif
--
1.7.10.4