xref: /rk3399_rockchip-uboot/drivers/gpio/bcm6345_gpio.c (revision e64bdb2fcfce7e002964e72f2732920ecda4b74c)
1*e64bdb2fSÁlvaro Fernández Rojas /*
2*e64bdb2fSÁlvaro Fernández Rojas  * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
3*e64bdb2fSÁlvaro Fernández Rojas  *
4*e64bdb2fSÁlvaro Fernández Rojas  * Derived from linux/arch/mips/bcm63xx/gpio.c:
5*e64bdb2fSÁlvaro Fernández Rojas  *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
6*e64bdb2fSÁlvaro Fernández Rojas  *	Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org>
7*e64bdb2fSÁlvaro Fernández Rojas  *
8*e64bdb2fSÁlvaro Fernández Rojas  * SPDX-License-Identifier:	GPL-2.0+
9*e64bdb2fSÁlvaro Fernández Rojas  */
10*e64bdb2fSÁlvaro Fernández Rojas 
11*e64bdb2fSÁlvaro Fernández Rojas #include <common.h>
12*e64bdb2fSÁlvaro Fernández Rojas #include <errno.h>
13*e64bdb2fSÁlvaro Fernández Rojas #include <asm/gpio.h>
14*e64bdb2fSÁlvaro Fernández Rojas #include <asm/io.h>
15*e64bdb2fSÁlvaro Fernández Rojas #include <dm/device.h>
16*e64bdb2fSÁlvaro Fernández Rojas 
17*e64bdb2fSÁlvaro Fernández Rojas DECLARE_GLOBAL_DATA_PTR;
18*e64bdb2fSÁlvaro Fernández Rojas 
19*e64bdb2fSÁlvaro Fernández Rojas struct bcm6345_gpio_priv {
20*e64bdb2fSÁlvaro Fernández Rojas 	void __iomem *reg_dirout;
21*e64bdb2fSÁlvaro Fernández Rojas 	void __iomem *reg_data;
22*e64bdb2fSÁlvaro Fernández Rojas };
23*e64bdb2fSÁlvaro Fernández Rojas 
24*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_get_value(struct udevice *dev, unsigned offset)
25*e64bdb2fSÁlvaro Fernández Rojas {
26*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
27*e64bdb2fSÁlvaro Fernández Rojas 
28*e64bdb2fSÁlvaro Fernández Rojas 	return !!(readl_be(priv->reg_data) & BIT(offset));
29*e64bdb2fSÁlvaro Fernández Rojas }
30*e64bdb2fSÁlvaro Fernández Rojas 
31*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset,
32*e64bdb2fSÁlvaro Fernández Rojas 				  int value)
33*e64bdb2fSÁlvaro Fernández Rojas {
34*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
35*e64bdb2fSÁlvaro Fernández Rojas 
36*e64bdb2fSÁlvaro Fernández Rojas 	if (value)
37*e64bdb2fSÁlvaro Fernández Rojas 		setbits_be32(priv->reg_data, BIT(offset));
38*e64bdb2fSÁlvaro Fernández Rojas 	else
39*e64bdb2fSÁlvaro Fernández Rojas 		clrbits_be32(priv->reg_data, BIT(offset));
40*e64bdb2fSÁlvaro Fernández Rojas 
41*e64bdb2fSÁlvaro Fernández Rojas 	return 0;
42*e64bdb2fSÁlvaro Fernández Rojas }
43*e64bdb2fSÁlvaro Fernández Rojas 
44*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_set_direction(void __iomem *dirout, unsigned offset,
45*e64bdb2fSÁlvaro Fernández Rojas 				      bool input)
46*e64bdb2fSÁlvaro Fernández Rojas {
47*e64bdb2fSÁlvaro Fernández Rojas 	if (input)
48*e64bdb2fSÁlvaro Fernández Rojas 		clrbits_be32(dirout, BIT(offset));
49*e64bdb2fSÁlvaro Fernández Rojas 	else
50*e64bdb2fSÁlvaro Fernández Rojas 		setbits_be32(dirout, BIT(offset));
51*e64bdb2fSÁlvaro Fernández Rojas 
52*e64bdb2fSÁlvaro Fernández Rojas 	return 0;
53*e64bdb2fSÁlvaro Fernández Rojas }
54*e64bdb2fSÁlvaro Fernández Rojas 
55*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_direction_input(struct udevice *dev, unsigned offset)
56*e64bdb2fSÁlvaro Fernández Rojas {
57*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
58*e64bdb2fSÁlvaro Fernández Rojas 
59*e64bdb2fSÁlvaro Fernández Rojas 	return bcm6345_gpio_set_direction(priv->reg_dirout, offset, 1);
60*e64bdb2fSÁlvaro Fernández Rojas }
61*e64bdb2fSÁlvaro Fernández Rojas 
62*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_direction_output(struct udevice *dev, unsigned offset,
63*e64bdb2fSÁlvaro Fernández Rojas 					 int value)
64*e64bdb2fSÁlvaro Fernández Rojas {
65*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
66*e64bdb2fSÁlvaro Fernández Rojas 
67*e64bdb2fSÁlvaro Fernández Rojas 	return bcm6345_gpio_set_direction(priv->reg_dirout, offset, 0);
68*e64bdb2fSÁlvaro Fernández Rojas }
69*e64bdb2fSÁlvaro Fernández Rojas 
70*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_get_function(struct udevice *dev, unsigned offset)
71*e64bdb2fSÁlvaro Fernández Rojas {
72*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
73*e64bdb2fSÁlvaro Fernández Rojas 
74*e64bdb2fSÁlvaro Fernández Rojas 	if (readl_be(priv->reg_dirout) & BIT(offset))
75*e64bdb2fSÁlvaro Fernández Rojas 		return GPIOF_OUTPUT;
76*e64bdb2fSÁlvaro Fernández Rojas 	else
77*e64bdb2fSÁlvaro Fernández Rojas 		return GPIOF_INPUT;
78*e64bdb2fSÁlvaro Fernández Rojas }
79*e64bdb2fSÁlvaro Fernández Rojas 
80*e64bdb2fSÁlvaro Fernández Rojas static const struct dm_gpio_ops bcm6345_gpio_ops = {
81*e64bdb2fSÁlvaro Fernández Rojas 	.direction_input = bcm6345_gpio_direction_input,
82*e64bdb2fSÁlvaro Fernández Rojas 	.direction_output = bcm6345_gpio_direction_output,
83*e64bdb2fSÁlvaro Fernández Rojas 	.get_value = bcm6345_gpio_get_value,
84*e64bdb2fSÁlvaro Fernández Rojas 	.set_value = bcm6345_gpio_set_value,
85*e64bdb2fSÁlvaro Fernández Rojas 	.get_function = bcm6345_gpio_get_function,
86*e64bdb2fSÁlvaro Fernández Rojas };
87*e64bdb2fSÁlvaro Fernández Rojas 
88*e64bdb2fSÁlvaro Fernández Rojas static int bcm6345_gpio_probe(struct udevice *dev)
89*e64bdb2fSÁlvaro Fernández Rojas {
90*e64bdb2fSÁlvaro Fernández Rojas 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
91*e64bdb2fSÁlvaro Fernández Rojas 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
92*e64bdb2fSÁlvaro Fernández Rojas 	fdt_addr_t data_addr, dirout_addr;
93*e64bdb2fSÁlvaro Fernández Rojas 	fdt_size_t data_size, dirout_size;
94*e64bdb2fSÁlvaro Fernández Rojas 
95*e64bdb2fSÁlvaro Fernández Rojas 	dirout_addr = dev_get_addr_size_index(dev, 0, &dirout_size);
96*e64bdb2fSÁlvaro Fernández Rojas 	if (dirout_addr == FDT_ADDR_T_NONE)
97*e64bdb2fSÁlvaro Fernández Rojas 		return -EINVAL;
98*e64bdb2fSÁlvaro Fernández Rojas 
99*e64bdb2fSÁlvaro Fernández Rojas 	data_addr = dev_get_addr_size_index(dev, 1, &data_size);
100*e64bdb2fSÁlvaro Fernández Rojas 	if (data_addr == FDT_ADDR_T_NONE)
101*e64bdb2fSÁlvaro Fernández Rojas 		return -EINVAL;
102*e64bdb2fSÁlvaro Fernández Rojas 
103*e64bdb2fSÁlvaro Fernández Rojas 	priv->reg_data = ioremap(data_addr, data_size);
104*e64bdb2fSÁlvaro Fernández Rojas 	priv->reg_dirout = ioremap(dirout_addr, dirout_size);
105*e64bdb2fSÁlvaro Fernández Rojas 
106*e64bdb2fSÁlvaro Fernández Rojas 	uc_priv->gpio_count = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
107*e64bdb2fSÁlvaro Fernández Rojas 					      "ngpios", 32);
108*e64bdb2fSÁlvaro Fernández Rojas 	uc_priv->bank_name = dev->name;
109*e64bdb2fSÁlvaro Fernández Rojas 
110*e64bdb2fSÁlvaro Fernández Rojas 	return 0;
111*e64bdb2fSÁlvaro Fernández Rojas }
112*e64bdb2fSÁlvaro Fernández Rojas 
113*e64bdb2fSÁlvaro Fernández Rojas static const struct udevice_id bcm6345_gpio_ids[] = {
114*e64bdb2fSÁlvaro Fernández Rojas 	{ .compatible = "brcm,bcm6345-gpio" },
115*e64bdb2fSÁlvaro Fernández Rojas 	{ /* sentinel */ }
116*e64bdb2fSÁlvaro Fernández Rojas };
117*e64bdb2fSÁlvaro Fernández Rojas 
118*e64bdb2fSÁlvaro Fernández Rojas U_BOOT_DRIVER(bcm6345_gpio) = {
119*e64bdb2fSÁlvaro Fernández Rojas 	.name = "bcm6345-gpio",
120*e64bdb2fSÁlvaro Fernández Rojas 	.id = UCLASS_GPIO,
121*e64bdb2fSÁlvaro Fernández Rojas 	.of_match = bcm6345_gpio_ids,
122*e64bdb2fSÁlvaro Fernández Rojas 	.ops = &bcm6345_gpio_ops,
123*e64bdb2fSÁlvaro Fernández Rojas 	.priv_auto_alloc_size = sizeof(struct bcm6345_gpio_priv),
124*e64bdb2fSÁlvaro Fernández Rojas 	.probe = bcm6345_gpio_probe,
125*e64bdb2fSÁlvaro Fernández Rojas };
126