diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/intel_scu_ipc.c | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index b6a03447ea63..a0dc41e27733 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c | |||
@@ -151,7 +151,7 @@ static inline u8 ipc_data_readb(u32 offset) /* Read ipc byte data */ | |||
151 | return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset); | 151 | return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset); |
152 | } | 152 | } |
153 | 153 | ||
154 | static inline u8 ipc_data_readl(u32 offset) /* Read ipc u32 data */ | 154 | static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */ |
155 | { | 155 | { |
156 | return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); | 156 | return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); |
157 | } | 157 | } |
@@ -181,18 +181,19 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | |||
181 | int nc; | 181 | int nc; |
182 | u32 offset = 0; | 182 | u32 offset = 0; |
183 | u32 err = 0; | 183 | u32 err = 0; |
184 | u8 cbuf[IPC_WWBUF_SIZE] = { '\0' }; | 184 | u8 cbuf[IPC_WWBUF_SIZE] = { }; |
185 | u32 *wbuf = (u32 *)&cbuf; | 185 | u32 *wbuf = (u32 *)&cbuf; |
186 | 186 | ||
187 | mutex_lock(&ipclock); | 187 | mutex_lock(&ipclock); |
188 | |||
188 | if (ipcdev.pdev == NULL) { | 189 | if (ipcdev.pdev == NULL) { |
189 | mutex_unlock(&ipclock); | 190 | mutex_unlock(&ipclock); |
190 | return -ENODEV; | 191 | return -ENODEV; |
191 | } | 192 | } |
192 | 193 | ||
193 | if (platform == 1) { | 194 | if (platform == PLATFORM_LANGWELL) { |
194 | /* Entry is 4 bytes for read/write, 5 bytes for read modify */ | 195 | /* Entry is 4 bytes for read/write, 5 bytes for read modify */ |
195 | for (nc = 0; nc < count; nc++) { | 196 | for (nc = 0; nc < count; nc++, offset += 3) { |
196 | cbuf[offset] = addr[nc]; | 197 | cbuf[offset] = addr[nc]; |
197 | cbuf[offset + 1] = addr[nc] >> 8; | 198 | cbuf[offset + 1] = addr[nc] >> 8; |
198 | if (id != IPC_CMD_PCNTRL_R) | 199 | if (id != IPC_CMD_PCNTRL_R) |
@@ -201,33 +202,44 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | |||
201 | cbuf[offset + 3] = data[nc + 1]; | 202 | cbuf[offset + 3] = data[nc + 1]; |
202 | offset += 1; | 203 | offset += 1; |
203 | } | 204 | } |
204 | offset += 3; | ||
205 | } | 205 | } |
206 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) | 206 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) |
207 | ipc_data_writel(wbuf[nc], offset); /* Write wbuff */ | 207 | ipc_data_writel(wbuf[nc], offset); /* Write wbuff */ |
208 | 208 | ||
209 | if (id != IPC_CMD_PCNTRL_M) | ||
210 | ipc_command((count*4) << 16 | id << 12 | 0 << 8 | op); | ||
211 | else | ||
212 | ipc_command((count*5) << 16 | id << 12 | 0 << 8 | op); | ||
213 | |||
209 | } else { | 214 | } else { |
210 | for (nc = 0, offset = 0; nc < count; nc++, offset += 2) | 215 | for (nc = 0; nc < count; nc++, offset += 2) { |
211 | ipc_data_writel(addr[nc], offset); /* Write addresses */ | 216 | cbuf[offset] = addr[nc]; |
212 | if (id != IPC_CMD_PCNTRL_R) { | 217 | cbuf[offset + 1] = addr[nc] >> 8; |
213 | for (nc = 0; nc < count; nc++, offset++) | ||
214 | ipc_data_writel(data[nc], offset); /* Write data */ | ||
215 | if (id == IPC_CMD_PCNTRL_M) | ||
216 | ipc_data_writel(data[nc + 1], offset); /* Mask value*/ | ||
217 | } | 218 | } |
218 | } | ||
219 | 219 | ||
220 | if (id != IPC_CMD_PCNTRL_M) | 220 | if (id == IPC_CMD_PCNTRL_R) { |
221 | ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op); | 221 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) |
222 | else | 222 | ipc_data_writel(wbuf[nc], offset); |
223 | ipc_command((count * 4) << 16 | id << 12 | 0 << 8 | op); | 223 | ipc_command((count*2) << 16 | id << 12 | 0 << 8 | op); |
224 | } else if (id == IPC_CMD_PCNTRL_W) { | ||
225 | for (nc = 0; nc < count; nc++, offset += 1) | ||
226 | cbuf[offset] = data[nc]; | ||
227 | for (nc = 0, offset = 0; nc < count; nc++, offset += 4) | ||
228 | ipc_data_writel(wbuf[nc], offset); | ||
229 | ipc_command((count*3) << 16 | id << 12 | 0 << 8 | op); | ||
230 | } else if (id == IPC_CMD_PCNTRL_M) { | ||
231 | cbuf[offset] = data[0]; | ||
232 | cbuf[offset + 1] = data[1]; | ||
233 | ipc_data_writel(wbuf[0], 0); /* Write wbuff */ | ||
234 | ipc_command(4 << 16 | id << 12 | 0 << 8 | op); | ||
235 | } | ||
236 | } | ||
224 | 237 | ||
225 | err = busy_loop(); | 238 | err = busy_loop(); |
226 | |||
227 | if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ | 239 | if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ |
228 | /* Workaround: values are read as 0 without memcpy_fromio */ | 240 | /* Workaround: values are read as 0 without memcpy_fromio */ |
229 | memcpy_fromio(cbuf, ipcdev.ipc_base + IPC_READ_BUFFER, 16); | 241 | memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); |
230 | if (platform == 1) { | 242 | if (platform == PLATFORM_LANGWELL) { |
231 | for (nc = 0, offset = 2; nc < count; nc++, offset += 3) | 243 | for (nc = 0, offset = 2; nc < count; nc++, offset += 3) |
232 | data[nc] = ipc_data_readb(offset); | 244 | data[nc] = ipc_data_readb(offset); |
233 | } else { | 245 | } else { |
@@ -800,6 +812,7 @@ static void ipc_remove(struct pci_dev *pdev) | |||
800 | 812 | ||
801 | static const struct pci_device_id pci_ids[] = { | 813 | static const struct pci_device_id pci_ids[] = { |
802 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, | 814 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, |
815 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, | ||
803 | { 0,} | 816 | { 0,} |
804 | }; | 817 | }; |
805 | MODULE_DEVICE_TABLE(pci, pci_ids); | 818 | MODULE_DEVICE_TABLE(pci, pci_ids); |