From d49ba79e42b7bd5fae984fd0800cd618919d4ade Mon Sep 17 00:00:00 2001 From: Ryan Harkin Date: Mon, 20 Aug 2012 11:12:00 +0100 Subject: drivers/stm: add kernel side API Latest code from Doug Deao @ TI to add a kernel side API to the STM framework. Signed-off-by: Ryan Harkin --- drivers/stm/stm_fw.c | 198 +++++++++++++++++++++++++---- drivers/stm/stm_fw.h | 7 ++ drivers/stm/stm_omap_ti1.0.c | 287 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 430 insertions(+), 62 deletions(-) mode change 100644 => 100755 drivers/stm/stm_fw.h mode change 100644 => 100755 drivers/stm/stm_omap_ti1.0.c diff --git a/drivers/stm/stm_fw.c b/drivers/stm/stm_fw.c index 057963c65e7..1ef1bda8080 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 old mode 100644 new mode 100755 index bcaa307d0ad..df95d415914 --- 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 old mode 100644 new mode 100755 index 9dbdb984a36..8300534677b --- a/drivers/stm/stm_omap_ti1.0.c +++ b/drivers/stm/stm_omap_ti1.0.c @@ -47,7 +47,7 @@ #include #include #include - +#include #include #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; -- cgit v1.2.3