GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user