/** * hsi_softreset_driver - Must be called following HSI SW RESET, to re-align * variable states with new HW state. * * @hsi_ctrl - reference to the hsi controller to be re-aligned. * */ void hsi_softreset_driver(struct hsi_dev *hsi_ctrl) { struct platform_device *pd = to_platform_device(hsi_ctrl->dev); struct hsi_platform_data *pdata = pd->dev.platform_data; struct hsi_port *hsi_p; unsigned int port; u32 revision; /* HSI port reset */ for (port = 0; port < hsi_ctrl->max_p; port++) { hsi_p = &hsi_ctrl->hsi_port[port]; hsi_p->counters_on = 1; hsi_p->reg_counters = pdata->ctx->pctx[port].hsr.counters; hsi_port_channels_reset(&hsi_ctrl->hsi_port[port]); } hsi_set_pm_force_hsi_on(hsi_ctrl); /* Re-Configure HSI ports */ hsi_set_ports_default(hsi_ctrl, pd); /* Gather info from registers for the driver.(REVISION) */ revision = hsi_inl(hsi_ctrl->base, HSI_SYS_REVISION_REG); if (hsi_driver_device_is_hsi(pd)) dev_info(hsi_ctrl->dev, "HSI Hardware REVISION 0x%x\n", revision); else dev_info(hsi_ctrl->dev, "SSI Hardware REVISION %d.%d\n", (revision & HSI_SSI_REV_MAJOR) >> 4, (revision & HSI_SSI_REV_MINOR)); }
void hsi_set_pm_default(struct hsi_dev *hsi_ctrl) { #if 0 /* Huawei 3-wire HSI tests ... Remove later ****/ dpr_0("hsi_driver.c:%s. hsi_ctrl->id=%d,hsi_mode=0x%08X;\n",__func__,hsi_ctrl->id,hsi_ctrl->hsi_port[hsi_ctrl->id].hsi_mode); //Add for Flashless 3HSI dbg if( (bool)(hsi_ctrl->hsi_port[hsi_ctrl->id].hsi_mode&XMM_HSI_PM_UNDFT)==true ) {//XMM_HSI_PM_UNDFT, HSI PM_unset_default标志; hsi_set_pm_force_hsi_on(hsi_ctrl); return; } #endif /* Huawei 3-wire HSI tests ... Remove later ****/ /* Set default SYSCONFIG PM settings */ hsi_outl((HSI_AUTOIDLE | HSI_SIDLEMODE_SMART_WAKEUP | HSI_MIDLEMODE_SMART_WAKEUP), hsi_ctrl->base, HSI_SYS_SYSCONFIG_REG); hsi_outl(HSI_CLK_AUTOGATING_ON, hsi_ctrl->base, HSI_GDD_GCR_REG); /* HSI_TODO : use the HWMOD API : omap_hwmod_set_slave_idlemode() */ }
/** * hsi_ioctl - HSI I/O control * @dev - hsi device channel reference to apply the I/O control * (or port associated to it) * @command - HSI I/O control command * @arg - parameter associated to the control command. NULL, if no parameter. * * Return 0 on success, a negative value on failure. * */ int hsi_ioctl(struct hsi_device *dev, unsigned int command, void *arg) { struct hsi_channel *ch; struct hsi_dev *hsi_ctrl; struct hsi_port *pport; void __iomem *base; unsigned int port, channel; u32 acwake; int err = 0; int fifo = 0; u8 ret; struct hsi_platform_data *pdata; if (unlikely((!dev) || (!dev->ch) || (!dev->ch->hsi_port) || (!dev->ch->hsi_port->hsi_controller)) || (!(dev->ch->flags & HSI_CH_OPEN))) { pr_err(LOG_NAME "HSI IOCTL Invalid parameter\n"); return -EINVAL; } ch = dev->ch; pport = ch->hsi_port; hsi_ctrl = ch->hsi_port->hsi_controller; port = ch->hsi_port->port_number; channel = ch->channel_number; base = hsi_ctrl->base; dev_dbg(hsi_ctrl->dev, "IOCTL: ch %d, command %d\n", channel, command); spin_lock_bh(&hsi_ctrl->lock); hsi_clocks_enable_channel(hsi_ctrl->dev, channel, __func__); switch (command) { case HSI_IOCTL_ACWAKE_UP: /* Wake up request to Modem (typically OMAP initiated) */ /* Symetrical disable will be done in HSI_IOCTL_ACWAKE_DOWN */ if (ch->flags & HSI_CH_ACWAKE) { dev_dbg(hsi_ctrl->dev, "Duplicate ACWAKE UP\n"); err = -EPERM; goto out; } ch->flags |= HSI_CH_ACWAKE; pport->acwake_status |= BIT(channel); /* We only claim once the wake line per channel */ acwake = hsi_inl(base, HSI_SYS_WAKE_REG(port)); if (!(acwake & HSI_WAKE(channel))) { hsi_outl(HSI_SET_WAKE(channel), base, HSI_SYS_SET_WAKE_REG(port)); } goto out; break; case HSI_IOCTL_ACWAKE_DOWN: /* Low power request initiation (OMAP initiated, typically */ /* following inactivity timeout) */ /* ACPU HSI block shall still be capable of receiving */ if (!(ch->flags & HSI_CH_ACWAKE)) { dev_dbg(hsi_ctrl->dev, "Duplicate ACWAKE DOWN\n"); err = -EPERM; goto out; } acwake = hsi_inl(base, HSI_SYS_WAKE_REG(port)); if (unlikely(pport->acwake_status != (acwake & HSI_WAKE_MASK))) { dev_warn(hsi_ctrl->dev, "ACWAKE shadow register mismatch" " acwake_status: 0x%x, HSI_SYS_WAKE_REG: 0x%x", pport->acwake_status, acwake); pport->acwake_status = acwake & HSI_WAKE_MASK; } /* SSI_TODO: add safety check for SSI also */ ch->flags &= ~HSI_CH_ACWAKE; pport->acwake_status &= ~BIT(channel); /* Release the wake line per channel */ if ((acwake & HSI_WAKE(channel))) { hsi_outl(HSI_CLEAR_WAKE(channel), base, HSI_SYS_CLEAR_WAKE_REG(port)); } goto out; break; case HSI_IOCTL_SEND_BREAK: hsi_outl(1, base, HSI_HST_BREAK_REG(port)); /*HSI_TODO : need to deactivate clock after BREAK frames sent*/ /*Use interrupt ? (if TX BREAK INT exists)*/ break; case HSI_IOCTL_GET_ACWAKE: if (!arg) { err = -EINVAL; goto out; } *(u32 *)arg = hsi_inl(base, HSI_SYS_WAKE_REG(port)); break; case HSI_IOCTL_FLUSH_RX: ret = hsi_hsr_fifo_flush_channel(hsi_ctrl, port, channel); if (arg) *(size_t *)arg = ret; /* Ack the RX Int */ hsi_outl_and(~HSI_HSR_DATAAVAILABLE(channel), base, HSI_SYS_MPU_STATUS_CH_REG(port, pport->n_irq, channel)); break; case HSI_IOCTL_FLUSH_TX: ret = hsi_hst_fifo_flush_channel(hsi_ctrl, port, channel); if (arg) *(size_t *)arg = ret; /* Ack the TX Int */ hsi_outl_and(~HSI_HST_DATAACCEPT(channel), base, HSI_SYS_MPU_STATUS_CH_REG(port, pport->n_irq, channel)); break; case HSI_IOCTL_GET_CAWAKE: if (!arg) { err = -EINVAL; goto out; } err = hsi_get_cawake(dev->ch->hsi_port); if (err < 0) { err = -ENODEV; goto out; } *(u32 *)arg = err; break; case HSI_IOCTL_SET_RX: if (!arg) { err = -EINVAL; goto out; } err = hsi_set_rx(dev->ch->hsi_port, (struct hsr_ctx *)arg); break; case HSI_IOCTL_GET_RX: if (!arg) { err = -EINVAL; goto out; } hsi_get_rx(dev->ch->hsi_port, (struct hsr_ctx *)arg); break; case HSI_IOCTL_SET_TX: if (!arg) { err = -EINVAL; goto out; } err = hsi_set_tx(dev->ch->hsi_port, (struct hst_ctx *)arg); break; case HSI_IOCTL_GET_TX: if (!arg) { err = -EINVAL; goto out; } hsi_get_tx(dev->ch->hsi_port, (struct hst_ctx *)arg); break; case HSI_IOCTL_SW_RESET: dev_info(hsi_ctrl->dev, "SW Reset\n"); err = hsi_softreset(hsi_ctrl); /* Reset HSI config to default */ hsi_softreset_driver(hsi_ctrl); break; case HSI_IOCTL_GET_FIFO_OCCUPANCY: if (!arg) { err = -EINVAL; goto out; } fifo = hsi_fifo_get_id(hsi_ctrl, channel, port); if (unlikely(fifo < 0)) { dev_err(hsi_ctrl->dev, "No valid FIFO id found for " "channel %d.\n", channel); err = -EFAULT; goto out; } *(size_t *)arg = hsi_get_rx_fifo_occupancy(hsi_ctrl, fifo); break; case HSI_IOCTL_SET_WAKE_RX_3WIRES_MODE: dev_info(hsi_ctrl->dev, "Entering RX wakeup in 3 wires mode (no CAWAKE)\n"); pport->wake_rx_3_wires_mode = 1; /* HSI-C1BUG00085: ixxx: HSI wakeup issue in 3 wires mode * HSI will NOT generate the Swakeup for 2nd frame if it entered * IDLE after 1st received frame */ if (is_hsi_errata(hsi_ctrl, HSI_ERRATUM_ixxx_3WIRES_NO_SWAKEUP)) if (hsi_driver_device_is_hsi(to_platform_device (hsi_ctrl->dev))) hsi_set_pm_force_hsi_on(hsi_ctrl); /* When WAKE is not available, ACREADY must be set to 1 at * reset else remote will never have a chance to transmit. */ hsi_outl_or(HSI_SET_WAKE_3_WIRES | HSI_SET_WAKE_READY_LVL_1, base, HSI_SYS_SET_WAKE_REG(port)); hsi_driver_disable_interrupt(pport, HSI_CAWAKEDETECTED); break; case HSI_IOCTL_SET_WAKE_RX_4WIRES_MODE: dev_info(hsi_ctrl->dev, "Entering RX wakeup in 4 wires mode\n"); pport->wake_rx_3_wires_mode = 0; /* HSI-C1BUG00085: ixxx: HSI wakeup issue in 3 wires mode * HSI will NOT generate the Swakeup for 2nd frame if it entered * IDLE after 1st received frame */ if (is_hsi_errata(hsi_ctrl, HSI_ERRATUM_ixxx_3WIRES_NO_SWAKEUP)) if (hsi_driver_device_is_hsi(to_platform_device (hsi_ctrl->dev))) hsi_set_pm_default(hsi_ctrl); hsi_driver_enable_interrupt(pport, HSI_CAWAKEDETECTED); hsi_outl_and(HSI_SET_WAKE_3_WIRES_MASK, base, HSI_SYS_SET_WAKE_REG(port)); break; case HSI_IOCTL_SET_HI_SPEED: if (!arg) { err = -EINVAL; goto out; } hsi_ctrl->hsi_fclk_req = *(unsigned int *)arg ? HSI_FCLK_HI_SPEED : HSI_FCLK_LOW_SPEED; if (hsi_ctrl->hsi_fclk_req == hsi_ctrl->hsi_fclk_current) { dev_dbg(hsi_ctrl->dev, "HSI FClk already @%ldHz\n", hsi_ctrl->hsi_fclk_current); goto out; } if (hsi_is_controller_transfer_ongoing(hsi_ctrl)) { err = -EBUSY; goto out; } hsi_ctrl->clock_change_ongoing = true; spin_unlock_bh(&hsi_ctrl->lock); pdata = dev_get_platdata(hsi_ctrl->dev); /* Set the HSI FCLK to requested value. */ err = pdata->device_scale(hsi_ctrl->dev, hsi_ctrl->dev, hsi_ctrl->hsi_fclk_req); if (err < 0) { dev_err(hsi_ctrl->dev, "%s: Cannot set HSI FClk to" " %ldHz, err %d\n", __func__, hsi_ctrl->hsi_fclk_req, err); } else { dev_info(hsi_ctrl->dev, "HSI FClk changed from %ldHz to" " %ldHz\n", hsi_ctrl->hsi_fclk_current, hsi_ctrl->hsi_fclk_req); hsi_ctrl->hsi_fclk_current = hsi_ctrl->hsi_fclk_req; } spin_lock_bh(&hsi_ctrl->lock); hsi_ctrl->clock_change_ongoing = false; break; case HSI_IOCTL_GET_SPEED: if (!arg) { err = -EINVAL; goto out; } *(unsigned long *)arg = hsi_ctrl->hsi_fclk_current; break; default: err = -ENOIOCTLCMD; break; } out: /* All IOCTL end by disabling the clocks, except ACWAKE high. */ hsi_clocks_disable_channel(hsi_ctrl->dev, channel, __func__); spin_unlock_bh(&hsi_ctrl->lock); return err; }
/* HSI Platform Device probing & hsi_device registration */ static int __init hsi_platform_device_probe(struct platform_device *pd) { struct hsi_platform_data *pdata = pd->dev.platform_data; struct hsi_dev *hsi_ctrl; u32 revision; int err; dev_dbg(&pd->dev, "HSI DRIVER : hsi_platform_device_probe\n"); dev_dbg(&pd->dev, "The platform device probed is an %s\n", hsi_driver_device_is_hsi(pd) ? "HSI" : "SSI"); if (!pdata) { dev_err(&pd->dev, "No platform_data found on hsi device\n"); return -ENXIO; } hsi_ctrl = kzalloc(sizeof(*hsi_ctrl), GFP_KERNEL); if (hsi_ctrl == NULL) { dev_err(&pd->dev, "Could not allocate memory for" " struct hsi_dev\n"); return -ENOMEM; } platform_set_drvdata(pd, hsi_ctrl); err = hsi_controller_init(hsi_ctrl, pd); if (err < 0) { dev_err(&pd->dev, "Could not initialize hsi controller:" " %d\n", err); goto rollback1; } /* Wakeup dependency was disabled for HSI <-> MPU PM_L3INIT_HSI_WKDEP */ #if 0 omap_writel(0x141, 0x4A307338); #endif pm_runtime_enable(hsi_ctrl->dev); pm_runtime_irq_safe(hsi_ctrl->dev); hsi_clocks_enable(hsi_ctrl->dev, __func__); /* Non critical SW Reset */ err = hsi_softreset(hsi_ctrl); if (err < 0) goto rollback2; hsi_set_pm_force_hsi_on(hsi_ctrl); /* Configure HSI ports */ hsi_set_ports_default(hsi_ctrl, pd); /* Gather info from registers for the driver.(REVISION) */ revision = hsi_inl(hsi_ctrl->base, HSI_SYS_REVISION_REG); if (hsi_driver_device_is_hsi(pd)) dev_info(hsi_ctrl->dev, "HSI Hardware REVISION 0x%x\n", revision); else dev_info(hsi_ctrl->dev, "SSI Hardware REVISION %d.%d\n", (revision & HSI_SSI_REV_MAJOR) >> 4, (revision & HSI_SSI_REV_MINOR)); err = hsi_debug_add_ctrl(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not add hsi controller to debugfs: %d\n", err); goto rollback2; } err = register_hsi_devices(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not register hsi_devices: %d\n", err); goto rollback3; } /* Allow HSI to wake up the platform */ device_init_wakeup(hsi_ctrl->dev, true); /* Set the HSI FCLK to default. */ if (!pdata->device_scale) { dev_err(&pd->dev, "%s: No platform device_scale function\n", __func__); err = -ENXIO; goto rollback3; } err = pdata->device_scale(hsi_ctrl->dev, hsi_ctrl->dev, pdata->default_hsi_fclk); if (err == -EBUSY) { dev_warn(&pd->dev, "Cannot set HSI FClk to default value: %ld. " "Will retry on next open\n", pdata->default_hsi_fclk); } else if (err) { dev_err(&pd->dev, "%s: Error %d setting HSI FClk to %ld.\n", __func__, err, pdata->default_hsi_fclk); goto rollback3; } else { hsi_ctrl->clock_rate = pdata->default_hsi_fclk; } /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); return 0; rollback3: hsi_debug_remove_ctrl(hsi_ctrl); rollback2: hsi_controller_exit(hsi_ctrl); /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); rollback1: kfree(hsi_ctrl); return err; }
/* HSI Platform Device probing & hsi_device registration */ static int __init hsi_platform_device_probe(struct platform_device *pd) { struct hsi_platform_data *pdata = dev_get_platdata(&pd->dev); struct hsi_dev *hsi_ctrl; u32 revision; int err; dev_dbg(&pd->dev, "HSI DRIVER : hsi_platform_device_probe\n"); dev_dbg(&pd->dev, "The platform device probed is an %s\n", hsi_driver_device_is_hsi(pd) ? "HSI" : "SSI"); if (!pdata) { dev_err(&pd->dev, "No platform_data found on hsi device\n"); return -ENXIO; } /* Check if mandatory board functions are populated */ if (!pdata->device_scale) { dev_err(&pd->dev, "Missing platform device_scale function\n"); return -ENOSYS; } hsi_ctrl = kzalloc(sizeof(*hsi_ctrl), GFP_KERNEL); if (hsi_ctrl == NULL) { dev_err(&pd->dev, "Could not allocate memory for" " struct hsi_dev\n"); return -ENOMEM; } platform_set_drvdata(pd, hsi_ctrl); err = hsi_controller_init(hsi_ctrl, pd); if (err < 0) { dev_err(&pd->dev, "Could not initialize hsi controller:" " %d\n", err); goto rollback1; } pm_runtime_enable(hsi_ctrl->dev); pm_runtime_irq_safe(hsi_ctrl->dev); hsi_clocks_enable(hsi_ctrl->dev, __func__); /* Non critical SW Reset */ err = hsi_softreset(hsi_ctrl); if (err < 0) goto rollback2; hsi_set_pm_force_hsi_on(hsi_ctrl); /* Configure HSI ports */ hsi_set_ports_default(hsi_ctrl, pd); /* Gather info from registers for the driver.(REVISION) */ revision = hsi_inl(hsi_ctrl->base, HSI_SYS_REVISION_REG); if (hsi_driver_device_is_hsi(pd)) dev_info(hsi_ctrl->dev, "HSI Hardware REVISION 0x%x\n", revision); else dev_info(hsi_ctrl->dev, "SSI Hardware REVISION %d.%d\n", (revision & HSI_SSI_REV_MAJOR) >> 4, (revision & HSI_SSI_REV_MINOR)); err = hsi_debug_add_ctrl(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not add hsi controller to debugfs: %d\n", err); goto rollback2; } err = register_hsi_devices(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not register hsi_devices: %d\n", err); goto rollback3; } /* Allow HSI to wake up the platform */ device_init_wakeup(hsi_ctrl->dev, true); /* Set the HSI FCLK to default. */ hsi_ctrl->hsi_fclk_req = pdata->default_hsi_fclk; err = pdata->device_scale(hsi_ctrl->dev, hsi_ctrl->dev, pdata->default_hsi_fclk); if (err == -EBUSY) { /* PM framework init is late_initcall, so it may not yet be */ /* initialized, so be prepared to retry later on open. */ dev_warn(&pd->dev, "Cannot set HSI FClk to default value: %ld. " "Will retry on next open\n", pdata->default_hsi_fclk); } else if (err) { dev_err(&pd->dev, "%s: Error %d setting HSI FClk to %ld.\n", __func__, err, pdata->default_hsi_fclk); goto rollback3; } else { hsi_ctrl->hsi_fclk_current = pdata->default_hsi_fclk; } /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); return 0; rollback3: hsi_debug_remove_ctrl(hsi_ctrl); rollback2: hsi_controller_exit(hsi_ctrl); /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); rollback1: kfree(hsi_ctrl); return err; }
static int __init hsi_platform_device_probe(struct platform_device *pd) { struct hsi_platform_data *pdata = dev_get_platdata(&pd->dev); struct hsi_dev *hsi_ctrl; u32 revision; int err; dev_dbg(&pd->dev, "HSI DRIVER : hsi_platform_device_probe\n"); dev_dbg(&pd->dev, "The platform device probed is an %s\n", hsi_driver_device_is_hsi(pd) ? "HSI" : "SSI"); if (!pdata) { dev_err(&pd->dev, "No platform_data found on hsi device\n"); return -ENXIO; } /* Check if mandatory board functions are populated */ if (!pdata->device_scale) { dev_err(&pd->dev, "Missing platform device_scale function\n"); return -ENOSYS; } hsi_ctrl = kzalloc(sizeof(*hsi_ctrl), GFP_KERNEL); if (hsi_ctrl == NULL) { dev_err(&pd->dev, "Could not allocate memory for" " struct hsi_dev\n"); return -ENOMEM; } //mo2haewoon.you => [START] #if defined (HSI_SEND_ATCOMMAND_TO_CAWAKE) INIT_WORK(&hsi_ctrl->ifx_work,ifx_check_handle_work); hsi_ctrl->ifx_wq = create_singlethread_workqueue("ifx_wq"); if(!hsi_ctrl->ifx_wq){ printk("Failed to setup workqueue - ifx_wq \n"); } #endif //mo2haewoon.you => [END] platform_set_drvdata(pd, hsi_ctrl); err = hsi_controller_init(hsi_ctrl, pd); if (err < 0) { dev_err(&pd->dev, "Could not initialize hsi controller:" " %d\n", err); goto rollback1; } pm_runtime_enable(hsi_ctrl->dev); pm_runtime_irq_safe(hsi_ctrl->dev); hsi_clocks_enable(hsi_ctrl->dev, __func__); /* Non critical SW Reset */ err = hsi_softreset(hsi_ctrl); if (err < 0) goto rollback2; hsi_set_pm_force_hsi_on(hsi_ctrl); /* Configure HSI ports */ hsi_set_ports_default(hsi_ctrl, pd); /* Gather info from registers for the driver.(REVISION) */ revision = hsi_inl(hsi_ctrl->base, HSI_SYS_REVISION_REG); if (hsi_driver_device_is_hsi(pd)) dev_info(hsi_ctrl->dev, "HSI Hardware REVISION 0x%x\n", revision); else dev_info(hsi_ctrl->dev, "SSI Hardware REVISION %d.%d\n", (revision & HSI_SSI_REV_MAJOR) >> 4, (revision & HSI_SSI_REV_MINOR)); err = hsi_debug_add_ctrl(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not add hsi controller to debugfs: %d\n", err); goto rollback2; } err = register_hsi_devices(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not register hsi_devices: %d\n", err); goto rollback3; } //mo2haewoon.you => [START] #if defined (HSI_SEND_ATCOMMAND_TO_CAWAKE) /* Set the ts_gpio pin mux */ err = gpio_request(OMAP_SEND, "gpio_122"); gpio_direction_input(OMAP_SEND); irq_num_122 = gpio_to_irq(OMAP_SEND); err = request_irq(irq_num_122,ifx_check_handle_srdy_irq, IRQF_TRIGGER_RISING,HSI_MODULENAME, hsi_ctrl); if (err < 0) { pr_err("Modem-wait-check: couldn't request gpio interrupt 122\n"); } #endif //mo2haewoon.you => [END] /* Allow HSI to wake up the platform */ device_init_wakeup(hsi_ctrl->dev, true); /* Set the HSI FCLK to default. */ hsi_ctrl->hsi_fclk_req = pdata->default_hsi_fclk; err = pdata->device_scale(hsi_ctrl->dev, hsi_ctrl->dev, pdata->default_hsi_fclk); if (err == -EBUSY) { /* PM framework init is late_initcall, so it may not yet be */ /* initialized, so be prepared to retry later on open. */ dev_warn(&pd->dev, "Cannot set HSI FClk to default value: %ld. " "Will retry on next open\n", pdata->default_hsi_fclk); } else if (err) { dev_err(&pd->dev, "%s: Error %d setting HSI FClk to %ld.\n", __func__, err, pdata->default_hsi_fclk); goto rollback3; } else { hsi_ctrl->hsi_fclk_current = pdata->default_hsi_fclk; } /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); // LGE_CHANGE [MIPI-HSI] [email protected] [START] #if defined(CONFIG_MACH_LGE_COSMOPOLITAN) /* Set IMC CP core dump */ IFX_CP_CRASH_DUMP_INIT(); #endif #if defined(CONFIG_MACH_LGE_COSMO) /* Notify active/sleep status of AP to CP*/ ifx_init_modem_send(); #endif // LGE_CHANGE [MIPI-HSI] [email protected] [END] return 0; rollback3: hsi_debug_remove_ctrl(hsi_ctrl); rollback2: hsi_controller_exit(hsi_ctrl); /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); rollback1: kfree(hsi_ctrl); return err; }
/* HSI Platform Device probing & hsi_device registration */ static int __init hsi_platform_device_probe(struct platform_device *pd) { struct hsi_platform_data *pdata = dev_get_platdata(&pd->dev); struct hsi_dev *hsi_ctrl; u32 revision; int err; dev_dbg(&pd->dev, "HSI DRIVER : hsi_platform_device_probe\n"); dev_dbg(&pd->dev, "The platform device probed is an %s\n", hsi_driver_device_is_hsi(pd) ? "HSI" : "SSI"); if (!pdata) { dev_err(&pd->dev, "No platform_data found on hsi device\n"); return -ENXIO; } if (!pdata->device_enable || !pdata->device_idle || !pdata->device_set_rate || !pdata->wakeup_enable || !pdata->wakeup_disable || !pdata->wakeup_is_from_hsi || !pdata->board_suspend) { dev_err(&pd->dev, "Missing platform function pointers\n"); return -EINVAL; } hsi_ctrl = kzalloc(sizeof(*hsi_ctrl), GFP_KERNEL); if (hsi_ctrl == NULL) { dev_err(&pd->dev, "Could not allocate memory for" " struct hsi_dev\n"); return -ENOMEM; } platform_set_drvdata(pd, hsi_ctrl); err = hsi_controller_init(hsi_ctrl, pd); if (err < 0) { dev_err(&pd->dev, "Could not initialize hsi controller:" " %d\n", err); goto rollback1; } #ifdef USE_PM_RUNTIME_FOR_HSI pm_runtime_enable(hsi_ctrl->dev); #endif err = hsi_clocks_enable(hsi_ctrl->dev, __func__); if (err < 0) { dev_err(&pd->dev, "Could not enable clocks for hsi: %d\n", err); goto rollback1; } /* Non critical SW Reset */ err = hsi_softreset(hsi_ctrl); if (err < 0) goto rollback2; hsi_set_pm_force_hsi_on(hsi_ctrl); /* Configure HSI ports */ hsi_set_ports_default(hsi_ctrl, pd); /* Gather info from registers for the driver.(REVISION) */ revision = hsi_inl(hsi_ctrl->base, HSI_SYS_REVISION_REG); if (hsi_driver_device_is_hsi(pd)) dev_info(hsi_ctrl->dev, "HSI Hardware REVISION 0x%x\n", revision); else dev_info(hsi_ctrl->dev, "SSI Hardware REVISION %d.%d\n", (revision & HSI_SSI_REV_MAJOR) >> 4, (revision & HSI_SSI_REV_MINOR)); err = hsi_debug_add_ctrl(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not add hsi controller to debugfs: %d\n", err); goto rollback2; } err = register_hsi_devices(hsi_ctrl); if (err < 0) { dev_err(&pd->dev, "Could not register hsi_devices: %d\n", err); goto rollback3; } /* Allow HSI to wake up the platform */ device_init_wakeup(hsi_ctrl->dev, true); /* Set the HSI FCLK to default. */ err = pdata->device_set_rate(hsi_ctrl->dev, hsi_ctrl->dev, pdata->default_hsi_fclk); if (err) dev_err(&pd->dev, "Cannot set HSI FClk to default value: %ld\n", pdata->default_hsi_fclk); /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); #if defined(CONFIG_MACH_LGE_COSMOPOLITAN) /* Set IMC CP core dump */ IFX_CP_CRASH_DUMP_INIT(); /* Notify active/sleep status of AP to CP*/ ifx_init_modem_send(); #endif #if defined(HSI_GPIO_CAWKAE_NOTIFY_ENABLE) ifx_init_gpio_cawake_notify(hsi_ctrl); #endif return err; rollback3: hsi_debug_remove_ctrl(hsi_ctrl); rollback2: hsi_controller_exit(hsi_ctrl); /* From here no need for HSI HW access */ hsi_clocks_disable(hsi_ctrl->dev, __func__); rollback1: kfree(hsi_ctrl); return err; }