mmc: Import MMC/SDCard support from libusb

This commit is contained in:
Sebastian Huber 2015-03-16 22:10:36 +01:00
parent 024e064449
commit fc9e83bb68
21 changed files with 7140 additions and 53 deletions

View File

@ -59,6 +59,8 @@ LIB_C_FILES += rtemsbsd/local/miibus_if.c
LIB_C_FILES += rtemsbsd/local/pcib_if.c
LIB_C_FILES += rtemsbsd/local/pci_if.c
LIB_C_FILES += rtemsbsd/local/usb_if.c
LIB_C_FILES += rtemsbsd/local/mmcbus_if.c
LIB_C_FILES += rtemsbsd/local/mmcbr_if.c
LIB_C_FILES += rtemsbsd/rtems/ipsec_get_policylen.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-assert.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-arp-processor.c
@ -68,6 +70,7 @@ LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-bus-dma-mbuf.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-cam.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-chunk.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-conf.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-configintrhook.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-delay.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-get-ethernet-addr.c
LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-get-file.c
@ -129,6 +132,7 @@ LIB_C_FILES += rtemsbsd/sys/dev/usb/controller/ohci_lpc24xx.c
LIB_C_FILES += rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c
LIB_C_FILES += rtemsbsd/sys/dev/smc/if_smc_nexus.c
LIB_C_FILES += rtemsbsd/sys/dev/ffec/if_ffec_mcf548x.c
LIB_C_FILES += rtemsbsd/sys/dev/dw_mmc/dw_mmc.c
LIB_C_FILES += rtemsbsd/sys/net/if_ppp.c
LIB_C_FILES += rtemsbsd/sys/net/ppp_tty.c
LIB_C_FILES += rtemsbsd/telnetd/check_passwd.c
@ -205,6 +209,9 @@ LIB_C_FILES += freebsd/sys/libkern/fls.c
LIB_C_FILES += freebsd/sys/libkern/inet_ntoa.c
LIB_C_FILES += freebsd/sys/libkern/random.c
LIB_C_FILES += freebsd/sys/vm/uma_core.c
LIB_C_FILES += freebsd/sys/dev/mmc/mmc.c
LIB_C_FILES += freebsd/sys/dev/mmc/mmcsd.c
LIB_C_FILES += freebsd/sys/dev/sdhci/sdhci.c
LIB_C_FILES += freebsd/sys/kern/sys_socket.c
LIB_C_FILES += freebsd/sys/kern/uipc_syscalls.c
LIB_C_FILES += freebsd/sys/net/bridgestp.c

View File

@ -11,15 +11,10 @@ GENERATED += $(LOCAL_INC)/usb_if.h
GENERATED += $(LOCAL_SRC)/usb_if.c
GENERATED += $(LOCAL_INC)/bus_if.h
GENERATED += $(LOCAL_SRC)/bus_if.c
GENERATED += $(LOCAL_INC)/linker_if.h
GENERATED += $(LOCAL_SRC)/linker_if.c
GENERATED += $(LOCAL_INC)/device_if.h
GENERATED += $(LOCAL_SRC)/device_if.c
GENERATED += $(LOCAL_INC)/usbdevs_data.h
GENERATED += $(LOCAL_INC)/usbdevs.h
GENERATED += $(LOCAL_INC)/vnode_if.h
GENERATED += $(LOCAL_INC)/vnode_if_newproto.h
GENERATED += $(LOCAL_INC)/vnode_if_typedef.h
GENERATED += $(LOCAL_INC)/miibus_if.h
GENERATED += $(LOCAL_SRC)/miibus_if.c
GENERATED += $(LOCAL_INC)/miidevs.h
@ -27,12 +22,10 @@ GENERATED += $(LOCAL_INC)/pci_if.h
GENERATED += $(LOCAL_SRC)/pci_if.c
GENERATED += $(LOCAL_INC)/pcib_if.h
GENERATED += $(LOCAL_SRC)/pcib_if.c
GENERATED += $(LOCAL_INC)/ofw_bus_if.h
GENERATED += $(LOCAL_SRC)/ofw_bus_if.c
GENERATED += $(LOCAL_INC)/ofw_if.h
GENERATED += $(LOCAL_SRC)/ofw_if.c
GENERATED += $(LOCAL_INC)/ata_if.h
GENERATED += $(LOCAL_SRC)/ata_if.c
GENERATED += $(LOCAL_INC)/mmcbr_if.h
GENERATED += $(LOCAL_SRC)/mmcbr_if.c
GENERATED += $(LOCAL_INC)/mmcbus_if.h
GENERATED += $(LOCAL_SRC)/mmcbus_if.c
all: $(GENERATED)
@ -44,18 +37,6 @@ $(LOCAL_INC)/usbdevs_data.h: $(FREEBSD_SRC)/sys/dev/usb/usbdevs
awk -f $(TOOLS)/usbdevs2h.awk $< -d
mv usbdevs_data.h $@
$(LOCAL_INC)/vnode_if.h: $(FREEBSD_SRC)/sys/kern/vnode_if.src
awk -f $(TOOLS)/vnode_if.awk $< -h
mv vnode_if.h $@
$(LOCAL_INC)/vnode_if_newproto.h: $(FREEBSD_SRC)/sys/kern/vnode_if.src
awk -f $(TOOLS)/vnode_if.awk $< -p
mv vnode_if_newproto.h $@
$(LOCAL_INC)/vnode_if_typedef.h: $(FREEBSD_SRC)/sys/kern/vnode_if.src
awk -f $(TOOLS)/vnode_if.awk $< -q
mv vnode_if_typedef.h $@
$(LOCAL_INC)/usb_if.h: $(FREEBSD_SRC)/sys/dev/usb/usb_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv usb_if.h $@
@ -72,14 +53,6 @@ $(LOCAL_SRC)/bus_if.c: $(FREEBSD_SRC)/sys/kern/bus_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv bus_if.c $@
$(LOCAL_INC)/linker_if.h: $(FREEBSD_SRC)/sys/kern/linker_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv linker_if.h $@
$(LOCAL_SRC)/linker_if.c: $(FREEBSD_SRC)/sys/kern/linker_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv linker_if.c $@
$(LOCAL_INC)/device_if.h: $(FREEBSD_SRC)/sys/kern/device_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv device_if.h $@
@ -116,26 +89,18 @@ $(LOCAL_SRC)/pcib_if.c: $(FREEBSD_SRC)/sys/dev/pci/pcib_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv pcib_if.c $@
$(LOCAL_INC)/ofw_bus_if.h: $(FREEBSD_SRC)/sys/dev/ofw/ofw_bus_if.m
$(LOCAL_INC)/mmcbus_if.h: $(FREEBSD_SRC)/sys/dev/mmc/mmcbus_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv ofw_bus_if.h $@
mv mmcbus_if.h $@
$(LOCAL_SRC)/ofw_bus_if.c: $(FREEBSD_SRC)/sys/dev/ofw/ofw_bus_if.m
$(LOCAL_SRC)/mmcbus_if.c: $(FREEBSD_SRC)/sys/dev/mmc/mmcbus_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv ofw_bus_if.c $@
mv mmcbus_if.c $@
$(LOCAL_INC)/ofw_if.h: $(FREEBSD_SRC)/sys/dev/ofw/ofw_if.m
$(LOCAL_INC)/mmcbr_if.h: $(FREEBSD_SRC)/sys/dev/mmc/mmcbr_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv ofw_if.h $@
mv mmcbr_if.h $@
$(LOCAL_SRC)/ofw_if.c: $(FREEBSD_SRC)/sys/dev/ofw/ofw_if.m
$(LOCAL_SRC)/mmcbr_if.c: $(FREEBSD_SRC)/sys/dev/mmc/mmcbr_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv ofw_if.c $@
$(LOCAL_INC)/ata_if.h: $(FREEBSD_SRC)/sys/dev/ata/ata_if.m
awk -f $(TOOLS)/makeobjops.awk $< -h
mv ata_if.h $@
$(LOCAL_SRC)/ata_if.c: $(FREEBSD_SRC)/sys/dev/ata/ata_if.m
awk -f $(TOOLS)/makeobjops.awk $< -c
mv ata_if.c $@
mv mmcbr_if.c $@

View File

