|
@@ -1100,3 +1100,126 @@ void bfin_gpio_irq_free(unsigned gpio)
|
|
|
dump_stack();
|
|
|
gpio_error(gpio);
|
|
|
hard_local_irq_restore(flags);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ unreserve(gpio_irq, gpio);
|
|
|
+
|
|
|
+ set_label(gpio, "free");
|
|
|
+
|
|
|
+ hard_local_irq_restore(flags);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void __bfin_gpio_direction_input(unsigned gpio)
|
|
|
+{
|
|
|
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
|
|
|
+ gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
|
|
|
+#else
|
|
|
+ gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
|
|
|
+#endif
|
|
|
+ gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
|
|
|
+}
|
|
|
+
|
|
|
+int bfin_gpio_direction_input(unsigned gpio)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (unlikely(!is_reserved(gpio, gpio, 0))) {
|
|
|
+ gpio_error(gpio);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ flags = hard_local_irq_save();
|
|
|
+ __bfin_gpio_direction_input(gpio);
|
|
|
+ AWA_DUMMY_READ(inen);
|
|
|
+ hard_local_irq_restore(flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(bfin_gpio_direction_input);
|
|
|
+
|
|
|
+void bfin_gpio_irq_prepare(unsigned gpio)
|
|
|
+{
|
|
|
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
|
|
|
+ unsigned long flags;
|
|
|
+#endif
|
|
|
+
|
|
|
+ port_setup(gpio, GPIO_USAGE);
|
|
|
+
|
|
|
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
|
|
|
+ flags = hard_local_irq_save();
|
|
|
+ __bfin_gpio_direction_input(gpio);
|
|
|
+ hard_local_irq_restore(flags);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+void bfin_gpio_set_value(unsigned gpio, int arg)
|
|
|
+{
|
|
|
+ if (arg)
|
|
|
+ gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
|
|
|
+ else
|
|
|
+ gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(bfin_gpio_set_value);
|
|
|
+
|
|
|
+int bfin_gpio_direction_output(unsigned gpio, int value)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (unlikely(!is_reserved(gpio, gpio, 0))) {
|
|
|
+ gpio_error(gpio);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ flags = hard_local_irq_save();
|
|
|
+
|
|
|
+ gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
|
|
|
+ gpio_set_value(gpio, value);
|
|
|
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
|
|
|
+ gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
|
|
|
+#else
|
|
|
+ gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
|
|
|
+#endif
|
|
|
+
|
|
|
+ AWA_DUMMY_READ(dir);
|
|
|
+ hard_local_irq_restore(flags);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(bfin_gpio_direction_output);
|
|
|
+
|
|
|
+int bfin_gpio_get_value(unsigned gpio)
|
|
|
+{
|
|
|
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
|
|
|
+ return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
|
|
|
+#else
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (unlikely(get_gpio_edge(gpio))) {
|
|
|
+ int ret;
|
|
|
+ flags = hard_local_irq_save();
|
|
|
+ set_gpio_edge(gpio, 0);
|
|
|
+ ret = get_gpio_data(gpio);
|
|
|
+ set_gpio_edge(gpio, 1);
|
|
|
+ hard_local_irq_restore(flags);
|
|
|
+ return ret;
|
|
|
+ } else
|
|
|
+ return get_gpio_data(gpio);
|
|
|
+#endif
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(bfin_gpio_get_value);
|
|
|
+
|
|
|
+/* If we are booting from SPI and our board lacks a strong enough pull up,
|
|
|
+ * the core can reset and execute the bootrom faster than the resistor can
|
|
|
+ * pull the signal logically high. To work around this (common) error in
|
|
|
+ * board design, we explicitly set the pin back to GPIO mode, force /CS
|
|
|
+ * high, and wait for the electrons to do their thing.
|
|
|
+ *
|
|
|
+ * This function only makes sense to be called from reset code, but it
|
|
|
+ * lives here as we need to force all the GPIO states w/out going through
|
|
|
+ * BUG() checks and such.
|
|
|
+ */
|
|
|
+void bfin_reset_boot_spi_cs(unsigned short pin)
|
|
|
+{
|
|
|
+ unsigned short gpio = P_IDENT(pin);
|
|
|
+ port_setup(gpio, GPIO_USAGE);
|