This mod does not work on the new trunk and Chaos Calmer 15.05 (since the revision r47045).
You need to discard this three changes to work property with this mod.
Now just remove three patches from git repository:
git rm target/linux/generic/patches-3.18/092-01-spi-Check-to-see-if-the-device-is-processing-a-messa.patch git rm target/linux/generic/patches-3.18/092-02-spi-Pump-transfers-inside-calling-context-for-spi_sy.patch git rm target/linux/generic/patches-3.18/092-03-spi-Only-idle-the-message-pump-in-the-worker-kthread.patchYou can also do this in same way for other branches…
Or you can use old Barrier Breaker 14.07 branch or Chaos Calmer 15.05 branch (up to revision r47042).
For example, to reset trunk branch to old revision r47042, use this command:
git reset --hard d8d8d594442086ce07b0401d472468b0c6a3c4ceYou can also do this in same way for other branches…
(Where the long parameter is a commit of necessary revision (git log −−grep 47042
)).
Scheme for First way |
---|
![]() This connection scheme was successfully tested on TP-LINK MR3220 v1 device (NO GPIO needed for this scheme) |
Two schems below for Second or Third way |
![]() This connection scheme was successfully tested on TP-LINK MR3220 v1 device (with GPIO power bus = 2.6V) |
![]() This connection scheme was successfully tested on TP-LINK WR841N v7.1 device (with GPIO power bus = ![]() |
There are three ways to modify the device and the source code for this device by using the same(common) CS0 and share it with SD-card /or/ any unused GPIO as CS1 /or/ Internal CS1 (it used by SPI controller).
And two ways for installing the required modules for detect and use the SD memory card is connected to the SPI bus of device.
At software level, this modification is almost no different from mmc_over_gpio, the only difference in the Independent slave SPI configuration of controller - that means we are using CS0
, CS1…CSn
line for each slave SPI-device.
On any platform with Atheros SoC we can see serial NOR-flash chip which is connected to SPI controller and it is used as primary boot device.
How to build your own firmware is covered here: build.
If you already have experience with compile own firmware, and you want to easy apply these changes as patch(es), you can just use this Linux console command:
Svn patch file format: | patch -u -p0 < patchfile.patch |
Git patch file format: | git apply patchfile.patchOR patch -u -p1 < patchfile.patch |
Where
patchfile.patch
must be placed in the trunk
or other branches directory.
Note: Keep in mind, very often the unused GPIOs a pulled-down to the ground or pulled-up to the power bus via resistor - this may affect on detection of SD memory cards.
![]() |
Using this method, you need to purchase a Single (or Schmitt-Trigger) Inverter Gate (which can operates on voltage 3.3V).
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c index 9323b31..2c51142 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c @@ -50,7 +50,7 @@ static struct ath79_spi_platform_data ath79_spi_data; void __init ath79_register_m25p80(struct flash_platform_data *pdata) { ath79_spi_data.bus_num = 0; - ath79_spi_data.num_chipselect = 1; + ath79_spi_data.num_chipselect = 2; ath79_spi0_cdata.is_flash = true; ath79_spi_info[0].platform_data = pdata; ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c index 5924ac5..5961732 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c @@ -9,6 +9,9 @@ */ #include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> #include <asm/mach-ath79/ath79.h> @@ -17,6 +20,7 @@ #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-m25p80.h" +#include "dev-spi.h" #include "dev-usb.h" #include "machtypes.h" @@ -32,6 +36,37 @@ #define TL_MR3X20_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_MR3X20_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3X20_KEYS_POLL_INTERVAL) +static struct mmc_spi_platform_data ath79_mmc_pdata = { + .detect_delay = 250, /* card detection delay in msec */ + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + + +/* + * Need to change cs_line to 2 (for AR72xx, AR933x) + * or 5 (for AR934x, QCA95xx), this GPIO num. is equivalent of + * internal CS0 line. + * In its core, this is a dummy, because internal CS0 line + * is locked by HW and SPI driver, and we can not use it at all. + * We use this to simply switch SPI bus to another device. + */ +static struct ath79_spi_controller_data ath79_spi1_cdata = { + .cs_type = ATH79_SPI_CS_TYPE_GPIO, + .cs_line = 2, + .is_flash = false, +}; + +static struct spi_board_info ath79_spi_info[] __initdata = { + { + .bus_num = 0, + .chip_select = 1, + .max_speed_hz = 25000000, + .modalias = "mmc_spi", + .platform_data = &ath79_mmc_pdata, + .controller_data = &ath79_spi1_cdata, + } +}; + static const char *tl_mr3x20_part_probes[] = { "tp-link", NULL, @@ -82,6 +117,9 @@ static void __init tl_ap99_setup(void) ath79_register_m25p80(&tl_mr3x20_flash_data); + spi_register_board_info(ath79_spi_info, + ARRAY_SIZE(ath79_spi_info)); + ath79_register_gpio_keys_polled(-1, TL_MR3X20_KEYS_POLL_INTERVAL, ARRAY_SIZE(tl_mr3x20_gpio_keys), tl_mr3x20_gpio_keys);
Recommended to use any unused GPIO-pin as CS1 for MMC/SD memory card.
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c index e5831d4..80760d5 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c @@ -50,7 +50,7 @@ static struct ath79_spi_platform_data ath79_spi_data; void __init ath79_register_m25p80(struct flash_platform_data *pdata) { ath79_spi_data.bus_num = 0; - ath79_spi_data.num_chipselect = 1; + ath79_spi_data.num_chipselect = 2; ath79_spi0_cdata.is_flash = true; ath79_spi_info[0].platform_data = pdata; ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c index 5924ac5..4d4ac42 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c @@ -9,6 +9,9 @@ */ #include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> #include <asm/mach-ath79/ath79.h> @@ -17,11 +20,13 @@ #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-m25p80.h" +#include "dev-spi.h" #include "dev-usb.h" #include "machtypes.h" #define TL_MR3X20_GPIO_LED_QSS 0 #define TL_MR3X20_GPIO_LED_SYSTEM 1 +#define TL_MR3X20_GPIO_CS1_MMC 7 #define TL_MR3X20_GPIO_LED_3G 8 #define TL_MR3X20_GPIO_BTN_RESET 11 @@ -32,6 +37,28 @@ #define TL_MR3X20_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_MR3X20_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3X20_KEYS_POLL_INTERVAL) +static struct mmc_spi_platform_data ath79_mmc_pdata = { + .detect_delay = 250, /* card detection delay in msec */ + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + +static struct ath79_spi_controller_data ath79_spi1_cdata = { + .cs_type = ATH79_SPI_CS_TYPE_GPIO, + .cs_line = TL_MR3X20_GPIO_CS1_MMC, + .is_flash = false, +}; + +static struct spi_board_info ath79_spi_info[] __initdata = { + { + .bus_num = 0, + .chip_select = 1, + .max_speed_hz = 25000000, + .modalias = "mmc_spi", + .platform_data = &ath79_mmc_pdata, + .controller_data = &ath79_spi1_cdata, + } +}; + static const char *tl_mr3x20_part_probes[] = { "tp-link", NULL, @@ -82,6 +109,9 @@ static void __init tl_ap99_setup(void) ath79_register_m25p80(&tl_mr3x20_flash_data); + spi_register_board_info(ath79_spi_info, + ARRAY_SIZE(ath79_spi_info)); + ath79_register_gpio_keys_polled(-1, TL_MR3X20_KEYS_POLL_INTERVAL, ARRAY_SIZE(tl_mr3x20_gpio_keys), tl_mr3x20_gpio_keys);
Internal CS | AR71XX | AR724X | AR933X | AR934X |
---|---|---|---|---|
CS1 | usualy LED or BUTTON (GPIO0) | UART In (GPIO9) | any unused GPIOs(11-22) (Software configurable multiplexer) |
|
CS2 | usualy LED or BUTTON (GPIO1) | UART Out (GPIO10) |
On platforms with AR71XX SoC: If you want to use the internal CS1 - you need to turn off GPIO0.
On platforms with AR724X SoC: If you want to use the internal CS1 - you need to turn off GPIO0.
On platforms with AR933X SoC: If you want to use the internal CS1 - you need to turn off UART.
On platforms with AR934X SoC: If you want to use the internal CS1 - you need to configure GPIO to CS1.
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c index e5831d4..80760d5 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c @@ -50,7 +50,7 @@ static struct ath79_spi_platform_data ath79_spi_data; void __init ath79_register_m25p80(struct flash_platform_data *pdata) { ath79_spi_data.bus_num = 0; - ath79_spi_data.num_chipselect = 1; + ath79_spi_data.num_chipselect = 2; ath79_spi0_cdata.is_flash = true; ath79_spi_info[0].platform_data = pdata; ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c index 5924ac5..1c6428f 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c @@ -9,19 +9,26 @@ */ #include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> #include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "common.h" #include "dev-eth.h" #include "dev-ap9x-pci.h" #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-m25p80.h" +#include "dev-spi.h" #include "dev-usb.h" #include "machtypes.h" #define TL_MR3X20_GPIO_LED_QSS 0 #define TL_MR3X20_GPIO_LED_SYSTEM 1 +#define TL_MR3X20_GPIO_CS1_MMC 7 #define TL_MR3X20_GPIO_LED_3G 8 #define TL_MR3X20_GPIO_BTN_RESET 11 @@ -32,6 +39,28 @@ #define TL_MR3X20_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_MR3X20_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3X20_KEYS_POLL_INTERVAL) +static struct mmc_spi_platform_data ath79_mmc_pdata = { + .detect_delay = 250, /* card detection delay in msec */ + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + +static struct ath79_spi_controller_data ath79_spi1_cdata = { + .cs_type = ATH79_SPI_CS_TYPE_INTERNAL, + .cs_line = 1, + .is_flash = false, +}; + +static struct spi_board_info ath79_spi_info[] __initdata = { + { + .bus_num = 0, + .chip_select = 1, + .max_speed_hz = 25000000, + .modalias = "mmc_spi", + .platform_data = &ath79_mmc_pdata, + .controller_data = &ath79_spi1_cdata, + } +}; + static const char *tl_mr3x20_part_probes[] = { "tp-link", NULL, @@ -80,8 +109,14 @@ static void __init tl_ap99_setup(void) u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + /* Enabling internal CS1, disable GPIO 0 */ + ath79_gpio_function_enable(AR724X_GPIO_FUNC_SPI_CS_EN1); + ath79_register_m25p80(&tl_mr3x20_flash_data); + spi_register_board_info(ath79_spi_info, + ARRAY_SIZE(ath79_spi_info)); + ath79_register_gpio_keys_polled(-1, TL_MR3X20_KEYS_POLL_INTERVAL, ARRAY_SIZE(tl_mr3x20_gpio_keys), tl_mr3x20_gpio_keys);
/* Enabling internal CS1, disable GPIO 0 */ ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN);
/* Enabling internal CS1, disable GPIO 0 */ ath79_gpio_function_enable(AR724X_GPIO_FUNC_SPI_CS_EN1);(Already used in the above example.)
/* Disable UART, enabling GPIO 9 and GPIO 10 */ ath79_gpio_function_disable(AR933X_GPIO_FUNC_UART_EN); /* Enabling internal CS1, disable GPIO 9 */ ath79_gpio_function_enable(AR933X_GPIO_FUNC_SPI_CS_EN1);
/* We chose GPIO11 - for this example. You can use any unused GPIOs(11-22) */ #define DEVICE_GPIO_CS1_MMC 11 /* custom register for CS2 (AR934X SoC), TODO in future ar71xx_regs.h */ #define AR934X_GPIO_OUT_SPI_CS2 8 ... /* Configure GPIO to MUX Select (CS1) */ ath79_gpio_output_select(DEVICE_GPIO_CS1_MMC, AR934X_GPIO_OUT_SPI_CS1);
![]() |
![]() We use SD Socket/SD card holder/SD Memory Card Connector with special integrated buttons - CD (Card Detect) and WP (Write Protect) |
Total we use two unused GPIOs: GPIO7→CS1, GPIO18→CD.
Create a new additional button on this example:
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c index e5831d4..80760d5 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c @@ -50,7 +50,7 @@ static struct ath79_spi_platform_data ath79_spi_data; void __init ath79_register_m25p80(struct flash_platform_data *pdata) { ath79_spi_data.bus_num = 0; - ath79_spi_data.num_chipselect = 1; + ath79_spi_data.num_chipselect = 2; ath79_spi0_cdata.is_flash = true; ath79_spi_info[0].platform_data = pdata; ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1); diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c index 5924ac5..9990d05 100644 --- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c +++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-mr3x20.c @@ -9,6 +9,9 @@ */ #include <linux/gpio.h> +#include <linux/mmc/host.h> +#include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> #include <asm/mach-ath79/ath79.h> @@ -17,21 +20,46 @@ #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-m25p80.h" +#include "dev-spi.h" #include "dev-usb.h" #include "machtypes.h" #define TL_MR3X20_GPIO_LED_QSS 0 #define TL_MR3X20_GPIO_LED_SYSTEM 1 +#define TL_MR3X20_GPIO_CS1_MMC 7 #define TL_MR3X20_GPIO_LED_3G 8 #define TL_MR3X20_GPIO_BTN_RESET 11 #define TL_MR3X20_GPIO_BTN_QSS 12 +#define TL_MR3X20_GPIO_BTN_MMC 18 #define TL_MR3X20_GPIO_USB_POWER 6 #define TL_MR3X20_KEYS_POLL_INTERVAL 20 /* msecs */ #define TL_MR3X20_KEYS_DEBOUNCE_INTERVAL (3 * TL_MR3X20_KEYS_POLL_INTERVAL) +static struct mmc_spi_platform_data ath79_mmc_pdata = { + .detect_delay = 250, /* card detection delay in msec */ + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, +}; + +static struct ath79_spi_controller_data ath79_spi1_cdata = { + .cs_type = ATH79_SPI_CS_TYPE_GPIO, + .cs_line = TL_MR3X20_GPIO_CS1_MMC, + .is_flash = false, +}; + +static struct spi_board_info ath79_spi_info[] __initdata = { + { + .bus_num = 0, + .chip_select = 1, + .max_speed_hz = 25000000, + .modalias = "mmc_spi", + .platform_data = &ath79_mmc_pdata, + .controller_data = &ath79_spi1_cdata, + } +}; + static const char *tl_mr3x20_part_probes[] = { "tp-link", NULL, @@ -72,6 +100,13 @@ static struct gpio_keys_button tl_mr3x20_gpio_keys[] __initdata = { .debounce_interval = TL_MR3X20_KEYS_DEBOUNCE_INTERVAL, .gpio = TL_MR3X20_GPIO_BTN_QSS, .active_low = 1, + }, { + .desc = "mmc", + .type = EV_KEY, + .code = BTN_0, + .debounce_interval = TL_MR3X20_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_MR3X20_GPIO_BTN_MMC, + .active_low = 1, } }; @@ -82,6 +117,11 @@ static void __init tl_ap99_setup(void) ath79_register_m25p80(&tl_mr3x20_flash_data); + spi_register_board_info(ath79_spi_info, + ARRAY_SIZE(ath79_spi_info)); + + gpio_direction_input(TL_MR3X20_GPIO_BTN_MMC); + ath79_register_gpio_keys_polled(-1, TL_MR3X20_KEYS_POLL_INTERVAL, ARRAY_SIZE(tl_mr3x20_gpio_keys), tl_mr3x20_gpio_keys);We could use GPIO to IRQ event as card detection (implemented in
mmc_spi
module) or GPIO to IRQ event as new hotplug SPI-device (implemented in standart SPI bus driver) - but in all this cases, it was found that it not support hotplug detection with removing the SD-card or SPI-device via the IRQ trigger.
The solution was found without the use of IRQ trigger:
After build and compiling the firmware, we just added additional button with the name mmc
.
Next, you need to create a configuration for the button mmc
:
uci add system button uci set system.@button[-1].button=mmc uci set system.@button[-1].action=pressed uci set system.@button[-1].handler='echo "spi0.1" > /sys/bus/spi/drivers/mmc_spi/unbind' uci add system button uci set system.@button[-1].button=mmc uci set system.@button[-1].action=released uci set system.@button[-1].handler='echo "spi0.1" > /sys/bus/spi/drivers/mmc_spi/bind' uci commit system
Note: Action pressed/released dependent on default state of GPIO (Input), i.e., sometimes you need to swap actions. Before removing SD-card from the slot, it is recommended to use the console commands sync
and unmount <partition>
- for correctly unmounting of a partition. Because if we remove SD-card(after recording on it) without using unmount commands - we risk losing some not recorded data.
... [ 1968.380000] mmc_spi spi0.1: SD/MMC host mmc0, no DMA, no WP, no poweroff [ 1968.550000] mmc0: SD Status: Invalid Allocation Unit size. [ 1968.560000] mmc0: host does not support reading read-only switch. assuming write-enable. [ 1968.570000] mmc0: new SD card on SPI [ 1968.570000] mmcblk0: mmc0:0000 00000 1.90 GiB [ 1968.580000] mmcblk0: p1 [ 1980.340000] mmc0: SPI card removed [ 2008.900000] mmc_spi spi0.1: SD/MMC host mmc0, no DMA, no WP, no poweroff [ 2009.070000] mmc0: SD Status: Invalid Allocation Unit size. [ 2009.080000] mmc0: host does not support reading read-only switch. assuming write-enable. [ 2009.090000] mmc0: new SD card on SPI [ 2009.090000] mmcblk0: mmc0:0000 00000 1.90 GiB [ 2009.100000] mmcblk0: p1 ...
![]() | By using this variant - NO need to install external modules kmod-mmc , kmod-mmc-spi and kmod-fs-ext4 . You can use the SD memory card as extroot (block-mount) with no problem. |
When we build own firmware we use standard menu make menuconfig
, after that we need to use special menu make kernel_menuconfig
.
In this kernel menu, select the asterisks following items:
(Use Arrows UP and DOWN to find and select) Device Drivers ---> (Press ENTER) <*> MMC/SD/SDIO card support ---- (Find this item and press SPACE twice from the <M> to turn the <*> and then press ENTER) ├<*> MMC block device driver (Find this item and press SPACE twice from the <M> to turn the <*>) └<*> MMC/SD/SDIO over SPI (Find this item and press SPACE twice from the <M> to turn the <*>) (Press ESC twice to go to the previous menu) File systems ---> (Press ENTER) <*> The Extended 4 (ext4) filesystem (Find this item and press SPACE twice from the <M> to turn the <*>) (Press ESC twice) (Use TAB or Arrows LEFT and RIGHT to select < Exit >) < Exit > < Yes >Besides MMC modules, we include the EXT4 module on the kernel level.
The integration of the required modules into the kernel, allows us to use detected SD-card on one level with NOR flash memory. For example: we can mount root-fs at kernel level by setting: CONFIG_CMDLINE="rootfstype=squashfs,jffs2,ext3 noinitrd root=/dev/mmcblk0p1 rootwait"
![]() | If we are using external modules kmod-mmc and kmod-mmc-spi - this does not allow to correctly mount /overlay or / (root) partitions through extroot. This problem is described in this old ticket. It's even considering that the use of these external modules, allow us to fully use the SD-card and mount it in the other mount points (except extroot). |
Update: The problem remained in r37142 firmware revision.
For extroot, use First way.
~ the same as AR724x tests
Read/write speed by using utility coreutils-dd:
root@OpenWrt:~# /usr/bin/dd count=14 bs=1M if=/dev/mmcblk0p1 of=/dev/null 14+0 records in 14+0 records out 14680064 bytes (15 MB) copied, 20.9663 s, 700 kB/s root@OpenWrt:~# /usr/bin/dd count=14 bs=1M if=/dev/zero of=/dev/mmcblk0p1 14+0 records in 14+0 records out 14680064 bytes (15 MB) copied, 25.2994 s, 580 kB/s root@OpenWrt:~#
Result hdparm:
root@OpenWrt:~# hdparm -Tt /dev/mmcblk0p1 /dev/mmcblk0p1: Timing cached reads: 2 MB in 2.96 seconds = 691.37 kB/sec Timing buffered disk reads: 2 MB in 3.05 seconds = 670.43 kB/sec root@OpenWrt:~#
root@OpenWrt:~# top Mem: 28224K used, 1120K free, 0K shrd, 5784K buff, 5592K cached CPU: 0% usr 99% sys 0% nic 0% idle 0% io 0% irq 0% sirq Load average: 1.21 0.88 0.60 2/60 28540 PID PPID USER STAT VSZ %VSZ %CPU COMMAND 2230 2 root RW 0 0% 55% [kworker/u:2] 2180 2 root SW 0 0% 36% [kworker/u:0] 559 2 root RW 0 0% 6% [mmcqd/0] ...
Conclusion: operations read/write speed via [ath79-spi↔spi-bitbang↔mmc_spi], directly depends on the frequency of the processor, because is used Bit-banging method to read/write the word.
TODO
TODO
Here it is necessary to specify method of performing the test.
We send two parallel commands(operations) read\write command with the division operator &
(execute the console command in the background).
Result next: while reading or writing spi0.0 and spi0.1 at the same time (the process does not matter), priority given to spi0.1 bus, i.e. until the end of read/write operation on the spi0.1 bus - on the spi0.0 bus will not begin the requested operation, all operations occurs as a priority and not a bug.
Operation | Probe |
---|---|
Idle | ~1mA |
Read data | ~18mA |
Write data | ~23mA |
... [ 0.730000] ath79-spi ath79-spi: master is unqueued, this is deprecated [ 0.740000] m25p80 spi0.0: found en25f32, expected m25p80 [ 0.750000] m25p80 spi0.0: en25f32 (4096 Kbytes) [ 0.750000] 5 tp-link partitions found on MTD device spi0.0 [ 0.760000] Creating 5 MTD partitions on "spi0.0": [ 0.760000] 0x000000000000-0x000000020000 : "u-boot" [ 0.770000] 0x000000020000-0x00000013de00 : "kernel" [ 0.770000] mtd: partition "kernel" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only [ 0.790000] 0x00000013de00-0x0000003f0000 : "rootfs" [ 0.790000] mtd: partition "rootfs" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only [ 0.810000] mtd: partition "rootfs" set to be root filesystem [ 0.810000] mtd: partition "rootfs_data" created automatically, ofs=370000, len=80000 [ 0.820000] 0x000000370000-0x0000003f0000 : "rootfs_data" [ 0.830000] 0x0000003f0000-0x000000400000 : "art" [ 0.840000] 0x000000020000-0x0000003f0000 : "firmware" [ 0.860000] libphy: ag71xx_mdio: probed [ 0.860000] eth0: Atheros AG71xx at 0xba000000, irq 5, mode:GMII [ 1.420000] eth0: Found an AR7240/AR9330 built-in switch [ 2.450000] eth1: Atheros AG71xx at 0xb9000000, irq 4, mode:MII [ 3.000000] ag71xx ag71xx.0 eth1: connected to PHY at ag71xx-mdio.1:04 [uid=004dd041, driver=Generic PHY] [ 3.050000] mmc_spi spi0.1: SD/MMC host mmc0, no DMA, no WP, no poweroff [ 3.060000] TCP: cubic registered [ 3.060000] NET: Registered protocol family 17 [ 3.070000] 8021q: 802.1Q VLAN Support v1.8 [ 3.080000] VFS: Mounted root (squashfs filesystem) readonly on device 31:2. [ 3.090000] Freeing unused kernel memory: 268k freed [ 3.310000] mmc0: host does not support reading read-only switch. assuming write-enable. [ 3.320000] mmc0: new SD card on SPI [ 3.480000] mmcblk0: mmc0:0000 00000 1.90 GiB [ 3.490000] mmcblk0: p1 ...
... [ 6.070000] mmc_spi spi0.1: SD/MMC host mmc0, no DMA, no WP, no poweroff ... [ 8.710000] mmc0: error -22 whilst initialising SD card ... [ 10.710000] mmc0: error -22 whilst initialising MMC card ...
root@OpenWrt:~# ls /dev/mmc* /dev/mmcblk0 /dev/mmcblk0p1 root@OpenWrt:~#
root@OpenWrt:~# cat /sys/kernel/debug/mmc0/ios clock: 25000000 Hz vdd: 20 (3.2 ~ 3.3 V) bus mode: 2 (push-pull) chip select: 1 (active high) power mode: 2 (on) bus width: 0 (1 bits) timing spec: 0 (legacy) signal voltage: 1 (3.30 V) root@OpenWrt:~#
https://forum.openwrt.org/viewtopic.php?id=54077
Porting this mod on LEDE Project:
https://forum.lede-project.org/t/ath79-sd-card-on-spi-bus-deep-mmc-mod/7527