aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/mipi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/mipi.c')
-rw-r--r--drivers/gpu/host1x/mipi.c148
1 files changed, 107 insertions, 41 deletions
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index 9882ea122024..fbc6ee6ca337 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -49,35 +49,47 @@
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)
60 73
61#define MIPI_CAL_BIAS_PAD_CFG1 0x17 74#define MIPI_CAL_BIAS_PAD_CFG1 0x17
75#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
62 76
63#define MIPI_CAL_BIAS_PAD_CFG2 0x18 77#define MIPI_CAL_BIAS_PAD_CFG2 0x18
64#define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) 78#define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1)
65 79
66static const struct module { 80struct tegra_mipi_pad {
67 unsigned long reg; 81 unsigned long data;
68} modules[] = { 82 unsigned long clk;
69 { .reg = MIPI_CAL_CONFIG_CSIA }, 83};
70 { .reg = MIPI_CAL_CONFIG_CSIB }, 84
71 { .reg = MIPI_CAL_CONFIG_CSIC }, 85struct tegra_mipi_soc {
72 { .reg = MIPI_CAL_CONFIG_CSID }, 86 bool has_clk_lane;
73 { .reg = MIPI_CAL_CONFIG_CSIE }, 87 const struct tegra_mipi_pad *pads;
74 { .reg = MIPI_CAL_CONFIG_DSIA }, 88 unsigned int num_pads;
75 { .reg = MIPI_CAL_CONFIG_DSIB },
76 { .reg = MIPI_CAL_CONFIG_DSIC },
77 { .reg = MIPI_CAL_CONFIG_DSID },
78}; 89};
79 90
80struct tegra_mipi { 91struct tegra_mipi {
92 const struct tegra_mipi_soc *soc;
81 void __iomem *regs; 93 void __iomem *regs;
82 struct mutex lock; 94 struct mutex lock;
83 struct clk *clk; 95 struct clk *clk;
@@ -90,16 +102,16 @@ struct tegra_mipi_device {
90 unsigned long pads; 102 unsigned long pads;
91}; 103};
92 104
93static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi, 105static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
94 unsigned long reg) 106 unsigned long offset)
95{ 107{
96 return readl(mipi->regs + (reg << 2)); 108 return readl(mipi->regs + (offset << 2));
97} 109}
98 110
99static inline void tegra_mipi_writel(struct tegra_mipi *mipi, 111static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
100 unsigned long value, unsigned long reg) 112 unsigned long offset)
101{ 113{
102 writel(value, mipi->regs + (reg << 2)); 114 writel(value, mipi->regs + (offset << 2));
103} 115}
104 116
105struct tegra_mipi_device *tegra_mipi_request(struct device *device) 117struct tegra_mipi_device *tegra_mipi_request(struct device *device)
@@ -117,36 +129,35 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device)
117 129
118 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 130 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
119 if (!dev) { 131 if (!dev) {
120 of_node_put(args.np);
121 err = -ENOMEM; 132 err = -ENOMEM;
122 goto out; 133 goto out;
123 } 134 }
124 135
125 dev->pdev = of_find_device_by_node(args.np); 136 dev->pdev = of_find_device_by_node(args.np);
126 if (!dev->pdev) { 137 if (!dev->pdev) {
127 of_node_put(args.np);
128 err = -ENODEV; 138 err = -ENODEV;
129 goto free; 139 goto free;
130 } 140 }
131 141
132 of_node_put(args.np);
133
134 dev->mipi = platform_get_drvdata(dev->pdev); 142 dev->mipi = platform_get_drvdata(dev->pdev);
135 if (!dev->mipi) { 143 if (!dev->mipi) {
136 err = -EPROBE_DEFER; 144 err = -EPROBE_DEFER;
137 goto pdev_put; 145 goto put;
138 } 146 }
139 147
148 of_node_put(args.np);
149
140 dev->pads = args.args[0]; 150 dev->pads = args.args[0];
141 dev->device = device; 151 dev->device = device;
142 152
143 return dev; 153 return dev;
144 154
145pdev_put: 155put:
146 platform_device_put(dev->pdev); 156 platform_device_put(dev->pdev);
147free: 157free:
148 kfree(dev); 158 kfree(dev);
149out: 159out:
160 of_node_put(args.np);
150 return ERR_PTR(err); 161 return ERR_PTR(err);
151} 162}
152EXPORT_SYMBOL(tegra_mipi_request); 163EXPORT_SYMBOL(tegra_mipi_request);
@@ -161,7 +172,7 @@ EXPORT_SYMBOL(tegra_mipi_free);
161static int tegra_mipi_wait(struct tegra_mipi *mipi) 172static int tegra_mipi_wait(struct tegra_mipi *mipi)
162{ 173{
163 unsigned long timeout = jiffies + msecs_to_jiffies(250); 174 unsigned long timeout = jiffies + msecs_to_jiffies(250);
164 unsigned long value; 175 u32 value;
165 176
166 while (time_before(jiffies, timeout)) { 177 while (time_before(jiffies, timeout)) {
167 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS); 178 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
@@ -177,8 +188,9 @@ static int tegra_mipi_wait(struct tegra_mipi *mipi)
177 188
178int tegra_mipi_calibrate(struct tegra_mipi_device *device) 189int tegra_mipi_calibrate(struct tegra_mipi_device *device)
179{ 190{
180 unsigned long value; 191 const struct tegra_mipi_soc *soc = device->mipi->soc;
181 unsigned int i; 192 unsigned int i;
193 u32 value;
182 int err; 194 int err;
183 195
184 err = clk_enable(device->mipi->clk); 196 err = clk_enable(device->mipi->clk);
@@ -192,23 +204,35 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
192 value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; 204 value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
193 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0); 205 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
194 206
207 tegra_mipi_writel(device->mipi, MIPI_CAL_BIAS_PAD_DRV_DN_REF(2),
208 MIPI_CAL_BIAS_PAD_CFG1);
209
195 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2); 210 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
196 value &= ~MIPI_CAL_BIAS_PAD_PDVREG; 211 value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
197 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); 212 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
198 213
199 for (i = 0; i < ARRAY_SIZE(modules); i++) { 214 for (i = 0; i < soc->num_pads; i++) {
200 if (device->pads & BIT(i)) 215 u32 clk = 0, data = 0;
201 value = MIPI_CAL_CONFIG_SELECT | 216
202 MIPI_CAL_CONFIG_HSPDOS(0) | 217 if (device->pads & BIT(i)) {
203 MIPI_CAL_CONFIG_HSPUOS(4) | 218 data = MIPI_CAL_CONFIG_SELECT |
204 MIPI_CAL_CONFIG_TERMOS(5); 219 MIPI_CAL_CONFIG_HSPDOS(0) |
205 else 220 MIPI_CAL_CONFIG_HSPUOS(4) |
206 value = 0; 221 MIPI_CAL_CONFIG_TERMOS(5);
222 clk = MIPI_CAL_CONFIG_SELECT |
223 MIPI_CAL_CONFIG_HSCLKPDOSD(0) |
224 MIPI_CAL_CONFIG_HSCLKPUOSD(4);
225 }
207 226
208 tegra_mipi_writel(device->mipi, value, modules[i].reg); 227 tegra_mipi_writel(device->mipi, data, soc->pads[i].data);
228
229 if (soc->has_clk_lane)
230 tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk);
209 } 231 }
210 232
211 tegra_mipi_writel(device->mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL); 233 value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
234 value |= MIPI_CAL_CTRL_START;
235 tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
212 236
213 err = tegra_mipi_wait(device->mipi); 237 err = tegra_mipi_wait(device->mipi);
214 238
@@ -219,16 +243,63 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
219} 243}
220EXPORT_SYMBOL(tegra_mipi_calibrate); 244EXPORT_SYMBOL(tegra_mipi_calibrate);
221 245
246static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
247 { .data = MIPI_CAL_CONFIG_CSIA },
248 { .data = MIPI_CAL_CONFIG_CSIB },
249 { .data = MIPI_CAL_CONFIG_CSIC },
250 { .data = MIPI_CAL_CONFIG_CSID },
251 { .data = MIPI_CAL_CONFIG_CSIE },
252 { .data = MIPI_CAL_CONFIG_DSIA },
253 { .data = MIPI_CAL_CONFIG_DSIB },
254 { .data = MIPI_CAL_CONFIG_DSIC },
255 { .data = MIPI_CAL_CONFIG_DSID },
256};
257
258static const struct tegra_mipi_soc tegra114_mipi_soc = {
259 .has_clk_lane = false,
260 .pads = tegra114_mipi_pads,
261 .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
262};
263
264static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
265 { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
266 { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
267 { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
268 { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
269 { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK },
270 { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIAB_CLK },
271 { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIAB_CLK },
272};
273
274static const struct tegra_mipi_soc tegra124_mipi_soc = {
275 .has_clk_lane = true,
276 .pads = tegra124_mipi_pads,
277 .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
278};
279
280static struct of_device_id tegra_mipi_of_match[] = {
281 { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
282 { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
283 { },
284};
285
222static int tegra_mipi_probe(struct platform_device *pdev) 286static int tegra_mipi_probe(struct platform_device *pdev)
223{ 287{
288 const struct of_device_id *match;
224 struct tegra_mipi *mipi; 289 struct tegra_mipi *mipi;
225 struct resource *res; 290 struct resource *res;
226 int err; 291 int err;
227 292
293 match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
294 if (!match)
295 return -ENODEV;
296
228 mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL); 297 mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
229 if (!mipi) 298 if (!mipi)
230 return -ENOMEM; 299 return -ENOMEM;
231 300
301 mipi->soc = match->data;
302
232 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 303 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
233 mipi->regs = devm_ioremap_resource(&pdev->dev, res); 304 mipi->regs = devm_ioremap_resource(&pdev->dev, res);
234 if (IS_ERR(mipi->regs)) 305 if (IS_ERR(mipi->regs))
@@ -260,11 +331,6 @@ static int tegra_mipi_remove(struct platform_device *pdev)
260 return 0; 331 return 0;
261} 332}
262 333
263static struct of_device_id tegra_mipi_of_match[] = {
264 { .compatible = "nvidia,tegra114-mipi", },
265 { },
266};
267
268struct platform_driver tegra_mipi_driver = { 334struct platform_driver tegra_mipi_driver = {
269 .driver = { 335 .driver = {
270 .name = "tegra-mipi", 336 .name = "tegra-mipi",