diff options
-rw-r--r-- | drivers/ata/ahci_da850.c | 91 |
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 | |||
41 | static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, | 32 | static 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 | ||
48 | static 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 | |||
58 | static int ahci_da850_softreset(struct ata_link *link, | 97 | static 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); |