summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ahci_da850.c91
1 files changed, 76 insertions, 15 deletions
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index d65088a2fd5f..1a50cd3b4233 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -29,17 +29,8 @@
29#define SATA_PHY_TXSWING(x) ((x) << 19) 29#define SATA_PHY_TXSWING(x) ((x) << 19)
30#define SATA_PHY_ENPLL(x) ((x) << 31) 30#define SATA_PHY_ENPLL(x) ((x) << 31)
31 31
32/*
33 * The multiplier needed for 1.5GHz PLL output.
34 *
35 * NOTE: This is currently hardcoded to be suitable for 100MHz crystal
36 * frequency (which is used by DA850 EVM board) and may need to be changed
37 * if you would like to use this driver on some other board.
38 */
39#define DA850_SATA_CLK_MULTIPLIER 7
40
41static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, 32static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
42 void __iomem *ahci_base) 33 void __iomem *ahci_base, u32 mpy)
43{ 34{
44 unsigned int val; 35 unsigned int val;
45 36
@@ -48,13 +39,61 @@ static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
48 val &= ~BIT(0); 39 val &= ~BIT(0);
49 writel(val, pwrdn_reg); 40 writel(val, pwrdn_reg);
50 41
51 val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) | 42 val = SATA_PHY_MPY(mpy) | SATA_PHY_LOS(1) | SATA_PHY_RXCDR(4) |
52 SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | 43 SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | SATA_PHY_ENPLL(1);
53 SATA_PHY_ENPLL(1);
54 44
55 writel(val, ahci_base + SATA_P0PHYCR_REG); 45 writel(val, ahci_base + SATA_P0PHYCR_REG);
56} 46}
57 47
48static u32 ahci_da850_calculate_mpy(unsigned long refclk_rate)
49{
50 u32 pll_output = 1500000000, needed;
51
52 /*
53 * We need to determine the value of the multiplier (MPY) bits.
54 * In order to include the 12.5 multiplier we need to first divide
55 * the refclk rate by ten.
56 *
57 * __div64_32() turned out to be unreliable, sometimes returning
58 * false results.
59 */
60 WARN((refclk_rate % 10) != 0, "refclk must be divisible by 10");
61 needed = pll_output / (refclk_rate / 10);
62
63 /*
64 * What we have now is (multiplier * 10).
65 *
66 * Let's determine the actual register value we need to write.
67 */
68
69 switch (needed) {
70 case 50:
71 return 0x1;
72 case 60:
73 return 0x2;
74 case 80:
75 return 0x4;
76 case 100:
77 return 0x5;
78 case 120:
79 return 0x6;
80 case 125:
81 return 0x7;
82 case 150:
83 return 0x8;
84 case 200:
85 return 0x9;
86 case 250:
87 return 0xa;
88 default:
89 /*
90 * We should have divided evenly - if not, return an invalid
91 * value.
92 */
93 return 0;
94 }
95}
96
58static int ahci_da850_softreset(struct ata_link *link, 97static int ahci_da850_softreset(struct ata_link *link,
59 unsigned int *class, unsigned long deadline) 98 unsigned int *class, unsigned long deadline)
60{ 99{
@@ -126,9 +165,10 @@ static int ahci_da850_probe(struct platform_device *pdev)
126{ 165{
127 struct device *dev = &pdev->dev; 166 struct device *dev = &pdev->dev;
128 struct ahci_host_priv *hpriv; 167 struct ahci_host_priv *hpriv;
129 struct resource *res;
130 void __iomem *pwrdn_reg; 168 void __iomem *pwrdn_reg;
169 struct resource *res;
131 struct clk *clk; 170 struct clk *clk;
171 u32 mpy;
132 int rc; 172 int rc;
133 173
134 hpriv = ahci_platform_get_resources(pdev); 174 hpriv = ahci_platform_get_resources(pdev);
@@ -150,6 +190,27 @@ static int ahci_da850_probe(struct platform_device *pdev)
150 hpriv->clks[0] = clk; 190 hpriv->clks[0] = clk;
151 } 191 }
152 192
193 /*
194 * The second clock used by ahci-da850 is the external REFCLK. If we
195 * didn't get it from ahci_platform_get_resources(), let's try to
196 * specify the con_id in clk_get().
197 */
198 if (!hpriv->clks[1]) {
199 clk = clk_get(dev, "refclk");
200 if (IS_ERR(clk)) {
201 dev_err(dev, "unable to obtain the reference clock");
202 return -ENODEV;
203 }
204
205 hpriv->clks[1] = clk;
206 }
207
208 mpy = ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1]));
209 if (mpy == 0) {
210 dev_err(dev, "invalid REFCLK multiplier value: 0x%x", mpy);
211 return -EINVAL;
212 }
213
153 rc = ahci_platform_enable_resources(hpriv); 214 rc = ahci_platform_enable_resources(hpriv);
154 if (rc) 215 if (rc)
155 return rc; 216 return rc;
@@ -162,7 +223,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
162 if (!pwrdn_reg) 223 if (!pwrdn_reg)
163 goto disable_resources; 224 goto disable_resources;
164 225
165 da850_sata_init(dev, pwrdn_reg, hpriv->mmio); 226 da850_sata_init(dev, pwrdn_reg, hpriv->mmio, mpy);
166 227
167 rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 228 rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
168 &ahci_platform_sht); 229 &ahci_platform_sht);