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 static int rockchip_gpio_probe(struct udevice *dev) 95 { 96 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 97 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 98 char *end; 99 int ret; 100 101 priv->regs = dev_read_addr_ptr(dev); 102 ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl); 103 if (ret) 104 return ret; 105 106 uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; 107 end = strrchr(dev->name, '@'); 108 priv->bank = trailing_strtoln(dev->name, end); 109 priv->name[0] = 'A' + priv->bank; 110 uc_priv->bank_name = priv->name; 111 112 return 0; 113 } 114 115 static const struct dm_gpio_ops gpio_rockchip_ops = { 116 .direction_input = rockchip_gpio_direction_input, 117 .direction_output = rockchip_gpio_direction_output, 118 .get_value = rockchip_gpio_get_value, 119 .set_value = rockchip_gpio_set_value, 120 .get_function = rockchip_gpio_get_function, 121 }; 122 123 static const struct udevice_id rockchip_gpio_ids[] = { 124 { .compatible = "rockchip,gpio-bank" }, 125 { } 126 }; 127 128 U_BOOT_DRIVER(gpio_rockchip) = { 129 .name = "gpio_rockchip", 130 .id = UCLASS_GPIO, 131 .of_match = rockchip_gpio_ids, 132 .ops = &gpio_rockchip_ops, 133 .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv), 134 .probe = rockchip_gpio_probe, 135 }; 136