WIP: got i2c-aspeed-test passing on x86
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1a0be02..f125468 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -359,6 +359,13 @@
 
 menu "Processor type and features"
 
+config PLATFORM_MOCK
+	bool "Enable a mock architecture used for unit testing."
+	depends on TEST && OF
+	default y
+	help
+	  "Used for testing stuff."
+
 config ZONE_DMA
 	bool "DMA memory allocation support" if EXPERT
 	default y
diff --git a/arch/x86/include/asm/io-mock.h b/arch/x86/include/asm/io-mock.h
new file mode 100644
index 0000000..8620743
--- /dev/null
+++ b/arch/x86/include/asm/io-mock.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Mock IO functions.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@google.com>
+ */
+
+#ifndef _ASM_UM_IO_MOCK_H
+#define _ASM_UM_IO_MOCK_H
+
+#include <asm/io.h>
+#include <test/mock.h>
+
+DECLARE_FUNCTION_MOCK(kunit_readb,
+		      RETURNS(u8), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(kunit_readw,
+		      RETURNS(u16), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(kunit_readl,
+		      RETURNS(u32), PARAMS(const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK(kunit_readq,
+		      RETURNS(u64), PARAMS(const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writeb,
+				  PARAMS(u8, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writew,
+				  PARAMS(u16, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writel,
+				  PARAMS(u32, const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writeq,
+				  PARAMS(u64, const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+
+
+DECLARE_FUNCTION_MOCK(kunit_readb_relaxed,
+		      RETURNS(u8), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(kunit_readw_relaxed,
+		      RETURNS(u16), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(kunit_readl_relaxed,
+		      RETURNS(u32), PARAMS(const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK(kunit_readq_relaxed,
+		      RETURNS(u64), PARAMS(const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writeb_relaxed,
+				  PARAMS(u8, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writew_relaxed,
+				  PARAMS(u16, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writel_relaxed,
+				  PARAMS(u32, const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK_VOID_RETURN(kunit_writeq_relaxed,
+				  PARAMS(u64, const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+
+#endif /* _ASM_UM_IO_MOCK_H */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 6de6484..7ddad59 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -410,4 +410,34 @@
 extern bool phys_mem_access_encrypted(unsigned long phys_addr,
 				      unsigned long size);
 
+#if IS_ENABLED(CONFIG_PLATFORM_MOCK)
+#define kunit_readb kunit_readb
+u8 kunit_readb(const volatile void __iomem *);
+
+#define kunit_readw kunit_readw
+u16 kunit_readw(const volatile void __iomem *);
+
+#define kunit_readl kunit_readl
+u32 kunit_readl(const volatile void __iomem *);
+
+#ifdef CONFIG_64BIT
+#define kunit_readq kunit_readq
+u64 kunit_readq(const volatile void __iomem *);
+#endif /* CONFIG_64BIT */
+
+#define kunit_writeb kunit_writeb
+void kunit_writeb(u8, const volatile void __iomem *);
+
+#define kunit_writew kunit_writew
+void kunit_writew(u16, const volatile void __iomem *);
+
+#define kunit_writel kunit_writel
+void kunit_writel(u32, const volatile void __iomem *);
+
+#ifdef CONFIG_64BIT
+#define kunit_writeq kunit_writeq
+void kunit_writeq(u64, const volatile void __iomem *);
+#endif /* CONFIG_64BIT */
+#endif
+
 #endif /* _ASM_X86_IO_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 8824d01..20841e0 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -139,6 +139,8 @@
 obj-$(CONFIG_UNWINDER_FRAME_POINTER)	+= unwind_frame.o
 obj-$(CONFIG_UNWINDER_GUESS)		+= unwind_guess.o
 
+obj-$(CONFIG_PLATFORM_MOCK) += io-mock.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/io-mock.c b/arch/x86/kernel/io-mock.c
new file mode 100644
index 0000000..091397c
--- /dev/null
+++ b/arch/x86/kernel/io-mock.c
@@ -0,0 +1,32 @@
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <test/mock.h>
+
+DEFINE_FUNCTION_MOCK(kunit_readb,
+		     RETURNS(u8), PARAMS(const volatile void __iomem *));
+
+DEFINE_FUNCTION_MOCK(kunit_readw,
+		     RETURNS(u16), PARAMS(const volatile void __iomem *));
+
+DEFINE_FUNCTION_MOCK(kunit_readl,
+		     RETURNS(u32), PARAMS(const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DEFINE_FUNCTION_MOCK(kunit_readq,
+		     RETURNS(u64), PARAMS(const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+DEFINE_FUNCTION_MOCK_VOID_RETURN(kunit_writeb,
+				 PARAMS(u8, const volatile void __iomem *));
+
+DEFINE_FUNCTION_MOCK_VOID_RETURN(kunit_writew,
+				 PARAMS(u16, const volatile void __iomem *));
+
+DEFINE_FUNCTION_MOCK_VOID_RETURN(kunit_writel,
+				 PARAMS(u32, const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DEFINE_FUNCTION_MOCK_VOID_RETURN(kunit_writeq,
+				 PARAMS(u64, const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 0e65e60..112bcdf 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -8,7 +8,7 @@
 #include <linux/device.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
-#include <linux/mock.h>
+#include <test/mock.h>
 
 static void devm_clk_release(struct device *dev, void *res)
 {
@@ -81,7 +81,7 @@
 	return *c == data;
 }
 
-void devm_clk_put(struct device *dev, struct clk *clk)
+void __mockable devm_clk_put(struct device *dev, struct clk *clk)
 {
 	int ret;
 
diff --git a/drivers/i2c/busses/i2c-aspeed-test.c b/drivers/i2c/busses/i2c-aspeed-test.c
index 084f562..28956fc 100644
--- a/drivers/i2c/busses/i2c-aspeed-test.c
+++ b/drivers/i2c/busses/i2c-aspeed-test.c
@@ -45,6 +45,11 @@
 			    unsigned long,
 			    const char *,
 			    void *));
+DEFINE_FUNCTION_MOCK(devm_clk_get,
+		     RETURNS(struct clk *),
+		     PARAMS(struct device *, const char *));
+DEFINE_FUNCTION_MOCK_VOID_RETURN(devm_clk_put,
+				 PARAMS(struct device *, struct clk *));
 
 static void call_irq_handler(struct work_struct *work)
 {
@@ -339,6 +344,17 @@
 	aspeed_i2c_25xx_get_clk_reg_val_params_test(test, 2176, 7, 8, 7);
 }
 
+struct clk {
+	struct clk_core	*core;
+	struct device *dev;
+	const char *dev_id;
+	const char *con_id;
+	unsigned long min_rate;
+	unsigned long max_rate;
+	unsigned int exclusive_count;
+	struct hlist_node clks_node;
+};
+
 static int aspeed_i2c_test_init(struct test *test)
 {
 	struct mock_param_capturer *adap_capturer,
@@ -346,7 +362,9 @@
 				   *irq_ctx_capturer;
 	struct aspeed_i2c_fake *i2c_fake;
 	struct aspeed_i2c_test *ctx;
+	struct clk *clk;
 
+	clk = test_kzalloc(test, sizeof(*clk), GFP_KERNEL);
 	i2c_fake = aspeed_i2c_fake_init(test, schedule_irq_handler_call);
 	ctx = test_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
@@ -378,6 +396,8 @@
 						      any(test),
                                                       capturer_to_matcher(irq_ctx_capturer))),
                 int_return(test, 0));
+	Returns(EXPECT_CALL(devm_clk_get(any(test), any(test))), ptr_return(test, clk));
+	Returns(EXPECT_CALL(devm_clk_put(any(test), any(test))), int_return(test, 0));
 
 	adap_capturer = mock_ptr_capturer_create(test, any(test));
 	ActionOnMatch(EXPECT_CALL(
@@ -387,6 +407,8 @@
 	ctx->pdev = of_fake_probe_platform_by_name(test,
 						   "aspeed-i2c-bus",
 						   "test-i2c-bus");
+	/* Don't let mock expectations bleed into test cases. */
+	mock_validate_expectations(mock_get_global_mock());
 	ASSERT_NOT_ERR_OR_NULL(test, ctx->pdev);
 
 	ASSERT_PARAM_CAPTURED(test, adap_capturer);
@@ -396,9 +418,6 @@
 	ctx->irq_handler = mock_capturer_get(irq_capturer, irq_handler_t);
 	ctx->irq_ctx = mock_capturer_get(irq_ctx_capturer, void *);
 
-	/* Don't let mock expectations bleed into test cases. */
-	mock_validate_expectations(mock_get_global_mock());
-
 	INIT_WORK(&ctx->call_irq_handler, call_irq_handler);
 
 	ctx->test = test;
diff --git a/include/test/test.h b/include/test/test.h
index 1369963..b3b6644 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -942,8 +942,8 @@
 			      "Asserted " #ptr " is not null, but is.");       \
 	if (IS_ERR(__ptr))						       \
 		__stream->add(__stream,					       \
-			      "Asserted " #ptr " is not error, but is: %ld",   \
-			      strerror_r(-PTR_ERR(__ptr), buf, sizeof(buf)));  \
+			      "Asserted " #ptr " is not error, but is: %ld (%s)",   \
+			      -PTR_ERR(__ptr), strerror_r(-PTR_ERR(__ptr), buf, sizeof(buf)));  \
 									       \
 	ASSERT_END(test, !IS_ERR_OR_NULL(__ptr), __stream);		       \
 } while (0)