PERFORCE change 106689 for review
Warner Losh
imp at FreeBSD.org
Mon Sep 25 15:58:22 PDT 2006
http://perforce.freebsd.org/chv.cgi?CH=106689
Change 106689 by imp at imp_lighthouse on 2006/09/25 22:57:32
checkpoint
Affected files ...
.. //depot/projects/arm/src/sys/dev/mmc/bridge.h#3 edit
.. //depot/projects/arm/src/sys/dev/mmc/mmc.c#3 edit
.. //depot/projects/arm/src/sys/dev/mmc/mmcbrvar.h#1 add
Differences ...
==== //depot/projects/arm/src/sys/dev/mmc/bridge.h#3 (text+ko) ====
@@ -59,6 +59,10 @@
vdd_330, vdd_340, vdd_350, vdd_360
};
+enum mmc_poewr_mode {
+ power_off = 0, power_up, power_on
+};
+
enum mmc_bus_mode {
opendrain = 1, pushpull
};
@@ -68,7 +72,7 @@
};
enum mmc_bus_width {
- bus_width_1 = 0, bus_width_4 = 2
+ bus_width_1 = 0, bus_width_4 = 2, bus_width_8 = 3
};
struct mmc_ios {
@@ -91,6 +95,7 @@
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can do 4-bit data transfers */
#define MMC_CAP_8_BIT_DATA (1 << 1) /* Can do 8-bit data transfers */
enum mmc_card_mode mode;
+ struct mmc_ios ios; /* Current state of the host */
};
#endif /* DEV_MMC_BRIDGE_H */
==== //depot/projects/arm/src/sys/dev/mmc/mmc.c#3 (text+ko) ====
@@ -36,6 +36,9 @@
#include <sys/bus.h>
#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+#include "mmcbr_if.h"
+#include "mmcbus_if.h"
struct mmc_softc {
device_t dev;
@@ -90,12 +93,109 @@
return (EBUSY); /* XXX */
}
+static int
+mmcbr_update_ios(device_t dev)
+{
+ return (MMCBR_UPDATE_IOS(device_get_parent(dev), dev));
+}
+
+static void
+mmc_rescan_cards(struct mmc_softc *sc)
+{
+ /* XXX: Look at the children and see if they respond to status */
+}
+
+static void
+mmc_power_up(struct mmc_softc *sc)
+{
+ device_t dev;
+
+ dev = sc->dev;
+ mmcbr_set_vdd(dev, mmc_highest_voltage(mmcbr_get_host_ocr(dev)));
+ mmcbr_set_bus_mode(dev, opendrain);
+ mmcbr_set_chip_select(dev, cs_dontcare);
+ mmcbr_set_bus_width(dev, bus_width_1);
+ mmcbr_set_power_mode(dev, power_up);
+ mmcbr_set_clock(dev, 0);
+ mmcbr_update_ios(dev);
+
+ // delay 1ms ?
+
+ mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev));
+ mmcbr_set_power_mode(dev, power_on);
+ mmcbr_update_ios(dev);
+
+ // delay 2ms ?
+}
+
+static void
+mmc_go_discovery(struct mmc_softc *sc)
+{
+ uint32_t ocr;
+ device_t dev;
+
+ dev = sc->dev;
+ if (mmcbr_get_power_mode(dev) != power_on) {
+ // First, try SD modes
+ mmcbr_set_mode(dev, mode_sd);
+ mmc_power_up(sc);
+ mmc_idle_cards(sc);
+ if (mmc_send_app_op_cond(sc, 0, &ocr)) {
+ // Failed, try MMC
+ mmcbr_set_mode(dev, mode_mmc);
+ if (mmc_send_op_cond(sc, 0, &ocr))
+ return; // Failed both, punt! XXX power down?
+ }
+ mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr));
+ if (mmcbr_get_ocr(dev) != 0)
+ mmc_idle_cards(sc);
+ } else {
+ mmcbr_set_bus_mode(dev, opendrain);
+ mmcbr_set_clock(dev, mmcbr_get_f_min(dev));
+ mmcbr_update_ios(dev);
+ // XXX recompute vdd based on new cards?
+ }
+ /*
+ * Make sure that we have a mutually agreeable voltage to at least
+ * one card on the bus.
+ */
+ if (mmcbr_get_ocr(dev) == 0)
+ return;
+ /* XXX Linux re-sends op_cond command here */
+ mmc_discover_cards(sc);
+
+ mmcbr_set_bus_mode(dev, pushpull);
+ mmcbr_update_ios(dev);
+ mmc_read_csds(sc);
+ if (mmcbr_get_mode(dev) == mode_sd)
+ mmc_read_scrs(sc);
+}
+
static void
+mmc_scan(struct mmc_softc *sc)
+{
+ device_t dev;
+
+ dev = sc->dev;
+ mmc_aquire_bus(sc);
+
+ if (mmcbr_get_power_mode(dev) == power_on)
+ mmc_rescan_cards(sc);
+ mmc_go_discovery(sc);
+ mmcbr_set_clock(dev, mmc_calculate_clock(sc));
+ mmcbr_update_ios(dev);
+
+ mmc_release_bus(sc);
+ // XXX probe/attach/detach children?
+}
+
+static void
mmc_delayed_attach(void *xsc)
{
struct mmc_softc *sc = xsc;
device_printf(sc->dev, "insert mmc/sd probe code here\n");
+ mmc_scan(sc);
config_intrhook_disestablish(&sc->config_intrhook);
}
More information about the p4-projects
mailing list