xref: /linux/drivers/gpio/gpio-mpfs.c (revision a987b78f3615e20c9cf9a85e38505bdcb7f19495)
1 // SPDX-License-Identifier: (GPL-2.0)
2 /*
3  * Microchip PolarFire SoC (MPFS) GPIO controller driver
4  *
5  * Copyright (c) 2018-2024 Microchip Technology Inc. and its subsidiaries
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/device.h>
10 #include <linux/errno.h>
11 #include <linux/gpio/driver.h>
12 #include <linux/init.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
16 #include <linux/spinlock.h>
17 
18 #define MPFS_GPIO_CTRL(i)		(0x4 * (i))
19 #define MPFS_MAX_NUM_GPIO		32
20 #define MPFS_GPIO_EN_INT		3
21 #define MPFS_GPIO_EN_OUT_BUF		BIT(2)
22 #define MPFS_GPIO_EN_IN			BIT(1)
23 #define MPFS_GPIO_EN_OUT		BIT(0)
24 #define MPFS_GPIO_DIR_MASK		GENMASK(2, 0)
25 
26 #define MPFS_GPIO_TYPE_INT_EDGE_BOTH	0x80
27 #define MPFS_GPIO_TYPE_INT_EDGE_NEG	0x60
28 #define MPFS_GPIO_TYPE_INT_EDGE_POS	0x40
29 #define MPFS_GPIO_TYPE_INT_LEVEL_LOW	0x20
30 #define MPFS_GPIO_TYPE_INT_LEVEL_HIGH	0x00
31 #define MPFS_GPIO_TYPE_INT_MASK		GENMASK(7, 5)
32 #define MPFS_IRQ_REG			0x80
33 #define MPFS_INP_REG			0x84
34 #define MPFS_OUTP_REG			0x88
35 
36 struct mpfs_gpio_chip {
37 	struct regmap *regs;
38 	struct gpio_chip gc;
39 };
40 
41 static const struct regmap_config mpfs_gpio_regmap_config = {
42 	.reg_bits = 32,
43 	.reg_stride = 4,
44 	.val_bits = 32,
45 };
46 
47 static int mpfs_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio_index)
48 {
49 	struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
50 
51 	regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
52 			   MPFS_GPIO_DIR_MASK, MPFS_GPIO_EN_IN);
53 
54 	return 0;
55 }
56 
57 static int mpfs_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio_index, int value)
58 {
59 	struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
60 
61 	regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index),
62 			   MPFS_GPIO_DIR_MASK, MPFS_GPIO_EN_IN);
63 	regmap_update_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index),
64 			   value << gpio_index);
65 
66 	return 0;
67 }
68 
69 static int mpfs_gpio_get_direction(struct gpio_chip *gc,
70 				   unsigned int gpio_index)
71 {
72 	struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
73 	unsigned int gpio_cfg;
74 
75 	regmap_read(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), &gpio_cfg);
76 	if (gpio_cfg & MPFS_GPIO_EN_IN)
77 		return GPIO_LINE_DIRECTION_IN;
78 
79 	return GPIO_LINE_DIRECTION_OUT;
80 }
81 
82 static int mpfs_gpio_get(struct gpio_chip *gc, unsigned int gpio_index)
83 {
84 	struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
85 
86 	if (mpfs_gpio_get_direction(gc, gpio_index) == GPIO_LINE_DIRECTION_OUT)
87 		return regmap_test_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index));
88 	else
89 		return regmap_test_bits(mpfs_gpio->regs, MPFS_INP_REG, BIT(gpio_index));
90 }
91 
92 static void mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value)
93 {
94 	struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc);
95 
96 	mpfs_gpio_get(gc, gpio_index);
97 
98 	regmap_update_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index),
99 			   value << gpio_index);
100 
101 	mpfs_gpio_get(gc, gpio_index);
102 }
103 
104 static int mpfs_gpio_probe(struct platform_device *pdev)
105 {
106 	struct device *dev = &pdev->dev;
107 	struct mpfs_gpio_chip *mpfs_gpio;
108 	struct clk *clk;
109 	void __iomem *base;
110 	int ngpios;
111 
112 	mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL);
113 	if (!mpfs_gpio)
114 		return -ENOMEM;
115 
116 	base = devm_platform_ioremap_resource(pdev, 0);
117 	if (IS_ERR(base))
118 		return dev_err_probe(dev, PTR_ERR(base), "failed to ioremap memory resource\n");
119 
120 	mpfs_gpio->regs = devm_regmap_init_mmio(dev, base, &mpfs_gpio_regmap_config);
121 	if (IS_ERR(mpfs_gpio->regs))
122 		return dev_err_probe(dev, PTR_ERR(mpfs_gpio->regs),
123 				     "failed to initialise regmap\n");
124 
125 	clk = devm_clk_get_enabled(dev, NULL);
126 	if (IS_ERR(clk))
127 		return dev_err_probe(dev, PTR_ERR(clk), "failed to get and enable clock\n");
128 
129 	ngpios = MPFS_MAX_NUM_GPIO;
130 	device_property_read_u32(dev, "ngpios", &ngpios);
131 	if (ngpios > MPFS_MAX_NUM_GPIO)
132 		ngpios = MPFS_MAX_NUM_GPIO;
133 
134 	mpfs_gpio->gc.direction_input = mpfs_gpio_direction_input;
135 	mpfs_gpio->gc.direction_output = mpfs_gpio_direction_output;
136 	mpfs_gpio->gc.get_direction = mpfs_gpio_get_direction;
137 	mpfs_gpio->gc.get = mpfs_gpio_get;
138 	mpfs_gpio->gc.set = mpfs_gpio_set;
139 	mpfs_gpio->gc.base = -1;
140 	mpfs_gpio->gc.ngpio = ngpios;
141 	mpfs_gpio->gc.label = dev_name(dev);
142 	mpfs_gpio->gc.parent = dev;
143 	mpfs_gpio->gc.owner = THIS_MODULE;
144 
145 	return devm_gpiochip_add_data(dev, &mpfs_gpio->gc, mpfs_gpio);
146 }
147 
148 static const struct of_device_id mpfs_gpio_of_ids[] = {
149 	{ .compatible = "microchip,mpfs-gpio", },
150 	{ /* end of list */ }
151 };
152 
153 static struct platform_driver mpfs_gpio_driver = {
154 	.probe = mpfs_gpio_probe,
155 	.driver = {
156 		.name = "microchip,mpfs-gpio",
157 		.of_match_table = mpfs_gpio_of_ids,
158 	},
159 };
160 builtin_platform_driver(mpfs_gpio_driver);
161