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