@ -659,6 +659,8 @@ rtems.addRTEMSSourceFiles(
'local/pcib_if.c',
'local/pci_if.c',
'local/usb_if.c',
'local/mmcbus_if.c',
'local/mmcbr_if.c',
'rtems/ipsec_get_policylen.c',
'rtems/rtems-bsd-assert.c',
'rtems/rtems-bsd-arp-processor.c',
@ -668,6 +670,7 @@ rtems.addRTEMSSourceFiles(
'rtems/rtems-bsd-cam.c',
'rtems/rtems-bsd-chunk.c',
'rtems/rtems-bsd-conf.c',
'rtems/rtems-bsd-configintrhook.c',
'rtems/rtems-bsd-delay.c',
'rtems/rtems-bsd-get-ethernet-addr.c',
'rtems/rtems-bsd-get-file.c',
@ -729,6 +732,7 @@ rtems.addRTEMSSourceFiles(
'sys/dev/usb/controller/ohci_lpc32xx.c',
'sys/dev/smc/if_smc_nexus.c',
'sys/dev/ffec/if_ffec_mcf548x.c',
'sys/dev/dw_mmc/dw_mmc.c',
'sys/net/if_ppp.c',
'sys/net/ppp_tty.c',
'telnetd/check_passwd.c',
@ -918,6 +922,24 @@ base.addKernelSpaceSourceFiles(
]
)
mmc = Module('mmc')
mmc.addKernelSpaceHeaderFiles(
[
'sys/dev/mmc/bridge.h',
'sys/dev/mmc/mmcbrvar.h',
'sys/dev/mmc/mmcreg.h',
'sys/dev/mmc/mmcvar.h',
'sys/dev/sdhci/sdhci.h',
]
)
mmc.addKernelSpaceSourceFiles(
[
'sys/dev/mmc/mmc.c',
'sys/dev/mmc/mmcsd.c',
'sys/dev/sdhci/sdhci.c',
]
)
devUsb = Module('dev_usb')
devUsb.addKernelSpaceHeaderFiles(
[
@ -2572,6 +2594,7 @@ mdnsresponder.addSourceFiles(
# Register all the Module instances with the Module Manager
mm.addModule(rtems)
mm.addModule(base)
mm.addModule(mmc)
mm.addModule(net)
mm.addModule(netinet)
mm.addModule(netinet6)

View File

@ -0,0 +1,138 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Portions of this software may have been developed with reference to
* the SD Simplified Specification. The following disclaimer may apply:
*
* The following conditions apply to the release of the simplified
* specification ("Simplified Specification") by the SD Card Association and
* the SD Group. The Simplified Specification is a subset of the complete SD
* Specification which is owned by the SD Card Association and the SD
* Group. This Simplified Specification is provided on a non-confidential
* basis subject to the disclaimers below. Any implementation of the
* Simplified Specification may require a license from the SD Card
* Association, SD Group, SD-3C LLC or other third parties.
*
* Disclaimers:
*
* The information contained in the Simplified Specification is presented only
* as a standard specification for SD Cards and SD Host/Ancillary products and
* is provided "AS-IS" without any representations or warranties of any
* kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
* Card Association for any damages, any infringements of patents or other
* right of the SD Group, SD-3C LLC, the SD Card Association or any third
* parties, which may result from its use. No license is granted by
* implication, estoppel or otherwise under any patent or other rights of the
* SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
* herein shall be construed as an obligation by the SD Group, the SD-3C LLC
* or the SD Card Association to disclose or distribute any technical
* information, know-how or other confidential information to any third party.
*
* $FreeBSD$
*/
#ifndef DEV_MMC_BRIDGE_H
#define DEV_MMC_BRIDGE_H
/*
* This file defines interfaces for the mmc bridge. The names chosen
* are similar to or the same as the names used in Linux to allow for
* easy porting of what Linux calls mmc host drivers. I use the
* FreeBSD terminology of bridge and bus for consistancy with other
* drivers in the system. This file corresponds roughly to the Linux
* linux/mmc/host.h file.
*
* A mmc bridge is a chipset that can have one or more mmc and/or sd
* cards attached to it. mmc cards are attached on a bus topology,
* while sd and sdio cards are attached using a star topology (meaning
* in practice each sd card has its own, independent slot). Each
* mmcbr is assumed to be derived from the mmcbr. This is done to
* allow for easier addition of bridges (as each bridge does not need
* to be added to the mmcbus file).
*
* Attached to the mmc bridge is an mmcbus. The mmcbus is described
* in dev/mmc/bus.h.
*/
/*
* mmc_ios is a structure that is used to store the state of the mmc/sd
* bus configuration. This include the bus' clock speed, its voltage,
* the bus mode for command output, the SPI chip select, some power
* states and the bus width.
*/
enum mmc_vdd {
vdd_150 = 0, vdd_155, vdd_160, vdd_165, vdd_170, vdd_180,
vdd_190, vdd_200, vdd_210, vdd_220, vdd_230, vdd_240, vdd_250,
vdd_260, vdd_270, vdd_280, vdd_290, vdd_300, vdd_310, vdd_320,
vdd_330, vdd_340, vdd_350, vdd_360
};
enum mmc_power_mode {
power_off = 0, power_up, power_on
};
enum mmc_bus_mode {
opendrain = 1, pushpull
};
enum mmc_chip_select {
cs_dontcare = 0, cs_high, cs_low
};
enum mmc_bus_width {
bus_width_1 = 0, bus_width_4 = 2, bus_width_8 = 3
};
enum mmc_bus_timing {
bus_timing_normal = 0, bus_timing_hs
};
struct mmc_ios {
uint32_t clock; /* Speed of the clock in Hz to move data */
enum mmc_vdd vdd; /* Voltage to apply to the power pins/ */
enum mmc_bus_mode bus_mode;
enum mmc_chip_select chip_select;
enum mmc_bus_width bus_width;
enum mmc_power_mode power_mode;
enum mmc_bus_timing timing;
};
enum mmc_card_mode {
mode_mmc, mode_sd
};
struct mmc_host {
int f_min;
int f_max;
uint32_t host_ocr;
uint32_t ocr;
uint32_t caps;
#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 */
#define MMC_CAP_HSPEED (1 << 2) /* Can do High Speed transfers */
enum mmc_card_mode mode;
struct mmc_ios ios; /* Current state of the host */
};
#endif /* DEV_MMC_BRIDGE_H */

1758
freebsd/sys/dev/mmc/mmc.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Portions of this software may have been developed with reference to
* the SD Simplified Specification. The following disclaimer may apply:
*
* The following conditions apply to the release of the simplified
* specification ("Simplified Specification") by the SD Card Association and
* the SD Group. The Simplified Specification is a subset of the complete SD
* Specification which is owned by the SD Card Association and the SD
* Group. This Simplified Specification is provided on a non-confidential
* basis subject to the disclaimers below. Any implementation of the
* Simplified Specification may require a license from the SD Card
* Association, SD Group, SD-3C LLC or other third parties.
*
* Disclaimers:
*
* The information contained in the Simplified Specification is presented only
* as a standard specification for SD Cards and SD Host/Ancillary products and
* is provided "AS-IS" without any representations or warranties of any
* kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
* Card Association for any damages, any infringements of patents or other
* right of the SD Group, SD-3C LLC, the SD Card Association or any third
* parties, which may result from its use. No license is granted by
* implication, estoppel or otherwise under any patent or other rights of the
* SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
* herein shall be construed as an obligation by the SD Group, the SD-3C LLC
* or the SD Card Association to disclose or distribute any technical
* information, know-how or other confidential information to any third party.
*
* "$FreeBSD$"
*/
#ifndef DEV_MMC_MMCBRVAR_H
#define DEV_MMC_MMCBRVAR_H
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcreg.h>
#include <rtems/bsd/local/mmcbr_if.h>
enum mmcbr_device_ivars {
MMCBR_IVAR_BUS_MODE,
MMCBR_IVAR_BUS_WIDTH,
MMCBR_IVAR_CHIP_SELECT,
MMCBR_IVAR_CLOCK,
MMCBR_IVAR_F_MIN,
MMCBR_IVAR_F_MAX,
MMCBR_IVAR_HOST_OCR,
MMCBR_IVAR_MODE,
MMCBR_IVAR_OCR,
MMCBR_IVAR_POWER_MODE,
MMCBR_IVAR_VDD,
MMCBR_IVAR_CAPS,
MMCBR_IVAR_TIMING,
MMCBR_IVAR_MAX_DATA
};
/*
* Simplified accessors for pci devices
*/
#define MMCBR_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(mmcbr, var, MMCBR, ivar, type)
MMCBR_ACCESSOR(bus_mode, BUS_MODE, int)
MMCBR_ACCESSOR(bus_width, BUS_WIDTH, int)
MMCBR_ACCESSOR(chip_select, CHIP_SELECT, int)
MMCBR_ACCESSOR(clock, CLOCK, int)
MMCBR_ACCESSOR(f_max, F_MAX, int)
MMCBR_ACCESSOR(f_min, F_MIN, int)
MMCBR_ACCESSOR(host_ocr, HOST_OCR, int)
MMCBR_ACCESSOR(mode, MODE, int)
MMCBR_ACCESSOR(ocr, OCR, int)
MMCBR_ACCESSOR(power_mode, POWER_MODE, int)
MMCBR_ACCESSOR(vdd, VDD, int)
MMCBR_ACCESSOR(caps, CAPS, int)
MMCBR_ACCESSOR(timing, TIMING, int)
MMCBR_ACCESSOR(max_data, MAX_DATA, int)
static int __inline
mmcbr_update_ios(device_t dev)
{
return (MMCBR_UPDATE_IOS(device_get_parent(dev), dev));
}
static int __inline
mmcbr_get_ro(device_t dev)
{
return (MMCBR_GET_RO(device_get_parent(dev), dev));
}
#endif /* DEV_MMC_MMCBRVAR_H */

View File

@ -0,0 +1,443 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Portions of this software may have been developed with reference to
* the SD Simplified Specification. The following disclaimer may apply:
*
* The following conditions apply to the release of the simplified
* specification ("Simplified Specification") by the SD Card Association and
* the SD Group. The Simplified Specification is a subset of the complete SD
* Specification which is owned by the SD Card Association and the SD
* Group. This Simplified Specification is provided on a non-confidential
* basis subject to the disclaimers below. Any implementation of the
* Simplified Specification may require a license from the SD Card
* Association, SD Group, SD-3C LLC or other third parties.
*
* Disclaimers:
*
* The information contained in the Simplified Specification is presented only
* as a standard specification for SD Cards and SD Host/Ancillary products and
* is provided "AS-IS" without any representations or warranties of any
* kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
* Card Association for any damages, any infringements of patents or other
* right of the SD Group, SD-3C LLC, the SD Card Association or any third
* parties, which may result from its use. No license is granted by
* implication, estoppel or otherwise under any patent or other rights of the
* SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
* herein shall be construed as an obligation by the SD Group, the SD-3C LLC
* or the SD Card Association to disclose or distribute any technical
* information, know-how or other confidential information to any third party.
*
* $FreeBSD$
*/
#ifndef DEV_MMC_MMCREG_H
#define DEV_MMC_MMCREG_H
/*
* This file contains the register definitions for the mmc and sd busses.
* They are taken from publicly available sources.
*/
struct mmc_data;
struct mmc_request;
struct mmc_command {
uint32_t opcode;
uint32_t arg;
uint32_t resp[4];
uint32_t flags; /* Expected responses */
#define MMC_RSP_PRESENT (1ul << 0) /* Response */
#define MMC_RSP_136 (1ul << 1) /* 136 bit response */
#define MMC_RSP_CRC (1ul << 2) /* Expect valid crc */
#define MMC_RSP_BUSY (1ul << 3) /* Card may send busy */
#define MMC_RSP_OPCODE (1ul << 4) /* Response include opcode */
#define MMC_RSP_MASK 0x1ful
#define MMC_CMD_AC (0ul << 5) /* Addressed Command, no data */
#define MMC_CMD_ADTC (1ul << 5) /* Addressed Data transfer cmd */
#define MMC_CMD_BC (2ul << 5) /* Broadcast command, no response */
#define MMC_CMD_BCR (3ul << 5) /* Broadcast command with response */
#define MMC_CMD_MASK (3ul << 5)
/* Possible response types defined in the standard: */
#define MMC_RSP_NONE (0)
#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC)
#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC)
#define MMC_RSP(x) ((x) & MMC_RSP_MASK)
uint32_t retries;
uint32_t error;
#define MMC_ERR_NONE 0
#define MMC_ERR_TIMEOUT 1
#define MMC_ERR_BADCRC 2
#define MMC_ERR_FIFO 3
#define MMC_ERR_FAILED 4
#define MMC_ERR_INVALID 5
#define MMC_ERR_NO_MEMORY 6
#define MMC_ERR_MAX 6
struct mmc_data *data; /* Data segment with cmd */
struct mmc_request *mrq; /* backpointer to request */
};
/*
* R1 responses
*
* Types (per SD 2.0 standard)
* e : error bit
* s : status bit
* r : detected and set for the actual command response
* x : Detected and set during command execution. The host can get
* the status by issuing a command with R1 response.
*
* Clear Condition (per SD 2.0 standard)
* a : according to the card current state.
* b : always related to the previous command. reception of a valid
* command will clear it (with a delay of one command).
* c : clear by read
*/
#define R1_OUT_OF_RANGE (1u << 31) /* erx, c */
#define R1_ADDRESS_ERROR (1u << 30) /* erx, c */
#define R1_BLOCK_LEN_ERROR (1u << 29) /* erx, c */
#define R1_ERASE_SEQ_ERROR (1u << 28) /* er, c */
#define R1_ERASE_PARAM (1u << 27) /* erx, c */
#define R1_WP_VIOLATION (1u << 26) /* erx, c */
#define R1_CARD_IS_LOCKED (1u << 25) /* sx, a */
#define R1_LOCK_UNLOCK_FAILED (1u << 24) /* erx, c */
#define R1_COM_CRC_ERROR (1u << 23) /* er, b */
#define R1_ILLEGAL_COMMAND (1u << 22) /* er, b */
#define R1_CARD_ECC_FAILED (1u << 21) /* erx, c */
#define R1_CC_ERROR (1u << 20) /* erx, c */
#define R1_ERROR (1u << 19) /* erx, c */
#define R1_CSD_OVERWRITE (1u << 16) /* erx, c */
#define R1_WP_ERASE_SKIP (1u << 15) /* erx, c */
#define R1_CARD_ECC_DISABLED (1u << 14) /* sx, a */
#define R1_ERASE_RESET (1u << 13) /* sr, c */
#define R1_CURRENT_STATE_MASK (0xfu << 9) /* sx, b */
#define R1_READY_FOR_DATA (1u << 8) /* sx, a */
#define R1_APP_CMD (1u << 5) /* sr, c */
#define R1_AKE_SEQ_ERROR (1u << 3) /* er, c */
#define R1_STATUS(x) ((x) & 0xFFFFE000)
#define R1_CURRENT_STATE(x) (((x) & R1_CURRENT_STATE_MASK) >> 9)
#define R1_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
#define R1_STATE_STBY 3
#define R1_STATE_TRAN 4
#define R1_STATE_DATA 5
#define R1_STATE_RCV 6
#define R1_STATE_PRG 7
#define R1_STATE_DIS 8
struct mmc_data {
size_t len; /* size of the data */
size_t xfer_len;
void *data; /* data buffer */
uint32_t flags;
#define MMC_DATA_WRITE (1UL << 0)
#define MMC_DATA_READ (1UL << 1)
#define MMC_DATA_STREAM (1UL << 2)
#define MMC_DATA_MULTI (1UL << 3)
struct mmc_request *mrq;
};
struct mmc_request {
struct mmc_command *cmd;
struct mmc_command *stop;
void (*done)(struct mmc_request *); /* Completion function */
void *done_data; /* requestor set data */
uint32_t flags;
#define MMC_REQ_DONE 1
};
/* Command definitions */
/* Class 0 and 1: Basic commands & read stream commands */
#define MMC_GO_IDLE_STATE 0
#define MMC_SEND_OP_COND 1
#define MMC_ALL_SEND_CID 2
#define MMC_SET_RELATIVE_ADDR 3
#define SD_SEND_RELATIVE_ADDR 3
#define MMC_SET_DSR 4
/* reserved: 5 */
#define MMC_SWITCH_FUNC 6
#define MMC_SWITCH_FUNC_CMDS 0
#define MMC_SWITCH_FUNC_SET 1
#define MMC_SWITCH_FUNC_CLR 2
#define MMC_SWITCH_FUNC_WR 3
#define MMC_SELECT_CARD 7
#define MMC_DESELECT_CARD 7
#define MMC_SEND_EXT_CSD 8
#define SD_SEND_IF_COND 8
#define MMC_SEND_CSD 9
#define MMC_SEND_CID 10
#define MMC_READ_DAT_UNTIL_STOP 11
#define MMC_STOP_TRANSMISSION 12
#define MMC_SEND_STATUS 13
#define MMC_BUSTEST_R 14
#define MMC_GO_INACTIVE_STATE 15
#define MMC_BUSTEST_W 19
/* Class 2: Block oriented read commands */
#define MMC_SET_BLOCKLEN 16
#define MMC_READ_SINGLE_BLOCK 17
#define MMC_READ_MULTIPLE_BLOCK 18
/* reserved: 19 */
/* Class 3: Stream write commands */
#define MMC_WRITE_DAT_UNTIL_STOP 20
/* reserved: 21 */
/* reserved: 22 */
/* Class 4: Block oriented write commands */
#define MMC_SET_BLOCK_COUNT 23
#define MMC_WRITE_BLOCK 24
#define MMC_WRITE_MULTIPLE_BLOCK 25
#define MMC_PROGARM_CID 26
#define MMC_PROGRAM_CSD 27
/* Class 6: Block oriented write protection commands */
#define MMC_SET_WRITE_PROT 28
#define MMC_CLR_WRITE_PROT 29
#define MMC_SEND_WRITE_PROT 30
/* reserved: 31 */
/* Class 5: Erase commands */
#define SD_ERASE_WR_BLK_START 32
#define SD_ERASE_WR_BLK_END 33
/* 34 -- reserved old command */
#define MMC_ERASE_GROUP_START 35
#define MMC_ERASE_GROUP_END 36
/* 37 -- reserved old command */
#define MMC_ERASE 38
/* Class 9: I/O mode commands */
#define MMC_FAST_IO 39
#define MMC_GO_IRQ_STATE 40
/* reserved: 41 */
/* Class 7: Lock card */
#define MMC_LOCK_UNLOCK 42
/* reserved: 43 */
/* reserved: 44 */
/* reserved: 45 */
/* reserved: 46 */
/* reserved: 47 */
/* reserved: 48 */
/* reserved: 49 */
/* reserved: 50 */
/* reserved: 51 */
/* reserved: 54 */
/* Class 8: Application specific commands */
#define MMC_APP_CMD 55
#define MMC_GEN_CMD 56
/* reserved: 57 */
/* reserved: 58 */
/* reserved: 59 */
/* reserved for mfg: 60 */
/* reserved for mfg: 61 */
/* reserved for mfg: 62 */
/* reserved for mfg: 63 */
/* Class 9: I/O cards (sd) */
#define SD_IO_RW_DIRECT 52
#define SD_IO_RW_EXTENDED 53
/* Class 10: Switch function commands */
#define SD_SWITCH_FUNC 6
/* reserved: 34 */
/* reserved: 35 */
/* reserved: 36 */
/* reserved: 37 */
/* reserved: 50 */
/* reserved: 57 */
/* Application specific commands for SD */
#define ACMD_SET_BUS_WIDTH 6
#define ACMD_SD_STATUS 13
#define ACMD_SEND_NUM_WR_BLOCKS 22
#define ACMD_SET_WR_BLK_ERASE_COUNT 23
#define ACMD_SD_SEND_OP_COND 41
#define ACMD_SET_CLR_CARD_DETECT 42
#define ACMD_SEND_SCR 51
/*
* EXT_CSD fields
*/
#define EXT_CSD_ERASE_GRP_DEF 175 /* R/W */
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_ERASE_TO_MULT 223 /* RO */
#define EXT_CSD_ERASE_GRP_SIZE 224 /* RO */
/*
* EXT_CSD field definitions
*/
#define EXT_CSD_CMD_SET_NORMAL 1
#define EXT_CSD_CMD_SET_SECURE 2
#define EXT_CSD_CMD_SET_CPSECURE 4
#define EXT_CSD_CARD_TYPE_26 1
#define EXT_CSD_CARD_TYPE_52 2
#define EXT_CSD_BUS_WIDTH_1 0
#define EXT_CSD_BUS_WIDTH_4 1
#define EXT_CSD_BUS_WIDTH_8 2
#define MMC_TYPE_26_MAX_HS 26000000
#define MMC_TYPE_52_MAX_HS 52000000
/*
* SD bus widths
*/
#define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2
/*
* SD Switch
*/
#define SD_SWITCH_MODE_CHECK 0
#define SD_SWITCH_MODE_SET 1
#define SD_SWITCH_GROUP1 0
#define SD_SWITCH_NORMAL_MODE 0
#define SD_SWITCH_HS_MODE 1
#define SD_SWITCH_NOCHANGE 0xF
#define SD_CLR_CARD_DETECT 0
#define SD_SET_CARD_DETECT 1
#define SD_MAX_HS 50000000
/* OCR bits */
/*
* in SD 2.0 spec, bits 8-14 are now marked reserved
* Low voltage in SD2.0 spec is bit 7, TBD voltage
* Low voltage in MC 3.31 spec is bit 7, 1.65-1.95V
* Specs prior to MMC 3.31 defined bits 0-7 as voltages down to 1.5V.
* 3.31 redefined them to be reserved and also said that cards had to
* support the 2.7-3.6V and fixed the OCR to be 0xfff8000 for high voltage
* cards. MMC 4.0 says that a dual voltage card responds with 0xfff8080.
* Looks like the fine-grained control of the voltage tolerance ranges
* was abandoned.
*
* The MMC_OCR_CCS appears to be valid for only SD cards.
*/
#define MMC_OCR_VOLTAGE 0x3fffffffU /* Vdd Voltage mask */
#define MMC_OCR_LOW_VOLTAGE (1u << 7) /* Low Voltage Range -- tbd */
#define MMC_OCR_200_210 (1U << 8) /* Vdd voltage 2.00 ~ 2.10 */
#define MMC_OCR_210_220 (1U << 9) /* Vdd voltage 2.10 ~ 2.20 */
#define MMC_OCR_220_230 (1U << 10) /* Vdd voltage 2.20 ~ 2.30 */
#define MMC_OCR_230_240 (1U << 11) /* Vdd voltage 2.30 ~ 2.40 */
#define MMC_OCR_240_250 (1U << 12) /* Vdd voltage 2.40 ~ 2.50 */
#define MMC_OCR_250_260 (1U << 13) /* Vdd voltage 2.50 ~ 2.60 */
#define MMC_OCR_260_270 (1U << 14) /* Vdd voltage 2.60 ~ 2.70 */
#define MMC_OCR_270_280 (1U << 15) /* Vdd voltage 2.70 ~ 2.80 */
#define MMC_OCR_280_290 (1U << 16) /* Vdd voltage 2.80 ~ 2.90 */
#define MMC_OCR_290_300 (1U << 17) /* Vdd voltage 2.90 ~ 3.00 */
#define MMC_OCR_300_310 (1U << 18) /* Vdd voltage 3.00 ~ 3.10 */
#define MMC_OCR_310_320 (1U << 19) /* Vdd voltage 3.10 ~ 3.20 */
#define MMC_OCR_320_330 (1U << 20) /* Vdd voltage 3.20 ~ 3.30 */
#define MMC_OCR_330_340 (1U << 21) /* Vdd voltage 3.30 ~ 3.40 */
#define MMC_OCR_340_350 (1U << 22) /* Vdd voltage 3.40 ~ 3.50 */
#define MMC_OCR_350_360 (1U << 23) /* Vdd voltage 3.50 ~ 3.60 */
#define MMC_OCR_CCS (1u << 30) /* Card Capacity status (SD vs SDHC) */
#define MMC_OCR_CARD_BUSY (1U << 31) /* Card Power up status */
/* CSD -- decoded structure */
struct mmc_cid {
uint32_t mid;
char pnm[8];
uint32_t psn;
uint16_t oid;
uint16_t mdt_year;
uint8_t mdt_month;
uint8_t prv;
uint8_t fwrev;
};
struct mmc_csd
{
uint8_t csd_structure;
uint8_t spec_vers;
uint16_t ccc;
uint16_t tacc;
uint32_t nsac;
uint32_t r2w_factor;
uint32_t tran_speed;
uint32_t read_bl_len;
uint32_t write_bl_len;
uint32_t vdd_r_curr_min;
uint32_t vdd_r_curr_max;
uint32_t vdd_w_curr_min;
uint32_t vdd_w_curr_max;
uint32_t wp_grp_size;
uint32_t erase_sector;
uint64_t capacity;
unsigned int read_bl_partial:1,
read_blk_misalign:1,
write_bl_partial:1,
write_blk_misalign:1,
dsr_imp:1,
erase_blk_en:1,
wp_grp_enable:1;
};
struct mmc_scr
{
unsigned char sda_vsn;
unsigned char bus_widths;
#define SD_SCR_BUS_WIDTH_1 (1<<0)
#define SD_SCR_BUS_WIDTH_4 (1<<2)
};
struct mmc_sd_status
{
uint8_t bus_width;
uint8_t secured_mode;
uint16_t card_type;
uint16_t prot_area;
uint8_t speed_class;
uint8_t perf_move;
uint8_t au_size;
uint16_t erase_size;
uint8_t erase_timeout;
uint8_t erase_offset;
};
/*
* Older versions of the MMC standard had a variable sector size. However,
* I've been able to find no old MMC or SD cards that have a non 512
* byte sector size anywhere, so we assume that such cards are very rare
* and only note their existance in passing here...
*/
#define MMC_SECTOR_SIZE 512
#endif /* DEV_MMCREG_H */

801
freebsd/sys/dev/mmc/mmcsd.c Normal file
View File

@ -0,0 +1,801 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Portions of this software may have been developed with reference to
* the SD Simplified Specification. The following disclaimer may apply:
*
* The following conditions apply to the release of the simplified
* specification ("Simplified Specification") by the SD Card Association and
* the SD Group. The Simplified Specification is a subset of the complete SD
* Specification which is owned by the SD Card Association and the SD
* Group. This Simplified Specification is provided on a non-confidential
* basis subject to the disclaimers below. Any implementation of the
* Simplified Specification may require a license from the SD Card
* Association, SD Group, SD-3C LLC or other third parties.
*
* Disclaimers:
*
* The information contained in the Simplified Specification is presented only
* as a standard specification for SD Cards and SD Host/Ancillary products and
* is provided "AS-IS" without any representations or warranties of any
* kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
* Card Association for any damages, any infringements of patents or other
* right of the SD Group, SD-3C LLC, the SD Card Association or any third
* parties, which may result from its use. No license is granted by
* implication, estoppel or otherwise under any patent or other rights of the
* SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
* herein shall be construed as an obligation by the SD Group, the SD-3C LLC
* or the SD Card Association to disclose or distribute any technical
* information, know-how or other confidential information to any third party.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <geom/geom_disk.h>
#include <dev/mmc/mmcbrvar.h>
#include <dev/mmc/mmcvar.h>
#include <dev/mmc/mmcreg.h>
#include <rtems/bsd/local/mmcbus_if.h>
#ifdef __rtems__
#include <machine/rtems-bsd-support.h>
#include <rtems/bdbuf.h>
#include <rtems/diskdevs.h>
#include <rtems/libio.h>
#include <rtems/media.h>
#endif /* __rtems__ */
#if __FreeBSD_version < 800002
#define kproc_create kthread_create
#define kproc_exit kthread_exit
#endif
struct mmcsd_softc {
device_t dev;
struct mtx sc_mtx;
#ifndef __rtems__
struct disk *disk;
struct proc *p;
struct bio_queue_head bio_queue;
daddr_t eblock, eend; /* Range remaining after the last erase. */
int running;
int suspend;
#endif /* __rtems__ */
};
/* bus entry points */
static int mmcsd_attach(device_t dev);
static int mmcsd_detach(device_t dev);
static int mmcsd_probe(device_t dev);
#ifndef __rtems__
/* disk routines */
static int mmcsd_close(struct disk *dp);
static int mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
off_t offset, size_t length);
static int mmcsd_open(struct disk *dp);
static void mmcsd_strategy(struct bio *bp);
static void mmcsd_task(void *arg);
#endif /* __rtems__ */
static int mmcsd_bus_bit_width(device_t dev);
#ifndef __rtems__
static daddr_t mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp);
static daddr_t mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp);
#endif /* __rtems__ */
#define MMCSD_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define MMCSD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define MMCSD_LOCK_INIT(_sc) \
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
"mmcsd", MTX_DEF)
#define MMCSD_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
#define MMCSD_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
#define MMCSD_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
static int
mmcsd_probe(device_t dev)
{
device_quiet(dev);
device_set_desc(dev, "MMC/SD Memory Card");
return (0);
}
#ifdef __rtems__
static rtems_status_code
rtems_bsd_mmcsd_set_block_size(struct mmcsd_softc *self, uint32_t block_size)
{
rtems_status_code status_code = RTEMS_SUCCESSFUL;
device_t dev = self->dev;
struct mmc_command cmd;
struct mmc_request req;
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
cmd.opcode = MMC_SET_BLOCKLEN;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
cmd.arg = block_size;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE) {
status_code = RTEMS_IO_ERROR;
}
return status_code;
}
static int
rtems_bsd_mmcsd_disk_read_write(struct mmcsd_softc *self, rtems_blkdev_request *blkreq)
{
rtems_status_code status_code = RTEMS_SUCCESSFUL;
device_t dev = self->dev;
int shift = mmc_get_high_cap(dev) ? 0 : 9;
int rca = mmc_get_rca(dev);
uint32_t buffer_count = blkreq->bufnum;
uint32_t transfer_bytes = blkreq->bufs[0].length;
uint32_t block_count = transfer_bytes / MMC_SECTOR_SIZE;
uint32_t opcode;
uint32_t data_flags;
uint32_t i;
if (blkreq->req == RTEMS_BLKDEV_REQ_WRITE) {
if (block_count > 1) {
opcode = MMC_WRITE_MULTIPLE_BLOCK;
} else {
opcode = MMC_WRITE_BLOCK;
}
data_flags = MMC_DATA_WRITE;
} else {
BSD_ASSERT(blkreq->req == RTEMS_BLKDEV_REQ_READ);
if (block_count > 1) {
opcode = MMC_READ_MULTIPLE_BLOCK;
} else {
opcode = MMC_READ_SINGLE_BLOCK;
}
data_flags = MMC_DATA_READ;
}
MMCSD_LOCK(self);
for (i = 0; i < buffer_count; ++i) {
rtems_blkdev_sg_buffer *sg = &blkreq->bufs [i];
struct mmc_request req;
struct mmc_command cmd;
struct mmc_command stop;
struct mmc_data data;
rtems_interval timeout;
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
memset(&stop, 0, sizeof(stop));
req.cmd = &cmd;
cmd.opcode = opcode;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
cmd.data = &data;
cmd.arg = sg->block << shift;
if (block_count > 1) {
data_flags |= MMC_DATA_MULTI;
stop.opcode = MMC_STOP_TRANSMISSION;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
req.stop = &stop;
}
data.flags = data_flags;;
data.data = sg->buffer;
data.mrq = &req;
data.len = transfer_bytes;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE) {
status_code = RTEMS_IO_ERROR;
goto error;
}
timeout = rtems_clock_tick_later_usec(250000);
while (1) {
struct mmc_request req2;
struct mmc_command cmd2;
uint32_t status;
memset(&req2, 0, sizeof(req2));
memset(&cmd2, 0, sizeof(cmd2));
req2.cmd = &cmd2;
cmd2.opcode = MMC_SEND_STATUS;
cmd2.arg = rca << 16;
cmd2.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req2);
if (req2.cmd->error != MMC_ERR_NONE) {
status_code = RTEMS_IO_ERROR;
goto error;
}
status = cmd2.resp[0];
if ((status & R1_READY_FOR_DATA) != 0
&& R1_CURRENT_STATE(status) != R1_STATE_PRG) {
break;
}
if (!rtems_clock_tick_before(timeout)) {
status_code = RTEMS_IO_ERROR;
goto error;
}
}
}
error:
MMCSD_UNLOCK(self);
rtems_blkdev_request_done(blkreq, status_code);
return 0;
}
static int
rtems_bsd_mmcsd_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
{
struct mmcsd_softc *self = rtems_disk_get_driver_data(dd);
if (req == RTEMS_BLKIO_REQUEST) {
rtems_blkdev_request *blkreq = arg;
return rtems_bsd_mmcsd_disk_read_write(self, blkreq);
} else if (req == RTEMS_BLKIO_CAPABILITIES) {
*(uint32_t *) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
return 0;
} else {
return rtems_blkdev_ioctl(dd, req, arg);
}
}
static rtems_status_code
rtems_bsd_mmcsd_attach_worker(rtems_media_state state, const char *src, char **dest, void *arg)
{
rtems_status_code status_code = RTEMS_SUCCESSFUL;
struct mmcsd_softc *self = arg;
char *disk = NULL;
if (state == RTEMS_MEDIA_STATE_READY) {
device_t dev = self->dev;
uint32_t block_count = mmc_get_media_size(dev);
uint32_t block_size = MMC_SECTOR_SIZE;
disk = rtems_media_create_path("/dev", src, device_get_unit(dev));
if (disk == NULL) {
printf("OOPS: create path failed\n");
goto error;
}
MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
status_code = rtems_bsd_mmcsd_set_block_size(self, block_size);
if (status_code != RTEMS_SUCCESSFUL) {
printf("OOPS: set block size failed\n");
goto error;
}
status_code = rtems_blkdev_create(disk, block_size,
block_count, rtems_bsd_mmcsd_disk_ioctl, self);
if (status_code != RTEMS_SUCCESSFUL) {
goto error;
}
*dest = strdup(disk, M_RTEMS_HEAP);
}
return RTEMS_SUCCESSFUL;
error:
free(disk, M_RTEMS_HEAP);
return RTEMS_IO_ERROR;
}
#endif /* __rtems__ */
static int
mmcsd_attach(device_t dev)
{
struct mmcsd_softc *sc;
#ifndef __rtems__
struct disk *d;
#endif /* __rtems__ */
intmax_t mb;
uint32_t speed;
uint32_t maxblocks;
char unit;
sc = device_get_softc(dev);
sc->dev = dev;
MMCSD_LOCK_INIT(sc);
#ifndef __rtems__
d = sc->disk = disk_alloc();
d->d_open = mmcsd_open;
d->d_close = mmcsd_close;
d->d_strategy = mmcsd_strategy;
d->d_dump = mmcsd_dump;
d->d_name = "mmcsd";
d->d_drv1 = sc;
d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */
d->d_sectorsize = mmc_get_sector_size(dev);
d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
d->d_stripeoffset = 0;
d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
d->d_unit = device_get_unit(dev);
d->d_flags = DISKFLAG_CANDELETE;
/*
* Display in most natural units. There's no cards < 1MB.
* The SD standard goes to 2GiB, but the data format supports
* up to 4GiB and some card makers push it up to this limit.
* The SDHC standard only goes to 32GiB (the data format in
* SDHC is good to 2TiB however, which isn't too ugly at
* 2048GiBm, so we note it in passing here and don't add the
* code to print TiB).
*/
mb = d->d_mediasize >> 20; /* 1MiB == 1 << 20 */
#else /* __rtems__ */
mb = mmc_get_media_size(dev);
mb *= mmc_get_sector_size(dev);
mb >>= 20;
#endif /* __rtems__ */
unit = 'M';
if (mb >= 10240) { /* 1GiB = 1024 MiB */
unit = 'G';
mb /= 1024;
}
/*
* Report the clock speed of the underlying hardware, which might be
* different than what the card reports due to hardware limitations.
* Report how many blocks the hardware transfers at once, but clip the
* number to MAXPHYS since the system won't initiate larger transfers.
*/
speed = mmcbr_get_clock(device_get_parent(dev));
maxblocks = mmc_get_max_data(dev);
if (maxblocks > MAXPHYS)
maxblocks = MAXPHYS;
device_printf(dev, "%ju%cB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n",
mb, unit, mmc_get_card_id_string(dev),
mmc_get_read_only(dev) ? " (read-only)" : "",
device_get_nameunit(device_get_parent(dev)),
speed / 1000000, (speed / 100000) % 10,
mmcsd_bus_bit_width(dev), maxblocks);
#ifndef __rtems__
disk_create(d, DISK_VERSION);
bioq_init(&sc->bio_queue);
sc->running = 1;
sc->suspend = 0;
sc->eblock = sc->eend = 0;
kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card");
#else /* __rtems__ */
rtems_status_code status_code = rtems_media_server_disk_attach(
device_get_name(dev),
rtems_bsd_mmcsd_attach_worker,
sc
);
BSD_ASSERT(status_code == RTEMS_SUCCESSFUL);
#endif /* __rtems__ */
return (0);
}
static int
mmcsd_detach(device_t dev)
{
struct mmcsd_softc *sc = device_get_softc(dev);
#ifndef __rtems__
MMCSD_LOCK(sc);
sc->suspend = 0;
if (sc->running > 0) {
/* kill thread */
sc->running = 0;
wakeup(sc);
/* wait for thread to finish. */
while (sc->running != -1)
msleep(sc, &sc->sc_mtx, 0, "detach", 0);
}
MMCSD_UNLOCK(sc);
/* Flush the request queue. */
bioq_flush(&sc->bio_queue, NULL, ENXIO);
/* kill disk */
disk_destroy(sc->disk);
#else /* __rtems__ */
BSD_PANIC("FIXME");
#endif /* __rtems__ */
MMCSD_LOCK_DESTROY(sc);
return (0);
}
static int
mmcsd_suspend(device_t dev)
{
#ifndef __rtems__
struct mmcsd_softc *sc = device_get_softc(dev);
MMCSD_LOCK(sc);
sc->suspend = 1;
if (sc->running > 0) {
/* kill thread */
sc->running = 0;
wakeup(sc);
/* wait for thread to finish. */
while (sc->running != -1)
msleep(sc, &sc->sc_mtx, 0, "detach", 0);
}
MMCSD_UNLOCK(sc);
#else /* __rtems__ */
BSD_PANIC("FIXME");
#endif /* __rtems__ */
return (0);
}
static int
mmcsd_resume(device_t dev)
{
#ifndef __rtems__
struct mmcsd_softc *sc = device_get_softc(dev);
MMCSD_LOCK(sc);
sc->suspend = 0;
if (sc->running <= 0) {
sc->running = 1;
MMCSD_UNLOCK(sc);
kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card");
} else
MMCSD_UNLOCK(sc);
#else /* __rtems__ */
BSD_PANIC("FIXME");
#endif /* __rtems__ */
return (0);
}
#ifndef __rtems__
static int
mmcsd_open(struct disk *dp)
{
return (0);
}
static int
mmcsd_close(struct disk *dp)
{
return (0);
}
static void
mmcsd_strategy(struct bio *bp)
{
struct mmcsd_softc *sc;
sc = (struct mmcsd_softc *)bp->bio_disk->d_drv1;
MMCSD_LOCK(sc);
if (sc->running > 0 || sc->suspend > 0) {
bioq_disksort(&sc->bio_queue, bp);
MMCSD_UNLOCK(sc);
wakeup(sc);
} else {
MMCSD_UNLOCK(sc);
biofinish(bp, NULL, ENXIO);
}
}
static daddr_t
mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
{
daddr_t block, end;
struct mmc_command cmd;
struct mmc_command stop;
struct mmc_request req;
struct mmc_data data;
device_t dev = sc->dev;
int sz = sc->disk->d_sectorsize;
block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz);
while (block < end) {
char *vaddr = bp->bio_data +
(block - bp->bio_pblkno) * sz;
int numblocks = min(end - block, mmc_get_max_data(dev));
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
memset(&stop, 0, sizeof(stop));
req.cmd = &cmd;
cmd.data = &data;
if (bp->bio_cmd == BIO_READ) {
if (numblocks > 1)
cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
else
cmd.opcode = MMC_READ_SINGLE_BLOCK;
} else {
if (numblocks > 1)
cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
else
cmd.opcode = MMC_WRITE_BLOCK;
}
cmd.arg = block;
if (!mmc_get_high_cap(dev))
cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
data.data = vaddr;
data.mrq = &req;
if (bp->bio_cmd == BIO_READ)
data.flags = MMC_DATA_READ;
else
data.flags = MMC_DATA_WRITE;
data.len = numblocks * sz;
if (numblocks > 1) {
data.flags |= MMC_DATA_MULTI;
stop.opcode = MMC_STOP_TRANSMISSION;
stop.arg = 0;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
req.stop = &stop;
}
// printf("Len %d %lld-%lld flags %#x sz %d\n",
// (int)data.len, (long long)block, (long long)end, data.flags, sz);
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE)
break;
block += numblocks;
}
return (block);
}
static daddr_t
mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
{
daddr_t block, end, start, stop;
struct mmc_command cmd;
struct mmc_request req;
device_t dev = sc->dev;
int sz = sc->disk->d_sectorsize;
int erase_sector;
block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz);
/* Coalesce with part remaining from previous request. */
if (block > sc->eblock && block <= sc->eend)
block = sc->eblock;
if (end >= sc->eblock && end < sc->eend)
end = sc->eend;
/* Safe round to the erase sector boundaries. */
erase_sector = mmc_get_erase_sector(dev);
start = block + erase_sector - 1; /* Round up. */
start -= start % erase_sector;
stop = end; /* Round down. */
stop -= end % erase_sector;
/* We can't erase area smaller then sector, store it for later. */
if (start >= stop) {
sc->eblock = block;
sc->eend = end;
return (end);
}
/* Set erase start position. */
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
if (mmc_get_card_type(dev) == mode_sd)
cmd.opcode = SD_ERASE_WR_BLK_START;
else
cmd.opcode = MMC_ERASE_GROUP_START;
cmd.arg = start;
if (!mmc_get_high_cap(dev))
cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err1: %d\n", req.cmd->error);
return (block);
}
/* Set erase stop position. */
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
if (mmc_get_card_type(dev) == mode_sd)
cmd.opcode = SD_ERASE_WR_BLK_END;
else
cmd.opcode = MMC_ERASE_GROUP_END;
cmd.arg = stop;
if (!mmc_get_high_cap(dev))
cmd.arg <<= 9;
cmd.arg--;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err2: %d\n", req.cmd->error);
return (block);
}
/* Erase range. */
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
req.cmd = &cmd;
cmd.opcode = MMC_ERASE;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
&req);
if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err3 %d\n", req.cmd->error);
return (block);
}
/* Store one of remaining parts for the next call. */
if (bp->bio_pblkno >= sc->eblock || block == start) {
sc->eblock = stop; /* Predict next forward. */
sc->eend = end;
} else {
sc->eblock = block; /* Predict next backward. */
sc->eend = start;
}
return (end);
}
static int
mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
off_t offset, size_t length)
{
struct disk *disk = arg;
struct mmcsd_softc *sc = (struct mmcsd_softc *)disk->d_drv1;
device_t dev = sc->dev;
struct bio bp;
daddr_t block, end;
/* length zero is special and really means flush buffers to media */
if (!length)
return (0);
bzero(&bp, sizeof(struct bio));
bp.bio_disk = disk;
bp.bio_pblkno = offset / disk->d_sectorsize;
bp.bio_bcount = length;
bp.bio_data = virtual;
bp.bio_cmd = BIO_WRITE;
end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize;
MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
block = mmcsd_rw(sc, &bp);
MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
return ((end < block) ? EIO : 0);
}
static void
mmcsd_task(void *arg)
{
struct mmcsd_softc *sc = (struct mmcsd_softc*)arg;
struct bio *bp;
int sz;
daddr_t block, end;
device_t dev;
dev = sc->dev;
while (1) {
MMCSD_LOCK(sc);
do {
if (sc->running == 0)
goto out;
bp = bioq_takefirst(&sc->bio_queue);
if (bp == NULL)
msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
} while (bp == NULL);
MMCSD_UNLOCK(sc);
if (bp->bio_cmd != BIO_READ && mmc_get_read_only(dev)) {
bp->bio_error = EROFS;
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
biodone(bp);
continue;
}
MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
sz = sc->disk->d_sectorsize;
block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz);
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
/* Access to the remaining erase block obsoletes it. */
if (block < sc->eend && end > sc->eblock)
sc->eblock = sc->eend = 0;
block = mmcsd_rw(sc, bp);
} else if (bp->bio_cmd == BIO_DELETE) {
block = mmcsd_delete(sc, bp);
}
MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
if (block < end) {
bp->bio_error = EIO;
bp->bio_resid = (end - block) * sz;
bp->bio_flags |= BIO_ERROR;
}
biodone(bp);
}
out:
/* tell parent we're done */
sc->running = -1;
MMCSD_UNLOCK(sc);
wakeup(sc);
kproc_exit(0);
}
#endif /* __rtems__ */
static int
mmcsd_bus_bit_width(device_t dev)
{
if (mmc_get_bus_width(dev) == bus_width_1)
return (1);
if (mmc_get_bus_width(dev) == bus_width_4)
return (4);
return (8);
}
static device_method_t mmcsd_methods[] = {
DEVMETHOD(device_probe, mmcsd_probe),
DEVMETHOD(device_attach, mmcsd_attach),
DEVMETHOD(device_detach, mmcsd_detach),
DEVMETHOD(device_suspend, mmcsd_suspend),
DEVMETHOD(device_resume, mmcsd_resume),
DEVMETHOD_END
};
static driver_t mmcsd_driver = {
"mmcsd",
mmcsd_methods,
sizeof(struct mmcsd_softc),
};
static devclass_t mmcsd_devclass;
DRIVER_MODULE(mmcsd, mmc, mmcsd_driver, mmcsd_devclass, NULL, NULL);

