[U-Boot] [PATCH v2 05/10] powerpc/ppc4xx: Support gdsys multichannel iocon hardware
dirk.eibach at gdsys.cc
dirk.eibach at gdsys.cc
Mon May 6 15:35:20 CEST 2013
From: Dirk Eibach <eibach at gdsys.de>
Signed-off-by: Dirk Eibach <dirk.eibach at gdsys.cc>
---
Changes in v2:
- fpga_state has been moved to arch_global_data
- include cmd_fpgad in iocon
- use multibus soft-i2c in iocon
board/gdsys/405ep/iocon.c | 253 ++++++++++++++++++++++++++++++++++++++-------
board/gdsys/common/osd.c | 25 +++--
include/configs/iocon.h | 44 ++++++--
include/gdsys_fpga.h | 15 +++-
4 files changed, 280 insertions(+), 57 deletions(-)
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c
index 0fc7db2..0ab8772 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->arch.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/board/gdsys/common/osd.c b/board/gdsys/common/osd.c
index 81c8136..2cfbe58 100644
--- a/board/gdsys/common/osd.c
+++ b/board/gdsys/common/osd.c
@@ -22,7 +22,8 @@
*/
#include <common.h>
-#include "bb_i2c.h"
+#include <i2c.h>
+#include <malloc.h>
#include <asm/io.h>
#include <gdsys_fpga.h>
@@ -69,6 +70,10 @@ enum {
unsigned int max_osd_screen = CONFIG_SYS_OSD_SCREENS - 1;
+#ifdef CONFIG_SYS_CH7301
+int ch7301_i2c[] = CONFIG_SYS_CH7301_I2C;
+#endif
+
#if defined(CONFIG_SYS_ICS8N3QV01) || defined(CONFIG_SYS_SIL1178)
static void fpga_iic_write(unsigned screen, u8 slave, u8 reg, u8 data)
{
@@ -318,6 +323,9 @@ int osd_probe(unsigned screen)
unsigned width;
unsigned height;
u8 value;
+#ifdef CONFIG_SYS_CH7301
+ int old_bus = i2c_get_bus_num();
+#endif
width = ((features & 0x3f00) >> 8) + 1;
height = (features & 0x001f) + 1;
@@ -326,16 +334,19 @@ int osd_probe(unsigned screen)
screen, version/100, version%100, width, height);
#ifdef CONFIG_SYS_CH7301
- value = bb_i2c_reg_read(screen, CH7301_I2C_ADDR, CH7301_DID);
+ i2c_set_bus_num(ch7301_i2c[screen]);
+ value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID);
if (value != 0x17) {
printf(" Probing CH7301 failed, DID %02x\n", value);
+ i2c_set_bus_num(old_bus);
return -1;
}
- bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPCP, 0x08);
- bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPD, 0x16);
- bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPF, 0x60);
- bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_DC, 0x09);
- bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_PM, 0xc0);
+ i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPCP, 0x08);
+ i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPD, 0x16);
+ i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPF, 0x60);
+ i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x09);
+ i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0xc0);
+ i2c_set_bus_num(old_bus);
#endif
#ifdef CONFIG_SYS_MPC92469AC
diff --git a/include/configs/iocon.h b/include/configs/iocon.h
index 5972711..921ac05 100644
--- a/include/configs/iocon.h
+++ b/include/configs/iocon.h
@@ -79,6 +79,7 @@
* Commands additional to the ones defined in amcc-common.h
*/
#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_FPGAD
#undef CONFIG_CMD_EEPROM
/*
@@ -116,23 +117,46 @@
#define CONFIG_SYS_I2C_PPC4XX_SPEED_0 400000
#define CONFIG_SYS_I2C_PPC4XX_SLAVE_0 0x7F
+#define CONFIG_SYS_I2C_SPEED 400000
+
+#define CONFIG_PCA953X /* NXP PCA9554 */
+#define CONFIG_PCA9698 /* NXP PCA9698 */
+
/*
* Software (bit-bang) I2C driver configuration
*/
+#define CONFIG_SYS_I2C_SOFT
+#define CONFIG_SYS_I2C_SOFT_SPEED 50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE 0x7F
+#define I2C_SOFT_DECLARATIONS2
+#define CONFIG_SYS_I2C_SOFT_SPEED_2 50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE_2 0x7F
+#define I2C_SOFT_DECLARATIONS3
+#define CONFIG_SYS_I2C_SOFT_SPEED_3 50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE_3 0x7F
+#define I2C_SOFT_DECLARATIONS4
+#define CONFIG_SYS_I2C_SOFT_SPEED_4 50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE_4 0x7F
+
+#define CONFIG_SYS_CH7301_I2C {1, 2, 3, 4}
#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_READ fpga_gpio_get(I2C_ADAP_HWNR, 0x0040) ? 1 : 0
+#define I2C_SDA(bit) if (bit) \
+ fpga_gpio_set(I2C_ADAP_HWNR, 0x0040); \
+ else \
+ fpga_gpio_clear(I2C_ADAP_HWNR, 0x0040)
+#define I2C_SCL(bit) if (bit) \
+ fpga_gpio_set(I2C_ADAP_HWNR, 0x0020); \
+ else \
+ fpga_gpio_clear(I2C_ADAP_HWNR, 0x0020)
#define I2C_DELAY udelay(25) /* 1/4 I2C clock duration */
/*
@@ -252,6 +276,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 +293,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.2.5
More information about the U-Boot
mailing list