]>
Commit | Line | Data |
---|---|---|
3194c3cd EP |
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 | }; |