Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision Next revisionBoth sides next revision | ||
| toh:tp-link:tl-mr3420:deep.mmc.hack [2016/01/19 11:25] – [How to connect SD-card to SPI bus] some cosmetic fixes Dioptimizer | toh:tp-link:tl-mr3420:deep.mmc.hack [2018/07/02 07:56] – minor addings/changes deoptim | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Deep MMC Mod ====== | ||
| + | {{page> | ||
| + | <WRAP center important 70%> | ||
| + | This mod does not work on the older **// | ||
| + | **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/ | ||
| + | < | ||
| + | git rm target/ | ||
| + | git rm target/ | ||
| + | git rm target/ | ||
| + | </ | ||
| + | **Note:** Instead of path **patches-3.18**, | ||
| + | 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: | ||
| + | < | ||
| + | You can also do this in same way for other branches... | ||
| + | |||
| + | //(Where the long parameter is a commit of necessary revision ('' | ||
| + | </ | ||
| + | |||
| + | ===== How to connect SD-card to SPI bus ===== | ||
| + | ^ <color red> | ||
| + | | {{media: | ||
| + | ^ <color red>Two schems below for Second or Third way</ | ||
| + | | {{media: | ||
| + | | {{media: | ||
| + | |||
| + | 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: | ||
| + | |||
| + | How to build your own firmware is covered here: [[: | ||
| + | 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: | < | ||
| + | | Git patch\\ file format: | < | ||
| + | |||
| + | {{: | ||
| + | |||
| + | ===== 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: | ||
| + | \\ | ||
| + | \\ | ||
| + | ==== First way, using common CS0 ==== | ||
| + | {{: | ||
| + | |||
| + | == Main changes in the source code of kernel: == | ||
| + | <hidden Old patch for Openwrt (before LEDE project)>< | ||
| + | diff --git a/ | ||
| + | index 9323b31..2c51142 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -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.num_chipselect = 1; | ||
| + | + ath79_spi_data.num_chipselect = 2; | ||
| + | | ||
| + | | ||
| + | | ||
| + | diff --git a/ | ||
| + | index 5924ac5..5961732 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -9,6 +9,9 @@ | ||
| + | */ | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | +#include < | ||
| + | +#include < | ||
| + | |||
| + | # | ||
| + | |||
| + | @@ -17,6 +20,7 @@ | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | +#include " | ||
| + | # | ||
| + | # | ||
| + | |||
| + | @@ -32,6 +36,37 @@ | ||
| + | # | ||
| + | # | ||
| + | |||
| + | +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 = " | ||
| + | + .platform_data = & | ||
| + | + .controller_data = & | ||
| + | + } | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | | ||
| + | | ||
| + | @@ -82,6 +117,9 @@ static void __init tl_ap99_setup(void) | ||
| + | |||
| + | | ||
| + | |||
| + | + spi_register_board_info(ath79_spi_info, | ||
| + | + ARRAY_SIZE(ath79_spi_info)); | ||
| + | + | ||
| + | | ||
| + | ARRAY_SIZE(tl_mr3x20_gpio_keys), | ||
| + | tl_mr3x20_gpio_keys); | ||
| + | |||
| + | </ | ||
| + | <hidden Patch for Openwrt/ | ||
| + | diff --git a/ | ||
| + | index e53d97d..269e469 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -7,8 +7,10 @@ | ||
| + | */ | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | # | ||
| + | # | ||
| + | +#include < | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | @@ -16,6 +18,11 @@ | ||
| + | # | ||
| + | # | ||
| + | |||
| + | +static struct mmc_spi_platform_data ath79_mmc_data = { | ||
| + | + .detect_delay = 100, /* msecs */ | ||
| + | + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | { | ||
| + | | ||
| + | @@ -27,18 +34,25 @@ static struct spi_board_info ath79_spi_info[] = { | ||
| + | | ||
| + | | ||
| + | | ||
| + | - .modalias = " | ||
| + | + .modalias = " | ||
| + | + .platform_data = & | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | +static int device_spi_cs_gpios[2] = { | ||
| + | + -ENOENT, | ||
| + | + 2, /* GPIO Number */ | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | |||
| + | void __init ath79_register_m25p80(struct flash_platform_data *pdata) | ||
| + | { | ||
| + | | ||
| + | - ath79_spi_data.num_chipselect = 1; | ||
| + | + ath79_spi_data.num_chipselect = 2; | ||
| + | + ath79_spi_data.cs_gpios = device_spi_cs_gpios; | ||
| + | | ||
| + | - ath79_register_spi(& | ||
| + | + ath79_register_spi(& | ||
| + | } | ||
| + | |||
| + | | ||
| + | |||
| + | </ | ||
| + | <hidden Patch for Openwrt (4.14+, ath79 platform, dts files)>< | ||
| + | diff --git a/ | ||
| + | index 3846d811ac..d845e06951 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -48,7 +48,19 @@ | ||
| + | |||
| + | & | ||
| + | | ||
| + | - 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, | ||
| + | + * 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>, <& | ||
| + | |||
| + | | ||
| + | | ||
| + | @@ -80,6 +92,13 @@ | ||
| + | }; | ||
| + | }; | ||
| + | }; | ||
| + | + | ||
| + | + sdcard@0 { | ||
| + | + compatible = " | ||
| + | + reg = <1>; | ||
| + | + spi-max-frequency = < | ||
| + | + voltage-ranges = <3200 3400>; | ||
| + | + }; | ||
| + | }; | ||
| + | |||
| + | & | ||
| + | |||
| + | </ | ||
| + | \\ | ||
| + | \\ | ||
| + | ==== 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)>< | ||
| + | diff --git a/ | ||
| + | index e5831d4..80760d5 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -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.num_chipselect = 1; | ||
| + | + ath79_spi_data.num_chipselect = 2; | ||
| + | | ||
| + | | ||
| + | | ||
| + | diff --git a/ | ||
| + | index 5924ac5..4d4ac42 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -9,6 +9,9 @@ | ||
| + | */ | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | +#include < | ||
| + | +#include < | ||
| + | |||
| + | # | ||
| + | |||
| + | @@ -17,11 +20,13 @@ | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | +#include " | ||
| + | # | ||
| + | # | ||
| + | |||
| + | # | ||
| + | # | ||
| + | +#define TL_MR3X20_GPIO_CS1_MMC 7 | ||
| + | # | ||
| + | |||
| + | # | ||
| + | @@ -32,6 +37,28 @@ | ||
| + | # | ||
| + | # | ||
| + | |||
| + | +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 = " | ||
| + | + .platform_data = & | ||
| + | + .controller_data = & | ||
| + | + } | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | | ||
| + | | ||
| + | @@ -82,6 +109,9 @@ static void __init tl_ap99_setup(void) | ||
| + | |||
| + | | ||
| + | |||
| + | + spi_register_board_info(ath79_spi_info, | ||
| + | + ARRAY_SIZE(ath79_spi_info)); | ||
| + | + | ||
| + | | ||
| + | ARRAY_SIZE(tl_mr3x20_gpio_keys), | ||
| + | tl_mr3x20_gpio_keys); | ||
| + | |||
| + | </ | ||
| + | <hidden Patch for Openwrt (4.14+, ath79 platform, dts files)>< | ||
| + | diff --git a/ | ||
| + | index 3846d811ac..58399eb4de 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -48,7 +48,12 @@ | ||
| + | |||
| + | & | ||
| + | | ||
| + | - 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>, <& | ||
| + | |||
| + | | ||
| + | | ||
| + | @@ -80,6 +85,13 @@ | ||
| + | }; | ||
| + | }; | ||
| + | }; | ||
| + | + | ||
| + | + sdcard@0 { | ||
| + | + compatible = " | ||
| + | + reg = <1>; | ||
| + | + spi-max-frequency = < | ||
| + | + voltage-ranges = <3200 3400>; | ||
| + | + }; | ||
| + | }; | ||
| + | |||
| + | & | ||
| + | |||
| + | </ | ||
| + | \\ | ||
| + | \\ | ||
| + | ==== Third way, using Internal CS1 ==== | ||
| + | |||
| + | ^ Internal CS ^ AR71XX | ||
| + | | CS1 | usualy LED or BUTTON (GPIO0) || UART In (GPIO9) | ||
| + | | 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 [[# | ||
| + | |||
| + | On platforms with AR724X SoC: If you want to use the internal CS1 - you need to [[# | ||
| + | |||
| + | On platforms with AR933X SoC: If you want to use the internal CS1 - you need to [[# | ||
| + | |||
| + | On platforms with AR934X SoC: If you want to use the internal CS1 - you need to [[# | ||
| + | |||
| + | == Main changes in the source code of kernel: == | ||
| + | <hidden Old patch for Openwrt (before LEDE project)>< | ||
| + | diff --git a/ | ||
| + | index e5831d4..80760d5 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -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.num_chipselect = 1; | ||
| + | + ath79_spi_data.num_chipselect = 2; | ||
| + | | ||
| + | | ||
| + | | ||
| + | diff --git a/ | ||
| + | index 5924ac5..1c6428f 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -9,19 +9,26 @@ | ||
| + | */ | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | +#include < | ||
| + | +#include < | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | |||
| + | +#include " | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | +#include " | ||
| + | # | ||
| + | # | ||
| + | |||
| + | # | ||
| + | # | ||
| + | +#define TL_MR3X20_GPIO_CS1_MMC 7 | ||
| + | # | ||
| + | |||
| + | # | ||
| + | @@ -32,6 +39,28 @@ | ||
| + | # | ||
| + | # | ||
| + | |||
| + | +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 = " | ||
| + | + .platform_data = & | ||
| + | + .controller_data = & | ||
| + | + } | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | | ||
| + | | ||
| + | @@ -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); | ||
| + | + | ||
| + | | ||
| + | |||
| + | + spi_register_board_info(ath79_spi_info, | ||
| + | + ARRAY_SIZE(ath79_spi_info)); | ||
| + | + | ||
| + | | ||
| + | ARRAY_SIZE(tl_mr3x20_gpio_keys), | ||
| + | tl_mr3x20_gpio_keys); | ||
| + | |||
| + | </ | ||
| + | <hidden Patch for Openwrt (4.14+, ath79 platform, dts files)>< | ||
| + | diff --git a/ | ||
| + | index 3846d811ac..ea915872dc 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -48,7 +48,10 @@ | ||
| + | |||
| + | & | ||
| + | | ||
| + | - num-cs = <1>; | ||
| + | + pinctrl-names = " | ||
| + | + pinctrl-0 = <& | ||
| + | + num-cs = <2>; | ||
| + | + cs-gpios = <0>, <0>; | ||
| + | |||
| + | | ||
| + | | ||
| + | @@ -80,6 +83,30 @@ | ||
| + | }; | ||
| + | }; | ||
| + | }; | ||
| + | + | ||
| + | + sdcard@0 { | ||
| + | + compatible = " | ||
| + | + reg = <1>; | ||
| + | + spi-max-frequency = < | ||
| + | + voltage-ranges = <3200 3400>; | ||
| + | + }; | ||
| + | +}; | ||
| + | + | ||
| + | +& | ||
| + | + enable_cs1_bit: | ||
| + | + pinctrl-single, | ||
| + | + /* | ||
| + | + * 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; | ||
| + | + * < | ||
| + | + */ | ||
| + | + 0x0 0x2000 0x2000 | ||
| + | + >; | ||
| + | + }; | ||
| + | }; | ||
| + | |||
| + | & | ||
| + | |||
| + | </ | ||
| + | \\ | ||
| + | == 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); | ||
| + | </ | ||
| + | </ | ||
| + | \\ | ||
| + | == 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); | ||
| + | </ | ||
| + | </ | ||
| + | <hidden Instruction for Openwrt (4.14+, ath79 platform, dts files)> | ||
| + | <code c> | ||
| + | ... | ||
| + | ... | ||
| + | /* Add this two lines to spi enum */ | ||
| + | pinctrl-names = " | ||
| + | pinctrl-0 = <& | ||
| + | ... | ||
| + | ... | ||
| + | &pinmux { | ||
| + | enable_cs1_bit: | ||
| + | pinctrl-single, | ||
| + | /* | ||
| + | * 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; | ||
| + | * < | ||
| + | */ | ||
| + | 0x0 0x2000 0x2000 | ||
| + | >; | ||
| + | }; | ||
| + | }; | ||
| + | </ | ||
| + | </ | ||
| + | **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); | ||
| + | </ | ||
| + | </ | ||
| + | \\ | ||
| + | == 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, | ||
| + | </ | ||
| + | </ | ||
| + | <hidden Instruction for Openwrt (4.14+, ath79 platform, dts files)> | ||
| + | <code c> | ||
| + | ... | ||
| + | ... | ||
| + | /* Add this two lines to spi enum */ | ||
| + | pinctrl-names = " | ||
| + | pinctrl-0 = <& | ||
| + | ... | ||
| + | ... | ||
| + | &pinmux { | ||
| + | gpio11_to_cs1_bit: | ||
| + | pinctrl-single, | ||
| + | /* | ||
| + | * 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; | ||
| + | * < | ||
| + | */ | ||
| + | /* | ||
| + | * 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 | ||
| + | >; | ||
| + | }; | ||
| + | }; | ||
| + | </ | ||
| + | </ | ||
| + | \\ | ||
| + | \\ | ||
| + | ==== How to implement the Hotplug of SD-card ==== | ||
| + | | {{media: | ||
| + | | {{media: | ||
| + | |||
| + | Total we use two unused GPIOs: **GPIO7-> | ||
| + | Create a new additional button on this example: | ||
| + | <hidden Old patch for Openwrt (before LEDE project)>< | ||
| + | diff --git a/ | ||
| + | index e5831d4..80760d5 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -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.num_chipselect = 1; | ||
| + | + ath79_spi_data.num_chipselect = 2; | ||
| + | | ||
| + | | ||
| + | | ||
| + | diff --git a/ | ||
| + | index 5924ac5..9990d05 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -9,6 +9,9 @@ | ||
| + | */ | ||
| + | |||
| + | # | ||
| + | +#include < | ||
| + | +#include < | ||
| + | +#include < | ||
| + | |||
| + | # | ||
| + | |||
| + | @@ -17,21 +20,46 @@ | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | +#include " | ||
| + | # | ||
| + | # | ||
| + | |||
| + | # | ||
| + | # | ||
| + | +#define TL_MR3X20_GPIO_CS1_MMC 7 | ||
| + | # | ||
| + | |||
| + | # | ||
| + | # | ||
| + | +#define TL_MR3X20_GPIO_BTN_MMC 18 | ||
| + | |||
| + | # | ||
| + | |||
| + | # | ||
| + | # | ||
| + | |||
| + | +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 = " | ||
| + | + .platform_data = & | ||
| + | + .controller_data = & | ||
| + | + } | ||
| + | +}; | ||
| + | + | ||
| + | | ||
| + | | ||
| + | | ||
| + | @@ -72,6 +100,13 @@ static struct gpio_keys_button tl_mr3x20_gpio_keys[] __initdata = { | ||
| + | | ||
| + | | ||
| + | | ||
| + | + }, { | ||
| + | + .desc = " | ||
| + | + .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) | ||
| + | |||
| + | | ||
| + | |||
| + | + spi_register_board_info(ath79_spi_info, | ||
| + | + ARRAY_SIZE(ath79_spi_info)); | ||
| + | + | ||
| + | + gpio_direction_input(TL_MR3X20_GPIO_BTN_MMC); | ||
| + | + | ||
| + | | ||
| + | ARRAY_SIZE(tl_mr3x20_gpio_keys), | ||
| + | tl_mr3x20_gpio_keys); | ||
| + | |||
| + | </ | ||
| + | <hidden Patch for Openwrt (4.14+, ath79 platform, dts files)>< | ||
| + | diff --git a/ | ||
| + | index 3846d811ac..d99bafcb2b 100644 | ||
| + | --- a/ | ||
| + | +++ b/ | ||
| + | @@ -22,13 +22,18 @@ | ||
| + | | ||
| + | | ||
| + | }; | ||
| + | - | ||
| + | qss { | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | }; | ||
| + | + mmc { | ||
| + | + label = " | ||
| + | + linux, | ||
| + | + gpios = <& | ||
| + | + debounce-interval = <60>; | ||
| + | + }; | ||
| + | }; | ||
| + | |||
| + | | ||
| + | @@ -48,7 +53,12 @@ | ||
| + | |||
| + | & | ||
| + | | ||
| + | - 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>, <& | ||
| + | |||
| + | | ||
| + | | ||
| + | @@ -80,6 +90,30 @@ | ||
| + | }; | ||
| + | }; | ||
| + | }; | ||
| + | + | ||
| + | + sdcard@0 { | ||
| + | + compatible = " | ||
| + | + 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' | ||
| + | + * SD Card. | ||
| + | + */ | ||
| + | + //gpios = <& | ||
| + | + /* | ||
| + | + * By default, Card Detect use " | ||
| + | + * Using the " | ||
| + | + * CD line is active high, i.e. it is high, when a | ||
| + | + * card is inserted. | ||
| + | + * (uncomment line below to enable this option) | ||
| + | + */ | ||
| + | + // | ||
| + | + spi-max-frequency = < | ||
| + | + voltage-ranges = <3200 3400>; | ||
| + | + }; | ||
| + | }; | ||
| + | |||
| + | & | ||
| + | |||
| + | </ | ||
| + | // We could use GPIO to IRQ event as card detection (implemented in '' | ||
| + | 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 **'' | ||
| + | Next, you need to [[docs: | ||
| + | <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=' | ||
| + | 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=' | ||
| + | uci commit system | ||
| + | </ | ||
| + | |||
| + | **Note:** Action pressed/ | ||
| + | |||
| + | == Log of hotplug process: == | ||
| + | < | ||
| + | ... | ||
| + | [ 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] | ||
| + | [ 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] | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | ==== Modules installation ==== | ||
| + | === First way, build it in kernel (Recommended) === | ||
| + | | {{: | ||
| + | |||
| + | |||
| + | == Integrating modules in kernel: == | ||
| + | When we build own firmware we use standard menu '' | ||
| + | In this kernel menu, select the **asterisks** following items: | ||
| + | < | ||
| + | (Use Arrows UP and DOWN to find and select) | ||
| + | Device Drivers ---> | ||
| + | <*> MMC/SD/SDIO card support ---- (Find this item and press SPACE twice from the <M> to turn the <*> and then press ENTER) | ||
| + | ├< | ||
| + | └< | ||
| + | (Press ESC twice to go to the previous menu) | ||
| + | File systems ---> | ||
| + | <*> 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: '' | ||
| + | |||
| + | |||
| + | === Second way, using external modules === | ||
| + | | {{: | ||
| + | |||
| + | ** Update: ** The problem remained in **r37142** firmware revision.\\ | ||
| + | For [[docs: | ||
| + | |||
| + | |||
| + | ==== Testing ==== | ||
| + | == (AR71xx) Speed testing spi0.1: == | ||
| + | ~ the same as AR724x tests | ||
| + | |||
| + | == (AR724x) Speed testing spi0.1: == | ||
| + | Read/write speed by using utility **coreutils-dd**: | ||
| + | < | ||
| + | root@OpenWrt: | ||
| + | 14+0 records in | ||
| + | 14+0 records out | ||
| + | 14680064 bytes (15 MB) copied, 20.9663 s, 700 kB/s | ||
| + | root@OpenWrt: | ||
| + | 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: | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | root@OpenWrt: | ||
| + | </ | ||
| + | |||
| + | == CPU load during read/write process: == | ||
| + | < | ||
| + | root@OpenWrt: | ||
| + | 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 | ||
| + | | ||
| + | | ||
| + | 559 2 root | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | **Conclusion: | ||
| + | |||
| + | == (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 ''&'' | ||
| + | |||
| + | 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 | ||
| + | | Idle | ||
| + | | Read data | ~18mA | | ||
| + | | Write data | ||
| + | |||
| + | ==== Logs ==== | ||
| + | == Log with loading and initializing SD-card: == | ||
| + | < | ||
| + | ... | ||
| + | [ 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 " | ||
| + | [ 0.760000] 0x000000000000-0x000000020000 : " | ||
| + | [ 0.770000] 0x000000020000-0x00000013de00 : " | ||
| + | [ 0.770000] mtd: partition " | ||
| + | [ 0.790000] 0x00000013de00-0x0000003f0000 : " | ||
| + | [ 0.790000] mtd: partition " | ||
| + | [ 0.810000] mtd: partition " | ||
| + | [ 0.810000] mtd: partition " | ||
| + | [ 0.820000] 0x000000370000-0x0000003f0000 : " | ||
| + | [ 0.830000] 0x0000003f0000-0x000000400000 : " | ||
| + | [ 0.840000] 0x000000020000-0x0000003f0000 : " | ||
| + | [ 0.860000] libphy: ag71xx_mdio: | ||
| + | [ 0.860000] eth0: Atheros AG71xx at 0xba000000, irq 5, mode:GMII | ||
| + | [ 1.420000] eth0: Found an AR7240/ | ||
| + | [ 2.450000] eth1: Atheros AG71xx at 0xb9000000, irq 4, mode:MII | ||
| + | [ 3.000000] ag71xx ag71xx.0 eth1: connected to PHY at ag71xx-mdio.1: | ||
| + | [ 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] | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | == Error type in the case that system has NOT detected the SD-card: == | ||
| + | < | ||
| + | ... | ||
| + | [ 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 | ||
| + | ... | ||
| + | [ | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | == After detecting the SD-card we can find partitions: == | ||
| + | < | ||
| + | root@OpenWrt: | ||
| + | / | ||
| + | root@OpenWrt: | ||
| + | </ | ||
| + | |||
| + | == Debug info: == | ||
| + | < | ||
| + | root@OpenWrt: | ||
| + | clock: | ||
| + | vdd: 20 (3.2 ~ 3.3 V) | ||
| + | bus mode: 2 (push-pull) | ||
| + | chip select: | ||
| + | power mode: 2 (on) | ||
| + | bus width: | ||
| + | timing spec: 0 (legacy) | ||
| + | signal voltage: 1 (3.30 V) | ||
| + | root@OpenWrt: | ||
| + | </ | ||
| + | |||
| + | ===== Forum discussion ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | Porting this mod on LEDE Project:\\ | ||
| + | [[https:// | ||