diff options
author | RGIB <gibellini.roberto@gmail.com> | 2016-05-27 15:41:13 +0200 |
---|---|---|
committer | Roberto Gibellini <gibellini.roberto@gmail.com> | 2016-05-27 06:45:25 -0700 |
commit | 462bab3a059ebeeb45dc3ebfef4ee8b39a4757e3 (patch) | |
tree | 7f5dc0a29e59087c4e83fe88173d3ce64a93d4e1 /drivers/misc/modem_if/sipc5_common.c | |
parent | 206f43e8ae09166ba608f520c60bb208661769ca (diff) | |
download | kernel_samsung_smdk4412-462bab3a059ebeeb45dc3ebfef4ee8b39a4757e3.zip kernel_samsung_smdk4412-462bab3a059ebeeb45dc3ebfef4ee8b39a4757e3.tar.gz kernel_samsung_smdk4412-462bab3a059ebeeb45dc3ebfef4ee8b39a4757e3.tar.bz2 |
smdk4412 : modem_if KK driver from N5100ZTCNL4
Change-Id: I7d1e6412700b5db293448aca99c53ac4a52fc1a8
Diffstat (limited to 'drivers/misc/modem_if/sipc5_common.c')
-rw-r--r-- | drivers/misc/modem_if/sipc5_common.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/drivers/misc/modem_if/sipc5_common.c b/drivers/misc/modem_if/sipc5_common.c new file mode 100644 index 0000000..e8574c2 --- /dev/null +++ b/drivers/misc/modem_if/sipc5_common.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2010 Samsung Electronics. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/poll.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/if_arp.h> +#include <linux/ip.h> +#include <linux/if_ether.h> +#include <linux/etherdevice.h> +#include <linux/device.h> + +#include "modem.h" +#include "modem_prj.h" +#include "modem_utils.h" + +/** + * sipc5_start_valid + * @cfg: configuration field of an SIPC5 link frame + * + * Returns TRUE if the start (configuration field) of an SIPC5 link frame + * is valid or returns FALSE if it is not valid. + * + */ +bool sipc5_start_valid(u8 *frm) +{ + return (*frm & SIPC5_START_MASK) == SIPC5_START_MASK; +} + +bool sipc5_padding_exist(u8 *frm) +{ + return (*frm & SIPC5_PADDING_EXIST) ? true : false; +} + +bool sipc5_multi_frame(u8 *frm) +{ + return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_CTL_FIELD_MASK; +} + +bool sipc5_ext_len(u8 *frm) +{ + return (*frm & SIPC5_EXT_FIELD_MASK) == SIPC5_EXT_LENGTH_MASK; +} + +/** + * sipc5_get_hdr_len + * @cfg: configuration field of an SIPC5 link frame + * + * Returns the length of SIPC5 link layer header in an SIPC5 link frame + * + */ +int sipc5_get_hdr_len(u8 *frm) +{ + if (*frm & SIPC5_EXT_FIELD_EXIST) { + if (*frm & SIPC5_CTL_FIELD_EXIST) + return SIPC5_HEADER_SIZE_WITH_CTL_FLD; + else + return SIPC5_HEADER_SIZE_WITH_EXT_LEN; + } else { + return SIPC5_MIN_HEADER_SIZE; + } +} + +/** + * sipc5_get_ch_id + * @frm: pointer to an SIPC5 frame + * + * Returns the channel ID in an SIPC5 link frame + * + */ +u8 sipc5_get_ch_id(u8 *frm) +{ + return *(frm + SIPC5_CH_ID_OFFSET); +} + +/** + * sipc5_get_ctrl_field + * @frm: pointer to an SIPC5 frame + * + * Returns the control field in an SIPC5 link frame + * + */ +u8 sipc5_get_ctrl_field(u8 *frm) +{ + return *(frm + SIPC5_CTL_OFFSET); +} + +/** + * sipc5_get_frame_len + * @frm: pointer to an SIPC5 link frame + * + * Returns the length of an SIPC5 link frame + * + */ +int sipc5_get_frame_len(u8 *frm) +{ + u8 cfg = frm[0]; + u16 *sz16 = (u16 *)(frm + SIPC5_LEN_OFFSET); + u32 *sz32 = (u32 *)(frm + SIPC5_LEN_OFFSET); + + if (unlikely(cfg & SIPC5_EXT_FIELD_EXIST)) { + if (cfg & SIPC5_CTL_FIELD_EXIST) + return (int)(*sz16); + else + return (int)(*sz32); + } else { + return (int)(*sz16); + } +} + +/** + * sipc5_calc_padding_size + * @len: length of an SIPC5 link frame + * + * Returns the padding size for an SIPC5 link frame + * + */ +int sipc5_calc_padding_size(int len) +{ + int residue = len & 0x3; + return residue ? (4 - residue) : 0; +} + +/** + * sipc5_get_total_len + * @frm: pointer to an SIPC5 link frame + * + * Returns the total length of an SIPC5 link frame with padding + * + */ +int sipc5_get_total_len(u8 *frm) +{ + int len = sipc5_get_frame_len(frm); + int pad = sipc5_padding_exist(frm) ? sipc5_calc_padding_size(len) : 0; + return len + pad; +} + +/** + * sipc5_build_config + * @iod: pointer to the IO device + * @ld: pointer to the link device + * @count: length of the data to be transmitted + * + * Builds a config value for an SIPC5 link frame header + * + * Returns the config value for the header or 0 for non-SIPC formats + */ +u8 sipc5_build_config(struct io_device *iod, struct link_device *ld, u32 count) +{ + u8 cfg = SIPC5_START_MASK; + + if (iod->format > IPC_MULTI_RAW && iod->id == 0) + return 0; + + if (ld->aligned) + cfg |= SIPC5_PADDING_EXIST; + +#if 0 + if ((count + SIPC5_MIN_HEADER_SIZE) > ld->mtu[dev]) + cfg |= SIPC5_CTL_FIELD_MASK; + else +#endif + if ((count + SIPC5_MIN_HEADER_SIZE) > 0xFFFF) + cfg |= SIPC5_EXT_LENGTH_MASK; + + return cfg; +} + +/** + * sipc5_build_header + * @iod: pointer to the IO device + * @ld: pointer to the link device + * @buff: pointer to a buffer in which an SIPC5 link frame header will be stored + * @cfg: value for the config field in the header + * @ctrl: value for the control field in the header + * @count: length of data in the SIPC5 link frame to be transmitted + * + * Builds the link layer header of an SIPC5 frame + */ +void sipc5_build_header(struct io_device *iod, struct link_device *ld, + u8 *buff, u8 cfg, u8 ctrl, u32 count) +{ + u16 *sz16 = (u16 *)(buff + SIPC5_LEN_OFFSET); + u32 *sz32 = (u32 *)(buff + SIPC5_LEN_OFFSET); + u32 hdr_len = sipc5_get_hdr_len(&cfg); + + /* Store the config field and the channel ID field */ + buff[SIPC5_CONFIG_OFFSET] = cfg; + buff[SIPC5_CH_ID_OFFSET] = iod->id; + + /* Store the frame length field */ + if (sipc5_ext_len(buff)) + *sz32 = (u32)(hdr_len + count); + else + *sz16 = (u16)(hdr_len + count); + + /* Store the control field */ + if (sipc5_multi_frame(buff)) + buff[SIPC5_CTL_OFFSET] = ctrl; +} + +/** + * std_udl_get_cmd + * @frm: pointer to an SIPC5 link frame + * + * Returns the standard BOOT/DUMP (STD_UDL) command in an SIPC5 BOOT/DUMP frame. + */ +u32 std_udl_get_cmd(u8 *frm) +{ + u8 *cmd = frm + sipc5_get_hdr_len(frm); + return *((u32 *)cmd); +} + +/** + * std_udl_with_payload + * @cmd: standard BOOT/DUMP command + * + * Returns true if the STD_UDL command has a payload. + */ +bool std_udl_with_payload(u32 cmd) +{ + u32 mask = cmd & STD_UDL_STEP_MASK; + return (mask && mask < STD_UDL_CRC) ? true : false; +} + |