4
* Syslink driver support functions for TI OMAP processors.
6
* Copyright (C) 2009-2010 Texas Instruments, Inc.
8
* This package is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
12
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17
#include <linux/types.h>
19
#include <linux/sched.h>
20
#include <linux/module.h>
21
#include <linux/mutex.h>
22
#include <linux/vmalloc.h>
23
#include <linux/uaccess.h>
25
#include <linux/delay.h>
26
#include <linux/slab.h>
28
/* Module level headers */
29
#include "../procdefs.h"
30
#include "../processor.h"
32
#include "../procmgr_drvdefs.h"
34
#include "../../ipu_pm/ipu_pm.h"
35
#include <syslink/multiproc.h>
36
#include <syslink/platform_mem.h>
37
#include <syslink/atomic_linux.h>
40
#define OMAP4430PROC_MODULEID (u16) 0xbbec
42
/* Macro to make a correct module magic number with refCount */
43
#define OMAP4430PROC_MAKE_MAGICSTAMP(x) ((OMAP4430PROC_MODULEID << 12u) | (x))
45
#define PG_MASK(pg_size) (~((pg_size)-1))
46
#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
48
/*OMAP4430 Module state object */
49
struct proc4430_module_object {
51
/* Size of configuration structure */
52
struct proc4430_config cfg;
53
/* OMAP4430 configuration structure */
54
struct proc4430_config def_cfg;
55
/* Default module configuration */
56
struct proc4430_params def_inst_params;
57
/* Default parameters for the OMAP4430 instances */
58
void *proc_handles[MULTIPROC_MAXPROCESSORS];
59
/* Processor handle array. */
60
struct mutex *gate_handle;
61
/* void * of gate to be used for local thread safety */
66
OMAP4430 instance object.
68
struct proc4430_object {
69
struct proc4430_params params;
70
/* Instance parameters (configuration values) */
71
atomic_t attach_count;
72
/* attach reference count */
76
/* =================================
78
* =================================
81
OMAP4430 state object variable
84
static struct proc4430_module_object proc4430_state = {
85
.config_size = sizeof(struct proc4430_config),
87
.def_inst_params.num_mem_entries = 0u,
88
.def_inst_params.mem_entries = NULL,
89
.def_inst_params.reset_vector_mem_entry = 0
93
/* =================================
94
* APIs directly called by applications
95
* =================================
98
* Function to get the default configuration for the OMAP4430
101
* This function can be called by the application to get their
102
* configuration parameter to proc4430_setup filled in by the
103
* OMAP4430 module with the default parameters. If the user
104
* does not wish to make any change in the default parameters, this
105
* API is not required to be called.
107
void proc4430_get_config(struct proc4430_config *cfg)
110
memcpy(cfg, &(proc4430_state.def_cfg),
111
sizeof(struct proc4430_config));
113
EXPORT_SYMBOL(proc4430_get_config);
116
* Function to setup the OMAP4430 module.
118
* This function sets up the OMAP4430 module. This function
119
* must be called before any other instance-level APIs can be
121
* Module-level configuration needs to be provided to this
122
* function. If the user wishes to change some specific config
123
* parameters, then proc4430_get_config can be called to get the
124
* configuration filled with the default values. After this, only
125
* the required configuration values can be changed. If the user
126
* does not wish to make any change in the default parameters, the
127
* application can simply call proc4430_setup with NULL
128
* parameters. The default parameters would get automatically used.
130
int proc4430_setup(struct proc4430_config *cfg)
133
struct proc4430_config tmp_cfg;
134
atomic_cmpmask_and_set(&proc4430_state.ref_count,
135
OMAP4430PROC_MAKE_MAGICSTAMP(0),
136
OMAP4430PROC_MAKE_MAGICSTAMP(0));
138
if (atomic_inc_return(&proc4430_state.ref_count) !=
139
OMAP4430PROC_MAKE_MAGICSTAMP(1)) {
144
proc4430_get_config(&tmp_cfg);
148
/* Create a default gate handle for local module protection. */
149
proc4430_state.gate_handle =
150
kmalloc(sizeof(struct mutex), GFP_KERNEL);
151
if (proc4430_state.gate_handle == NULL) {
156
mutex_init(proc4430_state.gate_handle);
158
/* Initialize the name to handles mapping array. */
159
memset(&proc4430_state.proc_handles, 0,
160
(sizeof(void *) * MULTIPROC_MAXPROCESSORS));
162
/* Copy the user provided values into the state object. */
163
memcpy(&proc4430_state.cfg, cfg,
164
sizeof(struct proc4430_config));
169
atomic_dec_return(&proc4430_state.ref_count);
173
EXPORT_SYMBOL(proc4430_setup);
176
* Function to destroy the OMAP4430 module.
178
* Once this function is called, other OMAP4430 module APIs,
179
* except for the proc4430_get_config API cannot be called
182
int proc4430_destroy(void)
187
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
188
OMAP4430PROC_MAKE_MAGICSTAMP(0),
189
OMAP4430PROC_MAKE_MAGICSTAMP(1))
194
if (!(atomic_dec_return(&proc4430_state.ref_count)
195
== OMAP4430PROC_MAKE_MAGICSTAMP(0))) {
201
/* Check if any OMAP4430 instances have not been
202
* deleted so far. If not,delete them.
205
for (i = 0; i < MULTIPROC_MAXPROCESSORS; i++) {
206
if (proc4430_state.proc_handles[i] == NULL)
208
proc4430_delete(&(proc4430_state.proc_handles[i]));
211
/* Check if the gate_handle was created internally. */
212
if (proc4430_state.gate_handle != NULL) {
213
mutex_destroy(proc4430_state.gate_handle);
214
kfree(proc4430_state.gate_handle);
220
EXPORT_SYMBOL(proc4430_destroy);
222
/*=================================================
223
* Function to initialize the parameters for this Processor
226
void proc4430_params_init(void *handle, struct proc4430_params *params)
228
struct proc4430_object *proc_object = (struct proc4430_object *)handle;
230
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
231
OMAP4430PROC_MAKE_MAGICSTAMP(0),
232
OMAP4430PROC_MAKE_MAGICSTAMP(1))
234
pr_err("proc4430_params_init failed - Module not initialized");
238
if (WARN_ON(params == NULL)) {
239
pr_err("proc4430_params_init failed "
240
"Argument of type proc4430_params * "
246
memcpy(params, &(proc4430_state.def_inst_params),
247
sizeof(struct proc4430_params));
249
memcpy(params, &(proc_object->params),
250
sizeof(struct proc4430_params));
252
EXPORT_SYMBOL(proc4430_params_init);
254
/*===================================================
255
*Function to create an instance of this Processor.
258
void *proc4430_create(u16 proc_id, const struct proc4430_params *params)
260
struct processor_object *handle = NULL;
261
struct proc4430_object *object = NULL;
263
BUG_ON(!IS_VALID_PROCID(proc_id));
264
BUG_ON(params == NULL);
266
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
267
OMAP4430PROC_MAKE_MAGICSTAMP(0),
268
OMAP4430PROC_MAKE_MAGICSTAMP(1))
270
pr_err("proc4430_create failed - Module not initialized");
274
/* Enter critical section protection. */
275
WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle));
276
if (proc4430_state.proc_handles[proc_id] != NULL) {
277
handle = proc4430_state.proc_handles[proc_id];
280
handle = (struct processor_object *)
281
vmalloc(sizeof(struct processor_object));
282
if (WARN_ON(handle == NULL))
285
handle->proc_fxn_table.attach = &proc4430_attach;
286
handle->proc_fxn_table.detach = &proc4430_detach;
287
handle->proc_fxn_table.read = &proc4430_read;
288
handle->proc_fxn_table.write = &proc4430_write;
289
handle->proc_fxn_table.control = &proc4430_control;
290
handle->proc_fxn_table.translateAddr =
291
&proc4430_translate_addr;
292
handle->proc_fxn_table.procinfo = &proc4430_proc_info;
293
handle->proc_fxn_table.virt_to_phys = &proc4430_virt_to_phys;
294
handle->state = PROC_MGR_STATE_UNKNOWN;
295
handle->object = vmalloc(sizeof(struct proc4430_object));
296
handle->proc_id = proc_id;
297
object = (struct proc4430_object *)handle->object;
298
if (params != NULL) {
299
/* Copy params into instance object. */
300
memcpy(&(object->params), (void *)params,
301
sizeof(struct proc4430_params));
303
if ((params != NULL) && (params->mem_entries != NULL)
304
&& (params->num_mem_entries > 0)) {
305
/* Allocate memory for, and copy mem_entries table*/
306
object->params.mem_entries = vmalloc(sizeof(struct
307
proc4430_mem_entry) *
308
params->num_mem_entries);
309
memcpy(object->params.mem_entries,
311
(sizeof(struct proc4430_mem_entry) *
312
params->num_mem_entries));
314
handle->boot_mode = PROC_MGR_BOOTMODE_NOLOAD;
315
/* Set the handle in the state object. */
316
proc4430_state.proc_handles[proc_id] = handle;
320
mutex_unlock(proc4430_state.gate_handle);
322
return (void *)handle;
324
EXPORT_SYMBOL(proc4430_create);
326
/*=================================================
327
* Function to delete an instance of this Processor.
329
* The user provided pointer to the handle is reset after
330
* successful completion of this function.
333
int proc4430_delete(void **handle_ptr)
336
struct proc4430_object *object = NULL;
337
struct processor_object *handle;
339
BUG_ON(handle_ptr == NULL);
340
BUG_ON(*handle_ptr == NULL);
342
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
343
OMAP4430PROC_MAKE_MAGICSTAMP(0),
344
OMAP4430PROC_MAKE_MAGICSTAMP(1))
346
pr_err("proc4430_delete failed Module not initialized");
350
handle = (struct processor_object *)(*handle_ptr);
351
BUG_ON(!IS_VALID_PROCID(handle->proc_id));
352
/* Enter critical section protection. */
353
WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle));
354
/* Reset handle in PwrMgr handle array. */
355
proc4430_state.proc_handles[handle->proc_id] = NULL;
356
/* Free memory used for the OMAP4430 object. */
357
if (handle->object != NULL) {
358
object = (struct proc4430_object *)handle->object;
359
if (object->params.mem_entries != NULL) {
360
vfree(object->params.mem_entries);
361
object->params.mem_entries = NULL;
363
vfree(handle->object);
364
handle->object = NULL;
366
/* Free memory used for the Processor object. */
369
/* Leave critical section protection. */
370
mutex_unlock(proc4430_state.gate_handle);
373
EXPORT_SYMBOL(proc4430_delete);
375
/*===================================================
376
* Function to open a handle to an instance of this Processor. This
377
* function is called when access to the Processor is required from
378
* a different process.
380
int proc4430_open(void **handle_ptr, u16 proc_id)
384
BUG_ON(handle_ptr == NULL);
385
BUG_ON(!IS_VALID_PROCID(proc_id));
387
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
388
OMAP4430PROC_MAKE_MAGICSTAMP(0),
389
OMAP4430PROC_MAKE_MAGICSTAMP(1))
391
pr_err("proc4430_open failed Module not initialized");
395
/* Initialize return parameter handle. */
398
/* Check if the PwrMgr exists and return the handle if found. */
399
if (proc4430_state.proc_handles[proc_id] == NULL) {
403
*handle_ptr = proc4430_state.proc_handles[proc_id];
407
EXPORT_SYMBOL(proc4430_open);
409
/*===============================================
410
* Function to close a handle to an instance of this Processor.
413
int proc4430_close(void *handle)
417
BUG_ON(handle == NULL);
419
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
420
OMAP4430PROC_MAKE_MAGICSTAMP(0),
421
OMAP4430PROC_MAKE_MAGICSTAMP(1))
423
pr_err("proc4430_close failed Module not initialized");
427
/* nothing to be done for now */
430
EXPORT_SYMBOL(proc4430_close);
432
/* =================================
433
* APIs called by Processor module (part of function table interface)
434
* =================================
436
/*================================
437
* Function to initialize the slave processor
440
int proc4430_attach(void *handle, struct processor_attach_params *params)
444
struct processor_object *proc_handle = NULL;
445
struct proc4430_object *object = NULL;
448
memory_map_info map_info;
450
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
451
OMAP4430PROC_MAKE_MAGICSTAMP(0),
452
OMAP4430PROC_MAKE_MAGICSTAMP(1))
454
pr_err("proc4430_attach failed Module not initialized");
458
if (WARN_ON(handle == NULL)) {
459
pr_err("proc4430_attach failed Driver handle is NULL");
463
if (WARN_ON(params == NULL)) {
464
pr_err("proc4430_attach failed"
465
"Argument processor_attach_params * is NULL");
469
proc_handle = (struct processor_object *)handle;
471
object = (struct proc4430_object *)proc_handle->object;
473
atomic_cmpmask_and_set(&object->attach_count,
474
OMAP4430PROC_MAKE_MAGICSTAMP(0),
475
OMAP4430PROC_MAKE_MAGICSTAMP(0));
476
atomic_inc_return(&object->attach_count);
478
pr_err("proc4430_attach num_mem_entries = %d",
479
object->params.num_mem_entries);
480
/* Return memory information in params. */
481
for (i = 0; (i < object->params.num_mem_entries); i++) {
482
/* If the configured master virtual address is invalid, get the
483
* actual address by mapping the physical address into master
484
* kernel memory space.
486
if ((object->params.mem_entries[i].master_virt_addr == (u32)-1)
487
&& (object->params.mem_entries[i].shared == true)) {
488
map_info.src = object->params.mem_entries[i].phys_addr;
489
map_info.size = object->params.mem_entries[i].size;
490
map_info.is_cached = false;
491
retval = platform_mem_map(&map_info);
493
pr_err("proc4430_attach failed\n");
497
object->params.mem_entries[i].master_virt_addr =
499
params->mem_entries[i].addr
500
[PROC_MGR_ADDRTYPE_MASTERKNLVIRT] =
502
params->mem_entries[i].addr
503
[PROC_MGR_ADDRTYPE_SLAVEVIRT] =
504
(object->params.mem_entries[i].slave_virt_addr);
505
/* User virtual will be filled by user side. For now,
506
fill in the physical address so that it can be used
507
by mmap to remap this region into user-space */
508
params->mem_entries[i].addr
509
[PROC_MGR_ADDRTYPE_MASTERUSRVIRT] = \
510
object->params.mem_entries[i].phys_addr;
511
params->mem_entries[i].size =
512
object->params.mem_entries[i].size;
515
params->num_mem_entries = map_count;
520
/*==========================================
521
* Function to detach from the Processor.
524
int proc4430_detach(void *handle)
526
struct processor_object *proc_handle = NULL;
527
struct proc4430_object *object = NULL;
529
memory_unmap_info unmap_info;
531
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
532
OMAP4430PROC_MAKE_MAGICSTAMP(0),
533
OMAP4430PROC_MAKE_MAGICSTAMP(1))
536
pr_err("proc4430_detach failed Module not initialized");
539
if (WARN_ON(handle == NULL)) {
540
pr_err("proc4430_detach failed "
541
"Argument Driverhandle is NULL");
545
proc_handle = (struct processor_object *)handle;
546
object = (struct proc4430_object *)proc_handle->object;
548
if (!(atomic_dec_return(&object->attach_count) == \
549
OMAP4430PROC_MAKE_MAGICSTAMP(0)))
552
for (i = 0; (i < object->params.num_mem_entries); i++) {
553
if ((object->params.mem_entries[i].master_virt_addr > 0)
554
&& (object->params.mem_entries[i].shared == true)) {
556
object->params.mem_entries[i].master_virt_addr;
557
unmap_info.size = object->params.mem_entries[i].size;
558
platform_mem_unmap(&unmap_info);
559
object->params.mem_entries[i].master_virt_addr =
567
/*==============================================
568
* Function to read from the slave processor's memory.
570
* Read from the slave processor's memory and copy into the
573
int proc4430_read(void *handle, u32 proc_addr, u32 *num_bytes,
577
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
578
OMAP4430PROC_MAKE_MAGICSTAMP(0),
579
OMAP4430PROC_MAKE_MAGICSTAMP(1))
581
pr_err("proc4430_read failed Module not initialized");
585
buffer = memcpy(buffer, (void *)proc_addr, *num_bytes);
591
/*==============================================
592
* Function to write into the slave processor's memory.
594
* Read from the provided buffer and copy into the slave
595
* processor's memory.
598
int proc4430_write(void *handle, u32 proc_addr, u32 *num_bytes,
603
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
604
OMAP4430PROC_MAKE_MAGICSTAMP(0),
605
OMAP4430PROC_MAKE_MAGICSTAMP(1))
607
pr_err("proc4430_write failed Module not initialized");
611
proc_addr = (u32)memcpy((void *)proc_addr, buffer, *num_bytes);
617
/*=========================================================
618
* Function to perform device-dependent operations.
620
* Performs device-dependent control operations as exposed by this
621
* implementation of the Processor module.
623
int proc4430_control(void *handle, int cmd, void *arg)
627
/*FIXME: Remove handle,etc if not used */
629
#ifdef CONFIG_SYSLINK_DUCATI_PM
630
/* Just for testing purpose */
633
retval = ipu_pm_notifications(APP_M3, cmd, NULL);
634
retval = ipu_pm_notifications(SYS_M3, cmd, NULL);
635
ipu_pm_save_ctx(SYS_M3);
638
retval = ipu_pm_notifications(APP_M3, cmd, NULL);
639
retval = ipu_pm_notifications(SYS_M3, cmd, NULL);
642
pr_err("Invalid notification\n");
644
if (retval != PM_SUCCESS)
645
pr_err("Error in notifications\n");
648
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
649
OMAP4430PROC_MAKE_MAGICSTAMP(0),
650
OMAP4430PROC_MAKE_MAGICSTAMP(1))
652
pr_err("proc4430_control failed Module not initialized");
660
/*=====================================================
661
* Function to translate between two types of address spaces.
663
* Translate between the specified address spaces.
665
int proc4430_translate_addr(void *handle,
666
void **dst_addr, enum proc_mgr_addr_type dst_addr_type,
667
void *src_addr, enum proc_mgr_addr_type src_addr_type)
670
struct processor_object *proc_handle = NULL;
671
struct proc4430_object *object = NULL;
672
struct proc4430_mem_entry *entry = NULL;
674
u32 fm_addr_base = (u32)NULL;
675
u32 to_addr_base = (u32)NULL;
678
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
679
OMAP4430PROC_MAKE_MAGICSTAMP(0),
680
OMAP4430PROC_MAKE_MAGICSTAMP(1))
682
pr_err("proc4430_translate_addr failed Module not initialized");
687
if (WARN_ON(handle == NULL)) {
691
if (WARN_ON(dst_addr == NULL)) {
695
if (WARN_ON(dst_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) {
699
if (WARN_ON(src_addr == NULL)) {
703
if (WARN_ON(src_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) {
708
proc_handle = (struct processor_object *)handle;
709
object = (struct proc4430_object *)proc_handle->object;
711
for (i = 0 ; i < object->params.num_mem_entries ; i++) {
712
entry = &(object->params.mem_entries[i]);
714
(src_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ?
715
entry->master_virt_addr : entry->slave_virt_addr;
717
(dst_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ?
718
entry->master_virt_addr : entry->slave_virt_addr;
719
/* Determine whether which way to convert */
720
if (((u32)src_addr < (fm_addr_base + entry->size)) &&
721
((u32)src_addr >= fm_addr_base)) {
723
*dst_addr = (void *)(((u32)src_addr - fm_addr_base)
729
/* This check must not be removed even with build optimize. */
730
if (WARN_ON(found == false)) {
731
/*Failed to translate address. */
742
/*=================================================
743
* Function to return list of translated mem entries
745
* This function takes the remote processor address as
746
* an input and returns the mapped Page entries in the
749
int proc4430_virt_to_phys(void *handle, u32 da, u32 *mapped_entries,
756
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
757
OMAP4430PROC_MAKE_MAGICSTAMP(0),
758
OMAP4430PROC_MAKE_MAGICSTAMP(1))
760
pr_err("proc4430_virt_to_phys failed Module not initialized");
765
if (handle == NULL || mapped_entries == NULL || num_of_entries == 0) {
769
da_align = PG_ALIGN_LOW((u32)da, PAGE_SIZE);
770
for (i = 0; i < num_of_entries; i++) {
771
mapped_entries[i] = da_align;
772
da_align += PAGE_SIZE;
777
pr_warn("proc4430_virtToPhys failed !!!!\n");
782
/*=================================================
783
* Function to return PROC4430 mem_entries info
786
int proc4430_proc_info(void *handle, struct proc_mgr_proc_info *procinfo)
788
struct processor_object *proc_handle = NULL;
789
struct proc4430_object *object = NULL;
790
struct proc4430_mem_entry *entry = NULL;
793
if (atomic_cmpmask_and_lt(&proc4430_state.ref_count,
794
OMAP4430PROC_MAKE_MAGICSTAMP(0),
795
OMAP4430PROC_MAKE_MAGICSTAMP(1))
797
pr_err("proc4430_proc_info failed Module not initialized");
801
if (WARN_ON(handle == NULL))
803
if (WARN_ON(procinfo == NULL))
806
proc_handle = (struct processor_object *)handle;
808
object = (struct proc4430_object *)proc_handle->object;
810
for (i = 0 ; i < object->params.num_mem_entries ; i++) {
811
entry = &(object->params.mem_entries[i]);
812
procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_MASTERKNLVIRT]
813
= entry->master_virt_addr;
814
procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_SLAVEVIRT]
815
= entry->slave_virt_addr;
816
procinfo->mem_entries[i].size = entry->size;
818
procinfo->num_mem_entries = object->params.num_mem_entries;
819
procinfo->boot_mode = proc_handle->boot_mode;
823
pr_warn("proc4430_proc_info failed !!!!\n");