Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
toh:tp-link:tl-mr3420:deep.mmc.hack [2017/08/13 10:16] Dioptimizertoh:tp-link:tl-mr3420:deep.mmc.hack [2018/07/02 07:56] – minor addings/changes deoptim
Line 1: Line 1:
 +====== Deep MMC Mod ======
 +{{page>meta:infobox:cleanup&noheader&nofooter&noeditbtn}}
  
 +<WRAP center important 70%>
 +This mod does not work on the older **//LEDE//** and **//Chaos Calmer 15.05//** (since the revision [[https://dev.openwrt.org/changeset/47045|r47045]]).
 +**But it works completely on the newest kernel 4.14+(ath79) and does not need to delete anything.**
 +\\
 +If you use older version of branch then you need to discard/remove this three changes to work property with this mod:
 +<code>
 +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.patch
 +</code>
 +**Note:** Instead of path **patches-3.18**, new versions already use **pending-3.18** path.
 +You can also do remove those patches 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:
 +<code>git reset --hard d8d8d594442086ce07b0401d472468b0c6a3c4ce</code>
 +You can also do this in same way for other branches...
 +
 +//(Where the long parameter is a commit of necessary revision (''git log −−grep 47042'')).//
 +</WRAP>
 +
 +===== How to connect SD-card to SPI bus =====
 +^  <color red>Scheme for First way</color>  ^
 +|  {{media:tplink:tl-mr3420:tl-mr3420-v1_common_CS_line.png?nolink|First connection scheme}} \\ //This connection scheme was successfully tested on TP-LINK MR3220 v1 device \\ (**NO** GPIO needed for this scheme)//  |
 +^  <color red>Two schems below for Second or Third way</color>  ^
 +|  {{media:tplink:tl-mr3420:tl-mr3420-v1_sd-card.png?nolink|Second connection scheme}} \\ //This connection scheme was successfully tested on TP-LINK MR3220 v1 device \\ (with GPIO power bus = 2.6V)//  |
 +|  {{media:tplink:tl-wr841:tl-wr841n-v7_sd-card.png?nolink|Third connection scheme}} \\ //This connection scheme was successfully tested on TP-LINK WR841N v7.1 device \\ (with GPIO power bus = FIXME)//  |
 +
 +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 [[docs:guide-user:hardware:mmc_over_gpio|mmc_over_gpio]], the only difference in the [[wp>Serial_Peripheral_Interface_Bus#Independent_slave_SPI_configuration|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: [[:docs:guide-developer:build-system:start]].\\
 +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: | <code>patch -u -p0 < patchfile.patch</code> |
 +| Git patch\\ file format: | <code>git apply patchfile.patch</code> OR <code>patch -u -p1 < patchfile.patch</code> |
 +
 +{{:meta:icons:tango:48px-emblem-important.svg.png?nolink&16|Important! }} Where ''patchfile.patch'' must be placed in the ''trunk'' or other branches directory.\\
 +
 +===== Connection MMC/SD memory card to the spi0.1 bus =====
 +**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.
 +|  {{media:doc:hardware:gpio_pullup_pulldown.png?nolink}}  |
 +\\
 +\\
 +==== First way, using common CS0 ====
 +{{:meta:icons:tango:48px-emblem-important.svg.png?nolink&16|Important! }} Using this method, you need to purchase a Single (or Schmitt-Trigger) Inverter Gate (which can operates on voltage 3.3V).
 +
 +== Main changes in the source code of kernel: ==
 +<hidden Old patch for Openwrt (before LEDE project)><code diff>
 +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);
 +
 +</code></hidden>
 +<hidden Patch for Openwrt/LEDE (4.9, ar71xx platform, mach-*.c files)><code diff>
 +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 e53d97d..269e469 100644
 +--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
 ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
 +@@ -7,8 +7,10 @@
 +  */
 + 
 + #include <linux/init.h>
 ++#include <linux/mmc/host.h>
 + #include <linux/spi/spi.h>
 + #include <linux/spi/flash.h>
 ++#include <linux/spi/mmc_spi.h>
 + #include <linux/mtd/mtd.h>
 + #include <linux/mtd/partitions.h>
 + #include <linux/mtd/concat.h>
 +@@ -16,6 +18,11 @@
 + #include "dev-spi.h"
 + #include "dev-m25p80.h"
 + 
 ++static struct mmc_spi_platform_data ath79_mmc_data = {
 ++ .detect_delay = 100, /* msecs */
 ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
 ++};
 ++
 + static struct spi_board_info ath79_spi_info[] = {
 +  {
 +  .bus_num = 0,
 +@@ -27,18 +34,25 @@ static struct spi_board_info ath79_spi_info[] = {
 +  .bus_num = 0,
 +  .chip_select = 1,
 +  .max_speed_hz   = 25000000,
 +- .modalias = "m25p80",
 ++ .modalias = "mmc_spi",
 ++ .platform_data = &ath79_mmc_data,
 +  }
 + };
 + 
 ++static int device_spi_cs_gpios[2] = {
 ++ -ENOENT,
 ++ 2, /* GPIO Number */
 ++};
 ++
 + 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_spi_data.cs_gpios = device_spi_cs_gpios;
 +  ath79_spi_info[0].platform_data = pdata;
 +- ath79_register_spi(&ath79_spi_data, ath79_spi_info, 1);
 ++ ath79_register_spi(&ath79_spi_data, ath79_spi_info, 2);
 + }
 + 
 + static struct flash_platform_data *multi_pdata;
 +
 +</code></hidden>
 +<hidden Patch for Openwrt (4.14+, ath79 platform, dts files)><code diff>
 +diff --git a/target/linux/ath79/dts/ar7241_tp-link.dtsi b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +index 3846d811ac..d845e06951 100644
 +--- a/target/linux/ath79/dts/ar7241_tp-link.dtsi
 ++++ b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +@@ -48,7 +48,19 @@
 + 
 + &spi {
 +  status = "okay";
 +- num-cs = <1>;
 ++ num-cs = <2>;
 ++ /*
 ++ * First value is default pin for flash, second value
 ++ * (via comma) the GPIO number for sdcard. But we used
 ++ * gpio 2 and it equivalent of internal CS0 line. And
 ++ * we use it because we use common bus SPI0.0 for two
 ++ * devices (default Low polarity chip-select, custom
 ++ * High polarity chip-select).
 ++ * 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.
 ++ */
 ++ cs-gpios = <0>, <&gpio 2 GPIO_ACTIVE_HIGH>;
 + 
 +  flash@0 {
 +  #address-cells = <1>;
 +@@ -80,6 +92,13 @@
 +  };
 +  };
 +  };
 ++
 ++ sdcard@0 {
 ++ compatible = "mmc-spi-slot";
 ++ reg = <1>;
 ++ spi-max-frequency = <25000000>;
 ++ voltage-ranges = <3200 3400>;
 ++ };
 + };
 + 
 + &pcie {
 +
 +</code></hidden>
 +\\
 +\\
 +==== Second way, using GPIO as CS1 (Recommended) ====
 +Recommended to use any unused GPIO-pin as CS1 for MMC/SD memory card.
 +
 +== Main changes in the source code of kernel: ==
 +<hidden Old patch for Openwrt (before LEDE project)><code diff>
 +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);
 +
 +</code></hidden>
 +<hidden Patch for Openwrt (4.14+, ath79 platform, dts files)><code diff>
 +diff --git a/target/linux/ath79/dts/ar7241_tp-link.dtsi b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +index 3846d811ac..58399eb4de 100644
 +--- a/target/linux/ath79/dts/ar7241_tp-link.dtsi
 ++++ b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +@@ -48,7 +48,12 @@
 + 
 + &spi {
 +  status = "okay";
 +- num-cs = <1>;
 ++ num-cs = <2>;
 ++ /*
 ++ * Where first parameter <0> is default CS0 pin for flash
 ++ * and second parameter is GPIO Number for sdcard.
 ++ */
 ++ cs-gpios = <0>, <&gpio 7 GPIO_ACTIVE_HIGH>;
 + 
 +  flash@0 {
 +  #address-cells = <1>;
 +@@ -80,6 +85,13 @@
 +  };
 +  };
 +  };
 ++
 ++ sdcard@0 {
 ++ compatible = "mmc-spi-slot";
 ++ reg = <1>;
 ++ spi-max-frequency = <25000000>;
 ++ voltage-ranges = <3200 3400>;
 ++ };
 + };
 + 
 + &pcie {
 +
 +</code></hidden>
 +\\
 +\\
 +==== Third way, using Internal CS1 ====
 +
 +^ Internal CS ^ AR71XX  ^ AR724X ^ AR933X ^ AR934X ^
 +| CS1         | usualy LED or BUTTON (GPIO0) || UART In (GPIO9)   | any unused GPIOs(11-22) \\ (Software configurable \\ [[wp>Multiplexer|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 [[#switching#gpio0#to#cs1#on#ar71xx#soc|turn off GPIO0]].
 +
 +On platforms with AR724X SoC: If you want to use the internal CS1 - you need to [[#switching#gpio0#to#cs1#on#ar724x#soc|turn off GPIO0]].
 +
 +On platforms with AR933X SoC: If you want to use the internal CS1 - you need to [[#turn#off#uart#and#switching#gpio9(rx)#to#cs1#on#ar933x#soc|turn off UART]].
 +
 +On platforms with AR934X SoC: If you want to use the internal CS1 - you need to [[#configure#gpio11#to#cs1#on#ar934x#soc|configure GPIO to CS1]].
 +
 +== Main changes in the source code of kernel: ==
 +<hidden Old patch for Openwrt (before LEDE project)><code diff>
 +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);
 +
 +</code></hidden>
 +<hidden Patch for Openwrt (4.14+, ath79 platform, dts files)><code diff>
 +diff --git a/target/linux/ath79/dts/ar7241_tp-link.dtsi b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +index 3846d811ac..ea915872dc 100644
 +--- a/target/linux/ath79/dts/ar7241_tp-link.dtsi
 ++++ b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +@@ -48,7 +48,10 @@
 + 
 + &spi {
 +  status = "okay";
 +- num-cs = <1>;
 ++ pinctrl-names = "default";
 ++ pinctrl-0 = <&enable_cs1_bit>;
 ++ num-cs = <2>;
 ++ cs-gpios = <0>, <0>;
 + 
 +  flash@0 {
 +  #address-cells = <1>;
 +@@ -80,6 +83,30 @@
 +  };
 +  };
 +  };
 ++
 ++ sdcard@0 {
 ++ compatible = "mmc-spi-slot";
 ++ reg = <1>;
 ++ spi-max-frequency = <25000000>;
 ++ voltage-ranges = <3200 3400>;
 ++ };
 ++};
 ++
 ++&pinmux {
 ++ enable_cs1_bit: pinmux_enable_cs1_bit {
 ++ pinctrl-single,bits = <
 ++ /*
 ++ * Set AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) to 1,
 ++ * i.e. enable hardware CS1 but it turn-off GPIO0;
 ++ * Formula: *addr = (*addr & ~sub-mask) |
 ++ * (value & sub-mask);
 ++ * Where: addr is 0x18000000 + 0x40000 + 0x28 is
 ++ * base address of AR724X GPIO functions;
 ++ * <addr_offset value sub-mask>
 ++ */
 ++ 0x0 0x2000 0x2000
 ++ >;
 ++ };
 + };
 + 
 + &pcie {
 +
 +</code></hidden>
 +\\
 +== Switching GPIO0 to CS1 on AR71XX SoC: ==
 +<hidden Instruction for old Openwrt (including LEDE project)>
 +<code c>
 + /* Enabling internal CS1, disable GPIO 0 */
 + ath79_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN);
 +</code>
 +</hidden>
 +\\
 +== Switching GPIO0 to CS1 on AR724X SoC: ==
 +<hidden Instruction for old Openwrt (including LEDE project)>
 +<code c>
 + /* Enabling internal CS1, disable GPIO 0 */
 + ath79_gpio_function_enable(AR724X_GPIO_FUNC_SPI_CS_EN1);
 +</code>
 +</hidden>
 +<hidden Instruction for Openwrt (4.14+, ath79 platform, dts files)>
 +<code c>
 + ...
 + ...
 + /* Add this two lines to spi enum */
 + pinctrl-names = "default";
 + pinctrl-0 = <&enable_cs1_bit>;
 + ...
 + ...
 +&pinmux {
 + enable_cs1_bit: pinmux_enable_cs1_bit {
 + pinctrl-single,bits = <
 + /*
 + * Set AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) to 1,
 + * i.e. enable hardware CS1 but it turn-off GPIO0;
 + * Formula: *addr = (*addr & ~sub-mask) |
 + * (value & sub-mask);
 + * Where: addr is 0x18000000 + 0x40000 + 0x28 is
 + * base address of AR724X GPIO functions;
 + * <addr_offset value sub-mask>
 + */
 + 0x0 0x2000 0x2000
 + >;
 + };
 + };
 +</code>
 +</hidden>
 +**Note:** Already used in the example above.
 +\\
 +== Turn off UART and switching GPIO9(Rx) to CS1 on AR933X SoC: ==
 +<hidden Instruction for old Openwrt (including LEDE project)>
 +<code c>
 + /* 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);
 +</code>
 +</hidden>
 +\\
 +== Configure GPIO11 to CS1 on AR934X SoC: ==
 +<hidden Instruction for old Openwrt (including LEDE project)>
 +<code c>
 + /* 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);
 +</code>
 +</hidden>
 +<hidden Instruction for Openwrt (4.14+, ath79 platform, dts files)>
 +<code c>
 + ...
 + ...
 + /* Add this two lines to spi enum */
 + pinctrl-names = "default";
 + pinctrl-0 = <&gpio11_to_cs1_bit>;
 + ...
 + ...
 +&pinmux {
 + gpio11_to_cs1_bit: pinmux_gpio11_to_cs1_bit {
 + pinctrl-single,bits = <
 + /*
 + * Set AR934X_GPIO_OUT_SPI_CS1 7 value to GPIO11,
 + * i.e. enable hardware CS1 but it turn-off GPIO11;
 + * Formula: *addr = (*addr & ~sub-mask) |
 + * (value & sub-mask);
 + * Where: addr is 0x18000000 + 0x40000 + 0x2C is
 + * base address of AR934X GPIO Output functions;
 + * <addr_offset value sub-mask>;
 + */
 + /*
 + * 0x2c+0x8 addr_offset for GPIO11(Bit 31:24);
 + * 0x2c+0xc addr_offset for GPIO12-GPIO15;
 + * 0x2c+0x10 addr_offset for GPIO16-GPIO19;
 + * 0x7 value (with Bitwise Left Shift) for mux CS1
 + * use 0x8 value for mux CS2;
 + */
 + 0x8 0x7000000 0xff000000
 + >;
 + };
 + };
 +</code>
 +</hidden>
 +\\
 +\\
 +==== How to implement the Hotplug of SD-card ====
 +|  {{media:doc:hardware:memory_card_connectors_memory_card_billboard.gif?nolink}}  |
 +|  {{media:tplink:tl-mr3420:moz-screenshot-4.png?nolink|Connection scheme}} \\ //We use [[https://www.google.com.ua/search?q=SD+Socket+OR+SD+card+holder+OR+SD+Memory+Card+connector&tbm=isch|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:
 +<hidden Old patch for Openwrt (before LEDE project)><code diff>
 +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);
 +
 +</code></hidden>
 +<hidden Patch for Openwrt (4.14+, ath79 platform, dts files)><code diff>
 +diff --git a/target/linux/ath79/dts/ar7241_tp-link.dtsi b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +index 3846d811ac..d99bafcb2b 100644
 +--- a/target/linux/ath79/dts/ar7241_tp-link.dtsi
 ++++ b/target/linux/ath79/dts/ar7241_tp-link.dtsi
 +@@ -22,13 +22,18 @@
 +  gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
 +  debounce-interval = <60>;
 +  };
 +-
 +  qss {
 +  label = "qss";
 +  linux,code = <KEY_WPS_BUTTON>;
 +  gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
 +  debounce-interval = <60>;
 +  };
 ++ mmc {
 ++ label = "mmc";
 ++ linux,code = <BTN_0>;
 ++ gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
 ++ debounce-interval = <60>;
 ++ };
 +  };
 + 
 +  gpio_leds: gpio-leds {
 +@@ -48,7 +53,12 @@
 + 
 + &spi {
 +  status = "okay";
 +- num-cs = <1>;
 ++ num-cs = <2>;
 ++ /*
 ++ * Where first parameter <0> is default CS0 pin for flash
 ++ * and second parameter is GPIO Number for sdcard.
 ++ */
 ++ cs-gpios = <0>, <&gpio 7 GPIO_ACTIVE_HIGH>;
 + 
 +  flash@0 {
 +  #address-cells = <1>;
 +@@ -80,6 +90,30 @@
 +  };
 +  };
 +  };
 ++
 ++ sdcard@0 {
 ++ compatible = "mmc-spi-slot";
 ++ reg = <1>;
 ++ /*
 ++ * If you need to use GPIO18 as Card Detect and
 ++ * IRQ trigger (as standard implementation) - just
 ++ * uncomment line below (but don't forget delete
 ++ * the equivalent gpio-key). We don't use this
 ++ * property because it doesn't detect removing of
 ++ * SD Card.
 ++ */
 ++ //gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
 ++ /*
 ++ * By default, Card Detect use "active low" state.
 ++ * Using the "cd-inverted" property means, that the
 ++ * CD line is active high, i.e. it is high, when a
 ++ * card is inserted.
 ++ * (uncomment line below to enable this option)
 ++ */
 ++ //cd-inverted;
 ++ spi-max-frequency = <25000000>;
 ++ voltage-ranges = <3200 3400>;
 ++ };
 + };
 + 
 + &pcie {
 +
 +</code></hidden>
 +// 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. IRQ trigger needed if your gpio controller could be in sleep/idle state (and those CD gpio switch could be ignored by the system) - in that cause use standard implementation(not buttons).\\
 +   Or FIXME   //
 +
 +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 [[docs:guide-user:hardware:hardware.button#using.atheros.00-button.uci|create a configuration(/etc/hotplug.d/button/00-button)]] for the button **''mmc''**:
 +<code bash>
 +uci add system button
 +uci set system.@button[-1].button=BTN_0
 +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=BTN_0
 +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
 +</code>
 +
 +**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.
 +
 +== Log of hotplug process: ==
 +<code>
 +...
 +[ 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
 +...
 +</code>
 +
 +==== Modules installation ====
 +=== First way, build it in kernel (Recommended) ===
 +| {{:meta:icons:tango:dialog-information.png?nolink}} | 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 [[docs:guide-user:additional-software:extroot_configuration]] (block-mount) with no problem. |
 +
 +
 +== Integrating modules in kernel: ==
 +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:
 +<code>
 +(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 >
 +</code>
 +//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"''
 +
 +
 +=== Second way, using external modules ===
 +| {{:meta:icons:tango:48px-emblem-important.svg.png?nolink |Important!}} | If we are using external modules ''kmod-mmc'' and ''kmod-mmc-spi'' - this does not allow to correctly mount ''<color magenta>/overlay</color>'' \\ or ''<color blue>/</color>'' (root) partitions through [[docs:guide-user:additional-software:extroot_configuration]]. This problem is described in [[https://dev.openwrt.org/ticket/7768|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 [[docs:guide-user:additional-software:extroot_configuration]]). |
 +
 +** Update: ** The problem remained in **r37142** firmware revision.\\ 
 +For [[docs:guide-user:additional-software:extroot_configuration]], use First way.
 +
 +
 +==== Testing ====
 +== (AR71xx) Speed testing spi0.1: ==
 +~ the same as AR724x tests
 +
 +== (AR724x) Speed testing spi0.1: ==
 +Read/write speed by using utility **coreutils-dd**:
 +<code>
 +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:~#
 +</code>
 +
 +Result **hdparm**:
 +<code>
 +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:~#
 +</code>
 +
 +== CPU load during read/write process: ==
 +<code>
 +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%  55% [kworker/u:2]
 + 2180     2 root     SW         0%  36% [kworker/u:0]
 +  559     2 root     RW         0%   6% [mmcqd/0]
 +...
 +</code>
 +
 +**Conclusion:** operations read/write speed via [ath79-spi<->spi-bitbang<->mmc_spi], directly depends on the frequency of the processor, because is used [[wp>Bit-banging|Bit-banging]] method to read/write the word.
 +
 +== (AR933x) Speed testing spi0.1: ==
 +FIXME TODO
 +
 +== (AR934x) Speed testing spi0.1: ==
 +FIXME TODO
 +
 +== Access to spi0.0 and spi0.1 at the one time: ==
 +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.
 +
 +== Power ==
 +^ Operation    ^ Probe   ^
 +| Idle          ~1mA   |
 +| Read data    |  ~18mA  |
 +| Write data    ~23mA  |
 +
 +==== Logs ====
 +== Log with loading and initializing SD-card: ==
 +<code>
 +...
 +[    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
 +...
 +</code>
 +
 +== Error type in the case that system has NOT detected the SD-card: ==
 +<code>
 +...
 +[    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
 +...
 +</code>
 +
 +== After detecting the SD-card we can find partitions: ==
 +<code>
 +root@OpenWrt:~# ls /dev/mmc*
 +/dev/mmcblk0    /dev/mmcblk0p1
 +root@OpenWrt:~#
 +</code>
 +
 +== Debug info: ==
 +<code>
 +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:~#
 +</code>
 +
 +===== Forum discussion =====
 +
 +[[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]]
  • Last modified: 2021/10/15 09:06
  • by bobafetthotmail