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