GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2007
# Stefan Roese, DENX Software Engineering, sr@denx.de.
obj-$(CONFIG_SYS_FPGA_COMMON) += fpga.o
obj-$(CONFIG_CMD_IOLOOP) += cmd_ioloop.o
obj-$(CONFIG_CONTROLCENTERD) += dp501.o
obj-$(CONFIG_TARGET_HRCON) += osd.o mclink.o dp501.o phy.o ioep-fpga.o fanctrl.o
obj-$(CONFIG_TARGET_STRIDER) += mclink.o dp501.o phy.o ioep-fpga.o adv7611.o ch7301.o
obj-$(CONFIG_TARGET_STRIDER) += fanctrl.o
obj-$(CONFIG_STRIDER_CON) += osd.o
obj-$(CONFIG_STRIDER_CON_DP) += osd.o
obj-$(CONFIG_TARGET_GAZERBEAM) += osd.o ihs_mdio.o ioep-fpga.o
ifdef CONFIG_OSD
obj-$(CONFIG_GDSYS_LEGACY_OSD_CMDS) += osd_cmd.o
endif
@@ -0,0 +1,180 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <i2c.h>
#define ADV7611_I2C_ADDR 0x4c
#define ADV7611_RDINFO 0x2051
/*
* ADV7611 I2C Addresses in u-boot notation
*/
enum {
CP_I2C_ADDR = 0x22,
DPLL_I2C_ADDR = 0x26,
KSV_I2C_ADDR = 0x32,
HDMI_I2C_ADDR = 0x34,
EDID_I2C_ADDR = 0x36,
INFOFRAME_I2C_ADDR = 0x3e,
CEC_I2C_ADDR = 0x40,
IO_I2C_ADDR = ADV7611_I2C_ADDR,
};
/*
* Global Control Registers
*/
enum {
IO_RD_INFO_MSB = 0xea,
IO_RD_INFO_LSB = 0xeb,
IO_CEC_ADDR = 0xf4,
IO_INFOFRAME_ADDR = 0xf5,
IO_DPLL_ADDR = 0xf8,
IO_KSV_ADDR = 0xf9,
IO_EDID_ADDR = 0xfa,
IO_HDMI_ADDR = 0xfb,
IO_CP_ADDR = 0xfd,
};
int adv7611_i2c[] = CONFIG_SYS_ADV7611_I2C;
int adv7611_probe(unsigned int screen)
{
int old_bus = i2c_get_bus_num();
unsigned int rd_info;
int res = 0;
i2c_set_bus_num(adv7611_i2c[screen]);
rd_info = (i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_MSB) << 8)
| i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_LSB);
if (rd_info != ADV7611_RDINFO) {
res = -1;
goto out;
}
/*
* set I2C addresses to default values
*/
i2c_reg_write(IO_I2C_ADDR, IO_CEC_ADDR, CEC_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_INFOFRAME_ADDR, INFOFRAME_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_DPLL_ADDR, DPLL_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_KSV_ADDR, KSV_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_EDID_ADDR, EDID_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_HDMI_ADDR, HDMI_I2C_ADDR << 1);
i2c_reg_write(IO_I2C_ADDR, IO_CP_ADDR, CP_I2C_ADDR << 1);
/*
* do magic initialization sequence from
* "ADV7611 Register Settings Recommendations Revision 1.5"
* with most registers undocumented
*/
i2c_reg_write(CP_I2C_ADDR, 0x6c, 0x00);
i2c_reg_write(HDMI_I2C_ADDR, 0x9b, 0x03);
i2c_reg_write(HDMI_I2C_ADDR, 0x6f, 0x08);
i2c_reg_write(HDMI_I2C_ADDR, 0x85, 0x1f);
i2c_reg_write(HDMI_I2C_ADDR, 0x87, 0x70);
i2c_reg_write(HDMI_I2C_ADDR, 0x57, 0xda);
i2c_reg_write(HDMI_I2C_ADDR, 0x58, 0x01);
i2c_reg_write(HDMI_I2C_ADDR, 0x03, 0x98);
i2c_reg_write(HDMI_I2C_ADDR, 0x4c, 0x44);
/*
* IO_REG_02, default 0xf0
*
* INP_COLOR_SPACE (IO, Address 0x02[7:4])
* default: 0b1111 auto
* set to : 0b0001 force RGB (range 0 to 255) input
*
* RGB_OUT (IO, Address 0x02[1])
* default: 0 YPbPr color space output
* set to : 1 RGB color space output
*/
i2c_reg_write(IO_I2C_ADDR, 0x02, 0x12);
/*
* IO_REG_03, default 0x00
*
* OP_FORMAT_SEL (IO, Address 0x03[7:0])
* default: 0x00 8-bit SDR ITU-656 mode
* set to : 0x40 24-bit 4:4:4 SDR mode
*/
i2c_reg_write(IO_I2C_ADDR, 0x03, 0x40);
/*
* IO_REG_05, default 0x2c
*
* AVCODE_INSERT_EN (IO, Address 0x05[2])
* default: 1 insert AV codes into data stream
* set to : 0 do not insert AV codes into data stream
*/
i2c_reg_write(IO_I2C_ADDR, 0x05, 0x28);
/*
* IO_REG_0C, default 0x62
*
* POWER_DOWN (IO, Address 0x0C[5])
* default: 1 chip is powered down
* set to : 0 chip is operational
*/
i2c_reg_write(IO_I2C_ADDR, 0x0c, 0x42);
/*
* IO_REG_15, default 0xbe
*
* TRI_SYNCS (IO, Address 0x15[3)
* TRI_LLC (IO, Address 0x15[2])
* TRI_PIX (IO, Address 0x15[1])
* default: 1 video output pins are tristate
* set to : 0 video output pins are active
*/
i2c_reg_write(IO_I2C_ADDR, 0x15, 0xb0);
/*
* HDMI_REGISTER_02H, default 0xff
*
* CLOCK_TERMA_DISABLE (HDMI, Address 0x83[0])
* default: 1 disable termination
* set to : 0 enable termination
* Future options are:
* - use the chips automatic termination control
* - set this manually on cable detect
* but at the moment this seems a safe default.
*/
i2c_reg_write(HDMI_I2C_ADDR, 0x83, 0xfe);
/*
* HDMI_CP_CNTRL_1, default 0x01
*
* HDMI_FRUN_EN (CP, Address 0xBA[0])
* default: 1 Enable the free run feature in HDMI mode
* set to : 0 Disable the free run feature in HDMI mode
*/
i2c_reg_write(CP_I2C_ADDR, 0xba, 0x00);
/*
* INT1_CONFIGURATION, default 0x20
*
* INTRQ_DUR_SEL[1:0] (IO, Address 0x40[7:6])
* default: 00 Interrupt signal is active for 4 Xtal periods
* set to : 11 Active until cleared
*
* INTRQ_OP_SEL[1:0] (IO, Address 0x40[1:0])
* default: 00 Open drain
* set to : 10 Drives high when active
*/
i2c_reg_write(IO_I2C_ADDR, 0x40, 0xc2);
out:
i2c_set_bus_num(old_bus);
return res;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _ADV7611_H_
#define _ADV7611_H_
int adv7611_probe(unsigned int screen);
#endif
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
/* Chrontel CH7301C DVI Transmitter */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <asm/io.h>
#include <errno.h>
#include <i2c.h>
#define CH7301_I2C_ADDR 0x75
enum {
CH7301_CM = 0x1c, /* Clock Mode Register */
CH7301_IC = 0x1d, /* Input Clock Register */
CH7301_GPIO = 0x1e, /* GPIO Control Register */
CH7301_IDF = 0x1f, /* Input Data Format Register */
CH7301_CD = 0x20, /* Connection Detect Register */
CH7301_DC = 0x21, /* DAC Control Register */
CH7301_HPD = 0x23, /* Hot Plug Detection Register */
CH7301_TCTL = 0x31, /* DVI Control Input Register */
CH7301_TPCP = 0x33, /* DVI PLL Charge Pump Ctrl Register */
CH7301_TPD = 0x34, /* DVI PLL Divide Register */
CH7301_TPVT = 0x35, /* DVI PLL Supply Control Register */
CH7301_TPF = 0x36, /* DVI PLL Filter Register */
CH7301_TCT = 0x37, /* DVI Clock Test Register */
CH7301_TSTP = 0x48, /* Test Pattern Register */
CH7301_PM = 0x49, /* Power Management register */
CH7301_VID = 0x4a, /* Version ID Register */
CH7301_DID = 0x4b, /* Device ID Register */
CH7301_DSP = 0x56, /* DVI Sync polarity Register */
};
int ch7301_i2c[] = CONFIG_SYS_CH7301_I2C;
int ch7301_probe(unsigned screen, bool power)
{
u8 value;
i2c_set_bus_num(ch7301_i2c[screen]);
if (i2c_probe(CH7301_I2C_ADDR))
return -1;
value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID);
if (value != 0x17)
return -1;
if (power) {
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);
} else {
i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x00);
i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0x01);
}
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _CH7301_H_
#define _CH7301_H_
int ch7301_probe(unsigned screen, bool power);
#endif
@@ -0,0 +1,581 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#include <common.h>
#include <command.h>
#include <console.h>
#include <gdsys_fpga.h>
#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
#include <dm.h>
#include <misc.h>
#include <regmap.h>
#include <board.h>
#include "../../../drivers/misc/gdsys_soc.h"
#include "../../../drivers/misc/gdsys_ioep.h"
#include "../../../drivers/misc/ihs_fpga.h"
const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2;
#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
enum status_print_type {
STATUS_LOUD = 0,
STATUS_SILENT = 1,
};
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
enum {
STATE_TX_PACKET_BUILDING = BIT(0),
STATE_TX_TRANSMITTING = BIT(1),
STATE_TX_BUFFER_FULL = BIT(2),
STATE_TX_ERR = BIT(3),
STATE_RECEIVE_TIMEOUT = BIT(4),
STATE_PROC_RX_STORE_TIMEOUT = BIT(5),
STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6),
STATE_RX_DIST_ERR = BIT(7),
STATE_RX_LENGTH_ERR = BIT(8),
STATE_RX_FRAME_CTR_ERR = BIT(9),
STATE_RX_FCS_ERR = BIT(10),
STATE_RX_PACKET_DROPPED = BIT(11),
STATE_RX_DATA_LAST = BIT(12),
STATE_RX_DATA_FIRST = BIT(13),
STATE_RX_DATA_AVAILABLE = BIT(15),
};
enum {
IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5),
IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6),
IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7),
IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8),
};
enum {
CTRL_PROC_RECEIVE_ENABLE = BIT(12),
CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
};
struct io_generic_packet {
u16 target_address;
u16 source_address;
u8 packet_type;
u8 bc;
u16 packet_length;
} __attribute__((__packed__));
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
unsigned long long rx_ctr;
unsigned long long tx_ctr;
unsigned long long err_ctr;
#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
struct udevice *dev;
#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
static void io_check_status(uint fpga, u16 status, enum status_print_type type)
{
u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
if (!(status & mask)) {
FPGA_SET_REG(fpga, ep.rx_tx_status, status);
return;
}
err_ctr++;
FPGA_SET_REG(fpga, ep.rx_tx_status, status);
if (type == STATUS_SILENT)
return;
if (status & STATE_RX_PACKET_DROPPED)
printf("RX_PACKET_DROPPED, status %04x\n", status);
if (status & STATE_RX_DIST_ERR)
printf("RX_DIST_ERR\n");
if (status & STATE_RX_LENGTH_ERR)
printf("RX_LENGTH_ERR\n");
if (status & STATE_RX_FRAME_CTR_ERR)
printf("RX_FRAME_CTR_ERR\n");
if (status & STATE_RX_FCS_ERR)
printf("RX_FCS_ERR\n");
if (status & STATE_TX_ERR)
printf("TX_ERR\n");
}
#else
static void io_check_status(struct udevice *dev, enum status_print_type type)
{
u16 status = 0;
int ret;
ret = misc_call(dev, 0, NULL, 0, &status, 0);
if (!ret)
return;
err_ctr++;
if (type != STATUS_LOUD)
return;
if (status & STATE_RX_PACKET_DROPPED)
printf("RX_PACKET_DROPPED, status %04x\n", status);
if (status & STATE_RX_DIST_ERR)
printf("RX_DIST_ERR\n");
if (status & STATE_RX_LENGTH_ERR)
printf("RX_LENGTH_ERR\n");
if (status & STATE_RX_FRAME_CTR_ERR)
printf("RX_FRAME_CTR_ERR\n");
if (status & STATE_RX_FCS_ERR)
printf("RX_FCS_ERR\n");
if (status & STATE_TX_ERR)
printf("TX_ERR\n");
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
static void io_send(uint fpga, uint size)
{
uint k;
struct io_generic_packet packet = {
.source_address = 1,
.packet_type = 1,
.packet_length = size,
};
u16 *p = (u16 *)&packet;
for (k = 0; k < sizeof(packet) / 2; ++k)
FPGA_SET_REG(fpga, ep.transmit_data, *p++);
for (k = 0; k < (size + 1) / 2; ++k)
FPGA_SET_REG(fpga, ep.transmit_data, k);
FPGA_SET_REG(fpga, ep.rx_tx_control,
CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
tx_ctr++;
}
#else
static void io_send(struct udevice *dev, uint size)
{
uint k;
u16 buffer[HEADER_WORDS + 128];
struct io_generic_packet header = {
.source_address = 1,
.packet_type = 1,
.packet_length = size,
};
const uint words = (size + 1) / 2;
memcpy(buffer, &header, 2 * HEADER_WORDS);
for (k = 0; k < words; ++k)
buffer[k + HEADER_WORDS] = (2 * k + 1) + ((2 * k) << 8);
misc_write(dev, 0, buffer, HEADER_WORDS + words);
tx_ctr++;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
static void io_receive(uint fpga)
{
u16 rx_tx_status;
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
u16 rx;
if (rx_tx_status & STATE_RX_DATA_LAST)
rx_ctr++;
FPGA_GET_REG(fpga, ep.receive_data, &rx);
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
}
}
#else
static void io_receive(struct udevice *dev)
{
u16 buffer[HEADER_WORDS + 128];
if (!misc_read(dev, 0, buffer, 0))
rx_ctr++;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
static void io_reflect(uint fpga)
{
u16 buffer[128];
uint k = 0;
uint n;
u16 rx_tx_status;
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
if (rx_tx_status & STATE_RX_DATA_LAST)
break;
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
}
if (!k)
return;
for (n = 0; n < k; ++n)
FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
FPGA_SET_REG(fpga, ep.rx_tx_control,
CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
tx_ctr++;
}
#else
static void io_reflect(struct udevice *dev)
{
u16 buffer[HEADER_WORDS + 128];
struct io_generic_packet *header;
if (misc_read(dev, 0, buffer, 0))
return;
header = (struct io_generic_packet *)&buffer;
misc_write(dev, 0, buffer, HEADER_WORDS + header->packet_length);
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
/*
* FPGA io-endpoint reflector
*
* Syntax:
* ioreflect {fpga} {reportrate}
*/
int do_ioreflect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
uint fpga;
uint rate = 0;
unsigned long long last_seen = 0;
if (argc < 2)
return CMD_RET_USAGE;
fpga = simple_strtoul(argv[1], NULL, 10);
/*
* If another parameter, it is the report rate in packets.
*/
if (argc > 2)
rate = simple_strtoul(argv[2], NULL, 10);
/* Enable receive path */
FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
/* Set device address to dummy 1*/
FPGA_SET_REG(fpga, ep.device_address, 1);
rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
while (1) {
u16 top_int;
u16 rx_tx_status;
FPGA_GET_REG(fpga, top_interrupt, &top_int);
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
io_check_status(fpga, rx_tx_status, STATUS_SILENT);
if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
(top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
io_reflect(fpga);
if (rate) {
if (!(tx_ctr % rate) && (tx_ctr != last_seen))
printf("refl %llu, err %llu\n", tx_ctr,
err_ctr);
last_seen = tx_ctr;
}
if (ctrlc())
break;
}
return 0;
}
#else
/*
* FPGA io-endpoint reflector
*
* Syntax:
* ioreflect {reportrate}
*/
int do_ioreflect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct udevice *fpga;
struct regmap *map;
uint rate = 0;
unsigned long long last_seen = 0;
if (!dev) {
printf("No device selected\n");
return 1;
}
gdsys_soc_get_fpga(dev, &fpga);
regmap_init_mem(dev_ofnode(dev), &map);
/* Enable receive path */
misc_set_enabled(dev, true);
rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
while (1) {
uint top_int;
ihs_fpga_get(map, top_interrupt, &top_int);
io_check_status(dev, STATUS_SILENT);
if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
(top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
io_reflect(dev);
if (rate) {
if (!(tx_ctr % rate) && (tx_ctr != last_seen))
printf("refl %llu, err %llu\n", tx_ctr,
err_ctr);
last_seen = tx_ctr;
}
if (ctrlc())
break;
}
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#define DISP_LINE_LEN 16
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
/*
* FPGA io-endpoint looptest
*
* Syntax:
* ioloop {fpga} {size} {rate}
*/
int do_ioloop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
uint fpga;
uint size;
uint rate = 0;
if (argc < 3)
return CMD_RET_USAGE;
/*
* FPGA is specified since argc > 2
*/
fpga = simple_strtoul(argv[1], NULL, 10);
/*
* packet size is specified since argc > 2
*/
size = simple_strtoul(argv[2], NULL, 10);
/*
* If another parameter, it is the test rate in packets per second.
*/
if (argc > 3)
rate = simple_strtoul(argv[3], NULL, 10);
/* enable receive path */
FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
/* set device address to dummy 1*/
FPGA_SET_REG(fpga, ep.device_address, 1);
rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
while (1) {
u16 top_int;
u16 rx_tx_status;
FPGA_GET_REG(fpga, top_interrupt, &top_int);
FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
io_check_status(fpga, rx_tx_status, STATUS_LOUD);
if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
io_send(fpga, size);
if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
io_receive(fpga);
if (rate) {
if (ctrlc())
break;
udelay(1000000 / rate);
if (!(tx_ctr % rate))
printf("d %llu, tx %llu, rx %llu, err %llu\n",
tx_ctr - rx_ctr, tx_ctr, rx_ctr,
err_ctr);
}
}
return 0;
}
#else
/*
* FPGA io-endpoint looptest
*
* Syntax:
* ioloop {size} {rate}
*/
int do_ioloop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
uint size;
uint rate = 0;
struct udevice *fpga;
struct regmap *map;
if (!dev) {
printf("No device selected\n");
return 1;
}
gdsys_soc_get_fpga(dev, &fpga);
regmap_init_mem(dev_ofnode(dev), &map);
if (argc < 2)
return CMD_RET_USAGE;
/*
* packet size is specified since argc > 1
*/
size = simple_strtoul(argv[2], NULL, 10);
/*
* If another parameter, it is the test rate in packets per second.
*/
if (argc > 2)
rate = simple_strtoul(argv[3], NULL, 10);
/* Enable receive path */
misc_set_enabled(dev, true);
rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
while (1) {
uint top_int;
if (ctrlc())
break;
ihs_fpga_get(map, top_interrupt, &top_int);
io_check_status(dev, STATUS_LOUD);
if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
io_send(dev, size);
if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
io_receive(dev);
if (rate) {
udelay(1000000 / rate);
if (!(tx_ctr % rate))
printf("d %llu, tx %llu, rx %llu, err %llu\n",
tx_ctr - rx_ctr, tx_ctr, rx_ctr,
err_ctr);
}
}
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
int do_iodev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct udevice *ioep = NULL;
struct udevice *board;
char name[8];
int ret;
if (board_get(&board))
return CMD_RET_FAILURE;
if (argc > 1) {
int i = simple_strtoul(argv[1], NULL, 10);
snprintf(name, sizeof(name), "ioep%d", i);
ret = uclass_get_device_by_phandle(UCLASS_MISC, board, name, &ioep);
if (ret || !ioep) {
printf("Invalid IOEP %d\n", i);
return CMD_RET_FAILURE;
}
dev = ioep;
} else {
int i = 0;
while (1) {
snprintf(name, sizeof(name), "ioep%d", i);
ret = uclass_get_device_by_phandle(UCLASS_MISC, board, name, &ioep);
if (ret || !ioep)
break;
printf("IOEP %d:\t%s\n", i++, ioep->name);
}
if (dev)
printf("\nSelected IOEP: %s\n", dev->name);
else
puts("\nNo IOEP selected.\n");
}
return 0;
}
#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
U_BOOT_CMD(
ioloop, 4, 0, do_ioloop,
"fpga io-endpoint looptest",
"fpga packetsize [packets/sec]"
);
U_BOOT_CMD(
ioreflect, 3, 0, do_ioreflect,
"fpga io-endpoint reflector",
"fpga reportrate"
);
#else
U_BOOT_CMD(
ioloop, 3, 0, do_ioloop,
"fpga io-endpoint looptest",
"packetsize [packets/sec]"
);
U_BOOT_CMD(
ioreflect, 2, 0, do_ioreflect,
"fpga io-endpoint reflector",
"reportrate"
);
U_BOOT_CMD(
iodev, 2, 0, do_iodev,
"fpga io-endpoint listing/selection",
"[ioep device to select]"
);
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,161 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2012
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
/* Parade Technologies Inc. DP501 DisplayPort DVI/HDMI Transmitter */
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <asm/io.h>
#include <errno.h>
#include <i2c.h>
#define DP501_I2C_ADDR 0x08
#ifdef CONFIG_SYS_DP501_I2C
int dp501_i2c[] = CONFIG_SYS_DP501_I2C;
#endif
#ifdef CONFIG_SYS_DP501_BASE
int dp501_base[] = CONFIG_SYS_DP501_BASE;
#endif
static void dp501_setbits(u8 addr, u8 reg, u8 mask)
{
u8 val;
val = i2c_reg_read(addr, reg);
setbits_8(&val, mask);
i2c_reg_write(addr, reg, val);
}
static void dp501_clrbits(u8 addr, u8 reg, u8 mask)
{
u8 val;
val = i2c_reg_read(addr, reg);
clrbits_8(&val, mask);
i2c_reg_write(addr, reg, val);
}
static int dp501_detect_cable_adapter(u8 addr)
{
u8 val = i2c_reg_read(addr, 0x00);
return !(val & 0x04);
}
static void dp501_link_training(u8 addr)
{
u8 val;
u8 link_bw;
u8 max_lane_cnt;
u8 lane_cnt;
val = i2c_reg_read(addr, 0x51);
if (val >= 0x0a)
link_bw = 0x0a;
else
link_bw = 0x06;
if (link_bw != val)
printf("DP sink supports %d Mbps link rate, set to %d Mbps\n",
val * 270, link_bw * 270);
i2c_reg_write(addr, 0x5d, link_bw); /* set link_bw */
val = i2c_reg_read(addr, 0x52);
max_lane_cnt = val & 0x1f;
if (max_lane_cnt >= 4)
lane_cnt = 4;
else
lane_cnt = max_lane_cnt;
if (lane_cnt != max_lane_cnt)
printf("DP sink supports %d lanes, set to %d lanes\n",
max_lane_cnt, lane_cnt);
i2c_reg_write(addr, 0x5e, lane_cnt | (val & 0x80)); /* set lane_cnt */
val = i2c_reg_read(addr, 0x53);
i2c_reg_write(addr, 0x5c, val); /* set downspread_ctl */
i2c_reg_write(addr, 0x5f, 0x0d); /* start training */
}
void dp501_powerup(u8 addr)
{
dp501_clrbits(addr, 0x0a, 0x30); /* power on encoder */
dp501_setbits(addr, 0x0a, 0x0e); /* block HDCP and MCCS on I2C bride*/
i2c_reg_write(addr, 0x27, 0x30); /* Hardware auto detect DVO timing */
dp501_setbits(addr, 0x72, 0x80); /* DPCD read enable */
dp501_setbits(addr, 0x30, 0x20); /* RS polynomial select */
i2c_reg_write(addr, 0x71, 0x20); /* Enable Aux burst write */
dp501_setbits(addr, 0x78, 0x30); /* Disable HPD2 IRQ */
dp501_clrbits(addr, 0x2f, 0x40); /* Link FIFO reset selection */
dp501_clrbits(addr, 0x60, 0x20); /* Enable scrambling */
#ifdef CONFIG_SYS_DP501_VCAPCTRL0
i2c_reg_write(addr, 0x24, CONFIG_SYS_DP501_VCAPCTRL0);
#else
i2c_reg_write(addr, 0x24, 0xc0); /* SDR mode 0, ext. H/VSYNC */
#endif
#ifdef CONFIG_SYS_DP501_DIFFERENTIAL
i2c_reg_write(addr + 2, 0x24, 0x10); /* clock input differential */
i2c_reg_write(addr + 2, 0x25, 0x04);
i2c_reg_write(addr + 2, 0x26, 0x10);
#else
i2c_reg_write(addr + 2, 0x24, 0x02); /* clock input single ended */
#endif
i2c_reg_write(addr + 2, 0x1a, 0x04); /* SPDIF input method TTL */
i2c_reg_write(addr + 2, 0x00, 0x18); /* driving strength */
i2c_reg_write(addr + 2, 0x03, 0x06); /* driving strength */
i2c_reg_write(addr, 0x2c, 0x00); /* configure N value */
i2c_reg_write(addr, 0x2d, 0x00); /* configure N value */
i2c_reg_write(addr, 0x2e, 0x0c); /* configure N value */
i2c_reg_write(addr, 0x76, 0xff); /* clear all interrupt */
dp501_setbits(addr, 0x78, 0x03); /* clear all interrupt */
i2c_reg_write(addr, 0x75, 0xf8); /* aux channel reset */
i2c_reg_write(addr, 0x75, 0x00); /* clear aux channel reset */
i2c_reg_write(addr, 0x87, 0x7f); /* set retry counter as 7
retry interval 400us */
if (dp501_detect_cable_adapter(addr)) {
printf("DVI/HDMI cable adapter detected\n");
i2c_reg_write(addr, 0x5e, 0x04); /* enable 4 channel */
dp501_clrbits(addr, 0x00, 0x08); /* DVI/HDMI HDCP operation */
} else {
printf("no DVI/HDMI cable adapter detected\n");
dp501_setbits(addr, 0x00, 0x08); /* for DP HDCP operation */
dp501_link_training(addr);
}
}
void dp501_powerdown(u8 addr)
{
dp501_setbits(addr, 0x0a, 0x30); /* power down encoder, standby mode */
}
int dp501_probe(unsigned screen, bool power)
{
#ifdef CONFIG_SYS_DP501_BASE
uint8_t dp501_addr = dp501_base[screen];
#else
uint8_t dp501_addr = DP501_I2C_ADDR;
#endif
#ifdef CONFIG_SYS_DP501_I2C
i2c_set_bus_num(dp501_i2c[screen]);
#endif
if (i2c_probe(dp501_addr))
return -1;
dp501_powerup(dp501_addr);
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,31 @@
/*
* (C) Copyright 2012
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef _DP501_H_
#define _DP501_H_
void dp501_powerup(u8 addr);
void dp501_powerdown(u8 addr);
int dp501_probe(unsigned screen, bool power);
#endif
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <i2c.h>
enum {
FAN_CONFIG = 0x03,
FAN_TACHLIM_LSB = 0x48,
FAN_TACHLIM_MSB = 0x49,
FAN_PWM_FREQ = 0x4D,
};
void init_fan_controller(u8 addr)
{
int val;
/* set PWM Frequency to 2.5% resolution */
i2c_reg_write(addr, FAN_PWM_FREQ, 20);
/* set Tachometer Limit */
i2c_reg_write(addr, FAN_TACHLIM_LSB, 0x10);
i2c_reg_write(addr, FAN_TACHLIM_MSB, 0x0a);
/* enable Tach input */
val = i2c_reg_read(addr, FAN_CONFIG) | 0x04;
i2c_reg_write(addr, FAN_CONFIG, val);
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2015
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _FANCTRL_H_
#define _FANCTRL_H_
void init_fan_controller(u8 addr);
#endif
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2013
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <gdsys_fpga.h>
#include <asm/io.h>
int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
{
out_le16(reg, data);
return 0;
}
int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
{
*data = in_le16(reg);
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,163 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#include <common.h>
#include <miiphy.h>
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <gdsys_fpga.h>
#else
#include <fdtdec.h>
#include <dm.h>
#include <regmap.h>
#endif
#include "ihs_mdio.h"
#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
enum {
REG_MDIO_CONTROL = 0x0,
REG_MDIO_ADDR_DATA = 0x2,
REG_MDIO_RX_DATA = 0x4,
};
static inline u16 read_reg(struct udevice *fpga, uint base, uint addr)
{
struct regmap *map;
u8 *ptr;
regmap_init_mem(dev_ofnode(fpga), &map);
ptr = regmap_get_range(map, 0);
return in_le16((u16 *)(ptr + base + addr));
}
static inline void write_reg(struct udevice *fpga, uint base, uint addr,
u16 val)
{
struct regmap *map;
u8 *ptr;
regmap_init_mem(dev_ofnode(fpga), &map);
ptr = regmap_get_range(map, 0);
out_le16((u16 *)(ptr + base + addr), val);
}
#endif
static inline u16 read_control(struct ihs_mdio_info *info)
{
u16 val;
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
FPGA_GET_REG(info->fpga, mdio.control, &val);
#else
val = read_reg(info->fpga, info->base, REG_MDIO_CONTROL);
#endif
return val;
}
static inline void write_control(struct ihs_mdio_info *info, u16 val)
{
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
FPGA_SET_REG(info->fpga, mdio.control, val);
#else
write_reg(info->fpga, info->base, REG_MDIO_CONTROL, val);
#endif
}
static inline void write_addr_data(struct ihs_mdio_info *info, u16 val)
{
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
FPGA_SET_REG(info->fpga, mdio.address_data, val);
#else
write_reg(info->fpga, info->base, REG_MDIO_ADDR_DATA, val);
#endif
}
static inline u16 read_rx_data(struct ihs_mdio_info *info)
{
u16 val;
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
#else
val = read_reg(info->fpga, info->base, REG_MDIO_RX_DATA);
#endif
return val;
}
static int ihs_mdio_idle(struct mii_dev *bus)
{
struct ihs_mdio_info *info = bus->priv;
u16 val;
unsigned int ctr = 0;
do {
val = read_control(info);
udelay(100);
if (ctr++ > 10)
return -1;
} while (!(val & (1 << 12)));
return 0;
}
static int ihs_mdio_reset(struct mii_dev *bus)
{
ihs_mdio_idle(bus);
return 0;
}
static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
int regnum)
{
struct ihs_mdio_info *info = bus->priv;
u16 val;
ihs_mdio_idle(bus);
write_control(info,
((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
/* wait for rx data available */
udelay(100);
val = read_rx_data(info);
return val;
}
static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
int regnum, u16 value)
{
struct ihs_mdio_info *info = bus->priv;
ihs_mdio_idle(bus);
write_addr_data(info, value);
write_control(info, ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
return 0;
}
int ihs_mdio_init(struct ihs_mdio_info *info)
{
struct mii_dev *bus = mdio_alloc();
if (!bus) {
printf("Failed to allocate FSL MDIO bus\n");
return -1;
}
bus->read = ihs_mdio_read;
bus->write = ihs_mdio_write;
bus->reset = ihs_mdio_reset;
strcpy(bus->name, info->name);
bus->priv = info;
return mdio_register(bus);
}
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _IHS_MDIO_H_
#define _IHS_MDIO_H_
struct ihs_mdio_info {
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
u32 fpga;
#else
struct udevice *fpga;
int base;
#endif
char *name;
};
int ihs_mdio_init(struct ihs_mdio_info *info);
#endif
@@ -0,0 +1,589 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <gdsys_fpga.h>
enum pcb_video_type {
PCB_DVI_SL,
PCB_DP_165MPIX,
PCB_DP_300MPIX,
PCB_HDMI,
PCB_DP_1_2,
PCB_HDMI_2_0,
};
enum pcb_transmission_type {
PCB_CAT_1G,
PCB_FIBER_3G,
PCB_CAT_10G,
PCB_FIBER_10G,
};
enum carrier_speed {
CARRIER_SPEED_1G,
CARRIER_SPEED_3G,
CARRIER_SPEED_2_5G = CARRIER_SPEED_3G,
CARRIER_SPEED_10G,
};
enum ram_config {
RAM_DDR2_32BIT_295MBPS,
RAM_DDR3_32BIT_590MBPS,
RAM_DDR3_48BIT_590MBPS,
RAM_DDR3_64BIT_1800MBPS,
RAM_DDR3_48BIT_1800MBPS,
};
enum sysclock {
SYSCLK_147456,
};
struct fpga_versions {
bool video_channel;
bool con_side;
enum pcb_video_type pcb_video_type;
enum pcb_transmission_type pcb_transmission_type;
unsigned int hw_version;
};
struct fpga_features {
u8 video_channels;
u8 carriers;
enum carrier_speed carrier_speed;
enum ram_config ram_config;
enum sysclock sysclock;
bool pcm_tx;
bool pcm_rx;
bool spdif_tx;
bool spdif_rx;
bool usb2;
bool rs232;
bool compression_type1;
bool compression_type2;
bool compression_type3;
bool interlace;
bool osd;
bool compression_pipes;
};
#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM
static int get_versions(unsigned int fpga, struct fpga_versions *versions)
{
enum {
VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12),
VERSIONS_FPGA_CON_SIDE = BIT(13),
VERSIONS_FPGA_SC = BIT(14),
VERSIONS_PCB_CON = BIT(9),
VERSIONS_PCB_SC = BIT(8),
VERSIONS_PCB_VIDEO_MASK = 0x3 << 6,
VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6,
VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6,
VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4,
VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4,
VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4,
VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4,
VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4,
VERSIONS_HW_VER_MASK = 0xf << 0,
};
u16 raw_versions;
memset(versions, 0, sizeof(struct fpga_versions));
FPGA_GET_REG(fpga, versions, &raw_versions);
versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL;
versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE;
switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) {
case VERSIONS_PCB_VIDEO_DP_1_2:
versions->pcb_video_type = PCB_DP_1_2;
break;
case VERSIONS_PCB_VIDEO_HDMI_2_0:
versions->pcb_video_type = PCB_HDMI_2_0;
break;
}
switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) {
case VERSIONS_PCB_TRANSMISSION_FIBER_10G:
versions->pcb_transmission_type = PCB_FIBER_10G;
break;
case VERSIONS_PCB_TRANSMISSION_CAT_10G:
versions->pcb_transmission_type = PCB_CAT_10G;
break;
case VERSIONS_PCB_TRANSMISSION_FIBER_3G:
versions->pcb_transmission_type = PCB_FIBER_3G;
break;
case VERSIONS_PCB_TRANSMISSION_CAT_1G:
versions->pcb_transmission_type = PCB_CAT_1G;
break;
}
versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
return 0;
}
static int get_features(unsigned int fpga, struct fpga_features *features)
{
enum {
FEATURE_SPDIF_RX = BIT(15),
FEATURE_SPDIF_TX = BIT(14),
FEATURE_PCM_RX = BIT(13),
FEATURE_PCM_TX = BIT(12),
FEATURE_RAM_MASK = GENMASK(11, 8),
FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8,
FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8,
FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8,
FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8,
FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8,
FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6),
FEATURE_CARRIER_SPEED_1G = 0x0 << 6,
FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6,
FEATURE_CARRIER_SPEED_10G = 0x2 << 6,
FEATURE_CARRIERS_MASK = GENMASK(5, 4),
FEATURE_CARRIERS_0 = 0x0 << 4,
FEATURE_CARRIERS_1 = 0x1 << 4,
FEATURE_CARRIERS_2 = 0x2 << 4,
FEATURE_CARRIERS_4 = 0x3 << 4,
FEATURE_USB2 = BIT(3),
FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0),
FEATURE_VIDEOCHANNELS_0 = 0x0 << 0,
FEATURE_VIDEOCHANNELS_1 = 0x1 << 0,
FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0,
FEATURE_VIDEOCHANNELS_2 = 0x3 << 0,
};
enum {
EXT_FEATURE_OSD = BIT(15),
EXT_FEATURE_ETHERNET = BIT(9),
EXT_FEATURE_INTERLACE = BIT(8),
EXT_FEATURE_RS232 = BIT(7),
EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4),
EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4,
EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4,
EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4,
EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0),
EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1),
EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2),
};
u16 raw_features;
u16 raw_extended_features;
memset(features, 0, sizeof(struct fpga_features));
FPGA_GET_REG(fpga, fpga_features, &raw_features);
FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) {
case FEATURE_VIDEOCHANNELS_0:
features->video_channels = 0;
break;
case FEATURE_VIDEOCHANNELS_1:
features->video_channels = 1;
break;
case FEATURE_VIDEOCHANNELS_1_1:
case FEATURE_VIDEOCHANNELS_2:
features->video_channels = 2;
break;
};
switch (raw_features & FEATURE_CARRIERS_MASK) {
case FEATURE_CARRIERS_0:
features->carriers = 0;
break;
case FEATURE_CARRIERS_1:
features->carriers = 1;
break;
case FEATURE_CARRIERS_2:
features->carriers = 2;
break;
case FEATURE_CARRIERS_4:
features->carriers = 4;
break;
}
switch (raw_features & FEATURE_CARRIER_SPEED_MASK) {
case FEATURE_CARRIER_SPEED_1G:
features->carrier_speed = CARRIER_SPEED_1G;
break;
case FEATURE_CARRIER_SPEED_2_5G:
features->carrier_speed = CARRIER_SPEED_2_5G;
break;
case FEATURE_CARRIER_SPEED_10G:
features->carrier_speed = CARRIER_SPEED_10G;
break;
}
switch (raw_features & FEATURE_RAM_MASK) {
case FEATURE_RAM_DDR2_32BIT_295MBPS:
features->ram_config = RAM_DDR2_32BIT_295MBPS;
break;
case FEATURE_RAM_DDR3_32BIT_590MBPS:
features->ram_config = RAM_DDR3_32BIT_590MBPS;
break;
case FEATURE_RAM_DDR3_48BIT_590MBPS:
features->ram_config = RAM_DDR3_48BIT_590MBPS;
break;
case FEATURE_RAM_DDR3_64BIT_1800MBPS:
features->ram_config = RAM_DDR3_64BIT_1800MBPS;
break;
case FEATURE_RAM_DDR3_48BIT_1800MBPS:
features->ram_config = RAM_DDR3_48BIT_1800MBPS;
break;
}
features->pcm_tx = raw_features & FEATURE_PCM_TX;
features->pcm_rx = raw_features & FEATURE_PCM_RX;
features->spdif_tx = raw_features & FEATURE_SPDIF_TX;
features->spdif_rx = raw_features & FEATURE_SPDIF_RX;
features->usb2 = raw_features & FEATURE_USB2;
features->rs232 = raw_extended_features & EXT_FEATURE_RS232;
features->compression_type1 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE1;
features->compression_type2 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE2;
features->compression_type3 = raw_extended_features & EXT_FEATURE_COMPRESSION_TYPE3;
features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE;
features->osd = raw_extended_features & EXT_FEATURE_OSD;
features->compression_pipes = raw_extended_features & EXT_FEATURE_COMPRESSION_PERF_MASK;
return 0;
}
#else
static int get_versions(unsigned int fpga, struct fpga_versions *versions)
{
enum {
/* HW version encoding is a mess, leave it for the moment */
VERSIONS_HW_VER_MASK = 0xf << 0,
VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4),
VERSIONS_SFP = BIT(5),
VERSIONS_VIDEO_MASK = 0x7 << 6,
VERSIONS_VIDEO_DVI = 0x0 << 6,
VERSIONS_VIDEO_DP_165 = 0x1 << 6,
VERSIONS_VIDEO_DP_300 = 0x2 << 6,
VERSIONS_VIDEO_HDMI = 0x3 << 6,
VERSIONS_UT_MASK = 0xf << 12,
VERSIONS_UT_MAIN_SERVER = 0x0 << 12,
VERSIONS_UT_MAIN_USER = 0x1 << 12,
VERSIONS_UT_VIDEO_SERVER = 0x2 << 12,
VERSIONS_UT_VIDEO_USER = 0x3 << 12,
};
u16 raw_versions;
memset(versions, 0, sizeof(struct fpga_versions));
FPGA_GET_REG(fpga, versions, &raw_versions);
switch (raw_versions & VERSIONS_UT_MASK) {
case VERSIONS_UT_MAIN_SERVER:
versions->video_channel = false;
versions->con_side = false;
break;
case VERSIONS_UT_MAIN_USER:
versions->video_channel = false;
versions->con_side = true;
break;
case VERSIONS_UT_VIDEO_SERVER:
versions->video_channel = true;
versions->con_side = false;
break;
case VERSIONS_UT_VIDEO_USER:
versions->video_channel = true;
versions->con_side = true;
break;
}
switch (raw_versions & VERSIONS_VIDEO_MASK) {
case VERSIONS_VIDEO_DVI:
versions->pcb_video_type = PCB_DVI_SL;
break;
case VERSIONS_VIDEO_DP_165:
versions->pcb_video_type = PCB_DP_165MPIX;
break;
case VERSIONS_VIDEO_DP_300:
versions->pcb_video_type = PCB_DP_300MPIX;
break;
case VERSIONS_VIDEO_HDMI:
versions->pcb_video_type = PCB_HDMI;
break;
}
versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
if (raw_versions & VERSIONS_SFP)
versions->pcb_transmission_type = PCB_FIBER_3G;
else
versions->pcb_transmission_type = PCB_CAT_1G;
return 0;
}
static int get_features(unsigned int fpga, struct fpga_features *features)
{
enum {
FEATURE_CARRIER_SPEED_2_5 = BIT(4),
FEATURE_RAM_MASK = 0x7 << 5,
FEATURE_RAM_DDR2_32BIT = 0x0 << 5,
FEATURE_RAM_DDR3_32BIT = 0x1 << 5,
FEATURE_RAM_DDR3_48BIT = 0x2 << 5,
FEATURE_PCM_AUDIO_TX = BIT(9),
FEATURE_PCM_AUDIO_RX = BIT(10),
FEATURE_OSD = BIT(11),
FEATURE_USB20 = BIT(12),
FEATURE_COMPRESSION_MASK = 7 << 13,
FEATURE_COMPRESSION_TYPE1 = 0x1 << 13,
FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13,
FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13,
};
enum {
EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0),
EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1),
EXTENDED_FEATURE_RS232 = BIT(2),
EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3),
EXTENDED_FEATURE_INTERLACE = BIT(4),
};
u16 raw_features;
#ifdef GDSYS_LEGACY_DRIVERS
u16 raw_extended_features;
#endif
memset(features, 0, sizeof(struct fpga_features));
FPGA_GET_REG(fpga, fpga_features, &raw_features);
#ifdef GDSYS_LEGACY_DRIVERS
FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
#endif
features->video_channels = raw_features & 0x3;
features->carriers = (raw_features >> 2) & 0x3;
features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5)
? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G;
switch (raw_features & FEATURE_RAM_MASK) {
case FEATURE_RAM_DDR2_32BIT:
features->ram_config = RAM_DDR2_32BIT_295MBPS;
break;
case FEATURE_RAM_DDR3_32BIT:
features->ram_config = RAM_DDR3_32BIT_590MBPS;
break;
case FEATURE_RAM_DDR3_48BIT:
features->ram_config = RAM_DDR3_48BIT_590MBPS;
break;
}
features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX;
features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX;
#ifdef GDSYS_LEGACY_DRIVERS
features->spdif_tx = raw_extended_features & EXTENDED_FEATURE_SPDIF_AUDIO_TX;
features->spdif_rx = raw_extended_features & EXTENDED_FEATURE_SPDIF_AUDIO_RX;
#endif
features->usb2 = raw_features & FEATURE_USB20;
#ifdef GDSYS_LEGACY_DRIVERS
features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232;
#endif
features->compression_type1 = false;
features->compression_type2 = false;
features->compression_type3 = false;
switch (raw_features & FEATURE_COMPRESSION_MASK) {
case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3:
features->compression_type3 = true;
case FEATURE_COMPRESSION_TYPE1_TYPE2:
features->compression_type2 = true;
case FEATURE_COMPRESSION_TYPE1:
features->compression_type1 = true;
break;
}
#ifdef GDSYS_LEGACY_DRIVERS
features->interlace = raw_extended_features & EXTENDED_FEATURE_INTERLACE;
#endif
features->osd = raw_features & FEATURE_OSD;
#ifdef GDSYS_LEGACY_DRIVERS
features->compression_pipes = raw_extended_features & EXTENDED_FEATURE_COMPRESSION_PIPES;
#endif
return 0;
}
#endif
bool ioep_fpga_has_osd(unsigned int fpga)
{
struct fpga_features features;
get_features(fpga, &features);
return features.osd;
}
void ioep_fpga_print_info(unsigned int fpga)
{
u16 fpga_version;
struct fpga_versions versions;
struct fpga_features features;
FPGA_GET_REG(fpga, fpga_version, &fpga_version);
get_versions(fpga, &versions);
get_features(fpga, &features);
if (versions.video_channel)
printf("Videochannel");
else
printf("Mainchannel");
if (versions.con_side)
printf(" User");
else
printf(" Server");
// FIXME
#if 0
if (versions & (1<<4))
printf(" UC");
#endif
switch(versions.pcb_transmission_type) {
case PCB_CAT_1G:
case PCB_CAT_10G:
printf(" CAT");
break;
case PCB_FIBER_3G:
case PCB_FIBER_10G:
printf(" Fiber");
break;
};
switch (versions.pcb_video_type) {
case PCB_DVI_SL:
printf(" DVI,");
break;
case PCB_DP_165MPIX:
printf(" DP 165MPix/s,");
break;
case PCB_DP_300MPIX:
printf(" DP 300MPix/s,");
break;
case PCB_HDMI:
printf(" HDMI,");
break;
case PCB_DP_1_2:
printf(" DP 1.2,");
break;
case PCB_HDMI_2_0:
printf(" HDMI 2.0,");
break;
}
printf(" FPGA V %d.%02d\n features: ",
fpga_version / 100, fpga_version % 100);
if (!features.compression_type1 &&
!features.compression_type2 &&
!features.compression_type3)
printf("no compression, ");
if (features.compression_type1)
printf("type1, ");
if (features.compression_type2)
printf("type2, ");
if (features.compression_type3)
printf("type3, ");
printf("%sosd", features.osd ? "" : "no ");
if (features.pcm_rx && features.pcm_tx)
printf(", pcm rx+tx");
else if(features.pcm_rx)
printf(", pcm rx");
else if(features.pcm_tx)
printf(", pcm tx");
if (features.spdif_rx && features.spdif_tx)
printf(", spdif rx+tx");
else if(features.spdif_rx)
printf(", spdif rx");
else if(features.spdif_tx)
printf(", spdif tx");
puts(",\n ");
switch (features.sysclock) {
case SYSCLK_147456:
printf("clock 147.456 MHz");
break;
}
switch (features.ram_config) {
case RAM_DDR2_32BIT_295MBPS:
printf(", RAM 32 bit DDR2");
break;
case RAM_DDR3_32BIT_590MBPS:
printf(", RAM 32 bit DDR3");
break;
case RAM_DDR3_48BIT_590MBPS:
case RAM_DDR3_48BIT_1800MBPS:
printf(", RAM 48 bit DDR3");
break;
case RAM_DDR3_64BIT_1800MBPS:
printf(", RAM 64 bit DDR3");
break;
}
printf(", %d carrier(s)", features.carriers);
switch(features.carrier_speed) {
case CARRIER_SPEED_1G:
printf(", 1Gbit/s");
break;
case CARRIER_SPEED_3G:
printf(", 3Gbit/s");
break;
case CARRIER_SPEED_10G:
printf(", 10Gbit/s");
break;
}
printf(", %d video channel(s)\n", features.video_channels);
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _IOEP_FPGA_H_
#define _IOEP_FPGA_H_
void ioep_fpga_print_info(unsigned int fpga);
bool ioep_fpga_has_osd(unsigned int fpga);
#endif
@@ -0,0 +1,140 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2012
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <asm/io.h>
#include <errno.h>
#include <gdsys_fpga.h>
enum {
MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7,
MCINT_TX_ERROR_EV = 1 << 9,
MCINT_TX_BUFFER_FREE = 1 << 10,
MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11,
MCINT_RX_ERROR_EV = 1 << 13,
MCINT_RX_CONTENT_AVAILABLE = 1 << 14,
MCINT_RX_PACKET_RECEIVED_EV = 1 << 15,
};
int mclink_probe(void)
{
unsigned int k;
int slaves = 0;
for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) {
int timeout = 0;
unsigned int ctr = 0;
u16 mc_status;
FPGA_GET_REG(k, mc_status, &mc_status);
if (!(mc_status & (1 << 15)))
break;
FPGA_SET_REG(k, mc_control, 0x8000);
FPGA_GET_REG(k, mc_status, &mc_status);
while (!(mc_status & (1 << 14))) {
udelay(100);
if (ctr++ > 500) {
timeout = 1;
break;
}
FPGA_GET_REG(k, mc_status, &mc_status);
}
if (timeout)
break;
printf("waited %d us for mclink %d to come up\n", ctr * 100, k);
slaves++;
}
return slaves;
}
int mclink_send(u8 slave, u16 addr, u16 data)
{
unsigned int ctr = 0;
u16 int_status;
u16 rx_cmd_status;
u16 rx_cmd;
/* reset interrupt status */
FPGA_GET_REG(0, mc_int, &int_status);
FPGA_SET_REG(0, mc_int, int_status);
/* send */
FPGA_SET_REG(0, mc_tx_address, addr);
FPGA_SET_REG(0, mc_tx_data, data);
FPGA_SET_REG(0, mc_tx_cmd, (slave & 0x03) << 14);
FPGA_SET_REG(0, mc_control, 0x8001);
/* wait for reply */
FPGA_GET_REG(0, mc_int, &int_status);
while (!(int_status & MCINT_RX_PACKET_RECEIVED_EV)) {
udelay(100);
if (ctr++ > 3)
return -ETIMEDOUT;
FPGA_GET_REG(0, mc_int, &int_status);
}
FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
rx_cmd = (rx_cmd_status >> 12) & 0x03;
if (rx_cmd != 0)
printf("mclink_send: received cmd %d, expected %d\n", rx_cmd,
0);
return 0;
}
int mclink_receive(u8 slave, u16 addr, u16 *data)
{
u16 rx_cmd_status;
u16 rx_cmd;
u16 int_status;
unsigned int ctr = 0;
/* send read request */
FPGA_SET_REG(0, mc_tx_address, addr);
FPGA_SET_REG(0, mc_tx_cmd,
((slave & 0x03) << 14) | (1 << 12) | (1 << 0));
FPGA_SET_REG(0, mc_control, 0x8001);
/* wait for reply */
FPGA_GET_REG(0, mc_int, &int_status);
while (!(int_status & MCINT_RX_CONTENT_AVAILABLE)) {
udelay(100);
if (ctr++ > 3)
return -ETIMEDOUT;
FPGA_GET_REG(0, mc_int, &int_status);
}
/* check reply */
FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
if ((rx_cmd_status >> 14) != slave) {
printf("mclink_receive: reply from slave %d, expected %d\n",
rx_cmd_status >> 14, slave);
return -EINVAL;
}
rx_cmd = (rx_cmd_status >> 12) & 0x03;
if (rx_cmd != 1) {
printf("mclink_send: received cmd %d, expected %d\n",
rx_cmd, 1);
return -EIO;
}
FPGA_GET_REG(0, mc_rx_data, data);
return 0;
}
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2012
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _MCLINK_H_
#define _MCLINK_H_
int mclink_probe(void);
int mclink_send(u8 slave, u16 addr, u16 data);
int mclink_receive(u8 slave, u16 addr, u16 *data);
#endif
@@ -0,0 +1,503 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2010
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
#include <common.h>
#include <i2c.h>
#include <malloc.h>
#include "ch7301.h"
#include "dp501.h"
#include <gdsys_fpga.h>
#define ICS8N3QV01_I2C_ADDR 0x6E
#define ICS8N3QV01_FREF 114285000
#define ICS8N3QV01_FREF_LL 114285000LL
#define ICS8N3QV01_F_DEFAULT_0 156250000LL
#define ICS8N3QV01_F_DEFAULT_1 125000000LL
#define ICS8N3QV01_F_DEFAULT_2 100000000LL
#define ICS8N3QV01_F_DEFAULT_3 25175000LL
#define SIL1178_MASTER_I2C_ADDRESS 0x38
#define SIL1178_SLAVE_I2C_ADDRESS 0x39
#define PIXCLK_640_480_60 25180000
#define MAX_X_CHARS 53
#define MAX_Y_CHARS 26
#ifdef CONFIG_SYS_OSD_DH
#define MAX_OSD_SCREEN 8
#define OSD_DH_BASE 4
#else
#define MAX_OSD_SCREEN 4
#endif
#ifdef CONFIG_SYS_OSD_DH
#define OSD_SET_REG(screen, fld, val) \
do { \
if (screen >= OSD_DH_BASE) \
FPGA_SET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
else \
FPGA_SET_REG(screen, osd0.fld, val); \
} while (0)
#else
#define OSD_SET_REG(screen, fld, val) \
FPGA_SET_REG(screen, osd0.fld, val)
#endif
#ifdef CONFIG_SYS_OSD_DH
#define OSD_GET_REG(screen, fld, val) \
do { \
if (screen >= OSD_DH_BASE) \
FPGA_GET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
else \
FPGA_GET_REG(screen, osd0.fld, val); \
} while (0)
#else
#define OSD_GET_REG(screen, fld, val) \
FPGA_GET_REG(screen, osd0.fld, val)
#endif
unsigned int base_width;
unsigned int base_height;
size_t bufsize;
u16 *buf;
unsigned int osd_screen_mask = 0;
#ifdef CONFIG_SYS_ICS8N3QV01_I2C
int ics8n3qv01_i2c[] = CONFIG_SYS_ICS8N3QV01_I2C;
#endif
#ifdef CONFIG_SYS_SIL1178_I2C
int sil1178_i2c[] = CONFIG_SYS_SIL1178_I2C;
#endif
#ifdef CONFIG_SYS_MPC92469AC
static void mpc92469ac_calc_parameters(unsigned int fout,
unsigned int *post_div, unsigned int *feedback_div)
{
unsigned int n = *post_div;
unsigned int m = *feedback_div;
unsigned int a;
unsigned int b = 14745600 / 16;
if (fout < 50169600)
n = 8;
else if (fout < 100339199)
n = 4;
else if (fout < 200678399)
n = 2;
else
n = 1;
a = fout * n + (b / 2); /* add b/2 for proper rounding */
m = a / b;
*post_div = n;
*feedback_div = m;
}
static void mpc92469ac_set(unsigned screen, unsigned int fout)
{
unsigned int n;
unsigned int m;
unsigned int bitval = 0;
mpc92469ac_calc_parameters(fout, &n, &m);
switch (n) {
case 1:
bitval = 0x00;
break;
case 2:
bitval = 0x01;
break;
case 4:
bitval = 0x02;
break;
case 8:
bitval = 0x03;
break;
}
FPGA_SET_REG(screen, mpc3w_control, (bitval << 9) | m);
}
#endif
#ifdef CONFIG_SYS_ICS8N3QV01_I2C
static unsigned int ics8n3qv01_get_fout_calc(unsigned index)
{
unsigned long long n;
unsigned long long mint;
unsigned long long mfrac;
u8 reg_a, reg_b, reg_c, reg_d, reg_f;
unsigned long long fout_calc;
if (index > 3)
return 0;
reg_a = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0 + index);
reg_b = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 4 + index);
reg_c = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 8 + index);
reg_d = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 12 + index);
reg_f = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20 + index);
mint = ((reg_a >> 1) & 0x1f) | (reg_f & 0x20);
mfrac = ((reg_a & 0x01) << 17) | (reg_b << 9) | (reg_c << 1)
| (reg_d >> 7);
n = reg_d & 0x7f;
fout_calc = (mint * ICS8N3QV01_FREF_LL
+ mfrac * ICS8N3QV01_FREF_LL / 262144LL
+ ICS8N3QV01_FREF_LL / 524288LL
+ n / 2)
/ n
* 1000000
/ (1000000 - 100);
return fout_calc;
}
static void ics8n3qv01_calc_parameters(unsigned int fout,
unsigned int *_mint, unsigned int *_mfrac,
unsigned int *_n)
{
unsigned int n;
unsigned int foutiic;
unsigned int fvcoiic;
unsigned int mint;
unsigned long long mfrac;
n = (2215000000U + fout / 2) / fout;
if ((n & 1) && (n > 5))
n -= 1;
foutiic = fout - (fout / 10000);
fvcoiic = foutiic * n;
mint = fvcoiic / 114285000;
if ((mint < 17) || (mint > 63))
printf("ics8n3qv01_calc_parameters: cannot determine mint\n");
mfrac = ((unsigned long long)fvcoiic % 114285000LL) * 262144LL
/ 114285000LL;
*_mint = mint;
*_mfrac = mfrac;
*_n = n;
}
static void ics8n3qv01_set(unsigned int fout)
{
unsigned int n;
unsigned int mint;
unsigned int mfrac;
unsigned int fout_calc;
unsigned long long fout_prog;
long long off_ppm;
u8 reg0, reg4, reg8, reg12, reg18, reg20;
fout_calc = ics8n3qv01_get_fout_calc(1);
off_ppm = (fout_calc - ICS8N3QV01_F_DEFAULT_1) * 1000000
/ ICS8N3QV01_F_DEFAULT_1;
printf(" PLL is off by %lld ppm\n", off_ppm);
fout_prog = (unsigned long long)fout * (unsigned long long)fout_calc
/ ICS8N3QV01_F_DEFAULT_1;
ics8n3qv01_calc_parameters(fout_prog, &mint, &mfrac, &n);
reg0 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0) & 0xc0;
reg0 |= (mint & 0x1f) << 1;
reg0 |= (mfrac >> 17) & 0x01;
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 0, reg0);
reg4 = mfrac >> 9;
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 4, reg4);
reg8 = mfrac >> 1;
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 8, reg8);
reg12 = mfrac << 7;
reg12 |= n & 0x7f;
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 12, reg12);
reg18 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 18) & 0x03;
reg18 |= 0x20;
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 18, reg18);
reg20 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20) & 0x1f;
reg20 |= mint & (1 << 5);
i2c_reg_write(ICS8N3QV01_I2C_ADDR, 20, reg20);
}
#endif
static int osd_write_videomem(unsigned screen, unsigned offset,
u16 *data, size_t charcount)
{
unsigned int k;
for (k = 0; k < charcount; ++k) {
if (offset + k >= bufsize)
return -1;
#ifdef CONFIG_SYS_OSD_DH
if (screen >= OSD_DH_BASE)
FPGA_SET_REG(screen - OSD_DH_BASE,
videomem1[offset + k], data[k]);
else
FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
#else
FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
#endif
}
return charcount;
}
static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned screen;
if (argc < 5) {
cmd_usage(cmdtp);
return 1;
}
for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
unsigned x;
unsigned y;
unsigned charcount;
unsigned len;
u8 color;
unsigned int k;
char *text;
int res;
if (!(osd_screen_mask & (1 << screen)))
continue;
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
color = simple_strtoul(argv[3], NULL, 16);
text = argv[4];
charcount = strlen(text);
len = (charcount > bufsize) ? bufsize : charcount;
for (k = 0; k < len; ++k)
buf[k] = (text[k] << 8) | color;
res = osd_write_videomem(screen, y * base_width + x, buf, len);
if (res < 0)
return res;
OSD_SET_REG(screen, control, 0x0049);
}
return 0;
}
int osd_probe(unsigned screen)
{
u16 version;
u16 features;
int old_bus = i2c_get_bus_num();
bool pixclock_present = false;
bool output_driver_present = false;
OSD_GET_REG(0, version, &version);
OSD_GET_REG(0, features, &features);
base_width = ((features & 0x3f00) >> 8) + 1;
base_height = (features & 0x001f) + 1;
bufsize = base_width * base_height;
buf = malloc(sizeof(u16) * bufsize);
if (!buf)
return -1;
#ifdef CONFIG_SYS_OSD_DH
printf("OSD%d-%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
(screen >= OSD_DH_BASE) ? (screen - OSD_DH_BASE) : screen,
(screen > 3) ? 1 : 0, version/100, version%100, base_width,
base_height);
#else
printf("OSD%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
screen, version/100, version%100, base_width, base_height);
#endif
/* setup pixclock */
#ifdef CONFIG_SYS_MPC92469AC
pixclock_present = true;
mpc92469ac_set(screen, PIXCLK_640_480_60);
#endif
#ifdef CONFIG_SYS_ICS8N3QV01_I2C
i2c_set_bus_num(ics8n3qv01_i2c[screen]);
if (!i2c_probe(ICS8N3QV01_I2C_ADDR)) {
ics8n3qv01_set(PIXCLK_640_480_60);
pixclock_present = true;
}
#endif
if (!pixclock_present)
printf(" no pixelclock found\n");
/* setup output driver */
#ifdef CONFIG_SYS_CH7301_I2C
if (!ch7301_probe(screen, true))
output_driver_present = true;
#endif
#ifdef CONFIG_SYS_SIL1178_I2C
i2c_set_bus_num(sil1178_i2c[screen]);
if (!i2c_probe(SIL1178_SLAVE_I2C_ADDRESS)) {
if (i2c_reg_read(SIL1178_SLAVE_I2C_ADDRESS, 0x02) == 0x06) {
/*
* magic initialization sequence,
* adapted from datasheet
*/
i2c_reg_write(SIL1178_SLAVE_I2C_ADDRESS, 0x08, 0x36);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x44);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x4c);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0e, 0x10);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0a, 0x80);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x09, 0x30);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0c, 0x89);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0d, 0x60);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x36);
i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x37);
output_driver_present = true;
}
}
#endif
#ifdef CONFIG_SYS_DP501_I2C
if (!dp501_probe(screen, true))
output_driver_present = true;
#endif
if (!output_driver_present)
printf(" no output driver found\n");
OSD_SET_REG(screen, xy_size, ((32 - 1) << 8) | (16 - 1));
OSD_SET_REG(screen, x_pos, 0x007f);
OSD_SET_REG(screen, y_pos, 0x005f);
if (pixclock_present && output_driver_present)
osd_screen_mask |= 1 << screen;
i2c_set_bus_num(old_bus);
return 0;
}
int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned screen;
if ((argc < 4) || (strlen(argv[3]) % 4)) {
cmd_usage(cmdtp);
return 1;
}
for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
unsigned x;
unsigned y;
unsigned k;
u16 buffer[base_width];
char *rp;
u16 *wp = buffer;
unsigned count = (argc > 4) ?
simple_strtoul(argv[4], NULL, 16) : 1;
if (!(osd_screen_mask & (1 << screen)))
continue;
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
rp = argv[3];
while (*rp) {
char substr[5];
memcpy(substr, rp, 4);
substr[4] = 0;
*wp = simple_strtoul(substr, NULL, 16);
rp += 4;
wp++;
if (wp - buffer > base_width)
break;
}
for (k = 0; k < count; ++k) {
unsigned offset =
y * base_width + x + k * (wp - buffer);
osd_write_videomem(screen, offset, buffer,
wp - buffer);
}
OSD_SET_REG(screen, control, 0x0049);
}
return 0;
}
int osd_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned screen;
unsigned x;
unsigned y;
if (argc < 3) {
cmd_usage(cmdtp);
return 1;
}
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
if (!x || (x > 64) || (x > MAX_X_CHARS) ||
!y || (y > 32) || (y > MAX_Y_CHARS)) {
cmd_usage(cmdtp);
return 1;
}
for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
if (!(osd_screen_mask & (1 << screen)))
continue;
OSD_SET_REG(screen, xy_size, ((x - 1) << 8) | (y - 1));
OSD_SET_REG(screen, x_pos, 32767 * (640 - 12 * x) / 65535);
OSD_SET_REG(screen, y_pos, 32767 * (480 - 18 * y) / 65535);
}
return 0;
}
U_BOOT_CMD(
osdw, 5, 0, osd_write,
"write 16-bit hex encoded buffer to osd memory",
"pos_x pos_y buffer count\n"
);
U_BOOT_CMD(
osdp, 5, 0, osd_print,
"write ASCII buffer to osd memory",
"pos_x pos_y color text\n"
);
U_BOOT_CMD(
osdsize, 3, 0, osd_size,
"set OSD XY size in characters",
"size_x(max. " __stringify(MAX_X_CHARS)
") size_y(max. " __stringify(MAX_Y_CHARS) ")\n"
);
#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2010
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _OSD_H_
#define _OSD_H_
int ch7301_probe(unsigned screen, bool power);
int osd_probe(unsigned screen);
#endif
@@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2017
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*
* based on the gdsys osd driver, which is
*
* (C) Copyright 2010
* Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
*/
#include <common.h>
#include <dm.h>
#include <hexdump.h>
#include <video_osd.h>
#include <malloc.h>
static int do_osd_write(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
struct udevice *dev;
uint x, y;
uint count;
char *hexstr;
u8 *buffer;
size_t buflen;
int res;
if (argc < 4 || (strlen(argv[3])) % 2)
return CMD_RET_USAGE;
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
hexstr = argv[3];
count = (argc > 4) ? simple_strtoul(argv[4], NULL, 16) : 1;
buflen = strlen(hexstr) / 2;
buffer = malloc(buflen);
if (!buffer) {
puts("Memory allocation failure\n");
return CMD_RET_FAILURE;
}
res = hex2bin(buffer, hexstr, buflen);
if (res) {
free(buffer);
puts("Hexadecimal input contained invalid characters\n");
return CMD_RET_FAILURE;
}
for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
dev;
uclass_next_device(&dev)) {
int res;
res = video_osd_set_mem(dev, x, y, buffer, buflen, count);
if (res) {
free(buffer);
printf("Could not write to video mem on osd %s\n",
dev->name);
return CMD_RET_FAILURE;
}
}
free(buffer);
return CMD_RET_SUCCESS;
}
static int do_osd_print(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
struct udevice *dev;
uint x, y;
u8 color;
char *text;
if (argc < 5)
return CMD_RET_USAGE;
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
color = simple_strtoul(argv[3], NULL, 16);
text = argv[4];
for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
dev;
uclass_next_device(&dev)) {
int res;
res = video_osd_print(dev, x, y, color, text);
if (res) {
printf("Could not print string to osd %s\n", dev->name);
return CMD_RET_FAILURE;
}
}
return CMD_RET_SUCCESS;
}
static int do_osd_size(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
struct udevice *dev;
uint x, y;
if (argc < 3)
return CMD_RET_USAGE;
x = simple_strtoul(argv[1], NULL, 16);
y = simple_strtoul(argv[2], NULL, 16);
for (uclass_first_device(UCLASS_VIDEO_OSD, &dev);
dev;
uclass_next_device(&dev)) {
int res;
res = video_osd_set_size(dev, x, y);
if (res) {
printf("Could not set size on osd %s\n", dev->name);
return CMD_RET_FAILURE;
}
}
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(
osdw, 5, 0, do_osd_write,
"write 16-bit hex encoded buffer to osd memory",
"osdw [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory\n"
);
U_BOOT_CMD(
osdp, 5, 0, do_osd_print,
"write ASCII buffer to osd memory",
"osdp [pos_x] [pos_y] [color] [text] - write ASCII buffer to osd memory\n"
);
U_BOOT_CMD(
osdsize, 3, 0, do_osd_size,
"set OSD XY size in characters",
"osdsize [size_x] [size_y] - set OSD XY size in characters\n"
);
@@ -0,0 +1,277 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#include <common.h>
#include <miiphy.h>
enum {
MIICMD_SET,
MIICMD_MODIFY,
MIICMD_VERIFY_VALUE,
MIICMD_WAIT_FOR_VALUE,
};
struct mii_setupcmd {
u8 token;
u8 reg;
u16 data;
u16 mask;
u32 timeout;
};
/*
* verify we are talking to a 88e1518
*/
struct mii_setupcmd verify_88e1518[] = {
{ MIICMD_SET, 22, 0x0000 },
{ MIICMD_VERIFY_VALUE, 2, 0x0141, 0xffff },
{ MIICMD_VERIFY_VALUE, 3, 0x0dd0, 0xfff0 },
};
/*
* workaround for erratum mentioned in 88E1518 release notes
*/
struct mii_setupcmd fixup_88e1518[] = {
{ MIICMD_SET, 22, 0x00ff },
{ MIICMD_SET, 17, 0x214b },
{ MIICMD_SET, 16, 0x2144 },
{ MIICMD_SET, 17, 0x0c28 },
{ MIICMD_SET, 16, 0x2146 },
{ MIICMD_SET, 17, 0xb233 },
{ MIICMD_SET, 16, 0x214d },
{ MIICMD_SET, 17, 0xcc0c },
{ MIICMD_SET, 16, 0x2159 },
{ MIICMD_SET, 22, 0x0000 },
};
/*
* default initialization:
* - set RGMII receive timing to "receive clock transition when data stable"
* - set RGMII transmit timing to "transmit clock internally delayed"
* - set RGMII output impedance target to 78,8 Ohm
* - run output impedance calibration
* - set autonegotiation advertise to 1000FD only
*/
struct mii_setupcmd default_88e1518[] = {
{ MIICMD_SET, 22, 0x0002 },
{ MIICMD_MODIFY, 21, 0x0030, 0x0030 },
{ MIICMD_MODIFY, 25, 0x0000, 0x0003 },
{ MIICMD_MODIFY, 24, 0x8000, 0x8000 },
{ MIICMD_WAIT_FOR_VALUE, 24, 0x4000, 0x4000, 2000 },
{ MIICMD_SET, 22, 0x0000 },
{ MIICMD_MODIFY, 4, 0x0000, 0x01e0 },
{ MIICMD_MODIFY, 9, 0x0200, 0x0300 },
};
/*
* turn off CLK125 for PHY daughterboard
*/
struct mii_setupcmd ch1fix_88e1518[] = {
{ MIICMD_SET, 22, 0x0002 },
{ MIICMD_MODIFY, 16, 0x0006, 0x0006 },
{ MIICMD_SET, 22, 0x0000 },
};
/*
* perform copper software reset
*/
struct mii_setupcmd swreset_88e1518[] = {
{ MIICMD_SET, 22, 0x0000 },
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
{ MIICMD_WAIT_FOR_VALUE, 0, 0x0000, 0x8000, 2000 },
};
/*
* special one for 88E1514:
* Force SGMII to Copper mode
*/
struct mii_setupcmd mii_to_copper_88e1514[] = {
{ MIICMD_SET, 22, 0x0012 },
{ MIICMD_MODIFY, 20, 0x0001, 0x0007 },
{ MIICMD_MODIFY, 20, 0x8000, 0x8000 },
{ MIICMD_SET, 22, 0x0000 },
};
/*
* turn off SGMII auto-negotiation
*/
struct mii_setupcmd sgmii_autoneg_off_88e1518[] = {
{ MIICMD_SET, 22, 0x0001 },
{ MIICMD_MODIFY, 0, 0x0000, 0x1000 },
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
{ MIICMD_SET, 22, 0x0000 },
};
/*
* invert LED2 polarity
*/
struct mii_setupcmd invert_led2_88e1514[] = {
{ MIICMD_SET, 22, 0x0003 },
{ MIICMD_MODIFY, 17, 0x0030, 0x0010 },
{ MIICMD_SET, 22, 0x0000 },
};
static int process_setupcmd(const char *bus, unsigned char addr,
struct mii_setupcmd *setupcmd)
{
int res;
u8 reg = setupcmd->reg;
u16 data = setupcmd->data;
u16 mask = setupcmd->mask;
u32 timeout = setupcmd->timeout;
u16 orig_data;
unsigned long start;
debug("mii %s:%u reg %2u ", bus, addr, reg);
switch (setupcmd->token) {
case MIICMD_MODIFY:
res = miiphy_read(bus, addr, reg, &orig_data);
if (res)
break;
debug("is %04x. (value %04x mask %04x) ", orig_data, data,
mask);
data = (orig_data & ~mask) | (data & mask);
/* fallthrough */
case MIICMD_SET:
debug("=> %04x\n", data);
res = miiphy_write(bus, addr, reg, data);
break;
case MIICMD_VERIFY_VALUE:
res = miiphy_read(bus, addr, reg, &orig_data);
if (res)
break;
if ((orig_data & mask) != (data & mask))
res = -1;
debug("(value %04x mask %04x) == %04x? %s\n", data, mask,
orig_data, res ? "FAIL" : "PASS");
break;
case MIICMD_WAIT_FOR_VALUE:
res = -1;
start = get_timer(0);
while ((res != 0) && (get_timer(start) < timeout)) {
res = miiphy_read(bus, addr, reg, &orig_data);
if (res)
continue;
if ((orig_data & mask) != (data & mask))
res = -1;
}
debug("(value %04x mask %04x) == %04x? %s after %lu ms\n", data,
mask, orig_data, res ? "FAIL" : "PASS",
get_timer(start));
break;
default:
res = -1;
break;
}
return res;
}
static int process_setup(const char *bus, unsigned char addr,
struct mii_setupcmd *setupcmd, unsigned int count)
{
int res = 0;
unsigned int k;
for (k = 0; k < count; ++k) {
res = process_setupcmd(bus, addr, &setupcmd[k]);
if (res) {
printf("mii cmd %u on bus %s addr %u failed, aborting setup\n",
setupcmd[k].token, bus, addr);
break;
}
}
return res;
}
int setup_88e1518(const char *bus, unsigned char addr)
{
int res;
res = process_setup(bus, addr,
verify_88e1518, ARRAY_SIZE(verify_88e1518));
if (res)
return res;
res = process_setup(bus, addr,
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
if (res)
return res;
res = process_setup(bus, addr,
default_88e1518, ARRAY_SIZE(default_88e1518));
if (res)
return res;
if (addr) {
res = process_setup(bus, addr,
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
if (res)
return res;
}
res = process_setup(bus, addr,
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
if (res)
return res;
return 0;
}
int setup_88e1514(const char *bus, unsigned char addr)
{
int res;
res = process_setup(bus, addr,
verify_88e1518, ARRAY_SIZE(verify_88e1518));
if (res)
return res;
res = process_setup(bus, addr,
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
if (res)
return res;
res = process_setup(bus, addr,
mii_to_copper_88e1514,
ARRAY_SIZE(mii_to_copper_88e1514));
if (res)
return res;
res = process_setup(bus, addr,
sgmii_autoneg_off_88e1518,
ARRAY_SIZE(sgmii_autoneg_off_88e1518));
if (res)
return res;
res = process_setup(bus, addr,
invert_led2_88e1514,
ARRAY_SIZE(invert_led2_88e1514));
if (res)
return res;
res = process_setup(bus, addr,
default_88e1518, ARRAY_SIZE(default_88e1518));
if (res)
return res;
if (addr) {
res = process_setup(bus, addr,
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
if (res)
return res;
}
res = process_setup(bus, addr,
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
if (res)
return res;
return 0;
}
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2014
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef _PHY_H_
#define _PHY_H_
int setup_88e1514(const char *bus, unsigned char addr);
int setup_88e1518(const char *bus, unsigned char addr);
#endif