Commit 3194c3cddf7bbb7d2d74097e54f587953d0bb35f
Committed by
Alexey Brodkin
1 parent
d9d76023ea
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
ARC: HSDK: introduce CREG GPIO driver
The HSDK can manage some pins via CREG registers block. Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Showing 4 changed files with 124 additions and 0 deletions Side-by-side Diff
MAINTAINERS
... | ... | @@ -59,6 +59,12 @@ |
59 | 59 | T: git git://git.denx.de/u-boot-arc.git |
60 | 60 | F: arch/arc/ |
61 | 61 | |
62 | +ARC HSDK CREG GPIO | |
63 | +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | |
64 | +S: Maintained | |
65 | +L: uboot-snps-arc@synopsys.com | |
66 | +F: drivers/gpio/hsdk-creg-gpio.c | |
67 | + | |
62 | 68 | ARM |
63 | 69 | M: Albert Aribaud <albert.u.boot@aribaud.net> |
64 | 70 | S: Maintained |
drivers/gpio/Kconfig
... | ... | @@ -80,6 +80,13 @@ |
80 | 80 | help |
81 | 81 | This driver supports i.MX7ULP Rapid GPIO2P controller. |
82 | 82 | |
83 | +config HSDK_CREG_GPIO | |
84 | + bool "HSDK CREG GPIO griver" | |
85 | + depends on DM | |
86 | + default n | |
87 | + help | |
88 | + This driver supports CREG GPIOs on Synopsys HSDK SOC. | |
89 | + | |
83 | 90 | config LPC32XX_GPIO |
84 | 91 | bool "LPC32XX GPIO driver" |
85 | 92 | depends on DM |
drivers/gpio/Makefile
... | ... | @@ -54,6 +54,7 @@ |
54 | 54 | obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o |
55 | 55 | obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o |
56 | 56 | obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o |
57 | +obj-$(CONFIG_HSDK_CREG_GPIO) += hsdk-creg-gpio.o | |
57 | 58 | obj-$(CONFIG_IMX_RGPIO2P) += imx_rgpio2p.o |
58 | 59 | obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o |
59 | 60 | obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o |
drivers/gpio/hsdk-creg-gpio.c
1 | +/* | |
2 | + * Synopsys HSDK SDP Generic PLL clock driver | |
3 | + * | |
4 | + * Copyright (C) 2017 Synopsys | |
5 | + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | |
6 | + * | |
7 | + * This file is licensed under the terms of the GNU General Public | |
8 | + * License version 2. This program is licensed "as is" without any | |
9 | + * warranty of any kind, whether express or implied. | |
10 | + */ | |
11 | + | |
12 | +#include <asm-generic/gpio.h> | |
13 | +#include <asm/io.h> | |
14 | +#include <common.h> | |
15 | +#include <dm.h> | |
16 | +#include <errno.h> | |
17 | +#include <linux/printk.h> | |
18 | + | |
19 | +DECLARE_GLOBAL_DATA_PTR; | |
20 | + | |
21 | +#define HSDK_CREG_MAX_GPIO 8 | |
22 | + | |
23 | +#define GPIO_ACTIVATE 0x2 | |
24 | +#define GPIO_DEACTIVATE 0x3 | |
25 | +#define GPIO_PIN_MASK 0x3 | |
26 | +#define BIT_PER_GPIO 2 | |
27 | + | |
28 | +struct hsdk_creg_gpio { | |
29 | + uint32_t *regs; | |
30 | +}; | |
31 | + | |
32 | +static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val) | |
33 | +{ | |
34 | + struct hsdk_creg_gpio *hcg = dev_get_priv(dev); | |
35 | + uint32_t reg = readl(hcg->regs); | |
36 | + uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE; | |
37 | + | |
38 | + reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO)); | |
39 | + reg |= (cmd << (oft * BIT_PER_GPIO)); | |
40 | + | |
41 | + writel(reg, hcg->regs); | |
42 | + | |
43 | + return 0; | |
44 | +} | |
45 | + | |
46 | +static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft, | |
47 | + int val) | |
48 | +{ | |
49 | + hsdk_creg_gpio_set_value(dev, oft, val); | |
50 | + | |
51 | + return 0; | |
52 | +} | |
53 | + | |
54 | +static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft) | |
55 | +{ | |
56 | + pr_err("hsdk-creg-gpio can't be used as input!\n"); | |
57 | + | |
58 | + return -ENOTSUPP; | |
59 | +} | |
60 | + | |
61 | +static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft) | |
62 | +{ | |
63 | + struct hsdk_creg_gpio *hcg = dev_get_priv(dev); | |
64 | + uint32_t val = readl(hcg->regs); | |
65 | + | |
66 | + val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK; | |
67 | + return (val == GPIO_DEACTIVATE) ? 1 : 0; | |
68 | +} | |
69 | + | |
70 | +static const struct dm_gpio_ops hsdk_creg_gpio_ops = { | |
71 | + .direction_output = hsdk_creg_gpio_direction_output, | |
72 | + .direction_input = hsdk_creg_gpio_direction_input, | |
73 | + .set_value = hsdk_creg_gpio_set_value, | |
74 | + .get_value = hsdk_creg_gpio_get_value, | |
75 | +}; | |
76 | + | |
77 | +static int hsdk_creg_gpio_probe(struct udevice *dev) | |
78 | +{ | |
79 | + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
80 | + struct hsdk_creg_gpio *hcg = dev_get_priv(dev); | |
81 | + | |
82 | + hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev); | |
83 | + | |
84 | + uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1); | |
85 | + if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO) | |
86 | + uc_priv->gpio_count = HSDK_CREG_MAX_GPIO; | |
87 | + | |
88 | + uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name"); | |
89 | + if (!uc_priv->bank_name) | |
90 | + uc_priv->bank_name = dev_read_name(dev); | |
91 | + | |
92 | + pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n", | |
93 | + uc_priv->bank_name, hcg->regs, uc_priv->gpio_count); | |
94 | + | |
95 | + return 0; | |
96 | +} | |
97 | + | |
98 | +static const struct udevice_id hsdk_creg_gpio_ids[] = { | |
99 | + { .compatible = "snps,hsdk-creg-gpio" }, | |
100 | + { } | |
101 | +}; | |
102 | + | |
103 | +U_BOOT_DRIVER(gpio_hsdk_creg) = { | |
104 | + .name = "gpio_hsdk_creg", | |
105 | + .id = UCLASS_GPIO, | |
106 | + .ops = &hsdk_creg_gpio_ops, | |
107 | + .probe = hsdk_creg_gpio_probe, | |
108 | + .of_match = hsdk_creg_gpio_ids, | |
109 | + .platdata_auto_alloc_size = sizeof(struct hsdk_creg_gpio), | |
110 | +}; |