View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Portions of this software may have been developed with reference to
* the SD Simplified Specification. The following disclaimer may apply:
*
* The following conditions apply to the release of the simplified
* specification ("Simplified Specification") by the SD Card Association and
* the SD Group. The Simplified Specification is a subset of the complete SD
* Specification which is owned by the SD Card Association and the SD
* Group. This Simplified Specification is provided on a non-confidential
* basis subject to the disclaimers below. Any implementation of the
* Simplified Specification may require a license from the SD Card
* Association, SD Group, SD-3C LLC or other third parties.
*
* Disclaimers:
*
* The information contained in the Simplified Specification is presented only
* as a standard specification for SD Cards and SD Host/Ancillary products and
* is provided "AS-IS" without any representations or warranties of any
* kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
* Card Association for any damages, any infringements of patents or other
* right of the SD Group, SD-3C LLC, the SD Card Association or any third
* parties, which may result from its use. No license is granted by
* implication, estoppel or otherwise under any patent or other rights of the
* SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
* herein shall be construed as an obligation by the SD Group, the SD-3C LLC
* or the SD Card Association to disclose or distribute any technical
* information, know-how or other confidential information to any third party.
*
* "$FreeBSD$"
*/
#ifndef DEV_MMC_MMCVAR_H
#define DEV_MMC_MMCVAR_H
#include <dev/mmc/bridge.h>
enum mmc_device_ivars {
MMC_IVAR_DSR_IMP,
MMC_IVAR_MEDIA_SIZE,
MMC_IVAR_RCA,
MMC_IVAR_SECTOR_SIZE,
MMC_IVAR_TRAN_SPEED,
MMC_IVAR_READ_ONLY,
MMC_IVAR_HIGH_CAP,
MMC_IVAR_CARD_TYPE,
MMC_IVAR_BUS_WIDTH,
MMC_IVAR_ERASE_SECTOR,
MMC_IVAR_MAX_DATA,
MMC_IVAR_CARD_ID_STRING
};
/*
* Simplified accessors for pci devices
*/
#define MMC_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(mmc, var, MMC, ivar, type)
MMC_ACCESSOR(dsr_imp, DSR_IMP, int)
#ifndef __rtems__
MMC_ACCESSOR(media_size, MEDIA_SIZE, off_t)
#else /* __rtems__ */
/*
* The instance variable value storage is limited by the uintptr_t type. Since
* off_t has more bits than uintptr_t on most RTEMS targets, we need this hack.
*/
MMC_ACCESSOR(media_size, MEDIA_SIZE, uintptr_t)
#endif /* __rtems__ */
MMC_ACCESSOR(rca, RCA, int)
MMC_ACCESSOR(sector_size, SECTOR_SIZE, int)
MMC_ACCESSOR(tran_speed, TRAN_SPEED, int)
MMC_ACCESSOR(read_only, READ_ONLY, int)
MMC_ACCESSOR(high_cap, HIGH_CAP, int)
MMC_ACCESSOR(card_type, CARD_TYPE, int)
MMC_ACCESSOR(bus_width, BUS_WIDTH, int)
MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int)
MMC_ACCESSOR(max_data, MAX_DATA, int)
MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *)
#endif /* DEV_MMC_MMCVAR_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
/*-
* Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* PCI registers
*/
#define PCI_SDHCI_IFPIO 0x00
#define PCI_SDHCI_IFDMA 0x01
#define PCI_SDHCI_IFVENDOR 0x02
#define PCI_SLOT_INFO 0x40 /* 8 bits */
#define PCI_SLOT_INFO_SLOTS(x) (((x >> 4) & 7) + 1)
#define PCI_SLOT_INFO_FIRST_BAR(x) ((x) & 7)
/*
* Controller registers
*/
#define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_BLOCK_SIZE 0x04
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06
#define SDHCI_ARGUMENT 0x08
#define SDHCI_TRANSFER_MODE 0x0C
#define SDHCI_TRNS_DMA 0x01
#define SDHCI_TRNS_BLK_CNT_EN 0x02
#define SDHCI_TRNS_ACMD12 0x04
#define SDHCI_TRNS_READ 0x10
#define SDHCI_TRNS_MULTI 0x20
#define SDHCI_COMMAND_FLAGS 0x0E
#define SDHCI_CMD_RESP_NONE 0x00
#define SDHCI_CMD_RESP_LONG 0x01
#define SDHCI_CMD_RESP_SHORT 0x02
#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
#define SDHCI_CMD_RESP_MASK 0x03
#define SDHCI_CMD_CRC 0x08
#define SDHCI_CMD_INDEX 0x10
#define SDHCI_CMD_DATA 0x20
#define SDHCI_CMD_TYPE_NORMAL 0x00
#define SDHCI_CMD_TYPE_SUSPEND 0x40
#define SDHCI_CMD_TYPE_RESUME 0x80
#define SDHCI_CMD_TYPE_ABORT 0xc0
#define SDHCI_CMD_TYPE_MASK 0xc0
#define SDHCI_COMMAND 0x0F
#define SDHCI_RESPONSE 0x10
#define SDHCI_BUFFER 0x20
#define SDHCI_PRESENT_STATE 0x24
#define SDHCI_CMD_INHIBIT 0x00000001
#define SDHCI_DAT_INHIBIT 0x00000002
#define SDHCI_DAT_ACTIVE 0x00000004
#define SDHCI_DOING_WRITE 0x00000100
#define SDHCI_DOING_READ 0x00000200
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
#define SDHCI_CARD_STABLE 0x00020000
#define SDHCI_CARD_PIN 0x00040000
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_STATE_DAT 0x00700000
#define SDHCI_STATE_CMD 0x00800000
#define SDHCI_HOST_CONTROL 0x28
#define SDHCI_CTRL_LED 0x01
#define SDHCI_CTRL_4BITBUS 0x02
#define SDHCI_CTRL_HISPD 0x04
#define SDHCI_CTRL_SDMA 0x08
#define SDHCI_CTRL_ADMA2 0x10
#define SDHCI_CTRL_ADMA264 0x18
#define SDHCI_CTRL_CARD_DET 0x40
#define SDHCI_CTRL_FORCE_CARD 0x80
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
#define SDHCI_POWER_180 0x0A
#define SDHCI_POWER_300 0x0C
#define SDHCI_POWER_330 0x0E
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
#define SDHCI_WAKE_UP_CONTROL 0x2B
#define SDHCI_CLOCK_CONTROL 0x2C
#define SDHCI_DIVIDER_SHIFT 8
#define SDHCI_CLOCK_CARD_EN 0x0004
#define SDHCI_CLOCK_INT_STABLE 0x0002
#define SDHCI_CLOCK_INT_EN 0x0001
#define SDHCI_TIMEOUT_CONTROL 0x2E
#define SDHCI_SOFTWARE_RESET 0x2F
#define SDHCI_RESET_ALL 0x01
#define SDHCI_RESET_CMD 0x02
#define SDHCI_RESET_DATA 0x04
#define SDHCI_INT_STATUS 0x30
#define SDHCI_INT_ENABLE 0x34
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
#define SDHCI_INT_BLOCK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
#define SDHCI_INT_CARD_INSERT 0x00000040
#define SDHCI_INT_CARD_REMOVE 0x00000080
#define SDHCI_INT_CARD_INT 0x00000100
#define SDHCI_INT_ERROR 0x00008000
#define SDHCI_INT_TIMEOUT 0x00010000
#define SDHCI_INT_CRC 0x00020000
#define SDHCI_INT_END_BIT 0x00040000
#define SDHCI_INT_INDEX 0x00080000
#define SDHCI_INT_DATA_TIMEOUT 0x00100000
#define SDHCI_INT_DATA_CRC 0x00200000
#define SDHCI_INT_DATA_END_BIT 0x00400000
#define SDHCI_INT_BUS_POWER 0x00800000
#define SDHCI_INT_ACMD12ERR 0x01000000
#define SDHCI_INT_ADMAERR 0x02000000
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
SDHCI_INT_DATA_END_BIT)
#define SDHCI_ACMD12_ERR 0x3C
#define SDHCI_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
#define SDHCI_TIMEOUT_CLK_SHIFT 0
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
#define SDHCI_CLOCK_BASE_MASK 0x00003F00
#define SDHCI_CLOCK_BASE_SHIFT 8
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
#define SDHCI_CAN_DO_ADMA2 0x00080000
#define SDHCI_CAN_DO_HISPD 0x00200000
#define SDHCI_CAN_DO_DMA 0x00400000
#define SDHCI_CAN_DO_SUSPEND 0x00800000
#define SDHCI_CAN_VDD_330 0x01000000
#define SDHCI_CAN_VDD_300 0x02000000
#define SDHCI_CAN_VDD_180 0x04000000
#define SDHCI_CAN_DO_64BIT 0x10000000
#define SDHCI_MAX_CURRENT 0x48
#define SDHCI_SLOT_INT_STATUS 0xFC
#define SDHCI_HOST_VERSION 0xFE
#define SDHCI_VENDOR_VER_MASK 0xFF00
#define SDHCI_VENDOR_VER_SHIFT 8
#define SDHCI_SPEC_VER_MASK 0x00FF
#define SDHCI_SPEC_VER_SHIFT 0

