diff options
author | Roger Quadros <rogerq@ti.com> | 2014-03-07 01:13:39 -0500 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2014-03-09 03:15:10 -0400 |
commit | 61f546747715683c334ef231fd648522312dc5ff (patch) | |
tree | a5134105df1218bb67fc6ea9c5ced0c0baeda8f9 | |
parent | 1562864f0f034ea393230b470d104e1196b4a5f1 (diff) |
phy: ti-pipe3: Add SATA DPLL support
USB and SATA DPLLs need different settings. Provide
the SATA DPLL settings and use the proper DPLL settings
based on device tree node's compatible_id.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | drivers/phy/phy-ti-pipe3.c | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 211703c87fb9..f141237131c3 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -66,6 +66,11 @@ struct pipe3_dpll_params { | |||
66 | u32 mf; | 66 | u32 mf; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | struct pipe3_dpll_map { | ||
70 | unsigned long rate; | ||
71 | struct pipe3_dpll_params params; | ||
72 | }; | ||
73 | |||
69 | struct ti_pipe3 { | 74 | struct ti_pipe3 { |
70 | void __iomem *pll_ctrl_base; | 75 | void __iomem *pll_ctrl_base; |
71 | struct device *dev; | 76 | struct device *dev; |
@@ -73,20 +78,27 @@ struct ti_pipe3 { | |||
73 | struct clk *wkupclk; | 78 | struct clk *wkupclk; |
74 | struct clk *sys_clk; | 79 | struct clk *sys_clk; |
75 | struct clk *refclk; | 80 | struct clk *refclk; |
81 | struct pipe3_dpll_map *dpll_map; | ||
76 | }; | 82 | }; |
77 | 83 | ||
78 | struct pipe3_dpll_map { | 84 | static struct pipe3_dpll_map dpll_map_usb[] = { |
79 | unsigned long rate; | ||
80 | struct pipe3_dpll_params params; | ||
81 | }; | ||
82 | |||
83 | static struct pipe3_dpll_map dpll_map[] = { | ||
84 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ | 85 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ |
85 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ | 86 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ |
86 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ | 87 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ |
87 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ | 88 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ |
88 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ | 89 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ |
89 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ | 90 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ |
91 | { }, /* Terminator */ | ||
92 | }; | ||
93 | |||
94 | static struct pipe3_dpll_map dpll_map_sata[] = { | ||
95 | {12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */ | ||
96 | {16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */ | ||
97 | {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ | ||
98 | {20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */ | ||
99 | {26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */ | ||
100 | {38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */ | ||
101 | { }, /* Terminator */ | ||
90 | }; | 102 | }; |
91 | 103 | ||
92 | static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset) | 104 | static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset) |
@@ -100,15 +112,20 @@ static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset, | |||
100 | __raw_writel(data, addr + offset); | 112 | __raw_writel(data, addr + offset); |
101 | } | 113 | } |
102 | 114 | ||
103 | static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(unsigned long rate) | 115 | static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy) |
104 | { | 116 | { |
105 | int i; | 117 | unsigned long rate; |
118 | struct pipe3_dpll_map *dpll_map = phy->dpll_map; | ||
106 | 119 | ||
107 | for (i = 0; i < ARRAY_SIZE(dpll_map); i++) { | 120 | rate = clk_get_rate(phy->sys_clk); |
108 | if (rate == dpll_map[i].rate) | 121 | |
109 | return &dpll_map[i].params; | 122 | for (; dpll_map->rate; dpll_map++) { |
123 | if (rate == dpll_map->rate) | ||
124 | return &dpll_map->params; | ||
110 | } | 125 | } |
111 | 126 | ||
127 | dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate); | ||
128 | |||
112 | return NULL; | 129 | return NULL; |
113 | } | 130 | } |
114 | 131 | ||
@@ -182,16 +199,11 @@ static void ti_pipe3_dpll_relock(struct ti_pipe3 *phy) | |||
182 | static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy) | 199 | static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy) |
183 | { | 200 | { |
184 | u32 val; | 201 | u32 val; |
185 | unsigned long rate; | ||
186 | struct pipe3_dpll_params *dpll_params; | 202 | struct pipe3_dpll_params *dpll_params; |
187 | 203 | ||
188 | rate = clk_get_rate(phy->sys_clk); | 204 | dpll_params = ti_pipe3_get_dpll_params(phy); |
189 | dpll_params = ti_pipe3_get_dpll_params(rate); | 205 | if (!dpll_params) |
190 | if (!dpll_params) { | ||
191 | dev_err(phy->dev, | ||
192 | "No DPLL configuration for %lu Hz SYS CLK\n", rate); | ||
193 | return -EINVAL; | 206 | return -EINVAL; |
194 | } | ||
195 | 207 | ||
196 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | 208 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); |
197 | val &= ~PLL_REGN_MASK; | 209 | val &= ~PLL_REGN_MASK; |
@@ -244,6 +256,10 @@ static struct phy_ops ops = { | |||
244 | .owner = THIS_MODULE, | 256 | .owner = THIS_MODULE, |
245 | }; | 257 | }; |
246 | 258 | ||
259 | #ifdef CONFIG_OF | ||
260 | static const struct of_device_id ti_pipe3_id_table[]; | ||
261 | #endif | ||
262 | |||
247 | static int ti_pipe3_probe(struct platform_device *pdev) | 263 | static int ti_pipe3_probe(struct platform_device *pdev) |
248 | { | 264 | { |
249 | struct ti_pipe3 *phy; | 265 | struct ti_pipe3 *phy; |
@@ -253,8 +269,10 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
253 | struct device_node *node = pdev->dev.of_node; | 269 | struct device_node *node = pdev->dev.of_node; |
254 | struct device_node *control_node; | 270 | struct device_node *control_node; |
255 | struct platform_device *control_pdev; | 271 | struct platform_device *control_pdev; |
272 | const struct of_device_id *match; | ||
256 | 273 | ||
257 | if (!node) | 274 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev); |
275 | if (!match) | ||
258 | return -EINVAL; | 276 | return -EINVAL; |
259 | 277 | ||
260 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 278 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
@@ -263,6 +281,12 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
263 | return -ENOMEM; | 281 | return -ENOMEM; |
264 | } | 282 | } |
265 | 283 | ||
284 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | ||
285 | if (!phy->dpll_map) { | ||
286 | dev_err(&pdev->dev, "no DPLL data\n"); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
266 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | 290 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); |
267 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | 291 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); |
268 | if (IS_ERR(phy->pll_ctrl_base)) | 292 | if (IS_ERR(phy->pll_ctrl_base)) |
@@ -388,8 +412,18 @@ static const struct dev_pm_ops ti_pipe3_pm_ops = { | |||
388 | 412 | ||
389 | #ifdef CONFIG_OF | 413 | #ifdef CONFIG_OF |
390 | static const struct of_device_id ti_pipe3_id_table[] = { | 414 | static const struct of_device_id ti_pipe3_id_table[] = { |
391 | { .compatible = "ti,phy-usb3" }, | 415 | { |
392 | { .compatible = "ti,omap-usb3" }, | 416 | .compatible = "ti,phy-usb3", |
417 | .data = dpll_map_usb, | ||
418 | }, | ||
419 | { | ||
420 | .compatible = "ti,omap-usb3", | ||
421 | .data = dpll_map_usb, | ||
422 | }, | ||
423 | { | ||
424 | .compatible = "ti,phy-pipe3-sata", | ||
425 | .data = dpll_map_sata, | ||
426 | }, | ||
393 | {} | 427 | {} |
394 | }; | 428 | }; |
395 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); | 429 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); |