mc_tcu3: Switch to hwilib instead of own hwinfo implementation

Use hwilib in vendorcode/siemens/hwilib to get fields from hwinfo
instead of having mainboard specific hwinfo code.
This patch does not change the functional behavior in any way.

Change-Id: Idb226a82a08b1b753f654c5cde106236e72f33c3
Signed-off-by: Werner Zeh <werner.zeh@siemens.com>
Reviewed-on: https://review.coreboot.org/14506
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Werner Zeh 2016-04-25 12:24:17 +02:00
parent 223498fa16
commit bf13d3f567
9 changed files with 120 additions and 377 deletions

View File

@ -30,6 +30,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select USE_BLOBS
select CBFS_AUTOGEN_ATTRIBUTES
select FSP_BAYTRAIL_GFX_INIT
select USE_SIEMENS_HWILIB
config MAINBOARD_DIR
string

View File

@ -13,11 +13,8 @@
## GNU General Public License for more details.
##
romstage-y += modhwinfo.c
ramstage-y += gpio.c
ramstage-y += irqroute.c
ramstage-y += modhwinfo.c
ramstage-y += lcd_panel.c
ramstage-y += ptn3460.c

View File

@ -15,11 +15,11 @@
#include <cbfs.h>
#include <console/console.h>
#include <string.h>
#include "modhwinfo.h"
#include "soc/gpio.h"
#include "lcd_panel.h"
#include "ptn3460.h"
/** \brief Reads GPIOs used for LCD panel encoding and returns the 4 bit value
* @param no parameters
* @return LCD panel type encoded in 4 bits
@ -42,10 +42,8 @@ u8 get_lcd_panel_type(void)
*/
int setup_lcd_panel(void)
{
u8 lcd_type;
u8 lcd_type;
int status;
struct edidinfo *eib = NULL;
struct shortinfo *sib = NULL;
char blockname[33];
lcd_type = get_lcd_panel_type();
@ -71,20 +69,12 @@ int setup_lcd_panel(void)
status = 1;
break;
}
/* Now that we have the panel type, get the matching block and setup */
/* the DP2LVDS converter accordingly */
eib = get_edidinfo(blockname);
sib = get_shortinfo(blockname);
if ((!eib) || (!sib)) {
printk(BIOS_ERR, "LCD: Info block named \"%s\" not found!\n", blockname);
status = 1;
} else {
printk(BIOS_INFO, "LCD: Found SIB at 0x%x, EIB at 0x%x\n",
(int)sib, (int)eib);
status = ptn3460_init(lcd_type, eib, sib);
/* Now that we have the panel type, setup the DP2LVDS converter */
status = ptn3460_init(blockname);
if (status)
printk(BIOS_ERR, "LCD: Setup PTN with status 0x%x\n", status);
else
printk(BIOS_INFO, "LCD: Setup PTN with status 0x%x\n", status);
}
return status;
}

View File