View File

@ -88,6 +88,13 @@ RTEMS_BSD_DEFINE_NEXUS_DEVICE(cgem, 0, RTEMS_ARRAY_SIZE(cgem0_res),
SYSINIT_DRIVER_REFERENCE(e1000phy, miibus);
#elif defined(LIBBSP_ARM_ALTERA_CYCLONE_V_BSP_H)
RTEMS_BSD_DEFINE_NEXUS_DEVICE(dw_mmc, 0, 0, NULL);
SYSINIT_DRIVER_REFERENCE(mmc, dw_mmc);
SYSINIT_DRIVER_REFERENCE(mmcsd, mmc);
#elif defined(LIBBSP_POWERPC_QORIQ_BSP_H)
#if !QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT)

View File

@ -0,0 +1,79 @@
/*
* This file is produced automatically.
* Do not modify anything in here by hand.
*
* Created from source file
* dev/mmc/mmcbr_if.m
* with
* makeobjops.awk
*
* See the source file for legal information
*/
#ifndef _mmcbr_if_h_
#define _mmcbr_if_h_
/** @brief Unique descriptor for the MMCBR_UPDATE_IOS() method */
extern struct kobjop_desc mmcbr_update_ios_desc;
/** @brief A function implementing the MMCBR_UPDATE_IOS() method */
typedef int mmcbr_update_ios_t(device_t brdev, device_t reqdev);
static __inline int MMCBR_UPDATE_IOS(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbr_update_ios);
return ((mmcbr_update_ios_t *) _m)(brdev, reqdev);
}
/** @brief Unique descriptor for the MMCBR_REQUEST() method */
extern struct kobjop_desc mmcbr_request_desc;
/** @brief A function implementing the MMCBR_REQUEST() method */
typedef int mmcbr_request_t(device_t brdev, device_t reqdev,
struct mmc_request *req);
static __inline int MMCBR_REQUEST(device_t brdev, device_t reqdev,
struct mmc_request *req)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbr_request);
return ((mmcbr_request_t *) _m)(brdev, reqdev, req);
}
/** @brief Unique descriptor for the MMCBR_GET_RO() method */
extern struct kobjop_desc mmcbr_get_ro_desc;
/** @brief A function implementing the MMCBR_GET_RO() method */
typedef int mmcbr_get_ro_t(device_t brdev, device_t reqdev);
static __inline int MMCBR_GET_RO(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbr_get_ro);
return ((mmcbr_get_ro_t *) _m)(brdev, reqdev);
}
/** @brief Unique descriptor for the MMCBR_ACQUIRE_HOST() method */
extern struct kobjop_desc mmcbr_acquire_host_desc;
/** @brief A function implementing the MMCBR_ACQUIRE_HOST() method */
typedef int mmcbr_acquire_host_t(device_t brdev, device_t reqdev);
static __inline int MMCBR_ACQUIRE_HOST(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbr_acquire_host);
return ((mmcbr_acquire_host_t *) _m)(brdev, reqdev);
}
/** @brief Unique descriptor for the MMCBR_RELEASE_HOST() method */
extern struct kobjop_desc mmcbr_release_host_desc;
/** @brief A function implementing the MMCBR_RELEASE_HOST() method */
typedef int mmcbr_release_host_t(device_t brdev, device_t reqdev);
static __inline int MMCBR_RELEASE_HOST(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbr_release_host);
return ((mmcbr_release_host_t *) _m)(brdev, reqdev);
}
#endif /* _mmcbr_if_h_ */

