soc/amd/common/block/i2c: Move SoC agnostic parts into common
The logic behind I2C bus initialization, I2C MMIO base address getter
and setter, I2C bus ACPI name resolution are identical for all the AMD
SoCs. Hence moving all the SoC agnotic parts of the driver into the
common driver and just configure the SoC specific parts into individual
I2C drivers.
BUG=None
TEST=Build Dalboz and Grunt. Boot to OS in Dalboz. Ensure that the I2C
peripherals are detected as earlier in Dalboz. Verify some I2C
peripheral functionality like trackpad and touchscreen.
Change-Id: Ic9c99ec769d7d8ad7e1e566fdf42a5206657183d
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Suggested-by: Kyosti Malkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51509
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/amd/stoneyridge/chip.c b/src/soc/amd/stoneyridge/chip.c
index 8082165..fbf205e 100644
--- a/src/soc/amd/stoneyridge/chip.c
+++ b/src/soc/amd/stoneyridge/chip.c
@@ -14,12 +14,12 @@
#include <amdblocks/psp.h>
#include <amdblocks/agesawrapper.h>
#include <amdblocks/agesawrapper_call.h>
+#include <amdblocks/i2c.h>
#include "chip.h"
/* Supplied by i2c.c */
-extern struct device_operations stoneyridge_i2c_mmio_ops;
-extern const char *i2c_acpi_name(const struct device *dev);
+extern struct device_operations soc_amd_i2c_mmio_ops;
struct device_operations cpu_bus_ops = {
.read_resources = noop_read_resources,
@@ -98,6 +98,18 @@
.acpi_name = soc_acpi_name,
};
+static void set_mmio_dev_ops(struct device *dev)
+{
+ switch (dev->path.mmio.addr) {
+ case I2CA_BASE_ADDRESS:
+ case I2CB_BASE_ADDRESS:
+ case I2CC_BASE_ADDRESS:
+ case I2CD_BASE_ADDRESS:
+ dev->ops = &soc_amd_i2c_mmio_ops;
+ break;
+ }
+}
+
static void enable_dev(struct device *dev)
{
/* Set the operations if it is a special bus type */
@@ -109,8 +121,7 @@
dev->ops = &cpu_bus_ops;
break;
case DEVICE_PATH_MMIO:
- if (i2c_acpi_name(dev) != NULL)
- dev->ops = &stoneyridge_i2c_mmio_ops;
+ set_mmio_dev_ops(dev);
break;
default:
break;
diff --git a/src/soc/amd/stoneyridge/i2c.c b/src/soc/amd/stoneyridge/i2c.c
index 7b0bc77..a098775 100644
--- a/src/soc/amd/stoneyridge/i2c.c
+++ b/src/soc/amd/stoneyridge/i2c.c
@@ -1,118 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-#include <device/mmio.h>
-#include <acpi/acpi.h>
-#include <console/console.h>
-#include <delay.h>
-#include <device/device.h>
-#include <drivers/i2c/designware/dw_i2c.h>
#include <amdblocks/acpimmio.h>
#include <amdblocks/i2c.h>
#include <soc/iomap.h>
-#include <soc/pci_devs.h>
-#include <soc/southbridge.h>
#include <soc/i2c.h>
#include "chip.h"
-#define I2C_BUS_ADDRESS(x) (I2C_BASE_ADDRESS + I2C_DEVICE_SIZE * (x))
-#define I2CA_BASE_ADDRESS (I2C_BUS_ADDRESS(0))
-#define I2CB_BASE_ADDRESS (I2C_BUS_ADDRESS(1))
-#define I2CC_BASE_ADDRESS (I2C_BUS_ADDRESS(2))
-#define I2CD_BASE_ADDRESS (I2C_BUS_ADDRESS(3))
-
-/* Global to provide access to chip.c */
-const char *i2c_acpi_name(const struct device *dev);
-
-static const uintptr_t i2c_bus_address[] = {
- I2CA_BASE_ADDRESS,
- I2CB_BASE_ADDRESS,
- I2CC_BASE_ADDRESS,
- I2CD_BASE_ADDRESS,
+static const struct soc_i2c_ctrlr_info i2c_ctrlr[] = {
+ { I2C_MASTER_MODE, I2CA_BASE_ADDRESS, "I2CA" },
+ { I2C_MASTER_MODE, I2CB_BASE_ADDRESS, "I2CB" },
+ { I2C_MASTER_MODE, I2CC_BASE_ADDRESS, "I2CC" },
+ { I2C_MASTER_MODE, I2CD_BASE_ADDRESS, "I2CD" },
};
-uintptr_t dw_i2c_base_address(unsigned int bus)
+const struct soc_i2c_ctrlr_info *soc_get_i2c_ctrlr_info(size_t *num_ctrlrs)
{
- return bus < I2C_DEVICE_COUNT ? i2c_bus_address[bus] : 0;
+ *num_ctrlrs = ARRAY_SIZE(i2c_ctrlr);
+ return i2c_ctrlr;
}
-const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
+const struct dw_i2c_bus_config *soc_get_i2c_bus_config(size_t *num_buses)
{
- const struct soc_amd_stoneyridge_config *config;
+ const struct soc_amd_stoneyridge_config *config = config_of_soc();
- if (bus >= ARRAY_SIZE(i2c_bus_address))
- return NULL;
-
- /* config is not NULL; if it was, config_of_soc calls die() internally */
- config = config_of_soc();
-
- return &config->i2c[bus];
+ *num_buses = ARRAY_SIZE(config->i2c);
+ return config->i2c;
}
-
-const char *i2c_acpi_name(const struct device *dev)
-{
- switch (dev->path.mmio.addr) {
- case I2CA_BASE_ADDRESS:
- return "I2CA";
- case I2CB_BASE_ADDRESS:
- return "I2CB";
- case I2CC_BASE_ADDRESS:
- return "I2CC";
- case I2CD_BASE_ADDRESS:
- return "I2CD";
- default:
- return NULL;
- }
-}
-
-int dw_i2c_soc_dev_to_bus(const struct device *dev)
-{
- switch (dev->path.mmio.addr) {
- case I2CA_BASE_ADDRESS:
- return 0;
- case I2CB_BASE_ADDRESS:
- return 1;
- case I2CC_BASE_ADDRESS:
- return 2;
- case I2CD_BASE_ADDRESS:
- return 3;
- }
- return -1;
-}
-
-static void dw_i2c_soc_init(bool is_early_init)
-{
- size_t i;
- const struct soc_amd_stoneyridge_config *config;
-
- /* config is not NULL; if it was, config_of_soc calls die() internally */
- config = config_of_soc();
-
- for (i = 0; i < ARRAY_SIZE(config->i2c); i++) {
- const struct dw_i2c_bus_config *cfg = &config->i2c[i];
-
- if (cfg->early_init != is_early_init)
- continue;
-
- if (dw_i2c_init(i, cfg))
- printk(BIOS_ERR, "Failed to init i2c bus %zd\n", i);
- }
-}
-
-void i2c_soc_early_init(void)
-{
- dw_i2c_soc_init(true);
-}
-
-void i2c_soc_init(void)
-{
- dw_i2c_soc_init(false);
-}
-
-struct device_operations stoneyridge_i2c_mmio_ops = {
- /* TODO(teravest): Move I2C resource info here. */
- .read_resources = noop_read_resources,
- .set_resources = noop_set_resources,
- .scan_bus = scan_smbus,
- .acpi_name = i2c_acpi_name,
- .acpi_fill_ssdt = dw_i2c_acpi_fill_ssdt,
-};
diff --git a/src/soc/amd/stoneyridge/include/soc/iomap.h b/src/soc/amd/stoneyridge/include/soc/iomap.h
index 7832dad..b3c78e8 100644
--- a/src/soc/amd/stoneyridge/include/soc/iomap.h
+++ b/src/soc/amd/stoneyridge/include/soc/iomap.h
@@ -15,6 +15,12 @@
#define I2C_DEVICE_SIZE 0x00001000
#define I2C_DEVICE_COUNT 4
+#define I2C_BUS_ADDRESS(x) (I2C_BASE_ADDRESS + I2C_DEVICE_SIZE * (x))
+#define I2CA_BASE_ADDRESS (I2C_BUS_ADDRESS(0))
+#define I2CB_BASE_ADDRESS (I2C_BUS_ADDRESS(1))
+#define I2CC_BASE_ADDRESS (I2C_BUS_ADDRESS(2))
+#define I2CD_BASE_ADDRESS (I2C_BUS_ADDRESS(3))
+
#if CONFIG(HPET_ADDRESS_OVERRIDE)
#error HPET address override is not allowed and must be fixed at 0xfed00000
#endif
diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h
index 9480e8b..8aa881b 100644
--- a/src/soc/amd/stoneyridge/include/soc/southbridge.h
+++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h
@@ -250,10 +250,4 @@
int mainboard_get_xhci_oc_map(uint16_t *usb_oc_map);
int mainboard_get_ehci_oc_map(uint16_t *usb_oc_map);
-/* Initialize all the i2c buses that are marked with early init. */
-void i2c_soc_early_init(void);
-
-/* Initialize all the i2c buses that are not marked with early init. */
-void i2c_soc_init(void);
-
#endif /* AMD_STONEYRIDGE_SOUTHBRIDGE_H */