diff options
-rw-r--r-- | drivers/pch/pch-uclass.c | 10 | ||||
-rw-r--r-- | drivers/pch/sandbox_pch.c | 17 | ||||
-rw-r--r-- | include/pch.h | 48 | ||||
-rw-r--r-- | test/dm/pch.c | 19 |
4 files changed, 93 insertions, 1 deletions
diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c index 831b283d7b..caf8b72803 100644 --- a/drivers/pch/pch-uclass.c +++ b/drivers/pch/pch-uclass.c @@ -51,6 +51,16 @@ int pch_get_io_base(struct udevice *dev, u32 *iobasep) return ops->get_io_base(dev, iobasep); } +int pch_ioctl(struct udevice *dev, ulong req, void *data, int size) +{ + struct pch_ops *ops = pch_get_ops(dev); + + if (!ops->ioctl) + return -ENOSYS; + + return ops->ioctl(dev, req, data, size); +} + UCLASS_DRIVER(pch) = { .id = UCLASS_PCH, .name = "pch", diff --git a/drivers/pch/sandbox_pch.c b/drivers/pch/sandbox_pch.c index 81f8156c2e..76f552527e 100644 --- a/drivers/pch/sandbox_pch.c +++ b/drivers/pch/sandbox_pch.c @@ -48,11 +48,28 @@ static int sandbox_pch_get_io_base(struct udevice *dev, u32 *iobasep) return 0; } +int sandbox_pch_ioctl(struct udevice *dev, enum pch_req_t req, void *data, + int size) +{ + switch (req) { + case PCH_REQ_TEST1: + return -ENOSYS; + case PCH_REQ_TEST2: + return *(char *)data; + case PCH_REQ_TEST3: + *(char *)data = 'x'; + return 1; + default: + return -ENOSYS; + } +} + static const struct pch_ops sandbox_pch_ops = { .get_spi_base = sandbox_pch_get_spi_base, .set_spi_protect = sandbox_pch_set_spi_protect, .get_gpio_base = sandbox_pch_get_gpio_base, .get_io_base = sandbox_pch_get_io_base, + .ioctl = sandbox_pch_ioctl, }; static const struct udevice_id sandbox_pch_ids[] = { diff --git a/include/pch.h b/include/pch.h index 73994b8343..b8b62d74ac 100644 --- a/include/pch.h +++ b/include/pch.h @@ -11,7 +11,20 @@ #define BIOS_CTRL_BIOSWE BIT(0) -/* Operations for the Platform Controller Hub */ +/* All the supported PCH ioctls */ +enum pch_req_t { + PCH_REQ_TEST1, /* Test requests for sandbox driver */ + PCH_REQ_TEST2, + PCH_REQ_TEST3, + + PCH_REQ_COUNT, /* Number of ioctrls supported */ +}; + +/** + * struct pch_ops - Operations for the Platform Controller Hub + * + * Consider using ioctl() to add rarely used or driver-specific operations. + */ struct pch_ops { /** * get_spi_base() - get the address of SPI base @@ -49,6 +62,23 @@ struct pch_ops { * @return 0 if OK, -ve on error (e.g. there is no IO base) */ int (*get_io_base)(struct udevice *dev, u32 *iobasep); + + /** + * ioctl() - perform misc read/write operations + * + * This is a catch-all operation intended to avoid adding lots of + * methods to this uclass, of which few are commonly used. Uncommon + * operations that pertain only to a few devices in this uclass should + * use this method instead of adding new methods. + * + * @dev: PCH device to check + * @req: PCH request ID + * @data: Input/output data + * @size: Size of input data (and maximum size of output data) + * @return size of output data on sucesss, -ve on error + */ + int (*ioctl)(struct udevice *dev, enum pch_req_t req, void *data, + int size); }; #define pch_get_ops(dev) ((struct pch_ops *)(dev)->driver->ops) @@ -90,4 +120,20 @@ int pch_get_gpio_base(struct udevice *dev, u32 *gbasep); */ int pch_get_io_base(struct udevice *dev, u32 *iobasep); +/** + * pch_ioctl() - perform misc read/write operations + * + * This is a catch-all operation intended to avoid adding lots of + * methods to this uclass, of which few are commonly used. Uncommon + * operations that pertain only to a few devices in this uclass should + * use this method instead of adding new methods. + * + * @dev: PCH device to check + * @req: PCH request ID + * @data: Input/output data + * @size: Size of input data (and maximum size of output data) + * @return size of output data on sucesss, -ve on error + */ +int pch_ioctl(struct udevice *dev, ulong req, void *data, int size); + #endif diff --git a/test/dm/pch.c b/test/dm/pch.c index f184445342..54e33d187b 100644 --- a/test/dm/pch.c +++ b/test/dm/pch.c @@ -34,3 +34,22 @@ static int dm_test_pch_base(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_pch_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test sandbox PCH ioctl */ +static int dm_test_pch_ioctl(struct unit_test_state *uts) +{ + struct udevice *dev; + char data; + + ut_assertok(uclass_first_device_err(UCLASS_PCH, &dev)); + + ut_asserteq(-ENOSYS, pch_ioctl(dev, PCH_REQ_TEST1, NULL, 0)); + + ut_asserteq('a', pch_ioctl(dev, PCH_REQ_TEST2, "a", 1)); + + ut_asserteq(1, pch_ioctl(dev, PCH_REQ_TEST3, &data, 1)); + ut_asserteq('x', data); + + return 0; +} +DM_TEST(dm_test_pch_ioctl, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); |