1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 4 * Bhuvanchandra DV, Toradex, Inc. 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <errno.h> 10 #include <fdtdec.h> 11 #include <asm/gpio.h> 12 #include <asm/mach-imx/iomux-v3.h> 13 #include <asm/io.h> 14 #include <malloc.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 struct vybrid_gpios { 19 unsigned int chip; 20 struct vybrid_gpio_regs *reg; 21 }; 22 23 static int vybrid_gpio_direction_input(struct udevice *dev, unsigned gpio) 24 { 25 const struct vybrid_gpios *gpios = dev_get_priv(dev); 26 27 gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); 28 imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_IN); 29 30 return 0; 31 } 32 33 static int vybrid_gpio_direction_output(struct udevice *dev, unsigned gpio, 34 int value) 35 { 36 const struct vybrid_gpios *gpios = dev_get_priv(dev); 37 38 gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); 39 gpio_set_value(gpio, value); 40 imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_OUT); 41 42 return 0; 43 } 44 45 static int vybrid_gpio_get_value(struct udevice *dev, unsigned gpio) 46 { 47 const struct vybrid_gpios *gpios = dev_get_priv(dev); 48 49 return ((readl(&gpios->reg->gpio_pdir) & (1 << gpio))) ? 1 : 0; 50 } 51 52 static int vybrid_gpio_set_value(struct udevice *dev, unsigned gpio, 53 int value) 54 { 55 const struct vybrid_gpios *gpios = dev_get_priv(dev); 56 if (value) 57 writel((1 << gpio), &gpios->reg->gpio_psor); 58 else 59 writel((1 << gpio), &gpios->reg->gpio_pcor); 60 61 return 0; 62 } 63 64 static int vybrid_gpio_get_function(struct udevice *dev, unsigned gpio) 65 { 66 const struct vybrid_gpios *gpios = dev_get_priv(dev); 67 u32 g_state = 0; 68 69 gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); 70 71 imx_iomux_gpio_get_function(gpio, &g_state); 72 73 if (((g_state & (0x07 << PAD_MUX_MODE_SHIFT)) >> PAD_MUX_MODE_SHIFT) > 0) 74 return GPIOF_FUNC; 75 if (g_state & PAD_CTL_OBE_ENABLE) 76 return GPIOF_OUTPUT; 77 if (g_state & PAD_CTL_IBE_ENABLE) 78 return GPIOF_INPUT; 79 if (!(g_state & PAD_CTL_OBE_IBE_ENABLE)) 80 return GPIOF_UNUSED; 81 82 return GPIOF_UNKNOWN; 83 } 84 85 static const struct dm_gpio_ops gpio_vybrid_ops = { 86 .direction_input = vybrid_gpio_direction_input, 87 .direction_output = vybrid_gpio_direction_output, 88 .get_value = vybrid_gpio_get_value, 89 .set_value = vybrid_gpio_set_value, 90 .get_function = vybrid_gpio_get_function, 91 }; 92 93 static int vybrid_gpio_probe(struct udevice *dev) 94 { 95 struct vybrid_gpios *gpios = dev_get_priv(dev); 96 struct vybrid_gpio_platdata *plat = dev_get_platdata(dev); 97 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 98 99 uc_priv->bank_name = plat->port_name; 100 uc_priv->gpio_count = VYBRID_GPIO_COUNT; 101 gpios->reg = (struct vybrid_gpio_regs *)plat->base; 102 gpios->chip = plat->chip; 103 104 return 0; 105 } 106 107 static int vybrid_gpio_odata_to_platdata(struct udevice *dev) 108 { 109 struct vybrid_gpio_platdata *plat = dev_get_platdata(dev); 110 fdt_addr_t base_addr; 111 112 base_addr = devfdt_get_addr(dev); 113 if (base_addr == FDT_ADDR_T_NONE) 114 return -EINVAL; 115 116 plat->base = base_addr; 117 plat->chip = dev->req_seq; 118 plat->port_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL); 119 120 return 0; 121 } 122 123 static const struct udevice_id vybrid_gpio_ids[] = { 124 { .compatible = "fsl,vf610-gpio" }, 125 { } 126 }; 127 128 U_BOOT_DRIVER(gpio_vybrid) = { 129 .name = "gpio_vybrid", 130 .id = UCLASS_GPIO, 131 .ops = &gpio_vybrid_ops, 132 .of_match = vybrid_gpio_ids, 133 .ofdata_to_platdata = vybrid_gpio_odata_to_platdata, 134 .probe = vybrid_gpio_probe, 135 .priv_auto_alloc_size = sizeof(struct vybrid_gpios), 136 .platdata_auto_alloc_size = sizeof(struct vybrid_gpio_platdata), 137 }; 138