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