View File

@ -0,0 +1,55 @@
/*
* This file is produced automatically.
* Do not modify anything in here by hand.
*
* Created from source file
* dev/mmc/mmcbus_if.m
* with
* makeobjops.awk
*
* See the source file for legal information
*/
#ifndef _mmcbus_if_h_
#define _mmcbus_if_h_
/** @brief Unique descriptor for the MMCBUS_WAIT_FOR_REQUEST() method */
extern struct kobjop_desc mmcbus_wait_for_request_desc;
/** @brief A function implementing the MMCBUS_WAIT_FOR_REQUEST() method */
typedef int mmcbus_wait_for_request_t(device_t brdev, device_t reqdev,
struct mmc_request *req);
static __inline int MMCBUS_WAIT_FOR_REQUEST(device_t brdev, device_t reqdev,
struct mmc_request *req)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbus_wait_for_request);
return ((mmcbus_wait_for_request_t *) _m)(brdev, reqdev, req);
}
/** @brief Unique descriptor for the MMCBUS_ACQUIRE_BUS() method */
extern struct kobjop_desc mmcbus_acquire_bus_desc;
/** @brief A function implementing the MMCBUS_ACQUIRE_BUS() method */
typedef int mmcbus_acquire_bus_t(device_t brdev, device_t reqdev);
static __inline int MMCBUS_ACQUIRE_BUS(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbus_acquire_bus);
return ((mmcbus_acquire_bus_t *) _m)(brdev, reqdev);
}
/** @brief Unique descriptor for the MMCBUS_RELEASE_BUS() method */
extern struct kobjop_desc mmcbus_release_bus_desc;
/** @brief A function implementing the MMCBUS_RELEASE_BUS() method */
typedef int mmcbus_release_bus_t(device_t brdev, device_t reqdev);
static __inline int MMCBUS_RELEASE_BUS(device_t brdev, device_t reqdev)
{
kobjop_t _m;
KOBJOPLOOKUP(((kobj_t)brdev)->ops,mmcbus_release_bus);
return ((mmcbus_release_bus_t *) _m)(brdev, reqdev);
}
#endif /* _mmcbus_if_h_ */

