xref: /openbmc/u-boot/drivers/gpio/hsdk-creg-gpio.c (revision 3194c3cddf7bbb7d2d74097e54f587953d0bb35f)
1*3194c3cdSEugeniy Paltsev /*
2*3194c3cdSEugeniy Paltsev  * Synopsys HSDK SDP Generic PLL clock driver
3*3194c3cdSEugeniy Paltsev  *
4*3194c3cdSEugeniy Paltsev  * Copyright (C) 2017 Synopsys
5*3194c3cdSEugeniy Paltsev  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
6*3194c3cdSEugeniy Paltsev  *
7*3194c3cdSEugeniy Paltsev  * This file is licensed under the terms of the GNU General Public
8*3194c3cdSEugeniy Paltsev  * License version 2. This program is licensed "as is" without any
9*3194c3cdSEugeniy Paltsev  * warranty of any kind, whether express or implied.
10*3194c3cdSEugeniy Paltsev  */
11*3194c3cdSEugeniy Paltsev 
12*3194c3cdSEugeniy Paltsev #include <asm-generic/gpio.h>
13*3194c3cdSEugeniy Paltsev #include <asm/io.h>
14*3194c3cdSEugeniy Paltsev #include <common.h>
15*3194c3cdSEugeniy Paltsev #include <dm.h>
16*3194c3cdSEugeniy Paltsev #include <errno.h>
17*3194c3cdSEugeniy Paltsev #include <linux/printk.h>
18*3194c3cdSEugeniy Paltsev 
19*3194c3cdSEugeniy Paltsev DECLARE_GLOBAL_DATA_PTR;
20*3194c3cdSEugeniy Paltsev 
21*3194c3cdSEugeniy Paltsev #define HSDK_CREG_MAX_GPIO	8
22*3194c3cdSEugeniy Paltsev 
23*3194c3cdSEugeniy Paltsev #define GPIO_ACTIVATE		0x2
24*3194c3cdSEugeniy Paltsev #define GPIO_DEACTIVATE		0x3
25*3194c3cdSEugeniy Paltsev #define GPIO_PIN_MASK		0x3
26*3194c3cdSEugeniy Paltsev #define BIT_PER_GPIO		2
27*3194c3cdSEugeniy Paltsev 
28*3194c3cdSEugeniy Paltsev struct hsdk_creg_gpio {
29*3194c3cdSEugeniy Paltsev 	uint32_t *regs;
30*3194c3cdSEugeniy Paltsev };
31*3194c3cdSEugeniy Paltsev 
32*3194c3cdSEugeniy Paltsev static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val)
33*3194c3cdSEugeniy Paltsev {
34*3194c3cdSEugeniy Paltsev 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
35*3194c3cdSEugeniy Paltsev 	uint32_t reg = readl(hcg->regs);
36*3194c3cdSEugeniy Paltsev 	uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE;
37*3194c3cdSEugeniy Paltsev 
38*3194c3cdSEugeniy Paltsev 	reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO));
39*3194c3cdSEugeniy Paltsev 	reg |=  (cmd << (oft * BIT_PER_GPIO));
40*3194c3cdSEugeniy Paltsev 
41*3194c3cdSEugeniy Paltsev 	writel(reg, hcg->regs);
42*3194c3cdSEugeniy Paltsev 
43*3194c3cdSEugeniy Paltsev 	return 0;
44*3194c3cdSEugeniy Paltsev }
45*3194c3cdSEugeniy Paltsev 
46*3194c3cdSEugeniy Paltsev static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft,
47*3194c3cdSEugeniy Paltsev 					   int val)
48*3194c3cdSEugeniy Paltsev {
49*3194c3cdSEugeniy Paltsev 	hsdk_creg_gpio_set_value(dev, oft, val);
50*3194c3cdSEugeniy Paltsev 
51*3194c3cdSEugeniy Paltsev 	return 0;
52*3194c3cdSEugeniy Paltsev }
53*3194c3cdSEugeniy Paltsev 
54*3194c3cdSEugeniy Paltsev static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
55*3194c3cdSEugeniy Paltsev {
56*3194c3cdSEugeniy Paltsev 	pr_err("hsdk-creg-gpio can't be used as input!\n");
57*3194c3cdSEugeniy Paltsev 
58*3194c3cdSEugeniy Paltsev 	return -ENOTSUPP;
59*3194c3cdSEugeniy Paltsev }
60*3194c3cdSEugeniy Paltsev 
61*3194c3cdSEugeniy Paltsev static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft)
62*3194c3cdSEugeniy Paltsev {
63*3194c3cdSEugeniy Paltsev 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
64*3194c3cdSEugeniy Paltsev 	uint32_t val = readl(hcg->regs);
65*3194c3cdSEugeniy Paltsev 
66*3194c3cdSEugeniy Paltsev 	val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK;
67*3194c3cdSEugeniy Paltsev 	return (val == GPIO_DEACTIVATE) ? 1 : 0;
68*3194c3cdSEugeniy Paltsev }
69*3194c3cdSEugeniy Paltsev 
70*3194c3cdSEugeniy Paltsev static const struct dm_gpio_ops hsdk_creg_gpio_ops = {
71*3194c3cdSEugeniy Paltsev 	.direction_output	= hsdk_creg_gpio_direction_output,
72*3194c3cdSEugeniy Paltsev 	.direction_input	= hsdk_creg_gpio_direction_input,
73*3194c3cdSEugeniy Paltsev 	.set_value		= hsdk_creg_gpio_set_value,
74*3194c3cdSEugeniy Paltsev 	.get_value		= hsdk_creg_gpio_get_value,
75*3194c3cdSEugeniy Paltsev };
76*3194c3cdSEugeniy Paltsev 
77*3194c3cdSEugeniy Paltsev static int hsdk_creg_gpio_probe(struct udevice *dev)
78*3194c3cdSEugeniy Paltsev {
79*3194c3cdSEugeniy Paltsev 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
80*3194c3cdSEugeniy Paltsev 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
81*3194c3cdSEugeniy Paltsev 
82*3194c3cdSEugeniy Paltsev 	hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev);
83*3194c3cdSEugeniy Paltsev 
84*3194c3cdSEugeniy Paltsev 	uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
85*3194c3cdSEugeniy Paltsev 	if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO)
86*3194c3cdSEugeniy Paltsev 		uc_priv->gpio_count = HSDK_CREG_MAX_GPIO;
87*3194c3cdSEugeniy Paltsev 
88*3194c3cdSEugeniy Paltsev 	uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
89*3194c3cdSEugeniy Paltsev 	if (!uc_priv->bank_name)
90*3194c3cdSEugeniy Paltsev 		uc_priv->bank_name = dev_read_name(dev);
91*3194c3cdSEugeniy Paltsev 
92*3194c3cdSEugeniy Paltsev 	pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n",
93*3194c3cdSEugeniy Paltsev 		 uc_priv->bank_name, hcg->regs, uc_priv->gpio_count);
94*3194c3cdSEugeniy Paltsev 
95*3194c3cdSEugeniy Paltsev 	return 0;
96*3194c3cdSEugeniy Paltsev }
97*3194c3cdSEugeniy Paltsev 
98*3194c3cdSEugeniy Paltsev static const struct udevice_id hsdk_creg_gpio_ids[] = {
99*3194c3cdSEugeniy Paltsev 	{ .compatible = "snps,hsdk-creg-gpio" },
100*3194c3cdSEugeniy Paltsev 	{ }
101*3194c3cdSEugeniy Paltsev };
102*3194c3cdSEugeniy Paltsev 
103*3194c3cdSEugeniy Paltsev U_BOOT_DRIVER(gpio_hsdk_creg) = {
104*3194c3cdSEugeniy Paltsev 	.name	= "gpio_hsdk_creg",
105*3194c3cdSEugeniy Paltsev 	.id	= UCLASS_GPIO,
106*3194c3cdSEugeniy Paltsev 	.ops	= &hsdk_creg_gpio_ops,
107*3194c3cdSEugeniy Paltsev 	.probe	= hsdk_creg_gpio_probe,
108*3194c3cdSEugeniy Paltsev 	.of_match = hsdk_creg_gpio_ids,
109*3194c3cdSEugeniy Paltsev 	.platdata_auto_alloc_size = sizeof(struct hsdk_creg_gpio),
110*3194c3cdSEugeniy Paltsev };
111