Staging: sep: first pass after indent
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / sep / sep_ext_with_pci_driver.c
CommitLineData
cd1bb431
MA
1/*
2 *
3 * sep_ext_with_pci_driver.c - Security Processor Driver
4 * pci initialization functions
5 *
6 * Copyright(c) 2009 Intel Corporation. All rights reserved.
7 * Copyright(c) 2009 Discretix. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 * CONTACTS:
24 *
25 * Mark Allyn mark.a.allyn@intel.com
26 *
27 * CHANGES:
28 *
29 * 2009.06.26 Initial publish
30 *
31 */
32
33#include <linux/init.h>
34#include <linux/module.h>
35#include <linux/fs.h>
36#include <linux/cdev.h>
37#include <linux/kdev_t.h>
38#include <linux/semaphore.h>
39#include <linux/mm.h>
40#include <linux/poll.h>
41#include <linux/wait.h>
42#include <linux/ioctl.h>
43#include <linux/ioport.h>
44#include <linux/io.h>
45#include <linux/interrupt.h>
46#include <linux/pagemap.h>
47#include <linux/pci.h>
48#include <linux/firmware.h>
49#include <linux/sched.h>
50#include "sep_driver_hw_defs.h"
51#include "sep_driver_config.h"
52#include "sep_driver_api.h"
53#include "sep_driver_ext_api.h"
f5e3980f 54#include "sep_dev.h"
cd1bb431
MA
55
56#if SEP_DRIVER_ARM_DEBUG_MODE
57
58#define CRYS_SEP_ROM_length 0x4000
59
60#define CRYS_SEP_ROM_start_address 0x8000C000UL
61
62#define CRYS_SEP_ROM_start_address_offset 0xC000UL
63
64#define SEP_ROM_BANK_register 0x80008420UL
65
66#define SEP_ROM_BANK_register_offset 0x8420UL
67
68#define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0x82000000
69
70/* 2M size */
71/* #define SEP_RAR_IO_MEM_REGION_SIZE (1024*1024*2)
72
73static unsigned long CRYS_SEP_ROM[] = {
74 #include "SEP_ROM_image.h"
75};
76
77#else
78*/
79
80/*-------------
81 THOSE 2 definitions are specific to the board - must be
82 defined during integration
83---------------*/
84#define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0xFF0D0000
85
86/* 2M size */
87
d19cf32f 88#endif /* SEP_DRIVER_ARM_DEBUG_MODE */
cd1bb431
MA
89
90#define BASE_ADDRESS_FOR_SYSTEM 0xfffc0000
91#define SEP_RAR_IO_MEM_REGION_SIZE 0x40000
92
d19cf32f 93irqreturn_t sep_inthandler(int irq, void *dev_id);
cd1bb431 94
f5e3980f 95/* Keep this a single static object for now to keep the conversion easy */
cd1bb431 96
f5e3980f
AC
97static struct sep_device sep_instance;
98struct sep_device *sep_dev = &sep_instance;
cd1bb431
MA
99
100/* temporary */
101unsigned long jiffies_future;
102
103/*-----------------------------
104 private functions
105--------------------------------*/
106
107/*
108 function that is activated on the succesfull probe of the SEP device
109*/
d19cf32f 110static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
cd1bb431
MA
111
112static struct pci_device_id sep_pci_id_tbl[] = {
d19cf32f
AC
113 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
114 {0}
cd1bb431
MA
115};
116
117MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl);
118
cd1bb431
MA
119/* field for registering driver to PCI device */
120static struct pci_driver sep_pci_driver = {
121 .name = "sep_sec_driver",
122 .id_table = sep_pci_id_tbl,
123 .probe = sep_probe
124};
125
cd1bb431
MA
126/*
127 This functions locks the area of the resisnd and cache sep code
128*/
129void sep_lock_cache_resident_area(void)
130{
131 return;
132}
133
cd1bb431
MA
134/*
135 This functions copies the cache and resident from their source location into
136 destination memory, which is external to Linux VM and is given as
137 physical address
138*/
d19cf32f 139int sep_copy_cache_resident_to_area(unsigned long src_cache_addr, unsigned long cache_size_in_bytes, unsigned long src_resident_addr, unsigned long resident_size_in_bytes, unsigned long *dst_new_cache_addr_ptr, unsigned long *dst_new_resident_addr_ptr)
cd1bb431 140{
cd1bb431 141 unsigned long resident_addr;
cd1bb431 142 unsigned long cache_addr;
cd1bb431
MA
143 const struct firmware *fw;
144
145 char *cache_name = "cache.image.bin";
d19cf32f 146 char *res_name = "resident.image.bin";
cd1bb431
MA
147
148 /* error */
149 int error;
150
151 /*--------------------------------
152 CODE
153 -------------------------------------*/
154 error = 0;
155
d19cf32f
AC
156 edbg("SEP Driver:rar_virtual is %p\n", sep_dev->rar_virtual_address);
157 edbg("SEP Driver:rar_physical is %08lx\n", sep_dev->rar_physical_address);
cd1bb431 158
d19cf32f 159 sep_dev->rar_region_addr = (unsigned long) sep_dev->rar_virtual_address;
cd1bb431 160
f5e3980f
AC
161 sep_dev->cache_physical_address = sep_dev->rar_physical_address;
162 sep_dev->cache_virtual_address = sep_dev->rar_virtual_address;
cd1bb431
MA
163
164 /* load cache */
f5e3980f 165 error = request_firmware(&fw, cache_name, &sep_dev->sep_pci_dev_ptr->dev);
cd1bb431 166 if (error) {
d19cf32f 167 edbg("SEP Driver:cant request cache fw\n");
cd1bb431
MA
168 goto end_function;
169 }
170
d19cf32f
AC
171 edbg("SEP Driver:cache data loc is %p\n", (void *) fw->data);
172 edbg("SEP Driver:cache data size is %08Zx\n", fw->size);
cd1bb431 173
d19cf32f 174 memcpy((void *) sep_dev->cache_virtual_address, (void *) fw->data, fw->size);
cd1bb431 175
f5e3980f 176 sep_dev->cache_size = fw->size;
cd1bb431 177
d19cf32f 178 cache_addr = (unsigned long) sep_dev->cache_virtual_address;
cd1bb431
MA
179
180 release_firmware(fw);
181
d19cf32f
AC
182 sep_dev->resident_physical_address = sep_dev->cache_physical_address + sep_dev->cache_size;
183 sep_dev->resident_virtual_address = sep_dev->cache_virtual_address + sep_dev->cache_size;
cd1bb431
MA
184
185 /* load resident */
f5e3980f 186 error = request_firmware(&fw, res_name, &sep_dev->sep_pci_dev_ptr->dev);
cd1bb431 187 if (error) {
d19cf32f 188 edbg("SEP Driver:cant request res fw\n");
cd1bb431
MA
189 goto end_function;
190 }
191
d19cf32f
AC
192 edbg("SEP Driver:res data loc is %p\n", (void *) fw->data);
193 edbg("SEP Driver:res data size is %08Zx\n", fw->size);
cd1bb431 194
d19cf32f 195 memcpy((void *) sep_dev->resident_virtual_address, (void *) fw->data, fw->size);
cd1bb431 196
f5e3980f 197 sep_dev->resident_size = fw->size;
cd1bb431
MA
198
199 release_firmware(fw);
200
d19cf32f 201 resident_addr = (unsigned long) sep_dev->resident_virtual_address;
cd1bb431 202
d19cf32f
AC
203 edbg("SEP Driver:resident_addr (physical )is %08lx\n", sep_dev->resident_physical_address);
204 edbg("SEP Driver:cache_addr (physical) is %08lx\n", sep_dev->cache_physical_address);
cd1bb431 205
d19cf32f
AC
206 edbg("SEP Driver:resident_addr (logical )is %08lx\n", resident_addr);
207 edbg("SEP Driver:cache_addr (logical) is %08lx\n", cache_addr);
cd1bb431 208
d19cf32f
AC
209 edbg("SEP Driver:resident_size is %08lx\n", sep_dev->resident_size);
210 edbg("SEP Driver:cache_size is %08lx\n", sep_dev->cache_size);
cd1bb431
MA
211
212
213
214 /* physical addresses */
f5e3980f
AC
215 *dst_new_cache_addr_ptr = sep_dev->cache_physical_address;
216 *dst_new_resident_addr_ptr = sep_dev->resident_physical_address;
f93e4bf9 217end_function:
cd1bb431
MA
218 return error;
219}
220
221/*
222 This functions maps and allocates the
223 shared area on the external RAM (device)
224 The input is shared_area_size - the size of the memory to
225 allocate. The outputs
226 are kernel_shared_area_addr_ptr - the kerenl
227 address of the mapped and allocated
228 shared area, and phys_shared_area_addr_ptr
229 - the physical address of the shared area
230*/
d19cf32f 231int sep_map_and_alloc_shared_area(unsigned long shared_area_size, unsigned long *kernel_shared_area_addr_ptr, unsigned long *phys_shared_area_addr_ptr)
cd1bb431
MA
232{
233 // shared_virtual_address = ioremap_nocache(0xda00000,shared_area_size);
f5e3980f
AC
234 sep_dev->shared_virtual_address = kmalloc(shared_area_size, GFP_KERNEL);
235 if (!sep_dev->shared_virtual_address) {
d19cf32f 236 edbg("sep_driver:shared memory kmalloc failed\n");
cd1bb431
MA
237 return -1;
238 }
f5e3980f
AC
239 /* FIXME */
240 sep_dev->shared_physical_address = __pa(sep_dev->shared_virtual_address);
f93e4bf9 241 /* shared_physical_address = 0xda00000; */
d19cf32f 242 *kernel_shared_area_addr_ptr = (unsigned long) sep_dev->shared_virtual_address;
cd1bb431 243 /* set the physical address of the shared area */
f5e3980f 244 *phys_shared_area_addr_ptr = sep_dev->shared_physical_address;
d19cf32f
AC
245 edbg("SEP Driver:shared_virtual_address is %p\n", sep_dev->shared_virtual_address);
246 edbg("SEP Driver:shared_region_size is %08lx\n", shared_area_size);
247 edbg("SEP Driver:shared_physical_addr is %08lx\n", *phys_shared_area_addr_ptr);
cd1bb431
MA
248
249 return 0;
250}
251
252/*
253 This functions unmaps and deallocates the shared area
254 on the external RAM (device)
255 The input is shared_area_size - the size of the memory to deallocate,kernel_
256 shared_area_addr_ptr - the kernel address of the mapped and allocated
257 shared area,phys_shared_area_addr_ptr - the physical address of
258 the shared area
259*/
d19cf32f 260void sep_unmap_and_free_shared_area(unsigned long shared_area_size, unsigned long kernel_shared_area_addr, unsigned long phys_shared_area_addr)
cd1bb431 261{
d19cf32f 262 kfree((void *) kernel_shared_area_addr);
cd1bb431
MA
263}
264
265/*
266 This functions returns the physical address inside shared area according
267 to the virtual address. It can be either on the externa RAM device
268 (ioremapped), or on the system RAM
269 This implementation is for the external RAM
270*/
271unsigned long sep_shared_area_virt_to_phys(unsigned long virt_address)
272{
d19cf32f
AC
273 edbg("SEP Driver:sh virt to phys v %08lx\n", virt_address);
274 edbg("SEP Driver:sh virt to phys p %08lx\n", sep_dev->shared_physical_address + (virt_address - (unsigned long) sep_dev->shared_virtual_address));
275
276 return (unsigned long) sep_dev->shared_physical_address + (virt_address - (unsigned long) sep_dev->shared_virtual_address);
cd1bb431
MA
277}
278
279/*
280 This functions returns the virtual address inside shared area
281 according to the physical address. It can be either on the
282 externa RAM device (ioremapped), or on the system RAM This implementation
283 is for the external RAM
284*/
285unsigned long sep_shared_area_phys_to_virt(unsigned long phys_address)
286{
d19cf32f 287 return (unsigned long) sep_dev->shared_virtual_address + (phys_address - sep_dev->shared_physical_address);
cd1bb431
MA
288}
289
290
291/*
292 function that is activaed on the succesfull probe of the SEP device
293*/
d19cf32f 294static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
cd1bb431 295{
f93e4bf9 296 int error = 0;
cd1bb431 297
d19cf32f 298 edbg("Sep pci probe starting\n");
cd1bb431
MA
299
300 /* enable the device */
301 error = pci_enable_device(pdev);
302 if (error) {
d19cf32f 303 edbg("error enabling pci device\n");
cd1bb431
MA
304 goto end_function;
305 }
306
307 /* set the pci dev pointer */
f5e3980f 308 sep_dev->sep_pci_dev_ptr = pdev;
cd1bb431
MA
309
310 /* get the io memory start address */
f5e3980f
AC
311 sep_dev->io_memory_start_physical_address = pci_resource_start(pdev, 0);
312 if (!sep_dev->io_memory_start_physical_address) {
d19cf32f 313 edbg("SEP Driver error pci resource start\n");
cd1bb431
MA
314 goto end_function;
315 }
316
317 /* get the io memory end address */
f5e3980f
AC
318 sep_dev->io_memory_end_physical_address = pci_resource_end(pdev, 0);
319 if (!sep_dev->io_memory_end_physical_address) {
d19cf32f 320 edbg("SEP Driver error pci resource end\n");
cd1bb431
MA
321 goto end_function;
322 }
323
d19cf32f 324 sep_dev->io_memory_size = sep_dev->io_memory_end_physical_address - sep_dev->io_memory_start_physical_address + 1;
cd1bb431 325
d19cf32f 326 edbg("SEP Driver:io_memory_start_physical_address is %08lx\n", sep_dev->io_memory_start_physical_address);
cd1bb431 327
d19cf32f 328 edbg("SEP Driver:io_memory_end_phyaical_address is %08lx\n", sep_dev->io_memory_end_physical_address);
cd1bb431 329
d19cf32f 330 edbg("SEP Driver:io_memory_size is %08lx\n", sep_dev->io_memory_size);
cd1bb431 331
d19cf32f 332 sep_dev->io_memory_start_virtual_address = ioremap_nocache(sep_dev->io_memory_start_physical_address, sep_dev->io_memory_size);
f5e3980f 333 if (!sep_dev->io_memory_start_virtual_address) {
d19cf32f 334 edbg("SEP Driver error ioremap of io memory\n");
cd1bb431
MA
335 goto end_function;
336 }
337
d19cf32f 338 edbg("SEP Driver:io_memory_start_virtual_address is %p\n", sep_dev->io_memory_start_virtual_address);
cd1bb431 339
d19cf32f 340 sep_dev->reg_base_address = (void __iomem *) sep_dev->io_memory_start_virtual_address;
cd1bb431
MA
341
342
343 /* set up system base address and shared memory location */
344
d19cf32f 345 sep_dev->rar_virtual_address = kmalloc(2 * SEP_RAR_IO_MEM_REGION_SIZE, GFP_KERNEL);
cd1bb431 346
f5e3980f 347 if (!sep_dev->rar_virtual_address) {
d19cf32f 348 edbg("SEP Driver:cant kmalloc rar\n");
cd1bb431 349 goto end_function;
d19cf32f 350 }
f5e3980f
AC
351 /* FIXME */
352 sep_dev->rar_physical_address = __pa(sep_dev->rar_virtual_address);
cd1bb431 353
d19cf32f 354 edbg("SEP Driver:rar_physical is %08lx\n", sep_dev->rar_physical_address);
d19cf32f 355 edbg("SEP Driver:rar_virtual is %p\n", sep_dev->rar_virtual_address);
cd1bb431 356
cd1bb431
MA
357#if !SEP_DRIVER_POLLING_MODE
358
d19cf32f 359 edbg("SEP Driver: about to write IMR and ICR REG_ADDR\n");
cd1bb431
MA
360
361 /* clear ICR register */
d19cf32f 362 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF);
cd1bb431
MA
363
364 /* set the IMR register - open only GPR 2 */
d19cf32f 365 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
cd1bb431
MA
366
367 /* figure out our irq */
f5e3980f 368 /* FIXME: */
d19cf32f 369 error = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, (u8 *) & sep_dev->sep_irq);
cd1bb431 370
d19cf32f 371 edbg("SEP Driver: my irq is %d\n", sep_irq);
cd1bb431 372
d19cf32f 373 edbg("SEP Driver: about to call request_irq\n");
cd1bb431 374 /* get the interrupt line */
d19cf32f 375 error = request_irq(sep_irq, sep_inthandler, IRQF_SHARED, "sep_driver", &sep_dev->reg_base_address);
cd1bb431
MA
376 if (error)
377 goto end_function;
378
379 goto end_function;
d19cf32f 380 edbg("SEP Driver: about to write IMR REG_ADDR");
cd1bb431
MA
381
382 /* set the IMR register - open only GPR 2 */
d19cf32f 383 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
cd1bb431 384
d19cf32f 385#endif /* SEP_DRIVER_POLLING_MODE */
f93e4bf9 386end_function:
cd1bb431
MA
387 return error;
388}
389
390/*
391 this function registers th driver to
392 the device subsystem( either PCI, USB, etc)
393*/
394int sep_register_driver_to_device(void)
395{
396 return pci_register_driver(&sep_pci_driver);
397}
398
399
400
f5e3980f 401void sep_load_rom_code(void)
cd1bb431
MA
402{
403#if SEP_DRIVER_ARM_DEBUG_MODE
404 /* Index variables */
405 unsigned long i, k, j;
406 unsigned long regVal;
407 unsigned long Error;
408 unsigned long warning;
409
410 /* Loading ROM from SEP_ROM_image.h file */
411 k = sizeof(CRYS_SEP_ROM);
412
d19cf32f 413 edbg("SEP Driver: DX_CC_TST_SepRomLoader start\n");
cd1bb431 414
d19cf32f
AC
415 edbg("SEP Driver: k is %lu\n", k);
416 edbg("SEP Driver: sep_dev->reg_base_address is %p\n", sep_dev->reg_base_address);
417 edbg("SEP Driver: CRYS_SEP_ROM_start_address_offset is %p\n", CRYS_SEP_ROM_start_address_offset);
cd1bb431
MA
418
419 for (i = 0; i < 4; i++) {
420 /* write bank */
79de99e8 421 sep_write_reg(sep_dev, SEP_ROM_BANK_register_offset, i);
cd1bb431
MA
422
423 for (j = 0; j < CRYS_SEP_ROM_length / 4; j++) {
d19cf32f 424 sep_write_reg(sep_dev, CRYS_SEP_ROM_start_address_offset + 4 * j, CRYS_SEP_ROM[i * 0x1000 + j]);
cd1bb431
MA
425
426 k = k - 4;
427
428 if (k == 0) {
429 j = CRYS_SEP_ROM_length;
430 i = 4;
431 }
432 }
433 }
434
d19cf32f 435 /* reset the SEP */
79de99e8 436 sep_write_reg(sep_dev, HW_HOST_SEP_SW_RST_REG_ADDR, 0x1);
cd1bb431
MA
437
438 /* poll for SEP ROM boot finish */
439 do {
79de99e8 440 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
cd1bb431
MA
441 } while (!regVal);
442
d19cf32f 443 edbg("SEP Driver: ROM polling ended\n");
cd1bb431
MA
444
445 switch (regVal) {
446 case 0x1:
447 /* fatal error - read erro status from GPRO */
79de99e8 448 Error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
d19cf32f 449 edbg("SEP Driver: ROM polling case 1\n");
cd1bb431
MA
450 break;
451 case 0x2:
452 /* Boot First Phase ended */
79de99e8 453 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
d19cf32f 454 edbg("SEP Driver: ROM polling case 2\n");
cd1bb431
MA
455 break;
456 case 0x4:
457 /* Cold boot ended successfully */
79de99e8 458 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
d19cf32f 459 edbg("SEP Driver: ROM polling case 4\n");
cd1bb431
MA
460 Error = 0;
461 break;
462 case 0x8:
463 /* Warmboot ended successfully */
79de99e8 464 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
d19cf32f 465 edbg("SEP Driver: ROM polling case 8\n");
cd1bb431
MA
466 Error = 0;
467 break;
468 case 0x10:
469 /* ColdWarm boot ended successfully */
79de99e8 470 warning = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
d19cf32f 471 edbg("SEP Driver: ROM polling case 16\n");
cd1bb431
MA
472 Error = 0;
473 break;
474 case 0x20:
d19cf32f 475 edbg("SEP Driver: ROM polling case 32\n");
cd1bb431
MA
476 break;
477 }
478
479#endif
480}