soc: qcom: Introduce pon ops for sdx55

Introduce new pon ops for sdx55 to be used in Kona with external
modem.

Change-Id: I039594eb30cb4ec9f43819a5f7d4c1048477e4bd
Signed-off-by: Rishabh Bhatnagar <rishabhb@codeaurora.org>
This commit is contained in:
Rishabh Bhatnagar 2018-10-16 10:52:40 -07:00
parent 93d797f613
commit 8c5156ceee
4 changed files with 173 additions and 1 deletions

View file

@ -1045,6 +1045,120 @@ static int sdx50m_setup_hw(struct mdm_ctrl *mdm,
return ret;
}
static int sdx55m_setup_hw(struct mdm_ctrl *mdm,
const struct mdm_ops *ops,
struct platform_device *pdev)
{
int ret;
struct device_node *node;
struct esoc_clink *esoc;
const struct esoc_clink_ops *const clink_ops = ops->clink_ops;
const struct mdm_pon_ops *pon_ops = ops->pon_ops;
mdm->dev = &pdev->dev;
mdm->pon_ops = pon_ops;
node = pdev->dev.of_node;
esoc = devm_kzalloc(mdm->dev, sizeof(*esoc), GFP_KERNEL);
if (IS_ERR_OR_NULL(esoc)) {
dev_err(mdm->dev, "cannot allocate esoc device\n");
return PTR_ERR(esoc);
}
esoc->pdev = pdev;
mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
if (!mdm->mdm_queue) {
dev_err(mdm->dev, "could not create mdm_queue\n");
return -ENOMEM;
}
mdm->irq_mask = 0;
mdm->ready = false;
ret = mdm_dt_parse_gpios(mdm);
if (ret) {
esoc_mdm_log("Failed to parse DT gpios\n");
dev_err(mdm->dev, "Failed to parse DT gpios\n");
goto err_destroy_wrkq;
}
ret = mdm_pon_dt_init(mdm);
if (ret) {
esoc_mdm_log("Failed to parse PON DT gpios\n");
dev_err(mdm->dev, "Failed to parse PON DT gpio\n");
goto err_destroy_wrkq;
}
ret = mdm_pinctrl_init(mdm);
if (ret) {
esoc_mdm_log("Failed to init pinctrl\n");
dev_err(mdm->dev, "Failed to init pinctrl\n");
goto err_destroy_wrkq;
}
ret = mdm_pon_setup(mdm);
if (ret) {
esoc_mdm_log("Failed to setup PON\n");
dev_err(mdm->dev, "Failed to setup PON\n");
goto err_destroy_wrkq;
}
ret = mdm_configure_ipc(mdm, pdev);
if (ret) {
esoc_mdm_log("Failed to configure the ipc\n");
dev_err(mdm->dev, "Failed to configure the ipc\n");
goto err_release_ipc;
}
esoc->name = SDX55M_LABEL;
mdm->dual_interface = of_property_read_bool(node,
"qcom,mdm-dual-link");
esoc->link_name = SDX55M_PCIE;
ret = of_property_read_string(node, "qcom,mdm-link-info",
&esoc->link_info);
if (ret)
dev_info(mdm->dev, "esoc link info missing\n");
mdm->skip_restart_for_mdm_crash = of_property_read_bool(node,
"qcom,esoc-skip-restart-for-mdm-crash");
esoc->clink_ops = clink_ops;
esoc->parent = mdm->dev;
esoc->owner = THIS_MODULE;
esoc->np = pdev->dev.of_node;
set_esoc_clink_data(esoc, mdm);
ret = esoc_clink_register(esoc);
if (ret) {
esoc_mdm_log("esoc registration failed\n");
dev_err(mdm->dev, "esoc registration failed\n");
goto err_free_irq;
}
dev_dbg(mdm->dev, "esoc registration done\n");
esoc_mdm_log("Done configuring the GPIOs and esoc registration\n");
init_completion(&mdm->debug_done);
INIT_WORK(&mdm->mdm_status_work, mdm_status_fn);
INIT_WORK(&mdm->restart_reason_work, mdm_get_restart_reason);
INIT_DELAYED_WORK(&mdm->mdm2ap_status_check_work, mdm2ap_status_check);
mdm->get_restart_reason = false;
mdm->debug_fail = false;
mdm->esoc = esoc;
mdm->init = 0;
mdm_debug_gpio_ipc_log(mdm);
return 0;
err_free_irq:
mdm_free_irq(mdm);
err_release_ipc:
mdm_release_ipc_gpio(mdm);
err_destroy_wrkq:
destroy_workqueue(mdm->mdm_queue);
return ret;
}
static struct esoc_clink_ops mdm_cops = {
.cmd_exe = mdm_cmd_exe,
.get_status = mdm_get_status,
@ -1064,11 +1178,19 @@ static struct mdm_ops sdx50m_ops = {
.pon_ops = &sdx50m_pon_ops,
};
static struct mdm_ops sdx55m_ops = {
.clink_ops = &mdm_cops,
.config_hw = sdx55m_setup_hw,
.pon_ops = &sdx55m_pon_ops,
};
static const struct of_device_id mdm_dt_match[] = {
{ .compatible = "qcom,ext-mdm9x55",
.data = &mdm9x55_ops, },
{ .compatible = "qcom,ext-sdx50m",
.data = &sdx50m_ops, },
{ .compatible = "qcom,ext-sdx55m",
.data = &sdx55m_ops, },
{},
};
MODULE_DEVICE_TABLE(of, mdm_dt_match);

View file

@ -507,6 +507,10 @@ static struct esoc_compat compat_table[] = {
.name = "SDX50M",
.data = NULL,
},
{
.name = "SDX55M",
.data = NULL,
},
};
static struct esoc_drv esoc_ssr_drv = {

View file

@ -55,7 +55,43 @@ static int sdx50m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
* Allow PS hold assert to be detected
*/
if (!atomic)
usleep_range(80000,180000);
usleep_range(80000, 180000);
else
/*
* The flow falls through this path as a part of the
* panic handler, which has to executed atomically.
*/
mdelay(100);
esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
soft_reset_direction_de_assert);
gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
soft_reset_direction_de_assert);
return 0;
}
/* This function can be called from atomic context. */
static int sdx55m_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
{
int soft_reset_direction_assert = 0,
soft_reset_direction_de_assert = 1;
if (mdm->soft_reset_inverted) {
soft_reset_direction_assert = 1;
soft_reset_direction_de_assert = 0;
}
esoc_mdm_log("RESET GPIO value (before doing a reset): %d\n",
gpio_get_value(MDM_GPIO(mdm, AP2MDM_SOFT_RESET)));
esoc_mdm_log("Setting AP2MDM_SOFT_RESET = %d\n",
soft_reset_direction_assert);
gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
soft_reset_direction_assert);
/*
* Allow PS hold assert to be detected
*/
if (!atomic)
usleep_range(80000, 180000);
else
/*
* The flow falls through this path as a part of the
@ -263,3 +299,10 @@ struct mdm_pon_ops sdx50m_pon_ops = {
.dt_init = mdm4x_pon_dt_init,
.setup = mdm4x_pon_setup,
};
struct mdm_pon_ops sdx55m_pon_ops = {
.pon = mdm4x_do_first_power_on,
.soft_reset = sdx55m_toggle_soft_reset,
.dt_init = mdm4x_pon_dt_init,
.setup = mdm4x_pon_setup,
};

View file

@ -24,6 +24,8 @@
#define MDM9x55_PCIE "PCIe"
#define SDX50M_LABEL "SDX50M"
#define SDX50M_PCIE "PCIe"
#define SDX55M_LABEL "SDX55M"
#define SDX55M_PCIE "PCIe"
#define MDM2AP_STATUS_TIMEOUT_MS 120000L
#define MDM_MODEM_TIMEOUT 3000
#define DEF_RAMDUMP_TIMEOUT 120000
@ -145,4 +147,5 @@ static inline int mdm_pon_setup(struct mdm_ctrl *mdm)
extern struct mdm_pon_ops mdm9x55_pon_ops;
extern struct mdm_pon_ops sdx50m_pon_ops;
extern struct mdm_pon_ops sdx55m_pon_ops;
#endif