Some SD host controllers cannot handle extended use of 3.3V signaling.
To accommodate these controllers, add a capability that requires us to
negotiate the voltage down from 3.3V during card initialization.
Signed-off-by: Kyle Roeschley <kyle.roeschley@ni.com>
Signed-off-by: Jennifer Dahm <jennifer.dahm@ni.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
                }
        }
 
+       if (host->caps2 & MMC_CAP2_AVOID_3_3V &&
+           host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+               pr_err("%s: Host failed to negotiate down from 3.3V\n",
+                       mmc_hostname(host));
+               err = -EINVAL;
+               goto free_card;
+       }
+
        if (!oldcard)
                host->card = card;
 
 
                        mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
                }
        }
+
+       if (host->caps2 & MMC_CAP2_AVOID_3_3V &&
+           host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+               pr_err("%s: Host failed to negotiate down from 3.3V\n",
+                       mmc_hostname(host));
+               err = -EINVAL;
+               goto free_card;
+       }
 done:
        host->card = card;
        return 0;
 
                if (err)
                        goto remove;
        }
+
+       if (host->caps2 & MMC_CAP2_AVOID_3_3V &&
+           host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+               pr_err("%s: Host failed to negotiate down from 3.3V\n",
+                       mmc_hostname(host));
+               err = -EINVAL;
+               goto remove;
+       }
 finish:
        if (!oldcard)
                host->card = card;
 
 #define MMC_CAP2_NO_MMC                (1 << 22)       /* Do not send (e)MMC commands during initialization */
 #define MMC_CAP2_CQE           (1 << 23)       /* Has eMMC command queue engine */
 #define MMC_CAP2_CQE_DCMD      (1 << 24)       /* CQE can issue a direct command */
+#define MMC_CAP2_AVOID_3_3V    (1 << 25)       /* Host must negotiate down from 3.3V */
 
        int                     fixed_drv_type; /* fixed driver type for non-removable media */