@ -29,9 +29,47 @@
#include <arch/io.h>
#include <arch/interrupt.h>
#include <boot/coreboot_tables.h>
#include <hwilib.h>
#include "lcd_panel.h"
/** \brief This function will search for a MAC address which can be assigned
* to a MACPHY.
* @param pci_bdf Bus, device and function of the given PCI-device
* @param mac buffer where to store the MAC address
* @return cb_err CB_ERR or CB_SUCCESS
*/
enum cb_err mainboard_get_mac_address(u16 bus, u8 devfn, u8 mac[6])
{
uint8_t mac_adr[6];
u32 i;
/* Open main hwinfo block */
if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
return CB_ERR;
/* Get first MAC address from hwinfo. */
if (hwilib_get_field(Mac1, mac_adr, sizeof(mac_adr)) != sizeof(mac_adr))
return CB_ERR;
/* Ensure the first MAC-Address is not completely 0x00 or 0xff */
for (i = 0; i < 6; i++) {
if (mac_adr[i] != 0xFF)
break;
}
if (i == 6){
return CB_ERR;
}
for (i = 0; i < 6; i++) {
if (mac_adr[i] != 0x00)
break;
}
if (i == 6){
return CB_ERR;
} else {
memcpy(mac, mac_adr, 6);
return CB_SUCCESS;
}
}
/*
* mainboard_enable is executed as first thing after enumerate_buses().
* This is the earliest point to add customization.

View File

@ -1,144 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Siemens AG.
*
* 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; version 2 of the License.
*
* 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.
*/
#include "modhwinfo.h"
#include "lcd_panel.h"
#include <cbfs.h>
#include <string.h>
/** \brief This function will find the first linked info block.
* @param *filename Filename in cbfs
* @param *file_offset Pointer to the offset of the cbfs file contents
* @return u8* Pointer to the found block
*/
u8* get_first_linked_block(char *filename, u8 **file_offset)
{
u8* block_ptr = NULL;
block_ptr = cbfs_boot_map_with_leak(filename, 0x50, NULL);
if (!block_ptr)
return NULL;
if (!strncmp((char*)block_ptr, "H1W2M3I4", LEN_MAGIC_NUM)) {
if ((*((u16*)(block_ptr + HWI_LEN_OFFSET)) == LEN_MAIN_HWINFO) &&
(*((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) != 0x00)) {
*file_offset = block_ptr;
return *((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) + block_ptr;
} else
return NULL;
} else if (!strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)) {
*file_offset = block_ptr;
return block_ptr;
} else
return NULL;
}
/** \brief This function will find the main info block
* @param *filename Filename in cbfs
* @return *hwinfo Pointer to the data of the main info block
*/
struct hwinfo* get_hwinfo(char *filename)
{
struct hwinfo* main_hwinfo;
main_hwinfo = cbfs_boot_map_with_leak(filename, 0x50, NULL);
if ((main_hwinfo) &&
(!strncmp(main_hwinfo->magicNumber, "H1W2M3I4", LEN_MAGIC_NUM)) &&
(main_hwinfo->length == LEN_MAIN_HWINFO))
return main_hwinfo;
else
return NULL;
}
/** \brief This function will find the short info block
* @param *filename Filename in cbfs
* @return *shortinfo Pointer to the data of the short info block
*/
struct shortinfo* get_shortinfo(char *filename)
{
u8 *block_ptr = NULL;
u8 *file_offset = NULL;
block_ptr = get_first_linked_block(filename, &file_offset);
if ((block_ptr == NULL) ||
(strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)))
return NULL;
if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO)
return (struct shortinfo *)block_ptr;
block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_EDID)));
if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO)
return (struct shortinfo *)block_ptr;
else
return NULL;
}
/** \brief This function will find the edid info block
* @param *filename Filename in cbfs
* @return *edidinfo Pointer to the data of the edid info block
*/
struct edidinfo* get_edidinfo(char *filename)
{
u8 *block_ptr = NULL;
u8 *file_offset = NULL;
block_ptr = get_first_linked_block(filename, &file_offset);
if ((block_ptr == NULL) ||
(strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)))
return NULL;
if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO)
return (struct edidinfo *)block_ptr;
block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_SIB)));
if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO)
return (struct edidinfo *)block_ptr;
else
return NULL;
}
/** \brief This function will search for a MAC address which can be assigned
* to a MACPHY.
* @param pci_bdf Bus, device and function of the given PCI-device
* @param mac buffer where to store the MAC address
* @return cb_err CB_ERR or CB_SUCCESS
*/
enum cb_err mainboard_get_mac_address(u16 bus, u8 devfn, u8 mac[6])
{
struct hwinfo* main_hwinfo;
u32 i;
main_hwinfo = get_hwinfo((char*)"hwinfo.hex");
if (!main_hwinfo)
return CB_ERR;
/* Ensure the first MAC-Address is not completely 0x00 or 0xff */
for (i = 0; i < 6; i++) {
if (main_hwinfo->macAddress1[i] != 0xFF)
break;
}
if (i == 6){
return CB_ERR;
}
for (i = 0; i < 6; i++) {
if (main_hwinfo->macAddress1[i] != 0x00)
break;
}
if (i == 6){
return CB_ERR;
} else {
memcpy(mac, main_hwinfo->macAddress1, 6);
return CB_SUCCESS;
}
}

View File

