drivers/i2c/i2c_dw.c: rewrite for PCI(e) support
The legacy PCI support in the DesignWare I2C driver is replaced with the new PCIe support. The Intel Quark X1000 SoC and the galileo board configurations are updated accordingly. Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
parent
59ebe6a072
commit
309dfef511
9 changed files with 86 additions and 122 deletions
|
@ -40,7 +40,7 @@ config GPIO_PCAL9535A_0_DEV_NAME
|
||||||
config GPIO_PCAL9535A_0_I2C_ADDR
|
config GPIO_PCAL9535A_0_I2C_ADDR
|
||||||
default 0x25
|
default 0x25
|
||||||
config GPIO_PCAL9535A_0_I2C_MASTER_DEV_NAME
|
config GPIO_PCAL9535A_0_I2C_MASTER_DEV_NAME
|
||||||
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_90007000_LABEL)"
|
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_0_LABEL)"
|
||||||
|
|
||||||
endif # GPIO_PCAL9535A_0
|
endif # GPIO_PCAL9535A_0
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ config GPIO_PCAL9535A_1_DEV_NAME
|
||||||
config GPIO_PCAL9535A_1_I2C_ADDR
|
config GPIO_PCAL9535A_1_I2C_ADDR
|
||||||
default 0x26
|
default 0x26
|
||||||
config GPIO_PCAL9535A_1_I2C_MASTER_DEV_NAME
|
config GPIO_PCAL9535A_1_I2C_MASTER_DEV_NAME
|
||||||
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_90007000_LABEL)"
|
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_0_LABEL)"
|
||||||
|
|
||||||
endif # GPIO_PCAL9535A_1
|
endif # GPIO_PCAL9535A_1
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ config GPIO_PCAL9535A_2_DEV_NAME
|
||||||
config GPIO_PCAL9535A_2_I2C_ADDR
|
config GPIO_PCAL9535A_2_I2C_ADDR
|
||||||
default 0x27
|
default 0x27
|
||||||
config GPIO_PCAL9535A_2_I2C_MASTER_DEV_NAME
|
config GPIO_PCAL9535A_2_I2C_MASTER_DEV_NAME
|
||||||
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_90007000_LABEL)"
|
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_0_LABEL)"
|
||||||
|
|
||||||
endif # GPIO_PCAL9535A_2
|
endif # GPIO_PCAL9535A_2
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ config PWM_PCA9685_0_DEV_NAME
|
||||||
config PWM_PCA9685_0_I2C_ADDR
|
config PWM_PCA9685_0_I2C_ADDR
|
||||||
default 0x47
|
default 0x47
|
||||||
config PWM_PCA9685_0_I2C_MASTER_DEV_NAME
|
config PWM_PCA9685_0_I2C_MASTER_DEV_NAME
|
||||||
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_90007000_LABEL)"
|
default "$(dt_str_val,DT_SNPS_DESIGNWARE_I2C_0_LABEL)"
|
||||||
|
|
||||||
endif # PWM_PCA9685_0
|
endif # PWM_PCA9685_0
|
||||||
endif # PWM_PCA9685
|
endif # PWM_PCA9685
|
||||||
|
|
|
@ -17,7 +17,6 @@ CONFIG_PINMUX=y
|
||||||
CONFIG_I2C=y
|
CONFIG_I2C=y
|
||||||
CONFIG_I2C_DW=y
|
CONFIG_I2C_DW=y
|
||||||
CONFIG_I2C_0=y
|
CONFIG_I2C_0=y
|
||||||
CONFIG_I2C_DW_0_IRQ_SHARED=y
|
|
||||||
CONFIG_GPIO_PCAL9535A=y
|
CONFIG_GPIO_PCAL9535A=y
|
||||||
CONFIG_GPIO_SCH=y
|
CONFIG_GPIO_SCH=y
|
||||||
CONFIG_GPIO_SCH_0=y
|
CONFIG_GPIO_SCH_0=y
|
||||||
|
|
|
@ -22,28 +22,4 @@ config I2C_DW_CLOCK_SPEED
|
||||||
int "Set the clock speed for I2C"
|
int "Set the clock speed for I2C"
|
||||||
default 32
|
default 32
|
||||||
|
|
||||||
config I2C_DW_SHARED_IRQ
|
|
||||||
bool
|
|
||||||
|
|
||||||
choice
|
|
||||||
prompt "I2C_0 Interrupts via"
|
|
||||||
default I2C_DW_0_IRQ_DIRECT
|
|
||||||
depends on I2C_0
|
|
||||||
|
|
||||||
config I2C_DW_0_IRQ_DIRECT
|
|
||||||
bool "Direct Hardware Interrupt"
|
|
||||||
help
|
|
||||||
When interrupts fire, the driver's ISR function is being called
|
|
||||||
directly.
|
|
||||||
|
|
||||||
config I2C_DW_0_IRQ_SHARED
|
|
||||||
bool "Shared IRQ"
|
|
||||||
depends on SHARED_IRQ
|
|
||||||
select I2C_DW_SHARED_IRQ
|
|
||||||
help
|
|
||||||
When interrupts fire, the shared IRQ driver is notified.
|
|
||||||
Then the shared IRQ driver dispatches the interrupt to other drivers.
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
endif # I2C_DW
|
endif # I2C_DW
|
||||||
|
|
|
@ -22,10 +22,6 @@
|
||||||
|
|
||||||
#include <misc/util.h>
|
#include <misc/util.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SHARED_IRQ
|
|
||||||
#include <shared_irq.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_IOAPIC
|
#ifdef CONFIG_IOAPIC
|
||||||
#include <drivers/ioapic.h>
|
#include <drivers/ioapic.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -198,16 +194,6 @@ static void i2c_dw_isr(void *arg)
|
||||||
*/
|
*/
|
||||||
intr_stat.raw = regs->ic_intr_stat.raw;
|
intr_stat.raw = regs->ic_intr_stat.raw;
|
||||||
|
|
||||||
#if CONFIG_SHARED_IRQ
|
|
||||||
/* If using with shared IRQ, this function will be called
|
|
||||||
* by the shared IRQ driver. So check here if the interrupt
|
|
||||||
* is coming from the I2C controller (or somewhere else).
|
|
||||||
*/
|
|
||||||
if (!intr_stat.raw) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Causes of an interrupt:
|
* Causes of an interrupt:
|
||||||
* - STOP condition is detected
|
* - STOP condition is detected
|
||||||
|
@ -620,42 +606,22 @@ static const struct i2c_driver_api funcs = {
|
||||||
.transfer = i2c_dw_transfer,
|
.transfer = i2c_dw_transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
|
||||||
static inline int i2c_dw_pci_setup(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_dw_dev_config * const dw = dev->driver_data;
|
|
||||||
|
|
||||||
pci_bus_scan_init();
|
|
||||||
|
|
||||||
if (!pci_bus_scan(&dw->pci_dev)) {
|
|
||||||
LOG_DBG("Could not find device");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_ENUMERATION
|
|
||||||
dw->base_address = dw->pci_dev.addr;
|
|
||||||
#endif
|
|
||||||
pci_enable_regs(&dw->pci_dev);
|
|
||||||
|
|
||||||
pci_show(&dw->pci_dev);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define i2c_dw_pci_setup(_unused_) (1)
|
|
||||||
#endif /* CONFIG_PCI */
|
|
||||||
|
|
||||||
static int i2c_dw_initialize(struct device *dev)
|
static int i2c_dw_initialize(struct device *dev)
|
||||||
{
|
{
|
||||||
const struct i2c_dw_rom_config * const rom = dev->config->config_info;
|
const struct i2c_dw_rom_config * const rom = dev->config->config_info;
|
||||||
struct i2c_dw_dev_config * const dw = dev->driver_data;
|
struct i2c_dw_dev_config * const dw = dev->driver_data;
|
||||||
volatile struct i2c_dw_registers *regs;
|
volatile struct i2c_dw_registers *regs;
|
||||||
|
|
||||||
if (!i2c_dw_pci_setup(dev)) {
|
#ifdef I2C_DW_PCIE_ENABLED
|
||||||
dev->driver_api = NULL;
|
if (rom->pcie) {
|
||||||
return -EIO;
|
if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw->base_address = pcie_get_mbar(rom->pcie_bdf, 0);
|
||||||
|
pcie_set_cmd(rom->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
k_sem_init(&dw->device_sync_sem, 0, UINT_MAX);
|
k_sem_init(&dw->device_sync_sem, 0, UINT_MAX);
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,18 @@
|
||||||
#include <i2c.h>
|
#include <i2c.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#if DT_SNPS_DESIGNWARE_I2C_0_PCIE || \
|
||||||
#include <pci/pci.h>
|
DT_SNPS_DESIGNWARE_I2C_1_PCIE || \
|
||||||
#include <pci/pci_mgr.h>
|
DT_SNPS_DESIGNWARE_I2C_2_PCIE || \
|
||||||
#endif /* CONFIG_PCI */
|
DT_SNPS_DESIGNWARE_I2C_3_PCIE || \
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_4_PCIE || \
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_5_PCIE || \
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_6_PCIE || \
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_7_PCIE
|
||||||
|
BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_PCIE), "DW I2C in DT needs CONFIG_PCIE");
|
||||||
|
#define I2C_DW_PCIE_ENABLED
|
||||||
|
#include <drivers/pcie/pcie.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -86,15 +94,14 @@ typedef void (*i2c_isr_cb_t)(struct device *port);
|
||||||
|
|
||||||
struct i2c_dw_rom_config {
|
struct i2c_dw_rom_config {
|
||||||
i2c_isr_cb_t config_func;
|
i2c_isr_cb_t config_func;
|
||||||
|
u32_t bitrate;
|
||||||
#ifdef CONFIG_I2C_DW_SHARED_IRQ
|
#ifdef I2C_DW_PCIE_ENABLED
|
||||||
char *shared_irq_dev_name;
|
bool pcie;
|
||||||
#endif /* CONFIG_I2C_DW_SHARED_IRQ */
|
pcie_bdf_t pcie_bdf;
|
||||||
|
pcie_id_t pcie_id;
|
||||||
u32_t bitrate;
|
#endif /* I2C_DW_PCIE_ENABLED */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct i2c_dw_dev_config {
|
struct i2c_dw_dev_config {
|
||||||
u32_t base_address;
|
u32_t base_address;
|
||||||
struct k_sem device_sync_sem;
|
struct k_sem device_sync_sem;
|
||||||
|
@ -112,9 +119,6 @@ struct i2c_dw_dev_config {
|
||||||
u8_t request_bytes;
|
u8_t request_bytes;
|
||||||
u8_t xfr_flags;
|
u8_t xfr_flags;
|
||||||
bool support_hs_mode;
|
bool support_hs_mode;
|
||||||
#ifdef CONFIG_PCI
|
|
||||||
struct pci_dev_info pci_dev;
|
|
||||||
#endif /* CONFIG_PCI */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -10,24 +10,17 @@ static void i2c_config_@NUM@(struct device *port);
|
||||||
|
|
||||||
static const struct i2c_dw_rom_config i2c_config_dw_@NUM@ = {
|
static const struct i2c_dw_rom_config i2c_config_dw_@NUM@ = {
|
||||||
.config_func = i2c_config_@NUM@,
|
.config_func = i2c_config_@NUM@,
|
||||||
|
|
||||||
#ifdef CONFIG_I2C_DW_@NUM@_IRQ_SHARED
|
|
||||||
.shared_irq_dev_name = DT_I2C_DW_@NUM@_IRQ_SHARED_NAME,
|
|
||||||
#endif
|
|
||||||
.bitrate = DT_SNPS_DESIGNWARE_I2C_@NUM@_CLOCK_FREQUENCY,
|
.bitrate = DT_SNPS_DESIGNWARE_I2C_@NUM@_CLOCK_FREQUENCY,
|
||||||
|
|
||||||
|
#if DT_SNPS_DESIGNWARE_I2C_@NUM@_PCIE
|
||||||
|
.pcie = true,
|
||||||
|
.pcie_bdf = DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS,
|
||||||
|
.pcie_id = DT_SNPS_DESIGNWARE_I2C_@NUM@_SIZE,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct i2c_dw_dev_config i2c_@NUM@_runtime = {
|
static struct i2c_dw_dev_config i2c_@NUM@_runtime = {
|
||||||
.base_address = DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS,
|
.base_address = DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS
|
||||||
#if CONFIG_PCI
|
|
||||||
.pci_dev.class_type = I2C_DW_@NUM@_PCI_CLASS,
|
|
||||||
.pci_dev.bus = I2C_DW_@NUM@_PCI_BUS,
|
|
||||||
.pci_dev.dev = I2C_DW_@NUM@_PCI_DEV,
|
|
||||||
.pci_dev.vendor_id = I2C_DW_@NUM@_PCI_VENDOR_ID,
|
|
||||||
.pci_dev.device_id = I2C_DW_@NUM@_PCI_DEVICE_ID,
|
|
||||||
.pci_dev.function = I2C_DW_@NUM@_PCI_FUNCTION,
|
|
||||||
.pci_dev.bar = I2C_DW_@NUM@_PCI_BAR,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE_AND_API_INIT(i2c_@NUM@, DT_SNPS_DESIGNWARE_I2C_@NUM@_LABEL,
|
DEVICE_AND_API_INIT(i2c_@NUM@, DT_SNPS_DESIGNWARE_I2C_@NUM@_LABEL,
|
||||||
|
@ -41,19 +34,51 @@ DEVICE_AND_API_INIT(i2c_@NUM@, DT_SNPS_DESIGNWARE_I2C_@NUM@_LABEL,
|
||||||
#endif
|
#endif
|
||||||
static void i2c_config_@NUM@(struct device *port)
|
static void i2c_config_@NUM@(struct device *port)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_I2C_DW_@NUM@_IRQ_SHARED)
|
ARG_UNUSED(port);
|
||||||
const struct i2c_dw_rom_config * const config =
|
|
||||||
port->config->config_info;
|
#if DT_SNPS_DESIGNWARE_I2C_@NUM@_PCIE
|
||||||
struct device *shared_irq_dev;
|
#if DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0 == PCIE_IRQ_DETECT
|
||||||
|
|
||||||
|
/* PCI(e) with auto IRQ detection */
|
||||||
|
|
||||||
|
BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS),
|
||||||
|
"DW I2C PCI auto-IRQ needs CONFIG_DYNAMIC_INTERRUPTS");
|
||||||
|
|
||||||
|
unsigned int irq;
|
||||||
|
|
||||||
|
irq = pcie_wired_irq(DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS);
|
||||||
|
|
||||||
|
if (irq == PCIE_CONF_INTR_IRQ_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_connect_dynamic(irq,
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_PRIORITY,
|
||||||
|
i2c_dw_isr, DEVICE_GET(i2c_@NUM@),
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_SENSE);
|
||||||
|
pcie_irq_enable(DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS, irq);
|
||||||
|
|
||||||
shared_irq_dev = device_get_binding(config->shared_irq_dev_name);
|
|
||||||
shared_irq_isr_register(shared_irq_dev, (isr_t)i2c_dw_isr, port);
|
|
||||||
shared_irq_enable(shared_irq_dev, port);
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
/* PCI(e) with fixed or MSI IRQ */
|
||||||
|
|
||||||
|
IRQ_CONNECT(DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0,
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_PRIORITY,
|
||||||
|
i2c_dw_isr, DEVICE_GET(i2c_@NUM@),
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_SENSE);
|
||||||
|
pcie_irq_enable(DT_SNPS_DESIGNWARE_I2C_@NUM@_BASE_ADDRESS,
|
||||||
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* not PCI(e) */
|
||||||
|
|
||||||
IRQ_CONNECT(DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0,
|
IRQ_CONNECT(DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0,
|
||||||
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_PRIORITY,
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_PRIORITY,
|
||||||
i2c_dw_isr, DEVICE_GET(i2c_@NUM@),
|
i2c_dw_isr, DEVICE_GET(i2c_@NUM@),
|
||||||
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_SENSE);
|
DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0_SENSE);
|
||||||
irq_enable(DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0);
|
irq_enable(DT_SNPS_DESIGNWARE_I2C_@NUM@_IRQ_0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,4 +29,9 @@ properties:
|
||||||
description: required interrupts
|
description: required interrupts
|
||||||
generation: define
|
generation: define
|
||||||
|
|
||||||
|
pcie:
|
||||||
|
type: boolean
|
||||||
|
category: optional
|
||||||
|
description: attached via PCI(e) bus
|
||||||
|
generation: define
|
||||||
...
|
...
|
||||||
|
|
|
@ -69,13 +69,14 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c0: i2c@90007000 {
|
i2c0: i2c@0 {
|
||||||
compatible = "snps,designware-i2c";
|
compatible = "snps,designware-i2c";
|
||||||
clock-frequency = <I2C_BITRATE_STANDARD>;
|
clock-frequency = <I2C_BITRATE_STANDARD>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x90007000 0x400>;
|
pcie;
|
||||||
interrupts = <18 IRQ_TYPE_LEVEL_LOW 2>;
|
reg = <PCIE_BDF(0,21,2) PCIE_ID(0x8086,0x0934)>;
|
||||||
|
interrupts = <25 IRQ_TYPE_LEVEL_LOW 2>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
label = "I2C_0";
|
label = "I2C_0";
|
||||||
|
|
||||||
|
|
|
@ -85,18 +85,6 @@
|
||||||
#define DT_GPIO_DW_0_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW)
|
#define DT_GPIO_DW_0_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* I2C
|
|
||||||
*/
|
|
||||||
#define I2C_DW_0_PCI_VENDOR_ID 0x8086
|
|
||||||
#define I2C_DW_0_PCI_DEVICE_ID 0x0934
|
|
||||||
#define I2C_DW_0_PCI_CLASS 0x0C
|
|
||||||
|
|
||||||
#define I2C_DW_0_PCI_BUS 0
|
|
||||||
#define I2C_DW_0_PCI_DEV 21
|
|
||||||
#define I2C_DW_0_PCI_FUNCTION 2
|
|
||||||
#define I2C_DW_0_PCI_BAR 0
|
|
||||||
|
|
||||||
#ifdef CONFIG_IOAPIC
|
#ifdef CONFIG_IOAPIC
|
||||||
#define UART_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW)
|
#define UART_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW)
|
||||||
#endif /* CONFIG_IOAPIC */
|
#endif /* CONFIG_IOAPIC */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue