common: fit: Allow U-Boot images to be booted
[oweals/u-boot.git] / drivers / gpio / mpc85xx_gpio.c
index 17755dfb9243dcc4100e9bd0ca6c941e210c45ae..3754a8215c3630db7c33cc50a13eff8959fa6b04 100644 (file)
@@ -73,6 +73,25 @@ static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
        setbits_be32(&base->gpdir, gpios);
 }
 
+static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
+{
+       return in_be32(&base->gpodr) & mask;
+}
+
+static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32
+                                             gpios)
+{
+       /* GPODR register 1 -> open drain on */
+       setbits_be32(&base->gpodr, gpios);
+}
+
+static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base,
+                                              u32 gpios)
+{
+       /* GPODR register 0 -> open drain off (actively driven) */
+       clrbits_be32(&base->gpodr, gpios);
+}
+
 static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio)
 {
        struct mpc85xx_gpio_data *data = dev_get_priv(dev);
@@ -115,6 +134,26 @@ static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio)
        }
 }
 
+static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio)
+{
+       struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+       return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio));
+}
+
+static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio,
+                                      int value)
+{
+       struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+       if (value) {
+               mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio));
+       } else {
+               mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio));
+       }
+       return 0;
+}
+
 static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
 {
        struct mpc85xx_gpio_data *data = dev_get_priv(dev);
@@ -124,23 +163,41 @@ static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
        return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
 }
 
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
-       struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+       struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
        fdt_addr_t addr;
        fdt_size_t size;
 
        addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
                                                  "reg", 0, &size);
 
-       data->addr = addr;
-       data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
+       plat->addr = addr;
+       plat->size = size;
+       plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                                 "ngpios", 32);
 
-       if (!data->base)
+       return 0;
+}
+#endif
+
+static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev)
+{
+       struct mpc85xx_gpio_data *priv = dev_get_priv(dev);
+       struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
+       unsigned long size = plat->size;
+
+       if (size == 0)
+               size = 0x100;
+
+       priv->addr = plat->addr;
+       priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size);
+
+       if (!priv->base)
                return -ENOMEM;
 
-       data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
-                                         "ngpios", 32);
-       data->dat_shadow = 0;
+       priv->gpio_count = plat->ngpios;
+       priv->dat_shadow = 0;
 
        return 0;
 }
@@ -151,6 +208,8 @@ static int mpc85xx_gpio_probe(struct udevice *dev)
        struct mpc85xx_gpio_data *data = dev_get_priv(dev);
        char name[32], *str;
 
+       mpc85xx_gpio_platdata_to_priv(dev);
+
        snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
        str = strdup(name);
 
@@ -168,6 +227,8 @@ static const struct dm_gpio_ops gpio_mpc85xx_ops = {
        .direction_output       = mpc85xx_gpio_direction_output,
        .get_value              = mpc85xx_gpio_get_value,
        .set_value              = mpc85xx_gpio_set_value,
+       .get_open_drain         = mpc85xx_gpio_get_open_drain,
+       .set_open_drain         = mpc85xx_gpio_set_open_drain,
        .get_function           = mpc85xx_gpio_get_function,
 };
 
@@ -180,8 +241,11 @@ U_BOOT_DRIVER(gpio_mpc85xx) = {
        .name   = "gpio_mpc85xx",
        .id     = UCLASS_GPIO,
        .ops    = &gpio_mpc85xx_ops,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
        .ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat),
        .of_match = mpc85xx_gpio_ids,
+#endif
        .probe  = mpc85xx_gpio_probe,
        .priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
 };