summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Harkin <ryan.harkin@linaro.org>2012-08-20 11:12:00 +0100
committerRyan Harkin <ryan.harkin@linaro.org>2012-08-20 11:12:00 +0100
commitd49ba79e42b7bd5fae984fd0800cd618919d4ade (patch)
tree78042ba8c72bfeb33c88351d21efd4479b09ad6f
parent05a941246794127815ac8b4ed7da0fe70a2b779e (diff)
downloadstm-doug-kernel-api.tar.gz
drivers/stm: add kernel side APIdoug-kernel-api
Latest code from Doug Deao @ TI to add a kernel side API to the STM framework. Signed-off-by: Ryan Harkin <ryan.harkin@linaro.org>
-rw-r--r--drivers/stm/stm_fw.c198
-rwxr-xr-x[-rw-r--r--]drivers/stm/stm_fw.h7
-rwxr-xr-x[-rw-r--r--]drivers/stm/stm_omap_ti1.0.c287
3 files changed, 430 insertions, 62 deletions
diff --git a/drivers/stm/stm_fw.c b/drivers/stm/stm_fw.c
index 057963c..1ef1bda 100644
--- a/drivers/stm/stm_fw.c
+++ b/drivers/stm/stm_fw.c
@@ -93,6 +93,8 @@ static struct stm_device dev;
*****************************************************************************/
static int8_t cal_checksum(unsigned char *buf, int cnt);
+static struct stm_chn_descriptor *gen_chn_descriptor(enum stm_usecase uc_id);
+
static void rm_chn_descriptor(struct stm_chn_descriptor *chn_descriptor);
static int parse_to_user(char *buf, loff_t buf_pos,
@@ -125,7 +127,7 @@ static ssize_t stm_file_write(struct file *filp, const char __user *user_buf,
struct stm_chn_descriptor *chn_descriptor = filp->private_data;
char *buf = NULL;
char *kbuf = NULL;
- bool uspace = false;
+ bool uspace = (chn_descriptor->write_dentry != NULL) ? true : false;
bool timestamp = false;
uint msg_cnt = 0;
int ret = 0;
@@ -180,9 +182,13 @@ static ssize_t stm_file_write(struct file *filp, const char __user *user_buf,
goto stm_file_write_exit;
}
- if (copy_from_user(kbuf + header, user_buf, count)) {
- ret = -EFAULT;
- goto stm_file_write_exit;
+ if (uspace == true) {
+ if (copy_from_user(kbuf + header, user_buf, count)) {
+ ret = -EFAULT;
+ goto stm_file_write_exit;
+ }
+ } else {
+ memcpy(kbuf + header, user_buf, count);
}
if (chn_descriptor->ost_enable) {
@@ -212,7 +218,6 @@ static ssize_t stm_file_write(struct file *filp, const char __user *user_buf,
case VENDOR:
buf = (char *)user_buf;
- uspace = true;
/* Note module specific driver can treat timestamp as false*/
timestamp = true;
msg_cnt = count;
@@ -220,7 +225,6 @@ static ssize_t stm_file_write(struct file *filp, const char __user *user_buf,
case RAW:
buf = (char *)user_buf;
- uspace = true;
timestamp = true;
msg_cnt = count;
break;
@@ -310,23 +314,27 @@ static ssize_t config_file_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct stm_chn_descriptor *chn_descriptor = file->private_data;
+ bool uspace = (chn_descriptor->write_dentry != NULL) ? true : false;
char *kbuf = NULL, kbuffer[MAX_CONFIG_STRING_BYTES];
enum config_id cfg_id;
int cfg_len;
int err = 0;
bool vendor_pass = false;
- if (count > MAX_CONFIG_STRING_BYTES) {
+ /* Get userspace string and assure termination */
+ if (count >= sizeof(kbuffer)) {
err = -EINVAL;
goto cfg_wrt_exit1;
}
- /* Get userspace string and assure termination */
- if (count >= sizeof(kbuffer))
- return -EINVAL;
-
- if (copy_from_user(kbuffer, user_buf, count))
- return -EFAULT;
+ if (uspace) {
+ if (copy_from_user(kbuffer, user_buf, count)) {
+ err = -EFAULT;
+ goto cfg_wrt_exit1;
+ }
+ } else {
+ memcpy(kbuffer, user_buf, count);
+ }
kbuffer[count] = 0;
@@ -390,8 +398,13 @@ static ssize_t config_file_write(struct file *file, const char __user *user_buf,
chn_descriptor->ost_enable = false;
break;
case CFGID_FMT_USER:
- chn_descriptor->msg_format = USER;
- vendor_pass = true;
+ if (uspace) {
+ chn_descriptor->msg_format = USER;
+ vendor_pass = true;
+ } else {
+ err = -EINVAL;
+ vendor_pass = false;
+ }
break;
case CFGID_FMT_VENDOR:
chn_descriptor->msg_format = VENDOR;
@@ -421,16 +434,38 @@ cfg_wrt_exit1:
return count;
}
+
+enum attr_id {
+ ATTR_CHN_ENABLE,
+ ATTR_CHN_PROTECT,
+ ATTR_MODE_VENDOR,
+ ATTR_MODE_USER,
+ ATTR_MODE_RAW,
+ ATTR_LAST
+};
+
+static struct _attributes {
+ char *name;
+ unsigned int value;
+} attributes[] = {
+ [ATTR_CHN_ENABLE] = {"chn_enable", 0},
+ [ATTR_CHN_PROTECT] = {"chn_protected", 0},
+ [ATTR_MODE_VENDOR] = {"mode_vendor", 1},
+ [ATTR_MODE_USER] = {"mode_user", 0},
+ [ATTR_MODE_RAW] = {"mode_raw", 0}
+};
+
/* Provide channel configuration data on user read from file */
static ssize_t config_file_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct stm_chn_descriptor *chn_descriptor = file->private_data;
- const int max_buf = 256;
+ const int max_buf = 320;
char buf[max_buf];
int buf_cnt = 0;
char delims[] = ",";
loff_t buf_pos = 0;
+ int i;
if (!dev.stm_ops->config_read)
return 0;
@@ -438,9 +473,24 @@ static ssize_t config_file_read(struct file *file, char __user *user_buf,
if (mutex_lock_interruptible(&chn_descriptor->lock))
return -ERESTARTSYS;
+ /* get the attributes the framework driver knows about */
+ attributes[ATTR_CHN_ENABLE].value = chn_descriptor->chn_enable;
+ attributes[ATTR_CHN_PROTECT].value = chn_descriptor->write_protect;
+ attributes[ATTR_MODE_VENDOR].value =
+ (chn_descriptor->msg_format == VENDOR);
+ attributes[ATTR_MODE_USER].value =
+ (chn_descriptor->msg_format == USER);
+ attributes[ATTR_MODE_RAW].value = (chn_descriptor->msg_format == RAW);
+
+ for (i = 0; i < ATTR_LAST; i++) {
+ buf_cnt += snprintf(buf+buf_cnt, max_buf-buf_cnt,
+ "%s %u\n,", attributes[i].name,
+ attributes[i].value);
+ }
+
/* config_read puts formatted comma seperated strings in buf */
buf_cnt = dev.stm_ops->config_read(chn_descriptor->chn_id,
- buf, max_buf);
+ buf+buf_cnt, max_buf-buf_cnt);
mutex_unlock(&chn_descriptor->lock);
@@ -615,6 +665,7 @@ static ssize_t request_file_write(struct file *filp,
}
}
+#if 0
/* Malloc the channel descriptor */
chn_descriptor = kmalloc(sizeof *chn_descriptor, GFP_KERNEL);
if (!chn_descriptor) {
@@ -645,7 +696,14 @@ static ssize_t request_file_write(struct file *filp,
chn_descriptor->chn_id = NULL;
goto alloc_err_exit;
}
+#else
+ chn_descriptor = gen_chn_descriptor(uc_id);
+ if (IS_ERR(chn_descriptor)) {
+ err = PTR_ERR(chn_descriptor);
+ goto err_exit;
+ }
+#endif
/* If user command create debugfs message write file */
if (uc_id == USER_CHANNEL_REQUEST) {
@@ -691,8 +749,10 @@ static ssize_t request_file_write(struct file *filp,
goto alloc_err_exit;
}
+#if 0
list_add_tail(&chn_descriptor->chn_list_link,
&dev.chn_list_head);
+#endif
break;
@@ -720,12 +780,10 @@ static ssize_t request_file_write(struct file *filp,
err = -EINVAL;
goto err_exit;
}
-
- rm_chn_descriptor(chn_descriptor);
-
+#if 0
list_del(&chn_descriptor->chn_list_link);
-
- kfree(chn_descriptor);
+#endif
+ rm_chn_descriptor(chn_descriptor);
break;
@@ -744,7 +802,6 @@ static ssize_t request_file_write(struct file *filp,
alloc_err_exit:
rm_chn_descriptor(chn_descriptor);
- kfree(chn_descriptor);
err_exit:
mutex_unlock(&dev.lock);
@@ -897,7 +954,52 @@ module_exit(stm_fw_exit);
MODULE_LICENSE("Dual BSD/GPL");
/*****************************************************************************/
-/* Support functions */
+/* Public Kernel APIs */
+/*****************************************************************************/
+void *stm_channel_alloc(enum stm_usecase uc_id)
+{
+ struct stm_chn_descriptor *chn_descriptor = NULL;
+
+ chn_descriptor = gen_chn_descriptor(uc_id);
+ if (IS_ERR(chn_descriptor))
+ return (void *)PTR_ERR(chn_descriptor);
+
+/* Note: for kernel defined channnels chn_descriptor->write_dentry is NULL. */
+
+ return (void *)chn_descriptor;
+}
+
+int stm_channel_free(void *chn_id)
+{
+ rm_chn_descriptor((struct stm_chn_descriptor *)chn_id);
+ return 0;
+}
+int stm_channel_config(void *chn_id, char * config_string)
+{
+ struct file cfgfile;
+ loff_t offset = 0;
+ cfgfile.private_data = chn_id;
+
+ return config_file_write(&cfgfile, config_string,
+ strlen(config_string), &offset);
+}
+int stm_channel_write(void *chn_id, void * src, size_t byte_cnt)
+{
+ struct file wrtfile;
+ loff_t offset = 0;
+ wrtfile.private_data = chn_id;
+
+ return stm_file_write(&wrtfile, src, byte_cnt, &offset);
+
+}
+
+EXPORT_SYMBOL(stm_channel_alloc);
+EXPORT_SYMBOL(stm_channel_free);
+EXPORT_SYMBOL(stm_channel_config);
+EXPORT_SYMBOL(stm_channel_write);
+
+/*****************************************************************************/
+/* Support functions */
/*****************************************************************************/
static int8_t cal_checksum(unsigned char *buf, int cnt)
{
@@ -909,6 +1011,50 @@ static int8_t cal_checksum(unsigned char *buf, int cnt)
return -checksum;
}
+static struct stm_chn_descriptor *gen_chn_descriptor(enum stm_usecase uc_id)
+{
+ int err;
+ struct stm_chn_descriptor *chn_descriptor = NULL;
+
+ /* Malloc the channel descriptor */
+ chn_descriptor = kmalloc(sizeof *chn_descriptor, GFP_KERNEL);
+ if (!chn_descriptor) {
+ err = -ENOMEM;
+ goto gen_chn_exit;
+ }
+
+ /* Initialize chn descriptor */
+ chn_descriptor->write_dentry = NULL;
+ chn_descriptor->config_dentry = NULL;
+ chn_descriptor->chn_enable = true;
+ chn_descriptor->write_protect = true;
+
+ mutex_init(&chn_descriptor->lock);
+ chn_descriptor->msg_format = VENDOR;
+ chn_descriptor->msg_timing = GUARANTEED;
+ chn_descriptor->ost_protocol = OST_PROTOCOL_CHARSTREAM;
+ chn_descriptor->ost_entity = OST_ENTITY_ID;
+ chn_descriptor->timestamp_enable = true;
+ chn_descriptor->checksum_enable = false;
+ /* set to invlaid id so first write will export pid message */
+ chn_descriptor->pid = 0;
+
+ /* Allocate a channel */
+ err = dev.stm_ops->allocate_channel(uc_id, &chn_descriptor->chn_id);
+ if (err < 0) {
+ chn_descriptor->chn_id = NULL;
+ goto gen_chn_exit;
+ }
+
+ list_add_tail(&chn_descriptor->chn_list_link, &dev.chn_list_head);
+
+ return chn_descriptor;
+
+gen_chn_exit:
+ kfree(chn_descriptor);
+ return ERR_PTR(err);
+}
+
static void rm_chn_descriptor(struct stm_chn_descriptor *chn_descriptor)
{
if (!chn_descriptor)
@@ -923,6 +1069,10 @@ static void rm_chn_descriptor(struct stm_chn_descriptor *chn_descriptor)
if (chn_descriptor->chn_id)
dev.stm_ops->free_channel(chn_descriptor->chn_id);
+ list_del(&chn_descriptor->chn_list_link);
+
+ kfree(chn_descriptor);
+
}
diff --git a/drivers/stm/stm_fw.h b/drivers/stm/stm_fw.h
index bcaa307..df95d41 100644..100755
--- a/drivers/stm/stm_fw.h
+++ b/drivers/stm/stm_fw.h
@@ -74,4 +74,11 @@ struct stm_operations {
int stm_register(struct stm_operations *stm_ops);
int stm_unregister(void);
+/* Public Kernel APIs */
+void * stm_channel_alloc(enum stm_usecase usecase_id);
+int stm_channel_free(void *chn_id);
+int stm_channel_config(void *chn_id, char * config_string);
+int stm_channel_write(void *chn_id, void * src, size_t byte_cnt);
+
+
#endif
diff --git a/drivers/stm/stm_omap_ti1.0.c b/drivers/stm/stm_omap_ti1.0.c
index 9dbdb98..8300534 100644..100755
--- a/drivers/stm/stm_omap_ti1.0.c
+++ b/drivers/stm/stm_omap_ti1.0.c
@@ -47,7 +47,7 @@
#include <linux/err.h>
#include <linux/mm.h>
#include <linux/version.h>
-
+#include <linux/clk.h>
#include <plat/omap44xx.h>
#include "stm_fw.h"
@@ -72,7 +72,7 @@ static int32_t stm_put_bin(void *phdr_buf, int32_t hdr_size, void *pmsg_buf,
static struct chn_alloc *construct_chn_obj(int chn, int chn_num);
static bool stm_app_ownership(void);
-
+static int stm_set_enable(void);
static bool stm_test_enable(void);
static bool stm_test_clock(void);
@@ -110,6 +110,10 @@ static uint32_t stm_cntl_iobase;
#define STM_SWMCTRL3_OFFSET 0x030
#define STM_SWMCTRL4_OFFSET 0x034
#define STM_HWMCTRL_OFFSET 0x038
+#define STM_PTI_CONFIG_OFFSET 0x03C
+#define STM_PTI_COUNTD_OFFSET 0x040
+#define STM_ATB_CONFIG_OFFSET 0x044
+#define STM_ATB_POINTER_OFFSET 0x048
#define STM_LOCK_OFFSET 0xFB0
#define STM_LOCK_STATUS_OFFSET 0xFB4
@@ -129,6 +133,17 @@ static uint32_t stm_cntl_iobase;
#define STM_LOCK_STATUS_MASK 0x2
#define STM_LOCK_STATUS_LOCKED 0x2
#define STM_LOCK_IMPLEMENTED 0x1
+/* STM PTI CONFIG Register bits for ETB routing */
+#define STM_PTI_CONFIG_PTICLK_GATE (1 << 7)
+#define STM_PTI_CONFIG_PORTSIZE_4BIT (2 << 4)
+#define STM_PTI_CONFIG_DUALEDGE_CLK (0 << 3)
+/* STM PTI COUNT DOWN Register value */
+#define STM_PTI_COUNTD_VALUE 0xFC
+/* STM ATB Config values */
+#define STM_ATB_CONFIG_ENABLE (1 << 16)
+#define STM_ATB_CONFIG_8xCHN_REPEAT (0xF << 12)
+#define STM_ATB_CONFIG_8xMST_REPEAT (0x8 << 12)
+
/* STM element size */
enum {
@@ -154,6 +169,9 @@ struct stm_device {
struct mutex lock;
struct list_head chn_list_head;
int user_allocated_chn_cnt;
+ bool stm_module_enable;
+ bool route_stm_to_pti;
+ bool route_stm_to_etb;
DECLARE_BITMAP(chn_map, STM_CHANNEL_TOTAL);
DECLARE_BITMAP(sw_master_map, STM_MAX_SW_MASTERS);
DECLARE_BITMAP(hw_master_map, STM_MAX_HW_MASTERS);
@@ -600,7 +618,7 @@ int stm_config_write(void *chn_id, char *config_buf)
void *map;
int max;
uint32_t master_select;
- uint32_t master_mask;
+ uint32_t mask;
unsigned int i;
const int num_ulongs = 2;
const int max_ulong = 255;
@@ -656,10 +674,31 @@ int stm_config_write(void *chn_id, char *config_buf)
chn_obj->msg_data_type = BIN32;
break;
case CFGID_ROUTE_TO_ETB:
- /* Note: call stm_app_ownership first*/
- /* Note: need to set rate at which masters are generated
- * for ETB.
- */
+ if (!stm_app_ownership()) {
+ ret = -EACCES;
+ goto stm_config_write_exit;
+ }
+
+ /* Setup the PTI port for ETB export */
+ iowrite32(STM_PTI_CONFIG_PTICLK_GATE
+ | STM_PTI_CONFIG_PORTSIZE_4BIT
+ | STM_PTI_CONFIG_DUALEDGE_CLK,
+ (void *)(stm_cntl_iobase + STM_PTI_CONFIG_OFFSET));
+
+ /* Set PTI Count down value - number of null messages exported
+ before a new master id is generated */
+ iowrite32(STM_PTI_COUNTD_VALUE ,
+ (void *)(stm_cntl_iobase + STM_PTI_COUNTD_OFFSET));
+
+ /* Setup the ATB Config for ETB export */
+ iowrite32(STM_ATB_CONFIG_ENABLE
+ | STM_ATB_CONFIG_8xCHN_REPEAT
+ | STM_ATB_CONFIG_8xMST_REPEAT,
+ (void *)(stm_cntl_iobase + STM_ATB_CONFIG_OFFSET));
+
+ dev.route_stm_to_pti = 0;
+ dev.route_stm_to_etb = 1;
+
break;
case CFGID_ROUTE_TO_PTI:
@@ -667,6 +706,10 @@ int stm_config_write(void *chn_id, char *config_buf)
* really just a command to disable the ETB routing.
* TODO: Think about changing to CFGID_ROUTE_TO_NULL
*/
+
+ dev.route_stm_to_pti = 1;
+ dev.route_stm_to_etb = 0;
+
break;
case CFGID_SET_MASTER:
@@ -680,7 +723,10 @@ int stm_config_write(void *chn_id, char *config_buf)
ret = -EACCES;
goto stm_config_write_exit;
}
-
+/* TODO: Test that after a set master, since stm_app_ownership leaves the STM
+ * module in claim state, that stm_eanble must be sent for new messages to
+ * get generated.
+ */
/* Test for an avaiable master select */
if (data[0] & HW_MASTER_MASK) {
map = dev.hw_master_map;
@@ -713,13 +759,18 @@ int stm_config_write(void *chn_id, char *config_buf)
iowrite32(master_select, (void *)(stm_cntl_iobase +
STM_SWMCTRL1_OFFSET));
/* set master mask value */
- master_mask = ioread32((void *)stm_cntl_iobase +
+ mask = ioread32((void *)stm_cntl_iobase +
STM_SWMCTRL2_OFFSET);
- master_mask |= data[1] << (i * 8);
- iowrite32(master_mask, (void *)(stm_cntl_iobase +
+ mask |= data[1] << (i * 8);
+ iowrite32(mask, (void *)(stm_cntl_iobase +
STM_SWMCTRL2_OFFSET));
-/* TODO:: Add fixed values for other domain master selection registers. */
-/* These may not actually need to be set. */
+
+ /* set doamin mask value to enable all domains */
+ mask = ioread32((void *)stm_cntl_iobase +
+ STM_SWMCTRL4_OFFSET);
+ mask |= 0x7 << (i * 8);
+ iowrite32(mask, (void *)(stm_cntl_iobase +
+ STM_SWMCTRL4_OFFSET));
}
break;
@@ -745,6 +796,8 @@ int stm_config_write(void *chn_id, char *config_buf)
goto stm_config_write_exit;
}
+ dev.stm_module_enable = true;
+
break;
case CFGID_STM_DISABLE:
@@ -769,6 +822,8 @@ int stm_config_write(void *chn_id, char *config_buf)
goto stm_config_write_exit;
}
+ dev.stm_module_enable = false;
+
break;
case CFGID_GUARANTEED_TIMING:
@@ -788,13 +843,47 @@ stm_config_write_exit:
}
+
+enum attr_id {
+ ATTR_STM_CHN,
+ ATTR_BYTE_CNT,
+ ATTR_STRING,
+ ATTR_BIN8,
+ ATTR_BIN16,
+ ATTR_BIN32,
+ ATTR_GUARANTEED,
+ ATTR_ROUTE_TO_PTI,
+ ATTR_ROUTE_TO_ETB,
+ ATTR_MODULE_ENABLE,
+ ATTR_ATB_POINTER,
+ ATTR_LAST
+};
+
+static struct _attributes {
+ char *name;
+ unsigned int value;
+} attributes[] = {
+ [ATTR_STM_CHN] = {"stm_channel", 0},
+ [ATTR_BYTE_CNT] = {"xmt_byte_count", 0},
+ [ATTR_STRING] = {"msgtype_string", 1},
+ [ATTR_BIN8] = {"msgtype_binary8", 0},
+ [ATTR_BIN16] = {"msgtype_binary16", 0},
+ [ATTR_BIN32] = {"msgtype_binary32", 0},
+ [ATTR_GUARANTEED] = {"msg_guaranteed_xmit", 1},
+ [ATTR_MODULE_ENABLE] = {"stm_module_enable", 0},
+ [ATTR_ROUTE_TO_PTI] {"route_stm_to_pti", 1},
+ [ATTR_ROUTE_TO_ETB] = {"route_stm_to_etb", 0},
+ [ATTR_ATB_POINTER] = {"atb_pointer", 0},
+};
+
+
/* Provide comma seperated list of configuration and channel state info. */
int stm_config_read(void *chn_id, char *config_string, int count)
{
struct chn_alloc *chn_obj = chn_id;
int buf_cnt = 0;
- char *chn_format = NULL;
+ int i;
if (!config_string || count < 1 || !chn_obj)
return -EINVAL;
@@ -802,29 +891,23 @@ int stm_config_read(void *chn_id, char *config_string, int count)
if (mutex_lock_interruptible(&chn_obj->chn_lock))
return -ERESTARTSYS;
- buf_cnt = snprintf(config_string, count, "STM channel %d\n,",
- chn_obj->chn);
-
- switch (chn_obj->msg_format) {
- case VENDOR:
- chn_format = config_cmds[CFGID_FMT_VENDOR];
- break;
- case USER:
- chn_format = config_cmds[CFGID_FMT_USER];
- break;
- case RAW:
- chn_format = config_cmds[CFGID_FMT_RAW];
- break;
- }
- if (chn_format)
+ attributes[ATTR_STM_CHN].value = chn_obj->chn;
+ attributes[ATTR_BYTE_CNT].value = chn_obj->xmit_byte_count;
+ attributes[ATTR_STRING].value = (chn_obj->msg_data_type == STRING);
+ attributes[ATTR_BIN8].value = (chn_obj->msg_data_type == BIN8);
+ attributes[ATTR_BIN16].value = (chn_obj->msg_data_type == BIN16);
+ attributes[ATTR_BIN32].value = (chn_obj->msg_data_type == BIN32);
+ attributes[ATTR_MODULE_ENABLE].value = dev.stm_module_enable;
+ attributes[ATTR_ROUTE_TO_PTI].value = dev.route_stm_to_pti;
+ attributes[ATTR_ROUTE_TO_ETB].value = dev.route_stm_to_etb;
+ attributes[ATTR_ATB_POINTER].value = ioread32((void *)(stm_cntl_iobase
+ + STM_ATB_POINTER_OFFSET));
+
+ for (i = 0; i < ATTR_LAST; i++) {
buf_cnt += snprintf(config_string+buf_cnt, count-buf_cnt,
- "Channel format %s\n,", chn_format);
-
- /* Note: If any other strings are added, this string must be terminated
- * with a comma.
- */
- buf_cnt += snprintf(config_string+buf_cnt, count-buf_cnt,
- "Transmit Byte Count %d\n", chn_obj->xmit_byte_count);
+ "%s %u\n,", attributes[i].name,
+ attributes[i].value);
+ }
mutex_unlock(&chn_obj->chn_lock);
@@ -850,6 +933,10 @@ void stm_ti_clean(void)
struct list_head *ptr, *tmp;
struct chn_alloc *chn_obj = NULL;
+ int ret = 0;
+ struct clk *stm_clk = NULL;
+ struct clk *pdm_stm_clk = NULL;
+
list_for_each_safe(ptr, tmp, &dev.chn_list_head) {
chn_obj = list_entry(ptr, struct chn_alloc, chn_list_link);
kfree(chn_obj);
@@ -867,12 +954,44 @@ void stm_ti_clean(void)
release_mem_region(stm_base_address, STM_ADDRESS_SPACE);
release_mem_region(stm_control_base, STM_ADDRESS_SPACE);
+#if 0
+ /* OMAP only */
+// pdm_stm_clk = clk_get(NULL, "pmd_stm_clock_mux_ck");
+ pdm_stm_clk = clk_get(NULL, "l3_main_3_ick");
+ if (IS_ERR(pdm_stm_clk)) {
+ ret = PTR_ERR(pdm_stm_clk);
+#if 0
+ goto init_err;
+#else
+ pr_err("stm_ti1.0: driver pmd_stm_clock_mux_ck get error %d\n", ret);
+#endif
+ }
+ else
+ clk_disable(pdm_stm_clk);
+
+// stm_clk = clk_get(NULL, "stm_clk_div_ck");
+ stm_clk = clk_get(NULL, "l3_instr_ick");
+ if (IS_ERR(stm_clk)) {
+ ret = PTR_ERR(stm_clk);
+#if 0
+ goto init_err;
+#else
+ pr_err("stm_ti1.0: driver stm_clk_div_ck get error %d\n", ret);
+#endif
+ }
+ else
+ clk_disable(stm_clk);
+#endif
+
}
int __init stm_ti_init(void)
{
-
+ struct clk * l3_main_clk = NULL;
+ struct clk * l3_instr_clk = NULL;
+ struct clk * m6_clk_parent = NULL;
+ struct clk * pdm_stm_mux_clk = NULL;
int ret = 0;
if (!request_mem_region(stm_base_address, STM_ADDRESS_SPACE,
@@ -901,6 +1020,72 @@ int __init stm_ti_init(void)
goto init_err;
}
+#if 1
+ /* OMAP only */
+// pdm_stm_clk = clk_get(NULL, "pmd_stm_clock_mux_ck");
+ l3_main_clk = clk_get(NULL, "l3_main_3_ick");
+ if (IS_ERR(l3_main_clk)) {
+ ret = PTR_ERR(l3_main_clk);
+#if 0
+ goto init_err;
+#else
+ pr_err("stm_ti1.0: pmd stm_clock_mux_ck get error %d\n", ret);
+#endif
+ }
+ else {
+ ret = clk_enable(l3_main_clk);
+ if (ret)
+ pr_err("stm_ti1.0: pmd stm_clock_mux_ck enable error %d\n", ret);
+ }
+
+// stm_clk = clk_get(NULL, "stm_clk_div_ck");
+ l3_instr_clk = clk_get(NULL, "l3_instr_ick");
+ if (IS_ERR(l3_instr_clk)) {
+ ret = PTR_ERR(l3_instr_clk);
+#if 0
+ goto init_err;
+#else
+ pr_err("stm_ti1.0: stm_clk_div_ck get error %d\n", ret);
+#endif
+ }
+ else {
+ ret = clk_enable(l3_instr_clk);
+ if (ret)
+ pr_err("stm_ti1.0: stm_clk_div_ck enable error %d\n", ret);
+ }
+
+ /* Set CM_DIV_M6_DPLL_CORE for 166Mhz */
+ m6_clk_parent = clk_get(NULL, "dpll_core_m6x2_ck");
+ ret = clk_enable(m6_clk_parent);
+
+ {
+ long rate = clk_get_rate(m6_clk_parent);
+ pr_err("stm_ti1.0: m6_clk_parent %ld\n", rate);
+
+ }
+
+// ret = clk_set_rate(m6_clk_parent, 17777777);
+ ret = clk_set_rate(m6_clk_parent, 166666666);
+
+ {
+ long rate = clk_get_rate(m6_clk_parent);
+ pr_err("stm_ti1.0: m6_clk_parent %ld\n", rate);
+
+ }
+
+ pdm_stm_mux_clk = clk_get(NULL, "pmd_stm_clock_mux_ck");
+ ret = clk_set_parent( pdm_stm_mux_clk, m6_clk_parent);
+
+
+ /* Set ownership of module to app and enable */
+ ret = stm_set_enable();
+ if (ret) {
+// ret = -EACCES;
+// goto stm_config_write_exit;
+ pr_err("stm_ti1.0: STM module ownership not granted or STM enable failed %d\n", ret);
+ }
+#endif
+
/* Register with the STM Framework Drvier */
ret = stm_register(&stm_ti_ops);
if (ret < 0)
@@ -909,6 +1094,9 @@ int __init stm_ti_init(void)
mutex_init(&dev.lock);
INIT_LIST_HEAD(&dev.chn_list_head);
dev.user_allocated_chn_cnt = 0;
+ dev.stm_module_enable = true;
+ dev.route_stm_to_pti = 1;
+ dev.route_stm_to_etb = 0;
return ret;
@@ -943,7 +1131,7 @@ static struct chn_alloc *construct_chn_obj(int chn, int chn_num)
chn_obj = kmalloc(sizeof(struct chn_alloc), GFP_KERNEL);
if (!chn_obj)
- return (struct chn_alloc *)-ENOMEM;
+ return ERR_PTR(-ENOMEM);
mutex_init(&chn_obj->chn_lock);
chn_obj->chn = chn;
@@ -1245,6 +1433,29 @@ stm_app_ownership_exit:
return ret;
}
+static int stm_set_enable()
+{
+ uint32_t control;
+ /*
+ * if avaiable set ownership to application (verses host
+ * debugger)
+ */
+ if (!stm_app_ownership())
+ return -EACCES;
+
+ iowrite32(STM_MODULE_ENABLE, (void *)(stm_cntl_iobase
+ + STM_SWMCTRL0_OFFSET));
+
+ control = ioread32((void *)(stm_cntl_iobase
+ + STM_SWMCTRL0_OFFSET));
+
+ if ((control & STM_OWNERSHIP_MASK) != STM_OWNERSHIP_ENABLED)
+ return -EFAULT;
+
+ return 0;
+
+}
+
static bool stm_test_enable()
{
uint32_t control;