@ -1,166 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Siemens AG
*
* 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; version 2 of the License.
*
* 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.
*/
#ifndef _MODHWINFO_H_
#define _MODHWINFO_H_
#include <types.h>
#define LEN_MAGIC_NUM 8
#define LEN_MLFB 20
#define LEN_SERIAL_NUM 16
#define LEN_HW_REVISION 2
#define LEN_MAC_ADDRESS 6
#define LEN_SPD 128
#define NUMBER_OF_MAC_ADDR 4
#define LEN_EDID 128
#define LEN_MAIN_HWINFO 509
#define LEN_SHORT_INFO 289
#define LEN_EDID_INFO 181
#define NEXT_OFFSET_HWINFO 476
#define NEXT_OFFSET_SIB 260
#define NEXT_OFFSET_EDID 176
#define HWI_LEN_OFFSET 12
/* Define some masks and values */
#define SIB_HWINIT_IDX 0x0e
#define SIB_COLOR_6BIT 0x00
#define SIB_COLOR_8BIT 0x01
#define SIB_COLOR_10BIT 0x02
#define SIB_DISP_CON_IDX 0x16
#define SIB_LVDS_SINGLE_LANE 0x00
#define SIB_LVDS_DUAL_LANE 0x05
struct PhysDevStruc {
u8 bustype;
u8 devfn;
u16 bus;
} __attribute__ ((packed));
struct hwinfo {
// Offset 0x0
char magicNumber[LEN_MAGIC_NUM];
// Offset 0x08
u8 versionID[4];
// Offset 0x0c
u16 length;
// Offset 0x0e
char BGR_Name[128];
//Offset 0x8e
char MLFB[LEN_MLFB];
// Offset 0xa2
u8 uniqueNumber[16];
// Offset 0xb2
u8 fill_1[12];
// Offset 0xbe
u8 hwRevision[LEN_HW_REVISION];
//Offset 0xc0
u8 macAddress1[LEN_MAC_ADDRESS];
u8 numOfAuxMacAddr1;
u8 fill_2;
//Offset 0xc8
u8 macAddress2[LEN_MAC_ADDRESS];
u8 numOfAuxMacAddr2;
u8 fill_3;
//Offset 0xd0
u8 macAddress3[LEN_MAC_ADDRESS];
u8 numOfAuxMacAddr3;
u8 fill_4;
//Offset 0xd8
u8 macAddress4[LEN_MAC_ADDRESS];
u8 numOfAuxMacAddr4;
u8 fill_5;
// Offset 0xe0
u8 SPD[LEN_SPD];
// Offset 0x160
u8 fill_6[88];
// Offset 0x1b8
u32 featureFlags;
// Offset 0x1bc
u8 fill_7[4];
// Offset 0x1c0
u32 biosFlags;
// Offset 0x1c4
u8 fill_8[8];
//Offset 0x1cc
struct PhysDevStruc etherDev[NUMBER_OF_MAC_ADDR];
// Offset 0x1dc
s32 nextInfoOffset;
// Offset 0x1e0
u8 fill_9[4];
// Offset 0x1e4
u32 portRTC;
// Offset 0x1e8
u8 typeRTC;
// Offset 0x1e9
u8 fill_10[20];
} __attribute__ ((packed));
struct shortinfo {
// Offset 0x0
char magicNumber[LEN_MAGIC_NUM];
// Offset 0x08
u8 versionID[4];
// Offset 0x0c
u16 length;
// Offset 0x0e
char BGR_Name[128];
//Offset 0x8e
char MLFB[LEN_MLFB];
// Offset 0xa2
u8 uniqueNumber[26];
// Offset 0xbc
u8 fill_1[12];
//Offset 0xc8
u8 hwRevision[2];
// Offset 0xca
u8 fill_2[18];
// Offset 0xdc
u8 panelFeatures[32];
// Offset 0xfc
u8 fill_3[8];
// Offset 0x104
s32 nextInfoOffset;
// Offset 0x108
u8 fill_4[25];
} __attribute__ ((packed));
struct edidinfo {
// Offset 0x0
char magicNumber[LEN_MAGIC_NUM];
// Offset 0x08
u8 versionID[4];
// Offset 0x0c
u16 length;
// Offset 0x0e
u8 fill_1[2];
// Offset 0x10
u8 edid[LEN_EDID];
// Offset 0x90
u8 fill_2[32];
// Offset 0xb0
s32 nextInfoOffset;
// Offset 0xb4
u8 fill_3;
} __attribute__ ((packed));
u8* get_first_linked_block(char *filename, u8 **starting_adr);
struct hwinfo* get_hwinfo(char *filename);
struct shortinfo* get_shortinfo(char *filename);
struct edidinfo* get_edidinfo(char *filename);
enum cb_err mainboard_get_mac_address(u16 bus, u8 devfn, u8 mac[6]);
#endif /* _MODHWINFO_H_ */

View File

