From 14d9a53162ec4beedd63e132b059d4971836dfba Mon Sep 17 00:00:00 2001 From: Oron Peled Date: Mon, 16 Nov 2015 15:42:21 -0500 Subject: [PATCH] xpp: support for RAM type register commands Signed-off-by: Tzafrir Cohen --- drivers/dahdi/xpp/card_fxs.c | 22 +++++++- drivers/dahdi/xpp/card_global.c | 99 ++++++++++++++++++++++++++++++++- drivers/dahdi/xpp/card_global.h | 9 +++ drivers/dahdi/xpp/xbus-sysfs.c | 14 ++++- drivers/dahdi/xpp/xproto.c | 19 +++++++ drivers/dahdi/xpp/xproto.h | 16 ++++++ 6 files changed, 176 insertions(+), 3 deletions(-) diff --git a/drivers/dahdi/xpp/card_fxs.c b/drivers/dahdi/xpp/card_fxs.c index ddb6e2f..fc5a9af 100644 --- a/drivers/dahdi/xpp/card_fxs.c +++ b/drivers/dahdi/xpp/card_fxs.c @@ -81,6 +81,9 @@ enum fxs_leds { #define SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH) \ xpp_register_request((xbus), (xpd), (port), \ (writing), 0x1E, 1, (reg), (dL), 1, (dH), 0) +#define RAM_REQUEST(xbus, xpd, port, writing, addr, data) \ + xpp_ram_request((xbus), (xpd), (port), \ + (writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0) #define VALID_PORT(port) \ (((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST) @@ -1595,7 +1598,24 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) (indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high)); } - if (!indirect && regnum == REG_TYPE1_DTMF_DECODE) { + if (info->h.bytes == REG_CMD_SIZE(RAM)) { + uint addr; + unsigned long val; + XPD_INFO(xpd, "RAM reply is not fully implemented(%s)\n", __func__); + XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n", + info->h.portnum, + REG_FIELD_RAM(info, addr_low), + REG_FIELD_RAM(info, addr_high), + REG_FIELD_RAM(info, data_0), + REG_FIELD_RAM(info, data_1), + REG_FIELD_RAM(info, data_2), + REG_FIELD_RAM(info, data_3)); + addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low); + val = (REG_FIELD_RAM(info, data_3) << 24) | + (REG_FIELD_RAM(info, data_2) << 16) | + (REG_FIELD_RAM(info, data_1) << 8) | + REG_FIELD_RAM(info, data_0); + } else if (!indirect && regnum == REG_TYPE1_DTMF_DECODE) { __u8 val = REG_FIELD(info, data_low); process_dtmf(xpd, info->h.portnum, val); diff --git a/drivers/dahdi/xpp/card_global.c b/drivers/dahdi/xpp/card_global.c index 989c01f..c5f9f1c 100644 --- a/drivers/dahdi/xpp/card_global.c +++ b/drivers/dahdi/xpp/card_global.c @@ -90,7 +90,7 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[]) int portno; bool writing; int op; /* [W]rite, [R]ead */ - int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */ + int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */ bool do_subreg = 0; int regnum; int subreg; @@ -169,6 +169,16 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[]) num_args--; /* No data low */ //XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode); break; + case 'R': + switch (op) { + case 'W': + num_args += 5; /* add: addr_high, data_[0-3] */ + break; + case 'R': + num_args += 2; /* add: addr_low, addr_high */ + break; + } + break; default: XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode); goto out; @@ -197,6 +207,31 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[]) addr_mode == 'm'); goto out; } + if (addr_mode == 'R') { + __u8 input[6]; + int i; + + if (num_args - 2 > 6) { + XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2); + goto out; + } + for (i = 0; i < num_args - 2; i++, argno++) { + input[i] = parse_hexbyte(argv[argno]); + if (input[i] < 0) { + XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]); + goto out; + } + } + ret = xpp_ram_request(xpd->xbus, xpd, portno, writing, + input[0], + input[1], + input[2], + input[3], + input[4], + input[5], + 1); + goto out; + } /* Normal (non-Magic) register commands */ do_datah = 0; if (argno >= argc) { @@ -415,6 +450,67 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, } EXPORT_SYMBOL(xpp_register_request); +int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, + bool writing, + __u8 addr_low, + __u8 addr_high, + __u8 data_0, + __u8 data_1, + __u8 data_2, + __u8 data_3, + bool should_reply) +{ + int ret = 0; + xframe_t *xframe; + xpacket_t *pack; + reg_cmd_t *reg_cmd; + + if (!xbus) { + DBG(REGS, "NO XBUS\n"); + return -EINVAL; + } + XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx); + LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n", + (writing) ? 'W' : 'R', + addr_low, addr_high, + data_0, data_1, data_2, data_3); + reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); + /* do not count the 'bytes' field */ + reg_cmd->h.bytes = REG_CMD_SIZE(RAM); + reg_cmd->h.is_multibyte = 0; + if (portno == PORT_BROADCAST) { + reg_cmd->h.portnum = 0; + REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1; + } else { + reg_cmd->h.portnum = portno; + REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0; + } + reg_cmd->h.eoframe = 0; + REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ + REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1; + REG_FIELD_RAM(reg_cmd, do_datah) = 1; + REG_FIELD_RAM(reg_cmd, do_subreg) = 1; + REG_FIELD_RAM(reg_cmd, addr_low) = addr_low; + REG_FIELD_RAM(reg_cmd, addr_high) = addr_high; + REG_FIELD_RAM(reg_cmd, data_0) = data_0; + REG_FIELD_RAM(reg_cmd, data_1) = data_1; + REG_FIELD_RAM(reg_cmd, data_2) = data_2; + REG_FIELD_RAM(reg_cmd, data_3) = data_3; + if (should_reply) + xpd->requested_reply = *reg_cmd; + if (debug & DBG_REGS) { + dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit, + reg_cmd->h.portnum, reg_cmd); + dump_packet("REG_RAM", pack, 1); + } + if (!xframe->usec_towait) { /* default processing time of SPI */ + xframe->usec_towait = 1000; + } + ret = send_cmd_frame(xbus, xframe); + return ret; +} +EXPORT_SYMBOL(xpp_ram_request); + /* * The XPD parameter is totaly ignored by the driver and firmware as well. */ @@ -594,6 +690,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY) } switch (reg->h.bytes) { case REG_CMD_SIZE(REG): + case REG_CMD_SIZE(RAM): return CALL_XMETHOD(card_register_reply, xpd, reg); } XPD_ERR(xpd, "REGISTER_REPLY: bad packet_len=%d\n", pack->head.packet_len); diff --git a/drivers/dahdi/xpp/card_global.h b/drivers/dahdi/xpp/card_global.h index 14fec6c..86d4431 100644 --- a/drivers/dahdi/xpp/card_global.h +++ b/drivers/dahdi/xpp/card_global.h @@ -77,6 +77,15 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, bool should_reply); int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno, bool eoftx, __u8 *buf, unsigned len); +int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno, + bool writing, + __u8 addr_low, + __u8 addr_high, + __u8 data_0, + __u8 data_1, + __u8 data_2, + __u8 data_3, + bool should_reply); extern xproto_table_t PROTO_TABLE(GLOBAL); int run_initialize_registers(xpd_t *xpd); int parse_chip_command(xpd_t *xpd, char *cmdline); diff --git a/drivers/dahdi/xpp/xbus-sysfs.c b/drivers/dahdi/xpp/xbus-sysfs.c index de84dad..8e81670 100644 --- a/drivers/dahdi/xpp/xbus-sysfs.c +++ b/drivers/dahdi/xpp/xbus-sysfs.c @@ -518,7 +518,19 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf) REG_FIELD(regs, data_high)); } else datah_str[0] = '\0'; - if (REG_FIELD(regs, do_subreg)) { + if (regs->h.bytes == REG_CMD_SIZE(RAM)) { + len += + sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n"); + len += + sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n", + regs->h.portnum, + REG_FIELD_RAM(regs, addr_low), + REG_FIELD_RAM(regs, addr_high), + REG_FIELD_RAM(regs, data_0), + REG_FIELD_RAM(regs, data_1), + REG_FIELD_RAM(regs, data_2), + REG_FIELD_RAM(regs, data_3)); + } else if (REG_FIELD(regs, do_subreg)) { len += sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n", (do_datah) ? "\tDH" : ""); diff --git a/drivers/dahdi/xpp/xproto.c b/drivers/dahdi/xpp/xproto.c index 4e977c4..cd4b34c 100644 --- a/drivers/dahdi/xpp/xproto.c +++ b/drivers/dahdi/xpp/xproto.c @@ -387,6 +387,25 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, msg, regcmd->h.bytes); return; } + if (regcmd->h.bytes == REG_CMD_SIZE(RAM)) { + snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum, + (REG_FIELD_RAM(regcmd, all_ports_broadcast)) ? "*" : ""); + if (REG_FIELD_RAM(regcmd, read_request)) { + action = 'R'; + } else { + action = 'W'; + } + PORT_DBG(REGS, xbus, unit, port, + "%s: %s %cR %02X %02X %02X %02X %02X %02X\n", + msg, port_buf, action, + REG_FIELD_RAM(regcmd, addr_low), + REG_FIELD_RAM(regcmd, addr_high), + REG_FIELD_RAM(regcmd, data_0), + REG_FIELD_RAM(regcmd, data_1), + REG_FIELD_RAM(regcmd, data_2), + REG_FIELD_RAM(regcmd, data_3)); + return; + } if (regcmd->h.is_multibyte) { char buf[MAX_PROC_WRITE + 1]; int i; diff --git a/drivers/dahdi/xpp/xproto.h b/drivers/dahdi/xpp/xproto.h index 20e25be..534a0cd 100644 --- a/drivers/dahdi/xpp/xproto.h +++ b/drivers/dahdi/xpp/xproto.h @@ -188,6 +188,20 @@ struct reg_cmd_REG { __u8 data_high; } PACKED; +struct reg_cmd_RAM { + __u8 reserved:4; + __u8 do_datah:1; + __u8 do_subreg:1; + __u8 read_request:1; + __u8 all_ports_broadcast:1; + __u8 addr_low; + __u8 addr_high; + __u8 data_0; + __u8 data_1; + __u8 data_2; + __u8 data_3; +} PACKED; + typedef struct reg_cmd { struct reg_cmd_header h; union { @@ -196,6 +210,7 @@ typedef struct reg_cmd { struct { __u8 xdata[MULTIBYTE_MAX_LEN]; } PACKED d; + struct reg_cmd_RAM m; } PACKED alt; } PACKED reg_cmd_t; @@ -203,6 +218,7 @@ typedef struct reg_cmd { #define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant)) #define REG_FIELD(regptr, member) ((regptr)->alt.r.member) #define REG_XDATA(regptr) ((regptr)->alt.d.xdata) +#define REG_FIELD_RAM(regptr, member) ((regptr)->alt.m.member) #ifdef __KERNEL__