1 /* 2 * Take drivers/gpio/gpio-74x164.c as reference. 3 * 4 * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver 5 * 6 * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 * 10 */ 11 12 #include <common.h> 13 #include <errno.h> 14 #include <dm.h> 15 #include <fdtdec.h> 16 #include <malloc.h> 17 #include <asm/gpio.h> 18 #include <asm/io.h> 19 #include <dt-bindings/gpio/gpio.h> 20 #include <spi.h> 21 22 DECLARE_GLOBAL_DATA_PTR; 23 24 /* 25 * struct gen_74x164_chip - Data for 74Hx164 26 * 27 * @oe: OE pin 28 * @nregs: number of registers 29 * @buffer: buffer for chained chips 30 */ 31 #define GEN_74X164_NUMBER_GPIOS 8 32 33 struct gen_74x164_priv { 34 struct gpio_desc oe; 35 u32 nregs; 36 /* 37 * Since the nregs are chained, every byte sent will make 38 * the previous byte shift to the next register in the 39 * chain. Thus, the first byte sent will end up in the last 40 * register at the end of the transfer. So, to have a logical 41 * numbering, store the bytes in reverse order. 42 */ 43 u8 *buffer; 44 }; 45 46 static int gen_74x164_write_conf(struct udevice *dev) 47 { 48 struct gen_74x164_priv *priv = dev_get_priv(dev); 49 int ret; 50 51 ret = dm_spi_claim_bus(dev); 52 if (ret) 53 return ret; 54 55 ret = dm_spi_xfer(dev, priv->nregs * 8, priv->buffer, NULL, 56 SPI_XFER_BEGIN | SPI_XFER_END); 57 58 dm_spi_release_bus(dev); 59 60 return ret; 61 } 62 63 static int gen_74x164_get_value(struct udevice *dev, unsigned offset) 64 { 65 struct gen_74x164_priv *priv = dev_get_priv(dev); 66 uint bank = priv->nregs - 1 - offset / 8; 67 uint pin = offset % 8; 68 69 return (priv->buffer[bank] >> pin) & 0x1; 70 } 71 72 static int gen_74x164_set_value(struct udevice *dev, unsigned offset, 73 int value) 74 { 75 struct gen_74x164_priv *priv = dev_get_priv(dev); 76 uint bank = priv->nregs - 1 - offset / 8; 77 uint pin = offset % 8; 78 int ret; 79 80 if (value) 81 priv->buffer[bank] |= 1 << pin; 82 else 83 priv->buffer[bank] &= ~(1 << pin); 84 85 ret = gen_74x164_write_conf(dev); 86 if (ret) 87 return ret; 88 89 return 0; 90 } 91 92 static int gen_74x164_direction_input(struct udevice *dev, unsigned offset) 93 { 94 return -ENOSYS; 95 } 96 97 static int gen_74x164_direction_output(struct udevice *dev, unsigned offset, 98 int value) 99 { 100 return gen_74x164_set_value(dev, offset, value); 101 } 102 103 static int gen_74x164_get_function(struct udevice *dev, unsigned offset) 104 { 105 return GPIOF_OUTPUT; 106 } 107 108 static int gen_74x164_xlate(struct udevice *dev, struct gpio_desc *desc, 109 struct fdtdec_phandle_args *args) 110 { 111 desc->offset = args->args[0]; 112 desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; 113 114 return 0; 115 } 116 117 static const struct dm_gpio_ops gen_74x164_ops = { 118 .direction_input = gen_74x164_direction_input, 119 .direction_output = gen_74x164_direction_output, 120 .get_value = gen_74x164_get_value, 121 .set_value = gen_74x164_set_value, 122 .get_function = gen_74x164_get_function, 123 .xlate = gen_74x164_xlate, 124 }; 125 126 static int gen_74x164_probe(struct udevice *dev) 127 { 128 struct gen_74x164_priv *priv = dev_get_priv(dev); 129 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 130 char *str, name[32]; 131 int ret; 132 const void *fdt = gd->fdt_blob; 133 int node = dev_of_offset(dev); 134 135 snprintf(name, sizeof(name), "%s_", dev->name); 136 str = strdup(name); 137 if (!str) 138 return -ENOMEM; 139 140 /* 141 * See Linux kernel: 142 * Documentation/devicetree/bindings/gpio/gpio-74x164.txt 143 */ 144 priv->nregs = fdtdec_get_int(fdt, node, "registers-number", 1); 145 priv->buffer = calloc(priv->nregs, sizeof(u8)); 146 if (!priv->buffer) { 147 ret = -ENOMEM; 148 goto free_str; 149 } 150 151 ret = fdtdec_get_byte_array(fdt, node, "registers-default", 152 priv->buffer, priv->nregs); 153 if (ret) 154 dev_dbg(dev, "No registers-default property\n"); 155 156 ret = gpio_request_by_name(dev, "oe-gpios", 0, &priv->oe, 157 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 158 if (ret) { 159 dev_dbg(dev, "No oe-pins property\n"); 160 } 161 162 uc_priv->bank_name = str; 163 uc_priv->gpio_count = priv->nregs * 8; 164 165 ret = gen_74x164_write_conf(dev); 166 if (ret) 167 goto free_buf; 168 169 dev_dbg(dev, "%s is ready\n", dev->name); 170 171 return 0; 172 173 free_buf: 174 free(priv->buffer); 175 free_str: 176 free(str); 177 return ret; 178 } 179 180 static const struct udevice_id gen_74x164_ids[] = { 181 { .compatible = "fairchild,74hc595" }, 182 { } 183 }; 184 185 U_BOOT_DRIVER(74x164) = { 186 .name = "74x164", 187 .id = UCLASS_GPIO, 188 .ops = &gen_74x164_ops, 189 .probe = gen_74x164_probe, 190 .priv_auto_alloc_size = sizeof(struct gen_74x164_priv), 191 .of_match = gen_74x164_ids, 192 }; 193