1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Delta TN48M CPLD GPIO driver |
4 | * |
5 | * Copyright (C) 2021 Sartura Ltd. |
6 | * |
7 | * Author: Robert Marko <robert.marko@sartura.hr> |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/gpio/driver.h> |
12 | #include <linux/gpio/regmap.h> |
13 | #include <linux/mod_devicetable.h> |
14 | #include <linux/module.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/regmap.h> |
17 | |
18 | enum tn48m_gpio_type { |
19 | TN48M_GP0 = 1, |
20 | TN48M_GPI, |
21 | }; |
22 | |
23 | struct tn48m_gpio_config { |
24 | int ngpio; |
25 | int ngpio_per_reg; |
26 | enum tn48m_gpio_type type; |
27 | }; |
28 | |
29 | static const struct tn48m_gpio_config tn48m_gpo_config = { |
30 | .ngpio = 4, |
31 | .ngpio_per_reg = 4, |
32 | .type = TN48M_GP0, |
33 | }; |
34 | |
35 | static const struct tn48m_gpio_config tn48m_gpi_config = { |
36 | .ngpio = 4, |
37 | .ngpio_per_reg = 4, |
38 | .type = TN48M_GPI, |
39 | }; |
40 | |
41 | static int tn48m_gpio_probe(struct platform_device *pdev) |
42 | { |
43 | const struct tn48m_gpio_config *gpio_config; |
44 | struct gpio_regmap_config config = {}; |
45 | struct regmap *regmap; |
46 | u32 base; |
47 | int ret; |
48 | |
49 | if (!pdev->dev.parent) |
50 | return -ENODEV; |
51 | |
52 | gpio_config = device_get_match_data(dev: &pdev->dev); |
53 | if (!gpio_config) |
54 | return -ENODEV; |
55 | |
56 | ret = device_property_read_u32(dev: &pdev->dev, propname: "reg" , val: &base); |
57 | if (ret) |
58 | return ret; |
59 | |
60 | regmap = dev_get_regmap(dev: pdev->dev.parent, NULL); |
61 | if (!regmap) |
62 | return -ENODEV; |
63 | |
64 | config.regmap = regmap; |
65 | config.parent = &pdev->dev; |
66 | config.ngpio = gpio_config->ngpio; |
67 | config.ngpio_per_reg = gpio_config->ngpio_per_reg; |
68 | switch (gpio_config->type) { |
69 | case TN48M_GP0: |
70 | config.reg_set_base = base; |
71 | break; |
72 | case TN48M_GPI: |
73 | config.reg_dat_base = base; |
74 | break; |
75 | default: |
76 | return -EINVAL; |
77 | } |
78 | |
79 | return PTR_ERR_OR_ZERO(ptr: devm_gpio_regmap_register(dev: &pdev->dev, config: &config)); |
80 | } |
81 | |
82 | static const struct of_device_id tn48m_gpio_of_match[] = { |
83 | { .compatible = "delta,tn48m-gpo" , .data = &tn48m_gpo_config }, |
84 | { .compatible = "delta,tn48m-gpi" , .data = &tn48m_gpi_config }, |
85 | { } |
86 | }; |
87 | MODULE_DEVICE_TABLE(of, tn48m_gpio_of_match); |
88 | |
89 | static struct platform_driver tn48m_gpio_driver = { |
90 | .driver = { |
91 | .name = "delta-tn48m-gpio" , |
92 | .of_match_table = tn48m_gpio_of_match, |
93 | }, |
94 | .probe = tn48m_gpio_probe, |
95 | }; |
96 | module_platform_driver(tn48m_gpio_driver); |
97 | |
98 | MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>" ); |
99 | MODULE_DESCRIPTION("Delta TN48M CPLD GPIO driver" ); |
100 | MODULE_LICENSE("GPL" ); |
101 | |