diff options
author | Sean Paul <seanpaul@chromium.org> | 2014-09-10 10:52:04 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-11-13 10:11:54 -0500 |
commit | 08a15cc34ddf7b7247122de44687364bcd82c2bf (patch) | |
tree | 33ca5ff135cf820045f3ef00be5d42f1944bed79 | |
parent | 26f7a92a3a275cad7b0f39063e8cd92e002aff1a (diff) |
gpu: host1x: mipi: Calibrate clock lanes
Include the clock lanes when calibrating the MIPI PHY on Tegra124
compatible devices.
Signed-off-by: Sean Paul <seanpaul@chromium.org>
[treding@nvidia.com: bikeshedding]
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/host1x/mipi.c | 124 |
1 files changed, 92 insertions, 32 deletions
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c index 0d8c3ae8db6a..22e20c2399c5 100644 --- a/drivers/gpu/host1x/mipi.c +++ b/drivers/gpu/host1x/mipi.c | |||
@@ -49,11 +49,24 @@ | |||
49 | #define MIPI_CAL_CONFIG_DSIC 0x10 | 49 | #define MIPI_CAL_CONFIG_DSIC 0x10 |
50 | #define MIPI_CAL_CONFIG_DSID 0x11 | 50 | #define MIPI_CAL_CONFIG_DSID 0x11 |
51 | 51 | ||
52 | #define MIPI_CAL_CONFIG_DSIAB_CLK 0x19 | ||
53 | #define MIPI_CAL_CONFIG_DSICD_CLK 0x1a | ||
54 | #define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b | ||
55 | #define MIPI_CAL_CONFIG_CSICD_CLK 0x1c | ||
56 | #define MIPI_CAL_CONFIG_CSIE_CLK 0x1d | ||
57 | |||
58 | /* for data and clock lanes */ | ||
52 | #define MIPI_CAL_CONFIG_SELECT (1 << 21) | 59 | #define MIPI_CAL_CONFIG_SELECT (1 << 21) |
60 | |||
61 | /* for data lanes */ | ||
53 | #define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16) | 62 | #define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16) |
54 | #define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8) | 63 | #define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8) |
55 | #define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0) | 64 | #define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0) |
56 | 65 | ||
66 | /* for clock lanes */ | ||
67 | #define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8) | ||
68 | #define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0) | ||
69 | |||
57 | #define MIPI_CAL_BIAS_PAD_CFG0 0x16 | 70 | #define MIPI_CAL_BIAS_PAD_CFG0 0x16 |
58 | #define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1) | 71 | #define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1) |
59 | #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0) | 72 | #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0) |
@@ -63,21 +76,19 @@ | |||
63 | #define MIPI_CAL_BIAS_PAD_CFG2 0x18 | 76 | #define MIPI_CAL_BIAS_PAD_CFG2 0x18 |
64 | #define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) | 77 | #define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) |
65 | 78 | ||
66 | static const struct module { | 79 | struct tegra_mipi_pad { |
67 | unsigned long reg; | 80 | unsigned long data; |
68 | } modules[] = { | 81 | unsigned long clk; |
69 | { .reg = MIPI_CAL_CONFIG_CSIA }, | 82 | }; |
70 | { .reg = MIPI_CAL_CONFIG_CSIB }, | 83 | |
71 | { .reg = MIPI_CAL_CONFIG_CSIC }, | 84 | struct tegra_mipi_soc { |
72 | { .reg = MIPI_CAL_CONFIG_CSID }, | 85 | bool has_clk_lane; |
73 | { .reg = MIPI_CAL_CONFIG_CSIE }, | 86 | const struct tegra_mipi_pad *pads; |
74 | { .reg = MIPI_CAL_CONFIG_DSIA }, | 87 | unsigned int num_pads; |
75 | { .reg = MIPI_CAL_CONFIG_DSIB }, | ||
76 | { .reg = MIPI_CAL_CONFIG_DSIC }, | ||
77 | { .reg = MIPI_CAL_CONFIG_DSID }, | ||
78 | }; | 88 | }; |
79 | 89 | ||
80 | struct tegra_mipi { | 90 | struct tegra_mipi { |
91 | const struct tegra_mipi_soc *soc; | ||
81 | void __iomem *regs; | 92 | void __iomem *regs; |
82 | struct mutex lock; | 93 | struct mutex lock; |
83 | struct clk *clk; | 94 | struct clk *clk; |
@@ -117,36 +128,35 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device) | |||
117 | 128 | ||
118 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 129 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
119 | if (!dev) { | 130 | if (!dev) { |
120 | of_node_put(args.np); | ||
121 | err = -ENOMEM; | 131 | err = -ENOMEM; |
122 | goto out; | 132 | goto out; |
123 | } | 133 | } |
124 | 134 | ||
125 | dev->pdev = of_find_device_by_node(args.np); | 135 | dev->pdev = of_find_device_by_node(args.np); |
126 | if (!dev->pdev) { | 136 | if (!dev->pdev) { |
127 | of_node_put(args.np); | ||
128 | err = -ENODEV; | 137 | err = -ENODEV; |
129 | goto free; | 138 | goto free; |
130 | } | 139 | } |
131 | 140 | ||
132 | of_node_put(args.np); | ||
133 | |||
134 | dev->mipi = platform_get_drvdata(dev->pdev); | 141 | dev->mipi = platform_get_drvdata(dev->pdev); |
135 | if (!dev->mipi) { | 142 | if (!dev->mipi) { |
136 | err = -EPROBE_DEFER; | 143 | err = -EPROBE_DEFER; |
137 | goto pdev_put; | 144 | goto put; |
138 | } | 145 | } |
139 | 146 | ||
147 | of_node_put(args.np); | ||
148 | |||
140 | dev->pads = args.args[0]; | 149 | dev->pads = args.args[0]; |
141 | dev->device = device; | 150 | dev->device = device; |
142 | 151 | ||
143 | return dev; | 152 | return dev; |
144 | 153 | ||
145 | pdev_put: | 154 | put: |
146 | platform_device_put(dev->pdev); | 155 | platform_device_put(dev->pdev); |
147 | free: | 156 | free: |
148 | kfree(dev); | 157 | kfree(dev); |
149 | out: | 158 | out: |
159 | of_node_put(args.np); | ||
150 | return ERR_PTR(err); | 160 | return ERR_PTR(err); |
151 | } | 161 | } |
152 | EXPORT_SYMBOL(tegra_mipi_request); | 162 | EXPORT_SYMBOL(tegra_mipi_request); |
@@ -177,6 +187,7 @@ static int tegra_mipi_wait(struct tegra_mipi *mipi) | |||
177 | 187 | ||
178 | int tegra_mipi_calibrate(struct tegra_mipi_device *device) | 188 | int tegra_mipi_calibrate(struct tegra_mipi_device *device) |
179 | { | 189 | { |
190 | const struct tegra_mipi_soc *soc = device->mipi->soc; | ||
180 | unsigned int i; | 191 | unsigned int i; |
181 | u32 value; | 192 | u32 value; |
182 | int err; | 193 | int err; |
@@ -196,16 +207,23 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device) | |||
196 | value &= ~MIPI_CAL_BIAS_PAD_PDVREG; | 207 | value &= ~MIPI_CAL_BIAS_PAD_PDVREG; |
197 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); | 208 | tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); |
198 | 209 | ||
199 | for (i = 0; i < ARRAY_SIZE(modules); i++) { | 210 | for (i = 0; i < soc->num_pads; i++) { |
200 | if (device->pads & BIT(i)) | 211 | u32 clk = 0, data = 0; |
201 | value = MIPI_CAL_CONFIG_SELECT | | 212 | |
202 | MIPI_CAL_CONFIG_HSPDOS(0) | | 213 | if (device->pads & BIT(i)) { |
203 | MIPI_CAL_CONFIG_HSPUOS(4) | | 214 | data = MIPI_CAL_CONFIG_SELECT | |
204 | MIPI_CAL_CONFIG_TERMOS(5); | 215 | MIPI_CAL_CONFIG_HSPDOS(0) | |
205 | else | 216 | MIPI_CAL_CONFIG_HSPUOS(4) | |
206 | value = 0; | 217 | MIPI_CAL_CONFIG_TERMOS(5); |
218 | clk = MIPI_CAL_CONFIG_SELECT | | ||
219 | MIPI_CAL_CONFIG_HSCLKPDOSD(0) | | ||
220 | MIPI_CAL_CONFIG_HSCLKPUOSD(4); | ||
221 | } | ||
222 | |||
223 | tegra_mipi_writel(device->mipi, data, soc->pads[i].data); | ||
207 | 224 | ||
208 | tegra_mipi_writel(device->mipi, value, modules[i].reg); | 225 | if (soc->has_clk_lane) |
226 | tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk); | ||
209 | } | 227 | } |
210 | 228 | ||
211 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); | 229 | value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); |
@@ -221,16 +239,63 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device) | |||
221 | } | 239 | } |
222 | EXPORT_SYMBOL(tegra_mipi_calibrate); | 240 | EXPORT_SYMBOL(tegra_mipi_calibrate); |
223 | 241 | ||
242 | static const struct tegra_mipi_pad tegra114_mipi_pads[] = { | ||
243 | { .data = MIPI_CAL_CONFIG_CSIA }, | ||
244 | { .data = MIPI_CAL_CONFIG_CSIB }, | ||
245 | { .data = MIPI_CAL_CONFIG_CSIC }, | ||
246 | { .data = MIPI_CAL_CONFIG_CSID }, | ||
247 | { .data = MIPI_CAL_CONFIG_CSIE }, | ||
248 | { .data = MIPI_CAL_CONFIG_DSIA }, | ||
249 | { .data = MIPI_CAL_CONFIG_DSIB }, | ||
250 | { .data = MIPI_CAL_CONFIG_DSIC }, | ||
251 | { .data = MIPI_CAL_CONFIG_DSID }, | ||
252 | }; | ||
253 | |||
254 | static const struct tegra_mipi_soc tegra114_mipi_soc = { | ||
255 | .has_clk_lane = false, | ||
256 | .pads = tegra114_mipi_pads, | ||
257 | .num_pads = ARRAY_SIZE(tegra114_mipi_pads), | ||
258 | }; | ||
259 | |||
260 | static const struct tegra_mipi_pad tegra124_mipi_pads[] = { | ||
261 | { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, | ||
262 | { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, | ||
263 | { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, | ||
264 | { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, | ||
265 | { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK }, | ||
266 | { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, | ||
267 | { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, | ||
268 | }; | ||
269 | |||
270 | static const struct tegra_mipi_soc tegra124_mipi_soc = { | ||
271 | .has_clk_lane = true, | ||
272 | .pads = tegra124_mipi_pads, | ||
273 | .num_pads = ARRAY_SIZE(tegra124_mipi_pads), | ||
274 | }; | ||
275 | |||
276 | static struct of_device_id tegra_mipi_of_match[] = { | ||
277 | { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc }, | ||
278 | { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc }, | ||
279 | { }, | ||
280 | }; | ||
281 | |||
224 | static int tegra_mipi_probe(struct platform_device *pdev) | 282 | static int tegra_mipi_probe(struct platform_device *pdev) |
225 | { | 283 | { |
284 | const struct of_device_id *match; | ||
226 | struct tegra_mipi *mipi; | 285 | struct tegra_mipi *mipi; |
227 | struct resource *res; | 286 | struct resource *res; |
228 | int err; | 287 | int err; |
229 | 288 | ||
289 | match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node); | ||
290 | if (!match) | ||
291 | return -ENODEV; | ||
292 | |||
230 | mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL); | 293 | mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL); |
231 | if (!mipi) | 294 | if (!mipi) |
232 | return -ENOMEM; | 295 | return -ENOMEM; |
233 | 296 | ||
297 | mipi->soc = match->data; | ||
298 | |||
234 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 299 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
235 | mipi->regs = devm_ioremap_resource(&pdev->dev, res); | 300 | mipi->regs = devm_ioremap_resource(&pdev->dev, res); |
236 | if (IS_ERR(mipi->regs)) | 301 | if (IS_ERR(mipi->regs)) |
@@ -262,11 +327,6 @@ static int tegra_mipi_remove(struct platform_device *pdev) | |||
262 | return 0; | 327 | return 0; |
263 | } | 328 | } |
264 | 329 | ||
265 | static struct of_device_id tegra_mipi_of_match[] = { | ||
266 | { .compatible = "nvidia,tegra114-mipi", }, | ||
267 | { }, | ||
268 | }; | ||
269 | |||
270 | struct platform_driver tegra_mipi_driver = { | 330 | struct platform_driver tegra_mipi_driver = { |
271 | .driver = { | 331 | .driver = { |
272 | .name = "tegra-mipi", | 332 | .name = "tegra-mipi", |