GNU Linux-libre 4.19.264-gnu1
[releases.git] / arch / powerpc / sysdev / micropatch.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /* Microcode patches for the CPM as supplied by Motorola.
4  * This is the one for IIC/SPI.  There is a newer one that
5  * also relocates SMC2, but this would require additional changes
6  * to uart.c, so I am holding off on that for a moment.
7  */
8 #include <linux/init.h>
9 #include <linux/errno.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/param.h>
13 #include <linux/string.h>
14 #include <linux/mm.h>
15 #include <linux/interrupt.h>
16 #include <asm/irq.h>
17 #include <asm/page.h>
18 #include <asm/pgtable.h>
19 #include <asm/8xx_immap.h>
20 #include <asm/cpm.h>
21 #include <asm/cpm1.h>
22
23 /*
24  * I2C/SPI relocation patch arrays.
25  */
26
27 #ifdef CONFIG_I2C_SPI_UCODE_PATCH
28
29 /*(DEBLOBBED)*/
30
31 /*(DEBLOBBED)*/
32 #endif
33
34 /*
35  * I2C/SPI/SMC1 relocation patch arrays.
36  */
37
38 #ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
39
40 /*(DEBLOBBED)*/
41
42 /*(DEBLOBBED)*/
43
44 /*(DEBLOBBED)*/
45 #endif
46
47 /*
48  *  USB SOF patch arrays.
49  */
50
51 #ifdef CONFIG_USB_SOF_UCODE_PATCH
52
53 /*(DEBLOBBED)*/
54
55 /*(DEBLOBBED)*/
56 #endif
57
58 void __init cpm_load_patch(cpm8xx_t *cp)
59 {
60         volatile uint           *dp;            /* Dual-ported RAM. */
61         volatile cpm8xx_t       *commproc;
62 #if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
63     defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
64         volatile iic_t          *iip;
65         volatile struct spi_pram *spp;
66 #ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
67         volatile smc_uart_t     *smp;
68 #endif
69 #endif
70         int     i;
71
72         commproc = cp;
73
74 #ifdef CONFIG_USB_SOF_UCODE_PATCH
75         commproc->cp_rccr = 0;
76
77         dp = (uint *)(commproc->cp_dpmem);
78         for (i=0; i<(sizeof(patch_2000)/4); i++)
79                 *dp++ = patch_2000[i];
80
81         dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
82         for (i=0; i<(sizeof(patch_2f00)/4); i++)
83                 *dp++ = patch_2f00[i];
84
85         commproc->cp_rccr = 0x0009;
86
87         printk("USB SOF microcode patch installed\n");
88 #endif /* CONFIG_USB_SOF_UCODE_PATCH */
89
90 #if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
91     defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
92
93         commproc->cp_rccr = 0;
94
95         dp = (uint *)(commproc->cp_dpmem);
96         for (i=0; i<(sizeof(patch_2000)/4); i++)
97                 *dp++ = patch_2000[i];
98
99         dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
100         for (i=0; i<(sizeof(patch_2f00)/4); i++)
101                 *dp++ = patch_2f00[i];
102
103         iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC];
104 # define RPBASE 0x0500
105         iip->iic_rpbase = RPBASE;
106
107         /* Put SPI above the IIC, also 32-byte aligned.
108         */
109         i = (RPBASE + sizeof(iic_t) + 31) & ~31;
110         spp = (struct spi_pram *)&commproc->cp_dparam[PROFF_SPI];
111         spp->rpbase = i;
112
113 # if defined(CONFIG_I2C_SPI_UCODE_PATCH)
114         commproc->cp_cpmcr1 = 0x802a;
115         commproc->cp_cpmcr2 = 0x8028;
116         commproc->cp_cpmcr3 = 0x802e;
117         commproc->cp_cpmcr4 = 0x802c;
118         commproc->cp_rccr = 1;
119
120         printk("I2C/SPI microcode patch installed.\n");
121 # endif /* CONFIG_I2C_SPI_UCODE_PATCH */
122
123 # if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
124
125         dp = (uint *)&(commproc->cp_dpmem[0x0e00]);
126         for (i=0; i<(sizeof(patch_2e00)/4); i++)
127                 *dp++ = patch_2e00[i];
128
129         commproc->cp_cpmcr1 = 0x8080;
130         commproc->cp_cpmcr2 = 0x808a;
131         commproc->cp_cpmcr3 = 0x8028;
132         commproc->cp_cpmcr4 = 0x802a;
133         commproc->cp_rccr = 3;
134
135         smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1];
136         smp->smc_rpbase = 0x1FC0;
137
138         printk("I2C/SPI/SMC1 microcode patch installed.\n");
139 # endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */
140
141 #endif /* some variation of the I2C/SPI patch was selected */
142 }
143
144 /*
145  *  Take this entire routine out, since no one calls it and its
146  * logic is suspect.
147  */
148
149 #if 0
150 void
151 verify_patch(volatile immap_t *immr)
152 {
153         volatile uint           *dp;
154         volatile cpm8xx_t       *commproc;
155         int i;
156
157         commproc = (cpm8xx_t *)&immr->im_cpm;
158
159         printk("cp_rccr %x\n", commproc->cp_rccr);
160         commproc->cp_rccr = 0;
161
162         dp = (uint *)(commproc->cp_dpmem);
163         for (i=0; i<(sizeof(patch_2000)/4); i++)
164                 if (*dp++ != patch_2000[i]) {
165                         printk("patch_2000 bad at %d\n", i);
166                         dp--;
167                         printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]);
168                         break;
169                 }
170
171         dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
172         for (i=0; i<(sizeof(patch_2f00)/4); i++)
173                 if (*dp++ != patch_2f00[i]) {
174                         printk("patch_2f00 bad at %d\n", i);
175                         dp--;
176                         printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]);
177                         break;
178                 }
179
180         commproc->cp_rccr = 0x0009;
181 }
182 #endif