1a6d2a3b4SBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0-or-later 2a6d2a3b4SBartosz Golaszewski /* 3a6d2a3b4SBartosz Golaszewski * Copyright (C) Qualcomm Technologies, Inc. and/or its subsidiaries 4a6d2a3b4SBartosz Golaszewski */ 5a6d2a3b4SBartosz Golaszewski 6*9672edf7SBartosz Golaszewski #include <linux/cleanup.h> 7*9672edf7SBartosz Golaszewski #include <linux/err.h> 8a6d2a3b4SBartosz Golaszewski #include <linux/fwnode.h> 9a6d2a3b4SBartosz Golaszewski #include <linux/gpio/consumer.h> 10a6d2a3b4SBartosz Golaszewski #include <linux/gpio/driver.h> 11a6d2a3b4SBartosz Golaszewski #include <linux/gpio/machine.h> 12a6d2a3b4SBartosz Golaszewski #include <linux/gpio/property.h> 13a6d2a3b4SBartosz Golaszewski #include <linux/notifier.h> 14a6d2a3b4SBartosz Golaszewski #include <linux/platform_device.h> 15a6d2a3b4SBartosz Golaszewski #include <linux/property.h> 16*9672edf7SBartosz Golaszewski #include <linux/types.h> 17a6d2a3b4SBartosz Golaszewski 18*9672edf7SBartosz Golaszewski #include <kunit/fwnode.h> 19a6d2a3b4SBartosz Golaszewski #include <kunit/platform_device.h> 20a6d2a3b4SBartosz Golaszewski #include <kunit/test.h> 21a6d2a3b4SBartosz Golaszewski 22a6d2a3b4SBartosz Golaszewski #define GPIO_TEST_PROVIDER "gpio-test-provider" 23a6d2a3b4SBartosz Golaszewski #define GPIO_SWNODE_TEST_CONSUMER "gpio-swnode-test-consumer" 24*9672edf7SBartosz Golaszewski #define GPIO_PROBE_ORDER_TEST_CONSUMER "gpio-probe-order-test-consumer" 25*9672edf7SBartosz Golaszewski #define GPIO_PROBE_DEFER_TEST_CONSUMER "gpio-probe-defer-test-consumer" 26a6d2a3b4SBartosz Golaszewski #define GPIO_UNBIND_TEST_CONSUMER "gpio-unbind-test-consumer" 27a05cfd98SBartosz Golaszewski #define GPIO_CONSUMER_NAME "gpio-swnode-consumer-test-device" 28a05cfd98SBartosz Golaszewski 29a05cfd98SBartosz Golaszewski #define GPIO_TEST_PROVIDER_NGPIO 4 30a05cfd98SBartosz Golaszewski 31a05cfd98SBartosz Golaszewski /* 32a05cfd98SBartosz Golaszewski * The test provider tracks per-line direction and value so that lines can be 33a05cfd98SBartosz Golaszewski * driven as both inputs and outputs - this is needed to exercise input as well 34a05cfd98SBartosz Golaszewski * as output GPIO hogs. 35a05cfd98SBartosz Golaszewski */ 36a05cfd98SBartosz Golaszewski struct gpio_test_provider_data { 37a05cfd98SBartosz Golaszewski DECLARE_BITMAP(is_output, GPIO_TEST_PROVIDER_NGPIO); 38a05cfd98SBartosz Golaszewski DECLARE_BITMAP(values, GPIO_TEST_PROVIDER_NGPIO); 39a05cfd98SBartosz Golaszewski }; 40a6d2a3b4SBartosz Golaszewski 41a6d2a3b4SBartosz Golaszewski static int gpio_test_provider_get_direction(struct gpio_chip *gc, unsigned int offset) 42a6d2a3b4SBartosz Golaszewski { 43a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data = gpiochip_get_data(gc); 44a05cfd98SBartosz Golaszewski 45a05cfd98SBartosz Golaszewski return test_bit(offset, data->is_output) ? 46a05cfd98SBartosz Golaszewski GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 47a05cfd98SBartosz Golaszewski } 48a05cfd98SBartosz Golaszewski 49a05cfd98SBartosz Golaszewski static int gpio_test_provider_direction_input(struct gpio_chip *gc, unsigned int offset) 50a05cfd98SBartosz Golaszewski { 51a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data = gpiochip_get_data(gc); 52a05cfd98SBartosz Golaszewski 53a05cfd98SBartosz Golaszewski clear_bit(offset, data->is_output); 54a05cfd98SBartosz Golaszewski 55a05cfd98SBartosz Golaszewski return 0; 56a05cfd98SBartosz Golaszewski } 57a05cfd98SBartosz Golaszewski 58a05cfd98SBartosz Golaszewski static int gpio_test_provider_direction_output(struct gpio_chip *gc, unsigned int offset, 59a05cfd98SBartosz Golaszewski int value) 60a05cfd98SBartosz Golaszewski { 61a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data = gpiochip_get_data(gc); 62a05cfd98SBartosz Golaszewski 63a05cfd98SBartosz Golaszewski set_bit(offset, data->is_output); 64a05cfd98SBartosz Golaszewski __assign_bit(offset, data->values, value); 65a05cfd98SBartosz Golaszewski 66a05cfd98SBartosz Golaszewski return 0; 67a05cfd98SBartosz Golaszewski } 68a05cfd98SBartosz Golaszewski 69a05cfd98SBartosz Golaszewski static int gpio_test_provider_get(struct gpio_chip *gc, unsigned int offset) 70a05cfd98SBartosz Golaszewski { 71a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data = gpiochip_get_data(gc); 72a05cfd98SBartosz Golaszewski 73a05cfd98SBartosz Golaszewski return test_bit(offset, data->values); 74a6d2a3b4SBartosz Golaszewski } 75a6d2a3b4SBartosz Golaszewski 76a6d2a3b4SBartosz Golaszewski static int gpio_test_provider_set(struct gpio_chip *gc, unsigned int offset, int value) 77a6d2a3b4SBartosz Golaszewski { 78a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data = gpiochip_get_data(gc); 79a05cfd98SBartosz Golaszewski 80a05cfd98SBartosz Golaszewski __assign_bit(offset, data->values, value); 81a05cfd98SBartosz Golaszewski 82a6d2a3b4SBartosz Golaszewski return 0; 83a6d2a3b4SBartosz Golaszewski } 84a6d2a3b4SBartosz Golaszewski 85a6d2a3b4SBartosz Golaszewski static int gpio_test_provider_probe(struct platform_device *pdev) 86a6d2a3b4SBartosz Golaszewski { 87a05cfd98SBartosz Golaszewski struct gpio_test_provider_data *data; 88a6d2a3b4SBartosz Golaszewski struct device *dev = &pdev->dev; 89a6d2a3b4SBartosz Golaszewski struct gpio_chip *gc; 90a6d2a3b4SBartosz Golaszewski 91a6d2a3b4SBartosz Golaszewski gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); 92a6d2a3b4SBartosz Golaszewski if (!gc) 93a6d2a3b4SBartosz Golaszewski return -ENOMEM; 94a6d2a3b4SBartosz Golaszewski 95a05cfd98SBartosz Golaszewski data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 96a05cfd98SBartosz Golaszewski if (!data) 97a05cfd98SBartosz Golaszewski return -ENOMEM; 98a05cfd98SBartosz Golaszewski 99a05cfd98SBartosz Golaszewski /* Lines start as outputs to preserve the default for lookup tests. */ 100a05cfd98SBartosz Golaszewski bitmap_fill(data->is_output, GPIO_TEST_PROVIDER_NGPIO); 101a05cfd98SBartosz Golaszewski 102a6d2a3b4SBartosz Golaszewski gc->base = -1; 103a05cfd98SBartosz Golaszewski gc->ngpio = GPIO_TEST_PROVIDER_NGPIO; 104a05cfd98SBartosz Golaszewski gc->label = GPIO_CONSUMER_NAME; 105a6d2a3b4SBartosz Golaszewski gc->parent = dev; 106a6d2a3b4SBartosz Golaszewski gc->owner = THIS_MODULE; 107a6d2a3b4SBartosz Golaszewski 108a6d2a3b4SBartosz Golaszewski gc->get_direction = gpio_test_provider_get_direction; 109a05cfd98SBartosz Golaszewski gc->direction_input = gpio_test_provider_direction_input; 110a05cfd98SBartosz Golaszewski gc->direction_output = gpio_test_provider_direction_output; 111a05cfd98SBartosz Golaszewski gc->get = gpio_test_provider_get; 112a6d2a3b4SBartosz Golaszewski gc->set = gpio_test_provider_set; 113a6d2a3b4SBartosz Golaszewski 114a05cfd98SBartosz Golaszewski return devm_gpiochip_add_data(dev, gc, data); 115a6d2a3b4SBartosz Golaszewski } 116a6d2a3b4SBartosz Golaszewski 117a6d2a3b4SBartosz Golaszewski static struct platform_driver gpio_test_provider_driver = { 118a6d2a3b4SBartosz Golaszewski .probe = gpio_test_provider_probe, 119a6d2a3b4SBartosz Golaszewski .driver = { 120a6d2a3b4SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 121a6d2a3b4SBartosz Golaszewski }, 122a6d2a3b4SBartosz Golaszewski }; 123a6d2a3b4SBartosz Golaszewski 124a6d2a3b4SBartosz Golaszewski static const struct software_node gpio_test_provider_swnode = { 125a6d2a3b4SBartosz Golaszewski .name = "gpio-test-provider-primary", 126a6d2a3b4SBartosz Golaszewski }; 127a6d2a3b4SBartosz Golaszewski 128a6d2a3b4SBartosz Golaszewski struct gpio_swnode_consumer_pdata { 129a6d2a3b4SBartosz Golaszewski bool gpio_ok; 130a05cfd98SBartosz Golaszewski int errno; 131a6d2a3b4SBartosz Golaszewski }; 132a6d2a3b4SBartosz Golaszewski 133a6d2a3b4SBartosz Golaszewski static const struct gpio_swnode_consumer_pdata gpio_swnode_pdata_template = { 134a6d2a3b4SBartosz Golaszewski .gpio_ok = false, 135a05cfd98SBartosz Golaszewski .errno = 0, 136a6d2a3b4SBartosz Golaszewski }; 137a6d2a3b4SBartosz Golaszewski 138a6d2a3b4SBartosz Golaszewski static int gpio_swnode_consumer_probe(struct platform_device *pdev) 139a6d2a3b4SBartosz Golaszewski { 140a6d2a3b4SBartosz Golaszewski struct device *dev = &pdev->dev; 141a6d2a3b4SBartosz Golaszewski struct gpio_swnode_consumer_pdata *pdata = dev_get_platdata(dev); 142a6d2a3b4SBartosz Golaszewski struct gpio_desc *desc; 143a6d2a3b4SBartosz Golaszewski 144a6d2a3b4SBartosz Golaszewski desc = devm_gpiod_get(dev, "foo", GPIOD_OUT_HIGH); 145a05cfd98SBartosz Golaszewski if (IS_ERR(desc)) { 146a05cfd98SBartosz Golaszewski pdata->errno = PTR_ERR(desc); 147a6d2a3b4SBartosz Golaszewski return PTR_ERR(desc); 148a05cfd98SBartosz Golaszewski } 149a6d2a3b4SBartosz Golaszewski 150a6d2a3b4SBartosz Golaszewski pdata->gpio_ok = true; 151a6d2a3b4SBartosz Golaszewski 152a6d2a3b4SBartosz Golaszewski return 0; 153a6d2a3b4SBartosz Golaszewski } 154a6d2a3b4SBartosz Golaszewski 155a6d2a3b4SBartosz Golaszewski static struct platform_driver gpio_swnode_consumer_driver = { 156a6d2a3b4SBartosz Golaszewski .probe = gpio_swnode_consumer_probe, 157a6d2a3b4SBartosz Golaszewski .driver = { 158a6d2a3b4SBartosz Golaszewski .name = GPIO_SWNODE_TEST_CONSUMER, 159a6d2a3b4SBartosz Golaszewski }, 160a6d2a3b4SBartosz Golaszewski }; 161a6d2a3b4SBartosz Golaszewski 162069547f9SBartosz Golaszewski static int gpio_swnode_register_drivers(struct kunit *test) 163a6d2a3b4SBartosz Golaszewski { 164a6d2a3b4SBartosz Golaszewski int ret; 165a6d2a3b4SBartosz Golaszewski 166a6d2a3b4SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_test_provider_driver); 167a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 168a6d2a3b4SBartosz Golaszewski 169a6d2a3b4SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_swnode_consumer_driver); 170a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 171a6d2a3b4SBartosz Golaszewski 172069547f9SBartosz Golaszewski return 0; 173069547f9SBartosz Golaszewski } 174069547f9SBartosz Golaszewski 175069547f9SBartosz Golaszewski static void gpio_swnode_lookup_by_primary(struct kunit *test) 176069547f9SBartosz Golaszewski { 177069547f9SBartosz Golaszewski struct gpio_swnode_consumer_pdata *pdata; 178069547f9SBartosz Golaszewski struct platform_device_info pdevinfo; 179069547f9SBartosz Golaszewski struct property_entry properties[2]; 180069547f9SBartosz Golaszewski struct platform_device *pdev; 181069547f9SBartosz Golaszewski bool bound = false; 182069547f9SBartosz Golaszewski 183a6d2a3b4SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 184a6d2a3b4SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 185a6d2a3b4SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 186a6d2a3b4SBartosz Golaszewski .swnode = &gpio_test_provider_swnode, 187a6d2a3b4SBartosz Golaszewski }; 188a6d2a3b4SBartosz Golaszewski 189a6d2a3b4SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 190a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 191a6d2a3b4SBartosz Golaszewski 192a6d2a3b4SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 193a6d2a3b4SBartosz Golaszewski &gpio_test_provider_swnode, 194a6d2a3b4SBartosz Golaszewski 0, GPIO_ACTIVE_HIGH); 195a6d2a3b4SBartosz Golaszewski properties[1] = (struct property_entry){ }; 196a6d2a3b4SBartosz Golaszewski 197a6d2a3b4SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 198a6d2a3b4SBartosz Golaszewski .name = GPIO_SWNODE_TEST_CONSUMER, 199a6d2a3b4SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 200a6d2a3b4SBartosz Golaszewski .data = &gpio_swnode_pdata_template, 201a6d2a3b4SBartosz Golaszewski .size_data = sizeof(gpio_swnode_pdata_template), 202a6d2a3b4SBartosz Golaszewski .properties = properties, 203a6d2a3b4SBartosz Golaszewski }; 204a6d2a3b4SBartosz Golaszewski 205a6d2a3b4SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 206a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 207a6d2a3b4SBartosz Golaszewski 208a6d2a3b4SBartosz Golaszewski wait_for_device_probe(); 209a6d2a3b4SBartosz Golaszewski scoped_guard(device, &pdev->dev) 210a6d2a3b4SBartosz Golaszewski bound = device_is_bound(&pdev->dev); 211a6d2a3b4SBartosz Golaszewski 212a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 213a6d2a3b4SBartosz Golaszewski 214a6d2a3b4SBartosz Golaszewski pdata = dev_get_platdata(&pdev->dev); 215a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, pdata->gpio_ok); 216a6d2a3b4SBartosz Golaszewski } 217a6d2a3b4SBartosz Golaszewski 218a6d2a3b4SBartosz Golaszewski static void gpio_swnode_lookup_by_secondary(struct kunit *test) 219a6d2a3b4SBartosz Golaszewski { 220a6d2a3b4SBartosz Golaszewski struct gpio_swnode_consumer_pdata *pdata; 221a6d2a3b4SBartosz Golaszewski struct platform_device_info pdevinfo; 222a6d2a3b4SBartosz Golaszewski struct property_entry properties[2]; 223a6d2a3b4SBartosz Golaszewski struct fwnode_handle *primary; 224a6d2a3b4SBartosz Golaszewski struct platform_device *pdev; 225a6d2a3b4SBartosz Golaszewski bool bound = false; 226a6d2a3b4SBartosz Golaszewski 227a6d2a3b4SBartosz Golaszewski /* 228a6d2a3b4SBartosz Golaszewski * Can't live on the stack as it will still get referenced in cleanup 229a6d2a3b4SBartosz Golaszewski * path after this function returns. 230a6d2a3b4SBartosz Golaszewski */ 231a6d2a3b4SBartosz Golaszewski primary = kunit_kzalloc(test, sizeof(*primary), GFP_KERNEL); 232a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, primary); 233a6d2a3b4SBartosz Golaszewski 234a6d2a3b4SBartosz Golaszewski fwnode_init(primary, NULL); 235a6d2a3b4SBartosz Golaszewski 236a6d2a3b4SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 237a6d2a3b4SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 238a6d2a3b4SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 239a6d2a3b4SBartosz Golaszewski .fwnode = primary, 240a6d2a3b4SBartosz Golaszewski .swnode = &gpio_test_provider_swnode, 241a6d2a3b4SBartosz Golaszewski }; 242a6d2a3b4SBartosz Golaszewski 243a6d2a3b4SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 244a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 245a6d2a3b4SBartosz Golaszewski 246a6d2a3b4SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 247a6d2a3b4SBartosz Golaszewski &gpio_test_provider_swnode, 248a6d2a3b4SBartosz Golaszewski 0, GPIO_ACTIVE_HIGH); 249a6d2a3b4SBartosz Golaszewski properties[1] = (struct property_entry){ }; 250a6d2a3b4SBartosz Golaszewski 251a6d2a3b4SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 252a6d2a3b4SBartosz Golaszewski .name = GPIO_SWNODE_TEST_CONSUMER, 253a6d2a3b4SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 254a6d2a3b4SBartosz Golaszewski .data = &gpio_swnode_pdata_template, 255a6d2a3b4SBartosz Golaszewski .size_data = sizeof(gpio_swnode_pdata_template), 256a6d2a3b4SBartosz Golaszewski .properties = properties, 257a6d2a3b4SBartosz Golaszewski }; 258a6d2a3b4SBartosz Golaszewski 259a6d2a3b4SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 260a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 261a6d2a3b4SBartosz Golaszewski 262a6d2a3b4SBartosz Golaszewski wait_for_device_probe(); 263a6d2a3b4SBartosz Golaszewski scoped_guard(device, &pdev->dev) 264a6d2a3b4SBartosz Golaszewski bound = device_is_bound(&pdev->dev); 265a6d2a3b4SBartosz Golaszewski 266a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 267a6d2a3b4SBartosz Golaszewski 268a6d2a3b4SBartosz Golaszewski pdata = dev_get_platdata(&pdev->dev); 269a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, pdata->gpio_ok); 270a6d2a3b4SBartosz Golaszewski } 271a6d2a3b4SBartosz Golaszewski 272a6d2a3b4SBartosz Golaszewski static struct kunit_case gpio_swnode_lookup_tests[] = { 273a6d2a3b4SBartosz Golaszewski KUNIT_CASE(gpio_swnode_lookup_by_primary), 274a6d2a3b4SBartosz Golaszewski KUNIT_CASE(gpio_swnode_lookup_by_secondary), 275a6d2a3b4SBartosz Golaszewski { } 276a6d2a3b4SBartosz Golaszewski }; 277a6d2a3b4SBartosz Golaszewski 278a6d2a3b4SBartosz Golaszewski static struct kunit_suite gpio_swnode_lookup_test_suite = { 279a6d2a3b4SBartosz Golaszewski .name = "gpio-swnode-lookup", 280a6d2a3b4SBartosz Golaszewski .test_cases = gpio_swnode_lookup_tests, 281069547f9SBartosz Golaszewski .init = gpio_swnode_register_drivers, 282a6d2a3b4SBartosz Golaszewski }; 283a6d2a3b4SBartosz Golaszewski 284*9672edf7SBartosz Golaszewski static void gpio_swnode_unregister_swnode(void *data) 285*9672edf7SBartosz Golaszewski { 286*9672edf7SBartosz Golaszewski software_node_unregister(data); 287*9672edf7SBartosz Golaszewski } 288*9672edf7SBartosz Golaszewski 289*9672edf7SBartosz Golaszewski struct gpio_probe_order_pdata { 290*9672edf7SBartosz Golaszewski unsigned int probe_count; 291*9672edf7SBartosz Golaszewski bool gpio_ok; 292*9672edf7SBartosz Golaszewski }; 293*9672edf7SBartosz Golaszewski 294*9672edf7SBartosz Golaszewski static const struct gpio_probe_order_pdata gpio_probe_order_pdata_template = { 295*9672edf7SBartosz Golaszewski .probe_count = 0, 296*9672edf7SBartosz Golaszewski .gpio_ok = false, 297*9672edf7SBartosz Golaszewski }; 298*9672edf7SBartosz Golaszewski 299*9672edf7SBartosz Golaszewski static int gpio_probe_order_consumer_probe(struct platform_device *pdev) 300*9672edf7SBartosz Golaszewski { 301*9672edf7SBartosz Golaszewski struct device *dev = &pdev->dev; 302*9672edf7SBartosz Golaszewski struct gpio_probe_order_pdata *pdata = dev_get_platdata(dev); 303*9672edf7SBartosz Golaszewski struct gpio_desc *desc; 304*9672edf7SBartosz Golaszewski 305*9672edf7SBartosz Golaszewski pdata->probe_count++; 306*9672edf7SBartosz Golaszewski 307*9672edf7SBartosz Golaszewski desc = devm_gpiod_get(dev, "foo", GPIOD_OUT_HIGH); 308*9672edf7SBartosz Golaszewski if (IS_ERR(desc)) 309*9672edf7SBartosz Golaszewski return PTR_ERR(desc); 310*9672edf7SBartosz Golaszewski 311*9672edf7SBartosz Golaszewski pdata->gpio_ok = true; 312*9672edf7SBartosz Golaszewski 313*9672edf7SBartosz Golaszewski return 0; 314*9672edf7SBartosz Golaszewski } 315*9672edf7SBartosz Golaszewski 316*9672edf7SBartosz Golaszewski static struct platform_driver gpio_probe_order_consumer_driver = { 317*9672edf7SBartosz Golaszewski .probe = gpio_probe_order_consumer_probe, 318*9672edf7SBartosz Golaszewski .driver = { 319*9672edf7SBartosz Golaszewski .name = GPIO_PROBE_ORDER_TEST_CONSUMER, 320*9672edf7SBartosz Golaszewski }, 321*9672edf7SBartosz Golaszewski }; 322*9672edf7SBartosz Golaszewski 323*9672edf7SBartosz Golaszewski /* 324*9672edf7SBartosz Golaszewski * Verify that fw_devlink orders the probe of a GPIO consumer after its 325*9672edf7SBartosz Golaszewski * provider. The consumer references the provider through a software node and 326*9672edf7SBartosz Golaszewski * is registered first. fw_devlink must defer it before its driver's probe() 327*9672edf7SBartosz Golaszewski * is ever entered, so the consumer probes exactly once - only after the 328*9672edf7SBartosz Golaszewski * provider is added and bound. 329*9672edf7SBartosz Golaszewski */ 330*9672edf7SBartosz Golaszewski static void gpio_swnode_probe_order(struct kunit *test) 331*9672edf7SBartosz Golaszewski { 332*9672edf7SBartosz Golaszewski struct property_entry properties[2] = { }; 333*9672edf7SBartosz Golaszewski struct gpio_probe_order_pdata *pdata; 334*9672edf7SBartosz Golaszewski struct platform_device_info pdevinfo; 335*9672edf7SBartosz Golaszewski struct platform_device *prvd, *cons; 336*9672edf7SBartosz Golaszewski bool bound = false; 337*9672edf7SBartosz Golaszewski int ret; 338*9672edf7SBartosz Golaszewski 339*9672edf7SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_test_provider_driver); 340*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 341*9672edf7SBartosz Golaszewski 342*9672edf7SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_probe_order_consumer_driver); 343*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 344*9672edf7SBartosz Golaszewski 345*9672edf7SBartosz Golaszewski ret = software_node_register(&gpio_test_provider_swnode); 346*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 347*9672edf7SBartosz Golaszewski 348*9672edf7SBartosz Golaszewski ret = kunit_add_action_or_reset(test, gpio_swnode_unregister_swnode, 349*9672edf7SBartosz Golaszewski (void *)&gpio_test_provider_swnode); 350*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 351*9672edf7SBartosz Golaszewski 352*9672edf7SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 353*9672edf7SBartosz Golaszewski &gpio_test_provider_swnode, 354*9672edf7SBartosz Golaszewski 0, GPIO_ACTIVE_HIGH); 355*9672edf7SBartosz Golaszewski 356*9672edf7SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 357*9672edf7SBartosz Golaszewski .name = GPIO_PROBE_ORDER_TEST_CONSUMER, 358*9672edf7SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 359*9672edf7SBartosz Golaszewski .data = &gpio_probe_order_pdata_template, 360*9672edf7SBartosz Golaszewski .size_data = sizeof(gpio_probe_order_pdata_template), 361*9672edf7SBartosz Golaszewski .properties = properties, 362*9672edf7SBartosz Golaszewski }; 363*9672edf7SBartosz Golaszewski 364*9672edf7SBartosz Golaszewski cons = kunit_platform_device_register_full(test, &pdevinfo); 365*9672edf7SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cons); 366*9672edf7SBartosz Golaszewski 367*9672edf7SBartosz Golaszewski wait_for_device_probe(); 368*9672edf7SBartosz Golaszewski scoped_guard(device, &cons->dev) 369*9672edf7SBartosz Golaszewski bound = device_is_bound(&cons->dev); 370*9672edf7SBartosz Golaszewski 371*9672edf7SBartosz Golaszewski KUNIT_ASSERT_FALSE(test, bound); 372*9672edf7SBartosz Golaszewski 373*9672edf7SBartosz Golaszewski pdata = dev_get_platdata(&cons->dev); 374*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, pdata->probe_count, 0); 375*9672edf7SBartosz Golaszewski KUNIT_ASSERT_FALSE(test, pdata->gpio_ok); 376*9672edf7SBartosz Golaszewski 377*9672edf7SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 378*9672edf7SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 379*9672edf7SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 380*9672edf7SBartosz Golaszewski .swnode = &gpio_test_provider_swnode, 381*9672edf7SBartosz Golaszewski }; 382*9672edf7SBartosz Golaszewski 383*9672edf7SBartosz Golaszewski prvd = kunit_platform_device_register_full(test, &pdevinfo); 384*9672edf7SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prvd); 385*9672edf7SBartosz Golaszewski 386*9672edf7SBartosz Golaszewski wait_for_device_probe(); 387*9672edf7SBartosz Golaszewski 388*9672edf7SBartosz Golaszewski scoped_guard(device, &prvd->dev) 389*9672edf7SBartosz Golaszewski bound = device_is_bound(&prvd->dev); 390*9672edf7SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 391*9672edf7SBartosz Golaszewski 392*9672edf7SBartosz Golaszewski scoped_guard(device, &cons->dev) 393*9672edf7SBartosz Golaszewski bound = device_is_bound(&cons->dev); 394*9672edf7SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 395*9672edf7SBartosz Golaszewski 396*9672edf7SBartosz Golaszewski pdata = dev_get_platdata(&cons->dev); 397*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, pdata->probe_count, 1); 398*9672edf7SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, pdata->gpio_ok); 399*9672edf7SBartosz Golaszewski } 400*9672edf7SBartosz Golaszewski 401*9672edf7SBartosz Golaszewski struct gpio_probe_defer_pdata { 402*9672edf7SBartosz Golaszewski unsigned int probe_count; 403*9672edf7SBartosz Golaszewski int gpio_err; 404*9672edf7SBartosz Golaszewski }; 405*9672edf7SBartosz Golaszewski 406*9672edf7SBartosz Golaszewski static const struct gpio_probe_defer_pdata gpio_probe_defer_pdata_template = { 407*9672edf7SBartosz Golaszewski .probe_count = 0, 408*9672edf7SBartosz Golaszewski .gpio_err = 0, 409*9672edf7SBartosz Golaszewski }; 410*9672edf7SBartosz Golaszewski 411*9672edf7SBartosz Golaszewski static int gpio_probe_defer_consumer_probe(struct platform_device *pdev) 412*9672edf7SBartosz Golaszewski { 413*9672edf7SBartosz Golaszewski struct device *dev = &pdev->dev; 414*9672edf7SBartosz Golaszewski struct gpio_probe_defer_pdata *pdata = dev_get_platdata(dev); 415*9672edf7SBartosz Golaszewski struct gpio_desc *desc; 416*9672edf7SBartosz Golaszewski 417*9672edf7SBartosz Golaszewski pdata->probe_count++; 418*9672edf7SBartosz Golaszewski 419*9672edf7SBartosz Golaszewski desc = devm_gpiod_get(dev, "foo", GPIOD_OUT_HIGH); 420*9672edf7SBartosz Golaszewski if (IS_ERR(desc)) { 421*9672edf7SBartosz Golaszewski pdata->gpio_err = PTR_ERR(desc); 422*9672edf7SBartosz Golaszewski return pdata->gpio_err; 423*9672edf7SBartosz Golaszewski } 424*9672edf7SBartosz Golaszewski 425*9672edf7SBartosz Golaszewski pdata->gpio_err = 0; 426*9672edf7SBartosz Golaszewski 427*9672edf7SBartosz Golaszewski return 0; 428*9672edf7SBartosz Golaszewski } 429*9672edf7SBartosz Golaszewski 430*9672edf7SBartosz Golaszewski static struct platform_driver gpio_probe_defer_consumer_driver = { 431*9672edf7SBartosz Golaszewski .probe = gpio_probe_defer_consumer_probe, 432*9672edf7SBartosz Golaszewski .driver = { 433*9672edf7SBartosz Golaszewski .name = GPIO_PROBE_DEFER_TEST_CONSUMER, 434*9672edf7SBartosz Golaszewski }, 435*9672edf7SBartosz Golaszewski }; 436*9672edf7SBartosz Golaszewski 437*9672edf7SBartosz Golaszewski /* 438*9672edf7SBartosz Golaszewski * Verify that a GPIO consumer referencing a provider whose software node is 439*9672edf7SBartosz Golaszewski * not registered yet, defers its probe instead of failing. 440*9672edf7SBartosz Golaszewski * 441*9672edf7SBartosz Golaszewski * The provider software node is deliberately left unregistered when the 442*9672edf7SBartosz Golaszewski * consumer is added. fw_devlink cannot resolve the reference, so it creates no 443*9672edf7SBartosz Golaszewski * supplier link and does not order the consumer - the consumer's probe() runs 444*9672edf7SBartosz Golaszewski * and reaches devm_gpiod_get(). The swnode GPIO lookup returns -ENOTCONN for a 445*9672edf7SBartosz Golaszewski * reference to an unregistered node, which gpiolib maps to -EPROBE_DEFER. Once 446*9672edf7SBartosz Golaszewski * the provider software node and device appear, the deferred consumer probes 447*9672edf7SBartosz Golaszewski * again and binds. 448*9672edf7SBartosz Golaszewski */ 449*9672edf7SBartosz Golaszewski static void gpio_swnode_probe_defer_on_unregistered(struct kunit *test) 450*9672edf7SBartosz Golaszewski { 451*9672edf7SBartosz Golaszewski struct property_entry properties[2] = { }; 452*9672edf7SBartosz Golaszewski struct gpio_probe_defer_pdata *pdata; 453*9672edf7SBartosz Golaszewski struct platform_device_info pdevinfo; 454*9672edf7SBartosz Golaszewski struct platform_device *prvd, *cons; 455*9672edf7SBartosz Golaszewski struct fwnode_handle *fwnode; 456*9672edf7SBartosz Golaszewski bool bound = false; 457*9672edf7SBartosz Golaszewski int ret; 458*9672edf7SBartosz Golaszewski 459*9672edf7SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_test_provider_driver); 460*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 461*9672edf7SBartosz Golaszewski 462*9672edf7SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_probe_defer_consumer_driver); 463*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 464*9672edf7SBartosz Golaszewski 465*9672edf7SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 466*9672edf7SBartosz Golaszewski &gpio_test_provider_swnode, 467*9672edf7SBartosz Golaszewski 0, GPIO_ACTIVE_HIGH); 468*9672edf7SBartosz Golaszewski 469*9672edf7SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 470*9672edf7SBartosz Golaszewski .name = GPIO_PROBE_DEFER_TEST_CONSUMER, 471*9672edf7SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 472*9672edf7SBartosz Golaszewski .data = &gpio_probe_defer_pdata_template, 473*9672edf7SBartosz Golaszewski .size_data = sizeof(gpio_probe_defer_pdata_template), 474*9672edf7SBartosz Golaszewski .properties = properties, 475*9672edf7SBartosz Golaszewski }; 476*9672edf7SBartosz Golaszewski 477*9672edf7SBartosz Golaszewski cons = kunit_platform_device_register_full(test, &pdevinfo); 478*9672edf7SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cons); 479*9672edf7SBartosz Golaszewski 480*9672edf7SBartosz Golaszewski wait_for_device_probe(); 481*9672edf7SBartosz Golaszewski scoped_guard(device, &cons->dev) 482*9672edf7SBartosz Golaszewski bound = device_is_bound(&cons->dev); 483*9672edf7SBartosz Golaszewski 484*9672edf7SBartosz Golaszewski KUNIT_ASSERT_FALSE(test, bound); 485*9672edf7SBartosz Golaszewski 486*9672edf7SBartosz Golaszewski pdata = dev_get_platdata(&cons->dev); 487*9672edf7SBartosz Golaszewski KUNIT_ASSERT_GT(test, pdata->probe_count, 0); 488*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, pdata->gpio_err, -EPROBE_DEFER); 489*9672edf7SBartosz Golaszewski 490*9672edf7SBartosz Golaszewski fwnode = kunit_software_node_register(test, &gpio_test_provider_swnode); 491*9672edf7SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fwnode); 492*9672edf7SBartosz Golaszewski 493*9672edf7SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 494*9672edf7SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 495*9672edf7SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 496*9672edf7SBartosz Golaszewski .swnode = &gpio_test_provider_swnode, 497*9672edf7SBartosz Golaszewski }; 498*9672edf7SBartosz Golaszewski 499*9672edf7SBartosz Golaszewski prvd = kunit_platform_device_register_full(test, &pdevinfo); 500*9672edf7SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prvd); 501*9672edf7SBartosz Golaszewski 502*9672edf7SBartosz Golaszewski wait_for_device_probe(); 503*9672edf7SBartosz Golaszewski 504*9672edf7SBartosz Golaszewski scoped_guard(device, &prvd->dev) 505*9672edf7SBartosz Golaszewski bound = device_is_bound(&prvd->dev); 506*9672edf7SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 507*9672edf7SBartosz Golaszewski 508*9672edf7SBartosz Golaszewski scoped_guard(device, &cons->dev) 509*9672edf7SBartosz Golaszewski bound = device_is_bound(&cons->dev); 510*9672edf7SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 511*9672edf7SBartosz Golaszewski 512*9672edf7SBartosz Golaszewski pdata = dev_get_platdata(&cons->dev); 513*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, pdata->gpio_err, 0); 514*9672edf7SBartosz Golaszewski 515*9672edf7SBartosz Golaszewski /* Tear down the consumer before the provider to free the GPIO. */ 516*9672edf7SBartosz Golaszewski kunit_platform_device_unregister(test, cons); 517*9672edf7SBartosz Golaszewski } 518*9672edf7SBartosz Golaszewski 519*9672edf7SBartosz Golaszewski static int gpio_swnode_probe_order_test_init(struct kunit *test) 520*9672edf7SBartosz Golaszewski { 521*9672edf7SBartosz Golaszewski /* 522*9672edf7SBartosz Golaszewski * A prior test may have left a managed device link teardown queued on 523*9672edf7SBartosz Golaszewski * the device_link_mq. Flush it so that software_node_register() 524*9672edf7SBartosz Golaszewski * doesn't spuriously see the node as registered and fail with -EEXIST. 525*9672edf7SBartosz Golaszewski */ 526*9672edf7SBartosz Golaszewski device_link_wait_removal(); 527*9672edf7SBartosz Golaszewski 528*9672edf7SBartosz Golaszewski return 0; 529*9672edf7SBartosz Golaszewski } 530*9672edf7SBartosz Golaszewski 531*9672edf7SBartosz Golaszewski static struct kunit_case gpio_swnode_probe_order_tests[] = { 532*9672edf7SBartosz Golaszewski KUNIT_CASE(gpio_swnode_probe_order), 533*9672edf7SBartosz Golaszewski KUNIT_CASE(gpio_swnode_probe_defer_on_unregistered), 534*9672edf7SBartosz Golaszewski { } 535*9672edf7SBartosz Golaszewski }; 536*9672edf7SBartosz Golaszewski 537*9672edf7SBartosz Golaszewski static struct kunit_suite gpio_swnode_probe_order_test_suite = { 538*9672edf7SBartosz Golaszewski .name = "gpio-swnode-probe-order", 539*9672edf7SBartosz Golaszewski .test_cases = gpio_swnode_probe_order_tests, 540*9672edf7SBartosz Golaszewski .init = gpio_swnode_probe_order_test_init, 541*9672edf7SBartosz Golaszewski }; 542*9672edf7SBartosz Golaszewski 543a6d2a3b4SBartosz Golaszewski static BLOCKING_NOTIFIER_HEAD(gpio_unbind_notifier); 544a6d2a3b4SBartosz Golaszewski 545a6d2a3b4SBartosz Golaszewski struct gpio_unbind_consumer_drvdata { 546a6d2a3b4SBartosz Golaszewski struct device *dev; 547a6d2a3b4SBartosz Golaszewski struct gpio_desc *desc; 548a6d2a3b4SBartosz Golaszewski struct notifier_block nb; 549a6d2a3b4SBartosz Golaszewski int set_retval; 550a6d2a3b4SBartosz Golaszewski }; 551a6d2a3b4SBartosz Golaszewski 552a6d2a3b4SBartosz Golaszewski static int gpio_unbind_notify(struct notifier_block *nb, unsigned long action, 553a6d2a3b4SBartosz Golaszewski void *data) 554a6d2a3b4SBartosz Golaszewski { 555a6d2a3b4SBartosz Golaszewski struct gpio_unbind_consumer_drvdata *drvdata = 556a6d2a3b4SBartosz Golaszewski container_of(nb, struct gpio_unbind_consumer_drvdata, nb); 557a6d2a3b4SBartosz Golaszewski struct device *dev = data; 558a6d2a3b4SBartosz Golaszewski 559a6d2a3b4SBartosz Golaszewski if (dev != drvdata->dev) 560a6d2a3b4SBartosz Golaszewski return NOTIFY_DONE; 561a6d2a3b4SBartosz Golaszewski 562a6d2a3b4SBartosz Golaszewski drvdata->set_retval = gpiod_set_value_cansleep(drvdata->desc, 0); 563a6d2a3b4SBartosz Golaszewski 564a6d2a3b4SBartosz Golaszewski return NOTIFY_OK; 565a6d2a3b4SBartosz Golaszewski } 566a6d2a3b4SBartosz Golaszewski 567a6d2a3b4SBartosz Golaszewski static void gpio_unbind_unregister_notifier(void *data) 568a6d2a3b4SBartosz Golaszewski { 569a6d2a3b4SBartosz Golaszewski struct notifier_block *nb = data; 570a6d2a3b4SBartosz Golaszewski 571a6d2a3b4SBartosz Golaszewski blocking_notifier_chain_unregister(&gpio_unbind_notifier, nb); 572a6d2a3b4SBartosz Golaszewski } 573a6d2a3b4SBartosz Golaszewski 574a6d2a3b4SBartosz Golaszewski static int gpio_unbind_consumer_probe(struct platform_device *pdev) 575a6d2a3b4SBartosz Golaszewski { 576a6d2a3b4SBartosz Golaszewski struct gpio_unbind_consumer_drvdata *data; 577a6d2a3b4SBartosz Golaszewski struct device *dev = &pdev->dev; 578a6d2a3b4SBartosz Golaszewski int ret; 579a6d2a3b4SBartosz Golaszewski 580a6d2a3b4SBartosz Golaszewski data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 581a6d2a3b4SBartosz Golaszewski if (!data) 582a6d2a3b4SBartosz Golaszewski return -ENOMEM; 583a6d2a3b4SBartosz Golaszewski 584a6d2a3b4SBartosz Golaszewski data->dev = dev; 585a6d2a3b4SBartosz Golaszewski 586a6d2a3b4SBartosz Golaszewski data->desc = devm_gpiod_get(dev, "foo", GPIOD_OUT_HIGH); 587a6d2a3b4SBartosz Golaszewski if (IS_ERR(data->desc)) 588a6d2a3b4SBartosz Golaszewski return PTR_ERR(data->desc); 589a6d2a3b4SBartosz Golaszewski 590a6d2a3b4SBartosz Golaszewski data->nb.notifier_call = gpio_unbind_notify; 591a6d2a3b4SBartosz Golaszewski ret = blocking_notifier_chain_register(&gpio_unbind_notifier, &data->nb); 592a6d2a3b4SBartosz Golaszewski if (ret) 593a6d2a3b4SBartosz Golaszewski return ret; 594a6d2a3b4SBartosz Golaszewski 595a6d2a3b4SBartosz Golaszewski ret = devm_add_action_or_reset(dev, gpio_unbind_unregister_notifier, &data->nb); 596a6d2a3b4SBartosz Golaszewski if (ret) 597a6d2a3b4SBartosz Golaszewski return ret; 598a6d2a3b4SBartosz Golaszewski 599a6d2a3b4SBartosz Golaszewski platform_set_drvdata(pdev, data); 600a6d2a3b4SBartosz Golaszewski 601a6d2a3b4SBartosz Golaszewski return 0; 602a6d2a3b4SBartosz Golaszewski } 603a6d2a3b4SBartosz Golaszewski 604a6d2a3b4SBartosz Golaszewski static struct platform_driver gpio_unbind_consumer_driver = { 605a6d2a3b4SBartosz Golaszewski .probe = gpio_unbind_consumer_probe, 606a6d2a3b4SBartosz Golaszewski .driver = { 607a6d2a3b4SBartosz Golaszewski .name = GPIO_UNBIND_TEST_CONSUMER, 608a6d2a3b4SBartosz Golaszewski }, 609a6d2a3b4SBartosz Golaszewski }; 610a6d2a3b4SBartosz Golaszewski 611a6d2a3b4SBartosz Golaszewski static void gpio_unbind_with_consumers(struct kunit *test) 612a6d2a3b4SBartosz Golaszewski { 613a6d2a3b4SBartosz Golaszewski struct gpio_unbind_consumer_drvdata *cons_data; 614a6d2a3b4SBartosz Golaszewski struct platform_device_info pdevinfo; 615a6d2a3b4SBartosz Golaszewski struct property_entry properties[2]; 616a6d2a3b4SBartosz Golaszewski struct platform_device *prvd, *cons; 617a6d2a3b4SBartosz Golaszewski bool bound = false; 618a6d2a3b4SBartosz Golaszewski int ret; 619a6d2a3b4SBartosz Golaszewski 620a6d2a3b4SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_test_provider_driver); 621a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 622a6d2a3b4SBartosz Golaszewski 623a6d2a3b4SBartosz Golaszewski ret = kunit_platform_driver_register(test, &gpio_unbind_consumer_driver); 624a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 625a6d2a3b4SBartosz Golaszewski 626a6d2a3b4SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 627a6d2a3b4SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 628a6d2a3b4SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 629a6d2a3b4SBartosz Golaszewski .swnode = &gpio_test_provider_swnode, 630a6d2a3b4SBartosz Golaszewski }; 631a6d2a3b4SBartosz Golaszewski 632a6d2a3b4SBartosz Golaszewski prvd = kunit_platform_device_register_full(test, &pdevinfo); 633a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prvd); 634a6d2a3b4SBartosz Golaszewski 635a6d2a3b4SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 636a6d2a3b4SBartosz Golaszewski &gpio_test_provider_swnode, 637a6d2a3b4SBartosz Golaszewski 0, GPIO_ACTIVE_HIGH); 638a6d2a3b4SBartosz Golaszewski properties[1] = (struct property_entry){ }; 639a6d2a3b4SBartosz Golaszewski 640*9672edf7SBartosz Golaszewski /* 641*9672edf7SBartosz Golaszewski * This test deliberately keeps the consumer bound while the provider 642*9672edf7SBartosz Golaszewski * is unregistered. fw_devlink would force-unbind the consumer before 643*9672edf7SBartosz Golaszewski * the provider so use the FWNODE_FLAG_LINKS_ADDED flag to opt out of 644*9672edf7SBartosz Golaszewski * it as a workaround. 645*9672edf7SBartosz Golaszewski */ 646*9672edf7SBartosz Golaszewski cons = kunit_platform_device_alloc(test, GPIO_UNBIND_TEST_CONSUMER, 647*9672edf7SBartosz Golaszewski PLATFORM_DEVID_NONE); 648a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cons); 649a6d2a3b4SBartosz Golaszewski 650*9672edf7SBartosz Golaszewski ret = device_create_managed_software_node(&cons->dev, properties, NULL); 651*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 652*9672edf7SBartosz Golaszewski 653*9672edf7SBartosz Golaszewski fwnode_set_flag(dev_fwnode(&cons->dev), FWNODE_FLAG_LINKS_ADDED); 654*9672edf7SBartosz Golaszewski 655*9672edf7SBartosz Golaszewski ret = kunit_platform_device_add(test, cons); 656*9672edf7SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, 0); 657*9672edf7SBartosz Golaszewski 658a6d2a3b4SBartosz Golaszewski wait_for_device_probe(); 659a6d2a3b4SBartosz Golaszewski scoped_guard(device, &cons->dev) 660a6d2a3b4SBartosz Golaszewski bound = device_is_bound(&cons->dev); 661a6d2a3b4SBartosz Golaszewski 662a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_TRUE(test, bound); 663a6d2a3b4SBartosz Golaszewski 664a6d2a3b4SBartosz Golaszewski kunit_platform_device_unregister(test, prvd); 665a6d2a3b4SBartosz Golaszewski 666a6d2a3b4SBartosz Golaszewski ret = blocking_notifier_call_chain(&gpio_unbind_notifier, 0, &cons->dev); 667a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, NOTIFY_OK); 668a6d2a3b4SBartosz Golaszewski 669a6d2a3b4SBartosz Golaszewski scoped_guard(device, &cons->dev) { 670a6d2a3b4SBartosz Golaszewski cons_data = platform_get_drvdata(cons); 671a6d2a3b4SBartosz Golaszewski ret = cons_data->set_retval; 672a6d2a3b4SBartosz Golaszewski } 673a6d2a3b4SBartosz Golaszewski 674a6d2a3b4SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, -ENODEV); 675a6d2a3b4SBartosz Golaszewski } 676a6d2a3b4SBartosz Golaszewski 677a6d2a3b4SBartosz Golaszewski static struct kunit_case gpio_unbind_with_consumers_tests[] = { 678a6d2a3b4SBartosz Golaszewski KUNIT_CASE(gpio_unbind_with_consumers), 679a6d2a3b4SBartosz Golaszewski { } 680a6d2a3b4SBartosz Golaszewski }; 681a6d2a3b4SBartosz Golaszewski 682a6d2a3b4SBartosz Golaszewski static struct kunit_suite gpio_unbind_with_consumers_test_suite = { 683a6d2a3b4SBartosz Golaszewski .name = "gpio-unbind-with-consumers", 684a6d2a3b4SBartosz Golaszewski .test_cases = gpio_unbind_with_consumers_tests, 685*9672edf7SBartosz Golaszewski /* We need this here too to clean any left over links. */ 686*9672edf7SBartosz Golaszewski .init = gpio_swnode_probe_order_test_init, 687a6d2a3b4SBartosz Golaszewski }; 688a6d2a3b4SBartosz Golaszewski 689a05cfd98SBartosz Golaszewski /* 690a05cfd98SBartosz Golaszewski * GPIO line hogs are described by child software nodes of the provider 691a05cfd98SBartosz Golaszewski * carrying the "gpio-hog" property. They are picked up automatically when the 692a05cfd98SBartosz Golaszewski * gpiochip is registered. Each hog below sits on a distinct line of the 693a05cfd98SBartosz Golaszewski * provider. 694a05cfd98SBartosz Golaszewski */ 695a05cfd98SBartosz Golaszewski #define GPIO_HOG_OUTPUT_HIGH_OFFSET 0 696a05cfd98SBartosz Golaszewski #define GPIO_HOG_OUTPUT_LOW_OFFSET 1 697a05cfd98SBartosz Golaszewski #define GPIO_HOG_INPUT_OFFSET 2 698a05cfd98SBartosz Golaszewski 699a05cfd98SBartosz Golaszewski static const u32 gpio_hog_output_high_gpios[] = { 700a05cfd98SBartosz Golaszewski GPIO_HOG_OUTPUT_HIGH_OFFSET, GPIO_ACTIVE_HIGH, 701a05cfd98SBartosz Golaszewski }; 702a05cfd98SBartosz Golaszewski 703a05cfd98SBartosz Golaszewski static const struct property_entry gpio_hog_output_high_properties[] = { 704a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_U32_ARRAY("gpios", gpio_hog_output_high_gpios), 705a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_STRING("line-name", "hog-output-high"), 706a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("output-high"), 707a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("gpio-hog"), 708a05cfd98SBartosz Golaszewski { } 709a05cfd98SBartosz Golaszewski }; 710a05cfd98SBartosz Golaszewski 711a05cfd98SBartosz Golaszewski static const struct software_node gpio_hog_output_high_swnode = 712a05cfd98SBartosz Golaszewski SOFTWARE_NODE("hog-output-high", gpio_hog_output_high_properties, 713a05cfd98SBartosz Golaszewski &gpio_test_provider_swnode); 714a05cfd98SBartosz Golaszewski 715a05cfd98SBartosz Golaszewski static const u32 gpio_hog_output_low_gpios[] = { 716a05cfd98SBartosz Golaszewski GPIO_HOG_OUTPUT_LOW_OFFSET, GPIO_ACTIVE_HIGH, 717a05cfd98SBartosz Golaszewski }; 718a05cfd98SBartosz Golaszewski 719a05cfd98SBartosz Golaszewski static const struct property_entry gpio_hog_output_low_properties[] = { 720a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_U32_ARRAY("gpios", gpio_hog_output_low_gpios), 721a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_STRING("line-name", "hog-output-low"), 722a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("output-low"), 723a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("gpio-hog"), 724a05cfd98SBartosz Golaszewski { } 725a05cfd98SBartosz Golaszewski }; 726a05cfd98SBartosz Golaszewski 727a05cfd98SBartosz Golaszewski static const struct software_node gpio_hog_output_low_swnode = 728a05cfd98SBartosz Golaszewski SOFTWARE_NODE("hog-output-low", gpio_hog_output_low_properties, 729a05cfd98SBartosz Golaszewski &gpio_test_provider_swnode); 730a05cfd98SBartosz Golaszewski 731a05cfd98SBartosz Golaszewski static const u32 gpio_hog_input_gpios[] = { 732a05cfd98SBartosz Golaszewski GPIO_HOG_INPUT_OFFSET, GPIO_ACTIVE_HIGH, 733a05cfd98SBartosz Golaszewski }; 734a05cfd98SBartosz Golaszewski 735a05cfd98SBartosz Golaszewski static const struct property_entry gpio_hog_input_properties[] = { 736a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_U32_ARRAY("gpios", gpio_hog_input_gpios), 737a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_STRING("line-name", "hog-input"), 738a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("input"), 739a05cfd98SBartosz Golaszewski PROPERTY_ENTRY_BOOL("gpio-hog"), 740a05cfd98SBartosz Golaszewski { } 741a05cfd98SBartosz Golaszewski }; 742a05cfd98SBartosz Golaszewski 743a05cfd98SBartosz Golaszewski static const struct software_node gpio_hog_input_swnode = 744a05cfd98SBartosz Golaszewski SOFTWARE_NODE("hog-input", gpio_hog_input_properties, 745a05cfd98SBartosz Golaszewski &gpio_test_provider_swnode); 746a05cfd98SBartosz Golaszewski 747a05cfd98SBartosz Golaszewski static const struct software_node *const gpio_hog_swnodes[] = { 748a05cfd98SBartosz Golaszewski &gpio_test_provider_swnode, 749a05cfd98SBartosz Golaszewski &gpio_hog_output_high_swnode, 750a05cfd98SBartosz Golaszewski &gpio_hog_output_low_swnode, 751a05cfd98SBartosz Golaszewski &gpio_hog_input_swnode, 752a05cfd98SBartosz Golaszewski NULL 753a05cfd98SBartosz Golaszewski }; 754a05cfd98SBartosz Golaszewski 755a05cfd98SBartosz Golaszewski /* 756a05cfd98SBartosz Golaszewski * Bring up the provider with a single hog child registered and verify both 757a05cfd98SBartosz Golaszewski * that the line was configured with the expected direction and that it is now 758a05cfd98SBartosz Golaszewski * exclusively owned (a consumer asking for the same line fails to bind). 759a05cfd98SBartosz Golaszewski * 760a05cfd98SBartosz Golaszewski * The provider node is referenced by the device through its fwnode rather than 761a05cfd98SBartosz Golaszewski * being handed to .swnode, so the device takes no software node reference of 762a05cfd98SBartosz Golaszewski * its own. Both the provider and the hog child are therefore test-managed and 763a05cfd98SBartosz Golaszewski * torn down (child first) once the test case completes. 764a05cfd98SBartosz Golaszewski */ 765a05cfd98SBartosz Golaszewski static void gpio_hog_assert(struct kunit *test, unsigned int offset, 766a05cfd98SBartosz Golaszewski int expected_direction) 767a05cfd98SBartosz Golaszewski { 768a05cfd98SBartosz Golaszewski struct gpio_swnode_consumer_pdata *pdata; 769a05cfd98SBartosz Golaszewski struct platform_device_info pdevinfo; 770a05cfd98SBartosz Golaszewski struct property_entry properties[2]; 771a05cfd98SBartosz Golaszewski struct platform_device *pdev; 772a05cfd98SBartosz Golaszewski struct fwnode_handle *fwnode; 773a05cfd98SBartosz Golaszewski struct gpio_desc *desc; 774a05cfd98SBartosz Golaszewski bool bound = true; 775a05cfd98SBartosz Golaszewski int ret; 776a05cfd98SBartosz Golaszewski 777a05cfd98SBartosz Golaszewski fwnode = software_node_fwnode(&gpio_test_provider_swnode); 778a05cfd98SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fwnode); 779a05cfd98SBartosz Golaszewski 780a05cfd98SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 781a05cfd98SBartosz Golaszewski .name = GPIO_TEST_PROVIDER, 782a05cfd98SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 783a05cfd98SBartosz Golaszewski .fwnode = fwnode, 784a05cfd98SBartosz Golaszewski }; 785a05cfd98SBartosz Golaszewski 786a05cfd98SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 787a05cfd98SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 788a05cfd98SBartosz Golaszewski 789a05cfd98SBartosz Golaszewski wait_for_device_probe(); 790a05cfd98SBartosz Golaszewski 791a05cfd98SBartosz Golaszewski /* The hog must have configured the line with the expected direction. */ 792a05cfd98SBartosz Golaszewski struct gpio_device *gdev __free(gpio_device_put) = 793a05cfd98SBartosz Golaszewski gpio_device_find_by_label(GPIO_CONSUMER_NAME); 794a05cfd98SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gdev); 795a05cfd98SBartosz Golaszewski 796a05cfd98SBartosz Golaszewski desc = gpio_device_get_desc(gdev, offset); 797a05cfd98SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, desc); 798a05cfd98SBartosz Golaszewski 799a05cfd98SBartosz Golaszewski ret = gpiod_get_direction(desc); 800a05cfd98SBartosz Golaszewski KUNIT_ASSERT_EQ(test, ret, expected_direction); 801a05cfd98SBartosz Golaszewski 802a05cfd98SBartosz Golaszewski /* A hogged line is owned exclusively, so a consumer must fail to bind. */ 803a05cfd98SBartosz Golaszewski properties[0] = PROPERTY_ENTRY_GPIO("foo-gpios", 804a05cfd98SBartosz Golaszewski &gpio_test_provider_swnode, 805a05cfd98SBartosz Golaszewski offset, GPIO_ACTIVE_HIGH); 806a05cfd98SBartosz Golaszewski properties[1] = (struct property_entry){ }; 807a05cfd98SBartosz Golaszewski 808a05cfd98SBartosz Golaszewski pdevinfo = (struct platform_device_info){ 809a05cfd98SBartosz Golaszewski .name = GPIO_SWNODE_TEST_CONSUMER, 810a05cfd98SBartosz Golaszewski .id = PLATFORM_DEVID_NONE, 811a05cfd98SBartosz Golaszewski .data = &gpio_swnode_pdata_template, 812a05cfd98SBartosz Golaszewski .size_data = sizeof(gpio_swnode_pdata_template), 813a05cfd98SBartosz Golaszewski .properties = properties, 814a05cfd98SBartosz Golaszewski }; 815a05cfd98SBartosz Golaszewski 816a05cfd98SBartosz Golaszewski pdev = kunit_platform_device_register_full(test, &pdevinfo); 817a05cfd98SBartosz Golaszewski KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); 818a05cfd98SBartosz Golaszewski 819a05cfd98SBartosz Golaszewski wait_for_device_probe(); 820a05cfd98SBartosz Golaszewski scoped_guard(device, &pdev->dev) 821a05cfd98SBartosz Golaszewski bound = device_is_bound(&pdev->dev); 822a05cfd98SBartosz Golaszewski 823a05cfd98SBartosz Golaszewski KUNIT_ASSERT_FALSE(test, bound); 824a05cfd98SBartosz Golaszewski 825a05cfd98SBartosz Golaszewski pdata = dev_get_platdata(&pdev->dev); 826a05cfd98SBartosz Golaszewski KUNIT_ASSERT_FALSE(test, pdata->gpio_ok); 827a05cfd98SBartosz Golaszewski KUNIT_ASSERT_EQ(test, pdata->errno, -EBUSY); 828a05cfd98SBartosz Golaszewski } 829a05cfd98SBartosz Golaszewski 830a05cfd98SBartosz Golaszewski static void gpio_hog_output_high(struct kunit *test) 831a05cfd98SBartosz Golaszewski { 832a05cfd98SBartosz Golaszewski gpio_hog_assert(test, GPIO_HOG_OUTPUT_HIGH_OFFSET, GPIO_LINE_DIRECTION_OUT); 833a05cfd98SBartosz Golaszewski } 834a05cfd98SBartosz Golaszewski 835a05cfd98SBartosz Golaszewski static void gpio_hog_output_low(struct kunit *test) 836a05cfd98SBartosz Golaszewski { 837a05cfd98SBartosz Golaszewski gpio_hog_assert(test, GPIO_HOG_OUTPUT_LOW_OFFSET, GPIO_LINE_DIRECTION_OUT); 838a05cfd98SBartosz Golaszewski } 839a05cfd98SBartosz Golaszewski 840a05cfd98SBartosz Golaszewski static void gpio_hog_input(struct kunit *test) 841a05cfd98SBartosz Golaszewski { 842a05cfd98SBartosz Golaszewski gpio_hog_assert(test, GPIO_HOG_INPUT_OFFSET, GPIO_LINE_DIRECTION_IN); 843a05cfd98SBartosz Golaszewski } 844a05cfd98SBartosz Golaszewski 845a05cfd98SBartosz Golaszewski static int gpio_hog_suite_init(struct kunit_suite *suite) 846a05cfd98SBartosz Golaszewski { 847a05cfd98SBartosz Golaszewski return software_node_register_node_group(gpio_hog_swnodes); 848a05cfd98SBartosz Golaszewski } 849a05cfd98SBartosz Golaszewski 850a05cfd98SBartosz Golaszewski static void gpio_hog_suite_exit(struct kunit_suite *suite) 851a05cfd98SBartosz Golaszewski { 852a05cfd98SBartosz Golaszewski software_node_unregister_node_group(gpio_hog_swnodes); 853a05cfd98SBartosz Golaszewski } 854a05cfd98SBartosz Golaszewski 855a05cfd98SBartosz Golaszewski static struct kunit_case gpio_swnode_hog_tests[] = { 856a05cfd98SBartosz Golaszewski KUNIT_CASE(gpio_hog_output_high), 857a05cfd98SBartosz Golaszewski KUNIT_CASE(gpio_hog_output_low), 858a05cfd98SBartosz Golaszewski KUNIT_CASE(gpio_hog_input), 859a05cfd98SBartosz Golaszewski { } 860a05cfd98SBartosz Golaszewski }; 861a05cfd98SBartosz Golaszewski 862a05cfd98SBartosz Golaszewski static struct kunit_suite gpio_swnode_hog_test_suite = { 863a05cfd98SBartosz Golaszewski .name = "gpio-swnode-hog", 864a05cfd98SBartosz Golaszewski .test_cases = gpio_swnode_hog_tests, 865a05cfd98SBartosz Golaszewski .suite_init = gpio_hog_suite_init, 866a05cfd98SBartosz Golaszewski .suite_exit = gpio_hog_suite_exit, 867a05cfd98SBartosz Golaszewski .init = gpio_swnode_register_drivers, 868a05cfd98SBartosz Golaszewski }; 869a05cfd98SBartosz Golaszewski 870a6d2a3b4SBartosz Golaszewski kunit_test_suites( 871a6d2a3b4SBartosz Golaszewski &gpio_swnode_lookup_test_suite, 872*9672edf7SBartosz Golaszewski &gpio_swnode_probe_order_test_suite, 873a6d2a3b4SBartosz Golaszewski &gpio_unbind_with_consumers_test_suite, 874a05cfd98SBartosz Golaszewski &gpio_swnode_hog_test_suite, 875a6d2a3b4SBartosz Golaszewski ); 876a6d2a3b4SBartosz Golaszewski 877a6d2a3b4SBartosz Golaszewski MODULE_DESCRIPTION("Test module for the GPIO subsystem"); 878a6d2a3b4SBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>"); 879a6d2a3b4SBartosz Golaszewski MODULE_LICENSE("GPL"); 880