1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2016 4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc 5 * 6 * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is 7 * 8 * Copyright 2010 eXMeritus, A Boeing Company 9 */ 10 11 #include <common.h> 12 #include <dm.h> 13 #include <mapmem.h> 14 #include <asm/gpio.h> 15 16 struct ccsr_gpio { 17 u32 gpdir; 18 u32 gpodr; 19 u32 gpdat; 20 u32 gpier; 21 u32 gpimr; 22 u32 gpicr; 23 }; 24 25 struct mpc8xxx_gpio_data { 26 /* The bank's register base in memory */ 27 struct ccsr_gpio __iomem *base; 28 /* The address of the registers; used to identify the bank */ 29 ulong addr; 30 /* The GPIO count of the bank */ 31 uint gpio_count; 32 /* The GPDAT register cannot be used to determine the value of output 33 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value 34 * for output pins 35 */ 36 u32 dat_shadow; 37 ulong type; 38 }; 39 40 enum { 41 MPC8XXX_GPIO_TYPE, 42 MPC5121_GPIO_TYPE, 43 }; 44 45 inline u32 gpio_mask(uint gpio) 46 { 47 return (1U << (31 - (gpio))); 48 } 49 50 static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask) 51 { 52 return in_be32(&base->gpdat) & mask; 53 } 54 55 static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask) 56 { 57 return in_be32(&base->gpdir) & mask; 58 } 59 60 static inline void mpc8xxx_gpio_set_in(struct ccsr_gpio *base, u32 gpios) 61 { 62 clrbits_be32(&base->gpdat, gpios); 63 /* GPDIR register 0 -> input */ 64 clrbits_be32(&base->gpdir, gpios); 65 } 66 67 static inline void mpc8xxx_gpio_set_low(struct ccsr_gpio *base, u32 gpios) 68 { 69 clrbits_be32(&base->gpdat, gpios); 70 /* GPDIR register 1 -> output */ 71 setbits_be32(&base->gpdir, gpios); 72 } 73 74 static inline void mpc8xxx_gpio_set_high(struct ccsr_gpio *base, u32 gpios) 75 { 76 setbits_be32(&base->gpdat, gpios); 77 /* GPDIR register 1 -> output */ 78 setbits_be32(&base->gpdir, gpios); 79 } 80 81 static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask) 82 { 83 return in_be32(&base->gpodr) & mask; 84 } 85 86 static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32 87 gpios) 88 { 89 /* GPODR register 1 -> open drain on */ 90 setbits_be32(&base->gpodr, gpios); 91 } 92 93 static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base, 94 u32 gpios) 95 { 96 /* GPODR register 0 -> open drain off (actively driven) */ 97 clrbits_be32(&base->gpodr, gpios); 98 } 99 100 static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio) 101 { 102 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 103 104 mpc8xxx_gpio_set_in(data->base, gpio_mask(gpio)); 105 return 0; 106 } 107 108 static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value) 109 { 110 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 111 112 if (value) { 113 data->dat_shadow |= gpio_mask(gpio); 114 mpc8xxx_gpio_set_high(data->base, gpio_mask(gpio)); 115 } else { 116 data->dat_shadow &= ~gpio_mask(gpio); 117 mpc8xxx_gpio_set_low(data->base, gpio_mask(gpio)); 118 } 119 return 0; 120 } 121 122 static int mpc8xxx_gpio_direction_output(struct udevice *dev, uint gpio, 123 int value) 124 { 125 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 126 127 /* GPIO 28..31 are input only on MPC5121 */ 128 if (data->type == MPC5121_GPIO_TYPE && gpio >= 28) 129 return -EINVAL; 130 131 return mpc8xxx_gpio_set_value(dev, gpio, value); 132 } 133 134 static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio) 135 { 136 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 137 138 if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) { 139 /* Output -> use shadowed value */ 140 return !!(data->dat_shadow & gpio_mask(gpio)); 141 } 142 143 /* Input -> read value from GPDAT register */ 144 return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio)); 145 } 146 147 static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio) 148 { 149 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 150 151 return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio)); 152 } 153 154 static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio, 155 int value) 156 { 157 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 158 159 if (value) 160 mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio)); 161 else 162 mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio)); 163 164 return 0; 165 } 166 167 static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) 168 { 169 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 170 int dir; 171 172 dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio)); 173 return dir ? GPIOF_OUTPUT : GPIOF_INPUT; 174 } 175 176 #if CONFIG_IS_ENABLED(OF_CONTROL) 177 static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev) 178 { 179 struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); 180 fdt_addr_t addr; 181 u32 reg[2]; 182 183 dev_read_u32_array(dev, "reg", reg, 2); 184 addr = dev_translate_address(dev, reg); 185 186 plat->addr = addr; 187 plat->size = reg[1]; 188 plat->ngpios = dev_read_u32_default(dev, "ngpios", 32); 189 190 return 0; 191 } 192 #endif 193 194 static int mpc8xxx_gpio_platdata_to_priv(struct udevice *dev) 195 { 196 struct mpc8xxx_gpio_data *priv = dev_get_priv(dev); 197 struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); 198 unsigned long size = plat->size; 199 ulong driver_data = dev_get_driver_data(dev); 200 201 if (size == 0) 202 size = 0x100; 203 204 priv->addr = plat->addr; 205 priv->base = map_sysmem(plat->addr, size); 206 207 if (!priv->base) 208 return -ENOMEM; 209 210 priv->gpio_count = plat->ngpios; 211 priv->dat_shadow = 0; 212 213 priv->type = driver_data; 214 215 return 0; 216 } 217 218 static int mpc8xxx_gpio_probe(struct udevice *dev) 219 { 220 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 221 struct mpc8xxx_gpio_data *data = dev_get_priv(dev); 222 char name[32], *str; 223 224 mpc8xxx_gpio_platdata_to_priv(dev); 225 226 snprintf(name, sizeof(name), "MPC@%lx_", data->addr); 227 str = strdup(name); 228 229 if (!str) 230 return -ENOMEM; 231 232 uc_priv->bank_name = str; 233 uc_priv->gpio_count = data->gpio_count; 234 235 return 0; 236 } 237 238 static const struct dm_gpio_ops gpio_mpc8xxx_ops = { 239 .direction_input = mpc8xxx_gpio_direction_input, 240 .direction_output = mpc8xxx_gpio_direction_output, 241 .get_value = mpc8xxx_gpio_get_value, 242 .set_value = mpc8xxx_gpio_set_value, 243 .get_open_drain = mpc8xxx_gpio_get_open_drain, 244 .set_open_drain = mpc8xxx_gpio_set_open_drain, 245 .get_function = mpc8xxx_gpio_get_function, 246 }; 247 248 static const struct udevice_id mpc8xxx_gpio_ids[] = { 249 { .compatible = "fsl,pq3-gpio", .data = MPC8XXX_GPIO_TYPE }, 250 { .compatible = "fsl,mpc8308-gpio", .data = MPC8XXX_GPIO_TYPE }, 251 { .compatible = "fsl,mpc8349-gpio", .data = MPC8XXX_GPIO_TYPE }, 252 { .compatible = "fsl,mpc8572-gpio", .data = MPC8XXX_GPIO_TYPE}, 253 { .compatible = "fsl,mpc8610-gpio", .data = MPC8XXX_GPIO_TYPE}, 254 { .compatible = "fsl,mpc5121-gpio", .data = MPC5121_GPIO_TYPE, }, 255 { .compatible = "fsl,qoriq-gpio", .data = MPC8XXX_GPIO_TYPE }, 256 { /* sentinel */ } 257 }; 258 259 U_BOOT_DRIVER(gpio_mpc8xxx) = { 260 .name = "gpio_mpc8xxx", 261 .id = UCLASS_GPIO, 262 .ops = &gpio_mpc8xxx_ops, 263 #if CONFIG_IS_ENABLED(OF_CONTROL) 264 .ofdata_to_platdata = mpc8xxx_gpio_ofdata_to_platdata, 265 .platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat), 266 .of_match = mpc8xxx_gpio_ids, 267 #endif 268 .probe = mpc8xxx_gpio_probe, 269 .priv_auto_alloc_size = sizeof(struct mpc8xxx_gpio_data), 270 }; 271