Skip to content

Commit 989489e

Browse files
committed
arc: axs10x - bump Linux kernel & headers to 4.2 release
Linux kernel 4.2 was finally released, so bumping from 4.2-rc5 to final release. Updating Linux headers to 4.2 branch since they are introduced in Buildroot as well already. Also adding 1 back-ported patch that makes SD/MMC cards usable on AXS boards. This patch will be a part of 4.3 (already in linux-next) and hopefully will make its way in 4.2.1. Once that patch appears in 4.2.x it must be removed from here. Cc: Peter Korsgaard <[email protected]> Cc: Thomas Petazzoni <[email protected]> Signed-off-by: Alexey Brodkin <[email protected]>
1 parent 4c48f4b commit 989489e

File tree

3 files changed

+206
-6
lines changed

3 files changed

+206
-6
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
From 969872e334937bd0956887a925f20f7a446af5f6 Mon Sep 17 00:00:00 2001
2+
From: Alexey Brodkin <[email protected]>
3+
Date: Thu, 25 Jun 2015 11:25:07 +0300
4+
Subject: [PATCH] mmc: dw_mmc: handle data blocks > than 4kB if IDMAC is used
5+
6+
As per DW MobileStorage databook "each descriptor can transfer up to 4kB
7+
of data in chained mode", moreover buffer size that is put in "des1" is
8+
limited to 13 bits, i.e. for example on attempt to
9+
IDMAC_SET_BUFFER1_SIZE(desc, 8192) size value that's effectively written
10+
will be 0.
11+
12+
On the platform with 8kB PAGE_SIZE I see dw_mmc gets data blocks in
13+
SG-list of 8kB size and that leads to unpredictable behavior of the
14+
SD/MMC controller.
15+
16+
In particular on write to FAT partition of SD-card the controller will
17+
stuck in the middle of DMA transaction.
18+
19+
Solution to the problem is simple - we need to pass large (> 4kB) data
20+
buffers to the controller via multiple descriptors. And that's what
21+
that change does.
22+
23+
What's interesting I did try original driver on same platform but
24+
configured with 4kB PAGE_SIZE and may confirm that data blocks passed
25+
in SG-list to dw_mmc never exeed 4kB limit - that explains why nobody
26+
ever faced a problem I did.
27+
28+
Signed-off-by: Alexey Brodkin <[email protected]>
29+
Cc: Seungwon Jeon <[email protected]>
30+
Cc: Jaehoon Chung <[email protected]>
31+
Cc: Ulf Hansson <[email protected]>
32+
33+
34+
Signed-off-by: Jaehoon Chung <[email protected]>
35+
---
36+
drivers/mmc/host/dw_mmc.c | 109 ++++++++++++++++++++++++++++++----------------
37+
1 file changed, 71 insertions(+), 38 deletions(-)
38+
39+
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
40+
index 40e9d8e..e41fb74 100644
41+
--- a/drivers/mmc/host/dw_mmc.c
42+
+++ b/drivers/mmc/host/dw_mmc.c
43+
@@ -99,6 +99,9 @@ struct idmac_desc {
44+
45+
__le32 des3; /* buffer 2 physical address */
46+
};
47+
+
48+
+/* Each descriptor can transfer up to 4KB of data in chained mode */
49+
+#define DW_MCI_DESC_DATA_LENGTH 0x1000
50+
#endif /* CONFIG_MMC_DW_IDMAC */
51+
52+
static bool dw_mci_reset(struct dw_mci *host);
53+
@@ -462,66 +465,96 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host)
54+
static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
55+
unsigned int sg_len)
56+
{
57+
+ unsigned int desc_len;
58+
int i;
59+
if (host->dma_64bit_address == 1) {
60+
- struct idmac_desc_64addr *desc = host->sg_cpu;
61+
+ struct idmac_desc_64addr *desc_first, *desc_last, *desc;
62+
+
63+
+ desc_first = desc_last = desc = host->sg_cpu;
64+
65+
- for (i = 0; i < sg_len; i++, desc++) {
66+
+ for (i = 0; i < sg_len; i++) {
67+
unsigned int length = sg_dma_len(&data->sg[i]);
68+
u64 mem_addr = sg_dma_address(&data->sg[i]);
69+
70+
- /*
71+
- * Set the OWN bit and disable interrupts for this
72+
- * descriptor
73+
- */
74+
- desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
75+
- IDMAC_DES0_CH;
76+
- /* Buffer length */
77+
- IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length);
78+
-
79+
- /* Physical address to DMA to/from */
80+
- desc->des4 = mem_addr & 0xffffffff;
81+
- desc->des5 = mem_addr >> 32;
82+
+ for ( ; length ; desc++) {
83+
+ desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
84+
+ length : DW_MCI_DESC_DATA_LENGTH;
85+
+
86+
+ length -= desc_len;
87+
+
88+
+ /*
89+
+ * Set the OWN bit and disable interrupts
90+
+ * for this descriptor
91+
+ */
92+
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
93+
+ IDMAC_DES0_CH;
94+
+
95+
+ /* Buffer length */
96+
+ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len);
97+
+
98+
+ /* Physical address to DMA to/from */
99+
+ desc->des4 = mem_addr & 0xffffffff;
100+
+ desc->des5 = mem_addr >> 32;
101+
+
102+
+ /* Update physical address for the next desc */
103+
+ mem_addr += desc_len;
104+
+
105+
+ /* Save pointer to the last descriptor */
106+
+ desc_last = desc;
107+
+ }
108+
}
109+
110+
/* Set first descriptor */
111+
- desc = host->sg_cpu;
112+
- desc->des0 |= IDMAC_DES0_FD;
113+
+ desc_first->des0 |= IDMAC_DES0_FD;
114+
115+
/* Set last descriptor */
116+
- desc = host->sg_cpu + (i - 1) *
117+
- sizeof(struct idmac_desc_64addr);
118+
- desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
119+
- desc->des0 |= IDMAC_DES0_LD;
120+
+ desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
121+
+ desc_last->des0 |= IDMAC_DES0_LD;
122+
123+
} else {
124+
- struct idmac_desc *desc = host->sg_cpu;
125+
+ struct idmac_desc *desc_first, *desc_last, *desc;
126+
+
127+
+ desc_first = desc_last = desc = host->sg_cpu;
128+
129+
- for (i = 0; i < sg_len; i++, desc++) {
130+
+ for (i = 0; i < sg_len; i++) {
131+
unsigned int length = sg_dma_len(&data->sg[i]);
132+
u32 mem_addr = sg_dma_address(&data->sg[i]);
133+
134+
- /*
135+
- * Set the OWN bit and disable interrupts for this
136+
- * descriptor
137+
- */
138+
- desc->des0 = cpu_to_le32(IDMAC_DES0_OWN |
139+
- IDMAC_DES0_DIC | IDMAC_DES0_CH);
140+
- /* Buffer length */
141+
- IDMAC_SET_BUFFER1_SIZE(desc, length);
142+
+ for ( ; length ; desc++) {
143+
+ desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
144+
+ length : DW_MCI_DESC_DATA_LENGTH;
145+
+
146+
+ length -= desc_len;
147+
+
148+
+ /*
149+
+ * Set the OWN bit and disable interrupts
150+
+ * for this descriptor
151+
+ */
152+
+ desc->des0 = cpu_to_le32(IDMAC_DES0_OWN |
153+
+ IDMAC_DES0_DIC |
154+
+ IDMAC_DES0_CH);
155+
+
156+
+ /* Buffer length */
157+
+ IDMAC_SET_BUFFER1_SIZE(desc, desc_len);
158+
159+
- /* Physical address to DMA to/from */
160+
- desc->des2 = cpu_to_le32(mem_addr);
161+
+ /* Physical address to DMA to/from */
162+
+ desc->des2 = cpu_to_le32(mem_addr);
163+
+
164+
+ /* Update physical address for the next desc */
165+
+ mem_addr += desc_len;
166+
+
167+
+ /* Save pointer to the last descriptor */
168+
+ desc_last = desc;
169+
+ }
170+
}
171+
172+
/* Set first descriptor */
173+
- desc = host->sg_cpu;
174+
- desc->des0 |= cpu_to_le32(IDMAC_DES0_FD);
175+
+ desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD);
176+
177+
/* Set last descriptor */
178+
- desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
179+
- desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC));
180+
- desc->des0 |= cpu_to_le32(IDMAC_DES0_LD);
181+
+ desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH |
182+
+ IDMAC_DES0_DIC));
183+
+ desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD);
184+
}
185+
186+
wmb();
187+
@@ -2394,7 +2427,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
188+
#ifdef CONFIG_MMC_DW_IDMAC
189+
mmc->max_segs = host->ring_size;
190+
mmc->max_blk_size = 65536;
191+
- mmc->max_seg_size = 0x1000;
192+
+ mmc->max_seg_size = DW_MCI_DESC_DATA_LENGTH;
193+
mmc->max_req_size = mmc->max_seg_size * host->ring_size;
194+
mmc->max_blk_count = mmc->max_req_size / 512;
195+
#else
196+
--
197+
2.4.3
198+

