diff options
19 files changed, 248 insertions, 226 deletions
diff --git a/src/drivers/i2c/designware/Kconfig b/src/drivers/i2c/designware/Kconfig new file mode 100644 index 0000000000..e4b7777daf --- /dev/null +++ b/src/drivers/i2c/designware/Kconfig @@ -0,0 +1,15 @@ +config DRIVERS_I2C_DESIGNWARE + bool + help + Designware I2C support + +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + depends on DRIVERS_I2C_DESIGNWARE + help + The i2c ip block's clock. + +config DRIVERS_I2C_DESIGNWARE_DEBUG + bool + default n + depends on DRIVERS_I2C_DESIGNWARE diff --git a/src/drivers/i2c/designware/Makefile.inc b/src/drivers/i2c/designware/Makefile.inc new file mode 100644 index 0000000000..0e92f05cd2 --- /dev/null +++ b/src/drivers/i2c/designware/Makefile.inc @@ -0,0 +1,8 @@ +ifeq ($(CONFIG_DRIVERS_I2C_DESIGNWARE),y) + +bootblock-y += dw_i2c.c +romstage-y += dw_i2c.c +verstage-y += dw_i2c.c +ramstage-y += dw_i2c.c + +endif diff --git a/src/soc/intel/common/block/i2c/lpss_i2c.c b/src/drivers/i2c/designware/dw_i2c.c index 9ae7831524..75f8871d56 100644 --- a/src/soc/intel/common/block/i2c/lpss_i2c.c +++ b/src/drivers/i2c/designware/dw_i2c.c @@ -2,7 +2,8 @@ * This file is part of the coreboot project. * * Copyright 2009 Vipin Kumar, ST Microelectronics - * Copyright 2016 Google Inc. + * Copyright 2017 Google Inc. + * Copyright 2017 Intel Corporation. * * 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 @@ -22,13 +23,12 @@ #include <device/pci.h> #include <device/pci_def.h> #include <device/pci_ids.h> -#include <intelblocks/lpss_i2c.h> #include <string.h> #include <timer.h> -#include "lpss_i2c.h" +#include "dw_i2c.h" /* Use a ~10ms timeout for various operations */ -#define LPSS_I2C_TIMEOUT_US 10000 +#define DW_I2C_TIMEOUT_US 10000 /* High and low times in different speed modes (in ns) */ enum { @@ -106,6 +106,56 @@ enum { INTR_STAT_GEN_CALL = (1 << 11), }; +/* I2C Controller MMIO register space */ +struct dw_i2c_regs { + uint32_t control; + uint32_t target_addr; + uint32_t slave_addr; + uint32_t master_addr; + uint32_t cmd_data; + uint32_t ss_scl_hcnt; + uint32_t ss_scl_lcnt; + uint32_t fs_scl_hcnt; + uint32_t fs_scl_lcnt; + uint32_t hs_scl_hcnt; + uint32_t hs_scl_lcnt; + uint32_t intr_stat; + uint32_t intr_mask; + uint32_t raw_intr_stat; + uint32_t rx_thresh; + uint32_t tx_thresh; + uint32_t clear_intr; + uint32_t clear_rx_under_intr; + uint32_t clear_rx_over_intr; + uint32_t clear_tx_over_intr; + uint32_t clear_rd_req_intr; + uint32_t clear_tx_abrt_intr; + uint32_t clear_rx_done_intr; + uint32_t clear_activity_intr; + uint32_t clear_stop_det_intr; + uint32_t clear_start_det_intr; + uint32_t clear_gen_call_intr; + uint32_t enable; + uint32_t status; + uint32_t tx_level; + uint32_t rx_level; + uint32_t sda_hold; + uint32_t tx_abort_source; + uint32_t slv_data_nak_only; + uint32_t dma_cr; + uint32_t dma_tdlr; + uint32_t dma_rdlr; + uint32_t sda_setup; + uint32_t ack_general_call; + uint32_t enable_status; + uint32_t fs_spklen; + uint32_t hs_spklen; + uint32_t clr_restart_det; + uint32_t comp_param1; + uint32_t comp_version; + uint32_t comp_type; +} __packed; + static const struct i2c_descriptor { enum i2c_speed speed; struct freq freq; @@ -204,7 +254,7 @@ static int counts_from_freq(const struct freq *fast, const struct freq *slow) } /* Enable this I2C controller */ -static void lpss_i2c_enable(struct lpss_i2c_regs *regs) +static void dw_i2c_enable(struct dw_i2c_regs *regs) { uint32_t enable = read32(®s->enable); @@ -213,7 +263,7 @@ static void lpss_i2c_enable(struct lpss_i2c_regs *regs) } /* Disable this I2C controller */ -static int lpss_i2c_disable(struct lpss_i2c_regs *regs) +static int dw_i2c_disable(struct dw_i2c_regs *regs) { uint32_t enable = read32(®s->enable); @@ -223,7 +273,7 @@ static int lpss_i2c_disable(struct lpss_i2c_regs *regs) write32(®s->enable, enable & ~ENABLE_CONTROLLER); /* Wait for enable bit to clear */ - stopwatch_init_usecs_expire(&sw, LPSS_I2C_TIMEOUT_US); + stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US); while (read32(®s->enable_status) & ENABLE_CONTROLLER) if (stopwatch_expired(&sw)) return -1; @@ -233,12 +283,12 @@ static int lpss_i2c_disable(struct lpss_i2c_regs *regs) } /* Wait for this I2C controller to go idle for transmit */ -static int lpss_i2c_wait_for_bus_idle(struct lpss_i2c_regs *regs) +static int dw_i2c_wait_for_bus_idle(struct dw_i2c_regs *regs) { struct stopwatch sw; /* Start timeout for up to 16 bytes in FIFO */ - stopwatch_init_usecs_expire(&sw, 16 * LPSS_I2C_TIMEOUT_US); + stopwatch_init_usecs_expire(&sw, 16 * DW_I2C_TIMEOUT_US); while (!stopwatch_expired(&sw)) { uint32_t status = read32(®s->status); @@ -257,14 +307,14 @@ static int lpss_i2c_wait_for_bus_idle(struct lpss_i2c_regs *regs) } /* Transfer one byte of one segment, sending stop bit if requested */ -static int lpss_i2c_transfer_byte(struct lpss_i2c_regs *regs, +static int dw_i2c_transfer_byte(struct dw_i2c_regs *regs, const struct i2c_msg *segment, size_t byte, int send_stop) { struct stopwatch sw; uint32_t cmd = CMD_DATA_CMD; /* Read op */ - stopwatch_init_usecs_expire(&sw, LPSS_I2C_TIMEOUT_US); + stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US); if (!(segment->flags & I2C_M_RD)) { /* Write op only: Wait for FIFO not full */ @@ -297,37 +347,38 @@ static int lpss_i2c_transfer_byte(struct lpss_i2c_regs *regs, return 0; } -int lpss_i2c_transfer(unsigned int bus, +int dw_i2c_transfer(unsigned int bus, const struct i2c_msg *segments, size_t count) { struct stopwatch sw; - struct lpss_i2c_regs *regs; + struct dw_i2c_regs *regs; size_t byte; int ret = -1; if (count == 0 || !segments) return -1; - regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); + regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus); if (!regs) { printk(BIOS_ERR, "I2C bus %u base address not found\n", bus); return -1; } - lpss_i2c_enable(regs); + dw_i2c_enable(regs); - if (lpss_i2c_wait_for_bus_idle(regs)) { + if (dw_i2c_wait_for_bus_idle(regs)) { printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus); goto out; } /* Process each segment */ while (count--) { - if (CONFIG_SOC_INTEL_COMMON_BLOCK_I2C_DEBUG) + if (IS_ENABLED(CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG)) { printk(BIOS_DEBUG, "i2c %u:%02x %s %d bytes : ", bus, segments->slave, (segments->flags & I2C_M_RD) ? "R" : "W", segments->len); + } /* Set target slave address */ write32(®s->target_addr, segments->slave); @@ -339,7 +390,7 @@ int lpss_i2c_transfer(unsigned int bus, * Repeated start will be automatically generated * by the controller on R->W or W->R switch. */ - if (lpss_i2c_transfer_byte(regs, segments, byte, + if (dw_i2c_transfer_byte(regs, segments, byte, count == 0) < 0) { printk(BIOS_ERR, "I2C %s failed: bus %u " "addr 0x%02x\n", @@ -349,18 +400,18 @@ int lpss_i2c_transfer(unsigned int bus, } } - if (CONFIG_SOC_INTEL_COMMON_BLOCK_I2C_DEBUG) { + if (IS_ENABLED(CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG)) { int j; for (j = 0; j < segments->len; j++) printk(BIOS_DEBUG, "%02x ", segments->buf[j]); - printk(BIOS_DEBUG, "\n"); + printk(BIOS_DEBUG, "\n"); } segments++; } /* Wait for interrupt status to indicate transfer is complete */ - stopwatch_init_usecs_expire(&sw, LPSS_I2C_TIMEOUT_US); + stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US); while (!(read32(®s->raw_intr_stat) & INTR_STAT_STOP_DET)) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "I2C stop bit not received\n"); @@ -372,13 +423,13 @@ int lpss_i2c_transfer(unsigned int bus, read32(®s->clear_stop_det_intr); /* Wait for the bus to go idle */ - if (lpss_i2c_wait_for_bus_idle(regs)) { + if (dw_i2c_wait_for_bus_idle(regs)) { printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus); goto out; } /* Flush the RX FIFO in case it is not empty */ - stopwatch_init_usecs_expire(&sw, 16 * LPSS_I2C_TIMEOUT_US); + stopwatch_init_usecs_expire(&sw, 16 * DW_I2C_TIMEOUT_US); while (read32(®s->status) & STATUS_RX_FIFO_NOT_EMPTY) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "I2C timeout flushing RX FIFO\n"); @@ -391,23 +442,23 @@ int lpss_i2c_transfer(unsigned int bus, out: read32(®s->clear_intr); - lpss_i2c_disable(regs); + dw_i2c_disable(regs); return ret; } /* Global I2C bus handler, defined in include/device/i2c_simple.h */ int platform_i2c_transfer(unsigned int bus, struct i2c_msg *msg, int count) { - return lpss_i2c_transfer(bus, msg, count < 0 ? 0 : count); + return dw_i2c_transfer(bus, msg, count < 0 ? 0 : count); } -static int lpss_i2c_set_speed_config(unsigned int bus, - const struct lpss_i2c_speed_config *config) +static int dw_i2c_set_speed_config(unsigned int bus, + const struct dw_i2c_speed_config *config) { - struct lpss_i2c_regs *regs; + struct dw_i2c_regs *regs; void *hcnt_reg, *lcnt_reg; - regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); + regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus); if (!regs || !config) return -1; @@ -442,11 +493,11 @@ static int lpss_i2c_set_speed_config(unsigned int bus, return 0; } -static int lpss_i2c_gen_config_rise_fall_time(struct lpss_i2c_regs *regs, +static int dw_i2c_gen_config_rise_fall_time(struct dw_i2c_regs *regs, enum i2c_speed speed, - const struct lpss_i2c_bus_config *bcfg, + const struct dw_i2c_bus_config *bcfg, int ic_clk, - struct lpss_i2c_speed_config *config) + struct dw_i2c_speed_config *config) { const struct i2c_descriptor *bus; const struct soc_clock *soc; @@ -458,12 +509,12 @@ static int lpss_i2c_gen_config_rise_fall_time(struct lpss_i2c_regs *regs, soc = get_soc_descriptor(ic_clk); if (bus == NULL) { - printk(BIOS_ERR, "lpss_i2c: invalid bus speed %d\n", speed); + printk(BIOS_ERR, "dw_i2c: invalid bus speed %d\n", speed); return -1; } if (soc == NULL) { - printk(BIOS_ERR, "lpss_i2c: invalid SoC clock speed %d MHz\n", + printk(BIOS_ERR, "dw_i2c: invalid SoC clock speed %d MHz\n", ic_clk); return -1; } @@ -482,9 +533,10 @@ static int lpss_i2c_gen_config_rise_fall_time(struct lpss_i2c_regs *regs, min_tlow_cnt = counts_from_time(&soc->freq, bus->min_tlow_ns); min_thigh_cnt = counts_from_time(&soc->freq, bus->min_thigh_ns); - printk(LPSS_DEBUG, "lpss_i2c: SoC %d/%d ns Bus: %d/%d ns\n", + printk(DW_I2C_DEBUG, "dw_i2c: SoC %d/%d ns Bus: %d/%d ns\n", soc->freq.ticks, soc->freq.ns, bus->freq.ticks, bus->freq.ns); - printk(LPSS_DEBUG, "lpss_i2c: period %d rise %d fall %d tlow %d thigh %d spk %d\n", + printk(DW_I2C_DEBUG, +" dw_i2c: period %d rise %d fall %d tlow %d thigh %d spk %d\n", period_cnt, rise_cnt, fall_cnt, min_tlow_cnt, min_thigh_cnt, spk_cnt); @@ -497,7 +549,7 @@ static int lpss_i2c_gen_config_rise_fall_time(struct lpss_i2c_regs *regs, lcnt = min_tlow_cnt - rise_cnt + fall_cnt - 1; if (hcnt < 0 || lcnt < 0) { - printk(BIOS_ERR, "lpss_i2c: bad counts. hcnt = %d lcnt = %d\n", + printk(BIOS_ERR, "dw_i2c: bad counts. hcnt = %d lcnt = %d\n", hcnt, lcnt); return -1; } @@ -525,26 +577,29 @@ static int lpss_i2c_gen_config_rise_fall_time(struct lpss_i2c_regs *regs, config->sda_hold = counts_from_time(&soc->freq, data_hold_time_ns); - printk(LPSS_DEBUG, "lpss_i2c: hcnt = %d lcnt = %d sda hold = %d\n", + printk(DW_I2C_DEBUG, "dw_i2c: hcnt = %d lcnt = %d sda hold = %d\n", hcnt, lcnt, config->sda_hold); return 0; } -int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs, +int dw_i2c_gen_speed_config(uintptr_t dw_i2c_addr, enum i2c_speed speed, - const struct lpss_i2c_bus_config *bcfg, - struct lpss_i2c_speed_config *config) + const struct dw_i2c_bus_config *bcfg, + struct dw_i2c_speed_config *config) { - const int ic_clk = CONFIG_SOC_INTEL_COMMON_LPSS_CLOCK_MHZ; + const int ic_clk = CONFIG_DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ; + struct dw_i2c_regs *regs; uint16_t hcnt_min, lcnt_min; int i; - _Static_assert(CONFIG_SOC_INTEL_COMMON_LPSS_CLOCK_MHZ != 0, - "SOC_INTEL_COMMON_LPSS_CLOCK_MHZ can't be zero!"); + regs = (struct dw_i2c_regs *)dw_i2c_addr; + + _Static_assert(CONFIG_DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ != 0, + "DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ can't be zero!"); /* Apply board specific override for this speed if found */ - for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) { + for (i = 0; i < DW_I2C_SPEED_CONFIG_COUNT; i++) { if (bcfg->speed_config[i].speed != speed) continue; memcpy(config, &bcfg->speed_config[i], sizeof(*config)); @@ -553,7 +608,7 @@ int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs, /* If rise time is set use the time calculation. */ if (bcfg->rise_time_ns) - return lpss_i2c_gen_config_rise_fall_time(regs, speed, bcfg, + return dw_i2c_gen_config_rise_fall_time(regs, speed, bcfg, ic_clk, config); if (speed >= I2C_SPEED_HIGH) { @@ -582,15 +637,15 @@ int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs, return 0; } -static int lpss_i2c_set_speed(unsigned int bus, enum i2c_speed speed, - const struct lpss_i2c_bus_config *bcfg) +static int dw_i2c_set_speed(unsigned int bus, enum i2c_speed speed, + const struct dw_i2c_bus_config *bcfg) { - struct lpss_i2c_regs *regs; - struct lpss_i2c_speed_config config; + struct dw_i2c_regs *regs; + struct dw_i2c_speed_config config; uint32_t control; /* Clock must be provided by Kconfig */ - regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); + regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus); if (!regs || !speed) return -1; @@ -609,14 +664,14 @@ static int lpss_i2c_set_speed(unsigned int bus, enum i2c_speed speed, } /* Generate speed config based on clock */ - if (lpss_i2c_gen_speed_config(regs, speed, bcfg, &config) < 0) + if (dw_i2c_gen_speed_config((uintptr_t)regs, speed, bcfg, &config) < 0) return -1; /* Select this speed in the control register */ write32(®s->control, control); /* Write the speed config that was generated earlier */ - lpss_i2c_set_speed_config(bus, &config); + dw_i2c_set_speed_config(bus, &config); return 0; } @@ -628,9 +683,9 @@ static int lpss_i2c_set_speed(unsigned int bus, enum i2c_speed speed, * The bus speed can be passed in Hz or using values from device/i2c.h and * will default to I2C_SPEED_FAST if it is not provided. */ -int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg) +int dw_i2c_init(unsigned int bus, const struct dw_i2c_bus_config *bcfg) { - struct lpss_i2c_regs *regs; + struct dw_i2c_regs *regs; enum i2c_speed speed; if (!bcfg) @@ -638,13 +693,13 @@ int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg) speed = bcfg->speed ? : I2C_SPEED_FAST; - regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); + regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus); if (!regs) { printk(BIOS_ERR, "I2C bus %u base address not found\n", bus); return -1; } - if (lpss_i2c_disable(regs) < 0) { + if (dw_i2c_disable(regs) < 0) { printk(BIOS_ERR, "I2C timeout disabling bus %u\n", bus); return -1; } @@ -654,7 +709,7 @@ int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg) CONTROL_RESTART_ENABLE); /* Set bus speed to FAST by default */ - if (lpss_i2c_set_speed(bus, speed, bcfg) < 0) { + if (dw_i2c_set_speed(bus, speed, bcfg) < 0) { printk(BIOS_ERR, "I2C failed to set speed for bus %u\n", bus); return -1; } @@ -666,7 +721,7 @@ int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg) /* Enable stop detection interrupt */ write32(®s->intr_mask, INTR_STAT_STOP_DET); - printk(BIOS_INFO, "LPSS I2C bus %u at 0x%p (%u KHz)\n", + printk(BIOS_INFO, "DW I2C bus %u at 0x%p (%u KHz)\n", bus, regs, speed / KHz); return 0; diff --git a/src/soc/intel/common/block/include/intelblocks/lpss_i2c.h b/src/drivers/i2c/designware/dw_i2c.h index 033081f4b9..8fea4e1c9b 100644 --- a/src/soc/intel/common/block/include/intelblocks/lpss_i2c.h +++ b/src/drivers/i2c/designware/dw_i2c.h @@ -1,33 +1,42 @@ /* * This file is part of the coreboot project. * - * Copyright 2016 Google Inc. + * Copyright 2017 Intel Corporation. * * 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 + * but WITHOUT ANY WARRANTY; without even the imfamiluarplied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#ifndef SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H -#define SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H +#ifndef __DRIVERS_I2C_DESIGNWARE_I2C_H__ +#define __DRIVERS_I2C_DESIGNWARE_I2C_H__ +#include <compiler.h> #include <device/device.h> #include <device/i2c.h> #include <stdint.h> +#if IS_ENABLED(CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG) +#define DW_I2C_DEBUG BIOS_DEBUG + +#else +#define DW_I2C_DEBUG BIOS_NEVER + +#endif // CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG + /* * Timing values are in units of clock period, with the clock speed - * provided by the SOC in CONFIG_SOC_INTEL_COMMON_LPSS_CLOCK_MHZ. + * provided by the SOC in CONFIG_DRIVERS_I2C_DESIGNWARE_I2C_CLOCK_MHZ * Automatic configuration is done based on requested speed, but the * values may need tuned depending on the board and the number of * devices present on the bus. */ -struct lpss_i2c_speed_config { +struct dw_i2c_speed_config { enum i2c_speed speed; /* SCL high and low period count */ uint16_t scl_lcnt; @@ -35,7 +44,7 @@ struct lpss_i2c_speed_config { /* * SDA hold time should be 300ns in standard and fast modes * and long enough for deterministic logic level change in - * fast-plus and high speed modes. + * fast-plus and high speed modes.familuar * * [15:0] SDA TX Hold Time * [23:16] SDA RX Hold Time @@ -49,9 +58,9 @@ struct lpss_i2c_speed_config { * config registers. These are treated separately so the speed config values * can be provided via ACPI to the OS. */ -#define LPSS_I2C_SPEED_CONFIG_COUNT 4 +#define DW_I2C_SPEED_CONFIG_COUNT 4 -struct lpss_i2c_bus_config { +struct dw_i2c_bus_config { /* Bus should be enabled prior to ramstage with temporary base */ int early_init; /* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */ @@ -64,17 +73,9 @@ struct lpss_i2c_bus_config { int fall_time_ns; int data_hold_time_ns; /* Specific bus speed configuration */ - struct lpss_i2c_speed_config speed_config[LPSS_I2C_SPEED_CONFIG_COUNT]; + struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT]; }; -#define LPSS_I2C_SPEED_CONFIG(speedval, lcnt, hcnt, hold) \ - { \ - .speed = I2C_SPEED_ ## speedval, \ - .scl_lcnt = (lcnt), \ - .scl_hcnt = (hcnt), \ - .sda_hold = (hold), \ - } - /* Functions to be implemented by SoC code */ /* Get base address for early init of I2C controllers. */ @@ -101,6 +102,39 @@ int i2c_soc_bus_to_devfn(unsigned int bus); * * Returns NULL if i2c config is not found */ -const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, +const struct dw_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, const struct device *dev); -#endif /* SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H */ + +/* Get I2C controller base address */ +uintptr_t dw_i2c_base_address(unsigned int bus); + +/* + * Initialize this bus controller and set the speed + * Return value: + * -1 = failure + * 0 = success +*/ +int dw_i2c_init(unsigned int bus, const struct dw_i2c_bus_config *bcfg); + +/* + * Generate speed config based on clock + * Return value: + * -1 = failure + * 0 = success +*/ +int dw_i2c_gen_speed_config(uintptr_t dw_i2c_addr, + enum i2c_speed speed, + const struct dw_i2c_bus_config *bcfg, + struct dw_i2c_speed_config *config); + +/* + * Process given I2C segments in a single transfer + * Return value: + * -1 = failure + * 0 = success + */ +int dw_i2c_transfer(unsigned int bus, + const struct i2c_msg *segments, + size_t count); + +#endif /* __DRIVERS_I2C_DESIGNWARE_I2C_H__ */ diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig index 89b5835f3c..2d5363d6b9 100644 --- a/src/soc/intel/apollolake/Kconfig +++ b/src/soc/intel/apollolake/Kconfig @@ -157,6 +157,10 @@ config SOC_INTEL_COMMON_LPSS_CLOCK_MHZ int default 133 +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default SOC_INTEL_COMMON_LPSS_CLOCK_MHZ + config CONSOLE_UART_BASE_ADDRESS depends on CONSOLE_SERIAL hex diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h index 78410fdbe5..8573cf44b5 100644 --- a/src/soc/intel/apollolake/chip.h +++ b/src/soc/intel/apollolake/chip.h @@ -23,8 +23,8 @@ #include <soc/gpe.h> #include <soc/gpio.h> #include <intelblocks/lpc_lib.h> -#include <intelblocks/lpss_i2c.h> #include <device/i2c_simple.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <soc/pm.h> #include <soc/usb.h> @@ -93,7 +93,7 @@ struct soc_intel_apollolake_config { enum serirq_mode serirq_mode; /* I2C bus configuration */ - struct lpss_i2c_bus_config i2c[APOLLOLAKE_I2C_DEV_MAX]; + struct dw_i2c_bus_config i2c[APOLLOLAKE_I2C_DEV_MAX]; uint8_t gpe0_dw1; /* GPE0_63_32 STS/EN */ uint8_t gpe0_dw2; /* GPE0_95_64 STS/EN */ diff --git a/src/soc/intel/apollolake/i2c.c b/src/soc/intel/apollolake/i2c.c index 4ae500ecce..5925f3d22c 100644 --- a/src/soc/intel/apollolake/i2c.c +++ b/src/soc/intel/apollolake/i2c.c @@ -16,12 +16,12 @@ #include <console/console.h> #include <device/device.h> #include <device/pci_def.h> -#include <intelblocks/lpss_i2c.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <soc/iomap.h> #include <soc/pci_devs.h> #include "chip.h" -const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, +const struct dw_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, const struct device *dev) { const struct soc_intel_apollolake_config *config; diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index beb812b080..b628370297 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -135,6 +135,10 @@ config SOC_INTEL_COMMON_LPSS_CLOCK_MHZ int default 120 +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default SOC_INTEL_COMMON_LPSS_CLOCK_MHZ + config SOC_INTEL_COMMON_BLOCK_GSPI_MAX int default 3 diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index fd89339e63..e984b4de23 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -18,8 +18,8 @@ #ifndef _SOC_CHIP_H_ #define _SOC_CHIP_H_ +#include <drivers/i2c/designware/dw_i2c.h> #include <intelblocks/gspi.h> -#include <intelblocks/lpss_i2c.h> #include <stdint.h> #include <soc/pch.h> #include <soc/gpio_defs.h> @@ -255,7 +255,7 @@ struct soc_intel_cannonlake_config { unsigned int sdcard_cd_gpio; /* I2C bus configuration */ - struct lpss_i2c_bus_config i2c[CANNONLAKE_I2C_DEV_MAX]; + struct dw_i2c_bus_config i2c[CANNONLAKE_I2C_DEV_MAX]; }; typedef struct soc_intel_cannonlake_config config_t; diff --git a/src/soc/intel/cannonlake/i2c.c b/src/soc/intel/cannonlake/i2c.c index b0c35238ee..03ced5f936 100644 --- a/src/soc/intel/cannonlake/i2c.c +++ b/src/soc/intel/cannonlake/i2c.c @@ -17,12 +17,12 @@ #include <console/console.h> #include <device/device.h> #include <device/pci_def.h> -#include <intelblocks/lpss_i2c.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <soc/iomap.h> #include <soc/pci_devs.h> #include "chip.h" -const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, +const struct dw_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, const struct device *dev) { const struct soc_intel_cannonlake_config *config; diff --git a/src/soc/intel/common/block/i2c/Kconfig b/src/soc/intel/common/block/i2c/Kconfig index 0e68dac6eb..e70796a439 100644 --- a/src/soc/intel/common/block/i2c/Kconfig +++ b/src/soc/intel/common/block/i2c/Kconfig @@ -1,5 +1,6 @@ config SOC_INTEL_COMMON_BLOCK_I2C bool + select DRIVERS_I2C_DESIGNWARE help Intel Processor Common I2C support diff --git a/src/soc/intel/common/block/i2c/Makefile.inc b/src/soc/intel/common/block/i2c/Makefile.inc index 24755c47d3..58feb5f781 100644 --- a/src/soc/intel/common/block/i2c/Makefile.inc +++ b/src/soc/intel/common/block/i2c/Makefile.inc @@ -1,11 +1,8 @@ -bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c -bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c +ifeq ($(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C),y) -romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c -romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c +bootblock-y += i2c_early.c +romstage-y += i2c_early.c +verstage-y += i2c_early.c +ramstage-y += i2c.c -verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c -verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c - -ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c -ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c.c +endif diff --git a/src/soc/intel/common/block/i2c/i2c.c b/src/soc/intel/common/block/i2c/i2c.c index 3bb7d11309..7200771a5a 100644 --- a/src/soc/intel/common/block/i2c/i2c.c +++ b/src/soc/intel/common/block/i2c/i2c.c @@ -18,16 +18,9 @@ #include <device/pci.h> #include <device/pci_def.h> #include <device/pci_ids.h> -#include <intelblocks/lpss_i2c.h> -#include "lpss_i2c.h" +#include <drivers/i2c/designware/dw_i2c.h> -static int lpss_i2c_dev_to_bus(struct device *dev) -{ - pci_devfn_t devfn = dev->path.pci.devfn; - return i2c_soc_devfn_to_bus(devfn); -} - -uintptr_t lpss_i2c_base_address(unsigned int bus) +uintptr_t dw_i2c_base_address(unsigned int bus) { int devfn; struct device *dev; @@ -52,6 +45,12 @@ uintptr_t lpss_i2c_base_address(unsigned int bus) return (uintptr_t)NULL; } +static int lpss_i2c_dev_to_bus(struct device *dev) +{ + pci_devfn_t devfn = dev->path.pci.devfn; + return i2c_soc_devfn_to_bus(devfn); +} + /* * Write ACPI object to describe speed configuration. * @@ -63,7 +62,7 @@ uintptr_t lpss_i2c_base_address(unsigned int bus) * HSCN: I2C_SPEED_HIGH */ static void lpss_i2c_acpi_write_speed_config( - const struct lpss_i2c_speed_config *config) + const struct dw_i2c_speed_config *config) { if (!config) return; @@ -93,7 +92,7 @@ static void lpss_i2c_acpi_write_speed_config( */ static void lpss_i2c_dev_init(struct device *dev) { - const struct lpss_i2c_bus_config *config; + const struct dw_i2c_bus_config *config; int bus = lpss_i2c_dev_to_bus(dev); if (bus < 0) @@ -104,7 +103,7 @@ static void lpss_i2c_dev_init(struct device *dev) if (!config) return; - lpss_i2c_init(bus, config); + dw_i2c_init(bus, config); } /* @@ -113,10 +112,10 @@ static void lpss_i2c_dev_init(struct device *dev) */ static void lpss_i2c_acpi_fill_ssdt(struct device *dev) { - const struct lpss_i2c_bus_config *bcfg; - struct lpss_i2c_regs *regs; - struct lpss_i2c_speed_config sgen; - enum i2c_speed speeds[LPSS_I2C_SPEED_CONFIG_COUNT] = { + const struct dw_i2c_bus_config *bcfg; + uintptr_t dw_i2c_addr; + struct dw_i2c_speed_config sgen; + enum i2c_speed speeds[DW_I2C_SPEED_CONFIG_COUNT] = { I2C_SPEED_STANDARD, I2C_SPEED_FAST, I2C_SPEED_FAST_PLUS, @@ -137,16 +136,17 @@ static void lpss_i2c_acpi_fill_ssdt(struct device *dev) if (!bcfg) return; - regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); - if (!regs) + dw_i2c_addr = dw_i2c_base_address(bus); + if (!dw_i2c_addr) return; acpigen_write_scope(acpi_device_path(dev)); /* Report timing values for the OS driver */ - for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) { + for (i = 0; i < DW_I2C_SPEED_CONFIG_COUNT; i++) { /* Generate speed config. */ - if (lpss_i2c_gen_speed_config(regs, speeds[i], bcfg, &sgen) < 0) + if (dw_i2c_gen_speed_config(dw_i2c_addr, speeds[i], bcfg, + &sgen) < 0) continue; /* Generate ACPI based on selected speed config */ @@ -159,7 +159,7 @@ static void lpss_i2c_acpi_fill_ssdt(struct device *dev) static int lpss_i2c_dev_transfer(struct device *dev, const struct i2c_msg *msg, size_t count) { - return lpss_i2c_transfer(lpss_i2c_dev_to_bus(dev), msg, count); + return dw_i2c_transfer(lpss_i2c_dev_to_bus(dev), msg, count); } static const struct i2c_bus_operations i2c_bus_ops = { diff --git a/src/soc/intel/common/block/i2c/i2c_early.c b/src/soc/intel/common/block/i2c/i2c_early.c index 74fc994ca3..f10147ed95 100644 --- a/src/soc/intel/common/block/i2c/i2c_early.c +++ b/src/soc/intel/common/block/i2c/i2c_early.c @@ -20,13 +20,12 @@ #include <device/i2c_simple.h> #include <device/pci.h> #include <device/pci_def.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <intelblocks/lpss.h> -#include <intelblocks/lpss_i2c.h> -#include "lpss_i2c.h" static int lpss_i2c_early_init_bus(unsigned int bus) { - const struct lpss_i2c_bus_config *config; + const struct dw_i2c_bus_config *config; const struct device *tree_dev; pci_devfn_t dev; int devfn; @@ -64,7 +63,7 @@ static int lpss_i2c_early_init_bus(unsigned int bus) lpss_reset_release(base); /* Initialize the controller */ - if (lpss_i2c_init(bus, config) < 0) { + if (dw_i2c_init(bus, config) < 0) { printk(BIOS_ERR, "I2C%u failed to initialize\n", bus); return -1; } @@ -72,7 +71,7 @@ static int lpss_i2c_early_init_bus(unsigned int bus) return 0; } -uintptr_t lpss_i2c_base_address(unsigned int bus) +uintptr_t dw_i2c_base_address(unsigned int bus) { int devfn; pci_devfn_t dev; diff --git a/src/soc/intel/common/block/i2c/lpss_i2c.h b/src/soc/intel/common/block/i2c/lpss_i2c.h deleted file mode 100644 index 72341621c0..0000000000 --- a/src/soc/intel/common/block/i2c/lpss_i2c.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2017 Intel Corporation. - * - * 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 <compiler.h> -#include <intelblocks/lpss_i2c.h> - -#define LPSS_DEBUG BIOS_NEVER - -/* I2C Controller MMIO register space */ -struct lpss_i2c_regs { - uint32_t control; - uint32_t target_addr; - uint32_t slave_addr; - uint32_t master_addr; - uint32_t cmd_data; - uint32_t ss_scl_hcnt; - uint32_t ss_scl_lcnt; - uint32_t fs_scl_hcnt; - uint32_t fs_scl_lcnt; - uint32_t hs_scl_hcnt; - uint32_t hs_scl_lcnt; - uint32_t intr_stat; - uint32_t intr_mask; - uint32_t raw_intr_stat; - uint32_t rx_thresh; - uint32_t tx_thresh; - uint32_t clear_intr; - uint32_t clear_rx_under_intr; - uint32_t clear_rx_over_intr; - uint32_t clear_tx_over_intr; - uint32_t clear_rd_req_intr; - uint32_t clear_tx_abrt_intr; - uint32_t clear_rx_done_intr; - uint32_t clear_activity_intr; - uint32_t clear_stop_det_intr; - uint32_t clear_start_det_intr; - uint32_t clear_gen_call_intr; - uint32_t enable; - uint32_t status; - uint32_t tx_level; - uint32_t rx_level; - uint32_t sda_hold; - uint32_t tx_abort_source; - uint32_t slv_data_nak_only; - uint32_t dma_cr; - uint32_t dma_tdlr; - uint32_t dma_rdlr; - uint32_t sda_setup; - uint32_t ack_general_call; - uint32_t enable_status; - uint32_t fs_spklen; - uint32_t hs_spklen; - uint32_t clr_restart_det; - uint32_t comp_param1; - uint32_t comp_version; - uint32_t comp_type; -} __packed; - -/* Get I2C controller base address */ -uintptr_t lpss_i2c_base_address(unsigned int bus); - -/* - * Initialize this bus controller and set the speed - * Return value: - * -1 = failure - * 0 = success -*/ -int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg); - -/* - * Generate speed cofnig based on clock - * Return value: - * -1 = failure - * 0 = success -*/ -int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs, - enum i2c_speed speed, - const struct lpss_i2c_bus_config *bcfg, - struct lpss_i2c_speed_config *config); - -/* - * Process given I2C segments in a single transfer - * Return value: - * -1 = failure - * 0 = success - */ -int lpss_i2c_transfer(unsigned int bus, const struct i2c_msg *, size_t count); diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig index 97ba7af7f2..7bb16d20d8 100644 --- a/src/soc/intel/skylake/Kconfig +++ b/src/soc/intel/skylake/Kconfig @@ -334,6 +334,10 @@ config SOC_INTEL_COMMON_LPSS_CLOCK_MHZ int default 120 +config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default SOC_INTEL_COMMON_LPSS_CLOCK_MHZ + config SOC_INTEL_COMMON_BLOCK_GSPI_MAX int default 2 diff --git a/src/soc/intel/skylake/bootblock/bootblock.c b/src/soc/intel/skylake/bootblock/bootblock.c index 058cec855b..57b01962a3 100644 --- a/src/soc/intel/skylake/bootblock/bootblock.c +++ b/src/soc/intel/skylake/bootblock/bootblock.c @@ -14,8 +14,8 @@ */ #include <bootblock_common.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <intelblocks/gspi.h> -#include <intelblocks/lpss_i2c.h> #include <soc/bootblock.h> asmlinkage void bootblock_c_entry(uint64_t base_timestamp) diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h index 8540e210aa..813974909a 100644 --- a/src/soc/intel/skylake/chip.h +++ b/src/soc/intel/skylake/chip.h @@ -21,8 +21,8 @@ #include <arch/acpi_device.h> #include <device/i2c_simple.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <intelblocks/gspi.h> -#include <intelblocks/lpss_i2c.h> #include <stdint.h> #include <soc/gpe.h> #include <soc/gpio.h> @@ -251,7 +251,7 @@ struct soc_intel_skylake_config { /* I2C */ /* Bus voltage level, default is 3.3V */ enum skylake_i2c_voltage i2c_voltage[SKYLAKE_I2C_DEV_MAX]; - struct lpss_i2c_bus_config i2c[SKYLAKE_I2C_DEV_MAX]; + struct dw_i2c_bus_config i2c[SKYLAKE_I2C_DEV_MAX]; /* GSPI */ struct gspi_cfg gspi[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX]; diff --git a/src/soc/intel/skylake/i2c.c b/src/soc/intel/skylake/i2c.c index 55e23e0906..6b457ce62c 100644 --- a/src/soc/intel/skylake/i2c.c +++ b/src/soc/intel/skylake/i2c.c @@ -15,12 +15,12 @@ #include <console/console.h> #include <device/device.h> -#include <intelblocks/lpss_i2c.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <soc/iomap.h> #include <soc/pci_devs.h> #include "chip.h" -const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, +const struct dw_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus, const struct device *dev) { const struct soc_intel_skylake_config *config; |