1 /* 2 * (C) Copyright 2015 Google, Inc 3 * 4 * (C) Copyright 2008-2014 Rockchip Electronics 5 * Peter, Software Engineering, <superpeter.cai@gmail.com>. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <dm.h> 12 #include <asm/errno.h> 13 #include <asm/gpio.h> 14 #include <asm/io.h> 15 #include <dt-bindings/gpio/gpio.h> 16 17 enum { 18 ROCKCHIP_GPIOS_PER_BANK = 32, 19 }; 20 21 #define OFFSET_TO_BIT(bit) (1UL << (bit)) 22 23 struct rockchip_gpio_priv { 24 struct rockchip_gpio_regs *regs; 25 char name[2]; 26 }; 27 28 static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset) 29 { 30 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 31 struct rockchip_gpio_regs *regs = priv->regs; 32 33 clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); 34 35 return 0; 36 } 37 38 static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset, 39 int value) 40 { 41 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 42 struct rockchip_gpio_regs *regs = priv->regs; 43 int mask = OFFSET_TO_BIT(offset); 44 45 clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); 46 setbits_le32(®s->swport_ddr, mask); 47 48 return 0; 49 } 50 51 static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset) 52 { 53 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 54 struct rockchip_gpio_regs *regs = priv->regs; 55 56 return readl(®s->ext_port) & OFFSET_TO_BIT(offset); 57 } 58 59 static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset, 60 int value) 61 { 62 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 63 struct rockchip_gpio_regs *regs = priv->regs; 64 int mask = OFFSET_TO_BIT(offset); 65 66 clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); 67 68 return 0; 69 } 70 71 static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) 72 { 73 return -ENOSYS; 74 } 75 76 static int rockchip_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, 77 struct fdtdec_phandle_args *args) 78 { 79 desc->offset = args->args[0]; 80 desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; 81 82 return 0; 83 } 84 85 static int rockchip_gpio_probe(struct udevice *dev) 86 { 87 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 88 struct rockchip_gpio_priv *priv = dev_get_priv(dev); 89 char *end; 90 int bank; 91 92 priv->regs = (struct rockchip_gpio_regs *)dev_get_addr(dev); 93 uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; 94 end = strrchr(dev->name, '@'); 95 bank = trailing_strtoln(dev->name, end); 96 priv->name[0] = 'A' + bank; 97 uc_priv->bank_name = priv->name; 98 99 return 0; 100 } 101 102 static const struct dm_gpio_ops gpio_rockchip_ops = { 103 .direction_input = rockchip_gpio_direction_input, 104 .direction_output = rockchip_gpio_direction_output, 105 .get_value = rockchip_gpio_get_value, 106 .set_value = rockchip_gpio_set_value, 107 .get_function = rockchip_gpio_get_function, 108 .xlate = rockchip_gpio_xlate, 109 }; 110 111 static const struct udevice_id rockchip_gpio_ids[] = { 112 { .compatible = "rockchip,gpio-bank" }, 113 { } 114 }; 115 116 U_BOOT_DRIVER(gpio_rockchip) = { 117 .name = "gpio_rockchip", 118 .id = UCLASS_GPIO, 119 .of_match = rockchip_gpio_ids, 120 .ops = &gpio_rockchip_ops, 121 .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv), 122 .probe = rockchip_gpio_probe, 123 }; 124