Loading drivers/slimbus/slim-msm.c +90 −11 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/slimbus/slimbus.h> #include <linux/msm-sps.h> #include <linux/gcd.h> #include "slim-msm.h" int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len) Loading Loading @@ -188,12 +189,54 @@ msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem) mem->phys_base = 0; } void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn) void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pipenum, u8 portnum) { u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT; writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver)); writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver)); writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver)); struct slim_controller *ctrl; struct slim_ch *chan; struct msm_slim_pshpull_parm *parm; u32 set_cfg = 0; struct slim_port_cfg cfg = dev->ctrl.ports[portnum].cfg; if (!dev) { pr_err("%s:Dev node is null\n", __func__); return; } if (portnum >= dev->port_nums) { pr_err("%s:Invalid port\n", __func__); return; } ctrl = &dev->ctrl; chan = ctrl->ports[portnum].ch; parm = &dev->pipes[portnum].psh_pull; if (cfg.watermark) set_cfg = (cfg.watermark << 1); else set_cfg = DEF_WATERMARK; if (cfg.port_opts & SLIM_OPT_NO_PACK) set_cfg |= DEF_NO_PACK; else set_cfg |= DEF_PACK; if (cfg.port_opts & SLIM_OPT_ALIGN_MSB) set_cfg |= DEF_ALIGN_MSB; else set_cfg |= DEF_ALIGN_LSB; set_cfg |= ENABLE_PORT; writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pipenum, dev->ver)); writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pipenum, dev->ver)); writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pipenum, dev->ver)); if (chan->prot == SLIM_PUSH || chan->prot == SLIM_PULL) { set_cfg = 0; set_cfg |= ((0xFFFF & parm->num_samples)<<16); set_cfg |= (0xFFFF & parm->rpt_period); writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_PSHPLLn, pipenum, dev->ver)); } /* Make sure that port registers are updated before returning */ mb(); } Loading @@ -216,15 +259,49 @@ static void msm_slim_disconn_pipe_port(struct msm_slim_ctrl *dev, u8 pn) dev->pipes[pn].connected = false; } int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) static void msm_slim_calc_pshpull_parm(struct msm_slim_ctrl *dev, u8 pn, struct slim_ch *prop) { struct msm_slim_endp *endpoint = &dev->pipes[pn]; struct sps_connect *cfg = &endpoint->config; struct msm_slim_pshpull_parm *parm = &endpoint->psh_pull; int chan_freq, round_off, divisor, super_freq; super_freq = dev->ctrl.a_framer->superfreq; if (prop->baser == SLIM_RATE_4000HZ) chan_freq = 4000 * prop->ratem; else if (prop->baser == SLIM_RATE_11025HZ) chan_freq = 11025 * prop->ratem; else chan_freq = prop->baser * prop->ratem; /* * If channel frequency is multiple of super frame frequency * ISO protocol is suggested */ if (!(chan_freq % super_freq)) { prop->prot = SLIM_HARD_ISO; return; } round_off = DIV_ROUND_UP(chan_freq, super_freq); divisor = gcd(round_off * super_freq, chan_freq); parm->num_samples = chan_freq/divisor; parm->rpt_period = (round_off * super_freq)/divisor; } int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) { struct msm_slim_endp *endpoint; struct sps_connect *cfg; struct slim_ch *prop; u32 stat; int ret; if (pn >= dev->port_nums) if (!dev || pn >= dev->port_nums) return -ENODEV; endpoint = &dev->pipes[pn]; cfg = &endpoint->config; prop = dev->ctrl.ports[pn].ch; endpoint = &dev->pipes[pn]; ret = sps_get_config(dev->pipes[pn].sps, cfg); Loading @@ -235,6 +312,9 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR | SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE; if (prop->prot == SLIM_PUSH || prop->prot == SLIM_PULL) msm_slim_calc_pshpull_parm(dev, pn, prop); if (dev->pipes[pn].connected && dev->ctrl.ports[pn].state == SLIM_P_CFG) { return -EISCONN; Loading @@ -248,7 +328,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) cfg->mode == SPS_MODE_DEST) || (dev->ctrl.ports[pn].flow == SLIM_SINK && cfg->mode == SPS_MODE_SRC)) { msm_hw_set_port(dev, endpoint->port_b); msm_hw_set_port(dev, endpoint->port_b, pn); return 0; } msm_slim_disconn_pipe_port(dev, pn); Loading Loading @@ -283,7 +363,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) if (!ret) { dev->pipes[pn].connected = true; msm_hw_set_port(dev, endpoint->port_b); msm_hw_set_port(dev, endpoint->port_b, pn); } return ret; } Loading Loading @@ -1093,7 +1173,6 @@ void msm_slim_deinit_ep(struct msm_slim_ctrl *dev, static void msm_slim_sps_unreg_event(struct sps_pipe *sps) { struct sps_register_event sps_event; memset(&sps_event, 0x00, sizeof(sps_event)); /* Disable interrupt and signal notification for Rx/Tx pipe */ sps_register_event(sps, &sps_event); Loading drivers/slimbus/slim-msm.h +16 −2 Original line number Diff line number Diff line Loading @@ -71,9 +71,12 @@ #define DEF_RETRY_MS 10 #define MSM_CONCUR_MSG 8 #define SAT_CONCUR_MSG 8 #define DEF_WATERMARK (8 << 1) #define DEF_ALIGN 0 #define DEF_ALIGN_LSB 0 #define DEF_ALIGN_MSB (1 << 7) #define DEF_PACK (1 << 6) #define DEF_NO_PACK 0 #define ENABLE_PORT 1 #define DEF_BLKSZ 0 Loading Loading @@ -197,6 +200,16 @@ struct msm_slim_sps_bam { int irq; }; /* * struct slim_pshpull_parm: Structure to store push pull protocol parameters * @num_samples: Number of samples in a period * @rpt_period: Repeat period value */ struct msm_slim_pshpull_parm { int num_samples; int rpt_period; }; struct msm_slim_endp { struct sps_pipe *sps; struct sps_connect config; Loading @@ -204,6 +217,7 @@ struct msm_slim_endp { struct sps_mem_buffer buf; bool connected; int port_b; struct msm_slim_pshpull_parm psh_pull; }; struct msm_slim_qmi { Loading Loading @@ -385,7 +399,7 @@ void msm_slim_put_ctrl(struct msm_slim_ctrl *dev); irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat); int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep); void msm_slim_free_endpoint(struct msm_slim_endp *ep); void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn); void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pipenum, u8 portnum); int msm_alloc_port(struct slim_controller *ctrl, u8 pn); void msm_dealloc_port(struct slim_controller *ctrl, u8 pn); int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn); Loading drivers/slimbus/slimbus.c +53 −7 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,39 @@ int slim_dealloc_mgrports(struct slim_device *sb, u32 *hdl, int nports) } EXPORT_SYMBOL_GPL(slim_dealloc_mgrports); /* * slim_config_mgrports: Configure manager side ports * @sb: device/client handle. * @ph: array of port handles for which this configuration is valid * @nports: Number of ports in ph * @cfg: configuration requested for port(s) * Configure port settings if they are different than the default ones. * Returns success if the config could be applied. Returns -EISCONN if the * port is in use */ int slim_config_mgrports(struct slim_device *sb, u32 *ph, int nports, struct slim_port_cfg *cfg) { int i; struct slim_controller *ctrl; if (!sb || !ph || !nports || !sb->ctrl || !cfg) return -EINVAL; ctrl = sb->ctrl; mutex_lock(&ctrl->sched.m_reconf); for (i = 0; i < nports; i++) { u8 pn = SLIM_HDL_TO_PORT(ph[i]); if (ctrl->ports[pn].state == SLIM_P_CFG) return -EISCONN; ctrl->ports[pn].cfg = *cfg; } mutex_unlock(&ctrl->sched.m_reconf); return 0; } EXPORT_SYMBOL(slim_config_mgrports); /* * slim_get_slaveport: Get slave port handle * @la: slave device logical address. Loading Loading @@ -1331,8 +1364,12 @@ static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph) ret = slim_processtxn(ctrl, &txn, false); if (ret) return ret; if (la == SLIM_LA_MANAGER) if (la == SLIM_LA_MANAGER) { ctrl->ports[pn].state = SLIM_P_UNCFG; ctrl->ports[pn].cfg.watermark = 0; ctrl->ports[pn].cfg.port_opts = 0; ctrl->ports[pn].ch = NULL; } return 0; } Loading @@ -1356,6 +1393,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) struct slim_ich *slc = &ctrl->chans[chan]; enum slim_port_flow flow = SLIM_HDL_TO_FLOW(srch); u8 la = SLIM_HDL_TO_LA(srch); u8 pn = SLIM_HDL_TO_PORT(srch); /* manager ports don't have direction when they are allocated */ if (la != SLIM_LA_MANAGER && flow != SLIM_SRC) Loading @@ -1364,7 +1402,6 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) mutex_lock(&ctrl->sched.m_reconf); if (la == SLIM_LA_MANAGER) { u8 pn = SLIM_HDL_TO_PORT(srch); if (pn >= ctrl->nports || ctrl->ports[pn].state != SLIM_P_UNCFG) { ret = -EINVAL; Loading @@ -1385,7 +1422,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) ret = -EALREADY; goto connect_src_err; } ctrl->ports[pn].ch = &slc->prop; ret = connect_port_ch(ctrl, chan, srch, SLIM_SRC); if (!ret) Loading Loading @@ -1444,8 +1481,10 @@ int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink, u16 chanh) (pn >= ctrl->nports || ctrl->ports[pn].state != SLIM_P_UNCFG)) ret = -EINVAL; else else { ctrl->ports[pn].ch = &slc->prop; ret = connect_port_ch(ctrl, chan, sinkh[j], SLIM_SINK); } if (ret) { for (j = j - 1; j >= 0; j--) disconnect_port_ch(ctrl, sinkh[j]); Loading Loading @@ -1638,14 +1677,21 @@ static int slim_remove_ch(struct slim_controller *ctrl, struct slim_ich *slc) * disconnect. It is client's responsibility to call disconnect * on ports owned by the slave device */ if (la == SLIM_LA_MANAGER) if (la == SLIM_LA_MANAGER) { ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG; ctrl->ports[SLIM_HDL_TO_PORT(ph)].ch = NULL; } } ph = slc->srch; la = SLIM_HDL_TO_LA(ph); if (la == SLIM_LA_MANAGER) ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG; if (la == SLIM_LA_MANAGER) { u8 pn = SLIM_HDL_TO_PORT(ph); ctrl->ports[pn].state = SLIM_P_UNCFG; ctrl->ports[pn].cfg.watermark = 0; ctrl->ports[pn].cfg.port_opts = 0; } kfree(slc->sinkh); slc->sinkh = NULL; Loading include/linux/slimbus/slimbus.h +30 −7 Original line number Diff line number Diff line Loading @@ -226,13 +226,13 @@ enum slim_port_req { }; /* * enum slim_port_cfg: Port configuration parameters requested. * User can request no configuration, packed data, or MSB aligned data port * enum slim_port_opts: Port options requested. * User can request no configuration, packed data, and/or MSB aligned data port */ enum slim_port_cfg { SLIM_CFG_NONE, SLIM_CFG_PACKED, SLIM_CFG_ALIGN_MSB, enum slim_port_opts { SLIM_OPT_NONE = 0, SLIM_OPT_NO_PACK = 1U, SLIM_OPT_ALIGN_MSB = 1U << 1, }; /* enum slim_port_flow: Port flow type (inbound/outbound). */ Loading @@ -250,6 +250,16 @@ enum slim_port_err { SLIM_P_NOT_OWNED, }; /* * struct slim_port_cfg: Port config for the manager port * port_opts: port options (bit-map) for this port * watermark: watermark level set for this port */ struct slim_port_cfg { u32 port_opts; u32 watermark; }; /* * struct slim_port: Internal structure used by framework to manage ports * @err: Port error if any for this port. Refer to enum above. Loading @@ -267,7 +277,7 @@ struct slim_port { enum slim_port_err err; enum slim_port_state state; enum slim_port_req req; enum slim_port_cfg cfg; struct slim_port_cfg cfg; enum slim_port_flow flow; struct slim_ch *ch; struct completion *xcomp; Loading Loading @@ -834,6 +844,19 @@ extern int slim_alloc_mgrports(struct slim_device *sb, enum slim_port_req req, /* Deallocate the port(s) allocated using the API above */ extern int slim_dealloc_mgrports(struct slim_device *sb, u32 *hdl, int hsz); /* * slim_config_mgrports: Configure manager side ports * @sb: device/client handle. * @ph: array of port handles for which this configuration is valid * @nports: Number of ports in ph * @cfg: configuration requested for port(s) * Configure port settings if they are different than the default ones. * Returns success if the config could be applied. Returns -EISCONN if the * port is in use */ extern int slim_config_mgrports(struct slim_device *sb, u32 *ph, int nports, struct slim_port_cfg *cfg); /* * slim_port_xfer: Schedule buffer to be transferred/received using port-handle. * @sb: client handle Loading Loading
drivers/slimbus/slim-msm.c +90 −11 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/slimbus/slimbus.h> #include <linux/msm-sps.h> #include <linux/gcd.h> #include "slim-msm.h" int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len) Loading Loading @@ -188,12 +189,54 @@ msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem) mem->phys_base = 0; } void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn) void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pipenum, u8 portnum) { u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT; writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver)); writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver)); writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver)); struct slim_controller *ctrl; struct slim_ch *chan; struct msm_slim_pshpull_parm *parm; u32 set_cfg = 0; struct slim_port_cfg cfg = dev->ctrl.ports[portnum].cfg; if (!dev) { pr_err("%s:Dev node is null\n", __func__); return; } if (portnum >= dev->port_nums) { pr_err("%s:Invalid port\n", __func__); return; } ctrl = &dev->ctrl; chan = ctrl->ports[portnum].ch; parm = &dev->pipes[portnum].psh_pull; if (cfg.watermark) set_cfg = (cfg.watermark << 1); else set_cfg = DEF_WATERMARK; if (cfg.port_opts & SLIM_OPT_NO_PACK) set_cfg |= DEF_NO_PACK; else set_cfg |= DEF_PACK; if (cfg.port_opts & SLIM_OPT_ALIGN_MSB) set_cfg |= DEF_ALIGN_MSB; else set_cfg |= DEF_ALIGN_LSB; set_cfg |= ENABLE_PORT; writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pipenum, dev->ver)); writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pipenum, dev->ver)); writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pipenum, dev->ver)); if (chan->prot == SLIM_PUSH || chan->prot == SLIM_PULL) { set_cfg = 0; set_cfg |= ((0xFFFF & parm->num_samples)<<16); set_cfg |= (0xFFFF & parm->rpt_period); writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_PSHPLLn, pipenum, dev->ver)); } /* Make sure that port registers are updated before returning */ mb(); } Loading @@ -216,15 +259,49 @@ static void msm_slim_disconn_pipe_port(struct msm_slim_ctrl *dev, u8 pn) dev->pipes[pn].connected = false; } int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) static void msm_slim_calc_pshpull_parm(struct msm_slim_ctrl *dev, u8 pn, struct slim_ch *prop) { struct msm_slim_endp *endpoint = &dev->pipes[pn]; struct sps_connect *cfg = &endpoint->config; struct msm_slim_pshpull_parm *parm = &endpoint->psh_pull; int chan_freq, round_off, divisor, super_freq; super_freq = dev->ctrl.a_framer->superfreq; if (prop->baser == SLIM_RATE_4000HZ) chan_freq = 4000 * prop->ratem; else if (prop->baser == SLIM_RATE_11025HZ) chan_freq = 11025 * prop->ratem; else chan_freq = prop->baser * prop->ratem; /* * If channel frequency is multiple of super frame frequency * ISO protocol is suggested */ if (!(chan_freq % super_freq)) { prop->prot = SLIM_HARD_ISO; return; } round_off = DIV_ROUND_UP(chan_freq, super_freq); divisor = gcd(round_off * super_freq, chan_freq); parm->num_samples = chan_freq/divisor; parm->rpt_period = (round_off * super_freq)/divisor; } int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) { struct msm_slim_endp *endpoint; struct sps_connect *cfg; struct slim_ch *prop; u32 stat; int ret; if (pn >= dev->port_nums) if (!dev || pn >= dev->port_nums) return -ENODEV; endpoint = &dev->pipes[pn]; cfg = &endpoint->config; prop = dev->ctrl.ports[pn].ch; endpoint = &dev->pipes[pn]; ret = sps_get_config(dev->pipes[pn].sps, cfg); Loading @@ -235,6 +312,9 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR | SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE; if (prop->prot == SLIM_PUSH || prop->prot == SLIM_PULL) msm_slim_calc_pshpull_parm(dev, pn, prop); if (dev->pipes[pn].connected && dev->ctrl.ports[pn].state == SLIM_P_CFG) { return -EISCONN; Loading @@ -248,7 +328,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) cfg->mode == SPS_MODE_DEST) || (dev->ctrl.ports[pn].flow == SLIM_SINK && cfg->mode == SPS_MODE_SRC)) { msm_hw_set_port(dev, endpoint->port_b); msm_hw_set_port(dev, endpoint->port_b, pn); return 0; } msm_slim_disconn_pipe_port(dev, pn); Loading Loading @@ -283,7 +363,7 @@ int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn) if (!ret) { dev->pipes[pn].connected = true; msm_hw_set_port(dev, endpoint->port_b); msm_hw_set_port(dev, endpoint->port_b, pn); } return ret; } Loading Loading @@ -1093,7 +1173,6 @@ void msm_slim_deinit_ep(struct msm_slim_ctrl *dev, static void msm_slim_sps_unreg_event(struct sps_pipe *sps) { struct sps_register_event sps_event; memset(&sps_event, 0x00, sizeof(sps_event)); /* Disable interrupt and signal notification for Rx/Tx pipe */ sps_register_event(sps, &sps_event); Loading
drivers/slimbus/slim-msm.h +16 −2 Original line number Diff line number Diff line Loading @@ -71,9 +71,12 @@ #define DEF_RETRY_MS 10 #define MSM_CONCUR_MSG 8 #define SAT_CONCUR_MSG 8 #define DEF_WATERMARK (8 << 1) #define DEF_ALIGN 0 #define DEF_ALIGN_LSB 0 #define DEF_ALIGN_MSB (1 << 7) #define DEF_PACK (1 << 6) #define DEF_NO_PACK 0 #define ENABLE_PORT 1 #define DEF_BLKSZ 0 Loading Loading @@ -197,6 +200,16 @@ struct msm_slim_sps_bam { int irq; }; /* * struct slim_pshpull_parm: Structure to store push pull protocol parameters * @num_samples: Number of samples in a period * @rpt_period: Repeat period value */ struct msm_slim_pshpull_parm { int num_samples; int rpt_period; }; struct msm_slim_endp { struct sps_pipe *sps; struct sps_connect config; Loading @@ -204,6 +217,7 @@ struct msm_slim_endp { struct sps_mem_buffer buf; bool connected; int port_b; struct msm_slim_pshpull_parm psh_pull; }; struct msm_slim_qmi { Loading Loading @@ -385,7 +399,7 @@ void msm_slim_put_ctrl(struct msm_slim_ctrl *dev); irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat); int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep); void msm_slim_free_endpoint(struct msm_slim_endp *ep); void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn); void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pipenum, u8 portnum); int msm_alloc_port(struct slim_controller *ctrl, u8 pn); void msm_dealloc_port(struct slim_controller *ctrl, u8 pn); int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn); Loading
drivers/slimbus/slimbus.c +53 −7 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,39 @@ int slim_dealloc_mgrports(struct slim_device *sb, u32 *hdl, int nports) } EXPORT_SYMBOL_GPL(slim_dealloc_mgrports); /* * slim_config_mgrports: Configure manager side ports * @sb: device/client handle. * @ph: array of port handles for which this configuration is valid * @nports: Number of ports in ph * @cfg: configuration requested for port(s) * Configure port settings if they are different than the default ones. * Returns success if the config could be applied. Returns -EISCONN if the * port is in use */ int slim_config_mgrports(struct slim_device *sb, u32 *ph, int nports, struct slim_port_cfg *cfg) { int i; struct slim_controller *ctrl; if (!sb || !ph || !nports || !sb->ctrl || !cfg) return -EINVAL; ctrl = sb->ctrl; mutex_lock(&ctrl->sched.m_reconf); for (i = 0; i < nports; i++) { u8 pn = SLIM_HDL_TO_PORT(ph[i]); if (ctrl->ports[pn].state == SLIM_P_CFG) return -EISCONN; ctrl->ports[pn].cfg = *cfg; } mutex_unlock(&ctrl->sched.m_reconf); return 0; } EXPORT_SYMBOL(slim_config_mgrports); /* * slim_get_slaveport: Get slave port handle * @la: slave device logical address. Loading Loading @@ -1331,8 +1364,12 @@ static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph) ret = slim_processtxn(ctrl, &txn, false); if (ret) return ret; if (la == SLIM_LA_MANAGER) if (la == SLIM_LA_MANAGER) { ctrl->ports[pn].state = SLIM_P_UNCFG; ctrl->ports[pn].cfg.watermark = 0; ctrl->ports[pn].cfg.port_opts = 0; ctrl->ports[pn].ch = NULL; } return 0; } Loading @@ -1356,6 +1393,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) struct slim_ich *slc = &ctrl->chans[chan]; enum slim_port_flow flow = SLIM_HDL_TO_FLOW(srch); u8 la = SLIM_HDL_TO_LA(srch); u8 pn = SLIM_HDL_TO_PORT(srch); /* manager ports don't have direction when they are allocated */ if (la != SLIM_LA_MANAGER && flow != SLIM_SRC) Loading @@ -1364,7 +1402,6 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) mutex_lock(&ctrl->sched.m_reconf); if (la == SLIM_LA_MANAGER) { u8 pn = SLIM_HDL_TO_PORT(srch); if (pn >= ctrl->nports || ctrl->ports[pn].state != SLIM_P_UNCFG) { ret = -EINVAL; Loading @@ -1385,7 +1422,7 @@ int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh) ret = -EALREADY; goto connect_src_err; } ctrl->ports[pn].ch = &slc->prop; ret = connect_port_ch(ctrl, chan, srch, SLIM_SRC); if (!ret) Loading Loading @@ -1444,8 +1481,10 @@ int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink, u16 chanh) (pn >= ctrl->nports || ctrl->ports[pn].state != SLIM_P_UNCFG)) ret = -EINVAL; else else { ctrl->ports[pn].ch = &slc->prop; ret = connect_port_ch(ctrl, chan, sinkh[j], SLIM_SINK); } if (ret) { for (j = j - 1; j >= 0; j--) disconnect_port_ch(ctrl, sinkh[j]); Loading Loading @@ -1638,14 +1677,21 @@ static int slim_remove_ch(struct slim_controller *ctrl, struct slim_ich *slc) * disconnect. It is client's responsibility to call disconnect * on ports owned by the slave device */ if (la == SLIM_LA_MANAGER) if (la == SLIM_LA_MANAGER) { ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG; ctrl->ports[SLIM_HDL_TO_PORT(ph)].ch = NULL; } } ph = slc->srch; la = SLIM_HDL_TO_LA(ph); if (la == SLIM_LA_MANAGER) ctrl->ports[SLIM_HDL_TO_PORT(ph)].state = SLIM_P_UNCFG; if (la == SLIM_LA_MANAGER) { u8 pn = SLIM_HDL_TO_PORT(ph); ctrl->ports[pn].state = SLIM_P_UNCFG; ctrl->ports[pn].cfg.watermark = 0; ctrl->ports[pn].cfg.port_opts = 0; } kfree(slc->sinkh); slc->sinkh = NULL; Loading
include/linux/slimbus/slimbus.h +30 −7 Original line number Diff line number Diff line Loading @@ -226,13 +226,13 @@ enum slim_port_req { }; /* * enum slim_port_cfg: Port configuration parameters requested. * User can request no configuration, packed data, or MSB aligned data port * enum slim_port_opts: Port options requested. * User can request no configuration, packed data, and/or MSB aligned data port */ enum slim_port_cfg { SLIM_CFG_NONE, SLIM_CFG_PACKED, SLIM_CFG_ALIGN_MSB, enum slim_port_opts { SLIM_OPT_NONE = 0, SLIM_OPT_NO_PACK = 1U, SLIM_OPT_ALIGN_MSB = 1U << 1, }; /* enum slim_port_flow: Port flow type (inbound/outbound). */ Loading @@ -250,6 +250,16 @@ enum slim_port_err { SLIM_P_NOT_OWNED, }; /* * struct slim_port_cfg: Port config for the manager port * port_opts: port options (bit-map) for this port * watermark: watermark level set for this port */ struct slim_port_cfg { u32 port_opts; u32 watermark; }; /* * struct slim_port: Internal structure used by framework to manage ports * @err: Port error if any for this port. Refer to enum above. Loading @@ -267,7 +277,7 @@ struct slim_port { enum slim_port_err err; enum slim_port_state state; enum slim_port_req req; enum slim_port_cfg cfg; struct slim_port_cfg cfg; enum slim_port_flow flow; struct slim_ch *ch; struct completion *xcomp; Loading Loading @@ -834,6 +844,19 @@ extern int slim_alloc_mgrports(struct slim_device *sb, enum slim_port_req req, /* Deallocate the port(s) allocated using the API above */ extern int slim_dealloc_mgrports(struct slim_device *sb, u32 *hdl, int hsz); /* * slim_config_mgrports: Configure manager side ports * @sb: device/client handle. * @ph: array of port handles for which this configuration is valid * @nports: Number of ports in ph * @cfg: configuration requested for port(s) * Configure port settings if they are different than the default ones. * Returns success if the config could be applied. Returns -EISCONN if the * port is in use */ extern int slim_config_mgrports(struct slim_device *sb, u32 *ph, int nports, struct slim_port_cfg *cfg); /* * slim_port_xfer: Schedule buffer to be transferred/received using port-handle. * @sb: client handle Loading