xref: /rk3399_rockchip-uboot/drivers/gpio/mvebu_gpio.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
1704d9a64SStefan Roese /*
2704d9a64SStefan Roese  * Copyright (C) 2016 Stefan Roese <sr@denx.de>
3704d9a64SStefan Roese  *
4704d9a64SStefan Roese  * SPDX-License-Identifier:	GPL-2.0+
5704d9a64SStefan Roese  */
6704d9a64SStefan Roese 
7704d9a64SStefan Roese #include <common.h>
8704d9a64SStefan Roese #include <dm.h>
9704d9a64SStefan Roese #include <asm/gpio.h>
10704d9a64SStefan Roese #include <asm/io.h>
11704d9a64SStefan Roese #include <errno.h>
12704d9a64SStefan Roese 
13704d9a64SStefan Roese DECLARE_GLOBAL_DATA_PTR;
14704d9a64SStefan Roese 
15704d9a64SStefan Roese #define MVEBU_GPIOS_PER_BANK	32
16704d9a64SStefan Roese 
17704d9a64SStefan Roese struct mvebu_gpio_regs {
18704d9a64SStefan Roese 	u32 data_out;
19704d9a64SStefan Roese 	u32 io_conf;
20704d9a64SStefan Roese 	u32 blink_en;
21704d9a64SStefan Roese 	u32 in_pol;
22704d9a64SStefan Roese 	u32 data_in;
23704d9a64SStefan Roese };
24704d9a64SStefan Roese 
25704d9a64SStefan Roese struct mvebu_gpio_priv {
26704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs;
27704d9a64SStefan Roese 	char name[2];
28704d9a64SStefan Roese };
29704d9a64SStefan Roese 
mvebu_gpio_direction_input(struct udevice * dev,unsigned int gpio)30704d9a64SStefan Roese static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
31704d9a64SStefan Roese {
32704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
33704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs = priv->regs;
34704d9a64SStefan Roese 
35704d9a64SStefan Roese 	setbits_le32(&regs->io_conf, BIT(gpio));
36704d9a64SStefan Roese 
37704d9a64SStefan Roese 	return 0;
38704d9a64SStefan Roese }
39704d9a64SStefan Roese 
mvebu_gpio_direction_output(struct udevice * dev,unsigned gpio,int value)40704d9a64SStefan Roese static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio,
41704d9a64SStefan Roese 				       int value)
42704d9a64SStefan Roese {
43704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
44704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs = priv->regs;
45704d9a64SStefan Roese 
46b23005ceSStefan Roese 	if (value)
47b23005ceSStefan Roese 		setbits_le32(&regs->data_out, BIT(gpio));
48b23005ceSStefan Roese 	else
49b23005ceSStefan Roese 		clrbits_le32(&regs->data_out, BIT(gpio));
50704d9a64SStefan Roese 	clrbits_le32(&regs->io_conf, BIT(gpio));
51704d9a64SStefan Roese 
52704d9a64SStefan Roese 	return 0;
53704d9a64SStefan Roese }
54704d9a64SStefan Roese 
mvebu_gpio_get_function(struct udevice * dev,unsigned gpio)55704d9a64SStefan Roese static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio)
56704d9a64SStefan Roese {
57704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
58704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs = priv->regs;
59704d9a64SStefan Roese 	u32 val;
60704d9a64SStefan Roese 
61704d9a64SStefan Roese 	val = readl(&regs->io_conf) & BIT(gpio);
62704d9a64SStefan Roese 	if (val)
63704d9a64SStefan Roese 		return GPIOF_INPUT;
64704d9a64SStefan Roese 	else
65704d9a64SStefan Roese 		return GPIOF_OUTPUT;
66704d9a64SStefan Roese }
67704d9a64SStefan Roese 
mvebu_gpio_set_value(struct udevice * dev,unsigned gpio,int value)68704d9a64SStefan Roese static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio,
69704d9a64SStefan Roese 				int value)
70704d9a64SStefan Roese {
71704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
72704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs = priv->regs;
73704d9a64SStefan Roese 
74704d9a64SStefan Roese 	if (value)
75704d9a64SStefan Roese 		setbits_le32(&regs->data_out, BIT(gpio));
76704d9a64SStefan Roese 	else
77704d9a64SStefan Roese 		clrbits_le32(&regs->data_out, BIT(gpio));
78704d9a64SStefan Roese 
79704d9a64SStefan Roese 	return 0;
80704d9a64SStefan Roese }
81704d9a64SStefan Roese 
mvebu_gpio_get_value(struct udevice * dev,unsigned gpio)82704d9a64SStefan Roese static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio)
83704d9a64SStefan Roese {
84704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
85704d9a64SStefan Roese 	struct mvebu_gpio_regs *regs = priv->regs;
86704d9a64SStefan Roese 
87704d9a64SStefan Roese 	return !!(readl(&regs->data_in) & BIT(gpio));
88704d9a64SStefan Roese }
89704d9a64SStefan Roese 
mvebu_gpio_probe(struct udevice * dev)90704d9a64SStefan Roese static int mvebu_gpio_probe(struct udevice *dev)
91704d9a64SStefan Roese {
92704d9a64SStefan Roese 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
93704d9a64SStefan Roese 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
94704d9a64SStefan Roese 
95*a821c4afSSimon Glass 	priv->regs = (struct mvebu_gpio_regs *)devfdt_get_addr(dev);
96704d9a64SStefan Roese 	uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
97704d9a64SStefan Roese 	priv->name[0] = 'A' + dev->req_seq;
98704d9a64SStefan Roese 	uc_priv->bank_name = priv->name;
99704d9a64SStefan Roese 
100704d9a64SStefan Roese 	return 0;
101704d9a64SStefan Roese }
102704d9a64SStefan Roese 
103704d9a64SStefan Roese static const struct dm_gpio_ops mvebu_gpio_ops = {
104704d9a64SStefan Roese 	.direction_input	= mvebu_gpio_direction_input,
105704d9a64SStefan Roese 	.direction_output	= mvebu_gpio_direction_output,
106704d9a64SStefan Roese 	.get_function		= mvebu_gpio_get_function,
107704d9a64SStefan Roese 	.get_value		= mvebu_gpio_get_value,
108704d9a64SStefan Roese 	.set_value		= mvebu_gpio_set_value,
109704d9a64SStefan Roese };
110704d9a64SStefan Roese 
111704d9a64SStefan Roese static const struct udevice_id mvebu_gpio_ids[] = {
112704d9a64SStefan Roese 	{ .compatible = "marvell,orion-gpio" },
113704d9a64SStefan Roese 	{ }
114704d9a64SStefan Roese };
115704d9a64SStefan Roese 
116704d9a64SStefan Roese U_BOOT_DRIVER(gpio_mvebu) = {
117704d9a64SStefan Roese 	.name			= "gpio_mvebu",
118704d9a64SStefan Roese 	.id			= UCLASS_GPIO,
119704d9a64SStefan Roese 	.of_match		= mvebu_gpio_ids,
120704d9a64SStefan Roese 	.ops			= &mvebu_gpio_ops,
121704d9a64SStefan Roese 	.probe			= mvebu_gpio_probe,
122704d9a64SStefan Roese 	.priv_auto_alloc_size	= sizeof(struct mvebu_gpio_priv),
123704d9a64SStefan Roese };
124