18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Philips UCB1400 GPIO driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Marek Vasut <marek.vasut@gmail.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/ucb1400.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci struct ucb1400_gpio *gpio; 148c2ecf20Sopenharmony_ci gpio = gpiochip_get_data(gc); 158c2ecf20Sopenharmony_ci ucb1400_gpio_set_direction(gpio->ac97, off, 0); 168c2ecf20Sopenharmony_ci return 0; 178c2ecf20Sopenharmony_ci} 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci struct ucb1400_gpio *gpio; 228c2ecf20Sopenharmony_ci gpio = gpiochip_get_data(gc); 238c2ecf20Sopenharmony_ci ucb1400_gpio_set_direction(gpio->ac97, off, 1); 248c2ecf20Sopenharmony_ci ucb1400_gpio_set_value(gpio->ac97, off, val); 258c2ecf20Sopenharmony_ci return 0; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct ucb1400_gpio *gpio; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci gpio = gpiochip_get_data(gc); 338c2ecf20Sopenharmony_ci return !!ucb1400_gpio_get_value(gpio->ac97, off); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct ucb1400_gpio *gpio; 398c2ecf20Sopenharmony_ci gpio = gpiochip_get_data(gc); 408c2ecf20Sopenharmony_ci ucb1400_gpio_set_value(gpio->ac97, off, val); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic int ucb1400_gpio_probe(struct platform_device *dev) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct ucb1400_gpio *ucb = dev_get_platdata(&dev->dev); 468c2ecf20Sopenharmony_ci int err = 0; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (!(ucb && ucb->gpio_offset)) { 498c2ecf20Sopenharmony_ci err = -EINVAL; 508c2ecf20Sopenharmony_ci goto err; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci platform_set_drvdata(dev, ucb); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci ucb->gc.label = "ucb1400_gpio"; 568c2ecf20Sopenharmony_ci ucb->gc.base = ucb->gpio_offset; 578c2ecf20Sopenharmony_ci ucb->gc.ngpio = 10; 588c2ecf20Sopenharmony_ci ucb->gc.owner = THIS_MODULE; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci ucb->gc.direction_input = ucb1400_gpio_dir_in; 618c2ecf20Sopenharmony_ci ucb->gc.direction_output = ucb1400_gpio_dir_out; 628c2ecf20Sopenharmony_ci ucb->gc.get = ucb1400_gpio_get; 638c2ecf20Sopenharmony_ci ucb->gc.set = ucb1400_gpio_set; 648c2ecf20Sopenharmony_ci ucb->gc.can_sleep = true; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci err = devm_gpiochip_add_data(&dev->dev, &ucb->gc, ucb); 678c2ecf20Sopenharmony_ci if (err) 688c2ecf20Sopenharmony_ci goto err; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (ucb->gpio_setup) 718c2ecf20Sopenharmony_ci err = ucb->gpio_setup(&dev->dev, ucb->gc.ngpio); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cierr: 748c2ecf20Sopenharmony_ci return err; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int ucb1400_gpio_remove(struct platform_device *dev) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci int err = 0; 818c2ecf20Sopenharmony_ci struct ucb1400_gpio *ucb = platform_get_drvdata(dev); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (ucb && ucb->gpio_teardown) { 848c2ecf20Sopenharmony_ci err = ucb->gpio_teardown(&dev->dev, ucb->gc.ngpio); 858c2ecf20Sopenharmony_ci if (err) 868c2ecf20Sopenharmony_ci return err; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return err; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic struct platform_driver ucb1400_gpio_driver = { 938c2ecf20Sopenharmony_ci .probe = ucb1400_gpio_probe, 948c2ecf20Sopenharmony_ci .remove = ucb1400_gpio_remove, 958c2ecf20Sopenharmony_ci .driver = { 968c2ecf20Sopenharmony_ci .name = "ucb1400_gpio" 978c2ecf20Sopenharmony_ci }, 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cimodule_platform_driver(ucb1400_gpio_driver); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); 1038c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1048c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:ucb1400_gpio"); 105