#include <kunit/test.h>
#include "irq-ast2700.h"
static void aspeed_intc0_resolve_route_bad_args(struct kunit *test)
{
static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 };
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
const struct irq_domain c0domain = { 0 };
int rc;
rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL);
KUNIT_EXPECT_EQ(test, rc, -EINVAL);
rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, -ENOENT);
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
0, c1ranges, &resolved);
KUNIT_EXPECT_EQ(test, rc, -ENOENT);
}
static int gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode,
const char *propname, const char **val, size_t nval)
{
if (!propname)
return -EINVAL;
if (!val)
return 1;
if (WARN_ON(nval != 1))
return -EOVERFLOW;
*val = "arm,gic-v3";
return 1;
}
static const struct fwnode_operations arm_gicv3_fwnode_ops = {
.property_read_string_array = gicv3_fwnode_read_string_array,
};
static void aspeed_intc_resolve_route_invalid_c0domain(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &arm_gicv3_fwnode_ops },
};
const struct irq_domain c0domain = { .fwnode = &intc0_node.fwnode };
static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 };
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_NE(test, rc, 0);
}
static int
aspeed_intc0_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle,
const char *propname, const char **val,
size_t nval)
{
if (!propname)
return -EINVAL;
if (!val)
return 1;
if (WARN_ON(nval != 1))
return -EOVERFLOW;
*val = "aspeed,ast2700-intc0";
return nval;
}
static const struct fwnode_operations intc0_fwnode_ops = {
.property_read_string_array = aspeed_intc0_fwnode_read_string_array,
};
static void
aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 128 }
}
}
};
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 128,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = { .ranges = intc0_ranges, .nranges = ARRAY_SIZE(intc0_ranges), }
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, resolved.start, 0);
KUNIT_EXPECT_EQ(test, resolved.count, 1);
KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 128);
}
static void
aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 128 }
}
}
};
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 129,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_NE(test, rc, 0);
}
static void aspeed_intc0_resolve_route_c1i1o1mc0i1o1(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 480 }
}
}
};
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 192,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, resolved.start, 0);
KUNIT_EXPECT_EQ(test, resolved.count, 1);
KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480);
}
static void aspeed_intc0_resolve_route_c1i2o2mc0i1o1(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 480 }
}
},
{
.start = 1,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 510 }
}
}
};
static const u32 c1outs[] = { 1 };
struct aspeed_intc_interrupt_range resolved;
static struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 208,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, resolved.start, 1);
KUNIT_EXPECT_EQ(test, resolved.count, 1);
KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510);
}
static void aspeed_intc0_resolve_route_c1i1o1mc0i2o1(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 510 }
}
},
};
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
static struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 192,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = {0},
}
},
{
.start = 208,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = {0},
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, resolved.start, 0);
KUNIT_EXPECT_EQ(test, resolved.count, 1);
KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510);
}
static void aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 1,
.param = { 480 }
}
}
};
static const u32 c1outs[] = {
AST2700_INTC_INVALID_ROUTE, 0
};
struct aspeed_intc_interrupt_range resolved;
struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 192,
.count = 1,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_EQ(test, rc, 1);
KUNIT_EXPECT_EQ(test, resolved.start, 0);
KUNIT_EXPECT_EQ(test, resolved.count, 1);
KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480);
}
static void
aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream(struct kunit *test)
{
struct device_node intc0_node = {
.fwnode = { .ops = &intc0_fwnode_ops },
};
struct aspeed_intc_interrupt_range c1ranges[] = {
{
.start = 0,
.count = 1,
.upstream = {
.fwnode = &intc0_node.fwnode,
.param_count = 0,
.param = { 0 }
}
}
};
static const u32 c1outs[] = { 0 };
struct aspeed_intc_interrupt_range resolved;
struct aspeed_intc_interrupt_range intc0_ranges[] = {
{
.start = 0,
.count = 0,
.upstream = {
.fwnode = NULL,
.param_count = 0,
.param = { 0 },
}
}
};
struct aspeed_intc0 intc0 = {
.ranges = {
.ranges = intc0_ranges,
.nranges = ARRAY_SIZE(intc0_ranges),
}
};
const struct irq_domain c0domain = {
.host_data = &intc0,
.fwnode = &intc0_node.fwnode
};
int rc;
rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs,
ARRAY_SIZE(c1ranges), c1ranges,
&resolved);
KUNIT_EXPECT_NE(test, rc, 0);
}
static struct kunit_case ast2700_intc0_test_cases[] = {
KUNIT_CASE(aspeed_intc0_resolve_route_bad_args),
KUNIT_CASE(aspeed_intc_resolve_route_invalid_c0domain),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i2o2mc0i1o1),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i2o1),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid),
KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream),
{},
};
static struct kunit_suite ast2700_intc0_test_suite = {
.name = "ast2700-intc0",
.test_cases = ast2700_intc0_test_cases,
};
kunit_test_suite(ast2700_intc0_test_suite);
MODULE_LICENSE("GPL");