aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Etheridge <detheridge@ti.com>2013-06-21 14:52:27 -0400
committerDave Airlie <airlied@redhat.com>2013-06-27 19:12:54 -0400
commit39de6194131c155901f96686a063212656d80c2e (patch)
tree251e3247c1c09c27bcd8401fce48aed92fdf7693
parentf7b4575601dafb3cf3c568465ec6980de6d09b94 (diff)
drm/tilcdc fixing i2c/slave initialization race
In certain senarios drm will initialize before i2c this means that i2c slave devices like the nxp tda998x will fail to be probed. This patch detects this condition then defers the probe of the slave device and the tilcdc main driver. Signed-off-by: Darren Etheridge <detheridge@ti.com> Acked-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c10
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h2
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.c53
3 files changed, 40 insertions, 25 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 1e8f273f7c8b..40b71da5a214 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -26,6 +26,7 @@
26#include "drm_fb_helper.h" 26#include "drm_fb_helper.h"
27 27
28static LIST_HEAD(module_list); 28static LIST_HEAD(module_list);
29static bool slave_probing;
29 30
30void tilcdc_module_init(struct tilcdc_module *mod, const char *name, 31void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
31 const struct tilcdc_module_ops *funcs) 32 const struct tilcdc_module_ops *funcs)
@@ -41,6 +42,11 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod)
41 list_del(&mod->list); 42 list_del(&mod->list);
42} 43}
43 44
45void tilcdc_slave_probedefer(bool defered)
46{
47 slave_probing = defered;
48}
49
44static struct of_device_id tilcdc_of_match[]; 50static struct of_device_id tilcdc_of_match[];
45 51
46static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, 52static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
@@ -580,6 +586,10 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
580 return -ENXIO; 586 return -ENXIO;
581 } 587 }
582 588
589 /* defer probing if slave is in deferred probing */
590 if (slave_probing == true)
591 return -EPROBE_DEFER;
592
583 return drm_platform_init(&tilcdc_driver, pdev); 593 return drm_platform_init(&tilcdc_driver, pdev);
584} 594}
585 595
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index 66df316ca434..093803683b25 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -117,7 +117,7 @@ struct tilcdc_module {
117void tilcdc_module_init(struct tilcdc_module *mod, const char *name, 117void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
118 const struct tilcdc_module_ops *funcs); 118 const struct tilcdc_module_ops *funcs);
119void tilcdc_module_cleanup(struct tilcdc_module *mod); 119void tilcdc_module_cleanup(struct tilcdc_module *mod);
120 120void tilcdc_slave_probedefer(bool defered);
121 121
122/* Panel config that needs to be set in the crtc, but is not coming from 122/* Panel config that needs to be set in the crtc, but is not coming from
123 * the mode timings. The display module is expected to call 123 * the mode timings. The display module is expected to call
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
index 8bf4fd19181c..dfffaf014022 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -298,6 +298,7 @@ static int slave_probe(struct platform_device *pdev)
298 struct tilcdc_module *mod; 298 struct tilcdc_module *mod;
299 struct pinctrl *pinctrl; 299 struct pinctrl *pinctrl;
300 uint32_t i2c_phandle; 300 uint32_t i2c_phandle;
301 struct i2c_adapter *slavei2c;
301 int ret = -EINVAL; 302 int ret = -EINVAL;
302 303
303 /* bail out early if no DT data: */ 304 /* bail out early if no DT data: */
@@ -306,44 +307,48 @@ static int slave_probe(struct platform_device *pdev)
306 return -ENXIO; 307 return -ENXIO;
307 } 308 }
308 309
309 slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); 310 /* Bail out early if i2c not specified */
310 if (!slave_mod)
311 return -ENOMEM;
312
313 mod = &slave_mod->base;
314
315 tilcdc_module_init(mod, "slave", &slave_module_ops);
316
317 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
318 if (IS_ERR(pinctrl))
319 dev_warn(&pdev->dev, "pins are not configured\n");
320
321 if (of_property_read_u32(node, "i2c", &i2c_phandle)) { 311 if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
322 dev_err(&pdev->dev, "could not get i2c bus phandle\n"); 312 dev_err(&pdev->dev, "could not get i2c bus phandle\n");
323 goto fail; 313 return ret;
324 } 314 }
325 315
326 mod->preferred_bpp = slave_info.bpp;
327
328 i2c_node = of_find_node_by_phandle(i2c_phandle); 316 i2c_node = of_find_node_by_phandle(i2c_phandle);
329 if (!i2c_node) { 317 if (!i2c_node) {
330 dev_err(&pdev->dev, "could not get i2c bus node\n"); 318 dev_err(&pdev->dev, "could not get i2c bus node\n");
331 goto fail; 319 return ret;
332 } 320 }
333 321
334 slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node); 322 /* but defer the probe if it can't be initialized it might come later */
335 if (!slave_mod->i2c) { 323 slavei2c = of_find_i2c_adapter_by_node(i2c_node);
324 of_node_put(i2c_node);
325
326 if (!slavei2c) {
327 ret = -EPROBE_DEFER;
328 tilcdc_slave_probedefer(true);
336 dev_err(&pdev->dev, "could not get i2c\n"); 329 dev_err(&pdev->dev, "could not get i2c\n");
337 goto fail; 330 return ret;
338 } 331 }
339 332
340 of_node_put(i2c_node); 333 slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
334 if (!slave_mod)
335 return -ENOMEM;
341 336
342 return 0; 337 mod = &slave_mod->base;
343 338
344fail: 339 mod->preferred_bpp = slave_info.bpp;
345 slave_destroy(mod); 340
346 return ret; 341 slave_mod->i2c = slavei2c;
342
343 tilcdc_module_init(mod, "slave", &slave_module_ops);
344
345 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
346 if (IS_ERR(pinctrl))
347 dev_warn(&pdev->dev, "pins are not configured\n");
348
349 tilcdc_slave_probedefer(false);
350
351 return 0;
347} 352}
348 353
349static int slave_remove(struct platform_device *pdev) 354static int slave_remove(struct platform_device *pdev)