1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2015 Google, Inc 4 * 5 * (C) Copyright 2008-2014 Rockchip Electronics 6 * Peter, Software Engineering, <superpeter.cai@gmail.com>. 7 */ 8 9 #include <common.h> 10 #include <dm.h> 11 #include <syscon.h> 12 #include <linux/errno.h> 13 #include <asm/gpio.h> 14 #include <asm/io.h> 15 #include <asm/arch/clock.h> 16 #include <dm/pinctrl.h> 17 #include <dt-bindings/clock/rk3288-cru.h> 18 19 enum { 20 ROCKCHIP_GPIOS_PER_BANK = 32, 21 }; 22 23 #define OFFSET_TO_BIT(bit) (1UL << (bit)) 24 25 struct rockchip_gpio_priv { 26 struct rockchip_gpio_regs *regs; 27 struct udevice *pinctrl; 28 int bank; 29 char name[2]; 30 }; 31 32 static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset) 33 { 34 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 35 struct rockchip_gpio_regs *regs = priv->regs; 36 37 clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); 38 39 return 0; 40 } 41 42 static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset, 43 int value) 44 { 45 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 46 struct rockchip_gpio_regs *regs = priv->regs; 47 int mask = OFFSET_TO_BIT(offset); 48 49 clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); 50 setbits_le32(®s->swport_ddr, mask); 51 52 return 0; 53 } 54 55 static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset) 56 { 57 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 58 struct rockchip_gpio_regs *regs = priv->regs; 59 60 return readl(®s->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0; 61 } 62 63 static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset, 64 int value) 65 { 66 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 67 struct rockchip_gpio_regs *regs = priv->regs; 68 int mask = OFFSET_TO_BIT(offset); 69 70 clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); 71 72 return 0; 73 } 74 75 static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) 76 { 77 #ifdef CONFIG_SPL_BUILD 78 return -ENODATA; 79 #else 80 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 81 struct rockchip_gpio_regs *regs = priv->regs; 82 bool is_output; 83 int ret; 84 85 ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset); 86 if (ret) 87 return ret; 88 is_output = readl(®s->swport_ddr) & OFFSET_TO_BIT(offset); 89 90 return is_output ? GPIOF_OUTPUT : GPIOF_INPUT; 91 #endif 92 } 93 94 /* Simple SPL interface to GPIOs */ 95 #ifdef CONFIG_SPL_BUILD 96 97 enum { 98 PULL_NONE_1V8 = 0, 99 PULL_DOWN_1V8 = 1, 100 PULL_UP_1V8 = 3, 101 }; 102 103 int spl_gpio_set_pull(void *vregs, uint gpio, int pull) 104 { 105 u32 *regs = vregs; 106 uint val; 107 108 regs += gpio >> GPIO_BANK_SHIFT; 109 gpio &= GPIO_OFFSET_MASK; 110 switch (pull) { 111 case GPIO_PULL_UP: 112 val = PULL_UP_1V8; 113 break; 114 case GPIO_PULL_DOWN: 115 val = PULL_DOWN_1V8; 116 break; 117 case GPIO_PULL_NORMAL: 118 default: 119 val = PULL_NONE_1V8; 120 break; 121 } 122 clrsetbits_le32(regs, 3 << (gpio * 2), val << (gpio * 2)); 123 124 return 0; 125 } 126 127 int spl_gpio_output(void *vregs, uint gpio, int value) 128 { 129 struct rockchip_gpio_regs * const regs = vregs; 130 131 clrsetbits_le32(®s->swport_dr, 1 << gpio, value << gpio); 132 133 /* Set direction */ 134 clrsetbits_le32(®s->swport_ddr, 1 << gpio, 1 << gpio); 135 136 return 0; 137 } 138 #endif /* CONFIG_SPL_BUILD */ 139 140 static int rockchip_gpio_probe(struct udevice *dev) 141 { 142 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 143 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 144 char *end; 145 int ret; 146 147 priv->regs = dev_read_addr_ptr(dev); 148 ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); 149 if (ret) 150 return ret; 151 152 uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; 153 end = strrchr(dev->name, '@'); 154 priv->bank = trailing_strtoln(dev->name, end); 155 priv->name[0] = 'A' + priv->bank; 156 uc_priv->bank_name = priv->name; 157 158 return 0; 159 } 160 161 static const struct dm_gpio_ops gpio_rockchip_ops = { 162 .direction_input = rockchip_gpio_direction_input, 163 .direction_output = rockchip_gpio_direction_output, 164 .get_value = rockchip_gpio_get_value, 165 .set_value = rockchip_gpio_set_value, 166 .get_function = rockchip_gpio_get_function, 167 }; 168 169 static const struct udevice_id rockchip_gpio_ids[] = { 170 { .compatible = "rockchip,gpio-bank" }, 171 { } 172 }; 173 174 U_BOOT_DRIVER(gpio_rockchip) = { 175 .name = "gpio_rockchip", 176 .id = UCLASS_GPIO, 177 .of_match = rockchip_gpio_ids, 178 .ops = &gpio_rockchip_ops, 179 .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv), 180 .probe = rockchip_gpio_probe, 181 }; 182