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