@ -14,33 +14,52 @@
*/
#include <console/console.h>
#include <hwilib.h>
#include "soc/i2c.h"
#include "ptn3460.h"
/** \brief This functions sets up the DP2LVDS-converter to be used with the
* appropriate lcd panel
* @param lcd_type Type of LCD we should set up the converter for
* @param *sib Pointer to short info block structure
* @param *eib Pointer to EDID info block structure
* @return 0 on success or error code
* @param *hwi_block Filename in CBFS of the block to use as HW-Info
* @return 0 on success or error code
*/
int ptn3460_init(char lcd_type, struct edidinfo *eib, struct shortinfo *sib)
int ptn3460_init(char *hwi_block)
{
struct ptn_3460_config cfg;
int status;
uint8_t disp_con = 0, color_depth = 0;
uint8_t edid_data[0x80];
if (!hwi_block || hwilib_find_blocks(hwi_block) != CB_SUCCESS) {
printk(BIOS_ERR, "LCD: Info block \"%s\" not found!\n",
hwi_block);
return 1;
}
status = i2c_init(PTN_I2C_CONTROLER);
if (status)
return (PTN_BUS_ERROR | status);
/* If we are here, we have all the desired information for setting up */
/* DP2LVDS converter. In addition, the information matches the connected */
/* LCD-panel and therefore, we do not have to distinguish between */
/* different panels here for the timing. Inside the converter, table 6 */
/* will be used for the timings. */
status = ptn3460_write_edid(6, eib->edid);
if (status)
/* Get all needed information from hwinfo block */
if (hwilib_get_field(Edid, edid_data, 0x80) != sizeof(edid_data)) {
printk(BIOS_ERR, "LCD: No EDID data available in %s\n",
hwi_block);
return 1;
}
if ((hwilib_get_field(PF_DisplCon, &disp_con, 1) != 1)) {
printk(BIOS_ERR, "LCD: Missing panel features from %s\n",
hwi_block);
return 1;
}
if (hwilib_get_field(PF_Color_Depth ,&color_depth, 1) != 1) {
printk(BIOS_ERR, "LCD: Missing panel features from %s\n",
hwi_block);
return 1;
}
/* Here, all the desired information for setting up DP2LVDS converter*/
/* are present. Inside the converter, table 6 will be used for */
/* the timings. */
if ((status = ptn3460_write_edid(6, edid_data)) != 0)
return status;
/* Select this table to be emulated */
ptn_select_edid(6);
@ -50,12 +69,12 @@ int ptn3460_init(char lcd_type, struct edidinfo *eib, struct shortinfo *sib)
if (status)
return (PTN_BUS_ERROR | status);
/* Set up configuration data according to the information blocks we get */
/* Set up configuration data according to the hwinfo blocks we get */
cfg.dp_interface_ctrl = 0;
cfg.lvds_interface_ctrl1 = 0x00;
if (sib->panelFeatures[SIB_DISP_CON_IDX] == SIB_LVDS_DUAL_LANE)
if (disp_con == PF_DISPLCON_LVDS_DUAL)
cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */
if ((sib->panelFeatures[SIB_HWINIT_IDX] & 0x03) == SIB_COLOR_6BIT)
if (color_depth == PF_COLOR_DEPTH_6BIT)
cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */
cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */

View File

@ -17,7 +17,6 @@
#define PTN3460_H_
#include <delay.h>
#include "modhwinfo.h"
#include "lcd_panel.h"
#define PTN_SLAVE_ADR 0x20
@ -66,7 +65,7 @@ struct ptn_3460_flash{
}__attribute__((packed));
int ptn3460_init(char lcd_type, struct edidinfo *eib, struct shortinfo *sib);
int ptn3460_init(char *hwi_block);
int ptn3460_read_edid(u8 edid_num, u8 *data);
int ptn3460_write_edid(u8 edid_num, u8 *data);
int ptn_select_edid(u8 edid_num);

View File

@ -33,7 +33,7 @@
#include <soc/acpi.h>
#include <soc/baytrail.h>
#include <drivers/intel/fsp1_0/fsp_util.h>
#include "modhwinfo.h"
#include <hwilib.h>
/**
* /brief mainboard call for setup that needs to be done before fsp init
@ -166,35 +166,44 @@ const PCH_AZALIA_CONFIG mainboard_AzaliaConfig = {
*/
void romstage_fsp_rt_buffer_callback(FSP_INIT_RT_BUFFER *FspRtBuffer)
{
struct hwinfo *hwi_main;
uint8_t spd[0x80];
UPD_DATA_REGION *UpdData = FspRtBuffer->Common.UpdDataRgnPtr;
/* Initialize the Azalia Verb Tables to mainboard specific version */
/* Initialize the Azalia Verb Tables to mainboard specific version. */
UpdData->AzaliaConfigPtr = (UINT32)&mainboard_AzaliaConfig;
/* Get SPD data from hardware information block and setup memory down */
/* parameters for FSP accordingly */
hwi_main = get_hwinfo((char*)"hwinfo.hex");
if (hwi_main) {
UpdData->PcdMemoryParameters.EnableMemoryDown = 1;
UpdData->PcdMemoryParameters.DRAMType = hwi_main->SPD[2];
UpdData->PcdMemoryParameters.DIMM0Enable = hwi_main->SPD[3] & 0x01;
UpdData->PcdMemoryParameters.DIMM1Enable = (hwi_main->SPD[3] >> 1) & 0x01;
UpdData->PcdMemoryParameters.DIMMDensity = hwi_main->SPD[4];
UpdData->PcdMemoryParameters.DIMMDWidth = hwi_main->SPD[5];
UpdData->PcdMemoryParameters.DIMMSides = hwi_main->SPD[7];
UpdData->PcdMemoryParameters.DIMMBusWidth = hwi_main->SPD[8];
UpdData->PcdMemoryParameters.DRAMSpeed = hwi_main->SPD[12];
UpdData->PcdMemoryParameters.DIMMtCL = hwi_main->SPD[14];
UpdData->PcdMemoryParameters.DIMMtWR = hwi_main->SPD[17];
UpdData->PcdMemoryParameters.DIMMtRPtRCD = hwi_main->SPD[18];
UpdData->PcdMemoryParameters.DIMMtRRD = hwi_main->SPD[19];
UpdData->PcdMemoryParameters.DIMMtWTR = hwi_main->SPD[26];
UpdData->PcdMemoryParameters.DIMMtRTP = hwi_main->SPD[27];
UpdData->PcdMemoryParameters.DIMMtFAW = hwi_main->SPD[28];
/*If one need output from MRC to be used in Intel RMT, simply */
/*enable the following line */
//UpdData->PcdMrcDebugMsg = 1;
} else
printk(BIOS_ERR, "HWInfo not found, leave default timings for DDR3.\n");
/* Get SPD data from hwinfo block and set up memory down */
/* parameters for FSP accordingly. */
if (hwilib_find_blocks("hwinfo.hex")) {
printk(BIOS_ERR,
"HWInfo not found, use default timings for DDR3.\n");
return;
}
if (hwilib_get_field(SPD, spd, sizeof(spd)) != sizeof(spd)) {
printk(BIOS_ERR,
"SPD not found in HWInfo, use defaults for DDR3.\n");
return;
}
/*Set up DDR timings from HWInfo. */
UpdData->PcdMemoryParameters.EnableMemoryDown = 1;
UpdData->PcdMemoryParameters.DRAMType = spd[2];
UpdData->PcdMemoryParameters.DIMM0Enable = spd[3] & 0x01;
UpdData->PcdMemoryParameters.DIMM1Enable = (spd[3] >> 1) & 0x01;
UpdData->PcdMemoryParameters.DIMMDensity = spd[4];
UpdData->PcdMemoryParameters.DIMMDWidth = spd[5];
UpdData->PcdMemoryParameters.DIMMSides = spd[7];
UpdData->PcdMemoryParameters.DIMMBusWidth = spd[8];
UpdData->PcdMemoryParameters.DRAMSpeed = spd[12];
UpdData->PcdMemoryParameters.DIMMtCL = spd[14];
UpdData->PcdMemoryParameters.DIMMtWR = spd[17];
UpdData->PcdMemoryParameters.DIMMtRPtRCD = spd[18];
UpdData->PcdMemoryParameters.DIMMtRRD = spd[19];
UpdData->PcdMemoryParameters.DIMMtWTR = spd[26];
UpdData->PcdMemoryParameters.DIMMtRTP = spd[27];
UpdData->PcdMemoryParameters.DIMMtFAW = spd[28];
/*If one need output from MRC to be used in Intel RMT, simply */
/*enable the following line */
//UpdData->PcdMrcDebugMsg = 1;
}