123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 |
- /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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.
- */
- /*
- * SATA init module.
- * To be used with SATA interface on MSM targets.
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/io.h>
- #include <linux/err.h>
- #include <linux/device.h>
- #include <linux/platform_device.h>
- #include <linux/dma-mapping.h>
- #include <linux/delay.h>
- #include <linux/clk.h>
- #include <linux/iopoll.h>
- #include <linux/regulator/consumer.h>
- #include <linux/ahci_platform.h>
- #include <mach/clk.h>
- /* PHY registers */
- #define UNIPHY_PLL_REFCLK_CFG 0x000
- #define UNIPHY_PLL_POSTDIV1_CFG 0x004
- #define UNIPHY_PLL_CHGPUMP_CFG 0x008
- #define UNIPHY_PLL_VCOLPF_CFG 0x00C
- #define UNIPHY_PLL_VREG_CFG 0x010
- #define UNIPHY_PLL_PWRGEN_CFG 0x014
- #define UNIPHY_PLL_DMUX_CFG 0x018
- #define UNIPHY_PLL_AMUX_CFG 0x01C
- #define UNIPHY_PLL_GLB_CFG 0x020
- #define UNIPHY_PLL_POSTDIV2_CFG 0x024
- #define UNIPHY_PLL_POSTDIV3_CFG 0x028
- #define UNIPHY_PLL_LPFR_CFG 0x02C
- #define UNIPHY_PLL_LPFC1_CFG 0x030
- #define UNIPHY_PLL_LPFC2_CFG 0x034
- #define UNIPHY_PLL_SDM_CFG0 0x038
- #define UNIPHY_PLL_SDM_CFG1 0x03C
- #define UNIPHY_PLL_SDM_CFG2 0x040
- #define UNIPHY_PLL_SDM_CFG3 0x044
- #define UNIPHY_PLL_SDM_CFG4 0x048
- #define UNIPHY_PLL_SSC_CFG0 0x04C
- #define UNIPHY_PLL_SSC_CFG1 0x050
- #define UNIPHY_PLL_SSC_CFG2 0x054
- #define UNIPHY_PLL_SSC_CFG3 0x058
- #define UNIPHY_PLL_LKDET_CFG0 0x05C
- #define UNIPHY_PLL_LKDET_CFG1 0x060
- #define UNIPHY_PLL_LKDET_CFG2 0x064
- #define UNIPHY_PLL_TEST_CFG 0x068
- #define UNIPHY_PLL_CAL_CFG0 0x06C
- #define UNIPHY_PLL_CAL_CFG1 0x070
- #define UNIPHY_PLL_CAL_CFG2 0x074
- #define UNIPHY_PLL_CAL_CFG3 0x078
- #define UNIPHY_PLL_CAL_CFG4 0x07C
- #define UNIPHY_PLL_CAL_CFG5 0x080
- #define UNIPHY_PLL_CAL_CFG6 0x084
- #define UNIPHY_PLL_CAL_CFG7 0x088
- #define UNIPHY_PLL_CAL_CFG8 0x08C
- #define UNIPHY_PLL_CAL_CFG9 0x090
- #define UNIPHY_PLL_CAL_CFG10 0x094
- #define UNIPHY_PLL_CAL_CFG11 0x098
- #define UNIPHY_PLL_EFUSE_CFG 0x09C
- #define UNIPHY_PLL_DEBUG_BUS_SEL 0x0A0
- #define UNIPHY_PLL_CTRL_42 0x0A4
- #define UNIPHY_PLL_CTRL_43 0x0A8
- #define UNIPHY_PLL_CTRL_44 0x0AC
- #define UNIPHY_PLL_CTRL_45 0x0B0
- #define UNIPHY_PLL_CTRL_46 0x0B4
- #define UNIPHY_PLL_CTRL_47 0x0B8
- #define UNIPHY_PLL_CTRL_48 0x0BC
- #define UNIPHY_PLL_STATUS 0x0C0
- #define UNIPHY_PLL_DEBUG_BUS0 0x0C4
- #define UNIPHY_PLL_DEBUG_BUS1 0x0C8
- #define UNIPHY_PLL_DEBUG_BUS2 0x0CC
- #define UNIPHY_PLL_DEBUG_BUS3 0x0D0
- #define UNIPHY_PLL_CTRL_54 0x0D4
- #define SATA_PHY_SER_CTRL 0x100
- #define SATA_PHY_TX_DRIV_CTRL0 0x104
- #define SATA_PHY_TX_DRIV_CTRL1 0x108
- #define SATA_PHY_TX_DRIV_CTRL2 0x10C
- #define SATA_PHY_TX_DRIV_CTRL3 0x110
- #define SATA_PHY_TX_RESV0 0x114
- #define SATA_PHY_TX_RESV1 0x118
- #define SATA_PHY_TX_IMCAL0 0x11C
- #define SATA_PHY_TX_IMCAL1 0x120
- #define SATA_PHY_TX_IMCAL2 0x124
- #define SATA_PHY_RX_IMCAL0 0x128
- #define SATA_PHY_RX_IMCAL1 0x12C
- #define SATA_PHY_RX_IMCAL2 0x130
- #define SATA_PHY_RX_TERM 0x134
- #define SATA_PHY_RX_TERM_RESV 0x138
- #define SATA_PHY_EQUAL 0x13C
- #define SATA_PHY_EQUAL_RESV 0x140
- #define SATA_PHY_OOB_TERM 0x144
- #define SATA_PHY_CDR_CTRL0 0x148
- #define SATA_PHY_CDR_CTRL1 0x14C
- #define SATA_PHY_CDR_CTRL2 0x150
- #define SATA_PHY_CDR_CTRL3 0x154
- #define SATA_PHY_CDR_CTRL4 0x158
- #define SATA_PHY_FA_LOAD0 0x15C
- #define SATA_PHY_FA_LOAD1 0x160
- #define SATA_PHY_CDR_CTRL_RESV 0x164
- #define SATA_PHY_PI_CTRL0 0x168
- #define SATA_PHY_PI_CTRL1 0x16C
- #define SATA_PHY_DESER_RESV 0x170
- #define SATA_PHY_RX_RESV0 0x174
- #define SATA_PHY_AD_TPA_CTRL 0x178
- #define SATA_PHY_REFCLK_CTRL 0x17C
- #define SATA_PHY_POW_DWN_CTRL0 0x180
- #define SATA_PHY_POW_DWN_CTRL1 0x184
- #define SATA_PHY_TX_DATA_CTRL 0x188
- #define SATA_PHY_BIST_GEN0 0x18C
- #define SATA_PHY_BIST_GEN1 0x190
- #define SATA_PHY_BIST_GEN2 0x194
- #define SATA_PHY_BIST_GEN3 0x198
- #define SATA_PHY_LBK_CTRL 0x19C
- #define SATA_PHY_TEST_DEBUG_CTRL 0x1A0
- #define SATA_PHY_ALIGNP 0x1A4
- #define SATA_PHY_PRBS_CFG0 0x1A8
- #define SATA_PHY_PRBS_CFG1 0x1AC
- #define SATA_PHY_PRBS_CFG2 0x1B0
- #define SATA_PHY_PRBS_CFG3 0x1B4
- #define SATA_PHY_CHAN_COMP_CHK_CNT 0x1B8
- #define SATA_PHY_RESET_CTRL 0x1BC
- #define SATA_PHY_RX_CLR 0x1C0
- #define SATA_PHY_RX_EBUF_CTRL 0x1C4
- #define SATA_PHY_ID0 0x1C8
- #define SATA_PHY_ID1 0x1CC
- #define SATA_PHY_ID2 0x1D0
- #define SATA_PHY_ID3 0x1D4
- #define SATA_PHY_RX_CHK_ERR_CNT0 0x1D8
- #define SATA_PHY_RX_CHK_ERR_CNT1 0x1DC
- #define SATA_PHY_RX_CHK_STAT 0x1E0
- #define SATA_PHY_TX_IMCAL_STAT 0x1E4
- #define SATA_PHY_RX_IMCAL_STAT 0x1E8
- #define SATA_PHY_RX_EBUF_STAT 0x1EC
- #define SATA_PHY_DEBUG_BUS_STAT0 0x1F0
- #define SATA_PHY_DEBUG_BUS_STAT1 0x1F4
- #define SATA_PHY_DEBUG_BUS_STAT2 0x1F8
- #define SATA_PHY_DEBUG_BUS_STAT3 0x1FC
- #define AHCI_HOST_CAP 0x00
- #define AHCI_HOST_CAP_MASK 0x1F
- #define AHCI_HOST_CAP_PMP (1 << 17)
- struct msm_sata_hba {
- struct platform_device *ahci_pdev;
- struct clk *slave_iface_clk;
- struct clk *bus_clk;
- struct clk *iface_clk;
- struct clk *src_clk;
- struct clk *rxoob_clk;
- struct clk *pmalive_clk;
- struct clk *cfg_clk;
- struct regulator *clk_pwr;
- struct regulator *pmp_pwr;
- void __iomem *phy_base;
- void __iomem *ahci_base;
- };
- static inline void msm_sata_delay_us(unsigned int delay)
- {
- /* sleep for max. 50us more to combine processor wakeups */
- usleep_range(delay, delay + 50);
- }
- static int msm_sata_clk_get_prepare_enable_set_rate(struct device *dev,
- const char *name, struct clk **out_clk, int rate)
- {
- int ret = 0;
- struct clk *clk;
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(dev, "failed to get clk: %s err = %d\n", name, ret);
- goto out;
- }
- if (rate >= 0) {
- ret = clk_set_rate(clk, rate);
- if (ret) {
- dev_err(dev, "failed to set rate: %d clk: %s err = %d\n",
- rate, name, ret);
- goto out;
- }
- }
- ret = clk_prepare_enable(clk);
- if (ret)
- dev_err(dev, "failed to enable clk: %s err = %d\n", name, ret);
- out:
- if (!ret)
- *out_clk = clk;
- return ret;
- }
- static int msm_sata_clk_get_prepare_enable(struct device *dev,
- const char *name, struct clk **out_clk)
- {
- return msm_sata_clk_get_prepare_enable_set_rate(dev, name, out_clk, -1);
- }
- static void msm_sata_clk_put_unprepare_disable(struct clk **clk)
- {
- if (*clk) {
- clk_disable_unprepare(*clk);
- clk_put(*clk);
- *clk = NULL;
- }
- }
- static int msm_sata_hard_reset(struct device *dev)
- {
- int ret;
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- ret = clk_reset(hba->iface_clk, CLK_RESET_ASSERT);
- if (ret) {
- dev_err(dev, "iface_clk assert failed %d\n", ret);
- goto out;
- }
- ret = clk_reset(hba->iface_clk, CLK_RESET_DEASSERT);
- if (ret) {
- dev_err(dev, "iface_clk de-assert failed %d\n", ret);
- goto out;
- }
- out:
- return ret;
- }
- static int msm_sata_clk_init(struct device *dev)
- {
- int ret = 0;
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- /* Enable AHB clock for system fabric slave port connected to SATA */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "slave_iface_clk", &hba->slave_iface_clk);
- if (ret)
- goto out;
- /* Enable AHB clock for system fabric and SATA core interface */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "iface_clk", &hba->iface_clk);
- if (ret)
- goto put_dis_slave_iface_clk;
- /* Enable AXI clock for SATA AXI master and slave interfaces */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "bus_clk", &hba->bus_clk);
- if (ret)
- goto put_dis_iface_clk;
- /* Enable the source clock for pmalive, rxoob and phy ref clocks */
- ret = msm_sata_clk_get_prepare_enable_set_rate(dev,
- "src_clk", &hba->src_clk, 100000000);
- if (ret)
- goto put_dis_bus_clk;
- /*
- * Enable RX OOB detection clock. The clock rate is
- * same as PHY reference clock (100MHz).
- */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "core_rxoob_clk", &hba->rxoob_clk);
- if (ret)
- goto put_dis_src_clk;
- /*
- * Enable power management always-on clock. The clock rate
- * is same as PHY reference clock (100MHz).
- */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "core_pmalive_clk", &hba->pmalive_clk);
- if (ret)
- goto put_dis_rxoob_clk;
- /* Enable PHY configuration AHB clock, fixed 64MHz clock */
- ret = msm_sata_clk_get_prepare_enable(dev,
- "cfg_clk", &hba->cfg_clk);
- if (ret)
- goto put_dis_pmalive_clk;
- return ret;
- put_dis_pmalive_clk:
- msm_sata_clk_put_unprepare_disable(&hba->pmalive_clk);
- put_dis_rxoob_clk:
- msm_sata_clk_put_unprepare_disable(&hba->rxoob_clk);
- put_dis_src_clk:
- msm_sata_clk_put_unprepare_disable(&hba->src_clk);
- put_dis_bus_clk:
- msm_sata_clk_put_unprepare_disable(&hba->bus_clk);
- put_dis_iface_clk:
- msm_sata_clk_put_unprepare_disable(&hba->iface_clk);
- put_dis_slave_iface_clk:
- msm_sata_clk_put_unprepare_disable(&hba->slave_iface_clk);
- out:
- return ret;
- }
- static void msm_sata_clk_deinit(struct device *dev)
- {
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- msm_sata_clk_put_unprepare_disable(&hba->cfg_clk);
- msm_sata_clk_put_unprepare_disable(&hba->pmalive_clk);
- msm_sata_clk_put_unprepare_disable(&hba->rxoob_clk);
- msm_sata_clk_put_unprepare_disable(&hba->src_clk);
- msm_sata_clk_put_unprepare_disable(&hba->bus_clk);
- msm_sata_clk_put_unprepare_disable(&hba->iface_clk);
- msm_sata_clk_put_unprepare_disable(&hba->slave_iface_clk);
- }
- static int msm_sata_vreg_get_enable_set_vdd(struct device *dev,
- const char *name, struct regulator **out_vreg,
- int min_uV, int max_uV, int hpm_uA)
- {
- int ret = 0;
- struct regulator *vreg;
- vreg = devm_regulator_get(dev, name);
- if (IS_ERR(vreg)) {
- ret = PTR_ERR(vreg);
- dev_err(dev, "Regulator: %s get failed, err=%d\n", name, ret);
- goto out;
- }
- if (regulator_count_voltages(vreg) > 0) {
- ret = regulator_set_voltage(vreg, min_uV, max_uV);
- if (ret) {
- dev_err(dev, "Regulator: %s set voltage failed, err=%d\n",
- name, ret);
- goto err;
- }
- ret = regulator_set_optimum_mode(vreg, hpm_uA);
- if (ret < 0) {
- dev_err(dev, "Regulator: %s set optimum mode(uA_load=%d) failed, err=%d\n",
- name, hpm_uA, ret);
- goto err;
- } else {
- /*
- * regulator_set_optimum_mode() can return non zero
- * value even for success case.
- */
- ret = 0;
- }
- }
- ret = regulator_enable(vreg);
- if (ret)
- dev_err(dev, "Regulator: %s enable failed, err=%d\n",
- name, ret);
- err:
- if (!ret)
- *out_vreg = vreg;
- else
- devm_regulator_put(vreg);
- out:
- return ret;
- }
- static int msm_sata_vreg_put_disable(struct device *dev,
- struct regulator *reg, const char *name, int max_uV)
- {
- int ret;
- if (!reg)
- return 0;
- ret = regulator_disable(reg);
- if (ret) {
- dev_err(dev, "Regulator: %s disable failed err=%d\n",
- name, ret);
- goto err;
- }
- if (regulator_count_voltages(reg) > 0) {
- ret = regulator_set_voltage(reg, 0, max_uV);
- if (ret < 0) {
- dev_err(dev, "Regulator: %s set voltage to 0 failed, err=%d\n",
- name, ret);
- goto err;
- }
- ret = regulator_set_optimum_mode(reg, 0);
- if (ret < 0) {
- dev_err(dev, "Regulator: %s set optimum mode(uA_load = 0) failed, err=%d\n",
- name, ret);
- goto err;
- } else {
- /*
- * regulator_set_optimum_mode() can return non zero
- * value even for success case.
- */
- ret = 0;
- }
- }
- err:
- devm_regulator_put(reg);
- return ret;
- }
- static int msm_sata_vreg_init(struct device *dev)
- {
- int ret = 0;
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- /*
- * The SATA clock generator needs 3.3V supply and can consume
- * max. 850mA during functional mode.
- */
- ret = msm_sata_vreg_get_enable_set_vdd(dev, "sata_ext_3p3v",
- &hba->clk_pwr, 3300000, 3300000, 850000);
- if (ret)
- goto out;
- /* Add 1ms regulator ramp-up delay */
- msm_sata_delay_us(1000);
- /* Read AHCI capability register to check if PMP is supported.*/
- if (readl_relaxed(hba->ahci_base +
- AHCI_HOST_CAP) & AHCI_HOST_CAP_PMP) {
- /* Power up port-multiplier */
- ret = msm_sata_vreg_get_enable_set_vdd(dev, "sata_pmp_pwr",
- &hba->pmp_pwr, 1800000, 1800000, 200000);
- if (ret) {
- msm_sata_vreg_put_disable(dev, hba->clk_pwr,
- "sata_ext_3p3v", 3300000);
- goto out;
- }
- /* Add 1ms regulator ramp-up delay */
- msm_sata_delay_us(1000);
- }
- out:
- return ret;
- }
- static void msm_sata_vreg_deinit(struct device *dev)
- {
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- msm_sata_vreg_put_disable(dev, hba->clk_pwr,
- "sata_ext_3p3v", 3300000);
- if (hba->pmp_pwr)
- msm_sata_vreg_put_disable(dev, hba->pmp_pwr,
- "sata_pmp_pwr", 1800000);
- }
- static void msm_sata_phy_deinit(struct device *dev)
- {
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- /* Power down PHY */
- writel_relaxed(0xF8, hba->phy_base + SATA_PHY_POW_DWN_CTRL0);
- writel_relaxed(0xFE, hba->phy_base + SATA_PHY_POW_DWN_CTRL1);
- /* Power down PLL block */
- writel_relaxed(0x00, hba->phy_base + UNIPHY_PLL_GLB_CFG);
- mb();
- devm_iounmap(dev, hba->phy_base);
- }
- static int msm_sata_phy_init(struct device *dev)
- {
- int ret = 0;
- u32 reg = 0;
- struct platform_device *pdev = to_platform_device(dev);
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- struct resource *mem;
- mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
- if (!mem) {
- dev_err(dev, "no mmio space\n");
- return -EINVAL;
- }
- hba->phy_base = devm_ioremap(dev, mem->start, resource_size(mem));
- if (!hba->phy_base) {
- dev_err(dev, "failed to allocate memory for SATA PHY\n");
- return -ENOMEM;
- }
- /* SATA phy initialization */
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_SER_CTRL);
- writel_relaxed(0xB1, hba->phy_base + SATA_PHY_POW_DWN_CTRL0);
- mb();
- msm_sata_delay_us(10);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_POW_DWN_CTRL0);
- writel_relaxed(0x3E, hba->phy_base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_RX_IMCAL0);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_TX_IMCAL0);
- writel_relaxed(0x02, hba->phy_base + SATA_PHY_TX_IMCAL2);
- /* Write UNIPHYPLL registers to configure PLL */
- writel_relaxed(0x04, hba->phy_base + UNIPHY_PLL_REFCLK_CFG);
- writel_relaxed(0x00, hba->phy_base + UNIPHY_PLL_PWRGEN_CFG);
- writel_relaxed(0x0A, hba->phy_base + UNIPHY_PLL_CAL_CFG0);
- writel_relaxed(0xF3, hba->phy_base + UNIPHY_PLL_CAL_CFG8);
- writel_relaxed(0x01, hba->phy_base + UNIPHY_PLL_CAL_CFG9);
- writel_relaxed(0xED, hba->phy_base + UNIPHY_PLL_CAL_CFG10);
- writel_relaxed(0x02, hba->phy_base + UNIPHY_PLL_CAL_CFG11);
- writel_relaxed(0x36, hba->phy_base + UNIPHY_PLL_SDM_CFG0);
- writel_relaxed(0x0D, hba->phy_base + UNIPHY_PLL_SDM_CFG1);
- writel_relaxed(0xA3, hba->phy_base + UNIPHY_PLL_SDM_CFG2);
- writel_relaxed(0xF0, hba->phy_base + UNIPHY_PLL_SDM_CFG3);
- writel_relaxed(0x00, hba->phy_base + UNIPHY_PLL_SDM_CFG4);
- writel_relaxed(0x19, hba->phy_base + UNIPHY_PLL_SSC_CFG0);
- writel_relaxed(0xE1, hba->phy_base + UNIPHY_PLL_SSC_CFG1);
- writel_relaxed(0x00, hba->phy_base + UNIPHY_PLL_SSC_CFG2);
- writel_relaxed(0x11, hba->phy_base + UNIPHY_PLL_SSC_CFG3);
- writel_relaxed(0x04, hba->phy_base + UNIPHY_PLL_LKDET_CFG0);
- writel_relaxed(0xFF, hba->phy_base + UNIPHY_PLL_LKDET_CFG1);
- writel_relaxed(0x02, hba->phy_base + UNIPHY_PLL_GLB_CFG);
- mb();
- msm_sata_delay_us(40);
- writel_relaxed(0x03, hba->phy_base + UNIPHY_PLL_GLB_CFG);
- mb();
- msm_sata_delay_us(400);
- writel_relaxed(0x05, hba->phy_base + UNIPHY_PLL_LKDET_CFG2);
- mb();
- /* poll for ready status, timeout after 1 sec */
- ret = readl_poll_timeout(hba->phy_base + UNIPHY_PLL_STATUS, reg,
- (reg & 1 << 0), 100, 1000000);
- if (ret) {
- dev_err(dev, "poll timeout UNIPHY_PLL_STATUS\n");
- goto out;
- }
- ret = readl_poll_timeout(hba->phy_base + SATA_PHY_TX_IMCAL_STAT, reg,
- (reg & 1 << 0), 100, 1000000);
- if (ret) {
- dev_err(dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
- goto out;
- }
- ret = readl_poll_timeout(hba->phy_base + SATA_PHY_RX_IMCAL_STAT, reg,
- (reg & 1 << 0), 100, 1000000);
- if (ret) {
- dev_err(dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
- goto out;
- }
- /* SATA phy calibrated succesfully, power up to functional mode */
- writel_relaxed(0x3E, hba->phy_base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_RX_IMCAL0);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_TX_IMCAL0);
- writel_relaxed(0x00, hba->phy_base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x59, hba->phy_base + SATA_PHY_CDR_CTRL0);
- writel_relaxed(0x04, hba->phy_base + SATA_PHY_CDR_CTRL1);
- writel_relaxed(0x00, hba->phy_base + SATA_PHY_CDR_CTRL2);
- writel_relaxed(0x00, hba->phy_base + SATA_PHY_PI_CTRL0);
- writel_relaxed(0x00, hba->phy_base + SATA_PHY_CDR_CTRL3);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_POW_DWN_CTRL0);
- writel_relaxed(0x11, hba->phy_base + SATA_PHY_TX_DATA_CTRL);
- writel_relaxed(0x43, hba->phy_base + SATA_PHY_ALIGNP);
- writel_relaxed(0x04, hba->phy_base + SATA_PHY_OOB_TERM);
- writel_relaxed(0x01, hba->phy_base + SATA_PHY_EQUAL);
- writel_relaxed(0x09, hba->phy_base + SATA_PHY_TX_DRIV_CTRL0);
- writel_relaxed(0x09, hba->phy_base + SATA_PHY_TX_DRIV_CTRL1);
- mb();
- dev_dbg(dev, "SATA PHY powered up in functional mode\n");
- out:
- /* power down PHY in case of failure */
- if (ret)
- msm_sata_phy_deinit(dev);
- return ret;
- }
- int msm_sata_init(struct device *ahci_dev, void __iomem *mmio)
- {
- int ret;
- struct device *dev = ahci_dev->parent;
- struct msm_sata_hba *hba = dev_get_drvdata(dev);
- /* Save ahci mmio to access vendor specific registers */
- hba->ahci_base = mmio;
- ret = msm_sata_clk_init(dev);
- if (ret) {
- dev_err(dev, "SATA clk init failed with err=%d\n", ret);
- goto out;
- }
- ret = msm_sata_vreg_init(dev);
- if (ret) {
- dev_err(dev, "SATA vreg init failed with err=%d\n", ret);
- msm_sata_clk_deinit(dev);
- goto out;
- }
- ret = msm_sata_phy_init(dev);
- if (ret) {
- dev_err(dev, "SATA PHY init failed with err=%d\n", ret);
- msm_sata_vreg_deinit(dev);
- msm_sata_clk_deinit(dev);
- goto out;
- }
- out:
- return ret;
- }
- void msm_sata_deinit(struct device *ahci_dev)
- {
- struct device *dev = ahci_dev->parent;
- msm_sata_phy_deinit(dev);
- msm_sata_vreg_deinit(dev);
- msm_sata_clk_deinit(dev);
- }
- static int msm_sata_suspend(struct device *ahci_dev)
- {
- msm_sata_deinit(ahci_dev);
- return 0;
- }
- static int msm_sata_resume(struct device *ahci_dev)
- {
- int ret;
- struct device *dev = ahci_dev->parent;
- ret = msm_sata_clk_init(dev);
- if (ret) {
- dev_err(dev, "SATA clk init failed with err=%d\n", ret);
- /*
- * If clock initialization failed, that means ahci driver
- * cannot access any register going further. Since there is
- * no check within ahci driver to check for clock failures,
- * panic here instead of making an unclocked register access.
- */
- BUG();
- }
- /* Issue asynchronous reset to reset PHY */
- ret = msm_sata_hard_reset(dev);
- if (ret)
- goto out;
- ret = msm_sata_vreg_init(dev);
- if (ret) {
- dev_err(dev, "SATA vreg init failed with err=%d\n", ret);
- /* Do not turn off clks, AHCI driver might do register access */
- goto out;
- }
- ret = msm_sata_phy_init(dev);
- if (ret) {
- dev_err(dev, "SATA PHY init failed with err=%d\n", ret);
- /* Do not turn off clks, AHCI driver might do register access */
- msm_sata_vreg_deinit(dev);
- goto out;
- }
- out:
- return ret;
- }
- static struct ahci_platform_data msm_ahci_pdata = {
- .init = msm_sata_init,
- .exit = msm_sata_deinit,
- .suspend = msm_sata_suspend,
- .resume = msm_sata_resume,
- };
- static int __devinit msm_sata_probe(struct platform_device *pdev)
- {
- struct platform_device *ahci;
- struct msm_sata_hba *hba;
- int ret = 0;
- hba = devm_kzalloc(&pdev->dev, sizeof(struct msm_sata_hba), GFP_KERNEL);
- if (!hba) {
- dev_err(&pdev->dev, "no memory\n");
- ret = -ENOMEM;
- goto err;
- }
- platform_set_drvdata(pdev, hba);
- ahci = platform_device_alloc("ahci", pdev->id);
- if (!ahci) {
- dev_err(&pdev->dev, "couldn't allocate ahci device\n");
- ret = -ENOMEM;
- goto err_free;
- }
- dma_set_coherent_mask(&ahci->dev, pdev->dev.coherent_dma_mask);
- ahci->dev.parent = &pdev->dev;
- ahci->dev.dma_mask = pdev->dev.dma_mask;
- ahci->dev.dma_parms = pdev->dev.dma_parms;
- hba->ahci_pdev = ahci;
- ret = platform_device_add_resources(ahci, pdev->resource,
- pdev->num_resources);
- if (ret) {
- dev_err(&pdev->dev, "couldn't add resources to ahci device\n");
- goto err_put_device;
- }
- ahci->dev.platform_data = &msm_ahci_pdata;
- ret = platform_device_add(ahci);
- if (ret) {
- dev_err(&pdev->dev, "failed to register ahci device\n");
- goto err_put_device;
- }
- return 0;
- err_put_device:
- platform_device_put(ahci);
- err_free:
- devm_kfree(&pdev->dev, hba);
- err:
- return ret;
- }
- static int __devexit msm_sata_remove(struct platform_device *pdev)
- {
- struct msm_sata_hba *hba = platform_get_drvdata(pdev);
- platform_device_unregister(hba->ahci_pdev);
- return 0;
- }
- static struct platform_driver msm_sata_driver = {
- .probe = msm_sata_probe,
- .remove = __devexit_p(msm_sata_remove),
- .driver = {
- .name = "msm_sata",
- },
- };
- module_platform_driver(msm_sata_driver);
- MODULE_LICENSE("GPL v2");
- MODULE_DESCRIPTION("AHCI platform MSM Glue Layer");
|