configs/snps_axs101_defconfig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ BR2_ROOTFS_OVERLAY="board/synopsys/axs10x/fs-overlay"
1010

1111
# Headers
1212
BR2_KERNEL_HEADERS_VERSION=y
13-
BR2_DEFAULT_KERNEL_VERSION="4.1"
14-
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_1=y
13+
BR2_DEFAULT_KERNEL_VERSION="4.2"
14+
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_2=y
1515

1616
# Kernel
1717
BR2_LINUX_KERNEL=y
1818
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
19-
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2-rc5"
19+
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2"
20+
BR2_LINUX_KERNEL_PATCH="board/synopsys/axs10x/patches/linux"
2021
BR2_LINUX_KERNEL_DEFCONFIG="axs101"
2122

2223
# Bootloader

configs/snps_axs103_defconfig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ BR2_ROOTFS_OVERLAY="board/synopsys/axs10x/fs-overlay"
1111

1212
# Headers
1313
BR2_KERNEL_HEADERS_VERSION=y
14-
BR2_DEFAULT_KERNEL_VERSION="4.1"
15-
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_1=y
14+
BR2_DEFAULT_KERNEL_VERSION="4.2"
15+
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_2=y
1616

1717
# Kernel
1818
BR2_LINUX_KERNEL=y
1919
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
20-
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2-rc5"
20+
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.2"
21+
BR2_LINUX_KERNEL_PATCH="board/synopsys/axs10x/patches/linux"
2122
BR2_LINUX_KERNEL_DEFCONFIG="axs103_smp"
2223

2324
# Bootloader

0 commit comments

Comments
 (0)