1 // SPDX-License-Identifier: GPL-2.0+
3 // Synopsys CREG (Control REGisters) GPIO driver
5 // Copyright (C) 2018 Synopsys
6 // Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
8 #include <linux/gpio/driver.h>
11 #include <linux/of_platform.h>
20 u8 bit_per_gpio
[MAX_GPIO
];
27 const struct creg_layout
*layout
;
30 static void creg_gpio_set(struct gpio_chip
*gc
, unsigned int offset
, int val
)
32 struct creg_gpio
*hcg
= gpiochip_get_data(gc
);
33 const struct creg_layout
*layout
= hcg
->layout
;
34 u32 reg
, reg_shift
, value
;
38 value
= val
? hcg
->layout
->on
[offset
] : hcg
->layout
->off
[offset
];
40 reg_shift
= layout
->shift
[offset
];
41 for (i
= 0; i
< offset
; i
++)
42 reg_shift
+= layout
->bit_per_gpio
[i
] + layout
->shift
[i
];
44 spin_lock_irqsave(&hcg
->lock
, flags
);
45 reg
= readl(hcg
->regs
);
46 reg
&= ~(GENMASK(layout
->bit_per_gpio
[i
] - 1, 0) << reg_shift
);
47 reg
|= (value
<< reg_shift
);
48 writel(reg
, hcg
->regs
);
49 spin_unlock_irqrestore(&hcg
->lock
, flags
);
52 static int creg_gpio_dir_out(struct gpio_chip
*gc
, unsigned int offset
, int val
)
54 creg_gpio_set(gc
, offset
, val
);
59 static int creg_gpio_validate_pg(struct device
*dev
, struct creg_gpio
*hcg
,
62 const struct creg_layout
*layout
= hcg
->layout
;
64 if (layout
->bit_per_gpio
[i
] < 1 || layout
->bit_per_gpio
[i
] > 8)
67 /* Check that on value fits its placeholder */
68 if (GENMASK(31, layout
->bit_per_gpio
[i
]) & layout
->on
[i
])
71 /* Check that off value fits its placeholder */
72 if (GENMASK(31, layout
->bit_per_gpio
[i
]) & layout
->off
[i
])
75 if (layout
->on
[i
] == layout
->off
[i
])
81 static int creg_gpio_validate(struct device
*dev
, struct creg_gpio
*hcg
,
87 if (hcg
->layout
->ngpio
< 1 || hcg
->layout
->ngpio
> MAX_GPIO
)
90 if (ngpios
< 1 || ngpios
> hcg
->layout
->ngpio
) {
91 dev_err(dev
, "ngpios must be in [1:%u]\n", hcg
->layout
->ngpio
);
95 for (i
= 0; i
< hcg
->layout
->ngpio
; i
++) {
96 if (creg_gpio_validate_pg(dev
, hcg
, i
))
99 reg_len
+= hcg
->layout
->shift
[i
] + hcg
->layout
->bit_per_gpio
[i
];
102 /* Check that we fit in 32 bit register */
109 static const struct creg_layout hsdk_cs_ctl
= {
111 .shift
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
112 .off
= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
113 .on
= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
114 .bit_per_gpio
= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }
117 static const struct creg_layout axs10x_flsh_cs_ctl
= {
122 .bit_per_gpio
= { 2 }
125 static const struct of_device_id creg_gpio_ids
[] = {
127 .compatible
= "snps,creg-gpio-axs10x",
128 .data
= &axs10x_flsh_cs_ctl
130 .compatible
= "snps,creg-gpio-hsdk",
132 }, { /* sentinel */ }
135 static int creg_gpio_probe(struct platform_device
*pdev
)
137 const struct of_device_id
*match
;
138 struct device
*dev
= &pdev
->dev
;
139 struct creg_gpio
*hcg
;
143 hcg
= devm_kzalloc(dev
, sizeof(struct creg_gpio
), GFP_KERNEL
);
147 hcg
->regs
= devm_platform_ioremap_resource(pdev
, 0);
148 if (IS_ERR(hcg
->regs
))
149 return PTR_ERR(hcg
->regs
);
151 match
= of_match_node(creg_gpio_ids
, pdev
->dev
.of_node
);
152 hcg
->layout
= match
->data
;
156 ret
= of_property_read_u32(dev
->of_node
, "ngpios", &ngpios
);
160 ret
= creg_gpio_validate(dev
, hcg
, ngpios
);
164 spin_lock_init(&hcg
->lock
);
166 hcg
->gc
.label
= dev_name(dev
);
168 hcg
->gc
.ngpio
= ngpios
;
169 hcg
->gc
.set
= creg_gpio_set
;
170 hcg
->gc
.direction_output
= creg_gpio_dir_out
;
171 hcg
->gc
.of_node
= dev
->of_node
;
173 ret
= devm_gpiochip_add_data(dev
, &hcg
->gc
, hcg
);
177 dev_info(dev
, "GPIO controller with %d gpios probed\n", ngpios
);
182 static struct platform_driver creg_gpio_snps_driver
= {
184 .name
= "snps-creg-gpio",
185 .of_match_table
= creg_gpio_ids
,
187 .probe
= creg_gpio_probe
,
189 builtin_platform_driver(creg_gpio_snps_driver
);