]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.4.181/asoc-rt5677-spi-disable-16bit-spi-transfers.patch
Linux 4.9.181
[thirdparty/kernel/stable-queue.git] / releases / 4.4.181 / asoc-rt5677-spi-disable-16bit-spi-transfers.patch
1 From a46eb523220e242affb9a6bc9bb8efc05f4f7459 Mon Sep 17 00:00:00 2001
2 From: Curtis Malainey <cujomalainey@chromium.org>
3 Date: Fri, 3 May 2019 12:32:14 -0700
4 Subject: ASoC: RT5677-SPI: Disable 16Bit SPI Transfers
5
6 From: Curtis Malainey <cujomalainey@chromium.org>
7
8 commit a46eb523220e242affb9a6bc9bb8efc05f4f7459 upstream.
9
10 The current algorithm allows 3 types of transfers, 16bit, 32bit and
11 burst. According to Realtek, 16bit transfers have a special restriction
12 in that it is restricted to the memory region of
13 0x18020000 ~ 0x18021000. This region is the memory location of the I2C
14 registers. The current algorithm does not uphold this restriction and
15 therefore fails to complete writes.
16
17 Since this has been broken for some time it likely no one is using it.
18 Better to simply disable the 16 bit writes. This will allow users to
19 properly load firmware over SPI without data corruption.
20
21 Signed-off-by: Curtis Malainey <cujomalainey@chromium.org>
22 Reviewed-by: Ben Zhang <benzh@chromium.org>
23 Signed-off-by: Mark Brown <broonie@kernel.org>
24 Cc: stable@vger.kernel.org
25 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
26
27 ---
28 sound/soc/codecs/rt5677-spi.c | 35 ++++++++++++++++-------------------
29 1 file changed, 16 insertions(+), 19 deletions(-)
30
31 --- a/sound/soc/codecs/rt5677-spi.c
32 +++ b/sound/soc/codecs/rt5677-spi.c
33 @@ -60,13 +60,15 @@ static DEFINE_MUTEX(spi_mutex);
34 * RT5677_SPI_READ/WRITE_32: Transfer 4 bytes
35 * RT5677_SPI_READ/WRITE_BURST: Transfer any multiples of 8 bytes
36 *
37 - * For example, reading 260 bytes at 0x60030002 uses the following commands:
38 - * 0x60030002 RT5677_SPI_READ_16 2 bytes
39 + * Note:
40 + * 16 Bit writes and reads are restricted to the address range
41 + * 0x18020000 ~ 0x18021000
42 + *
43 + * For example, reading 256 bytes at 0x60030004 uses the following commands:
44 * 0x60030004 RT5677_SPI_READ_32 4 bytes
45 * 0x60030008 RT5677_SPI_READ_BURST 240 bytes
46 * 0x600300F8 RT5677_SPI_READ_BURST 8 bytes
47 * 0x60030100 RT5677_SPI_READ_32 4 bytes
48 - * 0x60030104 RT5677_SPI_READ_16 2 bytes
49 *
50 * Input:
51 * @read: true for read commands; false for write commands
52 @@ -81,15 +83,13 @@ static u8 rt5677_spi_select_cmd(bool rea
53 {
54 u8 cmd;
55
56 - if (align == 2 || align == 6 || remain == 2) {
57 - cmd = RT5677_SPI_READ_16;
58 - *len = 2;
59 - } else if (align == 4 || remain <= 6) {
60 + if (align == 4 || remain <= 4) {
61 cmd = RT5677_SPI_READ_32;
62 *len = 4;
63 } else {
64 cmd = RT5677_SPI_READ_BURST;
65 - *len = min_t(u32, remain & ~7, RT5677_SPI_BURST_LEN);
66 + *len = (((remain - 1) >> 3) + 1) << 3;
67 + *len = min_t(u32, *len, RT5677_SPI_BURST_LEN);
68 }
69 return read ? cmd : cmd + 1;
70 }
71 @@ -110,7 +110,7 @@ static void rt5677_spi_reverse(u8 *dst,
72 }
73 }
74
75 -/* Read DSP address space using SPI. addr and len have to be 2-byte aligned. */
76 +/* Read DSP address space using SPI. addr and len have to be 4-byte aligned. */
77 int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
78 {
79 u32 offset;
80 @@ -126,7 +126,7 @@ int rt5677_spi_read(u32 addr, void *rxbu
81 if (!g_spi)
82 return -ENODEV;
83
84 - if ((addr & 1) || (len & 1)) {
85 + if ((addr & 3) || (len & 3)) {
86 dev_err(&g_spi->dev, "Bad read align 0x%x(%zu)\n", addr, len);
87 return -EACCES;
88 }
89 @@ -161,13 +161,13 @@ int rt5677_spi_read(u32 addr, void *rxbu
90 }
91 EXPORT_SYMBOL_GPL(rt5677_spi_read);
92
93 -/* Write DSP address space using SPI. addr has to be 2-byte aligned.
94 - * If len is not 2-byte aligned, an extra byte of zero is written at the end
95 +/* Write DSP address space using SPI. addr has to be 4-byte aligned.
96 + * If len is not 4-byte aligned, then extra zeros are written at the end
97 * as padding.
98 */
99 int rt5677_spi_write(u32 addr, const void *txbuf, size_t len)
100 {
101 - u32 offset, len_with_pad = len;
102 + u32 offset;
103 int status = 0;
104 struct spi_transfer t;
105 struct spi_message m;
106 @@ -180,22 +180,19 @@ int rt5677_spi_write(u32 addr, const voi
107 if (!g_spi)
108 return -ENODEV;
109
110 - if (addr & 1) {
111 + if (addr & 3) {
112 dev_err(&g_spi->dev, "Bad write align 0x%x(%zu)\n", addr, len);
113 return -EACCES;
114 }
115
116 - if (len & 1)
117 - len_with_pad = len + 1;
118 -
119 memset(&t, 0, sizeof(t));
120 t.tx_buf = buf;
121 t.speed_hz = RT5677_SPI_FREQ;
122 spi_message_init_with_transfers(&m, &t, 1);
123
124 - for (offset = 0; offset < len_with_pad;) {
125 + for (offset = 0; offset < len;) {
126 spi_cmd = rt5677_spi_select_cmd(false, (addr + offset) & 7,
127 - len_with_pad - offset, &t.len);
128 + len - offset, &t.len);
129
130 /* Construct SPI message header */
131 buf[0] = spi_cmd;