64
rtemsbsd/local/mmcbr_if.c Normal file
View File

@ -0,0 +1,64 @@
#include <machine/rtems-bsd-kernel-space.h>
/*
* This file is produced automatically.
* Do not modify anything in here by hand.
*
* Created from source file
* freebsd-org/sys/dev/mmc/mmcbr_if.m
* with
* makeobjops.awk
*
* See the source file for legal information
*/
#include <rtems/bsd/sys/param.h>
#include <sys/queue.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/types.h>
#include <sys/bus.h>
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcreg.h>
#include <rtems/bsd/local/mmcbr_if.h>
struct kobj_method mmcbr_update_ios_method_default = {
&mmcbr_update_ios_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbr_update_ios_desc = {
0, &mmcbr_update_ios_method_default
};
struct kobj_method mmcbr_request_method_default = {
&mmcbr_request_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbr_request_desc = {
0, &mmcbr_request_method_default
};
struct kobj_method mmcbr_get_ro_method_default = {
&mmcbr_get_ro_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbr_get_ro_desc = {
0, &mmcbr_get_ro_method_default
};
struct kobj_method mmcbr_acquire_host_method_default = {
&mmcbr_acquire_host_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbr_acquire_host_desc = {
0, &mmcbr_acquire_host_method_default
};
struct kobj_method mmcbr_release_host_method_default = {
&mmcbr_release_host_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbr_release_host_desc = {
0, &mmcbr_release_host_method_default
};

View File

@ -0,0 +1,47 @@
#include <machine/rtems-bsd-kernel-space.h>
/*
* This file is produced automatically.
* Do not modify anything in here by hand.
*
* Created from source file
* freebsd-org/sys/dev/mmc/mmcbus_if.m
* with
* makeobjops.awk
*
* See the source file for legal information
*/
#include <rtems/bsd/sys/param.h>
#include <sys/queue.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/bus.h>
#include <dev/mmc/mmcreg.h>
#include <dev/mmc/bridge.h>
#include <rtems/bsd/local/mmcbus_if.h>
struct kobj_method mmcbus_wait_for_request_method_default = {
&mmcbus_wait_for_request_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbus_wait_for_request_desc = {
0, &mmcbus_wait_for_request_method_default
};
struct kobj_method mmcbus_acquire_bus_method_default = {
&mmcbus_acquire_bus_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbus_acquire_bus_desc = {
0, &mmcbus_acquire_bus_method_default
};
struct kobj_method mmcbus_release_bus_method_default = {
&mmcbus_release_bus_desc, (kobjop_t) kobj_error_method
};
struct kobjop_desc mmcbus_release_bus_desc = {
0, &mmcbus_release_bus_method_default
};

View File

@ -151,7 +151,7 @@ rtems_bsd_scsi_inquiry(union ccb *ccb, struct scsi_inquiry_data *inq_data)
rtems_bsd_ccb_callback,
BSD_SCSI_TAG,
(u_int8_t *) inq_data,
sizeof(*inq_data) - 1,
SHORT_INQUIRY_LENGTH,
FALSE,
0,
SSD_MIN_SIZE,
@ -339,11 +339,11 @@ rtems_bsd_sim_attach_worker(rtems_media_state state, const char *src, char **des
}
sc = rtems_bsd_scsi_inquiry(&sim->ccb, &inq_data);
if (sc != RTEMS_SUCCESSFUL) {
if (sc == RTEMS_SUCCESSFUL) {
scsi_print_inquiry(&inq_data);
} else {
BSD_PRINTF("OOPS: inquiry failed\n");
goto error;
}
scsi_print_inquiry(&inq_data);
for (retries = 0; retries <= 3; ++retries) {
sc = rtems_bsd_scsi_test_unit_ready(&sim->ccb);
@ -353,10 +353,14 @@ rtems_bsd_sim_attach_worker(rtems_media_state state, const char *src, char **des
}
if (sc != RTEMS_SUCCESSFUL) {
BSD_PRINTF("OOPS: test unit ready failed\n");
goto error;
}
sc = rtems_bsd_scsi_read_capacity(&sim->ccb, &block_count, &block_size);
for (retries = 0; retries <= 3; ++retries) {
sc = rtems_bsd_scsi_read_capacity(&sim->ccb, &block_count, &block_size);
if (sc == RTEMS_SUCCESSFUL) {
break;
}
}
if (sc != RTEMS_SUCCESSFUL) {
BSD_PRINTF("OOPS: read capacity failed\n");
goto error;

View File

@ -0,0 +1,58 @@
/**
* @file
*
* @ingroup rtems_bsd_rtems
*
* @brief TODO.
*/
/*
* Copyright (c) 2011 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <info@embedded-brains.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <machine/rtems-bsd-kernel-space.h>
#include <rtems/bsd/sys/param.h>
#include <rtems/bsd/sys/types.h>
#include <sys/kernel.h>
int
config_intrhook_establish(struct intr_config_hook *hook)
{
(*hook->ich_func)(hook->ich_arg);
return (0);
}
void
config_intrhook_disestablish(struct intr_config_hook *hook)
{
/* Do nothing */
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <info@embedded-brains.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DW_MMC_DW_MMCREG_H
#define DW_MMC_DW_MMCREG_H
#define DW_MMC_CTRL 0x000
#define DW_MMC_PWREN 0x004
#define DW_MMC_CLKDIV 0x008
#define DW_MMC_CLKSRC 0x00c
#define DW_MMC_CLKENA 0x010
#define DW_MMC_TMOUT 0x014
#define DW_MMC_CTYPE 0x018
#define DW_MMC_BLKSIZ 0x01c
#define DW_MMC_BYTCNT 0x020
#define DW_MMC_INTMASK 0x024
#define DW_MMC_CMDARG 0x028
#define DW_MMC_CMD 0x02c
#define DW_MMC_RESP0 0x030
#define DW_MMC_RESP1 0x034
#define DW_MMC_RESP2 0x038
#define DW_MMC_RESP3 0x03c
#define DW_MMC_MINTSTS 0x040
#define DW_MMC_RINTSTS 0x044
#define DW_MMC_STATUS 0x048
#define DW_MMC_FIFOTH 0x04c
#define DW_MMC_CDETECT 0x050
#define DW_MMC_WRTPRT 0x054
#define DW_MMC_GPIO 0x058
#define DW_MMC_TCBCNT 0x05c
#define DW_MMC_TBBCNT 0x060
#define DW_MMC_DEBNCE 0x064
#define DW_MMC_USRID 0x068
#define DW_MMC_VERID 0x06c
#define DW_MMC_HCON 0x070
#define DW_MMC_UHS_REG 0x074
#define DW_MMC_RST_N 0x078
#define DW_MMC_BMOD 0x080
#define DW_MMC_PLDMND 0x084
#define DW_MMC_DBADDR 0x088
#define DW_MMC_IDSTS 0x08c
#define DW_MMC_IDINTEN 0x090
#define DW_MMC_DSCADDR 0x094
#define DW_MMC_BUFADDR 0x098
#define DW_MMC_DATA 0x200
/* Control Register */
#define DW_MMC_CTRL_DMA_ENABLE (1u << 25)
#define DW_MMC_CTRL_CEATA_INT_EN (1u << 11)
#define DW_MMC_CTRL_SEND_AS_CCSD (1u << 10)
#define DW_MMC_CTRL_SEND_CCSD (1u << 9)
#define DW_MMC_CTRL_ABRT_READ_DATA (1u << 8)
#define DW_MMC_CTRL_SEND_IRQ_RESP (1u << 7)
#define DW_MMC_CTRL_READ_WAIT (1u << 6)
#define DW_MMC_CTRL_INT_ENABLE (1u << 4)
#define DW_MMC_CTRL_DMA_RESET (1u << 2)
#define DW_MMC_CTRL_FIFO_RESET (1u << 1)
#define DW_MMC_CTRL_RESET (1u << 0)
/* Power Enable Register */
#define DW_MMC_PWREN_ENABLE (1u << 0)
/* Clock Enable Register */
#define DW_MMC_CLKEN_LOW_PWR (1u << 16)
#define DW_MMC_CLKEN_ENABLE (1u << 0)
/* Timeout Register */
#define DW_MMC_TMOUT_DATA(x) ((x) << 8)
#define DW_MMC_TMOUT_DATA_MSK 0xffffff00
#define DW_MMC_TMOUT_RESP(x) ((x) & 0xFF)
#define DW_MMC_TMOUT_RESP_MSK 0xff
/* Card Type Register */
#define DW_MMC_CTYPE_8BIT (1u << 16)
#define DW_MMC_CTYPE_4BIT (1u << 0)
#define DW_MMC_CTYPE_1BIT 0
/* Interrupt Status and Interrupt Mask Register */
#define DW_MMC_INT_SDIO(x) (1u << (16 + (x)))
#define DW_MMC_INT_EBE (1u << 15)
#define DW_MMC_INT_ACD (1u << 14)
#define DW_MMC_INT_SBE (1u << 13)
#define DW_MMC_INT_HLE (1u << 12)
#define DW_MMC_INT_FRUN (1u << 11)
#define DW_MMC_INT_HTO (1u << 10)
#define DW_MMC_INT_DRTO (1u << 9)
#define DW_MMC_INT_RTO (1u << 8)
#define DW_MMC_INT_DCRC (1u << 7)
#define DW_MMC_INT_RCRC (1u << 6)
#define DW_MMC_INT_RXDR (1u << 5)
#define DW_MMC_INT_TXDR (1u << 4)
#define DW_MMC_INT_DTO (1u << 3)
#define DW_MMC_INT_CMD_DONE (1u << 2)
#define DW_MMC_INT_RE (1u << 1)
#define DW_MMC_INT_CD (1u << 0)
#define DW_MMC_INT_ERROR (DW_MMC_INT_RE | DW_MMC_INT_RCRC | DW_MMC_INT_DCRC \
| DW_MMC_INT_DRTO | DW_MMC_INT_RTO | DW_MMC_INT_EBE)
/* Command Register */
#define DW_MMC_CMD_START (1u << 31)
#define DW_MMC_CMD_USE_HOLD_REG (1u << 29)
#define DW_MMC_CMD_VOLT_SWITCH (1u << 28)
#define DW_MMC_CMD_BOOT_MODE (1u << 27)
#define DW_MMC_CMD_DISABLE_BOOT (1u << 26)
#define DW_MMC_CMD_EXP_BOOT_ACK (1u << 25)
#define DW_MMC_CMD_ENABLE_BOOT (1u << 24)
#define DW_MMC_CMD_CCS_EXP (1u << 23)
#define DW_MMC_CMD_CEATA_RD (1u << 22)
#define DW_MMC_CMD_UPDATE_CLK (1u << 21)
#define DW_MMC_CMD_SEND_INIT (1u << 15)
#define DW_MMC_CMD_STOP_ABRT (1u << 14)
#define DW_MMC_CMD_PRV_DATA_WAIT (1u << 13)
#define DW_MMC_CMD_SEND_STOP (1u << 12)
#define DW_MMC_CMD_STREAM_MODE (1u << 11)
#define DW_MMC_CMD_DATA_WR (1u << 10)
#define DW_MMC_CMD_DATA_EXP (1u << 9)
#define DW_MMC_CMD_RESP_CRC (1u << 8)
#define DW_MMC_CMD_RESP_LONG (1u << 7)
#define DW_MMC_CMD_RESP_EXP (1u << 6)
#define DW_MMC_CMD_INDEX(x) ((x) & 0x1f)
/* Status Register */
#define DW_MMC_STATUS_GET_FIFO_CNT(x) (((x) >> 17) & 0x1fff)
#define DW_MMC_STATUS_GET_RESP_IDX(x) (((x) >> 11) & 0x3f)
#define DW_MMC_STATUS_DS_MC_BUSY (1u << 10)
#define DW_MMC_STATUS_CARD_DATA_BUSY (1u << 9)
#define DW_MMC_STATUS_CARD_PRESENT (1u << 8)
#define DW_MMC_STATUS_GET_FSM_STATE(x) (((x) >> 4) & 0xf)
#define DW_MMC_STATUS_FIFO_FULL (1u << 3)
#define DW_MMC_STATUS_FIFO_EMPTY (1u << 2)
#define DW_MMC_STATUS_FIFO_TX_WM (1u << 1)
#define DW_MMC_STATUS_FIFO_RX_WM (1u << 0)
/* DMA and FIFO Control Register */
#define DW_MMC_FIFOTH_BSZ(x) ((x) << 28)
#define DW_MMC_FIFOTH_BSZ_MSK DW_MMC_FIFOTH_BSZ(0x7)
#define DW_MMC_FIFOTH_RX_WMARK(x) ((x) << 16)
#define DW_MMC_FIFOTH_RX_WMARK_MSK DW_MMC_FIFOTH_RX_WMARK(0xfff)
#define DW_MMC_FIFOTH_TX_WMARK(x) ((x) << 0)
#define DW_MMC_FIFOTH_TX_WMARK_MSK DW_MMC_FIFOTH_TX_WMARK(0xfff)
/* Card Detect Register */
#define DW_MMC_CDETECT_NOT_DETECTED (1u << 0)
/* Write Protect Register */
#define DW_MMC_WRTPRT_ENABLED (1u << 0)
/* Hardware Reset Register */
#define DW_MMC_RST_N_ACTIVE_MODE (1u << 0)
/* Bus Mode Register */
#define DW_MMC_BMOD_DE (1u << 7)
#define DW_MMC_BMOD_FB (1u << 1)
#define DW_MMC_BMOD_SWR (1u << 0)
/* Internal DMAC Status and Interrupt DMAC Interrupt Enable Register */
#define DW_MMC_IDMAC_INT_GET_FSM(x) (((x) >> 13) & 0xf)
#define DW_MMC_IDMAC_INT_GET_EB(x) (((x) >> 10) & 0x7)
#define DW_MMC_IDMAC_INT_AIS (1u << 9)
#define DW_MMC_IDMAC_INT_NIS (1u << 8)
#define DW_MMC_IDMAC_INT_CES (1u << 5)
#define DW_MMC_IDMAC_INT_DU (1u << 4)
#define DW_MMC_IDMAC_INT_FBE (1u << 2)
#define DW_MMC_IDMAC_INT_RI (1u << 1)
#define DW_MMC_IDMAC_INT_TI (1u << 0)
/* Internal DMA descriptor */
struct dw_mmc_des {
uint32_t des0;
uint32_t des1;
uint32_t des2;
uint32_t des3;
};
#define DW_MMC_DES0_OWN (1u << 31)
#define DW_MMC_DES0_CES (1u << 30)
#define DW_MMC_DES0_ER (1u << 5)
#define DW_MMC_DES0_CH (1u << 4)
#define DW_MMC_DES0_FS (1u << 3)
#define DW_MMC_DES0_LD (1u << 2)
#define DW_MMC_DES0_DIC (1u << 1)
#define DW_MMC_DES1_BS2(x) ((x) << 13)
#define DW_MMC_DES1_BS1(x) ((x) << 0)
#define DW_MMC_DES1_MAX_BS 4096
/* FIFO dimensions */
#define DW_MMC_FIFO_DEPTH 1024
#define DW_MMC_FIFO_WIDTH 4
#endif /* DW_MMC_DW_MMCREG_H */

View File

@ -287,6 +287,7 @@ SYSINIT_NEED_NET_PF_UNIX;
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM