Skip to content

Commit

Permalink
soc/intel/fsp_baytrail: use designware I2C driver
Browse files Browse the repository at this point in the history
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C
bus device structure. The internal I2C controllers are now handled by
the generic PCI driver approach and generic I2C access is enabled.
As orientation for the I2C code the actual solution from
soc/intel/apollolake I2C was taken. All the I2C specific parts were
removed from lpss.c and have been implemented in the I2C driver.
Future merge to soc/intel/common/block/i2c/i2c.c would be possible.

With this patch I2C chip devices can now be used in devicetree.

TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.

Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60
Signed-off-by: Uwe Poeche <uwe.poeche@siemens.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36062
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
  • Loading branch information
UwePoeche authored and pgeorgi committed Oct 24, 2019
1 parent 285975d commit ed309e5
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 416 deletions.
6 changes: 6 additions & 0 deletions src/mainboard/siemens/mc_tcu3/mainboard.c
Expand Up @@ -69,10 +69,16 @@ enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
* This is the earliest point to add customization.
*/
static void mainboard_enable(struct device *dev)
{

}

static void mainboard_final(void *chip_info)
{
setup_lcd_panel();
}

struct chip_operations mainboard_ops = {
.enable_dev = mainboard_enable,
.final = mainboard_final,
};
79 changes: 41 additions & 38 deletions src/mainboard/siemens/mc_tcu3/ptn3460.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Siemens AG
* Copyright (C) 2014-2019 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
Expand All @@ -18,7 +18,7 @@
#include <string.h>
#include <delay.h>
#include <types.h>

#include <device/i2c_simple.h>
#include "soc/i2c.h"
#include "ptn3460.h"

Expand All @@ -34,17 +34,14 @@ int ptn3460_init(char *hwi_block)
uint8_t disp_con = 0, color_depth = 0;
uint8_t edid_data[0x80];
uint8_t hwid[4], tcu31_hwid[4] = {7, 9, 2, 0};
uint8_t i;

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_CONTROLLER);
if (status)
return (PTN_BUS_ERROR | 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",
Expand All @@ -69,8 +66,8 @@ int ptn3460_init(char *hwi_block)
/* Select this table to be emulated */
ptn_select_edid(6);
/* Read PTN configuration data */
status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
(u8*)&cfg, PTN_CONFIG_LEN);
status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, (u8 *) &cfg,
sizeof(struct ptn_3460_config));
if (status)
return (PTN_BUS_ERROR | status);

Expand All @@ -81,28 +78,29 @@ int ptn3460_init(char *hwi_block)
cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */
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 */
/* Swap LVDS even and odd lanes for HW-ID 7.9.2.0 only. */
if (hwilib_get_field(HWID, hwid, sizeof(hwid)) == sizeof(hwid) &&
!(memcmp(hwid, tcu31_hwid, sizeof(hwid)))) {
cfg.lvds_interface_ctrl3 = 0x01; /* swap LVDS even and odd */
} else
cfg.lvds_interface_ctrl3 = 0x00; /* no LVDS signal swap */
cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */
cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */
cfg.t12_timing = 20; /* 1 second re-power delay */
cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */
cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */
cfg.backlight_ctrl = 0; /* Enable backlight control */
cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */
cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */
cfg.t12_timing = 20; /* 1 second re-power delay */
cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */
cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */
cfg.backlight_ctrl = 0; /* Enable backlight control */

/* Write back configuration data to PTN3460 */
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
(u8*)&cfg, PTN_CONFIG_LEN);
if (status)
return (PTN_BUS_ERROR | status);
else
return PTN_NO_ERROR;
for (i = 0; i < sizeof(struct ptn_3460_config); i++) {
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + i,
*(((uint8_t *) &cfg) + i));
if (status)
return (PTN_BUS_ERROR | status);
}

return PTN_NO_ERROR;
}

/** \brief This functions reads one desired EDID data structure from PTN3460
Expand All @@ -117,14 +115,13 @@ int ptn3460_read_edid(u8 edid_num, u8 *data)
if (edid_num > PTN_MAX_EDID_NUM)
return PTN_INVALID_EDID;
/* First enable access to the desired EDID table */
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
&edid_num, 1);
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num);
if (status)
return (PTN_BUS_ERROR | status);

/* Now we can simply read back EDID-data */
status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
data, PTN_EDID_LEN);
status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, data,
PTN_EDID_LEN);
if (status)
return (PTN_BUS_ERROR | status);
else
Expand All @@ -139,22 +136,24 @@ int ptn3460_read_edid(u8 edid_num, u8 *data)
int ptn3460_write_edid(u8 edid_num, u8 *data)
{
int status;
int i;

if (edid_num > PTN_MAX_EDID_NUM)
return PTN_INVALID_EDID;

/* First enable access to the desired EDID table */
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
&edid_num, 1);
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num);
if (status)
return (PTN_BUS_ERROR | status);

/* Now we can simply write EDID-data to ptn3460 */
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
data, PTN_EDID_LEN);
if (status)
return (PTN_BUS_ERROR | status);
else
return PTN_NO_ERROR;
for (i = 0; i < PTN_EDID_LEN; i++) {
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF + i,
data[i]);
if (status)
return (PTN_BUS_ERROR | status);
}
return PTN_NO_ERROR;
}

/** \brief This functions selects one of 7 EDID-tables inside PTN3460
Expand All @@ -171,8 +170,7 @@ int ptn_select_edid (u8 edid_num)
return PTN_INVALID_EDID;
/* Enable emulation of the desired EDID table */
val = (edid_num << 1) | 1;
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4,
&val, 1);
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4, val);
if (status)
return (PTN_BUS_ERROR | status);
else
Expand All @@ -188,14 +186,19 @@ int ptn_select_edid (u8 edid_num)
*/
int ptn3460_flash_config(void)
{
int status;
int status, i;
struct ptn_3460_flash flash;

flash.cmd = 0x01; /* perform erase and flash cycle */
flash.magic = 0x7845; /* Magic number to protect flash operation */
flash.trigger = 0x56; /* This value starts flash operation */
status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF,
(u8*)&flash, PTN_FLASH_CFG_LEN);

for (i = 0; i < sizeof(struct ptn_3460_flash); i++) {
status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF+i,
*(((uint8_t *) &flash) + i));
if (status)
return (PTN_BUS_ERROR | status);
}
if (status) {
return (PTN_BUS_ERROR | status);
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/soc/intel/fsp_baytrail/Kconfig
Expand Up @@ -44,6 +44,7 @@ config CPU_SPECIFIC_OPTIONS
select MICROCODE_BLOB_NOT_HOOKED_UP
select INTEL_DESCRIPTOR_MODE_CAPABLE
select HAVE_SPI_CONSOLE_SUPPORT
select DRIVERS_I2C_DESIGNWARE

# Microcode header files are delivered in FSP package
select USES_MICROCODE_HEADER_FILES if HAVE_FSP_BIN
Expand Down Expand Up @@ -103,6 +104,14 @@ config CPU_MICROCODE_HEADER_FILES
string
default "../intel/cpu/baytrail/microcode/M0130673322.h ../intel/cpu/baytrail/microcode/M0130679901.h ../intel/cpu/baytrail/microcode/M0230672228.h"

config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ
int
default 133

config SOC_INTEL_I2C_DEV_MAX
int
default 7

## Baytrail Specific FSP Kconfig
source src/soc/intel/fsp_baytrail/fsp/Kconfig

Expand Down
3 changes: 2 additions & 1 deletion src/soc/intel/fsp_baytrail/Makefile.inc
Expand Up @@ -3,7 +3,7 @@
#
# Copyright (C) 2010 Google Inc.
# Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
# Copyright (C) 2016 Siemens AG
# Copyright (C) 2016-2019 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
Expand Down Expand Up @@ -34,6 +34,7 @@ romstage-y += memmap.c
romstage-y += pmutil.c
romstage-y += spi.c
romstage-y += tsc_freq.c
romstage-y += i2c.c

postcar-y += tsc_freq.c

Expand Down
4 changes: 4 additions & 0 deletions src/soc/intel/fsp_baytrail/chip.h
Expand Up @@ -20,6 +20,7 @@

#include <arch/acpi.h>
#include <drivers/intel/fsp1_0/fsp_values.h>
#include <drivers/i2c/designware/dw_i2c.h>

/* The devicetree parser expects chip.h to reside directly in the path
* specified by the devicetree. */
Expand Down Expand Up @@ -346,6 +347,9 @@ struct soc_intel_fsp_baytrail_config {
int lpe_codec_clk_freq; /* 19 or 25 are valid. */
int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */

/* Structure for designware I2C controller */
struct dw_i2c_bus_config i2c[CONFIG_SOC_INTEL_I2C_DEV_MAX];

/* ***** ACPI configuration ***** */
/* Options for these are in src/arch/x86/include/arch/acpi.h */
uint8_t fadt_pm_profile;
Expand Down

0 comments on commit ed309e5

Please sign in to comment.