18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * CLPS711X GPIO driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012,2013 Alexander Shiyan <shc_work@mail.ru> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/err.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic int clps711x_gpio_probe(struct platform_device *pdev) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 168c2ecf20Sopenharmony_ci void __iomem *dat, *dir; 178c2ecf20Sopenharmony_ci struct gpio_chip *gc; 188c2ecf20Sopenharmony_ci int err, id; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci if (!np) 218c2ecf20Sopenharmony_ci return -ENODEV; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci id = of_alias_get_id(np, "gpio"); 248c2ecf20Sopenharmony_ci if ((id < 0) || (id > 4)) 258c2ecf20Sopenharmony_ci return -ENODEV; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); 288c2ecf20Sopenharmony_ci if (!gc) 298c2ecf20Sopenharmony_ci return -ENOMEM; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci dat = devm_platform_ioremap_resource(pdev, 0); 328c2ecf20Sopenharmony_ci if (IS_ERR(dat)) 338c2ecf20Sopenharmony_ci return PTR_ERR(dat); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci dir = devm_platform_ioremap_resource(pdev, 1); 368c2ecf20Sopenharmony_ci if (IS_ERR(dir)) 378c2ecf20Sopenharmony_ci return PTR_ERR(dir); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci switch (id) { 408c2ecf20Sopenharmony_ci case 3: 418c2ecf20Sopenharmony_ci /* PORTD is inverted logic for direction register */ 428c2ecf20Sopenharmony_ci err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL, 438c2ecf20Sopenharmony_ci NULL, dir, 0); 448c2ecf20Sopenharmony_ci break; 458c2ecf20Sopenharmony_ci default: 468c2ecf20Sopenharmony_ci err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL, 478c2ecf20Sopenharmony_ci dir, NULL, 0); 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (err) 528c2ecf20Sopenharmony_ci return err; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci switch (id) { 558c2ecf20Sopenharmony_ci case 4: 568c2ecf20Sopenharmony_ci /* PORTE is 3 lines only */ 578c2ecf20Sopenharmony_ci gc->ngpio = 3; 588c2ecf20Sopenharmony_ci break; 598c2ecf20Sopenharmony_ci default: 608c2ecf20Sopenharmony_ci break; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci gc->base = -1; 648c2ecf20Sopenharmony_ci gc->owner = THIS_MODULE; 658c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, gc); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return devm_gpiochip_add_data(&pdev->dev, gc, NULL); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic const struct of_device_id __maybe_unused clps711x_gpio_ids[] = { 718c2ecf20Sopenharmony_ci { .compatible = "cirrus,ep7209-gpio" }, 728c2ecf20Sopenharmony_ci { } 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, clps711x_gpio_ids); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic struct platform_driver clps711x_gpio_driver = { 778c2ecf20Sopenharmony_ci .driver = { 788c2ecf20Sopenharmony_ci .name = "clps711x-gpio", 798c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(clps711x_gpio_ids), 808c2ecf20Sopenharmony_ci }, 818c2ecf20Sopenharmony_ci .probe = clps711x_gpio_probe, 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_cimodule_platform_driver(clps711x_gpio_driver); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 868c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); 878c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CLPS711X GPIO driver"); 888c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:clps711x-gpio"); 89